arcadia-prestige-1.21.1-1.3.0
Curse Maven Snippet
What's new
Added
- Solo progression, earn cosmetics by playing. New
[solo_progression]config section turns cosmetic effects into something a singleplayer world or a private server can actually work towards. Players accumulate Prestige Points from play time, mob and boss kills, quest claims, daily rewards, daily milestones, duel wins and advancements (every source has its own configurable rate, and0disables it), then spend them to unlock any effect permanently. Costs are set per tier (vip/vip_plus/mvp/founder) with per-effect overrides in a"rainbow=25000,orbit=500"style string, and an optionaldaily_capbounds how much can be earned per real day.modeis what keeps the shop economy intact.AUTO(the default) enables progression only when no permission backend is bound, which is the signature of a singleplayer world, a LAN game or a private server; an official server running LuckPerms is left completely untouched.ALWAYSenables it everywhere,NEVERguarantees it never runs. Unlocks are additive and never remove rank-granted access, and switching the system off later leaves stored unlocks on disk, simply unconsulted.- Two storage backends. The database is used whenever arcadia-lib has an active pool; otherwise progress is written to
config/arcadia/prestige/solo_progress.json. Without that fallback progression would reset on every restart in exactly the setup it exists for. Writes are debounced and flushed off the main thread, on logout and on server stop. - Anti-AFK. The per-minute reward only pays out when the player's position or view angle changed since the previous sample, so mining in place still counts but an AFK pool does not.
- Bad config cannot open the shop up. An unrecognised
modeis corrected back toAUTOon load rather than crashing or landing in an undefined state, and becauseAUTOswitches itself off wherever LuckPerms is bound, a typo on a ranked server leaves progression disabled. Malformedoverridesentries are skipped individually with a named warning while the valid ones still apply. Both paths were exercised on a running server. - New commands:
/arcadia_prestige progress(own summary, next unlock, what is affordable), plus OP-onlyprogress status|give|set|reset|unlock|lock.
- Ten effects made of real blocks and items, bringing the roster to 65: A third wave, all of them static, all carrying solid game models on top of their particles. Grimoire (VIP) circles three books at chest height, Harvest (VIP) walks pumpkins and hay up a rising helix, Apiary (VIP) keeps a loose swarm of honeycomb that never falls into step, Forge (VIP+) turns an anvil, an iron block and a blast furnace in a shower of sparks, Obelisk (VIP+) stacks a chiselled stone column above the head, Hoard (MVP) drags a wide low ring of gold, emerald, diamond and lapis, Arsenal (MVP) swings netherite weapons on a vertical ring that itself rotates, Orrery (Founder) runs a working solar system with a glowstone star and three planets on widening rings, Sentinels (Founder) locks two crying obsidian guardians to the shoulders so they follow the body rather than the world, and Regalia (Founder) wears a crown band of gold, diamond and netherite.
- The block companion system is data now. Comet and Meteor had carried a block since 1.2.x through a hardcoded pair of block states and two hand-written orbits. What is drawn and how it moves is declared next to the effect itself, in one of nine placement patterns, so an effect and its companion can no longer drift apart.
- Blocks and items are the same thing. Every piece goes through the item renderer with the identity display context, so a block item comes out as a small solid cube and a flat item as the sprite players know from the ground, with the scale meaning the same for both. That is what lets Arsenal carry an actual trident and Grimoire an actual enchanted book.
- The cost is bounded on purpose. A model draw is far more expensive than a particle and none of them batch. Pieces are halved past half the configured render distance, the pass stops at 96 pieces per frame across everyone in view, and
render_block_companions = falseskips it entirely. The particle passes for these ten are deliberately restrained so they light the pieces rather than compete with them.
- Twenty further effects, bringing the roster to 55: A second wave, five per rank tier. Static: Firefly and Ember (VIP), Crystal and Tide (VIP+), Sanctum, Vortex and Beacon (MVP), Abyss, Aurora and Seraph (Founder). Movement: Dash, Dust and Windrun (VIP), Frostpath, Thunderstep and Magma (VIP+), Stardust and Venom (MVP), Spectre and Celestial (Founder). The Cosmetics tab now spans five pages: pages 0 to 2 are the 40 static effects, pages 3 and 4 the 25 movement ones, so a player looking for one kind never has to hunt across a mixed page. The tier shown is a built-in default used for solo-progression pricing and for the UI label when LuckPerms has no opinion; on a ranked server the group holding the node still decides.
- Ten new cosmetic effects, bringing the roster to 35: Static: Frost (hex ice crown, frozen rune ring, drifting motes), Arcane (three counter-rotating runic circles with inscribed glyphs and inward-drawn mana), Lotus (breathing petal mandala at the feet with pollen lift-off), Eclipse (dark disk above the head with a flaring corona and solar prominences), Prism (rotating triangular prism casting a spectral refraction fan). Movement: Bloom (flowers sprouting in your footsteps), Runes (glowing glyph tablets left behind), Tempest (wind vortex and cloud puffs churning behind you), Phoenix (beating burning wings with an ember wake), Inferno (scorched ground, heat haze and lava spurts). The Cosmetics tab now spans three pages (Static I-IV, Movement I-III).
- Client config,
config/arcadia/prestige/client.toml. Purely local rendering preferences, nothing sent to the server and nothing affecting gameplay: particlequality(AUTOfollows the vanilla particle slider, plusHIGH/MEDIUM/LOW/OFF),max_visible_effects,max_distance,near_distance,hide_own_effects_first_person(now persisted across restarts instead of resetting every launch),show_other_players_effects,hide_invisible_players,render_block_companionsandreopen_dashboard_on_exit. - Feature switches,
[features]. Independent master switches forcosmetics,daily_rewards,quests,eloandeffect_preview. Turning one off stops its event tracking and shows a clear notice in its tab; nothing is deleted, so flipping it back on restores the saved state. - Quality-of-life commands:
/arcadia_prestige effect <id>andeffect off(with tab completion over every effect id, permission-checked server-side),preview [effect],stats(streak, ELO, quests, cosmetics owned, points),questsandleaderboard(both documented in the README since 1.2.x but never actually implemented), andcosmetics rescan(documented inCosmeticPermissionScanner's javadoc since 1.2.14 but never wired up). - Preview HUD names the row: With 65 effects a bare "21/65" says nothing about where you are, so the overlay now shows which dashboard row the effect belongs to, using the same label the Cosmetics tab uses. Shift-scroll steps by five, which is exactly one row, so the readout doubles as a guide to what that jump does.
- Keybinds:
Equip previewed effect(defaultR) and two unbound-by-default keys,Open effect previewandShow/hide your own effects, so installing the mod never steals a key a player already uses. [performance]config section:batch_login_sync,quest_cache_daysandleaderboard_cache_secondsexpose the tuning behind the fixes below.
Fixed
- Effect preview was completely dead: Clicking the spyglass in the Cosmetics tab did nothing at all. The click handler lived in
com.arcadia.prestige.client.DashboardScreen, a class that is never registered: since the dashboard moved to arcadia-lib the menu is bound tocom.arcadia.lib.client.DashboardScreen, so Prestige's copy was unreachable dead code and itsmouseClickednever ran. Server-side,CosmeticsTabHandler.handleClickhad no case for slot 47 either, so the click was swallowed on both sides. Preview is now driven from the server: the tab handler answers slot 47 by sending a newS2CStartPreviewpayload, which works regardless of which screen implementation is showing the menu and lets the server ship the authoritative unlocked-effect list with it. The deadDashboardScreenclass has been removed. - Preview no longer fights with effect syncing: It used to overwrite the shared
PlayerEffectCacheentry and restore it on exit, so anS2CParticleSyncarriving mid-preview clobbered what the player was looking at, and an interrupted exit could leave the wrong effect cached. Preview state now lives entirely inEffectPreviewHandlerand is merged in at render time, so it cannot be disturbed and needs no restore step. - Client effect state leaked across worlds:
PlayerEffectCache.clear()existed but had zero callers. Effects synced on one server stayed in memory after disconnect and reappeared in the next world joined in the same session, on whichever players happened to reuse those UUIDs. Now cleared onClientPlayerNetworkEvent.LoggingOut, together with the preview state and the renderer's position history. ParticleRendererposition history grew without bound:trailPositionsandlastPositionswere plainHashMaps that were only ever written to. Every player ever seen with an effect kept an entry, plus up to 14Vec3objects each, for the lifetime of the client. They are now swept periodically and cleared on disconnect.- Quest cache grew without bound:
QuestManager.CACHEkept every day a player had ever been seen on, for every player, for the process lifetime. Days beyondperformance.quest_cache_daysare now evicted, and a player's entry is dropped on logout. - Body-attached effects streamed out behind a moving player: Halos, rings, wings and discs visibly lagged while walking or sprinting instead of staying on the player. Minecraft particles are fire-and-forget world-space objects and nothing can attach one to an entity after it spawns;
DustParticleBasegives them a lifetime of up to 40 ticks, so a player sprinting at 0.28 blocks per tick left a static ring up to eleven blocks behind by the time it expired. Every emission site now routes through a helper that adds the owner's per-tick motion to the particle's velocity, for body-attached effects only, since movement effects are meant to be left behind. The carry is scaled per particle type against the decompiled vanilla source: Ă—10 for dust (which multiplies the supplied velocity by 0.1), Ă—1 for End Rod (which uses it directly), and skipped for types like Portal that treat the argument as a displacement amplitude rather than a velocity, where injecting a player's speed would distort the shape instead of moving it. A further 1.3Ă— over-compensation offsets the friction vanilla applies and cannot be disabled. This cannot be exact: measured across a dust particle's life at sprint speed it cuts the mean gap from 2.12 blocks to 1.18, and an End Rod's from 2.57 to 1.14, rather than to zero. Perfect adhesion would require custom entities, not particles. - Trail effects drew a dotted line instead of a trail: Rainbow, Stardust and Dash placed particles only on trail-history samples, which sit about 0.56 blocks apart at sprint speed. Each segment is now subdivided to a target spacing so the ribbon stays continuous at any pace. Dash additionally reused its lane index as the interpolation factor, so its streaks bunched at the start of every segment instead of spanning it. Subdivision is clamped tightly: measured at a looser clamp Rainbow reached 416 particles per pass against 112 before, so its history was shortened from 14 samples to 10 to pay for the added density, landing at 144.
- A null mob type crashed the duel result handler:
PlayerEloData.withWincalledmobType.isEmpty()straight on its argument, so aDuelResultEventcarrying a null mob type took down the whole ELO update with aNullPointerException.EloDatabase.loadreached the same code withResultSet.getString, which is null for a NULL column. The record now normalises null to blank in its constructor, covering every construction path, andwithWinkeeps the existing favourite rather than throwing. Found by compiling the class on its own and running it, since neither it norEloCalculatorhas any Minecraft dependency. - Unlock ordering was discarded on every save:
PlayerProgressstores unlocks in aLinkedHashSetfor deterministic ordering, then handed outSet.copyOf, whose iteration order is unspecified and randomised per JVM run. The persisted CSV was therefore rewritten in a different order on every save even when nothing had changed, churningsolo_progress.jsonand issuing pointless database updates. - Cosmetics tab lost its page indicator: the progression summary was placed in slot 49, which is where
DashboardTabHandler.buildBottomBarwrites the "page X / Y" paper. It is now in slot 48 and both coexist. - Solo progression had nothing to unlock in singleplayer:
PermissionService.canUseCosmeticdelegates to the lenienthasPermission, and with no permission backend bound the lib installsPERMISSIVEon an integrated server, which grants every permission. So a singleplayer world reported every cosmetic as already owned and progression could never sell anything, in exactly the environment it was written for.CosmeticAccess.hasRankGrantnow ignores that blanket grant while progression is active, and only then: a singleplayer world runningmode = "NEVER"still has every cosmetic free exactly as before 1.3.0, and a LuckPerms server is unaffected either way.PermissionService.canUseCosmeticis now called from a single place so a correction lands everywhere at once. - Equipping from preview did nothing, but claimed it worked: the preview's equip key sent the lib's
C2SDashboardAction.SELECT_PARTICLE, which dispatches toplayer.containerMenuand returns silently unless that menu is aDashboardMenu. Preview deliberately closes the dashboard, so the server ignored every equip while the client optimistically printed "Equipped …". A dedicatedC2SEquipEffectpayload now carries it, revalidates access server-side throughCosmeticAccess, and the confirmation message comes from the side that actually saves. - Québec French was missing 75 strings:
fr_ca.jsonhad never been brought up to date withfr_fr.json, so a large part of the hub, the quest tab, the leaderboard tab, the daily tab and every command message fell back to English. All live keys are now translated in both French files.
Performance
- Allocation-free particle tick loop: The per-tick nearest-player selection built a
HashMapof boxed distances, copied the entry set into anArrayListand full-sorted it, ten times a second, to then use at most ten results. It is now a bounded insertion into reusable fixed arrays: no collections, no boxing, no sort. - Gradient colours come from lookup tables: Rainbow allocated a fresh
DustParticleOptionsper particle: up to 14 trail positions Ă— 8 lanes = 112 allocations per render call, per player in view, ten times a second. Trail, Comet, Galaxy, Pulsar, Shockwave, Binary and Prism did the same on a smaller scale. All of them now read from pre-built tables (a 32Ă—8 hue/size grid, plus a 16-step ramp per gradient effect); quantisation at particle scale is visually indistinguishable. - Effect dispatch no longer allocates:
renderEffectcalledeffectId.toLowerCase(Locale.ROOT)on every dispatch. Ids are canonicalised once at the cache boundary and the switch reads them directly. Math.random()replaced by the sharedRandom: Helix, Meteor, Comet, Galaxy and Hearts usedMath.random(), which goes through a globally shared synchronized generator, on the render thread.- Bulk login sync: Joining a server sent one packet per online player with an active effect, so a full 100-slot server produced a burst of ~100 tiny payloads on every single join. They are now bundled into one
S2CParticleBulkSync(toggleable viaperformance.batch_login_sync). - ELO leaderboard is memoized: Opening the leaderboard tab re-sorted the entire rating cache, or re-queried the database, on every render including refreshes triggered by unrelated clicks. Results are cached for
performance.leaderboard_cache_secondsand invalidated when a duel moves a rating. - Cosmetic particles respect the vanilla particle slider: At the default
quality = AUTO,Decreasedhalves density andMinimalrenders nothing. A player who already turned vanilla particles down should not have to hunt for a second setting. - Invisible and spectator players are skipped: Effects no longer render through an Invisibility potion or for spectators, which was both a rendering cost and a PvP information leak.
- Rendering pauses when the game does: The tick loop now exits early on
Minecraft.isPaused(). - Per-pass particle budget:
max_visible_effectscounts players, not cost, and effects are nowhere near equally expensive: Hearts emits about 2 particles per pass, Rainbow about 112, a 50x spread that a player cap treats identically. Every effect now carries a render weight in the registry, and the client stops adding further-away effects onceparticle_budget(default 600) is used up. Typical mixed play spends about 250 and is unaffected; ten players all wearing Rainbow drop from ten rendered to six. The nearest effect is exempt, so the budget can never blank the screen, and0restores pure count-based limiting.
Changed
- Single source of truth for cosmetic effects: New
com.arcadia.prestige.cosmeticpackage (CosmeticEffects,CosmeticEffect,CosmeticGroup,CosmeticTier,CosmeticAccess). The effect list used to be duplicated across four places (the Cosmetics tab rows,CosmeticPermissionScanner.ALL_COSMETICS,EffectPreviewHandler.ALL_EFFECTSand the renderer's movement set), and drift between them is precisely what made whole GUI rows unclickable in 1.2.15. Adding an effect is now one line inCosmeticEffects, one render branch and one translation key per language. - All access checks route through
CosmeticAccess: A single place answers "may this player use this effect?", combining the LuckPerms grant with the progression unlock. That is what lets progression be switched off server-wide with every call site following automatically. - Network protocol version bumped to
2: An older client and a newer server now refuse to connect rather than silently mis-decoding the new payloads. - Declared
arcadia_libdependency corrected to[1.2.14,): It was[1.0.0,), which no version of Prestige has been able to honour for some time. 1.3.0 callsPermissionService.hasRealBackend,ArcadiaConfigPaths.dataFile,JsonFileStore,DatabaseManager.isDatabaseActive,LibMenusandStaffPetEntities, none of which exist in early lib releases, so an out-of-date library passed the dependency check and then died on aNoSuchMethodErrormid-startup. NeoForge now reports the real requirement before loading anything. The optionalarcadia_petsandarcadia_ahranges are deliberately left permissive: those are reached through the registry and reflection with vanilla fallbacks, so an old version degrades gracefully rather than needing to be blocked. The release workflow's generated notes were still advertising 1.2.0 as well. - Dead
PrestigeHubScreenandPrestigeCardremoved: Prestige's own full-screen hub, superseded when the hub moved to arcadia-lib and/arcadia_prestigestarted callingArcadiaLibNet.sendOpenHub. Neither had a single reference left: no Java call site, no resource entry, and the mod registers no screens at all.PrestigeCardalso carried a latent crash, resolvingLibModItems.ARCADIA_STAR.get()from a static initializer, which throws if the class is touched before the item registry is frozen. Thearcadia_prestige.hub.*translation keys are deliberately kept: unused strings cost nothing at runtime, and removing one that another Arcadia module turns out to reference would put a raw key on screen. - Dead
ArcadiaConfigremoved: A static holder with zero references left anywhere in the mod. Every value in it had already been superseded: grades byPrestigeConfigand lib'sPermissionConfig, particle distances and visible count by the newPrestigeClientConfig, andserver_idby lib'sServerContextback in 1.2.2. It also carried placeholder database constants including aDB_PASSfield, which has no business sitting in source even as a dev default.
The three entries below describe work carried out in arcadia-lib, not in this mod. They were already pending in the Unreleased section and are listed here because they change how Prestige behaves. No file in arcadia-lib was modified as part of 1.3.0; Prestige consumes it as a read-only
compileOnlydependency.
- Staff pet entities removed, moved to arcadia-lib.
StaffPetEntity,StaffPetEntities,StaffPetRendererand the 17 entity registrations now live in arcadia-lib (≥ 1.2.10). Lets arcadia-pets and arcadia-ah render Mythic staff pets without requiring Prestige to be installed (e.g. on a singleplayer save with only Pets + Lib). Existing pet items / AH listings carrying the legacyarcadia_prestige:staff_*mob type are migrated automatically by lib's namespace helper, no save migration needed. - Staff entity translation keys moved to arcadia-lib (
entity.arcadia_lib.staff_*). - Database / core service init removed from
ArcadiaDashboard:DatabaseConfig.SPECregistration plus the calls toDatabaseManager.initialize(),PlayerDataHandler.init(),EconomyService.init(),PermissionService.init()and the matchingshutdown()chain now live inArcadiaLib(≥ 1.2.10). Was the actual reason AH and Pets stopped working in any modset that didn't include Prestige.
Ajouts
- Progression solo, gagner des cosmétiques en jouant. La nouvelle section de config
[solo_progression]transforme les effets cosmĂ©tiques en quelque chose qu'un monde solo ou un serveur privĂ© peut rĂ©ellement viser. Les joueurs accumulent des Points de Prestige via le temps de jeu, les monstres et boss tuĂ©s, les quĂªtes rĂ©clamĂ©es, les rĂ©compenses journalières, les paliers journaliers, les duels gagnĂ©s et les progrès (chaque source a son propre taux configurable,0la dĂ©sactive), puis les dĂ©pensent pour dĂ©bloquer dĂ©finitivement n'importe quel effet. Les coĂ»ts se règlent par palier (vip/vip_plus/mvp/founder) avec des surcharges par effet dans une chaĂ®ne du style"rainbow=25000,orbit=500", et undaily_capoptionnel borne le gain par journĂ©e rĂ©elle.- C'est
modequi protège l'économie de la boutique.AUTO(par défaut) n'active la progression que si aucun backend de permissions n'est lié, ce qui est la signature d'un monde solo, d'une partie LAN ou d'un serveur privé ; un serveur officiel sous LuckPerms n'est absolument pas touché.ALWAYSl'active partout,NEVERgarantit qu'elle ne tourne jamais. Les déblocages sont additifs, ne retirent jamais un accès accordé par un grade, et désactiver le système plus tard laisse les déblocages sur disque, simplement ignorés. - Deux backends de stockage. La base de données est utilisée dès qu'arcadia-lib a un pool actif ; sinon la progression est écrite dans
config/arcadia/prestige/solo_progress.json. Sans ce fallback, la progression se rĂ©initialiserait Ă chaque redĂ©marrage prĂ©cisĂ©ment dans la configuration pour laquelle elle existe. Les Ă©critures sont regroupĂ©es et vidĂ©es hors du thread principal, Ă la dĂ©connexion et Ă l'arrĂªt du serveur. - Anti-AFK. La rĂ©compense par minute n'est versĂ©e que si la position ou l'angle de vue du joueur a changĂ© depuis le relevĂ© prĂ©cĂ©dent : miner sur place compte toujours, une ferme AFK non.
- Nouvelles commandes :
/arcadia_prestige progress(résumé personnel, prochain déblocage, ce qui est accessible), plusprogress status|give|set|reset|unlock|lockréservées aux OP.
- C'est
- Dix effets faits de vrais blocs et objets, portant le total Ă 65 : Une troisième vague, tous statiques, tous portant de vrais modèles de jeu en plus de leurs particules. Grimoire (VIP) fait tourner trois livres Ă hauteur de poitrine, Moisson (VIP) fait monter citrouilles et bottes de foin le long d'une hĂ©lice, Rucher (VIP) entretient un essaim de rayons de miel dont aucune pièce n'est en phase, Forge (VIP+) fait tourner une enclume, un bloc de fer et un haut fourneau dans une gerbe d'Ă©tincelles, ObĂ©lisque (VIP+) empile une colonne de pierre sculptĂ©e au-dessus de la tĂªte, TrĂ©sor (MVP) traĂ®ne un large anneau bas d'or, d'Ă©meraude, de diamant et de lapis, Arsenal (MVP) balance des armes en netherite sur un anneau vertical qui tourne lui-mĂªme, PlanĂ©taire (Founder) fait fonctionner un vrai système solaire avec une Ă©toile de pierre lumineuse et trois planètes sur des anneaux croissants, Sentinelles (Founder) fixe deux gardiens d'obsidienne pleureuse aux Ă©paules pour qu'ils suivent le corps et non le monde, et Couronne (Founder) porte un bandeau d'or, de diamant et de netherite.
- Le système de compagnons est devenu une donnĂ©e. Comète et MĂ©tĂ©ore portaient un bloc depuis les 1.2.x, via une paire d'Ă©tats de bloc en dur et deux orbites Ă©crites Ă la main. Ce qui est affichĂ© et comment ça bouge se dĂ©clare dĂ©sormais Ă cĂ´tĂ© de l'effet lui-mĂªme, dans l'un des neuf motifs de placement, pour qu'un effet et son compagnon ne puissent plus diverger.
- Blocs et objets sont la mĂªme chose. Chaque pièce passe par le renderer d'items avec le contexte d'affichage identitĂ© : un item de bloc sort en petit cube solide et un item plat en sprite tel qu'on le connaĂ®t au sol, l'Ă©chelle voulant dire la mĂªme chose pour les deux. C'est ce qui permet Ă Arsenal de porter un vrai trident et Ă Grimoire un vrai livre enchantĂ©.
- Le coĂ»t est bornĂ© volontairement. Un rendu de modèle est bien plus cher qu'une particule et aucun ne se groupe avec les autres. Le nombre de pièces est divisĂ© par deux au-delĂ de la moitiĂ© de la distance de rendu configurĂ©e, la passe s'arrĂªte Ă 96 pièces par frame tous joueurs confondus, et
render_block_companions = falsela saute entièrement. Les passes de particules de ces dix effets sont volontairement sobres, pour éclairer les pièces plutôt que leur faire concurrence.
- Vingt effets supplémentaires, portant le total à 55 : Une seconde vague, cinq par palier de grade. Statiques : Lucioles et Braises (VIP), Cristal et Marée (VIP+), Sanctuaire, Vortex et Balise (MVP), Abysse, Aurore et Séraphin (Founder). Mouvement : Élan, Poussière et Course du Vent (VIP), Sentier Gelé, Pas de Foudre et Magma (VIP+), Poussière d'Étoiles et Venin (MVP), Spectre et Constellation (Founder). L'onglet Cosmétiques compte désormais cinq pages : les pages 0 à 2 regroupent les 40 effets statiques, les pages 3 et 4 les 25 effets de mouvement, pour qu'un joueur cherchant un type n'ait jamais à fouiller une page mélangée. Le palier affiché est une valeur par défaut interne, utilisée pour le prix en progression solo et pour le libellé quand LuckPerms ne dit rien ; sur un serveur à grades, c'est le groupe qui détient le node qui décide.
- Dix nouveaux effets cosmĂ©tiques, portant le total Ă 35 : Statiques : Givre (couronne de glace hexagonale, cercle de runes gelĂ©es, particules flottantes), Arcane (trois cercles runiques contra-rotatifs avec glyphes inscrits et mana attirĂ©e vers le centre), Lotus (mandala de pĂ©tales au sol qui respire, avec envol de pollen), Éclipse (disque sombre au-dessus de la tĂªte, couronne solaire pulsante et protubĂ©rances), Prisme (prisme triangulaire rotatif projetant un Ă©ventail de rĂ©fraction spectral). Mouvement : Floraison (des fleurs poussent dans tes pas), Runes (tablettes de glyphes lumineux laissĂ©es derrière toi), TempĂªte (vortex de vent et bouffĂ©es de nuages dans ton sillage), PhĂ©nix (ailes enflammĂ©es battantes et traĂ®nĂ©e de braises), Brasier (sol calcinĂ©, air brĂ»lant et jets de lave). L'onglet CosmĂ©tiques compte dĂ©sormais trois pages (Statique I-IV, Mouvement I-III).
- Config client,
config/arcadia/prestige/client.toml. Préférences de rendu purement locales, rien n'est envoyé au serveur et rien n'affecte le gameplay :qualitydes particules (AUTOsuit le curseur de particules vanilla, plusHIGH/MEDIUM/LOW/OFF),max_visible_effects,max_distance,near_distance,hide_own_effects_first_person(désormais conservé entre les redémarrages au lieu de se réinitialiser à chaque lancement),show_other_players_effects,hide_invisible_players,render_block_companionsetreopen_dashboard_on_exit. - Interrupteurs de fonctionnalités,
[features]. Interrupteurs indĂ©pendants pourcosmetics,daily_rewards,quests,eloeteffect_preview. En dĂ©sactiver un arrĂªte son suivi d'Ă©vĂ©nements et affiche un message clair dans son onglet ; rien n'est supprimĂ©, donc le rĂ©activer restaure l'Ă©tat sauvegardĂ©. - Commandes de confort :
/arcadia_prestige effect <id>eteffect off(avec complĂ©tion sur tous les ids d'effets, vĂ©rification de permission cĂ´tĂ© serveur),preview [effect],stats(sĂ©rie, ELO, quĂªtes, cosmĂ©tiques possĂ©dĂ©s, points),questsetleaderboard(toutes deux documentĂ©es dans le README depuis les 1.2.x mais jamais rĂ©ellement implĂ©mentĂ©es), etcosmetics rescan(documentĂ©e dans la javadoc deCosmeticPermissionScannerdepuis la 1.2.14 mais jamais branchĂ©e). - Le HUD d'aperçu nomme la ligne : Avec 65 effets, un simple « 21/65 » ne dit rien sur l'endroit oĂ¹ l'on se trouve : l'overlay affiche dĂ©sormais la ligne du dashboard Ă laquelle appartient l'effet, avec le mĂªme libellĂ© que l'onglet CosmĂ©tiques. Le shift-molette avance de cinq, soit exactement une ligne, donc l'indication sert aussi de repère sur ce que fait ce saut.
- Raccourcis clavier :
Équiper l'effet prévisualisé(par défautR) et deux touches non assignées par défaut,Ouvrir l'aperçu d'effetsetAfficher/masquer ses propres effets, pour qu'installer le mod ne vole jamais une touche déjà utilisée par le joueur. - Section de config
[performance]:batch_login_sync,quest_cache_daysetleaderboard_cache_secondsexposent le réglage derrière les correctifs ci-dessous.
Correctifs
- L'aperçu d'effets était totalement mort : Cliquer sur la longue-vue dans l'onglet Cosmétiques ne faisait strictement rien. Le gestionnaire de clic vivait dans
com.arcadia.prestige.client.DashboardScreen, une classe jamais enregistrĂ©e : depuis que le dashboard a migrĂ© vers arcadia-lib, le menu est liĂ© Ăcom.arcadia.lib.client.DashboardScreen, donc la copie de Prestige Ă©tait du code mort inatteignable et sonmouseClickedne s'exĂ©cutait jamais. CĂ´tĂ© serveur,CosmeticsTabHandler.handleClickn'avait pas non plus de cas pour le slot 47, donc le clic Ă©tait avalĂ© des deux cĂ´tĂ©s. L'aperçu est dĂ©sormais pilotĂ© par le serveur : le handler d'onglet rĂ©pond au slot 47 en envoyant un nouveau payloadS2CStartPreview, ce qui fonctionne quelle que soit l'implĂ©mentation d'Ă©cran affichant le menu et permet au serveur de transmettre avec lui la liste faisant autoritĂ© des effets dĂ©bloquĂ©s. La classe morteDashboardScreena Ă©tĂ© supprimĂ©e. - L'aperçu n'entre plus en conflit avec la synchro d'effets : Il Ă©crasait auparavant l'entrĂ©e partagĂ©e de
PlayerEffectCacheet la restaurait Ă la sortie, donc unS2CParticleSyncarrivant pendant l'aperçu Ă©crasait ce que le joueur regardait, et une sortie interrompue pouvait laisser le mauvais effet en cache. L'Ă©tat d'aperçu vit maintenant entièrement dansEffectPreviewHandleret est fusionnĂ© au moment du rendu : il ne peut plus Ăªtre perturbĂ© et n'a besoin d'aucune Ă©tape de restauration. - L'Ă©tat d'effets cĂ´tĂ© client fuyait entre les mondes :
PlayerEffectCache.clear()existait mais n'avait aucun appelant. Les effets synchronisĂ©s sur un serveur restaient en mĂ©moire après dĂ©connexion et rĂ©apparaissaient dans le monde suivant rejoint durant la mĂªme session, sur les joueurs qui rĂ©utilisaient ces UUID. DĂ©sormais vidĂ© surClientPlayerNetworkEvent.LoggingOut, avec l'Ă©tat d'aperçu et l'historique de positions du renderer. - L'historique de positions de
ParticleRenderergrossissait sans limite :trailPositionsetlastPositionsĂ©taient de simplesHashMapdans lesquelles on ne faisait qu'Ă©crire. Chaque joueur jamais vu avec un effet gardait une entrĂ©e, plus jusqu'Ă 14 objetsVec3chacun, pour toute la durĂ©e de vie du client. Elles sont maintenant balayĂ©es pĂ©riodiquement et vidĂ©es Ă la dĂ©connexion. - Le cache de quĂªtes grossissait sans limite :
QuestManager.CACHEconservait chaque jour oĂ¹ un joueur avait Ă©tĂ© vu, pour chaque joueur, pour toute la durĂ©e du processus. Les jours au-delĂ deperformance.quest_cache_dayssont maintenant Ă©vincĂ©s, et l'entrĂ©e d'un joueur est supprimĂ©e Ă sa dĂ©connexion. - Les effets attachĂ©s au corps traĂ®naient derrière un joueur en mouvement : Halos, anneaux, ailes et disques dĂ©crochaient visiblement en marchant ou en sprintant au lieu de rester sur le joueur. Les particules Minecraft sont des objets en espace monde de type « Ă©mettre et oublier » : rien ne peut en attacher une Ă une entitĂ© après l'Ă©mission, et
DustParticleBaseleur donne une durĂ©e de vie allant jusqu'Ă 40 ticks. Un joueur sprintant Ă 0,28 bloc par tick laissait donc un anneau statique jusqu'Ă onze blocs derrière lui avant qu'il ne disparaisse. Tous les points d'Ă©mission passent dĂ©sormais par un helper qui ajoute le mouvement par tick du porteur Ă la vitesse de la particule, uniquement pour les effets attachĂ©s au corps : les effets de mouvement sont censĂ©s rester derrière. Le report est calibrĂ© par type de particule contre la source vanilla dĂ©compilĂ©e : Ă—10 pour les poussières (qui multiplient la vitesse fournie par 0,1), Ă—1 pour l'End Rod (qui l'utilise telle quelle), et ignorĂ© pour les types comme Portal qui traitent l'argument comme une amplitude de dĂ©placement et non une vitesse, oĂ¹ injecter la vitesse d'un joueur dĂ©formerait la figure au lieu de la dĂ©placer. Une sur-compensation de 1,3Ă— compense en plus la friction que vanilla applique et qu'on ne peut pas dĂ©sactiver. Ce ne peut pas Ăªtre exact : mesurĂ© sur la durĂ©e de vie d'une poussière en sprint, l'Ă©cart moyen passe de 2,12 blocs Ă 1,18, et celui d'un End Rod de 2,57 Ă 1,14, pas Ă zĂ©ro. Une adhĂ©rence parfaite exigerait des entitĂ©s custom, pas des particules. - Les effets de traĂ®nĂ©e dessinaient une ligne pointillĂ©e plutĂ´t qu'une traĂ®nĂ©e : Arc-en-Ciel, Poussière d'Étoiles et Élan ne posaient des particules que sur les Ă©chantillons d'historique, espacĂ©s d'environ 0,56 bloc en sprint. Chaque segment est maintenant subdivisĂ© selon un espacement cible pour que le ruban reste continu quelle que soit l'allure. Élan rĂ©utilisait en plus son index de voie comme facteur d'interpolation, donc ses traits se tassaient au dĂ©but de chaque segment au lieu de le parcourir. La subdivision est plafonnĂ©e serrĂ© : mesurĂ© avec un plafond plus large, Arc-en-Ciel atteignait 416 particules par passe contre 112 auparavant, donc son historique passe de 14 Ă©chantillons Ă 10 pour payer la densitĂ© ajoutĂ©e, atterrissant Ă 144.
- Un type de mob null faisait planter le gestionnaire de résultat de duel :
PlayerEloData.withWinappelaitmobType.isEmpty()directement sur son argument, donc unDuelResultEventportant un type de mob null faisait tomber toute la mise Ă jour ELO sur uneNullPointerException.EloDatabase.loadatteignait le mĂªme code viaResultSet.getString, qui vaut null pour une colonne NULL. Le record normalise dĂ©sormais null en chaĂ®ne vide dans son constructeur, ce qui couvre tous les chemins de construction, etwithWinconserve le favori existant au lieu de lever. TrouvĂ© en compilant la classe seule et en l'exĂ©cutant, ni elle niEloCalculatorn'ayant de dĂ©pendance Minecraft. - L'ordre des dĂ©blocages Ă©tait perdu Ă chaque sauvegarde :
PlayerProgressstocke les dĂ©blocages dans unLinkedHashSetpour garantir un ordre dĂ©terministe, puis renvoyait unSet.copyOf, dont l'ordre d'itĂ©ration est non spĂ©cifiĂ© et randomisĂ© Ă chaque JVM. Le CSV persistĂ© Ă©tait donc réécrit dans un ordre diffĂ©rent Ă chaque sauvegarde mĂªme sans modification, provoquant du churn sursolo_progress.jsonet des mises Ă jour inutiles en base. - L'onglet CosmĂ©tiques perdait son indicateur de page : le rĂ©sumĂ© de progression Ă©tait placĂ© au slot 49, lĂ oĂ¹
DashboardTabHandler.buildBottomBarécrit le papier « page X / Y ». Il est maintenant au slot 48 et les deux coexistent. - La progression solo n'avait rien à débloquer en solo :
PermissionService.canUseCosmeticdélègue auhasPermissionpermissif, et sans backend de permissions la lib installePERMISSIVEsur un serveur intégré, qui accorde toutes les permissions. Un monde solo signalait donc tous les cosmétiques comme déjà possédés et la progression ne pouvait rien vendre, précisément dans l'environnement pour lequel elle a été écrite.CosmeticAccess.hasRankGrantignore désormais cet octroi global tant que la progression est active, et seulement dans ce cas : un monde solo enmode = "NEVER"garde tous les cosmétiques gratuits exactement comme avant la 1.3.0, et un serveur LuckPerms n'est affecté ni dans un cas ni dans l'autre.PermissionService.canUseCosmeticn'est plus appelé que d'un seul endroit, pour qu'une correction s'applique partout d'un coup. - Équiper depuis l'aperçu ne faisait rien, tout en prétendant avoir réussi : la touche d'équipement de l'aperçu envoyait le
C2SDashboardAction.SELECT_PARTICLEde la lib, qui dispatche versplayer.containerMenuet sort silencieusement si ce menu n'est pas unDashboardMenu. L'aperçu ferme volontairement le dashboard, donc le serveur ignorait chaque équipement pendant que le client affichait « … équipé » de façon optimiste. Un payload dédiéC2SEquipEffectle transporte désormais, revalide l'accès côté serveur viaCosmeticAccess, et le message de confirmation vient du côté qui sauvegarde réellement. - Il manquait 75 chaînes en français québécois :
fr_ca.jsonn'avait jamais Ă©tĂ© remis Ă niveau avecfr_fr.json, donc une grande partie du hub, de l'onglet quĂªtes, de l'onglet classement, de l'onglet journalier et tous les messages de commandes retombaient sur l'anglais. Toutes les clĂ©s vivantes sont dĂ©sormais traduites dans les deux fichiers français.
Performance
- Boucle de tick des particules sans allocation : La sélection par tick des joueurs les plus proches construisait une
HashMapde distances boxées, recopiait l'ensemble des entrées dans uneArrayListet la triait entièrement, dix fois par seconde, pour n'utiliser au plus que dix résultats. C'est désormais une insertion bornée dans des tableaux fixes réutilisés : aucune collection, aucun boxing, aucun tri. - Les couleurs de dégradé viennent de tables de lookup : Arc-en-Ciel allouait un
DustParticleOptionsneuf par particule : jusqu'Ă 14 positions de traĂ®nĂ©e Ă— 8 voies = 112 allocations par appel de rendu, par joueur visible, dix fois par seconde. TraĂ®nĂ©e, Comète, Galaxie, Pulsar, Onde de Choc, Binaire et Prisme faisaient de mĂªme Ă plus petite Ă©chelle. Tous lisent maintenant dans des tables prĂ©-construites (une grille teinte/taille 32Ă—8, plus une rampe de 16 pas par effet Ă dĂ©gradĂ©) ; la quantification est visuellement indiscernable Ă l'Ă©chelle d'une particule. - La rĂ©partition des effets n'alloue plus :
renderEffectappelaiteffectId.toLowerCase(Locale.ROOT)Ă chaque rĂ©partition. Les ids sont canonisĂ©s une seule fois Ă l'entrĂ©e du cache et leswitchles lit directement. Math.random()remplacĂ© par leRandompartagĂ© : HĂ©lice, MĂ©tĂ©ore, Comète, Galaxie et CÅ“urs utilisaientMath.random(), qui passe par un gĂ©nĂ©rateur synchronisĂ© global, sur le thread de rendu.- Synchro de connexion groupĂ©e : Rejoindre un serveur envoyait un paquet par joueur en ligne ayant un effet actif, donc un serveur plein de 100 slots produisait une rafale d'environ 100 minuscules payloads Ă chaque connexion. Ils sont maintenant regroupĂ©s en un seul
S2CParticleBulkSync(dĂ©sactivable viaperformance.batch_login_sync). - Le classement ELO est mĂ©moĂ¯sĂ© : Ouvrir l'onglet classement retriait tout le cache de ratings, ou re-interrogeait la base, Ă chaque rendu, y compris les rafraĂ®chissements dĂ©clenchĂ©s par des clics sans rapport. Les rĂ©sultats sont mis en cache pour
performance.leaderboard_cache_secondset invalidés dès qu'un duel déplace un rating. - Les particules cosmétiques respectent le curseur de particules vanilla : Avec
quality = AUTO(par défaut),Réduitesdivise la densité par deux etMinimalesn'affiche rien. Un joueur qui a déjà baissé les particules vanilla ne devrait pas avoir à chercher un second réglage. - Les joueurs invisibles et spectateurs sont ignorés : Les effets ne traversent plus une potion d'Invisibilité et ne s'affichent plus pour les spectateurs, ce qui était à la fois un coût de rendu et une fuite d'information en PvP.
- Le rendu se met en pause avec le jeu : La boucle de tick sort maintenant immédiatement sur
Minecraft.isPaused(). - Budget de particules par passe :
max_visible_effectscompte des joueurs, pas un coĂ»t, et les effets sont loin d'Ăªtre Ă©quivalents : CÅ“urs Ă©met environ 2 particules par passe, Arc-en-Ciel environ 112, un Ă©cart de 50x qu'un plafond de joueurs traite Ă l'identique. Chaque effet porte dĂ©sormais un poids de rendu dans le registre, et le client cesse d'ajouter les effets les plus lointains une foisparticle_budget(600 par dĂ©faut) Ă©puisĂ©. Une partie mixte typique consomme environ 250 et n'est pas affectĂ©e ; dix joueurs tous en Arc-en-Ciel passent de dix rendus Ă six. L'effet le plus proche est exemptĂ©, donc le budget ne peut jamais vider l'Ă©cran, et0rĂ©tablit la limitation par simple comptage.
Modifications
- Source unique de vérité pour les effets cosmétiques : Nouveau package
com.arcadia.prestige.cosmetic(CosmeticEffects,CosmeticEffect,CosmeticGroup,CosmeticTier,CosmeticAccess). La liste des effets était dupliquée à quatre endroits (les lignes de l'onglet Cosmétiques,CosmeticPermissionScanner.ALL_COSMETICS,EffectPreviewHandler.ALL_EFFECTSet l'ensemble « mouvement » du renderer), et la dérive entre eux est précisément ce qui rendait des lignes entières du GUI incliquables en 1.2.15. Ajouter un effet demande désormais une ligne dansCosmeticEffects, une branche de rendu et une clé de traduction par langue. - Toutes les vérifications d'accès passent par
CosmeticAccess: Un seul endroit rĂ©pond à « ce joueur peut-il utiliser cet effet ? », en combinant l'octroi LuckPerms et le dĂ©blocage par progression. C'est ce qui permet de dĂ©sactiver la progression Ă l'Ă©chelle du serveur en laissant tous les appelants suivre automatiquement. - Version du protocole rĂ©seau passĂ©e Ă
2: Un client ancien et un serveur récent refusent maintenant de se connecter au lieu de mal décoder silencieusement les nouveaux payloads. - Dépendance
arcadia_libdĂ©clarĂ©e corrigĂ©e en[1.2.14,): Elle Ă©tait Ă[1.0.0,), ce qu'aucune version de Prestige ne pouvait honorer depuis un moment. La 1.3.0 appellePermissionService.hasRealBackend,ArcadiaConfigPaths.dataFile,JsonFileStore,DatabaseManager.isDatabaseActive,LibMenusetStaffPetEntities, absents des premières versions de la lib : une bibliothèque pĂ©rimĂ©e passait donc la vĂ©rification de dĂ©pendance puis mourait sur unNoSuchMethodErroren plein dĂ©marrage. NeoForge annonce dĂ©sormais la vraie exigence avant de charger quoi que ce soit. Les plages optionnellesarcadia_petsetarcadia_ahrestent volontairement permissives : elles passent par le registre et la rĂ©flexion avec des replis vanilla, donc une version ancienne dĂ©grade proprement au lieu de devoir Ăªtre bloquĂ©e. Les notes gĂ©nĂ©rĂ©es par le workflow de release annonçaient elles aussi encore 1.2.0. PrestigeHubScreenetPrestigeCardmorts supprimĂ©s : Le hub plein Ă©cran propre Ă Prestige, rendu obsolète quand le hub a migrĂ© vers arcadia-lib et que/arcadia_prestiges'est mis Ă appelerArcadiaLibNet.sendOpenHub. Aucun des deux n'avait la moindre rĂ©fĂ©rence restante : aucun site d'appel Java, aucune entrĂ©e dans les resources, et le mod n'enregistre aucun Ă©cran.PrestigeCardportait en prime un plantage latent, rĂ©solvantLibModItems.ARCADIA_STAR.get()depuis un initialiseur statique, ce qui lève une exception si la classe est touchĂ©e avant le gel du registre d'items. Les clĂ©s de traductionarcadia_prestige.hub.*sont volontairement conservĂ©es : des chaĂ®nes inutilisĂ©es ne coĂ»tent rien Ă l'exĂ©cution, alors qu'en supprimer une qu'un autre module Arcadia rĂ©fĂ©rencerait afficherait une clĂ© brute Ă l'Ă©cran.ArcadiaConfigmort supprimĂ© : Un porteur de constantes statiques sans aucune rĂ©fĂ©rence restante dans le mod. Chacune de ses valeurs Ă©tait dĂ©jĂ remplacĂ©e : les grades parPrestigeConfiget lePermissionConfigde la lib, les distances et le nombre de particules visibles par le nouveauPrestigeClientConfig, etserver_idpar leServerContextde la lib depuis la 1.2.2. Il portait aussi des constantes de base de donnĂ©es de remplissage dont un champDB_PASS, qui n'a rien Ă faire dans le code source mĂªme comme valeur de dĂ©veloppement.
Les trois entrées ci-dessous décrivent des travaux réalisés dans arcadia-lib, pas dans ce mod. Elles étaient déjà en attente dans la section Unreleased et figurent ici parce qu'elles changent le comportement de Prestige. Aucun fichier d'arcadia-lib n'a été modifié dans le cadre de la 1.3.0 ; Prestige la consomme comme dépendance
compileOnlyen lecture seule.
- Entités des pets staff retirées, déplacées vers arcadia-lib.
StaffPetEntity,StaffPetEntities,StaffPetRendereret les 17 enregistrements d'entitĂ© vivent maintenant dans arcadia-lib (≥ 1.2.10). arcadia-pets et arcadia-ah peuvent afficher les pets staff Mythic sans avoir besoin d'installer Prestige (ex. en solo avec seulement Pets + Lib). Les pet items / annonces HDV existants qui portent l'ancien namespacearcadia_prestige:staff_*sont migrĂ©s automatiquement par le helper de namespace de lib, aucune migration de save nĂ©cessaire. - ClĂ©s de traduction d'entitĂ© staff dĂ©placĂ©es dans arcadia-lib (
entity.arcadia_lib.staff_*). - Init DB / services centraux retiré de
ArcadiaDashboard: L'enregistrement deDatabaseConfig.SPECplus les appels ĂDatabaseManager.initialize(),PlayerDataHandler.init(),EconomyService.init(),PermissionService.init()et la chaĂ®ne deshutdown()correspondante vivent maintenant dansArcadiaLib(≥ 1.2.10). C'Ă©tait la vraie raison pour laquelle l'HDV et Pets ne marchaient plus dans un modset sans Prestige.ArcadiaDashboard.onServerAboutToStartse rĂ©sume maintenant ĂCosmeticPermissionScanner.init().
This mod has no additional files

