2026-09-05 14:00:24 +02:00
# Staged composite-tile generation
[Java API index ](../API.md )
`MultipartGenerator.generateCompositeTile(TileEntity, java.lang.Iterable<TMultiPart>, boolean)` selects a tile's
2026-10-15 16:39:36 +02:00
generated capabilities without loading its parts. The [compiling example ](../../src/functionalTest/java/codechicken/multipart/examples/CompositeGenerationExample.java )
then assigns world/position and loads the same parts, leaving installation to its caller.
2026-09-05 14:00:24 +02:00
```java
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 ](PART_LOADING.md ). 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
2026-09-16 12:44:33 +02:00
For saved-NBT client previews, prefer the complete [client preview helper ](CLIENT_PREVIEW.md ). 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.
2026-09-05 14:58:24 +02:00
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 ](../API.md#direct-calls-and-optional-integration ).
For temporary interoperability with an existing reflective integration, the method can also be resolved with:
2026-09-05 14:00:24 +02:00
```java
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.
2026-09-16 12:44:33 +02:00
- **Older Schematica integrations:** remove `JavaConversions.collectionAsScalaIterable` from generation; keep material resolution,
2026-09-05 14:00:24 +02:00
[factory lookup ](FACTORY_LOOKUP.md ), side-specific microblock construction, per-part NBT loading and rejection when
any part is missing. Preserve its following tile `readFromNBT` , `loadPartList(parts)` and per-part notification order.
2026-09-16 12:44:33 +02:00
- **Older GuideNH integrations:** keep promotion of parts to their client variants, then use a Java list for generation. Preserve its
2026-09-05 14:00:24 +02:00
same-instance branch, copying of coordinates/world/block state, storage assignment where required, loading,
`notifyTileChange` and `markRender` . Generation does not perform any of those steps automatically.
The old companion's `generateCompositeTile(TileEntity, scala.collection.Iterable, boolean)` keeps its descriptor and
2026-10-15 16:39:36 +02:00
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 ](MICROBLOCK_CREATION.md ).