Merge commit '889eba1df501e190f9019cc42bad1606477c4cce' into pullstream

This commit is contained in:
Rebekah 2024-02-14 06:25:25 -05:00
commit 5b536dbfbb
Signed by: oneechanhax
GPG Key ID: 183EB7902964DAE5
5 changed files with 77 additions and 44 deletions

View File

@ -57,6 +57,7 @@ target_sources(
Root.cpp
Scoreboard.cpp
Server.cpp
SetChunkData.cpp
SpawnPrepare.cpp
StatisticsManager.cpp
StringCompression.cpp

30
src/SetChunkData.cpp Normal file
View File

@ -0,0 +1,30 @@
#include "Globals.h"
#include "SetChunkData.h"
#include "BlockType.h"
#include "Entities/Entity.h"
void SetChunkData::UpdateHeightMap()
{
for (int x = 0; x < cChunkDef::Width; x++)
{
for (int z = 0; z < cChunkDef::Width; z++)
{
HEIGHTTYPE Height = 0;
for (HEIGHTTYPE y = cChunkDef::Height - 1; y > 0; y--)
{
BLOCKTYPE BlockType = BlockData.GetBlock({x, y, z});
if (BlockType != E_BLOCK_AIR)
{
Height = y;
break;
}
} // for y
auto idx = x + cChunkDef::Width * z;
HeightMap[idx] = Height;
} // for z
} // for x
}

View File

@ -28,6 +28,7 @@
/** Contains the data for a loaded / generated chunk, ready to be set into a cWorld. */
struct SetChunkData
{
/** Initialise the structure with chunk coordinates.
@ -49,4 +50,8 @@ struct SetChunkData
cBlockEntities BlockEntities;
bool IsLightValid;
/** Recalculates the HeightMap based on BlockData contents. */
void UpdateHeightMap();
};

View File

@ -101,7 +101,7 @@ Since only the header is actually in the memory, this number can be high, but st
////////////////////////////////////////////////////////////////////////////////
// cWSSAnvil:
cWSSAnvil::cWSSAnvil(cWorld * a_World, int a_CompressionFactor) :
cWSSAnvil::cWSSAnvil(cWorld * a_World, int a_CompressionFactor):
Super(a_World),
m_Compressor(a_CompressionFactor)
{
@ -194,7 +194,7 @@ bool cWSSAnvil::SaveChunk(const cChunkCoords & a_Chunk)
void cWSSAnvil::ChunkLoadFailed(int a_ChunkX, int a_ChunkZ, const AString & a_Reason, const ContiguousByteBufferView a_ChunkDataToSave)
void cWSSAnvil::ChunkLoadFailed(const cChunkCoords a_ChunkCoords, const AString & a_Reason, const ContiguousByteBufferView a_ChunkDataToSave)
{
// Construct the filename for offloading:
auto OffloadFileName = fmt::format(FMT_STRING("{0}{1}region{1}badchunks"), m_World->GetDataPath(), cFile::PathSeparator());
@ -208,16 +208,16 @@ void cWSSAnvil::ChunkLoadFailed(int a_ChunkX, int a_ChunkZ, const AString & a_Re
#endif
OffloadFileName.append(fmt::format(
FMT_STRING("{}ch.{}.{}.{}-{:02d}-{:02d}-{:02d}-{:02d}-{:02d}.dat"),
cFile::PathSeparator(), a_ChunkX, a_ChunkZ,
cFile::PathSeparator(), a_ChunkCoords.m_ChunkX, a_ChunkCoords.m_ChunkZ,
stm.tm_year + 1900, stm.tm_mon + 1, stm.tm_mday, stm.tm_hour, stm.tm_min, stm.tm_sec
));
// Log the warning to console:
const int RegionX = FAST_FLOOR_DIV(a_ChunkX, 32);
const int RegionZ = FAST_FLOOR_DIV(a_ChunkZ, 32);
const int RegionX = FAST_FLOOR_DIV(a_ChunkCoords.m_ChunkX, 32);
const int RegionZ = FAST_FLOOR_DIV(a_ChunkCoords.m_ChunkZ, 32);
auto Info = fmt::format(
FMT_STRING("Loading chunk [{}, {}] for world {} from file r.{}.{}.mca failed: {} Offloading old chunk data to file {} and regenerating chunk."),
a_ChunkX, a_ChunkZ, m_World->GetName(), RegionX, RegionZ, a_Reason, OffloadFileName
FMT_STRING("Loading chunk {} for world {} from file r.{}.{}.mca failed: {} Offloading old chunk data to file {} and regenerating chunk."),
a_ChunkCoords, m_World->GetName(), RegionX, RegionZ, a_Reason, OffloadFileName
);
LOGWARNING("%s", Info);
@ -345,7 +345,7 @@ bool cWSSAnvil::LoadChunkFromData(const cChunkCoords & a_Chunk, const Contiguous
}
catch (const std::exception & Oops)
{
ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, Oops.what(), a_Data);
ChunkLoadFailed(a_Chunk, Oops.what(), a_Data);
return false;
}
}
@ -375,21 +375,21 @@ bool cWSSAnvil::LoadChunkFromNBT(const cChunkCoords & a_Chunk, const cParsedNBT
int Level = a_NBT.FindChildByName(0, "Level");
if (Level < 0)
{
ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, "Missing NBT tag: Level", a_RawChunkData);
ChunkLoadFailed(a_Chunk, "Missing NBT tag: Level", a_RawChunkData);
return false;
}
int Sections = a_NBT.FindChildByName(Level, "Sections");
if ((Sections < 0) || (a_NBT.GetType(Sections) != TAG_List))
{
ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, "Missing NBT tag: Sections", a_RawChunkData);
ChunkLoadFailed(a_Chunk, "Missing NBT tag: Sections", a_RawChunkData);
return false;
}
eTagType SectionsType = a_NBT.GetChildrenType(Sections);
if ((SectionsType != TAG_Compound) && (SectionsType != TAG_End))
{
ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, "NBT tag has wrong type: Sections", a_RawChunkData);
ChunkLoadFailed(a_Chunk, "NBT tag has wrong type: Sections", a_RawChunkData);
return false;
}
for (int Child = a_NBT.GetFirstChild(Sections); Child >= 0; Child = a_NBT.GetNextSibling(Child))
@ -397,14 +397,14 @@ bool cWSSAnvil::LoadChunkFromNBT(const cChunkCoords & a_Chunk, const cParsedNBT
const int SectionYTag = a_NBT.FindChildByName(Child, "Y");
if ((SectionYTag < 0) || (a_NBT.GetType(SectionYTag) != TAG_Byte))
{
ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, "NBT tag missing or has wrong: Y", a_RawChunkData);
ChunkLoadFailed(a_Chunk, "NBT tag missing or has wrong: Y", a_RawChunkData);
return false;
}
const int Y = a_NBT.GetByte(SectionYTag);
if ((Y < 0) || (Y > static_cast<int>(cChunkDef::NumSections - 1)))
{
ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, "NBT tag exceeds chunk bounds: Y", a_RawChunkData);
ChunkLoadFailed(a_Chunk, "NBT tag exceeds chunk bounds: Y", a_RawChunkData);
return false;
}
@ -420,7 +420,7 @@ bool cWSSAnvil::LoadChunkFromNBT(const cChunkCoords & a_Chunk, const cParsedNBT
}
else
{
ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, "Missing chunk block/light data", a_RawChunkData);
ChunkLoadFailed(a_Chunk, "Missing chunk block/light data", a_RawChunkData);
return false;
}
} // for itr - LevelSections[]
@ -428,15 +428,14 @@ bool cWSSAnvil::LoadChunkFromNBT(const cChunkCoords & a_Chunk, const cParsedNBT
// Load the biomes from NBT, if present and valid:
if (!LoadBiomeMapFromNBT(Data.BiomeMap, a_NBT, a_NBT.FindChildByName(Level, "Biomes")))
{
ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, "Missing chunk biome data", a_RawChunkData);
ChunkLoadFailed(a_Chunk, "Missing chunk biome data", a_RawChunkData);
return false;
}
// Height map too:
// Load the Height map, if it fails, recalculate it:
if (!LoadHeightMapFromNBT(Data.HeightMap, a_NBT, a_NBT.FindChildByName(Level, "HeightMap")))
{
ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, "Missing chunk height data", a_RawChunkData);
return false;
Data.UpdateHeightMap();
}
// Load the entities from NBT:
@ -3997,21 +3996,21 @@ bool cWSSAnvil::cMCAFile::GetChunkData(const cChunkCoords & a_Chunk, ContiguousB
UInt32 ChunkSize = 0;
if (m_File.Read(&ChunkSize, 4) != 4)
{
m_ParentSchema.ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, "Cannot read chunk size", {});
m_ParentSchema.ChunkLoadFailed(a_Chunk, "Cannot read chunk size", {});
return false;
}
ChunkSize = ntohl(ChunkSize);
if (ChunkSize < 1)
{
// Chunk size too small
m_ParentSchema.ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, "Chunk size too small", {});
m_ParentSchema.ChunkLoadFailed(a_Chunk, "Chunk size too small", {});
return false;
}
char CompressionType = 0;
if (m_File.Read(&CompressionType, 1) != 1)
{
m_ParentSchema.ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, "Cannot read chunk compression", {});
m_ParentSchema.ChunkLoadFailed(a_Chunk, "Cannot read chunk compression", {});
return false;
}
ChunkSize--;
@ -4019,14 +4018,14 @@ bool cWSSAnvil::cMCAFile::GetChunkData(const cChunkCoords & a_Chunk, ContiguousB
a_Data = m_File.Read(ChunkSize);
if (a_Data.size() != ChunkSize)
{
m_ParentSchema.ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, "Cannot read entire chunk data", a_Data);
m_ParentSchema.ChunkLoadFailed(a_Chunk, "Cannot read entire chunk data", a_Data);
return false;
}
if (CompressionType != 2)
{
// Chunk is in an unknown compression
m_ParentSchema.ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, fmt::format(FMT_STRING("Unknown chunk compression: {}"), CompressionType), a_Data);
m_ParentSchema.ChunkLoadFailed(a_Chunk, fmt::format(FMT_STRING("Unknown chunk compression: {}"), CompressionType), a_Data);
return false;
}
return true;

View File

@ -46,22 +46,7 @@ class ChunkBlockData;
enum
{
/** Maximum number of chunks in an MCA file - also the count of the header items */
MCA_MAX_CHUNKS = 32 * 32,
/** The MCA header is 8 KiB */
MCA_HEADER_SIZE = MCA_MAX_CHUNKS * 8,
/** There are 5 bytes of header in front of each chunk */
MCA_CHUNK_HEADER_LENGTH = 5,
} ;
/** Implements the Anvil world storage schema. */
class cWSSAnvil:
public cWSSchema
{
@ -74,6 +59,19 @@ public:
protected:
enum
{
/** Maximum number of chunks in an MCA file - also the count of the header items */
MCA_MAX_CHUNKS = 32 * 32,
/** The MCA header is 8 KiB */
MCA_HEADER_SIZE = MCA_MAX_CHUNKS * 8,
/** There are 5 bytes of header in front of each chunk */
MCA_CHUNK_HEADER_LENGTH = 5,
} ;
class cMCAFile
{
public:
@ -83,9 +81,9 @@ protected:
bool GetChunkData (const cChunkCoords & a_Chunk, ContiguousByteBuffer & a_Data);
bool SetChunkData (const cChunkCoords & a_Chunk, ContiguousByteBufferView a_Data);
int GetRegionX (void) const {return m_RegionX; }
int GetRegionZ (void) const {return m_RegionZ; }
const AString & GetFileName(void) const {return m_FileName; }
int GetRegionX () const {return m_RegionX; }
int GetRegionZ () const {return m_RegionZ; }
const AString & GetFileName() const {return m_FileName; }
protected:
@ -118,7 +116,7 @@ protected:
Compression::Compressor m_Compressor;
/** Reports that the specified chunk failed to load and saves the chunk data to an external file. */
void ChunkLoadFailed(int a_ChunkX, int a_ChunkZ, const AString & a_Reason, ContiguousByteBufferView a_ChunkDataToSave);
void ChunkLoadFailed(const cChunkCoords a_ChunkCoords, const AString & a_Reason, ContiguousByteBufferView a_ChunkDataToSave);
/** Gets chunk data from the correct file; locks file CS as needed */
bool GetChunkData(const cChunkCoords & a_Chunk, ContiguousByteBuffer & a_Data);
@ -322,5 +320,5 @@ protected:
// cWSSchema overrides:
virtual bool LoadChunk(const cChunkCoords & a_Chunk) override;
virtual bool SaveChunk(const cChunkCoords & a_Chunk) override;
virtual const AString GetName(void) const override {return "anvil"; }
virtual const AString GetName() const override {return "anvil"; }
} ;