/
ZombieSpawnService.java — spawnBossZombie()setArmorContents() was called without setting drop chances to 0.
Bukkit's default drop chance is ~8.5%, so players could farm Diamond Helmet /
Chestplate by killing the Boss.setHelmetDropChance(0f), setChestplateDropChance(0f),
setLeggingsDropChance(0f), and setBootsDropChance(0f) after every armour
assignment, including the custom-model-data head path.evolveZombie() multiplier overriddenZombieSpawnService.java — spawnBossZombie()spawnCustomZombie() internally called evolveZombie() which
applied a tier health multiplier (up to ×2.5 for ABERRANT), but spawnBossZombie()
then hard-reset the attribute to boss.health config value, discarding the tier
scaling entirely.spawnBossZombie() now sets bossHealth first, then calls
evolveZombie() so the tier multiplier compounds on top of the intended base.
Boss HP in late-game now scales correctly with the threat level.ZombieEvolutionService.java — determineTier()else branch covered threat >= 30, but the class-level
comment stated "Threat > 50: Aberrant possible". Players hit ABERRANT-tier
enemies during Phase 3 (Day ~15) instead of Phase 5 (Day ~25+).threat < 50 bracket (no ABERRANT, Mutated max)
and moved ABERRANT to threat >= 50 only, matching the original design intent./zapoc infect shows hardcoded "10m" regardless of configZombieApoc.java — onCommand() case "infect"incubationTicks was read from config but immediately discarded;
the player message used the literal string "10m".timeDisplay is now derived from incubationTicks / 20 seconds so the
displayed time always reflects the actual configured value.hashCode() % 2 (uneven distribution)ZombieBehaviorTask.java — run()UUID.hashCode() is a 32-bit hash with no uniformity guarantee.
In practice this can result in 70 % of zombies processed on one tick and 30 % on
the other, defeating the purpose of two-bucket batching.UUID.getLeastSignificantBits() which is
a raw 64-bit random value from the UUID v4 spec, giving near-perfect 50/50 split.HallucinationListener double-registration on /zapoc reloadZombieApoc.java — startTasks()startTasks() checked if (hallucinationListener == null) before
creating a new instance, but cancelAllTasks() already set it to null.
In specific edge cases (e.g. psychological-horror.enabled toggled via config
between reloads) the old instance could survive unregistered yet the new instance
would be registered on top.startTasks() now unconditionally calls HandlerList.unregisterAll() and
nulls the field before constructing a fresh HallucinationListener, making the
lifecycle explicit and immune to ordering issues.WorldEventTask blood-moon maps leak UUID entries for unloaded worldsWorldEventTask.javabloodMoonStates and bloodMoonRolledDay used world UUIDs as keys
but never removed entries when a world was unloaded (e.g. on map rotation or
/mv unload). Over time this created an unbounded set of stale entries.WorldEventTask now implements Listener and handles WorldUnloadEvent
to remove both maps' entries for the unloaded world. The task is registered and
unregistered as a listener in startTasks() / cancelAllTasks().ZombieBehaviorTask.javamoanEnabled, moanChance, moanVol, moanPitch,
mutationEnabled, mutationInterval, and breakingEnabled were fetched from
FileConfiguration on every call to run().reloadSunConfigCache().handleExplosive() reads explosive.power from YAML at explosion timeZombieBehaviorTask.javacachedExplosivePower field, populated in reloadSunConfigCache().CampfireManager.isInsideSafeZone() reads check-radius from YAML per callCampfireManager.javaplugin.getMechanicsConfig().getInt("campfires.check-radius", 100)
was called on every invocation. isInsideSafeZone() is called once per second
per online player from PlayerStatusTask, making this a hot path.cachedCheckRadius field, initialised in the constructor and
refreshed in reload().TurretListener used legacy ChatColor string APITurretListener.javanet.kyori.adventure.text.Component
using NamedTextColor and TextDecoration, the standard approach on Paper 1.16+.ZombieApoc.sendActionBar() used BungeeCord spigot bridgeZombieApoc.javaplayer.spigot().sendMessage(ChatMessageType.ACTION_BAR, ...)
with the Paper-native player.sendActionBar(Component) call.
Removed unused net.md_5.bungee.api.* imports.
ZombieApocalypseSSS is a comprehensive Minecraft plugin that transforms your server into a thrilling zombie survival apocalypse. Featuring advanced zombie AI, evolving variants, player infection mechanics, psychological horror elements, and dynamic events