Inventory sync, item tracking & locks
Three modules that build on each other:
| Module | Contents | requires |
|---|---|---|
inventory-sync | Inventories of all players in the database; /invsee for online and offline players and players on other servers; optionally a shared inventory for several servers; overflow storage for full inventories | – |
item-tracking | Invisible item IDs, complete history, chest registry, stock, statistics, assignment, /deleteitem | inventory-sync |
locks | Item and chest locks, automatic locks by quantity | item-tracking |
License: inventory-sync, item-tracking and locks need an EternalSystem license. Free in the base by default are core, punishments, reports and lobby; which modules are free can change – the dashboard shows locked modules grayed out.
Enabling
- Enable the modules on every game server, e.g. via the
survivaloreconomypreset (see Modules & Presets). - Also enable
inventory-syncon the proxy:/invseeruns there, resolves offline targets and players on other servers, and opens the GUI on the viewer's server. - All servers and the REST API need the same MySQL database.
- Everything is in the
inventory-syncsection ofconfig.yml(same file on Spigot and proxy).
Inventory sync
inventory-sync:
enabled: true
mode: separate # separate = each server has its own inventory, global = one for the whole network
groups: {} # only with separate: servers with a shared inventory
# survival: [survival-1, survival-2]
parts:
inventory: true
armor: true
offhand: true
enderchest: true
experience: true
health: true
hunger: true
effects: true
gamemode: false
autosave-seconds: 60 # snapshot interval for online players; quitting always saves immediately
join-load-timeout-ms: 3000 # how long the new server waits for the old server's quit save
| Option | Default | Meaning |
|---|---|---|
mode | separate | separate: every server stores its own inventory (for viewing only). global: one inventory for the whole network, loaded on join and saved on quit/server switch. |
groups | {} | In separate mode: servers in a group share one inventory. |
parts.* | everything except gamemode | What is saved and (with global/groups) carried over. |
Scope is the key of a saved inventory: the server name (separate), the group name or global. The dashboard and /invsee <Spieler> <Scope> show all scopes a player has ever had.
Server switch with global/groups: the old server writes the snapshot on quit and releases the sync session. Until then, the new server freezes the player (no inventory access, no picking up), then loads and applies the state. After a crash, every server releases its stuck sessions on startup.
In-game commands
| Command | Permission | Module | Description |
|---|---|---|---|
/invsee <Spieler> | eternal.base.invsee | inventory-sync | One view for all cases (inventory, hotbar, armor, offhand, ender chest button), always editable. Target on the same server: live in both directions. Target on another server: you are connected there. Target offline: saved state; changes are applied on the next join |
/invsee <Spieler> <Scope> | eternal.sync.view | inventory-sync | Saved state of a specific scope; editable with eternal.base.invsee or eternal.sync.edit, otherwise read only |
| Left-click in the read-only GUI | eternal.sync.history | item-tracking | Item history in chat |
| Right-click in the read-only GUI | eternal.sync.lock.item | locks | Lock/unlock the item |
/trackitem [history|<id>] (/itemtrack, /itemhistory) | eternal.sync.history | item-tracking | ID of the item in your hand (click copies) and who owned it before; history = full history, <id> = by ID |
/trackchest (/chesttrack, /trackcontainer) | eternal.sync.history | item-tracking | The chest/frame/block you are looking at: chest ID, owner, all users |
/deleteitem [Grund] (/delitem) | eternal.sync.delete.item | item-tracking | Without a reason ([Grund]): destroy GUI. With a reason: destroy the item in your hand immediately |
/itemlock <lock|unlock|info> [Grund] | eternal.sync.lock.item | locks | Lock the item in your hand |
/chestlock <hard|soft|off|info> [Grund] (/containerlock) | eternal.sync.lock.container | locks | Lock the container you are looking at |
/expandedinv [Spieler] (/ei) | eternal.expandedinv.use | inventory-sync | Open the overflow storage, taking out only (see overflow storage) |
Protection bypass for mods (module inventory-sync, no command): mods interact completely normally. If something forbids a right-click – a chest lock, PlotSquared, WorldGuard, GriefPrevention – Eternal lifts the ban only for the categories the player has a permission for. Vanilla then does the rest (the door opens, the chest opens live with animation). Whatever the mod is allowed to do anyway stays unchanged.
| Permission | Allowed despite protection | Default |
|---|---|---|
eternal.inspect.container.view | Open chests, barrels, shulkers, furnaces, hoppers … | Staff |
eternal.inspect.container.take | Take from chests opened this way (without it: click, shift-click, hotbar swap, double-click are blocked) | Admin |
eternal.inspect.container.put | Put into chests opened this way (without it: dragging and shift-click from your own inventory are also blocked) | Admin |
eternal.inspect.door | Doors, trapdoors, fence gates | Staff |
eternal.inspect.switch | Levers, buttons | Admin |
eternal.inspect.use | Other usable blocks (anvil, bed, note block, lectern …) | Admin |
eternal.inspect.* grants everything. A locked dragon egg is never released (a click would teleport it). If a locked gravity block (dragon egg, anvil, sand …) falls because its support is missing, it falls normally – the lock moves with it to where it lands. If it would break into an item in the process (torch trick), it jumps back to its place.
While an offline inventory is being edited, the GUI holds a lock. If the player joins, the GUI closes; the player gets a notice about the change. If the lock cannot be taken (player is online, someone else is editing), the GUI stays read-only.
Rank protection
As with punishments, the viewer needs a higher level than the target (level = maximum of eternal.tier.N and rank priority). This applies in-game and in the dashboard, for inventories and item histories (there, the current owner counts). eternal.sync.bypass or eternal.bypass remove the protection.
Without rank priorities and without eternal.tier.*, everyone has level 0 – then nobody can see other players' inventories. Staff then need eternal.sync.bypass.
Overflow storage (expanded inventory)
The overflow storage („Zwischenlager“, part of inventory-sync) catches what no longer fits into a full inventory. Every player turns it on themselves: /settings → Zwischenlager (expandedinv.collect, default off; the entry appears with eternal.expandedinv.use, see Player settings).
- Collecting: when it is on and the inventory is full, items you walk over go into the overflow storage. Auto-pickup drops that no longer fit into the inventory go there too.
- Network-wide: the storage lives in the database and is the same on all servers – at most 270 stacks (6 pages of 45).
- Taking out only:
/expandedinvor/eiopens it. A click puts the stack into your inventory if it fits completely. Putting items in is never possible. - Storage full: the player gets a message, the items stay on the ground.
- Rules still apply: every collection fires the normal pickup event – item locks, lobby protection, the
no_pickupperk (see Perks) and item tracking work just as with a normal pickup. - Dupe-safe across servers: changes use optimistic versioning; if two servers conflict, the change is retried.
Other players' overflow storage
| Usage | Permission | Default level |
|---|---|---|
/ei – your own storage | eternal.expandedinv.use | All |
/ei <Spieler> – player online on this server | eternal.expandedinv.others | Team |
/ei <Spieler> – offline or on another server | additionally eternal.expandedinv.others.offline | Team |
| Take items out of someone else's storage | eternal.expandedinv.others.take | Admin |
Every removal from someone else's storage is logged in the console. The same rank protection as for /invsee applies; eternal.sync.bypass removes it.
In the dashboard, a player's inventory page shows a Zwischenlager ("Overflow storage") card with all stacks and their lock state; a click on an item opens its history (permission eternal.web.inventory.view, API GET /players/{name}/expanded-inv).
Item tracking
Every item gets an invisible ID (eternal_item_id in the PersistentDataContainer; on 1.8–1.13 in a hidden lore line, see Versions). Logged are who had it when, which chest it is in (with coordinates and who put it there), and server switches.
inventory-sync:
item-tracking:
enabled: true
stack-mode: id # id = every stack has a stack ID, log = only history per material
stack-log-materials: [] # always in log mode, e.g. [COBBLESTONE, DIRT, NETHERRACK]
log-stack-hopper-moves: false # log hopper merges of stack-ID items (many rows)
container-flush-ticks: 10 # write live chest contents every X ticks, 0 = only on close
container-exclude-types: [] # e.g. [HOPPER] for huge farms
tracked-blocks: [SPAWNER, DRAGON_EGG, BEACON, ...] # keep their ID when placed
track-frames: true # log items in frames
log-hopper-moves: true
scan-interval-seconds: 3 # scan for new items without an event (/give, other plugins)
lock-refresh-seconds: 5 # reload locks from the DB
Stack IDs: a split stack keeps the ID only on the larger part; the other part immediately gets a new one (event SPLIT, in creative mode CLONED). When items come together (click, shift-click, double-click, pickup, hopper, furnace, crafting), they take over the ID of the target stack (MERGE); if an entire stack is absorbed into another, its ID is closed (STACKED).
Events (selection): REGISTER, PICKUP, DROP, DEATH_DROP, DESPAWN, CONTAINER_PUT/CONTAINER_TAKE, HOPPER_MOVE, CONTAINER_BROKEN, SERVER_SWITCH, LOCK/UNLOCK, MERGE, SPLIT, STACKED, DESTROYED (with cause: lava, fire, explosion, cactus, void, lightning, durability, consumed), DELETED (destroyed by staff), FRAME_PUT/FRAME_TAKE, PLACED/BROKEN, TRADE (see Party, friends & clans).
Chest registry: every chest, every frame and every placed special block gets a chest ID (#12). Contents are recorded live – player clicks, hoppers, droppers, furnaces, brewing stands, placing, breaking, explosions – and saved in one transaction every container-flush-ticks. Entity inventories (minecart with chest, donkey, llama) are not captured.
Known gaps: results from the stonecutter, anvil, grindstone, loom and villager trading land as a separate stack and only take over the ID on the next scan.
Destroying (/deleteitem)
/deleteitem opens a GUI: put items in, close it, then the chat asks for the reason for 10 seconds (no answer = no reason). Every stack is logged as DELETED with player, time and reason; untracked items get an ID first. Taking items out is only possible with eternal.sync.delete.item.take – without this permission, putting items in is final.
Locks
| Kind | Effect |
|---|---|
| Item lock | The item cannot be moved, dropped, placed or consumed – in the inventory as well as in the chest. Hoppers do not pull it. |
Chest HARD | The chest cannot be opened, broken or blown up; hoppers in/out are blocked. |
Chest SOFT | The chest opens, but nothing can be taken out. Putting items in is still allowed; breaking is blocked. |
| Frame / placed block | One lock; breaking, explosions, pistons (and for the dragon egg, the teleport) are blocked. |
Double chests: a lock on one half protects both. Parts split off a locked stack inherit the lock. eternal.sync.lock.bypass ignores all locks. Locks from the dashboard or from other servers take effect after at most lock-refresh-seconds.
Automatic locks (dashboard, permission eternal.web.thresholds.manage): rules "lock from quantity X" per stack, chest, inventory or player, for one material or *, optionally only for one player, for chests optionally the chest itself (soft). The API checks every 15 s. Owners with eternal.sync.lock.bypass are skipped.
Dashboard
| Page | Permission | Contents |
|---|---|---|
| Spieler ("Players") → Inventar ansehen ("View inventory") | eternal.web.inventory.view | Inventory per scope in the game layout (armor, 3×9, hotbar, ender chest, effects, level/health/hunger); click on an item → history and lock |
| ↳ Zwischenlager ("Overflow storage") card | eternal.web.inventory.view | All stacks in the overflow storage with lock state; click → history |
| ↳ Remove items / „Zu mir“ ("To me") | eternal.web.inventory.edit | Online immediately, offline on the next join |
| Item-Tracking → Statistik ("Statistics") | eternal.web.tracking | What exists most, who has the most, new items and trading in 24 h, automatic locks |
| Item-Tracking → Items | eternal.web.inventory.view | Search by ID, material, name, owner, server, location (chest/player/ground), locked only; full history |
| Item-Tracking → Kisten ("Chests") | eternal.web.inventory.view | Filters (contains item, server, with contents, locked, broken; All/Chests/Placed), detail view with contents, tracked items, history; „Live“ refresh every 3 s |
| Item-Tracking → Kisten-Sperren ("Chest locks") | eternal.web.inventory.view | All locks, new lock by coordinates |
| Item-Tracking → Spieler ("Players") | eternal.web.tracking | Everything a player owns (inventories + chests) |
| Item-Tracking → Auto-Sperren ("Automatic locks") | eternal.web.thresholds.manage | Create/change rules |
| Set/lift locks | eternal.web.locks.manage | Buttons on the pages above |
| Teleport button on chests | eternal.web.tracking.teleport | Online: you are taken there in-game. Offline: /tppos x y z welt copied to the clipboard |
| Item tracking → Zurücksetzen ("Reset") | eternal.web.admin | Wipe tracking data network-wide (choose: items & history, stock, locks, auto-lock rules); confirm by typing "ZURÜCKSETZEN" |
Reset is final – take a backup first (Cloud › Backups or mysqldump). Within seconds the servers clear their caches and register everything players carry again. Items keep their id mark and reappear in the registry on their next contact. Deleting directly in the database is not needed (and leaves the servers' caches stale).
Every item with an ID has an owner (the last player who held it). If it is in a shared chest, it stays assigned to them.
Permissions
| Permission | Default level | Purpose |
|---|---|---|
eternal.base.invsee | Team | /invsee live and editable |
eternal.sync.view | Team | /invsee <Spieler> <Scope> |
eternal.sync.edit | Admin | Edit saved inventories |
eternal.sync.bypass | Admin | Bypass rank protection for inventories and history |
eternal.sync.history | Team | /trackitem, /trackchest, chest ID in the chest title |
eternal.sync.lock.item | Admin | /itemlock |
eternal.sync.lock.container | Admin | /chestlock |
eternal.sync.lock.bypass | Admin | Ignore locks |
eternal.sync.delete.item | Admin | /deleteitem |
eternal.sync.delete.item.take | Admin | Take items back out of the destroy GUI |
eternal.expandedinv.use | All | Your own overflow storage and the „Zwischenlager“ setting |
eternal.expandedinv.others | Team | /ei <Spieler> on this server |
eternal.expandedinv.others.offline | Team | /ei <Spieler> offline / on other servers |
eternal.expandedinv.others.take | Admin | Take from other players' overflow storage (logged) |
In-game, the plugin.yml defaults also apply (e.g. eternal.sync.delete.item: op) as long as Eternal Perms does not define anything. See Permissions reference.
Common pitfalls
/invseedoes not find offline players:inventory-syncis missing on the proxy.- Inventory "jumps back" with
global: the old server saves too slowly – increasejoin-load-timeout-ms, check database latency. - Huge tables because of farms: put bulk goods in
stack-log-materials, leavelog-stack-hopper-moves: false, and if neededcontainer-exclude-types: [HOPPER]. - Item icons are missing in the dashboard: the icons come from
assets.mcasset.cloud. Ineternal-web/src/app/core/api.config.tsyou can pointtextureUrlto your own host or empty it (then only the material text is shown). - Edited offline inventories do not arrive: the player must join a server of the matching scope.