mirror of
https://github.com/GTNewHorizons/ForgeMultipart.git
synced 2026-11-13 17:04:25 +00:00
test: characterize tile change trait
Seven behavioral tests and a generated-interface freeze, both against the untouched Scala trait. Nothing in the frozen consumer baseline references TTileChangeTile or a $class helper for it, so there is no binary fixture to take: the load-bearing surface is INeighborTileChange, which is already Java and unchanged. The behavior pinned is the flag lifecycle and the coordinate filter. bindPart only ever ors the flag in, copyFrom takes it from another change tile but leaves it alone for a plain source, clearParts resets it, and partRemoved recomputes from the remaining list rather than from the part handed to it. onNeighborTileChange dispatches only for an axial offset of one or two blocks, and marks the two-block case weak. The runtime interface is the exact thirteen methods: six overrides, the field getter and setter, and five super accessors.
This commit is contained in:
1 parent
bde3445488
commit
003e8f94ca
2 files changed
+221
No files matched your search
@@ -39,6 +39,7 @@ import codechicken.multipart.TMultiPart;
|
||||
import codechicken.multipart.TileMultipart;
|
||||
import codechicken.multipart.asm.MultipartMixinFactory;
|
||||
import codechicken.multipart.scalatraits.TSlottedTile;
|
||||
import codechicken.multipart.scalatraits.TTileChangeTile;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import scala.collection.JavaConversions;
|
||||
@@ -214,6 +215,52 @@ class ForgeEnvironmentSmokeTest {
|
||||
assertSame(replacement, trait.getMethod("v_partMap").invoke(first));
|
||||
}
|
||||
|
||||
@Test
|
||||
void generatesAndCachesTileChangeTileClass() throws Exception {
|
||||
int traitId = MultipartMixinFactory.getId(TTileChangeTile.class.getName().replace('.', '/'));
|
||||
assertFalse(traitId < 0);
|
||||
|
||||
BitSet traits = new BitSet();
|
||||
traits.set(traitId);
|
||||
Object first = MultipartMixinFactory.construct(traits, Nil$.MODULE$);
|
||||
Object second = MultipartMixinFactory.construct(traits, Nil$.MODULE$);
|
||||
Class<?> trait = Class.forName("codechicken.multipart.scalatraits.TTileChangeTile");
|
||||
|
||||
assertTrue(first instanceof TileMultipart);
|
||||
assertTrue(first instanceof TTileChangeTile);
|
||||
assertTrue(trait.isInterface());
|
||||
assertNotSame(first, second);
|
||||
assertSame(first.getClass(), second.getClass());
|
||||
assertEquals(0, trait.getDeclaredFields().length);
|
||||
Set<String> signatures = new TreeSet<>();
|
||||
for (java.lang.reflect.Method method : trait.getDeclaredMethods()) {
|
||||
signatures.add(method.getName() + org.objectweb.asm.Type.getMethodDescriptor(method));
|
||||
}
|
||||
String prefix = "codechicken$multipart$scalatraits$TTileChangeTile$$super$";
|
||||
assertEquals(
|
||||
new TreeSet<>(
|
||||
Arrays.asList(
|
||||
"bindPart(Lcodechicken/multipart/TMultiPart;)V",
|
||||
"clearParts()V",
|
||||
"copyFrom(Lcodechicken/multipart/TileMultipart;)V",
|
||||
"getWeakChanges()Z",
|
||||
"onNeighborTileChange(III)V",
|
||||
"partRemoved(Lcodechicken/multipart/TMultiPart;I)V",
|
||||
"weakTileChanges()Z",
|
||||
"weakTileChanges_$eq(Z)V",
|
||||
prefix + "bindPart(Lcodechicken/multipart/TMultiPart;)V",
|
||||
prefix + "clearParts()V",
|
||||
prefix + "copyFrom(Lcodechicken/multipart/TileMultipart;)V",
|
||||
prefix + "onNeighborTileChange(III)V",
|
||||
prefix + "partRemoved(Lcodechicken/multipart/TMultiPart;I)V")),
|
||||
signatures);
|
||||
|
||||
assertEquals(boolean.class, first.getClass().getDeclaredField("weakTileChanges").getType());
|
||||
trait.getMethod("weakTileChanges_$eq", boolean.class).invoke(first, true);
|
||||
assertEquals(true, trait.getMethod("weakTileChanges").invoke(first));
|
||||
assertEquals(false, trait.getMethod("weakTileChanges").invoke(second), "State is per tile");
|
||||
}
|
||||
|
||||
@Test
|
||||
void generatedJavaTraitOverridesPartialOcclusion() throws Exception {
|
||||
PartialPart existing = new PartialPart(voxel(0));
|
||||
|
||||
+174
@@ -0,0 +1,174 @@
|
||||
package codechicken.multipart.test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.BitSet;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import codechicken.multipart.INeighborTileChange;
|
||||
import codechicken.multipart.TMultiPart;
|
||||
import codechicken.multipart.TileMultipart;
|
||||
import codechicken.multipart.asm.MultipartMixinFactory;
|
||||
import codechicken.multipart.scalatraits.TTileChangeTile;
|
||||
import scala.collection.immutable.Nil$;
|
||||
|
||||
/** Consumer-visible state and behavior of the generated neighbor-tile-change trait. */
|
||||
class TTileChangeTileFunctionalTest {
|
||||
|
||||
@Test
|
||||
void theFlagStartsFalseAndIsPublishedThroughGetWeakChanges() {
|
||||
TileMultipart tile = newTileChangeTile();
|
||||
|
||||
assertFalse(weakTileChanges(tile));
|
||||
assertFalse(tile.getWeakChanges());
|
||||
}
|
||||
|
||||
@Test
|
||||
void bindPartOnlyEverSetsTheFlag() {
|
||||
TileMultipart tile = newTileChangeTile();
|
||||
|
||||
tile.bindPart(new PlainPart());
|
||||
assertFalse(tile.getWeakChanges(), "A part that is not an INeighborTileChange contributes nothing");
|
||||
|
||||
tile.bindPart(new ChangePart("quiet", false));
|
||||
assertFalse(tile.getWeakChanges());
|
||||
|
||||
tile.bindPart(new ChangePart("weak", true));
|
||||
assertTrue(tile.getWeakChanges());
|
||||
|
||||
// The flag is or-ed in, so a later quiet part cannot clear it.
|
||||
tile.bindPart(new ChangePart("quiet2", false));
|
||||
assertTrue(tile.getWeakChanges());
|
||||
}
|
||||
|
||||
@Test
|
||||
void copyFromTakesTheFlagOnlyFromAnotherChangeTile() {
|
||||
TileMultipart source = newTileChangeTile();
|
||||
source.bindPart(new ChangePart("weak", true));
|
||||
TileMultipart target = newTileChangeTile();
|
||||
|
||||
target.copyFrom(source);
|
||||
assertTrue(target.getWeakChanges());
|
||||
|
||||
// A plain source leaves the existing value alone rather than clearing it.
|
||||
target.copyFrom(new TileMultipart());
|
||||
assertTrue(target.getWeakChanges());
|
||||
}
|
||||
|
||||
@Test
|
||||
void clearPartsResetsTheFlagAndTheSuperclassList() {
|
||||
TileMultipart tile = newTileChangeTile();
|
||||
tile.addPart_do(new ChangePart("weak", true));
|
||||
assertTrue(tile.getWeakChanges());
|
||||
|
||||
tile.clearParts();
|
||||
|
||||
assertFalse(tile.getWeakChanges());
|
||||
assertTrue(tile.jPartList().isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void partRemovedRecomputesTheFlagFromTheRemainingParts() {
|
||||
TileMultipart tile = newTileChangeTile();
|
||||
ChangePart weak = new ChangePart("weak", true);
|
||||
ChangePart quiet = new ChangePart("quiet", false);
|
||||
tile.addPart_do(weak);
|
||||
tile.addPart_do(quiet);
|
||||
assertTrue(tile.getWeakChanges());
|
||||
|
||||
// partRemoved recomputes from the list, so the part must already be gone from it.
|
||||
tile.partList_$eq(seq(quiet));
|
||||
tile.partRemoved(weak, 0);
|
||||
assertFalse(tile.getWeakChanges());
|
||||
|
||||
tile.partList_$eq(seq(quiet, weak));
|
||||
tile.partRemoved(quiet, 0);
|
||||
assertTrue(tile.getWeakChanges(), "A remaining weak part keeps the flag set");
|
||||
}
|
||||
|
||||
@Test
|
||||
void neighborChangesDispatchOnlyWithinTwoBlocksAlongOneAxis() {
|
||||
TileMultipart tile = newTileChangeTile();
|
||||
ChangePart part = new ChangePart("weak", true);
|
||||
tile.addPart_do(part);
|
||||
|
||||
// The tile sits at the origin, so the neighbor coordinates are the offset.
|
||||
tile.onNeighborTileChange(1, 0, 0);
|
||||
tile.onNeighborTileChange(0, -2, 0);
|
||||
assertEquals(Arrays.asList("5:false", "0:true"), part.calls);
|
||||
|
||||
part.calls.clear();
|
||||
tile.onNeighborTileChange(0, 0, 0); // no distance
|
||||
tile.onNeighborTileChange(3, 0, 0); // too far
|
||||
tile.onNeighborTileChange(1, 1, 0); // not axial, so no side
|
||||
assertTrue(part.calls.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void onlyPartsWantingNeighborChangesAreCalled() {
|
||||
TileMultipart tile = newTileChangeTile();
|
||||
ChangePart listening = new ChangePart("weak", true);
|
||||
tile.addPart_do(new PlainPart());
|
||||
tile.addPart_do(listening);
|
||||
|
||||
tile.onNeighborTileChange(0, 1, 0);
|
||||
|
||||
assertEquals(Arrays.asList("1:false"), listening.calls);
|
||||
}
|
||||
|
||||
private static TileMultipart newTileChangeTile() {
|
||||
int traitId = MultipartMixinFactory.getId(TTileChangeTile.class.getName().replace('.', '/'));
|
||||
BitSet traits = new BitSet();
|
||||
traits.set(traitId);
|
||||
return (TileMultipart) MultipartMixinFactory.construct(traits, Nil$.MODULE$);
|
||||
}
|
||||
|
||||
private static boolean weakTileChanges(TileMultipart tile) {
|
||||
return ((TTileChangeTile) tile).weakTileChanges();
|
||||
}
|
||||
|
||||
private static scala.collection.Seq<TMultiPart> seq(TMultiPart... parts) {
|
||||
return scala.collection.JavaConversions.asScalaBuffer(new ArrayList<>(Arrays.asList(parts))).toList();
|
||||
}
|
||||
|
||||
private static class PlainPart extends TMultiPart {
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "tilechange_test:plain";
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ChangePart extends PlainPart implements INeighborTileChange {
|
||||
|
||||
private final String type;
|
||||
private final boolean weak;
|
||||
private final List<String> calls = new ArrayList<>();
|
||||
|
||||
private ChangePart(String type, boolean weak) {
|
||||
this.type = type;
|
||||
this.weak = weak;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "tilechange_test:" + type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean weakTileChanges() {
|
||||
return weak;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNeighborTileChanged(int side, boolean weak) {
|
||||
calls.add(side + ":" + weak);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user