Make FCollection's set field transient to skip redundant serialization#9991
Merged
tool4ever merged 1 commit intoCard-Forge:masterfrom Mar 5, 2026
Merged
Conversation
The set duplicates all list elements during Java serialization. Since the list is the source of truth, rebuild the set from it in readObject() instead of serializing it. Also fixes HashMap bucket corruption on deserialization of circular object graphs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Hanmac
approved these changes
Mar 5, 2026
Contributor
|
Are we sure we never serialized any of these when writing stuff like Quest/PlanarConquest/Adventure saves? Or that if we did, it's backwards compatible? |
Contributor
|
hmn, I see no direct reason why it would become incompatible this way |
Contributor
|
Yeah, looking over it I guess these are mostly just used for in-game and GUI collections. It's the ItemPools that would be more dangerous if modified. We still need to move away from Java serialization for saving files at some point, but that's neither here nor there. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
FCollection's internalHashSetfieldtransient, skipping it during Java serializationreadObject()to rebuild the set from the list after deserializationfinalfrom the set field (required because field initializers don't run during Java deserialization — the field isnullafterdefaultReadObject()and must be reassigned inreadObject())Context
Discussed with @tool4ever based on the investigation in copyChangedProps.md (change #3 + RE 3 feedback).
FCollectionis a hybrid list+set data structure that is serialized on every networksetGameViewcall. The set duplicates all list element references — since Java serialization shares object references within a singlewriteObjectcall, these are back-references (~5 bytes each) rather than full copies, but it's still pure waste across dozens of collections per GameView.The list is the source of truth for element order and indexed access. Rebuilding the set from the list in
readObject()is equivalent to serializing it, but also guarantees correct HashMap bucket placement — eliminating a class of structural HashMap corruption observed during network play testing where deserialized entries end up in wrong buckets due to circular object graph references.🤖 Generated with Claude Code