Closes the YOU500 inventory-loss path documented in AUDIT-2026-05-07.md. Bumps to 1.1.0 per CHANGELOG. F1 — void-damage guard: new EntityDamageEvent listener at HIGHEST, ignoreCancelled=true. While a UUID sits in pendingTransit, DamageCause.VOID is cancelled, the player is healed to 20.0, fall/fire reset, sync-TP back to limbo spawn. Console gets a WARN with intended TP target. This single guard would have saved YOU500's inventory. F2 — recovery on teleportAsync false / exception: replaces the previous log-only branch in doTeleport. On failure: sync-TP to limbo spawn, bump per-UUID retry counter, schedule retry after 30 ticks. After MAX_RETRIES=3 failures: leave at limbo spawn in GameMode.SPECTATOR, log SEVERE with full saved coords + reason, alert console for manual `/authlimbo tp` action. Player stays in pendingTransit across retries so F1 keeps protecting them. F4 — pre-empt AuthMe's broken teleport: new LoginEvent handler at EventPriority.LOWEST that adds the UUID to pendingTransit and sync-TPs the player to limbo spawn BEFORE AuthMe-ReReloaded's own internal post-login teleport runs. AuthMe's teleport then operates against an irrelevant location; the existing MONITOR handler still wins last with the authoritative restore. Net effect: closes the void-death window even when the saved chunk is far out and slow to load. Internal: ConcurrentHashMap-backed pendingTransit set + retryCounts map, both watchdog-timed-out after 5 s so we never leak entries on edge cases. No new Maven dependencies. Privacy invariant unchanged — F4 actually strengthens limbo-on-join by guaranteeing the limbo position is reasserted at LOGIN-LOWEST. Build: mvn -B clean package (in maven:3.9-eclipse-temurin-21 container) -> BUILD SUCCESS, AuthLimbo-1.1.0.jar produced.
4.6 KiB
4.6 KiB
Changelog
All notable changes to AuthLimbo are documented here. The format is based on Keep a Changelog, and the project follows Semantic Versioning.
[1.1.0] - 2026-05-07
Data-loss bug fix release. Triggered by the YOU500 incident on
racked.ru at 2026-05-07 17:13:39 UTC — full inventory void-death during
AuthMe's post-login teleport. See AUDIT-2026-05-07.md for the full
forensic trace and ROADMAP.md for tracking.
Added
- F1 — VOID-damage guard during post-login restore. New
EntityDamageEventlistener atEventPriority.HIGHEST, ignoreCancelled=true. While a player UUID sits inpendingTransit(post-LoginEvent, pre-restore-success),DamageCause.VOIDevents are cancelled, the player is healed to full, and sync-teleported back to limbo spawn. Console gets a WARN with the player name + intended TP target. This single guard would have saved YOU500's inventory. - F2 — Recovery on
teleportAsyncfuture == false. The previous log-and-abandon branch inLoginListener.doTeleportis replaced with a retry loop. On any failure (false future, exceptional future, or chunk-load throw): synchronously snap the player back to limbo spawn, increment a per-UUID retry counter, schedule anotherdoTeleportafter 30 ticks (~1.5 s). After 3 failures: leave the player at limbo spawn inGameMode.SPECTATOR, log SEVERE with full saved coords + retry count, and alert console with manual-intervention instructions (/authlimbo tp <player>). Players stay inpendingTransitacross retries so F1 keeps protecting them. - F4 — Pre-empt AuthMe's broken teleport. New
LoginEventlistener atEventPriority.LOWEST(runs BEFORE AuthMe-ReReloaded's own internal post-login teleport). Action: synchronously TP the player back to limbo spawn and add their UUID topendingTransit. AuthMe's subsequent teleport then operates against an irrelevant location, and our existing MONITOR handler still wins last with the authoritative restore. Net effect: closes the void-death window even when the saved chunk is far out and slow to load.
Internal
- New
Set<UUID> pendingTransit(ConcurrentHashMap.newKeySet) andMap<UUID, Integer> retryCountsonLoginListener. Both are watchdog-timed-out after 5 s so we never leak entries on edge cases. - Constants:
MAX_RETRIES=3,RETRY_DELAY_TICKS=30,PENDING_TIMEOUT_TICKS=100. - No new Maven dependencies. No new public API.
Privacy
- Limbo-on-join invariant unchanged. F4 actually strengthens it by guaranteeing the limbo position is reasserted at LOGIN-LOWEST.
Test plan (reproduces YOU500 in dev Paper 1.21.x + AuthMe-ReReloaded fork b49)
- Set saved coord far out (e.g. X=10000, Z=10000) in
authme.dbfor a test account so the chunk is unloaded at login. Restart server. Login. Expect: F4 sync-TPs to limbo spawn first; F2 retries on false future; F1 catches any VOID damage during transit; player ends up at saved coords with full inventory. - Set saved Y above world build limit (e.g. 5000). Login. Expect: F2 recovery branch retries up to 3 times, then drops the player into spectator at limbo spawn with admin alert.
- Trigger a synthetic VOID damage during transit (debug command). Expect: F1 cancels the damage, snaps player back to limbo spawn at full health, restore continues.
[1.0.0] - 2026-04-30
Initial public release.
Added
- Auth-limbo void world manager. Creates and configures
auth_limboworld with no Multiverse-Core dependency. - AuthMe
LoginEventlistener atMONITORpriority. Reads saved quit coordinates directly fromplugins/AuthMe/authme.db(SQLite, read-only) and forces a delayedteleportAsyncto those coordinates after AuthMe's own broken teleport runs. AuthMeAsyncPreLoginEventlistener for chunk preload. Pins the destination chunk viaChunk#addPluginChunkTicketbefore login completes to avoid the unloaded-chunk race documented in Paper #4085. Tickets are released 5 seconds after the teleport completes.- Optional 5x5 barrier platform at limbo spawn so unauth players can't fall into the void.
/authlimbo reloadand/authlimbo tp <player>admin commands gated onauthlimbo.admin.- Shaded SQLite JDBC driver (
org.xerial:sqlite-jdbc 3.46.1.3, relocated toru.authlimbo.shaded.sqlite) so the plugin reads AuthMe's database without classpath collisions.
Compatibility
- Paper / Purpur 1.21.11 (api-version
1.21). - Java 21.
- AuthMe-ReReloaded HaHaWTH fork b49 (
fr.xephi:authme:5.6.0-FORK-b49) as a hard dependency.