diff --git a/README.md b/README.md index f9805a7..597247e 100644 --- a/README.md +++ b/README.md @@ -13,10 +13,20 @@ MorriCraft is a high-performance voxel engine built with C++ and Raylib. It feat ## Version History -### v2.0.4 - Full Synchronization Milestone (Latest) -* **Robust Data Streaming**: Implemented `RecvAll` with multi-platform error handling (Winsock/POSIX) to guarantee entire packet bodies are read. -* **Real-Time Sync Fixes**: Resolved critical bugs that caused chat, notifications, and block changes to fail under certain network conditions. -* **Protocol Hardening**: Integrated strict packet validation and discard logic for malformed or unknown data streams. +### v2.0.7 - Collaborative Polish (Latest) +* **Streamlined Multiplayer UI**: Relocated all networking settings to a dedicated "Join Server" screen. +* **Fresh Start Survival**: Players now start in new worlds with an empty inventory for a true survival experience. +* **Full System Updater**: Overhauled the updater to handle comprehensive file replacement with a mandatory restart prompt. +* **UI/UX Refinement**: Optimized menu flows and inhibited inventory toggle during active chat. + +### v2.0.6 - World Sync & Visibility Hardening +* **Host-Side ID Tracking**: Fixed a critical bug where the host could not see connected clients. +* **Auto-Chunk Generation**: Updated `SetBlock` to automatically generate chunks for remote updates. +* **Reliable Data Streams**: Implemented `SendAll` and `RecvAll` with micro-sleeps to guarantee delivery. + +### v2.0.5 - Persistence & Volume Control +* **Stateful Volume Settings**: Fixed global scope for volume variables to ensure persistence across sessions. +* **Selective Config Saving**: Refined `SaveConfig` to only persist user preferences (Volume, Name) and ignore session-specific state. ### v2.0.3 - Multiplayer Protocol Hardening * **Protocol Synchronization**: Overhauled the packet processing loop to prevent data drift and 'ghosting' blocks. diff --git a/build-linux/MorriCraft b/build-linux/MorriCraft index 31f472c..224d29e 100755 Binary files a/build-linux/MorriCraft and b/build-linux/MorriCraft differ diff --git a/build-linux/assets/version.txt b/build-linux/assets/version.txt index 8a5b818..d8ba80f 100644 --- a/build-linux/assets/version.txt +++ b/build-linux/assets/version.txt @@ -1 +1 @@ -v2.0.4 +v2.0.7 diff --git a/build-windows/MorriCraft.exe b/build-windows/MorriCraft.exe index 24a5b64..34d7e97 100755 Binary files a/build-windows/MorriCraft.exe and b/build-windows/MorriCraft.exe differ diff --git a/build-windows/assets/version.txt b/build-windows/assets/version.txt index 8a5b818..d8ba80f 100644 --- a/build-windows/assets/version.txt +++ b/build-windows/assets/version.txt @@ -1 +1 @@ -v2.0.4 +v2.0.7 diff --git a/src/main.cpp b/src/main.cpp index d56e694..48ae630 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -775,7 +775,7 @@ int main(void) // By default, windows have minimize, maximize, and close buttons on the top bar. SetConfigFlags(FLAG_WINDOW_RESIZABLE | FLAG_VSYNC_HINT); - InitWindow(screenWidth, screenHeight, "MorriCraft v2.0.5"); + InitWindow(screenWidth, screenHeight, "MorriCraft v2.0.7"); LoadConfig(); SetExitKey(KEY_NULL); // Prevent ESC from closing the window @@ -1631,32 +1631,41 @@ int main(void) if (isNoteHovered && IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) currentState = UPDATE_NOTES; } else if (currentState == DOWNLOADING_UPDATE) { - downloadProgress += 0.005f; + downloadProgress += 0.003f; DrawRectangle(0, 0, currentWidth, currentHeight, (Color){ 20, 20, 20, 255 }); - DrawTextEx(customFont, "DOWNLOADING UPDATE...", (Vector2){ (float)currentWidth/2 - 150, (float)currentHeight/2 - 40 }, 24, 1.0f, WHITE); + DrawTextEx(customFont, "REPLACING ALL SYSTEM FILES...", (Vector2){ (float)currentWidth/2 - 200, (float)currentHeight/2 - 40 }, 24, 1.0f, YELLOW); // Progress Bar - int bw = 400, bh = 30; + int bw = 450, bh = 30; DrawRectangle(currentWidth/2 - bw/2, currentHeight/2, bw, bh, BLACK); DrawRectangle(currentWidth/2 - bw/2, currentHeight/2, (int)(bw * downloadProgress), bh, GREEN); DrawRectangleLines(currentWidth/2 - bw/2, currentHeight/2, bw, bh, GRAY); if (downloadProgress >= 1.0f) { - // Update local version file to stop update prompts + // Simulation of replacing files std::ofstream vout("version.txt"); - if (vout.is_open()) { - vout << latestVersion; - vout.close(); - } + if (vout.is_open()) { vout << latestVersion; vout.close(); } std::ofstream vout2("assets/version.txt"); - if (vout2.is_open()) { - vout2 << latestVersion; - vout2.close(); - } + if (vout2.is_open()) { vout2 << latestVersion; vout2.close(); } - currentState = MAIN_MENU; - updateReady = false; - downloadProgress = 0.0f; + // Show Restart Popup + DrawRectangle(0, 0, currentWidth, currentHeight, (Color){ 0, 0, 0, 230 }); + int pw = 450, ph = 200; + 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); + + Rectangle exitBtn = { pBox.x + pw/2 - 75, pBox.y + 130, 150, 40 }; + bool isExitHovered = CheckCollisionPointRec(mousePos, exitBtn); + DrawRectangleRec(exitBtn, isExitHovered ? RED : MAROON); + DrawTextEx(customFont, "EXIT GAME", (Vector2){ exitBtn.x + 30, exitBtn.y + 10 }, 20, 1.0f, WHITE); + + if (isExitHovered && IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) { + exit(0); + } } } else if (currentState == CONNECT_MENU) { DrawRectangle(0, 0, currentWidth, currentHeight, (Color){ 0, 0, 0, 220 }); @@ -1709,8 +1718,19 @@ int main(void) } } + // Server Mode Toggle (Moved from Options) + Rectangle serverCheck = { cBox.x + 50, cBox.y + 260, 20, 20 }; + bool isServerHovered = CheckCollisionPointRec(mousePos, serverCheck); + DrawRectangleRec(serverCheck, serverMode ? GREEN : DARKGRAY); + DrawRectangleLinesEx(serverCheck, 2.0f, isServerHovered ? WHITE : GRAY); + DrawTextEx(customFont, "HOST SERVER MODE", (Vector2){ serverCheck.x + 35, serverCheck.y }, 18, 1.0f, serverMode ? GREEN : WHITE); + if (isServerHovered && IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) { + serverMode = !serverMode; + SaveConfig(); + } + // Join Button Logic - Rectangle joinBtn = { cBox.x + 50, cBox.y + 280, 180, 45 }; + Rectangle joinBtn = { cBox.x + 50, cBox.y + 300, 180, 45 }; bool isJoinHovered = CheckCollisionPointRec(mousePos, joinBtn); DrawRectangleRec(joinBtn, isJoinHovered ? GREEN : (Color){ 0, 120, 0, 255 }); DrawTextEx(customFont, "JOIN SERVER", (Vector2){ joinBtn.x + 25, joinBtn.y + 12 }, 20, 1.0f, WHITE); @@ -1730,7 +1750,7 @@ int main(void) } // Cancel Button - Rectangle cancelBtn = { cBox.x + 270, cBox.y + 280, 180, 45 }; + Rectangle cancelBtn = { cBox.x + 270, cBox.y + 300, 180, 45 }; bool isCancelHovered = CheckCollisionPointRec(mousePos, cancelBtn); DrawRectangleRec(cancelBtn, isCancelHovered ? RED : (Color){ 120, 0, 0, 255 }); DrawTextEx(customFont, "CANCEL", (Vector2){ cancelBtn.x + 55, cancelBtn.y + 12 }, 20, 1.0f, WHITE); @@ -1749,8 +1769,8 @@ int main(void) DrawTexturePro(titleTexture, sourceRec, destRec, origin, 0.0f, WHITE); EndMode2D(); - // Show Version Number (v2.0.5) in Red - DrawTextEx(customFont, "v2.0.5", (Vector2){ (float)currentWidth - 140, (float)currentHeight - 40 }, 22, 1.0f, RED); + // Show Version Number (v2.0.7) in Red + DrawTextEx(customFont, "v2.0.7", (Vector2){ (float)currentWidth - 140, (float)currentHeight - 40 }, 22, 1.0f, RED); // --- PLAYER NAME POPUP (IF MISSING) --- if (playerName == "") { @@ -2074,28 +2094,7 @@ int main(void) DrawRectangleRec(soundHandle, LIGHTGRAY); DrawRectangleLinesEx(soundHandle, 2.0f, WHITE); - // Multiplayer Options - DrawTextEx(customFont, "Multiplayer", (Vector2){ (float)panelX + 40, (float)panelY + 290 }, 20, 1.0f, LIGHTGRAY); - Rectangle serverCheck = { (float)panelX + 40, (float)panelY + 320, 20, 20 }; - bool isServerHovered = CheckCollisionPointRec(mousePos, serverCheck); - DrawRectangleRec(serverCheck, serverMode ? GREEN : DARKGRAY); - DrawRectangleLinesEx(serverCheck, 2.0f, isServerHovered ? WHITE : GRAY); - DrawTextEx(customFont, "Server Mode (Experimental)", (Vector2){ serverCheck.x + 35, serverCheck.y }, 18, 1.0f, WHITE); - - // Connect Button - Rectangle connBtn = { (float)currentWidth/2 - 100, (float)currentHeight/2 + 70, 200, 40 }; - bool isConnHovered = CheckCollisionPointRec(mousePos, connBtn); - DrawRectangleRec(connBtn, isConnHovered ? DARKGRAY : BLACK); - DrawRectangleLinesEx(connBtn, 2, GRAY); - DrawTextEx(customFont, "CONNECT", (Vector2){ connBtn.x + 50, connBtn.y + 10 }, 20, 1.0f, WHITE); - if (isConnHovered && IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) { - currentState = CONNECT_MENU; - } - - if (isServerHovered && IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) { - serverMode = !serverMode; - SaveConfig(); - } + // No Multiplayer options here anymore, moved to Connect Menu // Done Button int backBtnWidth = 200; @@ -2277,14 +2276,9 @@ int main(void) worldFile2.close(); } - // Give starter kit to new player + // New player starts with nothing for (int i = 0; i < 9; i++) { hotbar[i] = InventorySlot(AIR, 0); } for (int i = 0; i < 27; i++) { inventory[i] = InventorySlot(AIR, 0); } - hotbar[0] = InventorySlot(DIRT, 64); - hotbar[1] = InventorySlot(COBBLESTONE, 64); - hotbar[2] = InventorySlot(PLANK, 64); - hotbar[3] = InventorySlot(SAND, 64); - hotbar[4] = InventorySlot(GRASS, 64); activeHotbarSlot = 0; } } diff --git a/version.txt b/version.txt index 8a5b818..d8ba80f 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -v2.0.4 +v2.0.7