aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.Client/ServerChunkCache.cpp
diff options
context:
space:
mode:
authordaoge <3523206925@qq.com>2026-03-03 03:04:10 +0800
committerGitHub <noreply@github.com>2026-03-03 03:04:10 +0800
commitb3feddfef372618c8a9d7a0abcaf18cfad866c18 (patch)
tree267761c3bb39241ba5c347bfbe2254d06686e287 /Minecraft.Client/ServerChunkCache.cpp
parent84c31a2331f7a0ec85b9d438992e244f60e5020f (diff)
feat: TU19 (Dec 2014) Features & Content (#155)
* try to resolve merge conflict * feat: TU19 (Dec 2014) Features & Content (#32) * December 2014 files * Working release build * Fix compilation issues * Add sound to Windows64Media * Add DLC content and force Tutorial DLC * Revert "Add DLC content and force Tutorial DLC" This reverts commit 97a43994725008e35fceb984d5549df9c8cea470. * Disable broken light packing * Disable breakpoint during DLC texture map load Allows DLC loading but the DLC textures are still broken * Fix post build not working * ... * fix vs2022 build * fix cmake build --------- Co-authored-by: Loki <lokirautio@gmail.com>
Diffstat (limited to 'Minecraft.Client/ServerChunkCache.cpp')
-rw-r--r--Minecraft.Client/ServerChunkCache.cpp116
1 files changed, 100 insertions, 16 deletions
diff --git a/Minecraft.Client/ServerChunkCache.cpp b/Minecraft.Client/ServerChunkCache.cpp
index 1fe1a86f..619efa98 100644
--- a/Minecraft.Client/ServerChunkCache.cpp
+++ b/Minecraft.Client/ServerChunkCache.cpp
@@ -11,6 +11,7 @@
#include "..\Minecraft.World\ThreadName.h"
#include "..\Minecraft.World\compression.h"
#include "..\Minecraft.World\OldChunkStorage.h"
+#include "..\Minecraft.World\Tile.h"
ServerChunkCache::ServerChunkCache(ServerLevel *level, ChunkStorage *storage, ChunkSource *source)
{
@@ -40,6 +41,7 @@ ServerChunkCache::ServerChunkCache(ServerLevel *level, ChunkStorage *storage, Ch
// 4J-PB added
ServerChunkCache::~ServerChunkCache()
{
+ storage->WaitForAll(); // MGH - added to fix crash bug 175183
delete emptyChunk;
delete cache;
delete source;
@@ -307,6 +309,76 @@ LevelChunk *ServerChunkCache::getChunkLoadedOrUnloaded(int x, int z)
}
#endif
+
+// 4J MGH added, for expanding worlds, to kill any player changes and reset the chunk
+#ifdef _LARGE_WORLDS
+void ServerChunkCache::overwriteLevelChunkFromSource(int x, int z)
+{
+ int ix = x + XZOFFSET;
+ int iz = z + XZOFFSET;
+ // Check we're in range of the stored level
+ if( ( ix < 0 ) || ( ix >= XZSIZE ) ) assert(0);
+ if( ( iz < 0 ) || ( iz >= XZSIZE ) ) assert(0);
+ int idx = ix * XZSIZE + iz;
+
+ LevelChunk *chunk = NULL;
+ chunk = source->getChunk(x, z);
+ assert(chunk);
+ if(chunk)
+ {
+ save(chunk);
+ }
+}
+
+
+
+void ServerChunkCache::updateOverwriteHellChunk(LevelChunk* origChunk, LevelChunk* playerChunk, int xMin, int xMax, int zMin, int zMax)
+{
+
+ // replace a section of the chunk with the original source data, if it hasn't already changed
+ for(int x=xMin;x<xMax;x++)
+ {
+ for(int z=zMin;z<zMax;z++)
+ {
+ for(int y=0;y<256;y++)
+ {
+ int playerTile = playerChunk->getTile(x,y,z);
+ if(playerTile == Tile::unbreakable_Id) // if the tile is still unbreakable, the player hasn't changed it, so we can replace with the source
+ playerChunk->setTileAndData(x, y, z, origChunk->getTile(x,y,z), origChunk->getData(x,y,z));
+ }
+ }
+ }
+}
+
+void ServerChunkCache::overwriteHellLevelChunkFromSource(int x, int z, int minVal, int maxVal)
+{
+ int ix = x + XZOFFSET;
+ int iz = z + XZOFFSET;
+ // Check we're in range of the stored level
+ if( ( ix < 0 ) || ( ix >= XZSIZE ) ) assert(0);
+ if( ( iz < 0 ) || ( iz >= XZSIZE ) ) assert(0);
+ int idx = ix * XZSIZE + iz;
+ autoCreate = true;
+ LevelChunk* playerChunk = getChunk(x, z);
+ autoCreate = false;
+ LevelChunk* origChunk = source->getChunk(x, z);
+ assert(origChunk);
+ if(playerChunk!= emptyChunk)
+ {
+ if(x == minVal)
+ updateOverwriteHellChunk(origChunk, playerChunk, 0, 4, 0, 16);
+ if(x == maxVal)
+ updateOverwriteHellChunk(origChunk, playerChunk, 12, 16, 0, 16);
+ if(z == minVal)
+ updateOverwriteHellChunk(origChunk, playerChunk, 0, 16, 0, 4);
+ if(z == maxVal)
+ updateOverwriteHellChunk(origChunk, playerChunk, 0, 16, 12, 16);
+ }
+ save(playerChunk);
+}
+
+#endif
+
// 4J Added //
#ifdef _LARGE_WORLDS
void ServerChunkCache::dontDrop(int x, int z)
@@ -335,7 +407,7 @@ LevelChunk *ServerChunkCache::load(int x, int z)
}
if (levelChunk != NULL)
{
- levelChunk->lastSaveTime = level->getTime();
+ levelChunk->lastSaveTime = level->getGameTime();
}
return levelChunk;
}
@@ -351,7 +423,7 @@ void ServerChunkCache::save(LevelChunk *levelChunk)
{
if (storage == NULL) return;
- levelChunk->lastSaveTime = level->getTime();
+ levelChunk->lastSaveTime = level->getGameTime();
storage->save(level, levelChunk);
}
@@ -866,20 +938,28 @@ bool ServerChunkCache::tick()
LevelChunk *chunk = m_toDrop.front();
if(!chunk->isUnloaded())
{
- save(chunk);
- saveEntities(chunk);
- chunk->unload(true);
-
- //loadedChunks.remove(cp);
- //loadedChunkList.remove(chunk);
- AUTO_VAR(it, std::find( m_loadedChunkList.begin(), m_loadedChunkList.end(), chunk) );
- if(it != m_loadedChunkList.end()) m_loadedChunkList.erase(it);
-
- int ix = chunk->x + XZOFFSET;
- int iz = chunk->z + XZOFFSET;
- int idx = ix * XZSIZE + iz;
- m_unloadedCache[idx] = chunk;
- cache[idx] = NULL;
+ // Don't unload a chunk that contains a player, as this will cause their entity to be removed from the level itself and they will never tick again.
+ // This can happen if a player moves a long distance in one tick, for example when the server thread has locked up doing something for a while whilst a player
+ // kept moving. In this case, the player is moved in the player chunk map (driven by the network packets being processed for their new position) before the
+ // player's tick is called to remove them from the chunk they used to be in, and add them to their current chunk. This will only be a temporary state and
+ // we should be able to unload the chunk on the next call to this tick.
+ if( !chunk->containsPlayer() )
+ {
+ save(chunk);
+ saveEntities(chunk);
+ chunk->unload(true);
+
+ //loadedChunks.remove(cp);
+ //loadedChunkList.remove(chunk);
+ AUTO_VAR(it, std::find( m_loadedChunkList.begin(), m_loadedChunkList.end(), chunk) );
+ if(it != m_loadedChunkList.end()) m_loadedChunkList.erase(it);
+
+ int ix = chunk->x + XZOFFSET;
+ int iz = chunk->z + XZOFFSET;
+ int idx = ix * XZSIZE + iz;
+ m_unloadedCache[idx] = chunk;
+ cache[idx] = NULL;
+ }
}
m_toDrop.pop_front();
}
@@ -912,6 +992,10 @@ TilePos *ServerChunkCache::findNearestMapFeature(Level *level, const wstring &fe
return source->findNearestMapFeature(level, featureName, x, y, z);
}
+void ServerChunkCache::recreateLogicStructuresForChunk(int chunkX, int chunkZ)
+{
+}
+
int ServerChunkCache::runSaveThreadProc(LPVOID lpParam)
{
SaveThreadData *params = (SaveThreadData *)lpParam;