File Details
arcadia-lib-1.2.14
- R
- Jun 9, 2026
- 2.57 MB
- 1.1K
- 1.21.1
- NeoForge
File Name
arcadia-lib-1.2.14.jar
Supported Versions
- 1.21.1
Curse Maven Snippet
## [1.2.14] - 2026-06-08 (latest)
### Fixed
- **Staff/ranked players lost ALL cosmetics when LuckPerms bound late (regression)** — `LuckPermsBackend.createOrFallback()` ran at `ServerAboutToStartEvent`; if LuckPerms had not finished registering its provider yet, `LuckPermsProvider.get()` threw, the backend resolved to `null`, and `PermissionService` fell back to `DENY` (fail-closed) for the whole session. Every `arcadia.cosmetic.*` check — wildcard included — then returned `false`, so staff and VIP/MVP players saw all cosmetics locked. The backend now **binds lazily**: when LuckPerms is not ready at init it defers and re-resolves the provider on first use, so wildcard and grade nodes work again as soon as LuckPerms is up. No hard-coded staff bypass introduced.
- **Permission checks raced ahead of LuckPerms' user cache** — `LuckPermsBackend` returned `false`/`default` when `getUserManager().getUser()` returned `null` (user not yet cached, e.g. a GUI built on the same tick as join). It now loads the user synchronously (`loadUser().join()`) as a fallback before checking.
- **Real LuckPerms init failure cause is now logged** — `createOrFallback()` logs the exception message (not just the class name) and distinguishes "not ready yet" from "genuinely absent".
- **`AchievementManager.loaded` visibility** — Made `volatile`: it is written by `init()` and read via `isLoaded()` from background DB/scheduler threads, so a reader could observe a stale value.
### Performance
- **`LuckPermsBackend.getGrade()` resolves permission data once** — was re-resolving `QueryOptions` context up to three times per call (MVP/VIP+/VIP probes); now probes all three grade nodes against a single resolved `PermissionData`.
- **`DashboardScreen` no longer recomputes carousel neighbours every frame** — prev/next nav targets (each doing a list alloc + sort) were recomputed in `render()` and `mouseClicked()`; now cached and refreshed only when the observed tab changes.
- **`ArcadiaHubScreen.drawCard()` drops redundant `Component` allocations** — label/sub-label were wrapped in a `Component.literal(translatable.getString())` every frame per card; now kept as translatables (language-correct) and resolved lazily only on the text-wrap path.
- **`TextFormatter.format()` single-pass placeholder replacement** — replaced the per-key `String.replace()` loop (a full scan + new `String` each key) with one regex pass; values are inserted literally via `quoteReplacement` and unknown `{keys}` are preserved, matching the old semantics.
### Correctifs
- **Les joueurs staff/gradés perdaient TOUS leurs cosmétiques quand LuckPerms se liait tard (régression)** — `LuckPermsBackend.createOrFallback()` s'exécutait au `ServerAboutToStartEvent` ; si LuckPerms n'avait pas fini d'enregistrer son provider, `LuckPermsProvider.get()` levait une exception, le backend valait `null`, et `PermissionService` retombait sur `DENY` (fail-closed) pour toute la session. Toute vérification `arcadia.cosmetic.*` — wildcard inclus — renvoyait alors `false`, donc le staff et les VIP/MVP voyaient tous les cosmétiques verrouillés. Le backend se **lie désormais paresseusement** : si LuckPerms n'est pas prêt à l'init, il diffère et re-résout le provider au premier usage, donc les nodes wildcard et de grade refonctionnent dès que LuckPerms est disponible. Aucun bypass staff codé en dur introduit.
- **Les vérifications de permission devançaient le cache utilisateur de LuckPerms** — `LuckPermsBackend` renvoyait `false`/`default` quand `getUserManager().getUser()` renvoyait `null` (utilisateur pas encore en cache, ex. un GUI construit au tick de la connexion). Il charge désormais l'utilisateur de façon synchrone (`loadUser().join()`) en repli avant de vérifier.
- **La vraie cause d'échec d'init LuckPerms est désormais journalisée** — `createOrFallback()` journalise le message de l'exception (pas seulement le nom de classe) et distingue « pas encore prêt » de « réellement absent ».
- **Visibilité de `AchievementManager.loaded`** — Passé en `volatile` : écrit par `init()` et lu via `isLoaded()` depuis des threads DB/scheduler en arrière-plan, un lecteur pouvait voir une valeur périmée.
### Performance
- **`LuckPermsBackend.getGrade()` résout les données de permission une seule fois** — re-résolvait le contexte `QueryOptions` jusqu'à trois fois par appel (sondes MVP/VIP+/VIP) ; sonde désormais les trois nodes de grade contre une unique `PermissionData` résolue.
- **`DashboardScreen` ne recalcule plus les voisins du carrousel à chaque frame** — les cibles nav prev/next (chacune avec une allocation de liste + tri) étaient recalculées dans `render()` et `mouseClicked()` ; désormais mises en cache et rafraîchies seulement quand l'onglet observé change.
- **`ArcadiaHubScreen.drawCard()` supprime des allocations `Component` redondantes** — le label/sous-label était enveloppé dans un `Component.literal(translatable.getString())` à chaque frame par carte ; conservé désormais en translatable (correct pour la langue) et résolu paresseusement uniquement sur le chemin de retour à la ligne.
- **`TextFormatter.format()` remplacement des placeholders en une passe** — remplacé la boucle `String.replace()` par clé (un scan complet + une nouvelle `String` par clé) par une unique passe regex ; les valeurs sont insérées littéralement via `quoteReplacement` et les `{clés}` inconnues sont préservées, conformément à l'ancienne sémantique.

