1
0

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
This commit is contained in:
Tycho 2014-01-19 07:38:59 -08:00
parent 9aca5b4b99
commit e14ddff1c0
8 changed files with 116 additions and 90 deletions

View File

@ -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
}

View File

@ -31,6 +31,7 @@ Serialization will never put zero-level enchantments into the stringspec and wil
*/ */
class cEnchantments class cEnchantments
{ {
friend class cEnchantmentSerializer;
public: public:
/// Individual enchantment IDs, corresponding to their NBT IDs ( http://www.minecraftwiki.net/wiki/Data_Values#Enchantment_IDs ) /// Individual enchantment IDs, corresponding to their NBT IDs ( http://www.minecraftwiki.net/wiki/Data_Values#Enchantment_IDs )
enum enum
@ -96,11 +97,7 @@ public:
/// Returns true if a_Other doesn't contain exactly the same enchantments and levels /// Returns true if a_Other doesn't contain exactly the same enchantments and levels
bool operator !=(const cEnchantments & a_Other) const; 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: protected:
/// Maps enchantment ID -> enchantment level /// Maps enchantment ID -> enchantment level

View File

@ -16,6 +16,7 @@
#include "../UI/Window.h" #include "../UI/Window.h"
#include "../Entities/Pickup.h" #include "../Entities/Pickup.h"
#include "../WorldStorage/FastNBT.h" #include "../WorldStorage/FastNBT.h"
#include "../WorldStorage/EnchantmentSerializer.h"
#include "../StringCompression.h" #include "../StringCompression.h"
#ifdef _MSC_VER #ifdef _MSC_VER
@ -763,7 +764,7 @@ void cProtocol132::WriteItem(const cItem & a_Item)
// Send the enchantments: // Send the enchantments:
cFastNBTWriter Writer; cFastNBTWriter Writer;
const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench"; 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(); Writer.Finish();
AString Compressed; AString Compressed;
CompressStringGZIP(Writer.GetResult().data(), Writer.GetResult().size(), 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);
} }
} }

View File

@ -16,6 +16,7 @@ Implements the 1.7.x protocol classes:
#include "../Server.h" #include "../Server.h"
#include "../World.h" #include "../World.h"
#include "../WorldStorage/FastNBT.h" #include "../WorldStorage/FastNBT.h"
#include "../WorldStorage/EnchantmentSerializer.h"
#include "../StringCompression.h" #include "../StringCompression.h"
#include "../Entities/ExpOrb.h" #include "../Entities/ExpOrb.h"
#include "../Entities/Minecart.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 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()) if (!a_Item.m_Enchantments.IsEmpty())
{ {
const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench"; 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()) if (!a_Item.IsBothNameAndLoreEmpty())
{ {

View File

@ -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
}

View File

@ -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);
};

View File

@ -4,6 +4,7 @@
#include "Globals.h" #include "Globals.h"
#include "NBTChunkSerializer.h" #include "NBTChunkSerializer.h"
#include "EnchantmentSerializer.h"
#include "../BlockID.h" #include "../BlockID.h"
#include "../ItemGrid.h" #include "../ItemGrid.h"
#include "../StringCompression.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"; const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench";
m_Writer.BeginCompound("tag"); m_Writer.BeginCompound("tag");
a_Item.m_Enchantments.WriteToNBTCompound(m_Writer, TagName); cEnchantmentSerializer::WriteToNBTCompound(a_Item.m_Enchantments, m_Writer, TagName);
m_Writer.EndCompound(); m_Writer.EndCompound();
} }

View File

@ -7,6 +7,7 @@
#include "WSSAnvil.h" #include "WSSAnvil.h"
#include "NBTChunkSerializer.h" #include "NBTChunkSerializer.h"
#include "FastNBT.h" #include "FastNBT.h"
#include "EnchantmentSerializer.h"
#include "zlib/zlib.h" #include "zlib/zlib.h"
#include "../World.h" #include "../World.h"
#include "../BlockID.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); int EnchTag = a_NBT.FindChildByName(TagTag, EnchName);
if (EnchTag > 0) if (EnchTag > 0)
{ {
a_Item.m_Enchantments.ParseFromNBT(a_NBT, EnchTag); cEnchantmentSerializer::ParseFromNBT(a_Item.m_Enchantments, a_NBT, EnchTag);
} }
return true; return true;