Refactor the syncing of regen of units
Description
This issue is an introduction to what needs to happen in https://github.com/FAForever/fa/pull/4135, if you do not intend to do https://github.com/FAForever/fa/issues/4135 too then please leave this issue for someone who does
The regeneration rate can be adjusted in the simulation. This is particularly noticeable when a units gains a level via experience. This is synced to the UI via the sync table. This includes some additional baggage, including:
-
- A complicated (and expensive) indexing approach for syncing the data with the UI
-
- A lot of table and field allocations with regard to the
UnitDatatable
- A lot of table and field allocations with regard to the
For 1, note that this is the meta table of self.Sync as set here. As a consequence, all the index calls run via these functions.
Course of action
We'll take a similar approach to https://github.com/FAForever/fa/pull/3916, where we use the recently found Unit:GetStat and Unit:SetStat functions. These allow for direct communication with the UI, without using the sync. As a result we'll need to make the following changes:
-
- Instead of storing the intermediate status in
self.Sync, we store it in separate values that we keep track of inself
- Instead of storing the intermediate status in
-
- We initialize all required values during
OnCreate, unless the unit does not support keeping track of experience. This includes the amount of experience and the amount required for the next level
- We initialize all required values during
-
- We initialize the stats by calling
unit:GetStatduring OnCreate
- We initialize the stats by calling
-
- We update all functions related to adjusting regen rate, including:
-
Unit:SetRegen
-
- We update the UI to use
UserUnit:GetStatwhen we want to view the current experience values
- We update the UI to use
Note that 1 and 2 should closely resemble how it works in https://github.com/FAForever/fa/pull/3916, and that 3 is required to prevent an engine bug. We need to try and get the stat (as that prepares the statistic in the engine) before we can set it (which crashes if it tries to read a value that does not exist).
Test plan
The functionality of the regen rate should remain the same. Technically you should be able to play a replay without desyncing, as the computation is not adjusted (just the information we send to the UI is). In practice this is impossible due to floating point inaccuracy, however.
Sanity checklist:
- At no point can the game do a
Unit:SetStaton a value that has not been prepared usingUnit:GetStat
Learning goals
Tackle small refactoring that spans across the sim to the UI.