Two quality-of-life peaufinages.
(1) Advancements file mtime cache [VanillaSync.snapshotPlayerData]
Each snapshot previously called Files.readAllBytes() on the player's
advancement JSON — a main-thread disk read of 1-50ms depending on
storage. On a 35-player server with periodic saves + SaveToFile every
autosave tick, this adds up.
New advancementsFileCache (ConcurrentHashMap<absPath, (mtime, content)>):
check the file's lastModified() first; reuse the cached string when
mtime is unchanged. PlayerAdvancements.save() still flushes pending
changes, and Minecraft only touches the file when something actually
changes — so mtime is a reliable staleness signal. Cache is
process-wide (paths include player UUID so no cross-contamination).
Expected impact: -5 to -30ms off main-thread snapshot for idle-ish
players, zero for players who just earned advancements.
(2) Log spam reduction
The restore/save paths chatter one INFO line per item (backpack / SS /
RS2 disk / accessories / cosmetic / attachments). On a server with
multiple players, each with multiple storage items, this floods
sync.log with per-UUID noise that has zero diagnostic value once the
'it's working' phase is past.
Demoted to DEBUG:
- [restore-backpack] uuid=X nbt_keys=N cleared_via=api
- [restore-ss] uuid=X nbt_keys=N
- Storing backpack data for player X
- Saved backpack data for UUID X
- Scanning inventory for Sophisticated Storage items for player X
- Saved Sophisticated Storage item data for UUID X
- Saved RS2 disk data for UUID X via save() NBT
- Saved RS2 disk data for UUID X via codec reflection
- Restored RS2 disk data for UUID X
- Restored Accessories data for player X
- Restored CosmeticArmor data for player X
- Restored NeoForge attachments for player X
Kept at INFO (per-save summaries):
- Saved N RS2 disk(s) via direct codec (player-scoped)
- Saved N RS2 disk(s) via legacy full-save fallback
- Logout save completed for player X in Nms
- Sync data for player X completed in Nms
- [perf-logout] core=Xms backpacks=Yms ss=Zms rs2=Wms total=Nms
- [emergency-flush] flushed N players
Net effect: sync.log goes from ~10 lines per cross-server transfer
to ~3. Still full diagnostic trace available with log_level=DEBUG.
Unchanged behavior, faster snapshots, cleaner logs.
|
||
|---|---|---|
| .github | ||
| compat-mods | ||
| gradle/wrapper | ||
| src/main | ||
| .gitattributes | ||
| .gitignore | ||
| build.gradle | ||
| CHANGELOG.md | ||
| docker-compose.yml | ||
| ERROR_LOG.md | ||
| gradle.properties | ||
| gradlew | ||
| gradlew.bat | ||
| LICENSE | ||
| README.md | ||
| settings.gradle | ||
| TEST_PROCEDURE_v2.1.5.html | ||
PlayerSync
PlayerSync is a Minecraft Forge mod that synchronizes player data across multiple servers using a MySQL backend. It allows players to maintain their inventory, equipment, experience, advancements, and more when moving between servers in a network.
Mod Support
Any other mods support is also possible.
Development Setup
Database Setup (Docker)
A docker-compose.yml file is provided for easily setting up a MariaDB database instance for development testing.
- Make sure Docker is installed.
- Inside your work directory run:
This will download the MariaDB image (if not already present) and start a database container in the background.docker compose up -d - Stoppinng the Database
docker compose down
Data Persistence: The database uses a Docker volume, ensuring your data persists even if you stop and restart the containers.
Database Management Tool
The docker-compose.yml also includes an Adminer service, a lightweight database management tool.
- Access Adminer in your web browser at http://localhost:8080.
- Log in using the server with
- username:
playersync - database:
playersync - password: see docker-compose.yml
- username:
For debugging purposes, you can enable use_legacy_serialization to have readable database fields. This can cause crashes and unintended side-effects. Do not enable this on a production server if not absolutely necessary!
Running the Mod
The project uses Gradle for building and running. Use the provided Gradle wrapper (gradlew for Linux/macOS, gradlew.bat for Windows).
- Make sure that the MySQL database you configured is running.
- Run the Server
or on Windows:./gradlew runServer
This task compiles the mod and starts a dedicated Minecraft server instance with the mod loaded in the.\gradlew.bat runServerrundirectory. - Run the Client
or on Windows:./gradlew runClient.\gradlew.bat runClient