diff options
author | madmaxoft@gmail.com <madmaxoft@gmail.com@0a769ca7-a7f5-676a-18bf-c427514a06d6> | 2012-03-07 23:09:55 +0100 |
---|---|---|
committer | madmaxoft@gmail.com <madmaxoft@gmail.com@0a769ca7-a7f5-676a-18bf-c427514a06d6> | 2012-03-07 23:09:55 +0100 |
commit | 7219e74c7ca47013fb5fe99707f38ae7417257af (patch) | |
tree | e3f459f1823679243cfac7a3ac94970a98eb5adf | |
parent | ChunkSender: Fixed a potential crash: removing a client means that no Send() is called on that client anymore (diff) | |
download | cuberite-7219e74c7ca47013fb5fe99707f38ae7417257af.tar cuberite-7219e74c7ca47013fb5fe99707f38ae7417257af.tar.gz cuberite-7219e74c7ca47013fb5fe99707f38ae7417257af.tar.bz2 cuberite-7219e74c7ca47013fb5fe99707f38ae7417257af.tar.lz cuberite-7219e74c7ca47013fb5fe99707f38ae7417257af.tar.xz cuberite-7219e74c7ca47013fb5fe99707f38ae7417257af.tar.zst cuberite-7219e74c7ca47013fb5fe99707f38ae7417257af.zip |
-rw-r--r-- | source/NBT.cpp | 95 | ||||
-rw-r--r-- | source/NBT.h | 19 | ||||
-rw-r--r-- | source/WSSAnvil.cpp | 124 | ||||
-rw-r--r-- | source/WSSAnvil.h | 13 |
4 files changed, 240 insertions, 11 deletions
diff --git a/source/NBT.cpp b/source/NBT.cpp index c48124cb3..c600a1868 100644 --- a/source/NBT.cpp +++ b/source/NBT.cpp @@ -88,11 +88,11 @@ cNBTTag * cNBTTag::CreateTag(cNBTTag * a_Parent, eTagType a_Type, const AString -cNBTTag * cNBTTag::FindChildByPath(const AString & iPath)
+const cNBTTag * cNBTTag::FindChildByPath(const AString & iPath) const
{
size_t PrevIdx = 0;
size_t idx = iPath.find('\\');
- cNBTTag * res = this;
+ const cNBTTag * res = this;
while ((res != NULL) && (idx != AString::npos))
{
res = res->FindChildByName(AString(iPath, PrevIdx, idx - PrevIdx));
@@ -191,9 +191,9 @@ cNBTTag * cNBTList::GetChildByIdx(size_t iIndex) -cNBTTag * cNBTList::FindChildByName(const AString & a_Name)
+cNBTTag * cNBTList::FindChildByName(const AString & a_Name) const
{
- for (cNBTTags::iterator itr = m_Children.begin(); itr != m_Children.end(); ++itr)
+ for (cNBTTags::const_iterator itr = m_Children.begin(); itr != m_Children.end(); ++itr)
{
if ((*itr)->GetName() == a_Name)
{
@@ -260,9 +260,9 @@ cNBTTag * cNBTCompound::GetChildByIdx(size_t iIndex) -cNBTTag * cNBTCompound::FindChildByName(const AString & a_Name)
+cNBTTag * cNBTCompound::FindChildByName(const AString & a_Name) const
{
- for (cNBTTags::iterator itr = m_Children.begin(); itr != m_Children.end(); ++itr)
+ for (cNBTTags::const_iterator itr = m_Children.begin(); itr != m_Children.end(); ++itr)
{
if ((*itr)->GetName() == a_Name)
{
@@ -580,6 +580,7 @@ int cNBTParser::ReadTag(const char ** a_Data, int * a_Length, cNBTTag::eTagType return ERROR_PRIVATE_NBTPARSER_BADTYPE;
}
+#undef CASE_SIMPLE_TAG
@@ -618,3 +619,85 @@ cNBTTree * cNBTParser::Parse(const char * a_Data, int a_Length) +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Dumping the NBT tree (debug-only)
+
+#ifdef _DEBUG
+
+#define CASE_SIMPLE_TAG(TYPE,FMT) \
+ case cNBTTag::TAG_##TYPE: \
+ { \
+ AString out; \
+ Printf(out, "%sTAG_" TEXT(#TYPE) TEXT("(\"%hs\"): %") TEXT(FMT) TEXT("\n"), Indent.c_str(), a_Tree->GetName().c_str(), ((cNBT##TYPE *)a_Tree)->m_Value); \
+ OutputDebugString(out.c_str()); \
+ break; \
+ }
+
+void DumpTree(const cNBTTree * a_Tree, int a_Level)
+{
+ AString Indent(a_Level, TEXT(' '));
+ HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
+ switch (a_Tree->GetType())
+ {
+ CASE_SIMPLE_TAG(Byte, "d")
+ CASE_SIMPLE_TAG(Short, "d")
+ CASE_SIMPLE_TAG(Int, "d")
+ CASE_SIMPLE_TAG(Long, "I64d")
+ CASE_SIMPLE_TAG(Float, "f")
+ CASE_SIMPLE_TAG(Double, "f")
+
+ case cNBTTag::TAG_ByteArray:
+ {
+ AString out;
+ Printf(out, "%sTAG_ByteArray(\"%hs\"): %d bytes\n", Indent.c_str(), a_Tree->GetName().c_str(), ((cNBTByteArray *)a_Tree)->m_Value.size());
+ OutputDebugString(out.c_str());
+ break;
+ }
+
+ case cNBTTag::TAG_String:
+ {
+ AString out;
+ Printf(out, "%sTAG_String(\"%hs\"): %d bytes: \"%hs\"\n", Indent.c_str(), a_Tree->GetName().c_str(), ((cNBTString *)a_Tree)->m_Value.size(), ((cNBTString *)a_Tree)->m_Value.c_str());
+ OutputDebugString(out.c_str());
+ break;
+ }
+
+ case cNBTTag::TAG_List:
+ {
+ const cNBTTags & Children = ((cNBTList *)a_Tree)->GetChildren();
+ AString out;
+ Printf(out, "%sTAG_List(\"%hs\"): %d items of type %d\n%s{\n", Indent.c_str(), a_Tree->GetName().c_str(), Children.size(), ((cNBTList *)a_Tree)->GetChildrenType(), Indent.c_str());
+ OutputDebugString(out.c_str());
+ for (cNBTTags::const_iterator itr = Children.begin(); itr != Children.end(); ++itr)
+ {
+ DumpTree(*itr, a_Level + 1);
+ } // for itr - Children[]
+ Printf(out, "%s}\n", Indent.c_str());
+ OutputDebugString(out.c_str());
+ break;
+ }
+
+ case cNBTTag::TAG_Compound:
+ {
+ const cNBTTags & Children = ((cNBTCompound *)a_Tree)->GetChildren();
+ AString out;
+ Printf(out, "%sTAG_Compound(\"%hs\"): %d items\n%s{\n", Indent.c_str(), a_Tree->GetName().c_str(), Children.size(), Indent.c_str());
+ OutputDebugString(out.c_str());
+ for (cNBTTags::const_iterator itr = Children.begin(); itr != Children.end(); ++itr)
+ {
+ DumpTree(*itr, a_Level + 1);
+ } // for itr - Children[]
+ Printf(out, "%s}\n", Indent.c_str());
+ OutputDebugString(out.c_str());
+ break;
+ }
+ }
+}
+
+#undef CASE_SIMPLE_TAG
+
+#endif // _DEBUG
+
+
+
+
diff --git a/source/NBT.h b/source/NBT.h index 5bad0492c..a05e574de 100644 --- a/source/NBT.h +++ b/source/NBT.h @@ -62,8 +62,8 @@ public: static cNBTTag * CreateTag(cNBTTag * a_Parent, eTagType a_Type, const AString & a_Name); // Creates a new instance of a tag specified by iType, uses the correct class
- virtual cNBTTag * FindChildByName(const AString & a_Name) {return NULL; }
- cNBTTag * FindChildByPath(const AString & a_Path);
+ virtual cNBTTag * FindChildByName(const AString & a_Name) const {return NULL; }
+ const cNBTTag * FindChildByPath(const AString & a_Path) const;
} ;
typedef cNBTTag cNBTTree;
@@ -118,7 +118,7 @@ public: cNBTTag * GetChildByIdx (size_t a_Index);
const cNBTTags & GetChildren (void) const {return m_Children; }
size_t GetChildrenCount(void) const {return m_Children.size(); }
- virtual cNBTTag * FindChildByName (const AString & a_Name) override;
+ virtual cNBTTag * FindChildByName (const AString & a_Name) const override;
int SetChildrenType(eTagType a_Type); // Only valid when list empty
eTagType GetChildrenType(void) const {return m_ChildrenType; }
@@ -142,7 +142,7 @@ public: cNBTTag * GetChildByIdx (size_t a_Index);
const cNBTTags & GetChildren (void) const {return m_Children; }
size_t GetChildrenCount(void) const {return m_Children.size(); }
- virtual cNBTTag * FindChildByName (const AString & a_Name) override;
+ virtual cNBTTag * FindChildByName (const AString & a_Name) const override;
} ;
@@ -199,3 +199,14 @@ public: +
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Dumping the tree (DEBUG-only)
+
+#ifdef _DEBUG
+void DumpTree(const cNBTTree * a_Tree, int a_Level = 0);
+#endif // _DEBUG
+
+
+
+
diff --git a/source/WSSAnvil.cpp b/source/WSSAnvil.cpp index 8b0bbbae8..ce9afc652 100644 --- a/source/WSSAnvil.cpp +++ b/source/WSSAnvil.cpp @@ -9,6 +9,8 @@ #include "zlib.h"
#include "NBT.h"
#include "BlockID.h"
+#include "cChestEntity.h"
+#include "cItem.h"
@@ -219,7 +221,9 @@ bool cWSSAnvil::LoadChunkFromNBT(const cChunkCoords & a_Chunk, cNBTTag & a_NBT) cEntityList Entities;
cBlockEntityList BlockEntities;
- // TODO: Load the entities from NBT
+ // Load the entities from NBT:
+ LoadEntitiesFromNBT (Entities, (cNBTList *)(a_NBT.FindChildByPath("Level\\Entities")));
+ LoadBlockEntitiesFromNBT(BlockEntities, (cNBTList *)(a_NBT.FindChildByPath("Level\\TileEntities")));
// Reorder the chunk data - walk the MCA-formatted data sequentially and copy it into the right place in the ChunkData:
char ChunkData[cChunk::c_BlockDataSize];
@@ -260,6 +264,124 @@ bool cWSSAnvil::LoadChunkFromNBT(const cChunkCoords & a_Chunk, cNBTTag & a_NBT) +void cWSSAnvil::LoadEntitiesFromNBT(cEntityList & a_Entitites, const cNBTList * a_NBT)
+{
+ // TODO: Load the entities
+}
+
+
+
+
+
+void cWSSAnvil::LoadBlockEntitiesFromNBT(cBlockEntityList & a_BlockEntities, const cNBTList * a_NBT)
+{
+ if ((a_NBT == NULL) || (a_NBT->GetType() != cNBTTag::TAG_List))
+ {
+ return;
+ }
+ const cNBTTags & Tags = a_NBT->GetChildren();
+
+ for (cNBTTags::const_iterator itr = Tags.begin(); itr != Tags.end(); ++itr)
+ {
+ if ((*itr)->GetType() != cNBTTag::TAG_Compound)
+ {
+ continue;
+ }
+ cNBTString * sID = (cNBTString *)((*itr)->FindChildByName("id"));
+ if (sID == NULL)
+ {
+ continue;
+ }
+ if (sID->m_Value == "Chest")
+ {
+ LoadChestFromNBT(a_BlockEntities, (cNBTCompound *)(*itr));
+ }
+ // TODO: Other block entities
+ } // for itr - Tags[]
+}
+
+
+
+
+
+void cWSSAnvil::LoadChestFromNBT(cBlockEntityList & a_BlockEntities, const cNBTCompound * a_NBT)
+{
+ ASSERT(a_NBT != NULL);
+ ASSERT(a_NBT->GetType() == cNBTTag::TAG_Compound);
+ int x, y, z;
+ if (!GetBlockEntityNBTPos(a_NBT, x, y, z))
+ {
+ return;
+ }
+ cNBTList * Items = (cNBTList *)(a_NBT->FindChildByName("Items"));
+ if ((Items == NULL) || (Items->GetType() != cNBTTag::TAG_List))
+ {
+ return; // Make it an empty chest
+ }
+ std::auto_ptr<cChestEntity> Chest(new cChestEntity(x, y, z, m_World));
+ const cNBTTags & ItemDefs = Items->GetChildren();
+ for (cNBTTags::const_iterator itr = ItemDefs.begin(); itr != ItemDefs.end(); ++itr)
+ {
+ cNBTByte * Slot = (cNBTByte *)((*itr)->FindChildByName("Slot"));
+ if ((Slot == NULL) || (Slot->GetType() != cNBTTag::TAG_Byte))
+ {
+ continue;
+ }
+ cItem Item;
+ cNBTShort * ID = (cNBTShort *)((*itr)->FindChildByName("id"));
+ if ((ID == NULL) || (ID->GetType() != cNBTTag::TAG_Short))
+ {
+ continue;
+ }
+ Item.m_ItemID = (ENUM_ITEM_ID)(ID->m_Value);
+ cNBTShort * Damage = (cNBTShort *)((*itr)->FindChildByName("Damage"));
+ if ((Damage == NULL) || (Damage->GetType() != cNBTTag::TAG_Short))
+ {
+ continue;
+ }
+ Item.m_ItemHealth = Damage->m_Value;
+ cNBTByte * Count = (cNBTByte *)((*itr)->FindChildByName("Count"));
+ if ((Count == NULL) || (Count->GetType() != cNBTTag::TAG_Byte))
+ {
+ continue;
+ }
+ Item.m_ItemCount = Count->m_Value;
+ Chest->SetSlot(Slot->m_Value, Item);
+ } // for itr - ItemDefs[]
+ a_BlockEntities.push_back(Chest.release());
+}
+
+
+
+
+
+bool cWSSAnvil::GetBlockEntityNBTPos(const cNBTCompound * a_NBT, int & a_X, int & a_Y, int & a_Z)
+{
+ cNBTInt * x = (cNBTInt *)(a_NBT->FindChildByName("x"));
+ if ((x == NULL) || (x->GetType() != cNBTTag::TAG_Int))
+ {
+ return false;
+ }
+ cNBTInt * y = (cNBTInt *)(a_NBT->FindChildByName("y"));
+ if ((y == NULL) || (y->GetType() != cNBTTag::TAG_Int))
+ {
+ return false;
+ }
+ cNBTInt * z = (cNBTInt *)(a_NBT->FindChildByName("z"));
+ if ((z == NULL) || (z->GetType() != cNBTTag::TAG_Int))
+ {
+ return false;
+ }
+ a_X = x->m_Value;
+ a_Y = y->m_Value;
+ a_Z = z->m_Value;
+ return true;
+}
+
+
+
+
+
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cWSSAnvil::cMCAFile:
diff --git a/source/WSSAnvil.h b/source/WSSAnvil.h index f02a30119..1052d0e5a 100644 --- a/source/WSSAnvil.h +++ b/source/WSSAnvil.h @@ -26,6 +26,8 @@ enum // fwd: "NBT.h"
class cNBTTag;
+class cNBTList;
+class cNBTCompound;
@@ -81,6 +83,17 @@ protected: /// Loads the chunk from NBT data (no locking needed)
bool LoadChunkFromNBT(const cChunkCoords & a_Chunk, cNBTTag & a_NBT);
+ /// Loads the chunk's entities from NBT data (a_NBT is the Level\\Entities list tag; may be NULL)
+ void LoadEntitiesFromNBT(cEntityList & a_Entitites, const cNBTList * a_NBT);
+
+ /// Loads the chunk's BlockEntities from NBT data (a_NBT is the Level\\TileEntities list tag; may be NULL)
+ void LoadBlockEntitiesFromNBT(cBlockEntityList & a_BlockEntitites, const cNBTList * a_NBT);
+
+ void LoadChestFromNBT(cBlockEntityList & a_BlockEntities, const cNBTCompound * a_NBT);
+
+ /// Helper function for extracting the X, Y, and Z int subtags of a NBT compound; returns true if successful
+ bool GetBlockEntityNBTPos(const cNBTCompound * a_NBT, int & a_X, int & a_Y, int & a_Z);
+
/// Gets the correct MCA file either from cache or from disk, manages the m_MCAFiles cache; assumes m_CS is locked
cMCAFile * LoadMCAFile(const cChunkCoords & a_Chunk);
|