From 763ff90a6110384cc67ec6767fbfb244cabd1ea4 Mon Sep 17 00:00:00 2001 From: Brian Neumann-Fopiano Date: Thu, 11 Jun 2026 22:53:38 -0400 Subject: [PATCH] Headless Pipeline --- core/purity-allowlist.txt | 20 --- .../core/structure/StructureIndexService.java | 4 +- .../arcane/iris/engine/IrisEngineMantle.java | 10 +- .../iris/engine/decorator/DecoratorCore.java | 129 +++++++------- .../arcane/iris/engine/framework/Engine.java | 9 +- .../iris/engine/mantle/EngineMantle.java | 16 +- .../iris/engine/mantle/MantleWriter.java | 25 +-- .../MantleFloatingObjectComponent.java | 15 +- .../components/MantleObjectComponent.java | 23 ++- .../engine/modifier/IrisDepositModifier.java | 14 +- .../modifier/IrisPerfectionModifier.java | 28 +-- .../engine/modifier/IrisPostModifier.java | 115 ++++++------- .../engine/object/BlockDataMergeSupport.java | 32 ++++ .../iris/engine/object/IrisBlockData.java | 23 +-- .../arcane/iris/engine/object/IrisCoral.java | 2 +- .../iris/engine/object/IrisCrystal.java | 2 +- .../engine/object/IrisDepositVariant.java | 23 +-- .../arcane/iris/engine/object/IrisEntity.java | 30 +++- .../iris/engine/object/IrisFormation.java | 2 +- .../arcane/iris/engine/object/IrisFungus.java | 2 +- .../arcane/iris/engine/object/IrisObject.java | 162 ++++++++---------- .../engine/object/IrisObjectRotation.java | 15 ++ .../engine/object/IrisProceduralBlocks.java | 72 ++++++-- .../engine/object/IrisProceduralTree.java | 2 +- .../arcane/iris/engine/object/IrisRuin.java | 2 +- .../engine/object/coral/CoralGenerator.java | 30 ++-- .../object/crystal/CrystalGenerator.java | 20 +-- .../formation/FormationBlockResolver.java | 7 +- .../object/formation/FormationGenerator.java | 6 +- .../engine/object/fungi/FungusGenerator.java | 14 +- .../object/fungi/FungusStemBuilder.java | 4 +- .../engine/object/ruin/RuinBlockCanvas.java | 12 +- .../object/ruin/RuinDecoratorApplier.java | 4 +- .../engine/object/ruin/RuinGenerator.java | 10 +- .../object/tree/ProceduralTreeGenerator.java | 17 +- .../engine/object/tree/TreeBlockResolver.java | 110 ++++++------ .../engine/object/tree/TreePlausibility.java | 22 ++- .../platform/bukkit/BukkitBlockState.java | 16 ++ .../art/arcane/iris/util/common/data/B.java | 4 + .../project/matter/IrisMatterSupport.java | 2 + .../matter/slices/PlatformBlockMatter.java | 39 +++++ .../art/arcane/iris/probe/StubPlatform.java | 10 ++ .../arcane/iris/spi/PlatformBlockState.java | 4 + 43 files changed, 589 insertions(+), 519 deletions(-) create mode 100644 core/src/main/java/art/arcane/iris/util/project/matter/slices/PlatformBlockMatter.java diff --git a/core/purity-allowlist.txt b/core/purity-allowlist.txt index 6aa991004..e19929db5 100644 --- a/core/purity-allowlist.txt +++ b/core/purity-allowlist.txt @@ -87,14 +87,8 @@ art/arcane/iris/engine/framework/EngineAssignedWorldManager.java art/arcane/iris/engine/framework/EnginePlayer.java art/arcane/iris/engine/framework/EngineWorldManager.java art/arcane/iris/engine/framework/placer/WorldObjectPlacer.java -art/arcane/iris/engine/mantle/EngineMantle.java art/arcane/iris/engine/mantle/MantleWriter.java -art/arcane/iris/engine/mantle/components/MantleFloatingObjectComponent.java -art/arcane/iris/engine/mantle/components/MantleObjectComponent.java -art/arcane/iris/engine/modifier/IrisDepositModifier.java art/arcane/iris/engine/modifier/IrisFloatingChildBiomeModifier.java -art/arcane/iris/engine/modifier/IrisPerfectionModifier.java -art/arcane/iris/engine/modifier/IrisPostModifier.java art/arcane/iris/engine/object/BlockDataMergeSupport.java art/arcane/iris/engine/object/IPostBlockAccess.java art/arcane/iris/engine/object/IrisAttributeModifier.java @@ -108,7 +102,6 @@ art/arcane/iris/engine/object/IrisCommandRegistry.java art/arcane/iris/engine/object/IrisCompat.java art/arcane/iris/engine/object/IrisCompatabilityBlockFilter.java art/arcane/iris/engine/object/IrisCompatabilityItemFilter.java -art/arcane/iris/engine/object/IrisDepositVariant.java art/arcane/iris/engine/object/IrisDimension.java art/arcane/iris/engine/object/IrisDirection.java art/arcane/iris/engine/object/IrisEffect.java @@ -121,7 +114,6 @@ art/arcane/iris/engine/object/IrisObject.java art/arcane/iris/engine/object/IrisObjectPlacement.java art/arcane/iris/engine/object/IrisObjectRotation.java art/arcane/iris/engine/object/IrisPotionEffect.java -art/arcane/iris/engine/object/IrisProceduralBlocks.java art/arcane/iris/engine/object/IrisSurface.java art/arcane/iris/engine/object/IrisTree.java art/arcane/iris/engine/object/IrisVanillaLootTable.java @@ -132,18 +124,6 @@ art/arcane/iris/engine/object/LegacyTileData.java art/arcane/iris/engine/object/PotionEffectTypes.java art/arcane/iris/engine/object/TileData.java art/arcane/iris/engine/object/annotations/functions/LootTableKeyFunction.java -art/arcane/iris/engine/object/coral/CoralGenerator.java -art/arcane/iris/engine/object/crystal/CrystalGenerator.java -art/arcane/iris/engine/object/formation/FormationBlockResolver.java -art/arcane/iris/engine/object/formation/FormationGenerator.java -art/arcane/iris/engine/object/fungi/FungusGenerator.java -art/arcane/iris/engine/object/fungi/FungusStemBuilder.java -art/arcane/iris/engine/object/ruin/RuinBlockCanvas.java -art/arcane/iris/engine/object/ruin/RuinDecoratorApplier.java -art/arcane/iris/engine/object/ruin/RuinGenerator.java -art/arcane/iris/engine/object/tree/ProceduralTreeGenerator.java -art/arcane/iris/engine/object/tree/TreeBlockResolver.java -art/arcane/iris/engine/object/tree/TreePlausibility.java art/arcane/iris/engine/platform/BukkitChunkGenerator.java art/arcane/iris/engine/platform/DummyBiomeProvider.java art/arcane/iris/engine/platform/DummyChunkGenerator.java diff --git a/core/src/main/java/art/arcane/iris/core/structure/StructureIndexService.java b/core/src/main/java/art/arcane/iris/core/structure/StructureIndexService.java index 09749c268..f68d02812 100644 --- a/core/src/main/java/art/arcane/iris/core/structure/StructureIndexService.java +++ b/core/src/main/java/art/arcane/iris/core/structure/StructureIndexService.java @@ -21,6 +21,7 @@ package art.arcane.iris.core.structure; import art.arcane.iris.spi.IrisLogging; import art.arcane.iris.core.loader.IrisData; import art.arcane.iris.core.nms.INMS; +import art.arcane.iris.util.project.matter.IrisMatterSupport; import art.arcane.volmlib.util.collection.KList; import com.google.gson.GsonBuilder; @@ -37,12 +38,13 @@ import java.util.concurrent.ConcurrentHashMap; public final class StructureIndexService { private static final Set GENERATED = ConcurrentHashMap.newKeySet(); + private static final boolean BUKKIT_PRESENT = IrisMatterSupport.isBukkitPresent(); private StructureIndexService() { } public static File writeOnce(IrisData data) { - if (data == null) { + if (!BUKKIT_PRESENT || data == null) { return null; } diff --git a/core/src/main/java/art/arcane/iris/engine/IrisEngineMantle.java b/core/src/main/java/art/arcane/iris/engine/IrisEngineMantle.java index 5be90893b..7d6cb3e08 100644 --- a/core/src/main/java/art/arcane/iris/engine/IrisEngineMantle.java +++ b/core/src/main/java/art/arcane/iris/engine/IrisEngineMantle.java @@ -33,6 +33,7 @@ import art.arcane.iris.engine.mantle.components.MantleFluidBodyComponent; import art.arcane.iris.engine.mantle.components.MantleObjectComponent; import art.arcane.iris.engine.mantle.components.IrisStructureComponent; import art.arcane.iris.spi.IrisLogging; +import art.arcane.iris.spi.PlatformBlockState; import art.arcane.iris.util.project.matter.IrisMatterSupport; import art.arcane.volmlib.util.collection.KList; import art.arcane.volmlib.util.collection.KMap; @@ -66,6 +67,7 @@ import java.util.Set; @EqualsAndHashCode(exclude = "engine") @ToString(exclude = "engine") public class IrisEngineMantle implements EngineMantle { + private static final boolean BUKKIT_PRESENT = IrisMatterSupport.isBukkitPresent(); private final Engine engine; private final Mantle mantle; @Getter(AccessLevel.NONE) @@ -229,7 +231,13 @@ public class IrisEngineMantle implements EngineMantle { @Override public Class classifyValue(Object value) { - return BukkitPlatform.classifyMantleValue(value); + if (value instanceof PlatformBlockState) { + return PlatformBlockState.class; + } + if (BUKKIT_PRESENT) { + return BukkitPlatform.classifyMantleValue(value); + } + return value.getClass(); } @Override diff --git a/core/src/main/java/art/arcane/iris/engine/decorator/DecoratorCore.java b/core/src/main/java/art/arcane/iris/engine/decorator/DecoratorCore.java index 04e3b3040..c868fe9cb 100644 --- a/core/src/main/java/art/arcane/iris/engine/decorator/DecoratorCore.java +++ b/core/src/main/java/art/arcane/iris/engine/decorator/DecoratorCore.java @@ -18,30 +18,37 @@ package art.arcane.iris.engine.decorator; -import art.arcane.iris.platform.bukkit.BukkitBlockResolution; - import art.arcane.iris.core.loader.IrisData; import art.arcane.iris.engine.mantle.EngineMantle; import art.arcane.iris.engine.object.IrisBiome; import art.arcane.iris.engine.object.IrisDecorationPart; import art.arcane.iris.engine.object.IrisDecorator; +import art.arcane.iris.engine.object.IrisProceduralBlocks; import art.arcane.iris.platform.bukkit.BukkitBlockState; import art.arcane.iris.spi.IrisLogging; import art.arcane.iris.spi.PlatformBlockState; +import art.arcane.iris.util.common.data.B; import art.arcane.iris.util.project.hunk.Hunk; import art.arcane.volmlib.util.math.RNG; -import org.bukkit.Material; import org.bukkit.block.BlockFace; import org.bukkit.block.BlockSupport; -import org.bukkit.block.data.Bisected; import org.bukkit.block.data.BlockData; import org.bukkit.block.data.MultipleFacing; -import org.bukkit.block.data.type.PointedDripstone; final class DecoratorCore { private static final long SEED_OFFSET = 29356788L; private static final long PART_FACTOR = 10439677L; + private static final boolean BUKKIT_PRESENT = detectBukkit(); + + private static boolean detectBukkit() { + try { + Class.forName("org.bukkit.Bukkit", false, DecoratorCore.class.getClassLoader()); + return true; + } catch (ClassNotFoundException e) { + return false; + } + } static final ThreadLocal SCRATCH_OPTS = ThreadLocal.withInitial(PlaceOpts::new); @@ -99,27 +106,31 @@ final class DecoratorCore { return; } - BlockData rawBd = (BlockData) bd.nativeHandle(); - if (rawBd instanceof Bisected) { - BlockData top = rawBd.clone(); - ((Bisected) top).setHalf(Bisected.Half.TOP); + String half = IrisProceduralBlocks.propertyValue(bd, "half"); + if (half != null) { try { - if (!caveSkipFluid || !BukkitBlockResolution.isFluid(unwrap(data.get(x, height + 2, z)))) { - data.set(x, height + 2, z, BukkitBlockState.of(top)); + if (!caveSkipFluid || !B.isFluid(data.get(x, height + 2, z))) { + data.set(x, height + 2, z, bd.withProperty("half", topHalfValue(half))); } } catch (Throwable e) { IrisLogging.reportError(e); } - BlockData bottom = rawBd.clone(); - ((Bisected) bottom).setHalf(Bisected.Half.BOTTOM); - bd = BukkitBlockState.of(bottom); + bd = bd.withProperty("half", bottomHalfValue(half)); } - if (BukkitBlockResolution.isAir(unwrap(data.get(x, height + 1, z)))) { + if (B.isAir(data.get(x, height + 1, z))) { data.set(x, height + 1, z, fixFacesForHunk(bd, data, x, z, realX, height + 1, realZ, mantle)); } } + private static String topHalfValue(String half) { + return half.equals("upper") || half.equals("lower") ? "upper" : "top"; + } + + private static String bottomHalfValue(String half) { + return half.equals("upper") || half.equals("lower") ? "lower" : "bottom"; + } + static void placeSurfaceSingle(IrisDecorator decorator, int x, int z, int realX, int height, int realZ, Hunk data, RNG rng, IrisData irisData, @@ -133,7 +144,7 @@ final class DecoratorCore { } if (decorator.getForceBlock() != null) { - if (caveSkipFluid && BukkitBlockResolution.isFluid(unwrap(bdx))) { + if (caveSkipFluid && B.isFluid(bdx)) { return; } data.set(x, height, z, fixFacesForHunk( @@ -152,23 +163,19 @@ final class DecoratorCore { } } - BlockData rawBd = bd == null ? null : (BlockData) bd.nativeHandle(); - if (rawBd instanceof Bisected) { - BlockData top = rawBd.clone(); - ((Bisected) top).setHalf(Bisected.Half.TOP); + String half = bd == null ? null : IrisProceduralBlocks.propertyValue(bd, "half"); + if (half != null) { try { - if (!caveSkipFluid || !BukkitBlockResolution.isFluid(unwrap(data.get(x, height + 2, z)))) { - data.set(x, height + 2, z, BukkitBlockState.of(top)); + if (!caveSkipFluid || !B.isFluid(data.get(x, height + 2, z))) { + data.set(x, height + 2, z, bd.withProperty("half", topHalfValue(half))); } } catch (Throwable e) { IrisLogging.reportError(e); } - BlockData bottom = rawBd.clone(); - ((Bisected) bottom).setHalf(Bisected.Half.BOTTOM); - bd = BukkitBlockState.of(bottom); + bd = bd.withProperty("half", bottomHalfValue(half)); } - if (BukkitBlockResolution.isAir(unwrap(data.get(x, height + 1, z)))) { + if (B.isAir(data.get(x, height + 1, z))) { data.set(x, height + 1, z, fixFacesForHunk(bd, data, x, z, realX, height + 1, realZ, mantle)); } } @@ -197,7 +204,7 @@ final class DecoratorCore { int stack = computeStack(decorator, rng, realX, realZ, irisData, effectiveMax); if (stack == 1) { - if (opts.caveSkipFluid && BukkitBlockResolution.isFluid(unwrap(data.get(x, height, z)))) { + if (opts.caveSkipFluid && B.isFluid(data.get(x, height, z))) { return; } data.set(x, height, z, decorator.pickBlockDataTop(rng, irisData, realX, realZ)); @@ -225,12 +232,12 @@ final class DecoratorCore { break; } - if (opts.caveSkipFluid && BukkitBlockResolution.isFluid(unwrap(data.get(x, height + 1 + i, z)))) { + if (opts.caveSkipFluid && B.isFluid(data.get(x, height + 1 + i, z))) { break; } - if (bd.nativeHandle() instanceof PointedDripstone) { - bd = dripstoneBlock(stack, i, BlockFace.UP); + if (IrisProceduralBlocks.materialKey(bd).equals("minecraft:pointed_dripstone")) { + bd = dripstoneBlock(stack, i, "up"); } data.set(x, height + 1 + i, z, bd); @@ -243,7 +250,7 @@ final class DecoratorCore { int stack = computeStack(decorator, rng, realX, realZ, irisData, max); if (stack == 1) { - if (opts.caveSkipFluid && BukkitBlockResolution.isFluid(unwrap(data.get(x, height, z)))) { + if (opts.caveSkipFluid && B.isFluid(data.get(x, height, z))) { return; } data.set(x, height, z, fixFacesForHunk( @@ -263,11 +270,11 @@ final class DecoratorCore { ? decorator.pickBlockDataTop(rng, irisData, realX, realZ) : decorator.pickBlockData(rng, irisData, realX, realZ); - if (bd != null && bd.nativeHandle() instanceof PointedDripstone) { - bd = dripstoneBlock(stack, i, BlockFace.DOWN); + if (bd != null && IrisProceduralBlocks.materialKey(bd).equals("minecraft:pointed_dripstone")) { + bd = dripstoneBlock(stack, i, "down"); } - if (opts.caveSkipFluid && BukkitBlockResolution.isFluid(unwrap(data.get(x, h, z)))) { + if (opts.caveSkipFluid && B.isFluid(data.get(x, h, z))) { break; } data.set(x, h, z, fixFacesForHunk(bd, data, x, z, realX, h, realZ, mantle)); @@ -283,20 +290,16 @@ final class DecoratorCore { return; } - BlockData rawBd = (BlockData) bd.nativeHandle(); - if (rawBd instanceof Bisected) { - BlockData top = rawBd.clone(); - ((Bisected) top).setHalf(Bisected.Half.TOP); + String half = IrisProceduralBlocks.propertyValue(bd, "half"); + if (half != null) { try { if (max > 2) { - data.set(xf, height + 2, zf, BukkitBlockState.of(top)); + data.set(xf, height + 2, zf, bd.withProperty("half", topHalfValue(half))); } } catch (Throwable e) { IrisLogging.reportError(e); } - BlockData bottom = rawBd.clone(); - ((Bisected) bottom).setHalf(Bisected.Half.BOTTOM); - bd = BukkitBlockState.of(bottom); + bd = bd.withProperty("half", bottomHalfValue(half)); } if (max > 1) { @@ -336,10 +339,10 @@ final class DecoratorCore { static PlatformBlockState fixFacesForHunk(PlatformBlockState b, Hunk hunk, int rX, int rZ, int x, int y, int z, EngineMantle mantle) { - BlockData rawB = unwrap(b); - if (!BukkitBlockResolution.isVineBlock(rawB)) { + if (!BUKKIT_PRESENT || !B.isVineBlock(b)) { return b; } + BlockData rawB = (BlockData) b.nativeHandle(); BlockData cloned = rawB.clone(); MultipleFacing data = (MultipleFacing) cloned; data.getFaces().forEach(f -> data.setFace(f, false)); @@ -351,13 +354,11 @@ final class DecoratorCore { } int yy = y + f.getModY(); - BlockData r = null; + PlatformBlockState rs = null; if (mantle != null) { - r = mantle.getMantle().get(x + f.getModX(), yy, z + f.getModZ(), BlockData.class); - } - if (r == null) { - r = (BlockData) EngineMantle.AIR.nativeHandle(); + rs = mantle.getMantle().get(x + f.getModX(), yy, z + f.getModZ(), PlatformBlockState.class); } + BlockData r = rs == null ? (BlockData) EngineMantle.AIR.nativeHandle() : (BlockData) rs.nativeHandle(); if (r.isFaceSturdy(f.getOppositeFace(), BlockSupport.FULL)) { if (data.getAllowedFaces().contains(f)) { found = true; @@ -372,7 +373,7 @@ final class DecoratorCore { continue; } - r = unwrap(hunk.get(xx, yy, zz)); + r = (BlockData) hunk.get(xx, yy, zz).nativeHandle(); if (r.isFaceSturdy(f.getOppositeFace(), BlockSupport.FULL)) { if (data.getAllowedFaces().contains(f)) { found = true; @@ -390,13 +391,12 @@ final class DecoratorCore { } static boolean canGoOn(PlatformBlockState decorator, PlatformBlockState surface) { + if (!BUKKIT_PRESENT) { + return B.isSolid(surface); + } return ((BlockData) surface.nativeHandle()).isFaceSturdy(BlockFace.UP, BlockSupport.FULL); } - private static BlockData unwrap(PlatformBlockState state) { - return state == null ? null : (BlockData) state.nativeHandle(); - } - private static int computeStack(IrisDecorator decorator, RNG rng, double realX, double realZ, IrisData irisData, int max) { int stack = decorator.getHeight(rng, realX, realZ, irisData); @@ -411,23 +411,16 @@ final class DecoratorCore { private static volatile PlatformBlockState[] dripstoneUp; private static volatile PlatformBlockState[] dripstoneDown; - private static PlatformBlockState[] buildDripstoneArr(BlockFace direction) { - PointedDripstone.Thickness[] order = { - PointedDripstone.Thickness.TIP, - PointedDripstone.Thickness.FRUSTUM, - PointedDripstone.Thickness.BASE - }; + private static PlatformBlockState[] buildDripstoneArr(String direction) { + String[] order = {"tip", "frustum", "base"}; PlatformBlockState[] arr = new PlatformBlockState[3]; for (int k = 0; k < 3; k++) { - BlockData bd = Material.POINTED_DRIPSTONE.createBlockData(); - ((PointedDripstone) bd).setThickness(order[k]); - ((PointedDripstone) bd).setVerticalDirection(direction); - arr[k] = BukkitBlockState.of(bd); + arr[k] = B.getState("minecraft:pointed_dripstone[thickness=" + order[k] + ",vertical_direction=" + direction + "]"); } return arr; } - private static PlatformBlockState dripstoneBlock(int stack, int i, BlockFace direction) { + private static PlatformBlockState dripstoneBlock(int stack, int i, String direction) { int thIdx; if (i == stack - 1) { thIdx = 0; @@ -436,14 +429,14 @@ final class DecoratorCore { } else { thIdx = 2; } - if (direction == BlockFace.UP) { + if (direction.equals("up")) { if (dripstoneUp == null) { - dripstoneUp = buildDripstoneArr(BlockFace.UP); + dripstoneUp = buildDripstoneArr("up"); } return dripstoneUp[thIdx]; } if (dripstoneDown == null) { - dripstoneDown = buildDripstoneArr(BlockFace.DOWN); + dripstoneDown = buildDripstoneArr("down"); } return dripstoneDown[thIdx]; } diff --git a/core/src/main/java/art/arcane/iris/engine/framework/Engine.java b/core/src/main/java/art/arcane/iris/engine/framework/Engine.java index d7efdef97..ca80d0453 100644 --- a/core/src/main/java/art/arcane/iris/engine/framework/Engine.java +++ b/core/src/main/java/art/arcane/iris/engine/framework/Engine.java @@ -18,7 +18,6 @@ package art.arcane.iris.engine.framework; -import art.arcane.iris.platform.bukkit.BukkitBlockResolution; import art.arcane.iris.core.IrisSettings; import art.arcane.iris.engine.framework.render.RenderType; @@ -42,7 +41,7 @@ import art.arcane.volmlib.util.collection.KMap; import art.arcane.iris.util.project.context.ChunkContext; import art.arcane.iris.util.project.context.IrisContext; import art.arcane.iris.util.common.data.DataProvider; -import art.arcane.iris.util.common.data.IrisCustomData; +import art.arcane.iris.util.common.data.B; import art.arcane.volmlib.util.documentation.BlockCoordinates; import art.arcane.volmlib.util.documentation.ChunkCoordinates; import art.arcane.volmlib.util.function.Function2; @@ -61,7 +60,6 @@ import art.arcane.volmlib.util.scheduling.ChronoLatch; import art.arcane.iris.util.common.scheduling.J; import art.arcane.iris.util.project.stream.ProceduralStream; import org.bukkit.World; -import org.bukkit.block.data.BlockData; import org.jetbrains.annotations.Nullable; import java.awt.Color; @@ -303,11 +301,10 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat return; } - BlockData blockData = (BlockData) data.nativeHandle(); - if (BukkitBlockResolution.isUpdatable(blockData)) { + if (B.isUpdatable(data)) { getMantle().updateBlock(x, y, z); } - if (blockData instanceof IrisCustomData) { + if (data.isCustom()) { getMantle().getMantle().flag(x >> 4, z >> 4, MantleFlag.CUSTOM_ACTIVE, true); } } diff --git a/core/src/main/java/art/arcane/iris/engine/mantle/EngineMantle.java b/core/src/main/java/art/arcane/iris/engine/mantle/EngineMantle.java index 63c158e4b..9975b410e 100644 --- a/core/src/main/java/art/arcane/iris/engine/mantle/EngineMantle.java +++ b/core/src/main/java/art/arcane/iris/engine/mantle/EngineMantle.java @@ -45,9 +45,7 @@ import art.arcane.volmlib.util.matter.Matter; import art.arcane.volmlib.util.matter.slices.UpdateMatter; import art.arcane.iris.util.common.parallel.MultiBurst; import art.arcane.iris.util.common.scheduling.J; -import art.arcane.iris.platform.bukkit.BukkitBlockState; import art.arcane.iris.spi.PlatformBlockState; -import org.bukkit.block.data.BlockData; import org.jetbrains.annotations.UnmodifiableView; import java.util.List; @@ -119,10 +117,10 @@ public interface EngineMantle extends MatterGenerator { } default PlatformBlockState get(int x, int y, int z) { - BlockData block = getMantle().get(x, y, z, BlockData.class); + PlatformBlockState block = getMantle().get(x, y, z, PlatformBlockState.class); if (block == null) return AIR; - return BukkitBlockState.of(block); + return block; } default boolean isPreventingDecay() { @@ -209,14 +207,14 @@ public interface EngineMantle extends MatterGenerator { int rawUpper = upperCtx.getUpperSurfaceY(worldX, worldZ); upperYs[i] = Math.max(rawUpper, he + gap); } - chunk.iterate(BlockData.class, (lx, y, lz, value) -> { + chunk.iterate(PlatformBlockState.class, (lx, y, lz, value) -> { int colIdx = (lx << 4) | (lz & 15); if (y < upperYs[colIdx]) { - blocks.set(lx, y, lz, BukkitBlockState.of(value)); + blocks.set(lx, y, lz, value); } }); } else { - chunk.iterate(BlockData.class, (lx, y, lz, value) -> blocks.set(lx, y, lz, BukkitBlockState.of(value))); + chunk.iterate(PlatformBlockState.class, (lx, y, lz, value) -> blocks.set(lx, y, lz, value)); } } finally { chunk.release(); @@ -276,7 +274,7 @@ public interface EngineMantle extends MatterGenerator { MantleChunk chunk = getMantle().getChunk(x, z).use(); try { chunk.raiseFlagUnchecked(MantleFlag.CLEANED, () -> { - chunk.deleteSlices(BlockData.class); + chunk.deleteSlices(PlatformBlockState.class); chunk.deleteSlices(String.class); chunk.deleteSlices(TileWrapper.class); chunk.deleteSlices(Identifier.class); @@ -295,7 +293,7 @@ public interface EngineMantle extends MatterGenerator { MantleChunk chunk = getMantle().getChunk(x, z).use(); try { chunk.raiseFlagUnchecked(MantleFlag.CLEANED, () -> { - chunk.deleteSlices(BlockData.class); + chunk.deleteSlices(PlatformBlockState.class); chunk.deleteSlices(TileWrapper.class); chunk.deleteSlices(Identifier.class); chunk.deleteSlices(UpdateMatter.class); diff --git a/core/src/main/java/art/arcane/iris/engine/mantle/MantleWriter.java b/core/src/main/java/art/arcane/iris/engine/mantle/MantleWriter.java index b2c9abae1..875cf0639 100644 --- a/core/src/main/java/art/arcane/iris/engine/mantle/MantleWriter.java +++ b/core/src/main/java/art/arcane/iris/engine/mantle/MantleWriter.java @@ -18,7 +18,6 @@ package art.arcane.iris.engine.mantle; -import art.arcane.iris.platform.bukkit.BukkitBlockResolution; import art.arcane.iris.spi.IrisLogging; import art.arcane.iris.util.project.matter.TileWrapper; @@ -48,7 +47,7 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import lombok.Data; import art.arcane.iris.platform.bukkit.BukkitBlockState; import art.arcane.iris.spi.PlatformBlockState; -import org.bukkit.block.data.BlockData; +import art.arcane.iris.util.common.data.B; import org.bukkit.util.Vector; import java.util.*; @@ -166,7 +165,7 @@ public class MantleWriter implements IObjectPlacer, AutoCloseable { return; } - if (y == 0 && t instanceof BlockData && engineMantle.getEngine().getDimension().isBedrock()) { + if (y == 0 && t instanceof PlatformBlockState && engineMantle.getEngine().getDimension().isBedrock()) { return; } @@ -174,7 +173,8 @@ public class MantleWriter implements IObjectPlacer, AutoCloseable { if (chunk == null) return; Matter matter = chunk.getOrCreate(y >> 4); - matter.slice(matter.getClass(t)).set(x & 15, y & 15, z & 15, t); + Class sliceType = t instanceof PlatformBlockState ? PlatformBlockState.class : matter.getClass(t); + matter.slice(sliceType).set(x & 15, y & 15, z & 15, t); } public boolean setDataIfAbsent(int x, int y, int z, MatterCavern value) { @@ -220,7 +220,7 @@ public class MantleWriter implements IObjectPlacer, AutoCloseable { if (matter == null) { return; } - matter.slice(BlockData.class).set(x & 15, y & 15, z & 15, null); + matter.slice(PlatformBlockState.class).set(x & 15, y & 15, z & 15, null); } public T getData(int x, int y, int z, Class type) { @@ -273,19 +273,20 @@ public class MantleWriter implements IObjectPlacer, AutoCloseable { if (s == null) { return; } - BlockData d = (BlockData) s.nativeHandle(); - if (d instanceof IrisCustomData data) { - setData(x, y, z, data.getBase()); + if (s.isCustom() && s.nativeHandle() instanceof IrisCustomData data) { + setData(x, y, z, BukkitBlockState.of(data.getBase())); setData(x, y, z, data.getCustom()); - } else setData(x, y, z, d); + return; + } + setData(x, y, z, s); } @Override public PlatformBlockState get(int x, int y, int z) { - BlockData block = getData(x, y, z, BlockData.class); + PlatformBlockState block = getData(x, y, z, PlatformBlockState.class); if (block == null) return AIR; - return BukkitBlockState.of(block); + return block; } @Override @@ -300,7 +301,7 @@ public class MantleWriter implements IObjectPlacer, AutoCloseable { @Override public boolean isSolid(int x, int y, int z) { - return BukkitBlockResolution.isSolid((BlockData) get(x, y, z).nativeHandle()); + return B.isSolid(get(x, y, z)); } @Override diff --git a/core/src/main/java/art/arcane/iris/engine/mantle/components/MantleFloatingObjectComponent.java b/core/src/main/java/art/arcane/iris/engine/mantle/components/MantleFloatingObjectComponent.java index f36a56c43..b6b95865b 100644 --- a/core/src/main/java/art/arcane/iris/engine/mantle/components/MantleFloatingObjectComponent.java +++ b/core/src/main/java/art/arcane/iris/engine/mantle/components/MantleFloatingObjectComponent.java @@ -18,8 +18,8 @@ package art.arcane.iris.engine.mantle.components; -import art.arcane.iris.platform.bukkit.BukkitBlockResolution; +import art.arcane.iris.util.common.data.B; import art.arcane.iris.core.loader.IrisData; import art.arcane.iris.engine.IrisComplex; import art.arcane.iris.engine.data.cache.Cache; @@ -37,9 +37,9 @@ import art.arcane.iris.engine.object.IrisObject; import art.arcane.iris.engine.object.IrisObjectPlacement; import art.arcane.iris.engine.object.IrisObjectRotation; import art.arcane.iris.engine.object.IrisObjectTranslate; +import art.arcane.iris.engine.object.IrisProceduralBlocks; import art.arcane.iris.engine.object.ObjectPlaceMode; import art.arcane.iris.spi.IrisLogging; -import art.arcane.iris.util.common.data.IrisCustomData; import art.arcane.iris.util.common.math.IrisBlockVector; import art.arcane.iris.util.project.context.ChunkContext; import art.arcane.volmlib.util.collection.KList; @@ -47,8 +47,6 @@ import art.arcane.volmlib.util.documentation.ChunkCoordinates; import art.arcane.volmlib.util.mantle.flag.ReservedFlag; import art.arcane.volmlib.util.math.RNG; import art.arcane.iris.spi.PlatformBlockState; -import org.bukkit.Material; -import org.bukkit.block.data.BlockData; import java.io.File; import java.util.HashSet; @@ -451,12 +449,11 @@ public class MantleFloatingObjectComponent extends IrisMantleComponent { if (state == null) { return false; } - BlockData data = (BlockData) state.nativeHandle(); PlatformBlockState existingState = placer.get(x, y, z); - BlockData existing = existingState == null ? null : (BlockData) existingState.nativeHandle(); - boolean wouldReplace = existing != null && BukkitBlockResolution.isSolid(existing) && BukkitBlockResolution.isVineBlock(data); - boolean placesBlock = !data.getMaterial().equals(Material.AIR) && !data.getMaterial().equals(Material.CAVE_AIR) && !wouldReplace; - return data instanceof IrisCustomData || placesBlock; + boolean wouldReplace = B.isSolid(existingState) && B.isVineBlock(state); + String material = IrisProceduralBlocks.materialKey(state); + boolean placesBlock = !material.equals("minecraft:air") && !material.equals("minecraft:cave_air") && !wouldReplace; + return state.isCustom() || placesBlock; } private static boolean isFootprintFlat(FloatingObjectFootprint fp, int pickedXf, int pickedZf, int pickTopY, FloatingIslandSample[] samples, int tolerance) { diff --git a/core/src/main/java/art/arcane/iris/engine/mantle/components/MantleObjectComponent.java b/core/src/main/java/art/arcane/iris/engine/mantle/components/MantleObjectComponent.java index 06bdeb876..7b96ce15f 100644 --- a/core/src/main/java/art/arcane/iris/engine/mantle/components/MantleObjectComponent.java +++ b/core/src/main/java/art/arcane/iris/engine/mantle/components/MantleObjectComponent.java @@ -18,9 +18,9 @@ package art.arcane.iris.engine.mantle.components; -import art.arcane.iris.platform.bukkit.BukkitBlockResolution; import art.arcane.iris.core.IrisSettings; +import art.arcane.iris.util.common.data.B; import art.arcane.iris.engine.data.cache.Cache; import art.arcane.iris.engine.IrisComplex; import art.arcane.iris.engine.UpperDimensionContext; @@ -50,7 +50,6 @@ import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import art.arcane.iris.spi.PlatformBlockState; import art.arcane.iris.util.common.math.IrisBlockVector; -import org.bukkit.block.data.BlockData; import java.io.IOException; import java.util.Locale; @@ -584,7 +583,7 @@ public class MantleObjectComponent extends IrisMantleComponent { if (marker != null) { writer.setData(b.getX(), b.getY(), b.getZ(), marker); } - if (effectivePlacement.isDolphinTarget() && effectivePlacement.isUnderwater() && BukkitBlockResolution.isStorageChest(unwrap(data))) { + if (effectivePlacement.isDolphinTarget() && effectivePlacement.isUnderwater() && B.isStorageChest(data)) { writer.setData(b.getX(), b.getY(), b.getZ(), MatterStructurePOI.BURIED_TREASURE); } }, null, getData()); @@ -599,7 +598,7 @@ public class MantleObjectComponent extends IrisMantleComponent { if (marker != null) { writer.setData(b.getX(), b.getY(), b.getZ(), marker); } - if (effectivePlacement.isDolphinTarget() && effectivePlacement.isUnderwater() && BukkitBlockResolution.isStorageChest(unwrap(data))) { + if (effectivePlacement.isDolphinTarget() && effectivePlacement.isUnderwater() && B.isStorageChest(data)) { writer.setData(b.getX(), b.getY(), b.getZ(), MatterStructurePOI.BURIED_TREASURE); } }, null, getData()); @@ -611,7 +610,7 @@ public class MantleObjectComponent extends IrisMantleComponent { if (marker != null) { writer.setData(b.getX(), b.getY(), b.getZ(), marker); } - if (effectivePlacement.isDolphinTarget() && effectivePlacement.isUnderwater() && BukkitBlockResolution.isStorageChest(unwrap(data))) { + if (effectivePlacement.isDolphinTarget() && effectivePlacement.isUnderwater() && B.isStorageChest(data)) { writer.setData(b.getX(), b.getY(), b.getZ(), MatterStructurePOI.BURIED_TREASURE); } }, null, getData()); @@ -808,7 +807,7 @@ public class MantleObjectComponent extends IrisMantleComponent { if (marker != null) { writer.setData(b.getX(), b.getY(), b.getZ(), marker); } - if (effectivePlacement.isDolphinTarget() && effectivePlacement.isUnderwater() && BukkitBlockResolution.isStorageChest(unwrap(data))) { + if (effectivePlacement.isDolphinTarget() && effectivePlacement.isUnderwater() && B.isStorageChest(data)) { writer.setData(b.getX(), b.getY(), b.getZ(), MatterStructurePOI.BURIED_TREASURE); } }, null, getData()); @@ -988,7 +987,7 @@ public class MantleObjectComponent extends IrisMantleComponent { if (marker != null) { writer.setData(b.getX(), b.getY(), b.getZ(), marker); } - if (placement.isDolphinTarget() && placement.isUnderwater() && BukkitBlockResolution.isStorageChest(unwrap(data))) { + if (placement.isDolphinTarget() && placement.isUnderwater() && B.isStorageChest(data)) { writer.setData(b.getX(), b.getY(), b.getZ(), MatterStructurePOI.BURIED_TREASURE); } }, null, getData()); @@ -1496,10 +1495,6 @@ public class MantleObjectComponent extends IrisMantleComponent { && IrisSettings.get().getGeneral().isDebug(); } - private static BlockData unwrap(PlatformBlockState state) { - return state == null ? null : (BlockData) state.nativeHandle(); - } - private record ObjectPlacementSummary( int biomeSurfacePlacersChecked, int biomeSurfacePlacersTriggered, @@ -1624,7 +1619,11 @@ public class MantleObjectComponent extends IrisMantleComponent { if (placement == null) { continue; } - for (IrisObject variant : placement.getVariantObjects(getData())) { + KList variants = placement.getVariantObjects(getData()); + if (variants == null) { + continue; + } + for (IrisObject variant : variants) { if (variant == null) { continue; } diff --git a/core/src/main/java/art/arcane/iris/engine/modifier/IrisDepositModifier.java b/core/src/main/java/art/arcane/iris/engine/modifier/IrisDepositModifier.java index 8b29aace2..e132f7a14 100644 --- a/core/src/main/java/art/arcane/iris/engine/modifier/IrisDepositModifier.java +++ b/core/src/main/java/art/arcane/iris/engine/modifier/IrisDepositModifier.java @@ -18,8 +18,6 @@ package art.arcane.iris.engine.modifier; -import art.arcane.iris.platform.bukkit.BukkitBlockResolution; - import art.arcane.iris.engine.framework.Engine; import art.arcane.iris.engine.framework.EngineAssignedModifier; import art.arcane.iris.engine.object.*; @@ -31,10 +29,8 @@ import art.arcane.volmlib.util.math.RNG; import art.arcane.volmlib.util.matter.MatterCavern; import art.arcane.iris.util.common.parallel.BurstExecutor; import art.arcane.volmlib.util.scheduling.PrecisionStopwatch; -import art.arcane.iris.platform.bukkit.BukkitBlockState; import art.arcane.iris.spi.PlatformBlockState; -import org.bukkit.Material; -import org.bukkit.block.data.BlockData; +import art.arcane.iris.util.common.data.B; public class IrisDepositModifier extends EngineAssignedModifier { private final RNG rng; @@ -132,7 +128,7 @@ public class IrisDepositModifier extends EngineAssignedModifier height || nx > 15 || nx < 0 || ny > getEngine().getHeight() || ny < 0 || nz < 0 || nz > 15) { continue; } - if (!k.isReplaceBedrock() && ((BlockData) data.get(nx, ny, nz).nativeHandle()).getMaterial() == Material.BEDROCK) { + if (!k.isReplaceBedrock() && IrisProceduralBlocks.materialKey(data.get(nx, ny, nz)).equals("minecraft:bedrock")) { continue; } @@ -141,7 +137,7 @@ public class IrisDepositModifier extends EngineAssignedModifier= 0; k--) { PlatformBlockState b = output.get(finalI, k, j); - BlockData rawB = unwrap(b); - boolean now = b != null && !(BukkitBlockResolution.isAir(rawB) || BukkitBlockResolution.isFluid(rawB)); + boolean now = b != null && !(B.isAir(b) || B.isFluid(b)); if (now != inside) { inside = now; @@ -135,17 +131,16 @@ public class IrisPerfectionModifier extends EngineAssignedModifier if (g >= 4) { PlatformBlockState bcState = getPostBlock(x, h, z, currentPostX, currentPostZ, currentData); PlatformBlockState bState = getPostBlock(x, h + 1, z, currentPostX, currentPostZ, currentData); - BlockData b = (BlockData) bState.nativeHandle(); - Material m = ((BlockData) bcState.nativeHandle()).getMaterial(); - if ((b.getMaterial().isOccluding() && b.getMaterial().isSolid())) { - if (m.isSolid()) { + if (bState.isOccluding() && bState.isSolid()) { + if (bcState.isSolid()) { setPostBlock(x, h, z, bState, currentPostX, currentPostZ, currentData); h--; } @@ -128,15 +118,15 @@ public class IrisPostModifier extends EngineAssignedModifier g += hd == h + 1 ? 1 : 0; if (g >= 4) { - BlockData ba = (BlockData) getPostBlock(x, ha, z, currentPostX, currentPostZ, currentData).nativeHandle(); - BlockData bb = (BlockData) getPostBlock(x, hb, z, currentPostX, currentPostZ, currentData).nativeHandle(); - BlockData bc = (BlockData) getPostBlock(x, hc, z, currentPostX, currentPostZ, currentData).nativeHandle(); - BlockData bd = (BlockData) getPostBlock(x, hd, z, currentPostX, currentPostZ, currentData).nativeHandle(); + PlatformBlockState ba = getPostBlock(x, ha, z, currentPostX, currentPostZ, currentData); + PlatformBlockState bb = getPostBlock(x, hb, z, currentPostX, currentPostZ, currentData); + PlatformBlockState bc = getPostBlock(x, hc, z, currentPostX, currentPostZ, currentData); + PlatformBlockState bd = getPostBlock(x, hd, z, currentPostX, currentPostZ, currentData); g = 0; - g = BukkitBlockResolution.isSolid(ba) ? g + 1 : g; - g = BukkitBlockResolution.isSolid(bb) ? g + 1 : g; - g = BukkitBlockResolution.isSolid(bc) ? g + 1 : g; - g = BukkitBlockResolution.isSolid(bd) ? g + 1 : g; + g = B.isSolid(ba) ? g + 1 : g; + g = B.isSolid(bb) ? g + 1 : g; + g = B.isSolid(bc) ? g + 1 : g; + g = B.isSolid(bd) ? g + 1 : g; if (g >= 3) { setPostBlock(x, h + 1, z, getPostBlock(x, h, z, currentPostX, currentPostZ, currentData), currentPostX, currentPostZ, currentData); @@ -187,10 +177,9 @@ public class IrisPostModifier extends EngineAssignedModifier PlatformBlockState d = sc.isValid(getComplex().getSlopeStream().get(x, z)) ? biome.getSlab().get(rng, x, h, z, getData()) : null; if (d != null) { - BlockData rawD = (BlockData) d.nativeHandle(); - boolean cancel = BukkitBlockResolution.isAir(rawD); + boolean cancel = B.isAir(d); - if (rawD.getMaterial().equals(Material.SNOW) && h + 1 <= getDimension().getFluidHeight()) { + if (IrisProceduralBlocks.materialKey(d).equals("minecraft:snow") && h + 1 <= getDimension().getFluidHeight()) { cancel = true; } @@ -207,11 +196,9 @@ public class IrisPostModifier extends EngineAssignedModifier } // Waterlogging - BlockData b = (BlockData) getPostBlock(x, h, z, currentPostX, currentPostZ, currentData).nativeHandle(); + PlatformBlockState b = getPostBlock(x, h, z, currentPostX, currentPostZ, currentData); - if (b instanceof Waterlogged) { - BlockData cloned = b.clone(); - Waterlogged ww = (Waterlogged) cloned; + if (IrisProceduralBlocks.hasProperty(b, "waterlogged")) { boolean w = false; if (h <= getDimension().getFluidHeight() + 1) { @@ -222,90 +209,88 @@ public class IrisPostModifier extends EngineAssignedModifier } } - if (w != ww.isWaterlogged()) { - ww.setWaterlogged(w); - setPostBlock(x, h, z, BukkitBlockState.of(cloned), currentPostX, currentPostZ, currentData); + if (w != "true".equals(IrisProceduralBlocks.propertyValue(b, "waterlogged"))) { + setPostBlock(x, h, z, b.withProperty("waterlogged", String.valueOf(w)), currentPostX, currentPostZ, currentData); } - } else if (b.getMaterial().equals(Material.AIR) && h <= getDimension().getFluidHeight()) { + } else if (IrisProceduralBlocks.materialKey(b).equals("minecraft:air") && h <= getDimension().getFluidHeight()) { if ((isWaterOrWaterlogged(x + 1, h, z, currentPostX, currentPostZ, currentData) || isWaterOrWaterlogged(x - 1, h, z, currentPostX, currentPostZ, currentData) || isWaterOrWaterlogged(x, h, z + 1, currentPostX, currentPostZ, currentData) || isWaterOrWaterlogged(x, h, z - 1, currentPostX, currentPostZ, currentData))) { setPostBlock(x, h, z, States.WATER, currentPostX, currentPostZ, currentData); } } // Foliage - b = (BlockData) getPostBlock(x, h + 1, z, currentPostX, currentPostZ, currentData).nativeHandle(); + b = getPostBlock(x, h + 1, z, currentPostX, currentPostZ, currentData); - if (BukkitBlockResolution.isVineBlock(b) && b instanceof MultipleFacing) { - BlockData cloned = b.clone(); - MultipleFacing f = (MultipleFacing) cloned; + if (B.isVineBlock(b)) { + PlatformBlockState result = b; int finalH = h + 1; - f.getAllowedFaces().forEach(face -> { - BlockData d = (BlockData) getPostBlock(x + face.getModX(), finalH + face.getModY(), z + face.getModZ(), currentPostX, currentPostZ, currentData).nativeHandle(); - f.setFace(face, !BukkitBlockResolution.isAir(d) && !BukkitBlockResolution.isVineBlock(d)); - }); - if (!f.equals(b)) { - setPostBlock(x, h + 1, z, BukkitBlockState.of(cloned), currentPostX, currentPostZ, currentData); + for (String face : IrisProceduralBlocks.FACE_PROPERTIES) { + if (!IrisProceduralBlocks.hasProperty(b, face)) { + continue; + } + int[] mod = IrisProceduralBlocks.faceOffset(face); + PlatformBlockState d = getPostBlock(x + mod[0], finalH + mod[1], z + mod[2], currentPostX, currentPostZ, currentData); + result = result.withProperty(face, String.valueOf(!B.isAir(d) && !B.isVineBlock(d))); + } + if (!result.equals(b)) { + setPostBlock(x, h + 1, z, result, currentPostX, currentPostZ, currentData); } } - if (BukkitBlockResolution.isFoliage(b) || b.getMaterial().equals(Material.DEAD_BUSH)) { - Material onto = ((BlockData) getPostBlock(x, h, z, currentPostX, currentPostZ, currentData).nativeHandle()).getMaterial(); + if (B.isFoliage(b) || IrisProceduralBlocks.materialKey(b).equals("minecraft:dead_bush")) { + PlatformBlockState onto = getPostBlock(x, h, z, currentPostX, currentPostZ, currentData); - if (!BukkitBlockResolution.canPlaceOnto(b.getMaterial(), onto) && !BukkitBlockResolution.isDecorant(b)) { + if (!B.canPlaceOnto(b, onto) && !B.isDecorant(b)) { setPostBlock(x, h + 1, z, States.AIR, currentPostX, currentPostZ, currentData); } } } public boolean isAir(int x, int y, int z, int currentPostX, int currentPostZ, Hunk currentData) { - BlockData d = (BlockData) getPostBlock(x, y, z, currentPostX, currentPostZ, currentData).nativeHandle(); - return d.getMaterial().equals(Material.AIR) || d.getMaterial().equals(Material.CAVE_AIR); + String material = IrisProceduralBlocks.materialKey(getPostBlock(x, y, z, currentPostX, currentPostZ, currentData)); + return material.equals("minecraft:air") || material.equals("minecraft:cave_air"); } public boolean hasGravity(int x, int y, int z, int currentPostX, int currentPostZ, Hunk currentData) { - BlockData d = (BlockData) getPostBlock(x, y, z, currentPostX, currentPostZ, currentData).nativeHandle(); - return d.getMaterial().equals(Material.SAND) || d.getMaterial().equals(Material.RED_SAND) || d.getMaterial().equals(Material.BLACK_CONCRETE_POWDER) || d.getMaterial().equals(Material.BLUE_CONCRETE_POWDER) || d.getMaterial().equals(Material.BROWN_CONCRETE_POWDER) || d.getMaterial().equals(Material.CYAN_CONCRETE_POWDER) || d.getMaterial().equals(Material.GRAY_CONCRETE_POWDER) || d.getMaterial().equals(Material.GREEN_CONCRETE_POWDER) || d.getMaterial().equals(Material.LIGHT_BLUE_CONCRETE_POWDER) || d.getMaterial().equals(Material.LIGHT_GRAY_CONCRETE_POWDER) || d.getMaterial().equals(Material.LIME_CONCRETE_POWDER) || d.getMaterial().equals(Material.MAGENTA_CONCRETE_POWDER) || d.getMaterial().equals(Material.ORANGE_CONCRETE_POWDER) || d.getMaterial().equals(Material.PINK_CONCRETE_POWDER) || d.getMaterial().equals(Material.PURPLE_CONCRETE_POWDER) || d.getMaterial().equals(Material.RED_CONCRETE_POWDER) || d.getMaterial().equals(Material.WHITE_CONCRETE_POWDER) || d.getMaterial().equals(Material.YELLOW_CONCRETE_POWDER); + String material = IrisProceduralBlocks.materialKey(getPostBlock(x, y, z, currentPostX, currentPostZ, currentData)); + return material.equals("minecraft:sand") || material.equals("minecraft:red_sand") || material.endsWith("_concrete_powder"); } public boolean isSolid(int x, int y, int z, int currentPostX, int currentPostZ, Hunk currentData) { - BlockData d = (BlockData) getPostBlock(x, y, z, currentPostX, currentPostZ, currentData).nativeHandle(); - return d.getMaterial().isSolid() && !BukkitBlockResolution.isVineBlock(d); + PlatformBlockState d = getPostBlock(x, y, z, currentPostX, currentPostZ, currentData); + return B.isSolid(d) && !B.isVineBlock(d); } public boolean isSolidNonSlab(int x, int y, int z, int currentPostX, int currentPostZ, Hunk currentData) { - BlockData d = (BlockData) getPostBlock(x, y, z, currentPostX, currentPostZ, currentData).nativeHandle(); - return d.getMaterial().isSolid() && !(d instanceof Slab); + PlatformBlockState d = getPostBlock(x, y, z, currentPostX, currentPostZ, currentData); + return B.isSolid(d) && !IrisProceduralBlocks.materialKey(d).endsWith("_slab"); } public boolean isAirOrWater(int x, int y, int z, int currentPostX, int currentPostZ, Hunk currentData) { - BlockData d = (BlockData) getPostBlock(x, y, z, currentPostX, currentPostZ, currentData).nativeHandle(); - return d.getMaterial().equals(Material.WATER) || d.getMaterial().equals(Material.AIR) || d.getMaterial().equals(Material.CAVE_AIR); + String material = IrisProceduralBlocks.materialKey(getPostBlock(x, y, z, currentPostX, currentPostZ, currentData)); + return material.equals("minecraft:water") || material.equals("minecraft:air") || material.equals("minecraft:cave_air"); } public boolean isSlab(int x, int y, int z, int currentPostX, int currentPostZ, Hunk currentData) { - BlockData d = (BlockData) getPostBlock(x, y, z, currentPostX, currentPostZ, currentData).nativeHandle(); - return d instanceof Slab; + return IrisProceduralBlocks.materialKey(getPostBlock(x, y, z, currentPostX, currentPostZ, currentData)).endsWith("_slab"); } public boolean isSnowLayer(int x, int y, int z, int currentPostX, int currentPostZ, Hunk currentData) { - BlockData d = (BlockData) getPostBlock(x, y, z, currentPostX, currentPostZ, currentData).nativeHandle(); - return d.getMaterial().equals(Material.SNOW); + return IrisProceduralBlocks.materialKey(getPostBlock(x, y, z, currentPostX, currentPostZ, currentData)).equals("minecraft:snow"); } public boolean isWater(int x, int y, int z, int currentPostX, int currentPostZ, Hunk currentData) { - BlockData d = (BlockData) getPostBlock(x, y, z, currentPostX, currentPostZ, currentData).nativeHandle(); - return d.getMaterial().equals(Material.WATER); + return IrisProceduralBlocks.materialKey(getPostBlock(x, y, z, currentPostX, currentPostZ, currentData)).equals("minecraft:water"); } public boolean isWaterOrWaterlogged(int x, int y, int z, int currentPostX, int currentPostZ, Hunk currentData) { - BlockData d = (BlockData) getPostBlock(x, y, z, currentPostX, currentPostZ, currentData).nativeHandle(); - return d.getMaterial().equals(Material.WATER) || (d instanceof Waterlogged && ((Waterlogged) d).isWaterlogged()); + PlatformBlockState d = getPostBlock(x, y, z, currentPostX, currentPostZ, currentData); + return IrisProceduralBlocks.materialKey(d).equals("minecraft:water") || "true".equals(IrisProceduralBlocks.propertyValue(d, "waterlogged")); } public boolean isLiquid(int x, int y, int z, int currentPostX, int currentPostZ, Hunk currentData) { - BlockData d = (BlockData) getPostBlock(x, y, z, currentPostX, currentPostZ, currentData).nativeHandle(); - return d instanceof Levelled; + return IrisProceduralBlocks.hasProperty(getPostBlock(x, y, z, currentPostX, currentPostZ, currentData), "level"); } public void setPostBlock(int x, int y, int z, PlatformBlockState d, int currentPostX, int currentPostZ, Hunk currentData) { diff --git a/core/src/main/java/art/arcane/iris/engine/object/BlockDataMergeSupport.java b/core/src/main/java/art/arcane/iris/engine/object/BlockDataMergeSupport.java index 4c1867062..db9e60a52 100644 --- a/core/src/main/java/art/arcane/iris/engine/object/BlockDataMergeSupport.java +++ b/core/src/main/java/art/arcane/iris/engine/object/BlockDataMergeSupport.java @@ -8,14 +8,46 @@ import org.bukkit.block.data.BlockData; import java.util.function.Function; final class BlockDataMergeSupport { + private static final boolean BUKKIT_PRESENT = detectBukkit(); + private BlockDataMergeSupport() { } + private static boolean detectBukkit() { + try { + Class.forName("org.bukkit.Bukkit", false, BlockDataMergeSupport.class.getClassLoader()); + return true; + } catch (ClassNotFoundException e) { + return false; + } + } + static PlatformBlockState merge(PlatformBlockState base, PlatformBlockState update) { + if (!BUKKIT_PRESENT) { + return mergeByKey(base, update); + } BlockData merged = merge((BlockData) base.nativeHandle(), (BlockData) update.nativeHandle(), BukkitBlockResolution::get); return merged == null ? null : BukkitBlockState.of(merged); } + private static PlatformBlockState mergeByKey(PlatformBlockState base, PlatformBlockState update) { + String key = update.key(); + int bracket = key.indexOf('['); + if (bracket < 0) { + return base; + } + PlatformBlockState merged = base; + String body = key.substring(bracket + 1, key.lastIndexOf(']')); + for (String entry : body.split(",")) { + int equals = entry.indexOf('='); + if (equals < 0) { + continue; + } + merged = merged.withProperty(entry.substring(0, equals).trim(), entry.substring(equals + 1).trim()); + } + return merged; + } + static BlockData merge(BlockData base, BlockData update, Function resolver) { try { return base.merge(update); diff --git a/core/src/main/java/art/arcane/iris/engine/object/IrisBlockData.java b/core/src/main/java/art/arcane/iris/engine/object/IrisBlockData.java index 7035c7416..b55577fcb 100644 --- a/core/src/main/java/art/arcane/iris/engine/object/IrisBlockData.java +++ b/core/src/main/java/art/arcane/iris/engine/object/IrisBlockData.java @@ -146,18 +146,13 @@ public class IrisBlockData extends IrisRegistrant { public PlatformBlockState getBlockData(IrisData data) { return blockdata.aquire(() -> { - BlockData b = null; - IrisBlockData customData = data.getBlockLoader().load(getBlock(), false); if (customData != null) { PlatformBlockState customState = customData.getBlockData(data); - b = customState == null ? null : (BlockData) customState.nativeHandle(); - if (b != null) { - b = b.clone(); - - String st = b.getAsString(true); + if (customState != null) { + String st = customState.key(); if (st.contains("[")) { st = st.split("\\Q[\\E")[0]; @@ -175,27 +170,25 @@ public class IrisBlockData extends IrisRegistrant { IrisLogging.debug("Block Data used " + sx + " (CUSTOM)"); } - BlockData bx = BukkitBlockResolution.get(sx); + PlatformBlockState bx = B.getState(sx); if (bx != null) { - return BukkitBlockState.of(bx); + return bx; } - if (b != null) { - return BukkitBlockState.of(b); - } + return customState; } } String ss = keyify(getBlock()) + computeProperties(); - b = BukkitBlockResolution.get(ss); + PlatformBlockState resolved = B.getState(ss); if (debug) { IrisLogging.debug("Block Data used " + ss); } - if (b != null) { - return BukkitBlockState.of(b); + if (resolved != null) { + return resolved; } if (backup != null) { diff --git a/core/src/main/java/art/arcane/iris/engine/object/IrisCoral.java b/core/src/main/java/art/arcane/iris/engine/object/IrisCoral.java index 90ded30fb..0ab933dcc 100644 --- a/core/src/main/java/art/arcane/iris/engine/object/IrisCoral.java +++ b/core/src/main/java/art/arcane/iris/engine/object/IrisCoral.java @@ -208,7 +208,7 @@ public class IrisCoral implements IrisProceduralPlacement { public IrisObject getVariantObject(IrisData data, RNG rng) { KList baked = getVariantObjects(data); - if (baked.isEmpty()) { + if (baked == null || baked.isEmpty()) { return null; } return baked.get(rng.i(baked.size())); diff --git a/core/src/main/java/art/arcane/iris/engine/object/IrisCrystal.java b/core/src/main/java/art/arcane/iris/engine/object/IrisCrystal.java index bd8810c0c..7ee29c393 100644 --- a/core/src/main/java/art/arcane/iris/engine/object/IrisCrystal.java +++ b/core/src/main/java/art/arcane/iris/engine/object/IrisCrystal.java @@ -187,7 +187,7 @@ public class IrisCrystal implements IrisProceduralPlacement { public IrisObject getVariantObject(IrisData data, RNG rng) { KList baked = getVariantObjects(data); - if (baked.isEmpty()) { + if (baked == null || baked.isEmpty()) { return null; } return baked.get(rng.i(baked.size())); diff --git a/core/src/main/java/art/arcane/iris/engine/object/IrisDepositVariant.java b/core/src/main/java/art/arcane/iris/engine/object/IrisDepositVariant.java index 459808e57..5facf11c2 100644 --- a/core/src/main/java/art/arcane/iris/engine/object/IrisDepositVariant.java +++ b/core/src/main/java/art/arcane/iris/engine/object/IrisDepositVariant.java @@ -18,8 +18,6 @@ package art.arcane.iris.engine.object; -import art.arcane.iris.platform.bukkit.BukkitBlockResolution; - import art.arcane.iris.core.loader.IrisData; import art.arcane.iris.engine.data.cache.AtomicCache; import art.arcane.iris.engine.object.annotations.Desc; @@ -31,11 +29,9 @@ import art.arcane.volmlib.util.collection.KMap; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import art.arcane.iris.platform.bukkit.BukkitBlockState; import art.arcane.iris.spi.PlatformBlockState; +import art.arcane.iris.util.common.data.B; import lombok.experimental.Accessors; -import org.bukkit.Material; -import org.bukkit.block.data.BlockData; @Snippet("deposit-variant") @Accessors(chain = true) @@ -44,7 +40,7 @@ import org.bukkit.block.data.BlockData; @Desc("Remaps ore block ids to alternate block ids within a vertical band. Ores declared at dimension, region, and biome scope can be rewritten at placement time (for example, iron_ore -> deepslate_iron_ore inside a deep carving band, or yourmod:iron -> yourmod:moon_iron inside a lunar biome).") @Data public class IrisDepositVariant { - private final transient AtomicCache> resolved = new AtomicCache<>(); + private final transient AtomicCache> resolved = new AtomicCache<>(); @Required @MinNumber(-2048) @@ -67,23 +63,22 @@ public class IrisDepositVariant { return null; } - KMap map = resolved.aquire(() -> buildResolved(rdata)); - BlockData target = map.get(((BlockData) ore.nativeHandle()).getMaterial()); - return target == null ? null : BukkitBlockState.of(target); + KMap map = resolved.aquire(() -> buildResolved(rdata)); + return map.get(IrisProceduralBlocks.materialKey(ore)); } - private KMap buildResolved(IrisData rdata) { - KMap out = new KMap<>(); + private KMap buildResolved(IrisData rdata) { + KMap out = new KMap<>(); for (java.util.Map.Entry entry : remap.entrySet()) { - BlockData source = BukkitBlockResolution.getOrNull(entry.getKey(), false); - BlockData target = BukkitBlockResolution.getOrNull(entry.getValue(), true); + PlatformBlockState source = B.getStateOrNull(entry.getKey(), false); + PlatformBlockState target = B.getStateOrNull(entry.getValue(), true); if (source == null || target == null) { continue; } - out.put(source.getMaterial(), target); + out.put(IrisProceduralBlocks.materialKey(source), target); } return out; diff --git a/core/src/main/java/art/arcane/iris/engine/object/IrisEntity.java b/core/src/main/java/art/arcane/iris/engine/object/IrisEntity.java index 7ffcab8f8..d36c13098 100644 --- a/core/src/main/java/art/arcane/iris/engine/object/IrisEntity.java +++ b/core/src/main/java/art/arcane/iris/engine/object/IrisEntity.java @@ -72,10 +72,10 @@ import static art.arcane.iris.util.common.data.registry.Particles.ITEM; public class IrisEntity extends IrisRegistrant { @Required @Desc("The type of entity to spawn. To spawn a mythic mob, set this type to unknown and define mythic type.") - private EntityType type = EntityType.UNKNOWN; + private EntityType type = null; @Desc("The SpawnReason to spawn the entity with.") - private CreatureSpawnEvent.SpawnReason reason = CreatureSpawnEvent.SpawnReason.NATURAL; + private CreatureSpawnEvent.SpawnReason reason = null; @Desc("The custom name of this entity") private String customName = ""; @@ -146,10 +146,10 @@ public class IrisEntity extends IrisRegistrant { private boolean spawnEffectRiseOutOfGround = false; @Desc("The main gene for a panda if the entity type is a panda") - private Gene pandaMainGene = Gene.NORMAL; + private Gene pandaMainGene = null; @Desc("The hidden gene for a panda if the entity type is a panda") - private Gene pandaHiddenGene = Gene.NORMAL; + private Gene pandaHiddenGene = null; @Desc("The this entity is ageable, set it's baby status") private boolean baby = false; @@ -171,6 +171,22 @@ public class IrisEntity extends IrisRegistrant { @Desc("Run raw commands when this entity is spawned. Use {x}, {y}, and {z} for location. /summon pig {x} {y} {z}") private KList rawCommands = new KList<>(); + public EntityType getType() { + return type == null ? EntityType.UNKNOWN : type; + } + + public CreatureSpawnEvent.SpawnReason getReason() { + return reason == null ? CreatureSpawnEvent.SpawnReason.NATURAL : reason; + } + + public Gene getPandaMainGene() { + return pandaMainGene == null ? Gene.NORMAL : pandaMainGene; + } + + public Gene getPandaHiddenGene() { + return pandaHiddenGene == null ? Gene.NORMAL : pandaHiddenGene; + } + public Entity spawn(Engine gen, Location at) { return spawn(gen, at, new RNG(at.hashCode())); } @@ -385,11 +401,7 @@ public class IrisEntity extends IrisRegistrant { return null; } - if (type == null) { - return null; - } - - if (EntityType.UNKNOWN.equals(type) && !isSpecialType()) { + if (EntityType.UNKNOWN.equals(getType()) && !isSpecialType()) { return null; } diff --git a/core/src/main/java/art/arcane/iris/engine/object/IrisFormation.java b/core/src/main/java/art/arcane/iris/engine/object/IrisFormation.java index b2366ef11..da8b4a518 100644 --- a/core/src/main/java/art/arcane/iris/engine/object/IrisFormation.java +++ b/core/src/main/java/art/arcane/iris/engine/object/IrisFormation.java @@ -212,7 +212,7 @@ public class IrisFormation implements IrisProceduralPlacement { public IrisObject getVariantObject(IrisData data, RNG rng) { KList baked = getVariantObjects(data); - if (baked.isEmpty()) { + if (baked == null || baked.isEmpty()) { return null; } return baked.get(rng.i(baked.size())); diff --git a/core/src/main/java/art/arcane/iris/engine/object/IrisFungus.java b/core/src/main/java/art/arcane/iris/engine/object/IrisFungus.java index 76bf6109f..1c7e3f549 100644 --- a/core/src/main/java/art/arcane/iris/engine/object/IrisFungus.java +++ b/core/src/main/java/art/arcane/iris/engine/object/IrisFungus.java @@ -219,7 +219,7 @@ public class IrisFungus implements IrisProceduralPlacement { public IrisObject getVariantObject(IrisData data, RNG rng) { KList baked = getVariantObjects(data); - if (baked.isEmpty()) { + if (baked == null || baked.isEmpty()) { return null; } return baked.get(rng.i(baked.size())); diff --git a/core/src/main/java/art/arcane/iris/engine/object/IrisObject.java b/core/src/main/java/art/arcane/iris/engine/object/IrisObject.java index 41a0d05f0..75053687f 100644 --- a/core/src/main/java/art/arcane/iris/engine/object/IrisObject.java +++ b/core/src/main/java/art/arcane/iris/engine/object/IrisObject.java @@ -18,8 +18,6 @@ package art.arcane.iris.engine.object; -import art.arcane.iris.platform.bukkit.BukkitBlockResolution; - import art.arcane.iris.core.loader.IrisData; import art.arcane.iris.core.loader.IrisRegistrant; import art.arcane.iris.engine.data.cache.AtomicCache; @@ -33,7 +31,6 @@ import art.arcane.volmlib.util.collection.KList; import art.arcane.volmlib.util.collection.KMap; import art.arcane.iris.util.project.context.IrisContext; import art.arcane.iris.util.common.data.B; -import art.arcane.iris.util.common.data.IrisCustomData; import art.arcane.iris.util.common.data.VectorMap; import art.arcane.volmlib.util.format.Form; import art.arcane.iris.util.project.interpolation.IrisInterpolation; @@ -56,15 +53,8 @@ import lombok.Getter; import lombok.Setter; import lombok.experimental.Accessors; import org.bukkit.Location; -import org.bukkit.Material; import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; import org.bukkit.block.data.BlockData; -import org.bukkit.block.data.MultipleFacing; -import org.bukkit.block.data.Waterlogged; -import org.bukkit.block.data.type.Leaves; -import org.bukkit.block.data.type.Slab; -import org.bukkit.block.data.type.Stairs; import java.io.*; import java.util.*; @@ -167,14 +157,18 @@ public class IrisObject extends IrisRegistrant { } private static boolean shouldStilt(PlatformBlockState state) { - BlockData data = (BlockData) state.nativeHandle(); - if (!data.getMaterial().isOccluding()) { + if (!state.isOccluding()) { return false; } - if (data instanceof Stairs || data instanceof Slab) { + String material = materialKey(state); + if (material.endsWith("_stairs") || material.endsWith("_slab")) { return false; } - return data.getMaterial() != Material.DIRT_PATH; + return !material.equals("minecraft:dirt_path"); + } + + private static String materialKey(PlatformBlockState state) { + return IrisProceduralBlocks.materialKey(state); } public AxisAlignedBB getAABB() { @@ -327,11 +321,11 @@ public class IrisObject extends IrisRegistrant { for (int i = 0; i < s; i++) { IrisBlockVector pos = new IrisBlockVector(din.readShort(), din.readShort(), din.readShort()); - BlockData data = BukkitBlockResolution.get(din.readUTF()); + PlatformBlockState data = B.getState(din.readUTF()); if (isStructureMarker(data)) { continue; } - blocks.put(pos, data == null ? null : BukkitBlockState.of(data)); + blocks.put(pos, data); } if (din.available() == 0) @@ -369,11 +363,11 @@ public class IrisObject extends IrisRegistrant { for (i = 0; i < s; i++) { IrisBlockVector pos = new IrisBlockVector(din.readShort(), din.readShort(), din.readShort()); - BlockData data = BukkitBlockResolution.get(palette.get(din.readShort())); + PlatformBlockState data = B.getState(palette.get(din.readShort())); if (isStructureMarker(data)) { continue; } - blocks.put(pos, data == null ? null : BukkitBlockState.of(data)); + blocks.put(pos, data); } s = din.readInt(); @@ -383,12 +377,12 @@ public class IrisObject extends IrisRegistrant { } } - private static boolean isStructureMarker(BlockData data) { + private static boolean isStructureMarker(PlatformBlockState data) { if (data == null) { return false; } - Material m = data.getMaterial(); - return m == Material.JIGSAW || m == Material.STRUCTURE_BLOCK || m == Material.STRUCTURE_VOID; + String material = materialKey(data); + return material.equals("minecraft:jigsaw") || material.equals("minecraft:structure_block") || material.equals("minecraft:structure_void"); } public void write(OutputStream o) throws IOException { @@ -1000,15 +994,16 @@ public class IrisObject extends IrisRegistrant { } PlatformBlockState data = blocks.get(i); - BlockData rawData = data == null ? null : (BlockData) data.nativeHandle(); + if (data == null) { + continue; + } for (PlatformBlockState k : j.getMark(rdata)) { if (max <= 0) { break; } - BlockData rawMark = (BlockData) k.nativeHandle(); - if (j.isExact() ? rawMark.matches(rawData) : rawMark.getMaterial().equals(rawData.getMaterial())) { + if (j.isExact() ? k.matches(data) : materialKey(k).equals(materialKey(data))) { boolean a = !blocks.containsKey((IrisBlockVector) i.clone().add(new IrisBlockVector(0, 1, 0))); boolean fff = !blocks.containsKey((IrisBlockVector) i.clone().add(new IrisBlockVector(0, 2, 0))); @@ -1058,22 +1053,17 @@ public class IrisObject extends IrisRegistrant { } } - if (placer.isPreventingDecay() && ((BlockData) data.nativeHandle()) instanceof Leaves && !((Leaves) ((BlockData) data.nativeHandle())).isPersistent()) { - BlockData leaves = ((BlockData) data.nativeHandle()).clone(); - ((Leaves) leaves).setPersistent(true); - data = BukkitBlockState.of(leaves); + if (placer.isPreventingDecay() && IrisProceduralBlocks.hasProperty(data, "distance") && "false".equals(IrisProceduralBlocks.propertyValue(data, "persistent"))) { + data = data.withProperty("persistent", "true"); } for (IrisObjectReplace j : config.getEdit()) { if (rng.chance(j.getChance())) { for (PlatformBlockState k : j.getFind(rdata)) { - BlockData rawFind = (BlockData) k.nativeHandle(); - BlockData rawData = (BlockData) data.nativeHandle(); - if (j.isExact() ? rawFind.matches(rawData) : rawFind.getMaterial().equals(rawData.getMaterial())) { + if (j.isExact() ? k.matches(data) : materialKey(k).equals(materialKey(data))) { PlatformBlockState newData = j.getReplace(rng, i.getX() + x, i.getY() + y, i.getZ() + z, rdata); - BlockData rawNew = (BlockData) newData.nativeHandle(); - if (rawNew.getMaterial() == rawData.getMaterial() && !(rawNew instanceof IrisCustomData || rawData instanceof IrisCustomData)) + if (materialKey(newData).equals(materialKey(data)) && !(newData.isCustom() || data.isCustom())) data = BlockDataMergeSupport.merge(data, newData); else data = newData; @@ -1098,7 +1088,7 @@ public class IrisObject extends IrisRegistrant { zz += config.warp(rng, i.getZ() + z, i.getY() + y, i.getX() + x, getLoader()); } - if (yv < 0 && (config.getMode().equals(ObjectPlaceMode.PAINT)) && !BukkitBlockResolution.isVineBlock((BlockData) data.nativeHandle())) { + if (yv < 0 && (config.getMode().equals(ObjectPlaceMode.PAINT)) && !B.isVineBlock(data)) { yy = (int) Math.round(i.getY()) + Math.floorDiv(h, 2) + placer.getHighest(xx, zz, getLoader(), config.isUnderwater()); } @@ -1118,27 +1108,12 @@ public class IrisObject extends IrisRegistrant { continue; } - if (((BlockData) data.nativeHandle()) instanceof Waterlogged && shouldAutoWaterlogBlock(placer, config, yv, xx, yy, zz)) { - BlockData waterlogged = ((BlockData) data.nativeHandle()).clone(); - ((Waterlogged) waterlogged).setWaterlogged(true); - data = BukkitBlockState.of(waterlogged); + if (IrisProceduralBlocks.hasProperty(data, "waterlogged") && shouldAutoWaterlogBlock(placer, config, yv, xx, yy, zz)) { + data = data.withProperty("waterlogged", "true"); } - if (BukkitBlockResolution.isVineBlock((BlockData) data.nativeHandle())) { - BlockData fData = ((BlockData) data.nativeHandle()).clone(); - MultipleFacing f = (MultipleFacing) fData; - boolean facesChanged = false; - for (BlockFace face : f.getAllowedFaces()) { - PlatformBlockState facingState = placer.get(xx + face.getModX(), yy + face.getModY(), zz + face.getModZ()); - BlockData facingBlock = facingState == null ? null : (BlockData) facingState.nativeHandle(); - if (BukkitBlockResolution.isSolid(facingBlock) && !BukkitBlockResolution.isVineBlock(facingBlock)) { - f.setFace(face, true); - facesChanged = true; - } - } - if (facesChanged) { - data = BukkitBlockState.of(fData); - } + if (B.isVineBlock(data)) { + data = attachVineFaces(placer, data, xx, yy, zz); } if (listener != null) { @@ -1150,12 +1125,11 @@ public class IrisObject extends IrisRegistrant { } PlatformBlockState existingState = placer.get(xx, yy, zz); - BlockData existingRaw = existingState == null ? null : (BlockData) existingState.nativeHandle(); - BlockData rawData = (BlockData) data.nativeHandle(); - boolean wouldReplace = BukkitBlockResolution.isSolid(existingRaw) && BukkitBlockResolution.isVineBlock(rawData); - boolean place = !rawData.getMaterial().equals(Material.AIR) && !rawData.getMaterial().equals(Material.CAVE_AIR) && !wouldReplace; + boolean wouldReplace = B.isSolid(existingState) && B.isVineBlock(data); + String material = materialKey(data); + boolean place = !material.equals("minecraft:air") && !material.equals("minecraft:cave_air") && !wouldReplace; - if (rawData instanceof IrisCustomData || place) { + if (data.isCustom() || place) { placer.set(xx, yy, zz, data); if (tile != null) { placer.setTile(xx, yy, zz, tile); @@ -1239,9 +1213,9 @@ public class IrisObject extends IrisRegistrant { if (settings != null && settings.getPalette() != null) { d = config.getStiltSettings().getPalette().get(rng, x, y, z, rdata); } else { - Material mat = ((BlockData) d.nativeHandle()).getMaterial(); - if (mat == Material.GRASS_BLOCK || mat == Material.MYCELIUM || mat == Material.PODZOL || mat == Material.DIRT_PATH) { - d = BukkitBlockState.of(Material.DIRT.createBlockData()); + String mat = materialKey(d); + if (mat.equals("minecraft:grass_block") || mat.equals("minecraft:mycelium") || mat.equals("minecraft:podzol") || mat.equals("minecraft:dirt_path")) { + d = B.getState("minecraft:dirt"); } } @@ -1260,12 +1234,13 @@ public class IrisObject extends IrisRegistrant { for (IrisObjectReplace j : config.getEdit()) { if (rng.chance(j.getChance())) { for (PlatformBlockState k : j.getFind(rdata)) { - BlockData rawFind = (BlockData) k.nativeHandle(); - BlockData rawD = d == null ? null : (BlockData) d.nativeHandle(); - if (j.isExact() ? rawFind.matches(rawD) : rawFind.getMaterial().equals(rawD.getMaterial())) { + if (d == null) { + continue; + } + if (j.isExact() ? k.matches(d) : materialKey(k).equals(materialKey(d))) { PlatformBlockState newData = j.getReplace(rng, i.getX() + x, i.getY() + y, i.getZ() + z, rdata); - if (((BlockData) newData.nativeHandle()).getMaterial() == rawD.getMaterial()) { + if (materialKey(newData).equals(materialKey(d))) { d = BlockDataMergeSupport.merge(d, newData); } else { d = newData; @@ -1275,7 +1250,7 @@ public class IrisObject extends IrisRegistrant { } } - if (d == null || !((BlockData) d.nativeHandle()).getMaterial().isOccluding()) + if (d == null || !d.isOccluding()) continue; xx = x + (int) Math.round(i.getX()); @@ -1344,10 +1319,8 @@ public class IrisObject extends IrisRegistrant { int highest = placer.getHighest(xx, zz, getLoader(), true); - if (((BlockData) d.nativeHandle()) instanceof Waterlogged && shouldAutoWaterlogBlock(placer, config, yv, xx, highest, zz)) { - BlockData waterlogged = ((BlockData) d.nativeHandle()).clone(); - ((Waterlogged) waterlogged).setWaterlogged(true); - d = BukkitBlockState.of(waterlogged); + if (IrisProceduralBlocks.hasProperty(d, "waterlogged") && shouldAutoWaterlogBlock(placer, config, yv, xx, highest, zz)) { + d = d.withProperty("waterlogged", "true"); } int lowerBound = highest - 1; @@ -1369,7 +1342,7 @@ public class IrisObject extends IrisRegistrant { for (int j = lowest + y; j > lowerBound; j--) { PlatformBlockState fluidState = placer.get(xx, j, zz); - if (BukkitBlockResolution.isFluid(fluidState == null ? null : (BlockData) fluidState.nativeHandle())) { + if (B.isFluid(fluidState)) { break; } if (eroding) { @@ -1385,21 +1358,8 @@ public class IrisObject extends IrisRegistrant { } } - if (BukkitBlockResolution.isVineBlock((BlockData) d.nativeHandle())) { - BlockData fData = ((BlockData) d.nativeHandle()).clone(); - MultipleFacing f = (MultipleFacing) fData; - boolean facesChanged = false; - for (BlockFace face : f.getAllowedFaces()) { - PlatformBlockState facingState = placer.get(xx + face.getModX(), j + face.getModY(), zz + face.getModZ()); - BlockData facingBlock = facingState == null ? null : (BlockData) facingState.nativeHandle(); - if (BukkitBlockResolution.isSolid(facingBlock) && !BukkitBlockResolution.isVineBlock(facingBlock)) { - f.setFace(face, true); - facesChanged = true; - } - } - if (facesChanged) { - d = BukkitBlockState.of(fData); - } + if (B.isVineBlock(d)) { + d = attachVineFaces(placer, d, xx, j, zz); } placer.set(xx, j, zz, d); } @@ -1499,7 +1459,7 @@ public class IrisObject extends IrisRegistrant { targetY = Math.max(worldMin + 1, Math.min(worldMax, targetY)); if (targetY > origY) { PlatformBlockState fill = complex != null ? complex.getRockStream().get(cx, cz) : null; - if (fill == null || BukkitBlockResolution.isAir((BlockData) fill.nativeHandle())) { + if (B.isAir(fill)) { fill = States.STONE; } for (int yy = origY + 1; yy <= targetY; yy++) { @@ -1569,8 +1529,22 @@ public class IrisObject extends IrisRegistrant { return false; } - BlockData raw = (BlockData) existing.nativeHandle(); - return BukkitBlockResolution.isWater(raw) || BukkitBlockResolution.isWaterLogged(raw); + return B.isWater(existing) || B.isWaterLogged(existing); + } + + private static PlatformBlockState attachVineFaces(IObjectPlacer placer, PlatformBlockState data, int x, int y, int z) { + PlatformBlockState result = data; + for (String face : IrisProceduralBlocks.FACE_PROPERTIES) { + if (!IrisProceduralBlocks.hasProperty(data, face)) { + continue; + } + int[] mod = IrisProceduralBlocks.faceOffset(face); + PlatformBlockState facing = placer.get(x + mod[0], y + mod[1], z + mod[2]); + if (B.isSolid(facing) && !B.isVineBlock(facing)) { + result = result.withProperty(face, "true"); + } + } + return result; } public IrisObject rotateCopy(IrisObjectRotation rt) { @@ -1709,7 +1683,7 @@ public class IrisObject extends IrisRegistrant { if (IrisInterpolation.getTrilinear(x, y, z, rad, (xx, yy, zz) -> { PlatformBlockState data = v.get(new IrisBlockVector((int) xx, (int) yy, (int) zz)); - if (data == null || ((BlockData) data.nativeHandle()).getMaterial().isAir()) { + if (B.isAir(data)) { return 0; } @@ -1740,7 +1714,7 @@ public class IrisObject extends IrisRegistrant { if (IrisInterpolation.getTricubic(x, y, z, rad, (xx, yy, zz) -> { PlatformBlockState data = v.get(new IrisBlockVector((int) xx, (int) yy, (int) zz)); - if (data == null || ((BlockData) data.nativeHandle()).getMaterial().isAir()) { + if (B.isAir(data)) { return 0; } @@ -1775,7 +1749,7 @@ public class IrisObject extends IrisRegistrant { if (IrisInterpolation.getTrihermite(x, y, z, rad, (xx, yy, zz) -> { PlatformBlockState data = v.get(new IrisBlockVector((int) xx, (int) yy, (int) zz)); - if (data == null || ((BlockData) data.nativeHandle()).getMaterial().isAir()) { + if (B.isAir(data)) { return 0; } @@ -1798,7 +1772,7 @@ public class IrisObject extends IrisRegistrant { readLock.lock(); PlatformBlockState r = blocks.get(vv); - if (r != null && !((BlockData) r.nativeHandle()).getMaterial().isAir()) { + if (!B.isAir(r)) { return r; } @@ -1807,7 +1781,7 @@ public class IrisObject extends IrisRegistrant { for (var entry : blocks) { PlatformBlockState dat = entry.getValue(); - if (((BlockData) dat.nativeHandle()).getMaterial().isAir()) { + if (B.isAir(dat)) { continue; } diff --git a/core/src/main/java/art/arcane/iris/engine/object/IrisObjectRotation.java b/core/src/main/java/art/arcane/iris/engine/object/IrisObjectRotation.java index 2df30ce79..2d19d9b91 100644 --- a/core/src/main/java/art/arcane/iris/engine/object/IrisObjectRotation.java +++ b/core/src/main/java/art/arcane/iris/engine/object/IrisObjectRotation.java @@ -47,6 +47,17 @@ import java.util.Map; @Desc("Configures rotation for iris") @Data public class IrisObjectRotation { + private static final boolean BUKKIT_PRESENT = detectBukkit(); + + private static boolean detectBukkit() { + try { + Class.forName("org.bukkit.Bukkit", false, IrisObjectRotation.class.getClassLoader()); + return true; + } catch (ClassNotFoundException e) { + return false; + } + } + private static final class Faces { private static final List WALL_FACES = List.of(BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST); } @@ -266,6 +277,10 @@ public class IrisObjectRotation { return null; } + if (!BUKKIT_PRESENT) { + return state; + } + BlockData raw = ((BlockData) state.nativeHandle()).clone(); BlockData rotated = rotate(raw, spinx, spiny, spinz); return rotated == null ? null : BukkitBlockState.of(rotated); diff --git a/core/src/main/java/art/arcane/iris/engine/object/IrisProceduralBlocks.java b/core/src/main/java/art/arcane/iris/engine/object/IrisProceduralBlocks.java index 8cc7094c5..fc994a800 100644 --- a/core/src/main/java/art/arcane/iris/engine/object/IrisProceduralBlocks.java +++ b/core/src/main/java/art/arcane/iris/engine/object/IrisProceduralBlocks.java @@ -18,45 +18,87 @@ package art.arcane.iris.engine.object; -import art.arcane.iris.platform.bukkit.BukkitBlockResolution; - import art.arcane.iris.core.loader.IrisData; -import art.arcane.iris.platform.bukkit.BukkitBlockState; import art.arcane.iris.spi.PlatformBlockState; +import art.arcane.iris.util.common.data.B; import art.arcane.iris.util.common.math.IrisBlockVector; import art.arcane.iris.util.common.math.Vector3i; import art.arcane.volmlib.util.math.RNG; -import org.bukkit.block.data.BlockData; import java.util.Map; /** * Shared low-level helpers for building procedural objects in memory: resolving a - * single block id or a noise palette into BlockData, and assembling a raw block - * map into a centered IrisObject anchored so its y=0 layer sits one block above - * the terrain surface (same convention the tree generator uses). + * single block id or a noise palette into a platform block state, and assembling a + * raw block map into a centered IrisObject anchored so its y=0 layer sits one block + * above the terrain surface (same convention the tree generator uses). */ public final class IrisProceduralBlocks { + public static final String[] FACE_PROPERTIES = {"north", "east", "south", "west", "up", "down"}; + private IrisProceduralBlocks() { } + public static int[] faceOffset(String face) { + return switch (face) { + case "north" -> new int[]{0, 0, -1}; + case "south" -> new int[]{0, 0, 1}; + case "east" -> new int[]{1, 0, 0}; + case "west" -> new int[]{-1, 0, 0}; + case "up" -> new int[]{0, 1, 0}; + default -> new int[]{0, -1, 0}; + }; + } + public static boolean paletteSet(IrisMaterialPalette palette) { return palette != null && palette.getPalette() != null && !palette.getPalette().isEmpty(); } - public static BlockData resolve(String block, IrisMaterialPalette palette, IrisData data, int x, int y, int z, RNG paletteRng) { + public static PlatformBlockState resolve(String block, IrisMaterialPalette palette, IrisData data, int x, int y, int z, RNG paletteRng) { if (paletteSet(palette)) { - PlatformBlockState state = palette.get(paletteRng, x, y, z, data); - return state == null ? null : ((BlockData) state.nativeHandle()).clone(); + return palette.get(paletteRng, x, y, z, data); } if (block != null && !block.isEmpty()) { - BlockData bd = BukkitBlockResolution.getOrNull(block, false); - return bd == null ? null : bd.clone(); + return B.getStateOrNull(block, false); } return null; } - public static IrisObject assemble(Map blocks) { + public static boolean hasProperty(PlatformBlockState state, String property) { + return propertyValue(state, property) != null; + } + + public static String materialKey(PlatformBlockState state) { + String key = state.key(); + int bracket = key.indexOf('['); + return bracket < 0 ? key : key.substring(0, bracket); + } + + public static String propertyValue(PlatformBlockState state, String property) { + String key = state.key(); + int bracket = key.indexOf('['); + if (bracket < 0) { + return null; + } + int start = key.indexOf("[" + property + "=", bracket); + if (start < 0) { + start = key.indexOf("," + property + "=", bracket); + } + if (start < 0) { + return null; + } + int valueStart = key.indexOf('=', start) + 1; + int end = key.indexOf(',', valueStart); + if (end < 0) { + end = key.indexOf(']', valueStart); + } + if (end < 0) { + return null; + } + return key.substring(valueStart, end); + } + + public static IrisObject assemble(Map blocks) { if (blocks == null || blocks.isEmpty()) { return null; } @@ -84,12 +126,12 @@ public final class IrisProceduralBlocks { int cz = d / 2; IrisObject object = new IrisObject(w, h, d); - for (Map.Entry entry : blocks.entrySet()) { + for (Map.Entry entry : blocks.entrySet()) { Vector3i v = entry.getKey(); int nx = v.getBlockX() - minX - cx; int ny = v.getBlockY() - cy + 1; int nz = v.getBlockZ() - minZ - cz; - object.getBlocks().put(new IrisBlockVector(nx, ny, nz), BukkitBlockState.of(entry.getValue())); + object.getBlocks().put(new IrisBlockVector(nx, ny, nz), entry.getValue()); } return object; diff --git a/core/src/main/java/art/arcane/iris/engine/object/IrisProceduralTree.java b/core/src/main/java/art/arcane/iris/engine/object/IrisProceduralTree.java index b95e70710..8afd0e3ce 100644 --- a/core/src/main/java/art/arcane/iris/engine/object/IrisProceduralTree.java +++ b/core/src/main/java/art/arcane/iris/engine/object/IrisProceduralTree.java @@ -297,7 +297,7 @@ public class IrisProceduralTree implements IrisProceduralPlacement { public IrisObject getVariantObject(IrisData data, RNG rng) { KList baked = getVariantObjects(data); - if (baked.isEmpty()) { + if (baked == null || baked.isEmpty()) { return null; } return baked.get(rng.i(baked.size())); diff --git a/core/src/main/java/art/arcane/iris/engine/object/IrisRuin.java b/core/src/main/java/art/arcane/iris/engine/object/IrisRuin.java index c24f1d117..a1d556bbd 100644 --- a/core/src/main/java/art/arcane/iris/engine/object/IrisRuin.java +++ b/core/src/main/java/art/arcane/iris/engine/object/IrisRuin.java @@ -177,7 +177,7 @@ public class IrisRuin implements IrisProceduralPlacement { public IrisObject getVariantObject(IrisData data, RNG rng) { KList baked = getVariantObjects(data); - if (baked.isEmpty()) { + if (baked == null || baked.isEmpty()) { return null; } return baked.get(rng.i(baked.size())); diff --git a/core/src/main/java/art/arcane/iris/engine/object/coral/CoralGenerator.java b/core/src/main/java/art/arcane/iris/engine/object/coral/CoralGenerator.java index e9d018b57..dde2938f5 100644 --- a/core/src/main/java/art/arcane/iris/engine/object/coral/CoralGenerator.java +++ b/core/src/main/java/art/arcane/iris/engine/object/coral/CoralGenerator.java @@ -23,10 +23,9 @@ import art.arcane.iris.engine.object.IrisCoral; import art.arcane.iris.engine.object.IrisObject; import art.arcane.iris.engine.object.IrisProceduralBlocks; import art.arcane.iris.engine.object.tree.TreeFunctions; +import art.arcane.iris.spi.PlatformBlockState; import art.arcane.iris.util.common.math.Vector3i; import art.arcane.volmlib.util.math.RNG; -import org.bukkit.block.data.BlockData; -import org.bukkit.block.data.Waterlogged; import java.util.HashMap; import java.util.Map; @@ -52,7 +51,7 @@ public final class CoralGenerator { case TENDRIL -> buildTendril(canvas, coral, height, shapeSeed, rng); } - Map resolved = resolve(canvas, coral, data); + Map resolved = resolve(canvas, coral, data); return IrisProceduralBlocks.assemble(resolved); } @@ -231,30 +230,33 @@ public final class CoralGenerator { }; } - private static Map resolve(CoralCanvas canvas, IrisCoral coral, IrisData data) { - Map out = new HashMap<>(); + private static Map resolve(CoralCanvas canvas, IrisCoral coral, IrisData data) { + Map out = new HashMap<>(); RNG paletteRng = new RNG(coral.getSeed()); for (Map.Entry entry : canvas.getCells().entrySet()) { int[] xyz = CoralCanvas.decode(entry.getKey()); int x = xyz[0]; int y = xyz[1]; int z = xyz[2]; - BlockData bd; + PlatformBlockState state; if (entry.getValue() == CoralCanvas.Role.TIP) { - bd = IrisProceduralBlocks.resolve(coral.getTipBlock(), coral.getTipPalette(), data, x, y, z, paletteRng); - if (bd == null) { - bd = IrisProceduralBlocks.resolve(coral.getBlock(), coral.getBlockPalette(), data, x, y, z, paletteRng); + state = IrisProceduralBlocks.resolve(coral.getTipBlock(), coral.getTipPalette(), data, x, y, z, paletteRng); + if (state == null) { + state = IrisProceduralBlocks.resolve(coral.getBlock(), coral.getBlockPalette(), data, x, y, z, paletteRng); } } else { - bd = IrisProceduralBlocks.resolve(coral.getBlock(), coral.getBlockPalette(), data, x, y, z, paletteRng); + state = IrisProceduralBlocks.resolve(coral.getBlock(), coral.getBlockPalette(), data, x, y, z, paletteRng); } - if (bd == null) { + if (state == null) { continue; } - if (coral.isWaterlogged() && bd instanceof Waterlogged waterlogged) { - waterlogged.setWaterlogged(true); + if (coral.isWaterlogged() && IrisProceduralBlocks.hasProperty(state, "waterlogged")) { + try { + state = state.withProperty("waterlogged", "true"); + } catch (IllegalArgumentException ignored) { + } } - out.put(new Vector3i(x, y, z), bd); + out.put(new Vector3i(x, y, z), state); } return out; } diff --git a/core/src/main/java/art/arcane/iris/engine/object/crystal/CrystalGenerator.java b/core/src/main/java/art/arcane/iris/engine/object/crystal/CrystalGenerator.java index 693fed3e0..2104c655c 100644 --- a/core/src/main/java/art/arcane/iris/engine/object/crystal/CrystalGenerator.java +++ b/core/src/main/java/art/arcane/iris/engine/object/crystal/CrystalGenerator.java @@ -22,9 +22,9 @@ import art.arcane.iris.core.loader.IrisData; import art.arcane.iris.engine.object.IrisCrystal; import art.arcane.iris.engine.object.IrisObject; import art.arcane.iris.engine.object.IrisProceduralBlocks; +import art.arcane.iris.spi.PlatformBlockState; import art.arcane.iris.util.common.math.Vector3i; import art.arcane.volmlib.util.math.RNG; -import org.bukkit.block.data.BlockData; import java.util.HashMap; import java.util.Map; @@ -40,7 +40,7 @@ public final class CrystalGenerator { CrystalBaseBuilder.build(canvas, crystal, structureSeed + 977L); CrystalShardBuilder.build(canvas, crystal, rng); - Map resolved = new HashMap<>(); + Map resolved = new HashMap<>(); RNG paletteRng = new RNG(crystal.getSeed()); RNG tipRng = new RNG(crystal.getSeed() + (variantIndex * 31337L) + 4099L); @@ -49,7 +49,7 @@ public final class CrystalGenerator { int x = position.getBlockX(); int y = position.getBlockY(); int z = position.getBlockZ(); - BlockData blockData = resolveRole(crystal, entry.getValue(), data, x, y, z, paletteRng, tipRng); + PlatformBlockState blockData = resolveRole(crystal, entry.getValue(), data, x, y, z, paletteRng, tipRng); if (blockData == null) { continue; } @@ -59,7 +59,7 @@ public final class CrystalGenerator { return IrisProceduralBlocks.assemble(resolved); } - private static BlockData resolveRole(IrisCrystal crystal, CrystalRole role, IrisData data, int x, int y, int z, RNG paletteRng, RNG tipRng) { + private static PlatformBlockState resolveRole(IrisCrystal crystal, CrystalRole role, IrisData data, int x, int y, int z, RNG paletteRng, RNG tipRng) { return switch (role) { case BASE -> resolveBase(crystal, data, x, y, z, paletteRng); case SHARD -> resolveShard(crystal, data, x, y, z, paletteRng); @@ -67,11 +67,11 @@ public final class CrystalGenerator { }; } - private static BlockData resolveBase(IrisCrystal crystal, IrisData data, int x, int y, int z, RNG paletteRng) { + private static PlatformBlockState resolveBase(IrisCrystal crystal, IrisData data, int x, int y, int z, RNG paletteRng) { boolean hasBase = IrisProceduralBlocks.paletteSet(crystal.getBasePalette()) || (crystal.getBaseBlock() != null && !crystal.getBaseBlock().isEmpty()); if (hasBase) { - BlockData base = IrisProceduralBlocks.resolve(crystal.getBaseBlock(), crystal.getBasePalette(), data, x, y, z, paletteRng); + PlatformBlockState base = IrisProceduralBlocks.resolve(crystal.getBaseBlock(), crystal.getBasePalette(), data, x, y, z, paletteRng); if (base != null) { return base; } @@ -79,17 +79,17 @@ public final class CrystalGenerator { return resolveShard(crystal, data, x, y, z, paletteRng); } - private static BlockData resolveShard(IrisCrystal crystal, IrisData data, int x, int y, int z, RNG paletteRng) { + private static PlatformBlockState resolveShard(IrisCrystal crystal, IrisData data, int x, int y, int z, RNG paletteRng) { return IrisProceduralBlocks.resolve(crystal.getBlock(), crystal.getBlockPalette(), data, x, y, z, paletteRng); } - private static BlockData resolveTip(IrisCrystal crystal, IrisData data, int x, int y, int z, RNG paletteRng, RNG tipRng) { + private static PlatformBlockState resolveTip(IrisCrystal crystal, IrisData data, int x, int y, int z, RNG paletteRng, RNG tipRng) { boolean hasTip = IrisProceduralBlocks.paletteSet(crystal.getTipPalette()) || (crystal.getTipBlock() != null && !crystal.getTipBlock().isEmpty()); if (hasTip) { if (tipRng.chance(crystal.getTipChance())) { - BlockData tip = IrisProceduralBlocks.resolve(crystal.getTipBlock(), crystal.getTipPalette(), data, x, y, z, paletteRng); + PlatformBlockState tip = IrisProceduralBlocks.resolve(crystal.getTipBlock(), crystal.getTipPalette(), data, x, y, z, paletteRng); if (tip != null) { return tip; } @@ -99,7 +99,7 @@ public final class CrystalGenerator { if (crystal.isGlow() && crystal.getGlowBlock() != null && !crystal.getGlowBlock().isEmpty()) { if (tipRng.chance(crystal.getTipChance())) { - BlockData glow = IrisProceduralBlocks.resolve(crystal.getGlowBlock(), null, data, x, y, z, paletteRng); + PlatformBlockState glow = IrisProceduralBlocks.resolve(crystal.getGlowBlock(), null, data, x, y, z, paletteRng); if (glow != null) { return glow; } diff --git a/core/src/main/java/art/arcane/iris/engine/object/formation/FormationBlockResolver.java b/core/src/main/java/art/arcane/iris/engine/object/formation/FormationBlockResolver.java index 4eb0e426c..b801ef582 100644 --- a/core/src/main/java/art/arcane/iris/engine/object/formation/FormationBlockResolver.java +++ b/core/src/main/java/art/arcane/iris/engine/object/formation/FormationBlockResolver.java @@ -25,20 +25,19 @@ import art.arcane.iris.engine.object.IrisProceduralBlocks; import art.arcane.iris.spi.PlatformBlockState; import art.arcane.iris.util.common.math.Vector3i; import art.arcane.volmlib.util.math.RNG; -import org.bukkit.block.data.BlockData; public final class FormationBlockResolver { private FormationBlockResolver() { } - public static BlockData resolve(IrisFormation f, IrisData data, FormationCanvas.Role role, Vector3i raw) { + public static PlatformBlockState resolve(IrisFormation f, IrisData data, FormationCanvas.Role role, Vector3i raw) { int x = raw.getBlockX(); int y = raw.getBlockY(); int z = raw.getBlockZ(); RNG paletteRng = new RNG(f.getSeed()); if (role == FormationCanvas.Role.CAP && capDefined(f)) { - BlockData cap = IrisProceduralBlocks.resolve(f.getCapBlock(), f.getCapPalette(), data, x, y, z, paletteRng); + PlatformBlockState cap = IrisProceduralBlocks.resolve(f.getCapBlock(), f.getCapPalette(), data, x, y, z, paletteRng); if (cap != null) { return cap; } @@ -50,7 +49,7 @@ public final class FormationBlockResolver { int band = Math.floorDiv(y, thickness); PlatformBlockState strataState = strata.get(new RNG(f.getSeed() + (band * 31L)), x, band, z, data); if (strataState != null) { - return ((BlockData) strataState.nativeHandle()).clone(); + return strataState; } } diff --git a/core/src/main/java/art/arcane/iris/engine/object/formation/FormationGenerator.java b/core/src/main/java/art/arcane/iris/engine/object/formation/FormationGenerator.java index 94c84ca77..19d773660 100644 --- a/core/src/main/java/art/arcane/iris/engine/object/formation/FormationGenerator.java +++ b/core/src/main/java/art/arcane/iris/engine/object/formation/FormationGenerator.java @@ -22,9 +22,9 @@ import art.arcane.iris.core.loader.IrisData; import art.arcane.iris.engine.object.IrisFormation; import art.arcane.iris.engine.object.IrisObject; import art.arcane.iris.engine.object.IrisProceduralBlocks; +import art.arcane.iris.spi.PlatformBlockState; import art.arcane.iris.util.common.math.Vector3i; import art.arcane.volmlib.util.math.RNG; -import org.bukkit.block.data.BlockData; import java.util.HashMap; import java.util.Map; @@ -57,9 +57,9 @@ public final class FormationGenerator { return null; } - Map resolved = new HashMap<>(); + Map resolved = new HashMap<>(); for (Map.Entry entry : canvas.getCells().entrySet()) { - BlockData bd = FormationBlockResolver.resolve(f, data, entry.getValue(), entry.getKey()); + PlatformBlockState bd = FormationBlockResolver.resolve(f, data, entry.getValue(), entry.getKey()); if (bd == null) { continue; } diff --git a/core/src/main/java/art/arcane/iris/engine/object/fungi/FungusGenerator.java b/core/src/main/java/art/arcane/iris/engine/object/fungi/FungusGenerator.java index 16da73058..1e63cdfa0 100644 --- a/core/src/main/java/art/arcane/iris/engine/object/fungi/FungusGenerator.java +++ b/core/src/main/java/art/arcane/iris/engine/object/fungi/FungusGenerator.java @@ -22,9 +22,9 @@ import art.arcane.iris.core.loader.IrisData; import art.arcane.iris.engine.object.IrisFungus; import art.arcane.iris.engine.object.IrisObject; import art.arcane.iris.engine.object.IrisProceduralBlocks; +import art.arcane.iris.spi.PlatformBlockState; import art.arcane.iris.util.common.math.Vector3i; import art.arcane.volmlib.util.math.RNG; -import org.bukkit.block.data.BlockData; import java.util.HashMap; import java.util.Map; @@ -48,10 +48,10 @@ public final class FungusGenerator { } RNG paletteRng = new RNG(fungus.getSeed()); - Map resolved = new HashMap<>(); + Map resolved = new HashMap<>(); for (Map.Entry entry : roles.entrySet()) { Vector3i pos = entry.getKey(); - BlockData bd = resolveRole(fungus, entry.getValue(), data, pos, paletteRng); + PlatformBlockState bd = resolveRole(fungus, entry.getValue(), data, pos, paletteRng); if (bd == null) { continue; } @@ -63,7 +63,7 @@ public final class FungusGenerator { private static void buildUpright(Map roles, IrisFungus fungus, int height, RNG rng, long baseSeed) { int stemHeight = Math.max(1, height); - Map stemCells = new HashMap<>(); + Map stemCells = new HashMap<>(); double[] top = FungusStemBuilder.build(stemCells, fungus, stemHeight, baseSeed); for (Vector3i v : stemCells.keySet()) { roles.put(v, FungusCellRole.STEM); @@ -84,7 +84,7 @@ public final class FungusGenerator { return rng.i(lo, hi + 1); } - private static BlockData resolveRole(IrisFungus fungus, FungusCellRole role, IrisData data, Vector3i pos, RNG paletteRng) { + private static PlatformBlockState resolveRole(IrisFungus fungus, FungusCellRole role, IrisData data, Vector3i pos, RNG paletteRng) { int x = pos.getBlockX(); int y = pos.getBlockY(); int z = pos.getBlockZ(); @@ -92,11 +92,11 @@ public final class FungusGenerator { case STEM -> IrisProceduralBlocks.resolve(fungus.getStem(), fungus.getStemPalette(), data, x, y, z, paletteRng); case CAP -> IrisProceduralBlocks.resolve(fungus.getCap(), fungus.getCapPalette(), data, x, y, z, paletteRng); case GILL -> { - BlockData gill = IrisProceduralBlocks.resolve(fungus.getGillBlock(), fungus.getGillPalette(), data, x, y, z, paletteRng); + PlatformBlockState gill = IrisProceduralBlocks.resolve(fungus.getGillBlock(), fungus.getGillPalette(), data, x, y, z, paletteRng); yield gill != null ? gill : IrisProceduralBlocks.resolve(fungus.getCap(), fungus.getCapPalette(), data, x, y, z, paletteRng); } case SPOT -> { - BlockData spot = IrisProceduralBlocks.resolve(fungus.getSpotBlock(), fungus.getSpotPalette(), data, x, y, z, paletteRng); + PlatformBlockState spot = IrisProceduralBlocks.resolve(fungus.getSpotBlock(), fungus.getSpotPalette(), data, x, y, z, paletteRng); yield spot != null ? spot : IrisProceduralBlocks.resolve(fungus.getCap(), fungus.getCapPalette(), data, x, y, z, paletteRng); } }; diff --git a/core/src/main/java/art/arcane/iris/engine/object/fungi/FungusStemBuilder.java b/core/src/main/java/art/arcane/iris/engine/object/fungi/FungusStemBuilder.java index 677a8b196..58d5120c0 100644 --- a/core/src/main/java/art/arcane/iris/engine/object/fungi/FungusStemBuilder.java +++ b/core/src/main/java/art/arcane/iris/engine/object/fungi/FungusStemBuilder.java @@ -20,8 +20,8 @@ package art.arcane.iris.engine.object.fungi; import art.arcane.iris.engine.object.IrisFungus; import art.arcane.iris.engine.object.tree.TreeFunctions; +import art.arcane.iris.spi.PlatformBlockState; import art.arcane.iris.util.common.math.Vector3i; -import org.bukkit.block.data.BlockData; import java.util.Map; @@ -29,7 +29,7 @@ public final class FungusStemBuilder { private FungusStemBuilder() { } - public static double[] build(Map stemCells, IrisFungus fungus, int stemHeight, long seed) { + public static double[] build(Map stemCells, IrisFungus fungus, int stemHeight, long seed) { int width = Math.max(1, Math.min(3, fungus.getStemWidth())); double maxLean = stemHeight * Math.tan(Math.toRadians(Math.max(0.0, fungus.getStemCurve()))); double leanRad = Math.toRadians(fungus.getStemLeanAzimuth()); diff --git a/core/src/main/java/art/arcane/iris/engine/object/ruin/RuinBlockCanvas.java b/core/src/main/java/art/arcane/iris/engine/object/ruin/RuinBlockCanvas.java index e416f1f0f..a3333ccad 100644 --- a/core/src/main/java/art/arcane/iris/engine/object/ruin/RuinBlockCanvas.java +++ b/core/src/main/java/art/arcane/iris/engine/object/ruin/RuinBlockCanvas.java @@ -18,8 +18,8 @@ package art.arcane.iris.engine.object.ruin; +import art.arcane.iris.spi.PlatformBlockState; import art.arcane.iris.util.common.math.Vector3i; -import org.bukkit.block.data.BlockData; import java.util.HashMap; import java.util.Map; @@ -33,7 +33,7 @@ final class RuinBlockCanvas { static final class Cell { private Role role; private boolean structural; - private BlockData accentData; + private PlatformBlockState accentData; Cell(Role role, boolean structural) { this.role = role; @@ -48,7 +48,7 @@ final class RuinBlockCanvas { return structural; } - BlockData accentData() { + PlatformBlockState accentData() { return accentData; } @@ -57,7 +57,7 @@ final class RuinBlockCanvas { this.structural = this.structural || structuralNext; } - void makeAccent(BlockData data) { + void makeAccent(PlatformBlockState data) { this.role = Role.ACCENT; this.structural = false; this.accentData = data; @@ -80,14 +80,14 @@ final class RuinBlockCanvas { } } - void accent(int x, int y, int z, BlockData data) { + void accent(int x, int y, int z, PlatformBlockState data) { if (data == null) { return; } cells.put(new Vector3i(x, y, z), accentCell(data)); } - private static Cell accentCell(BlockData data) { + private static Cell accentCell(PlatformBlockState data) { Cell cell = new Cell(Role.ACCENT, false); cell.makeAccent(data); return cell; diff --git a/core/src/main/java/art/arcane/iris/engine/object/ruin/RuinDecoratorApplier.java b/core/src/main/java/art/arcane/iris/engine/object/ruin/RuinDecoratorApplier.java index ce41f64cc..6dee8bf8c 100644 --- a/core/src/main/java/art/arcane/iris/engine/object/ruin/RuinDecoratorApplier.java +++ b/core/src/main/java/art/arcane/iris/engine/object/ruin/RuinDecoratorApplier.java @@ -20,10 +20,10 @@ package art.arcane.iris.engine.object.ruin; import art.arcane.iris.core.loader.IrisData; import art.arcane.iris.engine.object.IrisProceduralBlocks; +import art.arcane.iris.spi.PlatformBlockState; import art.arcane.iris.engine.object.IrisRuinDecorator; import art.arcane.iris.util.common.math.Vector3i; import art.arcane.volmlib.util.math.RNG; -import org.bukkit.block.data.BlockData; import java.util.ArrayList; import java.util.HashMap; @@ -48,7 +48,7 @@ final class RuinDecoratorApplier { if (!rng.chance(decorator.getChance())) { continue; } - BlockData bd = IrisProceduralBlocks.resolve(decorator.getBlock(), decorator.getPalette(), data, v.getBlockX(), v.getBlockY(), v.getBlockZ(), paletteRng); + PlatformBlockState bd = IrisProceduralBlocks.resolve(decorator.getBlock(), decorator.getPalette(), data, v.getBlockX(), v.getBlockY(), v.getBlockZ(), paletteRng); if (bd != null) { canvas.accent(v.getBlockX(), v.getBlockY(), v.getBlockZ(), bd); } diff --git a/core/src/main/java/art/arcane/iris/engine/object/ruin/RuinGenerator.java b/core/src/main/java/art/arcane/iris/engine/object/ruin/RuinGenerator.java index a8fb9555c..f63a7dc23 100644 --- a/core/src/main/java/art/arcane/iris/engine/object/ruin/RuinGenerator.java +++ b/core/src/main/java/art/arcane/iris/engine/object/ruin/RuinGenerator.java @@ -21,11 +21,11 @@ package art.arcane.iris.engine.object.ruin; import art.arcane.iris.core.loader.IrisData; import art.arcane.iris.engine.object.IrisObject; import art.arcane.iris.engine.object.IrisProceduralBlocks; +import art.arcane.iris.spi.PlatformBlockState; import art.arcane.iris.engine.object.IrisRuin; import art.arcane.iris.engine.object.tree.TreeFunctions; import art.arcane.iris.util.common.math.Vector3i; import art.arcane.volmlib.util.math.RNG; -import org.bukkit.block.data.BlockData; import java.util.ArrayList; import java.util.HashMap; @@ -148,11 +148,11 @@ public final class RuinGenerator { } int span = Math.max(1, maxY - minY); - Map blocks = new HashMap<>(); + Map blocks = new HashMap<>(); for (Map.Entry entry : canvas.cells().entrySet()) { Vector3i v = entry.getKey(); RuinBlockCanvas.Cell cell = entry.getValue(); - BlockData bd; + PlatformBlockState bd; if (cell.role() == RuinBlockCanvas.Role.ACCENT) { bd = cell.accentData(); } else { @@ -166,7 +166,7 @@ public final class RuinGenerator { return IrisProceduralBlocks.assemble(blocks); } - private static BlockData structuralBlock(IrisRuin ruin, RuinBlockCanvas.Cell cell, Vector3i v, IrisData data, RNG paletteRng, double scale, double mossiness, long weatherSeed, int minY, int span) { + private static PlatformBlockState structuralBlock(IrisRuin ruin, RuinBlockCanvas.Cell cell, Vector3i v, IrisData data, RNG paletteRng, double scale, double mossiness, long weatherSeed, int minY, int span) { boolean weathered = false; if (mossiness > 0.0) { int sx = (int) Math.round(v.getBlockX() * scale); @@ -179,7 +179,7 @@ public final class RuinGenerator { } if (weathered) { - BlockData wd = IrisProceduralBlocks.resolve(ruin.getWeatheredBlock(), ruin.getWeatheringPalette(), data, v.getBlockX(), v.getBlockY(), v.getBlockZ(), paletteRng); + PlatformBlockState wd = IrisProceduralBlocks.resolve(ruin.getWeatheredBlock(), ruin.getWeatheringPalette(), data, v.getBlockX(), v.getBlockY(), v.getBlockZ(), paletteRng); if (wd != null) { return wd; } diff --git a/core/src/main/java/art/arcane/iris/engine/object/tree/ProceduralTreeGenerator.java b/core/src/main/java/art/arcane/iris/engine/object/tree/ProceduralTreeGenerator.java index 2ca8220e8..a6dbe7e36 100644 --- a/core/src/main/java/art/arcane/iris/engine/object/tree/ProceduralTreeGenerator.java +++ b/core/src/main/java/art/arcane/iris/engine/object/tree/ProceduralTreeGenerator.java @@ -21,10 +21,9 @@ package art.arcane.iris.engine.object.tree; import art.arcane.iris.core.loader.IrisData; import art.arcane.iris.engine.object.IrisObject; import art.arcane.iris.engine.object.IrisProceduralTree; -import art.arcane.iris.platform.bukkit.BukkitBlockState; +import art.arcane.iris.spi.PlatformBlockState; import art.arcane.iris.util.common.math.IrisBlockVector; import art.arcane.volmlib.util.math.RNG; -import org.bukkit.block.data.BlockData; import java.util.ArrayList; import java.util.HashMap; @@ -64,16 +63,16 @@ public final class ProceduralTreeGenerator { TreeSupport.ensureLeavesSupported(canvas, 24); } - Map resolved = new HashMap<>(); + Map resolved = new HashMap<>(); Set trunkPositions = new HashSet<>(); Set leafPositions = new HashSet<>(); for (Map.Entry entry : canvas.getCells().entrySet()) { TreeBlockCanvas.Cell cell = entry.getValue(); - BlockData bd = TreeBlockResolver.resolve(tree, data, cell, entry.getKey()); - if (bd == null) { + PlatformBlockState state = TreeBlockResolver.resolve(tree, data, cell, entry.getKey()); + if (state == null) { continue; } - resolved.put(entry.getKey(), bd); + resolved.put(entry.getKey(), state); if (cell.role() == TreeBlockCanvas.Role.TRUNK || cell.role() == TreeBlockCanvas.Role.SECONDARY_TRUNK) { trunkPositions.add(entry.getKey()); } else if (cell.role() == TreeBlockCanvas.Role.LEAF || cell.role() == TreeBlockCanvas.Role.SECONDARY_LEAF) { @@ -86,7 +85,7 @@ public final class ProceduralTreeGenerator { return assemble(resolved); } - private static IrisObject assemble(Map resolved) { + private static IrisObject assemble(Map resolved) { if (resolved.isEmpty()) { return null; } @@ -114,12 +113,12 @@ public final class ProceduralTreeGenerator { int cz = d / 2; IrisObject object = new IrisObject(w, h, d); - for (Map.Entry entry : resolved.entrySet()) { + for (Map.Entry entry : resolved.entrySet()) { TreeBlockCanvas.Vec v = entry.getKey(); int nx = v.x() - minX - cx; int ny = v.y() - cy + 1; int nz = v.z() - minZ - cz; - object.getBlocks().put(new IrisBlockVector(nx, ny, nz), BukkitBlockState.of(entry.getValue())); + object.getBlocks().put(new IrisBlockVector(nx, ny, nz), entry.getValue()); } return object; diff --git a/core/src/main/java/art/arcane/iris/engine/object/tree/TreeBlockResolver.java b/core/src/main/java/art/arcane/iris/engine/object/tree/TreeBlockResolver.java index 3bf810f29..04c73e4af 100644 --- a/core/src/main/java/art/arcane/iris/engine/object/tree/TreeBlockResolver.java +++ b/core/src/main/java/art/arcane/iris/engine/object/tree/TreeBlockResolver.java @@ -18,50 +18,44 @@ package art.arcane.iris.engine.object.tree; -import art.arcane.iris.platform.bukkit.BukkitBlockResolution; - import art.arcane.iris.core.loader.IrisData; import art.arcane.iris.engine.object.IrisMaterialPalette; +import art.arcane.iris.engine.object.IrisProceduralBlocks; import art.arcane.iris.engine.object.IrisProceduralTree; import art.arcane.iris.engine.object.IrisTreeDecorator; import art.arcane.iris.spi.PlatformBlockState; +import art.arcane.iris.util.common.data.B; import art.arcane.volmlib.util.math.RNG; -import org.bukkit.Axis; -import org.bukkit.Material; -import org.bukkit.block.BlockFace; -import org.bukkit.block.data.BlockData; -import org.bukkit.block.data.Directional; -import org.bukkit.block.data.Orientable; public final class TreeBlockResolver { private TreeBlockResolver() { } - public static BlockData resolve(IrisProceduralTree tree, IrisData data, TreeBlockCanvas.Cell cell, TreeBlockCanvas.Vec pos) { + public static PlatformBlockState resolve(IrisProceduralTree tree, IrisData data, TreeBlockCanvas.Cell cell, TreeBlockCanvas.Vec pos) { RNG paletteRng = new RNG(tree.getSeed()); RNG posRng = new RNG(tree.getSeed() ^ positionHash(pos)); switch (cell.role()) { case TRUNK -> { - BlockData bd = resolveBlock(tree.getTrunk(), tree.getTrunkPalette(), data, pos, paletteRng); - return finishTrunk(bd, cell); + PlatformBlockState state = resolveBlock(tree.getTrunk(), tree.getTrunkPalette(), data, pos, paletteRng); + return finishTrunk(state, cell); } case SECONDARY_TRUNK -> { - BlockData bd = resolveBlock(tree.getSecondaryTrunk(), tree.getSecondaryTrunkPalette(), data, pos, paletteRng); - if (bd == null) { - bd = resolveBlock(tree.getTrunk(), tree.getTrunkPalette(), data, pos, paletteRng); + PlatformBlockState state = resolveBlock(tree.getSecondaryTrunk(), tree.getSecondaryTrunkPalette(), data, pos, paletteRng); + if (state == null) { + state = resolveBlock(tree.getTrunk(), tree.getTrunkPalette(), data, pos, paletteRng); } - return finishTrunk(bd, cell); + return finishTrunk(state, cell); } case LEAF -> { return resolveBlock(tree.getLeaves(), tree.getLeavesPalette(), data, pos, paletteRng); } case SECONDARY_LEAF -> { - BlockData bd = resolveSecondaryLeaf(tree, data, pos, paletteRng, posRng); - if (bd == null) { - bd = resolveBlock(tree.getLeaves(), tree.getLeavesPalette(), data, pos, paletteRng); + PlatformBlockState state = resolveSecondaryLeaf(tree, data, pos, paletteRng, posRng); + if (state == null) { + state = resolveBlock(tree.getLeaves(), tree.getLeavesPalette(), data, pos, paletteRng); } - return bd; + return state; } case DECORATOR -> { int index = cell.decoratorIndex(); @@ -69,14 +63,14 @@ public final class TreeBlockResolver { return null; } IrisTreeDecorator dec = tree.getDecorators().get(index); - BlockData bd = resolveBlock(dec.getBlock(), dec.getPalette(), data, pos, paletteRng); - if (bd != null && cell.facing() != null && bd instanceof Directional directional) { + PlatformBlockState state = resolveBlock(dec.getBlock(), dec.getPalette(), data, pos, paletteRng); + if (state != null && cell.facing() != null && IrisProceduralBlocks.hasProperty(state, "facing")) { try { - directional.setFacing(BlockFace.valueOf(cell.facing().toUpperCase())); + state = state.withProperty("facing", cell.facing().toLowerCase()); } catch (IllegalArgumentException ignored) { } } - return bd; + return state; } default -> { return null; @@ -84,33 +78,32 @@ public final class TreeBlockResolver { } } - private static BlockData finishTrunk(BlockData bd, TreeBlockCanvas.Cell cell) { - if (bd == null) { + private static PlatformBlockState finishTrunk(PlatformBlockState state, TreeBlockCanvas.Cell cell) { + if (state == null) { return null; } - if (cell.axis() != TreeBlockCanvas.Axis.NONE && bd instanceof Orientable orientable) { + if (cell.axis() != TreeBlockCanvas.Axis.NONE && IrisProceduralBlocks.hasProperty(state, "axis")) { try { - orientable.setAxis(Axis.valueOf(cell.axis().name())); + state = state.withProperty("axis", cell.axis().name().toLowerCase()); } catch (IllegalArgumentException ignored) { } } if (cell.exposed()) { - return woodCap(bd); + return woodCap(state); } - return bd; + return state; } - private static BlockData resolveSecondaryLeaf(IrisProceduralTree tree, IrisData data, TreeBlockCanvas.Vec pos, RNG paletteRng, RNG posRng) { + private static PlatformBlockState resolveSecondaryLeaf(IrisProceduralTree tree, IrisData data, TreeBlockCanvas.Vec pos, RNG paletteRng, RNG posRng) { if (TreeTrunkBuilder.paletteSet(tree.getSecondaryLeavesPalette())) { - PlatformBlockState state = tree.getSecondaryLeavesPalette().get(paletteRng, pos.x(), pos.y(), pos.z(), data); - return state == null ? null : ((BlockData) state.nativeHandle()).clone(); + return tree.getSecondaryLeavesPalette().get(paletteRng, pos.x(), pos.y(), pos.z(), data); } if (tree.getWeightedSecondaryLeaves() != null && !tree.getWeightedSecondaryLeaves().isEmpty()) { String picked = pickWeighted(tree, posRng); - return picked == null ? null : cloneOrNull(BukkitBlockResolution.getOrNull(picked, false)); + return picked == null ? null : B.getStateOrNull(picked, false); } if (tree.getSecondaryLeaves() != null && !tree.getSecondaryLeaves().isEmpty()) { - return cloneOrNull(BukkitBlockResolution.getOrNull(tree.getSecondaryLeaves(), false)); + return B.getStateOrNull(tree.getSecondaryLeaves(), false); } return null; } @@ -134,42 +127,41 @@ public final class TreeBlockResolver { return tree.getWeightedSecondaryLeaves().get(tree.getWeightedSecondaryLeaves().size() - 1).getBlock(); } - private static BlockData resolveBlock(String block, IrisMaterialPalette palette, IrisData data, TreeBlockCanvas.Vec pos, RNG paletteRng) { + private static PlatformBlockState resolveBlock(String block, IrisMaterialPalette palette, IrisData data, TreeBlockCanvas.Vec pos, RNG paletteRng) { if (TreeTrunkBuilder.paletteSet(palette)) { - PlatformBlockState state = palette.get(paletteRng, pos.x(), pos.y(), pos.z(), data); - return state == null ? null : ((BlockData) state.nativeHandle()).clone(); + return palette.get(paletteRng, pos.x(), pos.y(), pos.z(), data); } if (block != null && !block.isEmpty()) { - return cloneOrNull(BukkitBlockResolution.getOrNull(block, false)); + return B.getStateOrNull(block, false); } return null; } - private static BlockData woodCap(BlockData bd) { - String name = bd.getMaterial().name(); - String woodName = null; - if (name.endsWith("_LOG")) { - woodName = name.substring(0, name.length() - 4) + "_WOOD"; - } else if (name.endsWith("_STEM")) { - woodName = name.substring(0, name.length() - 5) + "_HYPHAE"; + private static PlatformBlockState woodCap(PlatformBlockState state) { + String key = state.key(); + int bracket = key.indexOf('['); + String base = bracket < 0 ? key : key.substring(0, bracket); + String woodKey = null; + if (base.endsWith("_log")) { + woodKey = base.substring(0, base.length() - 4) + "_wood"; + } else if (base.endsWith("_stem")) { + woodKey = base.substring(0, base.length() - 5) + "_hyphae"; } - if (woodName == null) { - return bd; + if (woodKey == null) { + return state; } - try { - Material wood = Material.valueOf(woodName); - BlockData wb = wood.createBlockData(); - if (wb instanceof Orientable wo && bd instanceof Orientable bo) { - wo.setAxis(bo.getAxis()); + PlatformBlockState wood = B.getStateOrNull(woodKey, false); + if (wood == null) { + return state; + } + String axis = IrisProceduralBlocks.propertyValue(state, "axis"); + if (axis != null && IrisProceduralBlocks.hasProperty(wood, "axis")) { + try { + wood = wood.withProperty("axis", axis); + } catch (IllegalArgumentException ignored) { } - return wb; - } catch (IllegalArgumentException ignored) { - return bd; } - } - - private static BlockData cloneOrNull(BlockData bd) { - return bd == null ? null : bd.clone(); + return wood; } private static long positionHash(TreeBlockCanvas.Vec pos) { diff --git a/core/src/main/java/art/arcane/iris/engine/object/tree/TreePlausibility.java b/core/src/main/java/art/arcane/iris/engine/object/tree/TreePlausibility.java index 062e44357..b9e6af329 100644 --- a/core/src/main/java/art/arcane/iris/engine/object/tree/TreePlausibility.java +++ b/core/src/main/java/art/arcane/iris/engine/object/tree/TreePlausibility.java @@ -18,9 +18,9 @@ package art.arcane.iris.engine.object.tree; +import art.arcane.iris.engine.object.IrisProceduralBlocks; import art.arcane.iris.engine.object.IrisProceduralTree; -import org.bukkit.block.data.BlockData; -import org.bukkit.block.data.type.Leaves; +import art.arcane.iris.spi.PlatformBlockState; import java.util.ArrayDeque; import java.util.HashMap; @@ -37,12 +37,12 @@ public final class TreePlausibility { private TreePlausibility() { } - public static void apply(Map resolved, Set trunkPositions, + public static void apply(Map resolved, Set trunkPositions, Set leafPositions, IrisProceduralTree tree) { Set realLeaves = new HashSet<>(); for (TreeBlockCanvas.Vec v : leafPositions) { - BlockData bd = resolved.get(v); - if (bd instanceof Leaves) { + PlatformBlockState state = resolved.get(v); + if (state != null && IrisProceduralBlocks.hasProperty(state, "persistent") && IrisProceduralBlocks.hasProperty(state, "distance")) { realLeaves.add(v); } } @@ -53,18 +53,16 @@ public final class TreePlausibility { Map distance = computeDistances(trunkPositions, realLeaves); for (TreeBlockCanvas.Vec v : realLeaves) { - Leaves leaf = (Leaves) resolved.get(v); + PlatformBlockState leaf = resolved.get(v); Integer d = distance.get(v); if (!tree.isPlausible()) { - leaf.setPersistent(true); - leaf.setDistance(1); + leaf = leaf.withProperty("persistent", "true").withProperty("distance", "1"); } else if (d != null && d < MAX_DISTANCE) { - leaf.setPersistent(false); - leaf.setDistance(Math.max(1, d)); + leaf = leaf.withProperty("persistent", "false").withProperty("distance", String.valueOf(Math.max(1, d))); } else { - leaf.setPersistent(true); - leaf.setDistance(MAX_DISTANCE); + leaf = leaf.withProperty("persistent", "true").withProperty("distance", String.valueOf(MAX_DISTANCE)); } + resolved.put(v, leaf); } } diff --git a/core/src/main/java/art/arcane/iris/platform/bukkit/BukkitBlockState.java b/core/src/main/java/art/arcane/iris/platform/bukkit/BukkitBlockState.java index 57aac5217..d368b3106 100644 --- a/core/src/main/java/art/arcane/iris/platform/bukkit/BukkitBlockState.java +++ b/core/src/main/java/art/arcane/iris/platform/bukkit/BukkitBlockState.java @@ -39,6 +39,7 @@ public final class BukkitBlockState implements PlatformBlockState { private final String namespace; private volatile Boolean air; private volatile Boolean solid; + private volatile Boolean occluding; private volatile Boolean fluid; private volatile Boolean water; private volatile Boolean foliage; @@ -142,6 +143,21 @@ public final class BukkitBlockState implements PlatformBlockState { return cached; } + @Override + public boolean isOccluding() { + Boolean cached = occluding; + if (cached == null) { + cached = data.getMaterial().isOccluding(); + occluding = cached; + } + return cached; + } + + @Override + public boolean isCustom() { + return data instanceof IrisCustomData; + } + @Override public boolean isFluid() { Boolean cached = fluid; diff --git a/core/src/main/java/art/arcane/iris/util/common/data/B.java b/core/src/main/java/art/arcane/iris/util/common/data/B.java index ba174c1b4..c1bc517c4 100644 --- a/core/src/main/java/art/arcane/iris/util/common/data/B.java +++ b/core/src/main/java/art/arcane/iris/util/common/data/B.java @@ -41,6 +41,10 @@ public class B { return state != null && state.isSolid(); } + public static boolean isOccluding(PlatformBlockState state) { + return state != null && state.isOccluding(); + } + public static boolean isFluid(PlatformBlockState state) { return state != null && state.isFluid(); } diff --git a/core/src/main/java/art/arcane/iris/util/project/matter/IrisMatterSupport.java b/core/src/main/java/art/arcane/iris/util/project/matter/IrisMatterSupport.java index 262c70de0..af102fd75 100644 --- a/core/src/main/java/art/arcane/iris/util/project/matter/IrisMatterSupport.java +++ b/core/src/main/java/art/arcane/iris/util/project/matter/IrisMatterSupport.java @@ -23,6 +23,7 @@ import art.arcane.iris.engine.object.IrisObject; import art.arcane.iris.spi.IrisLogging; import art.arcane.iris.util.project.matter.slices.EntityMatter; import art.arcane.iris.util.project.matter.slices.IdentifierMatter; +import art.arcane.iris.util.project.matter.slices.PlatformBlockMatter; import art.arcane.iris.util.project.matter.slices.SpawnerMatter; import art.arcane.iris.util.project.matter.slices.TileMatter; import art.arcane.volmlib.util.matter.IrisMatter; @@ -59,6 +60,7 @@ public final class IrisMatterSupport { IrisMatter.registerSliceType(new EntityMatter()); IrisMatter.registerSliceType(new IdentifierMatter()); + IrisMatter.registerSliceType(new PlatformBlockMatter()); IrisMatter.registerSliceType(new SpawnerMatter()); IrisMatter.registerSliceType(new TileMatter()); registered = true; diff --git a/core/src/main/java/art/arcane/iris/util/project/matter/slices/PlatformBlockMatter.java b/core/src/main/java/art/arcane/iris/util/project/matter/slices/PlatformBlockMatter.java new file mode 100644 index 000000000..fc939a5cb --- /dev/null +++ b/core/src/main/java/art/arcane/iris/util/project/matter/slices/PlatformBlockMatter.java @@ -0,0 +1,39 @@ +package art.arcane.iris.util.project.matter.slices; + +import art.arcane.iris.spi.PlatformBlockState; +import art.arcane.iris.util.common.data.B; +import art.arcane.volmlib.util.data.palette.Palette; +import art.arcane.volmlib.util.matter.Sliced; +import art.arcane.volmlib.util.matter.slices.RawMatter; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +@Sliced +public class PlatformBlockMatter extends RawMatter { + + public PlatformBlockMatter() { + this(1, 1, 1); + } + + public PlatformBlockMatter(int width, int height, int depth) { + super(width, height, depth, PlatformBlockState.class); + } + + @Override + public Palette getGlobalPalette() { + return null; + } + + @Override + public void writeNode(PlatformBlockState b, DataOutputStream dos) throws IOException { + dos.writeUTF(b.key()); + } + + @Override + public PlatformBlockState readNode(DataInputStream din) throws IOException { + PlatformBlockState state = B.getState(din.readUTF()); + return state == null ? B.getAirState() : state; + } +} diff --git a/probe/src/main/java/art/arcane/iris/probe/StubPlatform.java b/probe/src/main/java/art/arcane/iris/probe/StubPlatform.java index 57cede732..7fa213c2b 100644 --- a/probe/src/main/java/art/arcane/iris/probe/StubPlatform.java +++ b/probe/src/main/java/art/arcane/iris/probe/StubPlatform.java @@ -88,6 +88,16 @@ public final class StubPlatform implements IrisPlatform { return !isAir(); } + @Override + public boolean isOccluding() { + return isSolid(); + } + + @Override + public boolean isCustom() { + return false; + } + @Override public boolean isFluid() { return false; diff --git a/spi/src/main/java/art/arcane/iris/spi/PlatformBlockState.java b/spi/src/main/java/art/arcane/iris/spi/PlatformBlockState.java index a9e348d82..0fdd0b888 100644 --- a/spi/src/main/java/art/arcane/iris/spi/PlatformBlockState.java +++ b/spi/src/main/java/art/arcane/iris/spi/PlatformBlockState.java @@ -30,6 +30,10 @@ public interface PlatformBlockState { boolean isSolid(); + boolean isOccluding(); + + boolean isCustom(); + boolean isFluid(); boolean isWater();