A Minecraft Forge mod that synchronizes player data across multiple servers using a MySQL backend.
Go to file
laforetbrut 7bf2cd6bcc Phase 11: fix heartbeat-frozen misdetection + reduce RACE log spam
Production logs (2026-04-22 05:41-05:44) revealed two Phase 10 regressions:

Bug A: force-claim on healthy peer due to wrong heartbeat threshold.
  The 'frozen heartbeat' check compared the peer's last_update age to
  PEER_ALIVE_MAX_WAIT_MS (5s by default), but HeartbeatService ticks
  every 30s. Between ticks the peer's last_update is naturally 0-30s old.
  Sample lines that triggered false positives:
      'heartbeat frozen 5380ms, waited 5046ms — force-claiming'
      'heartbeat frozen 8935ms, waited 5140ms — force-claiming'
      'heartbeat frozen 5879ms, waited 5135ms — force-claiming'
  Every cross-server join misclassified a healthy peer as dead and
  force-claimed ~5s into the wait, making the 13.7s 'first restore'
  observed in the logs. Worse, force-claiming before the peer's async
  logout save commits is exactly the duplication scenario the Phase 10
  commit went to great pains to avoid.

  Fix: compare peer age against PEER_STALE_THRESHOLD_SECONDS (60s default).
  Matches the existing isPeerServerStale() semantics — a peer is frozen
  only when it has genuinely stopped heartbeating, not just between ticks.
  Log now shows both numbers: 'heartbeat stale Xms > Yms, waited Zms'.

Bug B: RACE log spam.
  The last_server poll logged a line every 500ms — up to 120 lines per
  cross-server join with no new information after the first few. With
  multiple concurrent joins this made sync.log unreadable. Now the RACE
  line only fires every 10 attempts (every 5s at default interval),
  plus the decision points (heartbeat-stale force-claim, slow-peer warn).

Also routes [perf-logout] breakdown to sync.log via SyncLogger.perf
so field reports include the core/backpacks/ss/rs2 split — we were
logging it only to server.log which admins rarely forward.
2026-04-22 07:52:49 +02:00
.github Bump gradle/actions from 4 to 5 2025-10-14 16:55:21 +08:00
compat-mods Add compat-mods staging folder for mod compatibility analysis 2026-04-22 03:33:11 +02:00
gradle/wrapper migrate from ForgeGradle to ModDevGradle legacy 2025-05-02 22:40:39 +00:00
src/main Phase 11: fix heartbeat-frozen misdetection + reduce RACE log spam 2026-04-22 07:52:49 +02:00
.gitattributes Initial commit 2022-12-08 16:59:20 +08:00
.gitignore Fix backpack/curios dup, perf overhaul, drop chat+cobblemon 2026-04-22 02:50:26 +02:00
build.gradle jarJar: declare version ranges for MySQL + HikariCP 2026-04-22 06:46:24 +02:00
CHANGELOG.md Phase 8: 20+ new config keys + 14 admin commands (/playersync) 2026-04-22 06:34:02 +02:00
docker-compose.yml use volume for docker-compose db to persist data 2025-05-01 18:42:58 +00:00
ERROR_LOG.md Phase 6: docs (CHANGELOG, ERROR_LOG, TEST_PROCEDURE) 2026-04-22 06:09:08 +02:00
gradle.properties perf: zero JDBC on server thread + HikariCP + parallel shutdown + audit fixes 2026-03-29 18:58:27 +02:00
gradlew migrate from ForgeGradle to ModDevGradle legacy 2025-05-02 22:40:39 +00:00
gradlew.bat migrate from ForgeGradle to ModDevGradle legacy 2025-05-02 22:40:39 +00:00
LICENSE Create LICENSE 2022-12-08 17:11:47 +08:00
README.md readme: add section on how to setup a dev env 2025-05-01 16:59:05 +00:00
settings.gradle half done, noticed about advancement can't store normally 2025-06-07 00:55:30 +08:00
TEST_PROCEDURE_v2.1.5.html Phase 6: docs (CHANGELOG, ERROR_LOG, TEST_PROCEDURE) 2026-04-22 06:09:08 +02:00

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.

  1. Make sure Docker is installed.
  2. Inside your work directory run:
    docker compose up -d
    
    This will download the MariaDB image (if not already present) and start a database container in the background.
  3. 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.

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).

  1. Make sure that the MySQL database you configured is running.
  2. Run the Server
    ./gradlew runServer
    
    or on Windows:
    .\gradlew.bat runServer
    
    This task compiles the mod and starts a dedicated Minecraft server instance with the mod loaded in the run directory.
  3. Run the Client
    ./gradlew runClient
    
    or on Windows:
    .\gradlew.bat runClient