From d6cb6e0423fe38478c69f5d249882a01d727f0ed Mon Sep 17 00:00:00 2001 From: Howaner Date: Wed, 7 May 2014 12:30:30 +0200 Subject: [PATCH] Add repair cost to cItem, add custom name to NBTChunkSerializer and fix anvil bugs. --- src/Item.cpp | 4 ++ src/Item.h | 22 +++++---- src/Items/ItemHandler.cpp | 9 ---- src/Items/ItemHandler.h | 3 -- src/Protocol/Protocol17x.cpp | 11 +++++ src/UI/SlotArea.cpp | 60 +++++++++++++++---------- src/WorldStorage/NBTChunkSerializer.cpp | 37 ++++++++++++--- src/WorldStorage/WSSAnvil.cpp | 34 +++++++++++--- 8 files changed, 124 insertions(+), 56 deletions(-) diff --git a/src/Item.cpp b/src/Item.cpp index 7e472f6d8..d32164bc4 100644 --- a/src/Item.cpp +++ b/src/Item.cpp @@ -151,6 +151,8 @@ void cItem::GetJson(Json::Value & a_OutValue) const a_OutValue["Colours"] = m_FireworkItem.ColoursToString(m_FireworkItem); a_OutValue["FadeColours"] = m_FireworkItem.FadeColoursToString(m_FireworkItem); } + + a_OutValue["RepairCost"] = m_RepairCost; } } @@ -179,6 +181,8 @@ void cItem::FromJson(const Json::Value & a_Value) m_FireworkItem.ColoursFromString(a_Value.get("Colours", "").asString(), m_FireworkItem); m_FireworkItem.FadeColoursFromString(a_Value.get("FadeColours", "").asString(), m_FireworkItem); } + + m_RepairCost = (unsigned short)a_Value.get("RepairCost", 0).asInt(); } } diff --git a/src/Item.h b/src/Item.h index 8eb0a1f4e..7e2fc6cff 100644 --- a/src/Item.h +++ b/src/Item.h @@ -40,6 +40,7 @@ public: m_ItemDamage(0), m_CustomName(""), m_Lore(""), + m_RepairCost(0), m_FireworkItem() { } @@ -60,6 +61,7 @@ public: m_Enchantments(a_Enchantments), m_CustomName (a_CustomName), m_Lore (a_Lore), + m_RepairCost (0), m_FireworkItem() { if (!IsValidItem(m_ItemType)) @@ -85,7 +87,8 @@ public: m_Enchantments(a_CopyFrom.m_Enchantments), m_CustomName (a_CopyFrom.m_CustomName), m_Lore (a_CopyFrom.m_Lore), - m_FireworkItem(a_CopyFrom.m_FireworkItem) + m_FireworkItem(a_CopyFrom.m_FireworkItem), + m_RepairCost (a_CopyFrom.m_RepairCost) { } @@ -100,6 +103,7 @@ public: m_Enchantments.Clear(); m_CustomName = ""; m_Lore = ""; + m_RepairCost = 0; m_FireworkItem.EmptyData(); } @@ -109,6 +113,7 @@ public: m_ItemType = E_ITEM_EMPTY; m_ItemCount = 0; m_ItemDamage = 0; + m_RepairCost = 0; } @@ -190,14 +195,15 @@ public: // tolua_begin - short m_ItemType; - char m_ItemCount; - short m_ItemDamage; - cEnchantments m_Enchantments; - AString m_CustomName; - AString m_Lore; + short m_ItemType; + char m_ItemCount; + short m_ItemDamage; + cEnchantments m_Enchantments; + AString m_CustomName; + AString m_Lore; - cFireworkItem m_FireworkItem; + cFireworkItem m_FireworkItem; + UInt16 m_RepairCost; }; // tolua_end diff --git a/src/Items/ItemHandler.cpp b/src/Items/ItemHandler.cpp index 5cc5b66a0..d97f986ba 100644 --- a/src/Items/ItemHandler.cpp +++ b/src/Items/ItemHandler.cpp @@ -521,15 +521,6 @@ bool cItemHandler::CanRepairWithRawMaterial(short a_ItemType) -int cItemHandler::GetRepairCost(void) -{ - return 0; -} - - - - - bool cItemHandler::CanHarvestBlock(BLOCKTYPE a_BlockType) { UNUSED(a_BlockType); diff --git a/src/Items/ItemHandler.h b/src/Items/ItemHandler.h index ca090eb29..e13198cd7 100644 --- a/src/Items/ItemHandler.h +++ b/src/Items/ItemHandler.h @@ -88,9 +88,6 @@ public: /** Can the anvil repair this item, when a_Item is the second input? */ virtual bool CanRepairWithRawMaterial(short a_ItemType); - /** Get the repair cost from the item, or 0 if the item hasn't repair cost. */ - virtual int GetRepairCost(void); - /** Called before a block is placed into a world. The handler should return true to allow placement, false to refuse. Also, the handler should set a_BlockType and a_BlockMeta to correct values for the newly placed block. diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index bc9aff0c0..c4fb9d424 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -2278,6 +2278,13 @@ void cProtocol172::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata) } break; } + case TAG_Int: + { + if (TagName == "RepairCost") + { + a_Item.m_RepairCost = (UInt16)NBT.GetInt(tag); + } + } default: LOGD("Unimplemented NBT data when parsing!"); break; } } @@ -2451,6 +2458,10 @@ void cProtocol172::cPacketizer::WriteItem(const cItem & a_Item) // Send the enchantments and custom names: cFastNBTWriter Writer; + if (a_Item.m_RepairCost != 0) + { + Writer.AddInt("RepairCost", (Int32)a_Item.m_RepairCost); + } if (!a_Item.m_Enchantments.IsEmpty()) { const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench"; diff --git a/src/UI/SlotArea.cpp b/src/UI/SlotArea.cpp index fcf5f6f6b..c4c95c7b1 100644 --- a/src/UI/SlotArea.cpp +++ b/src/UI/SlotArea.cpp @@ -866,16 +866,19 @@ void cSlotAreaAnvil::UpdateResult(cPlayer & a_Player) m_MaximumCost = 0; m_StackSizeToBeUsedInRepair = 0; - int RepairCost = cItemHandler::GetItemHandler(Input)->GetRepairCost(); + UInt16 RepairCost = Input.m_RepairCost; int NeedExp = 0; + bool IsEnchantBook = false; if (!SecondInput.IsEmpty()) { - RepairCost += cItemHandler::GetItemHandler(SecondInput)->GetRepairCost(); + IsEnchantBook = (SecondInput.m_ItemType == E_ITEM_ENCHANTED_BOOK); + + RepairCost += SecondInput.m_RepairCost; if (Input.IsDamageable() && cItemHandler::GetItemHandler(Input)->CanRepairWithRawMaterial(SecondInput.m_ItemType)) { // Tool and armor repair with special item (iron / gold / diamond / ...) int DamageDiff = std::min((int)Input.m_ItemDamage, (int)Input.GetMaxDamage() / 4); - if (DamageDiff < 0) + if (DamageDiff <= 0) { // No enchantment Output.Empty(); @@ -898,7 +901,7 @@ void cSlotAreaAnvil::UpdateResult(cPlayer & a_Player) else { // Tool and armor repair with two tools / armors - if (!Input.IsSameType(SecondInput) || !Input.IsDamageable()) + if (!IsEnchantBook && (!Input.IsSameType(SecondInput) || !Input.IsDamageable())) { // No enchantment Output.Empty(); @@ -907,20 +910,23 @@ void cSlotAreaAnvil::UpdateResult(cPlayer & a_Player) return; } - int FirstDamageDiff = Input.GetMaxDamage() - Input.m_ItemDamage; - int SecondDamageDiff = SecondInput.GetMaxDamage() - SecondInput.m_ItemDamage; - int Damage = SecondDamageDiff + Input.GetMaxDamage() * 12 / 100; - - int NewItemDamage = Input.GetMaxDamage() - (FirstDamageDiff + Damage); - if (NewItemDamage > 0) + if ((Input.GetMaxDamage() > 0) && !IsEnchantBook) { - NewItemDamage = 0; - } + int FirstDamageDiff = Input.GetMaxDamage() - Input.m_ItemDamage; + int SecondDamageDiff = SecondInput.GetMaxDamage() - SecondInput.m_ItemDamage; + int Damage = SecondDamageDiff + Input.GetMaxDamage() * 12 / 100; - if (NewItemDamage < Input.m_ItemDamage) - { - Input.m_ItemDamage = NewItemDamage; - NeedExp += std::max(1, Damage / 100); + int NewItemDamage = Input.GetMaxDamage() - (FirstDamageDiff + Damage); + if (NewItemDamage > 0) + { + NewItemDamage = 0; + } + + if (NewItemDamage < Input.m_ItemDamage) + { + Input.m_ItemDamage = NewItemDamage; + NeedExp += std::max(1, Damage / 100); + } } // TODO: Add enchantments. @@ -934,7 +940,7 @@ void cSlotAreaAnvil::UpdateResult(cPlayer & a_Player) // Remove custom name if (!Input.m_CustomName.empty()) { - NameChangeExp = (Input.IsDamageable()) ? 4 : (Input.m_ItemCount * 5); + NameChangeExp = (Input.IsDamageable()) ? 7 : (Input.m_ItemCount * 5); NeedExp += NameChangeExp; Input.m_CustomName = ""; } @@ -942,7 +948,7 @@ void cSlotAreaAnvil::UpdateResult(cPlayer & a_Player) else if (RepairedItemName != Input.m_CustomName) { // Change custom name - NameChangeExp = (Input.IsDamageable()) ? 4 : (Input.m_ItemCount * 5); + NameChangeExp = (Input.IsDamageable()) ? 7 : (Input.m_ItemCount * 5); NeedExp += NameChangeExp; if (!Input.m_CustomName.empty()) @@ -962,7 +968,7 @@ void cSlotAreaAnvil::UpdateResult(cPlayer & a_Player) Input.Empty(); } - if (NameChangeExp == NeedExp && NameChangeExp > 0 && m_MaximumCost >= 40) + if ((NameChangeExp == NeedExp) && (NameChangeExp > 0) && (m_MaximumCost >= 40)) { m_MaximumCost = 39; } @@ -971,17 +977,23 @@ void cSlotAreaAnvil::UpdateResult(cPlayer & a_Player) Input.Empty(); } - /* TODO: Add repair cost to cItem and not ItemHandler. This is required for this function! if (!Input.IsEmpty()) { - RepairCost = max(cItemHandler::GetItemHandler(Input)->GetRepairCost(), cItemHandler::GetItemHandler(SecondInput)->GetRepairCost()); + RepairCost = std::max(Input.m_RepairCost, SecondInput.m_RepairCost); if (!Input.m_CustomName.empty()) { - RepairCost -= 9; + if (RepairCost < 9) + { + RepairCost = 0; + } + else + { + RepairCost -= 9; + } } - RepairCost = max(RepairCost, 0); RepairCost += 2; - }*/ + Input.m_RepairCost = RepairCost; + } SetSlot(2, a_Player, Input); m_ParentWindow.SetProperty(0, m_MaximumCost, a_Player); diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp index fd356c7de..b696a8f69 100644 --- a/src/WorldStorage/NBTChunkSerializer.cpp +++ b/src/WorldStorage/NBTChunkSerializer.cpp @@ -88,23 +88,48 @@ void cNBTChunkSerializer::Finish(void) void cNBTChunkSerializer::AddItem(const cItem & a_Item, int a_Slot, const AString & a_CompoundName) { m_Writer.BeginCompound(a_CompoundName); - m_Writer.AddShort("id", (short)(a_Item.m_ItemType)); - m_Writer.AddShort("Damage", a_Item.m_ItemDamage); - m_Writer.AddByte ("Count", a_Item.m_ItemCount); + m_Writer.AddShort("id", (short)(a_Item.m_ItemType)); + m_Writer.AddShort("Damage", a_Item.m_ItemDamage); + m_Writer.AddByte ("Count", a_Item.m_ItemCount); if (a_Slot >= 0) { m_Writer.AddByte ("Slot", (unsigned char)a_Slot); } - // Write the enchantments: - if (!a_Item.m_Enchantments.IsEmpty() || ((a_Item.m_ItemType == E_ITEM_FIREWORK_ROCKET) || (a_Item.m_ItemType == E_ITEM_FIREWORK_STAR))) + // Write the tag compound (for enchantment, firework, custom name and repair cost): + if ( + (!a_Item.m_Enchantments.IsEmpty()) || + ((a_Item.m_ItemType == E_ITEM_FIREWORK_ROCKET) || (a_Item.m_ItemType == E_ITEM_FIREWORK_STAR)) || + (a_Item.m_RepairCost > 0) || + (a_Item.m_CustomName != "") || + (a_Item.m_Lore != "") + ) { m_Writer.BeginCompound("tag"); + if (a_Item.m_RepairCost > 0) + { + m_Writer.AddInt("RepairCost", (Int32)a_Item.m_RepairCost); + } + + if ((a_Item.m_CustomName != "") || (a_Item.m_Lore != "")) + { + m_Writer.BeginCompound("display"); + if (a_Item.m_CustomName != "") + { + m_Writer.AddString("Name", a_Item.m_CustomName); + } + if (a_Item.m_Lore != "") + { + m_Writer.AddString("Lore", a_Item.m_Lore); + } + m_Writer.EndCompound(); + } + if ((a_Item.m_ItemType == E_ITEM_FIREWORK_ROCKET) || (a_Item.m_ItemType == E_ITEM_FIREWORK_STAR)) { cFireworkItem::WriteToNBTCompound(a_Item.m_FireworkItem, m_Writer, (ENUM_ITEM_ID)a_Item.m_ItemType); } - + if (!a_Item.m_Enchantments.IsEmpty()) { const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench"; diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index f33178173..b1c6238ab 100644 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -645,18 +645,16 @@ bool cWSSAnvil::LoadItemFromNBT(cItem & a_Item, const cParsedNBT & a_NBT, int a_ } int Damage = a_NBT.FindChildByName(a_TagIdx, "Damage"); - if ((Damage < 0) || (a_NBT.GetType(Damage) != TAG_Short)) + if ((Damage > 0) && (a_NBT.GetType(Damage) == TAG_Short)) { - return false; + a_Item.m_ItemDamage = a_NBT.GetShort(Damage); } - a_Item.m_ItemDamage = a_NBT.GetShort(Damage); int Count = a_NBT.FindChildByName(a_TagIdx, "Count"); - if ((Count < 0) || (a_NBT.GetType(Count) != TAG_Byte)) + if ((Count > 0) && (a_NBT.GetType(Count) == TAG_Byte)) { - return false; + a_Item.m_ItemCount = a_NBT.GetByte(Count); } - a_Item.m_ItemCount = a_NBT.GetByte(Count); // Find the "tag" tag, used for enchantments and other extra data int TagTag = a_NBT.FindChildByName(a_TagIdx, "tag"); @@ -666,6 +664,29 @@ bool cWSSAnvil::LoadItemFromNBT(cItem & a_Item, const cParsedNBT & a_NBT, int a_ return true; } + // Load repair cost: + int RepairCost = a_NBT.FindChildByName(TagTag, "RepairCost"); + if ((RepairCost > 0) && (a_NBT.GetType(RepairCost) == TAG_Int)) + { + a_Item.m_RepairCost = (UInt16)a_NBT.GetInt(RepairCost); + } + + // Load display name: + int DisplayTag = a_NBT.FindChildByName(TagTag, "display"); + if (DisplayTag > 0) + { + int DisplayName = a_NBT.FindChildByName(DisplayTag, "Name"); + if ((DisplayName > 0) && (a_NBT.GetType(DisplayName) == TAG_String)) + { + a_Item.m_CustomName = a_NBT.GetString(DisplayName); + } + int Lore = a_NBT.FindChildByName(DisplayTag, "Lore"); + if ((Lore > 0) && (a_NBT.GetType(Lore) == TAG_String)) + { + a_Item.m_Lore = a_NBT.GetString(Lore); + } + } + // Load enchantments: const char * EnchName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench"; int EnchTag = a_NBT.FindChildByName(TagTag, EnchName); @@ -674,6 +695,7 @@ bool cWSSAnvil::LoadItemFromNBT(cItem & a_Item, const cParsedNBT & a_NBT, int a_ EnchantmentSerializer::ParseFromNBT(a_Item.m_Enchantments, a_NBT, EnchTag); } + // Load firework data: int FireworksTag = a_NBT.FindChildByName(TagTag, ((a_Item.m_ItemType == E_ITEM_FIREWORK_STAR) ? "Fireworks" : "Explosion")); if (EnchTag > 0) {