Skip to main content

EternalTD Content Packages

EternalTD 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:

  • FREE
  • PREMIUM
  • RESOURCES

The setup menu currently exposes those as:

  • Free Content
  • Premium Packs
  • Resources

Verified Premade Packages​

These are the premade packages currently defined in the repo:

PackageCategoryToggleable in /etd setupTracked assets
EternalTD Hub WorldFreeNoServer world-container folder etd_spawn
EternalTD TutorialFreeYestutorial.yml, tutorial_waves.yml, tutorial_npc.yml, etd_tutorial
Towers of the Grassy LandsFreeYes5 level files, 1 waves file, 1 NPC file, 5 worlds
Towers from the DepthsPremiumYes5 level files, 1 waves file, 1 NPC file, 5 worlds
Towers of the Rising SunPremiumYes5 level files, 1 waves file, 1 NPC file, 5 worlds
EternalTD Custom ModelsResourcesNoMarker 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 for level.dat — requiring level.dat would flip the package to "not installed" during a partial migration and trigger a re-install that Paper then refuses to merge.
  • The model package has a content fallback. A non-empty FreeMinecraftModels/models/EternalTD default towers or legacy FreeMinecraftModels/Models/EternalTD default towers folder under plugins/ counts as present. EternalTD then tries to write the marker; a write failure is logged. This folder list is defined in code, not the package YAML.

These are presence and enablement checks, not a playable-content check. A marker can remain after models are removed, and detecting a world folder does not validate its contents. Missing tracked assets take precedence as partially installed; with all assets present, a mix of enabled and disabled tracked configs also gives that state.

Toggleable vs Shared Packages​

Toggleable packages work by flipping isEnabled inside tracked config files under:

plugins/EternalTD/levels/
plugins/EternalTD/waves/
plugins/EternalTD/npcs/

The package's own isEnabled flag is saved too, followed by an EternalTD restart. Disabling keeps the files on disk. The installed state is determined by the tracked files, not just the package flag. The toggle reads every tracked file before writing any of them; if one cannot be read, no file is changed. Likewise, if /etd setup cannot read a tracked file while refreshing package states, the menu does not open and you are told to check the console.

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
  • select missing or outdated packages for downloads; updates select outdated packages and skip cached access denials
  • reload EternalTD automatically after successful downloads

For normal downloads, cached access is advisory: the authenticated download request makes the current access decision. Packages already downloaded and current are skipped, even if their configs are disabled. Use their setup toggle to enable them. /etd forcereinstallcontent <package|all> repairs missing or damaged files even at the current version; all selects detected downloads, while a named Nightbreak slug can target a wholly missing package.

/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 requests content and access refreshes on a five-minute 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/, and npcs/, so packages that ship their files in a subfolder are still detected.
  • Towers of the Rising Sun previously tracked its wave file as towers_of_the_rising_sun.yml while the pack actually ships towers_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.