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)