Skip to content

Blog 2026 04 26

Claude edited this page Apr 28, 2026 · 1 revision

Home > Blog > 2026-04-26

Dev Log — 26 April 2026

The editor got a massive overhaul: a world-space part-position panel with weighted variants and side-modes, a world-space block-variant menu with lock groups, and a new Exit button. Auto-promote landed for weights and part assignments, the classpath scanner unified template discovery, and public-release assets (LICENSE, mods.toml, logo) shipped. 24 PRs merged.

Note: The GitHub Release pipeline (CI workflows) shipped the following morning. These changes are available from v0.70.0 onwards — see Downloads for the latest jar.


Features

World-space block-variant menu with lock groups (#71)

Tap Z while looking at a block inside any editor plot (carriage / contents / part / track) to open a billboarded panel anchored to the targeted face. The panel lists every candidate block with its name and weight, and a six-cell toolbar: Copy | Add | Lock | Remove | Clear | X.

  • Add captures the player's main hand; empty hand adds the air-sentinel ("nothing").
  • Copy produces a dungeontrain:variant_clipboard item (styled after a command block) that carries the full variant list and lock-id in NBT.
  • Lock groups — clicking Lock cycles the cell's lock-id 0 → nextFreeLockId() → 0. Cells with the same non-zero lock-id share their state list (auto-propagated on edit) and share their random pick at spawn. The only way two cells join a group is via Copy/Paste.
  • Hold-Z + right-click still appends a held block — the legacy flow is preserved; tap vs. hold is detected client-side (≤ 8-tick press without an interaction = tap).
  • Schema bumped v3 → v4. Cells with lockId > 0 serialize as { "lockId": K, "states": [...] }; lockId = 0 cells remain bare arrays so v3 sidecars round-trip diff-clean.
  • Protocol bumped 4 → 5 with three new packets: BlockVariantSyncPacket (S2C), BlockVariantEditPacket (C2S), BlockVariantMenuTogglePacket (C2S).
  • First DeferredRegister<Item> in the project (the clipboard item).

World-space part-position menu with weighted + sided variants (#67)

A billboarded panel auto-opens anchored on the inward face of FLOOR / WALLS / ROOF / DOORS regions inside carriage variant plots. Toolbar: Add | Remove | Clear | X. Each entry shows its weight; walls and doors also show a 3-state side-mode toggle: (2) both sides, (1) one side, (1|2) either side, rolled deterministically per (seed, carriageIndex, kind).

  • Slash-command parity: /dungeontrain editor part add now accepts an optional [weight] arg.
  • Schema bump to .parts.json v2: entries become { name, weight[, sideMode] }. Full back-compat for v1 string entries (loaded as weight=1, sideMode=BOTH); on first save the file is rewritten in v2 form.
  • Protocol bumped 3 → 4. Three new packets: PartAssignmentSync (S2C), PartAssignmentEdit (C2S; ops ADD/REMOVE/CLEAR/BUMP_WEIGHT/CYCLE_SIDE_MODE), PartMenuToggle (C2S).
  • EditorMenuScreen gains a "Part Variant Menu" toggle row; /dungeontrain editor partmenu on|off mirrors it.

Stair adjunct row in Tracks editor + new sleeperless track (#66)

PillarAdjunct.STAIRS templates had full world-side infrastructure but were missing from EditorModel's sealed dispatch — so the row never appeared in category iteration, the HUD didn't recognise the plot, and /dt save all skipped them. Adds EditorModel.AdjunctModel and wires every instanceof EditorModel.* cascade across SaveCommand, ResetCommand, EditorCommand, and VariantOverlayRenderer.

Stair plots now appear next to pillars in the Tracks category with their own row of variants. A new bundled sleeperless.nbt track template also ships with this PR.

Save bundled templates + fix adjunct weight row (#68)

New bundled templates committed to src/main/resources/data/dungeontrain/:

  • pillars/adjunct_stairs/ladder.nbt
  • tracks/sleepside.nbt
  • Refreshed pillars/adjunct_stairs/default.nbt and tracks/sleeperless.nbt

Also fixes a bug in VariantOverlayRenderer.modelNameFor() where the missing AdjunctModel case caused the editor weight row to persist bogus entries like {"adjunct_stairs": 20} to weights.json. Bundled weights are now clean: adjunct_stairs/weights.json = {"default": 20}.

Editor Exit button replaces Back (#72)

The bottom < Back row in EditorMenuScreen is replaced with an Exit button that runs dungeontrain editor exit. Previous behaviour merely popped the menu stack, leaving the player stranded inside the editor plot. Exit now fully unwinds the session, clears the editor plots, and teleports the player back to where they entered. EnterCategoryMenuScreen retains its < Back for the drilled-in sub-screen.

Auto-promote weight tweaks to source tree (#73)

Every in-game weight edit (/dt editor weight, the [-] Weight (N) [+] HUD row) now writes to both config/dungeontrain/.../weights.json (local override) and src/main/resources/data/dungeontrain/.../weights.json (bundled default). The auto-promote is gated on sourceTreeAvailable() — end-user installs are unaffected.

Unified classpath scan for bundled template variants (#74)

All four template registries — CarriageVariantRegistry, CarriageContentsRegistry, CarriagePartRegistry, TrackVariantRegistry — now use a shared BundledNbtScanner that walks the classpath at server start. Drop a new .nbt into src/main/resources/data/dungeontrain/... and it auto-registers; no manifest update required. Handles file:, jar:, and Forge's union: URL schemes.

Auto-promote part-variant edits to source tree (#75)

The same source-tree write-through from #73 now applies to per-carriage part assignments edited via the in-world block-variant menu. Every menu mutation writes to both config/dungeontrain/templates/<id>.parts.json and src/main/resources/data/dungeontrain/templates/<id>.parts.json. No devmode on toggle required; the gate is purely whether src/main/resources/ is writable.

Prevent duplicate variants in menus (#77)

Both the block-variant menu and the part-variant menu now reject duplicate entries at insertion time, keeping variant lists clean without needing a manual dedup pass.

New roof/wall parts, windowed template, content updates (#79)

New bundled parts: additional roof and wall pieces plus a windowed carriage template. Existing content received polish updates.

In-place previews on name click — block-variant and parts menus (#83, #85)

Clicking an entry name in the block-variant menu or the parts menu now previews that block or part in-place inside the plot so you can audition options visually without committing the change.

Per-entry rotation: lock / random / options (#89)

Each block-variant entry now carries its own rotation mode: lock (use the source block's exact rotation), random (randomise on place), or options (cycle through a listed set). The editor shows a live preview of the selected mode while authoring.

First public release prep (#90)

LICENSE (MIT), mods.toml metadata fields, and the refreshed mod logo are committed in preparation for the first public release.


Fixes

Parts grid uses bedrock cage (#69)

CarriagePartEditor was the only editor using Blocks.BARRIER for its outline cage. Barriers are invisible in survival, so the parts grid (FLOOR / WALLS / DOORS / ROOF rows) appeared as floating templates while the carriage row above had clear bedrock bounds. One-line change switches OUTLINE_BLOCK to Blocks.BEDROCK for visual consistency across the entire carriages-editor scene.

Part-position menus hidden while X command menu is open (#70)

The auto-opening part-position panel now early-returns when CommandMenuState.isOpen(), so it hides the moment the worldspace X menu opens. When X closes, the panel pops back on whatever the crosshair is now on.

Variant entry cleared on block break in editor plots (#80)

Breaking a block inside an editor plot now clears its associated variant entry, so stale variant data can no longer accumulate on air blocks.

Paste preserves source texture; lock-id renders on all six faces (#81)

Paste operations carry the source block's texture through correctly. The lock-id indicator now renders on all six faces of the target block.

Remove button wipes plot blocks and bedrock cage (#82)

Pressing Remove now fully clears both the plot's block content and its surrounding bedrock cage, leaving no ghost geometry.

Block-variant menu anchor no longer drifts (#86, #87)

The block-variant context menu anchor froze at the wrong screen position when the player moved after opening the menu. The anchor is now recaptured on every click.

Block-variant data recovered; sidecar auto-promoted in dev mode (#88)

Lost block-variant data (entries that went missing after certain editor operations) is now recovered correctly. In dev mode, the variant sidecar is auto-promoted to the source tree so edits persist across restarts.


Part name freed on rename so it can be reused (#78)

Renaming a part now releases the old name immediately. Previously the old name stayed reserved until a restart, making it impossible to re-use it within the same session.


Tests

Stale AdjunctStairsBundledGenTool removed (#91)

A test that expected a 3-entry palette in adjunct_stairs/default.nbt was failing after the bundled template was refreshed to 7 entries. The test was deleted rather than updated — it tested the shape of a specific NBT file rather than behaviour, so it provided little ongoing value.

Clone this wiki locally