Test Procedure — PlayerSync v2.1.5
Date : 2026-04-22 | Branch: 1.21.1-dev | Minecraft 1.21.1 / NeoForge 21.1.137 / Java 21
Setup
- Démarrer MariaDB dev :
docker compose up -d
- Build :
./gradlew build — le JAR apparaît dans build/libs/playersync-1.21.1-2.1.5.jar
- Deux instances serveur nécessaires :
./gradlew runServer (Server A) + copie avec Server_id différent dans run-2/config/playersync-common.toml (Server B)
- Adminer :
http://localhost:8080 (login playersync/playersync)
- Monitorer en continu :
tail -f run/logs/playersync/sync.log
Scenarios to test
CRITICAL
1. Drop + deco rapide + reco (regression Phase 0)
Expected:
- Inventory does NOT contain the sword
- The ItemEntity is still on the ground where dropped
- Player has exactly 1 copy of the sword total
- Log shows
[SAVE] LOGOUT completed then either no SaveToFile BG write or a [GUARD] SaveToFile BG skipped — player already offline in DB
CRITICAL
2. Backpack duplication (Sophisticated Backpacks)
Expected:
- Exactly 10 diamond blocks (no duplication)
- Log shows
[restore-backpack] uuid=... nbt_keys=... cleared_via=api (or reflection as fallback)
- No WARN about failed removeBackpackContents
CRITICAL
3. Sophisticated Storage shulker duplication
Expected:
- Exactly original diamond count
- Log shows
[CONTAINER_CLOSE] for Player B (viewer forced closed)
- Log shows
[restore-ss] uuid=... nbt_keys=...
CRITICAL
4. Kill -9 / OOM recovery
Expected:
- On startup log:
[crash-recovery] cleared N orphan online=1 rows
- On startup log:
[crash-recovery] JVM shutdown hook installed AND ideally (if hook ran): [emergency-flush] flushed N players
- Inventory matches last state before kill (within ~10 min auto-save window)
HIGH
5. Zombie peer server join (no 30s wait)
Expected:
- Join happens within a few seconds (not 30s)
- Log shows
[RACE] Peer server 99999 is dead/zombie — taking over
- DB now shows
last_server=<thisServer>, online=1
HIGH
6. Periodic auto-save (10 min)
Expected:
- Log shows
[periodic-save] queued snapshots for N player(s) after 1 min
- Post-crash inventory reflects the state AT the last periodic tick
HIGH
7. Pool saturation WARN log
Expected:
- At least one line like
[POOL] executor active=0 queue=0 pool_idle=4 | hikari active=0 idle=4
- No WARN unless under load
HIGH
8. Heartbeat updates server_info
Expected:
last_update advances by ~10000 ms at every refresh
- Log shows
[heartbeat] started on boot
MEDIUM
9. Curios capability unavailable — no wipe
Expected:
- If cap was unavailable: log shows
[store-curios] handler unavailable for ... skipping write
- Curios row in DB NOT wiped
MEDIUM
10. Cross-server claim + downstream short-circuit
Expected:
- Server A may log
[GUARD] (last_server guard blocked) if B claimed during A's save
- If blocked:
[SAVE_SKIP] LOGOUT skipped: core guard blocked
- Player inventory on B = inventory as it was on A (no merge, no overwrite)
Regression checks
Watch for these regressions after Phase 0-5 deployment:
- TPS drop during auto-save ticks (periodic save at 10 min should be invisible to gameplay)
- HikariCP leak warnings —
leakDetectionThreshold=25000, warnings mean a connection held >25s
- CallerRunsPolicy triggering (queue full) — look for WARN
[pool-stats] executor queue high
- Deadlock on logout → join (bgLock serialization) — log should show
[SAVE] LOGOUT completed within ~500ms
- Reflection fallback firing repeatedly — means upstream removeBackpackContents / removeStorageContents API broke
Procédure de Test — PlayerSync v2.1.5 (Version Française)
Date : 2026-04-22 | Branche : 1.21.1-dev | Minecraft 1.21.1 / NeoForge 21.1.137 / Java 21
Mise en place
- Démarrer MariaDB dev :
docker compose up -d
- Build :
./gradlew build — le JAR sort dans build/libs/playersync-1.21.1-2.1.5.jar
- Deux instances serveur nécessaires :
./gradlew runServer (Serveur A) + copie avec Server_id différent dans run-2/config/playersync-common.toml (Serveur B)
- Adminer :
http://localhost:8080 (login playersync/playersync)
- Monitorer en continu :
tail -f run/logs/playersync/sync.log
Scénarios à tester
CRITIQUE
1. Drop + déco rapide + reco (régression Phase 0)
Résultat attendu :
- L'inventaire ne contient PAS l'épée
- L'ItemEntity est toujours au sol où elle a été drop
- Le joueur a exactement 1 copie de l'épée au total
- Logs :
[SAVE] LOGOUT completed puis soit aucun write SaveToFile BG, soit [GUARD] SaveToFile BG skipped — player already offline in DB
CRITIQUE
2. Duplication Backpack (Sophisticated Backpacks)
Résultat attendu :
- Exactement 10 blocs de diamant (pas de duplication)
- Logs :
[restore-backpack] uuid=... nbt_keys=... cleared_via=api (ou reflection en fallback)
- Aucun WARN sur un removeBackpackContents raté
CRITIQUE
3. Duplication shulker Sophisticated Storage
Résultat attendu :
- Compte de diamants identique à l'original
- Logs :
[CONTAINER_CLOSE] pour le Joueur B (viewer force-fermé)
- Logs :
[restore-ss] uuid=... nbt_keys=...
CRITIQUE
4. Recovery kill -9 / OOM
Résultat attendu :
- Au boot : log
[crash-recovery] cleared N orphan online=1 rows
- Au boot :
[crash-recovery] JVM shutdown hook installed ET idéalement (si le hook a tourné) : [emergency-flush] flushed N players
- L'inventaire correspond au dernier état avant kill (dans la fenêtre auto-save ~10 min)
HIGH
5. Join sur serveur peer zombie (pas d'attente 30s)
Résultat attendu :
- La connexion se fait en quelques secondes (pas 30s)
- Logs :
[RACE] Peer server 99999 is dead/zombie — taking over
- La DB affiche maintenant
last_server=<thisServer>, online=1
HIGH
6. Auto-save périodique (10 min)
Résultat attendu :
- Log :
[periodic-save] queued snapshots for N player(s) après 1 min
- L'inventaire post-crash reflète l'état AU dernier tick périodique
HIGH
7. Log WARN sur saturation pool
Résultat attendu :
- Au moins une ligne comme
[POOL] executor active=0 queue=0 pool_idle=4 | hikari active=0 idle=4
- Aucun WARN sauf sous charge
HIGH
8. Heartbeat update server_info
Résultat attendu :
last_update avance de ~10000 ms à chaque refresh
- Log :
[heartbeat] started au boot
MEDIUM
9. Capability Curios absente — pas de wipe
Résultat attendu :
- Si cap absente : log
[store-curios] handler unavailable for ... skipping write
- Row curios en DB NON wipée
MEDIUM
10. Claim cross-server + court-circuit downstream
Résultat attendu :
- Serveur A peut logger
[GUARD] (last_server guard a bloqué) si B a claim pendant la save de A
- Si blocké :
[SAVE_SKIP] LOGOUT skipped: core guard blocked
- Inventaire joueur sur B = inventaire tel qu'il était sur A (pas de merge, pas d'overwrite)
Vérifications régressions
Surveiller ces régressions après le déploiement Phases 0-5 :
- TPS drop pendant les ticks auto-save (la save périodique à 10 min doit être invisible gameplay)
- Warnings HikariCP leak —
leakDetectionThreshold=25000, warnings = connexion tenue >25s
- Déclenchement CallerRunsPolicy (queue pleine) — WARN
[pool-stats] executor queue high
- Deadlock sur logout → join (sérialisation bgLock) — le log doit montrer
[SAVE] LOGOUT completed en ~500ms
- Fallback reflection qui tourne répétitivement — signifie que l'API upstream removeBackpackContents / removeStorageContents a été cassée
Author: vyrriox | PlayerSync v2.1.5 | 2026-04-22