Sunset box

- Unused in flywheel and not a productive utility for others with the
  new features
This commit is contained in:
Jozufozu 2024-07-13 21:36:15 -07:00
parent 0c5995bad8
commit c4c4d45b0b
4 changed files with 0 additions and 714 deletions

View File

@ -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);
}
}

View File

@ -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<BlockPos> 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 + ')';
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}