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.
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)