Skip to content

[3.3.5] Core/Pet: Fix PetSpellMap <-> DB sync#20112

Merged
Treeston merged 2 commits into
TrinityCore:3.3.5from
necropola:3.3.5
Aug 6, 2017
Merged

[3.3.5] Core/Pet: Fix PetSpellMap <-> DB sync#20112
Treeston merged 2 commits into
TrinityCore:3.3.5from
necropola:3.3.5

Conversation

@necropola

@necropola necropola commented Aug 4, 2017

Copy link
Copy Markdown
Contributor

PetSpellMap entries with state == PETSPELL_REMOVED must not be erased before DB sync.

The previous patch was only a partial fix for the issue and didn't actually address the root cause, which is PetSpellMap and characters.pet_spellare getting out of sync. The current fix only helps with (ranked non-talent) spells that are toggled on the pet action bar, because those are also written to characters.character_pet.
Ranked non-talent spells that are not on the pet action bar, but put on auto via the pet spell book only are not correctly remembered without this second fix.

@Treeston

Treeston commented Aug 5, 2017

Copy link
Copy Markdown
Contributor

I'm not intricately familiar with the relevant code paths. Could you outline the incorrect logic vs your correct fix?

@necropola

necropola commented Aug 6, 2017

Copy link
Copy Markdown
Contributor Author

The idea - as far as I understood after analyzing the code - is that PetSpellMap is the server-side memory representation of the pet's spell book which is made persistent by saving to / loading from certain tables in the character database (pet_spell in particular). For performance reasons the database isn't updated on every change of the map but as a bulk operation on certain events , e. g. mounting/unmounting.

PetSpellMap basically stores the currently available spells along with anactive value (autocast on/off) and a state value (map entry needs to be written to / deleted from database). A map entry must not be erased from the map until it is deleted from the database. Instead it needs to be flagged for deletion by setting the state value to PETSPELL_REMOVED. Which means only the DB syncing code should be actually erasing entries fromPetSpellMap.

There are currently two occurrences of m_spells.erase() outside of the DB sync code. One doesn't seem to cause problems (unchanged), but the other (removed) can actually lead to the pathological case of erasing an entry from the PetSpellMap before it is also deleted from the DB. In fact it happens whenaddSpell cleans up PetSpellMap from lower ranked spells. The result is that PetSpellMap in memory and its representation on disk (DB) get out of sync. Multiple ranks of the same spell are still in pet_spell and get loaded from the DB on unmount / pet call, passed into addSpell and finally lead to autocast on/off not being properly restored.

I originally just noticed that the pet bar autocast issue only happens when there are entries for different ranks of the same spell in the pet_spell table (DB) and I was able to fix it (per pet) by manually deleting the lower ranks from the DB. Then I noticed how much effort the code puts into removing lower rank spells from PetSpellMap but that it fails to correctly update the DB. And finally I spotted the reason,

But why did my previous patch seem to have fixed autocast settings?
Well, it only fixed it for spells that are on the pet bar, not for those that are only toggled via spell book. The ugly fact that autocast settings are stored in two places (pet_spell for all spells, and character_pet for spells on the action bar) was able to obscure the root cause for a long time ...

@Treeston

Treeston commented Aug 6, 2017

Copy link
Copy Markdown
Contributor

👍 great analysis and good catch

@Treeston Treeston merged commit ecf5978 into TrinityCore:3.3.5 Aug 6, 2017
@necropola

Copy link
Copy Markdown
Contributor Author

Seems you integrated a slightly different fix. Guess that's alright. It reminds me to keep my work in a separate branch (3.3.5-my_work) to avoid merge conflicts when pulling "3.3.5" from upstream. :-)

@Treeston

Treeston commented Aug 6, 2017

Copy link
Copy Markdown
Contributor

You can simply base your branches on upstream/3.3.5 then push just the PR branch itself to your fork. No reason to keep your fork's main 3.3.5 branch up-to-date all the time.

Aokromes pushed a commit to Aokromes/TrinityCore that referenced this pull request Aug 13, 2017
Shauren pushed a commit that referenced this pull request Aug 22, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants