Unofficial site, not affiliated with modrinth.com.What is this?
Плагины/TrialChamberPro
TrialChamberPro

TrialChamberPro

Because Trial Chambers deserve better than being a "one and done" dungeon.

1.7K
20

TrialChamberPro 1.4.2-mc26

release1 мая 2026 г.

This plugin version is compatible with Minecraft 26.X.X

1.4.2 - 2026-05-02

Fixed

  • //undo no longer gets hijacked by TCP after a chamber generation. The previous UndoListener cancelled //undo at HIGHEST priority and demanded confirm / cancel in chat — but the chat handler only cleared the pending state on cancel, leaving the per-player last entry forever. Once any chamber had been generated in the session, every subsequent //undo (even for unrelated WorldEdit edits made hours later, or by a moderator joining after the fact) was intercepted, the chat prompt fired, and the actual WorldEdit undo never ran. There was also no path to retry: cancelling re-armed the same intercept, and confirming only deleted the DB registration without rolling back the placed blocks. The whole interception model was wrong — chamber registration is a DB write, not a WorldEdit edit, so it doesn't belong on WE's undo stack to begin with. New behavior: TCP never cancels //undo. WorldEdit's stack is fully untouched, any depth, any time. A new passive PostUndoHintListener observes //undo (and /undo) at MONITOR priority without cancelling and, only if the player happens to be standing inside a registered chamber when they run undo, posts a one-line tip suggesting /tcp delete <name> to also clean up the registration. Generation now also emits a one-time chamber-created-rollback-tip immediately after chamber-created so users learn the two-step rollback (//undo for blocks → /tcp delete for registration) up front. UndoListener.kt and UndoTracker.kt deleted.

Localization

  • messages.yml: removed obsolete undo-confirm, undo-confirm-pending, undo-deleted, undo-failed, undo-cancelled, undo-expired (the chat-prompt strings from the old confirmation flow). Added undo-cleanup-hint (passive post-//undo tip) and chamber-created-rollback-tip (post-generation tip). The paste-undo-hint key is unchanged — schematic paste still references //undo correctly because that path always was a normal WorldEdit edit.

TrialChamberPro 1.4.2

release1 мая 2026 г.

1.4.2 - 2026-05-02

Fixed

  • //undo no longer gets hijacked by TCP after a chamber generation. The previous UndoListener cancelled //undo at HIGHEST priority and demanded confirm / cancel in chat — but the chat handler only cleared the pending state on cancel, leaving the per-player last entry forever. Once any chamber had been generated in the session, every subsequent //undo (even for unrelated WorldEdit edits made hours later, or by a moderator joining after the fact) was intercepted, the chat prompt fired, and the actual WorldEdit undo never ran. There was also no path to retry: cancelling re-armed the same intercept, and confirming only deleted the DB registration without rolling back the placed blocks. The whole interception model was wrong — chamber registration is a DB write, not a WorldEdit edit, so it doesn't belong on WE's undo stack to begin with. New behavior: TCP never cancels //undo. WorldEdit's stack is fully untouched, any depth, any time. A new passive PostUndoHintListener observes //undo (and /undo) at MONITOR priority without cancelling and, only if the player happens to be standing inside a registered chamber when they run undo, posts a one-line tip suggesting /tcp delete <name> to also clean up the registration. Generation now also emits a one-time chamber-created-rollback-tip immediately after chamber-created so users learn the two-step rollback (//undo for blocks → /tcp delete for registration) up front. UndoListener.kt and UndoTracker.kt deleted.

Localization

  • messages.yml: removed obsolete undo-confirm, undo-confirm-pending, undo-deleted, undo-failed, undo-cancelled, undo-expired (the chat-prompt strings from the old confirmation flow). Added undo-cleanup-hint (passive post-//undo tip) and chamber-created-rollback-tip (post-generation tip). The paste-undo-hint key is unchanged — schematic paste still references //undo correctly because that path always was a normal WorldEdit edit.

TrialChamberPro 1.4.1-mc26

release1 мая 2026 г.

This plugin version is compatible with Minecraft 26.X.X

1.4.1 - 2026-04-29

Fixed

  • Auto-discovery now merges adjacent chamber regions instead of double-registering them. The previous flow registered every BFS result as a fresh chamber and only short-circuited if the candidate's center fell inside an existing AABB. Two physically distinct vanilla chambers ~500 blocks apart, or a single physical chamber whose two halves seeded discovery from different chunks, would happily produce two side-by-side auto_world_* entries (the user-reported case: auto_world_851_747 + auto_world_891_765 registered in the same millisecond, ~40 blocks apart on the X axis). New behavior: after BFS produces a candidate AABB, ChamberDiscoveryManager scans cached chambers in the same world for any whose AABB sits within discovery.merge-distance-blocks (Chebyshev edge-to-edge, default 250) of the candidate. If found, the existing chamber's bounds are unioned with the candidate via the new ChamberManager.updateBounds(...), the chamber is rescanned to absorb the new vaults/spawners, and (if discovery.auto-snapshot is enabled) the snapshot is regenerated. If not found, registration proceeds as before. New discovery.max-merged-volume (default 1,500,000 blocks) caps how far a runaway daisy-chain can grow so a pathological geometry can't swallow large regions into a single logical chamber. Set discovery.merge-distance-blocks: -1 to disable merging entirely and restore the v1.2.25 behavior.
  • Discovery registration race closed. Two near-simultaneous BFS results (typical during the startup sweep) could both pass the existing-chamber check before either committed — the merge logic above wouldn't help if both registrations were already in flight. New kotlinx.coroutines.sync.Mutex in ChamberDiscoveryManager serializes the entire registration step (mutex acquisition → cache scan → merge-or-create → mark processed). Throughput cost is zero in practice — registration fires at most a handful of times per session and is gated by the chunk-load / startup-sweep cadence anyway.

Changed — UX & GUI

  • Main menu flattened — SettingsMenuView removed. The previous "Settings → Plugin Settings → Global Settings" path had two papercut bugs: clicking "Settings" on the main menu opened a "Plugin Settings" hub whose only meaningful contents (Global Settings, Protection Settings, Performance Info, Reload Configuration) could just as well live one level up; and the back button on Protection Settings landed on Plugin Settings instead of the main menu, leaving the user one step deeper than they started. New main menu is a 6-row layout: Chambers / Loot Tables / Global Settings / Protection Settings on row 1, Help / Performance Info / Statistics on row 2, Reload Configuration centered on row 4 (shift-click to fire so accidental clicks don't reload), Close on row 5. SettingsMenuView.kt deleted; Screen.SETTINGS_MENU and MenuService.openSettingsMenu removed; back-button destinations in GlobalSettingsView and ProtectionMenuView updated from gui.common.dest-settingsgui.common.dest-main-menu. gui.settings-menu.* keys deleted from messages.yml; gui.main-menu.settings-name/lore renamed global-settings-name/lore; new performance-name/lore and reload-name/lore keys added under gui.main-menu. CustomMobProviderView's back button still uses dest-settings because it goes back to chamber settings, not the deleted plugin-settings hub.
  • Loot editor now shows the effective drop rate per item. The Amount/Chance/Rolls model is technically accurate but genuinely confusing: a user looking at "Amount: 2-4" + "Chance: 20%" tends to read that as "20% chance of getting 2-4 of this item per opening", and the separate "Rolls: 1-3" tile multiplies the per-draw probability without making that visually obvious on the items themselves. Each item lore now includes a new Expected: ≈X per vault opening line computed as avg(draws) × (weight / totalWeight) × avg(amount) for weighted items, and avg(amount) for guaranteed items (which always drop once per opening). Adaptive precision: ≥10 → integer, ≥1 → one decimal, <1 → two decimals (so a 1-in-50 tier item still reads ≈0.02 rather than rounding to 0). The per-item "Chance: X%" line is now suffixed with " per draw" to make the relationship explicit. The "Rolls Configuration" tile is renamed "Draws per Opening" and its lore opens with three plain-English lines explaining that each opening picks N items from the weighted list, each draw chooses one item using its chance, and more draws = more total loot. Bumping the draws slider visibly recomputes every Expected line in real time so the multiplicative relationship becomes self-evident. Pure presentation change — loot.yml data model untouched.
  • Help view rebuilt to mirror /tcp help and cover every wired subcommand. Audit found mobs (v1.3.0) was missing from chat help entirely, and both mobs and give (v1.3.1) were missing from the GUI Help view. Two dead chat-help keys (help-procgen, help-teleport — subcommands that don't exist) deleted. Chat help reordered into logical groups (Browse → Create → Manage → Loot/Mobs → Players & rewards → Admin) with a comment in TCPCommand.sendHelp noting the order mirrors the GUI tile grouping so future edits don't drift. Wording tightened on help-generate, help-snapshot, help-loot, help-vault, help-key, help-leaderboard, help-info, help-list, and help-reload to drop jargon ("WE wand", "saved var") and uninformative phrases ("Manage snapshots"). GUI Help view re-laid out to a 4 + 4 + 1 tile grid: row 1 overview (Commands / Permissions / About), row 2 gameplay command groups (Chambers / Loot / Vaults & Keys / Stats), row 3 admin & setup command groups (Snapshots / Generate / Custom Mobs / Spawner Presets), row 4 lone Admin Tools tile, row 5 navigation. New mobs-cmd and give-cmd tiles cover the previously absent commands. Every tile lore opens with one plain-English sentence describing the group ("Browse and manage existing chambers." / "View or override per-chamber loot." etc.) before listing the actual commands. The permissions tile expanded from 5 entries to ~13 organized into Admin / Player / Bypass / Notifications groups.

Localization

  • Every text change in this release routes through messages.yml. No Component.text(...) literals introduced anywhere; all new and changed strings are translatable through the existing gui.<view>.* and flat * key system. New keys: discovery-merged, gui.main-menu.global-settings-name/lore, gui.main-menu.performance-name/lore, gui.main-menu.reload-name/lore, gui.loot-editor.item-expected, gui.help-menu.mobs-cmd-name/lore, gui.help-menu.give-cmd-name/lore, help-mobs. Removed keys: every key under gui.settings-menu.*, help-procgen, help-teleport, gui.main-menu.settings-name/lore (renamed). Changed keys: gui.loot-editor.item-chance, gui.loot-editor.rolls-name, gui.loot-editor.rolls-lore, gui.main-menu.protection-name, every gui.help-menu.* lore. The chat-help block in messages.yml was scattered across two locations (lines 152-166 and 225-228); all entries are now consolidated into a single contiguous block in the order sendHelp emits them.

Added

  • Startup schema check for messages.yml. New MessagesSchemaValidator (run from onEnable immediately after ConfigValidator) loads the JAR-bundled messages.yml and the user's deployed copy, walks both for leaf keys (filtering out ConfigurationSection containers so a parent path doesn't mask a missing leaf), and logs a warning listing every key the bundle defines that the user's file lacks — up to 25 enumerated, then truncated with ... and N more. Output includes a 4-step recovery path (rename → restart → port translations) and notes the debug.skip-messages-schema-check: true opt-out. Pure log surface — never modifies the user's file, never blocks startup. Motivated by a v1.4.0 user bug report where <missing: gui.loot-table-list.table-name-normal> reached the GUI because the deployed messages.yml was an older copy that predated the gui.loot-table-list.* block; the check would have surfaced that as a console warning at startup.

Config additions

  • discovery.merge-distance-blocks (default 250) — Chebyshev edge-to-edge distance below which two regions are folded into a single chamber. Set to -1 to disable merging.
  • discovery.max-merged-volume (default 1500000) — hard cap on the post-merge bounding-box volume in blocks. Above this the merge is rejected and the new region is logged as a skip (region debounce still applies).
  • debug.skip-messages-schema-check (default false) — set to true to silence the new messages.yml schema check. Not recommended; the check is purely informative and the warning means GUI/chat surfaces are showing literal <missing: ...> placeholders.

TrialChamberPro 1.4.1

release1 мая 2026 г.

1.4.1 - 2026-04-29

Fixed

  • Auto-discovery now merges adjacent chamber regions instead of double-registering them. The previous flow registered every BFS result as a fresh chamber and only short-circuited if the candidate's center fell inside an existing AABB. Two physically distinct vanilla chambers ~500 blocks apart, or a single physical chamber whose two halves seeded discovery from different chunks, would happily produce two side-by-side auto_world_* entries (the user-reported case: auto_world_851_747 + auto_world_891_765 registered in the same millisecond, ~40 blocks apart on the X axis). New behavior: after BFS produces a candidate AABB, ChamberDiscoveryManager scans cached chambers in the same world for any whose AABB sits within discovery.merge-distance-blocks (Chebyshev edge-to-edge, default 250) of the candidate. If found, the existing chamber's bounds are unioned with the candidate via the new ChamberManager.updateBounds(...), the chamber is rescanned to absorb the new vaults/spawners, and (if discovery.auto-snapshot is enabled) the snapshot is regenerated. If not found, registration proceeds as before. New discovery.max-merged-volume (default 1,500,000 blocks) caps how far a runaway daisy-chain can grow so a pathological geometry can't swallow large regions into a single logical chamber. Set discovery.merge-distance-blocks: -1 to disable merging entirely and restore the v1.2.25 behavior.
  • Discovery registration race closed. Two near-simultaneous BFS results (typical during the startup sweep) could both pass the existing-chamber check before either committed — the merge logic above wouldn't help if both registrations were already in flight. New kotlinx.coroutines.sync.Mutex in ChamberDiscoveryManager serializes the entire registration step (mutex acquisition → cache scan → merge-or-create → mark processed). Throughput cost is zero in practice — registration fires at most a handful of times per session and is gated by the chunk-load / startup-sweep cadence anyway.

Changed — UX & GUI

  • Main menu flattened — SettingsMenuView removed. The previous "Settings → Plugin Settings → Global Settings" path had two papercut bugs: clicking "Settings" on the main menu opened a "Plugin Settings" hub whose only meaningful contents (Global Settings, Protection Settings, Performance Info, Reload Configuration) could just as well live one level up; and the back button on Protection Settings landed on Plugin Settings instead of the main menu, leaving the user one step deeper than they started. New main menu is a 6-row layout: Chambers / Loot Tables / Global Settings / Protection Settings on row 1, Help / Performance Info / Statistics on row 2, Reload Configuration centered on row 4 (shift-click to fire so accidental clicks don't reload), Close on row 5. SettingsMenuView.kt deleted; Screen.SETTINGS_MENU and MenuService.openSettingsMenu removed; back-button destinations in GlobalSettingsView and ProtectionMenuView updated from gui.common.dest-settingsgui.common.dest-main-menu. gui.settings-menu.* keys deleted from messages.yml; gui.main-menu.settings-name/lore renamed global-settings-name/lore; new performance-name/lore and reload-name/lore keys added under gui.main-menu. CustomMobProviderView's back button still uses dest-settings because it goes back to chamber settings, not the deleted plugin-settings hub.
  • Loot editor now shows the effective drop rate per item. The Amount/Chance/Rolls model is technically accurate but genuinely confusing: a user looking at "Amount: 2-4" + "Chance: 20%" tends to read that as "20% chance of getting 2-4 of this item per opening", and the separate "Rolls: 1-3" tile multiplies the per-draw probability without making that visually obvious on the items themselves. Each item lore now includes a new Expected: ≈X per vault opening line computed as avg(draws) × (weight / totalWeight) × avg(amount) for weighted items, and avg(amount) for guaranteed items (which always drop once per opening). Adaptive precision: ≥10 → integer, ≥1 → one decimal, <1 → two decimals (so a 1-in-50 tier item still reads ≈0.02 rather than rounding to 0). The per-item "Chance: X%" line is now suffixed with " per draw" to make the relationship explicit. The "Rolls Configuration" tile is renamed "Draws per Opening" and its lore opens with three plain-English lines explaining that each opening picks N items from the weighted list, each draw chooses one item using its chance, and more draws = more total loot. Bumping the draws slider visibly recomputes every Expected line in real time so the multiplicative relationship becomes self-evident. Pure presentation change — loot.yml data model untouched.
  • Help view rebuilt to mirror /tcp help and cover every wired subcommand. Audit found mobs (v1.3.0) was missing from chat help entirely, and both mobs and give (v1.3.1) were missing from the GUI Help view. Two dead chat-help keys (help-procgen, help-teleport — subcommands that don't exist) deleted. Chat help reordered into logical groups (Browse → Create → Manage → Loot/Mobs → Players & rewards → Admin) with a comment in TCPCommand.sendHelp noting the order mirrors the GUI tile grouping so future edits don't drift. Wording tightened on help-generate, help-snapshot, help-loot, help-vault, help-key, help-leaderboard, help-info, help-list, and help-reload to drop jargon ("WE wand", "saved var") and uninformative phrases ("Manage snapshots"). GUI Help view re-laid out to a 4 + 4 + 1 tile grid: row 1 overview (Commands / Permissions / About), row 2 gameplay command groups (Chambers / Loot / Vaults & Keys / Stats), row 3 admin & setup command groups (Snapshots / Generate / Custom Mobs / Spawner Presets), row 4 lone Admin Tools tile, row 5 navigation. New mobs-cmd and give-cmd tiles cover the previously absent commands. Every tile lore opens with one plain-English sentence describing the group ("Browse and manage existing chambers." / "View or override per-chamber loot." etc.) before listing the actual commands. The permissions tile expanded from 5 entries to ~13 organized into Admin / Player / Bypass / Notifications groups.

Localization

  • Every text change in this release routes through messages.yml. No Component.text(...) literals introduced anywhere; all new and changed strings are translatable through the existing gui.<view>.* and flat * key system. New keys: discovery-merged, gui.main-menu.global-settings-name/lore, gui.main-menu.performance-name/lore, gui.main-menu.reload-name/lore, gui.loot-editor.item-expected, gui.help-menu.mobs-cmd-name/lore, gui.help-menu.give-cmd-name/lore, help-mobs. Removed keys: every key under gui.settings-menu.*, help-procgen, help-teleport, gui.main-menu.settings-name/lore (renamed). Changed keys: gui.loot-editor.item-chance, gui.loot-editor.rolls-name, gui.loot-editor.rolls-lore, gui.main-menu.protection-name, every gui.help-menu.* lore. The chat-help block in messages.yml was scattered across two locations (lines 152-166 and 225-228); all entries are now consolidated into a single contiguous block in the order sendHelp emits them.

Added

  • Startup schema check for messages.yml. New MessagesSchemaValidator (run from onEnable immediately after ConfigValidator) loads the JAR-bundled messages.yml and the user's deployed copy, walks both for leaf keys (filtering out ConfigurationSection containers so a parent path doesn't mask a missing leaf), and logs a warning listing every key the bundle defines that the user's file lacks — up to 25 enumerated, then truncated with ... and N more. Output includes a 4-step recovery path (rename → restart → port translations) and notes the debug.skip-messages-schema-check: true opt-out. Pure log surface — never modifies the user's file, never blocks startup. Motivated by a v1.4.0 user bug report where <missing: gui.loot-table-list.table-name-normal> reached the GUI because the deployed messages.yml was an older copy that predated the gui.loot-table-list.* block; the check would have surfaced that as a console warning at startup.

Config additions

  • discovery.merge-distance-blocks (default 250) — Chebyshev edge-to-edge distance below which two regions are folded into a single chamber. Set to -1 to disable merging.
  • discovery.max-merged-volume (default 1500000) — hard cap on the post-merge bounding-box volume in blocks. Above this the merge is rejected and the new region is logged as a skip (region debounce still applies).
  • debug.skip-messages-schema-check (default false) — set to true to silence the new messages.yml schema check. Not recommended; the check is purely informative and the warning means GUI/chat surfaces are showing literal <missing: ...> placeholders.

TrialChamberPro 1.4.0-mc26

release26 апреля 2026 г.

This plugin version is compatible with Minecraft 26.X.X

1.4.0 - 2026-04-26

Added

  • Phase 2 of the public extension API — three more seams aimed at premium add-on modules and third-party integrations. No breaking changes; all existing behavior preserved when no listener / service is registered.
  • DatabaseManager opened for extension. Class is now open (was final) and the plugin constructor parameter is protected so subclasses in other packages can access it. The instance is auto-registered with Bukkit's ServicesManager at TCP startup so consumers can resolve it via Bukkit.getServicesManager().load(DatabaseManager::class.java). Designed for the planned premium "Network Sync" module that adds Postgres / MariaDB / Redis backends. (Note: TCP itself currently still references its own databaseManager field directly throughout its own codebase, so subclass replacement only takes effect for callers that explicitly resolve via the services manager — full runtime substitution at every call site is planned for a future major version.)
  • ChamberResetEvent.snapshotOverride (mutable ByteArray?) — pre-reset hook lets listeners substitute a different snapshot for a single reset cycle without persistently modifying the chamber's on-disk snapshot. Bytes must be a gzip-compressed serialized SnapshotData (TCP's native snapshot format). New SnapshotManager.loadSnapshotFromBytes(bytes, contextLabel) deserializes the override; falls back to the on-disk snapshot with a logged warning if the override fails to load. Designed for premium / third-party "schematic injection" or "instance variant" workflows.
  • WildSpawnerResolver SPI in api/ — pluggable lookup for the question "should this wild trial spawner spawn custom-plugin mobs, and if so, which provider + mob ids?". Lifts the long-standing limitation that TCP's Custom Mob Provider only worked inside registered chambers. Implementations register as a Bukkit service (ServicesManager.register(WildSpawnerResolver::class.java, ...)); TCP's SpawnerWaveListener consults the active resolver on every wild-spawner spawn observation. Returning a non-null Config(providerId, normalIds, ominousIds) triggers TCP's existing replace-after-spawn logic — vanilla mob removed the same tick, custom provider mob spawned at the same location, wave tracking and key drops preserved. The seam lives in free TCP; the resolver implementation will ship in the planned premium "Wild Custom-Mob Spawners" module (per the v1.3.1 architectural boundary: trial-spawner-only is the line, wild-spawner custom mobs are premium territory).
  • SpawnerPresetManager.PRESET_ID_KEY_NAME + automatic PDC tagging — every item produced by SpawnerPresetManager.getItem (i.e. given out via /tcp give <preset>) now carries a tcp:preset_id PersistentDataContainer tag with the source preset's id.
  • SpawnerPresetPlaceListener — copies the tcp:preset_id tag from a placed trial-spawner item onto the resulting block's TileState. Lets WildSpawnerResolver implementations identify which preset a placed wild spawner originated from, even after the source ItemStack is gone. Tag survives chamber resets, chunk unloads, and world reloads via Minecraft's standard TileEntity persistence. Vanilla /give minecraft:trial_spawner items (no tag) are ignored.

Added — MiniMessage support

  • First-class MiniMessage support across every user-facing text surface. New MessageParser utility (utils/MessageParser.kt) translates raw messages.yml entries through MiniMessage as the primary syntax while remaining fully backwards-compatible with legacy & colour/format codes (and &#RRGGBB hex). Existing messages.yml files render unchanged; users adopt MM syntax entry-by-entry on their own schedule. Mixed input works too — &aHello <gradient:#ff0000:#0000ff>world</gradient> renders correctly.
  • MM features now usable in TCP messages that legacy & codes can't express:
    • Gradients: <gradient:#ff5500:#0000ff>Sunset to ocean</gradient>
    • Click events: <click:run_command:'/tcp menu'>[Open menu]</click>
    • Hover tooltips: <hover:show_text:'Bonus active'><gold>★</gold></hover>
    • Custom fonts (resource-pack supplied): <font:server:fancy>...</font>
    • Cleaner hex syntax: <#FF5500> instead of &#FF5500
  • New TrialChamberPro.getMessageComponent(key, ...): Component — companion to the existing getMessage() String method. Returns a fully-styled Adventure Component preserving all MiniMessage features (gradients, click/hover, fonts) end-to-end through Player.sendMessage(Component).
  • All ~349 sendMessage call sites in TCP migrated from the legacy String path to getMessageComponent so chat messages get full MiniMessage fidelity. Includes boss bar text, chat notifications (vault opened, chamber entered, reset warnings, spectator messages, discovery announcements, wave completion), death messages, and all command feedback.
  • GUI helpers (getGuiText, getGuiLore) now route through MessageParser — item names and lore in all 18 admin GUI views support full MM fidelity.
  • Documentation updated (docs/configuration/messages.yml.md) — comprehensive coverage of both syntaxes side-by-side, mixed-format examples, and MM-only feature documentation. The messages.yml resource header explains the two formats with examples.
  • Conflict-free with other plugins — TCP parses its own messages internally; chat plugins (DiscordSRV, EssentialsXChat, ChatControl) only intercept AsyncChatEvent (player-typed chat), not plugin-sent notifications, so there's no double-processing risk. This is the same pattern MythicMobs, EcoEnchants, LuckPerms, and CMI use.

Fixed

  • Trial-spawner wave size off-by-one (the v1.3.2 follow-up). v1.3.2 introduced SpawnerWaveManager.computeExpectedMobs to read the spawner's actual total_mobs / total_mobs_added_per_player config instead of hard-coding 6. The formula was base + perPlayer × players, but Mojang's actual TrialSpawnerData formula is base + perPlayer × max(0, players - 1) — the FIRST detected player gets the base count, each ADDITIONAL player adds the per-player bonus. The off-by-one over-counted by perPlayer per nearby player, producing the user-reported bug "spawner has 20 configured, bar shows 1/30, wave actually ends at 20". Plugin now matches vanilla exactly: floor(base + perPlayer × additional) where additional = max(0, players - 1). Also switched ceilfloor to match Mojang's rounding.
  • Secondary fallback bug surfaced by the same code path. When Paper's state.trackedPlayers returned empty (e.g. between waves), the recompute fell back to wave.participatingPlayers.size — which counts players within the boss-bar detection radius (default 20 blocks), not within the spawner's requiredPlayerRange (default 14). With more players in the boss-bar radius than vanilla actually tracked, the fallback could inflate the result beyond what state.trackedPlayers.size would have produced. Fallback is now 1 so it can never exceed what the authoritative API would say.

Changed

  • ResetManager.resetChamber now consults ChamberResetEvent.snapshotOverride after firing the pre-event. If non-null, the override bytes are restored instead of the on-disk snapshot; if the override fails to load, the on-disk snapshot is used and a warning is logged. Internal helper restoreFromSnapshotBlocks extracted to share the BlockRestorer call between the on-disk and override paths.
  • SpawnerWaveListener gains a wild-spawner-replacement branch that fires immediately after configureWildSpawnerCooldown. When no WildSpawnerResolver service is registered (the default in free TCP), the branch is a single nullable lookup and a return-false — zero behavior change for end users.
  • TrialChamberPro.onEnable registers SpawnerPresetPlaceListener alongside the existing listener block, and registers the DatabaseManager instance with ServicesManager immediately after it initializes.
  • TrialChamberPro.getMessage and getMessageComponent share a new private helper rawMessageWithPrefix for placeholder substitution + chat-prefix logic. Behavior is identical to v1.3.x but the Component path now exists alongside the String path.
  • SpawnerWaveManager's private boss-bar getMessageComponent helper now delegates to plugin.getMessageComponent so boss bars inherit the same MM-aware parsing as chat messages. The local LegacyComponentSerializer import is removed.

Совместимость

Minecraft: Java Edition

26.1.x1.21.x

Платформы

Поддерживаемые окружения

Сервер

Детали

Лицензия:CC-BY-NC-ND-4.0
Опубликован:6 месяцев назад
Обновлён:2 дня назад
Главная