Headless Pipeline

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