fa icon indicating copy to clipboard operation
fa copied to clipboard

Refactor the syncing of experience of units

Open Garanas opened this issue 3 years ago • 0 comments

Description

The implementation of the experience (veterancy) system is done via the Sync table. Because of this it includes a lot of additional baggage, which includes:

    1. A complicated (and expensive) indexing approach for syncing the data with the UI
    1. A lot of table and field allocations with regard to the UnitData table

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. And there are a lot of those!

Course of action

We'll take a similar approach to https://github.com/FAForever/fa/issues/4134, 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:

    1. Instead of storing the intermediate status in self.Sync, we store it in separate values that we keep track of in self
    1. 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
    1. We initialize the stats by calling unit:GetStat during OnCreate
    1. We update all functions related to experience, including:
    • Unit:CalculateVeterancyLevel
    • Unit:CalculateVeterancyLevelAfterTransfer
    • Unit:SetVeterancy
    1. We update the UI to use UserUnit:GetStat when we want to view the current experience values

Note that 1 and 2 should closely resemble how it works in https://github.com/FAForever/fa/issues/4134, 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 experience system should remain the same. Technically you should be able to play a replay without desyncing, as the computation of experience is not adjusted (just the information we send to the UI is). In practice this is impossible due to floating point inaccuracy.

Sanity checklist:

  • There should virtually be no more calls to self.Sync in the unit class
  • At no point can the game do a Unit:SetStat on a value that has not been prepared using Unit:GetStat

Learning goals

Tackle large refactoring that spans across the sim to the UI.

Garanas avatar Aug 17 '22 18:08 Garanas