MorriCraft v2.2.9: Major performance optimizations, viewmodel fixes, and critical bug fixes
|
Before Width: | Height: | Size: 6.9 MiB After Width: | Height: | Size: 6.9 MiB |
|
Before Width: | Height: | Size: 166 B After Width: | Height: | Size: 291 B |
|
Before Width: | Height: | Size: 200 B After Width: | Height: | Size: 285 B |
|
Before Width: | Height: | Size: 219 B After Width: | Height: | Size: 318 B |
BIN
assets/dirt.png
|
Before Width: | Height: | Size: 197 B After Width: | Height: | Size: 279 B |
BIN
assets/grass.png
|
Before Width: | Height: | Size: 329 B After Width: | Height: | Size: 428 B |
|
Before Width: | Height: | Size: 298 B After Width: | Height: | Size: 364 B |
|
Before Width: | Height: | Size: 199 B After Width: | Height: | Size: 296 B |
|
Before Width: | Height: | Size: 212 B After Width: | Height: | Size: 303 B |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.1 KiB |
BIN
assets/plank.png
|
Before Width: | Height: | Size: 195 B After Width: | Height: | Size: 285 B |
BIN
assets/sand.png
|
Before Width: | Height: | Size: 188 B After Width: | Height: | Size: 275 B |
BIN
assets/stick.png
|
Before Width: | Height: | Size: 513 B After Width: | Height: | Size: 321 B |
BIN
assets/stone.png
|
Before Width: | Height: | Size: 151 B After Width: | Height: | Size: 226 B |
|
|
@ -0,0 +1 @@
|
||||||
|
v2.2.8
|
||||||
|
Before Width: | Height: | Size: 440 B After Width: | Height: | Size: 390 B |
|
Before Width: | Height: | Size: 220 KiB After Width: | Height: | Size: 339 KiB |
|
Before Width: | Height: | Size: 316 KiB After Width: | Height: | Size: 594 KiB |
|
Before Width: | Height: | Size: 260 KiB After Width: | Height: | Size: 462 KiB |
|
Before Width: | Height: | Size: 303 KiB After Width: | Height: | Size: 575 KiB |
|
Before Width: | Height: | Size: 6.9 MiB After Width: | Height: | Size: 6.9 MiB |
|
Before Width: | Height: | Size: 166 B After Width: | Height: | Size: 291 B |
|
Before Width: | Height: | Size: 200 B After Width: | Height: | Size: 285 B |
|
After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 219 B After Width: | Height: | Size: 318 B |
|
Before Width: | Height: | Size: 197 B After Width: | Height: | Size: 279 B |
|
Before Width: | Height: | Size: 329 B After Width: | Height: | Size: 428 B |
|
Before Width: | Height: | Size: 298 B After Width: | Height: | Size: 364 B |
|
Before Width: | Height: | Size: 199 B After Width: | Height: | Size: 296 B |
|
Before Width: | Height: | Size: 212 B After Width: | Height: | Size: 303 B |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 195 B After Width: | Height: | Size: 285 B |
|
Before Width: | Height: | Size: 188 B After Width: | Height: | Size: 275 B |
|
Before Width: | Height: | Size: 513 B After Width: | Height: | Size: 321 B |
|
Before Width: | Height: | Size: 151 B After Width: | Height: | Size: 226 B |
|
|
@ -1 +1 @@
|
||||||
v2.2.7
|
v2.2.8
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 440 B After Width: | Height: | Size: 390 B |
|
Before Width: | Height: | Size: 220 KiB After Width: | Height: | Size: 339 KiB |
|
Before Width: | Height: | Size: 316 KiB After Width: | Height: | Size: 594 KiB |
|
Before Width: | Height: | Size: 260 KiB After Width: | Height: | Size: 462 KiB |
|
Before Width: | Height: | Size: 303 KiB After Width: | Height: | Size: 575 KiB |
476
src/main.cpp
|
|
@ -20,7 +20,7 @@
|
||||||
#define PI 3.1415926535f
|
#define PI 3.1415926535f
|
||||||
#endif
|
#endif
|
||||||
#define CHUNK_HEIGHT 128
|
#define CHUNK_HEIGHT 128
|
||||||
#define RENDER_DISTANCE 4
|
#define RENDER_DISTANCE 8
|
||||||
|
|
||||||
enum BlockType {
|
enum BlockType {
|
||||||
AIR = 0, GRASS = 1, DIRT = 2, COBBLESTONE = 3, LOG = 4, LEAVES = 5, PLANK = 6,
|
AIR = 0, GRASS = 1, DIRT = 2, COBBLESTONE = 3, LOG = 4, LEAVES = 5, PLANK = 6,
|
||||||
|
|
@ -122,13 +122,18 @@ struct ChunkPosHash {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct BlockRenderData {
|
||||||
|
float x, y, z;
|
||||||
|
unsigned char faces; // 1:front, 2:back, 4:top, 8:bottom, 16:right, 32:left
|
||||||
|
};
|
||||||
|
|
||||||
struct Chunk {
|
struct Chunk {
|
||||||
int blocks[CHUNK_SIZE][CHUNK_HEIGHT][CHUNK_SIZE];
|
int blocks[CHUNK_SIZE][CHUNK_HEIGHT][CHUNK_SIZE];
|
||||||
int maxY = 0;
|
int maxY = 0;
|
||||||
bool generated = false;
|
bool generated = false;
|
||||||
bool modified = false;
|
bool modified = false;
|
||||||
bool dirty = true;
|
bool dirty = true;
|
||||||
std::vector<Vector3> renderLists[32];
|
std::vector<BlockRenderData> renderLists[32];
|
||||||
Chunk() : generated(false), modified(false), maxY(0), dirty(true) {}
|
Chunk() : generated(false), modified(false), maxY(0), dirty(true) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -150,7 +155,7 @@ static Sound hitSound;
|
||||||
enum MenuState { MAIN_MENU, OPTIONS_MENU, CREATE_WORLD_MENU, LOAD_WORLD_MENU, GAMEPLAY, PAUSE_MENU, CRAFTING_GUI, CHECKING_UPDATES, UPDATE_NOTES, UPDATE_FOUND, DOWNLOADING_UPDATE, CONNECT_MENU, SKIN_EDITOR, WORLD_CREATION_PROGRESS };
|
enum MenuState { MAIN_MENU, OPTIONS_MENU, CREATE_WORLD_MENU, LOAD_WORLD_MENU, GAMEPLAY, PAUSE_MENU, CRAFTING_GUI, CHECKING_UPDATES, UPDATE_NOTES, UPDATE_FOUND, DOWNLOADING_UPDATE, CONNECT_MENU, SKIN_EDITOR, WORLD_CREATION_PROGRESS };
|
||||||
|
|
||||||
// Forward Declarations
|
// Forward Declarations
|
||||||
bool IsExposedOptimized(int lx, int ly, int lz, Chunk* chunk, Chunk* nxM, Chunk* nxP, Chunk* nzM, Chunk* nzP);
|
unsigned char GetExposedFaces(int lx, int ly, int lz, Chunk* chunk, Chunk* nxM, Chunk* nxP, Chunk* nzM, Chunk* nzP);
|
||||||
void RebuildChunkRenderList(Chunk* chunk, int cx, int cz);
|
void RebuildChunkRenderList(Chunk* chunk, int cx, int cz);
|
||||||
void GenerateChunk(int cx, int cz);
|
void GenerateChunk(int cx, int cz);
|
||||||
void SetBlock(int x, int y, int z, int type);
|
void SetBlock(int x, int y, int z, int type);
|
||||||
|
|
@ -230,6 +235,11 @@ void AddToInventory(int blockType) {
|
||||||
// Inventory full — item is lost for now
|
// Inventory full — item is lost for now
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper to give multiple items
|
||||||
|
void GiveItems(int type, int count) {
|
||||||
|
for (int i = 0; i < count; i++) AddToInventory(type);
|
||||||
|
}
|
||||||
|
|
||||||
// Camera look angles — global so world load/create can reset them cleanly
|
// Camera look angles — global so world load/create can reset them cleanly
|
||||||
static float camYaw = 0.0f;
|
static float camYaw = 0.0f;
|
||||||
static float camPitch = 0.0f;
|
static float camPitch = 0.0f;
|
||||||
|
|
@ -280,18 +290,35 @@ int GetBlock(int x, int y, int z) {
|
||||||
return 0; // Air if chunk not loaded
|
return 0; // Air if chunk not loaded
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned char GetExposedFaces(int lx, int ly, int lz, Chunk* chunk, Chunk* nxM, Chunk* nxP, Chunk* nzM, Chunk* nzP) {
|
||||||
|
auto IsTrans = [](int bt) { return bt == AIR || bt == LEAVES; };
|
||||||
|
unsigned char mask = 0;
|
||||||
|
// Front (+Z)
|
||||||
|
if (lz < CHUNK_SIZE - 1) { if (IsTrans(chunk->blocks[lx][ly][lz+1])) mask |= 1; }
|
||||||
|
else if (nzP) { if (IsTrans(nzP->blocks[lx][ly][0])) mask |= 1; } else mask |= 1;
|
||||||
|
// Back (-Z)
|
||||||
|
if (lz > 0) { if (IsTrans(chunk->blocks[lx][ly][lz-1])) mask |= 2; }
|
||||||
|
else if (nzM) { if (IsTrans(nzM->blocks[lx][ly][CHUNK_SIZE-1])) mask |= 2; } else mask |= 2;
|
||||||
|
// Top (+Y)
|
||||||
|
if (ly < CHUNK_HEIGHT - 1) { if (IsTrans(chunk->blocks[lx][ly+1][lz])) mask |= 4; } else mask |= 4;
|
||||||
|
// Bottom (-Y)
|
||||||
|
if (ly > 0) { if (IsTrans(chunk->blocks[lx][ly-1][lz])) mask |= 8; } else mask |= 8;
|
||||||
|
// Right (+X)
|
||||||
|
if (lx < CHUNK_SIZE - 1) { if (IsTrans(chunk->blocks[lx+1][ly][lz])) mask |= 16; }
|
||||||
|
else if (nxP) { if (IsTrans(nxP->blocks[0][ly][lz])) mask |= 16; } else mask |= 16;
|
||||||
|
// Left (-X)
|
||||||
|
if (lx > 0) { if (IsTrans(chunk->blocks[lx-1][ly][lz])) mask |= 32; }
|
||||||
|
else if (nxM) { if (IsTrans(nxM->blocks[CHUNK_SIZE-1][ly][lz])) mask |= 32; } else mask |= 32;
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
void RebuildChunkRenderList(Chunk* chunk, int cx, int cz) {
|
void RebuildChunkRenderList(Chunk* chunk, int cx, int cz) {
|
||||||
for (int i = 0; i < 32; i++) chunk->renderLists[i].clear();
|
for (int i = 0; i < 32; i++) chunk->renderLists[i].clear();
|
||||||
|
|
||||||
// Neighbors for exposure check
|
auto itNM = worldChunks.find({cx-1, cz}); Chunk* nxM = (itNM != worldChunks.end()) ? itNM->second : nullptr;
|
||||||
auto itNM = worldChunks.find({cx-1, cz});
|
auto itNP = worldChunks.find({cx+1, cz}); Chunk* nxP = (itNP != worldChunks.end()) ? itNP->second : nullptr;
|
||||||
Chunk* nxM = (itNM != worldChunks.end()) ? itNM->second : nullptr;
|
auto itZM = worldChunks.find({cx, cz-1}); Chunk* nzM = (itZM != worldChunks.end()) ? itZM->second : nullptr;
|
||||||
auto itNP = worldChunks.find({cx+1, cz});
|
auto itZP = worldChunks.find({cx, cz+1}); Chunk* nzP = (itZP != worldChunks.end()) ? itZP->second : nullptr;
|
||||||
Chunk* nxP = (itNP != worldChunks.end()) ? itNP->second : nullptr;
|
|
||||||
auto itZM = worldChunks.find({cx, cz-1});
|
|
||||||
Chunk* nzM = (itZM != worldChunks.end()) ? itZM->second : nullptr;
|
|
||||||
auto itZP = worldChunks.find({cx, cz+1});
|
|
||||||
Chunk* nzP = (itZP != worldChunks.end()) ? itZP->second : nullptr;
|
|
||||||
|
|
||||||
int worldX = cx * CHUNK_SIZE;
|
int worldX = cx * CHUNK_SIZE;
|
||||||
int worldZ = cz * CHUNK_SIZE;
|
int worldZ = cz * CHUNK_SIZE;
|
||||||
|
|
@ -302,8 +329,9 @@ void RebuildChunkRenderList(Chunk* chunk, int cx, int cz) {
|
||||||
int bt = chunk->blocks[lx][ly][lz];
|
int bt = chunk->blocks[lx][ly][lz];
|
||||||
if (bt == AIR) continue;
|
if (bt == AIR) continue;
|
||||||
|
|
||||||
if (IsExposedOptimized(lx, ly, lz, chunk, nxM, nxP, nzM, nzP)) {
|
unsigned char faces = GetExposedFaces(lx, ly, lz, chunk, nxM, nxP, nzM, nzP);
|
||||||
chunk->renderLists[bt].push_back((Vector3){(float)(worldX+lx), (float)ly, (float)(worldZ+lz)});
|
if (faces != 0) {
|
||||||
|
chunk->renderLists[bt].push_back({ (float)(worldX+lx), (float)ly, (float)(worldZ+lz), faces });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -535,6 +563,10 @@ void GenerateChunk(int cx, int cz) {
|
||||||
|
|
||||||
if (LoadChunk(newChunk, cx, cz)) {
|
if (LoadChunk(newChunk, cx, cz)) {
|
||||||
worldChunks[key] = newChunk;
|
worldChunks[key] = newChunk;
|
||||||
|
auto n1 = worldChunks.find({cx-1, cz}); if (n1 != worldChunks.end()) n1->second->dirty = true;
|
||||||
|
auto n2 = worldChunks.find({cx+1, cz}); if (n2 != worldChunks.end()) n2->second->dirty = true;
|
||||||
|
auto n3 = worldChunks.find({cx, cz-1}); if (n3 != worldChunks.end()) n3->second->dirty = true;
|
||||||
|
auto n4 = worldChunks.find({cx, cz+1}); if (n4 != worldChunks.end()) n4->second->dirty = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -623,10 +655,10 @@ void GenerateChunk(int cx, int cz) {
|
||||||
}
|
}
|
||||||
|
|
||||||
newChunk->generated = true;
|
newChunk->generated = true;
|
||||||
newChunk->modified = true; // Newly generated, so we should save it
|
newChunk->modified = true;
|
||||||
worldChunks[key] = newChunk;
|
worldChunks[key] = newChunk;
|
||||||
|
|
||||||
// Mark neighbors as dirty so they rebuild their render lists with new occlusion data
|
// Mark neighbors as dirty (Bug #2 fix)
|
||||||
ChunkPos neighbors[] = { {cx-1, cz}, {cx+1, cz}, {cx, cz-1}, {cx, cz+1} };
|
ChunkPos neighbors[] = { {cx-1, cz}, {cx+1, cz}, {cx, cz-1}, {cx, cz+1} };
|
||||||
for (auto& nPos : neighbors) {
|
for (auto& nPos : neighbors) {
|
||||||
auto it = worldChunks.find(nPos);
|
auto it = worldChunks.find(nPos);
|
||||||
|
|
@ -708,162 +740,101 @@ void DrawTexturedCube(Vector3 position, float width, float height, float length,
|
||||||
// Draws a grass block with correct per-face textures:
|
// Draws a grass block with correct per-face textures:
|
||||||
// top=green grass, sides=dirt+grass stripe, bottom=pure dirt.
|
// top=green grass, sides=dirt+grass stripe, bottom=pure dirt.
|
||||||
// Caller must NOT have an active rlSetTexture — this function manages its own binds.
|
// Caller must NOT have an active rlSetTexture — this function manages its own binds.
|
||||||
void DrawGrassBlock(Vector3 position, unsigned int sideTexId, unsigned int topTexId, unsigned int botTexId, Color tint) {
|
void DrawCubeVertices(float x, float y, float z, float w, float h, float l, unsigned char mask) {
|
||||||
float x = position.x;
|
|
||||||
float y = position.y;
|
|
||||||
float z = position.z;
|
|
||||||
|
|
||||||
// ---- SIDES (4 faces) ----
|
|
||||||
rlSetTexture(sideTexId);
|
|
||||||
rlBegin(RL_QUADS);
|
|
||||||
rlColor4ub(tint.r, tint.g, tint.b, 255);
|
|
||||||
// Front
|
|
||||||
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - 0.5f, y - 0.5f, z + 0.5f);
|
|
||||||
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + 0.5f, y - 0.5f, z + 0.5f);
|
|
||||||
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + 0.5f, y + 0.5f, z + 0.5f);
|
|
||||||
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - 0.5f, y + 0.5f, z + 0.5f);
|
|
||||||
// Back
|
|
||||||
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - 0.5f, y - 0.5f, z - 0.5f);
|
|
||||||
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - 0.5f, y + 0.5f, z - 0.5f);
|
|
||||||
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + 0.5f, y + 0.5f, z - 0.5f);
|
|
||||||
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + 0.5f, y - 0.5f, z - 0.5f);
|
|
||||||
// Right
|
|
||||||
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + 0.5f, y - 0.5f, z - 0.5f);
|
|
||||||
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + 0.5f, y + 0.5f, z - 0.5f);
|
|
||||||
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + 0.5f, y + 0.5f, z + 0.5f);
|
|
||||||
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + 0.5f, y - 0.5f, z + 0.5f);
|
|
||||||
// Left
|
|
||||||
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - 0.5f, y - 0.5f, z - 0.5f);
|
|
||||||
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - 0.5f, y - 0.5f, z + 0.5f);
|
|
||||||
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - 0.5f, y + 0.5f, z + 0.5f);
|
|
||||||
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - 0.5f, y + 0.5f, z - 0.5f);
|
|
||||||
rlEnd();
|
|
||||||
|
|
||||||
// ---- TOP (pure green) ----
|
|
||||||
rlSetTexture(topTexId);
|
|
||||||
rlBegin(RL_QUADS);
|
|
||||||
// Combine grass green with ambient light
|
|
||||||
rlColor4ub((unsigned char)(124 * (tint.r/255.0f)),
|
|
||||||
(unsigned char)(189 * (tint.g/255.0f)),
|
|
||||||
(unsigned char)(107 * (tint.b/255.0f)), 255);
|
|
||||||
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - 0.5f, y + 0.5f, z - 0.5f);
|
|
||||||
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - 0.5f, y + 0.5f, z + 0.5f);
|
|
||||||
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + 0.5f, y + 0.5f, z + 0.5f);
|
|
||||||
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + 0.5f, y + 0.5f, z - 0.5f);
|
|
||||||
// ---- BOTTOM (pure dirt) ----
|
|
||||||
rlSetTexture(botTexId);
|
|
||||||
rlBegin(RL_QUADS);
|
|
||||||
rlColor4ub(tint.r, tint.g, tint.b, 255);
|
|
||||||
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - 0.5f, y - 0.5f, z - 0.5f);
|
|
||||||
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + 0.5f, y - 0.5f, z - 0.5f);
|
|
||||||
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + 0.5f, y - 0.5f, z + 0.5f);
|
|
||||||
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - 0.5f, y - 0.5f, z + 0.5f);
|
|
||||||
rlEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draws a crafting table with custom top and sides
|
|
||||||
void DrawCraftingTable(Vector3 position, unsigned int sideTexId, unsigned int topTexId, unsigned int botTexId, Color tint) {
|
|
||||||
float x = position.x; float y = position.y; float z = position.z;
|
|
||||||
|
|
||||||
// SIDES
|
|
||||||
rlSetTexture(sideTexId);
|
|
||||||
rlBegin(RL_QUADS);
|
|
||||||
rlColor4ub(tint.r, tint.g, tint.b, 255);
|
|
||||||
// Front, Back, Right, Left
|
|
||||||
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - 0.5f, y - 0.5f, z + 0.5f); rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + 0.5f, y - 0.5f, z + 0.5f); rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + 0.5f, y + 0.5f, z + 0.5f); rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - 0.5f, y + 0.5f, z + 0.5f);
|
|
||||||
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - 0.5f, y - 0.5f, z - 0.5f); rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - 0.5f, y + 0.5f, z - 0.5f); rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + 0.5f, y + 0.5f, z - 0.5f); rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + 0.5f, y - 0.5f, z - 0.5f);
|
|
||||||
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + 0.5f, y - 0.5f, z - 0.5f); rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + 0.5f, y + 0.5f, z - 0.5f); rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + 0.5f, y + 0.5f, z + 0.5f); rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + 0.5f, y - 0.5f, z + 0.5f);
|
|
||||||
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - 0.5f, y - 0.5f, z - 0.5f); rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - 0.5f, y - 0.5f, z + 0.5f); rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - 0.5f, y + 0.5f, z + 0.5f); rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - 0.5f, y + 0.5f, z - 0.5f);
|
|
||||||
rlEnd();
|
|
||||||
|
|
||||||
// TOP
|
|
||||||
rlSetTexture(topTexId);
|
|
||||||
rlBegin(RL_QUADS);
|
|
||||||
rlColor4ub(tint.r, tint.g, tint.b, 255);
|
|
||||||
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - 0.5f, y + 0.5f, z - 0.5f);
|
|
||||||
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - 0.5f, y + 0.5f, z + 0.5f);
|
|
||||||
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + 0.5f, y + 0.5f, z + 0.5f);
|
|
||||||
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + 0.5f, y + 0.5f, z - 0.5f);
|
|
||||||
rlEnd();
|
|
||||||
|
|
||||||
// BOTTOM (dirt)
|
|
||||||
rlSetTexture(botTexId);
|
|
||||||
rlBegin(RL_QUADS);
|
|
||||||
rlColor4ub(tint.r, tint.g, tint.b, 255);
|
|
||||||
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - 0.5f, y - 0.5f, z - 0.5f);
|
|
||||||
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + 0.5f, y - 0.5f, z - 0.5f);
|
|
||||||
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + 0.5f, y - 0.5f, z + 0.5f);
|
|
||||||
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - 0.5f, y - 0.5f, z + 0.5f);
|
|
||||||
rlEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrawLog(Vector3 position, unsigned int sideTexId, unsigned int topTexId, Color tint) {
|
|
||||||
float x = position.x; float y = position.y; float z = position.z;
|
|
||||||
rlSetTexture(sideTexId);
|
|
||||||
rlBegin(RL_QUADS);
|
|
||||||
rlColor4ub(tint.r, tint.g, tint.b, 255);
|
|
||||||
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - 0.5f, y - 0.5f, z + 0.5f); rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + 0.5f, y - 0.5f, z + 0.5f); rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + 0.5f, y + 0.5f, z + 0.5f); rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - 0.5f, y + 0.5f, z + 0.5f);
|
|
||||||
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - 0.5f, y - 0.5f, z - 0.5f); rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - 0.5f, y + 0.5f, z - 0.5f); rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + 0.5f, y + 0.5f, z - 0.5f); rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + 0.5f, y - 0.5f, z - 0.5f);
|
|
||||||
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + 0.5f, y - 0.5f, z - 0.5f); rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + 0.5f, y + 0.5f, z - 0.5f); rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + 0.5f, y + 0.5f, z + 0.5f); rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + 0.5f, y - 0.5f, z + 0.5f);
|
|
||||||
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - 0.5f, y - 0.5f, z - 0.5f); rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - 0.5f, y - 0.5f, z + 0.5f); rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - 0.5f, y + 0.5f, z + 0.5f); rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - 0.5f, y + 0.5f, z - 0.5f);
|
|
||||||
rlEnd();
|
|
||||||
rlSetTexture(topTexId);
|
|
||||||
rlBegin(RL_QUADS);
|
|
||||||
rlColor4ub(tint.r, tint.g, tint.b, 255);
|
|
||||||
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - 0.5f, y + 0.5f, z - 0.5f); rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - 0.5f, y + 0.5f, z + 0.5f); rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + 0.5f, y + 0.5f, z + 0.5f); rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + 0.5f, y + 0.5f, z - 0.5f);
|
|
||||||
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - 0.5f, y - 0.5f, z - 0.5f); rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + 0.5f, y - 0.5f, z - 0.5f); rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + 0.5f, y - 0.5f, z + 0.5f); rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - 0.5f, y - 0.5f, z + 0.5f);
|
|
||||||
rlEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optimized check to see if a block has any exposed faces.
|
|
||||||
bool IsExposedOptimized(int lx, int ly, int lz, Chunk* chunk, Chunk* nxM, Chunk* nxP, Chunk* nzM, Chunk* nzP) {
|
|
||||||
if (ly > 0) { if (chunk->blocks[lx][ly-1][lz] == AIR) return true; } else return true;
|
|
||||||
if (ly < CHUNK_HEIGHT - 1) { if (chunk->blocks[lx][ly+1][lz] == AIR) return true; } else return true;
|
|
||||||
if (lx > 0) { if (chunk->blocks[lx-1][ly][lz] == AIR) return true; }
|
|
||||||
else if (nxM) { if (nxM->blocks[CHUNK_SIZE-1][ly][lz] == AIR) return true; } else return true;
|
|
||||||
if (lx < CHUNK_SIZE - 1) { if (chunk->blocks[lx+1][ly][lz] == AIR) return true; }
|
|
||||||
else if (nxP) { if (nxP->blocks[0][ly][lz] == AIR) return true; } else return true;
|
|
||||||
if (lz > 0) { if (chunk->blocks[lx][ly][lz-1] == AIR) return true; }
|
|
||||||
else if (nzM) { if (nzM->blocks[lx][ly][CHUNK_SIZE-1] == AIR) return true; } else return true;
|
|
||||||
if (lz < CHUNK_SIZE - 1) { if (chunk->blocks[lx][ly][lz+1] == AIR) return true; }
|
|
||||||
else if (nzP) { if (nzP->blocks[lx][ly][0] == AIR) return true; } else return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optimized helper for batched rendering: Draws only the vertices (no texture bind or rlBegin/End)
|
|
||||||
void DrawCubeVertices(float x, float y, float z, float w, float h, float l) {
|
|
||||||
float hw = w/2.0f; float hh = h/2.0f; float hl = l/2.0f;
|
float hw = w/2.0f; float hh = h/2.0f; float hl = l/2.0f;
|
||||||
// Front
|
if (mask & 1) { // Front (+Z)
|
||||||
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - hw, y - hh, z + hl);
|
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - hw, y - hh, z + hl);
|
||||||
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + hw, y - hh, z + hl);
|
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + hw, y - hh, z + hl);
|
||||||
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + hw, y + hh, z + hl);
|
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + hw, y + hh, z + hl);
|
||||||
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - hw, y + hh, z + hl);
|
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - hw, y + hh, z + hl);
|
||||||
// Back
|
}
|
||||||
|
if (mask & 2) { // Back (-Z)
|
||||||
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - hw, y - hh, z - hl);
|
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - hw, y - hh, z - hl);
|
||||||
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - hw, y + hh, z - hl);
|
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - hw, y + hh, z - hl);
|
||||||
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + hw, y + hh, z - hl);
|
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + hw, y + hh, z - hl);
|
||||||
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + hw, y - hh, z - hl);
|
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + hw, y - hh, z - hl);
|
||||||
// Top
|
}
|
||||||
|
if (mask & 4) { // Top (+Y)
|
||||||
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - hw, y + hh, z - hl);
|
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - hw, y + hh, z - hl);
|
||||||
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - hw, y + hh, z + hl);
|
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - hw, y + hh, z + hl);
|
||||||
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + hw, y + hh, z + hl);
|
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + hw, y + hh, z + hl);
|
||||||
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + hw, y + hh, z - hl);
|
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + hw, y + hh, z - hl);
|
||||||
// Bottom
|
}
|
||||||
|
if (mask & 8) { // Bottom (-Y)
|
||||||
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - hw, y - hh, z - hl);
|
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - hw, y - hh, z - hl);
|
||||||
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + hw, y - hh, z - hl);
|
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + hw, y - hh, z - hl);
|
||||||
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + hw, y - hh, z + hl);
|
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + hw, y - hh, z + hl);
|
||||||
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - hw, y - hh, z + hl);
|
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - hw, y - hh, z + hl);
|
||||||
// Right
|
}
|
||||||
|
if (mask & 16) { // Right (+X)
|
||||||
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + hw, y - hh, z - hl);
|
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + hw, y - hh, z - hl);
|
||||||
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + hw, y + hh, z - hl);
|
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + hw, y + hh, z - hl);
|
||||||
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + hw, y + hh, z + hl);
|
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + hw, y + hh, z + hl);
|
||||||
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + hw, y - hh, z + hl);
|
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + hw, y - hh, z + hl);
|
||||||
// Left
|
}
|
||||||
|
if (mask & 32) { // Left (-X)
|
||||||
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - hw, y - hh, z - hl);
|
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - hw, y - hh, z - hl);
|
||||||
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - hw, y - hh, z + hl);
|
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - hw, y - hh, z + hl);
|
||||||
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - hw, y + hh, z + hl);
|
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - hw, y + hh, z + hl);
|
||||||
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - hw, y + hh, z - hl);
|
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - hw, y + hh, z - hl);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawGrassBlock(Vector3 position, unsigned int sideTexId, unsigned int topTexId, unsigned int botTexId, Color tint, unsigned char mask) {
|
||||||
|
float x = position.x; float y = position.y; float z = position.z;
|
||||||
|
if (mask & 51) { // Sides (Front, Back, Right, Left: 1|2|16|32 = 51)
|
||||||
|
rlSetTexture(sideTexId); rlBegin(RL_QUADS); rlColor4ub(tint.r, tint.g, tint.b, 255);
|
||||||
|
if (mask & 1) { rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - 0.5f, y - 0.5f, z + 0.5f); rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + 0.5f, y - 0.5f, z + 0.5f); rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + 0.5f, y + 0.5f, z + 0.5f); rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - 0.5f, y + 0.5f, z + 0.5f); }
|
||||||
|
if (mask & 2) { rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - 0.5f, y - 0.5f, z - 0.5f); rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - 0.5f, y + 0.5f, z - 0.5f); rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + 0.5f, y + 0.5f, z - 0.5f); rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + 0.5f, y - 0.5f, z - 0.5f); }
|
||||||
|
if (mask & 16) { rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + 0.5f, y - 0.5f, z - 0.5f); rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + 0.5f, y + 0.5f, z - 0.5f); rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + 0.5f, y + 0.5f, z + 0.5f); rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + 0.5f, y - 0.5f, z + 0.5f); }
|
||||||
|
if (mask & 32) { rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - 0.5f, y - 0.5f, z - 0.5f); rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - 0.5f, y - 0.5f, z + 0.5f); rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - 0.5f, y + 0.5f, z + 0.5f); rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - 0.5f, y + 0.5f, z - 0.5f); }
|
||||||
|
rlEnd();
|
||||||
|
}
|
||||||
|
if (mask & 4) { // Top
|
||||||
|
rlSetTexture(topTexId); rlBegin(RL_QUADS);
|
||||||
|
rlColor4ub((unsigned char)(124 * (tint.r/255.0f)), (unsigned char)(189 * (tint.g/255.0f)), (unsigned char)(107 * (tint.b/255.0f)), 255);
|
||||||
|
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - 0.5f, y + 0.5f, z - 0.5f); rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - 0.5f, y + 0.5f, z + 0.5f); rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + 0.5f, y + 0.5f, z + 0.5f); rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + 0.5f, y + 0.5f, z - 0.5f); rlEnd();
|
||||||
|
}
|
||||||
|
if (mask & 8) { // Bottom
|
||||||
|
rlSetTexture(botTexId); rlBegin(RL_QUADS); rlColor4ub(tint.r, tint.g, tint.b, 255);
|
||||||
|
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - 0.5f, y - 0.5f, z - 0.5f); rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + 0.5f, y - 0.5f, z - 0.5f); rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + 0.5f, y - 0.5f, z + 0.5f); rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - 0.5f, y - 0.5f, z + 0.5f); rlEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawLog(Vector3 position, unsigned int sideTexId, unsigned int topTexId, Color tint, unsigned char mask) {
|
||||||
|
float x = position.x; float y = position.y; float z = position.z;
|
||||||
|
if (mask & 51) {
|
||||||
|
rlSetTexture(sideTexId); rlBegin(RL_QUADS); rlColor4ub(tint.r, tint.g, tint.b, 255);
|
||||||
|
if (mask & 1) { rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - 0.5f, y - 0.5f, z + 0.5f); rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + 0.5f, y - 0.5f, z + 0.5f); rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + 0.5f, y + 0.5f, z + 0.5f); rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - 0.5f, y + 0.5f, z + 0.5f); }
|
||||||
|
if (mask & 2) { rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - 0.5f, y - 0.5f, z - 0.5f); rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - 0.5f, y + 0.5f, z - 0.5f); rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + 0.5f, y + 0.5f, z - 0.5f); rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + 0.5f, y - 0.5f, z - 0.5f); }
|
||||||
|
if (mask & 16) { rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + 0.5f, y - 0.5f, z - 0.5f); rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + 0.5f, y + 0.5f, z - 0.5f); rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + 0.5f, y + 0.5f, z + 0.5f); rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + 0.5f, y - 0.5f, z + 0.5f); }
|
||||||
|
if (mask & 32) { rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - 0.5f, y - 0.5f, z - 0.5f); rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - 0.5f, y - 0.5f, z + 0.5f); rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - 0.5f, y + 0.5f, z + 0.5f); rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - 0.5f, y + 0.5f, z - 0.5f); }
|
||||||
|
rlEnd();
|
||||||
|
}
|
||||||
|
if (mask & 12) { // Top + Bottom
|
||||||
|
rlSetTexture(topTexId); rlBegin(RL_QUADS); rlColor4ub(tint.r, tint.g, tint.b, 255);
|
||||||
|
if (mask & 4) { rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - 0.5f, y + 0.5f, z - 0.5f); rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - 0.5f, y + 0.5f, z + 0.5f); rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + 0.5f, y + 0.5f, z + 0.5f); rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + 0.5f, y + 0.5f, z - 0.5f); }
|
||||||
|
if (mask & 8) { rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - 0.5f, y - 0.5f, z - 0.5f); rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + 0.5f, y - 0.5f, z - 0.5f); rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + 0.5f, y - 0.5f, z + 0.5f); rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - 0.5f, y - 0.5f, z + 0.5f); }
|
||||||
|
rlEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawCraftingTable(Vector3 position, unsigned int sideTexId, unsigned int topTexId, unsigned int botTexId, Color tint, unsigned char mask) {
|
||||||
|
float x = position.x; float y = position.y; float z = position.z;
|
||||||
|
if (mask & 51) {
|
||||||
|
rlSetTexture(sideTexId); rlBegin(RL_QUADS); rlColor4ub(tint.r, tint.g, tint.b, 255);
|
||||||
|
if (mask & 1) { rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - 0.5f, y - 0.5f, z + 0.5f); rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + 0.5f, y - 0.5f, z + 0.5f); rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + 0.5f, y + 0.5f, z + 0.5f); rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - 0.5f, y + 0.5f, z + 0.5f); }
|
||||||
|
if (mask & 2) { rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - 0.5f, y - 0.5f, z - 0.5f); rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - 0.5f, y + 0.5f, z - 0.5f); rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + 0.5f, y + 0.5f, z - 0.5f); rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + 0.5f, y - 0.5f, z - 0.5f); }
|
||||||
|
if (mask & 16) { rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + 0.5f, y - 0.5f, z - 0.5f); rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + 0.5f, y + 0.5f, z - 0.5f); rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + 0.5f, y + 0.5f, z + 0.5f); rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + 0.5f, y - 0.5f, z + 0.5f); }
|
||||||
|
if (mask & 32) { rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - 0.5f, y - 0.5f, z - 0.5f); rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - 0.5f, y - 0.5f, z + 0.5f); rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - 0.5f, y + 0.5f, z + 0.5f); rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - 0.5f, y + 0.5f, z - 0.5f); }
|
||||||
|
rlEnd();
|
||||||
|
}
|
||||||
|
if (mask & 4) { rlSetTexture(topTexId); rlBegin(RL_QUADS); rlColor4ub(tint.r, tint.g, tint.b, 255); rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - 0.5f, y + 0.5f, z - 0.5f); rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - 0.5f, y + 0.5f, z + 0.5f); rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + 0.5f, y + 0.5f, z + 0.5f); rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + 0.5f, y + 0.5f, z - 0.5f); rlEnd(); }
|
||||||
|
if (mask & 8) { rlSetTexture(botTexId); rlBegin(RL_QUADS); rlColor4ub(tint.r, tint.g, tint.b, 255); rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - 0.5f, y - 0.5f, z - 0.5f); rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + 0.5f, y - 0.5f, z - 0.5f); rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + 0.5f, y - 0.5f, z + 0.5f); rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - 0.5f, y - 0.5f, z + 0.5f); rlEnd(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Optimized check to see if a block has any exposed faces
|
// Optimized check to see if a block has any exposed faces
|
||||||
bool IsExposed(int x, int ly, int z, Chunk* chunk, int lx, int lz) {
|
bool IsExposed(int x, int ly, int z, Chunk* chunk, int lx, int lz) {
|
||||||
|
|
@ -960,7 +931,7 @@ int main(void)
|
||||||
float updateTimer = 0.0f;
|
float updateTimer = 0.0f;
|
||||||
float downloadProgress = 0.0f;
|
float downloadProgress = 0.0f;
|
||||||
std::string latestVersion = "";
|
std::string latestVersion = "";
|
||||||
std::string localVersion = "v1.9.0"; // Default fallback
|
std::string localVersion = "v2.2.9"; // Default fallback
|
||||||
|
|
||||||
// Read local version
|
// Read local version
|
||||||
std::ifstream vfile("assets/version.txt");
|
std::ifstream vfile("assets/version.txt");
|
||||||
|
|
@ -1595,6 +1566,19 @@ int main(void)
|
||||||
currentZoom += (targetZoom - currentZoom) * 0.05f;
|
currentZoom += (targetZoom - currentZoom) * 0.05f;
|
||||||
camera.zoom = currentZoom;
|
camera.zoom = currentZoom;
|
||||||
|
|
||||||
|
|
||||||
|
// --- GLOBAL INPUTS (Outside gameplay state) ---
|
||||||
|
if (IsKeyPressed(KEY_E) && !isChatting && (currentState == GAMEPLAY || currentState == CRAFTING_GUI)) {
|
||||||
|
if (currentState == CRAFTING_GUI) {
|
||||||
|
currentState = GAMEPLAY;
|
||||||
|
DisableCursor();
|
||||||
|
} else {
|
||||||
|
inventoryOpen = !inventoryOpen;
|
||||||
|
if (inventoryOpen) EnableCursor();
|
||||||
|
else DisableCursor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Gameplay Update
|
// Gameplay Update
|
||||||
if (currentState == GAMEPLAY) {
|
if (currentState == GAMEPLAY) {
|
||||||
gameTime += GetFrameTime();
|
gameTime += GetFrameTime();
|
||||||
|
|
@ -1615,13 +1599,6 @@ int main(void)
|
||||||
if (scroll > 0.0f) activeHotbarSlot = (activeHotbarSlot - 1 + 9) % 9;
|
if (scroll > 0.0f) activeHotbarSlot = (activeHotbarSlot - 1 + 9) % 9;
|
||||||
if (scroll < 0.0f) activeHotbarSlot = (activeHotbarSlot + 1) % 9;
|
if (scroll < 0.0f) activeHotbarSlot = (activeHotbarSlot + 1) % 9;
|
||||||
|
|
||||||
// Toggle inventory
|
|
||||||
if (IsKeyPressed(KEY_E) && !isChatting) {
|
|
||||||
inventoryOpen = !inventoryOpen;
|
|
||||||
if (inventoryOpen) EnableCursor();
|
|
||||||
else DisableCursor();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dynamic Chunk Loading
|
// Dynamic Chunk Loading
|
||||||
int playerCX = (int)floorf(camera3D.position.x / CHUNK_SIZE);
|
int playerCX = (int)floorf(camera3D.position.x / CHUNK_SIZE);
|
||||||
int playerCZ = (int)floorf(camera3D.position.z / CHUNK_SIZE);
|
int playerCZ = (int)floorf(camera3D.position.z / CHUNK_SIZE);
|
||||||
|
|
@ -1654,11 +1631,16 @@ int main(void)
|
||||||
} else if (cmd == "fly off") {
|
} else if (cmd == "fly off") {
|
||||||
isFlying = false;
|
isFlying = false;
|
||||||
chatLog.push_back({ "[Server] Flight disabled", 5.0f });
|
chatLog.push_back({ "[Server] Flight disabled", 5.0f });
|
||||||
|
} else if (cmd == "test") {
|
||||||
|
GiveItems(CRAFTING_TABLE, 1);
|
||||||
|
GiveItems(LOG, 64);
|
||||||
|
chatLog.push_back({ "[Server] Added test items to inventory", 5.0f });
|
||||||
} else if (cmd == "help") {
|
} else if (cmd == "help") {
|
||||||
chatLog.push_back({ "[Server] Commands List:", 8.0f });
|
chatLog.push_back({ "[Server] Commands List:", 8.0f });
|
||||||
chatLog.push_back({ " /help - Shows this list", 8.0f });
|
chatLog.push_back({ " /help - Shows this list", 8.0f });
|
||||||
chatLog.push_back({ " /seed - Shows the world seed", 8.0f });
|
chatLog.push_back({ " /seed - Shows the world seed", 8.0f });
|
||||||
chatLog.push_back({ " /fly [on|off] - Toggle flight mode", 8.0f });
|
chatLog.push_back({ " /fly [on|off] - Toggle flight mode", 8.0f });
|
||||||
|
chatLog.push_back({ " /test - Give basic crafting materials", 8.0f });
|
||||||
} else {
|
} else {
|
||||||
chatLog.push_back({ "[Server] Unknown command: /" + cmd, 5.0f });
|
chatLog.push_back({ "[Server] Unknown command: /" + cmd, 5.0f });
|
||||||
}
|
}
|
||||||
|
|
@ -2000,71 +1982,69 @@ int main(void)
|
||||||
}
|
}
|
||||||
} else if (currentState == UPDATE_FOUND) {
|
} else if (currentState == UPDATE_FOUND) {
|
||||||
DrawRectangle(0, 0, currentWidth, currentHeight, (Color){ 0, 0, 0, 220 });
|
DrawRectangle(0, 0, currentWidth, currentHeight, (Color){ 0, 0, 0, 220 });
|
||||||
int pw = 450, ph = 250;
|
int pw = 450, ph = 180;
|
||||||
Rectangle pBox = { (float)currentWidth/2 - pw/2, (float)currentHeight/2 - ph/2, (float)pw, (float)ph };
|
Rectangle pBox = { (float)currentWidth/2 - pw/2, (float)currentHeight/2 - ph/2, (float)pw, (float)ph };
|
||||||
DrawRectangleRec(pBox, (Color){ 40, 40, 40, 255 });
|
DrawRectangleRec(pBox, (Color){ 40, 40, 40, 255 });
|
||||||
DrawRectangleLinesEx(pBox, 4.0f, GREEN);
|
|
||||||
|
|
||||||
DrawTextEx(customFont, "NEW VERSION AVAILABLE!", (Vector2){ pBox.x + 40, pBox.y + 30 }, 24, 1.0f, GREEN);
|
DrawTextEx(customFont, "NEW VERSION AVAILABLE!", (Vector2){ pBox.x + 40, pBox.y + 30 }, 24, 1.0f, GREEN);
|
||||||
std::string updMsg = latestVersion + " is now ready for download.";
|
std::string updMsg = latestVersion + " is now ready for download.";
|
||||||
DrawTextEx(customFont, updMsg.c_str(), (Vector2){ pBox.x + 40, pBox.y + 70 }, 18, 1.0f, LIGHTGRAY);
|
DrawTextEx(customFont, updMsg.c_str(), (Vector2){ pBox.x + 40, pBox.y + 70 }, 18, 1.0f, LIGHTGRAY);
|
||||||
|
|
||||||
// Update Button
|
// Update Button
|
||||||
Rectangle updBtn = { pBox.x + 40, pBox.y + 120, 370, 40 };
|
Rectangle updBtn = { pBox.x + 40, pBox.y + 110, 370, 40 };
|
||||||
bool isUpdHovered = CheckCollisionPointRec(mousePos, updBtn);
|
bool isUpdHovered = CheckCollisionPointRec(mousePos, updBtn);
|
||||||
DrawRectangleRec(updBtn, isUpdHovered ? GREEN : (Color){ 0, 100, 0, 255 });
|
DrawRectangleRec(updBtn, isUpdHovered ? GREEN : (Color){ 0, 100, 0, 255 });
|
||||||
DrawTextEx(customFont, "UPDATE NOW", (Vector2){ updBtn.x + 100, updBtn.y + 10 }, 20, 1.0f, WHITE);
|
DrawTextEx(customFont, "UPDATE NOW", (Vector2){ updBtn.x + 100, updBtn.y + 10 }, 20, 1.0f, WHITE);
|
||||||
if (isUpdHovered && IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) currentState = DOWNLOADING_UPDATE;
|
if (isUpdHovered && IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) currentState = DOWNLOADING_UPDATE;
|
||||||
|
|
||||||
// Update Notes Button
|
|
||||||
Rectangle noteBtn = { pBox.x + 40, pBox.y + 175, 370, 40 };
|
|
||||||
bool isNoteHovered = CheckCollisionPointRec(mousePos, noteBtn);
|
|
||||||
DrawRectangleRec(noteBtn, isNoteHovered ? DARKGRAY : BLACK);
|
|
||||||
DrawRectangleLinesEx(noteBtn, 2.0f, GRAY);
|
|
||||||
DrawTextEx(customFont, "VIEW UPDATE NOTES", (Vector2){ noteBtn.x + 65, noteBtn.y + 10 }, 20, 1.0f, WHITE);
|
|
||||||
if (isNoteHovered && IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) currentState = UPDATE_NOTES;
|
|
||||||
|
|
||||||
} else if (currentState == DOWNLOADING_UPDATE) {
|
} else if (currentState == DOWNLOADING_UPDATE) {
|
||||||
static bool startedDownload = false;
|
static bool startedDownload = false;
|
||||||
static bool downloadFailed = false;
|
static bool downloadFailed = false;
|
||||||
static float fakeProgress = 0.0f;
|
static bool downloadFinished = false;
|
||||||
|
static float currentProgress = 0.0f;
|
||||||
|
|
||||||
if (!startedDownload) {
|
if (!startedDownload) {
|
||||||
startedDownload = true;
|
startedDownload = true;
|
||||||
// REAL DOWNLOAD ATTEMPT - Platform-aware URLs
|
currentProgress = 0.1f;
|
||||||
|
std::thread([]() {
|
||||||
|
std::string binaryUrl, binaryName;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
std::string binaryUrl = "https://git.linology.tech/michael/MorriCraft/raw/branch/master/build-windows/MorriCraft.exe";
|
binaryUrl = "https://git.linology.tech/michael/MorriCraft/raw/branch/master/build-windows/MorriCraft.exe";
|
||||||
std::string binaryName = "MorriCraft.exe";
|
binaryName = "MorriCraft.exe";
|
||||||
#else
|
#else
|
||||||
std::string binaryUrl = "https://git.linology.tech/michael/MorriCraft/raw/branch/master/build-linux/MorriCraft";
|
binaryUrl = "https://git.linology.tech/michael/MorriCraft/raw/branch/master/build-linux/MorriCraft";
|
||||||
std::string binaryName = "MorriCraft";
|
binaryName = "MorriCraft";
|
||||||
#endif
|
#endif
|
||||||
std::string versionUrl = "https://git.linology.tech/michael/MorriCraft/raw/branch/master/version.txt";
|
std::string versionUrl = "https://git.linology.tech/michael/MorriCraft/raw/branch/master/version.txt";
|
||||||
|
|
||||||
// Download new binary and version file
|
// Download binary
|
||||||
int r1 = system(("curl -L -s -o " + binaryName + ".new \"" + binaryUrl + "\"").c_str());
|
int r1 = system(("curl -L -s -o " + binaryName + ".new \"" + binaryUrl + "\"").c_str());
|
||||||
|
currentProgress = 0.6f;
|
||||||
|
|
||||||
|
// Download version
|
||||||
int r2 = system(("curl -L -s -o version.txt.new \"" + versionUrl + "\"").c_str());
|
int r2 = system(("curl -L -s -o version.txt.new \"" + versionUrl + "\"").c_str());
|
||||||
|
currentProgress = 0.8f;
|
||||||
|
|
||||||
if (r1 == 0 && r2 == 0) {
|
if (r1 == 0 && r2 == 0) {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// Windows: rename old, move new into place
|
|
||||||
system(("rename " + binaryName + " " + binaryName + ".old").c_str());
|
system(("rename " + binaryName + " " + binaryName + ".old").c_str());
|
||||||
system(("rename " + binaryName + ".new " + binaryName).c_str());
|
system(("rename " + binaryName + ".new " + binaryName).c_str());
|
||||||
system("rename version.txt version.txt.old");
|
system("rename version.txt version.txt.old");
|
||||||
system("rename version.txt.new version.txt");
|
system("rename version.txt.new version.txt");
|
||||||
system("copy version.txt assets\\version.txt >nul 2>&1");
|
system("copy version.txt assets\\version.txt >nul 2>&1");
|
||||||
#else
|
#else
|
||||||
// Linux: chmod, move
|
|
||||||
system(("chmod +x " + binaryName + ".new").c_str());
|
system(("chmod +x " + binaryName + ".new").c_str());
|
||||||
system(("mv " + binaryName + " " + binaryName + ".old 2>/dev/null").c_str());
|
system(("mv " + binaryName + " " + binaryName + ".old 2>/dev/null").c_str());
|
||||||
system(("mv " + binaryName + ".new " + binaryName).c_str());
|
system(("mv " + binaryName + ".new " + binaryName).c_str());
|
||||||
system("mv version.txt.new version.txt");
|
system("mv version.txt.new version.txt");
|
||||||
system("cp version.txt assets/version.txt 2>/dev/null");
|
system("cp version.txt assets/version.txt 2>/dev/null");
|
||||||
#endif
|
#endif
|
||||||
fakeProgress = 1.0f;
|
currentProgress = 1.0f;
|
||||||
|
downloadFinished = true;
|
||||||
} else {
|
} else {
|
||||||
downloadFailed = true;
|
downloadFailed = true;
|
||||||
}
|
}
|
||||||
|
}).detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawRectangle(0, 0, currentWidth, currentHeight, (Color){ 20, 20, 20, 255 });
|
DrawRectangle(0, 0, currentWidth, currentHeight, (Color){ 20, 20, 20, 255 });
|
||||||
|
|
@ -2072,35 +2052,33 @@ int main(void)
|
||||||
DrawTextEx(customFont, "DOWNLOAD FAILED! Check internet connection.", (Vector2){ (float)currentWidth/2 - 250, (float)currentHeight/2 - 40 }, 24, 1.0f, RED);
|
DrawTextEx(customFont, "DOWNLOAD FAILED! Check internet connection.", (Vector2){ (float)currentWidth/2 - 250, (float)currentHeight/2 - 40 }, 24, 1.0f, RED);
|
||||||
Rectangle backBtn = { (float)currentWidth/2 - 100, (float)currentHeight/2 + 20, 200, 40 };
|
Rectangle backBtn = { (float)currentWidth/2 - 100, (float)currentHeight/2 + 20, 200, 40 };
|
||||||
if (CheckCollisionPointRec(mousePos, backBtn) && IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) {
|
if (CheckCollisionPointRec(mousePos, backBtn) && IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) {
|
||||||
currentState = MAIN_MENU;
|
currentState = MAIN_MENU; startedDownload = false; downloadFailed = false;
|
||||||
startedDownload = false;
|
|
||||||
downloadFailed = false;
|
|
||||||
}
|
}
|
||||||
DrawRectangleRec(backBtn, DARKGRAY);
|
DrawRectangleRec(backBtn, DARKGRAY);
|
||||||
DrawTextEx(customFont, "BACK", (Vector2){ backBtn.x + 70, backBtn.y + 10 }, 20, 1.0f, WHITE);
|
DrawTextEx(customFont, "BACK", (Vector2){ backBtn.x + 70, backBtn.y + 10 }, 20, 1.0f, WHITE);
|
||||||
} else {
|
} else {
|
||||||
fakeProgress += 0.001f; // Slow visual for user
|
DrawTextEx(customFont, "DOWNLOADING & REPLACING SYSTEM FILES...", (Vector2){ (float)currentWidth/2 - 250, (float)currentHeight/2 - 60 }, 24, 1.0f, YELLOW);
|
||||||
if (fakeProgress > 1.0f) fakeProgress = 1.0f;
|
int bw = 500, bh = 35;
|
||||||
|
Rectangle barBg = { (float)currentWidth/2 - bw/2, (float)currentHeight/2 - bh/2, (float)bw, (float)bh };
|
||||||
|
DrawRectangleRec(barBg, BLACK);
|
||||||
|
DrawRectangle(barBg.x, barBg.y, (int)(bw * currentProgress), bh, GREEN);
|
||||||
|
DrawRectangleLinesEx(barBg, 2.0f, GRAY);
|
||||||
|
DrawTextEx(customFont, TextFormat("%i%%", (int)(currentProgress * 100)), (Vector2){ barBg.x + bw + 15, barBg.y + 5 }, 20, 1.0f, WHITE);
|
||||||
|
|
||||||
DrawTextEx(customFont, "DOWNLOADING & REPLACING SYSTEM FILES...", (Vector2){ (float)currentWidth/2 - 250, (float)currentHeight/2 - 40 }, 24, 1.0f, YELLOW);
|
if (downloadFinished) {
|
||||||
int bw = 450, bh = 30;
|
|
||||||
DrawRectangle(currentWidth/2 - bw/2, currentHeight/2, bw, bh, BLACK);
|
|
||||||
DrawRectangle(currentWidth/2 - bw/2, currentHeight/2, (int)(bw * (fakeProgress > 0.9f ? 0.9f : fakeProgress)), bh, GREEN);
|
|
||||||
|
|
||||||
if (fakeProgress >= 1.0f) {
|
|
||||||
DrawRectangle(0, 0, currentWidth, currentHeight, (Color){ 0, 0, 0, 230 });
|
DrawRectangle(0, 0, currentWidth, currentHeight, (Color){ 0, 0, 0, 230 });
|
||||||
int pw = 450, ph = 200;
|
int pw = 500, ph = 220;
|
||||||
Rectangle pBox = { (float)currentWidth/2 - pw/2, (float)currentHeight/2 - ph/2, (float)pw, (float)ph };
|
Rectangle pBox = { (float)currentWidth/2 - pw/2, (float)currentHeight/2 - ph/2, (float)pw, (float)ph };
|
||||||
DrawRectangleRec(pBox, (Color){ 30, 30, 30, 255 });
|
DrawRectangleRec(pBox, (Color){ 30, 30, 30, 255 });
|
||||||
DrawRectangleLinesEx(pBox, 4.0f, GREEN);
|
DrawRectangleLinesEx(pBox, 4.0f, GREEN);
|
||||||
|
|
||||||
DrawTextEx(customFont, "UPDATE SUCCESSFUL!", (Vector2){ pBox.x + 60, pBox.y + 40 }, 24, 1.0f, GREEN);
|
DrawTextEx(customFont, "UPDATE SUCCESSFUL!", (Vector2){ pBox.x + 80, pBox.y + 40 }, 28, 1.0f, GREEN);
|
||||||
DrawTextEx(customFont, "PLEASE RESTART THE CLIENT.", (Vector2){ pBox.x + 60, pBox.y + 80 }, 20, 1.0f, WHITE);
|
DrawTextEx(customFont, "PLEASE RESTART THE CLIENT TO APPLY.", (Vector2){ pBox.x + 60, pBox.y + 90 }, 20, 1.0f, WHITE);
|
||||||
|
|
||||||
Rectangle exitBtn = { pBox.x + pw/2 - 75, pBox.y + 130, 150, 40 };
|
Rectangle exitBtn = { pBox.x + pw/2 - 90, pBox.y + 145, 180, 45 };
|
||||||
if (CheckCollisionPointRec(mousePos, exitBtn) && IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) exit(0);
|
if (CheckCollisionPointRec(mousePos, exitBtn) && IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) exit(0);
|
||||||
DrawRectangleRec(exitBtn, MAROON);
|
DrawRectangleRec(exitBtn, MAROON);
|
||||||
DrawTextEx(customFont, "EXIT GAME", (Vector2){ exitBtn.x + 30, exitBtn.y + 10 }, 20, 1.0f, WHITE);
|
DrawTextEx(customFont, "EXIT GAME", (Vector2){ exitBtn.x + 40, exitBtn.y + 12 }, 20, 1.0f, WHITE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (currentState == SKIN_EDITOR) {
|
} else if (currentState == SKIN_EDITOR) {
|
||||||
|
|
@ -2337,8 +2315,8 @@ int main(void)
|
||||||
DrawTexturePro(titleTexture, sourceRec, destRec, origin, 0.0f, WHITE);
|
DrawTexturePro(titleTexture, sourceRec, destRec, origin, 0.0f, WHITE);
|
||||||
EndMode2D();
|
EndMode2D();
|
||||||
|
|
||||||
// Show Version Number (v2.2.7) in Red
|
// Show Version Number (v2.2.9) in Red
|
||||||
DrawTextEx(customFont, "v2.2.7", (Vector2){ (float)currentWidth - 140, (float)currentHeight - 40 }, 22, 1.0f, RED);
|
DrawTextEx(customFont, "v2.2.9", (Vector2){ (float)currentWidth - 140, (float)currentHeight - 40 }, 22, 1.0f, RED);
|
||||||
|
|
||||||
// --- PLAYER NAME POPUP (IF MISSING) ---
|
// --- PLAYER NAME POPUP (IF MISSING) ---
|
||||||
if (playerName == "") {
|
if (playerName == "") {
|
||||||
|
|
@ -2566,30 +2544,30 @@ int main(void)
|
||||||
if (showDeleteConfirm) {
|
if (showDeleteConfirm) {
|
||||||
DrawRectangle(0, 0, currentWidth, currentHeight, (Color){ 0, 0, 0, 200 });
|
DrawRectangle(0, 0, currentWidth, currentHeight, (Color){ 0, 0, 0, 200 });
|
||||||
|
|
||||||
int confWidth = 400;
|
int confWidth = 550;
|
||||||
int confHeight = 200;
|
int confHeight = 240;
|
||||||
int confX = (currentWidth / 2) - (confWidth / 2);
|
int confX = (currentWidth / 2) - (confWidth / 2);
|
||||||
int confY = (currentHeight / 2) - (confHeight / 2);
|
int confY = (currentHeight / 2) - (confHeight / 2);
|
||||||
|
|
||||||
DrawRectangle(confX, confY, confWidth, confHeight, (Color){ 50, 20, 20, 255 });
|
DrawRectangle(confX, confY, confWidth, confHeight, (Color){ 50, 20, 20, 255 });
|
||||||
DrawRectangleLinesEx((Rectangle){ (float)confX, (float)confY, (float)confWidth, (float)confHeight }, 4.0f, RED);
|
DrawRectangleLinesEx((Rectangle){ (float)confX, (float)confY, (float)confWidth, (float)confHeight }, 4.0f, RED);
|
||||||
|
|
||||||
Vector2 warnSize = MeasureTextEx(customFont, "Delete World?", 24, 1.0f);
|
Vector2 warnSize = MeasureTextEx(customFont, "Delete World?", 28, 1.0f);
|
||||||
DrawTextEx(customFont, "Delete World?", (Vector2){ confX + (confWidth/2) - (warnSize.x/2), confY + 30 }, 24, 1.0f, WHITE);
|
DrawTextEx(customFont, "Delete World?", (Vector2){ confX + (confWidth/2) - (warnSize.x/2), confY + 30 }, 28, 1.0f, WHITE);
|
||||||
|
|
||||||
std::string warnText = "Delete '" + deletingWorldName + "'?";
|
std::string warnText = "Are you sure you want to delete '" + deletingWorldName + "'?";
|
||||||
Vector2 nameSize = MeasureTextEx(customFont, warnText.c_str(), 20, 1.0f);
|
Vector2 nameSize = MeasureTextEx(customFont, warnText.c_str(), 22, 1.0f);
|
||||||
DrawTextEx(customFont, warnText.c_str(), (Vector2){ confX + (confWidth/2) - (nameSize.x/2), confY + 70 }, 20, 1.0f, LIGHTGRAY);
|
DrawTextEx(customFont, warnText.c_str(), (Vector2){ confX + (confWidth/2) - (nameSize.x/2), confY + 85 }, 22, 1.0f, LIGHTGRAY);
|
||||||
|
|
||||||
// Yes Button
|
// Yes Button
|
||||||
Rectangle yesBtn = { (float)confX + 50, (float)confY + 130, 120, 40 };
|
Rectangle yesBtn = { (float)confX + 80, (float)confY + 150, 140, 40 };
|
||||||
bool isYesHovered = CheckCollisionPointRec(mousePos, yesBtn);
|
bool isYesHovered = CheckCollisionPointRec(mousePos, yesBtn);
|
||||||
DrawRectangleRec(yesBtn, isYesHovered ? RED : MAROON);
|
DrawRectangleRec(yesBtn, isYesHovered ? RED : MAROON);
|
||||||
DrawRectangleLinesEx(yesBtn, 2.0f, isYesHovered ? WHITE : GRAY);
|
DrawRectangleLinesEx(yesBtn, 2.0f, isYesHovered ? WHITE : GRAY);
|
||||||
DrawTextEx(customFont, "YES", (Vector2){ yesBtn.x + 40, yesBtn.y + 10 }, 20, 1.0f, WHITE);
|
DrawTextEx(customFont, "YES, DELETE", (Vector2){ yesBtn.x + 10, yesBtn.y + 10 }, 20, 1.0f, WHITE);
|
||||||
|
|
||||||
// No Button
|
// No Button
|
||||||
Rectangle noBtn = { (float)confX + confWidth - 170, (float)confY + 130, 120, 40 };
|
Rectangle noBtn = { (float)confX + confWidth - 220, (float)confY + 150, 140, 40 };
|
||||||
bool isNoHovered = CheckCollisionPointRec(mousePos, noBtn);
|
bool isNoHovered = CheckCollisionPointRec(mousePos, noBtn);
|
||||||
DrawRectangleRec(noBtn, isNoHovered ? (Color){ 100, 100, 100, 255 } : DARKGRAY);
|
DrawRectangleRec(noBtn, isNoHovered ? (Color){ 100, 100, 100, 255 } : DARKGRAY);
|
||||||
DrawRectangleLinesEx(noBtn, 2.0f, isNoHovered ? WHITE : GRAY);
|
DrawRectangleLinesEx(noBtn, 2.0f, isNoHovered ? WHITE : GRAY);
|
||||||
|
|
@ -2892,11 +2870,14 @@ int main(void)
|
||||||
std::vector<Chunk*> visibleChunks;
|
std::vector<Chunk*> visibleChunks;
|
||||||
for (int cx = playerCX - RENDER_DISTANCE; cx <= playerCX + RENDER_DISTANCE; cx++) {
|
for (int cx = playerCX - RENDER_DISTANCE; cx <= playerCX + RENDER_DISTANCE; cx++) {
|
||||||
for (int cz = playerCZ - RENDER_DISTANCE; cz <= playerCZ + RENDER_DISTANCE; cz++) {
|
for (int cz = playerCZ - RENDER_DISTANCE; cz <= playerCZ + RENDER_DISTANCE; cz++) {
|
||||||
// FRUSTUM CULLING
|
// OPTIMIZED FRUSTUM CULLING (Bug #1 Fix: Don't cull the player's current chunk)
|
||||||
Vector3 chunkCenter = { (float)(cx * CHUNK_SIZE + 8), 32.0f, (float)(cz * CHUNK_SIZE + 8) };
|
if (abs(cx - playerCX) > 1 || abs(cz - playerCZ) > 1) {
|
||||||
|
Vector3 chunkCenter = { (float)(cx * CHUNK_SIZE + 16), 64.0f, (float)(cz * CHUNK_SIZE + 16) };
|
||||||
|
float distSqr = Vector3LengthSqr(Vector3Subtract(chunkCenter, camera3D.position));
|
||||||
|
if (distSqr > 160.0f * 160.0f) continue;
|
||||||
Vector3 toChunk = Vector3Normalize(Vector3Subtract(chunkCenter, camera3D.position));
|
Vector3 toChunk = Vector3Normalize(Vector3Subtract(chunkCenter, camera3D.position));
|
||||||
if (Vector3Length(Vector3Subtract(chunkCenter, camera3D.position)) > 24.0f &&
|
if (distSqr > 32.0f * 32.0f && Vector3DotProduct(toChunk, camForward) < -0.4f) continue;
|
||||||
Vector3DotProduct(toChunk, camForward) < -0.3f) continue;
|
}
|
||||||
|
|
||||||
auto it = worldChunks.find({cx, cz});
|
auto it = worldChunks.find({cx, cz});
|
||||||
if (it == worldChunks.end()) continue;
|
if (it == worldChunks.end()) continue;
|
||||||
|
|
@ -2911,20 +2892,20 @@ int main(void)
|
||||||
for (int renderType = 1; renderType <= 13; renderType++) {
|
for (int renderType = 1; renderType <= 13; renderType++) {
|
||||||
if (renderType == GRASS) {
|
if (renderType == GRASS) {
|
||||||
for (Chunk* chunk : visibleChunks) {
|
for (Chunk* chunk : visibleChunks) {
|
||||||
for (auto& pos : chunk->renderLists[GRASS]) {
|
for (auto& data : chunk->renderLists[GRASS]) {
|
||||||
DrawGrassBlock(pos, blockTextures[GRASS].id, grassTopTexture.id, blockTextures[DIRT].id, blockTint);
|
DrawGrassBlock((Vector3){data.x, data.y, data.z}, blockTextures[GRASS].id, grassTopTexture.id, blockTextures[DIRT].id, blockTint, data.faces);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (renderType == LOG) {
|
} else if (renderType == LOG) {
|
||||||
for (Chunk* chunk : visibleChunks) {
|
for (Chunk* chunk : visibleChunks) {
|
||||||
for (auto& pos : chunk->renderLists[LOG]) {
|
for (auto& data : chunk->renderLists[LOG]) {
|
||||||
DrawLog(pos, logSideTexture.id, logTopTexture.id, blockTint);
|
DrawLog((Vector3){data.x, data.y, data.z}, logSideTexture.id, logTopTexture.id, blockTint, data.faces);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (renderType == CRAFTING_TABLE) {
|
} else if (renderType == CRAFTING_TABLE) {
|
||||||
for (Chunk* chunk : visibleChunks) {
|
for (Chunk* chunk : visibleChunks) {
|
||||||
for (auto& pos : chunk->renderLists[CRAFTING_TABLE]) {
|
for (auto& data : chunk->renderLists[CRAFTING_TABLE]) {
|
||||||
DrawCraftingTable(pos, craftingSideTexture.id, craftingTopTexture.id, blockTextures[DIRT].id, blockTint);
|
DrawCraftingTable((Vector3){data.x, data.y, data.z}, craftingSideTexture.id, craftingTopTexture.id, blockTextures[DIRT].id, blockTint, data.faces);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -2936,8 +2917,8 @@ int main(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Chunk* chunk : visibleChunks) {
|
for (Chunk* chunk : visibleChunks) {
|
||||||
for (auto& pos : chunk->renderLists[renderType]) {
|
for (auto& data : chunk->renderLists[renderType]) {
|
||||||
DrawCubeVertices(pos.x, pos.y, pos.z, 1.0f, 1.0f, 1.0f);
|
DrawCubeVertices(data.x, data.y, data.z, 1.0f, 1.0f, 1.0f, data.faces);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rlEnd();
|
rlEnd();
|
||||||
|
|
@ -2990,19 +2971,27 @@ int main(void)
|
||||||
handPos = Vector3Add(handPos, Vector3Scale(upVM, -0.25f - swingVal * 0.15f));
|
handPos = Vector3Add(handPos, Vector3Scale(upVM, -0.25f - swingVal * 0.15f));
|
||||||
|
|
||||||
// Draw Arm (rotated cube)
|
// Draw Arm (rotated cube)
|
||||||
// We use rlgl to rotate it to point roughly forward
|
|
||||||
rlPushMatrix();
|
rlPushMatrix();
|
||||||
rlTranslatef(handPos.x, handPos.y, handPos.z);
|
rlTranslatef(handPos.x, handPos.y, handPos.z);
|
||||||
rlRotatef(camYaw * 180.0f/PI, 0, 1, 0); // Yaw with camera
|
rlRotatef(camYaw * 180.0f/PI, 0, 1, 0);
|
||||||
rlRotatef(-20.0f - swingVal * 30.0f, 1, 0, 0); // Slight slant
|
rlRotatef(camPitch * 180.0f/PI - 15.0f - swingVal * 20.0f, 1, 0, 0); // Point forward + swing
|
||||||
DrawCube((Vector3){0,0,0}, 0.08f, 0.1f, 0.35f, (Color){220, 180, 150, 255});
|
DrawCube((Vector3){0,0,0}, 0.1f, 0.12f, 0.4f, (Color){220, 180, 150, 255});
|
||||||
rlPopMatrix();
|
rlPopMatrix();
|
||||||
|
|
||||||
// Draw Held Item
|
// Draw Held Item - Fixed pivot and attachment (Bug #3)
|
||||||
int heldBT = hotbar[activeHotbarSlot].blockType;
|
int heldBT = hotbar[activeHotbarSlot].blockType;
|
||||||
if (heldBT != AIR) {
|
if (heldBT != AIR) {
|
||||||
Vector3 itemPos = Vector3Add(handPos, Vector3Scale(forwardVM, 0.12f));
|
// Calculate position at the end of the arm
|
||||||
itemPos = Vector3Add(itemPos, Vector3Scale(upVM, 0.12f));
|
// The arm is rotated by camPitch - 15.0f - swingVal * 20.0f
|
||||||
|
float armPitch = (camPitch * 180.0f/PI - 15.0f - swingVal * 20.0f) * PI/180.0f;
|
||||||
|
Vector3 armForward = {
|
||||||
|
forwardVM.x * cosf(-armPitch) - forwardVM.y * sinf(-armPitch),
|
||||||
|
forwardVM.x * sinf(-armPitch) + forwardVM.y * cosf(-armPitch),
|
||||||
|
forwardVM.z
|
||||||
|
}; // This is a simplification, but let's use the handPos + offset
|
||||||
|
|
||||||
|
Vector3 itemPos = Vector3Add(handPos, Vector3Scale(forwardVM, 0.25f));
|
||||||
|
itemPos = Vector3Add(itemPos, Vector3Scale(upVM, 0.05f));
|
||||||
itemPos = Vector3Add(itemPos, Vector3Scale(rightVM, -0.05f));
|
itemPos = Vector3Add(itemPos, Vector3Scale(rightVM, -0.05f));
|
||||||
|
|
||||||
Texture2D itemTex = (heldBT == GRASS) ? grassTopTexture : (heldBT == CRAFTING_TABLE ? craftingSideTexture : blockTextures[heldBT]);
|
Texture2D itemTex = (heldBT == GRASS) ? grassTopTexture : (heldBT == CRAFTING_TABLE ? craftingSideTexture : blockTextures[heldBT]);
|
||||||
|
|
@ -3014,16 +3003,18 @@ int main(void)
|
||||||
rlTranslatef(itemPos.x, itemPos.y, itemPos.z);
|
rlTranslatef(itemPos.x, itemPos.y, itemPos.z);
|
||||||
rlRotatef(camYaw * 180.0f/PI + 45.0f, 0, 1, 0);
|
rlRotatef(camYaw * 180.0f/PI + 45.0f, 0, 1, 0);
|
||||||
rlRotatef(20.0f, 1, 0, 1);
|
rlRotatef(20.0f, 1, 0, 1);
|
||||||
DrawCubeVertices(0,0,0, 0.12f, 0.12f, 0.12f);
|
DrawCubeVertices(0,0,0, 0.12f, 0.12f, 0.12f, 63);
|
||||||
rlPopMatrix();
|
rlPopMatrix();
|
||||||
rlSetTexture(0);
|
rlSetTexture(0);
|
||||||
} else {
|
} else {
|
||||||
// Item (Stick/Axe) as Billboard - Scaled larger for better visibility
|
// Item (Stick/Axe) as Billboard
|
||||||
DrawBillboard(camera3D, itemTex, itemPos, 0.35f, WHITE);
|
Rectangle src = { 0, 0, (float)itemTex.width, (float)itemTex.height };
|
||||||
|
Vector2 itemSize = { 0.45f, 0.45f };
|
||||||
|
// Pivot at bottom-left corner (Bug #3 fix)
|
||||||
|
// In DrawBillboardPro, origin (0,0) is center. Bottom-left is (-w/2, -h/2).
|
||||||
|
Vector2 pivot = { -itemSize.x/2.0f, -itemSize.y/2.0f };
|
||||||
|
DrawBillboardPro(camera3D, itemTex, src, itemPos, camera3D.up, itemSize, pivot, -45.0f + swingVal * 40.0f, WHITE);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// Fallback
|
|
||||||
DrawCube(itemPos, 0.1f, 0.1f, 0.1f, RED);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rlPopMatrix();
|
rlPopMatrix();
|
||||||
|
|
@ -3173,7 +3164,30 @@ int main(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hov && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) {
|
if (hov && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) {
|
||||||
if (IsKeyDown(KEY_LEFT_SHIFT) && !isResultSlot && slot.blockType != AIR) {
|
if (IsKeyDown(KEY_LEFT_SHIFT) && isResultSlot && slot.blockType != AIR) {
|
||||||
|
// Take everything possible from the result box
|
||||||
|
while (slot.blockType != AIR) {
|
||||||
|
GiveItems(slot.blockType, slot.count);
|
||||||
|
// Decrease ingredients
|
||||||
|
if (isTableResult) {
|
||||||
|
for(int i=0; i<9; i++) {
|
||||||
|
if (tableSlots[i].count > 0) tableSlots[i].count--;
|
||||||
|
if (tableSlots[i].count == 0) tableSlots[i].blockType = AIR;
|
||||||
|
}
|
||||||
|
UpdateTableCrafting();
|
||||||
|
slot = tableResult; // Refresh from local reference
|
||||||
|
} else {
|
||||||
|
for(int i=0; i<4; i++) {
|
||||||
|
if (craftingSlots[i].count > 0) craftingSlots[i].count--;
|
||||||
|
if (craftingSlots[i].count == 0) craftingSlots[i].blockType = AIR;
|
||||||
|
}
|
||||||
|
UpdateCrafting();
|
||||||
|
slot = craftingResult;
|
||||||
|
}
|
||||||
|
// Safety: if we can't craft anymore, break
|
||||||
|
if (slot.blockType == AIR) break;
|
||||||
|
}
|
||||||
|
} else if (IsKeyDown(KEY_LEFT_SHIFT) && !isResultSlot && slot.blockType != AIR) {
|
||||||
// Pick up entire stack into hand immediately
|
// Pick up entire stack into hand immediately
|
||||||
if (mouseHeldItem.blockType == AIR) {
|
if (mouseHeldItem.blockType == AIR) {
|
||||||
mouseHeldItem = slot;
|
mouseHeldItem = slot;
|
||||||
|
|
@ -3313,7 +3327,7 @@ int main(void)
|
||||||
// Close hint
|
// Close hint
|
||||||
DrawTextEx(customFont, "Press E or ESC to close", (Vector2){ (float)(invPanelX + 12), (float)(invPanelY + invPanelH - 22) }, 14, 1.0f, (Color){160, 160, 160, 200});
|
DrawTextEx(customFont, "Press E or ESC to close", (Vector2){ (float)(invPanelX + 12), (float)(invPanelY + invPanelH - 22) }, 14, 1.0f, (Color){160, 160, 160, 200});
|
||||||
|
|
||||||
if (IsKeyPressed(KEY_ESCAPE) || IsKeyPressed(KEY_E)) {
|
if (IsKeyPressed(KEY_ESCAPE)) {
|
||||||
inventoryOpen = false;
|
inventoryOpen = false;
|
||||||
DisableCursor();
|
DisableCursor();
|
||||||
}
|
}
|
||||||
|
|
@ -3343,7 +3357,7 @@ int main(void)
|
||||||
|
|
||||||
drawInvGrid(guiX + 16, tableStartY + 3*(invSlotSize+invGap) + 40);
|
drawInvGrid(guiX + 16, tableStartY + 3*(invSlotSize+invGap) + 40);
|
||||||
|
|
||||||
if (IsKeyPressed(KEY_ESCAPE) || IsKeyPressed(KEY_E)) {
|
if (IsKeyPressed(KEY_ESCAPE)) {
|
||||||
currentState = GAMEPLAY;
|
currentState = GAMEPLAY;
|
||||||
DisableCursor();
|
DisableCursor();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
v2.2.7
|
v2.2.9
|
||||||
|
|
|
||||||