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 |
570
src/main.cpp
|
|
@ -20,7 +20,7 @@
|
|||
#define PI 3.1415926535f
|
||||
#endif
|
||||
#define CHUNK_HEIGHT 128
|
||||
#define RENDER_DISTANCE 4
|
||||
#define RENDER_DISTANCE 8
|
||||
|
||||
enum BlockType {
|
||||
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 {
|
||||
int blocks[CHUNK_SIZE][CHUNK_HEIGHT][CHUNK_SIZE];
|
||||
int maxY = 0;
|
||||
bool generated = false;
|
||||
bool modified = false;
|
||||
bool dirty = true;
|
||||
std::vector<Vector3> renderLists[32];
|
||||
std::vector<BlockRenderData> renderLists[32];
|
||||
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 };
|
||||
|
||||
// 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 GenerateChunk(int cx, int cz);
|
||||
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
|
||||
}
|
||||
|
||||
// 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
|
||||
static float camYaw = 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
|
||||
}
|
||||
|
||||
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) {
|
||||
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 itNP = worldChunks.find({cx+1, cz});
|
||||
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;
|
||||
auto itNM = worldChunks.find({cx-1, cz}); Chunk* nxM = (itNM != worldChunks.end()) ? itNM->second : nullptr;
|
||||
auto itNP = worldChunks.find({cx+1, cz}); 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 worldZ = cz * CHUNK_SIZE;
|
||||
|
|
@ -302,8 +329,9 @@ void RebuildChunkRenderList(Chunk* chunk, int cx, int cz) {
|
|||
int bt = chunk->blocks[lx][ly][lz];
|
||||
if (bt == AIR) continue;
|
||||
|
||||
if (IsExposedOptimized(lx, ly, lz, chunk, nxM, nxP, nzM, nzP)) {
|
||||
chunk->renderLists[bt].push_back((Vector3){(float)(worldX+lx), (float)ly, (float)(worldZ+lz)});
|
||||
unsigned char faces = GetExposedFaces(lx, ly, lz, chunk, nxM, nxP, nzM, nzP);
|
||||
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)) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -623,10 +655,10 @@ void GenerateChunk(int cx, int cz) {
|
|||
}
|
||||
|
||||
newChunk->generated = true;
|
||||
newChunk->modified = true; // Newly generated, so we should save it
|
||||
newChunk->modified = true;
|
||||
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} };
|
||||
for (auto& nPos : neighbors) {
|
||||
auto it = worldChunks.find(nPos);
|
||||
|
|
@ -708,163 +740,102 @@ void DrawTexturedCube(Vector3 position, float width, float height, float length,
|
|||
// Draws a grass block with correct per-face textures:
|
||||
// top=green grass, sides=dirt+grass stripe, bottom=pure dirt.
|
||||
// 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) {
|
||||
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) {
|
||||
void DrawCubeVertices(float x, float y, float z, float w, float h, float l, unsigned char mask) {
|
||||
float hw = w/2.0f; float hh = h/2.0f; float hl = l/2.0f;
|
||||
// Front
|
||||
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, 0.0f); rlVertex3f(x + hw, y + hh, z + hl);
|
||||
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - hw, y + hh, z + hl);
|
||||
// Back
|
||||
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(0.0f, 0.0f); rlVertex3f(x + hw, y + hh, z - hl);
|
||||
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + hw, y - hh, z - hl);
|
||||
// Top
|
||||
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(1.0f, 0.0f); rlVertex3f(x + hw, y + hh, z + hl);
|
||||
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + hw, y + hh, z - hl);
|
||||
// Bottom
|
||||
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, 0.0f); rlVertex3f(x + hw, y - hh, z + hl);
|
||||
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - hw, y - hh, z + hl);
|
||||
// Right
|
||||
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(0.0f, 0.0f); rlVertex3f(x + hw, y + hh, z + hl);
|
||||
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + hw, y - hh, z + hl);
|
||||
// Left
|
||||
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, 0.0f); rlVertex3f(x - hw, y + hh, z + hl);
|
||||
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - hw, y + hh, z - hl);
|
||||
if (mask & 1) { // Front (+Z)
|
||||
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, 0.0f); rlVertex3f(x + hw, y + hh, z + hl);
|
||||
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - hw, y + hh, z + hl);
|
||||
}
|
||||
if (mask & 2) { // Back (-Z)
|
||||
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(0.0f, 0.0f); rlVertex3f(x + hw, y + hh, z - hl);
|
||||
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + hw, y - hh, z - hl);
|
||||
}
|
||||
if (mask & 4) { // Top (+Y)
|
||||
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(1.0f, 0.0f); rlVertex3f(x + hw, y + hh, z + hl);
|
||||
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + hw, y + hh, z - hl);
|
||||
}
|
||||
if (mask & 8) { // Bottom (-Y)
|
||||
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, 0.0f); rlVertex3f(x + hw, y - hh, z + hl);
|
||||
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - hw, y - hh, z + hl);
|
||||
}
|
||||
if (mask & 16) { // Right (+X)
|
||||
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(0.0f, 0.0f); rlVertex3f(x + hw, y + hh, z + hl);
|
||||
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + hw, y - hh, z + hl);
|
||||
}
|
||||
if (mask & 32) { // Left (-X)
|
||||
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, 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
|
||||
bool IsExposed(int x, int ly, int z, Chunk* chunk, int lx, int lz) {
|
||||
// Local check (inside same chunk)
|
||||
|
|
@ -960,7 +931,7 @@ int main(void)
|
|||
float updateTimer = 0.0f;
|
||||
float downloadProgress = 0.0f;
|
||||
std::string latestVersion = "";
|
||||
std::string localVersion = "v1.9.0"; // Default fallback
|
||||
std::string localVersion = "v2.2.9"; // Default fallback
|
||||
|
||||
// Read local version
|
||||
std::ifstream vfile("assets/version.txt");
|
||||
|
|
@ -1595,6 +1566,19 @@ int main(void)
|
|||
currentZoom += (targetZoom - currentZoom) * 0.05f;
|
||||
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
|
||||
if (currentState == GAMEPLAY) {
|
||||
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;
|
||||
|
||||
// Toggle inventory
|
||||
if (IsKeyPressed(KEY_E) && !isChatting) {
|
||||
inventoryOpen = !inventoryOpen;
|
||||
if (inventoryOpen) EnableCursor();
|
||||
else DisableCursor();
|
||||
}
|
||||
|
||||
// Dynamic Chunk Loading
|
||||
int playerCX = (int)floorf(camera3D.position.x / CHUNK_SIZE);
|
||||
int playerCZ = (int)floorf(camera3D.position.z / CHUNK_SIZE);
|
||||
|
|
@ -1654,11 +1631,16 @@ int main(void)
|
|||
} else if (cmd == "fly off") {
|
||||
isFlying = false;
|
||||
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") {
|
||||
chatLog.push_back({ "[Server] Commands 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({ " /fly [on|off] - Toggle flight mode", 8.0f });
|
||||
chatLog.push_back({ " /test - Give basic crafting materials", 8.0f });
|
||||
} else {
|
||||
chatLog.push_back({ "[Server] Unknown command: /" + cmd, 5.0f });
|
||||
}
|
||||
|
|
@ -2000,71 +1982,69 @@ int main(void)
|
|||
}
|
||||
} else if (currentState == UPDATE_FOUND) {
|
||||
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 };
|
||||
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);
|
||||
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);
|
||||
|
||||
// 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);
|
||||
DrawRectangleRec(updBtn, isUpdHovered ? GREEN : (Color){ 0, 100, 0, 255 });
|
||||
DrawTextEx(customFont, "UPDATE NOW", (Vector2){ updBtn.x + 100, updBtn.y + 10 }, 20, 1.0f, WHITE);
|
||||
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) {
|
||||
static bool startedDownload = false;
|
||||
static bool downloadFailed = false;
|
||||
static float fakeProgress = 0.0f;
|
||||
static bool downloadFinished = false;
|
||||
static float currentProgress = 0.0f;
|
||||
|
||||
if (!startedDownload) {
|
||||
startedDownload = true;
|
||||
// REAL DOWNLOAD ATTEMPT - Platform-aware URLs
|
||||
#ifdef _WIN32
|
||||
std::string binaryUrl = "https://git.linology.tech/michael/MorriCraft/raw/branch/master/build-windows/MorriCraft.exe";
|
||||
std::string binaryName = "MorriCraft.exe";
|
||||
#else
|
||||
std::string binaryUrl = "https://git.linology.tech/michael/MorriCraft/raw/branch/master/build-linux/MorriCraft";
|
||||
std::string binaryName = "MorriCraft";
|
||||
#endif
|
||||
std::string versionUrl = "https://git.linology.tech/michael/MorriCraft/raw/branch/master/version.txt";
|
||||
|
||||
// Download new binary and version file
|
||||
int r1 = system(("curl -L -s -o " + binaryName + ".new \"" + binaryUrl + "\"").c_str());
|
||||
int r2 = system(("curl -L -s -o version.txt.new \"" + versionUrl + "\"").c_str());
|
||||
|
||||
if (r1 == 0 && r2 == 0) {
|
||||
currentProgress = 0.1f;
|
||||
std::thread([]() {
|
||||
std::string binaryUrl, binaryName;
|
||||
#ifdef _WIN32
|
||||
// Windows: rename old, move new into place
|
||||
system(("rename " + binaryName + " " + binaryName + ".old").c_str());
|
||||
system(("rename " + binaryName + ".new " + binaryName).c_str());
|
||||
system("rename version.txt version.txt.old");
|
||||
system("rename version.txt.new version.txt");
|
||||
system("copy version.txt assets\\version.txt >nul 2>&1");
|
||||
binaryUrl = "https://git.linology.tech/michael/MorriCraft/raw/branch/master/build-windows/MorriCraft.exe";
|
||||
binaryName = "MorriCraft.exe";
|
||||
#else
|
||||
// Linux: chmod, move
|
||||
system(("chmod +x " + binaryName + ".new").c_str());
|
||||
system(("mv " + binaryName + " " + binaryName + ".old 2>/dev/null").c_str());
|
||||
system(("mv " + binaryName + ".new " + binaryName).c_str());
|
||||
system("mv version.txt.new version.txt");
|
||||
system("cp version.txt assets/version.txt 2>/dev/null");
|
||||
binaryUrl = "https://git.linology.tech/michael/MorriCraft/raw/branch/master/build-linux/MorriCraft";
|
||||
binaryName = "MorriCraft";
|
||||
#endif
|
||||
fakeProgress = 1.0f;
|
||||
} else {
|
||||
downloadFailed = true;
|
||||
}
|
||||
std::string versionUrl = "https://git.linology.tech/michael/MorriCraft/raw/branch/master/version.txt";
|
||||
|
||||
// Download binary
|
||||
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());
|
||||
currentProgress = 0.8f;
|
||||
|
||||
if (r1 == 0 && r2 == 0) {
|
||||
#ifdef _WIN32
|
||||
system(("rename " + binaryName + " " + binaryName + ".old").c_str());
|
||||
system(("rename " + binaryName + ".new " + binaryName).c_str());
|
||||
system("rename version.txt version.txt.old");
|
||||
system("rename version.txt.new version.txt");
|
||||
system("copy version.txt assets\\version.txt >nul 2>&1");
|
||||
#else
|
||||
system(("chmod +x " + binaryName + ".new").c_str());
|
||||
system(("mv " + binaryName + " " + binaryName + ".old 2>/dev/null").c_str());
|
||||
system(("mv " + binaryName + ".new " + binaryName).c_str());
|
||||
system("mv version.txt.new version.txt");
|
||||
system("cp version.txt assets/version.txt 2>/dev/null");
|
||||
#endif
|
||||
currentProgress = 1.0f;
|
||||
downloadFinished = true;
|
||||
} else {
|
||||
downloadFailed = true;
|
||||
}
|
||||
}).detach();
|
||||
}
|
||||
|
||||
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);
|
||||
Rectangle backBtn = { (float)currentWidth/2 - 100, (float)currentHeight/2 + 20, 200, 40 };
|
||||
if (CheckCollisionPointRec(mousePos, backBtn) && IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) {
|
||||
currentState = MAIN_MENU;
|
||||
startedDownload = false;
|
||||
downloadFailed = false;
|
||||
currentState = MAIN_MENU; startedDownload = false; downloadFailed = false;
|
||||
}
|
||||
DrawRectangleRec(backBtn, DARKGRAY);
|
||||
DrawTextEx(customFont, "BACK", (Vector2){ backBtn.x + 70, backBtn.y + 10 }, 20, 1.0f, WHITE);
|
||||
} else {
|
||||
fakeProgress += 0.001f; // Slow visual for user
|
||||
if (fakeProgress > 1.0f) fakeProgress = 1.0f;
|
||||
DrawTextEx(customFont, "DOWNLOADING & REPLACING SYSTEM FILES...", (Vector2){ (float)currentWidth/2 - 250, (float)currentHeight/2 - 60 }, 24, 1.0f, YELLOW);
|
||||
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);
|
||||
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) {
|
||||
if (downloadFinished) {
|
||||
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 };
|
||||
DrawRectangleRec(pBox, (Color){ 30, 30, 30, 255 });
|
||||
DrawRectangleLinesEx(pBox, 4.0f, GREEN);
|
||||
|
||||
DrawTextEx(customFont, "UPDATE SUCCESSFUL!", (Vector2){ pBox.x + 60, pBox.y + 40 }, 24, 1.0f, GREEN);
|
||||
DrawTextEx(customFont, "PLEASE RESTART THE CLIENT.", (Vector2){ pBox.x + 60, pBox.y + 80 }, 20, 1.0f, WHITE);
|
||||
DrawTextEx(customFont, "UPDATE SUCCESSFUL!", (Vector2){ pBox.x + 80, pBox.y + 40 }, 28, 1.0f, GREEN);
|
||||
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);
|
||||
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) {
|
||||
|
|
@ -2337,8 +2315,8 @@ int main(void)
|
|||
DrawTexturePro(titleTexture, sourceRec, destRec, origin, 0.0f, WHITE);
|
||||
EndMode2D();
|
||||
|
||||
// Show Version Number (v2.2.7) in Red
|
||||
DrawTextEx(customFont, "v2.2.7", (Vector2){ (float)currentWidth - 140, (float)currentHeight - 40 }, 22, 1.0f, RED);
|
||||
// Show Version Number (v2.2.9) in Red
|
||||
DrawTextEx(customFont, "v2.2.9", (Vector2){ (float)currentWidth - 140, (float)currentHeight - 40 }, 22, 1.0f, RED);
|
||||
|
||||
// --- PLAYER NAME POPUP (IF MISSING) ---
|
||||
if (playerName == "") {
|
||||
|
|
@ -2566,30 +2544,30 @@ int main(void)
|
|||
if (showDeleteConfirm) {
|
||||
DrawRectangle(0, 0, currentWidth, currentHeight, (Color){ 0, 0, 0, 200 });
|
||||
|
||||
int confWidth = 400;
|
||||
int confHeight = 200;
|
||||
int confWidth = 550;
|
||||
int confHeight = 240;
|
||||
int confX = (currentWidth / 2) - (confWidth / 2);
|
||||
int confY = (currentHeight / 2) - (confHeight / 2);
|
||||
|
||||
DrawRectangle(confX, confY, confWidth, confHeight, (Color){ 50, 20, 20, 255 });
|
||||
DrawRectangleLinesEx((Rectangle){ (float)confX, (float)confY, (float)confWidth, (float)confHeight }, 4.0f, RED);
|
||||
|
||||
Vector2 warnSize = MeasureTextEx(customFont, "Delete World?", 24, 1.0f);
|
||||
DrawTextEx(customFont, "Delete World?", (Vector2){ confX + (confWidth/2) - (warnSize.x/2), confY + 30 }, 24, 1.0f, WHITE);
|
||||
Vector2 warnSize = MeasureTextEx(customFont, "Delete World?", 28, 1.0f);
|
||||
DrawTextEx(customFont, "Delete World?", (Vector2){ confX + (confWidth/2) - (warnSize.x/2), confY + 30 }, 28, 1.0f, WHITE);
|
||||
|
||||
std::string warnText = "Delete '" + deletingWorldName + "'?";
|
||||
Vector2 nameSize = MeasureTextEx(customFont, warnText.c_str(), 20, 1.0f);
|
||||
DrawTextEx(customFont, warnText.c_str(), (Vector2){ confX + (confWidth/2) - (nameSize.x/2), confY + 70 }, 20, 1.0f, LIGHTGRAY);
|
||||
std::string warnText = "Are you sure you want to delete '" + deletingWorldName + "'?";
|
||||
Vector2 nameSize = MeasureTextEx(customFont, warnText.c_str(), 22, 1.0f);
|
||||
DrawTextEx(customFont, warnText.c_str(), (Vector2){ confX + (confWidth/2) - (nameSize.x/2), confY + 85 }, 22, 1.0f, LIGHTGRAY);
|
||||
|
||||
// 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);
|
||||
DrawRectangleRec(yesBtn, isYesHovered ? RED : MAROON);
|
||||
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
|
||||
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);
|
||||
DrawRectangleRec(noBtn, isNoHovered ? (Color){ 100, 100, 100, 255 } : DARKGRAY);
|
||||
DrawRectangleLinesEx(noBtn, 2.0f, isNoHovered ? WHITE : GRAY);
|
||||
|
|
@ -2892,11 +2870,14 @@ int main(void)
|
|||
std::vector<Chunk*> visibleChunks;
|
||||
for (int cx = playerCX - RENDER_DISTANCE; cx <= playerCX + RENDER_DISTANCE; cx++) {
|
||||
for (int cz = playerCZ - RENDER_DISTANCE; cz <= playerCZ + RENDER_DISTANCE; cz++) {
|
||||
// FRUSTUM CULLING
|
||||
Vector3 chunkCenter = { (float)(cx * CHUNK_SIZE + 8), 32.0f, (float)(cz * CHUNK_SIZE + 8) };
|
||||
Vector3 toChunk = Vector3Normalize(Vector3Subtract(chunkCenter, camera3D.position));
|
||||
if (Vector3Length(Vector3Subtract(chunkCenter, camera3D.position)) > 24.0f &&
|
||||
Vector3DotProduct(toChunk, camForward) < -0.3f) continue;
|
||||
// OPTIMIZED FRUSTUM CULLING (Bug #1 Fix: Don't cull the player's current chunk)
|
||||
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));
|
||||
if (distSqr > 32.0f * 32.0f && Vector3DotProduct(toChunk, camForward) < -0.4f) continue;
|
||||
}
|
||||
|
||||
auto it = worldChunks.find({cx, cz});
|
||||
if (it == worldChunks.end()) continue;
|
||||
|
|
@ -2911,20 +2892,20 @@ int main(void)
|
|||
for (int renderType = 1; renderType <= 13; renderType++) {
|
||||
if (renderType == GRASS) {
|
||||
for (Chunk* chunk : visibleChunks) {
|
||||
for (auto& pos : chunk->renderLists[GRASS]) {
|
||||
DrawGrassBlock(pos, blockTextures[GRASS].id, grassTopTexture.id, blockTextures[DIRT].id, blockTint);
|
||||
for (auto& data : chunk->renderLists[GRASS]) {
|
||||
DrawGrassBlock((Vector3){data.x, data.y, data.z}, blockTextures[GRASS].id, grassTopTexture.id, blockTextures[DIRT].id, blockTint, data.faces);
|
||||
}
|
||||
}
|
||||
} else if (renderType == LOG) {
|
||||
for (Chunk* chunk : visibleChunks) {
|
||||
for (auto& pos : chunk->renderLists[LOG]) {
|
||||
DrawLog(pos, logSideTexture.id, logTopTexture.id, blockTint);
|
||||
for (auto& data : chunk->renderLists[LOG]) {
|
||||
DrawLog((Vector3){data.x, data.y, data.z}, logSideTexture.id, logTopTexture.id, blockTint, data.faces);
|
||||
}
|
||||
}
|
||||
} else if (renderType == CRAFTING_TABLE) {
|
||||
for (Chunk* chunk : visibleChunks) {
|
||||
for (auto& pos : chunk->renderLists[CRAFTING_TABLE]) {
|
||||
DrawCraftingTable(pos, craftingSideTexture.id, craftingTopTexture.id, blockTextures[DIRT].id, blockTint);
|
||||
for (auto& data : chunk->renderLists[CRAFTING_TABLE]) {
|
||||
DrawCraftingTable((Vector3){data.x, data.y, data.z}, craftingSideTexture.id, craftingTopTexture.id, blockTextures[DIRT].id, blockTint, data.faces);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -2936,8 +2917,8 @@ int main(void)
|
|||
}
|
||||
|
||||
for (Chunk* chunk : visibleChunks) {
|
||||
for (auto& pos : chunk->renderLists[renderType]) {
|
||||
DrawCubeVertices(pos.x, pos.y, pos.z, 1.0f, 1.0f, 1.0f);
|
||||
for (auto& data : chunk->renderLists[renderType]) {
|
||||
DrawCubeVertices(data.x, data.y, data.z, 1.0f, 1.0f, 1.0f, data.faces);
|
||||
}
|
||||
}
|
||||
rlEnd();
|
||||
|
|
@ -2990,19 +2971,27 @@ int main(void)
|
|||
handPos = Vector3Add(handPos, Vector3Scale(upVM, -0.25f - swingVal * 0.15f));
|
||||
|
||||
// Draw Arm (rotated cube)
|
||||
// We use rlgl to rotate it to point roughly forward
|
||||
rlPushMatrix();
|
||||
rlTranslatef(handPos.x, handPos.y, handPos.z);
|
||||
rlRotatef(camYaw * 180.0f/PI, 0, 1, 0); // Yaw with camera
|
||||
rlRotatef(-20.0f - swingVal * 30.0f, 1, 0, 0); // Slight slant
|
||||
DrawCube((Vector3){0,0,0}, 0.08f, 0.1f, 0.35f, (Color){220, 180, 150, 255});
|
||||
rlRotatef(camYaw * 180.0f/PI, 0, 1, 0);
|
||||
rlRotatef(camPitch * 180.0f/PI - 15.0f - swingVal * 20.0f, 1, 0, 0); // Point forward + swing
|
||||
DrawCube((Vector3){0,0,0}, 0.1f, 0.12f, 0.4f, (Color){220, 180, 150, 255});
|
||||
rlPopMatrix();
|
||||
|
||||
// Draw Held Item
|
||||
// Draw Held Item - Fixed pivot and attachment (Bug #3)
|
||||
int heldBT = hotbar[activeHotbarSlot].blockType;
|
||||
if (heldBT != AIR) {
|
||||
Vector3 itemPos = Vector3Add(handPos, Vector3Scale(forwardVM, 0.12f));
|
||||
itemPos = Vector3Add(itemPos, Vector3Scale(upVM, 0.12f));
|
||||
// Calculate position at the end of the arm
|
||||
// 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));
|
||||
|
||||
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);
|
||||
rlRotatef(camYaw * 180.0f/PI + 45.0f, 0, 1, 0);
|
||||
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();
|
||||
rlSetTexture(0);
|
||||
} else {
|
||||
// Item (Stick/Axe) as Billboard - Scaled larger for better visibility
|
||||
DrawBillboard(camera3D, itemTex, itemPos, 0.35f, WHITE);
|
||||
// Item (Stick/Axe) as Billboard
|
||||
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();
|
||||
|
|
@ -3173,7 +3164,30 @@ int main(void)
|
|||
}
|
||||
|
||||
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
|
||||
if (mouseHeldItem.blockType == AIR) {
|
||||
mouseHeldItem = slot;
|
||||
|
|
@ -3313,7 +3327,7 @@ int main(void)
|
|||
// 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});
|
||||
|
||||
if (IsKeyPressed(KEY_ESCAPE) || IsKeyPressed(KEY_E)) {
|
||||
if (IsKeyPressed(KEY_ESCAPE)) {
|
||||
inventoryOpen = false;
|
||||
DisableCursor();
|
||||
}
|
||||
|
|
@ -3343,7 +3357,7 @@ int main(void)
|
|||
|
||||
drawInvGrid(guiX + 16, tableStartY + 3*(invSlotSize+invGap) + 40);
|
||||
|
||||
if (IsKeyPressed(KEY_ESCAPE) || IsKeyPressed(KEY_E)) {
|
||||
if (IsKeyPressed(KEY_ESCAPE)) {
|
||||
currentState = GAMEPLAY;
|
||||
DisableCursor();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
v2.2.7
|
||||
v2.2.9
|
||||
|
|
|
|||