Welcome to the Hangar Open Beta. Please report any issue you encounter on GitHub!
Avatar for LucasTHCR

Cross-server inventory sync over MySQL. Ownership handover instead of timing, so nothing duplicates.

Report InvSYNC?

InvSYNC

Discord Release Downloads Servers License

Built with Java 21 Available for Paper Available for Spigot Available for Bukkit

Chat with us on Discord Available on Codeberg

bStats

InvSYNC

Cross-server player data synchronisation over MySQL, for Paper 1.21+.

Author: LucasTHCR - https://dc.gg/paperstream


What it does

Shares inventory, armour, offhand, ender chest, XP, health, hunger, potion effects and status values (absorption, exhaustion, air, burning, fall distance) between any number of servers through one MySQL database. Every part can be switched off individually.

Custom and modded items are stored through the server's own item format, so full NBT and component data survives. No ProtocolLib, no extra dependency.

What makes it different

Most inventory sync plugins write on quit, read on join and put a fixed delay in between. When the timing does not hold, items duplicate or a session is lost. InvSYNC does not rely on timing.

Ownership instead of a delay. A player's row is claimed by exactly one server at a time. When the player leaves, that server writes their data and hands the row back. The next server waits for the handover, not for a timer. Two servers can never hold the same player at once.

Everything happens before the player enters the world. Claiming, reading and decoding run in the pre-login phase. A failure ends as a login refusal rather than a half applied inventory.

Failures never destroy data.

Situation What happens
Another server still owns the data Login refused, retry in a moment
Stored data cannot be decoded Login refused, stored data untouched, copy kept for inspection
Data written by a newer Minecraft version Refused. Item data can be upgraded, never downgraded
Database unreachable at login Login refused, because letting a player in without their data means saving that emptiness later
Database unreachable at save Write parked on disk and retried; ownership stays held so no other server serves the outdated revision
Inventory cannot be read Previous revision stays, ownership handed back
Server crashed while holding rows Released automatically on next start

Empty is not the same as missing. A synchronised but empty inventory is applied, a section that is switched off is left alone. Collapsing the two duplicates items: a player who empties their inventory on one server gets the contents back on the next one.

Snapshots. Every save keeps a restorable copy. /invsync snapshots <player> lists them, /invsync restore <player> <id> rolls one back.

Install

  1. Create an empty MySQL database. InvSYNC creates the tables itself.
  2. Drop the jar into plugins/ on every server that should share data.
  3. Start once to generate config.yml, then stop.
  4. Fill in the database section.
  5. Give every server its own server-id. Leave it empty to derive one from the hostname and port, which is fine as long as no two servers collide.
  6. Start.

All servers must run the same Minecraft version, or at least never an older one than the version that last wrote the data.

Commands

Command Purpose
/invsync status Connection, ownership, parked saves
/invsync save <player> Write their data now
/invsync unlock <player> Release data stuck on a server that will not come back
/invsync snapshots <player> List restorable copies
/invsync restore <player> <id> Roll back to a copy
/invsync reload Re-read config.yml

Permissions: invsync.admin covers all of them, or grant invsync.admin.<subcommand> individually.

invsync.sync (default true) marks a player as synchronised, invsync.bypass excludes them entirely.

Configuration notes

database.* and server-id are only read on startup. Everything else is picked up by /invsync reload.

ownership.on-timeout decides what happens when the previous server does not hand the data back in time. deny refuses the login and loses nothing. takeover loads the data anyway and can duplicate items. The default is deny.

auto-save only protects against crashes. A normal quit always saves.

Building

mvn clean package

Produces target/InvSYNC-1.0-RELEASE.jar. MySQL Connector and HikariCP are shaded and relocated, so the jar has no external dependencies.

Tests

mvn test

The ownership tests start a real MariaDB for the run, because the locking depends on MySQL behaviour that a compatibility layer does not reproduce: INSERT IGNORE, affected row counts and InnoDB row locking. That server binary is a 149 MB test artifact; mvn package -DskipTests avoids it entirely.

What is covered:

  • 1000 races between 8 servers claiming the same player, exactly one winner each.
  • 500 consecutive server switches without losing or forking a revision.
  • Stale takeover, crash recovery scoping, refused writes after ownership moved, snapshot pruning, maintenance skipping claimed rows.
  • 2000 randomised snapshot round trips, plus format 1 and format 2 payloads decoding correctly under the current version.
  • Truncated, foreign and newer-format payloads raising an error rather than producing plausible looking data.
  • 1000 randomised economy settle runs against a fake economy plugin that loads late and overwrites, asserting no run ever reports success with a wrong balance.

Not covered: anything that needs a running Paper server, which includes item serialisation itself and the real Vault path.

Limits worth knowing

  • Ender chest size is assumed to be the vanilla 27 slots. Plugins that resize it are not accounted for.
  • Economy balances can be synchronised through Vault, but the feature is off by default and needs a second switch to enable. A balance changed while the player is offline is overwritten on their next login, and no design inside this plugin can prevent that. Pointing the economy plugin at a shared database is the better answer. See docs/vault-economy-plan.md.
  • Homes, claims and other plugin data are not synchronised.
  • Folia is not supported. Scheduling is confined to a few call sites, so adding it later is not a rewrite.

Metrics

InvSYNC reports anonymous usage data to bStats: server software and version, Java version, player count, and a handful of InvSYNC settings (timeout behaviour, which sections are synchronised, snapshot count, whether economy sync is on, and how many saves are currently parked on disk). No player names, no UUIDs, no inventory data, no database credentials.

Opt out for every plugin at once in plugins/bStats/config.yml.

License

GNU General Public License v3.0. See LICENSE.

Information

Category
Admin Tools
Published
August 22, 2026
License
1Downloads
0Stars

Pinned Versions

Members

1