diff --git a/src/ClassiCube.vcxproj b/src/ClassiCube.vcxproj
index 8e308cd77..90dfcbcc4 100644
--- a/src/ClassiCube.vcxproj
+++ b/src/ClassiCube.vcxproj
@@ -416,6 +416,7 @@
+
@@ -530,6 +531,7 @@
+
diff --git a/src/ClassiCube.vcxproj.filters b/src/ClassiCube.vcxproj.filters
index c9bfcac9c..05077b2c5 100644
--- a/src/ClassiCube.vcxproj.filters
+++ b/src/ClassiCube.vcxproj.filters
@@ -351,6 +351,9 @@
Source Files\Window
+
+ Header Files\Utils
+
@@ -755,6 +758,9 @@
Source Files\Map
+
+ Source Files\Utils
+
diff --git a/src/ModernLighting.c b/src/ModernLighting.c
index 77daf7ec0..b3628078d 100644
--- a/src/ModernLighting.c
+++ b/src/ModernLighting.c
@@ -11,79 +11,15 @@
#include "Chat.h"
#include "ExtMath.h"
#include "Options.h"
-
-/*########################################################################################################################*
-*----------------------------------------------------Queue thing ---------------------------------------------------------*
-*#########################################################################################################################*/
-
-struct LightQueue {
- IVec3* entries; /* Buffer holding the items in the Block queue */
- int capacity; /* Max number of elements in the buffer */
- int mask; /* capacity - 1, as capacity is always a power of two */
- int count; /* Number of used elements */
- int head; /* Head index into the buffer */
- int tail; /* Tail index into the buffer */
-};
-IVec3 LightQueue_EntryAtIndex(struct LightQueue* queue, int index) {
- return queue->entries[(queue->head + index) & queue->mask];
-}
-void LightQueue_Init(struct LightQueue* queue) {
- queue->entries = NULL;
- queue->capacity = 0;
- queue->mask = 0;
- queue->count = 0;
- queue->head = 0;
- queue->tail = 0;
-}
-static void LightQueue_Clear(struct LightQueue* queue) {
- if (!queue->entries) return;
- Mem_Free(queue->entries);
- LightQueue_Init(queue);
-}
-static void LightQueue_Resize(struct LightQueue* queue) {
- IVec3* entries;
- int i, idx, capacity;
- if (queue->capacity >= (Int32_MaxValue / 4)) {
- Chat_AddRaw("&cToo many block queue entries, clearing");
- LightQueue_Clear(queue);
- return;
- }
- capacity = queue->capacity * 2;
- if (capacity < 32) capacity = 32;
- entries = (IVec3*)Mem_Alloc(capacity, sizeof(IVec3), "Light queue");
- for (i = 0; i < queue->count; i++) {
- idx = (queue->head + i) & queue->mask;
- entries[i] = queue->entries[idx];
- }
- Mem_Free(queue->entries);
- queue->entries = entries;
- queue->capacity = capacity;
- queue->mask = capacity - 1; /* capacity is power of two */
- queue->head = 0;
- queue->tail = queue->count;
-}
-/* Appends an entry to the end of the queue, resizing if necessary. */
-void LightQueue_Enqueue(struct LightQueue* queue, IVec3 item) {
- if (queue->count == queue->capacity)
- LightQueue_Resize(queue);
- queue->entries[queue->tail] = item;
- queue->tail = (queue->tail + 1) & queue->mask;
- queue->count++;
-}
-/* Retrieves the entry from the front of the queue. */
-IVec3 LightQueue_Dequeue(struct LightQueue* queue) {
- IVec3 result = queue->entries[queue->head];
- queue->head = (queue->head + 1) & queue->mask;
- queue->count--;
- return result;
-}
-static struct LightQueue lightQueue;
+#include "Queue.h"
/*########################################################################################################################*
*----------------------------------------------------Modern lighting------------------------------------------------------*
*#########################################################################################################################*/
+static struct Queue lightQueue;
+
/* A 16x16 palette of sun and block light colors. */
/* It is indexed by a byte where the leftmost 4 bits represent sunlight level and the rightmost 4 bits represent blocklight level */
/* E.G. modernLighting_palette[0b_0010_0001] will give us the color for sun level 2 and block level 1 (lowest level is 0) */
@@ -173,7 +109,7 @@ static void ModernLighting_AllocState(void) {
chunkLightingDataFlags = (cc_uint8*)Mem_TryAllocCleared(chunksCount, sizeof(cc_uint8));
chunkLightingData = (LightingChunk*)Mem_TryAllocCleared(chunksCount, sizeof(LightingChunk));
- LightQueue_Init(&lightQueue);
+ Queue_Init(&lightQueue, sizeof(IVec3));
}
@@ -194,7 +130,7 @@ static void ModernLighting_FreeState(void) {
Mem_Free(chunkLightingData);
chunkLightingDataFlags = NULL;
chunkLightingData = NULL;
- LightQueue_Clear(&lightQueue);
+ Queue_Clear(&lightQueue);
}
/* Converts chunk x/y/z coordinates to the corresponding index in chunks array/list */
@@ -254,12 +190,12 @@ static cc_bool CanLightPass(BlockID thisBlock, Face face) {
static void CalcBlockLight(cc_uint8 blockLight, int x, int y, int z) {
SetBlocklight(blockLight, x, y, z, false);
IVec3 entry = { x, y, z };
- LightQueue_Enqueue(&lightQueue, entry);
+ Queue_Enqueue(&lightQueue, &entry);
//if (Blocks.BlocksLight[World_GetBlock(x, y, z)]) { return; }
while (lightQueue.count > 0) {
- IVec3 curNode = LightQueue_Dequeue(&lightQueue);
+ IVec3 curNode = *(IVec3*)(Queue_Dequeue(&lightQueue));
cc_uint8 curLight = GetBlocklight(curNode.x, curNode.y, curNode.z, false);
if (curLight <= 0) {
Platform_Log1("but there were still %i entries left...", &lightQueue.capacity);
@@ -277,7 +213,7 @@ static void CalcBlockLight(cc_uint8 blockLight, int x, int y, int z) {
CanLightPass(World_GetBlock(curNode.x, curNode.y, curNode.z), FACE_XMIN) &&
GetBlocklight(curNode.x, curNode.y, curNode.z, false) < curLight) {
SetBlocklight(curLight, curNode.x, curNode.y, curNode.z, false);
- LightQueue_Enqueue(&lightQueue, curNode);
+ Queue_Enqueue(&lightQueue, &curNode);
}
curNode.x += 2;
if (curNode.x < World.MaxX &&
@@ -285,7 +221,7 @@ static void CalcBlockLight(cc_uint8 blockLight, int x, int y, int z) {
CanLightPass(World_GetBlock(curNode.x, curNode.y, curNode.z), FACE_XMAX) &&
GetBlocklight(curNode.x, curNode.y, curNode.z, false) < curLight) {
SetBlocklight(curLight, curNode.x, curNode.y, curNode.z, false);
- LightQueue_Enqueue(&lightQueue, curNode);
+ Queue_Enqueue(&lightQueue, &curNode);
}
curNode.x--;
@@ -295,7 +231,7 @@ static void CalcBlockLight(cc_uint8 blockLight, int x, int y, int z) {
CanLightPass(World_GetBlock(curNode.x, curNode.y, curNode.z), FACE_YMIN) &&
GetBlocklight(curNode.x, curNode.y, curNode.z, false) < curLight) {
SetBlocklight(curLight, curNode.x, curNode.y, curNode.z, false);
- LightQueue_Enqueue(&lightQueue, curNode);
+ Queue_Enqueue(&lightQueue, &curNode);
}
curNode.y += 2;
if (curNode.y < World.MaxY &&
@@ -303,7 +239,7 @@ static void CalcBlockLight(cc_uint8 blockLight, int x, int y, int z) {
CanLightPass(World_GetBlock(curNode.x, curNode.y, curNode.z), FACE_YMAX) &&
GetBlocklight(curNode.x, curNode.y, curNode.z, false) < curLight) {
SetBlocklight(curLight, curNode.x, curNode.y, curNode.z, false);
- LightQueue_Enqueue(&lightQueue, curNode);
+ Queue_Enqueue(&lightQueue, &curNode);
}
curNode.y--;
@@ -313,7 +249,7 @@ static void CalcBlockLight(cc_uint8 blockLight, int x, int y, int z) {
CanLightPass(World_GetBlock(curNode.x, curNode.y, curNode.z), FACE_ZMIN) &&
GetBlocklight(curNode.x, curNode.y, curNode.z, false) < curLight) {
SetBlocklight(curLight, curNode.x, curNode.y, curNode.z, false);
- LightQueue_Enqueue(&lightQueue, curNode);
+ Queue_Enqueue(&lightQueue, &curNode);
}
curNode.z += 2;
if (curNode.z < World.MaxZ &&
@@ -321,7 +257,7 @@ static void CalcBlockLight(cc_uint8 blockLight, int x, int y, int z) {
CanLightPass(World_GetBlock(curNode.x, curNode.y, curNode.z), FACE_ZMAX) &&
GetBlocklight(curNode.x, curNode.y, curNode.z, false) < curLight) {
SetBlocklight(curLight, curNode.x, curNode.y, curNode.z, false);
- LightQueue_Enqueue(&lightQueue, curNode);
+ Queue_Enqueue(&lightQueue, &curNode);
}
}
}
@@ -329,12 +265,12 @@ static void CalcBlockLight(cc_uint8 blockLight, int x, int y, int z) {
static void CalcSkyLight(cc_uint8 blockLight, int x, int y, int z) {
SetBlocklight(blockLight, x, y, z, true);
IVec3 entry = { x, y, z };
- LightQueue_Enqueue(&lightQueue, entry);
+ Queue_Enqueue(&lightQueue, &entry);
//if (Blocks.BlocksLight[World_GetBlock(x, y, z)]) { return; }
while (lightQueue.count > 0) {
- IVec3 curNode = LightQueue_Dequeue(&lightQueue);
+ IVec3 curNode = *(IVec3*)(Queue_Dequeue(&lightQueue));
cc_uint8 curLight = GetBlocklight(curNode.x, curNode.y, curNode.z, true);
if (curLight <= 0) {
Platform_Log1("but there were still %i entries left...", &lightQueue.capacity);
@@ -354,7 +290,7 @@ static void CalcSkyLight(cc_uint8 blockLight, int x, int y, int z) {
GetBlocklight(curNode.x, curNode.y, curNode.z, true) < curLight) {
SetBlocklight(curLight, curNode.x, curNode.y, curNode.z, true);
IVec3 entry = { curNode.x, curNode.y, curNode.z };
- LightQueue_Enqueue(&lightQueue, entry);
+ Queue_Enqueue(&lightQueue, &entry);
}
curNode.x += 2;
if (curNode.x < World.MaxX &&
@@ -363,7 +299,7 @@ static void CalcSkyLight(cc_uint8 blockLight, int x, int y, int z) {
CanLightPass(World_GetBlock(curNode.x, curNode.y, curNode.z), FACE_XMAX) &&
GetBlocklight(curNode.x, curNode.y, curNode.z, true) < curLight) {
SetBlocklight(curLight, curNode.x, curNode.y, curNode.z, true);
- LightQueue_Enqueue(&lightQueue, curNode);
+ Queue_Enqueue(&lightQueue, &curNode);
}
curNode.x--;
@@ -374,7 +310,7 @@ static void CalcSkyLight(cc_uint8 blockLight, int x, int y, int z) {
CanLightPass(World_GetBlock(curNode.x, curNode.y, curNode.z), FACE_YMIN) &&
GetBlocklight(curNode.x, curNode.y, curNode.z, true) < curLight) {
SetBlocklight(curLight, curNode.x, curNode.y, curNode.z, true);
- LightQueue_Enqueue(&lightQueue, curNode);
+ Queue_Enqueue(&lightQueue, &curNode);
}
curNode.y += 2;
if (curNode.y < World.MaxY &&
@@ -383,7 +319,7 @@ static void CalcSkyLight(cc_uint8 blockLight, int x, int y, int z) {
CanLightPass(World_GetBlock(curNode.x, curNode.y, curNode.z), FACE_YMAX) &&
GetBlocklight(curNode.x, curNode.y, curNode.z, true) < curLight) {
SetBlocklight(curLight, curNode.x, curNode.y, curNode.z, true);
- LightQueue_Enqueue(&lightQueue, curNode);
+ Queue_Enqueue(&lightQueue, &curNode);
}
curNode.y--;
@@ -394,7 +330,7 @@ static void CalcSkyLight(cc_uint8 blockLight, int x, int y, int z) {
CanLightPass(World_GetBlock(curNode.x, curNode.y, curNode.z), FACE_ZMIN) &&
GetBlocklight(curNode.x, curNode.y, curNode.z, true) < curLight) {
SetBlocklight(curLight, curNode.x, curNode.y, curNode.z, true);
- LightQueue_Enqueue(&lightQueue, curNode);
+ Queue_Enqueue(&lightQueue, &curNode);
}
curNode.z += 2;
if (curNode.z < World.MaxZ &&
@@ -403,7 +339,7 @@ static void CalcSkyLight(cc_uint8 blockLight, int x, int y, int z) {
CanLightPass(World_GetBlock(curNode.x, curNode.y, curNode.z), FACE_ZMAX) &&
GetBlocklight(curNode.x, curNode.y, curNode.z, true) < curLight) {
SetBlocklight(curLight, curNode.x, curNode.y, curNode.z, true);
- LightQueue_Enqueue(&lightQueue, curNode);
+ Queue_Enqueue(&lightQueue, &curNode);
}
}
}
diff --git a/src/Queue.c b/src/Queue.c
new file mode 100644
index 000000000..d12efba95
--- /dev/null
+++ b/src/Queue.c
@@ -0,0 +1,67 @@
+#include "Core.h"
+#include "Constants.h"
+#include "Chat.h"
+#include "Platform.h"
+#include "Queue.h"
+
+void Queue_Init(struct Queue* queue, cc_uint32 structSize) {
+ queue->entries = NULL;
+ queue->structSize = structSize;
+ queue->capacity = 0;
+ queue->mask = 0;
+ queue->count = 0;
+ queue->head = 0;
+ queue->tail = 0;
+}
+void Queue_Clear(struct Queue* queue) {
+ if (!queue->entries) return;
+ Mem_Free(queue->entries);
+ Queue_Init(queue, queue->structSize);
+}
+static void Queue_Resize(struct Queue* queue) {
+ cc_uint8* entries;
+ int i, idx, capacity, headToEndSize, byteOffsetToHead;
+ if (queue->capacity >= (Int32_MaxValue / 4)) {
+ Chat_AddRaw("&cToo many generic queue entries, clearing");
+ Queue_Clear(queue);
+ return;
+ }
+ capacity = queue->capacity * 2;
+ if (capacity < 32) capacity = 32;
+ entries = (cc_uint8*)Mem_Alloc(capacity, queue->structSize, "Generic queue");
+
+ /* Elements must be readjusted to avoid index wrapping issues */
+ headToEndSize = (queue->capacity - queue->head) * queue->structSize;
+ byteOffsetToHead = queue->head * queue->structSize;
+ /* Copy from head to end */
+ Mem_Copy(entries, queue->entries + byteOffsetToHead, headToEndSize);
+ if (queue->head != 0) {
+ /* If there's any leftover before the head, copy that bit too */
+ Mem_Copy(entries + headToEndSize, queue->entries, byteOffsetToHead);
+ }
+
+ Mem_Free(queue->entries);
+
+ queue->entries = entries;
+ queue->capacity = capacity;
+ queue->mask = capacity - 1; /* capacity is power of two */
+ queue->head = 0;
+ queue->tail = queue->count;
+}
+/* Appends an entry to the end of the queue, resizing if necessary. */
+void Queue_Enqueue(struct Queue* queue, void* item) {
+ if (queue->count == queue->capacity)
+ Queue_Resize(queue);
+
+ //queue->entries[queue->tail] = item;
+ Mem_Copy(queue->entries + queue->tail * queue->structSize, item, queue->structSize);
+ queue->tail = (queue->tail + 1) & queue->mask;
+ queue->count++;
+}
+/* Retrieves the entry from the front of the queue. */
+void* Queue_Dequeue(struct Queue* queue) {
+ void* result = queue->entries + queue->head * queue->structSize;
+ queue->head = (queue->head + 1) & queue->mask;
+ queue->count--;
+ return result;
+}
\ No newline at end of file
diff --git a/src/Queue.h b/src/Queue.h
new file mode 100644
index 000000000..f62c94102
--- /dev/null
+++ b/src/Queue.h
@@ -0,0 +1,22 @@
+#include "Core.h"
+
+#ifndef CC_QUEUE_H
+#define CC_QUEUE_H
+
+struct Queue {
+ cc_uint8* entries; /* Buffer holding the bytes of the queue */
+ int structSize; /* Size in bytes of the type of structure this queue holds */
+ int capacity; /* Max number of elements in the buffer */
+ int mask; /* capacity - 1, as capacity is always a power of two */
+ int count; /* Number of used elements */
+ int head; /* Head index into the buffer */
+ int tail; /* Tail index into the buffer */
+};
+void Queue_Init(struct Queue* queue, cc_uint32 structSize);
+/* Appends an entry to the end of the queue, resizing if necessary. */
+void Queue_Enqueue(struct Queue* queue, void* item);
+/* Retrieves the entry from the front of the queue. */
+void* Queue_Dequeue(struct Queue* queue);
+/* Frees the memory of the queue and resets the members to 0. */
+void Queue_Clear(struct Queue* queue);
+#endif
\ No newline at end of file