diff --git a/README.md b/README.md index b389acd..25fd1ce 100644 --- a/README.md +++ b/README.md @@ -106,12 +106,13 @@ A pre-built `MorriCraft-Windows.zip` is available in the repository root. ## 📜 Version History -### v2.2.20 - UI Polish & Spawn Fixes (Current) -- **Ignore Update**: Added an "Ignore" button to the update prompt to skip updates for the current session. -- **Chat Fix**: Resolved an issue where the chat box would remain stuck open after sending a message. -- **Universal Tooltips**: Item names now appear when hovering over items in ALL screens (Chest, Crafting Table, and Cheat Menu). -- **Morning Spawn Fix**: Adjusted the initial spawn time to ensure new worlds start in bright daylight. -- **Version UI**: Moved the version number to the bottom-left to avoid cutting it off on different screen sizes. +### v2.2.21 - Save Fix & Updater Polish (Current) +- **Player Position Fix**: Resolved a critical bug where players would reset to spawn when reloading a world. Player coordinates are now correctly preserved. +- **Improved Updater**: Added "Downloading" and "Installing" status messages. +- **Dynamic Progress**: The progress bar now pulses during the download to show active background work. +- **Extraction Fix**: Resolved an issue where the updater failed to find the downloaded ZIP due to an incorrect filename extension. + +### v2.2.20 - UI Polish & Spawn Fixes ### v2.2.19 - Torch & persistence Overhaul diff --git a/release/MorriCraft-Linux.zip b/release/MorriCraft-Linux.zip index eadb5d1..6899708 100644 Binary files a/release/MorriCraft-Linux.zip and b/release/MorriCraft-Linux.zip differ diff --git a/release/MorriCraft-Windows.zip b/release/MorriCraft-Windows.zip index 8da1459..db27bed 100644 Binary files a/release/MorriCraft-Windows.zip and b/release/MorriCraft-Windows.zip differ diff --git a/release/version.txt b/release/version.txt index 0e44b4f..622320c 100644 --- a/release/version.txt +++ b/release/version.txt @@ -1 +1 @@ -v2.2.20 +v2.2.21 diff --git a/src/main.cpp b/src/main.cpp index 3681ada..9c9bc1b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -380,7 +380,7 @@ void RebuildChunkRenderList(Chunk* chunk, int cx, int cz) { unsigned char faces = GetExposedFaces(lx, ly, lz, chunk, nxM, nxP, nzM, nzP); if (faces != 0) { - // Simple Torch Lighting (v2.2.20) + // Simple Torch Lighting (v2.2.21) float blockLight = 0.0f; Vector3 bPos = {(float)(worldX+lx), (float)ly, (float)(worldZ+lz)}; for (const auto& tp : torchPositions) { @@ -965,7 +965,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.2.20"); + InitWindow(screenWidth, screenHeight, "MorriCraft v2.2.21"); LoadConfig(); SetExitKey(KEY_NULL); // Prevent ESC from closing the window @@ -1029,7 +1029,7 @@ int main(void) float updateTimer = 0.0f; float downloadProgress = 0.0f; std::string latestVersion = ""; - std::string localVersion = "v2.2.20"; // Default fallback + std::string localVersion = "v2.2.21"; // Default fallback // Read local version std::ifstream vfile("assets/version.txt"); @@ -1636,7 +1636,7 @@ int main(void) // --- GLOBAL TIME & AUDIO MANAGEMENT --- - float cycleLength = 600.0f; // Slower day cycle (v2.2.20: cut speed in half) + float cycleLength = 600.0f; // Slower day cycle (v2.2.21: cut speed in half) if (currentState == GAMEPLAY) gameTime += GetFrameTime(); float timeOfDay = fmodf(gameTime, cycleLength) / cycleLength; float sunAngle = timeOfDay * 2.0f * 3.14159f - 3.14159f/2.0f; @@ -1990,7 +1990,7 @@ int main(void) AddToInventory(targetBlock); NetSetBlock(hitX, hitY, hitZ, AIR); - // Tool Durability Logic (v2.2.20) + // Tool Durability Logic (v2.2.21) InventorySlot* slot = &hotbar[activeHotbarSlot]; if (slot->maxDurability > 0) { slot->durability--; @@ -2146,6 +2146,7 @@ int main(void) } else if (currentState == DOWNLOADING_UPDATE) { static bool startedDownload = false; static bool downloadFailed = false; + static bool isInstalling = false; static bool downloadFinished = false; static float currentProgress = 0.0f; @@ -2164,29 +2165,31 @@ int main(void) std::string versionUrl = "https://git.linology.tech/michael/MorriCraft/raw/branch/master/release/version.txt"; // Download binary - int r1 = system(("curl -L -s -o " + binaryName + ".new \"" + binaryUrl + "\"").c_str()); - currentProgress = 0.6f; + // v2.2.21: Download directly to the expected zip name + int r1 = system(("curl -L -s -o " + binaryName + " \"" + binaryUrl + "\"").c_str()); + currentProgress = 0.7f; // Download version int r2 = system(("curl -L -s -o version.txt.new \"" + versionUrl + "\"").c_str()); - currentProgress = 0.8f; + currentProgress = 0.9f; if (r1 == 0 && r2 == 0) { + isInstalling = true; #ifdef _WIN32 // Windows Update: Move exe, unzip assets system("move MorriCraft.exe MorriCraft.old >nul 2>&1"); - system("powershell -Command \"Expand-Archive -Path MorriCraft-Windows.zip -DestinationPath . -Force\""); + system(("powershell -Command \"Expand-Archive -Path " + binaryName + " -DestinationPath . -Force\"").c_str()); system("move version.txt.new version.txt >nul 2>&1"); system("copy version.txt assets\\version.txt >nul 2>&1"); - system("del MorriCraft-Windows.zip"); + system(("del " + binaryName).c_str()); #else // Linux Update: Move binary, unzip assets system("mv MorriCraft MorriCraft.old 2>/dev/null"); - system("unzip -o MorriCraft-Linux.zip"); + system(("unzip -o " + binaryName).c_str()); system("chmod +x MorriCraft"); system("mv version.txt.new version.txt 2>/dev/null"); system("cp version.txt assets/version.txt 2>/dev/null"); - system("rm MorriCraft-Linux.zip"); + system(("rm " + binaryName).c_str()); #endif currentProgress = 1.0f; downloadFinished = true; @@ -2206,7 +2209,13 @@ int main(void) DrawRectangleRec(backBtn, DARKGRAY); DrawTextEx(customFont, "BACK", (Vector2){ backBtn.x + 70, backBtn.y + 10 }, 20, 1.0f, WHITE); } else { - DrawTextEx(customFont, "Updating...", (Vector2){ (float)currentWidth/2 - 50, (float)currentHeight/2 - 60 }, 24, 1.0f, YELLOW); + if (isInstalling) { + DrawTextEx(customFont, "Installing update...", (Vector2){ (float)currentWidth/2 - 80, (float)currentHeight/2 - 60 }, 24, 1.0f, GREEN); + } else { + DrawTextEx(customFont, "Downloading update...", (Vector2){ (float)currentWidth/2 - 90, (float)currentHeight/2 - 60 }, 24, 1.0f, YELLOW); + // Dynamic progress pulse (v2.2.21) + if (currentProgress < 0.7f) currentProgress += 0.001f; + } int bw = 500, bh = 35; Rectangle barBg = { (float)currentWidth/2 - bw/2, (float)currentHeight/2 - bh/2, (float)bw, (float)bh }; DrawRectangleRec(barBg, BLACK); @@ -2478,8 +2487,8 @@ int main(void) DrawTexturePro(titleTexture, sourceRec, destRec, origin, 0.0f, WHITE); EndMode2D(); - // Show Version Number (v2.2.20) in Red - DrawTextEx(customFont, "v2.2.20", (Vector2){ 20, (float)currentHeight - 30 }, 22, 1.0f, RED); + // Show Version Number (v2.2.21) in Red + DrawTextEx(customFont, "v2.2.21", (Vector2){ 20, (float)currentHeight - 30 }, 22, 1.0f, RED); // --- PLAYER NAME POPUP (IF MISSING) --- if (playerName == "") { @@ -2652,11 +2661,12 @@ int main(void) if (worldFile.is_open()) { worldFile >> globalSeedHash >> spawnSavedX >> spawnSavedY >> spawnSavedZ; worldFile.close(); + } else { globalSeedHash = 12345; spawnSavedX = 0; spawnSavedY = -1; spawnSavedZ = 0; } - // Load Chests (v2.2.20) + // Load Chests (v2.2.21) chestInventories.clear(); std::ifstream cf("saves/" + currentWorldName + "/chests.dat", std::ios::binary); if (cf.is_open()) { @@ -2674,7 +2684,7 @@ int main(void) cf.close(); } - // Load Torches (v2.2.20) + // Load Torches (v2.2.21) torchPositions.clear(); std::ifstream tf("saves/" + currentWorldName + "/torches.dat", std::ios::binary); if (tf.is_open()) { @@ -2958,7 +2968,7 @@ int main(void) snprintf(worldName, sizeof(worldName), "%s", currentWorldName.c_str()); worldNameLen = strlen(worldName); - gameTime = 150.0f; // Start new world at 7:00 AM (v2.2.20 adjusted for slower cycle) + gameTime = 150.0f; // Start new world at 7:00 AM (v2.2.21 adjusted for slower cycle) if (serverMode) { serverSocket = socket(AF_INET, SOCK_STREAM, 0); @@ -3105,7 +3115,7 @@ int main(void) } else if (renderType == TORCH) { for (Chunk* chunk : visibleChunks) { for (auto& data : chunk->renderLists[TORCH]) { - // 3D Flickering Torch (v2.2.20) + // 3D Flickering Torch (v2.2.21) float flicker = sinf(GetTime() * 12.0f) * 0.03f; float h = 0.6f + flicker; float w = 0.12f; @@ -3349,7 +3359,7 @@ int main(void) (Vector2){ (float)(sx + (slotSize/2) - (countSize.x/2)), (float)(hotbarY + slotSize - 14) }, 12, 1.0f, WHITE); - // Draw Hotbar Durability Bar (v2.2.20) + // Draw Hotbar Durability Bar (v2.2.21) if (hotbar[s].maxDurability > 0 && hotbar[s].durability < hotbar[s].maxDurability) { float durP = (float)hotbar[s].durability / hotbar[s].maxDurability; int barW = slotSize - 10; @@ -3380,7 +3390,7 @@ int main(void) DrawRectangleRec(slotRect, hov ? (Color){90,90,90,255} : (Color){60,60,60,255}); DrawRectangleLinesEx(slotRect, 2.0f, hov ? WHITE : (Color){100,100,100,200}); - // Draw Durability Bar (v2.2.20) + // Draw Durability Bar (v2.2.21) if (slot.maxDurability > 0 && slot.durability < slot.maxDurability) { float durPercent = (float)slot.durability / slot.maxDurability; int barW = slotRect.width - 10; @@ -3656,7 +3666,7 @@ int main(void) } } if (hov && IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)) { - // Right click: pick up/place one (v2.2.20) + // Right click: pick up/place one (v2.2.21) if (mouseHeldItem.blockType == AIR) { if (chestInv[i].blockType != AIR && chestInv[i].count > 0) { mouseHeldItem = InventorySlot(chestInv[i].blockType, 1); @@ -3703,7 +3713,7 @@ int main(void) } } if (hov && IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)) { - // Right click logic for player inv in chest GUI (v2.2.20) + // Right click logic for player inv in chest GUI (v2.2.21) if (mouseHeldItem.blockType == AIR) { if (inventory[i].blockType != AIR && inventory[i].count > 0) { mouseHeldItem = InventorySlot(inventory[i].blockType, 1); @@ -3880,7 +3890,7 @@ int main(void) invf.close(); } - // Save Chests (v2.2.20) + // Save Chests (v2.2.21) std::ofstream cf("saves/" + currentWorldName + "/chests.dat", std::ios::binary); if (cf.is_open()) { uint32_t count = (uint32_t)chestInventories.size(); @@ -3896,7 +3906,7 @@ int main(void) cf.close(); } - // Save Torches (v2.2.20) + // Save Torches (v2.2.21) std::ofstream tf("saves/" + currentWorldName + "/torches.dat", std::ios::binary); if (tf.is_open()) { uint32_t count = (uint32_t)torchPositions.size(); diff --git a/version.txt b/version.txt index 0e44b4f..622320c 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -v2.2.20 +v2.2.21