summaryrefslogtreecommitdiffstats
path: root/source/Inventory.cpp
diff options
context:
space:
mode:
authormadmaxoft@gmail.com <madmaxoft@gmail.com@0a769ca7-a7f5-676a-18bf-c427514a06d6>2012-09-24 00:09:57 +0200
committermadmaxoft@gmail.com <madmaxoft@gmail.com@0a769ca7-a7f5-676a-18bf-c427514a06d6>2012-09-24 00:09:57 +0200
commitecfe6ab65bd1fc2c7f5733fe6ef4e6ddaac44a26 (patch)
tree898e37fe747f0fdcefeb88f833557fd45db3347c /source/Inventory.cpp
parentSource files cleanup: ChunkDataSerializer is Protocol-related (diff)
downloadcuberite-ecfe6ab65bd1fc2c7f5733fe6ef4e6ddaac44a26.tar
cuberite-ecfe6ab65bd1fc2c7f5733fe6ef4e6ddaac44a26.tar.gz
cuberite-ecfe6ab65bd1fc2c7f5733fe6ef4e6ddaac44a26.tar.bz2
cuberite-ecfe6ab65bd1fc2c7f5733fe6ef4e6ddaac44a26.tar.lz
cuberite-ecfe6ab65bd1fc2c7f5733fe6ef4e6ddaac44a26.tar.xz
cuberite-ecfe6ab65bd1fc2c7f5733fe6ef4e6ddaac44a26.tar.zst
cuberite-ecfe6ab65bd1fc2c7f5733fe6ef4e6ddaac44a26.zip
Diffstat (limited to 'source/Inventory.cpp')
-rw-r--r--source/Inventory.cpp427
1 files changed, 427 insertions, 0 deletions
diff --git a/source/Inventory.cpp b/source/Inventory.cpp
new file mode 100644
index 000000000..1ad349fb5
--- /dev/null
+++ b/source/Inventory.cpp
@@ -0,0 +1,427 @@
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "Inventory.h"
+#include "Player.h"
+#include "ClientHandle.h"
+#include "UI/Window.h"
+#include "Item.h"
+#include "Root.h"
+
+#include <json/json.h>
+
+#include "items/ItemHandler.h"
+
+
+
+
+
+cInventory::~cInventory()
+{
+ /*
+ // TODO
+ cWindow wnd = GetWindow();
+ if (wnd != NULL)
+ {
+ wnd->Close(*m_Owner);
+ }
+ CloseWindow();
+ */
+}
+
+
+
+
+
+cInventory::cInventory(cPlayer & a_Owner) :
+ m_Owner(a_Owner)
+{
+ for (unsigned int i = 0; i < c_NumSlots; i++)
+ {
+ m_Slots[i].Empty();
+ }
+
+ m_CraftSlots = m_Slots + c_CraftOffset;
+ m_ArmorSlots = m_Slots + c_ArmorOffset;
+ m_MainSlots = m_Slots + c_MainOffset;
+ m_HotSlots = m_Slots + c_HotOffset;
+
+ SetEquippedSlot(0);
+}
+
+
+
+
+
+bool cInventory::AddItem( cItem & a_Item )
+{
+ cItem BackupSlots[c_NumSlots];
+ memcpy( BackupSlots, m_Slots, c_NumSlots * sizeof( cItem ) );
+
+ bool ChangedSlots[c_NumSlots];
+ memset( ChangedSlots, false, c_NumSlots * sizeof( bool ) );
+
+ if( a_Item.m_ItemCount > 0 ) AddToBar( a_Item, c_HotOffset, c_HotSlots, ChangedSlots, 0 );
+ if( a_Item.m_ItemCount > 0 ) AddToBar( a_Item, c_MainOffset, c_MainSlots, ChangedSlots, 0 );
+ if( a_Item.m_ItemCount > 0 ) AddToBar( a_Item, c_HotOffset, c_HotSlots, ChangedSlots, 2 );
+ if( a_Item.m_ItemCount > 0 ) AddToBar( a_Item, c_MainOffset, c_MainSlots, ChangedSlots, 2 );
+
+ if( a_Item.m_ItemCount > 0 ) // Could not add all items
+ {
+ // retore backup
+ memcpy( m_Slots, BackupSlots, c_NumSlots * sizeof( cItem ) );
+ return false;
+ }
+
+ for(unsigned int i = 0; i < c_NumSlots; i++)
+ {
+ if( ChangedSlots[i] )
+ {
+ LOG("Item was added to %i ID:%i Count:%i", i, m_Slots[i].m_ItemID, m_Slots[i].m_ItemCount );
+ SendSlot(i);
+ }
+ }
+
+ return (a_Item.m_ItemCount == 0);
+}
+
+
+
+
+
+// TODO: Right now if you dont have enough items, the items you did have are removed, and the function returns false anyway
+bool cInventory::RemoveItem( cItem & a_Item )
+{
+ // First check equipped slot
+ if ((m_EquippedSlot >= 0) && (m_EquippedSlot < 9))
+ {
+ if (m_HotSlots[m_EquippedSlot].m_ItemID == a_Item.m_ItemID)
+ {
+ cItem & Item = m_HotSlots[m_EquippedSlot];
+ if(Item.m_ItemCount > a_Item.m_ItemCount)
+ {
+ Item.m_ItemCount -= a_Item.m_ItemCount;
+ SendSlot( m_EquippedSlot + c_HotOffset );
+ return true;
+ }
+ else if(Item.m_ItemCount > 0 )
+ {
+ a_Item.m_ItemCount -= Item.m_ItemCount;
+ Item.Empty();
+ SendSlot( m_EquippedSlot + c_HotOffset );
+ }
+ }
+ }
+
+ // Then check other slotz
+ if (a_Item.m_ItemCount > 0)
+ {
+ for(int i = 0; i < 36; i++)
+ {
+ cItem & Item = m_MainSlots[i];
+ if( Item.m_ItemID == a_Item.m_ItemID )
+ {
+ if(Item.m_ItemCount > a_Item.m_ItemCount)
+ {
+ Item.m_ItemCount -= a_Item.m_ItemCount;
+ SendSlot( i + c_MainOffset );
+ return true;
+ }
+ else if(Item.m_ItemCount > 0 )
+ {
+ a_Item.m_ItemCount -= Item.m_ItemCount;
+ Item.Empty();
+ SendSlot( i + c_MainOffset );
+ }
+ }
+ }
+ }
+
+ return (a_Item.m_ItemCount == 0);
+}
+
+
+
+
+
+void cInventory::Clear()
+{
+ for(unsigned int i = 0; i < c_NumSlots; i++)
+ m_Slots[i].Empty();
+}
+
+
+
+
+
+cItem * cInventory::GetSlotsForType( int a_Type )
+{
+ switch( a_Type )
+ {
+ case -1:
+ return m_MainSlots;
+ case -2:
+ return m_CraftSlots;
+ case -3:
+ return m_ArmorSlots;
+ }
+ return 0;
+}
+
+
+
+
+
+/*
+int cInventory::GetSlotCountForType( int a_Type )
+{
+ switch (a_Type)
+ {
+ case -1:
+ return 36;
+ case -2:
+ case -3:
+ return 4;
+ }
+ return 0;
+}
+*/
+
+
+
+
+
+cItem* cInventory::GetSlot( int a_SlotNum )
+{
+ if( a_SlotNum < 0 || a_SlotNum >= (short)c_NumSlots ) return 0;
+ return &m_Slots[a_SlotNum];
+}
+
+
+
+
+
+cItem* cInventory::GetFromHotBar( int a_SlotNum )
+{
+ if ((a_SlotNum < 0) || (a_SlotNum >= 9))
+ {
+ return NULL;
+ }
+ return &m_HotSlots[a_SlotNum];
+}
+
+
+
+
+
+void cInventory::SetEquippedSlot(int a_SlotNum)
+{
+ if ((a_SlotNum < 0) || (a_SlotNum >= 9))
+ {
+ m_EquippedSlot = 0;
+ }
+ else
+ {
+ m_EquippedSlot = (short)a_SlotNum;
+ }
+ m_EquippedItem = GetFromHotBar(m_EquippedSlot);
+}
+
+
+
+
+
+cItem & cInventory::GetEquippedItem(void)
+{
+ cItem* Item = GetFromHotBar( m_EquippedSlot );
+ if( Item )
+ {
+ *m_EquippedItem = *Item;
+ return *Item;
+ }
+ else
+ {
+ m_EquippedItem->Empty();
+ }
+ return *m_EquippedItem;
+}
+
+
+
+
+
+const cItem & cInventory::GetEquippedItem(void) const
+{
+ return *m_EquippedItem;
+}
+
+
+
+
+
+void cInventory::SendWholeInventory(cClientHandle & a_Client)
+{
+ a_Client.SendWholeInventory(*this);
+}
+
+
+
+
+
+void cInventory::SendSlot(int a_SlotNum)
+{
+ cItem * Item = GetSlot(a_SlotNum);
+ if (Item != NULL)
+ {
+ if (Item->IsEmpty())
+ {
+ // Sanitize items that are not completely empty (ie. count == 0, but type != empty)
+ Item->Empty();
+ }
+ m_Owner.GetClientHandle()->SendInventorySlot(0, a_SlotNum, *Item);
+ }
+}
+
+
+
+
+
+int cInventory::HowManyCanFit(short a_ItemType, short a_ItemDamage, int a_BeginSlot, int a_EndSlot)
+{
+ int res = 0;
+ for (int i = a_BeginSlot; i <= a_EndSlot; i++)
+ {
+ if (
+ m_Slots[i].IsEmpty() ||
+ ((m_Slots[i].m_ItemID == a_ItemType) && (m_Slots[i].m_ItemHealth == a_ItemDamage))
+ )
+ {
+ int MaxCount = ItemHandler(a_ItemType)->GetMaxStackSize();
+ ASSERT(m_Slots[i].m_ItemCount <= MaxCount);
+ res += MaxCount - m_Slots[i].m_ItemCount;
+ }
+ } // for i - m_Slots[]
+ return res;
+}
+
+
+
+
+
+int cInventory::MoveItem(short a_ItemType, short a_ItemDamage, int a_Count, int a_BeginSlot, int a_EndSlot)
+{
+ int res = 0;
+ for (int i = a_BeginSlot; i <= a_EndSlot; i++)
+ {
+ if (
+ m_Slots[i].IsEmpty() ||
+ ((m_Slots[i].m_ItemID == a_ItemType) && (m_Slots[i].m_ItemHealth == a_ItemDamage))
+ )
+ {
+ int MaxCount = ItemHandler(a_ItemType)->GetMaxStackSize();
+ ASSERT(m_Slots[i].m_ItemCount <= MaxCount);
+ int NumToMove = std::min(a_Count, MaxCount - m_Slots[i].m_ItemCount);
+ m_Slots[i].m_ItemCount += NumToMove;
+ m_Slots[i].m_ItemHealth = a_ItemDamage;
+ m_Slots[i].m_ItemID = a_ItemType;
+ SendSlot(i);
+ res += NumToMove;
+ a_Count -= NumToMove;
+ if (a_Count <= 0)
+ {
+ // No more items to distribute
+ return res;
+ }
+ }
+ } // for i - m_Slots[]
+ // No more space to distribute to
+ return res;
+}
+
+
+
+
+
+bool cInventory::AddToBar( cItem & a_Item, const int a_Offset, const int a_Size, bool* a_bChangedSlots, int a_Mode /* = 0 */ )
+{
+ // Fill already present stacks
+ if( a_Mode < 2 )
+ {
+ for(int i = 0; i < a_Size; i++)
+ {
+ if( m_Slots[i + a_Offset].m_ItemID == a_Item.m_ItemID && m_Slots[i + a_Offset].m_ItemCount < 64 && m_Slots[i + a_Offset].m_ItemHealth == a_Item.m_ItemHealth )
+ {
+ int NumFree = 64 - m_Slots[i + a_Offset].m_ItemCount;
+ if( NumFree >= a_Item.m_ItemCount )
+ {
+
+ //printf("1. Adding %i items ( free: %i )\n", a_Item.m_ItemCount, NumFree );
+ m_Slots[i + a_Offset].m_ItemCount += a_Item.m_ItemCount;
+ a_Item.m_ItemCount = 0;
+ a_bChangedSlots[i + a_Offset] = true;
+ break;
+ }
+ else
+ {
+ //printf("2. Adding %i items\n", NumFree );
+ m_Slots[i + a_Offset].m_ItemCount += (char)NumFree;
+ a_Item.m_ItemCount -= (char)NumFree;
+ a_bChangedSlots[i + a_Offset] = true;
+ }
+ }
+ }
+ }
+
+ if( a_Mode > 0 )
+ {
+ // If we got more left, find first empty slot
+ for(int i = 0; i < a_Size && a_Item.m_ItemCount > 0; i++)
+ {
+ if( m_Slots[i + a_Offset].m_ItemID == -1 )
+ {
+ m_Slots[i + a_Offset] = a_Item;
+ a_Item.m_ItemCount = 0;
+ a_bChangedSlots[i + a_Offset] = true;
+ }
+ }
+ }
+
+ return true;
+}
+
+
+
+
+
+void cInventory::SaveToJson(Json::Value & a_Value)
+{
+ for(unsigned int i = 0; i < c_NumSlots; i++)
+ {
+ Json::Value JSON_Item;
+ m_Slots[i].GetJson( JSON_Item );
+ a_Value.append( JSON_Item );
+ }
+}
+
+
+
+
+
+bool cInventory::LoadFromJson(Json::Value & a_Value)
+{
+ int SlotIdx = 0;
+
+ // TODO: Limit the number of slots written to the actual number of slots,
+ // otherwise an invalid json will crash the server!
+
+ for( Json::Value::iterator itr = a_Value.begin(); itr != a_Value.end(); ++itr )
+ {
+ m_Slots[SlotIdx].FromJson( *itr );
+ SlotIdx++;
+ }
+ return true;
+}
+
+
+
+