it works kinda but its laggy

This commit is contained in:
DrPerkyLegit 2026-05-19 16:42:23 -04:00
parent 42ee0b519e
commit 2830b973d4
9 changed files with 140 additions and 121 deletions

View file

@ -93,8 +93,8 @@ MultiPlayerChunkCache::MultiPlayerChunkCache(Level *level)
this->level = level;
this->cache = new LevelChunk *[XZSIZE * XZSIZE];
memset(this->cache, 0, XZSIZE * XZSIZE * sizeof(LevelChunk *));
//this->cache = new LevelChunk *[XZSIZE * XZSIZE];
//memset(this->cache, 0, XZSIZE * XZSIZE * sizeof(LevelChunk *));
InitializeCriticalSectionAndSpinCount(&m_csLoadCreate,4000);
}
@ -102,7 +102,7 @@ MultiPlayerChunkCache::~MultiPlayerChunkCache()
{
delete emptyChunk;
delete waterChunk;
delete cache;
dynamic_cache.clear(); //delete cache;
delete hasData;
for (auto& it : loadedChunkList)
@ -130,12 +130,10 @@ bool MultiPlayerChunkCache::reallyHasChunk(int x, int z)
if( ( ix < 0 ) || ( ix >= XZSIZE ) ) return true;
if( ( iz < 0 ) || ( iz >= XZSIZE ) ) return true;
int idx = ix * XZSIZE + iz;
auto itor = dynamic_cache.find(idx);
if (itor == dynamic_cache.end() || itor->second == nullptr) return false;
LevelChunk *chunk = cache[idx];
if( chunk == nullptr )
{
return false;
}
return hasData[idx];
}
@ -146,19 +144,18 @@ void MultiPlayerChunkCache::drop(const int x, const int z)
if ((ix < 0) || (ix >= XZSIZE)) return;
if ((iz < 0) || (iz >= XZSIZE)) return;
const int idx = ix * XZSIZE + iz;
LevelChunk* chunk = cache[idx];
auto itor = dynamic_cache.find(idx);
if (itor == dynamic_cache.end() || itor->second == nullptr || itor->second->isEmpty()) return;
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.
// Don't delete tile entities, as they won't get recreated unless they've got
// update packets. Tile entities are created on the client by the chunk rebuild.
chunk->unload(false);
// 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.
// Don't delete tile entities, as they won't get recreated unless they've got
// update packets. Tile entities are created on the client by the chunk rebuild.
itor->second->unload(false);
// Keep chunk in cache with structural data intact.
chunk->loaded = true;
}
// Keep chunk in cache with structural data intact.
itor->second->loaded = true;
}
LevelChunk *MultiPlayerChunkCache::create(int x, int z)
@ -169,11 +166,16 @@ LevelChunk *MultiPlayerChunkCache::create(int x, int z)
if( ( ix < 0 ) || ( ix >= XZSIZE ) ) return ( waterChunk ? waterChunk : emptyChunk );
if( ( iz < 0 ) || ( iz >= XZSIZE ) ) return ( waterChunk ? waterChunk : emptyChunk );
int idx = ix * XZSIZE + iz;
LevelChunk *chunk = cache[idx];
LevelChunk *lastChunk = chunk;
LevelChunk* chunk = nullptr;
LevelChunk* lastChunk = nullptr;
auto itor = dynamic_cache.find(idx);
if( chunk == nullptr )
{
if (itor != dynamic_cache.end()) {
chunk = itor->second;
lastChunk = chunk;
}
if (chunk == nullptr) {
EnterCriticalSection(&m_csLoadCreate);
//LevelChunk *chunk;
@ -210,9 +212,9 @@ LevelChunk *MultiPlayerChunkCache::create(int x, int z)
LeaveCriticalSection(&m_csLoadCreate);
#if ( defined _WIN64 || defined __LP64__ )
if( InterlockedCompareExchangeRelease64((LONG64 *)&cache[idx],(LONG64)chunk,(LONG64)lastChunk) == (LONG64)lastChunk )
if( InterlockedCompareExchangeRelease64((LONG64 *)&dynamic_cache[idx],(LONG64)chunk,(LONG64)lastChunk) == (LONG64)lastChunk )
#else
if( InterlockedCompareExchangeRelease((LONG *)&cache[idx],(LONG)chunk,(LONG)lastChunk) == (LONG)lastChunk )
if( InterlockedCompareExchangeRelease((LONG *)&dynamic_cache[idx],(LONG)chunk,(LONG)lastChunk) == (LONG)lastChunk )
#endif // _DURANGO
{
// If we're sharing with the server, we'll need to calculate our heightmap now, which isn't shared. If we aren't sharing with the server,
@ -232,7 +234,11 @@ LevelChunk *MultiPlayerChunkCache::create(int x, int z)
// Something else must have updated the cache. Return that chunk and discard this one. This really shouldn't be happening
// in multiplayer
delete chunk;
return cache[idx];
itor = dynamic_cache.find(idx);
if (itor == dynamic_cache.end()) return nullptr;
return itor->second;
}
}
@ -252,16 +258,11 @@ LevelChunk *MultiPlayerChunkCache::getChunk(int x, int z)
if( ( ix < 0 ) || ( ix >= XZSIZE ) ) return ( waterChunk ? waterChunk : emptyChunk );
if( ( iz < 0 ) || ( iz >= XZSIZE ) ) return ( waterChunk ? waterChunk : emptyChunk );
int idx = ix * XZSIZE + iz;
auto itor = dynamic_cache.find(idx);
LevelChunk *chunk = cache[idx];
if( chunk == nullptr )
{
return emptyChunk;
}
else
{
return chunk;
}
if (itor == dynamic_cache.end() || itor->second == nullptr) return emptyChunk;
return itor->second;
}
bool MultiPlayerChunkCache::save(bool force, ProgressListener *progressListener)

View file

@ -16,7 +16,7 @@ private:
vector<LevelChunk *> loadedChunkList;
LevelChunk **cache;
//LevelChunk **cache;
// 4J - added for multithreaded support
CRITICAL_SECTION m_csLoadCreate;
// 4J - size of cache is defined by size of one side - must be even
@ -44,5 +44,5 @@ public:
virtual void recreateLogicStructuresForChunk(int chunkX, int chunkZ);
virtual void dataReceived(int x, int z); // 4J added
virtual LevelChunk **getCache() { return cache; } // 4J added
virtual std::unordered_map<uint64_t, LevelChunk*>& getCache() { return dynamic_cache; } // 4J added
};

View file

@ -33,7 +33,7 @@ MultiPlayerLevel::MultiPlayerLevel(ClientConnection *connection, LevelSettings *
// 4J - this this used to be called in parent ctor via a virtual fn
chunkSource = createChunkSource();
// 4J - optimisation - keep direct reference of underlying cache here
chunkSourceCache = chunkSource->getCache();
dynamic_chunkSourceCache = chunkSource->getCache();
chunkSourceXZSize = chunkSource->m_XZSize;
// This also used to be called in parent ctor, but can't be called until chunkSource is created. Call now if required.

View file

@ -30,12 +30,12 @@ ServerChunkCache::ServerChunkCache(ServerLevel *level, ChunkStorage *storage, Ch
this->source = source;
this->m_XZSize = source->m_XZSize;
this->cache = new LevelChunk *[XZSIZE * XZSIZE];
memset(this->cache, 0, XZSIZE * XZSIZE * sizeof(LevelChunk *));
//this->cache = new LevelChunk *[XZSIZE * XZSIZE];
//memset(this->cache, 0, XZSIZE * XZSIZE * sizeof(LevelChunk *));
#ifdef _LARGE_WORLDS
m_unloadedCache = new LevelChunk *[XZSIZE * XZSIZE];
memset(m_unloadedCache, 0, XZSIZE * XZSIZE * sizeof(LevelChunk *));
//m_unloadedCache = new LevelChunk *[XZSIZE * XZSIZE];
//memset(m_unloadedCache, 0, XZSIZE * XZSIZE * sizeof(LevelChunk *));
#endif
InitializeCriticalSectionAndSpinCount(&m_csLoadCreate,4000);
@ -46,15 +46,15 @@ ServerChunkCache::~ServerChunkCache()
{
storage->WaitForAll(); // MGH - added to fix crash bug 175183
delete emptyChunk;
delete cache;
dynamic_cache.clear(); //delete cache;
delete source;
#ifdef _LARGE_WORLDS
for(unsigned int i = 0; i < XZSIZE * XZSIZE; ++i)
{
delete m_unloadedCache[i];
for (auto& pair : dynamic_unloadedCache) {
delete pair.second;
}
delete m_unloadedCache;
dynamic_unloadedCache.clear();
#endif
for (auto& it : m_loadedChunkList)
@ -73,8 +73,11 @@ bool ServerChunkCache::hasChunk(int x, int z)
if( ( ix < 0 ) || ( ix >= XZSIZE ) ) return true;
if( ( iz < 0 ) || ( iz >= XZSIZE ) ) return true;
int idx = ix * XZSIZE + iz;
LevelChunk *lc = cache[idx];
if( lc == nullptr ) return false;
auto itor = dynamic_cache.find(idx);
if (itor == dynamic_cache.end()) return false;
if (itor->second == nullptr) return false;
return true;
}
@ -90,11 +93,11 @@ void ServerChunkCache::drop(const int x, const int z)
if ((ix < 0) || (ix >= XZSIZE)) return;
if ((iz < 0) || (iz >= XZSIZE)) return;
const int idx = ix * XZSIZE + iz;
LevelChunk* chunk = cache[idx];
auto itor = dynamic_cache.find(idx);
if (chunk != nullptr)
if (itor != dynamic_cache.end() && itor->second != nullptr)
{
m_toDrop.push_back(chunk);
m_toDrop.push_back(itor->second);
}
}
@ -121,38 +124,40 @@ LevelChunk *ServerChunkCache::create(int x, int z, bool asyncPostProcess) // 4J
if( ( iz < 0 ) || ( iz >= XZSIZE ) ) return emptyChunk;
int idx = ix * XZSIZE + iz;
LevelChunk *chunk = cache[idx];
LevelChunk *lastChunk = chunk;
LevelChunk* chunk = nullptr;
LevelChunk* lastChunk = nullptr;
auto itor = dynamic_cache.find(idx);
if( ( chunk == nullptr ) || ( chunk->x != x ) || ( chunk->z != z ) )
{
if (itor != dynamic_cache.end()) {
chunk = itor->second;
lastChunk = chunk;
}
if (chunk == nullptr || chunk->x != x || chunk->z != z) {
EnterCriticalSection(&m_csLoadCreate);
chunk = load(x, z);
chunk = load(x, z);
#ifdef MINECRAFT_SERVER_BUILD
bool isNewChunk = (chunk == nullptr);
#endif
if (chunk == nullptr)
{
if (source == nullptr)
{
chunk = emptyChunk;
}
else
{
chunk = source->getChunk(x, z);
}
}
if (chunk != nullptr)
{
if (chunk == nullptr) {
if (source == nullptr) {
chunk = emptyChunk;
} else {
chunk = source->getChunk(x, z);
}
}
if (chunk != nullptr) {
chunk->load();
}
LeaveCriticalSection(&m_csLoadCreate);
#if ( defined _WIN64 || defined __LP64__ )
if( InterlockedCompareExchangeRelease64((LONG64 *)&cache[idx],(LONG64)chunk,(LONG64)lastChunk) == (LONG64)lastChunk )
if (InterlockedCompareExchangeRelease64((LONG64*)&dynamic_cache[idx], (LONG64)chunk, (LONG64)lastChunk) == (LONG64)lastChunk)
#else
if( InterlockedCompareExchangeRelease((LONG *)&cache[idx],(LONG)chunk,(LONG)lastChunk) == (LONG)lastChunk )
if (InterlockedCompareExchangeRelease((LONG*)&dynamic_cache[idx], (LONG)chunk, (LONG)lastChunk) == (LONG)lastChunk)
#endif // _DURANGO
{
// Successfully updated the cache
@ -162,7 +167,7 @@ LevelChunk *ServerChunkCache::create(int x, int z, bool asyncPostProcess) // 4J
// they are in fail ServerChunkCache::hasChunk.
source->lightChunk(chunk);
updatePostProcessFlags( x, z );
updatePostProcessFlags(x, z);
m_loadedChunkList.push_back(chunk);
@ -179,13 +184,13 @@ LevelChunk *ServerChunkCache::create(int x, int z, bool asyncPostProcess) // 4J
// the chunk which is to be processed itself rather than (what I presume to be) the correct position.
// Don't think we should change in case it alters level creation.
if( asyncPostProcess )
if (asyncPostProcess)
{
// 4J Stu - TODO This should also be calling the same code as chunk->checkPostProcess, but then we cannot guarantee we are in the server add the post-process request
if ( ( (chunk->terrainPopulated & LevelChunk::sTerrainPopulatedFromHere) == 0) && hasChunk(x + 1, z + 1) && hasChunk(x, z + 1) && hasChunk(x + 1, z)) MinecraftServer::getInstance()->addPostProcessRequest(this, x, z);
if (hasChunk(x - 1, z) && ((getChunk(x - 1, z)->terrainPopulated & LevelChunk::sTerrainPopulatedFromHere ) == 0 ) && hasChunk(x - 1, z + 1) && hasChunk(x, z + 1) && hasChunk(x - 1, z)) MinecraftServer::getInstance()->addPostProcessRequest(this, x - 1, z);
if (hasChunk(x, z - 1) && ((getChunk(x, z - 1)->terrainPopulated & LevelChunk::sTerrainPopulatedFromHere ) == 0 ) && hasChunk(x + 1, z - 1) && hasChunk(x, z - 1) && hasChunk(x + 1, z)) MinecraftServer::getInstance()->addPostProcessRequest(this, x, z - 1);
if (hasChunk(x - 1, z - 1) && ((getChunk(x - 1, z - 1)->terrainPopulated & LevelChunk::sTerrainPopulatedFromHere ) == 0 ) && hasChunk(x - 1, z - 1) && hasChunk(x, z - 1) && hasChunk(x - 1, z)) MinecraftServer::getInstance()->addPostProcessRequest(this, x - 1, z - 1);
if (((chunk->terrainPopulated & LevelChunk::sTerrainPopulatedFromHere) == 0) && hasChunk(x + 1, z + 1) && hasChunk(x, z + 1) && hasChunk(x + 1, z)) MinecraftServer::getInstance()->addPostProcessRequest(this, x, z);
if (hasChunk(x - 1, z) && ((getChunk(x - 1, z)->terrainPopulated & LevelChunk::sTerrainPopulatedFromHere) == 0) && hasChunk(x - 1, z + 1) && hasChunk(x, z + 1) && hasChunk(x - 1, z)) MinecraftServer::getInstance()->addPostProcessRequest(this, x - 1, z);
if (hasChunk(x, z - 1) && ((getChunk(x, z - 1)->terrainPopulated & LevelChunk::sTerrainPopulatedFromHere) == 0) && hasChunk(x + 1, z - 1) && hasChunk(x, z - 1) && hasChunk(x + 1, z)) MinecraftServer::getInstance()->addPostProcessRequest(this, x, z - 1);
if (hasChunk(x - 1, z - 1) && ((getChunk(x - 1, z - 1)->terrainPopulated & LevelChunk::sTerrainPopulatedFromHere) == 0) && hasChunk(x - 1, z - 1) && hasChunk(x, z - 1) && hasChunk(x - 1, z)) MinecraftServer::getInstance()->addPostProcessRequest(this, x - 1, z - 1);
}
else
{
@ -203,32 +208,33 @@ LevelChunk *ServerChunkCache::create(int x, int z, bool asyncPostProcess) // 4J
// oxooo ooooo oooxo oxPxo ooxoo
// ooooo ooooo ooooo ooxoo ooooo
if( hasChunk( x - 1, z ) && hasChunk( x - 2, z ) && hasChunk( x - 1, z + 1 ) && hasChunk( x - 1, z - 1 ) ) chunk->checkChests( this, x - 1, z );
if( hasChunk( x, z + 1) && hasChunk( x , z + 2 ) && hasChunk( x - 1, z + 1 ) && hasChunk( x + 1, z + 1 ) ) chunk->checkChests( this, x, z + 1);
if( hasChunk( x + 1, z ) && hasChunk( x + 2, z ) && hasChunk( x + 1, z + 1 ) && hasChunk( x + 1, z - 1 ) ) chunk->checkChests( this, x + 1, z );
if( hasChunk( x, z - 1) && hasChunk( x , z - 2 ) && hasChunk( x - 1, z - 1 ) && hasChunk( x + 1, z - 1 ) ) chunk->checkChests( this, x, z - 1);
if( hasChunk( x - 1, z ) && hasChunk( x + 1, z ) && hasChunk ( x, z - 1 ) && hasChunk( x, z + 1 ) ) chunk->checkChests( this, x, z );
if (hasChunk(x - 1, z) && hasChunk(x - 2, z) && hasChunk(x - 1, z + 1) && hasChunk(x - 1, z - 1)) chunk->checkChests(this, x - 1, z);
if (hasChunk(x, z + 1) && hasChunk(x, z + 2) && hasChunk(x - 1, z + 1) && hasChunk(x + 1, z + 1)) chunk->checkChests(this, x, z + 1);
if (hasChunk(x + 1, z) && hasChunk(x + 2, z) && hasChunk(x + 1, z + 1) && hasChunk(x + 1, z - 1)) chunk->checkChests(this, x + 1, z);
if (hasChunk(x, z - 1) && hasChunk(x, z - 2) && hasChunk(x - 1, z - 1) && hasChunk(x + 1, z - 1)) chunk->checkChests(this, x, z - 1);
if (hasChunk(x - 1, z) && hasChunk(x + 1, z) && hasChunk(x, z - 1) && hasChunk(x, z + 1)) chunk->checkChests(this, x, z);
LeaveCriticalSection(&m_csLoadCreate);
#ifdef MINECRAFT_SERVER_BUILD
FourKitBridge::FireChunkLoad(level->dimension->id, x, z, isNewChunk);
#endif
}
else
{
// Something else must have updated the cache. Return that chunk and discard this one
} else {
chunk->unload(true);
delete chunk;
return cache[idx];
itor = dynamic_cache.find(idx);
if (itor == dynamic_cache.end()) return nullptr;
return itor->second;
}
}
}
#ifdef __PS3__
Sleep(1);
#endif // __PS3__
return chunk;
return chunk;
}
// 4J Stu - Split out this function so that we get a chunk without loading entities
@ -241,11 +247,10 @@ LevelChunk *ServerChunkCache::getChunk(int x, int z)
if( ( ix < 0 ) || ( ix >= XZSIZE ) ) return emptyChunk;
if( ( iz < 0 ) || ( iz >= XZSIZE ) ) return emptyChunk;
int idx = ix * XZSIZE + iz;
auto itor = dynamic_cache.find(idx);
LevelChunk *lc = cache[idx];
if( lc )
{
return lc;
if (itor != dynamic_cache.end() && itor->second != nullptr) {
return itor->second;
}
if( level->isFindingSpawn || autoCreate )
@ -269,18 +274,19 @@ LevelChunk *ServerChunkCache::getChunkLoadedOrUnloaded(int x, int z)
if( ( ix < 0 ) || ( ix >= XZSIZE ) ) return emptyChunk;
if( ( iz < 0 ) || ( iz >= XZSIZE ) ) return emptyChunk;
int idx = ix * XZSIZE + iz;
LevelChunk *lc = cache[idx];
if( lc )
{
return lc;
auto itor = dynamic_cache.find(idx);
if (itor != dynamic_cache.end() && itor->second != nullptr) {
return itor->second;
}
}
lc = m_unloadedCache[idx];
if( lc )
{
return lc;
}
auto itor = dynamic_unloadedCache.find(idx);
if (itor != dynamic_unloadedCache.end() && itor->second != nullptr) {
return itor->second;
}
}
if( level->isFindingSpawn || autoCreate )
{
@ -412,8 +418,13 @@ LevelChunk *ServerChunkCache::load(int x, int z)
int ix = x + XZOFFSET;
int iz = z + XZOFFSET;
int idx = ix * XZSIZE + iz;
levelChunk = m_unloadedCache[idx];
m_unloadedCache[idx] = nullptr;
auto itor = dynamic_unloadedCache.find(idx);
if (itor != dynamic_unloadedCache.end()) {
levelChunk = itor->second;
dynamic_unloadedCache.erase(itor);
}
if(levelChunk == nullptr)
#endif
{
@ -943,7 +954,7 @@ bool ServerChunkCache::tick()
if (!level->noSave)
{
#ifdef _LARGE_WORLDS
for (int i = 0; i < 100; i++)
for (int i = 0; i < m_toDrop.size(); i++)
{
if (!m_toDrop.empty())
{
@ -973,9 +984,12 @@ bool ServerChunkCache::tick()
int ix = chunk->x + XZOFFSET;
int iz = chunk->z + XZOFFSET;
int idx = ix * XZSIZE + iz;
delete m_unloadedCache[idx];
m_unloadedCache[idx] = chunk;
cache[idx] = nullptr;
dynamic_unloadedCache.erase(idx);
dynamic_cache.erase(idx);
dynamic_unloadedCache.emplace(idx, chunk);
#ifdef MINECRAFT_SERVER_BUILD
}
#endif

View file

@ -20,13 +20,14 @@ private:
public:
bool autoCreate;
private:
LevelChunk **cache;
//LevelChunk **cache;
vector<LevelChunk *> m_loadedChunkList;
ServerLevel *level;
#ifdef _LARGE_WORLDS
deque<LevelChunk *> m_toDrop;
LevelChunk **m_unloadedCache;
//LevelChunk **m_unloadedCache;
std::unordered_map<uint64_t, LevelChunk*> dynamic_unloadedCache;
#endif
// 4J - added for multithreaded support
@ -52,7 +53,7 @@ public:
void updateOverwriteHellChunk(LevelChunk* origChunk, LevelChunk* playerChunk, int xMin, int xMax, int zMin, int zMax);
#endif
virtual LevelChunk **getCache() { return cache; } // 4J added
virtual std::unordered_map<uint64_t, LevelChunk*>& getCache() { return dynamic_cache; } // 4J added
#ifdef MINECRAFT_SERVER_BUILD
void regenerateChunk(int x, int z);
#endif

View file

@ -111,7 +111,7 @@ ServerLevel::ServerLevel(MinecraftServer *server, shared_ptr<LevelStorage>levelS
// 4J - this this used to be called in parent ctor via a virtual fn
chunkSource = createChunkSource();
// 4J - optimisation - keep direct reference of underlying cache here
chunkSourceCache = chunkSource->getCache();
dynamic_chunkSourceCache = chunkSource->getCache();
chunkSourceXZSize = chunkSource->m_XZSize;
// 4J - The listener used to be added in MinecraftServer::loadLevel but we need it to be set up before we do the next couple of things, or else chunks get loaded before we have the entity tracker set up to listen to them

View file

@ -59,6 +59,9 @@ public:
bool m_mediumEdgeMoat;
#endif
protected:
std::unordered_map<uint64_t, LevelChunk*> dynamic_cache;
public:
virtual ~ChunkSource() {}
@ -73,7 +76,7 @@ public:
virtual bool tick() = 0;
virtual bool shouldSave() = 0;
virtual LevelChunk **getCache() { return nullptr; } // 4J added
virtual std::unordered_map<uint64_t, LevelChunk*>& getCache() { return dynamic_cache; } // 4J added
virtual void dataReceived(int x, int z) {} // 4J added
/**

View file

@ -1333,14 +1333,14 @@ 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;
LevelChunk *c = chunkSourceCache[idx];
auto itor = dynamic_chunkSourceCache.find(idx);
if( c == nullptr ) return (int)layer;
if (itor == dynamic_chunkSourceCache.end() || itor->second == nullptr) return (int)layer;
if (y < 0) y = 0;
if (y >= maxBuildHeight) y = maxBuildHeight - 1;
return c->getBrightness(layer, x & 15, y, z & 15);
return itor->second->getBrightness(layer, x & 15, y, z & 15);
}
// 4J added as optimisation - if all the neighbouring brightesses are going to be in the one chunk, just get
@ -1382,12 +1382,12 @@ void Level::getNeighbourBrightnesses(int *brightnesses, LightLayer::variety laye
}
int idx = ix * chunkSourceXZSize + iz;
LevelChunk *c = chunkSourceCache[idx];
auto itor = dynamic_chunkSourceCache.find(idx);
// 4J Stu - The java LightLayer was an enum class type with a member "surrounding" which is what we
// were returning here. Surrounding has the same value as the enum value in our C++ code, so just cast
// it to an int
if( c == nullptr )
if(itor == dynamic_chunkSourceCache.end() || itor->second == nullptr )
{
for( int i = 0; i < 6; i++ )
{
@ -1397,7 +1397,7 @@ void Level::getNeighbourBrightnesses(int *brightnesses, LightLayer::variety laye
}
// Single call to the levelchunk too to avoid overhead of virtual fn calls
c->getNeighbourBrightnesses(brightnesses, layer, x & 15, y, z & 15);
itor->second->getNeighbourBrightnesses(brightnesses, layer, x & 15, y, z & 15);
}
}

View file

@ -524,7 +524,7 @@ public:
int getAuxValueForMap(PlayerUID xuid, int dimension, int centreXC, int centreZC, int scale);
// 4J - optimisation - keep direct reference of underlying cache here
LevelChunk **chunkSourceCache;
std::unordered_map<uint64_t, LevelChunk*> dynamic_chunkSourceCache;
int chunkSourceXZSize;
// 4J - added for implementation of finite limit to number of item entities, tnt and falling block entities