From e1196b0364fc559788d352ed4c027e219af19eda Mon Sep 17 00:00:00 2001 From: Brian Neumann-Fopiano Date: Thu, 11 Jun 2026 20:00:17 -0400 Subject: [PATCH] Vector Currency --- .../iris/core/commands/CommandObject.java | 5 +- .../iris/core/commands/CommandStudio.java | 2 +- .../iris/core/runtime/ObjectStudioLayout.java | 4 +- .../iris/core/tools/TreePlausibilizer.java | 12 +- .../iris/engine/decorator/DecoratorCore.java | 23 +- .../MantleFloatingObjectComponent.java | 16 +- .../components/MantleObjectComponent.java | 14 +- .../engine/modifier/IrisDepositModifier.java | 3 +- .../modifier/IrisPerfectionModifier.java | 67 ++-- .../engine/modifier/IrisPostModifier.java | 25 +- .../arcane/iris/engine/object/IrisBiome.java | 11 +- .../iris/engine/object/IrisCaveShape.java | 5 +- .../engine/object/IrisDepositGenerator.java | 5 +- .../iris/engine/object/IrisDimension.java | 4 - .../arcane/iris/engine/object/IrisObject.java | 218 +++++++------ .../engine/object/IrisObjectRotation.java | 46 ++- .../engine/object/IrisObjectTranslate.java | 10 +- .../engine/object/IrisProceduralBlocks.java | 3 +- .../object/tree/ProceduralTreeGenerator.java | 4 +- .../generators/ObjectStudioGenerator.java | 12 +- .../iris/util/common/data/VectorMap.java | 34 +- .../art/arcane/iris/util/common/format/C.java | 86 ++--- .../util/common/math/IrisBlockVector.java | 34 ++ .../iris/util/common/math/IrisVector.java | 163 ++++++++++ .../iris/util/common/math/Vector3i.java | 59 +++- .../iris/util/common/misc/Bindings.java | 2 +- .../iris/util/common/nbt/mca/NBTWorld.java | 41 +-- .../util/project/context/ChunkContext.java | 5 +- .../hunk/view/ChunkDataHunkHolder.java | 10 +- .../project/hunk/view/ChunkDataHunkView.java | 4 +- .../project/matter/IrisMatterSupport.java | 8 +- .../iris/util/project/sentry/ServerID.java | 10 +- .../object/IrisObjectRotationFlipTest.java | 18 +- .../context/ChunkContextPrefillPlanTest.java | 2 +- probe/build.gradle | 37 +++ .../art/arcane/iris/probe/ClassloadProbe.java | 137 ++++++++ .../art/arcane/iris/probe/StubPlatform.java | 300 ++++++++++++++++++ settings.gradle | 1 + 38 files changed, 1096 insertions(+), 344 deletions(-) create mode 100644 core/src/main/java/art/arcane/iris/util/common/math/IrisBlockVector.java create mode 100644 core/src/main/java/art/arcane/iris/util/common/math/IrisVector.java create mode 100644 probe/build.gradle create mode 100644 probe/src/main/java/art/arcane/iris/probe/ClassloadProbe.java create mode 100644 probe/src/main/java/art/arcane/iris/probe/StubPlatform.java diff --git a/adapters/bukkit/plugin/src/main/java/art/arcane/iris/core/commands/CommandObject.java b/adapters/bukkit/plugin/src/main/java/art/arcane/iris/core/commands/CommandObject.java index ed0b3955b..f00d14b6c 100644 --- a/adapters/bukkit/plugin/src/main/java/art/arcane/iris/core/commands/CommandObject.java +++ b/adapters/bukkit/plugin/src/main/java/art/arcane/iris/core/commands/CommandObject.java @@ -661,8 +661,9 @@ public class CommandObject implements DirectorExecutor { Iris.service(ObjectSVC.class).addChanges(futureChanges); if (edit) { - ItemStack newWand = WandSVC.createWand(block.clone().subtract(o.getCenter()).add(o.getW() - 1, - o.getH() + o.getCenter().clone().getY() - 1, o.getD() - 1), block.clone().subtract(o.getCenter().clone().setY(0))); + Vector center = new Vector(o.getCenter().getX(), o.getCenter().getY(), o.getCenter().getZ()); + ItemStack newWand = WandSVC.createWand(block.clone().subtract(center).add(o.getW() - 1, + o.getH() + center.getY() - 1, o.getD() - 1), block.clone().subtract(center.clone().setY(0))); if (WandSVC.isWand(wand)) { wand = newWand; player().getInventory().setItemInMainHand(wand); diff --git a/adapters/bukkit/plugin/src/main/java/art/arcane/iris/core/commands/CommandStudio.java b/adapters/bukkit/plugin/src/main/java/art/arcane/iris/core/commands/CommandStudio.java index 22e4ff19f..af68e9324 100644 --- a/adapters/bukkit/plugin/src/main/java/art/arcane/iris/core/commands/CommandStudio.java +++ b/adapters/bukkit/plugin/src/main/java/art/arcane/iris/core/commands/CommandStudio.java @@ -783,7 +783,7 @@ public class CommandStudio implements DirectorExecutor { } File ff = g.getData().getObjectLoader().findFile(i); - BlockVector sz = IrisObject.sampleSize(ff); + art.arcane.iris.util.common.math.IrisBlockVector sz = IrisObject.sampleSize(ff); nn3 = i + ": size=[" + sz.getBlockX() + "," + sz.getBlockY() + "," + sz.getBlockZ() + "] location=[" + ff.getPath() + "]"; stop.add(i); } catch (Throwable e) { diff --git a/core/src/main/java/art/arcane/iris/core/runtime/ObjectStudioLayout.java b/core/src/main/java/art/arcane/iris/core/runtime/ObjectStudioLayout.java index 5f2e56c91..f3669c505 100644 --- a/core/src/main/java/art/arcane/iris/core/runtime/ObjectStudioLayout.java +++ b/core/src/main/java/art/arcane/iris/core/runtime/ObjectStudioLayout.java @@ -23,7 +23,7 @@ import art.arcane.iris.core.loader.IrisData; import art.arcane.iris.engine.object.IrisObject; import art.arcane.volmlib.util.json.JSONArray; import art.arcane.volmlib.util.json.JSONObject; -import org.bukkit.util.BlockVector; +import art.arcane.iris.util.common.math.IrisBlockVector; import java.io.File; import java.nio.file.Files; @@ -96,7 +96,7 @@ public final class ObjectStudioLayout { if (file == null) { continue; } - BlockVector size; + IrisBlockVector size; try { size = IrisObject.sampleSize(file); } catch (Throwable e) { diff --git a/core/src/main/java/art/arcane/iris/core/tools/TreePlausibilizer.java b/core/src/main/java/art/arcane/iris/core/tools/TreePlausibilizer.java index 1b777d62b..c8ff25d77 100644 --- a/core/src/main/java/art/arcane/iris/core/tools/TreePlausibilizer.java +++ b/core/src/main/java/art/arcane/iris/core/tools/TreePlausibilizer.java @@ -29,7 +29,7 @@ import art.arcane.iris.spi.PlatformBlockState; import org.bukkit.block.data.BlockData; import org.bukkit.block.data.Orientable; import org.bukkit.block.data.type.Leaves; -import org.bukkit.util.BlockVector; +import art.arcane.iris.util.common.math.IrisBlockVector; import java.util.ArrayDeque; import java.util.ArrayList; @@ -92,8 +92,8 @@ public final class TreePlausibilizer { int minX = Integer.MAX_VALUE, minY = Integer.MAX_VALUE, minZ = Integer.MAX_VALUE; int maxX = Integer.MIN_VALUE, maxY = Integer.MIN_VALUE, maxZ = Integer.MIN_VALUE; - for (Map.Entry entry : blocks) { - BlockVector pos = entry.getKey(); + for (Map.Entry entry : blocks) { + IrisBlockVector pos = entry.getKey(); BlockData data = (BlockData) entry.getValue().nativeHandle(); long key = packKey(pos); positions.put(key, data); @@ -653,7 +653,7 @@ public final class TreePlausibilizer { return Tag.LEAVES.isTagged(data.getMaterial()) || data instanceof Leaves; } - private static long packKey(BlockVector pos) { + private static long packKey(IrisBlockVector pos) { return packXYZ(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ()); } @@ -671,9 +671,9 @@ public final class TreePlausibilizer { return new int[]{x, y, z}; } - private static BlockVector unpackKey(long key) { + private static IrisBlockVector unpackKey(long key) { int[] xyz = unpack(key); - return new BlockVector(xyz[0], xyz[1], xyz[2]); + return new IrisBlockVector(xyz[0], xyz[1], xyz[2]); } private record LogInsertion(long key, BlockData data) { 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 9af15220e..04e3b3040 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 @@ -230,7 +230,7 @@ final class DecoratorCore { } if (bd.nativeHandle() instanceof PointedDripstone) { - bd = BukkitBlockState.of(dripstoneBlock(stack, i, BlockFace.UP)); + bd = dripstoneBlock(stack, i, BlockFace.UP); } data.set(x, height + 1 + i, z, bd); @@ -264,7 +264,7 @@ final class DecoratorCore { : decorator.pickBlockData(rng, irisData, realX, realZ); if (bd != null && bd.nativeHandle() instanceof PointedDripstone) { - bd = BukkitBlockState.of(dripstoneBlock(stack, i, BlockFace.DOWN)); + bd = dripstoneBlock(stack, i, BlockFace.DOWN); } if (opts.caveSkipFluid && BukkitBlockResolution.isFluid(unwrap(data.get(x, h, z)))) { @@ -340,7 +340,8 @@ final class DecoratorCore { if (!BukkitBlockResolution.isVineBlock(rawB)) { return b; } - MultipleFacing data = (MultipleFacing) rawB.clone(); + BlockData cloned = rawB.clone(); + MultipleFacing data = (MultipleFacing) cloned; data.getFaces().forEach(f -> data.setFace(f, false)); boolean found = false; @@ -385,7 +386,7 @@ final class DecoratorCore { data.setFace(fallback, true); } } - return BukkitBlockState.of(data); + return BukkitBlockState.of(cloned); } static boolean canGoOn(PlatformBlockState decorator, PlatformBlockState surface) { @@ -407,28 +408,26 @@ final class DecoratorCore { return stack; } - // Lazily populated on first dripstone decoration — avoids Bukkit API at class-load time. - // Index: 0=TIP, 1=FRUSTUM, 2=BASE. Race on init is benign (only allocation cost, not correctness). - private static volatile BlockData[] dripstoneUp; - private static volatile BlockData[] dripstoneDown; + private static volatile PlatformBlockState[] dripstoneUp; + private static volatile PlatformBlockState[] dripstoneDown; - private static BlockData[] buildDripstoneArr(BlockFace direction) { + private static PlatformBlockState[] buildDripstoneArr(BlockFace direction) { PointedDripstone.Thickness[] order = { PointedDripstone.Thickness.TIP, PointedDripstone.Thickness.FRUSTUM, PointedDripstone.Thickness.BASE }; - BlockData[] arr = new BlockData[3]; + 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] = bd; + arr[k] = BukkitBlockState.of(bd); } return arr; } - private static BlockData dripstoneBlock(int stack, int i, BlockFace direction) { + private static PlatformBlockState dripstoneBlock(int stack, int i, BlockFace direction) { int thIdx; if (i == stack - 1) { thIdx = 0; 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 50635a3e5..f36a56c43 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 @@ -40,6 +40,7 @@ import art.arcane.iris.engine.object.IrisObjectTranslate; 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; import art.arcane.volmlib.util.documentation.ChunkCoordinates; @@ -48,7 +49,6 @@ import art.arcane.volmlib.util.math.RNG; import art.arcane.iris.spi.PlatformBlockState; import org.bukkit.Material; import org.bukkit.block.data.BlockData; -import org.bukkit.util.BlockVector; import java.io.File; import java.util.HashSet; @@ -384,7 +384,7 @@ public class MantleFloatingObjectComponent extends IrisMantleComponent { } private static boolean isFootprintFlatBottom(FloatingObjectFootprint fp, IrisObjectRotation rotation, int pickedXf, int pickedZf, int pickBottomY, FloatingIslandSample[] samples, int tolerance) { - BlockVector anchor = invertedFootprintAnchor(fp, rotation); + IrisBlockVector anchor = invertedFootprintAnchor(fp, rotation); int checked = 0; boolean touchedChunkEdge = false; long[] cells = fp.footprintXZ(); @@ -392,7 +392,7 @@ public class MantleFloatingObjectComponent extends IrisMantleComponent { long encoded = cells[i]; int kx = (int) (encoded >> 32); int kz = (int) (encoded & 0xFFFFFFFFL); - BlockVector cell = rotation.rotate(new BlockVector(kx, 0, kz), 0, 0, 0); + IrisBlockVector cell = rotation.rotate(new IrisBlockVector(kx, 0, kz), 0, 0, 0); int colXf = pickedXf + cell.getBlockX() - anchor.getBlockX(); int colZf = pickedZf + cell.getBlockZ() - anchor.getBlockZ(); if (colXf < 0 || colXf >= 16 || colZf < 0 || colZf >= 16) { @@ -439,12 +439,12 @@ public class MantleFloatingObjectComponent extends IrisMantleComponent { return minZ + pickedZf - invertedFootprintAnchor(fp, rotation).getBlockZ(); } - private static BlockVector invertedFootprintAnchor(FloatingObjectFootprint fp, IrisObjectRotation rotation) { - return rotation.rotate(new BlockVector(fp.getTallestKx(), 0, fp.getTallestKz()), 0, 0, 0); + private static IrisBlockVector invertedFootprintAnchor(FloatingObjectFootprint fp, IrisObjectRotation rotation) { + return rotation.rotate(new IrisBlockVector(fp.getTallestKx(), 0, fp.getTallestKz()), 0, 0, 0); } - private static BlockVector invertedSolidAnchor(FloatingObjectFootprint fp, IrisObjectRotation rotation) { - return rotation.rotate(new BlockVector(fp.getTallestKx(), fp.getLowestSolidKeyY(), fp.getTallestKz()), 0, 0, 0); + private static IrisBlockVector invertedSolidAnchor(FloatingObjectFootprint fp, IrisObjectRotation rotation) { + return rotation.rotate(new IrisBlockVector(fp.getTallestKx(), fp.getLowestSolidKeyY(), fp.getTallestKz()), 0, 0, 0); } private static boolean shouldWritePlacementMarker(IObjectPlacer placer, PlatformBlockState state, int x, int y, int z) { @@ -568,7 +568,7 @@ public class MantleFloatingObjectComponent extends IrisMantleComponent { if (f == null) { continue; } - BlockVector sz = IrisObject.sampleSize(f); + IrisBlockVector sz = IrisObject.sampleSize(f); int extent = Math.max(sz.getBlockX(), sz.getBlockZ()); if (extent > maxObjectExtent) { maxObjectExtent = extent; 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 9989d4c25..06bdeb876 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 @@ -49,7 +49,7 @@ import art.arcane.iris.util.project.noise.NoiseType; import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import art.arcane.iris.spi.PlatformBlockState; -import org.bukkit.util.BlockVector; +import art.arcane.iris.util.common.math.IrisBlockVector; import org.bukkit.block.data.BlockData; import java.io.IOException; @@ -1597,7 +1597,7 @@ public class MantleObjectComponent extends IrisMantleComponent { } } - KMap sizeCache = new KMap<>(); + KMap sizeCache = new KMap<>(); for (String i : objects) { updateRadiusBounds(sizeCache, xg, zg, i, 1D); } @@ -1635,14 +1635,14 @@ public class MantleObjectComponent extends IrisMantleComponent { } private void updateRadiusBounds( - KMap sizeCache, + KMap sizeCache, AtomicInteger xg, AtomicInteger zg, String objectKey, double scale ) { try { - BlockVector bv = loadObjectSize(sizeCache, objectKey); + IrisBlockVector bv = loadObjectSize(sizeCache, objectKey); if (bv == null) { throw new RuntimeException(); } @@ -1663,7 +1663,7 @@ public class MantleObjectComponent extends IrisMantleComponent { } private void updateVacuumRadiusBounds( - KMap sizeCache, + KMap sizeCache, AtomicInteger xg, AtomicInteger zg, IrisObjectPlacement placement @@ -1676,7 +1676,7 @@ public class MantleObjectComponent extends IrisMantleComponent { double scale = placement.getScale() != null ? Math.max(1D, placement.getScale().getMaxScale()) : 1D; for (String objectKey : placement.getPlace()) { try { - BlockVector bv = loadObjectSize(sizeCache, objectKey); + IrisBlockVector bv = loadObjectSize(sizeCache, objectKey); if (bv == null) { continue; } @@ -1691,7 +1691,7 @@ public class MantleObjectComponent extends IrisMantleComponent { } } - private BlockVector loadObjectSize(KMap sizeCache, String objectKey) { + private IrisBlockVector loadObjectSize(KMap sizeCache, String objectKey) { return sizeCache.computeIfAbsent(objectKey, k -> { try { return IrisObject.sampleSize(getData().getObjectLoader().findFile(objectKey)); 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 bd73dcb25..8b29aace2 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 @@ -35,7 +35,6 @@ import art.arcane.iris.platform.bukkit.BukkitBlockState; import art.arcane.iris.spi.PlatformBlockState; import org.bukkit.Material; import org.bukkit.block.data.BlockData; -import org.bukkit.util.BlockVector; public class IrisDepositModifier extends EngineAssignedModifier { private final RNG rng; @@ -125,7 +124,7 @@ public class IrisDepositModifier extends EngineAssignedModifier { - private static final PlatformBlockState AIR = B.getState("AIR"); - private static final PlatformBlockState WATER = B.getState("WATER"); - private static final Map ORE_BASES = buildOreBases(); + private static final class States { + private static final PlatformBlockState AIR = B.getState("AIR"); + private static final PlatformBlockState WATER = B.getState("WATER"); + private static final Map ORE_BASES = buildOreBases(); + } public IrisPerfectionModifier(Engine engine) { super(engine, "Perfection"); } - private static Map buildOreBases() { - Map map = new EnumMap<>(Material.class); + private static Map buildOreBases() { + Map map = new HashMap<>(); PlatformBlockState stone = B.getState("STONE"); PlatformBlockState deepslate = B.getState("DEEPSLATE"); PlatformBlockState netherrack = B.getState("NETHERRACK"); PlatformBlockState blackstone = B.getState("BLACKSTONE"); - map.put(Material.COAL_ORE, stone); - map.put(Material.COPPER_ORE, stone); - map.put(Material.IRON_ORE, stone); - map.put(Material.GOLD_ORE, stone); - map.put(Material.REDSTONE_ORE, stone); - map.put(Material.LAPIS_ORE, stone); - map.put(Material.DIAMOND_ORE, stone); - map.put(Material.EMERALD_ORE, stone); - map.put(Material.DEEPSLATE_COAL_ORE, deepslate); - map.put(Material.DEEPSLATE_COPPER_ORE, deepslate); - map.put(Material.DEEPSLATE_IRON_ORE, deepslate); - map.put(Material.DEEPSLATE_GOLD_ORE, deepslate); - map.put(Material.DEEPSLATE_REDSTONE_ORE, deepslate); - map.put(Material.DEEPSLATE_LAPIS_ORE, deepslate); - map.put(Material.DEEPSLATE_DIAMOND_ORE, deepslate); - map.put(Material.DEEPSLATE_EMERALD_ORE, deepslate); - map.put(Material.NETHER_GOLD_ORE, netherrack); - map.put(Material.NETHER_QUARTZ_ORE, netherrack); - map.put(Material.ANCIENT_DEBRIS, netherrack); - map.put(Material.GILDED_BLACKSTONE, blackstone); + map.put("minecraft:coal_ore", stone); + map.put("minecraft:copper_ore", stone); + map.put("minecraft:iron_ore", stone); + map.put("minecraft:gold_ore", stone); + map.put("minecraft:redstone_ore", stone); + map.put("minecraft:lapis_ore", stone); + map.put("minecraft:diamond_ore", stone); + map.put("minecraft:emerald_ore", stone); + map.put("minecraft:deepslate_coal_ore", deepslate); + map.put("minecraft:deepslate_copper_ore", deepslate); + map.put("minecraft:deepslate_iron_ore", deepslate); + map.put("minecraft:deepslate_gold_ore", deepslate); + map.put("minecraft:deepslate_redstone_ore", deepslate); + map.put("minecraft:deepslate_lapis_ore", deepslate); + map.put("minecraft:deepslate_diamond_ore", deepslate); + map.put("minecraft:deepslate_emerald_ore", deepslate); + map.put("minecraft:nether_gold_ore", netherrack); + map.put("minecraft:nether_quartz_ore", netherrack); + map.put("minecraft:ancient_debris", netherrack); + map.put("minecraft:gilded_blackstone", blackstone); return map; } + private static String baseKey(PlatformBlockState state) { + String key = state.key(); + int bracket = key.indexOf('['); + return bracket < 0 ? key : key.substring(0, bracket); + } + @Override public void onModify(int x, int z, Hunk output, boolean multicore, ChunkContext context) { PrecisionStopwatch p = PrecisionStopwatch.start(); @@ -147,11 +154,11 @@ public class IrisPerfectionModifier extends EngineAssignedModifier { - private static final PlatformBlockState AIR = B.getState("AIR"); - private static final PlatformBlockState WATER = B.getState("WATER"); + private static final class States { + private static final PlatformBlockState AIR = B.getState("AIR"); + private static final PlatformBlockState WATER = B.getState("WATER"); + } + private final RNG rng; public IrisPostModifier(Engine engine) { @@ -87,7 +90,7 @@ public class IrisPostModifier extends EngineAssignedModifier g += hd < h - 1 ? 1 : 0; if (g == 4 && isAir(x, h - 1, z, currentPostX, currentPostZ, currentData)) { - setPostBlock(x, h, z, AIR, currentPostX, currentPostZ, currentData); + setPostBlock(x, h, z, States.AIR, currentPostX, currentPostZ, currentData); for (int i = h - 1; i > 0; i--) { if (!isAir(x, i, z, currentPostX, currentPostZ, currentData)) { @@ -207,7 +210,8 @@ public class IrisPostModifier extends EngineAssignedModifier BlockData b = (BlockData) getPostBlock(x, h, z, currentPostX, currentPostZ, currentData).nativeHandle(); if (b instanceof Waterlogged) { - Waterlogged ww = (Waterlogged) b.clone(); + BlockData cloned = b.clone(); + Waterlogged ww = (Waterlogged) cloned; boolean w = false; if (h <= getDimension().getFluidHeight() + 1) { @@ -220,11 +224,11 @@ public class IrisPostModifier extends EngineAssignedModifier if (w != ww.isWaterlogged()) { ww.setWaterlogged(w); - setPostBlock(x, h, z, BukkitBlockState.of(ww), currentPostX, currentPostZ, currentData); + setPostBlock(x, h, z, BukkitBlockState.of(cloned), currentPostX, currentPostZ, currentData); } } else if (b.getMaterial().equals(Material.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, WATER, currentPostX, currentPostZ, currentData); + setPostBlock(x, h, z, States.WATER, currentPostX, currentPostZ, currentData); } } @@ -232,7 +236,8 @@ public class IrisPostModifier extends EngineAssignedModifier b = (BlockData) getPostBlock(x, h + 1, z, currentPostX, currentPostZ, currentData).nativeHandle(); if (BukkitBlockResolution.isVineBlock(b) && b instanceof MultipleFacing) { - MultipleFacing f = (MultipleFacing) b.clone(); + BlockData cloned = b.clone(); + MultipleFacing f = (MultipleFacing) cloned; int finalH = h + 1; f.getAllowedFaces().forEach(face -> { @@ -240,7 +245,7 @@ public class IrisPostModifier extends EngineAssignedModifier f.setFace(face, !BukkitBlockResolution.isAir(d) && !BukkitBlockResolution.isVineBlock(d)); }); if (!f.equals(b)) { - setPostBlock(x, h + 1, z, BukkitBlockState.of(f), currentPostX, currentPostZ, currentData); + setPostBlock(x, h + 1, z, BukkitBlockState.of(cloned), currentPostX, currentPostZ, currentData); } } @@ -248,7 +253,7 @@ public class IrisPostModifier extends EngineAssignedModifier Material onto = ((BlockData) getPostBlock(x, h, z, currentPostX, currentPostZ, currentData).nativeHandle()).getMaterial(); if (!BukkitBlockResolution.canPlaceOnto(b.getMaterial(), onto) && !BukkitBlockResolution.isDecorant(b)) { - setPostBlock(x, h + 1, z, AIR, currentPostX, currentPostZ, currentData); + setPostBlock(x, h + 1, z, States.AIR, currentPostX, currentPostZ, currentData); } } } @@ -312,6 +317,6 @@ public class IrisPostModifier extends EngineAssignedModifier public PlatformBlockState getPostBlock(int x, int y, int z, int cpx, int cpz, Hunk h) { PlatformBlockState b = h.getClosest(x & 15, y, z & 15); - return b == null ? AIR : b; + return b == null ? States.AIR : b; } } diff --git a/core/src/main/java/art/arcane/iris/engine/object/IrisBiome.java b/core/src/main/java/art/arcane/iris/engine/object/IrisBiome.java index 03668e8df..5f9da1cbd 100644 --- a/core/src/main/java/art/arcane/iris/engine/object/IrisBiome.java +++ b/core/src/main/java/art/arcane/iris/engine/object/IrisBiome.java @@ -43,9 +43,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; -import art.arcane.iris.platform.bukkit.BukkitBlockState; import art.arcane.iris.spi.PlatformBlockState; -import org.bukkit.Material; import org.bukkit.block.Biome; import java.awt.*; @@ -58,7 +56,10 @@ import java.util.EnumMap; @Data @EqualsAndHashCode(callSuper = false) public class IrisBiome extends IrisRegistrant implements IRare { - private static final PlatformBlockState BARRIER = BukkitBlockState.of(Material.BARRIER.createBlockData()); + private static final class States { + private static final PlatformBlockState BARRIER = B.getState("BARRIER"); + } + private final transient AtomicCache> genCache = new AtomicCache<>(); private final transient AtomicCache> genCacheMax = new AtomicCache<>(); private final transient AtomicCache> genCacheMin = new AtomicCache<>(); @@ -445,7 +446,7 @@ public class IrisBiome extends IrisRegistrant implements IRare { if (dim.isExplodeBiomePalettes()) { for (int j = 0; j < dim.getExplodeBiomePaletteSize(); j++) { - data.add(BARRIER); + data.add(States.BARRIER); if (data.size() >= maxDepth) { break; @@ -491,7 +492,7 @@ public class IrisBiome extends IrisRegistrant implements IRare { if (dim.isExplodeBiomePalettes()) { for (int j = 0; j < dim.getExplodeBiomePaletteSize(); j++) { - data.add(BARRIER); + data.add(States.BARRIER); if (data.size() >= maxDepth) { break; diff --git a/core/src/main/java/art/arcane/iris/engine/object/IrisCaveShape.java b/core/src/main/java/art/arcane/iris/engine/object/IrisCaveShape.java index 1990a146a..bd58d59b1 100644 --- a/core/src/main/java/art/arcane/iris/engine/object/IrisCaveShape.java +++ b/core/src/main/java/art/arcane/iris/engine/object/IrisCaveShape.java @@ -1,7 +1,7 @@ package art.arcane.iris.engine.object; -import art.arcane.iris.platform.bukkit.BukkitPlatform; import art.arcane.iris.engine.framework.Engine; +import art.arcane.iris.util.common.math.IrisBlockVector; import art.arcane.iris.engine.object.annotations.*; import art.arcane.volmlib.util.collection.KMap; import art.arcane.volmlib.util.collection.KSet; @@ -45,7 +45,8 @@ public class IrisCaveShape { var rotated = new KSet(); engine.getData().getObjectLoader().load(object).getBlocks().forEach((vector, data) -> { if (data.isAir()) return; - rotated.add(BukkitPlatform.positionOf(objectRotation.rotate(vector, pos.getX(), pos.getY(), pos.getZ()))); + IrisBlockVector rot = objectRotation.rotate(vector, pos.getX(), pos.getY(), pos.getZ()); + rotated.add(new IrisPosition(rot.getBlockX(), rot.getBlockY(), rot.getBlockZ())); }); return rotated; }); diff --git a/core/src/main/java/art/arcane/iris/engine/object/IrisDepositGenerator.java b/core/src/main/java/art/arcane/iris/engine/object/IrisDepositGenerator.java index dae7cc05a..fb5a0090e 100644 --- a/core/src/main/java/art/arcane/iris/engine/object/IrisDepositGenerator.java +++ b/core/src/main/java/art/arcane/iris/engine/object/IrisDepositGenerator.java @@ -22,6 +22,8 @@ import art.arcane.iris.core.loader.IrisData; import art.arcane.iris.engine.data.cache.AtomicCache; import art.arcane.iris.engine.framework.Engine; import art.arcane.iris.engine.object.annotations.*; +import art.arcane.iris.util.common.math.IrisBlockVector; +import art.arcane.iris.util.common.math.Vector3i; import art.arcane.volmlib.util.collection.KList; import art.arcane.volmlib.util.collection.KSet; import art.arcane.volmlib.util.math.BlockPosition; @@ -113,7 +115,8 @@ public class IrisDepositGenerator { int s = rngv.i(minSize, maxSize + 1); if (s == 1) { IrisObject o = new IrisObject(1, 1, 1); - o.getBlocks().put(o.getCenter(), nextBlock(rngv, rdata)); + Vector3i center = o.getCenter(); + o.getBlocks().put(new IrisBlockVector(center.getX(), center.getY(), center.getZ()), nextBlock(rngv, rdata)); return o; } diff --git a/core/src/main/java/art/arcane/iris/engine/object/IrisDimension.java b/core/src/main/java/art/arcane/iris/engine/object/IrisDimension.java index 9ff2364b1..f3f868f7c 100644 --- a/core/src/main/java/art/arcane/iris/engine/object/IrisDimension.java +++ b/core/src/main/java/art/arcane/iris/engine/object/IrisDimension.java @@ -21,7 +21,6 @@ package art.arcane.iris.engine.object; import art.arcane.iris.core.IrisSettings; import art.arcane.iris.core.ServerConfigurator.DimensionHeight; import art.arcane.iris.core.loader.IrisData; -import art.arcane.iris.platform.bukkit.BukkitBlockState; import art.arcane.iris.platform.bukkit.BukkitPlatform; import art.arcane.iris.spi.IrisLogging; import art.arcane.iris.spi.PlatformBlockState; @@ -49,7 +48,6 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; -import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.World.Environment; import org.bukkit.block.Biome; @@ -70,8 +68,6 @@ import java.util.Map; @Data @EqualsAndHashCode(callSuper = false) public class IrisDimension extends IrisRegistrant { - public static final PlatformBlockState STONE = BukkitBlockState.of(Material.STONE.createBlockData()); - public static final PlatformBlockState WATER = BukkitBlockState.of(Material.WATER.createBlockData()); private final transient AtomicCache parallaxSize = new AtomicCache<>(); private final transient AtomicCache rockLayerGenerator = new AtomicCache<>(); private final transient AtomicCache fluidLayerGenerator = new AtomicCache<>(); 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 1b17ab5a2..9c999f46f 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 @@ -20,7 +20,6 @@ package art.arcane.iris.engine.object; import art.arcane.iris.platform.bukkit.BukkitBlockResolution; -import art.arcane.iris.platform.bukkit.BukkitPlatform; import art.arcane.iris.core.loader.IrisData; import art.arcane.iris.core.loader.IrisRegistrant; import art.arcane.iris.engine.data.cache.AtomicCache; @@ -66,8 +65,6 @@ 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 org.bukkit.util.BlockVector; -import org.bukkit.util.Vector; import java.io.*; import java.util.*; @@ -82,10 +79,12 @@ import java.util.stream.StreamSupport; @Accessors(chain = true) @EqualsAndHashCode(callSuper = false) public class IrisObject extends IrisRegistrant { - protected static final Vector HALF = new Vector(0.5, 0.5, 0.5); - protected static final PlatformBlockState AIR = B.getState("CAVE_AIR"); - protected static final PlatformBlockState STONE = B.getState("STONE"); - protected static final PlatformBlockState VAIR = B.getState("VOID_AIR"); + protected static final IrisVector HALF = new IrisVector(0.5, 0.5, 0.5); + static final class States { + static final PlatformBlockState AIR = B.getState("CAVE_AIR"); + static final PlatformBlockState STONE = B.getState("STONE"); + static final PlatformBlockState VAIR = B.getState("VOID_AIR"); + } protected static final PlatformBlockState VAIR_DEBUG = B.getState("COBWEB"); protected static final PlatformBlockState[] SNOW_LAYERS = new PlatformBlockState[]{B.getState("minecraft:snow[layers=1]"), B.getState("minecraft:snow[layers=2]"), B.getState("minecraft:snow[layers=3]"), B.getState("minecraft:snow[layers=4]"), B.getState("minecraft:snow[layers=5]"), B.getState("minecraft:snow[layers=6]"), B.getState("minecraft:snow[layers=7]"), B.getState("minecraft:snow[layers=8]")}; private static final long IMPLAUSIBLE_BEDROCK_WARN_THROTTLE_MS = 5000L; @@ -134,24 +133,22 @@ public class IrisObject extends IrisRegistrant { this(0, 0, 0); } - public static BlockVector getCenterForSize(BlockVector size) { - return new BlockVector(size.getX() / 2, size.getY() / 2, size.getZ() / 2); + public static AxisAlignedBB getAABBFor(IrisBlockVector size) { + IrisBlockVector center = new IrisBlockVector(size.getX() / 2, size.getY() / 2, size.getZ() / 2); + IrisVector min = new IrisBlockVector(0, 0, 0).subtract(center); + IrisVector max = new IrisBlockVector(size.getX() - 1, size.getY() - 1, size.getZ() - 1).subtract(center); + return new AxisAlignedBB(new IrisPosition(min.getBlockX(), min.getBlockY(), min.getBlockZ()), + new IrisPosition(max.getBlockX(), max.getBlockY(), max.getBlockZ())); } - public static AxisAlignedBB getAABBFor(BlockVector size) { - BlockVector center = new BlockVector(size.getX() / 2, size.getY() / 2, size.getZ() / 2); - return new AxisAlignedBB(BukkitPlatform.positionOf(new BlockVector(0, 0, 0).subtract(center).toBlockVector()), - BukkitPlatform.positionOf(new BlockVector(size.getX() - 1, size.getY() - 1, size.getZ() - 1).subtract(center).toBlockVector())); - } - - public static BlockVector sampleSize(File file) throws IOException { + public static IrisBlockVector sampleSize(File file) throws IOException { try (DataInputStream din = new DataInputStream(new FileInputStream(file))) { - return new BlockVector(din.readInt(), din.readInt(), din.readInt()); + return new IrisBlockVector(din.readInt(), din.readInt(), din.readInt()); } } - private static List blocksBetweenTwoPoints(Vector loc1, Vector loc2) { - List locations = new ArrayList<>(); + private static List blocksBetweenTwoPoints(IrisVector loc1, IrisVector loc2) { + List locations = new ArrayList<>(); int topBlockX = Math.max(loc1.getBlockX(), loc2.getBlockX()); int bottomBlockX = Math.min(loc1.getBlockX(), loc2.getBlockX()); int topBlockY = Math.max(loc1.getBlockY(), loc2.getBlockY()); @@ -162,7 +159,7 @@ public class IrisObject extends IrisRegistrant { for (int x = bottomBlockX; x <= topBlockX; x++) { for (int z = bottomBlockZ; z <= topBlockZ; z++) { for (int y = bottomBlockY; y <= topBlockY; y++) { - locations.add(new BlockVector(x, y, z)); + locations.add(new IrisBlockVector(x, y, z)); } } } @@ -181,7 +178,7 @@ public class IrisObject extends IrisRegistrant { } public AxisAlignedBB getAABB() { - return aabb.aquire(() -> getAABBFor(new BlockVector(w, h, d))); + return aabb.aquire(() -> getAABBFor(new IrisBlockVector(w, h, d))); } public void ensureSmartBored(boolean debug) { @@ -190,7 +187,7 @@ public class IrisObject extends IrisRegistrant { } PrecisionStopwatch p = PrecisionStopwatch.start(); - PlatformBlockState vair = debug ? VAIR_DEBUG : VAIR; + PlatformBlockState vair = debug ? VAIR_DEBUG : States.VAIR; writeLock.lock(); AtomicInteger applied = new AtomicInteger(); if (blocks.isEmpty()) { @@ -200,10 +197,10 @@ public class IrisObject extends IrisRegistrant { return; } - BlockVector max = new BlockVector(Double.MIN_VALUE, Double.MIN_VALUE, Double.MIN_VALUE); - BlockVector min = new BlockVector(Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE); + IrisBlockVector max = new IrisBlockVector(Double.MIN_VALUE, Double.MIN_VALUE, Double.MIN_VALUE); + IrisBlockVector min = new IrisBlockVector(Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE); - for (BlockVector i : blocks.keys()) { + for (IrisBlockVector i : blocks.keys()) { max.setX(Math.max(i.getX(), max.getX())); min.setX(Math.min(i.getX(), min.getX())); max.setY(Math.max(i.getY(), max.getY())); @@ -223,7 +220,7 @@ public class IrisObject extends IrisRegistrant { int end = Integer.MIN_VALUE; for (int ray = min.getBlockX(); ray <= max.getBlockX(); ray++) { - if (blocks.containsKey(new Vector3i(ray, finalRayY, rayZ))) { + if (blocks.containsKey(new IrisBlockVector(ray, finalRayY, rayZ))) { start = Math.min(ray, start); end = Math.max(ray, end); } @@ -231,7 +228,7 @@ public class IrisObject extends IrisRegistrant { if (start != Integer.MAX_VALUE && end != Integer.MIN_VALUE) { for (int i = start; i <= end; i++) { - Vector3i v = new Vector3i(i, finalRayY, rayZ); + IrisBlockVector v = new IrisBlockVector(i, finalRayY, rayZ); if (!vair.equals(blocks.get(v))) { blocks.computeIfAbsent(v, (vv) -> vair); @@ -252,7 +249,7 @@ public class IrisObject extends IrisRegistrant { int end = Integer.MIN_VALUE; for (int ray = min.getBlockY(); ray <= max.getBlockY(); ray++) { - if (blocks.containsKey(new Vector3i(finalRayX, ray, rayZ))) { + if (blocks.containsKey(new IrisBlockVector(finalRayX, ray, rayZ))) { start = Math.min(ray, start); end = Math.max(ray, end); } @@ -260,7 +257,7 @@ public class IrisObject extends IrisRegistrant { if (start != Integer.MAX_VALUE && end != Integer.MIN_VALUE) { for (int i = start; i <= end; i++) { - Vector3i v = new Vector3i(finalRayX, i, rayZ); + IrisBlockVector v = new IrisBlockVector(finalRayX, i, rayZ); if (!vair.equals(blocks.get(v))) { blocks.computeIfAbsent(v, (vv) -> vair); @@ -281,7 +278,7 @@ public class IrisObject extends IrisRegistrant { int end = Integer.MIN_VALUE; for (int ray = min.getBlockZ(); ray <= max.getBlockZ(); ray++) { - if (blocks.containsKey(new Vector3i(finalRayX, rayY, ray))) { + if (blocks.containsKey(new IrisBlockVector(finalRayX, rayY, ray))) { start = Math.min(ray, start); end = Math.max(ray, end); } @@ -289,7 +286,7 @@ public class IrisObject extends IrisRegistrant { if (start != Integer.MAX_VALUE && end != Integer.MIN_VALUE) { for (int i = start; i <= end; i++) { - Vector3i v = new Vector3i(finalRayX, rayY, i); + IrisBlockVector v = new IrisBlockVector(finalRayX, rayY, i); if (!vair.equals(blocks.get(v))) { blocks.computeIfAbsent(v, (vv) -> vair); @@ -329,7 +326,7 @@ public class IrisObject extends IrisRegistrant { int s = din.readInt(); for (int i = 0; i < s; i++) { - Vector3i pos = new Vector3i(din.readShort(), din.readShort(), din.readShort()); + IrisBlockVector pos = new IrisBlockVector(din.readShort(), din.readShort(), din.readShort()); BlockData data = BukkitBlockResolution.get(din.readUTF()); if (isStructureMarker(data)) { continue; @@ -344,7 +341,7 @@ public class IrisObject extends IrisRegistrant { int size = din.readInt(); for (int i = 0; i < size; i++) { - states.put(new Vector3i(din.readShort(), din.readShort(), din.readShort()), TileData.read(din)); + states.put(new IrisBlockVector(din.readShort(), din.readShort(), din.readShort()), TileData.read(din)); } } catch (Throwable e) { IrisLogging.reportError(e); @@ -371,7 +368,7 @@ public class IrisObject extends IrisRegistrant { s = din.readInt(); for (i = 0; i < s; i++) { - Vector3i pos = new Vector3i(din.readShort(), din.readShort(), din.readShort()); + IrisBlockVector pos = new IrisBlockVector(din.readShort(), din.readShort(), din.readShort()); BlockData data = BukkitBlockResolution.get(palette.get(din.readShort())); if (isStructureMarker(data)) { continue; @@ -382,7 +379,7 @@ public class IrisObject extends IrisRegistrant { s = din.readInt(); for (i = 0; i < s; i++) { - states.put(new Vector3i(din.readShort(), din.readShort(), din.readShort()), TileData.read(din)); + states.put(new IrisBlockVector(din.readShort(), din.readShort(), din.readShort()), TileData.read(din)); } } @@ -550,10 +547,10 @@ public class IrisObject extends IrisRegistrant { public void shrinkwrap() { if (blocks.isEmpty()) return; - BlockVector min = new BlockVector(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE); - BlockVector max = new BlockVector(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE); + IrisBlockVector min = new IrisBlockVector(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE); + IrisBlockVector max = new IrisBlockVector(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE); - for (BlockVector i : blocks.keys()) { + for (IrisBlockVector i : blocks.keys()) { min.setX(Math.min(min.getX(), i.getX())); min.setY(Math.min(min.getY(), i.getY())); min.setZ(Math.min(min.getZ(), i.getZ())); @@ -577,14 +574,15 @@ public class IrisObject extends IrisRegistrant { VectorMap b = new VectorMap<>(); VectorMap s = new VectorMap<>(); + IrisBlockVector shift = new IrisBlockVector(offset.getX(), offset.getY(), offset.getZ()); blocks.forEach((vector, data) -> { - vector.add(offset); + vector.add(shift); b.put(vector, data); }); states.forEach((vector, data) -> { - vector.add(offset); + vector.add(shift); s.put(vector, data); }); @@ -604,16 +602,16 @@ public class IrisObject extends IrisRegistrant { states = dx; } - public Vector3i getSigned(int x, int y, int z) { + public IrisBlockVector getSigned(int x, int y, int z) { if (x >= w || y >= h || z >= d) { throw new RuntimeException(x + " " + y + " " + z + " exceeds limit of " + w + " " + h + " " + d); } - return (Vector3i) new Vector3i(x, y, z).subtract(center); + return new IrisBlockVector(x - center.getX(), y - center.getY(), z - center.getZ()); } public void setUnsigned(int x, int y, int z, PlatformBlockState block) { - Vector3i v = getSigned(x, y, z); + IrisBlockVector v = getSigned(x, y, z); if (block == null) { blocks.remove(v); @@ -624,7 +622,7 @@ public class IrisObject extends IrisRegistrant { } public void setUnsignedTile(int x, int y, int z, TileData tile) { - Vector3i v = getSigned(x, y, z); + IrisBlockVector v = getSigned(x, y, z); if (tile == null) { states.remove(v); @@ -634,7 +632,7 @@ public class IrisObject extends IrisRegistrant { } public void setUnsigned(int x, int y, int z, Block block, boolean legacy) { - Vector3i v = getSigned(x, y, z); + IrisBlockVector v = getSigned(x, y, z); if (block == null) { blocks.remove(v); @@ -738,8 +736,8 @@ public class IrisObject extends IrisRegistrant { int spinx = rng.imax() / 1000; int spiny = rng.imax() / 1000; int spinz = rng.imax() / 1000; - int rty = config.getRotation().rotate(new BlockVector(0, getCenter().getBlockY(), 0), spinx, spiny, spinz).getBlockY(); - int ty = config.getTranslate().translate(new BlockVector(0, getCenter().getBlockY(), 0), config.getRotation(), spinx, spiny, spinz).getBlockY(); + int rty = config.getRotation().rotate(new IrisBlockVector(0, getCenter().getBlockY(), 0), spinx, spiny, spinz).getBlockY(); + int ty = config.getTranslate().translate(new IrisBlockVector(0, getCenter().getBlockY(), 0), config.getRotation(), spinx, spiny, spinz).getBlockY(); int y = -1; int xx, zz; int yrand = config.getTranslate().getYRandom(); @@ -764,8 +762,8 @@ public class IrisObject extends IrisRegistrant { } } } else if (config.getMode().equals(ObjectPlaceMode.MAX_HEIGHT) || config.getMode().equals(ObjectPlaceMode.STILT)) { - BlockVector offset = new BlockVector(config.getTranslate().getX(), config.getTranslate().getY(), config.getTranslate().getZ()); - BlockVector rotatedDimensions = config.getRotation().rotate(new BlockVector(getW(), getH(), getD()), spinx, spiny, spinz).clone(); + IrisBlockVector offset = new IrisBlockVector(config.getTranslate().getX(), config.getTranslate().getY(), config.getTranslate().getZ()); + IrisBlockVector rotatedDimensions = config.getRotation().rotate(new IrisBlockVector(getW(), getH(), getD()), spinx, spiny, spinz).clone(); int xLength = (rotatedDimensions.getBlockX() / 2) + offset.getBlockX(); int minX = Math.min(x - xLength, x + xLength); int maxX = Math.max(x - xLength, x + xLength); @@ -786,8 +784,8 @@ public class IrisObject extends IrisRegistrant { } } } else if (config.getMode().equals(ObjectPlaceMode.FAST_MAX_HEIGHT) || config.getMode().equals(ObjectPlaceMode.FAST_STILT)) { - BlockVector offset = new BlockVector(config.getTranslate().getX(), config.getTranslate().getY(), config.getTranslate().getZ()); - BlockVector rotatedDimensions = config.getRotation().rotate(new BlockVector(getW(), getH(), getD()), spinx, spiny, spinz).clone(); + IrisBlockVector offset = new IrisBlockVector(config.getTranslate().getX(), config.getTranslate().getY(), config.getTranslate().getZ()); + IrisBlockVector rotatedDimensions = config.getRotation().rotate(new IrisBlockVector(getW(), getH(), getD()), spinx, spiny, spinz).clone(); int xRadius = (rotatedDimensions.getBlockX() / 2); int xLength = xRadius + offset.getBlockX(); @@ -813,8 +811,8 @@ public class IrisObject extends IrisRegistrant { } } else if (config.getMode().equals(ObjectPlaceMode.MIN_HEIGHT) || config.getMode() == ObjectPlaceMode.MIN_STILT) { y = rdata.getEngine().getHeight() + 1; - BlockVector offset = new BlockVector(config.getTranslate().getX(), config.getTranslate().getY(), config.getTranslate().getZ()); - BlockVector rotatedDimensions = config.getRotation().rotate(new BlockVector(getW(), getH(), getD()), spinx, spiny, spinz).clone(); + IrisBlockVector offset = new IrisBlockVector(config.getTranslate().getX(), config.getTranslate().getY(), config.getTranslate().getZ()); + IrisBlockVector rotatedDimensions = config.getRotation().rotate(new IrisBlockVector(getW(), getH(), getD()), spinx, spiny, spinz).clone(); int xLength = (rotatedDimensions.getBlockX() / 2) + offset.getBlockX(); int minX = Math.min(x - xLength, x + xLength); @@ -838,8 +836,8 @@ public class IrisObject extends IrisRegistrant { } } else if (config.getMode().equals(ObjectPlaceMode.FAST_MIN_HEIGHT) || config.getMode() == ObjectPlaceMode.FAST_MIN_STILT) { y = rdata.getEngine().getHeight() + 1; - BlockVector offset = new BlockVector(config.getTranslate().getX(), config.getTranslate().getY(), config.getTranslate().getZ()); - BlockVector rotatedDimensions = config.getRotation().rotate(new BlockVector(getW(), getH(), getD()), spinx, spiny, spinz).clone(); + IrisBlockVector offset = new IrisBlockVector(config.getTranslate().getX(), config.getTranslate().getY(), config.getTranslate().getZ()); + IrisBlockVector rotatedDimensions = config.getRotation().rotate(new IrisBlockVector(getW(), getH(), getD()), spinx, spiny, spinz).clone(); int xRadius = (rotatedDimensions.getBlockX() / 2); int xLength = xRadius + offset.getBlockX(); @@ -943,7 +941,7 @@ public class IrisObject extends IrisRegistrant { if (!config.isForcePlace() && !rawStructurePiece && (!config.getAllowedCollisions().isEmpty() || !config.getForbiddenCollisions().isEmpty())) { Engine engine = rdata.getEngine(); - BlockVector offset = new BlockVector(config.getTranslate().getX(), config.getTranslate().getY(), config.getTranslate().getZ()); + IrisBlockVector offset = new IrisBlockVector(config.getTranslate().getX(), config.getTranslate().getY(), config.getTranslate().getZ()); for (int i = x - Math.floorDiv(w, 2) + (int) offset.getX(); i <= x + Math.floorDiv(w, 2) - (w % 2 == 0 ? 1 : 0) + (int) offset.getX(); i++) { for (int j = y - Math.floorDiv(h, 2) + (int) offset.getY(); j <= y + Math.floorDiv(h, 2) - (h % 2 == 0 ? 1 : 0) + (int) offset.getY(); j++) { for (int k = z - Math.floorDiv(d, 2) + (int) offset.getZ(); k <= z + Math.floorDiv(d, 2) - (d % 2 == 0 ? 1 : 0) + (int) offset.getX(); k++) { @@ -963,11 +961,11 @@ public class IrisObject extends IrisRegistrant { } if (config.isBore()) { - BlockVector offset = new BlockVector(config.getTranslate().getX(), config.getTranslate().getY(), config.getTranslate().getZ()); + IrisBlockVector offset = new IrisBlockVector(config.getTranslate().getX(), config.getTranslate().getY(), config.getTranslate().getZ()); for (int i = x - Math.floorDiv(w, 2) + (int) offset.getX(); i <= x + Math.floorDiv(w, 2) - (w % 2 == 0 ? 1 : 0) + (int) offset.getX(); i++) { for (int j = y - Math.floorDiv(h, 2) - config.getBoreExtendMinY() + (int) offset.getY(); j <= y + Math.floorDiv(h, 2) + config.getBoreExtendMaxY() - (h % 2 == 0 ? 1 : 0) + (int) offset.getY(); j++) { for (int k = z - Math.floorDiv(d, 2) + (int) offset.getZ(); k <= z + Math.floorDiv(d, 2) - (d % 2 == 0 ? 1 : 0) + (int) offset.getX(); k++) { - placer.set(i, j, k, AIR); + placer.set(i, j, k, States.AIR); } } } @@ -980,7 +978,7 @@ public class IrisObject extends IrisRegistrant { y += yrand; readLock.lock(); - KMap markers = null; + KMap markers = null; try { if (config.getMarkers().isNotEmpty() && placer.getEngine() != null) { @@ -996,7 +994,7 @@ public class IrisObject extends IrisRegistrant { } int max = j.getMaximumMarkers(); - for (BlockVector i : list.shuffle()) { + for (IrisBlockVector i : list.shuffle()) { if (max <= 0) { break; } @@ -1011,8 +1009,8 @@ public class IrisObject extends IrisRegistrant { BlockData rawMark = (BlockData) k.nativeHandle(); if (j.isExact() ? rawMark.matches(rawData) : rawMark.getMaterial().equals(rawData.getMaterial())) { - boolean a = !blocks.containsKey((BlockVector) i.clone().add(new BlockVector(0, 1, 0))); - boolean fff = !blocks.containsKey((BlockVector) i.clone().add(new BlockVector(0, 2, 0))); + 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))); if (!marker.isEmptyAbove() || (a && fff)) { markers.put(i, j.getMarker()); @@ -1035,15 +1033,15 @@ public class IrisObject extends IrisRegistrant { } catch (Throwable e) { IrisLogging.reportError(e); IrisLogging.warn("Failed to read block node " + g.getBlockX() + "," + g.getBlockY() + "," + g.getBlockZ() + " in object " + getLoadKey() + " (cme)"); - d = AIR; + d = States.AIR; } if (d == null) { IrisLogging.warn("Failed to read block node " + g.getBlockX() + "," + g.getBlockY() + "," + g.getBlockZ() + " in object " + getLoadKey() + " (null)"); - d = AIR; + d = States.AIR; } - BlockVector i = g.clone(); + IrisBlockVector i = g.clone(); PlatformBlockState data = d; i = config.getRotation().rotate(i.clone(), spinx, spiny, spinz).clone(); if (ceilingHang) { @@ -1184,8 +1182,8 @@ public class IrisObject extends IrisRegistrant { double erodeMaxDist = 1; if (eroding) { int centroidCount = 0; - for (BlockVector g : blocks.keys()) { - BlockVector rot = config.getRotation().rotate(g.clone(), spinx, spiny, spinz).clone(); + for (IrisBlockVector g : blocks.keys()) { + IrisBlockVector rot = config.getRotation().rotate(g.clone(), spinx, spiny, spinz).clone(); rot = config.getTranslate().translate(rot.clone(), config.getRotation(), spinx, spiny, spinz).clone(); if (rot.getBlockY() == lowest) { PlatformBlockState bd = blocks.get(g); @@ -1200,8 +1198,8 @@ public class IrisObject extends IrisRegistrant { erodeCentroidX /= centroidCount; erodeCentroidZ /= centroidCount; } - for (BlockVector g : blocks.keys()) { - BlockVector rot = config.getRotation().rotate(g.clone(), spinx, spiny, spinz).clone(); + for (IrisBlockVector g : blocks.keys()) { + IrisBlockVector rot = config.getRotation().rotate(g.clone(), spinx, spiny, spinz).clone(); rot = config.getTranslate().translate(rot.clone(), config.getRotation(), spinx, spiny, spinz).clone(); if (rot.getBlockY() == lowest) { PlatformBlockState bd = blocks.get(g); @@ -1217,19 +1215,19 @@ public class IrisObject extends IrisRegistrant { } } - for (BlockVector g : blocks.keys()) { + for (IrisBlockVector g : blocks.keys()) { PlatformBlockState sourceData; try { sourceData = blocks.get(g); } catch (Throwable e) { IrisLogging.reportError(e); IrisLogging.warn("Failed to read block node " + g.getBlockX() + "," + g.getBlockY() + "," + g.getBlockZ() + " in object " + getLoadKey() + " (stilt cme)"); - sourceData = AIR; + sourceData = States.AIR; } if (sourceData == null) { IrisLogging.warn("Failed to read block node " + g.getBlockX() + "," + g.getBlockY() + "," + g.getBlockZ() + " in object " + getLoadKey() + " (stilt null)"); - sourceData = AIR; + sourceData = States.AIR; } if (!shouldStilt(sourceData)) { @@ -1246,7 +1244,7 @@ public class IrisObject extends IrisRegistrant { } } - BlockVector i = g.clone(); + IrisBlockVector i = g.clone(); i = config.getRotation().rotate(i.clone(), spinx, spiny, spinz).clone(); if (ceilingHang) { i.setY(-i.getBlockY()); @@ -1410,7 +1408,7 @@ public class IrisObject extends IrisRegistrant { } if (vacuuming && vacuumLowest != Integer.MAX_VALUE && placer.getEngine() != null) { - BlockVector rotDim = config.getRotation().rotate(new BlockVector(getW(), getH(), getD()), spinx, spiny, spinz).clone(); + IrisBlockVector rotDim = config.getRotation().rotate(new IrisBlockVector(getW(), getH(), getD()), spinx, spiny, spinz).clone(); int lowX = IrisObjectVacuum.footprintLow(rotDim.getBlockX()); int highX = IrisObjectVacuum.footprintHigh(rotDim.getBlockX()); int lowZ = IrisObjectVacuum.footprintLow(rotDim.getBlockZ()); @@ -1500,7 +1498,7 @@ public class IrisObject extends IrisRegistrant { if (targetY > origY) { PlatformBlockState fill = complex != null ? complex.getRockStream().get(cx, cz) : null; if (fill == null || BukkitBlockResolution.isAir((BlockData) fill.nativeHandle())) { - fill = STONE; + fill = States.STONE; } for (int yy = origY + 1; yy <= targetY; yy++) { placer.set(cx, yy, cz, fill); @@ -1509,7 +1507,7 @@ public class IrisObject extends IrisRegistrant { boolean inside = IrisObjectVacuum.outset(dx, lowX, highX) == 0 && IrisObjectVacuum.outset(dz, lowZ, highZ) == 0; int carveFloor = IrisObjectVacuum.carveFloorY(targetY, topY, inside); for (int yy = origY; yy >= carveFloor; yy--) { - placer.set(cx, yy, cz, AIR); + placer.set(cx, yy, cz, States.AIR); } } } @@ -1527,7 +1525,7 @@ public class IrisObject extends IrisRegistrant { } private boolean lacksFootprintSupport(IObjectPlacer placer, IrisObjectPlacement config, int x, int y, int z, int spinx, int spiny, int spinz) { - BlockVector rot = config.getRotation().rotate(new BlockVector(getW(), getH(), getD()), spinx, spiny, spinz).clone(); + IrisBlockVector rot = config.getRotation().rotate(new IrisBlockVector(getW(), getH(), getD()), spinx, spiny, spinz).clone(); int halfW = Math.max(0, Math.abs(rot.getBlockX()) / 2); int halfD = Math.max(0, Math.abs(rot.getBlockZ()) / 2); if (halfW == 0 && halfD == 0) { @@ -1603,7 +1601,7 @@ public class IrisObject extends IrisRegistrant { readLock.lock(); for (var entry : blocks) { var i = entry.getKey(); - Block b = at.clone().add(0, getCenter().getY(), 0).add(i).getBlock(); + Block b = at.clone().add(0, getCenter().getY(), 0).add(i.getX(), i.getY(), i.getZ()).getBlock(); b.setBlockData((BlockData) Objects.requireNonNull(entry.getValue()).nativeHandle(), false); if (states.containsKey(i)) { @@ -1618,7 +1616,7 @@ public class IrisObject extends IrisRegistrant { readLock.lock(); for (var entry : blocks) { var i = entry.getKey(); - Block b = at.clone().add(getCenter().getX(), getCenter().getY(), getCenter().getZ()).add(i).getBlock(); + Block b = at.clone().add(getCenter().getX(), getCenter().getY(), getCenter().getZ()).add(i.getX(), i.getY(), i.getZ()).getBlock(); b.setBlockData((BlockData) Objects.requireNonNull(entry.getValue()).nativeHandle(), false); if (states.containsKey(i)) { @@ -1630,8 +1628,8 @@ public class IrisObject extends IrisRegistrant { public void unplaceCenterY(Location at) { readLock.lock(); - for (BlockVector i : blocks.keys()) { - at.clone().add(getCenter().getX(), getCenter().getY(), getCenter().getZ()).add(i).getBlock().setBlockData((BlockData) AIR.nativeHandle(), false); + for (IrisBlockVector i : blocks.keys()) { + at.clone().add(getCenter().getX(), getCenter().getY(), getCenter().getZ()).add(i.getX(), i.getY(), i.getZ()).getBlock().setBlockData((BlockData) States.AIR.nativeHandle(), false); } readLock.unlock(); } @@ -1640,7 +1638,7 @@ public class IrisObject extends IrisRegistrant { if (interpolation == null) { interpolation = IrisObjectPlacementScaleInterpolator.NONE; } - Vector sm1 = new Vector(scale - 1, scale - 1, scale - 1); + IrisVector sm1 = new IrisVector(scale - 1, scale - 1, scale - 1); scale = Math.max(0.001, Math.min(50, scale)); if (scale < 1) { scale = scale - 0.0001; @@ -1650,7 +1648,7 @@ public class IrisObject extends IrisRegistrant { IrisPosition l2 = getAABB().min(); VectorMap placeBlock = new VectorMap<>(); - Vector center = getCenter(); + IrisVector center = new IrisVector(getCenter().getX(), getCenter().getY(), getCenter().getZ()); if (getH() == 2) { center = center.setY(center.getBlockY() + 0.5); } @@ -1675,9 +1673,9 @@ public class IrisObject extends IrisRegistrant { readLock.unlock(); for (var entry : placeBlock) { - BlockVector v = entry.getKey(); + IrisBlockVector v = entry.getKey(); if (scale > 1) { - for (BlockVector vec : blocksBetweenTwoPoints(v.clone().add(center), v.clone().add(center).add(sm1))) { + for (IrisBlockVector vec : blocksBetweenTwoPoints(v.clone().add(center), v.clone().add(center).add(sm1))) { oo.blocks.put(vec, entry.getValue()); } } else { @@ -1700,14 +1698,14 @@ public class IrisObject extends IrisRegistrant { writeLock.lock(); VectorMap v = blocks; VectorMap b = new VectorMap<>(); - BlockVector min = getAABB().minbv(); - BlockVector max = getAABB().maxbv(); + IrisPosition min = getAABB().min(); + IrisPosition max = getAABB().max(); - for (int x = min.getBlockX(); x <= max.getBlockX(); x++) { - for (int y = min.getBlockY(); y <= max.getBlockY(); y++) { - for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) { + for (int x = min.getX(); x <= max.getX(); x++) { + for (int y = min.getY(); y <= max.getY(); y++) { + for (int z = min.getZ(); z <= max.getZ(); z++) { if (IrisInterpolation.getTrilinear(x, y, z, rad, (xx, yy, zz) -> { - PlatformBlockState data = v.get(new BlockVector((int) xx, (int) yy, (int) zz)); + PlatformBlockState data = v.get(new IrisBlockVector((int) xx, (int) yy, (int) zz)); if (data == null || ((BlockData) data.nativeHandle()).getMaterial().isAir()) { return 0; @@ -1715,9 +1713,9 @@ public class IrisObject extends IrisRegistrant { return 1; }) >= 0.5) { - b.put(new BlockVector(x, y, z), nearestBlockData(x, y, z)); + b.put(new IrisBlockVector(x, y, z), nearestBlockData(x, y, z)); } else { - b.put(new BlockVector(x, y, z), AIR); + b.put(new IrisBlockVector(x, y, z), States.AIR); } } } @@ -1731,14 +1729,14 @@ public class IrisObject extends IrisRegistrant { writeLock.lock(); VectorMap v = blocks; VectorMap b = new VectorMap<>(); - BlockVector min = getAABB().minbv(); - BlockVector max = getAABB().maxbv(); + IrisPosition min = getAABB().min(); + IrisPosition max = getAABB().max(); - for (int x = min.getBlockX(); x <= max.getBlockX(); x++) { - for (int y = min.getBlockY(); y <= max.getBlockY(); y++) { - for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) { + for (int x = min.getX(); x <= max.getX(); x++) { + for (int y = min.getY(); y <= max.getY(); y++) { + for (int z = min.getZ(); z <= max.getZ(); z++) { if (IrisInterpolation.getTricubic(x, y, z, rad, (xx, yy, zz) -> { - PlatformBlockState data = v.get(new BlockVector((int) xx, (int) yy, (int) zz)); + PlatformBlockState data = v.get(new IrisBlockVector((int) xx, (int) yy, (int) zz)); if (data == null || ((BlockData) data.nativeHandle()).getMaterial().isAir()) { return 0; @@ -1746,9 +1744,9 @@ public class IrisObject extends IrisRegistrant { return 1; }) >= 0.5) { - b.put(new BlockVector(x, y, z), nearestBlockData(x, y, z)); + b.put(new IrisBlockVector(x, y, z), nearestBlockData(x, y, z)); } else { - b.put(new BlockVector(x, y, z), AIR); + b.put(new IrisBlockVector(x, y, z), States.AIR); } } } @@ -1766,14 +1764,14 @@ public class IrisObject extends IrisRegistrant { writeLock.lock(); VectorMap v = blocks; VectorMap b = new VectorMap<>(); - BlockVector min = getAABB().minbv(); - BlockVector max = getAABB().maxbv(); + IrisPosition min = getAABB().min(); + IrisPosition max = getAABB().max(); - for (int x = min.getBlockX(); x <= max.getBlockX(); x++) { - for (int y = min.getBlockY(); y <= max.getBlockY(); y++) { - for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) { + for (int x = min.getX(); x <= max.getX(); x++) { + for (int y = min.getY(); y <= max.getY(); y++) { + for (int z = min.getZ(); z <= max.getZ(); z++) { if (IrisInterpolation.getTrihermite(x, y, z, rad, (xx, yy, zz) -> { - PlatformBlockState data = v.get(new BlockVector((int) xx, (int) yy, (int) zz)); + PlatformBlockState data = v.get(new IrisBlockVector((int) xx, (int) yy, (int) zz)); if (data == null || ((BlockData) data.nativeHandle()).getMaterial().isAir()) { return 0; @@ -1781,9 +1779,9 @@ public class IrisObject extends IrisRegistrant { return 1; }, tension, bias) >= 0.5) { - b.put(new BlockVector(x, y, z), nearestBlockData(x, y, z)); + b.put(new IrisBlockVector(x, y, z), nearestBlockData(x, y, z)); } else { - b.put(new BlockVector(x, y, z), AIR); + b.put(new IrisBlockVector(x, y, z), States.AIR); } } } @@ -1794,7 +1792,7 @@ public class IrisObject extends IrisRegistrant { } private PlatformBlockState nearestBlockData(int x, int y, int z) { - BlockVector vv = new BlockVector(x, y, z); + IrisBlockVector vv = new IrisBlockVector(x, y, z); readLock.lock(); PlatformBlockState r = blocks.get(vv); 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 2ce95a1c2..7ca9d2f31 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 @@ -18,12 +18,12 @@ package art.arcane.iris.engine.object; -import art.arcane.iris.platform.bukkit.BukkitPlatform; import art.arcane.iris.engine.object.annotations.Desc; import art.arcane.iris.engine.object.annotations.Snippet; 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.math.IrisBlockVector; import art.arcane.volmlib.util.collection.KList; import art.arcane.volmlib.util.collection.KMap; import lombok.AllArgsConstructor; @@ -35,7 +35,6 @@ import org.bukkit.block.BlockFace; import org.bukkit.block.data.*; import org.bukkit.block.data.type.RedstoneWire; import org.bukkit.block.data.type.Wall; -import org.bukkit.util.BlockVector; import java.util.HashMap; import java.util.List; @@ -136,13 +135,25 @@ public class IrisObjectRotation { return e.rotateCopy(this); } - public BlockVector rotate(BlockVector direction) { + public IrisBlockVector rotate(IrisBlockVector direction) { return rotate(direction, 0, 0, 0); } public IrisDirection rotate(IrisDirection direction) { - BlockVector v = rotate(direction.toVector().toBlockVector()); - return IrisDirection.closest(v); + IrisBlockVector v = rotate(new IrisBlockVector(direction.x(), direction.y(), direction.z())); + double m = Double.MAX_VALUE; + IrisDirection s = null; + + for (IrisDirection i : IrisDirection.values()) { + double g = new IrisBlockVector(i.x(), i.y(), i.z()).distance(v); + + if (g < m) { + m = g; + s = i; + } + } + + return s; } public double getRotation(int spin, IrisAxisRotationClamp clamp) { @@ -157,7 +168,7 @@ public class IrisObjectRotation { return clamp.getRadians(spin); } - public BlockFace getFace(BlockVector v) { + public BlockFace getFace(IrisBlockVector v) { int x = (int) Math.round(v.getX()); int y = (int) Math.round(v.getY()); int z = (int) Math.round(v.getZ()); @@ -189,7 +200,7 @@ public class IrisObjectRotation { return BlockFace.SOUTH; } - public BlockFace getHexFace(BlockVector v) { + public BlockFace getHexFace(IrisBlockVector v) { int x = v.getBlockX(); int y = v.getBlockY(); int z = v.getBlockZ(); @@ -271,7 +282,7 @@ public class IrisObjectRotation { if (d instanceof Directional g) { BlockFace f = g.getFacing(); - BlockVector bv = new BlockVector(f.getModX(), f.getModY(), f.getModZ()); + IrisBlockVector bv = new IrisBlockVector(f.getModX(), f.getModY(), f.getModZ()); bv = rotate(bv.clone(), spinx, spiny, spinz); BlockFace t = getFace(bv); @@ -283,7 +294,7 @@ public class IrisObjectRotation { } else if (d instanceof Rotatable g) { BlockFace f = g.getRotation(); - BlockVector bv = new BlockVector(f.getModX(), 0, f.getModZ()); + IrisBlockVector bv = new IrisBlockVector(f.getModX(), 0, f.getModZ()); bv = rotate(bv.clone(), spinx, spiny, spinz); BlockFace face = getHexFace(bv); @@ -291,7 +302,7 @@ public class IrisObjectRotation { } else if (d instanceof Orientable g) { BlockFace f = getFace(g.getAxis()); - BlockVector bv = new BlockVector(f.getModX(), f.getModY(), f.getModZ()); + IrisBlockVector bv = new IrisBlockVector(f.getModX(), f.getModY(), f.getModZ()); bv = rotate(bv.clone(), spinx, spiny, spinz); Axis a = getAxis(bv); @@ -302,7 +313,7 @@ public class IrisObjectRotation { List faces = new KList<>(); for (BlockFace i : g.getFaces()) { - BlockVector bv = new BlockVector(i.getModX(), i.getModY(), i.getModZ()); + IrisBlockVector bv = new IrisBlockVector(i.getModX(), i.getModY(), i.getModZ()); bv = rotate(bv.clone(), spinx, spiny, spinz); BlockFace r = getFace(bv); @@ -323,7 +334,7 @@ public class IrisObjectRotation { for (BlockFace i : WALL_FACES) { Wall.Height h = wall.getHeight(i); - BlockVector bv = new BlockVector(i.getModX(), i.getModY(), i.getModZ()); + IrisBlockVector bv = new IrisBlockVector(i.getModX(), i.getModY(), i.getModZ()); bv = rotate(bv.clone(), spinx, spiny, spinz); BlockFace r = getFace(bv); if (WALL_FACES.contains(r)) { @@ -340,7 +351,7 @@ public class IrisObjectRotation { var allowed = wire.getAllowedFaces(); for (BlockFace i : allowed) { RedstoneWire.Connection connection = wire.getFace(i); - BlockVector bv = new BlockVector(i.getModX(), i.getModY(), i.getModZ()); + IrisBlockVector bv = new IrisBlockVector(i.getModX(), i.getModY(), i.getModZ()); bv = rotate(bv.clone(), spinx, spiny, spinz); BlockFace r = getFace(bv); if (allowed.contains(r)) @@ -359,7 +370,7 @@ public class IrisObjectRotation { return d; } - public Axis getAxis(BlockVector v) { + public Axis getAxis(IrisBlockVector v) { if (Math.abs(v.getBlockX()) > Math.max(Math.abs(v.getBlockY()), Math.abs(v.getBlockZ()))) { return Axis.X; } @@ -388,15 +399,16 @@ public class IrisObjectRotation { } public IrisPosition rotate(IrisPosition b, int spinx, int spiny, int spinz) { - return BukkitPlatform.positionOf(rotate(new BlockVector(b.getX(), b.getY(), b.getZ()), spinx, spiny, spinz)); + IrisBlockVector v = rotate(new IrisBlockVector(b.getX(), b.getY(), b.getZ()), spinx, spiny, spinz); + return new IrisPosition(v.getBlockX(), v.getBlockY(), v.getBlockZ()); } - public BlockVector rotate(BlockVector b, int spinx, int spiny, int spinz) { + public IrisBlockVector rotate(IrisBlockVector b, int spinx, int spiny, int spinz) { if (!canRotate()) { return b; } - BlockVector v = b.clone(); + IrisBlockVector v = b.clone(); if (canRotateX()) { if (getXAxis().isLocked()) { diff --git a/core/src/main/java/art/arcane/iris/engine/object/IrisObjectTranslate.java b/core/src/main/java/art/arcane/iris/engine/object/IrisObjectTranslate.java index 4e033ff55..6ce9d77f0 100644 --- a/core/src/main/java/art/arcane/iris/engine/object/IrisObjectTranslate.java +++ b/core/src/main/java/art/arcane/iris/engine/object/IrisObjectTranslate.java @@ -19,11 +19,11 @@ package art.arcane.iris.engine.object; import art.arcane.iris.engine.object.annotations.*; +import art.arcane.iris.util.common.math.IrisBlockVector; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; -import org.bukkit.util.BlockVector; @Snippet("object-translator") @Accessors(chain = true) @@ -57,17 +57,17 @@ public class IrisObjectTranslate { return x != 0 || y != 0 || z != 0; } - public BlockVector translate(BlockVector i) { + public IrisBlockVector translate(IrisBlockVector i) { if (canTranslate()) { - return (BlockVector) i.clone().add(new BlockVector(x, y, z)); + return (IrisBlockVector) i.clone().add(new IrisBlockVector(x, y, z)); } return i; } - public BlockVector translate(BlockVector clone, IrisObjectRotation rotation, int sx, int sy, int sz) { + public IrisBlockVector translate(IrisBlockVector clone, IrisObjectRotation rotation, int sx, int sy, int sz) { if (canTranslate()) { - return (BlockVector) clone.clone().add(rotation.rotate(new BlockVector(x, y, z), sx, sy, sz)); + return (IrisBlockVector) clone.clone().add(rotation.rotate(new IrisBlockVector(x, y, z), sx, sy, sz)); } return clone; 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 8f97e10ca..8cc7094c5 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 @@ -23,6 +23,7 @@ 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.math.IrisBlockVector; import art.arcane.iris.util.common.math.Vector3i; import art.arcane.volmlib.util.math.RNG; import org.bukkit.block.data.BlockData; @@ -88,7 +89,7 @@ public final class IrisProceduralBlocks { int nx = v.getBlockX() - minX - cx; int ny = v.getBlockY() - cy + 1; int nz = v.getBlockZ() - minZ - cz; - object.getBlocks().put(new Vector3i(nx, ny, nz), BukkitBlockState.of(entry.getValue())); + object.getBlocks().put(new IrisBlockVector(nx, ny, nz), BukkitBlockState.of(entry.getValue())); } return object; 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 75c51d811..2ca8220e8 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 @@ -22,7 +22,7 @@ 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.util.common.math.Vector3i; +import art.arcane.iris.util.common.math.IrisBlockVector; import art.arcane.volmlib.util.math.RNG; import org.bukkit.block.data.BlockData; @@ -119,7 +119,7 @@ public final class ProceduralTreeGenerator { int nx = v.x() - minX - cx; int ny = v.y() - cy + 1; int nz = v.z() - minZ - cz; - object.getBlocks().put(new Vector3i(nx, ny, nz), BukkitBlockState.of(entry.getValue())); + object.getBlocks().put(new IrisBlockVector(nx, ny, nz), BukkitBlockState.of(entry.getValue())); } return object; diff --git a/core/src/main/java/art/arcane/iris/engine/platform/studio/generators/ObjectStudioGenerator.java b/core/src/main/java/art/arcane/iris/engine/platform/studio/generators/ObjectStudioGenerator.java index 3285f6ec2..6d291bac2 100644 --- a/core/src/main/java/art/arcane/iris/engine/platform/studio/generators/ObjectStudioGenerator.java +++ b/core/src/main/java/art/arcane/iris/engine/platform/studio/generators/ObjectStudioGenerator.java @@ -37,7 +37,7 @@ import art.arcane.iris.util.common.data.VectorMap; import art.arcane.iris.util.common.math.Vector3i; import org.bukkit.Material; import org.bukkit.block.Biome; -import org.bukkit.util.BlockVector; +import art.arcane.iris.util.common.math.IrisBlockVector; import java.io.File; import java.util.LinkedHashMap; @@ -198,8 +198,8 @@ public class ObjectStudioGenerator extends EnginedStudioGenerator { int originY = cell.originY(); int originZ = cell.originZ(); - for (Map.Entry entry : blocks) { - BlockVector signed = entry.getKey(); + for (Map.Entry entry : blocks) { + IrisBlockVector signed = entry.getKey(); int worldX = originX + signed.getBlockX() + centerX; int worldY = originY + signed.getBlockY() + centerY; int worldZ = originZ + signed.getBlockZ() + centerZ; @@ -257,7 +257,7 @@ public class ObjectStudioGenerator extends EnginedStudioGenerator { } int cellCount = layout.cells().size(); - BlockVector worldExtent = computeExtent(layout); + IrisBlockVector worldExtent = computeExtent(layout); IrisLogging.info("Object Studio layout built: %d cells from %d pack(s), extent %d x %d blocks", cellCount, sources.size(), worldExtent.getBlockX(), worldExtent.getBlockZ()); } @@ -280,13 +280,13 @@ public class ObjectStudioGenerator extends EnginedStudioGenerator { return new File(new File(worldFolder, ".iris"), "object-studio-layout.json"); } - private static BlockVector computeExtent(ObjectStudioLayout layout) { + private static IrisBlockVector computeExtent(ObjectStudioLayout layout) { int maxX = 0; int maxZ = 0; for (GridCell cell : layout.cells()) { maxX = Math.max(maxX, cell.originX() + cell.w()); maxZ = Math.max(maxZ, cell.originZ() + cell.d()); } - return new BlockVector(maxX, 0, maxZ); + return new IrisBlockVector(maxX, 0, maxZ); } } diff --git a/core/src/main/java/art/arcane/iris/util/common/data/VectorMap.java b/core/src/main/java/art/arcane/iris/util/common/data/VectorMap.java index 056c45384..4bdc40709 100644 --- a/core/src/main/java/art/arcane/iris/util/common/data/VectorMap.java +++ b/core/src/main/java/art/arcane/iris/util/common/data/VectorMap.java @@ -2,7 +2,7 @@ package art.arcane.iris.util.common.data; import art.arcane.volmlib.util.collection.KMap; import lombok.NonNull; -import org.bukkit.util.BlockVector; +import art.arcane.iris.util.common.math.IrisBlockVector; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -11,7 +11,7 @@ import java.util.Map; import java.util.function.BiConsumer; import java.util.function.Function; -public class VectorMap implements Iterable> { +public class VectorMap implements Iterable> { private final Map> map = new KMap<>(); public int size() { @@ -22,7 +22,7 @@ public class VectorMap implements Iterable> { return map.values().stream().allMatch(Map::isEmpty); } - public boolean containsKey(@NonNull BlockVector vector) { + public boolean containsKey(@NonNull IrisBlockVector vector) { var chunk = map.get(chunk(vector)); return chunk != null && chunk.containsKey(relative(vector)); } @@ -31,22 +31,22 @@ public class VectorMap implements Iterable> { return map.values().stream().anyMatch(m -> m.containsValue(value)); } - public @Nullable T get(@NonNull BlockVector vector) { + public @Nullable T get(@NonNull IrisBlockVector vector) { var chunk = map.get(chunk(vector)); return chunk == null ? null : chunk.get(relative(vector)); } - public @Nullable T put(@NonNull BlockVector vector, @NonNull T value) { + public @Nullable T put(@NonNull IrisBlockVector vector, @NonNull T value) { return map.computeIfAbsent(chunk(vector), k -> new KMap<>()) .put(relative(vector), value); } - public @Nullable T computeIfAbsent(@NonNull BlockVector vector, @NonNull Function<@NonNull BlockVector, @NonNull T> mappingFunction) { + public @Nullable T computeIfAbsent(@NonNull IrisBlockVector vector, @NonNull Function<@NonNull IrisBlockVector, @NonNull T> mappingFunction) { return map.computeIfAbsent(chunk(vector), k -> new KMap<>()) .computeIfAbsent(relative(vector), $ -> mappingFunction.apply(vector)); } - public @Nullable T remove(@NonNull BlockVector vector) { + public @Nullable T remove(@NonNull IrisBlockVector vector) { var chunk = map.get(chunk(vector)); return chunk == null ? null : chunk.remove(relative(vector)); } @@ -59,7 +59,7 @@ public class VectorMap implements Iterable> { map.clear(); } - public void forEach(@NonNull BiConsumer<@NonNull BlockVector, @NonNull T> consumer) { + public void forEach(@NonNull BiConsumer<@NonNull IrisBlockVector, @NonNull T> consumer) { map.forEach((chunk, values) -> { int rX = chunk.x << 10; int rY = chunk.y << 10; @@ -72,11 +72,11 @@ public class VectorMap implements Iterable> { }); } - private static Key chunk(BlockVector vector) { + private static Key chunk(IrisBlockVector vector) { return new Key(vector.getBlockX() >> 10, vector.getBlockY() >> 10, vector.getBlockZ() >> 10); } - private static Key relative(BlockVector vector) { + private static Key relative(IrisBlockVector vector) { return new Key(vector.getBlockX() & 0x3FF, vector.getBlockY() & 0x3FF, vector.getBlockZ() & 0x3FF); } @@ -93,7 +93,7 @@ public class VectorMap implements Iterable> { return new ValueIterator(); } - public class EntryIterator implements Iterator> { + public class EntryIterator implements Iterator> { private final Iterator>> chunkIterator = map.entrySet().iterator(); private Iterator> relativeIterator; private int rX, rY, rZ; @@ -104,7 +104,7 @@ public class VectorMap implements Iterable> { } @Override - public Map.Entry next() { + public Map.Entry next() { if (relativeIterator == null || !relativeIterator.hasNext()) { if (!chunkIterator.hasNext()) throw new IllegalStateException("No more elements"); var chunk = chunkIterator.next(); @@ -125,7 +125,7 @@ public class VectorMap implements Iterable> { } } - public class KeyIterator implements Iterator, Iterable { + public class KeyIterator implements Iterator, Iterable { private final Iterator>> chunkIterator = map.entrySet().iterator(); private Iterator relativeIterator; private int rX, rY, rZ; @@ -136,7 +136,7 @@ public class VectorMap implements Iterable> { } @Override - public BlockVector next() { + public IrisBlockVector next() { if (relativeIterator == null || !relativeIterator.hasNext()) { var chunk = chunkIterator.next(); rX = chunk.getKey().x << 10; @@ -155,7 +155,7 @@ public class VectorMap implements Iterable> { } @Override - public @NotNull Iterator iterator() { + public @NotNull Iterator iterator() { return this; } } @@ -202,8 +202,8 @@ public class VectorMap implements Iterable> { this.hashCode = (x << 20) | (y << 10) | z; } - private BlockVector resolve(int rX, int rY, int rZ) { - return new BlockVector(rX + x, rY + y, rZ + z); + private IrisBlockVector resolve(int rX, int rY, int rZ) { + return new IrisBlockVector(rX + x, rY + y, rZ + z); } @Override diff --git a/core/src/main/java/art/arcane/iris/util/common/format/C.java b/core/src/main/java/art/arcane/iris/util/common/format/C.java index 0e1b17e4b..da4d62243 100644 --- a/core/src/main/java/art/arcane/iris/util/common/format/C.java +++ b/core/src/main/java/art/arcane/iris/util/common/format/C.java @@ -260,9 +260,7 @@ public enum C { @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") private final static Map BY_ID = new HashMap<>(); private final static Map BY_CHAR = new HashMap<>(); - private final static Map dyeChatMap = new HashMap<>(); private final static Map chatHexMap = new HashMap<>(); - private final static Map dyeHexMap = new HashMap<>(); static { chatHexMap.put(C.BLACK, "#000000"); @@ -282,38 +280,6 @@ public enum C { chatHexMap.put(C.LIGHT_PURPLE, "#FF55FF"); chatHexMap.put(C.YELLOW, "#FFFF55"); chatHexMap.put(C.WHITE, "#FFFFFF"); - dyeChatMap.put(DyeColor.BLACK, C.DARK_GRAY); - dyeChatMap.put(DyeColor.BLUE, C.DARK_BLUE); - dyeChatMap.put(DyeColor.BROWN, C.GOLD); - dyeChatMap.put(DyeColor.CYAN, C.AQUA); - dyeChatMap.put(DyeColor.GRAY, C.GRAY); - dyeChatMap.put(DyeColor.GREEN, C.DARK_GREEN); - dyeChatMap.put(DyeColor.LIGHT_BLUE, C.BLUE); - dyeChatMap.put(DyeColor.LIME, C.GREEN); - dyeChatMap.put(DyeColor.MAGENTA, C.LIGHT_PURPLE); - dyeChatMap.put(DyeColor.ORANGE, C.GOLD); - dyeChatMap.put(DyeColor.PINK, C.LIGHT_PURPLE); - dyeChatMap.put(DyeColor.PURPLE, C.DARK_PURPLE); - dyeChatMap.put(DyeColor.RED, C.RED); - dyeChatMap.put(DyeColor.LIGHT_GRAY, C.GRAY); - dyeChatMap.put(DyeColor.WHITE, C.WHITE); - dyeChatMap.put(DyeColor.YELLOW, C.YELLOW); - dyeHexMap.put(DyeColor.BLACK, "#181414"); - dyeHexMap.put(DyeColor.BLUE, "#253193"); - dyeHexMap.put(DyeColor.BROWN, "#56331c"); - dyeHexMap.put(DyeColor.CYAN, "#267191"); - dyeHexMap.put(DyeColor.GRAY, "#414141"); - dyeHexMap.put(DyeColor.GREEN, "#364b18"); - dyeHexMap.put(DyeColor.LIGHT_BLUE, "#6387d2"); - dyeHexMap.put(DyeColor.LIME, "#39ba2e"); - dyeHexMap.put(DyeColor.MAGENTA, "#be49c9"); - dyeHexMap.put(DyeColor.ORANGE, "#ea7e35"); - dyeHexMap.put(DyeColor.PINK, "#d98199"); - dyeHexMap.put(DyeColor.PURPLE, "#7e34bf"); - dyeHexMap.put(DyeColor.RED, "#9e2b27"); - dyeHexMap.put(DyeColor.LIGHT_GRAY, "#a0a7a7"); - dyeHexMap.put(DyeColor.WHITE, "#a4a4a4"); - dyeHexMap.put(DyeColor.YELLOW, "#c2b51c"); } static { @@ -323,6 +289,46 @@ public enum C { } } + private static final class DyeMaps { + private static final Map CHAT = new HashMap<>(); + private static final Map HEX = new HashMap<>(); + + static { + CHAT.put(DyeColor.BLACK, C.DARK_GRAY); + CHAT.put(DyeColor.BLUE, C.DARK_BLUE); + CHAT.put(DyeColor.BROWN, C.GOLD); + CHAT.put(DyeColor.CYAN, C.AQUA); + CHAT.put(DyeColor.GRAY, C.GRAY); + CHAT.put(DyeColor.GREEN, C.DARK_GREEN); + CHAT.put(DyeColor.LIGHT_BLUE, C.BLUE); + CHAT.put(DyeColor.LIME, C.GREEN); + CHAT.put(DyeColor.MAGENTA, C.LIGHT_PURPLE); + CHAT.put(DyeColor.ORANGE, C.GOLD); + CHAT.put(DyeColor.PINK, C.LIGHT_PURPLE); + CHAT.put(DyeColor.PURPLE, C.DARK_PURPLE); + CHAT.put(DyeColor.RED, C.RED); + CHAT.put(DyeColor.LIGHT_GRAY, C.GRAY); + CHAT.put(DyeColor.WHITE, C.WHITE); + CHAT.put(DyeColor.YELLOW, C.YELLOW); + HEX.put(DyeColor.BLACK, "#181414"); + HEX.put(DyeColor.BLUE, "#253193"); + HEX.put(DyeColor.BROWN, "#56331c"); + HEX.put(DyeColor.CYAN, "#267191"); + HEX.put(DyeColor.GRAY, "#414141"); + HEX.put(DyeColor.GREEN, "#364b18"); + HEX.put(DyeColor.LIGHT_BLUE, "#6387d2"); + HEX.put(DyeColor.LIME, "#39ba2e"); + HEX.put(DyeColor.MAGENTA, "#be49c9"); + HEX.put(DyeColor.ORANGE, "#ea7e35"); + HEX.put(DyeColor.PINK, "#d98199"); + HEX.put(DyeColor.PURPLE, "#7e34bf"); + HEX.put(DyeColor.RED, "#9e2b27"); + HEX.put(DyeColor.LIGHT_GRAY, "#a0a7a7"); + HEX.put(DyeColor.WHITE, "#a4a4a4"); + HEX.put(DyeColor.YELLOW, "#c2b51c"); + } + } + private final int intCode; private final char code; private final String token; @@ -511,15 +517,15 @@ public enum C { * @return the color */ public static C dyeToChat(DyeColor dclr) { - if (dyeChatMap.containsKey(dclr)) { - return dyeChatMap.get(dclr); + if (DyeMaps.CHAT.containsKey(dclr)) { + return DyeMaps.CHAT.get(dclr); } return C.MAGIC; } public static DyeColor chatToDye(ChatColor color) { - for (Map.Entry entry : dyeChatMap.entrySet()) { + for (Map.Entry entry : DyeMaps.CHAT.entrySet()) { if (entry.getValue().toString().equals(color.toString())) { return entry.getKey(); } @@ -538,8 +544,8 @@ public enum C { } public static String dyeToHex(DyeColor clr) { - if (dyeHexMap.containsKey(clr)) { - return dyeHexMap.get(clr); + if (DyeMaps.HEX.containsKey(clr)) { + return DyeMaps.HEX.get(clr); } return "#000000"; @@ -592,7 +598,7 @@ public enum C { str.append(""); str.append(""); - for (Map.Entry e : dyeHexMap.entrySet()) { + for (Map.Entry e : DyeMaps.HEX.entrySet()) { str.append(String.format("" + "", e.getKey().name(), e.getValue())); } diff --git a/core/src/main/java/art/arcane/iris/util/common/math/IrisBlockVector.java b/core/src/main/java/art/arcane/iris/util/common/math/IrisBlockVector.java new file mode 100644 index 000000000..288fb8e87 --- /dev/null +++ b/core/src/main/java/art/arcane/iris/util/common/math/IrisBlockVector.java @@ -0,0 +1,34 @@ +package art.arcane.iris.util.common.math; + +public class IrisBlockVector extends IrisVector { + public IrisBlockVector() { + super(); + } + + public IrisBlockVector(int x, int y, int z) { + super(x, y, z); + } + + public IrisBlockVector(double x, double y, double z) { + super(x, y, z); + } + + @Override + public IrisBlockVector clone() { + return (IrisBlockVector) super.clone(); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof IrisBlockVector other)) { + return false; + } + + return (int) other.getX() == (int) this.x && (int) other.getY() == (int) this.y && (int) other.getZ() == (int) this.z; + } + + @Override + public int hashCode() { + return (Integer.hashCode((int) x) >> 13) ^ (Integer.hashCode((int) y) >> 7) ^ Integer.hashCode((int) z); + } +} diff --git a/core/src/main/java/art/arcane/iris/util/common/math/IrisVector.java b/core/src/main/java/art/arcane/iris/util/common/math/IrisVector.java new file mode 100644 index 000000000..49c125ac4 --- /dev/null +++ b/core/src/main/java/art/arcane/iris/util/common/math/IrisVector.java @@ -0,0 +1,163 @@ +package art.arcane.iris.util.common.math; + +public class IrisVector implements Cloneable { + private static final double EPSILON = 0.000001; + protected double x; + protected double y; + protected double z; + + public IrisVector() { + this.x = 0; + this.y = 0; + this.z = 0; + } + + public IrisVector(int x, int y, int z) { + this.x = x; + this.y = y; + this.z = z; + } + + public IrisVector(double x, double y, double z) { + this.x = x; + this.y = y; + this.z = z; + } + + public double getX() { + return x; + } + + public double getY() { + return y; + } + + public double getZ() { + return z; + } + + public int getBlockX() { + return floor(x); + } + + public int getBlockY() { + return floor(y); + } + + public int getBlockZ() { + return floor(z); + } + + public IrisVector setX(double x) { + this.x = x; + return this; + } + + public IrisVector setY(double y) { + this.y = y; + return this; + } + + public IrisVector setZ(double z) { + this.z = z; + return this; + } + + public IrisVector add(IrisVector vec) { + x += vec.x; + y += vec.y; + z += vec.z; + return this; + } + + public IrisVector subtract(IrisVector vec) { + x -= vec.x; + y -= vec.y; + z -= vec.z; + return this; + } + + public IrisVector multiply(double m) { + x *= m; + y *= m; + z *= m; + return this; + } + + public double distance(IrisVector o) { + return Math.sqrt(square(x - o.x) + square(y - o.y) + square(z - o.z)); + } + + public double distanceSquared(IrisVector o) { + return square(x - o.x) + square(y - o.y) + square(z - o.z); + } + + public IrisVector rotateAroundX(double angle) { + double angleCos = Math.cos(angle); + double angleSin = Math.sin(angle); + double y = angleCos * this.y - angleSin * this.z; + double z = angleSin * this.y + angleCos * this.z; + return setY(y).setZ(z); + } + + public IrisVector rotateAroundY(double angle) { + double angleCos = Math.cos(angle); + double angleSin = Math.sin(angle); + double x = angleCos * this.x + angleSin * this.z; + double z = -angleSin * this.x + angleCos * this.z; + return setX(x).setZ(z); + } + + public IrisVector rotateAroundZ(double angle) { + double angleCos = Math.cos(angle); + double angleSin = Math.sin(angle); + double x = angleCos * this.x - angleSin * this.y; + double y = angleSin * this.x + angleCos * this.y; + return setX(x).setY(y); + } + + public IrisBlockVector toBlockVector() { + return new IrisBlockVector(x, y, z); + } + + @Override + public IrisVector clone() { + try { + return (IrisVector) super.clone(); + } catch (CloneNotSupportedException e) { + throw new Error(e); + } + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof IrisVector other)) { + return false; + } + + return Math.abs(x - other.x) < EPSILON && Math.abs(y - other.y) < EPSILON && Math.abs(z - other.z) < EPSILON && this.getClass().equals(obj.getClass()); + } + + @Override + public int hashCode() { + int hash = 7; + hash = 79 * hash + (int) (Double.doubleToLongBits(this.x) ^ (Double.doubleToLongBits(this.x) >>> 32)); + hash = 79 * hash + (int) (Double.doubleToLongBits(this.y) ^ (Double.doubleToLongBits(this.y) >>> 32)); + hash = 79 * hash + (int) (Double.doubleToLongBits(this.z) ^ (Double.doubleToLongBits(this.z) >>> 32)); + return hash; + } + + @Override + public String toString() { + return x + "," + y + "," + z; + } + + protected static int floor(double num) { + int floor = (int) num; + return floor == num ? floor : floor - (int) (Double.doubleToRawLongBits(num) >>> 63); + } + + private static double square(double num) { + return num * num; + } +} diff --git a/core/src/main/java/art/arcane/iris/util/common/math/Vector3i.java b/core/src/main/java/art/arcane/iris/util/common/math/Vector3i.java index ce25eaa73..9051e0c07 100644 --- a/core/src/main/java/art/arcane/iris/util/common/math/Vector3i.java +++ b/core/src/main/java/art/arcane/iris/util/common/math/Vector3i.java @@ -1,26 +1,65 @@ package art.arcane.iris.util.common.math; -import org.bukkit.util.BlockVector; -import org.bukkit.util.Vector; -import org.jetbrains.annotations.NotNull; +public class Vector3i implements Cloneable { + private final int x; + private final int y; + private final int z; -public class Vector3i extends BlockVector { public Vector3i(int x, int y, int z) { - super(x, y, z); + this.x = x; + this.y = y; + this.z = z; } - public Vector3i(Vector vec) { - super(vec); + public int getX() { + return x; + } + + public int getY() { + return y; + } + + public int getZ() { + return z; + } + + public int getBlockX() { + return x; + } + + public int getBlockY() { + return y; + } + + public int getBlockZ() { + return z; } - @NotNull @Override public Vector3i clone() { - return (Vector3i) super.clone(); + try { + return (Vector3i) super.clone(); + } catch (CloneNotSupportedException e) { + throw new Error(e); + } + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Vector3i other)) { + return false; + } + + return x == other.x && y == other.y && z == other.z; } @Override public int hashCode() { - return (int) x ^ ((int) z << 12) ^ ((int) y << 24); + return x ^ (z << 12) ^ (y << 24); + } + + @Override + public String toString() { + return x + "," + y + "," + z; } } diff --git a/core/src/main/java/art/arcane/iris/util/common/misc/Bindings.java b/core/src/main/java/art/arcane/iris/util/common/misc/Bindings.java index ff3138bc8..4175776c7 100644 --- a/core/src/main/java/art/arcane/iris/util/common/misc/Bindings.java +++ b/core/src/main/java/art/arcane/iris/util/common/misc/Bindings.java @@ -45,7 +45,7 @@ public class Bindings { var settings = IrisSettings.get().getSentry(); if (settings.disableAutoReporting || Sentry.isEnabled() || Boolean.getBoolean("iris.suppressReporting")) return; IrisLogging.info("Enabling Sentry for anonymous error reporting. You can disable this in the settings."); - IrisLogging.info("Your server ID is: " + ServerID.ID); + IrisLogging.info("Your server ID is: " + ServerID.getId()); Sentry.init(options -> { options.setDsn("http://4cdbb9ac953306529947f4ca1e8e6b26@sentry.volmit.com:8080/2"); diff --git a/core/src/main/java/art/arcane/iris/util/common/nbt/mca/NBTWorld.java b/core/src/main/java/art/arcane/iris/util/common/nbt/mca/NBTWorld.java index 678a6ff55..57c86b0c4 100644 --- a/core/src/main/java/art/arcane/iris/util/common/nbt/mca/NBTWorld.java +++ b/core/src/main/java/art/arcane/iris/util/common/nbt/mca/NBTWorld.java @@ -41,20 +41,23 @@ import java.util.Map; import java.util.Locale; public class NBTWorld { - private static final BlockData AIR = BukkitBlockResolution.get("AIR"); - private static final NBTWorldSupport.BlockStateCodec BLOCK_STATE_CODEC = NBTWorldSupport.blockStateCodec( - blockStateString -> BukkitBlockResolution.getOrNull(blockStateString, true), - BukkitBlockResolution::getAir, - blockData -> blockData.getAsString(true), - blockData -> { - NamespacedKey key = KeyedType.getKey(blockData.getMaterial()); - if (key == null) { - return "minecraft:" + blockData.getMaterial().name().toLowerCase(Locale.ROOT); + private static final class Holder { + private static final BlockData AIR = BukkitBlockResolution.get("AIR"); + private static final NBTWorldSupport.BlockStateCodec BLOCK_STATE_CODEC = NBTWorldSupport.blockStateCodec( + blockStateString -> BukkitBlockResolution.getOrNull(blockStateString, true), + BukkitBlockResolution::getAir, + blockData -> blockData.getAsString(true), + blockData -> { + NamespacedKey key = KeyedType.getKey(blockData.getMaterial()); + if (key == null) { + return "minecraft:" + blockData.getMaterial().name().toLowerCase(Locale.ROOT); + } + return key.getNamespace() + ":" + key.getKey(); } - return key.getNamespace() + ":" + key.getKey(); - } - ); - private static final Map biomeIds = computeBiomeIDs(); + ); + private static final Map BIOME_IDS = computeBiomeIDs(); + } + private final HyperLock hyperLock = new HyperLock(); private final MCAWorldStoreSupport regionStore; private final MCAWorldRuntimeSupport worldRuntime; @@ -124,11 +127,11 @@ public class NBTWorld { } public static BlockData getBlockData(CompoundTag tag) { - return BLOCK_STATE_CODEC.decode(tag); + return Holder.BLOCK_STATE_CODEC.decode(tag); } public static CompoundTag getCompound(BlockData bd) { - return BLOCK_STATE_CODEC.encode(bd); + return Holder.BLOCK_STATE_CODEC.encode(bd); } private static Map computeBiomeIDs() { @@ -193,7 +196,7 @@ public class NBTWorld { CompoundTag tag = worldRuntime.getBlockStateTag(x, y, z); if (tag == null) { - return AIR; + return Holder.AIR; } return getBlockData(tag); @@ -201,7 +204,7 @@ public class NBTWorld { IrisLogging.reportError(e); } - return AIR; + return Holder.AIR; } public void setBlockData(int x, int y, int z, BlockData data) { @@ -209,11 +212,11 @@ public class NBTWorld { } public int getBiomeId(Biome b) { - return biomeIds.get(b); + return Holder.BIOME_IDS.get(b); } public void setBiome(int x, int y, int z, Biome biome) { - worldRuntime.setBiomeId(x, y, z, biomeIds.get(biome)); + worldRuntime.setBiomeId(x, y, z, Holder.BIOME_IDS.get(biome)); } public Section getChunkSection(int x, int y, int z) { diff --git a/core/src/main/java/art/arcane/iris/util/project/context/ChunkContext.java b/core/src/main/java/art/arcane/iris/util/project/context/ChunkContext.java index cbc88d09d..d373d96a2 100644 --- a/core/src/main/java/art/arcane/iris/util/project/context/ChunkContext.java +++ b/core/src/main/java/art/arcane/iris/util/project/context/ChunkContext.java @@ -102,7 +102,10 @@ public class ChunkContext { return false; } - String threadName = Thread.currentThread().getName(); + return prefillAsyncEligible(Thread.currentThread().getName()); + } + + static boolean prefillAsyncEligible(String threadName) { return threadName != null && threadName.startsWith("Iris "); } diff --git a/core/src/main/java/art/arcane/iris/util/project/hunk/view/ChunkDataHunkHolder.java b/core/src/main/java/art/arcane/iris/util/project/hunk/view/ChunkDataHunkHolder.java index 7fccad5d0..4b895caec 100644 --- a/core/src/main/java/art/arcane/iris/util/project/hunk/view/ChunkDataHunkHolder.java +++ b/core/src/main/java/art/arcane/iris/util/project/hunk/view/ChunkDataHunkHolder.java @@ -18,16 +18,18 @@ package art.arcane.iris.util.project.hunk.view; -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.project.hunk.storage.AtomicHunk; -import org.bukkit.Material; import org.bukkit.block.data.BlockData; import org.bukkit.generator.ChunkGenerator.ChunkData; @SuppressWarnings("ClassCanBeRecord") public class ChunkDataHunkHolder extends AtomicHunk { - private static final PlatformBlockState AIR = BukkitBlockState.of(Material.AIR.createBlockData()); + private static final class States { + private static final PlatformBlockState AIR = B.getState("AIR"); + } + private final ChunkData chunk; public ChunkDataHunkHolder(ChunkData chunk) { @@ -54,7 +56,7 @@ public class ChunkDataHunkHolder extends AtomicHunk { public PlatformBlockState getRaw(int x, int y, int z) { PlatformBlockState b = super.getRaw(x, y, z); - return b != null ? b : AIR; + return b != null ? b : States.AIR; } public void apply() { diff --git a/core/src/main/java/art/arcane/iris/util/project/hunk/view/ChunkDataHunkView.java b/core/src/main/java/art/arcane/iris/util/project/hunk/view/ChunkDataHunkView.java index 85f9be732..6d51d3d76 100644 --- a/core/src/main/java/art/arcane/iris/util/project/hunk/view/ChunkDataHunkView.java +++ b/core/src/main/java/art/arcane/iris/util/project/hunk/view/ChunkDataHunkView.java @@ -29,12 +29,10 @@ import org.bukkit.generator.ChunkGenerator.ChunkData; @SuppressWarnings("ClassCanBeRecord") public class ChunkDataHunkView implements Hunk { - private static final BlockData AIR = BukkitBlockResolution.getAir(); - private final art.arcane.volmlib.util.hunk.view.ChunkDataHunkView view; public ChunkDataHunkView(ChunkData chunk) { - this.view = new art.arcane.volmlib.util.hunk.view.ChunkDataHunkView(chunk, AIR, (data) -> data instanceof IrisCustomData d ? d.getBase() : data); + this.view = new art.arcane.volmlib.util.hunk.view.ChunkDataHunkView(chunk, BukkitBlockResolution.getAir(), (data) -> data instanceof IrisCustomData d ? d.getBase() : data); } @Override 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 09db2fde6..9e26ab889 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 @@ -28,7 +28,7 @@ import art.arcane.iris.util.project.matter.slices.TileMatter; import art.arcane.volmlib.util.matter.IrisMatter; import art.arcane.volmlib.util.matter.Matter; import org.bukkit.block.data.BlockData; -import org.bukkit.util.BlockVector; +import art.arcane.iris.util.common.math.IrisBlockVector; import java.io.File; @@ -54,16 +54,16 @@ public final class IrisMatterSupport { ensureRegistered(); object.clean(); object.shrinkwrap(); - BlockVector min = new BlockVector(); + IrisBlockVector min = new IrisBlockVector(); Matter matter = new IrisMatter(Math.max(object.getW(), 1) + 1, Math.max(object.getH(), 1) + 1, Math.max(object.getD(), 1) + 1); - for (BlockVector i : object.getBlocks().keys()) { + for (IrisBlockVector i : object.getBlocks().keys()) { min.setX(Math.min(min.getX(), i.getX())); min.setY(Math.min(min.getY(), i.getY())); min.setZ(Math.min(min.getZ(), i.getZ())); } - for (BlockVector i : object.getBlocks().keys()) { + for (IrisBlockVector i : object.getBlocks().keys()) { matter.slice(BlockData.class).set(i.getBlockX() - min.getBlockX(), i.getBlockY() - min.getBlockY(), i.getBlockZ() - min.getBlockZ(), (BlockData) object.getBlocks().get(i).nativeHandle()); } diff --git a/core/src/main/java/art/arcane/iris/util/project/sentry/ServerID.java b/core/src/main/java/art/arcane/iris/util/project/sentry/ServerID.java index 0545c144c..69b99e06f 100644 --- a/core/src/main/java/art/arcane/iris/util/project/sentry/ServerID.java +++ b/core/src/main/java/art/arcane/iris/util/project/sentry/ServerID.java @@ -12,11 +12,17 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class ServerID { - public static final String ID = calculate(); + private static final class Holder { + private static final String ID = calculate(); + } + + public static String getId() { + return Holder.ID; + } public static User asUser() { User u = new User(); - u.setId(ID); + u.setId(Holder.ID); return u; } diff --git a/core/src/test/java/art/arcane/iris/engine/object/IrisObjectRotationFlipTest.java b/core/src/test/java/art/arcane/iris/engine/object/IrisObjectRotationFlipTest.java index 3d5b58921..12d099032 100644 --- a/core/src/test/java/art/arcane/iris/engine/object/IrisObjectRotationFlipTest.java +++ b/core/src/test/java/art/arcane/iris/engine/object/IrisObjectRotationFlipTest.java @@ -1,6 +1,6 @@ package art.arcane.iris.engine.object; -import org.bukkit.util.BlockVector; +import art.arcane.iris.util.common.math.IrisBlockVector; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -28,8 +28,8 @@ public class IrisObjectRotationFlipTest { @Test public void xFlip180WithY_zeroYaw_stillUsesFixedYRotation() { IrisObjectRotation rot = IrisObjectRotation.xFlip180WithY(0); - BlockVector v = new BlockVector(1, 2, 3); - BlockVector result = rot.rotate(v, 117, 253, 91); + IrisBlockVector v = new IrisBlockVector(1, 2, 3); + IrisBlockVector result = rot.rotate(v, 117, 253, 91); assertTrue(rot.canRotateY()); assertEquals(1, result.getBlockX()); assertEquals(-2, result.getBlockY()); @@ -39,8 +39,8 @@ public class IrisObjectRotationFlipTest { @Test public void xFlip180WithY_ninetyYaw_rotatesMirroredFootprint() { IrisObjectRotation rot = IrisObjectRotation.xFlip180WithY(90); - BlockVector v = new BlockVector(2, 5, 3); - BlockVector result = rot.rotate(v, 0, 0, 0); + IrisBlockVector v = new IrisBlockVector(2, 5, 3); + IrisBlockVector result = rot.rotate(v, 0, 0, 0); assertEquals(-3, result.getBlockX()); assertEquals(-5, result.getBlockY()); assertEquals(-2, result.getBlockZ()); @@ -49,8 +49,8 @@ public class IrisObjectRotationFlipTest { @Test public void xFlip180_rotateVector_negatesYandZ() { IrisObjectRotation rot = IrisObjectRotation.xFlip180(); - BlockVector v = new BlockVector(1, 2, 3); - BlockVector result = rot.rotate(v, 0, 0, 0); + IrisBlockVector v = new IrisBlockVector(1, 2, 3); + IrisBlockVector result = rot.rotate(v, 0, 0, 0); assertEquals(1, result.getBlockX()); assertEquals(-2, result.getBlockY()); assertEquals(-3, result.getBlockZ()); @@ -59,8 +59,8 @@ public class IrisObjectRotationFlipTest { @Test public void xFlip180_rotateNegativeVector_negatesYandZ() { IrisObjectRotation rot = IrisObjectRotation.xFlip180(); - BlockVector v = new BlockVector(-3, -5, -7); - BlockVector result = rot.rotate(v, 0, 0, 0); + IrisBlockVector v = new IrisBlockVector(-3, -5, -7); + IrisBlockVector result = rot.rotate(v, 0, 0, 0); assertEquals(-3, result.getBlockX()); assertEquals(5, result.getBlockY()); assertEquals(7, result.getBlockZ()); diff --git a/core/src/test/java/art/arcane/iris/util/project/context/ChunkContextPrefillPlanTest.java b/core/src/test/java/art/arcane/iris/util/project/context/ChunkContextPrefillPlanTest.java index 6d5ae33bb..fc073028d 100644 --- a/core/src/test/java/art/arcane/iris/util/project/context/ChunkContextPrefillPlanTest.java +++ b/core/src/test/java/art/arcane/iris/util/project/context/ChunkContextPrefillPlanTest.java @@ -172,7 +172,7 @@ public class ChunkContextPrefillPlanTest { return thread; }); try { - Future future = executor.submit(() -> ChunkContext.shouldPrefillAsync(2)); + Future future = executor.submit(() -> ChunkContext.prefillAsyncEligible(Thread.currentThread().getName())); boolean actual = future.get(10, TimeUnit.SECONDS); if (expected) { assertTrue(actual); diff --git a/probe/build.gradle b/probe/build.gradle new file mode 100644 index 000000000..dbd0a046b --- /dev/null +++ b/probe/build.gradle @@ -0,0 +1,37 @@ +plugins { + id 'application' +} + +group = 'art.arcane' +version = rootProject.version + +application { + mainClass = 'art.arcane.iris.probe.ClassloadProbe' +} + +dependencies { + implementation(project(':core')) + runtimeOnly(libs.paralithic) + runtimeOnly(libs.gson) + runtimeOnly(libs.lru) + runtimeOnly(libs.kotlin.coroutines) + runtimeOnly(libs.commons.io) + runtimeOnly(libs.commons.lang) + runtimeOnly(libs.commons.lang3) + runtimeOnly(libs.commons.math3) + runtimeOnly(libs.fastutil) + runtimeOnly(libs.caffeine) + runtimeOnly(libs.lz4) + runtimeOnly(libs.zip) + runtimeOnly('com.google.guava:guava:33.4.0-jre') + runtimeOnly(libs.sentry) + runtimeOnly(libs.oshi) + runtimeOnly(libs.byteBuddy.core) + runtimeOnly(libs.byteBuddy.agent) +} + +tasks.named('run', JavaExec).configure { + args(project(':core').layout.buildDirectory.dir('classes/java/main').get().asFile.absolutePath) + jvmArgs('--add-modules', 'jdk.incubator.vector') + dependsOn(':core:compileJava') +} diff --git a/probe/src/main/java/art/arcane/iris/probe/ClassloadProbe.java b/probe/src/main/java/art/arcane/iris/probe/ClassloadProbe.java new file mode 100644 index 000000000..600d42302 --- /dev/null +++ b/probe/src/main/java/art/arcane/iris/probe/ClassloadProbe.java @@ -0,0 +1,137 @@ +/* + * Iris is a World Generator for Minecraft Servers + * Copyright (c) 2026 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package art.arcane.iris.probe; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.TreeMap; +import java.util.stream.Stream; + +public final class ClassloadProbe { + private static final String[] CRITICAL_PREFIXES = { + "art.arcane.iris.engine.", + "art.arcane.iris.util.", + "art.arcane.iris.core.loader.", + "art.arcane.iris.spi.", + }; + + private static final String[] EXEMPT_PREFIXES = { + "art.arcane.iris.platform.bukkit.", + "art.arcane.iris.engine.platform.", + "art.arcane.iris.util.common.plugin.", + "art.arcane.iris.util.common.inventorygui.", + "art.arcane.iris.util.common.director.", + "art.arcane.iris.util.common.data.registry.", + }; + + private static final String[] EXEMPT_CLASSES = { + "art.arcane.iris.util.common.misc.Bindings", + "art.arcane.iris.util.common.misc.SlimJar", + "art.arcane.iris.util.common.misc.ServerProperties", + }; + + public static void main(String[] args) throws IOException { + art.arcane.iris.spi.IrisPlatforms.bind(new StubPlatform()); + boolean bukkitPresent = true; + try { + Class.forName("org.bukkit.Bukkit", false, ClassloadProbe.class.getClassLoader()); + } catch (ClassNotFoundException absent) { + bukkitPresent = false; + } + System.out.println("[probe] org.bukkit on classpath: " + bukkitPresent); + + Path classesRoot = Path.of(args[0]); + List names = new ArrayList<>(); + try (Stream walk = Files.walk(classesRoot)) { + walk.filter(p -> p.toString().endsWith(".class")) + .forEach(p -> { + String rel = classesRoot.relativize(p).toString(); + String name = rel.substring(0, rel.length() - 6).replace('/', '.'); + if (name.contains("$")) { + return; + } + names.add(name); + }); + } + names.sort(String::compareTo); + + TreeMap criticalFailures = new TreeMap<>(); + TreeMap otherFailures = new TreeMap<>(); + int loaded = 0; + int criticalTotal = 0; + for (String name : names) { + boolean critical = matchesAny(name, CRITICAL_PREFIXES) && !matchesAny(name, EXEMPT_PREFIXES) && !exactAny(name); + if (critical) { + criticalTotal++; + } + try { + Class.forName(name, true, ClassloadProbe.class.getClassLoader()); + loaded++; + } catch (Throwable failure) { + String cause = rootCause(failure); + if (critical) { + criticalFailures.put(name, cause); + } else { + otherFailures.put(name, cause); + } + } + } + + System.out.println("[probe] classes scanned: " + names.size() + ", initialized OK: " + loaded); + System.out.println("[probe] critical set: " + criticalTotal + ", critical failures: " + criticalFailures.size()); + criticalFailures.forEach((name, cause) -> System.out.println(" CRITICAL " + name + " -> " + cause)); + System.out.println("[probe] non-critical failures: " + otherFailures.size()); + otherFailures.forEach((name, cause) -> System.out.println(" other " + name + " -> " + cause)); + + if (!criticalFailures.isEmpty()) { + System.out.println("[probe] RESULT: FAIL"); + System.exit(1); + } + System.out.println("[probe] RESULT: PASS"); + } + + private static boolean exactAny(String name) { + for (String exempt : EXEMPT_CLASSES) { + if (name.equals(exempt)) { + return true; + } + } + return false; + } + + private static boolean matchesAny(String name, String[] prefixes) { + for (String prefix : prefixes) { + if (name.startsWith(prefix)) { + return true; + } + } + return false; + } + + private static String rootCause(Throwable failure) { + Throwable cause = failure; + while (cause.getCause() != null && cause.getCause() != cause) { + cause = cause.getCause(); + } + return cause.getClass().getSimpleName() + ": " + cause.getMessage(); + } +} diff --git a/probe/src/main/java/art/arcane/iris/probe/StubPlatform.java b/probe/src/main/java/art/arcane/iris/probe/StubPlatform.java new file mode 100644 index 000000000..3a94b8f13 --- /dev/null +++ b/probe/src/main/java/art/arcane/iris/probe/StubPlatform.java @@ -0,0 +1,300 @@ +/* + * Iris is a World Generator for Minecraft Servers + * Copyright (c) 2026 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package art.arcane.iris.probe; + +import art.arcane.iris.spi.IrisPlatform; +import art.arcane.iris.spi.LogLevel; +import art.arcane.iris.spi.PlatformBiome; +import art.arcane.iris.spi.PlatformBiomeWriter; +import art.arcane.iris.spi.PlatformBlockState; +import art.arcane.iris.spi.PlatformCapabilities; +import art.arcane.iris.spi.PlatformEntityType; +import art.arcane.iris.spi.PlatformItem; +import art.arcane.iris.spi.PlatformRegistries; +import art.arcane.iris.spi.PlatformScheduler; +import art.arcane.iris.spi.PlatformStructureHooks; + +import java.io.File; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +public final class StubPlatform implements IrisPlatform { + private final StubRegistries registries = new StubRegistries(); + + private static final class StubBlockState implements PlatformBlockState { + private static final ConcurrentHashMap CACHE = new ConcurrentHashMap<>(); + private final String key; + + private StubBlockState(String key) { + this.key = key; + } + + static StubBlockState of(String key) { + return CACHE.computeIfAbsent(key, StubBlockState::new); + } + + @Override + public String key() { + return key; + } + + @Override + public String namespace() { + int colon = key.indexOf(':'); + return colon >= 0 ? key.substring(0, colon) : "minecraft"; + } + + @Override + public boolean isAir() { + return key.endsWith("air"); + } + + @Override + public boolean isSolid() { + return !isAir(); + } + + @Override + public boolean isFluid() { + return false; + } + + @Override + public boolean isWater() { + return false; + } + + @Override + public boolean isWaterLogged() { + return false; + } + + @Override + public boolean isLit() { + return false; + } + + @Override + public boolean isUpdatable() { + return false; + } + + @Override + public boolean isFoliage() { + return false; + } + + @Override + public boolean isFoliagePlantable() { + return false; + } + + @Override + public boolean isDecorant() { + return false; + } + + @Override + public boolean isStorage() { + return false; + } + + @Override + public boolean isStorageChest() { + return false; + } + + @Override + public boolean isOre() { + return false; + } + + @Override + public boolean isDeepSlate() { + return false; + } + + @Override + public boolean isVineBlock() { + return false; + } + + @Override + public boolean canPlaceOnto(PlatformBlockState onto) { + return true; + } + + @Override + public boolean matches(PlatformBlockState state) { + return equals(state); + } + + @Override + public boolean hasTileEntity() { + return false; + } + + @Override + public PlatformBlockState withProperty(String name, String value) { + return this; + } + + @Override + public Object nativeHandle() { + return key; + } + } + + private static final class StubRegistries implements PlatformRegistries { + @Override + public PlatformBlockState block(String key) { + return StubBlockState.of(key); + } + + @Override + public PlatformBlockState blockOrNull(String key) { + return StubBlockState.of(key); + } + + @Override + public PlatformBlockState blockOrNull(String key, boolean warn) { + return StubBlockState.of(key); + } + + @Override + public PlatformBlockState air() { + return StubBlockState.of("minecraft:air"); + } + + @Override + public PlatformBlockState deepSlateOre(PlatformBlockState block, PlatformBlockState ore) { + return ore; + } + + @Override + public PlatformBiome biome(String key) { + return null; + } + + @Override + public PlatformItem item(String key) { + return null; + } + + @Override + public PlatformEntityType entity(String key) { + return null; + } + + @Override + public List blockKeys() { + return List.of(); + } + + @Override + public List biomeKeys() { + return List.of(); + } + + @Override + public List structureKeys() { + return List.of(); + } + } + + @Override + public String platformName() { + return "probe"; + } + + @Override + public String minecraftVersion() { + return "probe"; + } + + @Override + public PlatformRegistries registries() { + return registries; + } + + @Override + public PlatformScheduler scheduler() { + return null; + } + + @Override + public PlatformCapabilities capabilities() { + return null; + } + + @Override + public PlatformStructureHooks structureHooks() { + return null; + } + + @Override + public PlatformBiomeWriter biomeWriter() { + return null; + } + + @Override + public File dataFolder() { + return new File(System.getProperty("java.io.tmpdir"), "iris-probe"); + } + + @Override + public File dataFile(String... path) { + return new File(dataFolder(), String.join(File.separator, path)); + } + + @Override + public File pluginJar() { + return new File(dataFolder(), "probe.jar"); + } + + @Override + public int irisVersionNumber() { + return 0; + } + + @Override + public int minecraftVersionNumber() { + return 0; + } + + @Override + public void callEvent(Object event) { + } + + @Override + public void dispatchConsoleCommand(String command) { + } + + @Override + public void log(LogLevel level, String message) { + } + + @Override + public void msg(String message) { + } + + @Override + public void reportError(Throwable error) { + } +} diff --git a/settings.gradle b/settings.gradle index a35d058af..07f33339e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -69,6 +69,7 @@ if (useLocalVolmLib && localVolmLibDirectory != null) { } include(':core', ':core:agent') +include(':probe') include(':spi') include(':adapters:bukkit:plugin') include(':adapters:bukkit:nms:v1_21_R7')
Dye ColorColor
%1$sTest String