Skip to content

Crafttweaker integration - #98

Merged
dshadowwolf merged 9 commits into
MinecraftModDevelopmentMods:master-2.0-1.21.1-neofrom
dshadowwolf:crafttweaker-integration
Nov 7, 2026
Merged

dshadowwolf merged 9 commits into
MinecraftModDevelopmentMods:master-2.0-1.21.1-neofrom
dshadowwolf:crafttweaker-integration

Conversation

@dshadowwolf

Copy link
Copy Markdown
Collaborator

Add complex, almost feature-parity with ContentTweaker support for CraftTweaker to MMDLib 2.0

dshadowwolf and others added 9 commits November 7, 2026 09:44
Optional CraftTweaker support: #loader mmdlib scripts run once at startup,
before registry events, and define materials, standalone blocks and items,
and new block and item modules (mods.mmdlib.MaterialBuilder, BlockBuilder,
BlockModule, ItemBuilder, ItemModule). All CraftTweaker code lives in
compat/CraftTweaker; MMDLib's constructor reaches it through one call,
made only when CraftTweaker is loaded.

Generated resources: an always-enabled pack supplies blockstates, models,
names, loot tables and tags for script content. Material textures are
blank templates (derived from Base Metals art by
scripts/generate_material_templates.py) multiplied by the material
color; block and item textures come from scripts/mmdlibdata, which is
loaded as an override pack above the generated one.

Core changes the integration needs:
- MaterialExtensions.registerDefinitionSource: code-built materials,
  standalone blocks and items, planned with the same checks as files.
  Sources run after file modules install and before material files
  decode, so files can use modules a source registers.
- MaterialRuntimeSettings.tinted (default true): precolored materials
  skip the client tint.
- CraftTweaker as a compile-only, optional dependency with its
  annotation processor.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Expose script callbacks for item use, melee hits, block breaking, placement, stepping, random ticks, and clicks through shared material event contracts.

Support directional redstone inputs and outputs, delayed updates, comparator readings, and facing-aware generated models. Add runtime smoke fixtures, CraftTweaker game-test scripts, focused unit coverage, and API documentation.
Bring script-defined content closer to ContentTweaker's builder capabilities
without adding parallel script-only factories or extending core schemas and
runtime behavior. Preserve existing script syntax, registry identities, and
optional CraftTweaker loading.

Expose material repair and harvest settings, block runtime overrides, named
tool-stat methods, and typed generic-tool configuration. Add typed item, block,
module, and block-tag references that retain existing resolution timing.

Add module configuration snapshots with independent callback IDs and handler
maps, while retaining shared captured script variables and explicit external
callbacks. Fix item-module tag lookup so builders can inherit tags from modules
registered earlier in the same startup script run.

Add fluent item/block aliases, generated English names, and shape-aware default,
self, empty, and referenced loot controls. Keep resource metadata outside core
definitions, preserve double-slab drops, and retain external pack precedence.

Document the exposed API, runtime consumers, parity scope, executable examples,
and verification results. Record food and creative-tab follow-up TODOs for shared
Java/JSON/CraftTweaker support. Keep per-tool durability scaling explicitly
deferred: vanilla TieredItem replaces the factory's calculated durability with
the material tier's uses; material durability and speed scaling work.

Add focused unit and server fixtures plus isolated real-client smoke runs with
CraftTweaker present and absent. Include fixture texture provenance and keep
smoke content out of release artifacts.

Validation:
- ./gradlew --offline check build: passed; 190 unit tests, 85 MMDLib GameTests,
  52 companion GameTests, static assets, and packaging checks.
- Real integrated-client launches with and without CraftTweaker: passed using
  llvmpipe under Xvfb after native WSL graphics startup failed.
- Inspected rendered names/items/material textures and four directional blocks.
- Inspected release JAR: integration classes present; smoke content absent.
- git diff --check: passed.
- Copying a block module keeps a constant redstone output, and writes a
  constant comparator level back as a number instead of a string that
  RedstoneBlock rejects.
- item-hit fires only for player and mob attack damage; thorns and
  exploding creepers also name one entity as direct and causing source.
- Definition source names must be unique; a second source with the same
  name used to replace the first one's definitions silently.
- Plain items with a food component keep vanilla's use, so the hunger
  check still applies when a use time is set.
- Script hooks check that building is still allowed before changing
  anything, so a late call cannot swap a live handler.
- Duplicate standalone IDs from two sources no longer blame a definition
  file.
- Work out whether a material has a slab once, not once per block.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
RedstoneBlock.signal now delegates to RedstoneChange.signal in the api
package, so the face-signal rule exists once and api still does not
depend on runtime code.

docs/crafttweaker.md explains that on directional blocks compass names in
addInputFaces/addOutputFaces are the block's own sides (as if facing
north), while ctx.input() takes world directions, and recommends front,
back, left and right, which mean the same in both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A redstone block that reads only some faces dispatched redstone-changed on
every neighbor update, including changes on faces it does not read. With
no delay, a handler that toggled the block's output could loop until the
stack overflowed.

RedstoneBlock now remembers the last power on each read face, per
position and level, outside block state (six faces of 0-15 do not fit in
it). The event fires only when one of those faces changes, plus once when
the block has no record yet: when placed, or on its first update after
loading. Entries go when the block is removed, and a level's entries go
with the level.

The NAND gate game test now checks that powering an unread side does not
run the handler.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The companion client smoke failed in CI: its 240-second deadline started
when the test class loaded, so it counted launch time, and loading
CraftTweaker into that client made world creation about 28 seconds
slower. Locally it already passed with only about 18 seconds to spare.

- CompanionClientSmoke gets a 6-minute budget that starts at the title
  screen. Menus that never render still fail after 400 ticks.
- CraftTweaker's dev-run dependency moves to its own configuration,
  craftTweakerDevRuntime. The companion runs (client smoke, game tests,
  companion client) and the GUI smoke clients leave it and its ZenCode
  libraries out; they don't test it, and the CraftTweaker game tests do.
  runClient and runServer still load it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dshadowwolf
dshadowwolf merged commit 2dab4eb into MinecraftModDevelopmentMods:master-2.0-1.21.1-neo Nov 7, 2026
3 checks passed
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.

1 participant