refactor: port TFacePart to Java

Replaces TFacePart.scala with a Java interface and retains the
TFacePart$class bridge for OpenComputers, ProjRed and ProjectBlue. The
interface is descriptor-identical to the reference; the bridge adds only a
private constructor.

This is the first converted trait where Java default methods are safe.
TMultiPart declares neither solid nor redstoneConductionMap, and neither
does anything in the microblock superclass chain, so there is no
superclass method for a default to lose to. Both members therefore become
real defaults rather than staying abstract with explicit forwarders, and
no in-repo Scala needed changing. The rule for the remaining traits is to
check that condition before choosing.

A side effect is that Java classes can now inherit these members;
McSidedMetaPart previously had to declare both just to accept the
defaults, and stays descriptor-identical.

Adds the first functional coverage of runtime class generation against a
ported type. Microblock classes are built by ASM at run time, so the
server suite now checks that a generated FaceMicroblock resolves the
inherited default and that a generated HollowMicroblock still returns its
own overrides.

Validated with 43 plain-JVM tests, a clean build, and the Java 8 Forge
dedicated-server suite at 3 tests.
This commit is contained in:
Algent committed 2026-08-14 21:00:18 +02:00
1 parent d71a4b893d
commit 57130a6955
6 files changed
+120 -17

No files matched your search

@@ -13,6 +13,11 @@ import net.minecraft.server.MinecraftServer;
import org.junit.jupiter.api.Test;
import codechicken.microblock.FaceMicroClass$;
import codechicken.microblock.HollowMicroClass$;
import codechicken.microblock.Microblock;
import codechicken.microblock.MicroblockGenerator;
import codechicken.multipart.TFacePart;
import codechicken.multipart.TileMultipart;
import codechicken.multipart.asm.MultipartMixinFactory;
import codechicken.multipart.scalatraits.TSlottedTile;
@@ -41,6 +46,25 @@ class ForgeEnvironmentSmokeTest {
assertNotNull(server.worldServers[0]);
}
/**
* Microblock classes are generated by ASM at runtime. TFacePart's members are now Java interface defaults rather
* than Scala trait forwarders, so a generated class inherits them instead of declaring its own; this checks the JVM
* resolves them for a class that never existed at compile time.
*/
@Test
void generatedMicroblockInheritsFacePartDefaults() {
Microblock face = MicroblockGenerator.create(FaceMicroClass$.MODULE$, 0, false);
Microblock hollow = MicroblockGenerator.create(HollowMicroClass$.MODULE$, 0, false);
assertTrue(face instanceof TFacePart);
assertEquals(0, ((TFacePart) face).redstoneConductionMap());
// HollowMicroblock overrides both members, so its generated class must not pick up the defaults.
assertTrue(hollow instanceof TFacePart);
assertEquals(0x10, ((TFacePart) hollow).redstoneConductionMap());
assertFalse(((TFacePart) hollow).solid(0));
}
@Test
void generatesAndCachesSlottedTileClass() {
int traitId = MultipartMixinFactory.getId(TSlottedTile.class.getName().replace('.', '/'));