File Details
arcadia-lib-1.2.8
- R
- Apr 30, 2026
- 2.52 MB
- 29
- 1.21.1
- NeoForge
File Name
arcadia-lib-1.2.8.jar
Supported Versions
- 1.21.1
Curse Maven Snippet
## [1.2.8] - 2026-04-30 (latest)
### Fixed
- **Black screen / "world disappeared" when rejoining any world after a first quit (integrated client)** — `DatabaseManager.EXECUTOR` was a `static final ExecutorService` initialized once at class load. `shutdown()` (called when leaving a world) terminated the pool but never recreated it; the next `initialize()` call on a different world simply set `inMemoryMode=true` and returned without touching the executor. The first DB-async submit after re-login (typically `AuctionManager.drainMailbox` from `AuctionEventHandler.onPlayerLogin`) then hit `RejectedExecutionException: pool Terminated`, and the cascade nulled out `IPayloadContext.channelHandlerContext()` mid payload-split — the player got kicked with `Couldn't place player in world` and the client rendered a black screen. Two-front fix: (1) `EXECUTOR` is now a non-final volatile field rebuilt on demand by `ensureExecutor()`, and `initialize()` calls it on every entry so a re-login always has a live pool. The executor uses daemon threads named `ArcadiaLib-DB`. (2) `executeAsync` / `supplyAsync` defensively check `isShutdown() || isTerminated()` and fall back to inline execution rather than throwing — better one tick of main-thread work than a kicked player. `initialize()` also resets `inMemoryMode=false` on entry so a debug → integrated → dedicated transition picks up the right backend.
### Correctifs
- **Écran noir / « le monde a disparu » au moment de rejoindre n'importe quel monde après un premier quit (client intégré)** — `DatabaseManager.EXECUTOR` était un `static final ExecutorService` initialisé une seule fois au chargement de la classe. `shutdown()` (appelé en quittant un monde) terminait le pool sans jamais le recréer ; l'`initialize()` suivant sur un autre monde positionnait juste `inMemoryMode=true` et sortait sans toucher l'executor. Le premier submit DB async après reconnexion (typiquement `AuctionManager.drainMailbox` depuis `AuctionEventHandler.onPlayerLogin`) déclenchait alors `RejectedExecutionException: pool Terminated`, et la cascade nullifiait `IPayloadContext.channelHandlerContext()` au milieu d'un payload-split — le joueur se faisait kick avec `Couldn't place player in world` et le client affichait un écran noir. Correction sur deux fronts : (1) `EXECUTOR` devient un champ volatile non-final reconstruit à la demande par `ensureExecutor()`, et `initialize()` l'appelle à chaque entrée pour qu'une reconnexion ait toujours un pool vivant. L'executor utilise des threads daemon nommés `ArcadiaLib-DB`. (2) `executeAsync` / `supplyAsync` vérifient défensivement `isShutdown() || isTerminated()` et tombent sur une exécution inline plutôt que de jeter — mieux vaut un tick de main-thread qu'un joueur kické. `initialize()` réinitialise aussi `inMemoryMode=false` à l'entrée pour qu'une transition debug → intégré → dédié reprenne le bon backend.

