LCEMP commit: multiple savefile fixes
This commit is contained in:
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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -27,6 +27,7 @@ private:
|
||||
|
||||
protected:
|
||||
unordered_map<__int64, StructureStart *> cachedStructures;
|
||||
CRITICAL_SECTION m_csCachedStructures;
|
||||
|
||||
public:
|
||||
StructureFeature();
|
||||
|
||||
Reference in new issue
Block a user