From 265c810079acd2b82062827824f3ff65d495aa94 Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Sun, 28 Oct 2012 17:30:10 +0000 Subject: 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 --- source/WorldStorage/FastNBT.cpp | 2 +- source/WorldStorage/WSSAnvil.cpp | 83 ++++++++++++++++++++++++++++++++++------ source/WorldStorage/WSSAnvil.h | 5 ++- 3 files changed, 76 insertions(+), 14 deletions(-) (limited to 'source') diff --git a/source/WorldStorage/FastNBT.cpp b/source/WorldStorage/FastNBT.cpp index 13a6819e1..397df036e 100644 --- a/source/WorldStorage/FastNBT.cpp +++ b/source/WorldStorage/FastNBT.cpp @@ -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++) diff --git a/source/WorldStorage/WSSAnvil.cpp b/source/WorldStorage/WSSAnvil.cpp index ded7e4327..e12c3f0d9 100644 --- a/source/WorldStorage/WSSAnvil.cpp +++ b/source/WorldStorage/WSSAnvil.cpp @@ -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 diff --git a/source/WorldStorage/WSSAnvil.h b/source/WorldStorage/WSSAnvil.h index b0641b586..37c1f0b4e 100644 --- a/source/WorldStorage/WSSAnvil.h +++ b/source/WorldStorage/WSSAnvil.h @@ -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) -- cgit v1.2.3