UI Polish, Fresh Start Inventory, and Full System Updater - v2.0.7
This commit is contained in:
parent
be2148a415
commit
de7c60d9d7
18
README.md
18
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.
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1 +1 @@
|
|||
v2.0.4
|
||||
v2.0.7
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1 +1 @@
|
|||
v2.0.4
|
||||
v2.0.7
|
||||
|
|
|
|||
90
src/main.cpp
90
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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
v2.0.4
|
||||
v2.0.7
|
||||
|
|
|
|||
Loading…
Reference in New Issue