promotional bannermobile promotional banner

Arcadia Lib

Arcadia Lib is the shared foundation required by all Arcadia Pets, Prestige and AH. It provides the database layer, player data management and debug mode.

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

NeoForge

implementation "curse.maven:arcadia-lib-1493170:8016671"
Curse Maven does not yet support mods that have disabled 3rd party sharing

Learn more about Curse Maven

## [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.