- Only update shroud within the visible screen area, rather than the whole map. This improves performance on larger maps significantly when scrolling around since large portions of the shroud do not need to be updated.
- Provide methods in Shroud to return delegates to check for explored/visibility for tiles within a certain region. This allows it to return more efficient delegates whenever the region is within the map bounds, or shroud/fog is disabled. In the typical case where the region is in bounds and shroud/fog is enabled, the fast check is almost twice as fast as the slow check.
- Use the Shroud delegate functions in shroud rendering, frozen actors, minimap rendering and resource layer areas to provide a speedup since these areas of code can often take advantage of the fact they perform checks within the map boundary.
- Cache current element in CellRegionEnumerator to prevent repeated work if the element is accessed more than once.
- Decrease the size of elements in some arrays in hopes of reducing memory needs and improving cache hits.
- Extract an enum for edges rather than using magic numbers for everything.
- Remove duplicated code between FoggedEdges and ShroudedEdges by hosting the visibility function into a delegate.
- Make minimap methods more readable.
- Tidy formatting.
- Make some fields readonly.
- Remove unused usings.
- Avoid calling string.Split twice in SprintFont.Measure.
- Change ActorsInBox method of ActorMap and ScreenMap to avoid allocating and intermediate list. As a bonus this allows the sequence to be lazily consumed. Also avoid LINQ in these methods.
- In FrozenUnderFog.TickRender, the method exits early if no players are visible so the attempt at lazy generation was not needed.
- Unwrap a LINQ Any call in ClassicProductionQueue.Tick.
- Merge some successive Where calls in ProximityCapturable into single predicates.
Since FrozenUnderFog.Tick gets called a lot, these dictionary lookups were actually getting repeated a fair amount. Avoiding the repeated work is a minor performance improvement.
Targeted some methods that generated allocated a lot of memory in the main game loop:
- Actor.Render - Changed LINQ calls into equivalent loops. No allocation for delegates.
- Animation.Render - Returned an array rather than a yield expression. The array uses less memory than the complier generated enumerable.
- FrozenActor and FrozenUnderFog - Materialize the footprint into an array: The enumerable is not-trivial to evaluate is and evaluated many times inside the Tick function. The memory needed is minimal. Changed LINQ into equivalent loops to prevent delegate allocation. Should result in overall much faster calls.
- Widget.GetEventBounds - Changed LINQ calls into equivalent loops.
- MobileInfo.CanEnterCell - Changed LINQ calls into equivalent loops. Don't materialize list of blocking actors every time, instead enumerate them and only when they need to be checked.
- FrozenUnderFog.TickRender - Generate the renderables lazily and also remove a no-op Select call.
- Each player has their own shroud and their visibility does not extend outside of the shroud.
- Units and buildings can no longer target other units outside of their visibility. Buildings can still be targetted if they have been explored.
- GPS will provide visibility in the fog-of-war.
- Spies that infiltrate radar domes will gain their victim's exploration and reset it on all clients (if the victim does not have GPS)