Skip to content

Add XML-defined machines, generated screens and recipe bundles - #97

Merged
dshadowwolf merged 4 commits into
master-2.0-1.21.1-neofrom
codex/xml-machines
Nov 8, 2026
Merged

dshadowwolf merged 4 commits into
master-2.0-1.21.1-neofrom
codex/xml-machines

Conversation

@faceofcat

Copy link
Copy Markdown
Collaborator

Machines can now be declared in XML without a machine-specific block or block-entity class. The companion's SimpleCrusher inherits power and common controls from a base machine definition, generates its inventory/progress layout, and processes generated or authored recipes through the shared runtime.

  • Add machine XML inheritance, stable slot groups, generic registration/runtime, generated cube resources and recovery capsules. Support both individual slots and counted slot groups.
  • Add generators for screen placeholders/fills, centered machine inventories, clickable processor arrows that open JEI, and recipe views sized to display energy and processing time.
  • Add recipe generators with custom XML properties. Ore-to-ingot generation discovers metals from reload tags, supports ordered mod preferences and optional per-level tool/hardness cost scaling.
  • Add named multi-recipe JSON bundles with stable IDs, conditions and collision checks. Validate authored and generated recipes against XML machine groups before publishing a reload; failed reloads preserve the active recipes.
  • Combine a CRC32 of resolved machine XML with the screen fingerprint for client/server compatibility, including inherited storage settings.
  • Address the inventory review findings: optional highlights, duplicate recipe bindings, legacy slot/tank remapping, reserved save keys, clearer processor states, cached recipe admission and related cleanup.

The supported XML scope is powered item processing with one item storage, one processor/type and cube appearances. Fluid declarations, multiple processors and loose content packs remain future work. Public documentation and runnable XML/JSON examples are included.

Validation:

  • gradlew check build --offline passed after merging master-2.0-1.21.1-neo: 185 unit tests, 74 library GameTests, 67 companion GameTests, packaging/import/static-asset checks.
  • Focused SimpleCrusher client smoke passed registration, generated layout, recipe synchronization, bundled recipes in JEI, menu compatibility, rejected-reload preservation and subsequent successful reload.
  • Focused processor-button client smoke passed synchronized states, translated tooltips and real clicks.
  • The main-branch merge changed no source files; the focused client results cover the merged tree.
  • git diff --check passed.

@faceofcat
faceofcat requested a review from dshadowwolf November 7, 2026 16:51
@dshadowwolf

Copy link
Copy Markdown
Collaborator
  1. merge() matches inherited children by name+id, so a child machine that uses a different id for a single-valued element ends up with two siblings and fails to load.
  2. One bad machine recipe or one failing generator throws IllegalArgumentException inside the reload listener's apply(), which aborts the whole data reload instead of skipping that recipe the way vanilla does.
  3. key() gives every child without an id or name the same 'name:' key, and merge() puts children into a LinkedHashMap by key, so same-type siblings without ids collapse to the last one.
  4. Adding <xs:anyAttribute processContents="skip"/> to templateContent turns off unknown-attribute checks on every <fill> and <placeholder>, including hand-written screens that never use generators.
  5. The check that resource-group highlights point to existing screen elements was removed for all hosts, not only for XML machines (which compute their highlights from the screen and could never miss).
  6. Every block-entity construction re-runs the Screens lookup, scans all screen elements once per group, and repeats ScreenInventoryValidation, although all of it depends only on the definition.
  7. The reserved storage-ID list is a hand-copied duplicate of MachineInventoryLifecycle.RESERVED_KEYS (with 'energy' added) instead of reusing that set.
  8. Processor-button icons and value labels are hard-coded space-separated lists that must match the order and count of ProcessorButtonState values; the stop icon is repeated three times to pad for STALLED, BLOCKED and HELD.
  9. The same lambda that throws 'No generator context' is copied three times (ScreenLoader lines 42 and 104, ScreenTemplates line 24), and the BiFunction type is spelled out with full package names at each signature.
  10. Float.parseFloat(hardness) and the ResourceLocation.parse calls (mineable, textures, extends, recipe-type) throw raw exceptions with no file and line, unlike the number()/color() helpers in the same file.
  • if someone from a comma is the decimal separator nation writes a file using their national standard, it will break things with Float.parseFloat at a minimum.

@faceofcat

faceofcat commented Nov 8, 2026 •

Copy link
Copy Markdown
Collaborator Author
  1. Rejecting the candidate reload is intentional. Authored recipes and generators are validated as a complete set; a failure leaves the previously active recipes intact instead of publishing a partial set. This is covered by the failed-reload regression test.

  2. Missing highlight targets are intentionally optional for every host. Throwing during menu construction could disconnect a player over a cosmetic screen mismatch. The drawer already skips missing targets, and XML machines derive theirs from the screen.

fixed all the rest

* should be 5 not 3 but github renders it wrong :)

@dshadowwolf
dshadowwolf merged commit c3a58cc into master-2.0-1.21.1-neo Nov 8, 2026
5 checks passed
@faceofcat
faceofcat deleted the codex/xml-machines branch November 8, 2026 03:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants