puzzlepaint / freeage

An open-source reimplementation of the game engine of Age of Empires 2: Definitive Edition.
59 stars 4 forks source link

Worker map and multiple villager building speed #20

Closed MaanooAk closed 4 years ago

MaanooAk commented 4 years ago

I originally tried adding a vector of ClentUnit pointers to the ServerObject to keep track of workers, but then there was too difficult and possible buggy to maintain the list. So my idea is to have a map from ServerObject to ClentUnit:

  /// A map from objects to all of their workers. Workers are considered:
  /// - For buildings under construction: all the villagers building.
  /// - For buildings/units being repaired: all the villagers repairing. TODO: implement
  /// - For resources spots: all the villagers gathering. TODO: implement
  /// - For farms: the villager farming. TODO: implement
  /// The map is reconstructed in every frame.
  std::multimap<ServerObject*, ServerUnit*> workers;

The key is that the list is cleared at the start of every simulation step and used in this way:

    bool firstBuilder = workers.count(targetBuilding) == 0;
    workers.emplace(targetBuilding, villager);

The advantage of is (compared to a vector in each object) that you don't have to find all the cases where the villagers stops building and go update the list.

Note: After the "too many villagers -> retask" is implemented we can figure out if the ServerUnit pointers are needed and if not the map could be reduced to a std::map<ServerObject*, int> keeping track of just the number not the actual units.

I think this design opens up a lot of things to be implemented easily. What do you think?

This is quick pr before I go back to stats...

puzzlepaint commented 4 years ago

+1 for the per-frame check.

I think that instead of the multimap, it might be sufficient to store either only the number of workers per object, or only a bool saying whether any worker is currently working on an object.

I might be overlooking some other applications where a multimap might be useful though.

Let me know whether you want to merge this as-is (as it fixes the multi-villager building speed) or whether you would be fine with a std::unordered_set<ServerObject*> hasWorker or std::unordered_map<ServerObject*, int> numberOfWorkers as well.

puzzlepaint commented 4 years ago

Actually, to minimize friction, let's just merge this directly and then keep in mind to revisit it when implementing the villager distribution mechanism, as you suggested.