Previously, multiple stacks of the same item ID could overwrite data in each other because of how the logic in ContainerStore::add() works. For example, a stack of 5 grand soul gems with no souls would get added to the player, then the attempt to add a grand soul gem with a particular soul would retrieve the previous stack first before setting all of it to that soul, resulting in 6 grand soul gems with that soul.
Previously, unstacking items for a player led to a PlayerInventory packet being sent about the items' removal.
This change makes it so both a packet about their re-addition and their removal are sent instead, cancelling each other out, which is inelegant, but arguably preferable to complicating the sending of PlayerInventory packets again.
Enchanted inventory items continuously recharge their enchantment charges, which getItemPtrFromStore() should account for.
Additionally, prevent framelistener errors caused by PlayerItemUse packets about non-existent items.
This prevents infinite loops in certain client scripts from mods that use while loops to determine that all items of a certain type have been removed from a container, such as in the script BCSwap2Arg from Better_Clothes.
Previously, client mods adding packet-sending scripts to the spawn area made clients send the associated packets as soon as they inputted their character name when joining a server using those mods. This made the clients either get disconnected for not replying to a handshake first, or it made them get kicked for sending object packets that are disallowed for players who are not logged in.
To fix this, LocalPlayer's hasFinishedCharGen() has been replaced with isLoggedIn(), because the former was already returning true when players inputted their names.
Functions that add elements to a vector should not change the action. This fixes the last remaining oddity in Koncord's original implementation of inventory sync.
This makes it possible to send custom records used by players for their equipment before the hardcoded exchange of equipment packets takes place.
Additionally, remove the check for dead players because it has no real use and can potentially cause problems.
Previously, the player's currently selected weapon was being used in ranged attacks as in the original melee-oriented attack sync, which meant that shooting one type of projectile and then equipping another while the old projectile was still in the air turned the old projectile into the new projectile upon impact.
Additionally, avoid running most of the code in MechanicsHelper::assignAttackTarget() for non-hitting melee and ranged attacks.
This is done by including the final attackStrength used for ranged attacks in packets and then applying it in WeaponAnimation::releaseArrow() on other clients.