Links
Tags
Creators
Details
4.3
Compatibility
Changes
[4.3] โ Stabilization Patch 3
Fixed
High
-
H-04 ยท
FeastManagerโ double announce + possible double-spawn (FeastManager.java) Theannounce-minuteslist inconfig.ymlpreviously included both20and19, causing two broadcasts in the very first minute of the match. Even after the config was corrected in v4.1, a subtler edge still remained:timerSeconds == 0at the moment the PLAYING state begins, andfeastSeconds - 0 * 60 == 0โ meaning any 0-minute entry in the list would fire instantly. Fix: GuardtimerSeconds <= 0returns immediately. AddedfeastSpawnedset (ConcurrentHashMap-backed) so the feast spawns exactly once per match regardless of how many scheduler ticks land on the boundary second. AddedresetArena(name)to clear the flag between matches. -
H-06 ยท
DungeonManager.getMobHP()fallback40.0vs config60.0(DungeonManager.java) Theconfig.ymldeclareddungeons.mob-hp: 60.0as the intended default, but the code fallback was40.0. When the key was absent the generic dungeon mobs (Spider Queen, Crypt Stalker, Gold Miner, Temple Guardian) spawned with 40 HP โ one-third weaker than designed. Fallback corrected to60.0.
Medium
-
M-04 ยท
Excaliburโ reflection hit dungeon mobs, bypassed team system (Excalibur.java)performDamagedreflected against anyLivingEntityattacker. When a dungeon mob hit the Excalibur holder, the reflected damage still had the player as the source, which could splash into nearby arena players and bypassed team friendly-fire checks entirely (the team check only ran forPlayerattackers). Reflection is a PvP mechanic; mob attacks should not trigger it. Changed the guard frominstanceof LivingEntity attackertoinstanceof Player attacker. The projectile deflect block remains unchanged (projectiles can originate from any source). Also added a self-damage guard (attacker.equals(player)) for defensive robustness. -
M-05 ยท
MjolnirโrotationAnglefloat unbounded, overflows after ~18 h (Mjolnir.java)rotationAnglewas incremented byrotationSpeedon every passive tick with no upper bound. A 32-bit float mantissa has 24-bit precision; at 25ยฐ/tick ร 20 ticks/s the angle exceeds2ยฒโดin roughly 18 hours of continuous operation, after whichrotateY(Math.toRadians(angle))silently produces garbage rotation matrices and the thrown hammer stops orbiting correctly. Both increment sites now use% 360fto keep the angle in[0, 360). -
M-06 ยท
VeinMinerListenerโmaxVeinSizenot hot-reloadable (VeinMinerListener.java) The field was read once in the constructor and cached for the lifetime of the plugin./perf reload(or any config reload) had no effect on vein size until the next server restart. Removed the cached field;maxVeinSizeis now read from config on everyBlockBreakEventand passed as a parameter tofindVein(). -
M-08 ยท
ArenaListenerโ duplicate no-arg constructor using staticMain.getInstance()(ArenaListener.java) A second constructorpublic ArenaListener()accessedMain.getInstance()โ a static singleton call that fails during class initialisation if the plugin is not fully loaded, and couples the listener to the static instance rather than the injected one. The no-arg constructor was a leftover comment artifact; removed. -
M-09 ยท
DatabaseManager.getPlayerStats()โ synchronous query on main thread (DatabaseManager.java) The method opened a JDBC connection and ran aSELECTon whichever thread called it. When called from command handlers or event listeners on the main thread this blocked the server tick for the entire round-trip. Replaced withgetPlayerStatsAsync(UUID)returningCompletableFuture<Map<String,Object>>dispatched to the Bukkit async scheduler. The original synchronous method is kept as@Deprecated getPlayerStats()(delegates togetPlayerStatsSync) for any call-sites that already run on async threads. -
M-10 ยท
PerformanceOptimizer.toggleMonitoring()always returnedtrue(PerformanceOptimizer.java) The implementation wasreturn activeTasks.get() >= 0โ anAtomicIntegeris always โฅ 0, so the method always returnedtrueregardless of monitoring state. AddedAtomicBoolean monitoringEnabled(defaulttrue);toggleMonitoring()now inverts the flag and returns the new state.
Low
-
L-06 ยท
AbilityDispatcher.LEGEND_KEYstatic field initialised beforeonEnable()(AbilityDispatcher.java) The fieldprivate static final NamespacedKey LEGEND_KEY = new NamespacedKey(Main.getInstance(), "hg_ability")is evaluated when the class is first loaded. If any class (e.g. a command tab-completer) causedAbilityDispatcherto be loaded beforeMain.onEnable()completed,getInstance()returnednulland every subsequent ability dispatch threw NPE. Changed to lazy initialisation via a privategetLegendKey()method that constructs the key on first use. -
L-07 ยท Hardcoded test-item blacklist
gerald_sniffer/gruntilda/tim_enchanter(ArenaManager.java,config.yml) Three internal test legendary IDs were hard-coded instartCornucopiaPhase2(). Replacing them requires a recompile. Moved to config:legendary.excluded-ids: [](default empty). Server owners can now exclude any legendary from the active pool without touching source code. -
L-09 ยท
buildCornucopia()calledoriginalBlocks.clear()destroying prior tracking (ArenaManager.java) Spawn cages and dungeon structures calloriginalBlocks.put()to record every block they place, enabling full restoration on arena reset.buildCornucopia()calledarena.originalBlocks.clear()before building the Cornucopia, erasing all prior entries. On reset, only blocks placed after the clear were restored โ cages and dungeons were left as permanent terrain edits. Theclear()call is removed;CornucopiaBuilderalready appends to the map with individualput()calls. -
L-10 ยท
GameTaskextendsBukkitRunnablebut is never scheduled โ double-tick risk (GameTask.java)GameTaskwas a deadBukkitRunnablesubclass. The arena tick is driven entirely byArenaManager.tick()via the global loop inMain.onEnable(). If a future developer saw the class and scheduled it directly, every arena would tick twice per second.GameTask.run()now throwsUnsupportedOperationExceptionimmediately, surfacing the bug during development rather than silently corrupting timer state.
Projects on Modrinth are automatically available through a Maven repository for use with JVM build tools such as Gradle. To learn more about the Modrinth Maven API, click here.
Note: When available, you should use the creator's maven repo instead as it will have transitive dependency information that the Modrinth Maven API does not. You may also end up with duplicate dependencies if you use a mix of Modrinth and non-Modrinth Maven repositories for your dependencies, because the group identifier will be different when served through the Modrinth Maven API.
Maven coordinates:
Version ID:
build.gradle:
repositories {
exclusiveContent {
forRepository {
maven {
name = "Modrinth"
url = "https://api.modrinth.com/maven"
}
}
// forRepositories(fg.repository) // Uncomment when using ForgeGradle
filter {
includeGroup "maven.modrinth"
}
}
}
// Standard Gradle dependency
dependencies {
implementation "maven.modrinth:VxdGAFxk:q1sqVlcw"
}
// Legacy Loom dependency
dependencies {
modImplementation "maven.modrinth:VxdGAFxk:q1sqVlcw"
}

