mirror of
https://github.com/GTNewHorizons/ForgeMultipart.git
synced 2026-10-26 14:24:01 +00:00
feat: add inverse button orientation lookup
This commit is contained in:
1 parent
ebbc92378d
commit
9a6d1ec4fc
6 files changed
+71
-3
No files matched your search
@@ -55,6 +55,7 @@ Existing reflective binaries remain supported until consumer release and pack ad
|
||||
| Read FMP's global render registration ID | `TileMultipart.getRenderID()` - [render-ID meaning, lifecycle and setter](api/RENDER_ID.md) |
|
||||
| Inspect an existing tile or converted placeholder with a named result | `getOrConvertTileResult(World, BlockCoord)` - [conversion outcomes and placement lifecycle](api/TILE_CONVERSION.md) |
|
||||
| Add or remap multipart button attachment orientations | `ButtonPart.setOrientation(int, ForgeDirection)` - [metadata, face mapping and Et Futurum migration](api/BUTTON_ORIENTATIONS.md) |
|
||||
| Read a custom button's orientation metadata from its attachment face | `ButtonPart.metaForSide(int)` - [live inverse lookup and ProjectRed migration](api/BUTTON_ORIENTATIONS.md#reading-orientation-metadata) |
|
||||
|
||||
Each guide explains ownership, lifecycle, legacy replacements and limitations, and links to a compiling Java example
|
||||
exercised by the test suite. The loading/setter APIs are advanced reconstruction operations; ordinary placement and
|
||||
|
||||
@@ -35,6 +35,25 @@ This method does not define a vanilla button block's bounds. `ButtonPart` captur
|
||||
class initialization, after normal class transformations; a mod adding metadata orientations must still make its
|
||||
button block expose the matching bounds.
|
||||
|
||||
## Reading orientation metadata
|
||||
|
||||
`ButtonPart.metaForSide(int)` returns the current metadata for an attachment face index (`0` through `5`), including
|
||||
`-1` for an unmapped face. It reads the live inverse mapping, so both `setOrientation` and legacy array mutations or
|
||||
replacement remain visible. Invalid indices throw `IndexOutOfBoundsException`; the accessor does not mask indices,
|
||||
check world support, construct a part or reject an unmapped result on the caller's behalf.
|
||||
|
||||
ProjectRed's `ItemPartButtonCommons.newPart` can replace `ButtonPart.sideMetaMap(side ^ 1)` with:
|
||||
|
||||
```scala
|
||||
val b = getNewInst(ButtonPart.metaForSide(side ^ 1))
|
||||
```
|
||||
|
||||
Keep its existing vertical-face rejection, support check, custom factory and `onPlaced` call. Here `side` is the
|
||||
clicked face, so `side ^ 1` is the attachment face. `sideForMeta` performs the opposite lookup;
|
||||
`ButtonPart.placement` is not a replacement because it constructs an ordinary button and applies its own validation.
|
||||
The accessor is additive on this branch; rebuild/publish the development artifact before compiling a consumer
|
||||
against it. It is not yet tied to a released minimum FMP version.
|
||||
|
||||
## Migrating Et Futurum Requiem
|
||||
|
||||
Replace the reflective reads, four array writes and reflective field assignments with the two calls above. Do not
|
||||
@@ -43,11 +62,12 @@ Keep Et Futurum's existing FMP presence/version gate so older FMP versions never
|
||||
|
||||
The public mutable `metaSideMap` and `sideMetaMap` fields remain binary and reflective compatibility surfaces for old
|
||||
releases. New integrations should not read, replace or mutate them directly. Their removal still requires a released
|
||||
Et Futurum migration, target-pack adoption and a fresh consumer scan.
|
||||
Et Futurum migration, ProjectRed's inverse-lookup migration, target-pack adoption and a fresh consumer scan.
|
||||
|
||||
## Validation
|
||||
|
||||
Forge characterization first freezes the old Et Futurum mutation and verifies exact metadata and placement on all six
|
||||
faces. API tests verify the two direct calls produce the same arrays, displaced pairs remain one-to-one, invalid input
|
||||
is atomic, and the example compiles. A physical client with Et Futurum must still complete the
|
||||
is atomic, and the example compiles. Inverse-lookup coverage checks all faces, unmapped results, remapping, legacy
|
||||
mutation/replacement and invalid indices. A physical client with Et Futurum must still complete the
|
||||
[all-face button check](../migration/MANUAL_CHECKS.md) before release.
|
||||
@@ -769,6 +769,7 @@ tied to a released minimum dependency version. Unlisted contracts remain governe
|
||||
|
||||
| Legacy contract | Consumer and inspected source | Supported replacement | Consumer migration/release | Target-pack adoption and removal gate |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `ButtonPart.sideMetaMap[side ^ 1]` live inverse lookup | ProjectRed `e173952e96a4` and separate preparatory migration checkout: `illumination/items.scala`, `ItemPartButtonCommons.newPart` | `ButtonPart.metaForSide(side ^ 1)`; [lookup contract](../api/BUTTON_ORIENTATIONS.md#reading-orientation-metadata) | FMP accessor/example and regression coverage added; consumer replacement requires a rebuilt FMP artifact; preparatory migration is not upstream adoption | Retain the array until ProjectRed and Et Futurum migrations are released/adopted and a fresh scan clears legacy use |
|
||||
| `TRedstoneTile.openConnections(int)` | ProjectRed `e173952e96a4`: `transmission/redwires.scala` | Existing stable `IRedstoneTile.openConnections(int)` with the same mask/rotation logic; [guide](../api/TILE_TRAIT_ACCESS.md) | FMP source-access example and Forge coverage complete; consumer source patch/release pending | Retain the old runtime interface descriptor until adoption |
|
||||
| `TSlottedTile.v_partMap()` array mutation | OpenComputers `2c00f79be24b`: `PrintPart.toggleState` | `TileMultipart.refreshPartSlots(part)`; [equality, cache and notification contract](../api/TILE_TRAIT_ACCESS.md#refreshing-a-changed-slot-mask) | FMP API/example complete; consumer source patch/release pending, preserving validation and following sound/notify/packet/schedule order | Keep the live array/accessor ABI until released pack adoption; do not replace it with reflection or a whole-tile reload |
|
||||
| External Scala `LightMicroblock` registered through `MicroblockGenerator.registerTrait` | ProjectRed `e173952e96a4`: `illumination/lightmicroblocks.scala` | Java source trait registered by name, `IGeneratedMaterial`, typed sibling traversal and halo helper; [example](../api/MICROBLOCK_EXTENSIONS.md) | FMP example tested; consumer rewrite/release, existing config/halo wiring and physical-client checks pending | Retain external Scala trait ingestion until released-consumer adoption and internal Scala-trait removal |
|
||||
|
||||
@@ -14,4 +14,9 @@ public final class ButtonOrientationExample {
|
||||
ButtonPart.setOrientation(0, ForgeDirection.UP);
|
||||
ButtonPart.setOrientation(5, ForgeDirection.DOWN);
|
||||
}
|
||||
|
||||
/** Looks up a custom button's metadata without changing its placement or construction policy. */
|
||||
public static int metadataForClickedFace(int side) {
|
||||
return ButtonPart.metaForSide(side ^ 1);
|
||||
}
|
||||
}
|
||||
+29
@@ -22,6 +22,35 @@ class ButtonOrientationFunctionalTest {
|
||||
|
||||
private static final BlockCoord BUTTON = new BlockCoord(64, 200, 48);
|
||||
|
||||
@Test
|
||||
void inverseLookupReadsLiveMappingsWithoutPlacementValidation() {
|
||||
int[] originalMetaSideMap = ButtonPart.metaSideMap;
|
||||
int[] originalSideMetaMap = ButtonPart.sideMetaMap;
|
||||
try {
|
||||
ButtonPart.metaSideMap = new int[] { -1, 4, 5, 2, 3, -1, -1, -1 };
|
||||
ButtonPart.sideMetaMap = new int[] { -1, -1, 3, 4, 1, 2 };
|
||||
for (int side = 0; side < 6; side++) {
|
||||
assertEquals(ButtonPart.sideMetaMap[side], ButtonPart.metaForSide(side));
|
||||
assertEquals(ButtonPart.sideMetaMap[side ^ 1], ButtonOrientationExample.metadataForClickedFace(side));
|
||||
}
|
||||
assertEquals(-1, ButtonPart.metaForSide(0));
|
||||
ButtonPart.setOrientation(5, ForgeDirection.DOWN);
|
||||
assertEquals(5, ButtonPart.metaForSide(0));
|
||||
ButtonPart.setOrientation(5, ForgeDirection.UP);
|
||||
assertEquals(-1, ButtonPart.metaForSide(0));
|
||||
assertEquals(5, ButtonPart.metaForSide(1));
|
||||
ButtonPart.sideMetaMap[2] = 7;
|
||||
assertEquals(7, ButtonPart.metaForSide(2));
|
||||
ButtonPart.sideMetaMap = new int[] { 5, 0, 3, 4, 1, 2 };
|
||||
assertEquals(3, ButtonPart.metaForSide(2));
|
||||
assertThrows(IndexOutOfBoundsException.class, () -> ButtonPart.metaForSide(-1));
|
||||
assertThrows(IndexOutOfBoundsException.class, () -> ButtonPart.metaForSide(6));
|
||||
} finally {
|
||||
ButtonPart.metaSideMap = originalMetaSideMap;
|
||||
ButtonPart.sideMetaMap = originalSideMetaMap;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void etFuturumArrayMutationEnablesFloorAndCeilingPlacement() {
|
||||
World world = MinecraftServer.getServer().worldServers[0];
|
||||
|
||||
@@ -25,7 +25,8 @@ public class ButtonPart extends McSidedMetaPart implements IFaceRedstonePart {
|
||||
public static int[] metaSideMap = new int[] { -1, 4, 5, 2, 3, -1, -1, -1 };
|
||||
|
||||
/**
|
||||
* Legacy mutable inverse mapping retained for existing integrations; new code should use {@link #setOrientation}.
|
||||
* Legacy mutable inverse mapping retained for existing integrations; use {@link #metaForSide} to read and
|
||||
* {@link #setOrientation} to configure it.
|
||||
*/
|
||||
public static int[] sideMetaMap = new int[] { -1, -1, 3, 4, 1, 2 };
|
||||
public static Cuboid6[] cuboidRegions = setupCuboids();
|
||||
@@ -84,6 +85,17 @@ public class ButtonPart extends McSidedMetaPart implements IFaceRedstonePart {
|
||||
sideMetaMap[side] = metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current orientation metadata for an attachment face, or -1 if that face is unmapped. Reads the live
|
||||
* mapping, including changes made by legacy integrations. Does not check support or construct a part.
|
||||
*
|
||||
* @param side attachment face index, from 0 through 5; for a clicked face use {@code side ^ 1}
|
||||
* @throws IndexOutOfBoundsException if the index is outside the mapping
|
||||
*/
|
||||
public static int metaForSide(int side) {
|
||||
return sideMetaMap[side];
|
||||
}
|
||||
|
||||
public static BlockButton getButton(int meta) {
|
||||
return (meta & 0x10) > 0 ? woodenButton : stoneButton;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user