
ZombieApocalypseSSS
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
4.4.0
Compatibility
Changes
[4.4.0] - 2026-04-17 - Bug Purge & Correctness Update
Fixed
-
SurvivalGuideListener.PAGE_KEYNPE on startup —static final NamespacedKey PAGE_KEYwas initialised at class-load time before the plugin instance existed, causing aNullPointerExceptionon every server start.PAGE_KEYis now an instance field initialised in the constructor. (BF-01) -
InfectionListenerignoredinfection.enabledconfig — infection spread on every zombie hit regardless ofinfection.enabled: falseinconfig.yml.ZombieBehaviorServicealready checked the flag butInfectionListenerdid not, making the config option partially ineffective. (BF-02a) -
InfectionListenerignoredzapoc.immunepermission — players withzapoc.immunecould still receive infection points. The permission is now checked in bothInfectionListenerandZombieBehaviorService. (BF-02b) -
Day-based spawn-rate (
shouldSpawn()) was completely bypassed —ZombieBehaviorServiceruns atEventPriority.HIGHand cancelled natural spawns beforeSpawnListenerran, so the phase-based rates (40% / 70% / 90% / 100%) never took effect — zombies always spawned at 100% regardless of server age.shouldSpawn()is now called directly insideZombieBehaviorService.onCreatureSpawn. (BF-03) -
TurretManagercould permanently deleteturrets_data.yml— the save code calleddataFile.delete()beforerenameTo(). If the rename failed the data file was gone permanently. Replaced withFiles.move(ATOMIC_MOVE)and a non-atomic fallback. (BF-04) -
Sanity config multipliers loaded but never applied —
sanityDrainBase,nightMultiplier,infectedMultiplier,lowHealthMultiplier, andnearbyZombiesMultiplierwere read frommechanics.ymlbutupdateSanity()used hardcoded constants. Editing these values in config had no visible effect. All five multipliers are now applied correctly. (BF-05) -
whisperPhrasesconfig key loaded but never used —handleWhispers()used an internal hardcoded array instead of the phrases frommechanics.yml. Player-configured phrases includingphrases-vi/phrases-enare now displayed correctly. (BF-06) -
hg.no-netherite-dropbypass via corpse zombie — the death handler stripped netherite fromevent.getDrops()but then re-equipped the corpse zombie with raw armour including netherite. A player could kill the corpse to recover the items. Netherite is now stripped from the corpse's equipment when the option is enabled. (BF-07) -
Tank zombie
ENTITY_RAVAGER_STEPsound spam —handleTank()fired a full-volume step sound every 0.5 s with no throttle, flooding clients when multiple Tank zombies were active. A 10% per-call chance now limits the frequency. (BF-08) -
panicCooldownsHashMap memory leak — UUID entries were added on/zapoc panicbut never removed on disconnect. Entries are now removed inonPlayerQuit. (BF-09) -
Stalker spawn used zombie's world for player's Y lookup —
getHighestBlockYAt()was called on the zombie's world; if the target player had recently changed worlds the Y could be wrong. Player's own world is now used for the lookup. (BF-10)
Performance
-
handleSunEffect()YAML reads inside per-zombie loop eliminated — sevenFileConfiguration.get*()calls per zombie per tick removed. All sun-effect config values are now cached at task level and refreshed every 5 s. Eliminates ~1,400 redundant map lookups per second at 200 tracked zombies. (BF-11) -
Math.random()replaced withThreadLocalRandomthroughout — 20+ usages replaced acrossCampfireManager,ZombieApoc,ZombieBehaviorService,ZombieBehaviorTask,PlayerStatusTask,WorldEventTask,ZombieEvolutionService, andSpecialZombieListener. (BF-12)
Notes
- No config changes required. All existing
data.yml,campfires.yml, andturrets_data.ymlare fully compatible.
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:pSQD27Eo:oJnjB0Sm"
}
// Legacy Loom dependency
dependencies {
modImplementation "maven.modrinth:pSQD27Eo:oJnjB0Sm"
}
