mirror of
https://github.com/LCEMP/LCEMP.git
synced 2026-04-23 15:33:58 +00:00
fix: multiple savefile fixes
This commit is contained in:
parent
c1a9648bf4
commit
ff2cb7b582
|
|
@ -1474,6 +1474,33 @@ void MinecraftServer::tick()
|
|||
|
||||
tickCount++;
|
||||
|
||||
#ifdef WITH_SERVER_CODE
|
||||
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
|
||||
|
|
|
|||
|
|
@ -174,11 +174,12 @@ LevelChunk *MultiPlayerChunkCache::create(int x, int z)
|
|||
// 4J-JEV: We are about to use shared data, abort if the server is stopped and the data is deleted.
|
||||
if (MinecraftServer::getInstance()->serverHalted()) return NULL;
|
||||
|
||||
// If we're the host, then don't create the chunk, share data from the server's copy
|
||||
// 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
|
||||
|
|
|
|||
|
|
@ -149,8 +149,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)
|
||||
|
|
@ -470,7 +472,7 @@ void ServerChunkCache::postProcess(ChunkSource *parent, int x, int z )
|
|||
{
|
||||
LevelChunk *chunk = getChunk(x, z);
|
||||
if ( (chunk->terrainPopulated & LevelChunk::sTerrainPopulatedFromHere) == 0 )
|
||||
{
|
||||
{
|
||||
if (source != NULL)
|
||||
{
|
||||
PIXBeginNamedEvent(0,"Main post processing");
|
||||
|
|
@ -478,7 +480,7 @@ void ServerChunkCache::postProcess(ChunkSource *parent, int x, int z )
|
|||
PIXEndNamedEvent();
|
||||
|
||||
chunk->markUnsaved();
|
||||
}
|
||||
}
|
||||
|
||||
// Flag not only this chunk as being post-processed, but also all the chunks that this post-processing might affect. We can guarantee that these
|
||||
// chunks exist as that's determined before post-processing can even run
|
||||
|
|
|
|||
|
|
@ -89,7 +89,9 @@ bool WinsockNetLayer::Initialize()
|
|||
|
||||
s_initialized = true;
|
||||
|
||||
#ifndef WITH_SERVER_CODE
|
||||
StartDiscovery();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -455,24 +455,27 @@ LevelChunk *OldChunkStorage::load(Level *level, DataInputStream *dis)
|
|||
|
||||
CompoundTag *tag = NbtIo::read(dis);
|
||||
|
||||
loadEntities(levelChunk, level, tag);
|
||||
|
||||
if (tag->contains(L"TileTicks"))
|
||||
if (tag != NULL)
|
||||
{
|
||||
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"));
|
||||
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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete tag;
|
||||
delete tag;
|
||||
}
|
||||
|
||||
return levelChunk;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -664,7 +664,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();
|
||||
|
||||
|
|
@ -674,7 +674,7 @@ void RandomLevelSource::postProcess(ChunkSource *parent, int xt, int zt)
|
|||
int x = xo + pprandom->nextInt(16) + 8;
|
||||
int y = pprandom->nextInt(Level::genDepth);
|
||||
int z = zo + pprandom->nextInt(16) + 8;
|
||||
|
||||
|
||||
LakeFeature *calmWater = new LakeFeature(Tile::calmWater_Id);
|
||||
calmWater->place(level, pprandom, x, y, z);
|
||||
delete calmWater;
|
||||
|
|
|
|||
|
|
@ -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,15 +17,11 @@ 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
|
||||
{
|
||||
EnterCriticalSection(&m_cs);
|
||||
|
||||
// 4J Jev - changed back to use of the File class.
|
||||
//char file[MAX_PATH_SIZE];
|
||||
//sprintf(file,"%s\\region\\r.%d.%d.mcr",basePath,chunkX >> 5,chunkZ >> 5);
|
||||
|
||||
//File regionDir(basePath, L"region");
|
||||
|
||||
//File file(regionDir, wstring(L"r.") + _toString(chunkX>>5) + L"." + _toString(chunkZ>>5) + L".mcr" );
|
||||
MemSect(31);
|
||||
File file;
|
||||
if(useSplitSaves(saveFile->getSavePlatform()))
|
||||
|
|
@ -46,45 +42,37 @@ RegionFile *RegionFileCache::_getRegionFile(ConsoleSaveFile *saveFile, const wst
|
|||
// 4J Jev, put back in.
|
||||
if (ref != NULL)
|
||||
{
|
||||
LeaveCriticalSection(&m_cs);
|
||||
return ref;
|
||||
}
|
||||
|
||||
// 4J Stu - Remove for new save files
|
||||
/*
|
||||
if (!regionDir.exists())
|
||||
{
|
||||
regionDir.mkdirs();
|
||||
}
|
||||
*/
|
||||
if (cache.size() >= MAX_CACHE_SIZE)
|
||||
{
|
||||
_clear();
|
||||
}
|
||||
|
||||
RegionFile *reg = new RegionFile(saveFile, &file);
|
||||
cache[file] = reg; // 4J - this was originally a softReferenc
|
||||
cache[file] = reg; // 4J - this was originally a softReference
|
||||
LeaveCriticalSection(&m_cs);
|
||||
return reg;
|
||||
|
||||
}
|
||||
|
||||
void RegionFileCache::_clear() // 4J - TODO was synchronized
|
||||
void RegionFileCache::_clear() // 4J - synchronized (recursive CS is safe here)
|
||||
{
|
||||
EnterCriticalSection(&m_cs);
|
||||
AUTO_VAR(itEnd, cache.end());
|
||||
for( AUTO_VAR(it, cache.begin()); it != itEnd; it++ )
|
||||
{
|
||||
// 4J - removed try/catch
|
||||
// try {
|
||||
RegionFile *regionFile = it->second;
|
||||
if (regionFile != NULL)
|
||||
{
|
||||
regionFile->close();
|
||||
}
|
||||
delete regionFile;
|
||||
// } catch (IOException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
}
|
||||
cache.clear();
|
||||
LeaveCriticalSection(&m_cs);
|
||||
}
|
||||
|
||||
int RegionFileCache::_getSizeDelta(ConsoleSaveFile *saveFile, const wstring &prefix, int chunkX, int chunkZ)
|
||||
|
|
|
|||
|
|
@ -10,12 +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() { InitializeCriticalSectionAndSpinCount(&m_cs, 4000); }
|
||||
~RegionFileCache() { DeleteCriticalSection(&m_cs); }
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,12 +7,20 @@
|
|||
#include "net.minecraft.world.level.h"
|
||||
#include "LevelData.h"
|
||||
|
||||
StructureFeature::StructureFeature()
|
||||
{
|
||||
InitializeCriticalSectionAndSpinCount(&m_csCachedStructures, 4000);
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
@ -21,10 +29,13 @@ 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);
|
||||
if (cachedStructures.find(ChunkPos::hashCode(x, z)) != cachedStructures.end())
|
||||
{
|
||||
LeaveCriticalSection(&m_csCachedStructures);
|
||||
return;
|
||||
}
|
||||
LeaveCriticalSection(&m_csCachedStructures);
|
||||
|
||||
// clear random key
|
||||
random->nextInt();
|
||||
|
|
@ -32,7 +43,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -46,6 +59,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;
|
||||
|
|
@ -61,12 +75,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);
|
||||
for( AUTO_VAR(it, cachedStructures.begin()); it != cachedStructures.end(); it++ )
|
||||
{
|
||||
StructureStart *structureStart = it->second;
|
||||
|
|
@ -80,12 +96,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;
|
||||
}
|
||||
|
||||
|
|
@ -94,7 +112,7 @@ bool StructureFeature::isIntersection(int cellX, int cellZ)
|
|||
///////////////////////////////////////////
|
||||
bool StructureFeature::isInsideFeature(int cellX, int cellY, int cellZ)
|
||||
{
|
||||
//for (StructureStart structureStart : cachedStructures.values())
|
||||
EnterCriticalSection(&m_csCachedStructures);
|
||||
for(AUTO_VAR(it, cachedStructures.begin()); it != cachedStructures.end(); ++it)
|
||||
{
|
||||
StructureStart *pStructureStart = it->second;
|
||||
|
|
@ -103,14 +121,6 @@ bool StructureFeature::isInsideFeature(int cellX, int cellY, int cellZ)
|
|||
{
|
||||
if (pStructureStart->getBoundingBox()->intersects(cellX, cellZ, cellX, cellZ))
|
||||
{
|
||||
/*
|
||||
Iterator<StructurePiece> it = structureStart.getPieces().iterator();
|
||||
while (it.hasNext()) {
|
||||
StructurePiece next = it.next();
|
||||
if (next.getBoundingBox().isInside(cellX, cellY, cellZ)) {
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
list<StructurePiece *> *pieces=pStructureStart->getPieces();
|
||||
|
||||
for ( AUTO_VAR(it2, pieces->begin()); it2 != pieces->end(); it2++ )
|
||||
|
|
@ -118,12 +128,14 @@ bool StructureFeature::isInsideFeature(int cellX, int cellY, int cellZ)
|
|||
StructurePiece* piece = *it2;
|
||||
if ( piece->getBoundingBox()->isInside(cellX, cellY, cellZ) )
|
||||
{
|
||||
LeaveCriticalSection(&m_csCachedStructures);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&m_csCachedStructures);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -146,6 +158,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;
|
||||
|
|
@ -169,6 +182,7 @@ TilePos *StructureFeature::getNearestGeneratedFeature(Level *level, int cellX, i
|
|||
}
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&m_csCachedStructures);
|
||||
if (selected != NULL)
|
||||
{
|
||||
return selected;
|
||||
|
|
|
|||
|
|
@ -17,8 +17,10 @@ public:
|
|||
|
||||
protected:
|
||||
unordered_map<__int64, StructureStart *> cachedStructures;
|
||||
CRITICAL_SECTION m_csCachedStructures;
|
||||
|
||||
public:
|
||||
StructureFeature();
|
||||
~StructureFeature();
|
||||
|
||||
virtual void addFeature(Level *level, int x, int z, int xOffs, int zOffs, byteArray blocks);
|
||||
|
|
|
|||
Loading…
Reference in a new issue