test: freeze multipart NBT and description packets

This commit is contained in:
Algent committed 2026-08-27 18:11:28 +03:00
1 parent 6410cc0028
commit 57b314dd4e
4 files changed
+55 -20

No files matched your search

+12 -9
View File
@@ -23,15 +23,15 @@ No trustworthy tool will produce a maintainable Java port automatically. A decom
## Current status
The binary and source-level consumer audits are complete. Phase 0 still lacks exact description-packet fixtures and a
pre-optimization profile. The low-coupling Phase 3 queue is complete; before entering measured hot-path or generated
tile work, the immediate milestone is the audit-derived compatibility gate below.
The binary and source-level consumer audits are complete. Phase 0 still lacks a pre-optimization profile. The
low-coupling Phase 3 queue is complete; before entering measured hot-path work, the immediate milestone is the
remaining generated-tile portion of the audit-derived compatibility gate below.
That audit found and this branch has now repaired one existing regression: Schematica 1.12.6 reflects the original private
`MultiPartRegistry$` field `codechicken$multipart$MultiPartRegistry$$typeMap` and casts it to a Scala mutable map. The
companion again exposes that exact private field as a live view of the canonical Java `HashMap`, and a test performs
Schematica's reflective lookup. The remaining source-only member guards and `TileMultipart` ordering/move lifecycle
are also frozen; compact mixed-part NBT and description-packet fixtures are next.
Schematica's reflective lookup. The remaining source-only member guards, `TileMultipart` ordering/move lifecycle, and
compact mixed-part NBT/description packet are also frozen; generated-trait and pass-through fixtures are next.
Phase 1 has not properly started: GTNHLib is present but was added at `api` scope to satisfy a test compile rather
than because a migration change needed it, and no Forge mod dependency was declared. Revisit that entry only when a
@@ -305,8 +305,8 @@ Do this before another source conversion:
`registerMaterial` lookup.
- [x] Freeze `TileMultipart` order and lifecycle observations: `parts`/`id` NBT, `partList`/`jPartList`, `partMap`, slot
rebinding, add/remove/replace callback order, moving the live tile, and `onMoved`.
- [ ] Add compact mixed-part NBT and description-packet fixtures. Use representative fake parts in the existing test
harness; do not add all downstream mods as test dependencies.
- [x] Add compact mixed-part NBT and description-packet fixtures. The existing torch/button parts provide the needed
distinct IDs, order, slots and payload without adding downstream mods or a test-only part registry.
- [ ] Freeze one generated Scala trait, one Java trait, and representative pass-through interfaces before changing
built-in tile traits or either generator.
@@ -394,7 +394,7 @@ The work should move from low to high risk while keeping a buildable mixed-langu
Extensive tests are both possible and recommended here. Their purpose is not to prove that the current Scala behavior is ideal; it is to make its observable behavior explicit before translation, so every later difference is intentional.
The repository now has a Java-8-compatible JUnit Jupiter suite and a small Forge integration runner. The current
baseline is 130 plain-JVM tests and 24 Forge server tests. Minecraft 1.7.10 does not provide the modern GameTest
baseline is 130 plain-JVM tests and 25 Forge server tests. Minecraft 1.7.10 does not provide the modern GameTest
framework, so game-dependent coverage continues through the existing narrow Forge harness rather than a second test
framework.
@@ -620,4 +620,7 @@ generated-trait compatibility work. Scala-runtime removal remains a later projec
- Reproduced MatterManipulator's live-tile relocation shape. Removing the tile first calls `onWorldSeparate` for each
part in list order; after reinsertion, `onMoved` calls each part's `onMoved` and default `onWorldJoin`, again in list
order. The original generated tile, part instances, order, slot map and tile references survive.
- The expanded baseline is 130 plain-JVM tests and 24 Forge server tests, all passing.
- Froze the complete logical chunk-description payload around the same torch/button pair: packet type, chunk
coordinates, tile count, nibble-relative X/Z, full Y, part count, sorted runtime part IDs, part order and both meta
bytes. CodeChickenLib's deferred Deflater transport step is deliberately outside this FMP fixture.
- The expanded baseline is 130 plain-JVM tests and 25 Forge server tests, all passing.
+5 -3
View File
@@ -445,8 +445,9 @@ The Java port may add faster indexed storage, but all published views, serializa
packet consumers must observe one consistent order.
Current-branch verification: `MultipartHelperFunctionalTest` freezes ordered two-part NBT reconstruction and slot
rebinding. `TileMultipartLifecycleFunctionalTest` freezes add/remove callbacks and the MatterManipulator-shaped live
move, including ordered `onWorldSeparate` before ordered `onMoved`/`onWorldJoin`, without replacing the generated tile.
rebinding plus the exact logical chunk-description framing and part payload. `TileMultipartLifecycleFunctionalTest`
freezes add/remove callbacks and the MatterManipulator-shaped live move, including ordered `onWorldSeparate` before
ordered `onMoved`/`onWorldJoin`, without replacing the generated tile.
### Material IDs and packets
@@ -495,7 +496,8 @@ behavior:
3. Keep the completed `TileMultipart` list/map/slot and live-move characterization green before optimizing storage or
iteration.
4. Characterize pass-through interfaces and ProjectRed's external Scala trait before changing either generator.
5. Add mixed NBT/packet fixtures before converting microblocks and Minecraft part implementations.
5. Keep the completed compact mixed NBT/chunk-description fixture green; add subsystem-specific payload cases when
converting microblocks or Minecraft part implementations.
6. Treat Scala runtime removal as downstream coordination work after the Java port, not as a requirement of it.
With these gates, the source audit is actionable: the port can simplify internals freely where no listed observation
+8 -5
View File
@@ -57,7 +57,7 @@ awk -F'"' '/<testsuite /{t+=$4;f+=$8;e+=$10} END{print "tests="t" failures="f" e
grep -o 'tests="[0-9]*" skipped="[0-9]*" failures="[0-9]*" errors="[0-9]*"' run/server/junit-out/TEST-*.xml
```
Current baseline: **130 plain-JVM tests, 24 Forge server tests, all passing at their last completed runs.**
Current baseline: **130 plain-JVM tests, 25 Forge server tests, all passing at their last completed runs.**
### ABI diff against the reference
@@ -204,8 +204,11 @@ Tile list/order/slot behavior and the live move lifecycle are now frozen by focu
pin ordered `parts`/`id` NBT, published list views, slot rebinding, add/remove/replace behavior, and the relocation
sequence (`onWorldSeparate`, then `onMoved`/`onWorldJoin`) while preserving the original generated tile.
Next add compact mixed-part NBT and exact description-packet fixtures, followed by representative generated-trait and
pass-through fixtures. The checklist is in the "Immediate compatibility gate" section of `JAVA_MIGRATION.md`.
The same ordered torch/button pair now supplies a compact NBT fixture and an exact logical chunk-description fixture.
The latter pins FMP's framing and payload before CodeChickenLib applies deferred transport compression.
Next freeze representative generated Scala/Java traits and pass-through interfaces. The checklist is in the
"Immediate compatibility gate" section of `JAVA_MIGRATION.md`.
`IRedstonePart.scala` is misleadingly named and is **not** a marker-trait file. It holds six traits plus
`RedstoneInteractions`, whose `MODULE$` is load-bearing. After the compatibility gate and an initial profile, port the
@@ -228,8 +231,8 @@ all of `multipart/asm/`. The ASM subsystem should be last; freeze generated-clas
Every port since `TCuboidPart` has deferred something to it, and `BlockMultipart` leans on it hardest: breaking, selection boxes, collision, pick block, activation, particles and
light are covered by nothing automated. Run it in a real client before this branch goes near a release.
- No CPU or allocation profiles exist. Phase 4 has not started, so there is no baseline to compare against.
- Tile `parts`/`id` ordering now has a live NBT round-trip fixture, but broad part payload and exact description-packet
fixtures are still missing.
- Microblock-specific NBT and packet payloads still need characterization immediately before that subsystem changes;
the compact core tile/part fixture is complete.
- `TileMultipart`'s `partList` still republishes an immutable Scala `Seq` on every mutation, and `operate` still
allocates a `Function1` per call. Both are faithful to the reference and both are deliberately left for Phase 4,
which needs profiling first.
@@ -1,5 +1,6 @@
package codechicken.multipart.test;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
@@ -17,16 +18,20 @@ import net.minecraft.nbt.NBTTagList;
import net.minecraft.server.MinecraftServer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk;
import org.junit.jupiter.api.Test;
import codechicken.lib.packet.PacketCustom;
import codechicken.multipart.MultiPartRegistry;
import codechicken.multipart.MultipartHelper;
import codechicken.multipart.TMultiPart;
import codechicken.multipart.TileMultipart;
import codechicken.multipart.handler.MultipartSPH;
import codechicken.multipart.handler.MultipartSaveLoad;
import codechicken.multipart.minecraft.ButtonPart;
import codechicken.multipart.minecraft.TorchPart;
import io.netty.buffer.ByteBuf;
import scala.collection.JavaConversions;
/**
@@ -55,9 +60,7 @@ class MultipartHelperFunctionalTest {
@Test
void rebuildsAnOrderedSlottedTileFromItsOwnNbtAndPublishesTheLoadingWorld() {
World world = world();
TMultiPart torch = new TorchPart(5);
TMultiPart button = new ButtonPart(1);
TileMultipart saved = MultipartHelper.createTileFromParts(Arrays.asList(torch, button));
TileMultipart saved = mixedTile();
NBTTagCompound tag = new NBTTagCompound();
saved.writeToNBT(tag);
@@ -81,6 +84,26 @@ class MultipartHelperFunctionalTest {
assertSame(world, MultipartSaveLoad.loadingWorld());
}
@Test
void writesTheExactMixedPartChunkDescriptionPacket() {
World world = world();
Chunk chunk = world.getChunkFromChunkCoords(1, 2);
TileMultipart tile = mixedTile();
tile.xCoord = 18;
tile.yCoord = 200;
tile.zCoord = 35;
PacketCustom packet = MultipartSPH.getDescPacket(chunk, Collections.<TileEntity>singletonList(tile).iterator());
ByteBuf buffer = packet.getByteBuf();
byte[] actual = new byte[buffer.writerIndex()];
buffer.getBytes(0, actual);
// type | chunk x/z | tile count | local x/y/z | part count | torch id/meta | button id/meta
assertArrayEquals(
new byte[] { 2, 0, 0, 0, 1, 0, 0, 0, 2, 0, 1, 2, 0, 0, 0, (byte) 200, 3, 2, 3, 5, 0, 1 },
actual);
}
/** The id guard runs before anything else, so a foreign tag must not disturb the loading world. */
@Test
void leavesTheLoadingWorldAloneForATagItDoesNotOwn() {
@@ -125,6 +148,10 @@ class MultipartHelperFunctionalTest {
return world;
}
private static TileMultipart mixedTile() {
return MultipartHelper.createTileFromParts(Arrays.asList(new TorchPart(5), new ButtonPart(1)));
}
/** Matches only its own tile class, so registering it cannot affect any real chunk load. */
private static final class MarkerTile extends TileEntity {
}