EternalTD Content Packages
EternalTD now tracks official content through a content_packages config set and exposes those packages through /etd setup.
Package Categories
The current code uses three package categories:
FREEPREMIUMRESOURCES
The setup menu currently exposes those as:
Free ContentPremium PacksResources
Verified Premade Packages
These are the premade packages currently defined in the repo:
| Package | Category | Toggleable in /etd setup | Tracked assets |
|---|---|---|---|
EternalTD Hub World | Free | No | Server world-container folder etd_spawn |
EternalTD Tutorial | Free | Yes | tutorial.yml, tutorial_waves.yml, tutorial_npc.yml, etd_tutorial |
Towers of the Grassy Lands | Free | Yes | 5 level files, 1 waves file, 1 NPC file, 5 worlds |
Towers from the Depths | Premium | Yes | 5 level files, 1 waves file, 1 NPC file, 5 worlds |
Towers of the Rising Sun | Premium | Yes | 5 level files, 1 waves file, 1 NPC file, 5 worlds |
EternalTD Custom Models | Resources | No | Marker file only, plus imported FreeMinecraftModels content when present |
Package Lifecycle
The package browser currently distinguishes between:
- not downloaded
- not installed
- installed
- partially installed
- out of date and updatable
- out of date but inaccessible
- needs access
That state is computed from tracked assets on disk, isEnabled flags inside tracked config files, and Nightbreak access/update checks.
Two detection rules matter when a package looks stuck on "partially installed":
- World-container folders are matched at both layouts. Paper 26.1 and newer migrate plugin worlds into
<level-name>/dimensions/minecraft/<world>. EternalTD counts a world-container folder as present if it exists at either the legacy root or the migrated location, and it deliberately checks for the folder, not forlevel.dat— requiringlevel.datwould flip the package to "not installed" during a partial migration and trigger a re-install that Paper then refuses to merge. - Marker-tracked packages have a content fallback. A package tracked only by a marker file can also be detected by the presence of its content folders under
plugins/. When that happens the marker is written immediately so the state stays stable afterwards. This is what makes the custom models pack read as installed when its models were imported by hand instead of through the menu. The fallback folder list is defined in code, not read from the package's YAML.
Toggleable vs Shared Packages
Toggleable packages work by flipping isEnabled inside tracked config files under:
plugins/EternalTD/levels/
plugins/EternalTD/waves/
plugins/EternalTD/npcs/
Shared packages do not behave like normal toggles:
- The hub world is treated as shared installed content.
- The custom model pack is treated as shared resource content.
For those packages, the setup menu tells you to remove files manually and then run /etd reload.
Bulk Operations
The bulk content operations currently implemented are:
/etd downloadall— downloads the EternalTD plugin update and all available content/etd downloadallcontent— downloads all available content (no plugin update)/etd updatecontent(alias/etd updateallcontent) — downloads only outdated content
The content download/update commands:
- require a linked Nightbreak token
- download into
plugins/EternalTD/imports - skip packages that are inaccessible or already current
- reload EternalTD automatically after successful downloads
/etd downloadall additionally checks for and downloads a plugin update first; if no token is linked or authentication fails it stops before the content step.
Practical Notes
- Package checks deduplicate by Nightbreak slug before bulk download/update.
- The setup UI refreshes content and access info on a cooldown instead of hitting Nightbreak on every open.
- The custom models package writes a marker under
plugins/EternalTD/content_markers/so EternalTD can track that the shared resource package was downloaded. - Tracked level, wave, and NPC files are matched by filename anywhere beneath
levels/,waves/, andnpcs/, so packages that ship their files in a subfolder are still detected. Towers of the Rising Sunpreviously tracked its wave file astowers_of_the_rising_sun.ymlwhile the pack actually shipstowers_of_the_rising_sun_waves.yml, which left it permanently reading as not fully installed. The tracked name is now corrected automatically and written back to the package config on load — no manual fix needed.