All versions
1.5.0
Release
EternalTD 1.5.05 months ago 42
Compatibility
Minecraft: Java Edition
26.1.x
1.21.4–1.21.11
Platforms
Paper
Purpur
Spigot
Changes
EternalTD 1.5.0:
- [New] Now updated to run in Minecraft 1.21.4-21.1.2
- [New] Placement highlight — per-session BlockDisplay slab tracks the player's look ray and recolors by grid state (lime buildable, red occupied, light-blue path, hidden off-grid); started in LevelSession, lives in PlacementHighlight.
- [New] Nightbreak setup flow — EternalTDSetupMenu and EternalTDFirstTimeSetupMenu wired via NightbreakPluginSpec / NightbreakFirstTimeSetupSpec, with /etd setup, /etd downloadall, /etd updatecontent and the ETDPackage content pipeline (ContentPackageConfig, ETDPackageRefresher).
- [New] World protection — LevelSession registers each instanced world with MagmaCore InstanceProtector using WorldProtectionRules (no explosions, no liquid flow, no elytra, no fly toggle, no friendly fire, no vanilla mob spawning).
- [New] Phased init — onEnable now drives NightbreakPluginBootstrap with separate asyncInitialization / syncInitialization steps and proper shutdown / reload via reloadImportedContent.
- [Fix] Tower-fired projectiles and FMM-modeled mobs no longer face random directions while travelling — the ItemDisplay fake-arrow path in BasicDamageTower was reading the skeleton's body yaw on spawn / teleport, which is random when setAI(false) is set. ItemDisplay now spawns and teleports with yaw=0, pitch=0 so only the transformation Quaternionf controls visual orientation. Air WaveEntity movement now also sets the teleport Location direction to the movement vector so non-Mob flyers face their travel direction (Mob path was already handled by NMS forcedMove).
- [Fix] Tutorial "upgrade these towers" red arrows now actually appear above the towers — the reddownarrow indicator armor stand was spawning 4 blocks above the grid square, which placed it inside the tower structure. Now spawned 7 blocks up.
- [Fix] Tower lore stats no longer display long IEEE-754 floating-point tails (
123.4500000000007) — BasicDamageTower, SpyglassSupportTower, and ExplosionFactoryTower now wrap baseDamage, baselineBonusRange, baselineAoeRange, and other double lore fields with Round.twoDecimalPlaces, matching the formatting DamageTower.updateBonusDisplays already uses for bonus stats. - [Fix] Items dragged into an NPC's interaction menu are no longer lost on close — NPCEntity now unconditionally cancels InventoryClickEvent for clicks inside the menu (selection on left-click of the green pane still works), and a new dragInMenuEvent cancels InventoryDragEvent. NPC menus are now strictly read-only.
- [Fix] Spigot 26.1 spawn-world quirk — LevelSession rebuilds the spawn Location against the explicit world before teleport, since getSpawnLocation() could return the main world.
- [Fix] Paper 26.1+ world layout — WorldContainer uses MagmaCore TemporaryWorldManager.loadVoidTemporaryWorld and WorldFolderResolver to scan and delete both legacy and modern world folders, preventing index collisions and stale-data bleed-through.
- [Fix] BasicDamageTower projectile — replaced real Arrow entities (invalidated within ticks on 26.1) with an ItemDisplay fake arrow oriented via a Quaternionf transform, with manual damage on proximity.
- [Fix] Legacy data migration — onEnable renames legacy Levels / NPCs folders to lowercase levels / npcs.
- [Tweak] Air wave balance — air mobs now spawn at 50% HP and 50% speed (was 75% each). The +4 Y offset effectively shrinks every damage tower's horizontal reach against air targets (
sqrt(R² − 16)), and the old 75% multipliers didn't compensate enough for that range loss. FAST + AIR also no longer compounds to faster-than-ground speed (0.3 × 1.5 × 0.5 = 0.225is now slower than a normal ground mob's0.3). - [Tweak] World-folder-copy logging downgraded from WARN to debug — WorldContainer's per-file
File:/Target path:lines for every region / data file during instance world setup no longer scream at WARN level (~30 lines per tutorial instance). Genuine "Failed to copy" / "Failed to create" failures remain at WARN. - [Tweak] Build — Minecraft 1.21.11 API, Java 21 toolchain, FMM 2.5.0+, MagmaCore 2.2.0-SNAPSHOT, com.gradleup.shadow 9.0.0-beta12, LibsDisguises pinned at 10.0.18, EasyMinecraftGoals dependency dropped (now shaded via MagmaCore and relocated to com.magmaguy.eternaltd.easyminecraftgoals), ProtocolLib removed, /logify command and permission dropped.
- [Tweak] Requires latest FreeMinecraftModels (2.5.0+) and the matching MagmaCore build; softdepends on Floodgate and ResourcePackManager.
- [Tweak] Various MagmaCore library improvements (Lua scripting engine + zones moved to MagmaCore, EasyMinecraftGoals absorbed, NMS v26 / Paper 26.1 support, WorldFolderResolver + Paper-migration debris quarantine, TemporaryBlockManager and createTemporaryWorldWithGenerator / loadTemporaryWorldWithGenerator, SetupMenuBuilder + InfoButtonFactory + NightbreakSetupIcons shared UI, ContainerAllowlist / WorldProtectionRules instance protection, MagmaCore.exportSharedAssets / enableWorldProtections / isShutdownRequested, AdvancedCommand optional-argument support, LocationAPI with WorldGuard + GriefPrevention providers, Nightbreak token-change subscribers, ClientboundEntityPositionSyncPacket adoption on 1.21.2+ with Bedrock ClientboundBundlePacket skip, ArmorStand HeadPose force-send every tick for Bedrock attachable rebind, DAMAGE_INDICATOR particle count clamp, per-plugin Netty handler name in PacketInteractionListener, lazy Lua field support, ZipFile STORED-with-EXT-descriptor fix, dedup / rate-limited Nightbreak auth-failure logs).
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:mDarON5p:hK1cxjae"
}
// Legacy Loom dependency
dependencies {
modImplementation "maven.modrinth:mDarON5p:hK1cxjae"
}

