diff --git a/ClassicalSharp/Blocks/BlockInfo.cs b/ClassicalSharp/Blocks/BlockInfo.cs
index 71f56261b..f5a20ed98 100644
--- a/ClassicalSharp/Blocks/BlockInfo.cs
+++ b/ClassicalSharp/Blocks/BlockInfo.cs
@@ -326,7 +326,7 @@ namespace ClassicalSharp {
static void CalcCulling(BlockID block, BlockID other) {
if (!IsHidden(block, other)) {
// Block is not hidden at all, so we can just entirely skip per-face check
- BlockInfo.hidden[(block * Count) | other] = 0;
+ BlockInfo.hidden[(block * Count) + other] = 0;
} else {
Vector3 bMin = MinBB[block], bMax = MaxBB[block];
Vector3 oMin = MinBB[other], oMax = MaxBB[other];
@@ -348,7 +348,7 @@ namespace ClassicalSharp {
f |= occludedZ && oMin.Z == 0 && bMax.Z == 1 ? (1 << Side.Back) : 0;
f |= occludedY && (bothLiquid || (oMax.Y == 1 && bMin.Y == 0)) ? (1 << Side.Bottom) : 0;
f |= occludedY && (bothLiquid || (oMin.Y == 0 && bMax.Y == 1)) ? (1 << Side.Top) : 0;
- BlockInfo.hidden[(block * Count) | other] = (byte)f;
+ BlockInfo.hidden[(block * Count) + other] = (byte)f;
}
}
@@ -376,7 +376,7 @@ namespace ClassicalSharp {
/// Returns whether the face at the given face of the block
/// should be drawn with the neighbour 'other' present on the other side of the face.
public static bool IsFaceHidden(BlockID block, BlockID other, int tileSide) {
- return (hidden[(block * Count) | other] & (1 << tileSide)) != 0;
+ return (hidden[(block * Count) + other] & (1 << tileSide)) != 0;
}
}
}
diff --git a/ClassicalSharp/ClassicalSharp.csproj b/ClassicalSharp/ClassicalSharp.csproj
index 4dbfd5797..13be250a1 100644
--- a/ClassicalSharp/ClassicalSharp.csproj
+++ b/ClassicalSharp/ClassicalSharp.csproj
@@ -63,7 +63,7 @@
None
True
False
- TRACE;USE_DX;
+ TRACE;USE_DX;USE16_BIT
obj\
Project
diff --git a/ClassicalSharp/MeshBuilder/Builder.cs b/ClassicalSharp/MeshBuilder/Builder.cs
index fbb07b98d..5923878dd 100644
--- a/ClassicalSharp/MeshBuilder/Builder.cs
+++ b/ClassicalSharp/MeshBuilder/Builder.cs
@@ -32,7 +32,7 @@ namespace ClassicalSharp {
protected internal int width, length, height, sidesLevel, edgeLevel;
protected int maxX, maxY, maxZ, chunkEndX, chunkEndZ;
protected int cIndex;
- protected BlockRaw* chunk;
+ protected BlockID* chunk;
protected byte* counts;
protected int* bitFlags;
protected bool useBitFlags;
@@ -40,14 +40,31 @@ namespace ClassicalSharp {
bool BuildChunk(int x1, int y1, int z1, ref bool allAir) {
light = game.Lighting;
PreStretchTiles(x1, y1, z1);
- BlockRaw* chunkPtr = stackalloc BlockRaw[extChunkSize3]; chunk = chunkPtr;
+ BlockID* chunkPtr = stackalloc BlockID[extChunkSize3]; chunk = chunkPtr;
byte* countsPtr = stackalloc byte[chunkSize3 * Side.Sides]; counts = countsPtr;
int* bitsPtr = stackalloc int[extChunkSize3]; bitFlags = bitsPtr;
+ MemUtils.memset((IntPtr)chunkPtr, 0, 0, extChunkSize3 * sizeof(BlockID));
+
+ bool allSolid = false;
+ fixed (BlockRaw* mapPtr = map.blocks1) {
+ #if USE_16_BIT
+ if (BlockInfo.MaxDefined >= 256) {
+ ReadChunkData_16Bit(x1, y1, z1, mapPtr, ref allAir, ref allSolid);
+ } else {
+ ReadChunkData_8Bit(x1, y1, z1, mapPtr, ref allAir, ref allSolid);
+ }
+ #else
+ ReadChunkData_8Bit(x1, y1, z1, mapPtr, ref allAir, ref allSolid);
+ #endif
+
+ if (x1 == 0 || y1 == 0 || z1 == 0 || x1 + chunkSize >= width ||
+ y1 + chunkSize >= height || z1 + chunkSize >= length) allSolid = false;
+
+ if (allAir || allSolid) return false;
+ light.LightHint(x1 - 1, z1 - 1, mapPtr);
+ }
- MemUtils.memset((IntPtr)chunkPtr, 0, 0, extChunkSize3 * sizeof(BlockRaw));
- if (ReadChunkData(x1, y1, z1, ref allAir)) return false;
MemUtils.memset((IntPtr)countsPtr, 1, 0, chunkSize3 * Side.Sides);
-
int xMax = Math.Min(width, x1 + chunkSize);
int yMax = Math.Min(height, y1 + chunkSize);
int zMax = Math.Min(length, z1 + chunkSize);
@@ -75,10 +92,41 @@ namespace ClassicalSharp {
return true;
}
- bool ReadChunkData(int x1, int y1, int z1, ref bool outAllAir) { // only assign this variable once
+ void ReadChunkData_8Bit(int x1, int y1, int z1, BlockRaw* mapPtr, ref bool outAllAir, ref bool outAllSolid) { // only assign this variable once
bool allAir = true, allSolid = true;
- fixed (BlockRaw* mapPtr = map.blocks1) {
-
+ for (int yy = -1; yy < 17; yy++) {
+ int y = yy + y1;
+ if (y < 0) continue;
+ if (y >= height) break;
+ for (int zz = -1; zz < 17; zz++) {
+ int z = zz + z1;
+ if (z < 0) continue;
+ if (z >= length) break;
+
+ int index = (y * length + z) * width + (x1 - 1 - 1);
+ int chunkIndex = (yy + 1) * extChunkSize2 + (zz + 1) * extChunkSize + (-1 + 1) - 1;
+
+ for (int xx = -1; xx < 17; xx++) {
+ int x = xx + x1;
+ index++;
+ chunkIndex++;
+ if (x < 0) continue;
+ if (x >= width) break;
+ BlockID rawBlock = mapPtr[index];
+
+ allAir = allAir && BlockInfo.Draw[rawBlock] == DrawType.Gas;
+ allSolid = allSolid && BlockInfo.FullOpaque[rawBlock];
+ chunk[chunkIndex] = rawBlock;
+ }
+ }
+ outAllAir = allAir; outAllSolid = allSolid;
+ }
+ }
+
+ #if USE_16_BIT
+ void ReadChunkData_16Bit(int x1, int y1, int z1, BlockRaw* mapPtr, ref bool outAllAir, ref bool outAllSolid) { // only assign this variable once
+ bool allAir = true, allSolid = true;
+ fixed (BlockRaw* mapPtr2 = map.blocks2) {
for (int yy = -1; yy < 17; yy++) {
int y = yy + y1;
if (y < 0) continue;
@@ -97,24 +145,18 @@ namespace ClassicalSharp {
chunkIndex++;
if (x < 0) continue;
if (x >= width) break;
- BlockRaw rawBlock = mapPtr[index];
+ BlockID rawBlock = (BlockID)(mapPtr[index] | (mapPtr2[index] << 8));
allAir = allAir && BlockInfo.Draw[rawBlock] == DrawType.Gas;
allSolid = allSolid && BlockInfo.FullOpaque[rawBlock];
chunk[chunkIndex] = rawBlock;
}
}
+ outAllAir = allAir; outAllSolid = allSolid;
}
- outAllAir = allAir;
-
- if (x1 == 0 || y1 == 0 || z1 == 0 || x1 + chunkSize >= width ||
- y1 + chunkSize >= height || z1 + chunkSize >= length) allSolid = false;
-
- if (allAir || allSolid) return true;
- light.LightHint(x1 - 1, z1 - 1, mapPtr);
- return false;
}
}
+ #endif
public void MakeChunk(ChunkInfo info) {
int x = info.CentreX - 8, y = info.CentreY - 8, z = info.CentreZ - 8;
diff --git a/src/Client/EntityComponents.c b/src/Client/EntityComponents.c
index b9bdbf00d..fed8c9f88 100644
--- a/src/Client/EntityComponents.c
+++ b/src/Client/EntityComponents.c
@@ -227,12 +227,12 @@ void HacksComp_SetUserType(HacksComp* hacks, UInt8 value, bool setBlockPerms) {
hacks->CanSeeAllNames = isOp;
if (!setBlockPerms) return;
- Block_CanPlace[BLOCK_BEDROCK] = isOp;
- Block_CanDelete[BLOCK_BEDROCK] = isOp;
- Block_CanPlace[BLOCK_WATER] = isOp;
+ Block_CanPlace[BLOCK_BEDROCK] = isOp;
+ Block_CanDelete[BLOCK_BEDROCK] = isOp;
+ Block_CanPlace[BLOCK_WATER] = isOp;
Block_CanPlace[BLOCK_STILL_WATER] = isOp;
- Block_CanPlace[BLOCK_LAVA] = isOp;
- Block_CanPlace[BLOCK_STILL_LAVA] = isOp;
+ Block_CanPlace[BLOCK_LAVA] = isOp;
+ Block_CanPlace[BLOCK_STILL_LAVA] = isOp;
}
void HacksComp_CheckConsistency(HacksComp* hacks) {
diff --git a/src/Client/EntityComponents.h b/src/Client/EntityComponents.h
index 8faffba60..34ff1e5b0 100644
--- a/src/Client/EntityComponents.h
+++ b/src/Client/EntityComponents.h
@@ -68,7 +68,7 @@ typedef struct HacksComponent_ {
void HacksComp_Init(HacksComp* hacks);
bool HacksComp_CanJumpHigher(HacksComp* hacks);
bool HacksComp_Floating(HacksComp* hacks);
-void HacksComp_SetUserType(HacksComp* hacks, UInt8 value);
+void HacksComp_SetUserType(HacksComp* hacks, UInt8 value, bool setBlockPerms);
void HacksComp_CheckConsistency(HacksComp* hacks);
void HacksComp_UpdateState(HacksComp* hacks);