Afforess
The White Wizard
I have things mostly working, except for one major setback. FFreeListTrashArray containers are impossible to resynchronize mid-game. Saves work because they destroy or create a new FFreeListTrashArray. You can not re-organize the structure in-place, as they do not allow any choice of the IDs used to allocate indexes. This is bad for cities and units, which are stored in FFreeListTrashArray.
Destroying and Creating a new FFreeListTrashArray in its place is also not viable as the FFreeListTrashArray "tracks memory usage internally", meaning when you destroy it, it also destroys every object in its containers, calling the destructor on cities and units. Not good. The game's graphics engine is very unhappy if you wipe those.
I initially tried to iterate over the existing elements, and update them in place, if they had an ID that matched what was sent over to be resynced. If there was extra units not sent in the resync (client has extra units that the host game lacks) kill those. But it falls apart when the host game has extra units the client lacks. There is no way to allocate the units on the client and guarantee they will have the correct IDs from the FFreeListTrashArray, since you have no control over how it allocates ids.
Is this a big deal? Yes, if units are out of order in FFreeListTrashArray, they will be out of order when the game iterates over units (which happens often), and will cause a breakdown in the expected determinism.
I think the only reasonable option is to replace the FFreeListTrashArray for cities and units, and use a new storage container. FFreeListTrashArray is Firaxis's attempt at creating a Linked-Hash Map, which provides constant access with the key (ids) and also provides deterministic orderings when iterating over elements (which the stdext::hash_map lacks).
I was unhappy to discover the C++ STL has no Linked Hash Map standard object. This is a rather common feature in other languages... I now have to locate a suitable alternative. [I am considering just combining a std::vector and std::hash_map in a class, which could provide iteration via the vector, and constant access via the hash_map. Is anyone aware to any drawbacks to this approach, besides the duplicated memory footprint?]
Assuming I do replace FFreeListTrashArray with a Linked Hash Map, where I can control the ID-space, then the units/cities resync problems should be solved.
Destroying and Creating a new FFreeListTrashArray in its place is also not viable as the FFreeListTrashArray "tracks memory usage internally", meaning when you destroy it, it also destroys every object in its containers, calling the destructor on cities and units. Not good. The game's graphics engine is very unhappy if you wipe those.
I initially tried to iterate over the existing elements, and update them in place, if they had an ID that matched what was sent over to be resynced. If there was extra units not sent in the resync (client has extra units that the host game lacks) kill those. But it falls apart when the host game has extra units the client lacks. There is no way to allocate the units on the client and guarantee they will have the correct IDs from the FFreeListTrashArray, since you have no control over how it allocates ids.
Is this a big deal? Yes, if units are out of order in FFreeListTrashArray, they will be out of order when the game iterates over units (which happens often), and will cause a breakdown in the expected determinism.
I think the only reasonable option is to replace the FFreeListTrashArray for cities and units, and use a new storage container. FFreeListTrashArray is Firaxis's attempt at creating a Linked-Hash Map, which provides constant access with the key (ids) and also provides deterministic orderings when iterating over elements (which the stdext::hash_map lacks).
I was unhappy to discover the C++ STL has no Linked Hash Map standard object. This is a rather common feature in other languages... I now have to locate a suitable alternative. [I am considering just combining a std::vector and std::hash_map in a class, which could provide iteration via the vector, and constant access via the hash_map. Is anyone aware to any drawbacks to this approach, besides the duplicated memory footprint?]
Assuming I do replace FFreeListTrashArray with a Linked Hash Map, where I can control the ID-space, then the units/cities resync problems should be solved.