diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/box/Box.java b/common/src/lib/java/dev/engine_room/flywheel/lib/box/Box.java deleted file mode 100644 index 3955cde1b..000000000 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/box/Box.java +++ /dev/null @@ -1,142 +0,0 @@ -package dev.engine_room.flywheel.lib.box; - -import net.minecraft.util.Mth; -import net.minecraft.world.phys.AABB; - -public interface Box { - int getMinX(); - - int getMinY(); - - int getMinZ(); - - int getMaxX(); - - int getMaxY(); - - int getMaxZ(); - - default int sizeX() { - return getMaxX() - getMinX(); - } - - default int sizeY() { - return getMaxY() - getMinY(); - } - - default int sizeZ() { - return getMaxZ() - getMinZ(); - } - - default int volume() { - return sizeX() * sizeY() * sizeZ(); - } - - default boolean isEmpty() { - // if any dimension has side length 0 this box contains no volume - return getMinX() == getMaxX() || getMinY() == getMaxY() || getMinZ() == getMaxZ(); - } - - default boolean sameAs(Box other) { - return getMinX() == other.getMinX() && getMinY() == other.getMinY() && getMinZ() == other.getMinZ() && getMaxX() == other.getMaxX() && getMaxY() == other.getMaxY() && getMaxZ() == other.getMaxZ(); - } - - default boolean sameAs(Box other, int margin) { - return getMinX() == other.getMinX() - margin && - getMinY() == other.getMinY() - margin && - getMinZ() == other.getMinZ() - margin && - getMaxX() == other.getMaxX() + margin && - getMaxY() == other.getMaxY() + margin && - getMaxZ() == other.getMaxZ() + margin; - } - - default boolean sameAs(AABB other) { - return getMinX() == Math.floor(other.minX) - && getMinY() == Math.floor(other.minY) - && getMinZ() == Math.floor(other.minZ) - && getMaxX() == Math.ceil(other.maxX) - && getMaxY() == Math.ceil(other.maxY) - && getMaxZ() == Math.ceil(other.maxZ); - } - - default boolean intersects(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) { - return this.getMinX() < maxX && this.getMaxX() > minX && this.getMinY() < maxY && this.getMaxY() > minY && this.getMinZ() < maxZ && this.getMaxZ() > minZ; - } - - default boolean intersects(Box other) { - return this.intersects(other.getMinX(), other.getMinY(), other.getMinZ(), other.getMaxX(), other.getMaxY(), other.getMaxZ()); - } - - default boolean contains(int x, int y, int z) { - return x >= getMinX() - && x <= getMaxX() - && y >= getMinY() - && y <= getMaxY() - && z >= getMinZ() - && z <= getMaxZ(); - } - - default boolean contains(Box other) { - return other.getMinX() >= this.getMinX() - && other.getMaxX() <= this.getMaxX() - && other.getMinY() >= this.getMinY() - && other.getMaxY() <= this.getMaxY() - && other.getMinZ() >= this.getMinZ() - && other.getMaxZ() <= this.getMaxZ(); - } - - default void forEachContained(CoordinateConsumer func) { - int minX = getMinX(); - int minY = getMinY(); - int minZ = getMinZ(); - int maxX = getMaxX(); - int maxY = getMaxY(); - int maxZ = getMaxZ(); - - for (int x = minX; x < maxX; x++) { - for (int y = minY; y < maxY; y++) { - for (int z = minZ; z < maxZ; z++) { - func.accept(x, y, z); - } - } - } - } - - default boolean hasPowerOf2Sides() { - // this is only true if all individual side lengths are powers of 2 - return Mth.isPowerOfTwo(volume()); - } - - default MutableBox union(Box other) { - int minX = Math.min(this.getMinX(), other.getMinX()); - int minY = Math.min(this.getMinY(), other.getMinY()); - int minZ = Math.min(this.getMinZ(), other.getMinZ()); - int maxX = Math.max(this.getMaxX(), other.getMaxX()); - int maxY = Math.max(this.getMaxY(), other.getMaxY()); - int maxZ = Math.max(this.getMaxZ(), other.getMaxZ()); - return new MutableBox(minX, minY, minZ, maxX, maxY, maxZ); - } - - default MutableBox intersect(Box other) { - int minX = Math.max(this.getMinX(), other.getMinX()); - int minY = Math.max(this.getMinY(), other.getMinY()); - int minZ = Math.max(this.getMinZ(), other.getMinZ()); - int maxX = Math.min(this.getMaxX(), other.getMaxX()); - int maxY = Math.min(this.getMaxY(), other.getMaxY()); - int maxZ = Math.min(this.getMaxZ(), other.getMaxZ()); - return new MutableBox(minX, minY, minZ, maxX, maxY, maxZ); - } - - default AABB toAABB() { - return new AABB(getMinX(), getMinY(), getMinZ(), getMaxX(), getMaxY(), getMaxZ()); - } - - default MutableBox copy() { - return new MutableBox(getMinX(), getMinY(), getMinZ(), getMaxX(), getMaxY(), getMaxZ()); - } - - @FunctionalInterface - interface CoordinateConsumer { - void accept(int x, int y, int z); - } -} diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/box/MutableBox.java b/common/src/lib/java/dev/engine_room/flywheel/lib/box/MutableBox.java deleted file mode 100644 index db69a3883..000000000 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/box/MutableBox.java +++ /dev/null @@ -1,329 +0,0 @@ -package dev.engine_room.flywheel.lib.box; - -import java.util.Collection; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.SectionPos; -import net.minecraft.core.Vec3i; -import net.minecraft.util.Mth; -import net.minecraft.world.phys.AABB; - -public class MutableBox implements Box { - protected int minX; - protected int minY; - protected int minZ; - protected int maxX; - protected int maxY; - protected int maxZ; - - public MutableBox() { - } - - public MutableBox(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) { - this.minX = minX; - this.minY = minY; - this.minZ = minZ; - this.maxX = maxX; - this.maxY = maxY; - this.maxZ = maxZ; - } - - public static MutableBox from(AABB aabb) { - int minX = (int) Math.floor(aabb.minX); - int minY = (int) Math.floor(aabb.minY); - int minZ = (int) Math.floor(aabb.minZ); - int maxX = (int) Math.ceil(aabb.maxX); - int maxY = (int) Math.ceil(aabb.maxY); - int maxZ = (int) Math.ceil(aabb.maxZ); - return new MutableBox(minX, minY, minZ, maxX, maxY, maxZ); - } - - public static MutableBox from(Vec3i pos) { - return new MutableBox(pos.getX(), pos.getY(), pos.getZ(), pos.getX() + 1, pos.getY() + 1, pos.getZ() + 1); - } - - public static MutableBox from(SectionPos pos) { - return new MutableBox(pos.minBlockX(), pos.minBlockY(), pos.minBlockZ(), pos.maxBlockX() + 1, pos.maxBlockY() + 1, pos.maxBlockZ() + 1); - } - - public static MutableBox from(Vec3i start, Vec3i end) { - return new MutableBox(start.getX(), start.getY(), start.getZ(), end.getX() + 1, end.getY() + 1, end.getZ() + 1); - } - - public static MutableBox ofRadius(int radius) { - return new MutableBox(-radius, -radius, -radius, radius + 1, radius + 1, radius + 1); - } - - public static Box containingAll(Collection positions) { - if (positions.isEmpty()) { - return new MutableBox(); - } - int minX = Integer.MAX_VALUE; - int minY = Integer.MAX_VALUE; - int minZ = Integer.MAX_VALUE; - int maxX = Integer.MIN_VALUE; - int maxY = Integer.MIN_VALUE; - int maxZ = Integer.MIN_VALUE; - for (BlockPos pos : positions) { - minX = Math.min(minX, pos.getX()); - minY = Math.min(minY, pos.getY()); - minZ = Math.min(minZ, pos.getZ()); - maxX = Math.max(maxX, pos.getX()); - maxY = Math.max(maxY, pos.getY()); - maxZ = Math.max(maxZ, pos.getZ()); - } - return new MutableBox(minX, minY, minZ, maxX, maxY, maxZ); - } - - @Override - public int getMinX() { - return minX; - } - - @Override - public int getMinY() { - return minY; - } - - @Override - public int getMinZ() { - return minZ; - } - - @Override - public int getMaxX() { - return maxX; - } - - @Override - public int getMaxY() { - return maxY; - } - - @Override - public int getMaxZ() { - return maxZ; - } - - public void setMinX(int minX) { - this.minX = minX; - } - - public void setMinY(int minY) { - this.minY = minY; - } - - public MutableBox setMinZ(int minZ) { - this.minZ = minZ; - return this; - } - - public void setMaxX(int maxX) { - this.maxX = maxX; - } - - public void setMaxY(int maxY) { - this.maxY = maxY; - } - - public void setMaxZ(int maxZ) { - this.maxZ = maxZ; - } - - public void setMin(int x, int y, int z) { - minX = x; - minY = y; - minZ = z; - } - - public void setMax(int x, int y, int z) { - maxX = x; - maxY = y; - maxZ = z; - } - - public void setMin(Vec3i v) { - setMin(v.getX(), v.getY(), v.getZ()); - } - - public void setMax(Vec3i v) { - setMax(v.getX(), v.getY(), v.getZ()); - } - - public void assign(Box other) { - minX = other.getMinX(); - minY = other.getMinY(); - minZ = other.getMinZ(); - maxX = other.getMaxX(); - maxY = other.getMaxY(); - maxZ = other.getMaxZ(); - } - - public void assign(AABB other) { - minX = (int) Math.floor(other.minX); - minY = (int) Math.floor(other.minY); - minZ = (int) Math.floor(other.minZ); - maxX = (int) Math.ceil(other.maxX); - maxY = (int) Math.ceil(other.maxY); - maxZ = (int) Math.ceil(other.maxZ); - } - - public void assign(Vec3i start, Vec3i end) { - minX = start.getX(); - minY = start.getY(); - minZ = start.getZ(); - maxX = end.getX() + 1; - maxY = end.getY() + 1; - maxZ = end.getZ() + 1; - } - - public void unionAssign(Box other) { - minX = Math.min(this.minX, other.getMinX()); - minY = Math.min(this.minY, other.getMinY()); - minZ = Math.min(this.minZ, other.getMinZ()); - maxX = Math.max(this.maxX, other.getMaxX()); - maxY = Math.max(this.maxY, other.getMaxY()); - maxZ = Math.max(this.maxZ, other.getMaxZ()); - } - - public void unionAssign(AABB other) { - minX = Math.min(this.minX, (int) Math.floor(other.minX)); - minY = Math.min(this.minY, (int) Math.floor(other.minY)); - minZ = Math.min(this.minZ, (int) Math.floor(other.minZ)); - maxX = Math.max(this.maxX, (int) Math.ceil(other.maxX)); - maxY = Math.max(this.maxY, (int) Math.ceil(other.maxY)); - maxZ = Math.max(this.maxZ, (int) Math.ceil(other.maxZ)); - } - - public void intersectAssign(Box other) { - minX = Math.max(this.minX, other.getMinX()); - minY = Math.max(this.minY, other.getMinY()); - minZ = Math.max(this.minZ, other.getMinZ()); - maxX = Math.min(this.maxX, other.getMaxX()); - maxY = Math.min(this.maxY, other.getMaxY()); - maxZ = Math.min(this.maxZ, other.getMaxZ()); - } - - public void fixMinMax() { - int minX = Math.min(this.minX, this.maxX); - int minY = Math.min(this.minY, this.maxY); - int minZ = Math.min(this.minZ, this.maxZ); - int maxX = Math.max(this.minX, this.maxX); - int maxY = Math.max(this.minY, this.maxY); - int maxZ = Math.max(this.minZ, this.maxZ); - - this.minX = minX; - this.minY = minY; - this.minZ = minZ; - this.maxX = maxX; - this.maxY = maxY; - this.maxZ = maxZ; - } - - public void translate(int x, int y, int z) { - minX = minX + x; - maxX = maxX + x; - minY = minY + y; - maxY = maxY + y; - minZ = minZ + z; - maxZ = maxZ + z; - } - - public void translate(Vec3i by) { - translate(by.getX(), by.getY(), by.getZ()); - } - - public void grow(int x, int y, int z) { - minX = minX - x; - minY = minY - y; - minZ = minZ - z; - maxX = maxX + x; - maxY = maxY + y; - maxZ = maxZ + z; - } - - public void grow(int s) { - this.grow(s, s, s); - } - - /** - * Grow this box to have power of 2 side lengths, scaling from the minimum coords. - */ - public void nextPowerOf2() { - int sizeX = Mth.smallestEncompassingPowerOfTwo(sizeX()); - int sizeY = Mth.smallestEncompassingPowerOfTwo(sizeY()); - int sizeZ = Mth.smallestEncompassingPowerOfTwo(sizeZ()); - - maxX = minX + sizeX; - maxY = minY + sizeY; - maxZ = minZ + sizeZ; - } - - /** - * Grow this box to have power of 2 side length, scaling from the center. - */ - public void nextPowerOf2Centered() { - int sizeX = sizeX(); - int sizeY = sizeY(); - int sizeZ = sizeZ(); - - int newSizeX = Mth.smallestEncompassingPowerOfTwo(sizeX); - int newSizeY = Mth.smallestEncompassingPowerOfTwo(sizeY); - int newSizeZ = Mth.smallestEncompassingPowerOfTwo(sizeZ); - - int diffX = newSizeX - sizeX; - int diffY = newSizeY - sizeY; - int diffZ = newSizeZ - sizeZ; - - minX = minX - diffX / 2; // floor division for the minimums - minY = minY - diffY / 2; - minZ = minZ - diffZ / 2; - maxX = maxX + (diffX + 1) / 2; // ceiling divison for the maximums - maxY = maxY + (diffY + 1) / 2; - maxZ = maxZ + (diffZ + 1) / 2; - } - - public void mirrorAbout(Direction.Axis axis) { - Vec3i axisVec = Direction.get(Direction.AxisDirection.POSITIVE, axis) - .getNormal(); - int flipX = axisVec.getX() - 1; - int flipY = axisVec.getY() - 1; - int flipZ = axisVec.getZ() - 1; - - int maxX = this.maxX * flipX; - int maxY = this.maxY * flipY; - int maxZ = this.maxZ * flipZ; - this.maxX = this.minX * flipX; - this.maxY = this.minY * flipY; - this.maxZ = this.minZ * flipZ; - this.minX = maxX; - this.minY = maxY; - this.minZ = maxZ; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null) return false; - if (!(o instanceof Box that)) return false; - - return this.sameAs(that); - } - - @Override - public int hashCode() { - int result = minX; - result = 31 * result + minY; - result = 31 * result + minZ; - result = 31 * result + maxX; - result = 31 * result + maxY; - result = 31 * result + maxZ; - return result; - } - - @Override - public String toString() { - return "(" + minX + ", " + minY + ", " + minZ + ")->(" + maxX + ", " + maxY + ", " + maxZ + ')'; - } -} diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/light/LightPacking.java b/common/src/lib/java/dev/engine_room/flywheel/lib/light/LightPacking.java deleted file mode 100644 index 7cd9ce37e..000000000 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/light/LightPacking.java +++ /dev/null @@ -1,26 +0,0 @@ -package dev.engine_room.flywheel.lib.light; - -/** - * Utility class for bit-twiddling light. - */ -public class LightPacking { - public static int getBlock(short packed) { - return (packed >> 4) & 0xF; - } - - public static int getSky(short packed) { - return (packed >> 12) & 0xF; - } - - public static byte packLightNibbles(byte block, byte sky) { - return (byte) (block | (sky << 4)); - } - - public static int getBlock(byte packed) { - return packed & 0xF; - } - - public static int getSky(byte packed) { - return (packed >> 4) & 0xF; - } -} diff --git a/common/src/lib/java/dev/engine_room/flywheel/lib/light/LightVolume.java b/common/src/lib/java/dev/engine_room/flywheel/lib/light/LightVolume.java deleted file mode 100644 index ab71bcae3..000000000 --- a/common/src/lib/java/dev/engine_room/flywheel/lib/light/LightVolume.java +++ /dev/null @@ -1,217 +0,0 @@ -package dev.engine_room.flywheel.lib.light; - -import org.lwjgl.system.MemoryUtil; - -import dev.engine_room.flywheel.lib.box.Box; -import dev.engine_room.flywheel.lib.box.MutableBox; -import dev.engine_room.flywheel.lib.memory.MemoryBlock; -import net.minecraft.core.BlockPos; -import net.minecraft.core.SectionPos; -import net.minecraft.world.level.BlockAndTintGetter; -import net.minecraft.world.level.LightLayer; - -public class LightVolume implements Box { - protected final BlockAndTintGetter level; - protected final MutableBox box = new MutableBox(); - protected MemoryBlock lightData; - - public LightVolume(BlockAndTintGetter level, Box sampleVolume) { - this.level = level; - this.setBox(sampleVolume); - - this.lightData = MemoryBlock.malloc(this.box.volume() * 2); - } - - public Box getVolume() { - return box; - } - - @Override - public int getMinX() { - return box.getMinX(); - } - - @Override - public int getMinY() { - return box.getMinY(); - } - - @Override - public int getMinZ() { - return box.getMinZ(); - } - - @Override - public int getMaxX() { - return box.getMaxX(); - } - - @Override - public int getMaxY() { - return box.getMaxY(); - } - - @Override - public int getMaxZ() { - return box.getMaxZ(); - } - - public boolean isInvalid() { - return lightData == null; - } - - protected void setBox(Box box) { - this.box.assign(box); - } - - public short getPackedLight(int x, int y, int z) { - if (box.contains(x, y, z)) { - return MemoryUtil.memGetShort(levelPosToPtr(x, y, z)); - } else { - return 0; - } - } - - public void move(Box newSampleVolume) { - if (lightData == null) return; - - setBox(newSampleVolume); - int neededCapacity = box.volume() * 2; - if (neededCapacity > lightData.size()) { - lightData = lightData.realloc(neededCapacity); - } - initialize(); - } - - /** - * Completely (re)populate this volume with block and sky lighting data. - * This is expensive and should be avoided. - */ - public void initialize() { - if (lightData == null) return; - - copyLight(getVolume()); - markDirty(); - } - - protected void markDirty() { - // noop - } - - public void delete() { - lightData.free(); - lightData = null; - } - - /** - * Copy all light from the level into this volume. - * - * @param levelVolume the region in the level to copy data from. - */ - public void copyLight(Box levelVolume) { - BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(); - - int xShift = box.getMinX(); - int yShift = box.getMinY(); - int zShift = box.getMinZ(); - - levelVolume.forEachContained((x, y, z) -> { - pos.set(x, y, z); - - int block = this.level.getBrightness(LightLayer.BLOCK, pos); - int sky = this.level.getBrightness(LightLayer.SKY, pos); - - writeLight(x - xShift, y - yShift, z - zShift, block, sky); - }); - } - - protected void writeLight(int x, int y, int z, int block, int sky) { - byte b = (byte) ((block & 0xF) << 4); - byte s = (byte) ((sky & 0xF) << 4); - - long ptr = boxPosToPtr(x, y, z); - MemoryUtil.memPutByte(ptr, b); - MemoryUtil.memPutByte(ptr + 1, s); - } - - /** - * Copy block light from the level into this volume. - * - * @param levelVolume the region in the level to copy data from. - */ - public void copyBlock(Box levelVolume) { - var pos = new BlockPos.MutableBlockPos(); - - int xShift = box.getMinX(); - int yShift = box.getMinY(); - int zShift = box.getMinZ(); - - levelVolume.forEachContained((x, y, z) -> { - int light = this.level.getBrightness(LightLayer.BLOCK, pos.set(x, y, z)); - - writeBlock(x - xShift, y - yShift, z - zShift, light); - }); - } - - protected void writeBlock(int x, int y, int z, int block) { - byte b = (byte) ((block & 0xF) << 4); - - MemoryUtil.memPutByte(boxPosToPtr(x, y, z), b); - } - - /** - * Copy sky light from the level into this volume. - * - * @param levelVolume the region in the level to copy data from. - */ - public void copySky(Box levelVolume) { - var pos = new BlockPos.MutableBlockPos(); - - int xShift = box.getMinX(); - int yShift = box.getMinY(); - int zShift = box.getMinZ(); - - levelVolume.forEachContained((x, y, z) -> { - int light = this.level.getBrightness(LightLayer.SKY, pos.set(x, y, z)); - - writeSky(x - xShift, y - yShift, z - zShift, light); - }); - } - - protected void writeSky(int x, int y, int z, int sky) { - byte s = (byte) ((sky & 0xF) << 4); - - MemoryUtil.memPutByte(boxPosToPtr(x, y, z) + 1, s); - } - - protected long levelPosToPtr(int x, int y, int z) { - return lightData.ptr() + levelPosToPtrOffset(x, y, z); - } - - protected long boxPosToPtr(int x, int y, int z) { - return lightData.ptr() + boxPosToPtrOffset(x, y, z); - } - - protected int levelPosToPtrOffset(int x, int y, int z) { - x -= box.getMinX(); - y -= box.getMinY(); - z -= box.getMinZ(); - return boxPosToPtrOffset(x, y, z); - } - - protected int boxPosToPtrOffset(int x, int y, int z) { - return (x + box.sizeX() * (y + z * box.sizeY())) * 2; - } - - public void onLightUpdate(LightLayer type, SectionPos pos) { - if (lightData == null) return; - - MutableBox vol = MutableBox.from(pos); - if (!vol.intersects(getVolume())) return; - vol.intersectAssign(getVolume()); // compute the region contained by us that has dirty lighting data. - - if (type == LightLayer.BLOCK) copyBlock(vol); - else if (type == LightLayer.SKY) copySky(vol); - markDirty(); - } -}