mirror of
https://github.com/GTNewHorizons/ForgeMultipart.git
synced 2026-11-12 00:17:39 +00:00
refactor: port post microblock client to Java
Retain Scala state and lifecycle bridges with ordered virtual dispatch.
This commit is contained in:
1 parent
47885d15a8
commit
556fd519bb
7 files changed
+135
-68
No files matched your search
+4
-4
@@ -24,13 +24,13 @@ No trustworthy tool will produce a maintainable Java port automatically. A decom
|
||||
## Current status
|
||||
|
||||
Work continues on `algent/java`. The low-coupling queue, core part/tile types, registries, handlers, factories,
|
||||
placement/render helpers, both generators and all built-in tile traits are Java. Three files still contain generated
|
||||
placement/render helpers, both generators and all built-in tile traits are Java. Two files still contain generated
|
||||
microblock implementations in Scala, alongside the compiler/signature/analyser compatibility shells. The common,
|
||||
face, corner, edge and post traits retain inheritance/bridge declarations over Java behavior. Composite generation,
|
||||
Java-trait rewriting and compiler startup also delegate to Java helpers. Abstract Java mixins and Java-path side-only
|
||||
filtering are complete; multiple Scala-trait inheritance still needs its metadata. The next bounded target is
|
||||
`PostMicroblockClient` in `microblock/EdgeMicroblockTraits.scala`. Retain the post super-dispatch bridge and the
|
||||
ScalaSignature path-dependent model bridges.
|
||||
`HollowMicroblock` in `microblock/HollowMicroblockTraits.scala`, followed separately by its client trait. Retain the
|
||||
post lifecycle/super-dispatch bridges and the ScalaSignature path-dependent model bridges.
|
||||
|
||||
Start with [JAVA_MIGRATION_HANDOFF.md](JAVA_MIGRATION_HANDOFF.md) for the exact source/test baseline, workflow and
|
||||
Java-source limitations. Read both the [ABI inventory](JAVA_MIGRATION_ABI_INVENTORY.md) and
|
||||
@@ -367,7 +367,7 @@ cache remain reference-identical; pass-through-interface coverage remains green.
|
||||
### Phase 6 — Convert multipart core and microblocks
|
||||
|
||||
Status: core code, factories, ordinary helpers and common/face/corner/edge/post microblock trait behavior are Java.
|
||||
Three files still contain generated trait implementations. Extract their behavior while retaining Scala declarations where
|
||||
Two files still contain generated trait implementations. Extract their behavior while retaining Scala declarations where
|
||||
multiple-trait inheritance still needs signature metadata; abstract Java mixins and side filtering alone do not
|
||||
replace that metadata. The following gates continue to apply to those remaining units; completed per-type evidence
|
||||
is in the history.
|
||||
|
||||
@@ -518,6 +518,8 @@ opaque draws. Its Forge companion pins generated face bounds and solidity. The `
|
||||
tested by Extra Utilities' connected-texture renderer remains intact. Corner, edge and post tests freeze virtual
|
||||
access, every supported geometry, packed shape/material NBT and descriptions, edge conduction and post occlusion
|
||||
ordering. The post's frozen Scala superclass also pins its synthetic super dispatch, including short-circuiting.
|
||||
Post-client fixtures additionally exercise render/lifecycle dispatch, equality receivers, repeated virtual reads and
|
||||
ordered neighbour shrinking; Forge uses real cover/post geometry while client generation and GPU output remain manual.
|
||||
Full downstream mixed tiles and client-side selection remain Phase 7 integration cases.
|
||||
|
||||
With these gates, the source audit is actionable: the port can simplify internals freely where no listed observation
|
||||
|
||||
+15
-16
@@ -16,22 +16,22 @@ migration checkout; `codex/tile-compatibility-fixes` was deleted after its fixes
|
||||
|
||||
## Current state and next target
|
||||
|
||||
**357 plain-JVM tests and 226 Java 8 Forge tests pass, with zero failures/errors/skips.** Sources total **219 Java
|
||||
files and 9 Scala files / 1,140 nonblank Scala lines**. The packaged inventory has 442 classes.
|
||||
**365 plain-JVM tests and 227 Java 8 Forge tests pass, with zero failures/errors/skips.** Sources total **220 Java
|
||||
files and 9 Scala files / 1,104 nonblank Scala lines**. The packaged inventory has 443 classes.
|
||||
|
||||
Latest bounded target: `PostMicroblock` in `EdgeMicroblockTraits.scala` delegates its implementation to
|
||||
`PostMicroblockTraitLogic.java`. Its Scala declaration, inheritance metadata, `$class` bridges and singleton accessor
|
||||
remain. The Scala occlusion bridge retains the synthetic super call after Java evaluates the special cases and box
|
||||
test. Characterization was committed first as `afd6c69`, with frozen Scala post/face implementors and a real superclass
|
||||
predecessor. Tests pin call/failure ordering, virtual dispatch, read-only list behavior, all nine supported bounds,
|
||||
edge-item drops/picking, torch support, generated post/cover occlusion and NBT/description round-trips. Clean
|
||||
verification after stopping Gradle matches all 441 original class/member APIs, all 17 ScalaSignature payloads,
|
||||
3,696 non-target method bodies and all 116 generated dump names/hashes. Only the package-private helper is added.
|
||||
Local evidence is in `run/migration-post-trait-reference/`; `clean` preserves it.
|
||||
Latest bounded target: `PostMicroblockClient` delegates render/recalculation/shrink behavior to
|
||||
`PostMicroblockClientLogic.java`. Scala retains its state, inheritance metadata, `$class` and lifecycle/super
|
||||
forwarders. Characterization was committed first as `47885d1`: frozen Scala forwarders pin render pass selection,
|
||||
material reuse, repeated getters, equality receivers, collection `foreach`, split/reset behavior and lifecycle
|
||||
failure ordering. Forge exercises real cover/post geometry on all three axes through the client helper; actual
|
||||
client generation/GPU output remains a manual gate. Clean verification after stopping Gradle preserves all 441
|
||||
retained class/member APIs, all 17 ScalaSignature payloads, 3,703 unrelated method bodies and all 116 generated dumps.
|
||||
One internal Scala callback is replaced by the Java helper/callback under the shared classfile policy. Local evidence
|
||||
is in `run/migration-post-client-reference/`; `clean` preserves it.
|
||||
|
||||
**Next: port `PostMicroblockClient` in `microblock/EdgeMicroblockTraits.scala`.** Characterize render pass/bounds
|
||||
dispatch, lifecycle super-call ordering, face/post shrinking, split-bound reset and the size/transparency/axis
|
||||
tie-breaks before conversion. Retain equality semantics and observe virtual calls rather than caching them.
|
||||
**Next: port `HollowMicroblock` in `microblock/HollowMicroblockTraits.scala`.** Characterize its center connector
|
||||
lookup, hollow-size/slot geometry, normal/partial/collision boxes, subparts and occlusion super ordering before
|
||||
conversion. Leave `HollowMicroblockClient` rendering for a separate bounded target.
|
||||
Retain the Scala declarations where inheritance metadata is required, the external ProjectRed Scala-trait fixture
|
||||
and the ScalaSignature model bridges; compiler changes stay separate.
|
||||
|
||||
@@ -42,8 +42,7 @@ Remaining Scala units:
|
||||
| `multipart/asm/ASMMixinCompiler.scala` | Retained nested models, construction callbacks and Scala entry-point shell |
|
||||
| `multipart/asm/ScalaSignature.scala` | Named models, primitive/erased bridges and five generic inner-construction branches |
|
||||
| `multipart/asm/StackAnalyser.scala` | Class/companion/model shell over Java `StackAnalyserLogic` |
|
||||
| `microblock/MicroblockTraits.scala`, `FaceMicroblockTraits.scala`, `CornerMicroblockTraits.scala` | Six retained inheritance/bridge shells over Java implementation |
|
||||
| `microblock/EdgeMicroblockTraits.scala` | Edge/post shells over Java behavior, with retained post super dispatch; `PostMicroblockClient` implementation remains |
|
||||
| `microblock/MicroblockTraits.scala`, `FaceMicroblockTraits.scala`, `CornerMicroblockTraits.scala`, `EdgeMicroblockTraits.scala` | Nine retained state/inheritance/bridge shells over Java implementation, including post lifecycle/super dispatch |
|
||||
| `microblock/HollowMicroblockTraits.scala`, `TMicroOcclusion.scala` | Generated trait implementations; port in bounded groups while preserving inheritance metadata |
|
||||
|
||||
Both generators, both registries, core tile/part classes, ordinary microblock helpers/factories, handlers, networking,
|
||||
|
||||
@@ -41,7 +41,7 @@ Lamp Cover**, **Hollow Inverted White Lamp Cover**, **Inverted White Lamp Nook**
|
||||
| [ ] | Render several block micro-materials with Angelica shaders enabled, then render an unrelated block | Each face receives the matching block/meta shader material and the override is reset after the microblock draw | `MaterialRenderHelper.blockAndMeta` / `render` |
|
||||
| [ ] | Inspect face, hollow, edge and corner microblocks in inventory and as dropped entities | Every size/material combination uses the correct localized name and centered shape/material render | `ItemMicroPart` / `ItemMicroPartRenderer` / `MicroblockRender.renderItem` |
|
||||
| [ ] | Saw **Stone**, **Glass** and a ProjectRed **Inverted White Lamp** into face covers; place them on all six faces beside other microblocks, then inspect their inventory renders | Opaque covers retain their outer face while internal faces follow the shrink mask; transparent covers use the shrunk bounds, and inventory renders show the complete shape without missing or doubled faces | `FaceMicroblockClient.render` / `FaceMicroblockTraitLogic.render` |
|
||||
| [ ] | Place crossing posts of different sizes/transparency beside face covers, then add and remove neighbours | Post segments shrink and split at intersections without missing sections or stale render bounds | `PostMicroblockClient.recalcBounds` / `shrinkFace` / `shrinkPost` |
|
||||
| [ ] | Saw **Stone**, **Glass** and a ProjectRed **Inverted White Lamp** into strip/post shapes; place crossing posts on all three axes between face covers, then add and remove neighbours | Compare both split segments with the reference, including the second segment's use of physical bounds; removal resets the split without stale geometry or missing sections | `PostMicroblockClient.recalcBounds` / `PostMicroblockClientLogic` / `shrinkFace` / `shrinkPost` |
|
||||
| [ ] | Run connected AE2 **ME Glass Cable**, **ME Covered Cable** and **ME Dense Smart Cable**, plus ProjectRed **Framed Red Alloy Wire**, through hollow stone/glass covers on all six faces | Each opening follows the connector size; opaque and transparent rims, breaking overlay and highlight have no missing, doubled or stale sections after neighbour changes | `HollowMicroblockClient.recalcBounds` / `renderHollow` / `drawBreaking` / `drawHighlight` |
|
||||
| [ ] | Place touching face, corner and edge microblocks of mixed sizes/transparency, then add and remove neighbours | Intersections choose the same winner, opaque covered faces stay masked, and every surviving segment refreshes without gaps or stale bounds | `MicroOcclusion` / `TMicroOcclusionClient.recalcBounds` |
|
||||
|
||||
|
||||
@@ -1141,3 +1141,25 @@ differences belong in the [divergence ledger](../../JAVA_MIGRATION_DIVERGENCES.m
|
||||
versions remain verified. Sources total 219 Java files and 9 Scala files / 1,140 nonblank Scala lines.
|
||||
- Next: `PostMicroblockClient`; characterize render dispatch, lifecycle super ordering, shrink/split/reset behavior
|
||||
and size/transparency/axis tie-breaks before conversion. Client/GPU and full-pack checks remain manual.
|
||||
|
||||
### 2026-09-03 — Post microblock client implementation
|
||||
|
||||
- Committed eight JVM characterization tests and one Forge test first as `47885d1`. Frozen Scala 2.11.5 client forwarders
|
||||
and lifecycle predecessors pin the exact `-1` render branch, material reuse, live second-segment changes, repeated
|
||||
virtual size/transparency/axis reads, superclass ordering/exceptions and equality receiver dispatch (even on the
|
||||
same reference). Tests also pin collection `foreach`, neighbour order, fresh bounds copies, split reuse/reset and
|
||||
malformed face failures. Forge exercises real cover/post geometry across all three axes through the client helper.
|
||||
- Extracted five behavior methods to `PostMicroblockClientLogic.java`; retained Scala state/inheritance metadata,
|
||||
accessors and lifecycle/super forwarders. The named Java callback preserves `foreach` and replaces the internal
|
||||
Scala anonymous callback under the existing shared classfile policy. No algorithm fix or new effective divergence
|
||||
was introduced. In particular, the second split segment still copies physical bounds rather than the already
|
||||
face-clipped first segment; the new Forge check records that reference behavior.
|
||||
- Saved source/jar, reports and 116 generated dumps in ignored `run/migration-post-client-reference/`. Clean checks
|
||||
preserve all 441 retained class/member APIs, all 17 ScalaSignature payloads, 3,703 non-target method bodies and all
|
||||
116 generated names/hashes. Two Java classes replace one Scala callback, bringing the jar inventory to 443 classes.
|
||||
Formatting, checkstyle, build and Forge pass normally and after stopping Gradle for a clean rebuild: 365 JVM /
|
||||
227 Forge tests, zero failures/errors/skips. The forced Scala-compilation guard and all five packaged `@Mod` versions
|
||||
remain verified. Sources total 220 Java files and 9 Scala files / 1,104 nonblank Scala lines.
|
||||
- Expanded the existing manual post check with Stone, Glass and ProjectRed Inverted White Lamp examples. The
|
||||
dedicated server strips the client factory entry point; helper/geometry coverage does not establish actual client
|
||||
generation or GPU output. Next: `HollowMicroblock`, followed separately by `HollowMicroblockClient`.
|
||||
@@ -25,16 +25,8 @@ trait PostMicroblockClient extends PostMicroblock with MicroblockClient {
|
||||
var renderBounds1: Cuboid6 = _
|
||||
var renderBounds2: Cuboid6 = _
|
||||
|
||||
override def render(pos: Vector3, pass: Int) {
|
||||
val mat = getIMaterial
|
||||
if (pass == -1)
|
||||
MicroblockRender.renderCuboid(pos, mat, pass, getBounds, 0)
|
||||
else {
|
||||
MicroblockRender.renderCuboid(pos, mat, pass, renderBounds1, 0)
|
||||
if (renderBounds2 != null)
|
||||
MicroblockRender.renderCuboid(pos, mat, pass, renderBounds2, 0)
|
||||
}
|
||||
}
|
||||
override def render(pos: Vector3, pass: Int) =
|
||||
PostMicroblockClientLogic.render(this, pos, pass)
|
||||
|
||||
override def onPartChanged(part: TMultiPart) {
|
||||
recalcBounds()
|
||||
@@ -50,46 +42,15 @@ trait PostMicroblockClient extends PostMicroblock with MicroblockClient {
|
||||
recalcBounds()
|
||||
}
|
||||
|
||||
def recalcBounds() {
|
||||
renderBounds1 = getBounds.copy
|
||||
renderBounds2 = null
|
||||
def recalcBounds() = PostMicroblockClientLogic.recalcBounds(this)
|
||||
|
||||
shrinkFace(getShape << 1)
|
||||
shrinkFace(getShape << 1 | 1)
|
||||
def shrinkFace(fside: Int) = PostMicroblockClientLogic.shrinkFace(this, fside)
|
||||
|
||||
tile.partList.foreach(p =>
|
||||
if (p.isInstanceOf[PostMicroblock] && p != this)
|
||||
shrinkPost(p.asInstanceOf[PostMicroblock])
|
||||
)
|
||||
}
|
||||
def shrinkPost(post: PostMicroblock) =
|
||||
PostMicroblockClientLogic.shrinkPost(this, post)
|
||||
|
||||
def shrinkFace(fside: Int) {
|
||||
val part = tile.partMap(fside)
|
||||
if (part != null && part.getType.equals("mcr_face"))
|
||||
MicroOcclusion.shrink(
|
||||
renderBounds1,
|
||||
part.asInstanceOf[CommonMicroblock].getBounds,
|
||||
fside
|
||||
)
|
||||
}
|
||||
|
||||
def shrinkPost(post: PostMicroblock) {
|
||||
if (post == this)
|
||||
return
|
||||
|
||||
if (thisShrinks(post)) {
|
||||
if (renderBounds2 == null)
|
||||
renderBounds2 = getBounds.copy
|
||||
MicroOcclusion.shrink(renderBounds1, post.getBounds, getShape << 1 | 1)
|
||||
MicroOcclusion.shrink(renderBounds2, post.getBounds, getShape << 1)
|
||||
}
|
||||
}
|
||||
|
||||
def thisShrinks(other: PostMicroblock): Boolean = {
|
||||
if (getSize != other.getSize) return getSize < other.getSize
|
||||
if (isTransparent != other.isTransparent) return isTransparent
|
||||
return getShape > other.getShape
|
||||
}
|
||||
def thisShrinks(other: PostMicroblock): Boolean =
|
||||
PostMicroblockClientLogic.thisShrinks(this, other)
|
||||
}
|
||||
|
||||
trait PostMicroblock
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
package codechicken.microblock;
|
||||
|
||||
import codechicken.lib.vec.Vector3;
|
||||
import codechicken.microblock.MicroMaterialRegistry.IMicroMaterial;
|
||||
import codechicken.multipart.TMultiPart;
|
||||
import scala.runtime.AbstractFunction1;
|
||||
import scala.runtime.BoxedUnit;
|
||||
|
||||
/** Client behavior behind the retained Scala state, inheritance and lifecycle bridges. */
|
||||
final class PostMicroblockClientLogic {
|
||||
|
||||
private PostMicroblockClientLogic() {}
|
||||
|
||||
static void render(PostMicroblockClient part, Vector3 pos, int pass) {
|
||||
IMicroMaterial material = ((Microblock) part).getIMaterial();
|
||||
if (pass == -1) {
|
||||
MicroblockRender.renderCuboid(pos, material, pass, part.getBounds(), 0);
|
||||
} else {
|
||||
MicroblockRender.renderCuboid(pos, material, pass, part.renderBounds1(), 0);
|
||||
if (part.renderBounds2() != null) {
|
||||
MicroblockRender.renderCuboid(pos, material, pass, part.renderBounds2(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void recalcBounds(PostMicroblockClient part) {
|
||||
part.renderBounds1_$eq(part.getBounds().copy());
|
||||
part.renderBounds2_$eq(null);
|
||||
part.shrinkFace(((Microblock) part).getShape() << 1);
|
||||
part.shrinkFace(((Microblock) part).getShape() << 1 | 1);
|
||||
((TMultiPart) part).tile().partList().foreach(new ShrinkPosts(part));
|
||||
}
|
||||
|
||||
static void shrinkFace(PostMicroblockClient part, int side) {
|
||||
TMultiPart other = ((TMultiPart) part).tile().partMap(side);
|
||||
if (other != null && other.getType().equals("mcr_face")) {
|
||||
MicroOcclusion.shrink(part.renderBounds1(), ((CommonMicroblock) other).getBounds(), side);
|
||||
}
|
||||
}
|
||||
|
||||
static void shrinkPost(PostMicroblockClient part, PostMicroblock other) {
|
||||
// Scala equality calls the left operand's equals even when the references are identical.
|
||||
if (other == null ? part == null : other.equals(part)) {
|
||||
return;
|
||||
}
|
||||
if (part.thisShrinks(other)) {
|
||||
if (part.renderBounds2() == null) {
|
||||
part.renderBounds2_$eq(part.getBounds().copy());
|
||||
}
|
||||
MicroOcclusion.shrink(part.renderBounds1(), other.getBounds(), ((Microblock) part).getShape() << 1 | 1);
|
||||
MicroOcclusion.shrink(part.renderBounds2(), other.getBounds(), ((Microblock) part).getShape() << 1);
|
||||
}
|
||||
}
|
||||
|
||||
static boolean thisShrinks(PostMicroblockClient part, PostMicroblock other) {
|
||||
if (((Microblock) part).getSize() != ((Microblock) other).getSize()) {
|
||||
return ((Microblock) part).getSize() < ((Microblock) other).getSize();
|
||||
}
|
||||
if (((Microblock) part).isTransparent() != ((Microblock) other).isTransparent()) {
|
||||
return ((Microblock) part).isTransparent();
|
||||
}
|
||||
return ((Microblock) part).getShape() > ((Microblock) other).getShape();
|
||||
}
|
||||
|
||||
private static final class ShrinkPosts extends AbstractFunction1<TMultiPart, BoxedUnit>
|
||||
implements scala.Serializable {
|
||||
|
||||
private static final long serialVersionUID = 0L;
|
||||
private final PostMicroblockClient part;
|
||||
|
||||
ShrinkPosts(PostMicroblockClient part) {
|
||||
this.part = part;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BoxedUnit apply(TMultiPart other) {
|
||||
if (other instanceof PostMicroblock && !other.equals(part)) {
|
||||
part.shrinkPost((PostMicroblock) other);
|
||||
}
|
||||
return BoxedUnit.UNIT;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user