User report: 'Je veut juste que ça prenne en compte les disks que le joueur à
dans l inventaire' — confirming the rs2=1000ms+ observed in [perf-logout]
breakdowns. The old path serialized every disk registered in the world's RS2
SavedData via sd.save() then searched the resulting blob for the player's
UUIDs. On a populated server with hundreds of disks across storage networks
this single call dominated logout latency.
New path (Phase 16):
- Call repo.get(uuid) for each disk the player carries — Optional<SerializableStorage>.
- Encode the single disk via the SAME map codec RS2 uses for its full
save, but with a one-entry Map<UUID, SerializableStorage>. Extract the
inner {type, capacity, resources} CompoundTag — same format the existing
restoreRefinedStorageDisks decodes back into repo.set().
- Complexity drops from O(world disks) to O(player disks carried).
Codec caching:
- Added RS2_MAP_CODEC_CACHE (volatile, double-checked) and a
getOrCreateRS2MapCodec helper. Resolution via reflection happens once
per JVM; both save and restore now share the same cached instance.
Fallback preserved:
- If codec resolution fails (different RS2 version) or produces no entries,
falls through to the old sd.save() path. No regression for existing
deployments that worked before.
Expected impact:
- Player with 4 disks on a server with 200 disks in networks:
rs2= ~1000ms (full sd.save) -> rs2= ~60-100ms (4 repo.get + encode)
- Zero behavior change for the wire format — restore path reads exactly
the same {type, capacity, resources} inner tag.
Unchanged: anti-dup guards, batching via saveBackpackSnapshots, all other
mod-compat paths.
|
||
|---|---|---|
| .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