From a587ad352b4179f84e9d08179ad1adda73099fc6 Mon Sep 17 00:00:00 2001 From: FalsePattern <30945458+FalsePattern@users.noreply.github.com> Date: Fri, 6 May 2022 17:41:02 +0200 Subject: [PATCH] backport some stuff --- .../com/falsepattern/lib/compat/BlockPos.java | 569 ++++++++++++++++++ .../com/falsepattern/lib/compat/ChunkPos.java | 95 +++ .../com/falsepattern/lib/compat/Rotation.java | 128 ++++ .../com/falsepattern/lib/compat/Vec3i.java | 119 ++++ 4 files changed, 911 insertions(+) create mode 100644 src/main/java/com/falsepattern/lib/compat/BlockPos.java create mode 100644 src/main/java/com/falsepattern/lib/compat/ChunkPos.java create mode 100644 src/main/java/com/falsepattern/lib/compat/Rotation.java create mode 100644 src/main/java/com/falsepattern/lib/compat/Vec3i.java diff --git a/src/main/java/com/falsepattern/lib/compat/BlockPos.java b/src/main/java/com/falsepattern/lib/compat/BlockPos.java new file mode 100644 index 0000000..ab999b9 --- /dev/null +++ b/src/main/java/com/falsepattern/lib/compat/BlockPos.java @@ -0,0 +1,569 @@ +package com.falsepattern.lib.compat; + +import com.google.common.collect.AbstractIterator; +import com.google.common.collect.Lists; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.minecraft.entity.Entity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.MathHelper; +import net.minecraft.util.Vec3; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import javax.annotation.concurrent.Immutable; +import java.util.Iterator; +import java.util.List; + +@Immutable +public class BlockPos extends Vec3i { + /** + * An immutable block pos with zero as all coordinates. + */ + public static final BlockPos ORIGIN = new BlockPos(0, 0, 0); + private static final Logger LOGGER = LogManager.getLogger(); + private static final int NUM_X_BITS = 1 + MathHelper.calculateLogBaseTwo(MathHelper.roundUpToPowerOfTwo(30000000)); + private static final int NUM_Z_BITS = NUM_X_BITS; + private static final int NUM_Y_BITS = 64 - NUM_X_BITS - NUM_Z_BITS; + private static final long Y_MASK = (1L << NUM_Y_BITS) - 1L; + private static final int Y_SHIFT = NUM_Z_BITS; + private static final int X_SHIFT = Y_SHIFT + NUM_Y_BITS; + private static final long Z_MASK = (1L << NUM_Z_BITS) - 1L; + private static final long X_MASK = (1L << NUM_X_BITS) - 1L; + + public BlockPos(int x, int y, int z) { + super(x, y, z); + } + + public BlockPos(double x, double y, double z) { + super(x, y, z); + } + + public BlockPos(Entity source) { + this(source.posX, source.posY, source.posZ); + } + + public BlockPos(Vec3 vec) { + this(vec.xCoord, vec.yCoord, vec.zCoord); + } + + public BlockPos(Vec3i source) { + this(source.getX(), source.getY(), source.getZ()); + } + + /** + * Create a BlockPos from a serialized long value (created by toLong) + */ + public static BlockPos fromLong(long serialized) { + int i = (int) (serialized << 64 - X_SHIFT - NUM_X_BITS >> 64 - NUM_X_BITS); + int j = (int) (serialized << 64 - Y_SHIFT - NUM_Y_BITS >> 64 - NUM_Y_BITS); + int k = (int) (serialized << 64 - NUM_Z_BITS >> 64 - NUM_Z_BITS); + return new BlockPos(i, j, k); + } + + /** + * Create an Iterable that returns all positions in the box specified by the given corners. There is no requirement + * that one corner is greater than the other; individual coordinates will be swapped as needed. + *

+ * In situations where it is usable, prefer {@link #getAllInBoxMutable(BlockPos, BlockPos) instead as it has better + * performance (fewer allocations) + * + * @param from One corner of the box + * @param to Another corner of the box + * @see #getAllInBox(int, int, int, int, int, int) + * @see #getAllInBoxMutable(BlockPos, BlockPos) + */ + public static Iterable getAllInBox(BlockPos from, BlockPos to) { + return getAllInBox(Math.min(from.getX(), to.getX()), Math.min(from.getY(), to.getY()), Math.min(from.getZ(), to.getZ()), Math.max(from.getX(), to.getX()), Math.max(from.getY(), to.getY()), Math.max(from.getZ(), to.getZ())); + } + + /** + * Create an Iterable that returns all positions in the box specified by the coordinates. Coordinates must + * be in order; e.g. x1 <= x2. + *

+ * In situations where it is usable, prefer {@link #getAllInBoxMutable(BlockPos, BlockPos) instead as it has better + * performance (fewer allocations) + * + * @param x1 The lower x coordinate + * @param y1 The lower y coordinate + * @param z1 The lower z coordinate + * @param x2 The upper x coordinate + * @param y2 The upper y coordinate + * @param z2 The upper z coordinate + * @see #getAllInBox(BlockPos, BlockPos) + * @see #getAllInBoxMutable(BlockPos, BlockPos) + */ + public static Iterable getAllInBox(final int x1, final int y1, final int z1, final int x2, final int y2, final int z2) { + return new Iterable() { + public Iterator iterator() { + return new AbstractIterator() { + private boolean first = true; + private int lastPosX; + private int lastPosY; + private int lastPosZ; + + protected BlockPos computeNext() { + if (this.first) { + this.first = false; + this.lastPosX = x1; + this.lastPosY = y1; + this.lastPosZ = z1; + return new BlockPos(x1, y1, z1); + } else if (this.lastPosX == x2 && this.lastPosY == y2 && this.lastPosZ == z2) { + return this.endOfData(); + } else { + if (this.lastPosX < x2) { + ++this.lastPosX; + } else if (this.lastPosY < y2) { + this.lastPosX = x1; + ++this.lastPosY; + } else if (this.lastPosZ < z2) { + this.lastPosX = x1; + this.lastPosY = y1; + ++this.lastPosZ; + } + + return new BlockPos(this.lastPosX, this.lastPosY, this.lastPosZ); + } + } + }; + } + }; + } + + /** + * Creates an Iterable that returns all positions in the box specified by the given corners. There is no requirement + * that one corner is greater than the other; individual coordinates will be swapped as needed. + *

+ * This method uses {@link BlockPos.MutableBlockPos MutableBlockPos} instead of regular BlockPos, which grants + * better performance. However, the resulting BlockPos instances can only be used inside the iteration loop (as + * otherwise the value will change), unless {@link #toImmutable()} is called. This method is ideal for searching + * large areas and only storing a few locations. + * + * @param from One corner of the box + * @param to Another corner of the box + * @see #getAllInBox(BlockPos, BlockPos) + * @see #getAllInBox(int, int, int, int, int, int) + * @see #getAllInBoxMutable(BlockPos, BlockPos) + */ + public static Iterable getAllInBoxMutable(BlockPos from, BlockPos to) { + return getAllInBoxMutable(Math.min(from.getX(), to.getX()), Math.min(from.getY(), to.getY()), Math.min(from.getZ(), to.getZ()), Math.max(from.getX(), to.getX()), Math.max(from.getY(), to.getY()), Math.max(from.getZ(), to.getZ())); + } + + /** + * Creates an Iterable that returns all positions in the box specified by the given corners. Coordinates + * must be in order; e.g. x1 <= x2. + *

+ * This method uses {@link BlockPos.MutableBlockPos MutableBlockPos} instead of regular BlockPos, which grants + * better performance. However, the resulting BlockPos instances can only be used inside the iteration loop (as + * otherwise the value will change), unless {@link #toImmutable()} is called. This method is ideal for searching + * large areas and only storing a few locations. + * + * @param x1 The lower x coordinate + * @param y1 The lower y coordinate + * @param z1 The lower z coordinate + * @param x2 The upper x coordinate + * @param y2 The upper y coordinate + * @param z2 The upper z coordinate + * @see #getAllInBox(BlockPos, BlockPos) + * @see #getAllInBox(int, int, int, int, int, int) + * @see #getAllInBoxMutable(BlockPos, BlockPos) + */ + public static Iterable getAllInBoxMutable(final int x1, final int y1, final int z1, final int x2, final int y2, final int z2) { + return new Iterable() { + public Iterator iterator() { + return new AbstractIterator() { + private BlockPos.MutableBlockPos pos; + + protected BlockPos.MutableBlockPos computeNext() { + if (this.pos == null) { + this.pos = new BlockPos.MutableBlockPos(x1, y1, z1); + return this.pos; + } else if (this.pos.x == x2 && this.pos.y == y2 && this.pos.z == z2) { + return this.endOfData(); + } else { + if (this.pos.x < x2) { + ++this.pos.x; + } else if (this.pos.y < y2) { + this.pos.x = x1; + ++this.pos.y; + } else if (this.pos.z < z2) { + this.pos.x = x1; + this.pos.y = y1; + ++this.pos.z; + } + + return this.pos; + } + } + }; + } + }; + } + + /** + * Add the given coordinates to the coordinates of this BlockPos + */ + public BlockPos add(double x, double y, double z) { + return x == 0.0D && y == 0.0D && z == 0.0D ? this : new BlockPos((double) this.getX() + x, (double) this.getY() + y, (double) this.getZ() + z); + } + + /** + * Add the given coordinates to the coordinates of this BlockPos + */ + public BlockPos add(int x, int y, int z) { + return x == 0 && y == 0 && z == 0 ? this : new BlockPos(this.getX() + x, this.getY() + y, this.getZ() + z); + } + + /** + * Add the given Vector to this BlockPos + */ + public BlockPos add(Vec3i vec) { + return this.add(vec.getX(), vec.getY(), vec.getZ()); + } + + /** + * Subtract the given Vector from this BlockPos + */ + public BlockPos subtract(Vec3i vec) { + return this.add(-vec.getX(), -vec.getY(), -vec.getZ()); + } + + /** + * Offset this BlockPos 1 block up + */ + public BlockPos up() { + return this.up(1); + } + + /** + * Offset this BlockPos n blocks up + */ + public BlockPos up(int n) { + return this.offset(EnumFacing.UP, n); + } + + /** + * Offset this BlockPos 1 block down + */ + public BlockPos down() { + return this.down(1); + } + + /** + * Offset this BlockPos n blocks down + */ + public BlockPos down(int n) { + return this.offset(EnumFacing.DOWN, n); + } + + /** + * Offset this BlockPos 1 block in northern direction + */ + public BlockPos north() { + return this.north(1); + } + + /** + * Offset this BlockPos n blocks in northern direction + */ + public BlockPos north(int n) { + return this.offset(EnumFacing.NORTH, n); + } + + /** + * Offset this BlockPos 1 block in southern direction + */ + public BlockPos south() { + return this.south(1); + } + + /** + * Offset this BlockPos n blocks in southern direction + */ + public BlockPos south(int n) { + return this.offset(EnumFacing.SOUTH, n); + } + + /** + * Offset this BlockPos 1 block in western direction + */ + public BlockPos west() { + return this.west(1); + } + + /** + * Offset this BlockPos n blocks in western direction + */ + public BlockPos west(int n) { + return this.offset(EnumFacing.WEST, n); + } + + /** + * Offset this BlockPos 1 block in eastern direction + */ + public BlockPos east() { + return this.east(1); + } + + /** + * Offset this BlockPos n blocks in eastern direction + */ + public BlockPos east(int n) { + return this.offset(EnumFacing.EAST, n); + } + + /** + * Offset this BlockPos 1 block in the given direction + */ + public BlockPos offset(EnumFacing facing) { + return this.offset(facing, 1); + } + + /** + * Offsets this BlockPos n blocks in the given direction + */ + public BlockPos offset(EnumFacing facing, int n) { + return n == 0 ? this : new BlockPos(this.getX() + facing.getFrontOffsetX() * n, this.getY() + facing.getFrontOffsetY() * n, this.getZ() + facing.getFrontOffsetZ() * n); + } + + public BlockPos rotate(Rotation rotationIn) { + switch (rotationIn) { + case NONE: + default: + return this; + case CLOCKWISE_90: + return new BlockPos(-this.getZ(), this.getY(), this.getX()); + case CLOCKWISE_180: + return new BlockPos(-this.getX(), this.getY(), -this.getZ()); + case COUNTERCLOCKWISE_90: + return new BlockPos(this.getZ(), this.getY(), -this.getX()); + } + } + + /** + * Calculate the cross product of this and the given Vector + */ + public BlockPos crossProduct(Vec3i vec) { + return new BlockPos(this.getY() * vec.getZ() - this.getZ() * vec.getY(), this.getZ() * vec.getX() - this.getX() * vec.getZ(), this.getX() * vec.getY() - this.getY() * vec.getX()); + } + + /** + * Serialize this BlockPos into a long value + */ + public long toLong() { + return ((long) this.getX() & X_MASK) << X_SHIFT | ((long) this.getY() & Y_MASK) << Y_SHIFT | ((long) this.getZ() & Z_MASK); + } + + /** + * Returns a version of this BlockPos that is guaranteed to be immutable. + * + *

When storing a BlockPos given to you for an extended period of time, make sure you + * use this in case the value is changed internally.

+ */ + public BlockPos toImmutable() { + return this; + } + + public static class MutableBlockPos extends BlockPos { + /** + * Mutable X Coordinate + */ + protected int x; + /** + * Mutable Y Coordinate + */ + protected int y; + /** + * Mutable Z Coordinate + */ + protected int z; + + public MutableBlockPos() { + this(0, 0, 0); + } + + public MutableBlockPos(BlockPos pos) { + this(pos.getX(), pos.getY(), pos.getZ()); + } + + public MutableBlockPos(int x_, int y_, int z_) { + super(0, 0, 0); + this.x = x_; + this.y = y_; + this.z = z_; + } + + /** + * Add the given coordinates to the coordinates of this BlockPos + */ + public BlockPos add(double x, double y, double z) { + return super.add(x, y, z).toImmutable(); + } + + /** + * Add the given coordinates to the coordinates of this BlockPos + */ + public BlockPos add(int x, int y, int z) { + return super.add(x, y, z).toImmutable(); + } + + /** + * Offsets this BlockPos n blocks in the given direction + */ + public BlockPos offset(EnumFacing facing, int n) { + return super.offset(facing, n).toImmutable(); + } + + public BlockPos rotate(Rotation rotationIn) { + return super.rotate(rotationIn).toImmutable(); + } + + /** + * Gets the X coordinate. + */ + public int getX() { + return this.x; + } + + /** + * Gets the Y coordinate. + */ + public int getY() { + return this.y; + } + + public void setY(int yIn) { + this.y = yIn; + } + + /** + * Gets the Z coordinate. + */ + public int getZ() { + return this.z; + } + + /** + * None + */ + public BlockPos.MutableBlockPos setPos(int xIn, int yIn, int zIn) { + this.x = xIn; + this.y = yIn; + this.z = zIn; + return this; + } + + public BlockPos.MutableBlockPos setPos(double xIn, double yIn, double zIn) { + return this.setPos(MathHelper.floor_double(xIn), MathHelper.floor_double(yIn), MathHelper.floor_double(zIn)); + } + + @SideOnly(Side.CLIENT) + public BlockPos.MutableBlockPos setPos(Entity entityIn) { + return this.setPos(entityIn.posX, entityIn.posY, entityIn.posZ); + } + + public BlockPos.MutableBlockPos setPos(Vec3i vec) { + return this.setPos(vec.getX(), vec.getY(), vec.getZ()); + } + + public BlockPos.MutableBlockPos move(EnumFacing facing) { + return this.move(facing, 1); + } + + public BlockPos.MutableBlockPos move(EnumFacing facing, int n) { + return this.setPos(this.x + facing.getFrontOffsetX() * n, this.y + facing.getFrontOffsetY() * n, this.z + facing.getFrontOffsetZ() * n); + } + + /** + * Returns a version of this BlockPos that is guaranteed to be immutable. + * + *

When storing a BlockPos given to you for an extended period of time, make sure you + * use this in case the value is changed internally.

+ */ + public BlockPos toImmutable() { + return new BlockPos(this); + } + } + + public static final class PooledMutableBlockPos extends BlockPos.MutableBlockPos { + private static final List POOL = Lists.newArrayList(); + private boolean released; + + private PooledMutableBlockPos(int xIn, int yIn, int zIn) { + super(xIn, yIn, zIn); + } + + public static BlockPos.PooledMutableBlockPos retain() { + return retain(0, 0, 0); + } + + public static BlockPos.PooledMutableBlockPos retain(double xIn, double yIn, double zIn) { + return retain(MathHelper.floor_double(xIn), MathHelper.floor_double(yIn), MathHelper.floor_double(zIn)); + } + + @SideOnly(Side.CLIENT) + public static BlockPos.PooledMutableBlockPos retain(Vec3i vec) { + return retain(vec.getX(), vec.getY(), vec.getZ()); + } + + public static BlockPos.PooledMutableBlockPos retain(int xIn, int yIn, int zIn) { + synchronized (POOL) { + if (!POOL.isEmpty()) { + BlockPos.PooledMutableBlockPos pos = POOL.remove(POOL.size() - 1); + + if (pos != null && pos.released) { + pos.released = false; + pos.setPos(xIn, yIn, zIn); + return pos; + } + } + } + + return new BlockPos.PooledMutableBlockPos(xIn, yIn, zIn); + } + + public void release() { + synchronized (POOL) { + if (POOL.size() < 100) { + POOL.add(this); + } + + this.released = true; + } + } + + /** + * None + */ + public BlockPos.PooledMutableBlockPos setPos(int xIn, int yIn, int zIn) { + if (this.released) { + BlockPos.LOGGER.error("PooledMutableBlockPosition modified after it was released.", new Throwable()); + this.released = false; + } + + return (BlockPos.PooledMutableBlockPos) super.setPos(xIn, yIn, zIn); + } + + @SideOnly(Side.CLIENT) + public BlockPos.PooledMutableBlockPos setPos(Entity entityIn) { + return (BlockPos.PooledMutableBlockPos) super.setPos(entityIn); + } + + public BlockPos.PooledMutableBlockPos setPos(double xIn, double yIn, double zIn) { + return (BlockPos.PooledMutableBlockPos) super.setPos(xIn, yIn, zIn); + } + + public BlockPos.PooledMutableBlockPos setPos(Vec3i vec) { + return (BlockPos.PooledMutableBlockPos) super.setPos(vec); + } + + public BlockPos.PooledMutableBlockPos move(EnumFacing facing) { + return (BlockPos.PooledMutableBlockPos) super.move(facing); + } + + public BlockPos.PooledMutableBlockPos move(EnumFacing facing, int n) { + return (BlockPos.PooledMutableBlockPos) super.move(facing, n); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/falsepattern/lib/compat/ChunkPos.java b/src/main/java/com/falsepattern/lib/compat/ChunkPos.java new file mode 100644 index 0000000..fd5b5b8 --- /dev/null +++ b/src/main/java/com/falsepattern/lib/compat/ChunkPos.java @@ -0,0 +1,95 @@ +package com.falsepattern.lib.compat; + +import net.minecraft.entity.Entity; + +public class ChunkPos { + /** + * The X position of this Chunk Coordinate Pair + */ + public final int x; + /** + * The Z position of this Chunk Coordinate Pair + */ + public final int z; + + public ChunkPos(int x, int z) { + this.x = x; + this.z = z; + } + + public ChunkPos(BlockPos pos) { + this.x = pos.getX() >> 4; + this.z = pos.getZ() >> 4; + } + + /** + * Converts the chunk coordinate pair to a long + */ + public static long asLong(int x, int z) { + return (long) x & 4294967295L | ((long) z & 4294967295L) << 32; + } + + public int hashCode() { + int i = 1664525 * this.x + 1013904223; + int j = 1664525 * (this.z ^ -559038737) + 1013904223; + return i ^ j; + } + + public boolean equals(Object p_equals_1_) { + if (this == p_equals_1_) { + return true; + } else if (!(p_equals_1_ instanceof ChunkPos)) { + return false; + } else { + ChunkPos chunkpos = (ChunkPos) p_equals_1_; + return this.x == chunkpos.x && this.z == chunkpos.z; + } + } + + public double getDistanceSq(Entity entityIn) { + double d0 = this.x * 16 + 8; + double d1 = this.z * 16 + 8; + double d2 = d0 - entityIn.posX; + double d3 = d1 - entityIn.posZ; + return d2 * d2 + d3 * d3; + } + + /** + * Get the first world X coordinate that belongs to this Chunk + */ + public int getXStart() { + return this.x << 4; + } + + /** + * Get the first world Z coordinate that belongs to this Chunk + */ + public int getZStart() { + return this.z << 4; + } + + /** + * Get the last world X coordinate that belongs to this Chunk + */ + public int getXEnd() { + return (this.x << 4) + 15; + } + + /** + * Get the last world Z coordinate that belongs to this Chunk + */ + public int getZEnd() { + return (this.z << 4) + 15; + } + + /** + * Get the World coordinates of the Block with the given Chunk coordinates relative to this chunk + */ + public BlockPos getBlock(int x, int y, int z) { + return new BlockPos((this.x << 4) + x, y, (this.z << 4) + z); + } + + public String toString() { + return "[" + this.x + ", " + this.z + "]"; + } +} \ No newline at end of file diff --git a/src/main/java/com/falsepattern/lib/compat/Rotation.java b/src/main/java/com/falsepattern/lib/compat/Rotation.java new file mode 100644 index 0000000..c2e9bbc --- /dev/null +++ b/src/main/java/com/falsepattern/lib/compat/Rotation.java @@ -0,0 +1,128 @@ +package com.falsepattern.lib.compat; + +import net.minecraft.util.EnumFacing; + +public enum Rotation { + NONE("rotate_0"), + CLOCKWISE_90("rotate_90"), + CLOCKWISE_180("rotate_180"), + COUNTERCLOCKWISE_90("rotate_270"); + + private static final String[] rotationNames = new String[values().length]; + + static { + int i = 0; + + for (Rotation rotation : values()) { + rotationNames[i++] = rotation.name; + } + } + + private final String name; + + Rotation(String nameIn) { + this.name = nameIn; + } + + public Rotation add(Rotation rotation) { + switch (rotation) { + case CLOCKWISE_180: + switch (this) { + case NONE: + return CLOCKWISE_180; + case CLOCKWISE_90: + return COUNTERCLOCKWISE_90; + case CLOCKWISE_180: + return NONE; + case COUNTERCLOCKWISE_90: + return CLOCKWISE_90; + } + case COUNTERCLOCKWISE_90: + switch (this) { + case NONE: + return COUNTERCLOCKWISE_90; + case CLOCKWISE_90: + return NONE; + case CLOCKWISE_180: + return CLOCKWISE_90; + case COUNTERCLOCKWISE_90: + return CLOCKWISE_180; + } + case CLOCKWISE_90: + switch (this) { + case NONE: + return CLOCKWISE_90; + case CLOCKWISE_90: + return CLOCKWISE_180; + case CLOCKWISE_180: + return COUNTERCLOCKWISE_90; + case COUNTERCLOCKWISE_90: + return NONE; + } + default: + return this; + } + } + + public EnumFacing rotate(EnumFacing facing) { + if (facing == EnumFacing.UP || facing == EnumFacing.DOWN) { + return facing; + } + switch (this) { + case CLOCKWISE_90: + switch (facing) { + case NORTH: + return EnumFacing.EAST; + case EAST: + return EnumFacing.SOUTH; + case SOUTH: + return EnumFacing.WEST; + case WEST: + return EnumFacing.NORTH; + default: + throw new IllegalStateException("Unable to get Y-rotated facing of " + facing); + } + case CLOCKWISE_180: + switch (facing) { + case NORTH: + return EnumFacing.SOUTH; + case EAST: + return EnumFacing.WEST; + case SOUTH: + return EnumFacing.NORTH; + case WEST: + return EnumFacing.EAST; + default: + throw new IllegalStateException("Unable to get Y-rotated facing of " + facing); + } + case COUNTERCLOCKWISE_90: + switch (facing) { + case NORTH: + return EnumFacing.WEST; + case EAST: + return EnumFacing.NORTH; + case SOUTH: + return EnumFacing.EAST; + case WEST: + return EnumFacing.SOUTH; + default: + throw new IllegalStateException("Unable to get Y-rotated facing of " + facing); + } + default: + return facing; + } + } + + public int rotate(int x, int z) { + switch (this) { + case CLOCKWISE_90: + return (x + z / 4) % z; + case CLOCKWISE_180: + return (x + z / 2) % z; + case COUNTERCLOCKWISE_90: + return (x + z * 3 / 4) % z; + default: + return x; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/falsepattern/lib/compat/Vec3i.java b/src/main/java/com/falsepattern/lib/compat/Vec3i.java new file mode 100644 index 0000000..1bcc224 --- /dev/null +++ b/src/main/java/com/falsepattern/lib/compat/Vec3i.java @@ -0,0 +1,119 @@ +package com.falsepattern.lib.compat; + +import net.minecraft.util.MathHelper; + +import javax.annotation.concurrent.Immutable; +import java.util.Objects; + +@Immutable +public class Vec3i implements Comparable { + /** + * An immutable vector with zero as all coordinates. + */ + public static final Vec3i NULL_VECTOR = new Vec3i(0, 0, 0); + /** + * X coordinate + */ + private final int x; + /** + * Y coordinate + */ + private final int y; + /** + * Z coordinate + */ + private final int z; + + public Vec3i(int xIn, int yIn, int zIn) { + this.x = xIn; + this.y = yIn; + this.z = zIn; + } + + public Vec3i(double xIn, double yIn, double zIn) { + this(MathHelper.floor_double(xIn), MathHelper.floor_double(yIn), MathHelper.floor_double(zIn)); + } + + public int compareTo(Vec3i p_compareTo_1_) { + if (this.getY() == p_compareTo_1_.getY()) { + return this.getZ() == p_compareTo_1_.getZ() ? this.getX() - p_compareTo_1_.getX() : this.getZ() - p_compareTo_1_.getZ(); + } else { + return this.getY() - p_compareTo_1_.getY(); + } + } + + /** + * Gets the X coordinate. + */ + public int getX() { + return this.x; + } + + /** + * Gets the Y coordinate. + */ + public int getY() { + return this.y; + } + + /** + * Gets the Z coordinate. + */ + public int getZ() { + return this.z; + } + + /** + * Calculate the cross product of this and the given Vector + */ + public Vec3i crossProduct(Vec3i vec) { + return new Vec3i(this.getY() * vec.getZ() - this.getZ() * vec.getY(), this.getZ() * vec.getX() - this.getX() * vec.getZ(), this.getX() * vec.getY() - this.getY() * vec.getX()); + } + + public double getDistance(int xIn, int yIn, int zIn) { + double d0 = (this.getX() - xIn); + double d1 = (this.getY() - yIn); + double d2 = (this.getZ() - zIn); + return Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2); + } + + /** + * Calculate squared distance to the given coordinates + */ + public double distanceSq(double toX, double toY, double toZ) { + double d0 = (double) this.getX() - toX; + double d1 = (double) this.getY() - toY; + double d2 = (double) this.getZ() - toZ; + return d0 * d0 + d1 * d1 + d2 * d2; + } + + /** + * Compute square of distance from point x, y, z to center of this Block + */ + public double distanceSqToCenter(double xIn, double yIn, double zIn) { + double d0 = (double) this.getX() + 0.5D - xIn; + double d1 = (double) this.getY() + 0.5D - yIn; + double d2 = (double) this.getZ() + 0.5D - zIn; + return d0 * d0 + d1 * d1 + d2 * d2; + } + + /** + * Calculate squared distance to the given Vector + */ + public double distanceSq(Vec3i to) { + return this.distanceSq(to.getX(), to.getY(), to.getZ()); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Vec3i vec3i = (Vec3i) o; + return getX() == vec3i.getX() && getY() == vec3i.getY() && getZ() == vec3i.getZ(); + } + + @Override + public int hashCode() { + return Objects.hash(getX(), getY(), getZ()); + } +} \ No newline at end of file