From c2356bf29ea3d84c658958b29f03c8f46c4812bd Mon Sep 17 00:00:00 2001 From: Sneexy <60184397+SnenxyTengoku@users.noreply.github.com> Date: Wed, 1 Apr 2026 19:10:47 -0500 Subject: [PATCH 01/25] Minor docker/container fixes and edits (#1454) --- docker-compose.dedicated-server.ghcr.yml | 7 +++++-- docker-compose.dedicated-server.yml | 7 +++++-- docker/dedicated-server/entrypoint.sh | 5 ++--- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/docker-compose.dedicated-server.ghcr.yml b/docker-compose.dedicated-server.ghcr.yml index 8bcaf4843..7a9a95b23 100644 --- a/docker-compose.dedicated-server.ghcr.yml +++ b/docker-compose.dedicated-server.ghcr.yml @@ -1,12 +1,12 @@ services: minecraft-lce-dedicated-server: - image: ghcr.io/kuwacom/minecraft-lce-dedicated-server:nightly + image: ghcr.io/smartcmd/minecraft-lce-dedicated-server:nightly container_name: minecraft-lce-dedicated-server restart: unless-stopped tty: true stdin_open: true environment: - TZ: ${TZ:-Asia/Tokyo} + TZ: ${TZ:-Etc/UTC} WINEARCH: win64 WINEPREFIX: /var/opt/wineprefix64 WINEDEBUG: -all @@ -15,6 +15,9 @@ services: # minimum required virtual screen XVFB_DISPLAY: ${XVFB_DISPLAY:-:99} XVFB_SCREEN: ${XVFB_SCREEN:-720x1280x16} + # ip & port the server will run on + SERVER_BIND_IP: ${SERVER_BIND_IP:-0.0.0.0} + SERVER_PORT: ${SERVER_PORT:-25565} volumes: # - wineprefix64:/var/opt/wineprefix64 - ./server-data:/srv/persist diff --git a/docker-compose.dedicated-server.yml b/docker-compose.dedicated-server.yml index 4a0d33137..3dbe8bf64 100644 --- a/docker-compose.dedicated-server.yml +++ b/docker-compose.dedicated-server.yml @@ -10,7 +10,7 @@ services: tty: true stdin_open: true environment: - TZ: ${TZ:-Asia/Tokyo} + TZ: ${TZ:-Etc/UTC} WINEARCH: win64 WINEPREFIX: /var/opt/wineprefix64 WINEDEBUG: -all @@ -18,7 +18,10 @@ services: SERVER_CLI_INPUT_MODE: ${SERVER_CLI_INPUT_MODE:-stream} # minimum required virtual screen XVFB_DISPLAY: ${XVFB_DISPLAY:-:99} - XVFB_SCREEN: ${XVFB_SCREEN:-64x64x16} + XVFB_SCREEN: ${XVFB_SCREEN:-720x1280x16} + # ip & port the server will run on + SERVER_BIND_IP: ${SERVER_BIND_IP:-0.0.0.0} + SERVER_PORT: ${SERVER_PORT:-25565} volumes: # - wineprefix64:/var/opt/wineprefix64 - ./server-data:/srv/persist diff --git a/docker/dedicated-server/entrypoint.sh b/docker/dedicated-server/entrypoint.sh index 26b40da98..0eece2742 100644 --- a/docker/dedicated-server/entrypoint.sh +++ b/docker/dedicated-server/entrypoint.sh @@ -3,9 +3,8 @@ set -euo pipefail SERVER_DIR="/srv/mc" SERVER_EXE="Minecraft.Server.exe" -# ip & port are fixed since they run inside the container -SERVER_PORT="25565" -SERVER_BIND_IP="0.0.0.0" +SERVER_PORT="${SERVER_PORT:-25565}" +SERVER_BIND_IP="${SERVER_BIND_IP:-0.0.0.0}" PERSIST_DIR="/srv/persist" WINE_CMD="" From c4c4c08b960276d1ecf10fcd18d6ae77ff90841b Mon Sep 17 00:00:00 2001 From: Sylvessa <225480449+sylvessa@users.noreply.github.com> Date: Thu, 2 Apr 2026 00:01:27 -0500 Subject: [PATCH 02/25] Revert "Update actions workflows and add clang format check for PRs (#1418)" This reverts commit 38d58f2d8bb8af5516671b42940279d4e582d9c7 due to it causing spam and other problems with pull requests. --- .github/workflows/clang-format.yml | 48 ---------------------------- .github/workflows/nightly-server.yml | 11 +++---- .github/workflows/nightly.yml | 11 +++---- .github/workflows/pull-request.yml | 10 +++--- 4 files changed, 14 insertions(+), 66 deletions(-) delete mode 100644 .github/workflows/clang-format.yml diff --git a/.github/workflows/clang-format.yml b/.github/workflows/clang-format.yml deleted file mode 100644 index a01bada4e..000000000 --- a/.github/workflows/clang-format.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: Check formatting - -on: - pull_request: - paths: - - '**' - - '!.gitignore' - - '!*.md' - - '!.github/**' - - '.github/workflows/clang-format.yml' - -permissions: - contents: read - pull-requests: write - -jobs: - format-check: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - with: - ref: ${{ github.event.pull_request.head.sha }} - fetch-depth: 0 - - - name: Fetch base commit - run: git fetch origin ${{ github.event.pull_request.base.sha }} - - - name: Install clang-format-20 - run: | - wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc - sudo add-apt-repository -y "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-20 main" - sudo apt-get install -y -qq clang-format-20 - - - uses: reviewdog/action-setup@v1 - - - name: Check formatting on changed lines - env: - REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - git clang-format-20 --binary clang-format-20 \ - --diff ${{ github.event.pull_request.base.sha }} -- \ - '*.c' '*.cpp' '*.cc' '*.h' '*.hpp' \ - | reviewdog \ - -name="clang-format" \ - -f=diff \ - -reporter=github-pr-check \ - -fail-level=error \ - -filter-mode=added diff --git a/.github/workflows/nightly-server.yml b/.github/workflows/nightly-server.yml index 0fc20eb13..5450de9ac 100644 --- a/.github/workflows/nightly-server.yml +++ b/.github/workflows/nightly-server.yml @@ -5,12 +5,11 @@ on: push: branches: - 'main' - paths: - - '**' - - '!.gitignore' - - '!*.md' - - '!.github/**' - - '.github/workflows/nightly-server.yml' + paths-ignore: + - '.gitignore' + - '*.md' + - '.github/**' + - '!.github/workflows/nightly-server.yml' permissions: contents: write diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index a5b53be08..789db3e84 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -5,12 +5,11 @@ on: push: branches: - 'main' - paths: - - '**' - - '!.gitignore' - - '!*.md' - - '!.github/**' - - '.github/workflows/nightly.yml' + paths-ignore: + - '.gitignore' + - '*.md' + - '.github/**' + - '!.github/workflows/nightly.yml' permissions: contents: write diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 3b5398a00..9d57f4b4b 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -4,12 +4,10 @@ on: workflow_dispatch: pull_request: types: [opened, reopened, synchronize] - paths: - - '**' - - '!.gitignore' - - '!*.md' - - '!.github/**' - - '.github/workflows/pull-request.yml' + paths-ignore: + - '.gitignore' + - '*.md' + - '.github/*.md' jobs: build: From e4c08b8414f662a340005428dda81440a2ad140f Mon Sep 17 00:00:00 2001 From: Logan Gibson Date: Thu, 2 Apr 2026 00:43:33 -0700 Subject: [PATCH 03/25] Replace instances of hard-coded port in ports variable with SERVER_PORT variable in yml files (#1457) --- docker-compose.dedicated-server.ghcr.yml | 4 ++-- docker-compose.dedicated-server.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docker-compose.dedicated-server.ghcr.yml b/docker-compose.dedicated-server.ghcr.yml index 7a9a95b23..f311f834c 100644 --- a/docker-compose.dedicated-server.ghcr.yml +++ b/docker-compose.dedicated-server.ghcr.yml @@ -22,8 +22,8 @@ services: # - wineprefix64:/var/opt/wineprefix64 - ./server-data:/srv/persist ports: - - "25565:25565/tcp" - - "25565:25565/udp" + - "$SERVER_PORT:$SERVER_PORT/tcp" + - "$SERVER_PORT:$SERVER_PORT/udp" stop_grace_period: 30s # volumes: diff --git a/docker-compose.dedicated-server.yml b/docker-compose.dedicated-server.yml index 3dbe8bf64..23caf26fd 100644 --- a/docker-compose.dedicated-server.yml +++ b/docker-compose.dedicated-server.yml @@ -26,8 +26,8 @@ services: # - wineprefix64:/var/opt/wineprefix64 - ./server-data:/srv/persist ports: - - "25565:25565/tcp" - - "25565:25565/udp" + - "$SERVER_PORT:$SERVER_PORT/tcp" + - "$SERVER_PORT:$SERVER_PORT/udp" stop_grace_period: 30s # volumes: From 8bf034354426d5e3c2bf30fd755136e78f976fc0 Mon Sep 17 00:00:00 2001 From: Sylvessa <225480449+sylvessa@users.noreply.github.com> Date: Thu, 2 Apr 2026 17:16:31 -0500 Subject: [PATCH 04/25] fix: boat plr height & sneak height (#1459) --- Minecraft.Client/HumanoidModel.cpp | 2 +- Minecraft.Client/ItemInHandRenderer.cpp | 14 ++++++++++++++ Minecraft.Client/PlayerRenderer.cpp | 17 ++++++++++++++++- Minecraft.World/Boat.cpp | 2 +- 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/Minecraft.Client/HumanoidModel.cpp b/Minecraft.Client/HumanoidModel.cpp index c6c6b9f4f..f44654c33 100644 --- a/Minecraft.Client/HumanoidModel.cpp +++ b/Minecraft.Client/HumanoidModel.cpp @@ -241,7 +241,7 @@ void HumanoidModel::setupAnim(float time, float r, float bob, float yRot, float if (riding) { - if(uiBitmaskOverrideAnim&(1<xRot += -HALF_PI * 0.4f; arm1->xRot += -HALF_PI * 0.4f; diff --git a/Minecraft.Client/ItemInHandRenderer.cpp b/Minecraft.Client/ItemInHandRenderer.cpp index 13d4fc20d..749337da1 100644 --- a/Minecraft.Client/ItemInHandRenderer.cpp +++ b/Minecraft.Client/ItemInHandRenderer.cpp @@ -286,6 +286,20 @@ void ItemInHandRenderer::renderItem(shared_ptr mob, shared_ptrgetAnimOverrideBitmask() & (1 << HumanoidModel::eAnim_SmallModel)) + { + if (mob->isRiding()) + { + std::shared_ptr ridingEntity = mob->riding; + if (ridingEntity != nullptr) // Safety check; + { + yo += 0.3f; // reverts the change in Boat.cpp for smaller models. + } + } + } glEnable(GL_RESCALE_NORMAL); glTranslatef(-xo, -yo, 0); diff --git a/Minecraft.Client/PlayerRenderer.cpp b/Minecraft.Client/PlayerRenderer.cpp index 23dff77f8..bc4c61a73 100644 --- a/Minecraft.Client/PlayerRenderer.cpp +++ b/Minecraft.Client/PlayerRenderer.cpp @@ -199,11 +199,26 @@ void PlayerRenderer::render(shared_ptr _mob, double x, double y, double armorParts1->sneaking = armorParts2->sneaking = humanoidModel->sneaking = mob->isSneaking(); double yp = y - mob->heightOffset; - if (mob->isSneaking() && !mob->instanceof(eTYPE_LOCALPLAYER)) + if (mob->isSneaking()) { yp -= 2 / 16.0f; } + if (mob->getAnimOverrideBitmask() & (1 << HumanoidModel::eAnim_SmallModel)) + { + if (mob->isRiding()) + { + std::shared_ptr ridingEntity = mob->riding; + if (ridingEntity != nullptr) // Safety check; + { + if (ridingEntity->instanceof(eTYPE_BOAT)) + { + yp += 0.25f; // reverts the change in Boat.cpp for smaller models. + } + } + } + } + // Check if an idle animation is needed if(mob->getAnimOverrideBitmask()&(1< Date: Fri, 3 Apr 2026 22:01:48 +0200 Subject: [PATCH 05/25] Quality of life netherportal fix (#1337) * Working New portal checks fixed x axis portal with obsidian on z axis * Removed Debug code * Remove unnecessary code removed PortalTile:: from PortalTile::validPortalFrame * Remove more debug code --- Minecraft.World/PortalTile.cpp | 64 ++++++++++++++++++++++++---------- Minecraft.World/PortalTile.h | 1 + 2 files changed, 47 insertions(+), 18 deletions(-) diff --git a/Minecraft.World/PortalTile.cpp b/Minecraft.World/PortalTile.cpp index 5e664e656..1b64212b8 100644 --- a/Minecraft.World/PortalTile.cpp +++ b/Minecraft.World/PortalTile.cpp @@ -67,21 +67,8 @@ bool PortalTile::isCubeShaped() return false; } -bool PortalTile::trySpawnPortal(Level *level, int x, int y, int z, bool actuallySpawn) +bool PortalTile::validPortalFrame(Level* level, int x, int y, int z, int xd, int zd, bool actuallySpawn) { - int xd = 0; - int zd = 0; - if (level->getTile(x - 1, y, z) == Tile::obsidian_Id || level->getTile(x + 1, y, z) == Tile::obsidian_Id) xd = 1; - if (level->getTile(x, y, z - 1) == Tile::obsidian_Id || level->getTile(x, y, z + 1) == Tile::obsidian_Id) zd = 1; - - if (xd == zd) return false; - - if (level->getTile(x - xd, y, z - zd) == 0) - { - x -= xd; - z -= zd; - } - for (int xx = -1; xx <= 2; xx++) { for (int yy = -1; yy <= 3; yy++) @@ -101,9 +88,7 @@ bool PortalTile::trySpawnPortal(Level *level, int x, int y, int z, bool actually } } } - - if( !actuallySpawn ) - return true; + if (!actuallySpawn) return true; for (int xx = 0; xx < 2; xx++) { @@ -112,9 +97,52 @@ bool PortalTile::trySpawnPortal(Level *level, int x, int y, int z, bool actually level->setTileAndData(x + xd * xx, y + yy, z + zd * xx, Tile::portalTile_Id, 0, Tile::UPDATE_CLIENTS); } } - + return true; +} +bool PortalTile::trySpawnPortal(Level *level, int x, int y, int z, bool actuallySpawn) +{ + int xd = 0; + int zd = 0; + if (level->getTile(x - 1, y, z) == Tile::obsidian_Id || level->getTile(x + 1, y, z) == Tile::obsidian_Id) xd = 1; + if (level->getTile(x, y, z - 1) == Tile::obsidian_Id || level->getTile(x, y, z + 1) == Tile::obsidian_Id) zd = 1; + + bool twoPosible = false; // two neth portals posible (x and z direction) + if (xd == zd) + { + if (xd == 1) twoPosible = true; + else return false; + } + + bool changedx = false; // changed x so it can be reverted if two portals are posible + if (level->getTile(x - xd, y, z) == 0) + { + changedx = true; + x--; + } + else if (level->getTile(x, y, z - zd) == 0 && !twoPosible) + { + z--; + } + + if (!twoPosible) + { + if (!validPortalFrame(level, x, y, z, xd, zd, actuallySpawn)) return false; + } + else + { + if (!validPortalFrame(level, x, y, z, xd, 0, actuallySpawn)) + { + if (changedx) x++; // revert x (this check wants to check z not x and z) + + if (level->getTile(x, y, z - zd) == 0) z--; + + if (!validPortalFrame(level, x, y, z, 0, zd, actuallySpawn)) + return false; + } + } + return true; } void PortalTile::neighborChanged(Level *level, int x, int y, int z, int type) diff --git a/Minecraft.World/PortalTile.h b/Minecraft.World/PortalTile.h index 7be4320f2..7415efbf2 100644 --- a/Minecraft.World/PortalTile.h +++ b/Minecraft.World/PortalTile.h @@ -13,6 +13,7 @@ public: virtual void updateShape(LevelSource *level, int x, int y, int z, int forceData = -1, shared_ptr forceEntity = shared_ptr()); // 4J added forceData, forceEntity param virtual bool isSolidRender(bool isServerLevel = false); virtual bool isCubeShaped(); + virtual bool validPortalFrame(Level* level, int x, int y, int z, int xd, int zd, bool actuallySpawn); virtual bool trySpawnPortal(Level *level, int x, int y, int z, bool actuallySpawn); virtual void neighborChanged(Level *level, int x, int y, int z, int type); virtual bool shouldRenderFace(LevelSource *level, int x, int y, int z, int face); From 5e5849102f713f9bd4bd7fe6b5bf3684c0ac6bdc Mon Sep 17 00:00:00 2001 From: Loki Date: Fri, 3 Apr 2026 16:55:20 -0500 Subject: [PATCH 06/25] Add info about backports we will accept. --- BACKPORTING.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 BACKPORTING.md diff --git a/BACKPORTING.md b/BACKPORTING.md new file mode 100644 index 000000000..484fb3d23 --- /dev/null +++ b/BACKPORTING.md @@ -0,0 +1,15 @@ +# Approach to Backported Features +All backported features incorperated into MinecraftConsoles should be, when merged, functionally identical to their state in the version of the game we're currently targeting. This should be in reference to a known 4J build of LCE. Verification can either be done by doing a decompilation based match of the implementation or, alternatively, all functionality and limitations of the given feature should be compared against the version of LCE we're targeting. + +# Approach to Bugfixes +Anything that does not behave in an "expected" manner, especially if its behavior is not widely accepted as a gameplay mechanic, is valid for fixing in our repository. This includes bugfixes that were made in versions past the version we target, but excludes any visual changes that may not have been included at the build we're targeting. + +If you provide a visual bugfix that fixes a distinctive quirk of the LCE renderer, it should be provided in an "off by default" state that can be toggled on in-game by the user. There is no guarantee that we will merge it. + +If your visual bugfix is a fix added in a future version of LCE than the one we're targeting, it should also be put behind a toggle or equivalent system for keeping it off by default. + +# Targeted Version +We are currently accepting backports for up to and including TU24. Feature backports from TU25 and above will not be accepted. + +# Original Codebase +MinecraftConsoles is based on a WIP build of TU19, built on top of the December 2014 codebase. From 7dfe46aa5de55cc643ff7fc007369fd9a8275842 Mon Sep 17 00:00:00 2001 From: Loki Date: Fri, 3 Apr 2026 16:56:05 -0500 Subject: [PATCH 07/25] Add backporting link to Contributor's Guide --- CONTRIBUTING.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 855491da1..fd5d7f03f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,9 @@ # Scope of Project At the moment, this project's scope is generally limited outside of adding new content to the game (blocks, mobs, items). We are currently prioritizing stability, quality of life, and platform support over these things. +## Backporting +If you're backporting a feature, please read [BACKPORTING.md](./BACKPORTING.md) + ## Parity We are attempting to keep our version of LCE as close to visual and experience parity with the original console experience of LCE as possible. This means that we will not be accepting changes that... - Backport things from Java Edition that did not ever exist in LCE From a4e689095ce3d7dacf7dfc636890eee6f5c9caae Mon Sep 17 00:00:00 2001 From: Sylvessa <225480449+sylvessa@users.noreply.github.com> Date: Sat, 4 Apr 2026 22:04:02 -0500 Subject: [PATCH 08/25] fix: wither and ender dragon custom names (#1472) --- Minecraft.Client/EnderDragonRenderer.cpp | 5 +++++ Minecraft.Client/WitherBossRenderer.cpp | 4 ++++ Minecraft.World/EnderDragon.h | 2 +- Minecraft.World/WitherBoss.h | 2 +- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Minecraft.Client/EnderDragonRenderer.cpp b/Minecraft.Client/EnderDragonRenderer.cpp index 8b5b248c2..424bdff8e 100644 --- a/Minecraft.Client/EnderDragonRenderer.cpp +++ b/Minecraft.Client/EnderDragonRenderer.cpp @@ -89,6 +89,11 @@ void EnderDragonRenderer::render(shared_ptr _mob, double x, double y, do // 4J - dynamic cast required because we aren't using templates/generics in our version shared_ptr mob = dynamic_pointer_cast(_mob); BossMobGuiInfo::setBossHealth(mob, false); + if (!mob->getCustomName().empty()) + { + BossMobGuiInfo::name = mob->getCustomName(); + } + MobRenderer::render(mob, x, y, z, rot, a); if (mob->nearestCrystal != nullptr) { diff --git a/Minecraft.Client/WitherBossRenderer.cpp b/Minecraft.Client/WitherBossRenderer.cpp index e358c6dab..dc1d8f923 100644 --- a/Minecraft.Client/WitherBossRenderer.cpp +++ b/Minecraft.Client/WitherBossRenderer.cpp @@ -20,6 +20,10 @@ void WitherBossRenderer::render(shared_ptr entity, double x, double y, d shared_ptr mob = dynamic_pointer_cast(entity); BossMobGuiInfo::setBossHealth(mob, true); + if (!mob->getCustomName().empty()) + { + BossMobGuiInfo::name = mob->getCustomName(); + } int modelVersion = dynamic_cast(model)->modelVersion(); if (modelVersion != this->modelVersion) diff --git a/Minecraft.World/EnderDragon.h b/Minecraft.World/EnderDragon.h index 9f39767eb..1bb8f5ce1 100644 --- a/Minecraft.World/EnderDragon.h +++ b/Minecraft.World/EnderDragon.h @@ -183,7 +183,7 @@ public: double getHeadPartYRotDiff(int partIndex, doubleArray bodyPos, doubleArray partPos); Vec3 *getHeadLookVector(float a); - virtual wstring getAName() { return app.GetString(IDS_ENDERDRAGON); }; + virtual wstring getAName() { if (hasCustomName()) return getCustomName(); return app.GetString(IDS_ENDERDRAGON); }; virtual float getHealth() { return LivingEntity::getHealth(); }; virtual float getMaxHealth() { return LivingEntity::getMaxHealth(); }; }; diff --git a/Minecraft.World/WitherBoss.h b/Minecraft.World/WitherBoss.h index 47e2dff18..e066908ec 100644 --- a/Minecraft.World/WitherBoss.h +++ b/Minecraft.World/WitherBoss.h @@ -105,5 +105,5 @@ public: // 4J Stu - These are required for the BossMob interface virtual float getMaxHealth() { return Monster::getMaxHealth(); }; virtual float getHealth() { return Monster::getHealth(); }; - virtual wstring getAName() { return app.GetString(IDS_WITHER); }; + virtual wstring getAName() { if (hasCustomName()) return getCustomName(); return app.GetString(IDS_WITHER); }; }; \ No newline at end of file From c2ea1fa62b422ae682c1adf41677b937cd0df13e Mon Sep 17 00:00:00 2001 From: Sylvessa <225480449+sylvessa@users.noreply.github.com> Date: Sun, 5 Apr 2026 12:51:37 -0500 Subject: [PATCH 09/25] optimization: remove redundant lastTime setter (#1479) --- Minecraft.Client/MinecraftServer.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Minecraft.Client/MinecraftServer.cpp b/Minecraft.Client/MinecraftServer.cpp index 27ee68b65..1e3ed74ef 100644 --- a/Minecraft.Client/MinecraftServer.cpp +++ b/Minecraft.Client/MinecraftServer.cpp @@ -1795,7 +1795,6 @@ void MinecraftServer::run(int64_t seed, void *lpParameter) chunkPacketManagement_PostTick(); } - lastTime = getCurrentTimeMillis(); // int64_t afterall = System::currentTimeMillis(); // PIXReportCounter(L"Server time all",(float)(afterall-beforeall)); // PIXReportCounter(L"Server ticks",(float)tickcount); From 034c313ddf3ed6539eac91c9f320ff588ee3111d Mon Sep 17 00:00:00 2001 From: Sylvessa <225480449+sylvessa@users.noreply.github.com> Date: Sun, 5 Apr 2026 12:57:43 -0500 Subject: [PATCH 10/25] optimization: async dedicated server autosaving (#1473) --- Minecraft.Server/Windows64/ServerMain.cpp | 13 +++ Minecraft.Server/cmake/sources/Common.cmake | 2 + Minecraft.World/ConsoleSaveFileOriginal.cpp | 123 ++++++++++++++++++++ Minecraft.World/ConsoleSaveFileOriginal.h | 5 + 4 files changed, 143 insertions(+) diff --git a/Minecraft.Server/Windows64/ServerMain.cpp b/Minecraft.Server/Windows64/ServerMain.cpp index a8d5fc66b..c54bd3851 100644 --- a/Minecraft.Server/Windows64/ServerMain.cpp +++ b/Minecraft.Server/Windows64/ServerMain.cpp @@ -28,6 +28,7 @@ #include "../../Minecraft.World/TilePos.h" #include "../../Minecraft.World/compression.h" #include "../../Minecraft.World/OldChunkStorage.h" +#include "../../Minecraft.World/ConsoleSaveFileOriginal.h" #include "../../Minecraft.World/net.minecraft.world.level.tile.h" #include "../../Minecraft.World/Random.h" @@ -325,6 +326,7 @@ static void TickCoreSystems() g_NetworkManager.DoWork(); ProfileManager.Tick(); StorageManager.Tick(); + ConsoleSaveFileOriginal::flushPendingBackgroundSave(); } /** @@ -701,9 +703,20 @@ int main(int argc, char **argv) { C4JThread waitThread(&WaitForServerStoppedThreadProc, NULL, "WaitServerStopped"); waitThread.Run(); + while (waitThread.isRunning()) + { + TickCoreSystems(); + Sleep(10); + } waitThread.WaitForCompletion(INFINITE); } + while (ConsoleSaveFileOriginal::hasPendingBackgroundSave()) + { + TickCoreSystems(); + Sleep(10); + } + LogInfof("shutdown", "Cleaning up and exiting."); WinsockNetLayer::Shutdown(); LogDebugf("shutdown", "Network layer shutdown complete."); diff --git a/Minecraft.Server/cmake/sources/Common.cmake b/Minecraft.Server/cmake/sources/Common.cmake index 06aa0bfe1..1eaceee16 100644 --- a/Minecraft.Server/cmake/sources/Common.cmake +++ b/Minecraft.Server/cmake/sources/Common.cmake @@ -494,6 +494,8 @@ set(_MINECRAFT_SERVER_COMMON_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.Client/iob_shim.asm" "${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.Client/stdafx.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.Client/stubs.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.World/ConsoleSaveFileOriginal.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.World/ConsoleSaveFileOriginal.h" "${CMAKE_CURRENT_SOURCE_DIR}/../include/lce_filesystem/lce_filesystem.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Console/ServerCliInput.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Console/ServerCliInput.h" diff --git a/Minecraft.World/ConsoleSaveFileOriginal.cpp b/Minecraft.World/ConsoleSaveFileOriginal.cpp index 8a7d1f9ec..4d03c955d 100644 --- a/Minecraft.World/ConsoleSaveFileOriginal.cpp +++ b/Minecraft.World/ConsoleSaveFileOriginal.cpp @@ -12,6 +12,26 @@ #include "..\Minecraft.Client\Common\GameRules\LevelGenerationOptions.h" #include "..\Minecraft.World\net.minecraft.world.level.chunk.storage.h" +#ifdef MINECRAFT_SERVER_BUILD +#include +#include +#include + +static std::atomic s_bgSaveActive{false}; +static std::mutex s_bgSaveMutex; + +struct BackgroundSaveResult +{ + ConsoleSaveFile *owner = nullptr; + PBYTE thumbData = nullptr; + DWORD thumbSize = 0; + BYTE textMeta[88] = {}; + int textMetaBytes = 0; + bool pending = false; +}; +static BackgroundSaveResult s_bgResult; +#endif + #ifdef _XBOX #define RESERVE_ALLOCATION MEM_RESERVE | MEM_LARGE_PAGES @@ -673,6 +693,83 @@ void ConsoleSaveFileOriginal::Flush(bool autosave, bool updateThumbnail ) unsigned int fileSize = header.GetFileSize(); +#ifdef MINECRAFT_SERVER_BUILD + // on the server we dont want to block the tick thread doing compression!!! + // sna[pshot pvSaveMem while we still hold the lock then hand it off to a background thread + byte *snap = new (std::nothrow) byte[fileSize]; + if (snap) + { + // copy the save buffer while we still own the lock so nothing can write to it mid-copy + QueryPerformanceCounter(&qwTime); + memcpy(snap, pvSaveMem, fileSize); + QueryPerformanceCounter(&qwNewTime); + app.DebugPrintf("snapshot %u bytes in %.3f sec\n", fileSize, + (qwNewTime.QuadPart - qwTime.QuadPart) * fSecsPerTick); + + PBYTE thumb = nullptr; + DWORD thumbSz = 0; + app.GetSaveThumbnail(&thumb, &thumbSz); + + BYTE meta[88]; + ZeroMemory(meta, 88); + int64_t seed = 0; + bool hasSeed = false; + if (MinecraftServer *sv = MinecraftServer::getInstance(); sv && sv->levels[0]) + { + seed = sv->levels[0]->getLevelData()->getSeed(); + hasSeed = true; + } + int metaLen = app.CreateImageTextData(meta, seed, hasSeed, + app.GetGameHostOption(eGameHostOption_All), Minecraft::GetInstance()->getCurrentTexturePackId()); + + // telemetry + INT uid = 0; + StorageManager.GetSaveUniqueNumber(&uid); + TelemetryManager->RecordLevelSaveOrCheckpoint(ProfileManager.GetPrimaryPad(), uid, fileSize); + + ReleaseSaveAccess(); + s_bgSaveActive.store(true, std::memory_order_release); + + std::thread([snap, fileSize, thumb, thumbSz, meta, metaLen, this]() { + unsigned int compLen = fileSize + 8; + byte *buf = static_cast(StorageManager.AllocateSaveData(compLen)); + if (!buf) + { + // FAIL!! attempt precalc + compLen = 0; + Compression::getCompression()->Compress(nullptr, &compLen, snap, fileSize); + compLen += 8; + buf = static_cast(StorageManager.AllocateSaveData(compLen)); + } + if (buf) + { + // COM,PRESS + Compression::getCompression()->Compress(buf + 8, &compLen, snap, fileSize); + ZeroMemory(buf, 8); + memcpy(buf + 4, &fileSize, sizeof(fileSize)); + + // store the result so flushPendingBackgroundSave() can pick it up on the main thread next tick + // StorageManager isnt thread safe so we cant call SetSaveImages or SaveSaveData from here. Bwoomp + std::lock_guard lk(s_bgSaveMutex); + s_bgResult.owner = this; + s_bgResult.thumbData = thumb; + s_bgResult.thumbSize = thumbSz; + memcpy(s_bgResult.textMeta, meta, sizeof(meta)); + s_bgResult.textMetaBytes = metaLen; + s_bgResult.pending = true; + } + else + { + app.DebugPrintf("save buf alloc failed\n"); + s_bgSaveActive.store(false, std::memory_order_release); + } + delete[] snap; + }).detach(); + return; + } + app.DebugPrintf("snapshot alloc failed (%u bytes)\n", fileSize); +#endif + // Assume that the compression will make it smaller so initially attempt to allocate the current file size // We add 4 bytes to the start so that we can signal compressed data // And another 4 bytes to store the decompressed data size @@ -838,6 +935,10 @@ int ConsoleSaveFileOriginal::SaveSaveDataCallback(LPVOID lpParam,bool bRes) { ConsoleSaveFile *pClass=static_cast(lpParam); +#ifdef MINECRAFT_SERVER_BUILD + s_bgSaveActive.store(false, std::memory_order_release); +#endif + return 0; } @@ -1085,3 +1186,25 @@ void *ConsoleSaveFileOriginal::getWritePointer(FileEntry *file) { return static_cast(pvSaveMem) + file->currentFilePointer;; } + +#ifdef MINECRAFT_SERVER_BUILD +void ConsoleSaveFileOriginal::flushPendingBackgroundSave() +{ + std::lock_guard lk(s_bgSaveMutex); + if (!s_bgResult.pending) + return; + + StorageManager.SetSaveImages( + s_bgResult.thumbData, s_bgResult.thumbSize, + nullptr, 0, s_bgResult.textMeta, s_bgResult.textMetaBytes); + StorageManager.SaveSaveData(&ConsoleSaveFileOriginal::SaveSaveDataCallback, s_bgResult.owner); + + s_bgResult.pending = false; + // the actual write isnt done until SaveSaveDataCallback fires +} + +bool ConsoleSaveFileOriginal::hasPendingBackgroundSave() +{ + return s_bgSaveActive.load(std::memory_order_acquire); +} +#endif diff --git a/Minecraft.World/ConsoleSaveFileOriginal.h b/Minecraft.World/ConsoleSaveFileOriginal.h index 9c91fafcf..453cacd91 100644 --- a/Minecraft.World/ConsoleSaveFileOriginal.h +++ b/Minecraft.World/ConsoleSaveFileOriginal.h @@ -77,6 +77,11 @@ public: virtual void LockSaveAccess(); virtual void ReleaseSaveAccess(); +#ifdef MINECRAFT_SERVER_BUILD + static void flushPendingBackgroundSave(); + static bool hasPendingBackgroundSave(); +#endif + virtual ESavePlatform getSavePlatform(); virtual bool isSaveEndianDifferent(); virtual void setLocalPlatform(); From 98a86fc69b7d452c03f1a5f6652fae914c41f623 Mon Sep 17 00:00:00 2001 From: Fireblade <72758695+Firebladedoge229@users.noreply.github.com> Date: Mon, 6 Apr 2026 13:33:45 -0400 Subject: [PATCH 11/25] feat. set intro scene background to white (#1474) --- Minecraft.Client/Windows64/Windows64_Minecraft.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp index fa5f4cccb..b24350441 100644 --- a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp +++ b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp @@ -472,6 +472,8 @@ IDXGISwapChain* g_pSwapChain = nullptr; ID3D11RenderTargetView* g_pRenderTargetView = nullptr; ID3D11DepthStencilView* g_pDepthStencilView = nullptr; ID3D11Texture2D* g_pDepthStencilBuffer = nullptr; +static const float kClearColorWhite[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; +static const float kClearColorBlack[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; // // FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM) @@ -1564,7 +1566,14 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, continue; } + const float* clearColor = app.GetGameStarted() ? kClearColorBlack : kClearColorWhite; + RenderManager.SetClearColour(clearColor); RenderManager.StartFrame(); + if (!app.GetGameStarted()) + { + RenderManager.SetClearColour(kClearColorWhite); // set intro scene background to white + RenderManager.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } #if 0 if(pMinecraft->soundEngine->isStreamingWavebankReady() && !pMinecraft->soundEngine->isPlayingStreamingGameMusic() && From 413baaceed6fb9243a0346c36062217836bf6c80 Mon Sep 17 00:00:00 2001 From: Sylvessa <225480449+sylvessa@users.noreply.github.com> Date: Mon, 6 Apr 2026 12:34:02 -0500 Subject: [PATCH 12/25] fix: reorder autosave tick to account for weak hardware (#1482) --- Minecraft.Server/Windows64/ServerMain.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Minecraft.Server/Windows64/ServerMain.cpp b/Minecraft.Server/Windows64/ServerMain.cpp index c54bd3851..811334af1 100644 --- a/Minecraft.Server/Windows64/ServerMain.cpp +++ b/Minecraft.Server/Windows64/ServerMain.cpp @@ -657,7 +657,7 @@ int main(int argc, char **argv) break; } - if (autosaveRequested && app.GetXuiServerAction(kServerActionPad) == eXuiServerAction_Idle) + if (autosaveRequested && app.GetXuiServerAction(kServerActionPad) == eXuiServerAction_Idle && !ConsoleSaveFileOriginal::hasPendingBackgroundSave()) { LogWorldIO("autosave completed"); autosaveRequested = false; @@ -671,7 +671,7 @@ int main(int argc, char **argv) DWORD now = GetTickCount(); if ((LONG)(now - nextAutosaveTick) >= 0) { - if (app.GetXuiServerAction(kServerActionPad) == eXuiServerAction_Idle) + if (app.GetXuiServerAction(kServerActionPad) == eXuiServerAction_Idle && !ConsoleSaveFileOriginal::hasPendingBackgroundSave()) { LogWorldIO("requesting autosave"); app.SetXuiServerAction(kServerActionPad, eXuiServerAction_AutoSaveGame); @@ -687,16 +687,18 @@ int main(int argc, char **argv) LogInfof("shutdown", "Dedicated server stopped"); MinecraftServer *server = MinecraftServer::getInstance(); - if (server != NULL) - { - server->setSaveOnExit(true); - } - if (server != NULL) + if (server != NULL && !ConsoleSaveFileOriginal::hasPendingBackgroundSave()) { + server->setSaveOnExit(true); LogWorldIO("requesting save before shutdown"); LogWorldIO("using saveOnExit for shutdown"); } + if (ConsoleSaveFileOriginal::hasPendingBackgroundSave()) + { + LogWorldIO("Waiting for autosave to complete..."); + } + MinecraftServer::HaltServer(); if (g_NetworkManager.ServerStoppedValid()) From b928351e0b72d7d1db9f1c7ff393735f441551dc Mon Sep 17 00:00:00 2001 From: rucheykov Date: Mon, 6 Apr 2026 20:34:25 +0300 Subject: [PATCH 13/25] Update Windows64_Minecraft.cpp (#1468) --- .../Windows64/Windows64_Minecraft.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp index b24350441..bee49df0e 100644 --- a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp +++ b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp @@ -665,7 +665,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) } break; default: - return DefWindowProc(hWnd, message, wParam, lParam); + return DefWindowProcW(hWnd, message, wParam, lParam); } return 0; } @@ -677,23 +677,23 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) // ATOM MyRegisterClass(HINSTANCE hInstance) { - WNDCLASSEX wcex; + WNDCLASSEXW wcex; - wcex.cbSize = sizeof(WNDCLASSEX); + wcex.cbSize = sizeof(WNDCLASSEXW); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; - wcex.hIcon = LoadIcon(hInstance, "Minecraft"); + wcex.hIcon = LoadIconW(hInstance, L"Minecraft"); wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); - wcex.lpszMenuName = "Minecraft"; - wcex.lpszClassName = "MinecraftClass"; + wcex.lpszMenuName = L"Minecraft"; + wcex.lpszClassName = L"MinecraftClass"; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_MINECRAFTWINDOWS)); - return RegisterClassEx(&wcex); + return RegisterClassExW(&wcex); } // @@ -713,8 +713,8 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) RECT wr = {0, 0, g_rScreenWidth, g_rScreenHeight}; // set the size, but not the position AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE); // adjust the size - g_hWnd = CreateWindow( "MinecraftClass", - "Minecraft", + g_hWnd = CreateWindowW( L"MinecraftClass", + L"Minecraft", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, From 29edc4aff09cc37f7d88605cf4d4b79ba1021c51 Mon Sep 17 00:00:00 2001 From: Loki Date: Tue, 7 Apr 2026 14:31:30 -0500 Subject: [PATCH 14/25] Link to new Discord --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 303728adf..f948642de 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ![Legacy Edition Banner](.github/banner.png) # MinecraftConsoles (Legacy Console Edition) -[![Discord](https://img.shields.io/badge/Discord-Join%20Server-5865F2?logo=discord&logoColor=white)](https://discord.gg/jrum7HhegA) +[![Discord](https://img.shields.io/badge/Discord-Join%20Server-5865F2?logo=discord&logoColor=white)](https://discord.gg/dH8AZWGcau) This project is based on source code of Minecraft Legacy Console Edition v1.6.0560.0 (TU19) with some fixes and improvements applied. From 108e3dc233a5233b4001d578f0fdbe22c87ad37b Mon Sep 17 00:00:00 2001 From: Loki Date: Tue, 7 Apr 2026 15:52:48 -0500 Subject: [PATCH 15/25] Whitespace adjustment to test GitHub webhook --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f948642de..859c90526 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ The current goal of MinecraftConsoles is to be a multi-platform base for further See our our [Contributor's Guide](./CONTRIBUTING.md) for more information on the goals of this project. -## Download +## Download ### Client Windows users can download our [Nightly Build](https://github.com/smartcmd/MinecraftConsoles/releases/tag/nightly)! Simply download the `.zip` file and extract it to a folder where you'd like to keep the game. You can set your username in `username.txt` (you'll have to make this file) ### Server From 126943e06e8508447518ce625f3311a05d3f17ff Mon Sep 17 00:00:00 2001 From: Loki Date: Tue, 7 Apr 2026 17:44:00 -0500 Subject: [PATCH 16/25] Add details about org change to README --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 859c90526..db750d388 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,14 @@ [![Discord](https://img.shields.io/badge/Discord-Join%20Server-5865F2?logo=discord&logoColor=white)](https://discord.gg/dH8AZWGcau) +--- +## IMPORTANT UPDATE +**This repo was moved to a new org!** + +Please change all links and references from `smartcmd/MinecraftConsoles` to `MCLCE/MinecraftConsoles` instead. + +--- + This project is based on source code of Minecraft Legacy Console Edition v1.6.0560.0 (TU19) with some fixes and improvements applied. The current goal of MinecraftConsoles is to be a multi-platform base for further development, such as modding, backports, and anything else LCE. On top of that, we're working to make this a quality experience on Desktop with or without a controller while (long-term) retaining console support. From d0786f956d14c86bbaf93ebc76087a37cb9298d0 Mon Sep 17 00:00:00 2001 From: Loki Rautio Date: Tue, 7 Apr 2026 20:29:32 -0500 Subject: [PATCH 17/25] Update more references to old smartcmd repo --- .../Common/UI/UIScene_Credits.cpp | 22 ++++++++++--------- README.md | 6 ++--- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/Minecraft.Client/Common/UI/UIScene_Credits.cpp b/Minecraft.Client/Common/UI/UIScene_Credits.cpp index 02dc66201..8c8d43bc1 100644 --- a/Minecraft.Client/Common/UI/UIScene_Credits.cpp +++ b/Minecraft.Client/Common/UI/UIScene_Credits.cpp @@ -491,17 +491,19 @@ SCreditTextItemDef UIScene_Credits::gs_aCreditDefs[MAX_CREDIT_STRINGS] = {L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText}, {L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText}, {L"MinecraftConsoles", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eExtraLargeText}, - {L"Project Maintainers", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eLargeText}, - {L"smartcmd", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText}, - {L"codeHusky", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText}, - {L"Patoke", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText}, - {L"rtm516", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText}, - {L"mattsumi", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText}, - {L"dxf", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText}, - {L"la", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText}, {L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText}, - {L"Thank you to our 100+ contributors on GitHub!", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eLargeText}, - {L"github.com/smartcmd/MinecraftConsoles", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText}, + {L"Project Maintainers", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eLargeText}, + {L"codeHusky", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText}, + {L"mattsumi", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText}, + {L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText}, + {L"Former Maintainers", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eLargeText}, + {L"smartcmd", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText}, + {L"Patoke", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText}, + {L"rtm516", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText}, + {L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText}, + {L"Thank you to our 120+ contributors on GitHub!", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eLargeText}, + {L"github.com/MCLCE/MinecraftConsoles", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText}, + {L"(formerly smartcmd/MinecraftConsoles)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText}, {L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText}, {L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText}, {L"Additional Thanks", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eLargeText}, diff --git a/README.md b/README.md index db750d388..560a798a5 100644 --- a/README.md +++ b/README.md @@ -19,9 +19,9 @@ See our our [Contributor's Guide](./CONTRIBUTING.md) for more information on the ## Download ### Client -Windows users can download our [Nightly Build](https://github.com/smartcmd/MinecraftConsoles/releases/tag/nightly)! Simply download the `.zip` file and extract it to a folder where you'd like to keep the game. You can set your username in `username.txt` (you'll have to make this file) +Windows users can download our [Nightly Build](https://github.com/MCLCE/MinecraftConsoles/releases/tag/nightly)! Simply download the `.zip` file and extract it to a folder where you'd like to keep the game. You can set your username in `username.txt` (you'll have to make this file) ### Server -If you're looking for Dedicated Server software, download its [Nightly Build here](https://github.com/smartcmd/MinecraftConsoles/releases/tag/nightly-dedicated-server). Similar instructions to the client more or less, though see further down in this README for more info on that. +If you're looking for Dedicated Server software, download its [Nightly Build here](https://github.com/MCLCE/MinecraftConsoles/releases/tag/nightly-dedicated-server). Similar instructions to the client more or less, though see further down in this README for more info on that. ## Platform Support @@ -228,4 +228,4 @@ For more information, see [COMPILE.md](COMPILE.md). ## Star History -[![Star History Chart](https://api.star-history.com/svg?repos=smartcmd/MinecraftConsoles&type=date&legend=top-left)](https://www.star-history.com/?spm=a2c6h.12873639.article-detail.7.7b9d7fabjNxTRk#smartcmd/MinecraftConsoles&type=date&legend=top-left) +[![Star History Chart](https://api.star-history.com/svg?repos=MCLCE/MinecraftConsoles&type=date&legend=top-left)](https://www.star-history.com/?spm=a2c6h.12873639.article-detail.7.7b9d7fabjNxTRk#MCLCE/MinecraftConsoles&type=date&legend=top-left) From d25b762ca55626413afa624c86c8bace7c3356a2 Mon Sep 17 00:00:00 2001 From: Tyler Reese Date: Wed, 8 Apr 2026 20:34:48 -0700 Subject: [PATCH 18/25] Fix _jeb easter egg on sheep (#1488) Fixed the original jeb sheep behavior. For some reason the later code (now commented out) just completely overrid it --- Minecraft.Client/SheepRenderer.cpp | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/Minecraft.Client/SheepRenderer.cpp b/Minecraft.Client/SheepRenderer.cpp index 434505781..24e03a815 100644 --- a/Minecraft.Client/SheepRenderer.cpp +++ b/Minecraft.Client/SheepRenderer.cpp @@ -32,20 +32,30 @@ int SheepRenderer::prepareArmor(shared_ptr _sheep, int layer, floa int c2 = (value + 1) % Sheep::COLOR_LENGTH; float subStep = ((sheep->tickCount % colorDuration) + a) / static_cast(colorDuration); - glColor3f(Sheep::COLOR[c1][0] * (1.0f - subStep) + Sheep::COLOR[c2][0] * subStep, Sheep::COLOR[c1][1] * (1.0f - subStep) + Sheep::COLOR[c2][1] * subStep, Sheep::COLOR[c1][2] - * (1.0f - subStep) + Sheep::COLOR[c2][2] * subStep); + glColor3f( + Sheep::COLOR[c1][0] * (1.0f - subStep) + Sheep::COLOR[c2][0] * subStep, + Sheep::COLOR[c1][1] * (1.0f - subStep) + Sheep::COLOR[c2][1] * subStep, + Sheep::COLOR[c1][2] * (1.0f - subStep) + Sheep::COLOR[c2][2] * subStep); } else { - int color = sheep->getColor(); - glColor3f(Sheep::COLOR[color][0], Sheep::COLOR[color][1], Sheep::COLOR[color][2]); + float brightness = SharedConstants::TEXTURE_LIGHTING ? 1.0f : sheep->getBrightness(a); + int color = sheep->getColor(); + glColor3f(brightness * Sheep::COLOR[color][0], brightness * Sheep::COLOR[color][1], brightness * Sheep::COLOR[color][2]); + } // 4J - change brought forward from 1.8.2 - float brightness = SharedConstants::TEXTURE_LIGHTING ? 1.0f : sheep->getBrightness(a); - int color = sheep->getColor(); - glColor3f(brightness * Sheep::COLOR[color][0], brightness * Sheep::COLOR[color][1], brightness * Sheep::COLOR[color][2]); + + + /* Fix; this code originally completely overrided the _jeb and normal textures so i just commented it out and updated the part that should have worked. + + float brightness = SharedConstants::TEXTURE_LIGHTING ? 1.0f : sheep->getBrightness(a); + int color = sheep->getColor(); + glColor3f(brightness * Sheep::COLOR[color][0], brightness * Sheep::COLOR[color][1], brightness * Sheep::COLOR[color][2]); */ + + return 1; } return -1; From 744048f4551af13a0281a78d5136223810a588fb Mon Sep 17 00:00:00 2001 From: DrPerkyLegit <116128211+DrPerkyLegit@users.noreply.github.com> Date: Sun, 12 Apr 2026 23:48:08 -0400 Subject: [PATCH 19/25] Better Text Scaling (#1494) * f3 menu text scaling * Reduce overscaling above 1080p Restores original scaling for 1440p to try and keep the text size more sane on high DPI monitors --------- Co-authored-by: Loki Rautio --- Minecraft.Client/Gui.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Minecraft.Client/Gui.cpp b/Minecraft.Client/Gui.cpp index 5e3a954fe..a01cad89a 100644 --- a/Minecraft.Client/Gui.cpp +++ b/Minecraft.Client/Gui.cpp @@ -1208,7 +1208,20 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse) // Disable the depth test so the text shows on top of the paperdoll glDisable(GL_DEPTH_TEST); +#ifdef _WINDOWS64 + float scaleWidth = (g_rScreenWidth / 1920.0f); + float scaleHeight = (g_rScreenHeight / 1080.0f); + float scale = min(scaleWidth, scaleHeight); //stop stretching + + if (scale < 0.5f) scale = 0.5f; // force minimum scale + if (scale > 1.2f) // resolutions over 1296 pixels tall + { + scale = scale - 0.33f; // tame overscaling on 1440p + } + + glScalef(scale, scale, 1); +#endif // Loop through the lines and draw them all on screen int yPos = debugTop; for (const auto &line : lines) @@ -1217,6 +1230,9 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse) yPos += 10; } +#ifdef _WINDOWS64 + glScalef(1, 1, 1); +#endif // Restore the depth test glEnable(GL_DEPTH_TEST); From c7014f6b18b042b3a6af2b5408b5eef6aa74f0ea Mon Sep 17 00:00:00 2001 From: DrPerkyLegit <116128211+DrPerkyLegit@users.noreply.github.com> Date: Sun, 12 Apr 2026 23:50:16 -0400 Subject: [PATCH 20/25] feat: Scrollable chat (#1493) * chat scrolling * allow escape to close chat instead of opening pause --- Minecraft.Client/ChatScreen.cpp | 18 ++++++++++++ Minecraft.Client/ChatScreen.h | 4 +++ Minecraft.Client/Common/UI/UIController.cpp | 4 +++ Minecraft.Client/Common/UI/UIScene_HUD.cpp | 31 ++++++++++++++++----- Minecraft.Client/Gui.h | 1 + Minecraft.Client/Minecraft.cpp | 8 ++++-- Minecraft.Client/Screen.cpp | 2 +- 7 files changed, 58 insertions(+), 10 deletions(-) diff --git a/Minecraft.Client/ChatScreen.cpp b/Minecraft.Client/ChatScreen.cpp index 53c907224..cb1d875df 100644 --- a/Minecraft.Client/ChatScreen.cpp +++ b/Minecraft.Client/ChatScreen.cpp @@ -11,6 +11,7 @@ const wstring ChatScreen::allowedChars = SharedConstants::acceptableLetters; vector ChatScreen::s_chatHistory; int ChatScreen::s_historyIndex = -1; wstring ChatScreen::s_historyDraft; +int ChatScreen::s_chatIndex = 0; bool ChatScreen::isAllowedChatChar(wchar_t c) { @@ -22,6 +23,8 @@ ChatScreen::ChatScreen() frame = 0; cursorIndex = 0; s_historyIndex = -1; + + ChatScreen::s_chatIndex = 0; } void ChatScreen::init() @@ -83,6 +86,20 @@ void ChatScreen::handleHistoryDown() applyHistoryMessage(); } +int ChatScreen::getChatIndex() +{ + return ChatScreen::s_chatIndex; +} + +void ChatScreen::correctChatIndex(int newChatIndex) { + ChatScreen::s_chatIndex = newChatIndex; +} + +void ChatScreen::setWheelValue(int wheel) { + ChatScreen::s_chatIndex += wheel; + if (ChatScreen::s_chatIndex < 0) ChatScreen::s_chatIndex = 0; +} + void ChatScreen::keyPressed(wchar_t ch, int eventKey) { if (eventKey == Keyboard::KEY_ESCAPE) @@ -131,6 +148,7 @@ void ChatScreen::keyPressed(wchar_t ch, int eventKey) cursorIndex--; return; } + if (isAllowedChatChar(ch) && static_cast(message.length()) < SharedConstants::maxChatLength) { message.insert(cursorIndex, 1, ch); diff --git a/Minecraft.Client/ChatScreen.h b/Minecraft.Client/ChatScreen.h index c4e37a937..70d65e8ce 100644 --- a/Minecraft.Client/ChatScreen.h +++ b/Minecraft.Client/ChatScreen.h @@ -16,6 +16,7 @@ private: static std::vector s_chatHistory; static int s_historyIndex; static wstring s_historyDraft; + static int s_chatIndex; static const wstring allowedChars; static bool isAllowedChatChar(wchar_t c); @@ -28,6 +29,9 @@ public: virtual void handleHistoryUp(); virtual void handleHistoryDown(); + static int getChatIndex(); + static void correctChatIndex(int newChatIndex); + static void setWheelValue(int wheel); protected: void keyPressed(wchar_t ch, int eventKey); public: diff --git a/Minecraft.Client/Common/UI/UIController.cpp b/Minecraft.Client/Common/UI/UIController.cpp index b12ea5e73..046acefe5 100644 --- a/Minecraft.Client/Common/UI/UIController.cpp +++ b/Minecraft.Client/Common/UI/UIController.cpp @@ -1,5 +1,6 @@ #include "stdafx.h" #include "UIController.h" +#include #include "UI.h" #include "UIScene.h" #include "UIControl_Slider.h" @@ -1428,6 +1429,9 @@ void UIController::handleKeyPress(unsigned int iPad, unsigned int key) } #endif + if (key == 4) ChatScreen::setWheelValue(1); + if (key == 5) ChatScreen::setWheelValue(-1); + if(pressed) app.DebugPrintf("Pressed %d\n",key); if(released) app.DebugPrintf("Released %d\n",key); // Repeat handling diff --git a/Minecraft.Client/Common/UI/UIScene_HUD.cpp b/Minecraft.Client/Common/UI/UIScene_HUD.cpp index 213caa8dc..7d34ba0de 100644 --- a/Minecraft.Client/Common/UI/UIScene_HUD.cpp +++ b/Minecraft.Client/Common/UI/UIScene_HUD.cpp @@ -9,6 +9,7 @@ #include "..\..\EnderDragonRenderer.h" #include "..\..\..\Minecraft.World\net.minecraft.world.inventory.h" #include "..\..\..\Minecraft.World\StringHelpers.h" +#include UIScene_HUD::UIScene_HUD(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) { @@ -761,16 +762,31 @@ void UIScene_HUD::render(S32 width, S32 height, C4JRender::eViewportType viewpor void UIScene_HUD::handleTimerComplete(int id) { Minecraft *pMinecraft = Minecraft::GetInstance(); + bool isChatOpen = (dynamic_cast(pMinecraft->getScreen()) != nullptr); bool anyVisible = false; if(pMinecraft->localplayers[m_iPad]!= nullptr) { Gui *pGui = pMinecraft->gui; - //DWORD messagesToDisplay = min( CHAT_LINES_COUNT, pGui->getMessagesCount(m_iPad) ); - for( unsigned int i = 0; i < CHAT_LINES_COUNT; ++i ) + DWORD totalMessages = pGui->getMessagesCount(m_iPad); + DWORD messagesToDisplay = min( CHAT_LINES_COUNT, totalMessages); + DWORD maxScroll = max(0, totalMessages - messagesToDisplay); + + bool canScroll = messagesToDisplay < totalMessages; + int startIndex = (canScroll && isChatOpen ? ChatScreen::getChatIndex() : 0); + + if (startIndex > maxScroll) { + ChatScreen::correctChatIndex(maxScroll); + startIndex = maxScroll; + } + + app.DebugPrintf("handleTimerComplete: %d | %d | %d\n", maxScroll, startIndex, totalMessages); + + for( unsigned int i = 0; i < messagesToDisplay; ++i ) { - float opacity = pGui->getOpacity(m_iPad, i); - if( opacity > 0 ) + unsigned int msgIndex = startIndex + i; + float opacity = pGui->getOpacity(m_iPad, msgIndex); + if( opacity > 0 || isChatOpen) { #if 0 // def _WINDOWS64 // Use Iggy chat until Gui::render has visual parity // Chat drawn by Gui::render with color codes. Hides Iggy chat to avoid double chats. @@ -778,9 +794,10 @@ void UIScene_HUD::handleTimerComplete(int id) m_labelChatText[i].setOpacity(0); m_labelChatText[i].setLabel(L""); #else - m_controlLabelBackground[i].setOpacity(opacity); - m_labelChatText[i].setOpacity(opacity); - m_labelChatText[i].setLabel( pGui->getMessagesCount(m_iPad) ? pGui->getMessage(m_iPad,i) : L"" ); + + m_controlLabelBackground[i].setOpacity((isChatOpen ? 1 : opacity)); + m_labelChatText[i].setOpacity((isChatOpen ? 1 : opacity)); + m_labelChatText[i].setLabel(pGui->getMessage(m_iPad, msgIndex)); #endif anyVisible = true; } diff --git a/Minecraft.Client/Gui.h b/Minecraft.Client/Gui.h index 64b8dfbe8..440d4e5b4 100644 --- a/Minecraft.Client/Gui.h +++ b/Minecraft.Client/Gui.h @@ -17,6 +17,7 @@ private: static const int m_iMaxMessageWidth = 280; static ItemRenderer *itemRenderer; vector guiMessages[XUSER_MAX_COUNT]; + int chatIndex = 0; Random *random; Minecraft *minecraft; diff --git a/Minecraft.Client/Minecraft.cpp b/Minecraft.Client/Minecraft.cpp index 1ba432fd0..10167f955 100644 --- a/Minecraft.Client/Minecraft.cpp +++ b/Minecraft.Client/Minecraft.cpp @@ -1537,8 +1537,12 @@ void Minecraft::run_middle() // Utility keys always work regardless of KBM active state if(g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_PAUSE) && !ui.GetMenuDisplayed(i)) { - localplayers[i]->ullButtonsPressed|=1LL<(getScreen()) != nullptr) { + setScreen(nullptr); + } else { + localplayers[i]->ullButtonsPressed|=1LL< Date: Sun, 12 Apr 2026 23:50:46 -0400 Subject: [PATCH 21/25] fix: Increase entity network limit to 16k entities (#1492) --- Minecraft.Client/EntityTracker.cpp | 2 +- Minecraft.Client/ServerPlayer.cpp | 4 +-- Minecraft.Server/cmake/sources/Common.cmake | 1 + Minecraft.World/Entity.cpp | 34 ++++++++++++--------- Minecraft.World/Entity.h | 9 ++++-- Minecraft.World/MoveEntityPacket.cpp | 2 +- Minecraft.World/MoveEntityPacketSmall.cpp | 10 +++--- 7 files changed, 35 insertions(+), 27 deletions(-) diff --git a/Minecraft.Client/EntityTracker.cpp b/Minecraft.Client/EntityTracker.cpp index 087227e77..6f482b608 100644 --- a/Minecraft.Client/EntityTracker.cpp +++ b/Minecraft.Client/EntityTracker.cpp @@ -81,7 +81,7 @@ void EntityTracker::addEntity(shared_ptr e, int range, int updateInterva { assert(false); // Entity already tracked } - if( e->entityId >= 2048 ) + if( e->entityId >= 16384 ) { __debugbreak(); } diff --git a/Minecraft.Client/ServerPlayer.cpp b/Minecraft.Client/ServerPlayer.cpp index f57e8a3c9..41f74af55 100644 --- a/Minecraft.Client/ServerPlayer.cpp +++ b/Minecraft.Client/ServerPlayer.cpp @@ -147,12 +147,12 @@ void ServerPlayer::flagEntitiesToBeRemoved(unsigned int *flags, bool *removedFou { *removedFound = true; // before this left 192 bytes uninitialized!!!!! - memset(flags, 0, (2048 / 32) * sizeof(unsigned int)); + memset(flags, 0, (16384 / 32) * sizeof(unsigned int)); } for(int index : entitiesToRemove) { - if( index < 2048 ) + if( index < 16384 ) { unsigned int i = index / 32; unsigned int j = index % 32; diff --git a/Minecraft.Server/cmake/sources/Common.cmake b/Minecraft.Server/cmake/sources/Common.cmake index 1eaceee16..58ae26ce2 100644 --- a/Minecraft.Server/cmake/sources/Common.cmake +++ b/Minecraft.Server/cmake/sources/Common.cmake @@ -494,6 +494,7 @@ set(_MINECRAFT_SERVER_COMMON_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.Client/iob_shim.asm" "${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.Client/stdafx.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.Client/stubs.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.World/Entity.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.World/ConsoleSaveFileOriginal.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.World/ConsoleSaveFileOriginal.h" "${CMAKE_CURRENT_SOURCE_DIR}/../include/lce_filesystem/lce_filesystem.cpp" diff --git a/Minecraft.World/Entity.cpp b/Minecraft.World/Entity.cpp index 924312e59..6e275a2c3 100644 --- a/Minecraft.World/Entity.cpp +++ b/Minecraft.World/Entity.cpp @@ -27,13 +27,17 @@ const wstring Entity::RIDING_TAG = L"Riding"; -int Entity::entityCounter = 2048; // 4J - changed initialiser to 2048, as we are using range 0 - 2047 as special unique smaller ids for things that need network tracked +//int Entity::entityCounter = 2048; // 4J - changed initialiser to 2048, as we are using range 0 - 2047 as special unique smaller ids for things that need network tracked +int Entity::entityCounter = 16384; //now using full range of 0 - 16383, limit is 32k but we shouldnt need that yet DWORD Entity::tlsIdx = TlsAlloc(); // 4J - added getSmallId & freeSmallId methods -unsigned int Entity::entityIdUsedFlags[2048/32] = {0}; -unsigned int Entity::entityIdWanderFlags[2048/32] = {0}; -unsigned int Entity::entityIdRemovingFlags[2048/32] = {0}; +//unsigned int Entity::entityIdUsedFlags[2048/32] = {0}; +//unsigned int Entity::entityIdWanderFlags[2048/32] = {0}; +//unsigned int Entity::entityIdRemovingFlags[2048/32] = {0}; +unsigned int Entity::entityIdUsedFlags[16384/32] = {0}; +unsigned int Entity::entityIdWanderFlags[16384/32] = {0}; +unsigned int Entity::entityIdRemovingFlags[16384/32] = {0}; int Entity::extraWanderIds[EXTRA_WANDER_MAX] = {0}; int Entity::extraWanderTicks = 0; int Entity::extraWanderCount = 0; @@ -65,7 +69,7 @@ int Entity::getSmallId() } } - for( int i = 0; i < (2048 / 32 ); i++ ) + for( int i = 0; i < (16384 / 32 ); i++ ) { unsigned int uiFlags = *puiUsedFlags; if( uiFlags != 0xffffffff ) @@ -102,7 +106,7 @@ int Entity::getSmallId() if (entityCounter == 0x7ffffff) { - entityCounter = 2048; + entityCounter = 16384; } return fallbackId; #else @@ -116,7 +120,7 @@ void Entity::countFlagsForPIX() { int freecount = 0; unsigned int *puiUsedFlags = entityIdUsedFlags; - for( int i = 0; i < (2048 / 32 ); i++ ) + for( int i = 0; i < (16384 / 32 ); i++ ) { unsigned int uiFlags = *puiUsedFlags; if( uiFlags != 0xffffffff ) @@ -134,7 +138,7 @@ void Entity::countFlagsForPIX() puiUsedFlags++; } PIXAddNamedCounter(freecount,"Small Ids free"); - PIXAddNamedCounter(2048 - freecount,"Small Ids used"); + PIXAddNamedCounter(16384 - freecount,"Small Ids used"); } void Entity::resetSmallId() @@ -149,7 +153,7 @@ void Entity::resetSmallId() void Entity::freeSmallId(int index) { if( ( (size_t)TlsGetValue(tlsIdx) ) == 0 ) return; // Don't do anything with small ids if this isn't the server thread - if( index >= 2048 ) return; // Don't do anything if this isn't a short id + if( index >= 16384 ) return; // Don't do anything if this isn't a short id unsigned int i = index / 32; unsigned int j = index % 32; @@ -172,7 +176,7 @@ void Entity::useSmallIds() void Entity::considerForExtraWandering(bool enable) { if( ( (size_t)TlsGetValue(tlsIdx) ) == 0 ) return; // Don't do anything with small ids if this isn't the server thread - if( entityId >= 2048 ) return; // Don't do anything if this isn't a short id + if( entityId >= 16384 ) return; // Don't do anything if this isn't a short id unsigned int i = entityId / 32; unsigned int j = entityId % 32; @@ -192,7 +196,7 @@ void Entity::considerForExtraWandering(bool enable) bool Entity::isExtraWanderingEnabled() { if( ( (size_t)TlsGetValue(tlsIdx) ) == 0 ) return false; // Don't do anything with small ids if this isn't the server thread - if( entityId >= 2048 ) return false; // Don't do anything if this isn't a short id + if( entityId >= 16384 ) return false; // Don't do anything if this isn't a short id for( int i = 0; i < extraWanderCount; i++ ) { @@ -224,12 +228,12 @@ void Entity::tickExtraWandering() int entityId = 0; if( extraWanderCount ) { - entityId = ( extraWanderIds[ extraWanderCount - 1 ] + 1 ) % 2048; + entityId = ( extraWanderIds[ extraWanderCount - 1 ] + 1 ) % 16384; } extraWanderCount = 0; - for( int k = 0; ( k < 2048 ) && ( extraWanderCount < EXTRA_WANDER_MAX); k++ ) + for( int k = 0; ( k < 16384 ) && ( extraWanderCount < EXTRA_WANDER_MAX); k++ ) { unsigned int i = entityId / 32; unsigned int j = entityId % 32; @@ -241,7 +245,7 @@ void Entity::tickExtraWandering() // printf("%d, ", entityId); } - entityId = ( entityId + 1 ) % 2048; + entityId = ( entityId + 1 ) % 16384; } // printf("\n"); } @@ -261,7 +265,7 @@ void Entity::_init(bool useSmallId, Level *level) else { entityId = Entity::entityCounter++; - if(entityCounter == 0x7ffffff ) entityCounter = 2048; + if(entityCounter == 0x7ffffff ) entityCounter = 16384; } viewScale = 1.0; diff --git a/Minecraft.World/Entity.h b/Minecraft.World/Entity.h index a738c2ba7..9fb0f5489 100644 --- a/Minecraft.World/Entity.h +++ b/Minecraft.World/Entity.h @@ -382,9 +382,12 @@ private: int getSmallId(); void freeSmallId(int index); - static unsigned int entityIdUsedFlags[2048/32]; - static unsigned int entityIdWanderFlags[2048/32]; - static unsigned int entityIdRemovingFlags[2048/32]; + //static unsigned int entityIdUsedFlags[2048/32]; + //static unsigned int entityIdWanderFlags[2048/32]; + //static unsigned int entityIdRemovingFlags[2048/32]; + static unsigned int entityIdUsedFlags[16384/32]; + static unsigned int entityIdWanderFlags[16384/32]; + static unsigned int entityIdRemovingFlags[16384/32]; static int extraWanderIds[EXTRA_WANDER_MAX]; static int extraWanderCount; static int extraWanderTicks; diff --git a/Minecraft.World/MoveEntityPacket.cpp b/Minecraft.World/MoveEntityPacket.cpp index cae28e912..aef9e6217 100644 --- a/Minecraft.World/MoveEntityPacket.cpp +++ b/Minecraft.World/MoveEntityPacket.cpp @@ -35,7 +35,7 @@ void MoveEntityPacket::read(DataInputStream *dis) //throws IOException void MoveEntityPacket::write(DataOutputStream *dos) //throws IOException { - if( (id < 0 ) || (id >= 2048 ) ) + if( (id < 0 ) || (id >= 16384 ) ) { // We shouln't be tracking an entity that doesn't have a short type of id __debugbreak(); diff --git a/Minecraft.World/MoveEntityPacketSmall.cpp b/Minecraft.World/MoveEntityPacketSmall.cpp index ec67f37f2..7d91a15d5 100644 --- a/Minecraft.World/MoveEntityPacketSmall.cpp +++ b/Minecraft.World/MoveEntityPacketSmall.cpp @@ -19,7 +19,7 @@ MoveEntityPacketSmall::MoveEntityPacketSmall() MoveEntityPacketSmall::MoveEntityPacketSmall(int id) { - if( (id < 0 ) || (id >= 2048 ) ) + if( (id < 0 ) || (id >= 16384 ) ) { // We shouln't be tracking an entity that doesn't have a short type of id __debugbreak(); @@ -42,7 +42,7 @@ void MoveEntityPacketSmall::read(DataInputStream *dis) //throws IOException void MoveEntityPacketSmall::write(DataOutputStream *dos) //throws IOException { - if( (id < 0 ) || (id >= 2048 ) ) + if( (id < 0 ) || (id >= 16384 ) ) { // We shouln't be tracking an entity that doesn't have a short type of id __debugbreak(); @@ -99,7 +99,7 @@ void MoveEntityPacketSmall::PosRot::read(DataInputStream *dis) //throws IOExcept void MoveEntityPacketSmall::PosRot::write(DataOutputStream *dos) //throws IOException { - if( (id < 0 ) || (id >= 2048 ) ) + if( (id < 0 ) || (id >= 16384 ) ) { // We shouln't be tracking an entity that doesn't have a short type of id __debugbreak(); @@ -138,7 +138,7 @@ void MoveEntityPacketSmall::Pos::read(DataInputStream *dis) //throws IOException void MoveEntityPacketSmall::Pos::write(DataOutputStream *dos) //throws IOException { - if( (id < 0 ) || (id >= 2048 ) ) + if( (id < 0 ) || (id >= 16384 ) ) { // We shouln't be tracking an entity that doesn't have a short type of id __debugbreak(); @@ -176,7 +176,7 @@ void MoveEntityPacketSmall::Rot::read(DataInputStream *dis) //throws IOException void MoveEntityPacketSmall::Rot::write(DataOutputStream *dos) //throws IOException { - if( (id < 0 ) || (id >= 2048 ) ) + if( (id < 0 ) || (id >= 16384 ) ) { // We shouln't be tracking an entity that doesn't have a short type of id __debugbreak(); From 9e6e3de33807358f33a9d3a4dbb5c1e3c11830f7 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Mon, 13 Apr 2026 04:52:34 +0100 Subject: [PATCH 22/25] Improve actions file ignore rules (#1491) * Add clang-format workflow for pull request checks * Modify push paths in nightly workflow Updated paths for push event to include all files except specified ones. * Update paths for nightly-server workflow triggers * Modify paths for pull request triggers Update pull request workflow to include specific paths. * Remove formatting check workflow --- .github/workflows/nightly-server.yml | 11 ++++++----- .github/workflows/nightly.yml | 11 ++++++----- .github/workflows/pull-request.yml | 10 ++++++---- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/.github/workflows/nightly-server.yml b/.github/workflows/nightly-server.yml index 5450de9ac..0fc20eb13 100644 --- a/.github/workflows/nightly-server.yml +++ b/.github/workflows/nightly-server.yml @@ -5,11 +5,12 @@ on: push: branches: - 'main' - paths-ignore: - - '.gitignore' - - '*.md' - - '.github/**' - - '!.github/workflows/nightly-server.yml' + paths: + - '**' + - '!.gitignore' + - '!*.md' + - '!.github/**' + - '.github/workflows/nightly-server.yml' permissions: contents: write diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 789db3e84..a5b53be08 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -5,11 +5,12 @@ on: push: branches: - 'main' - paths-ignore: - - '.gitignore' - - '*.md' - - '.github/**' - - '!.github/workflows/nightly.yml' + paths: + - '**' + - '!.gitignore' + - '!*.md' + - '!.github/**' + - '.github/workflows/nightly.yml' permissions: contents: write diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 9d57f4b4b..3b5398a00 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -4,10 +4,12 @@ on: workflow_dispatch: pull_request: types: [opened, reopened, synchronize] - paths-ignore: - - '.gitignore' - - '*.md' - - '.github/*.md' + paths: + - '**' + - '!.gitignore' + - '!*.md' + - '!.github/**' + - '.github/workflows/pull-request.yml' jobs: build: From e730033bcc13c6b9b257680ae36108cdbb53cadd Mon Sep 17 00:00:00 2001 From: "Us3ful\"-Dev" Date: Mon, 13 Apr 2026 05:53:39 +0200 Subject: [PATCH 23/25] fix: Prevent end poem crash (#1489) Removed player name check that always fails to work on non host instances --- Minecraft.Client/Common/UI/UIScene_EndPoem.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/Minecraft.Client/Common/UI/UIScene_EndPoem.cpp b/Minecraft.Client/Common/UI/UIScene_EndPoem.cpp index 5b10e8cfe..6ca6abb18 100644 --- a/Minecraft.Client/Common/UI/UIScene_EndPoem.cpp +++ b/Minecraft.Client/Common/UI/UIScene_EndPoem.cpp @@ -50,14 +50,7 @@ UIScene_EndPoem::UIScene_EndPoem(int iPad, void *initData, UILayer *parentLayer) Minecraft *pMinecraft = Minecraft::GetInstance(); wstring playerName = L""; - if(pMinecraft->localplayers[ui.GetWinUserIndex()] != nullptr) - { - playerName = escapeXML( pMinecraft->localplayers[ui.GetWinUserIndex()]->getDisplayName() ); - } - else - { - playerName = escapeXML( pMinecraft->localplayers[ProfileManager.GetPrimaryPad()]->getDisplayName() ); - } + playerName = escapeXML( pMinecraft->localplayers[ProfileManager.GetPrimaryPad()]->getDisplayName() ); noNoiseString = replaceAll(noNoiseString,L"{*PLAYER*}",playerName); Random random(8124371); From e5ce9a06cdcd25a7bd1155160a2a95f1a48998fc Mon Sep 17 00:00:00 2001 From: Botch Date: Sun, 12 Apr 2026 21:55:07 -0600 Subject: [PATCH 24/25] fix: Disable font mipmapping (#1410) Fixes visual artifacts with signs, improving legibility at distances --- Minecraft.Client/Font.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Minecraft.Client/Font.cpp b/Minecraft.Client/Font.cpp index 1040eaa08..ff5b7ef2d 100644 --- a/Minecraft.Client/Font.cpp +++ b/Minecraft.Client/Font.cpp @@ -310,6 +310,8 @@ void Font::draw(const wstring &str, bool dropShadow, int initialColor) t->begin(); t->color(currentColor & 0x00ffffff, (currentColor >> 24) & 255); + bool prev = t->setMipmapEnable(false); // Disable mipmapping for fonts, and save previous enabled value to be restored later - Botch + for (int i = 0; i < static_cast(cleanStr.length()); ++i) { // Map character @@ -371,6 +373,8 @@ void Font::draw(const wstring &str, bool dropShadow, int initialColor) addCharacterQuad(c); } + t->setMipmapEnable(prev); //Reinstates previously used enabled value - Botch + t->end(); } From 050c501786e2a0d8a610cdf82e190889b27287ee Mon Sep 17 00:00:00 2001 From: Toru the Red Fox Date: Mon, 13 Apr 2026 04:56:24 +0100 Subject: [PATCH 25/25] Request dedicated GPU (#850) --- Minecraft.Client/Windows64/Windows64_Minecraft.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp index bee49df0e..3019c6f2a 100644 --- a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp +++ b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp @@ -57,6 +57,13 @@ extern Renderer InternalRenderManager; #include "Xbox/resource.h" +// request use of dedicated GPU from AMD and Nvidia drivers +extern "C" +{ + __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; + __declspec(dllexport) unsigned long NvOptimusEnablement = 0x00000001; +} + #ifdef _MSC_VER #pragma comment(lib, "legacy_stdio_definitions.lib") #endif