From e14ddff1c00919f1416bfa6da9568e2dff419559 Mon Sep 17 00:00:00 2001 From: Tycho Date: Sun, 19 Jan 2014 07:38:59 -0800 Subject: [PATCH 1/2] Spilt Writing of Enchantments to seperate class Created a new class cEnchantmentSerializer to serilize Enchantments to NBT. This breaks a dependecy chain between cChunkGenerator and cWorld. cEnchantmentSerializer is seperate from NBTWriter as it needs to access private members of cEnchantments so having it seperate reduces the spread of the frein modifier --- src/Enchantments.cpp | 79 -------------------- src/Enchantments.h | 7 +- src/Protocol/Protocol132.cpp | 5 +- src/Protocol/Protocol17x.cpp | 5 +- src/WorldStorage/EnchantmentSerializer.cpp | 87 ++++++++++++++++++++++ src/WorldStorage/EnchantmentSerializer.h | 17 +++++ src/WorldStorage/NBTChunkSerializer.cpp | 3 +- src/WorldStorage/WSSAnvil.cpp | 3 +- 8 files changed, 116 insertions(+), 90 deletions(-) create mode 100644 src/WorldStorage/EnchantmentSerializer.cpp create mode 100644 src/WorldStorage/EnchantmentSerializer.h diff --git a/src/Enchantments.cpp b/src/Enchantments.cpp index 95ca201f0..1d8188e96 100644 --- a/src/Enchantments.cpp +++ b/src/Enchantments.cpp @@ -213,87 +213,8 @@ bool cEnchantments::operator !=(const cEnchantments & a_Other) const -void cEnchantments::WriteToNBTCompound(cFastNBTWriter & a_Writer, const AString & a_ListTagName) const -{ - // Write the enchantments into the specified NBT writer - // begin with the LIST tag of the specified name ("ench" or "StoredEnchantments") - - a_Writer.BeginList(a_ListTagName, TAG_Compound); - for (cMap::const_iterator itr = m_Enchantments.begin(), end = m_Enchantments.end(); itr != end; ++itr) - { - a_Writer.BeginCompound(""); - a_Writer.AddShort("id", itr->first); - a_Writer.AddShort("lvl", itr->second); - a_Writer.EndCompound(); - } // for itr - m_Enchantments[] - a_Writer.EndList(); -} -void cEnchantments::ParseFromNBT(const cParsedNBT & a_NBT, int a_EnchListTagIdx) -{ - // Read the enchantments from the specified NBT list tag (ench or StoredEnchantments) - - // Verify that the tag is a list: - if (a_NBT.GetType(a_EnchListTagIdx) != TAG_List) - { - LOGWARNING("%s: Invalid EnchListTag type: exp %d, got %d. Enchantments not parsed", - __FUNCTION__, TAG_List, a_NBT.GetType(a_EnchListTagIdx) - ); - ASSERT(!"Bad EnchListTag type"); - return; - } - - // Verify that the list is of Compounds: - if (a_NBT.GetChildrenType(a_EnchListTagIdx) != TAG_Compound) - { - LOGWARNING("%s: Invalid NBT list children type: exp %d, got %d. Enchantments not parsed", - __FUNCTION__, TAG_Compound, a_NBT.GetChildrenType(a_EnchListTagIdx) - ); - ASSERT(!"Bad EnchListTag children type"); - return; - } - - Clear(); - - // Iterate over all the compound children, parse an enchantment from each: - for (int tag = a_NBT.GetFirstChild(a_EnchListTagIdx); tag >= 0; tag = a_NBT.GetNextSibling(tag)) - { - // tag is the compound inside the "ench" list tag - ASSERT(a_NBT.GetType(tag) == TAG_Compound); - - // Search for the id and lvl tags' values: - int id = -1, lvl = -1; - for (int ch = a_NBT.GetFirstChild(tag); ch >= 0; ch = a_NBT.GetNextSibling(ch)) - { - if (a_NBT.GetType(ch) != TAG_Short) - { - continue; - } - if (a_NBT.GetName(ch) == "id") - { - id = a_NBT.GetShort(ch); - } - else if (a_NBT.GetName(ch) == "lvl") - { - lvl = a_NBT.GetShort(ch); - } - } // for ch - children of the compound tag - - if ((id == -1) || (lvl <= 0)) - { - // Failed to parse either the id or the lvl, skip this compound - continue; - } - - // Store the enchantment: - m_Enchantments[id] = lvl; - } // for tag - children of the ench list tag -} - - - - diff --git a/src/Enchantments.h b/src/Enchantments.h index 7581b87b5..0f23f8657 100644 --- a/src/Enchantments.h +++ b/src/Enchantments.h @@ -31,6 +31,7 @@ Serialization will never put zero-level enchantments into the stringspec and wil */ class cEnchantments { +friend class cEnchantmentSerializer; public: /// Individual enchantment IDs, corresponding to their NBT IDs ( http://www.minecraftwiki.net/wiki/Data_Values#Enchantment_IDs ) enum @@ -96,11 +97,7 @@ public: /// Returns true if a_Other doesn't contain exactly the same enchantments and levels bool operator !=(const cEnchantments & a_Other) const; - /// Writes the enchantments into the specified NBT writer; begins with the LIST tag of the specified name ("ench" or "StoredEnchantments") - void WriteToNBTCompound(cFastNBTWriter & a_Writer, const AString & a_ListTagName) const; - - /// Reads the enchantments from the specified NBT list tag (ench or StoredEnchantments) - void ParseFromNBT(const cParsedNBT & a_NBT, int a_EnchListTagIdx); + protected: /// Maps enchantment ID -> enchantment level diff --git a/src/Protocol/Protocol132.cpp b/src/Protocol/Protocol132.cpp index 29fbb4bba..501a8474e 100644 --- a/src/Protocol/Protocol132.cpp +++ b/src/Protocol/Protocol132.cpp @@ -16,6 +16,7 @@ #include "../UI/Window.h" #include "../Entities/Pickup.h" #include "../WorldStorage/FastNBT.h" +#include "../WorldStorage/EnchantmentSerializer.h" #include "../StringCompression.h" #ifdef _MSC_VER @@ -763,7 +764,7 @@ void cProtocol132::WriteItem(const cItem & a_Item) // Send the enchantments: cFastNBTWriter Writer; const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench"; - a_Item.m_Enchantments.WriteToNBTCompound(Writer, TagName); + cEnchantmentSerializer::WriteToNBTCompound(a_Item.m_Enchantments, Writer, TagName); Writer.Finish(); AString Compressed; CompressStringGZIP(Writer.GetResult().data(), Writer.GetResult().size(), Compressed); @@ -849,7 +850,7 @@ int cProtocol132::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata) ) ) { - a_Item.m_Enchantments.ParseFromNBT(NBT, tag); + cEnchantmentSerializer::ParseFromNBT(a_Item.m_Enchantments, NBT, tag); } } diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 5b3a79555..44db659a5 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -16,6 +16,7 @@ Implements the 1.7.x protocol classes: #include "../Server.h" #include "../World.h" #include "../WorldStorage/FastNBT.h" +#include "../WorldStorage/EnchantmentSerializer.h" #include "../StringCompression.h" #include "../Entities/ExpOrb.h" #include "../Entities/Minecart.h" @@ -1696,7 +1697,7 @@ void cProtocol172::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata) ) ) { - a_Item.m_Enchantments.ParseFromNBT(NBT, tag); + cEnchantmentSerializer::ParseFromNBT(a_Item.m_Enchantments, NBT, tag); } else if ((NBT.GetType(tag) == TAG_Compound) && (NBT.GetName(tag) == "display")) // Custom name and lore tag { @@ -1781,7 +1782,7 @@ void cProtocol172::cPacketizer::WriteItem(const cItem & a_Item) if (!a_Item.m_Enchantments.IsEmpty()) { const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench"; - a_Item.m_Enchantments.WriteToNBTCompound(Writer, TagName); + cEnchantmentSerializer::WriteToNBTCompound(a_Item.m_Enchantments,Writer, TagName); } if (!a_Item.IsBothNameAndLoreEmpty()) { diff --git a/src/WorldStorage/EnchantmentSerializer.cpp b/src/WorldStorage/EnchantmentSerializer.cpp new file mode 100644 index 000000000..a481f1682 --- /dev/null +++ b/src/WorldStorage/EnchantmentSerializer.cpp @@ -0,0 +1,87 @@ + +#include "Globals.h" + +#include "EnchantmentSerializer.h" +#include "FastNBT.h" + +void cEnchantmentSerializer::WriteToNBTCompound(cEnchantments const& a_Enchantments, cFastNBTWriter & a_Writer, const AString & a_ListTagName) +{ + // Write the enchantments into the specified NBT writer + // begin with the LIST tag of the specified name ("ench" or "StoredEnchantments") + + a_Writer.BeginList(a_ListTagName, TAG_Compound); + for (cEnchantments::cMap::const_iterator itr = a_Enchantments.m_Enchantments.begin(), end = a_Enchantments.m_Enchantments.end(); itr != end; ++itr) + { + a_Writer.BeginCompound(""); + a_Writer.AddShort("id", itr->first); + a_Writer.AddShort("lvl", itr->second); + a_Writer.EndCompound(); + } // for itr - m_Enchantments[] + a_Writer.EndList(); +} + + + + + +void cEnchantmentSerializer::ParseFromNBT(cEnchantments& a_Enchantments, const cParsedNBT & a_NBT, int a_EnchListTagIdx) +{ + // Read the enchantments from the specified NBT list tag (ench or StoredEnchantments) + + // Verify that the tag is a list: + if (a_NBT.GetType(a_EnchListTagIdx) != TAG_List) + { + LOGWARNING("%s: Invalid EnchListTag type: exp %d, got %d. Enchantments not parsed", + __FUNCTION__, TAG_List, a_NBT.GetType(a_EnchListTagIdx) + ); + ASSERT(!"Bad EnchListTag type"); + return; + } + + // Verify that the list is of Compounds: + if (a_NBT.GetChildrenType(a_EnchListTagIdx) != TAG_Compound) + { + LOGWARNING("%s: Invalid NBT list children type: exp %d, got %d. Enchantments not parsed", + __FUNCTION__, TAG_Compound, a_NBT.GetChildrenType(a_EnchListTagIdx) + ); + ASSERT(!"Bad EnchListTag children type"); + return; + } + + a_Enchantments.Clear(); + + // Iterate over all the compound children, parse an enchantment from each: + for (int tag = a_NBT.GetFirstChild(a_EnchListTagIdx); tag >= 0; tag = a_NBT.GetNextSibling(tag)) + { + // tag is the compound inside the "ench" list tag + ASSERT(a_NBT.GetType(tag) == TAG_Compound); + + // Search for the id and lvl tags' values: + int id = -1, lvl = -1; + for (int ch = a_NBT.GetFirstChild(tag); ch >= 0; ch = a_NBT.GetNextSibling(ch)) + { + if (a_NBT.GetType(ch) != TAG_Short) + { + continue; + } + if (a_NBT.GetName(ch) == "id") + { + id = a_NBT.GetShort(ch); + } + else if (a_NBT.GetName(ch) == "lvl") + { + lvl = a_NBT.GetShort(ch); + } + } // for ch - children of the compound tag + + if ((id == -1) || (lvl <= 0)) + { + // Failed to parse either the id or the lvl, skip this compound + continue; + } + + // Store the enchantment: + a_Enchantments.m_Enchantments[id] = lvl; + } // for tag - children of the ench list tag +} + diff --git a/src/WorldStorage/EnchantmentSerializer.h b/src/WorldStorage/EnchantmentSerializer.h new file mode 100644 index 000000000..d616b0f62 --- /dev/null +++ b/src/WorldStorage/EnchantmentSerializer.h @@ -0,0 +1,17 @@ + +#pragma once + +#include "Enchantments.h" + +class cEnchantmentSerializer +{ + +public: + + /// Writes the enchantments into the specified NBT writer; begins with the LIST tag of the specified name ("ench" or "StoredEnchantments") + static void WriteToNBTCompound(cEnchantments const& a_Enchantments, cFastNBTWriter & a_Writer, const AString & a_ListTagName); + + /// Reads the enchantments from the specified NBT list tag (ench or StoredEnchantments) + static void ParseFromNBT(cEnchantments& a_Enchantments, const cParsedNBT & a_NBT, int a_EnchListTagIdx); + +}; diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp index e1205f2be..51e1a8d1b 100644 --- a/src/WorldStorage/NBTChunkSerializer.cpp +++ b/src/WorldStorage/NBTChunkSerializer.cpp @@ -4,6 +4,7 @@ #include "Globals.h" #include "NBTChunkSerializer.h" +#include "EnchantmentSerializer.h" #include "../BlockID.h" #include "../ItemGrid.h" #include "../StringCompression.h" @@ -91,7 +92,7 @@ void cNBTChunkSerializer::AddItem(const cItem & a_Item, int a_Slot, const AStrin { const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench"; m_Writer.BeginCompound("tag"); - a_Item.m_Enchantments.WriteToNBTCompound(m_Writer, TagName); + cEnchantmentSerializer::WriteToNBTCompound(a_Item.m_Enchantments, m_Writer, TagName); m_Writer.EndCompound(); } diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index 16513cd1b..702b809fb 100644 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -7,6 +7,7 @@ #include "WSSAnvil.h" #include "NBTChunkSerializer.h" #include "FastNBT.h" +#include "EnchantmentSerializer.h" #include "zlib/zlib.h" #include "../World.h" #include "../BlockID.h" @@ -639,7 +640,7 @@ bool cWSSAnvil::LoadItemFromNBT(cItem & a_Item, const cParsedNBT & a_NBT, int a_ int EnchTag = a_NBT.FindChildByName(TagTag, EnchName); if (EnchTag > 0) { - a_Item.m_Enchantments.ParseFromNBT(a_NBT, EnchTag); + cEnchantmentSerializer::ParseFromNBT(a_Item.m_Enchantments, a_NBT, EnchTag); } return true; From f13a14d2cf4a7858c22fe003acff6753d0d50ba1 Mon Sep 17 00:00:00 2001 From: Tycho Date: Sun, 19 Jan 2014 08:52:45 -0800 Subject: [PATCH 2/2] Switched EnchantmentSerilizer to namespace --- src/Enchantments.h | 11 ++++++++--- src/Protocol/Protocol132.cpp | 4 ++-- src/Protocol/Protocol17x.cpp | 4 ++-- src/WorldStorage/EnchantmentSerializer.cpp | 5 +++-- src/WorldStorage/EnchantmentSerializer.h | 12 ++++++------ src/WorldStorage/NBTChunkSerializer.cpp | 2 +- src/WorldStorage/WSSAnvil.cpp | 2 +- 7 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/Enchantments.h b/src/Enchantments.h index 0f23f8657..e984df92e 100644 --- a/src/Enchantments.h +++ b/src/Enchantments.h @@ -8,6 +8,7 @@ #pragma once +#include "WorldStorage/EnchantmentSerializer.h" @@ -20,7 +21,6 @@ class cParsedNBT; -// tolua_begin /** Class that stores item enchantments or stored-enchantments The enchantments may be serialized to a stringspec and read back from such stringspec. @@ -29,11 +29,12 @@ mapping each enchantment's id onto its level. ID may be either a number or the e Level value of 0 means no such enchantment, and it will not be stored in the m_Enchantments. Serialization will never put zero-level enchantments into the stringspec and will always use numeric IDs. */ +// tolua_begin class cEnchantments { -friend class cEnchantmentSerializer; public: /// Individual enchantment IDs, corresponding to their NBT IDs ( http://www.minecraftwiki.net/wiki/Data_Values#Enchantment_IDs ) + enum { enchProtection = 0, @@ -97,7 +98,11 @@ public: /// Returns true if a_Other doesn't contain exactly the same enchantments and levels bool operator !=(const cEnchantments & a_Other) const; - + /// Writes the enchantments into the specified NBT writer; begins with the LIST tag of the specified name ("ench" or "StoredEnchantments") + friend void EnchantmentSerializer::WriteToNBTCompound(cEnchantments const& a_Enchantments, cFastNBTWriter & a_Writer, const AString & a_ListTagName); + + /// Reads the enchantments from the specified NBT list tag (ench or StoredEnchantments) + friend void EnchantmentSerializer::ParseFromNBT(cEnchantments& a_Enchantments, const cParsedNBT & a_NBT, int a_EnchListTagIdx); protected: /// Maps enchantment ID -> enchantment level diff --git a/src/Protocol/Protocol132.cpp b/src/Protocol/Protocol132.cpp index 501a8474e..b4ca37d37 100644 --- a/src/Protocol/Protocol132.cpp +++ b/src/Protocol/Protocol132.cpp @@ -764,7 +764,7 @@ void cProtocol132::WriteItem(const cItem & a_Item) // Send the enchantments: cFastNBTWriter Writer; const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench"; - cEnchantmentSerializer::WriteToNBTCompound(a_Item.m_Enchantments, Writer, TagName); + EnchantmentSerializer::WriteToNBTCompound(a_Item.m_Enchantments, Writer, TagName); Writer.Finish(); AString Compressed; CompressStringGZIP(Writer.GetResult().data(), Writer.GetResult().size(), Compressed); @@ -850,7 +850,7 @@ int cProtocol132::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata) ) ) { - cEnchantmentSerializer::ParseFromNBT(a_Item.m_Enchantments, NBT, tag); + EnchantmentSerializer::ParseFromNBT(a_Item.m_Enchantments, NBT, tag); } } diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 44db659a5..c64441a1e 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -1697,7 +1697,7 @@ void cProtocol172::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata) ) ) { - cEnchantmentSerializer::ParseFromNBT(a_Item.m_Enchantments, NBT, tag); + EnchantmentSerializer::ParseFromNBT(a_Item.m_Enchantments, NBT, tag); } else if ((NBT.GetType(tag) == TAG_Compound) && (NBT.GetName(tag) == "display")) // Custom name and lore tag { @@ -1782,7 +1782,7 @@ void cProtocol172::cPacketizer::WriteItem(const cItem & a_Item) if (!a_Item.m_Enchantments.IsEmpty()) { const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench"; - cEnchantmentSerializer::WriteToNBTCompound(a_Item.m_Enchantments,Writer, TagName); + EnchantmentSerializer::WriteToNBTCompound(a_Item.m_Enchantments,Writer, TagName); } if (!a_Item.IsBothNameAndLoreEmpty()) { diff --git a/src/WorldStorage/EnchantmentSerializer.cpp b/src/WorldStorage/EnchantmentSerializer.cpp index a481f1682..56072207f 100644 --- a/src/WorldStorage/EnchantmentSerializer.cpp +++ b/src/WorldStorage/EnchantmentSerializer.cpp @@ -2,9 +2,10 @@ #include "Globals.h" #include "EnchantmentSerializer.h" +#include "Enchantments.h" #include "FastNBT.h" -void cEnchantmentSerializer::WriteToNBTCompound(cEnchantments const& a_Enchantments, cFastNBTWriter & a_Writer, const AString & a_ListTagName) +void EnchantmentSerializer::WriteToNBTCompound(cEnchantments const& a_Enchantments, cFastNBTWriter & a_Writer, const AString & a_ListTagName) { // Write the enchantments into the specified NBT writer // begin with the LIST tag of the specified name ("ench" or "StoredEnchantments") @@ -24,7 +25,7 @@ void cEnchantmentSerializer::WriteToNBTCompound(cEnchantments const& a_Enchantme -void cEnchantmentSerializer::ParseFromNBT(cEnchantments& a_Enchantments, const cParsedNBT & a_NBT, int a_EnchListTagIdx) +void EnchantmentSerializer::ParseFromNBT(cEnchantments& a_Enchantments, const cParsedNBT & a_NBT, int a_EnchListTagIdx) { // Read the enchantments from the specified NBT list tag (ench or StoredEnchantments) diff --git a/src/WorldStorage/EnchantmentSerializer.h b/src/WorldStorage/EnchantmentSerializer.h index d616b0f62..9ed362900 100644 --- a/src/WorldStorage/EnchantmentSerializer.h +++ b/src/WorldStorage/EnchantmentSerializer.h @@ -1,17 +1,17 @@ #pragma once -#include "Enchantments.h" +class cEnchantments; +class cFastNBTWriter; +class cParsedNBT; -class cEnchantmentSerializer +namespace EnchantmentSerializer { -public: - /// Writes the enchantments into the specified NBT writer; begins with the LIST tag of the specified name ("ench" or "StoredEnchantments") - static void WriteToNBTCompound(cEnchantments const& a_Enchantments, cFastNBTWriter & a_Writer, const AString & a_ListTagName); + void WriteToNBTCompound(cEnchantments const& a_Enchantments, cFastNBTWriter & a_Writer, const AString & a_ListTagName); /// Reads the enchantments from the specified NBT list tag (ench or StoredEnchantments) - static void ParseFromNBT(cEnchantments& a_Enchantments, const cParsedNBT & a_NBT, int a_EnchListTagIdx); + void ParseFromNBT(cEnchantments& a_Enchantments, const cParsedNBT & a_NBT, int a_EnchListTagIdx); }; diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp index 51e1a8d1b..91cc6b06d 100644 --- a/src/WorldStorage/NBTChunkSerializer.cpp +++ b/src/WorldStorage/NBTChunkSerializer.cpp @@ -92,7 +92,7 @@ void cNBTChunkSerializer::AddItem(const cItem & a_Item, int a_Slot, const AStrin { const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench"; m_Writer.BeginCompound("tag"); - cEnchantmentSerializer::WriteToNBTCompound(a_Item.m_Enchantments, m_Writer, TagName); + EnchantmentSerializer::WriteToNBTCompound(a_Item.m_Enchantments, m_Writer, TagName); m_Writer.EndCompound(); } diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index 702b809fb..25661de76 100644 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -640,7 +640,7 @@ bool cWSSAnvil::LoadItemFromNBT(cItem & a_Item, const cParsedNBT & a_NBT, int a_ int EnchTag = a_NBT.FindChildByName(TagTag, EnchName); if (EnchTag > 0) { - cEnchantmentSerializer::ParseFromNBT(a_Item.m_Enchantments, a_NBT, EnchTag); + EnchantmentSerializer::ParseFromNBT(a_Item.m_Enchantments, a_NBT, EnchTag); } return true;