1
0

Merge pull request #989 from Howaner/Anvil

Add repair cost to cItem, add custom name to NBTChunkSerializer and fix ...
This commit is contained in:
Mattes D 2014-05-07 22:18:53 +02:00
commit d1b719885d
9 changed files with 117 additions and 54 deletions

View File

@ -376,6 +376,7 @@ bool cInventory::DamageItem(int a_SlotNum, short a_Amount)
if (!Grid->DamageItem(GridSlotNum, a_Amount)) if (!Grid->DamageItem(GridSlotNum, a_Amount))
{ {
// The item has been damaged, but did not break yet // The item has been damaged, but did not break yet
SendSlot(a_SlotNum);
return false; return false;
} }

View File

@ -151,6 +151,8 @@ void cItem::GetJson(Json::Value & a_OutValue) const
a_OutValue["Colours"] = m_FireworkItem.ColoursToString(m_FireworkItem); a_OutValue["Colours"] = m_FireworkItem.ColoursToString(m_FireworkItem);
a_OutValue["FadeColours"] = m_FireworkItem.FadeColoursToString(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.ColoursFromString(a_Value.get("Colours", "").asString(), m_FireworkItem);
m_FireworkItem.FadeColoursFromString(a_Value.get("FadeColours", "").asString(), m_FireworkItem); m_FireworkItem.FadeColoursFromString(a_Value.get("FadeColours", "").asString(), m_FireworkItem);
} }
m_RepairCost = a_Value.get("RepairCost", 0).asInt();
} }
} }

View File

@ -40,6 +40,7 @@ public:
m_ItemDamage(0), m_ItemDamage(0),
m_CustomName(""), m_CustomName(""),
m_Lore(""), m_Lore(""),
m_RepairCost(0),
m_FireworkItem() m_FireworkItem()
{ {
} }
@ -60,6 +61,7 @@ public:
m_Enchantments(a_Enchantments), m_Enchantments(a_Enchantments),
m_CustomName (a_CustomName), m_CustomName (a_CustomName),
m_Lore (a_Lore), m_Lore (a_Lore),
m_RepairCost (0),
m_FireworkItem() m_FireworkItem()
{ {
if (!IsValidItem(m_ItemType)) if (!IsValidItem(m_ItemType))
@ -85,6 +87,7 @@ public:
m_Enchantments(a_CopyFrom.m_Enchantments), m_Enchantments(a_CopyFrom.m_Enchantments),
m_CustomName (a_CopyFrom.m_CustomName), m_CustomName (a_CopyFrom.m_CustomName),
m_Lore (a_CopyFrom.m_Lore), m_Lore (a_CopyFrom.m_Lore),
m_RepairCost (a_CopyFrom.m_RepairCost),
m_FireworkItem(a_CopyFrom.m_FireworkItem) m_FireworkItem(a_CopyFrom.m_FireworkItem)
{ {
} }
@ -100,6 +103,7 @@ public:
m_Enchantments.Clear(); m_Enchantments.Clear();
m_CustomName = ""; m_CustomName = "";
m_Lore = ""; m_Lore = "";
m_RepairCost = 0;
m_FireworkItem.EmptyData(); m_FireworkItem.EmptyData();
} }
@ -109,6 +113,7 @@ public:
m_ItemType = E_ITEM_EMPTY; m_ItemType = E_ITEM_EMPTY;
m_ItemCount = 0; m_ItemCount = 0;
m_ItemDamage = 0; m_ItemDamage = 0;
m_RepairCost = 0;
} }
@ -190,14 +195,15 @@ public:
// tolua_begin // tolua_begin
short m_ItemType; short m_ItemType;
char m_ItemCount; char m_ItemCount;
short m_ItemDamage; short m_ItemDamage;
cEnchantments m_Enchantments; cEnchantments m_Enchantments;
AString m_CustomName; AString m_CustomName;
AString m_Lore; AString m_Lore;
cFireworkItem m_FireworkItem; int m_RepairCost;
cFireworkItem m_FireworkItem;
}; };
// tolua_end // tolua_end

View File

@ -521,15 +521,6 @@ bool cItemHandler::CanRepairWithRawMaterial(short a_ItemType)
int cItemHandler::GetRepairCost(void)
{
return 0;
}
bool cItemHandler::CanHarvestBlock(BLOCKTYPE a_BlockType) bool cItemHandler::CanHarvestBlock(BLOCKTYPE a_BlockType)
{ {
UNUSED(a_BlockType); UNUSED(a_BlockType);

View File

@ -88,9 +88,6 @@ public:
/** Can the anvil repair this item, when a_Item is the second input? */ /** Can the anvil repair this item, when a_Item is the second input? */
virtual bool CanRepairWithRawMaterial(short a_ItemType); 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. /** Called before a block is placed into a world.
The handler should return true to allow placement, false to refuse. 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. Also, the handler should set a_BlockType and a_BlockMeta to correct values for the newly placed block.

View File

@ -2278,6 +2278,13 @@ void cProtocol172::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata)
} }
break; break;
} }
case TAG_Int:
{
if (TagName == "RepairCost")
{
a_Item.m_RepairCost = NBT.GetInt(tag);
}
}
default: LOGD("Unimplemented NBT data when parsing!"); break; 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: // Send the enchantments and custom names:
cFastNBTWriter Writer; cFastNBTWriter Writer;
if (a_Item.m_RepairCost != 0)
{
Writer.AddInt("RepairCost", a_Item.m_RepairCost);
}
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";

View File

@ -866,16 +866,19 @@ void cSlotAreaAnvil::UpdateResult(cPlayer & a_Player)
m_MaximumCost = 0; m_MaximumCost = 0;
m_StackSizeToBeUsedInRepair = 0; m_StackSizeToBeUsedInRepair = 0;
int RepairCost = cItemHandler::GetItemHandler(Input)->GetRepairCost(); int RepairCost = Input.m_RepairCost;
int NeedExp = 0; int NeedExp = 0;
bool IsEnchantBook = false;
if (!SecondInput.IsEmpty()) 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)) if (Input.IsDamageable() && cItemHandler::GetItemHandler(Input)->CanRepairWithRawMaterial(SecondInput.m_ItemType))
{ {
// Tool and armor repair with special item (iron / gold / diamond / ...) // Tool and armor repair with special item (iron / gold / diamond / ...)
int DamageDiff = std::min((int)Input.m_ItemDamage, (int)Input.GetMaxDamage() / 4); int DamageDiff = std::min((int)Input.m_ItemDamage, (int)Input.GetMaxDamage() / 4);
if (DamageDiff < 0) if (DamageDiff <= 0)
{ {
// No enchantment // No enchantment
Output.Empty(); Output.Empty();
@ -898,7 +901,7 @@ void cSlotAreaAnvil::UpdateResult(cPlayer & a_Player)
else else
{ {
// Tool and armor repair with two tools / armors // Tool and armor repair with two tools / armors
if (!Input.IsSameType(SecondInput) || !Input.IsDamageable()) if (!IsEnchantBook && (!Input.IsSameType(SecondInput) || !Input.IsDamageable()))
{ {
// No enchantment // No enchantment
Output.Empty(); Output.Empty();
@ -907,20 +910,23 @@ void cSlotAreaAnvil::UpdateResult(cPlayer & a_Player)
return; return;
} }
int FirstDamageDiff = Input.GetMaxDamage() - Input.m_ItemDamage; if ((Input.GetMaxDamage() > 0) && !IsEnchantBook)
int SecondDamageDiff = SecondInput.GetMaxDamage() - SecondInput.m_ItemDamage;
int Damage = SecondDamageDiff + Input.GetMaxDamage() * 12 / 100;
int NewItemDamage = Input.GetMaxDamage() - (FirstDamageDiff + Damage);
if (NewItemDamage > 0)
{ {
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) int NewItemDamage = Input.GetMaxDamage() - (FirstDamageDiff + Damage);
{ if (NewItemDamage > 0)
Input.m_ItemDamage = NewItemDamage; {
NeedExp += std::max(1, Damage / 100); NewItemDamage = 0;
}
if (NewItemDamage < Input.m_ItemDamage)
{
Input.m_ItemDamage = NewItemDamage;
NeedExp += std::max(1, Damage / 100);
}
} }
// TODO: Add enchantments. // TODO: Add enchantments.
@ -934,7 +940,7 @@ void cSlotAreaAnvil::UpdateResult(cPlayer & a_Player)
// Remove custom name // Remove custom name
if (!Input.m_CustomName.empty()) if (!Input.m_CustomName.empty())
{ {
NameChangeExp = (Input.IsDamageable()) ? 4 : (Input.m_ItemCount * 5); NameChangeExp = (Input.IsDamageable()) ? 7 : (Input.m_ItemCount * 5);
NeedExp += NameChangeExp; NeedExp += NameChangeExp;
Input.m_CustomName = ""; Input.m_CustomName = "";
} }
@ -942,7 +948,7 @@ void cSlotAreaAnvil::UpdateResult(cPlayer & a_Player)
else if (RepairedItemName != Input.m_CustomName) else if (RepairedItemName != Input.m_CustomName)
{ {
// Change custom name // Change custom name
NameChangeExp = (Input.IsDamageable()) ? 4 : (Input.m_ItemCount * 5); NameChangeExp = (Input.IsDamageable()) ? 7 : (Input.m_ItemCount * 5);
NeedExp += NameChangeExp; NeedExp += NameChangeExp;
if (!Input.m_CustomName.empty()) if (!Input.m_CustomName.empty())
@ -962,7 +968,7 @@ void cSlotAreaAnvil::UpdateResult(cPlayer & a_Player)
Input.Empty(); Input.Empty();
} }
if (NameChangeExp == NeedExp && NameChangeExp > 0 && m_MaximumCost >= 40) if ((NameChangeExp == NeedExp) && (NameChangeExp > 0) && (m_MaximumCost >= 40))
{ {
m_MaximumCost = 39; m_MaximumCost = 39;
} }
@ -971,17 +977,17 @@ void cSlotAreaAnvil::UpdateResult(cPlayer & a_Player)
Input.Empty(); Input.Empty();
} }
/* TODO: Add repair cost to cItem and not ItemHandler. This is required for this function!
if (!Input.IsEmpty()) 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()) if (!Input.m_CustomName.empty())
{ {
RepairCost -= 9; RepairCost -= 9;
} }
RepairCost = max(RepairCost, 0); RepairCost = std::max(RepairCost, 0);
RepairCost += 2; RepairCost += 2;
}*/ Input.m_RepairCost = RepairCost;
}
SetSlot(2, a_Player, Input); SetSlot(2, a_Player, Input);
m_ParentWindow.SetProperty(0, m_MaximumCost, a_Player); m_ParentWindow.SetProperty(0, m_MaximumCost, a_Player);

View File

@ -88,23 +88,48 @@ void cNBTChunkSerializer::Finish(void)
void cNBTChunkSerializer::AddItem(const cItem & a_Item, int a_Slot, const AString & a_CompoundName) void cNBTChunkSerializer::AddItem(const cItem & a_Item, int a_Slot, const AString & a_CompoundName)
{ {
m_Writer.BeginCompound(a_CompoundName); m_Writer.BeginCompound(a_CompoundName);
m_Writer.AddShort("id", (short)(a_Item.m_ItemType)); m_Writer.AddShort("id", (short)(a_Item.m_ItemType));
m_Writer.AddShort("Damage", a_Item.m_ItemDamage); m_Writer.AddShort("Damage", a_Item.m_ItemDamage);
m_Writer.AddByte ("Count", a_Item.m_ItemCount); m_Writer.AddByte ("Count", a_Item.m_ItemCount);
if (a_Slot >= 0) if (a_Slot >= 0)
{ {
m_Writer.AddByte ("Slot", (unsigned char)a_Slot); m_Writer.AddByte ("Slot", (unsigned char)a_Slot);
} }
// Write the enchantments: // 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))) 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"); m_Writer.BeginCompound("tag");
if (a_Item.m_RepairCost > 0)
{
m_Writer.AddInt("RepairCost", 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)) 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); cFireworkItem::WriteToNBTCompound(a_Item.m_FireworkItem, m_Writer, (ENUM_ITEM_ID)a_Item.m_ItemType);
} }
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";

View File

@ -645,18 +645,16 @@ bool cWSSAnvil::LoadItemFromNBT(cItem & a_Item, const cParsedNBT & a_NBT, int a_
} }
int Damage = a_NBT.FindChildByName(a_TagIdx, "Damage"); 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"); 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 // Find the "tag" tag, used for enchantments and other extra data
int TagTag = a_NBT.FindChildByName(a_TagIdx, "tag"); 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; 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 = 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: // Load enchantments:
const char * EnchName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench"; const char * EnchName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench";
int EnchTag = a_NBT.FindChildByName(TagTag, EnchName); 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); 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")); int FireworksTag = a_NBT.FindChildByName(TagTag, ((a_Item.m_ItemType == E_ITEM_FIREWORK_STAR) ? "Fireworks" : "Explosion"));
if (EnchTag > 0) if (EnchTag > 0)
{ {