diff --git a/Math/BlockPos.cs b/Math/BlockPos.cs index e2008b7fd..809789510 100644 --- a/Math/BlockPos.cs +++ b/Math/BlockPos.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel; using System.IO; using System.Runtime.CompilerServices; using Newtonsoft.Json; @@ -34,6 +35,21 @@ public int InternalY { public int Y; public int dimension; + public const int SlotDontCare = -1; + + /// + /// Performs a very fast hashing function on the positional (X, Y, Z, and dimension) parameters. Guaranteed to avoid collisions + /// only when the change in any given coordinate is less than 16; do not use it for a cryptographic hash. + /// + public ushort FastHash => (ushort)((dimension << 12) + (Y << 8) + (X << 4) + Z); + + [ProtoMember(4), DefaultValue(SlotDontCare)] + public int Slot { + get => (slot & 0xFFFF) == FastHash ? (slot >> 16) : SlotDontCare; + set => slot = (value << 16) | FastHash; + } + private int slot = SlotDontCare; + public const int DimensionBoundary = GlobalConstants.DimensionSizeInChunks * GlobalConstants.ChunkSize; @@ -62,12 +78,14 @@ public BlockPos(int x, int y, int z) this.dimension = y / DimensionBoundary; } - public BlockPos(int x, int y, int z, int dim) + public BlockPos(int x, int y, int z, int dim) : this(x, y, z, dim, SlotDontCare) { } + public BlockPos(int x, int y, int z, int dim, int slot) { this.X = x; this.Y = y; this.Z = z; this.dimension = dim; + this.Slot = slot; } [Obsolete("Not dimension-aware. Use overload with a dimension parameter instead")] @@ -78,12 +96,14 @@ public BlockPos(Vec3i vec) this.Z = vec.Z; } - public BlockPos(Vec3i vec, int dim) + public BlockPos(Vec3i vec, int dim) : this(vec, dim, SlotDontCare) { } + public BlockPos(Vec3i vec, int dim, int slot) { this.X = vec.X; this.Y = vec.Y; this.Z = vec.Z; this.dimension = dim; + this.Slot = slot; } /// @@ -97,14 +117,14 @@ public BlockPos(Vec4i vec) } /// - /// 0 = x, 1 = y, 2 = z + /// 0 = x, 1 = y, 2 = z, 3 = dimension, 4 = slot /// /// /// public int this[int i] { - get { return i == 0 ? X : i == 1 ? Y : i == 2 ? Z : dimension; } - set { if (i == 0) X = value; else if (i == 1) Y = value; else if (i == 2) Z = value; else dimension = value; } + get { return i == 0 ? X : i == 1 ? Y : i == 2 ? Z : i == 3 ? dimension : Slot; } + set { if (i == 0) X = value; else if (i == 1) Y = value; else if (i == 2) Z = value; else if (i == 3) dimension = value; else Slot = value; } } /// @@ -115,6 +135,7 @@ public int this[int i] public BlockPos Up(int dy = 1) { Y += dy; + Slot = SlotDontCare; return this; } @@ -126,6 +147,7 @@ public BlockPos Up(int dy = 1) public BlockPos Down(int dy = 1) { Y -= dy; + Slot = SlotDontCare; return this; } @@ -139,6 +161,7 @@ public BlockPos Set(Vec3d origin) X = (int)origin.X; Y = (int)origin.Y; Z = (int)origin.Z; + Slot = SlotDontCare; return this; } @@ -147,6 +170,7 @@ public BlockPos Set(Vec3i pos) X = pos.X; Y = pos.Y; Z = pos.Z; + Slot = SlotDontCare; return this; } @@ -155,6 +179,7 @@ public BlockPos Set(FastVec3i pos) X = pos.X; Y = pos.Y; Z = pos.Z; + Slot = SlotDontCare; return this; } @@ -169,6 +194,7 @@ public BlockPos SetAndCorrectDimension(Vec3d origin) Y = (int)origin.Y % DimensionBoundary; Z = (int)origin.Z; dimension = (int)origin.Y / DimensionBoundary; + Slot = SlotDontCare; return this; } @@ -185,6 +211,7 @@ public BlockPos SetAndCorrectDimension(int x, int y, int z) Y = y % DimensionBoundary; Z = z; dimension = y / DimensionBoundary; + Slot = SlotDontCare; return this; } @@ -202,6 +229,7 @@ public BlockPos Set(int x, int y, int z) X = x; Y = y; Z = z; + Slot = SlotDontCare; return this; } @@ -210,6 +238,7 @@ public BlockPos Set(float x, float y, float z) X = (int)x; Y = (int)y; Z = (int)z; + Slot = SlotDontCare; return this; } @@ -218,6 +247,7 @@ public BlockPos Set(BlockPos blockPos) X = blockPos.X; Y = blockPos.Y; Z = blockPos.Z; + Slot = SlotDontCare; return this; } @@ -236,6 +266,12 @@ public BlockPos SetDimension(int dim) return this; } + public BlockPos SetSlot(int slot) + { + this.slot = slot; + return this; + } + /// /// Sets this BlockPos to the x,y,z values given, and returns a boolean stating if the existing values were already equal to x,y,z /// @@ -249,9 +285,11 @@ public bool SetAndEquals(int x, int y, int z) X = x; Y = y; Z = z; + Slot = SlotDontCare; return false; } + // this does not preserve slot, as it's only used for particles public void ToBytes(BinaryWriter writer) { writer.Write(X); @@ -273,6 +311,7 @@ public Vec3i ToLocalPosition(ICoreAPI api) public BlockPos West() { X -= 1; + Slot = SlotDontCare; return this; } @@ -284,18 +323,21 @@ public static BlockPos CreateFromBytes(BinaryReader reader) public BlockPos North() { Z -= 1; + Slot = SlotDontCare; return this; } public BlockPos East() { X += 1; + Slot = SlotDontCare; return this; } public BlockPos South() { Z += 1; + Slot = SlotDontCare; return this; } @@ -398,7 +440,7 @@ public BlockPos UpCopy(int length = 1) [MethodImpl(MethodImplOptions.AggressiveInlining)] public virtual BlockPos Copy() { - return new BlockPos(X, Y, Z, dimension); + return new BlockPos(X, Y, Z, dimension, Slot); } @@ -409,7 +451,7 @@ public virtual BlockPos Copy() [MethodImpl(MethodImplOptions.AggressiveInlining)] public virtual BlockPos CopyAndCorrectDimension() { - return new BlockPos(X, Y % DimensionBoundary, Z, dimension + Y / DimensionBoundary); + return new BlockPos(X, Y % DimensionBoundary, Z, dimension + Y / DimensionBoundary, Slot); } @@ -428,6 +470,7 @@ public BlockPos Add(float dx, float dy, float dz) X += (int)dx; Y += (int)dy; Z += (int)dz; + Slot = SlotDontCare; return this; } @@ -445,6 +488,7 @@ public BlockPos Add(int dx, int dy, int dz) X += dx; Y += dy; Z += dz; + Slot = SlotDontCare; return this; } @@ -459,6 +503,7 @@ public BlockPos Add(Vec3i vector) X += vector.X; Y += vector.Y; Z += vector.Z; + Slot = SlotDontCare; return this; } @@ -473,6 +518,7 @@ public BlockPos Add(FastVec3i vector) X += vector.X; Y += vector.Y; Z += vector.Z; + Slot = SlotDontCare; return this; } @@ -488,6 +534,7 @@ public BlockPos Add(BlockPos pos) X += pos.X; Y += pos.Y; Z += pos.Z; + Slot = SlotDontCare; return this; } @@ -505,6 +552,7 @@ public BlockPos Add(BlockFacing facing, int length = 1) X += faceNormals.X * length; Y += faceNormals.Y * length; Z += faceNormals.Z * length; + Slot = SlotDontCare; return this; } @@ -520,6 +568,7 @@ public BlockPos Offset(BlockFacing facing) X += faceNormals.X; Y += faceNormals.Y; Z += faceNormals.Z; + Slot = SlotDontCare; return this; } @@ -606,6 +655,7 @@ public BlockPos Sub(BlockPos pos) X -= pos.X; Y -= pos.Y; Z -= pos.Z; + Slot = SlotDontCare; return this; } @@ -622,6 +672,7 @@ public BlockPos Sub(int x, int y, int z) X -= x; Y -= y; Z -= z; + Slot = SlotDontCare; return this; } @@ -814,22 +865,22 @@ public Vec3f ToVec3f() public override string ToString() { - return X + ", " + Y + ", " + Z + (dimension > 0 ? " : " + dimension : ""); + return X + ", " + Y + ", " + Z + (Slot != SlotDontCare ? " / " + Slot : "") + (dimension > 0 ? " : " + dimension : ""); } public override bool Equals(object obj) { - return (obj is BlockPos pos) && X == pos.X && Y == pos.Y && Z == pos.Z && dimension == pos.dimension; + return (obj is BlockPos pos) && X == pos.X && Y == pos.Y && Z == pos.Z && dimension == pos.dimension && Slot == pos.Slot; } public override int GetHashCode() { - return ((17 * 23 + X) * 23 + Y) * 23 + Z + dimension * 269023; + return ((17 * 23 + X) * 23 + Y) * 23 + Z + dimension * 269023 + Slot * 613849; } public bool Equals(BlockPos other) { - return other != null && X == other.X && Y == other.Y && Z == other.Z && dimension == other.dimension; + return other != null && X == other.X && Y == other.Y && Z == other.Z && dimension == other.dimension && Slot == other.Slot; } public bool Equals(int x, int y, int z)