diff --git a/.gitea/workflows/autobuild.yaml b/.gitea/workflows/autobuild.yaml index 7cb7028..dcd4b53 100644 --- a/.gitea/workflows/autobuild.yaml +++ b/.gitea/workflows/autobuild.yaml @@ -19,7 +19,7 @@ jobs: # echo "deb [signed-by=/usr/share/keyrings/ubuntu-archive-keyring.gpg] http://archive.ubuntu.com/ubuntu noble main" | sudo tee /tmp/only.list # sudo apt-get update -o Dir::Etc::sourcelist=/tmp/only.list -o Dir::Etc::sourceparts="-" -qq sudo apt update - sudo apt install -y build-essential cmake zip unzip make libxrandr-dev g++-mingw-w64-x86-64 gcc-mingw-w64-x86-64 g++-mingw-i686-x86-64 gcc-mingw-i686-x86-64 libxinerama-dev libxcursor-dev libxi-dev libgl-dev + sudo apt install -y build-essential cmake zip unzip make libxrandr-dev g++-mingw-w64-x86-64 gcc-mingw-w64-x86-64 g++-mingw-w64-i686 gcc-mingw-w64-i686 libxinerama-dev libxcursor-dev libxi-dev libgl-dev - name: Build makeheaders run: | diff --git a/data/resources/terrain.png b/data/resources/terrain.png index b95140c..0ac03da 100644 Binary files a/data/resources/terrain.png and b/data/resources/terrain.png differ diff --git a/src/helpers/chunks.cpp b/src/helpers/chunks.cpp index ee9dd79..079f53d 100644 --- a/src/helpers/chunks.cpp +++ b/src/helpers/chunks.cpp @@ -42,10 +42,10 @@ const BlockDef BLOCKS[] = { BlockDef{ "workbench", R_TranslucentAllSides, B_Stone, 3, 0, 23, 22, 23}, BlockDef{ "blue_block", R_Normal, B_Stone, 5, 0, 22}, BlockDef{ "yellow_block", R_Normal, B_Stone, 5, 0, 23}, - BlockDef{ "cyan_block", R_Normal, B_Stone, 5, 0, 24}, - BlockDef{ "magenta_block", R_Normal, B_Stone, 5, 0, 25}, - BlockDef{ "white_block", R_Normal, B_Stone, 5, 0, 26}, - BlockDef{ "black_block", R_Normal, B_Stone, 5, 0, 27}, + BlockDef{ "red_block", R_Normal, B_Stone, 5, 0, 24}, + BlockDef{ "green_block", R_Normal, B_Stone, 5, 0, 25}, + BlockDef{ "blue_block", R_Normal, B_Stone, 5, 0, 26}, + BlockDef{ "white_block", R_Normal, B_Stone, 5, 0, 27}, BlockDef{ "leaves", R_TranslucentAllSides, B_Grass, 1, 0, 28}, BlockDef{ "copper_ore", R_Normal, B_Stone, 7, 1, 5}, BlockDef{ "silver_ore", R_Normal, B_Stone, 7, 2, 6}, @@ -127,6 +127,36 @@ int GetSkyLight(World &world, int x, int y, int z) { int skyLight = (light >> 12) & 0xF; return skyLight; } +int GetRLight(World &world, int x, int y, int z) { + if(CheckOOBWorld(x, y, z)) return 0; + int locX = x % CHUNK_SIZE; + int locZ = z % CHUNK_SIZE; + int cx = x / CHUNK_SIZE; + int cz = z / CHUNK_SIZE; + uint16_t light = world.chunks[GetIndexWorld(cx, cz)].light[GetIndexChunk(locX, y, locZ)]; + int skyLight = (light >> 8) & 0xF; + return skyLight; +} +int GetGLight(World &world, int x, int y, int z) { + if(CheckOOBWorld(x, y, z)) return 0; + int locX = x % CHUNK_SIZE; + int locZ = z % CHUNK_SIZE; + int cx = x / CHUNK_SIZE; + int cz = z / CHUNK_SIZE; + uint16_t light = world.chunks[GetIndexWorld(cx, cz)].light[GetIndexChunk(locX, y, locZ)]; + int skyLight = (light >> 4) & 0xF; + return skyLight; +} +int GetBLight(World &world, int x, int y, int z) { + if(CheckOOBWorld(x, y, z)) return 0; + int locX = x % CHUNK_SIZE; + int locZ = z % CHUNK_SIZE; + int cx = x / CHUNK_SIZE; + int cz = z / CHUNK_SIZE; + uint16_t light = world.chunks[GetIndexWorld(cx, cz)].light[GetIndexChunk(locX, y, locZ)]; + int skyLight = light & 0xF; + return skyLight; +} Color GetLight(World &world, int x, int y, int z) { if(CheckOOBWorld(x, y, z)) return {0, 0, 0, 0}; int locX = x % CHUNK_SIZE; @@ -135,8 +165,19 @@ Color GetLight(World &world, int x, int y, int z) { int cz = z / CHUNK_SIZE; uint16_t light = world.chunks[GetIndexWorld(cx, cz)].light[GetIndexChunk(locX, y, locZ)]; int skyLight = ((light >> 12) & 0xF) * 16; - //return {((light >> 8) & 0xF) * 16 + skyLight, (light >> 4) * 16 + skyLight, (light & 0xF) * 16 + skyLight, 255}; - return {skyLight, skyLight, skyLight, 255}; + Color sky = {skyLight, skyLight, skyLight, 255}; + Color r = {((light >> 8) & 0xF) * 16 + skyLight, 0, 0, 255}; + Color g = {0, ((light >> 4) & 0xF) * 16 + skyLight, 0, 255}; + Color b = {0, 0, ((light >> 0) & 0xF) * 16 + skyLight, 255}; + Color f = ColorTint(sky, r); + f = ColorTint(f, g); + f = ColorTint(f, b); + return { + fmin((int)sky.r + (int)r.r, 255), + fmin((int)sky.g + (int)g.g, 255), + fmin((int)sky.b + (int)b.b, 255), + 255 + }; } bool CanTick(int blockType) { // TODO: make smarter in case other blocks can tick too! return blockType == BLOCK_SAND; @@ -244,7 +285,20 @@ void SetBlock(World &world, int x, int y, int z, int t) { } void SetLightChunk(Chunk *c, int x, int y, int z, uint8_t sky, uint8_t r, uint8_t g, uint8_t b) { - c->light[GetIndexChunk(x,y,z)] = sky << 12 | r << 8 | g << 4 | b; + int target = c->light[GetIndexChunk(x,y,z)]; + if(sky > 0) { + target |= sky << 12; + } + if(r > 0) { + target |= r << 8; + } + if(g > 0) { + target |= g << 4; + } + if(b > 0) { + target |= b; + } + c->light[GetIndexChunk(x,y,z)] = target; } void SetLight(World &world, int x, int y, int z, uint8_t sky, uint8_t r, uint8_t g, uint8_t b) { if(CheckOOBWorld(x, y, z)) { return; } @@ -553,6 +607,9 @@ void RebuildOpaqueMask(Chunk &chunk) { } void RebuildLighting(World &world, int startX, int startZ) { + const Vector3I dirs[6] = { (Vector3I){ 1, 0, 0 }, (Vector3I){ -1, 0, 0 }, (Vector3I){ 0, 1, 0 }, (Vector3I){ 0,-1, 0 }, (Vector3I){ 0, 0, 1 }, (Vector3I){ 0, 0,-1 } }; + + // sky lighting std::queue nodes; for (int cx = -1; cx <= 1; cx++) @@ -566,24 +623,20 @@ void RebuildLighting(World &world, int startX, int startZ) { if (y < 0) continue; Vector3I pos = { x + chunk.x * CHUNK_SIZE, y + 1, z + chunk.z * CHUNK_SIZE }; if (CheckOOBWorld(pos.x, pos.y, pos.z)) continue; + for (int _y = WORLD_HEIGHT; _y >= y; _y--) { SetLight(world, pos.x, _y, pos.z, 15, 0, 0, 0); } LightNode node{pos, 15}; - SetLight(world, pos.x, pos.y, pos.z, 15, 0, 0, 0); nodes.push(node); } } } } - - const Vector3I dirs[6] = { (Vector3I){ 1, 0, 0 }, (Vector3I){ -1, 0, 0 }, (Vector3I){ 0, 1, 0 }, (Vector3I){ 0,-1, 0 }, (Vector3I){ 0, 0, 1 }, (Vector3I){ 0, 0,-1 } }; - while (!nodes.empty()) { - std::cout << nodes.size() << std::endl; LightNode node = nodes.front(); nodes.pop(); @@ -595,7 +648,7 @@ void RebuildLighting(World &world, int startX, int startZ) { }; if (CheckOOBWorld(newPos.x, newPos.y, newPos.z)) continue; - if (GetBlock(world, newPos.x, newPos.y, newPos.z) != BLOCK_AIR) continue; + if (TestOpaqueMaskWorld(world, newPos.x, newPos.y, newPos.z)) continue; int newValue = node.value - 1; if (newValue <= 0) continue; @@ -605,6 +658,141 @@ void RebuildLighting(World &world, int startX, int startZ) { nodes.push({ newPos, newValue }); } } + + // red lighting + std::queue nodesR; + + for (int cx = -1; cx <= 1; cx++) + { + for (int cz = -1; cz <= 1; cz++) { + Chunk &chunk = world.chunks[GetIndexWorld(startX+cx, startZ+cz)]; + for (int i = 0; i < CHUNK_DATA_SIZE; i++) + { + int x, y, z; + GetXYZFromIndex(i, &x, &y, &z); + if (CheckOOBWorld(x, y, z)) continue; + if(chunk.blocks[i] != 18 && chunk.blocks[i] != 21) continue; + Vector3I pos = { x + chunk.x * CHUNK_SIZE, y, z + chunk.z * CHUNK_SIZE }; + std::cout << pos.y << std::endl; + LightNode node{pos, 15}; + nodesR.push(node); + } + } + } + + while (!nodesR.empty()) { + std::cout << nodesR.size() << std::endl; + LightNode node = nodesR.front(); + nodesR.pop(); + + for (int i = 0; i < 6; i++) { + Vector3I newPos = { + node.position.x + dirs[i].x, + node.position.y + dirs[i].y, + node.position.z + dirs[i].z + }; + + if (CheckOOBWorld(newPos.x, newPos.y, newPos.z)) continue; + if (TestOpaqueMaskWorld(world, newPos.x, newPos.y, newPos.z)) continue; + int newValue = node.value - 1; + if (newValue <= 0) continue; + + if (GetRLight(world, newPos.x, newPos.y, newPos.z) >= newValue) continue; + + SetLight(world, newPos.x, newPos.y, newPos.z, 0, newValue, 0, 0); + nodesR.push({ newPos, newValue }); + } + } + + // green lighting + std::queue nodesG; + + for (int cx = -1; cx <= 1; cx++) + { + for (int cz = -1; cz <= 1; cz++) { + Chunk &chunk = world.chunks[GetIndexWorld(startX+cx, startZ+cz)]; + for (int i = 0; i < CHUNK_DATA_SIZE; i++) + { + int x, y, z; + GetXYZFromIndex(i, &x, &y, &z); + if (CheckOOBWorld(x, y, z)) continue; + if(chunk.blocks[i] != 19 && chunk.blocks[i] != 21) continue; + Vector3I pos = { x + chunk.x * CHUNK_SIZE, y, z + chunk.z * CHUNK_SIZE }; + std::cout << pos.y << std::endl; + LightNode node{pos, 15}; + nodesG.push(node); + } + } + } + + while (!nodesG.empty()) { + std::cout << nodesG.size() << std::endl; + LightNode node = nodesG.front(); + nodesG.pop(); + + for (int i = 0; i < 6; i++) { + Vector3I newPos = { + node.position.x + dirs[i].x, + node.position.y + dirs[i].y, + node.position.z + dirs[i].z + }; + + if (CheckOOBWorld(newPos.x, newPos.y, newPos.z)) continue; + if (TestOpaqueMaskWorld(world, newPos.x, newPos.y, newPos.z)) continue; + int newValue = node.value - 1; + if (newValue <= 0) continue; + + if (GetGLight(world, newPos.x, newPos.y, newPos.z) >= newValue) continue; + + SetLight(world, newPos.x, newPos.y, newPos.z, 0, 0, newValue, 0); + nodesG.push({ newPos, newValue }); + } + } + + // blue lighting + std::queue nodesB; + + for (int cx = -1; cx <= 1; cx++) + { + for (int cz = -1; cz <= 1; cz++) { + Chunk &chunk = world.chunks[GetIndexWorld(startX+cx, startZ+cz)]; + for (int i = 0; i < CHUNK_DATA_SIZE; i++) + { + int x, y, z; + GetXYZFromIndex(i, &x, &y, &z); + if (CheckOOBWorld(x, y, z)) continue; + if(chunk.blocks[i] != 20 && chunk.blocks[i] != 21) continue; + Vector3I pos = { x + chunk.x * CHUNK_SIZE, y, z + chunk.z * CHUNK_SIZE }; + std::cout << pos.y << std::endl; + LightNode node{pos, 15}; + nodesB.push(node); + } + } + } + + while (!nodesB.empty()) { + std::cout << nodesB.size() << std::endl; + LightNode node = nodesB.front(); + nodesB.pop(); + + for (int i = 0; i < 6; i++) { + Vector3I newPos = { + node.position.x + dirs[i].x, + node.position.y + dirs[i].y, + node.position.z + dirs[i].z + }; + + if (CheckOOBWorld(newPos.x, newPos.y, newPos.z)) continue; + if (TestOpaqueMaskWorld(world, newPos.x, newPos.y, newPos.z)) continue; + int newValue = node.value - 1; + if (newValue <= 0) continue; + + if (GetBLight(world, newPos.x, newPos.y, newPos.z) >= newValue) continue; + + SetLight(world, newPos.x, newPos.y, newPos.z, 0, 0, 0, newValue); + nodesB.push({ newPos, newValue }); + } + } } #ifndef SERVER //Generates an opaque CRD (ChunkRenderData). Outputs the CRD. diff --git a/src/helpers/common.hpp b/src/helpers/common.hpp index 96a7f61..41aa1fa 100644 --- a/src/helpers/common.hpp +++ b/src/helpers/common.hpp @@ -78,7 +78,7 @@ #define DEFAULT_FONT_SIZE 16 #define TPS 30.0 #define TPS_DIV 1.0 / TPS -#define RENDER_DISTANCE 2 +#define RENDER_DISTANCE 5 #define RENDER_DISTANCE_SQUARED RENDER_DISTANCE*RENDER_DISTANCE #define MAX_HP 100 #define PATH_APPEND "resources/" @@ -307,6 +307,9 @@ extern const BlockDef BLOCKS[]; int GetBlock(World&world,int x,int y,int z); int GetHighestBlock(World&world,int x,int z); int GetSkyLight(World&world,int x,int y,int z); +int GetRLight(World&world,int x,int y,int z); +int GetGLight(World&world,int x,int y,int z); +int GetBLight(World&world,int x,int y,int z); Color GetLight(World&world,int x,int y,int z); bool CanTick(int blockType); bool GetCloud(int x,int z); @@ -463,10 +466,10 @@ inline void unpack6(uint8_t v,bool *b0,bool *b1,bool *b2,bool *b3,bool *b4,bool *b5 = (v >> 5) & 1; }; inline void GetXYZFromIndex(int index,int *x,int *y,int *z){ - *x = index & 15; - int tmp = index << 4; - *z = tmp & 15; - *y = tmp << 4; + *y = index / (CHUNK_SIZE * CHUNK_SIZE); + int rem = index % (CHUNK_SIZE * CHUNK_SIZE); + *z = rem / CHUNK_SIZE; + *x = rem % CHUNK_SIZE; }; inline int GetIndexChunk(int x,int y,int z){ if(x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_HEIGHT || z >= CHUNK_SIZE) return 0; diff --git a/src/helpers/inlines.hpp b/src/helpers/inlines.hpp index 87a7a9c..78e9649 100644 --- a/src/helpers/inlines.hpp +++ b/src/helpers/inlines.hpp @@ -20,14 +20,15 @@ inline void unpack6(uint8_t v, bool *b0, bool *b1, bool *b2, bool *b3, bool *b4, *b5 = (v >> 5) & 1; } -inline void GetXYZFromIndex(int index, int *x, int *y, int *z) { - *x = index & 15; - int tmp = index << 4; - *z = tmp & 15; - *y = tmp << 4; +inline void GetXYZFromIndex(int index, int* x, int* y, int* z) { + *y = index / (CHUNK_SIZE * CHUNK_SIZE); + int rem = index % (CHUNK_SIZE * CHUNK_SIZE); + *z = rem / CHUNK_SIZE; + *x = rem % CHUNK_SIZE; } + inline int GetIndexChunk(int x, int y, int z) { if(x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_HEIGHT || z >= CHUNK_SIZE) return 0; return x + CHUNK_SIZE * (z + CHUNK_SIZE * y); diff --git a/src/helpers/vars.hpp b/src/helpers/vars.hpp index f3bd8e8..77f91c4 100644 --- a/src/helpers/vars.hpp +++ b/src/helpers/vars.hpp @@ -102,7 +102,7 @@ #define TPS 30.0 #define TPS_DIV 1.0 / TPS //Rendering -#define RENDER_DISTANCE 2 +#define RENDER_DISTANCE 5 #define RENDER_DISTANCE_SQUARED RENDER_DISTANCE*RENDER_DISTANCE //Game stuff