From 4d745ab65cd26584af3670cfd4bae1494dc599b7 Mon Sep 17 00:00:00 2001 From: pieeebot <274605694+pieeebot@users.noreply.github.com> Date: Mon, 25 May 2026 21:05:50 +0300 Subject: [PATCH 1/7] Revert "fix: remove round robin chunk cache (#114)" This reverts commit bb62a9f559ceb83a1297a859afccbc4d31502789. --- Minecraft.Client/MultiPlayerChunkCache.cpp | 27 +++++++++++----------- Minecraft.Client/MultiPlayerChunkCache.h | 5 ++++ Minecraft.World/Level.cpp | 4 ++-- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/Minecraft.Client/MultiPlayerChunkCache.cpp b/Minecraft.Client/MultiPlayerChunkCache.cpp index 1f8dc357..e4cd1e0d 100644 --- a/Minecraft.Client/MultiPlayerChunkCache.cpp +++ b/Minecraft.Client/MultiPlayerChunkCache.cpp @@ -15,8 +15,8 @@ MultiPlayerChunkCache::MultiPlayerChunkCache(Level *level) XZSIZE = level->dimension->getXZSize(); // 4J Added XZOFFSET = XZSIZE/2; // 4J Added m_XZSize = XZSIZE; - hasData = new bool[XZSIZE * XZSIZE]; - memset(hasData, 0, sizeof(bool) * XZSIZE * XZSIZE); + hasData = new bool[LEVEL_MIN_WIDTH * LEVEL_MIN_WIDTH]; + memset(hasData, 0, sizeof(bool) * LEVEL_MIN_WIDTH * LEVEL_MIN_WIDTH); emptyChunk = new EmptyLevelChunk(level, byteArray(16 * 16 * Level::maxBuildHeight), 0, 0); @@ -93,8 +93,8 @@ MultiPlayerChunkCache::MultiPlayerChunkCache(Level *level) this->level = level; - this->cache = new LevelChunk *[XZSIZE * XZSIZE]; - memset(this->cache, 0, sizeof(LevelChunk*) * XZSIZE * XZSIZE); + this->cache = new LevelChunk *[LEVEL_MIN_WIDTH * LEVEL_MIN_WIDTH]; + memset(this->cache, 0, sizeof(LevelChunk*) * LEVEL_MIN_WIDTH * LEVEL_MIN_WIDTH); InitializeCriticalSectionAndSpinCount(&m_csLoadCreate,4000); } @@ -129,10 +129,11 @@ bool MultiPlayerChunkCache::reallyHasChunk(int x, int z) // Check we're in range of the stored level - if we aren't, then consider that we do have that chunk as we'll be able to use the water chunk there if( ( ix < 0 ) || ( ix >= XZSIZE ) ) return true; if( ( iz < 0 ) || ( iz >= XZSIZE ) ) return true; - int idx = ix * XZSIZE + iz; + + int idx = wrapCoord(x, LEVEL_MIN_WIDTH) * LEVEL_MIN_WIDTH + wrapCoord(z, LEVEL_MIN_WIDTH); LevelChunk *chunk = cache[idx]; - if (chunk == nullptr) + if (chunk == nullptr || chunk->x != x || chunk->z != z) { return false; } @@ -146,10 +147,10 @@ void MultiPlayerChunkCache::drop(const int x, const int z) if ((ix < 0) || (ix >= XZSIZE)) return; if ((iz < 0) || (iz >= XZSIZE)) return; - int idx = ix * XZSIZE + iz; + int idx = wrapCoord(x, LEVEL_MIN_WIDTH) * LEVEL_MIN_WIDTH + wrapCoord(z, LEVEL_MIN_WIDTH); LevelChunk* chunk = cache[idx]; - if (chunk != nullptr && !chunk->isEmpty()) + if (chunk != nullptr && !chunk->isEmpty() && chunk->x == x && chunk->z == z) { // Drop entities in the chunks, especially for the case when a player is dead // as they will not get the RemoveEntity packet if an entity is removed. @@ -169,12 +170,12 @@ LevelChunk *MultiPlayerChunkCache::create(int x, int z) // Check we're in range of the stored level if( ( ix < 0 ) || ( ix >= XZSIZE ) ) return ( waterChunk ? waterChunk : emptyChunk ); if( ( iz < 0 ) || ( iz >= XZSIZE ) ) return ( waterChunk ? waterChunk : emptyChunk ); - int idx = ix * XZSIZE + iz; + int idx = wrapCoord(x, LEVEL_MIN_WIDTH) * LEVEL_MIN_WIDTH + wrapCoord(z, LEVEL_MIN_WIDTH); LevelChunk *chunk = cache[idx]; LevelChunk *lastChunk = chunk; - if( chunk == nullptr ) + if( chunk == nullptr || chunk->x != x || chunk->z != z ) { EnterCriticalSection(&m_csLoadCreate); @@ -253,10 +254,10 @@ LevelChunk *MultiPlayerChunkCache::getChunk(int x, int z) // Check we're in range of the stored level if( ( ix < 0 ) || ( ix >= XZSIZE ) ) return ( waterChunk ? waterChunk : emptyChunk ); if( ( iz < 0 ) || ( iz >= XZSIZE ) ) return ( waterChunk ? waterChunk : emptyChunk ); - int idx = ix * XZSIZE + iz; + int idx = wrapCoord(x, LEVEL_MIN_WIDTH) * LEVEL_MIN_WIDTH + wrapCoord(z, LEVEL_MIN_WIDTH); LevelChunk *chunk = cache[idx]; - if( chunk == nullptr ) + if( chunk == nullptr || chunk->x != x || chunk->z != z ) { return emptyChunk; } @@ -315,6 +316,6 @@ void MultiPlayerChunkCache::dataReceived(int x, int z) // Check we're in range of the stored level if( ( ix < 0 ) || ( ix >= XZSIZE ) ) return; if( ( iz < 0 ) || ( iz >= XZSIZE ) ) return; - int idx = ix * XZSIZE + iz; + int idx = wrapCoord(x, LEVEL_MIN_WIDTH) * LEVEL_MIN_WIDTH + wrapCoord(z, LEVEL_MIN_WIDTH); hasData[idx] = true; } \ No newline at end of file diff --git a/Minecraft.Client/MultiPlayerChunkCache.h b/Minecraft.Client/MultiPlayerChunkCache.h index 203f3124..e018790b 100644 --- a/Minecraft.Client/MultiPlayerChunkCache.h +++ b/Minecraft.Client/MultiPlayerChunkCache.h @@ -45,4 +45,9 @@ public: virtual void dataReceived(int x, int z); // 4J added virtual LevelChunk **getCache() { return cache; } // 4J added + + static inline int wrapCoord(int v, int size) { + int r = v % size; + return (r < 0) ? r + size : r; + } }; \ No newline at end of file diff --git a/Minecraft.World/Level.cpp b/Minecraft.World/Level.cpp index d6284d95..49819aa6 100644 --- a/Minecraft.World/Level.cpp +++ b/Minecraft.World/Level.cpp @@ -1333,7 +1333,7 @@ int Level::getBrightness(LightLayer::variety layer, int x, int y, int z) if( ( ix < 0 ) || ( ix >= chunkSourceXZSize ) ) return 0; if( ( iz < 0 ) || ( iz >= chunkSourceXZSize ) ) return 0; - int idx = ix * chunkSourceXZSize + iz; + int idx = MultiPlayerChunkCache::wrapCoord(ix, LEVEL_MIN_WIDTH) * LEVEL_MIN_WIDTH + MultiPlayerChunkCache::wrapCoord(iz, LEVEL_MIN_WIDTH); LevelChunk *c = chunkSourceCache[idx]; if( c == nullptr) return (int)layer; @@ -1382,7 +1382,7 @@ void Level::getNeighbourBrightnesses(int *brightnesses, LightLayer::variety laye return; } - int idx = ix * chunkSourceXZSize + iz; + int idx = MultiPlayerChunkCache::wrapCoord(ix, LEVEL_MIN_WIDTH) * LEVEL_MIN_WIDTH + MultiPlayerChunkCache::wrapCoord(iz, LEVEL_MIN_WIDTH); LevelChunk *c = chunkSourceCache[idx]; // 4J Stu - The java LightLayer was an enum class type with a member "surrounding" which is what we From cd50236b8ad0c1fb79396253913deba966acea6c Mon Sep 17 00:00:00 2001 From: pieeebot <274605694+pieeebot@users.noreply.github.com> Date: Mon, 25 May 2026 21:06:22 +0300 Subject: [PATCH 2/7] Revert "feat: Feat/expanded worlds (#107)" This reverts commit 98c33aa6775b736937087fe140bad073e879679b. --- Minecraft.Client/Common/App_Defines.h | 3 +-- Minecraft.Client/MultiPlayerChunkCache.cpp | 29 ++++++++++------------ Minecraft.Client/MultiPlayerChunkCache.h | 5 ---- Minecraft.Server/ServerProperties.cpp | 11 -------- Minecraft.World/ChunkSource.h | 6 ++--- Minecraft.World/Level.cpp | 7 +++--- Minecraft.World/LevelData.cpp | 1 - 7 files changed, 19 insertions(+), 43 deletions(-) diff --git a/Minecraft.Client/Common/App_Defines.h b/Minecraft.Client/Common/App_Defines.h index 693bad2c..eeb9942d 100644 --- a/Minecraft.Client/Common/App_Defines.h +++ b/Minecraft.Client/Common/App_Defines.h @@ -56,8 +56,7 @@ enum EGameHostOptionWorldSize e_worldSize_Classic, e_worldSize_Small, e_worldSize_Medium, - e_worldSize_Large, - e_worldSize_Expanded + e_worldSize_Large }; diff --git a/Minecraft.Client/MultiPlayerChunkCache.cpp b/Minecraft.Client/MultiPlayerChunkCache.cpp index e4cd1e0d..302ff119 100644 --- a/Minecraft.Client/MultiPlayerChunkCache.cpp +++ b/Minecraft.Client/MultiPlayerChunkCache.cpp @@ -15,8 +15,8 @@ MultiPlayerChunkCache::MultiPlayerChunkCache(Level *level) XZSIZE = level->dimension->getXZSize(); // 4J Added XZOFFSET = XZSIZE/2; // 4J Added m_XZSize = XZSIZE; - hasData = new bool[LEVEL_MIN_WIDTH * LEVEL_MIN_WIDTH]; - memset(hasData, 0, sizeof(bool) * LEVEL_MIN_WIDTH * LEVEL_MIN_WIDTH); + hasData = new bool[XZSIZE * XZSIZE]; + memset(hasData, 0, sizeof(bool) * XZSIZE * XZSIZE); emptyChunk = new EmptyLevelChunk(level, byteArray(16 * 16 * Level::maxBuildHeight), 0, 0); @@ -93,8 +93,8 @@ MultiPlayerChunkCache::MultiPlayerChunkCache(Level *level) this->level = level; - this->cache = new LevelChunk *[LEVEL_MIN_WIDTH * LEVEL_MIN_WIDTH]; - memset(this->cache, 0, sizeof(LevelChunk*) * LEVEL_MIN_WIDTH * LEVEL_MIN_WIDTH); + this->cache = new LevelChunk *[XZSIZE * XZSIZE]; + memset(this->cache, 0, XZSIZE * XZSIZE * sizeof(LevelChunk *)); InitializeCriticalSectionAndSpinCount(&m_csLoadCreate,4000); } @@ -129,11 +129,10 @@ bool MultiPlayerChunkCache::reallyHasChunk(int x, int z) // Check we're in range of the stored level - if we aren't, then consider that we do have that chunk as we'll be able to use the water chunk there if( ( ix < 0 ) || ( ix >= XZSIZE ) ) return true; if( ( iz < 0 ) || ( iz >= XZSIZE ) ) return true; - - int idx = wrapCoord(x, LEVEL_MIN_WIDTH) * LEVEL_MIN_WIDTH + wrapCoord(z, LEVEL_MIN_WIDTH); + int idx = ix * XZSIZE + iz; LevelChunk *chunk = cache[idx]; - if (chunk == nullptr || chunk->x != x || chunk->z != z) + if( chunk == nullptr ) { return false; } @@ -146,11 +145,10 @@ void MultiPlayerChunkCache::drop(const int x, const int z) const int iz = z + XZOFFSET; if ((ix < 0) || (ix >= XZSIZE)) return; if ((iz < 0) || (iz >= XZSIZE)) return; - - int idx = wrapCoord(x, LEVEL_MIN_WIDTH) * LEVEL_MIN_WIDTH + wrapCoord(z, LEVEL_MIN_WIDTH); + const int idx = ix * XZSIZE + iz; LevelChunk* chunk = cache[idx]; - if (chunk != nullptr && !chunk->isEmpty() && chunk->x == x && chunk->z == z) + if (chunk != nullptr && !chunk->isEmpty()) { // Drop entities in the chunks, especially for the case when a player is dead // as they will not get the RemoveEntity packet if an entity is removed. @@ -170,12 +168,11 @@ LevelChunk *MultiPlayerChunkCache::create(int x, int z) // Check we're in range of the stored level if( ( ix < 0 ) || ( ix >= XZSIZE ) ) return ( waterChunk ? waterChunk : emptyChunk ); if( ( iz < 0 ) || ( iz >= XZSIZE ) ) return ( waterChunk ? waterChunk : emptyChunk ); - int idx = wrapCoord(x, LEVEL_MIN_WIDTH) * LEVEL_MIN_WIDTH + wrapCoord(z, LEVEL_MIN_WIDTH); - + int idx = ix * XZSIZE + iz; LevelChunk *chunk = cache[idx]; LevelChunk *lastChunk = chunk; - if( chunk == nullptr || chunk->x != x || chunk->z != z ) + if( chunk == nullptr ) { EnterCriticalSection(&m_csLoadCreate); @@ -254,10 +251,10 @@ LevelChunk *MultiPlayerChunkCache::getChunk(int x, int z) // Check we're in range of the stored level if( ( ix < 0 ) || ( ix >= XZSIZE ) ) return ( waterChunk ? waterChunk : emptyChunk ); if( ( iz < 0 ) || ( iz >= XZSIZE ) ) return ( waterChunk ? waterChunk : emptyChunk ); - int idx = wrapCoord(x, LEVEL_MIN_WIDTH) * LEVEL_MIN_WIDTH + wrapCoord(z, LEVEL_MIN_WIDTH); + int idx = ix * XZSIZE + iz; LevelChunk *chunk = cache[idx]; - if( chunk == nullptr || chunk->x != x || chunk->z != z ) + if( chunk == nullptr ) { return emptyChunk; } @@ -316,6 +313,6 @@ void MultiPlayerChunkCache::dataReceived(int x, int z) // Check we're in range of the stored level if( ( ix < 0 ) || ( ix >= XZSIZE ) ) return; if( ( iz < 0 ) || ( iz >= XZSIZE ) ) return; - int idx = wrapCoord(x, LEVEL_MIN_WIDTH) * LEVEL_MIN_WIDTH + wrapCoord(z, LEVEL_MIN_WIDTH); + int idx = ix * XZSIZE + iz; hasData[idx] = true; } \ No newline at end of file diff --git a/Minecraft.Client/MultiPlayerChunkCache.h b/Minecraft.Client/MultiPlayerChunkCache.h index e018790b..203f3124 100644 --- a/Minecraft.Client/MultiPlayerChunkCache.h +++ b/Minecraft.Client/MultiPlayerChunkCache.h @@ -45,9 +45,4 @@ public: virtual void dataReceived(int x, int z); // 4J added virtual LevelChunk **getCache() { return cache; } // 4J added - - static inline int wrapCoord(int v, int size) { - int r = v % size; - return (r < 0) ? r + size : r; - } }; \ No newline at end of file diff --git a/Minecraft.Server/ServerProperties.cpp b/Minecraft.Server/ServerProperties.cpp index 525be788..1b6c5c0a 100644 --- a/Minecraft.Server/ServerProperties.cpp +++ b/Minecraft.Server/ServerProperties.cpp @@ -628,8 +628,6 @@ static std::string WorldSizeToPropertyValue(int worldSize) return "medium"; case e_worldSize_Large: return "large"; - case e_worldSize_Expanded: - return "expanded"; case e_worldSize_Classic: default: return "classic"; @@ -646,8 +644,6 @@ static int WorldSizeToXzChunks(int worldSize) return LEVEL_WIDTH_MEDIUM; case e_worldSize_Large: return LEVEL_WIDTH_LARGE; - case e_worldSize_Expanded: - return LEVEL_WIDTH_EXPANDED; case e_worldSize_Classic: default: return LEVEL_WIDTH_CLASSIC; @@ -663,7 +659,6 @@ static int WorldSizeToHellScale(int worldSize) case e_worldSize_Medium: return HELL_LEVEL_SCALE_MEDIUM; case e_worldSize_Large: - case e_worldSize_Expanded: return HELL_LEVEL_SCALE_LARGE; case e_worldSize_Classic: default: @@ -699,12 +694,6 @@ static bool TryParseWorldSize(const std::string &lowered, int *outWorldSize) return true; } - if (lowered == "expanded" || lowered == "344" || lowered == "8") - { - *outWorldSize = e_worldSize_Expanded; - return true; - } - return false; } diff --git a/Minecraft.World/ChunkSource.h b/Minecraft.World/ChunkSource.h index 5b510ddb..37b0ecc3 100644 --- a/Minecraft.World/ChunkSource.h +++ b/Minecraft.World/ChunkSource.h @@ -7,14 +7,12 @@ class TilePos; // The maximum number of chunks that we can store #ifdef _LARGE_WORLDS // 4J Stu - Our default map (at zoom level 3) is 1024x1024 blocks (or 64 chunks) +#define LEVEL_MAX_WIDTH (5*64) //(6*54) + #define LEVEL_WIDTH_CLASSIC 54 #define LEVEL_WIDTH_SMALL 64 #define LEVEL_WIDTH_MEDIUM (3*64) #define LEVEL_WIDTH_LARGE (5*64) -#define LEVEL_WIDTH_EXPANDED (5*64) + 24 - - -#define LEVEL_MAX_WIDTH LEVEL_WIDTH_EXPANDED #else #define LEVEL_MAX_WIDTH 54 diff --git a/Minecraft.World/Level.cpp b/Minecraft.World/Level.cpp index 49819aa6..8478535b 100644 --- a/Minecraft.World/Level.cpp +++ b/Minecraft.World/Level.cpp @@ -46,7 +46,6 @@ DWORD Level::tlsIdxLightCache = TlsAlloc(); // 4J : WESTY : Added for time played stats. #include "net.minecraft.stats.h" -#include "../Minecraft.Client/MultiPlayerChunkCache.h" // 4J - Caching of lighting data added. This is implemented as a 16x16x16 cache of ints (ie 16K storage in total). The index of the element to be used in the array is determined by the lower // four bits of each x/y/z position, and the upper 7/4/7 bits of the x/y/z positions are stored within the element itself along with the cached values etc. The cache can be enabled per thread by @@ -1333,10 +1332,10 @@ int Level::getBrightness(LightLayer::variety layer, int x, int y, int z) if( ( ix < 0 ) || ( ix >= chunkSourceXZSize ) ) return 0; if( ( iz < 0 ) || ( iz >= chunkSourceXZSize ) ) return 0; - int idx = MultiPlayerChunkCache::wrapCoord(ix, LEVEL_MIN_WIDTH) * LEVEL_MIN_WIDTH + MultiPlayerChunkCache::wrapCoord(iz, LEVEL_MIN_WIDTH); + int idx = ix * chunkSourceXZSize + iz; LevelChunk *c = chunkSourceCache[idx]; - if( c == nullptr) return (int)layer; + if( c == nullptr ) return (int)layer; if (y < 0) y = 0; if (y >= maxBuildHeight) y = maxBuildHeight - 1; @@ -1382,7 +1381,7 @@ void Level::getNeighbourBrightnesses(int *brightnesses, LightLayer::variety laye return; } - int idx = MultiPlayerChunkCache::wrapCoord(ix, LEVEL_MIN_WIDTH) * LEVEL_MIN_WIDTH + MultiPlayerChunkCache::wrapCoord(iz, LEVEL_MIN_WIDTH); + int idx = ix * chunkSourceXZSize + iz; LevelChunk *c = chunkSourceCache[idx]; // 4J Stu - The java LightLayer was an enum class type with a member "surrounding" which is what we diff --git a/Minecraft.World/LevelData.cpp b/Minecraft.World/LevelData.cpp index e9f22fdb..0edd2d7e 100644 --- a/Minecraft.World/LevelData.cpp +++ b/Minecraft.World/LevelData.cpp @@ -185,7 +185,6 @@ LevelData::LevelData(CompoundTag *tag) case LEVEL_WIDTH_SMALL: hostOptionworldSize = e_worldSize_Small; break; case LEVEL_WIDTH_MEDIUM: hostOptionworldSize = e_worldSize_Medium; break; case LEVEL_WIDTH_LARGE: hostOptionworldSize = e_worldSize_Large; break; - case LEVEL_WIDTH_EXPANDED: hostOptionworldSize = e_worldSize_Expanded; break; default: assert(0); break; } app.SetGameHostOption(eGameHostOption_WorldSize, hostOptionworldSize ); From 6ed34078fd97c5056137461ea7e44a4c030471c2 Mon Sep 17 00:00:00 2001 From: pieeebot <274605694+pieeebot@users.noreply.github.com> Date: Mon, 25 May 2026 21:10:22 +0300 Subject: [PATCH 3/7] chore: release v1.0.7b --- BUMP | 2 +- NOTES.md | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/BUMP b/BUMP index 24a364be..ce96854b 100644 --- a/BUMP +++ b/BUMP @@ -1 +1 @@ -1.0.6b +1.0.7b diff --git a/NOTES.md b/NOTES.md index 01c3f9c2..5a3445e9 100644 --- a/NOTES.md +++ b/NOTES.md @@ -1,7 +1,6 @@ -# neoLegacy v1.0.5b +# neoLegacy v1.0.7b -### Bug Fixes -- Fixed crashing, lagging, and lighting issues caused by expanded world generation. +- Reverted "Expanded" world size due to it causing crashing and lighting issues. roadmap From ef0dad4ffc4094cc83fa05212613bed2899a418a Mon Sep 17 00:00:00 2001 From: Joud Kandeel <97121061+CDevJoud@users.noreply.github.com> Date: Mon, 25 May 2026 21:13:28 +0200 Subject: [PATCH 4/7] fix: memory leaks and heavily optimize the game (#117) * fixed performance issue on getting texture height for rendering the player model as it loades the player texture on every frame * updated the lifetime of the texture * fixed 20 MB memory leak * delay window display until engine init is done --- Minecraft.Client/MemTexture.h | 9 +++++++- Minecraft.Client/Textures.cpp | 8 ++++++- .../Windows64/Windows64_Minecraft.cpp | 22 +++++++++++++++---- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/Minecraft.Client/MemTexture.h b/Minecraft.Client/MemTexture.h index d11d68b1..4afa799c 100644 --- a/Minecraft.Client/MemTexture.h +++ b/Minecraft.Client/MemTexture.h @@ -10,7 +10,14 @@ public: int id; bool isLoaded; int ticksSinceLastUse; - static const int UNUSED_TICKS_TO_FREE = 20; + // @CDevJoud + // changing the lifetime of the texture from 20 ticks(1 sec) to 200 ticks (10 sec) + // as it helps the texture to have longer lifetime and reducing the usage of loadTexture for every second/frame + // note that we dont remove the code that removes the textures from `tick()` as it is required in memory limited environment such as older Consoles(PS3/XBOX360) + static const int UNUSED_TICKS_TO_FREE = 200; + + //default ctor for int Texture::getHeight(const wstring& url, int backup) + MemTexture() = default; MemTexture(const wstring& _name, PBYTE pbData, DWORD dwBytes, MemTextureProcessor *processor); ~MemTexture(); diff --git a/Minecraft.Client/Textures.cpp b/Minecraft.Client/Textures.cpp index 627255b6..0db18171 100644 --- a/Minecraft.Client/Textures.cpp +++ b/Minecraft.Client/Textures.cpp @@ -1256,8 +1256,14 @@ int Textures::getHeight(const wstring& url, int backup) if (img) { + MemTexture* _texture = new MemTexture(); + _texture->loadedImage = img; + _texture->isLoaded = true; + _texture->id = getTexture(_texture->loadedImage, C4JRender::TEXTURE_FORMAT_RxGyBzAw, MIPMAP); + int h = img->getHeight(); - delete img; + //delete img; // commenting this out and inserting the loaded texture to memTextures unordered_map + this->memTextures[url] = _texture; return h; } diff --git a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp index 03467061..91fd812f 100644 --- a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp +++ b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp @@ -824,8 +824,7 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) return FALSE; } - ShowWindow(g_hWnd, (nCmdShow != SW_HIDE) ? SW_SHOWMAXIMIZED : nCmdShow); - UpdateWindow(g_hWnd); + return TRUE; } @@ -1456,8 +1455,9 @@ void CleanupDevice() static Minecraft* InitialiseMinecraftRuntime() { app.loadMediaArchive(); - - RenderManager.Initialise(g_pd3dDevice, g_pSwapChain); + // @CDevJoud: No need to call this method as it gets called once in `InitDevice()` + // Calling it again and it results of 20MB of memory leak! + //RenderManager.Initialise(g_pd3dDevice, g_pSwapChain); app.loadStringTable(); ui.init(g_pd3dDevice, g_pImmediateContext, g_pRenderTargetView, g_pDepthStencilView, g_rScreenWidth, g_rScreenHeight); @@ -1790,6 +1790,20 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, hr = XuiTimersRun(); } #endif + + // @CDevJoud The window should only be shown after the engine/game + // initialization has fully completed. + // + // Showing the window too early especially on low end devices, + // may cause windows to display a "Not Responding" state while + // initialization is still in progress. + // + // This creates an unprofessional first impression for the player. + // Instead, initialize all engine systems first, then display the + // window once everything is ready. + ShowWindow(g_hWnd, (nCmdShow != SW_HIDE) ? SW_SHOWMAXIMIZED : nCmdShow); + UpdateWindow(g_hWnd); + MSG msg = {0}; while( WM_QUIT != msg.message && !app.m_bShutdown) { From ac3ece01c74ed0059833201758fc51a70ba85c03 Mon Sep 17 00:00:00 2001 From: Necmi Date: Mon, 25 May 2026 22:17:36 +0300 Subject: [PATCH 5/7] fix: stop elytra sound when going to mainmenu (#118) --- Minecraft.Client/Minecraft.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Minecraft.Client/Minecraft.cpp b/Minecraft.Client/Minecraft.cpp index 0889da34..578a9479 100644 --- a/Minecraft.Client/Minecraft.cpp +++ b/Minecraft.Client/Minecraft.cpp @@ -4438,6 +4438,8 @@ void Minecraft::setLevel(MultiPlayerLevel *level, int message /*=-1*/, shared_pt // 4J If we are setting the level to nullptr then we are exiting, so delete the levels if( level == nullptr ) { + if (soundEngine) soundEngine->stopElytraSound(); + if(levels[0]!=nullptr) { delete levels[0]; From 285fab70b2d110bcc67e461a0d32138be3686cd7 Mon Sep 17 00:00:00 2001 From: Fireblade <72758695+Firebladedoge229@users.noreply.github.com> Date: Mon, 25 May 2026 15:30:55 -0400 Subject: [PATCH 6/7] chore: update revelations url --- .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 12d5fe38..c4514c62 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -62,7 +62,7 @@ body: - type: input id: itsrevela attributes: - label: Is this reproducable in itsRevela/LCE-Revelations? (https://github.com/itsRevela/LCE-Revelations) + label: Is this reproducable in itsRevela/LCE-Revelations? (https://git.revela.dev/itsRevela/LCE-Revelations) description: If this was a "no idea" or similar, it will be rejected. validations: required: true From 544befe162d3d7a3647c6f40ae61c7cdf994baf4 Mon Sep 17 00:00:00 2001 From: Zero <128979226+lux-zero-161@users.noreply.github.com> Date: Tue, 26 May 2026 14:47:43 +0200 Subject: [PATCH 7/7] Fix multiple memory leaks and stale pooled allocations (#123) --- Minecraft.Client/GuiParticles.cpp | 10 ++++++++++ Minecraft.Client/GuiParticles.h | 1 + Minecraft.Client/Minecraft.cpp | 5 +++-- Minecraft.Client/Screen.cpp | 12 ++++++++++++ Minecraft.Client/Screen.h | 1 + Minecraft.World/AABB.cpp | 6 ++++++ Minecraft.World/Vec3.cpp | 6 ++++++ 7 files changed, 39 insertions(+), 2 deletions(-) diff --git a/Minecraft.Client/GuiParticles.cpp b/Minecraft.Client/GuiParticles.cpp index 79240288..864ea29e 100644 --- a/Minecraft.Client/GuiParticles.cpp +++ b/Minecraft.Client/GuiParticles.cpp @@ -8,6 +8,15 @@ GuiParticles::GuiParticles(Minecraft *mc) this->mc = mc; } +GuiParticles::~GuiParticles() +{ + for (GuiParticle *gp : particles) + { + delete gp; + } + particles.clear(); +} + void GuiParticles::tick() { for (unsigned int i = 0; i < particles.size(); i++) @@ -19,6 +28,7 @@ void GuiParticles::tick() if (gp->removed) { + delete gp; particles.erase(particles.begin()+i); i--; } diff --git a/Minecraft.Client/GuiParticles.h b/Minecraft.Client/GuiParticles.h index 0fe31811..cbfc089d 100644 --- a/Minecraft.Client/GuiParticles.h +++ b/Minecraft.Client/GuiParticles.h @@ -13,6 +13,7 @@ private: public: GuiParticles(Minecraft *mc); + ~GuiParticles(); void tick(); void add(GuiParticle *guiParticle); void render(float a); diff --git a/Minecraft.Client/Minecraft.cpp b/Minecraft.Client/Minecraft.cpp index 578a9479..886b96a9 100644 --- a/Minecraft.Client/Minecraft.cpp +++ b/Minecraft.Client/Minecraft.cpp @@ -526,9 +526,10 @@ LevelStorageSource *Minecraft::getLevelSource() void Minecraft::setScreen(Screen *screen) { - if (this->screen != nullptr) + Screen *oldScreen = this->screen; + if (oldScreen != nullptr) { - this->screen->removed(); + oldScreen->removed(); } #ifdef _WINDOWS64 diff --git a/Minecraft.Client/Screen.cpp b/Minecraft.Client/Screen.cpp index 071b42cc..38a645bb 100644 --- a/Minecraft.Client/Screen.cpp +++ b/Minecraft.Client/Screen.cpp @@ -23,6 +23,18 @@ Screen::Screen() // 4J added clickedButton = nullptr; } +Screen::~Screen() +{ + delete particles; + particles = nullptr; + + for (Button *button : buttons) + { + delete button; + } + buttons.clear(); +} + void Screen::render(int xm, int ym, float a) { for (Button* button : buttons) diff --git a/Minecraft.Client/Screen.h b/Minecraft.Client/Screen.h index 6b2cb945..04f9296d 100644 --- a/Minecraft.Client/Screen.h +++ b/Minecraft.Client/Screen.h @@ -22,6 +22,7 @@ public: GuiParticles *particles; Screen(); // 4J added + virtual ~Screen(); virtual void render(int xm, int ym, float a); protected: virtual void keyPressed(wchar_t eventCharacter, int eventKey); diff --git a/Minecraft.World/AABB.cpp b/Minecraft.World/AABB.cpp index af0501b4..b6fc1375 100644 --- a/Minecraft.World/AABB.cpp +++ b/Minecraft.World/AABB.cpp @@ -54,10 +54,16 @@ AABB *AABB::newPermanent(double x0, double y0, double z0, double x1, double y1, void AABB::clearPool() { + ThreadStorage *tls = static_cast(TlsGetValue(tlsIdx)); + if (tls != nullptr) + { + tls->poolPointer = 0; + } } void AABB::resetPool() { + clearPool(); } AABB *AABB::newTemp(double x0, double y0, double z0, double x1, double y1, double z1) diff --git a/Minecraft.World/Vec3.cpp b/Minecraft.World/Vec3.cpp index 75619bb0..cc9901a6 100644 --- a/Minecraft.World/Vec3.cpp +++ b/Minecraft.World/Vec3.cpp @@ -49,10 +49,16 @@ Vec3 *Vec3::newPermanent(double x, double y, double z) void Vec3::clearPool() { + ThreadStorage *tls = static_cast(TlsGetValue(tlsIdx)); + if (tls != nullptr) + { + tls->poolPointer = 0; + } } void Vec3::resetPool() { + clearPool(); } Vec3 *Vec3::newTemp(double x, double y, double z)