1
0
Fork 0

Fixed NBT IntArray serialization; Biomes are now saved to / loaded from Anvil

git-svn-id: http://mc-server.googlecode.com/svn/trunk@1015 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
madmaxoft@gmail.com 2012-10-28 17:30:10 +00:00
parent 96f7246df1
commit 265c810079
3 changed files with 76 additions and 14 deletions

View File

@ -502,7 +502,7 @@ void cFastNBTWriter::AddIntArray(const AString & a_Name, const int * a_Value, si
{
TagCommon(a_Name, TAG_IntArray);
Int32 len = htonl(a_NumElements);
m_Result.append((const char *)&len, 2);
m_Result.append((const char *)&len, 4);
int * Elements = (int *)(m_Result.data() + m_Result.size());
m_Result.append(a_NumElements * 4, (char)0);
for (size_t i = 0; i < a_NumElements; i++)

View File

@ -43,7 +43,13 @@ class cNBTChunkSerializer :
public cChunkDataSeparateCollector
{
public:
cChunkDef::BiomeMap m_Biomes;
unsigned char m_VanillaBiomes[cChunkDef::Width * cChunkDef::Width];
bool m_BiomesAreValid;
cNBTChunkSerializer(cFastNBTWriter & a_Writer) :
m_BiomesAreValid(false),
m_Writer(a_Writer),
m_IsTagOpen(false),
m_HasHadEntity(false),
@ -64,7 +70,7 @@ public:
bool IsLightValid(void) const {return m_IsLightValid; }
protected:
/* From cChunkDataSeparateCollector we inherit:
@ -74,16 +80,14 @@ protected:
- m_BlockSkyLight[]
*/
// TODO: Biomes
cFastNBTWriter & m_Writer;
bool m_IsTagOpen; // True if a tag has been opened in the callbacks and not yet closed.
bool m_HasHadEntity; // True if any Entity has already been received and processed
bool m_HasHadBlockEntity; // True if any BlockEntity has already been received and processed
bool m_IsLightValid; // True if the chunk lighting is valid
void AddBasicTileEntity(cBlockEntity * a_Entity, const char * a_EntityTypeID)
{
m_Writer.AddInt ("x", a_Entity->GetPosX());
@ -172,6 +176,27 @@ protected:
}
virtual void BiomeData(const cChunkDef::BiomeMap * a_BiomeMap) override
{
memcpy(m_Biomes, a_BiomeMap, sizeof(m_Biomes));
for (int i = 0; i < ARRAYCOUNT(m_Biomes); i++)
{
if ((*a_BiomeMap)[i] < 255)
{
// Normal MC biome, copy as-is:
m_VanillaBiomes[i] = (unsigned char)((*a_BiomeMap)[i]);
}
else
{
// TODO: MCS-specific biome, need to map to some basic MC biome:
ASSERT(!"Unimplemented MCS-specific biome");
return;
}
} // for i - m_BiomeMap[]
m_BiomesAreValid = true;
}
virtual void Entity(cEntity * a_Entity) override
{
// TODO: Add entity into NBT:
@ -475,9 +500,14 @@ bool cWSSAnvil::LoadChunkFromNBT(const cChunkCoords & a_Chunk, const cParsedNBT
CopyNBTData(a_NBT, Child, "BlockLight", (char *)&(BlockLight[y * 2048]), 2048);
} // for itr - LevelSections[]
// Load the biomes from NBT, if present and valid:
// Load the biomes from NBT, if present and valid. First try MCS-style, then Vanilla-style:
cChunkDef::BiomeMap BiomeMap;
cChunkDef::BiomeMap * Biomes = LoadBiomeMapFromNBT(&BiomeMap, a_NBT, a_NBT.FindChildByName(Level, "Biomes"));
cChunkDef::BiomeMap * Biomes = LoadBiomeMapFromNBT(&BiomeMap, a_NBT, a_NBT.FindChildByName(Level, "MCSBiomes"));
if (Biomes == NULL)
{
// MCS-style biomes not available, load vanilla-style:
Biomes = LoadVanillaBiomeMapFromNBT(&BiomeMap, a_NBT, a_NBT.FindChildByName(Level, "Biomes"));
}
// Load the entities from NBT:
cEntityList Entities;
@ -562,9 +592,9 @@ bool cWSSAnvil::SaveChunkToNBT(const cChunkCoords & a_Chunk, cFastNBTWriter & a_
}
Serializer.Finish(); // Close NBT tags
// TODO: Save biomes, both MCS (IntArray) and MC-vanilla (ByteArray):
// Level->Add(new cNBTByteArray(Level, "Biomes", AString(Serializer.m_Biomes, sizeof(Serializer.m_Biomes));
// Level->Add(new cNBTByteArray(Level, "MCSBiomes", AString(Serializer.m_Biomes, sizeof(Serializer.m_Biomes));
// Save biomes, both MCS (IntArray) and MC-vanilla (ByteArray):
a_Writer.AddByteArray("Biomes", (const char *)(Serializer.m_VanillaBiomes), ARRAYCOUNT(Serializer.m_VanillaBiomes));
a_Writer.AddIntArray ("MCSBiomes", (const int *)(Serializer.m_Biomes), ARRAYCOUNT(Serializer.m_Biomes));
// Save blockdata:
a_Writer.BeginList("Sections", TAG_Compound);
@ -601,7 +631,7 @@ bool cWSSAnvil::SaveChunkToNBT(const cChunkCoords & a_Chunk, cFastNBTWriter & a_
cChunkDef::BiomeMap * cWSSAnvil::LoadBiomeMapFromNBT(cChunkDef::BiomeMap * a_BiomeMap, const cParsedNBT & a_NBT, int a_TagIdx)
cChunkDef::BiomeMap * cWSSAnvil::LoadVanillaBiomeMapFromNBT(cChunkDef::BiomeMap * a_BiomeMap, const cParsedNBT & a_NBT, int a_TagIdx)
{
if ((a_TagIdx < 0) || (a_NBT.GetType(a_TagIdx) != TAG_ByteArray))
{
@ -612,9 +642,38 @@ cChunkDef::BiomeMap * cWSSAnvil::LoadBiomeMapFromNBT(cChunkDef::BiomeMap * a_Bio
// The biomes stored don't match in size
return NULL;
}
memcpy(a_BiomeMap, a_NBT.GetData(a_TagIdx), sizeof(*a_BiomeMap));
const unsigned char * VanillaBiomeData = (const unsigned char *)(a_NBT.GetData(a_TagIdx));
for (int i = 0; i < ARRAYCOUNT(*a_BiomeMap); i++)
{
if ((VanillaBiomeData)[i] == 0xff)
{
// Unassigned biomes
return NULL;
}
(*a_BiomeMap)[i] = (EMCSBiome)(VanillaBiomeData[i]);
}
return a_BiomeMap;
}
cChunkDef::BiomeMap * cWSSAnvil::LoadBiomeMapFromNBT(cChunkDef::BiomeMap * a_BiomeMap, const cParsedNBT & a_NBT, int a_TagIdx)
{
if ((a_TagIdx < 0) || (a_NBT.GetType(a_TagIdx) != TAG_IntArray))
{
return NULL;
}
if (a_NBT.GetDataLength(a_TagIdx) != sizeof(*a_BiomeMap))
{
// The biomes stored don't match in size
return NULL;
}
const int * BiomeData = (const int *)(a_NBT.GetData(a_TagIdx));
for (int i = 0; i < ARRAYCOUNT(*a_BiomeMap); i++)
{
(*a_BiomeMap)[i] = (EMCSBiome)(ntohl(BiomeData[i]));
if ((*a_BiomeMap)[i] == 0xff)
{
// Unassigned biomes

View File

@ -99,7 +99,10 @@ protected:
/// Saves the chunk into NBT data using a_Writer; returns true on success
bool SaveChunkToNBT(const cChunkCoords & a_Chunk, cFastNBTWriter & a_Writer);
/// Loads the chunk's biome map; returns a_BiomeMap if biomes present and valid, NULL otherwise
/// Loads the chunk's biome map from vanilla-format; returns a_BiomeMap if biomes present and valid, NULL otherwise
cChunkDef::BiomeMap * LoadVanillaBiomeMapFromNBT(cChunkDef::BiomeMap * a_BiomeMap, const cParsedNBT & a_NBT, int a_TagIdx);
/// Loads the chunk's biome map from MCS format; returns a_BiomeMap if biomes present and valid, NULL otherwise
cChunkDef::BiomeMap * LoadBiomeMapFromNBT(cChunkDef::BiomeMap * a_BiomeMap, const cParsedNBT & a_NBT, int a_TagIdx);
/// Loads the chunk's entities from NBT data (a_Tag is the Level\\Entities list tag; may be -1)