mirror of
https://github.com/GTNewHorizons/ForgeMultipart.git
synced 2026-11-13 17:04:25 +00:00
refactor: port microblock generator to Java
This commit is contained in:
1 parent
8d3010941c
commit
2f4972e6fd
6 files changed
+177
-36
No files matched your search
@@ -1202,3 +1202,12 @@ generated-trait compatibility work. Scala-runtime removal remains a later projec
|
||||
- A clean build passes all 257 plain-JVM tests and the Java 8 Forge server passes all 110 tests. All seven supported
|
||||
public surfaces and WR-CBE's static `recalcBounds` descriptor match the reference. `microblock/MicroblockGenerator.scala`
|
||||
is next.
|
||||
- Characterized `MicroblockGenerator` against untouched Scala. Three plain-JVM cases freeze its facade, companion,
|
||||
nested material interface, inherited `ASMMixinFactory`/`ScratchBitSet` shape, replaceable thread-local scratch state
|
||||
and load-bearing calls. One Forge case freezes the complete material-added external Scala-trait path.
|
||||
- Ported the facade, companion and real public static nested `IGeneratedMaterial` interface directly to Java while
|
||||
leaving the generator and ScalaSignature machinery unchanged. Scratch-bit reuse, base/client selection, material
|
||||
callback ordering, boxed constructor argument and the ProjectRed Scala-trait registration path are unchanged.
|
||||
- A clean build passes all 260 plain-JVM tests and the Java 8 Forge server passes all 111 tests. The same three runtime
|
||||
classes and every callable public descriptor match the reference, including ProjectRed's companion registration
|
||||
and GuideNH's exact companion `create` method. `multipart/MultipartGenerator.scala` is next.
|
||||
@@ -2997,3 +2997,50 @@ inventory contains no reference to it.
|
||||
- Raw `javap` comparison confirms identical callable public names/descriptors for all seven supported types and
|
||||
bytecode-identical retained trait/helper disassembly.
|
||||
- Actual neighbour-driven shrink and render-bound refresh remain on the manual checklist.
|
||||
|
||||
## 2026-09-02 — Microblock generator Java port
|
||||
|
||||
The `MicroblockGenerator` facade, companion and nested `IGeneratedMaterial` interface are now Java. The companion
|
||||
still extends the unchanged Scala `ASMMixinFactory<Microblock>` and implements the unchanged Scala `ScratchBitSet`;
|
||||
all ScalaSignature parsing, Scala-trait registration and generated-class compilation remain in the original ASM
|
||||
subsystem.
|
||||
|
||||
### Observable behavior
|
||||
|
||||
No known runtime divergence. Each `create` still clears and reuses the current thread's scratch `BitSet`, selects the
|
||||
microblock class's base trait, adds the client trait only for client construction, then lets an
|
||||
`IGeneratedMaterial` amend that same set before construction. The material ID remains a boxed `Integer` in the sole
|
||||
generated constructor argument.
|
||||
|
||||
The public scratch setter remains behaviorally replaceable despite being a compiler-oriented trait member. The
|
||||
Forge fixture proves an external material receives only the expected initial base bit, adds a registered third-party
|
||||
Scala trait, and produces a generated microblock with that trait's initialized state and dispatch.
|
||||
|
||||
### ABI and reflection compatibility
|
||||
|
||||
The facade, companion and nested material interface retain the same three binary names, hierarchy and callable
|
||||
public names/descriptors. `IGeneratedMaterial` remains a real public static member of `MicroblockGenerator`; the
|
||||
original pure abstract Scala trait emitted no `$class` helper, so none is removed.
|
||||
|
||||
ProjectRed's load-bearing `MicroblockGenerator$.registerTrait(Class): int` call remains exact, and the unchanged
|
||||
`ASMMixinFactory` still recognizes and compiles its external `LightMicroblock` Scala trait. GuideNH's exact reflective
|
||||
`MicroblockGenerator$.create(MicroblockClass, int, boolean)` lookup also remains exact. All inherited static
|
||||
forwarders, including the Scala `Seq`-shaped `construct`, keep their raw descriptors and generic surface.
|
||||
|
||||
Accepted classfile-only differences are the Java facade's private constructor, the ordinary non-public Java class
|
||||
initializer flag and removed Scala marker attributes. The private scratch `ThreadLocal` loses `ACC_FINAL`: Java
|
||||
cannot assign a final instance field through the required public Scala-trait setter, and preserving the setter's
|
||||
observable replacement behavior is more important than an unreferenced private modifier.
|
||||
|
||||
### Compiler artifacts
|
||||
|
||||
None. The clean reference and port jars contain the same three `MicroblockGenerator` classes.
|
||||
|
||||
### Validation
|
||||
|
||||
- `MicroblockGeneratorCharacterizationTest`: 3 plain-JVM tests, unchanged from the Scala baseline.
|
||||
- Clean complete plain-JVM suite: 260 tests, 0 failures, 0 errors.
|
||||
- Java 8 Forge dedicated-server suite: 111 tests, 0 failures, 0 errors, including material-driven addition,
|
||||
initialization and dispatch of the external Scala microblock trait.
|
||||
- Raw `javap` comparison confirms the exact three-class list and identical callable public names/descriptors.
|
||||
- The existing ProjectRed illuminated-microblock row remains the full-pack/client manual checkpoint.
|
||||
+16
-10
@@ -12,8 +12,8 @@ what breaks, and what is left. The other documents hold the reasoning.
|
||||
| `JAVA_MIGRATION_MANUAL_CHECKS.md` | What no automated test can cover, and must be checked by hand in a client |
|
||||
| `JAVA_MIGRATION_PROFILE.md` | The focused baseline, first measured result, findings, and exact rerun command |
|
||||
|
||||
Branch: `algent/java`. Base: `master`. 146 commits including the API-cleanup plan and separate characterization and
|
||||
port commits through micro occlusion.
|
||||
Branch: `algent/java`. Base: `master`. 148 commits including the API-cleanup plan and separate characterization and
|
||||
port commits through the microblock generator.
|
||||
|
||||
## The one rule that matters
|
||||
|
||||
@@ -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: **257 plain-JVM tests and 110 Java 8 Forge dedicated-server tests passing.** The ignored local server
|
||||
Current baseline: **260 plain-JVM tests and 111 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.
|
||||
|
||||
@@ -272,7 +272,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.
|
||||
|
||||
185 Java files, 16 Scala files, ~2,967 Scala lines left (non-blank; that is the metric this figure has always used).
|
||||
189 Java files, 15 Scala files, 2,807 Scala lines left (non-blank; that is the metric this figure has always used).
|
||||
|
||||
## What is left, and in what order
|
||||
|
||||
@@ -526,17 +526,23 @@ transparency decisions, render masks, traversal ranges and the complete trait de
|
||||
trait/helper disassembly is bytecode-identical; only the private shrink traversal closure disappears. WR-CBE's
|
||||
load-bearing static `MicroOcclusion.recalcBounds(JMicroShrinkRender, Cuboid6)` call remains exact.
|
||||
|
||||
**High.** `MicroblockGenerator.scala` is next. Freeze its inherited `ASMMixinFactory`/`ScratchBitSet` singleton,
|
||||
nested `IGeneratedMaterial` Scala trait, exact companion/reflection surface and fresh trait-bit selection before
|
||||
choosing the smallest safe split. ProjectRed exercises external Scala-trait generation and GuideNH pins the exact
|
||||
`create(MicroblockClass, int, boolean)` companion method. Do not combine this with `MultipartGenerator` or ASM work.
|
||||
The microblock generator is now a Java facade, companion and real nested material interface over the unchanged Scala
|
||||
`ASMMixinFactory` and `ScratchBitSet`. Three plain-JVM cases freeze all three runtime surfaces, scratch replacement
|
||||
and clearing, and the load-bearing call opcodes. One Forge case covers the previously missing full path from an
|
||||
`IGeneratedMaterial` callback through registered external Scala-trait initialization and dispatch. The runtime class
|
||||
list and all callable public descriptors remain exact for ProjectRed and GuideNH.
|
||||
|
||||
**High.** `MultipartGenerator.scala` is next. Freeze its companion-only GuideNH entry point, all `private[multipart]`
|
||||
members that must become public Java, trait registration maps, server/client exclusion flags, pass-through handling,
|
||||
scratch-bit reuse, generated class selection and construction before choosing a split. Reuse the extensive existing
|
||||
generated-tile fixtures and do not combine this with `MultipartMixinFactory` or the rest of ASM.
|
||||
|
||||
**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.
|
||||
|
||||
**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.
|
||||
**Phase 6/7, last.** The retained generated microblock traits, `MultipartGenerator`, and all of `multipart/asm/`.
|
||||
The ASM subsystem should be last; freeze generated-class fixtures before touching it.
|
||||
|
||||
**Pre-merge cleanup is explicit in `JAVA_MIGRATION.md`.** It covers relocating eligible Java files out of
|
||||
`src/main/scala`, reconsidering forced Scala compilation, refreshing the README, organizing the durable migration
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
package codechicken.microblock;
|
||||
|
||||
import java.util.BitSet;
|
||||
|
||||
import codechicken.microblock.MicroMaterialRegistry.IMicroMaterial;
|
||||
import codechicken.multipart.asm.ASMMixinFactory;
|
||||
import codechicken.multipart.asm.ScratchBitSet;
|
||||
import codechicken.multipart.asm.ScratchBitSet$class;
|
||||
import scala.Predef$;
|
||||
|
||||
public final class MicroblockGenerator$ extends ASMMixinFactory<Microblock> implements ScratchBitSet {
|
||||
|
||||
public static final MicroblockGenerator$ MODULE$ = new MicroblockGenerator$();
|
||||
|
||||
private ThreadLocal<BitSet> codechicken$multipart$asm$ScratchBitSet$$bitSets;
|
||||
|
||||
private MicroblockGenerator$() {
|
||||
super(Microblock.class, Predef$.MODULE$.wrapRefArray(new Class<?>[] { Integer.TYPE }));
|
||||
ScratchBitSet$class.$init$(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThreadLocal<BitSet> codechicken$multipart$asm$ScratchBitSet$$bitSets() {
|
||||
return codechicken$multipart$asm$ScratchBitSet$$bitSets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codechicken$multipart$asm$ScratchBitSet$_setter_$codechicken$multipart$asm$ScratchBitSet$$bitSets_$eq(
|
||||
ThreadLocal value) {
|
||||
codechicken$multipart$asm$ScratchBitSet$$bitSets = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BitSet getBitSet() {
|
||||
return ScratchBitSet$class.getBitSet(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BitSet freshBitSet() {
|
||||
return ScratchBitSet$class.freshBitSet(this);
|
||||
}
|
||||
|
||||
public Microblock create(MicroblockClass microClass, int materialId, boolean client) {
|
||||
BitSet traits = freshBitSet();
|
||||
traits.set(microClass.baseTraitId());
|
||||
if (client) {
|
||||
traits.set(microClass.clientTraitId());
|
||||
}
|
||||
|
||||
IMicroMaterial material = MicroMaterialRegistry.getMaterial(materialId);
|
||||
if (material instanceof MicroblockGenerator.IGeneratedMaterial) {
|
||||
((MicroblockGenerator.IGeneratedMaterial) material).addTraits(traits, microClass, client);
|
||||
}
|
||||
|
||||
return construct(traits, Predef$.MODULE$.wrapRefArray(new Object[] { Integer.valueOf(materialId) }));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package codechicken.microblock;
|
||||
|
||||
import java.util.BitSet;
|
||||
|
||||
import scala.collection.Seq;
|
||||
|
||||
public final class MicroblockGenerator {
|
||||
|
||||
public interface IGeneratedMaterial {
|
||||
|
||||
void addTraits(BitSet traits, MicroblockClass microClass, boolean client);
|
||||
}
|
||||
|
||||
private MicroblockGenerator() {}
|
||||
|
||||
public static Class<Microblock> baseType() {
|
||||
return MicroblockGenerator$.MODULE$.baseType();
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public static Object construct(BitSet traits, Seq arguments) {
|
||||
return MicroblockGenerator$.MODULE$.construct(traits, arguments);
|
||||
}
|
||||
|
||||
public static int getId(String trait) {
|
||||
return MicroblockGenerator$.MODULE$.getId(trait);
|
||||
}
|
||||
|
||||
public static int registerTrait(Class<?> trait) {
|
||||
return MicroblockGenerator$.MODULE$.registerTrait(trait);
|
||||
}
|
||||
|
||||
public static int registerTrait(String trait) {
|
||||
return MicroblockGenerator$.MODULE$.registerTrait(trait);
|
||||
}
|
||||
|
||||
public static BitSet getBitSet() {
|
||||
return MicroblockGenerator$.MODULE$.getBitSet();
|
||||
}
|
||||
|
||||
public static BitSet freshBitSet() {
|
||||
return MicroblockGenerator$.MODULE$.freshBitSet();
|
||||
}
|
||||
|
||||
public static Microblock create(MicroblockClass microClass, int material, boolean client) {
|
||||
return MicroblockGenerator$.MODULE$.create(microClass, material, client);
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package codechicken.microblock
|
||||
|
||||
import codechicken.multipart.asm.{ScratchBitSet, ASMMixinFactory}
|
||||
import java.util.BitSet
|
||||
|
||||
object MicroblockGenerator
|
||||
extends ASMMixinFactory(classOf[Microblock], classOf[Int])
|
||||
with ScratchBitSet {
|
||||
trait IGeneratedMaterial {
|
||||
def addTraits(traits: BitSet, mcrClass: MicroblockClass, client: Boolean)
|
||||
}
|
||||
|
||||
def create(mcrClass: MicroblockClass, material: Int, client: Boolean) = {
|
||||
val bitset = freshBitSet
|
||||
bitset.set(mcrClass.baseTraitId)
|
||||
if (client) bitset.set(mcrClass.clientTraitId)
|
||||
|
||||
MicroMaterialRegistry.getMaterial(material) match {
|
||||
case genMat: IGeneratedMaterial =>
|
||||
genMat.addTraits(bitset, mcrClass, client)
|
||||
case _ =>
|
||||
}
|
||||
|
||||
construct(bitset, material: Integer)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user