LCEMP commit: multiple savefile fixes

This commit is contained in:
pieeebot committed 2026-08-14 14:39:13 +03:00
1 parent feeff55924
commit 494235878e
13 files changed
+94 -32

No files matched your search

@@ -143,7 +143,9 @@ bool NetworkSocketLayer::Initialize()
s_initialized = true;
#ifndef _DEDICATED_SERVER
StartDiscovery();
#endif
return true;
}
+27
View File
@@ -1634,6 +1634,33 @@ void MinecraftServer::tick()
tickCount++;
#ifdef _DEDICATED_SERVER
if (tickCount % 6000 == 0 && !s_bServerHalted)
{
app.DebugPrintf("Auto-saving world...\n");
if (players != NULL)
{
players->saveAll(NULL);
}
for (unsigned int j = 0; j < levels.length; j++)
{
if (s_bServerHalted) break;
ServerLevel *level = levels[levels.length - 1 - j];
if (level) level->save(false, NULL, true);
}
if (!s_bServerHalted)
{
saveGameRules();
levels[0]->saveToDisc(NULL, true);
}
while (StorageManager.GetSaveState() != C4JStorage::ESaveGame_Idle)
{
Sleep(10);
}
app.DebugPrintf("Auto-save complete\n");
}
#endif
// 4J We need to update client difficulty levels based on the servers
Minecraft *pMinecraft = Minecraft::GetInstance();
// 4J-PB - sending this on the host changing the difficulty in the menus
+3 -2
View File
@@ -175,10 +175,11 @@ LevelChunk *MultiPlayerChunkCache::create(int x, int z)
if (MinecraftServer::getInstance()->serverHalted()) return NULL;
// If we're the host, then don't create the chunk, share data from the server's copy
int dimId = level->dimension->id;
#ifdef _LARGE_WORLDS
LevelChunk *serverChunk = MinecraftServer::getInstance()->getLevel(level->dimension->id)->cache->getChunkLoadedOrUnloaded(x,z);
LevelChunk *serverChunk = MinecraftServer::getInstance()->getLevel(dimId)->cache->getChunkLoadedOrUnloaded(x,z);
#else
LevelChunk *serverChunk = MinecraftServer::getInstance()->getLevel(level->dimension->id)->cache->getChunk(x,z);
LevelChunk *serverChunk = MinecraftServer::getInstance()->getLevel(dimId)->cache->getChunk(x,z);
#endif
chunk = new LevelChunk(level, x, z, serverChunk);
// Let renderer know that this chunk has been created - it might have made render data from the EmptyChunk if it got to a chunk before the server sent it
+2
View File
@@ -151,8 +151,10 @@ LevelChunk *ServerChunkCache::create(int x, int z, bool asyncPostProcess) // 4J
if( ( chunk == NULL ) || ( chunk->x != x ) || ( chunk->z != z ) )
{
bool wasLoaded = false;
EnterCriticalSection(&m_csLoadCreate);
chunk = load(x, z);
wasLoaded = (chunk != NULL);
if (chunk == NULL)
{
if (source == NULL)
+14 -15
View File
@@ -476,29 +476,28 @@ LevelChunk *OldChunkStorage::load(Level *level, DataInputStream *dis)
CompoundTag *tag = NbtIo::read(dis);
loadEntities(levelChunk, level, tag);
if (tag->contains(L"TileTicks"))
if (tag != NULL)
{
PIXBeginNamedEvent(0,"Loading TileTicks");
ListTag<CompoundTag> *tileTicks = (ListTag<CompoundTag> *) tag->getList(L"TileTicks");
loadEntities(levelChunk, level, tag);
if (tileTicks != NULL)
if (tag->contains(L"TileTicks"))
{
for (int i = 0; i < tileTicks->size(); i++)
{
CompoundTag *teTag = tileTicks->get(i);
ListTag<CompoundTag> *tileTicks = (ListTag<CompoundTag> *) tag->getList(L"TileTicks");
level->forceAddTileTick(teTag->getInt(L"x"), teTag->getInt(L"y"), teTag->getInt(L"z"), teTag->getInt(L"i"), teTag->getInt(L"t"), teTag->getInt(L"p"));
if (tileTicks != NULL)
{
for (int i = 0; i < tileTicks->size(); i++)
{
CompoundTag *teTag = tileTicks->get(i);
level->forceAddTileTick(teTag->getInt(L"x"), teTag->getInt(L"y"), teTag->getInt(L"z"), teTag->getInt(L"i"), teTag->getInt(L"t"));
}
}
}
PIXEndNamedEvent();
delete tag;
}
delete tag;
PIXEndNamedEvent();
return levelChunk;
}
+1 -1
View File
@@ -778,7 +778,7 @@ void RandomLevelSource::postProcess(ChunkSource *parent, int xt, int zt)
mineShaftFeature->postProcess(level, pprandom, xt, zt);
hasVillage = villageFeature->postProcess(level, pprandom, xt, zt);
strongholdFeature->postProcess(level, pprandom, xt, zt);
scatteredFeature->postProcess(level, random, xt, zt);
scatteredFeature->postProcess(level, pprandom, xt, zt);
}
PIXEndNamedEvent();
+6 -1
View File
@@ -38,7 +38,12 @@ RegionFile::RegionFile(ConsoleSaveFile *saveFile, File *path)
}
*/
fileEntry = m_saveFile->createFile( fileName->getName() );
wstring saveName = fileName->getPath();
for (size_t i = 0; i < saveName.size(); i++)
{
if (saveName[i] == L'\\') saveName[i] = L'/';
}
fileEntry = m_saveFile->createFile( ConsoleSavePath(saveName) );
m_saveFile->setFilePointer( fileEntry, 0, NULL, FILE_END );
if ( fileEntry->getFileSize() < SECTOR_BYTES)
+6 -7
View File
@@ -17,7 +17,7 @@ bool RegionFileCache::useSplitSaves(ESavePlatform platform)
};
}
RegionFile *RegionFileCache::_getRegionFile(ConsoleSaveFile *saveFile, const wstring &prefix, int chunkX, int chunkZ) // 4J - TODO was synchronized
RegionFile *RegionFileCache::_getRegionFile(ConsoleSaveFile *saveFile, const wstring &prefix, int chunkX, int chunkZ) // 4J - synchronized restored
{
// 4J Jev - changed back to use of the File class.
//char file[MAX_PATH_SIZE];
@@ -26,6 +26,7 @@ RegionFile *RegionFileCache::_getRegionFile(ConsoleSaveFile *saveFile, const wst
//File regionDir(basePath, L"region");
//File file(regionDir, wstring(L"r.") + _toString(chunkX>>5) + L"." + _toString(chunkZ>>5) + L".mcr" );
EnterCriticalSection(&m_cs);
MemSect(31);
File file;
if(useSplitSaves(saveFile->getSavePlatform()))
@@ -46,6 +47,7 @@ RegionFile *RegionFileCache::_getRegionFile(ConsoleSaveFile *saveFile, const wst
// 4J Jev, put back in.
if (ref != NULL)
{
LeaveCriticalSection(&m_cs);
return ref;
}
@@ -63,12 +65,14 @@ RegionFile *RegionFileCache::_getRegionFile(ConsoleSaveFile *saveFile, const wst
RegionFile *reg = new RegionFile(saveFile, &file);
cache[file] = reg; // 4J - this was originally a softReferenc
LeaveCriticalSection(&m_cs);
return reg;
}
void RegionFileCache::_clear() // 4J - TODO was synchronized
{
EnterCriticalSection(&m_cs);
AUTO_VAR(itEnd, cache.end());
for( AUTO_VAR(it, cache.begin()); it != itEnd; it++ )
{
@@ -85,6 +89,7 @@ void RegionFileCache::_clear() // 4J - TODO was synchronized
// }
}
cache.clear();
LeaveCriticalSection(&m_cs);
}
int RegionFileCache::_getSizeDelta(ConsoleSaveFile *saveFile, const wstring &prefix, int chunkX, int chunkZ)
@@ -120,9 +125,3 @@ DataOutputStream *RegionFileCache::_getChunkDataOutputStream(ConsoleSaveFile *sa
return r->getChunkDataOutputStream(chunkX & 31, chunkZ & 31);
}
}
RegionFileCache::~RegionFileCache()
{
_clear();
}
+3 -2
View File
@@ -10,13 +10,14 @@ private:
static const int MAX_CACHE_SIZE = 256;
unordered_map<File, RegionFile *, FileKeyHash, FileKeyEq> cache;
CRITICAL_SECTION m_cs;
static RegionFileCache s_defaultCache;
public:
// Made public and non-static so we can have a cache for input and output files
RegionFileCache() {}
~RegionFileCache();
RegionFileCache() { InitializeCriticalSectionAndSpinCount(&m_cs, 4000); }
~RegionFileCache() { DeleteCriticalSection(&m_cs); _clear(); }
RegionFile *_getRegionFile(ConsoleSaveFile *saveFile, const wstring &prefix, int chunkX, int chunkZ); // 4J - TODO was synchronized
void _clear(); // 4J - TODO was synchronized
+3 -2
View File
@@ -602,9 +602,10 @@ bool SparseDataStorage::isCompressed()
void SparseDataStorage::write(DataOutputStream *dos)
{
int count = ( dataAndCount >> 48 ) & 0xffff;
__int64 snapshot = dataAndCount;
int count = ( snapshot >> 48 ) & 0xffff;
dos->writeInt(count);
unsigned char *dataPointer = (unsigned char *)(dataAndCount & 0x0000ffffffffffff);
unsigned char *dataPointer = (unsigned char *)(snapshot & 0x0000ffffffffffff);
byteArray wrapper(dataPointer, count * 128 + 128);
dos->write(wrapper);
}
+3 -2
View File
@@ -619,9 +619,10 @@ bool SparseLightStorage::isCompressed()
void SparseLightStorage::write(DataOutputStream *dos)
{
int count = ( dataAndCount >> 48 ) & 0xffff;
__int64 snapshot = dataAndCount;
int count = ( snapshot >> 48 ) & 0xffff;
dos->writeInt(count);
unsigned char *dataPointer = (unsigned char *)(dataAndCount & 0x0000ffffffffffff);
unsigned char *dataPointer = (unsigned char *)(snapshot & 0x0000ffffffffffff);
byteArray wrapper(dataPointer, count * 128 + 128);
dos->write(wrapper);
}
+23
View File
@@ -9,6 +9,7 @@
StructureFeature::StructureFeature()
{
InitializeCriticalSectionAndSpinCount(&m_csCachedStructures, 4000);
#ifdef ENABLE_STRUCTURE_SAVING
savedData = nullptr;
#endif
@@ -16,10 +17,13 @@ StructureFeature::StructureFeature()
StructureFeature::~StructureFeature()
{
EnterCriticalSection(&m_csCachedStructures);
for( AUTO_VAR(it, cachedStructures.begin()); it != cachedStructures.end(); it++ )
{
delete it->second;
}
LeaveCriticalSection(&m_csCachedStructures);
DeleteCriticalSection(&m_csCachedStructures);
}
void StructureFeature::addFeature(Level *level, int x, int z, int xOffs, int zOffs, byteArray blocks)
@@ -28,12 +32,16 @@ void StructureFeature::addFeature(Level *level, int x, int z, int xOffs, int zOf
// the chunk being generated, but not all chunks are the sources of
// structures
EnterCriticalSection(&m_csCachedStructures);
restoreSavedData(level);
if (cachedStructures.find(ChunkPos::hashCode(x, z)) != cachedStructures.end())
{
LeaveCriticalSection(&m_csCachedStructures);
return;
}
LeaveCriticalSection(&m_csCachedStructures);
// clear random key
random->nextInt();
@@ -41,7 +49,9 @@ void StructureFeature::addFeature(Level *level, int x, int z, int xOffs, int zOf
if (isFeatureChunk(x, z,level->getLevelData()->getGenerator() == LevelType::lvl_flat))
{
StructureStart *start = createStructureStart(x, z);
EnterCriticalSection(&m_csCachedStructures);
cachedStructures[ChunkPos::hashCode(x, z)] = start;
LeaveCriticalSection(&m_csCachedStructures);
saveFeature(x, z, start);
}
}
@@ -58,6 +68,7 @@ bool StructureFeature::postProcess(Level *level, Random *random, int chunkX, int
int cz = (chunkZ << 4); // + 8;
bool intersection = false;
EnterCriticalSection(&m_csCachedStructures);
for( AUTO_VAR(it, cachedStructures.begin()); it != cachedStructures.end(); it++ )
{
StructureStart *structureStart = it->second;
@@ -76,12 +87,14 @@ bool StructureFeature::postProcess(Level *level, Random *random, int chunkX, int
}
}
}
LeaveCriticalSection(&m_csCachedStructures);
return intersection;
}
bool StructureFeature::isIntersection(int cellX, int cellZ)
{
EnterCriticalSection(&m_csCachedStructures);
restoreSavedData(level);
for( AUTO_VAR(it, cachedStructures.begin()); it != cachedStructures.end(); it++ )
@@ -97,12 +110,14 @@ bool StructureFeature::isIntersection(int cellX, int cellZ)
StructurePiece *next = *it2++;
if (next->getBoundingBox()->intersects(cellX, cellZ, cellX, cellZ))
{
LeaveCriticalSection(&m_csCachedStructures);
return true;
}
}
}
}
}
LeaveCriticalSection(&m_csCachedStructures);
return false;
}
@@ -114,6 +129,7 @@ bool StructureFeature::isInsideFeature(int cellX, int cellY, int cellZ)
StructureStart *StructureFeature::getStructureAt(int cellX, int cellY, int cellZ)
{
EnterCriticalSection(&m_csCachedStructures);
//for (StructureStart structureStart : cachedStructures.values())
for(AUTO_VAR(it, cachedStructures.begin()); it != cachedStructures.end(); ++it)
{
@@ -138,12 +154,14 @@ StructureStart *StructureFeature::getStructureAt(int cellX, int cellY, int cellZ
StructurePiece* piece = *it2;
if ( piece->getBoundingBox()->isInside(cellX, cellY, cellZ) )
{
LeaveCriticalSection(&m_csCachedStructures);
return pStructureStart;
}
}
}
}
}
LeaveCriticalSection(&m_csCachedStructures);
return NULL;
}
@@ -151,14 +169,17 @@ bool StructureFeature::isInsideBoundingFeature(int cellX, int cellY, int cellZ)
{
restoreSavedData(level);
EnterCriticalSection(&m_csCachedStructures);
for(AUTO_VAR(it, cachedStructures.begin()); it != cachedStructures.end(); ++it)
{
StructureStart *structureStart = it->second;
if (structureStart->isValid())
{
LeaveCriticalSection(&m_csCachedStructures);
return (structureStart->getBoundingBox()->intersects(cellX, cellZ, cellX, cellZ));
}
}
LeaveCriticalSection(&m_csCachedStructures);
return false;
}
@@ -182,6 +203,7 @@ TilePos *StructureFeature::getNearestGeneratedFeature(Level *level, int cellX, i
double minDistance = DBL_MAX;
TilePos *selected = NULL;
EnterCriticalSection(&m_csCachedStructures);
for(AUTO_VAR(it, cachedStructures.begin()); it != cachedStructures.end(); ++it)
{
StructureStart *pStructureStart = it->second;
@@ -205,6 +227,7 @@ TilePos *StructureFeature::getNearestGeneratedFeature(Level *level, int cellX, i
}
}
}
LeaveCriticalSection(&m_csCachedStructures);
if (selected != NULL)
{
return selected;
+1
View File
@@ -27,6 +27,7 @@ private:
protected:
unordered_map<__int64, StructureStart *> cachedStructures;
CRITICAL_SECTION m_csCachedStructures;
public:
StructureFeature();