- drop per-guide Validation sections; manual gates stay in MANUAL_CHECKS - drop audit/provenance lines (reference checkouts, dated refreshes, commit pins) - state version status and Scala-free compile check once in API.md - replace API.md status prose with link to migration status - fix RELEASE_NOTES dangling sentence - rewrite README for GTNH fork and Java port
5.6 KiB
Staged composite-tile generation
MultipartGenerator.generateCompositeTile(TileEntity, java.lang.Iterable<TMultiPart>, boolean) selects a tile's
generated capabilities without loading its parts. The compiling example
then assigns world/position and loads the same parts, leaving installation to its caller.
TileMultipart prepared = MultipartGenerator.generateCompositeTile(candidate, parts, client);
// Prepare world, coordinates and any required tile NBT before loading.
prepared.loadPartList(parts);
Use a List<TMultiPart> or another repeatable collection when the same parts will subsequently be loaded. Generation
accepts Iterable<TMultiPart>; loading accepts Collection<TMultiPart>. A one-shot iterable can select traits, but
cannot then supply the same parts again. The generator reads the input once on every call, including candidate reuse,
without copying it. Do not mutate it during generation or change the required capabilities between generation and loading.
Selection and ownership
| Candidate and required traits | Result |
|---|---|
| Null or a non-multipart tile | A fresh empty generated tile |
| Registered multipart class with exactly the required trait set | The same tile, with all existing state untouched |
| Registered multipart class with a different trait set or side | A fresh empty replacement; the candidate remains untouched |
| Multipart class unknown to the generator | NoSuchElementException, after reading the parts |
An empty iterable is valid and chooses the side's base tile. Order and duplicate parts do not add extra copies of a trait, but each input entry is visited. The generator caches constructed classes; fresh tiles are still distinct objects.
Generation does not load or bind parts, assign world/position, copy source state, invalidate an old tile, install a replacement or send notifications. New tiles have empty part storage and caches. Existing part-to-tile bindings remain until the caller loads/rebinds them; loading a replacement does not clear the old tile's stored list.
Call after trait registration on the initialization/game thread. Trait selection uses existing caches and scratch state. Iterator exceptions, null inputs/elements and unregistered-class failures propagate without rollback of that internal state. Generation is neither a placement check nor a transaction for replacing a live tile.
Side and loading lifecycle
client=true selects client tile capabilities. It does not turn server parts into client part variants; supply the
correctly constructed parts yourself. The world assigned for loading must agree with the intended side. The example
also allows null for explicitly worldless staging, which omits world-dependent loading callbacks.
Prepare position, world and any required tile NBT before loading. With a world, the default loader
notifies parts and neighbors and updates lighting; a client world also triggers onWorldJoin. Preserve the integration's
subsequent installation, tile/render notifications and synchronization. Do not add them blindly to a worldless preview.
For ordinary world placement use TileMultipart.canPlacePart / addPart. For immediate server construction and
loading, the existing MultipartHelper.createTileFromParts remains supported. It is not a substitute for consumers
that must set state between generation and loading.
Schematica and GuideNH migration
For saved-NBT client previews, prefer the complete client preview helper. It owns client part construction, generation, loading and local render preparation. Use this lower-level generator for reconstruction flows that need to prepare or reuse a candidate tile themselves.
Prefer the direct call MultipartGenerator.generateCompositeTile(candidate, parts, client), as in the compiling
example. Gate optional typed integration code as described in the API index.
For temporary interoperability with an existing reflective integration, the method can also be resolved with:
Method generate = MultipartGenerator.class.getMethod(
"generateCompositeTile", TileEntity.class, java.lang.Iterable.class, boolean.class);
TileMultipart tile = (TileMultipart) generate.invoke(null, candidate, parts, client);
An optional integration can obtain the owner through Class.forName("codechicken.multipart.MultipartGenerator").
Pass a Java list directly and cache the method during integration initialization.
- Older Schematica integrations: remove
JavaConversions.collectionAsScalaIterablefrom generation; keep material resolution, factory lookup, side-specific microblock construction, per-part NBT loading and rejection when any part is missing. Preserve its following tilereadFromNBT,loadPartList(parts)and per-part notification order. - Older GuideNH integrations: keep promotion of parts to their client variants, then use a Java list for generation. Preserve its
same-instance branch, copying of coordinates/world/block state, storage assignment where required, loading,
notifyTileChangeandmarkRender. Generation does not perform any of those steps automatically.
The old companion's generateCompositeTile(TileEntity, scala.collection.Iterable, boolean) keeps its descriptor and
body, deprecated for callers in favor of the static Java entry. Existing direct calls and Schematica's exact
reflective lookup remain valid. GuideNH's separate microblock-generator call has an
existing Java replacement.