refactor: port Angelica compat to Java

This commit is contained in:
Algent committed 2026-09-01 18:46:14 +02:00
1 parent a932f47dc1
commit 4761336d7b
5 files changed
+89 -32

No files matched your search

+7
View File
@@ -1113,3 +1113,10 @@ generated-trait compatibility work. Scala-runtime removal remains a later projec
- Added a dependent GitHub Actions job that accepts the EULA in its ephemeral runner and invokes the existing
self-validating `runFunctionalTestServer` task after the shared GTNH build. The Forge suite now gates pull requests
and pushes instead of being local-only.
- Characterized `AngelicaCompat` against untouched Scala. Two plain-JVM cases freeze its exact non-final public
surface, unusual `Object` return descriptors, `CapturingTessellator` guard, Iris calls and caught
`ClassCastException` fallback.
- Ported the sole class directly to Java while retaining `BoxedUnit.UNIT` on the normal path and `Unit$.MODULE$` on
the fallback path. Both jars contain the same runtime class and every callable descriptor matches the reference.
- A clean build passes all 230 plain-JVM tests and the Java 8 Forge server passes all 103 tests.
`microblock/ItemSaw.scala` is next.
+34
View File
@@ -2538,3 +2538,37 @@ and the downstream inventory contains no references to them.
- Clean reference/port jars retain the same two supported types; the seven compiler artifacts above disappear, and
raw `javap` comparison confirms identical callable public names/descriptors.
- File parsing, registration and IMC behavior are automated; this port adds no new client-only manual check.
## 2026-09-01 — AngelicaCompat Java port
The optional Angelica shader-material adapter is now Java.
### Observable behavior
No known runtime divergence. Both methods still act only when `Tessellator.instance` is a
`CapturingTessellator`, call the matching Iris shader-material hook, and catch only `ClassCastException`. The public
methods deliberately continue to return `Object`: the normal path returns `BoxedUnit.UNIT`, while the caught fallback
returns `Unit$.MODULE$`, exactly as the Scala bytecode did.
### ABI and reflection compatibility
`AngelicaCompat` remains a public, non-final class with one public no-argument constructor, no fields or interfaces,
and exactly these two callable methods:
- `setShaderMaterialOverride(Block, int): Object`
- `resetShaderMaterialOverride(): Object`
The downstream inventory contains no reference to this class, so no frozen consumer fixture is needed. Accepted
classfile-only differences are the removed Scala signature/marker attributes and the Java source-file marker.
### Compiler artifacts
No runtime class is added or removed; both clean jars contain only `AngelicaCompat.class` for this source unit.
### Validation
- `AngelicaCompatCharacterizationTest`: 2 plain-JVM tests, unchanged from the Scala baseline.
- Clean complete plain-JVM suite: 230 tests, 0 failures, 0 errors.
- Java 8 Forge dedicated-server suite: 103 tests, 0 failures, 0 errors.
- Raw `javap` comparison confirms identical class modifiers, constructor and callable public names/descriptors.
- Live shader-material selection and reset with Angelica remain on the manual checklist.
+13 -6
View File
@@ -67,7 +67,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: **228 plain-JVM tests and 103 Java 8 Forge dedicated-server tests passing.** The ignored local server
Current baseline: **230 plain-JVM tests and 103 Java 8 Forge dedicated-server tests passing.** The ignored local server
EULA is accepted in this checkout. GitHub Actions runs the same self-validating Forge suite in a dependent job after
the shared GTNH build; keep both jobs required.
@@ -253,7 +253,7 @@ All eight load-bearing `$class` helpers from the inventory, both registries, and
`MicroblockCPH`/`MicroblockSPH` and `MultipartPH`/`MultipartCPH`/`MultipartSPH` packet-handler units, plus
`MultipartSaveLoad`, `MissingMicroMaterial`, `DefaultContent`, `GrassMicroMaterial`/`TopMicroMaterial`,
`ItemMicroPart` plus its renderer, `MicroblockPlacement` plus its executable-placement and property types, and
`PlacementGrids`, plus `BlockMicroMaterial`, `MaterialRenderHelper`, and `ConfigContent`.
`PlacementGrids`, plus `BlockMicroMaterial`, `MaterialRenderHelper`, `ConfigContent`, and `AngelicaCompat`.
The complete `MultipartProxy` and `MicroblockProxy` server/client hierarchies and static facades are also Java.
Plus the six marker interfaces: `TSlottedPart`, `IRandomDisplayTick`, `INeighborTileChange`, `TRandomUpdateTick`,
@@ -269,7 +269,7 @@ across the port. It is also where the two shim constraints in the gotchas list w
`rayTraceAll`'s index production is now characterized, closing the gap the read-path cleanup left: the index written
into `ExtendedMOP.data` is what `reduceMOP` hands back to every click, activate, harvest and pick block.
156 Java files, 20 Scala files, ~3,496 Scala lines left (non-blank; that is the metric this figure has always used).
157 Java files, 19 Scala files, ~3,473 Scala lines left (non-blank; that is the metric this figure has always used).
## What is left, and in what order
@@ -459,14 +459,21 @@ shape, config-file generation and parsing, aliases and metadata ranges, malforme
and IMC validation. The two retained classes keep every callable descriptor; seven unreferenced Scala closure classes
disappear. The existing Forge lifecycle test still covers the real pre-init/init material-registration sequence.
**Low.** `AngelicaCompat.scala` is the next isolated target. It is a 23-line client hook with two methods and no
downstream inventory references; freeze its exact surface and the CapturingTessellator guard before translating it.
`AngelicaCompat` is now Java. Two plain-JVM cases freeze its non-final public shape, exact `Object`-returning method
descriptors, `CapturingTessellator` guard, Iris calls and caught-`ClassCastException` fallback. Both methods retain the
reference's `BoxedUnit.UNIT` normal result and `Unit$.MODULE$` fallback result; both jars contain the same sole runtime
class. The optional live Angelica render path remains on the manual checklist.
**Low/medium.** `ItemSaw.scala` is the next isolated target. It contains the config-backed saw item and its client
renderer singleton. Freeze both public surfaces, Iguana Tweaks' reflective `harvestLevel` field, durability/container
semantics and render-type selection before translating it; keep actual model/GL output on the manual checklist.
**Phase 5 is complete.** There are no Scala files left in `multipart/scalatraits/`. The client pair required the first
narrow generator relaxation: Java-trait parent linearization, explicit field-accessor recognition, and exclusion of
transient runtime caches from generated copying.
After `AngelicaCompat`, take the remaining material/render units deliberately before entering the shape hierarchy.
After `ItemSaw`, take `MicroblockRender` and the remaining material/render units deliberately before entering the
shape hierarchy.
**Phase 6/7, last.** `Microblock` and the microblock shape hierarchy, `MicroblockGenerator`, `MultipartGenerator`, and
all of `multipart/asm/`. The ASM subsystem should be last; freeze generated-class fixtures before touching it.
@@ -0,0 +1,35 @@
package codechicken.microblock;
import net.coderbot.iris.Iris;
import net.minecraft.block.Block;
import net.minecraft.client.renderer.Tessellator;
import com.gtnewhorizon.gtnhlib.client.renderer.CapturingTessellator;
import scala.Unit$;
import scala.runtime.BoxedUnit;
public class AngelicaCompat {
public Object setShaderMaterialOverride(Block block, int meta) {
try {
if (Tessellator.instance instanceof CapturingTessellator) {
Iris.setShaderMaterialOverride(block, meta);
}
return BoxedUnit.UNIT;
} catch (ClassCastException ignored) {
return Unit$.MODULE$;
}
}
public Object resetShaderMaterialOverride() {
try {
if (Tessellator.instance instanceof CapturingTessellator) {
Iris.resetShaderMaterialOverride();
}
return BoxedUnit.UNIT;
} catch (ClassCastException ignored) {
return Unit$.MODULE$;
}
}
}
@@ -1,26 +0,0 @@
package codechicken.microblock
import com.gtnewhorizon.gtnhlib.client.renderer.CapturingTessellator
import net.coderbot.iris.Iris
import net.minecraft.block.Block
import net.minecraft.client.renderer.Tessellator
class AngelicaCompat {
def setShaderMaterialOverride(block: Block, meta: Int) = {
try {
if (Tessellator.instance.isInstanceOf[CapturingTessellator])
Iris.setShaderMaterialOverride(block, meta)
} catch {
case ex: ClassCastException => Unit
}
}
def resetShaderMaterialOverride() = {
try {
if (Tessellator.instance.isInstanceOf[CapturingTessellator])
Iris.resetShaderMaterialOverride()
} catch {
case ex: ClassCastException => Unit
}
}
}