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;