Effects from the local server .dat file persisted when the player had
no effects saved in the DB. removeAllEffects() was only called inside
the if-block that checks for saved effect data, so it was skipped when
effectData was null/empty. Now effects are ALWAYS cleared before
restoring from DB.
SOL Onion food diversity is already synced via the generic NeoForge
attachment system (FoodPlayerData is a NeoForge attachment).
Vyrriox
- Sync RS2 disk storage contents between servers (storageReference UUID)
- Support both refinedstorage and extradisks namespaces
- Save: extract individual entries from StorageRepository SavedData
- Restore: decode via RS2 codec and inject into target server repository
- Skip restore if storage already exists on target server (no overwrite)
- Scan inventory + ender chest for disks
Vyrriox
Replace unbounded CachedThreadPool with bounded ThreadPoolExecutor.
Problem: CachedThreadPool creates unlimited threads. With many players
online and slow DB queries, thread count explodes (25000+ threads
observed in issue #169), causing memory leaks and server crashes.
Fix: ThreadPoolExecutor with 2 core / 8 max threads, 30s keepalive,
256-task bounded queue, and CallerRunsPolicy for backpressure.
When the queue is full, tasks execute on the calling thread instead
of creating more threads, providing natural flow control.
Closesmlus-asuka/PlayerSync#169
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a generic system that syncs ALL NeoForge player attachments,
covering per-player data from every mod in the modpack:
- Ars Nouveau: mana, glyph/spell knowledge
- Iron's Spellbooks: mana, learned spells, cooldowns
- Pehkui: player scale
- Spice of Life: Onion: food diversity history
- And ANY other mod using NeoForge's attachment system
Implementation:
- Save: extracts neoforge:attachments tag from player.saveWithoutId()
- Restore: uses reflection to call NeoForge's deserializeAttachments()
which ensures exact same deserialization path as normal player load
- Stored as BNBT in mod_player_data table (mod_id=neoforge_attachments)
Also verified CosmeticArmours (mod id: cosmeticarmoursmod) and
CosmeticWeapons (mod id: cosmeticweaponsmod) are content-only mods
that add craftable items - no custom player storage, fully handled
by existing inventory sync.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Per-player ReentrantLock prevents concurrent save/restore operations,
eliminating race conditions that could cause item duplication
- Save ALL online players on ServerStoppingEvent (before disconnect) to
prevent data loss from server shutdowns/restarts
- Lock acquired before restore on join, released in finally block
- Lock acquired before save on logout, cleaned up after completion
- Verified compatibility with 430-mod Arcadia V2 modpack:
- All item DataComponents from all mods preserved via BNBT serialization
- Curios items (Artifacts, Elytra Slot, Charm of Undying, etc.) synced
- Accessories items (Aether, Deep Aether) synced
- Server-specific data (FTB Quests/Chunks, Waystones, Lootr) correctly
NOT synced as intended
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add Accessories API sync for Aether mod accessory slots (pendant, cape,
gloves, rings, shield, misc). Uses same pattern as Curios: validate data
before clearing slots, PreparedStatements for DB operations
- Add Cosmetic Armor Reworked sync for 4 cosmetic armor slots via
InventoryManager/CosArmorAPI
- Add Apotheosis + Placebo as compileOnly deps. Apotheosis item data
(affixes, gems, sockets, rarity) travels with items via DataComponents
and is already synced by the inventory sync
- New generic mod_player_data DB table with composite key (uuid, mod_id)
for extensible mod-specific data storage
- Integrated save/restore in join, logout, and auto-save pipelines
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix advancements disappearing: use PreparedStatements for all SQL with
user data (advancement JSON contains chars that broke string-concat SQL),
add null safety for advancement file
- Fix multi-server kick: run doPlayerConnect synchronously instead of async
(players could join before the duplicate check completed)
- Fix Curios disappearing: clear slots AFTER validating data exists (not
before), use CuriosCache for dead players on logout instead of empty API
- Fix Sophisticated Storage items: add storeSophisticatedStorageItems() and
restoreSophisticatedStorageItems() to sync packed barrels/shulkers/chests
- Anti-duplication: clear all inventories before restoring from DB on join
- Fix tick counter: remove LevelTickEvent (fired per dimension = 3x too
fast), merge heartbeat into ServerTickEvent
- Fix connection leaks: use try-with-resources for all QueryResult
- Fix logout order: save data BEFORE marking player offline
- Skip auto-save for dead/unsynced players to prevent saving empty data
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This allows using PlayerSync with different minecraft versions and
even different sets of mods.
All unknown items are replaced by Paper with its original NBT data
encoded into the paper item.