2012-06-14 09:06:06 -04:00
# include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
2012-09-23 18:09:57 -04:00
# include "Inventory.h"
2013-08-19 05:39:13 -04:00
# include "Entities/Player.h"
2012-09-23 18:09:57 -04:00
# include "ClientHandle.h"
2012-09-23 13:19:34 -04:00
# include "UI/Window.h"
2012-09-23 18:09:57 -04:00
# include "Item.h"
# include "Root.h"
2013-05-19 14:22:37 -04:00
# include "World.h"
2012-06-14 09:06:06 -04:00
2013-11-27 03:17:25 -05:00
# include "json/json.h"
2012-06-14 09:06:06 -04:00
2012-09-29 09:59:32 -04:00
# include "Items/ItemHandler.h"
2012-08-11 15:54:57 -04:00
2012-06-14 09:06:06 -04:00
2013-05-19 14:22:37 -04:00
cInventory : : cInventory ( cPlayer & a_Owner ) :
2013-05-24 03:30:39 -04:00
m_ArmorSlots ( 1 , 4 ) , // 1 x 4 slots
m_InventorySlots ( 9 , 3 ) , // 9 x 3 slots
m_HotbarSlots ( 9 , 1 ) , // 9 x 1 slots
2017-05-24 02:09:58 -04:00
m_ShieldSlots ( 1 , 1 ) , // 1 x 1 slots
2013-05-19 14:22:37 -04:00
m_Owner ( a_Owner )
{
2013-05-24 03:30:39 -04:00
// Ask each ItemGrid to report changes to us:
m_ArmorSlots . AddListener ( * this ) ;
m_InventorySlots . AddListener ( * this ) ;
m_HotbarSlots . AddListener ( * this ) ;
2017-12-21 06:55:23 -05:00
m_ShieldSlots . AddListener ( * this ) ;
2016-02-05 16:45:45 -05:00
2013-05-19 14:22:37 -04:00
SetEquippedSlotNum ( 0 ) ;
}
2013-05-24 03:30:39 -04:00
void cInventory : : Clear ( void )
2012-06-14 09:06:06 -04:00
{
2013-05-24 03:30:39 -04:00
m_ArmorSlots . Clear ( ) ;
m_InventorySlots . Clear ( ) ;
m_HotbarSlots . Clear ( ) ;
2017-05-24 02:09:58 -04:00
m_ShieldSlots . Clear ( ) ;
2012-06-14 09:06:06 -04:00
}
2013-05-24 03:30:39 -04:00
int cInventory : : HowManyCanFit ( const cItem & a_ItemStack , bool a_ConsiderEmptySlots )
2012-06-14 09:06:06 -04:00
{
2013-05-24 03:30:39 -04:00
return HowManyCanFit ( a_ItemStack , 0 , invNumSlots - 1 , a_ConsiderEmptySlots ) ;
}
2012-06-14 09:06:06 -04:00
2013-05-24 03:30:39 -04:00
int cInventory : : HowManyCanFit ( const cItem & a_ItemStack , int a_BeginSlotNum , int a_EndSlotNum , bool a_ConsiderEmptySlots )
{
2013-12-22 09:28:47 -05:00
UNUSED ( a_ConsiderEmptySlots ) ;
2013-05-24 03:30:39 -04:00
if ( ( a_BeginSlotNum < 0 ) | | ( a_BeginSlotNum > = invNumSlots ) )
2012-06-14 09:06:06 -04:00
{
2013-05-24 03:30:39 -04:00
LOGWARNING ( " %s: Bad BeginSlotNum, got %d, there are %d slots; correcting to 0. " , __FUNCTION__ , a_BeginSlotNum , invNumSlots - 1 ) ;
a_BeginSlotNum = 0 ;
}
if ( ( a_EndSlotNum < 0 ) | | ( a_EndSlotNum > = invNumSlots ) )
{
LOGWARNING ( " %s: Bad EndSlotNum, got %d, there are %d slots; correcting to %d. " , __FUNCTION__ , a_BeginSlotNum , invNumSlots , invNumSlots - 1 ) ;
a_EndSlotNum = invNumSlots - 1 ;
}
if ( a_BeginSlotNum > a_EndSlotNum )
{
std : : swap ( a_BeginSlotNum , a_EndSlotNum ) ;
2012-06-14 09:06:06 -04:00
}
2013-05-24 03:30:39 -04:00
char NumLeft = a_ItemStack . m_ItemCount ;
int MaxStack = ItemHandler ( a_ItemStack . m_ItemType ) - > GetMaxStackSize ( ) ;
for ( int i = a_BeginSlotNum ; i < = a_EndSlotNum ; i + + )
2012-06-14 09:06:06 -04:00
{
2013-05-24 03:30:39 -04:00
const cItem & Slot = GetSlot ( i ) ;
if ( Slot . IsEmpty ( ) )
2012-06-14 09:06:06 -04:00
{
2013-05-24 03:30:39 -04:00
NumLeft - = MaxStack ;
2012-06-14 09:06:06 -04:00
}
2014-01-16 14:00:49 -05:00
else if ( Slot . IsEqual ( a_ItemStack ) )
2013-05-24 03:30:39 -04:00
{
NumLeft - = MaxStack - Slot . m_ItemCount ;
}
if ( NumLeft < = 0 )
{
// All items fit
return a_ItemStack . m_ItemCount ;
}
} // for i - m_Slots[]
return a_ItemStack . m_ItemCount - NumLeft ;
2012-06-14 09:06:06 -04:00
}
2018-07-26 17:24:36 -04:00
2015-05-18 09:30:16 -04:00
int cInventory : : AddItem ( const cItem & a_Item , bool a_AllowNewStacks )
2012-10-24 08:48:25 -04:00
{
2020-07-14 12:56:42 -04:00
m_Owner . AddKnownItem ( a_Item ) ;
2013-05-24 03:30:39 -04:00
cItem ToAdd ( a_Item ) ;
int res = 0 ;
2012-10-24 08:48:25 -04:00
2014-07-19 19:22:58 -04:00
// When the item is a armor, try to set it directly to the armor slot.
if ( ItemCategory : : IsArmor ( a_Item . m_ItemType ) )
{
2014-08-25 11:25:39 -04:00
for ( int i = 0 ; i < m_ArmorSlots . GetNumSlots ( ) ; i + + )
2014-07-19 19:22:58 -04:00
{
if ( m_ArmorSlots . GetSlot ( i ) . IsEmpty ( ) & & cSlotAreaArmor : : CanPlaceArmorInSlot ( i , a_Item ) )
{
m_ArmorSlots . SetSlot ( i , a_Item ) ;
return a_Item . m_ItemCount ;
}
}
}
2020-04-02 08:42:15 -04:00
// Add to existing stacks in the hotbar.
res + = m_HotbarSlots . AddItem ( ToAdd , false ) ;
ToAdd . m_ItemCount = static_cast < char > ( a_Item . m_ItemCount - res ) ;
if ( ToAdd . m_ItemCount = = 0 )
2015-05-18 09:30:16 -04:00
{
2020-04-02 08:42:15 -04:00
return res ;
}
2015-05-18 09:30:16 -04:00
2020-04-02 08:42:15 -04:00
// Add to existing stacks in main inventory.
res + = m_InventorySlots . AddItem ( ToAdd , false ) ;
ToAdd . m_ItemCount = static_cast < char > ( a_Item . m_ItemCount - res ) ;
if ( ToAdd . m_ItemCount = = 0 )
{
return res ;
}
2015-05-18 09:30:16 -04:00
2020-04-02 08:42:15 -04:00
// All existing stacks are now filled.
if ( ! a_AllowNewStacks )
{
return res ;
2015-05-18 09:30:16 -04:00
}
2020-04-02 08:42:15 -04:00
// Try adding new stacks to the hotbar.
res + = m_HotbarSlots . AddItem ( ToAdd , true ) ;
2015-07-29 11:04:03 -04:00
ToAdd . m_ItemCount = static_cast < char > ( a_Item . m_ItemCount - res ) ;
2013-05-24 03:30:39 -04:00
if ( ToAdd . m_ItemCount = = 0 )
{
return res ;
}
2016-02-05 16:45:45 -05:00
2020-04-02 08:42:15 -04:00
// Try adding new stacks to the main inventory.
res + = m_InventorySlots . AddItem ( ToAdd , true ) ;
2013-05-24 03:30:39 -04:00
return res ;
2012-10-24 08:48:25 -04:00
}
2015-05-18 09:30:16 -04:00
int cInventory : : AddItems ( cItems & a_ItemStackList , bool a_AllowNewStacks )
2012-06-14 09:06:06 -04:00
{
2013-05-24 03:30:39 -04:00
int TotalAdded = 0 ;
for ( cItems : : iterator itr = a_ItemStackList . begin ( ) ; itr ! = a_ItemStackList . end ( ) ; )
2012-06-14 09:06:06 -04:00
{
2015-05-18 09:30:16 -04:00
int NumAdded = AddItem ( * itr , a_AllowNewStacks ) ;
2013-05-24 03:30:39 -04:00
if ( itr - > m_ItemCount = = NumAdded )
2012-06-14 09:06:06 -04:00
{
2013-05-24 03:30:39 -04:00
itr = a_ItemStackList . erase ( itr ) ;
2012-06-14 09:06:06 -04:00
}
2013-05-24 03:30:39 -04:00
else
2012-06-14 09:06:06 -04:00
{
2013-05-24 03:30:39 -04:00
itr - > m_ItemCount - = NumAdded ;
+ + itr ;
2012-06-14 09:06:06 -04:00
}
2013-05-24 03:30:39 -04:00
TotalAdded + = NumAdded ;
2012-06-14 09:06:06 -04:00
}
2013-05-24 03:30:39 -04:00
return TotalAdded ;
2012-06-14 09:06:06 -04:00
}
2014-07-18 17:11:59 -04:00
int cInventory : : RemoveItem ( const cItem & a_ItemStack )
{
2017-05-24 02:09:58 -04:00
int RemovedItems = m_ShieldSlots . RemoveItem ( a_ItemStack ) ;
if ( RemovedItems < a_ItemStack . m_ItemCount )
{
RemovedItems + = m_HotbarSlots . RemoveItem ( a_ItemStack ) ;
}
2014-07-18 17:11:59 -04:00
if ( RemovedItems < a_ItemStack . m_ItemCount )
{
cItem Temp ( a_ItemStack ) ;
Temp . m_ItemCount - = RemovedItems ;
RemovedItems + = m_InventorySlots . RemoveItem ( Temp ) ;
}
return RemovedItems ;
}
2020-07-14 12:56:42 -04:00
cItem * cInventory : : FindItem ( const cItem & a_RecipeItem )
{
cItem * Item = m_ShieldSlots . FindItem ( a_RecipeItem ) ;
if ( Item ! = nullptr )
{
return Item ;
}
Item = m_HotbarSlots . FindItem ( a_RecipeItem ) ;
if ( Item ! = nullptr )
{
return Item ;
}
return m_InventorySlots . FindItem ( a_RecipeItem ) ;
}
2013-05-24 03:30:39 -04:00
bool cInventory : : RemoveOneEquippedItem ( void )
2012-06-14 09:06:06 -04:00
{
2013-05-24 03:30:39 -04:00
if ( m_HotbarSlots . GetSlot ( m_EquippedSlotNum ) . IsEmpty ( ) )
2013-05-19 14:22:37 -04:00
{
2013-05-24 03:30:39 -04:00
return false ;
2013-05-19 14:22:37 -04:00
}
2016-02-05 16:45:45 -05:00
2013-05-24 03:30:39 -04:00
m_HotbarSlots . ChangeSlotCount ( m_EquippedSlotNum , - 1 ) ;
return true ;
}
2020-04-02 08:42:15 -04:00
int cInventory : : ReplaceOneEquippedItem ( const cItem & a_Item , bool a_TryOtherSlots )
{
// Ignore whether there was an item in the slot to remove.
RemoveOneEquippedItem ( ) ;
auto EquippedItem = GetEquippedItem ( ) ;
if ( EquippedItem . IsEmpty ( ) )
{
SetEquippedItem ( a_Item ) ;
return a_Item . m_ItemCount ;
}
// Handle case when equipped item is the same as the replacement item.
cItem ItemsToAdd = a_Item ;
if ( EquippedItem . IsEqual ( ItemsToAdd ) )
{
cItemHandler Handler ( ItemsToAdd . m_ItemType ) ;
auto AmountToAdd = std : : min ( static_cast < char > ( Handler . GetMaxStackSize ( ) - EquippedItem . m_ItemCount ) , ItemsToAdd . m_ItemCount ) ;
EquippedItem . m_ItemCount + = AmountToAdd ;
SetEquippedItem ( EquippedItem ) ;
ItemsToAdd . m_ItemCount - = AmountToAdd ;
}
auto ItemsAdded = a_Item . m_ItemCount - ItemsToAdd . m_ItemCount ;
if ( ItemsToAdd . m_ItemCount = = 0 )
{
return ItemsAdded ;
}
if ( ! a_TryOtherSlots )
{
return ItemsAdded ;
}
// Try the rest of the inventory.
return AddItem ( ItemsToAdd ) + ItemsAdded ;
}
2013-05-24 03:30:39 -04:00
int cInventory : : HowManyItems ( const cItem & a_Item )
{
return
m_ArmorSlots . HowManyItems ( a_Item ) +
m_InventorySlots . HowManyItems ( a_Item ) +
2017-05-24 02:09:58 -04:00
m_HotbarSlots . HowManyItems ( a_Item ) +
m_ShieldSlots . HowManyItems ( a_Item ) ;
2013-05-24 03:30:39 -04:00
}
bool cInventory : : HasItems ( const cItem & a_ItemStack )
{
int CurrentlyHave = HowManyItems ( a_ItemStack ) ;
return ( CurrentlyHave > = a_ItemStack . m_ItemCount ) ;
2012-06-14 09:06:06 -04:00
}
2013-05-19 14:22:37 -04:00
void cInventory : : SetSlot ( int a_SlotNum , const cItem & a_Item )
2012-06-14 09:06:06 -04:00
{
2013-05-24 03:30:39 -04:00
if ( ( a_SlotNum < 0 ) | | ( a_SlotNum > = invNumSlots ) )
2012-06-14 09:06:06 -04:00
{
2013-05-24 03:30:39 -04:00
LOGWARNING ( " %s: requesting an invalid slot index: %d out of %d. Ignoring. " , __FUNCTION__ , a_SlotNum , invNumSlots - 1 ) ;
2013-05-19 14:22:37 -04:00
return ;
}
2013-05-24 03:30:39 -04:00
int GridSlotNum = 0 ;
cItemGrid * Grid = GetGridForSlotNum ( a_SlotNum , GridSlotNum ) ;
2014-10-20 16:55:07 -04:00
if ( Grid = = nullptr )
2013-05-19 14:22:37 -04:00
{
2013-05-24 03:30:39 -04:00
LOGWARNING ( " %s(%d): requesting an invalid itemgrid. Ignoring. " , __FUNCTION__ , a_SlotNum ) ;
return ;
2012-06-14 09:06:06 -04:00
}
2013-05-24 03:30:39 -04:00
Grid - > SetSlot ( GridSlotNum , a_Item ) ;
}
void cInventory : : SetArmorSlot ( int a_ArmorSlotNum , const cItem & a_Item )
{
m_ArmorSlots . SetSlot ( a_ArmorSlotNum , a_Item ) ;
2012-06-14 09:06:06 -04:00
}
2013-05-24 03:30:39 -04:00
void cInventory : : SetInventorySlot ( int a_InventorySlotNum , const cItem & a_Item )
2012-06-14 09:06:06 -04:00
{
2013-05-24 03:30:39 -04:00
m_InventorySlots . SetSlot ( a_InventorySlotNum , a_Item ) ;
}
void cInventory : : SetHotbarSlot ( int a_HotBarSlotNum , const cItem & a_Item )
{
m_HotbarSlots . SetSlot ( a_HotBarSlotNum , a_Item ) ;
2012-06-14 09:06:06 -04:00
}
2017-05-24 02:09:58 -04:00
void cInventory : : SetShieldSlot ( const cItem & a_Item )
{
m_ShieldSlots . SetSlot ( 0 , a_Item ) ;
}
2020-04-02 08:42:15 -04:00
void cInventory : : SetEquippedItem ( const cItem & a_Item )
{
SetHotbarSlot ( GetEquippedSlotNum ( ) , a_Item ) ;
}
2014-05-09 17:10:02 -04:00
void cInventory : : SendEquippedSlot ( )
{
int EquippedSlotNum = cInventory : : invArmorCount + cInventory : : invInventoryCount + GetEquippedSlotNum ( ) ;
SendSlot ( EquippedSlotNum ) ;
}
2013-05-19 14:22:37 -04:00
const cItem & cInventory : : GetSlot ( int a_SlotNum ) const
2012-06-14 09:06:06 -04:00
{
2013-05-24 03:30:39 -04:00
if ( ( a_SlotNum < 0 ) | | ( a_SlotNum > = invNumSlots ) )
2013-05-19 14:22:37 -04:00
{
2013-05-24 03:30:39 -04:00
LOGWARNING ( " %s: requesting an invalid slot index: %d out of %d. Returning the first inventory slot instead. " , __FUNCTION__ , a_SlotNum , invNumSlots - 1 ) ;
return m_InventorySlots . GetSlot ( 0 ) ;
2013-05-19 14:22:37 -04:00
}
2013-05-24 03:30:39 -04:00
int GridSlotNum = 0 ;
const cItemGrid * Grid = GetGridForSlotNum ( a_SlotNum , GridSlotNum ) ;
2014-10-20 16:55:07 -04:00
if ( Grid = = nullptr )
2013-05-24 03:30:39 -04:00
{
// Something went wrong, but we don't know what. We must return a value, so return the first inventory slot
LOGWARNING ( " %s(%d): requesting an invalid ItemGrid, returning the first inventory slot instead. " , __FUNCTION__ , a_SlotNum ) ;
return m_InventorySlots . GetSlot ( 0 ) ;
}
return Grid - > GetSlot ( GridSlotNum ) ;
}
const cItem & cInventory : : GetArmorSlot ( int a_ArmorSlotNum ) const
{
if ( ( a_ArmorSlotNum < 0 ) | | ( a_ArmorSlotNum > = invArmorCount ) )
{
LOGWARNING ( " %s: requesting an invalid slot index: %d out of %d. Returning the first one instead " , __FUNCTION__ , a_ArmorSlotNum , invArmorCount - 1 ) ;
return m_ArmorSlots . GetSlot ( 0 ) ;
}
return m_ArmorSlots . GetSlot ( a_ArmorSlotNum ) ;
2012-06-14 09:06:06 -04:00
}
2013-05-24 03:30:39 -04:00
const cItem & cInventory : : GetInventorySlot ( int a_InventorySlotNum ) const
2012-06-14 09:06:06 -04:00
{
2013-05-24 03:30:39 -04:00
if ( ( a_InventorySlotNum < 0 ) | | ( a_InventorySlotNum > = invInventoryCount ) )
2012-06-14 09:06:06 -04:00
{
2013-05-24 03:30:39 -04:00
LOGWARNING ( " %s: requesting an invalid slot index: %d out of %d. Returning the first one instead " , __FUNCTION__ , a_InventorySlotNum , invInventoryCount - 1 ) ;
return m_InventorySlots . GetSlot ( 0 ) ;
2012-06-14 09:06:06 -04:00
}
2013-05-24 03:30:39 -04:00
return m_InventorySlots . GetSlot ( a_InventorySlotNum ) ;
}
const cItem & cInventory : : GetHotbarSlot ( int a_SlotNum ) const
{
if ( ( a_SlotNum < 0 ) | | ( a_SlotNum > = invHotbarCount ) )
{
LOGWARNING ( " %s: requesting an invalid slot index: %d out of %d. Returning the first one instead " , __FUNCTION__ , a_SlotNum , invHotbarCount - 1 ) ;
return m_HotbarSlots . GetSlot ( 0 ) ;
}
return m_HotbarSlots . GetSlot ( a_SlotNum ) ;
2013-05-19 14:22:37 -04:00
}
2017-05-24 02:09:58 -04:00
const cItem & cInventory : : GetShieldSlot ( ) const
{
return m_ShieldSlots . GetSlot ( 0 ) ;
}
2013-05-19 14:22:37 -04:00
const cItem & cInventory : : GetEquippedItem ( void ) const
{
2013-05-24 03:30:39 -04:00
return GetHotbarSlot ( m_EquippedSlotNum ) ;
2012-06-14 09:06:06 -04:00
}
2013-05-19 14:22:37 -04:00
void cInventory : : SetEquippedSlotNum ( int a_SlotNum )
2012-06-14 09:06:06 -04:00
{
2013-05-24 03:30:39 -04:00
if ( ( a_SlotNum < 0 ) | | ( a_SlotNum > = invHotbarCount ) )
2012-09-20 09:25:54 -04:00
{
2013-05-24 03:30:39 -04:00
LOGWARNING ( " %s: requesting invalid slot index: %d out of %d. Setting 0 instead. " , __FUNCTION__ , a_SlotNum , invHotbarCount - 1 ) ;
2013-05-19 14:22:37 -04:00
m_EquippedSlotNum = 0 ;
2012-09-20 09:25:54 -04:00
}
else
{
2013-05-24 03:30:39 -04:00
m_EquippedSlotNum = a_SlotNum ;
2012-09-20 09:25:54 -04:00
}
2012-06-14 09:06:06 -04:00
}
2013-05-19 14:22:37 -04:00
bool cInventory : : DamageEquippedItem ( short a_Amount )
2012-06-14 09:06:06 -04:00
{
2013-05-24 03:30:39 -04:00
return DamageItem ( invHotbarOffset + m_EquippedSlotNum , a_Amount ) ;
2012-06-14 09:06:06 -04:00
}
2013-07-26 15:50:06 -04:00
int cInventory : : ChangeSlotCount ( int a_SlotNum , int a_AddToCount )
{
int GridSlotNum = 0 ;
cItemGrid * Grid = GetGridForSlotNum ( a_SlotNum , GridSlotNum ) ;
2014-10-20 16:55:07 -04:00
if ( Grid = = nullptr )
2013-07-26 15:50:06 -04:00
{
LOGWARNING ( " %s: invalid slot number, expected 0 .. %d, got %d; ignoring " , __FUNCTION__ , invNumSlots , a_SlotNum ) ;
return - 1 ;
}
return Grid - > ChangeSlotCount ( GridSlotNum , a_AddToCount ) ;
}
2013-05-19 14:22:37 -04:00
bool cInventory : : DamageItem ( int a_SlotNum , short a_Amount )
2012-08-24 03:58:26 -04:00
{
2013-05-24 03:30:39 -04:00
if ( ( a_SlotNum < 0 ) | | ( a_SlotNum > = invNumSlots ) )
2013-05-19 14:22:37 -04:00
{
2013-05-24 03:30:39 -04:00
LOGWARNING ( " %s: requesting an invalid slot index: %d out of %d " , __FUNCTION__ , a_SlotNum , invNumSlots - 1 ) ;
2013-05-19 14:22:37 -04:00
return false ;
}
2014-07-23 10:32:09 -04:00
if ( a_Amount < = 0 )
{
return false ;
}
2016-02-05 16:45:45 -05:00
2013-05-24 03:30:39 -04:00
int GridSlotNum = 0 ;
cItemGrid * Grid = GetGridForSlotNum ( a_SlotNum , GridSlotNum ) ;
2014-10-20 16:55:07 -04:00
if ( Grid = = nullptr )
2013-05-19 14:22:37 -04:00
{
2013-05-24 03:30:39 -04:00
LOGWARNING ( " %s(%d, %d): requesting an invalid grid, ignoring. " , __FUNCTION__ , a_SlotNum , a_Amount ) ;
return false ;
}
if ( ! Grid - > DamageItem ( GridSlotNum , a_Amount ) )
{
// The item has been damaged, but did not break yet
2014-05-07 14:59:25 -04:00
SendSlot ( a_SlotNum ) ;
2013-05-19 14:22:37 -04:00
return false ;
}
2016-02-05 16:45:45 -05:00
2013-05-19 14:22:37 -04:00
// The item has broken, remove it:
2013-10-18 12:01:19 -04:00
Grid - > EmptySlot ( GridSlotNum ) ;
2013-05-19 14:22:37 -04:00
return true ;
2012-08-24 03:58:26 -04:00
}
2013-05-24 03:30:39 -04:00
void cInventory : : CopyToItems ( cItems & a_Items )
{
m_ArmorSlots . CopyToItems ( a_Items ) ;
m_InventorySlots . CopyToItems ( a_Items ) ;
m_HotbarSlots . CopyToItems ( a_Items ) ;
}
2012-08-24 04:04:58 -04:00
void cInventory : : SendSlot ( int a_SlotNum )
2012-06-14 09:06:06 -04:00
{
2013-05-19 14:22:37 -04:00
cItem Item ( GetSlot ( a_SlotNum ) ) ;
if ( Item . IsEmpty ( ) )
2012-06-14 09:06:06 -04:00
{
2013-05-19 14:22:37 -04:00
// Sanitize items that are not completely empty (ie. count == 0, but type != empty)
Item . Empty ( ) ;
2012-06-14 09:06:06 -04:00
}
2015-07-29 11:04:03 -04:00
m_Owner . GetClientHandle ( ) - > SendInventorySlot ( 0 , static_cast < short > ( a_SlotNum + 5 ) , Item ) ; // Slots in the client are numbered "+ 5" because of crafting grid and result
2012-08-11 15:54:57 -04:00
}
2013-05-24 03:30:39 -04:00
/*
2012-08-19 07:51:17 -04:00
int cInventory : : MoveItem ( short a_ItemType , short a_ItemDamage , int a_Count , int a_BeginSlot , int a_EndSlot )
2012-08-11 15:54:57 -04:00
{
int res = 0 ;
for ( int i = a_BeginSlot ; i < = a_EndSlot ; i + + )
{
if (
m_Slots [ i ] . IsEmpty ( ) | |
2013-01-11 23:46:01 -05:00
( ( m_Slots [ i ] . m_ItemType = = a_ItemType ) & & ( m_Slots [ i ] . m_ItemDamage = = a_ItemDamage ) )
2012-08-11 15:54:57 -04:00
)
{
int MaxCount = ItemHandler ( a_ItemType ) - > GetMaxStackSize ( ) ;
ASSERT ( m_Slots [ i ] . m_ItemCount < = MaxCount ) ;
2012-08-14 04:33:09 -04:00
int NumToMove = std : : min ( a_Count , MaxCount - m_Slots [ i ] . m_ItemCount ) ;
2012-08-11 15:54:57 -04:00
m_Slots [ i ] . m_ItemCount + = NumToMove ;
2013-01-11 23:46:01 -05:00
m_Slots [ i ] . m_ItemDamage = a_ItemDamage ;
m_Slots [ i ] . m_ItemType = a_ItemType ;
2012-08-11 15:54:57 -04:00
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 ;
}
2013-05-24 03:30:39 -04:00
*/
2012-08-11 15:54:57 -04:00
2013-05-24 03:30:39 -04:00
int cInventory : : ArmorSlotNumToEntityEquipmentID ( short a_ArmorSlotNum )
2013-05-19 14:22:37 -04:00
{
2013-05-24 03:30:39 -04:00
switch ( a_ArmorSlotNum )
2013-05-19 14:22:37 -04:00
{
2013-05-24 03:30:39 -04:00
case 0 : return 4 ; // Helmet
case 1 : return 3 ; // Chestplate
case 2 : return 2 ; // Leggings
case 3 : return 1 ; // Boots
2013-05-19 14:22:37 -04:00
}
2013-05-24 03:30:39 -04:00
LOGWARN ( " %s: invalid armor slot number: %d " , __FUNCTION__ , a_ArmorSlotNum ) ;
2013-05-19 14:22:37 -04:00
return 0 ;
}
2013-05-24 03:30:39 -04:00
#if 0
2015-05-09 05:16:56 -04:00
bool cInventory : : AddToBar ( cItem & a_Item , const int a_Offset , const int a_Size , bool * a_bChangedSlots , int a_Mode /* = 0 */ )
2012-06-14 09:06:06 -04:00
{
// Fill already present stacks
2014-07-21 09:19:48 -04:00
if ( a_Mode < 2 )
2012-06-14 09:06:06 -04:00
{
2012-10-24 08:48:25 -04:00
int MaxStackSize = cItemHandler : : GetItemHandler ( a_Item . m_ItemType ) - > GetMaxStackSize ( ) ;
2014-07-20 17:10:31 -04:00
for ( int i = 0 ; i < a_Size ; i + + )
2012-06-14 09:06:06 -04:00
{
2014-12-05 06:56:53 -05:00
if (
( m_Slots [ i + a_Offset ] . m_ItemType = = a_Item . m_ItemType ) & &
( m_Slots [ i + a_Offset ] . m_ItemCount < MaxStackSize ) & &
( m_Slots [ i + a_Offset ] . m_ItemDamage = = a_Item . m_ItemDamage )
)
2012-06-14 09:06:06 -04:00
{
2012-10-24 08:48:25 -04:00
int NumFree = MaxStackSize - m_Slots [ i + a_Offset ] . m_ItemCount ;
2014-07-21 09:19:48 -04:00
if ( NumFree > = a_Item . m_ItemCount )
2012-06-14 09:06:06 -04:00
{
2014-07-21 09:19:48 -04:00
// printf("1. Adding %i items ( free: %i)\n", a_Item.m_ItemCount, NumFree);
2012-06-14 09:06:06 -04:00
m_Slots [ i + a_Offset ] . m_ItemCount + = a_Item . m_ItemCount ;
a_Item . m_ItemCount = 0 ;
a_bChangedSlots [ i + a_Offset ] = true ;
break ;
}
else
{
2014-07-21 09:19:48 -04:00
// printf("2. Adding %i items\n", NumFree);
2012-06-14 09:06:06 -04:00
m_Slots [ i + a_Offset ] . m_ItemCount + = ( char ) NumFree ;
a_Item . m_ItemCount - = ( char ) NumFree ;
a_bChangedSlots [ i + a_Offset ] = true ;
}
}
}
}
2014-07-21 09:19:48 -04:00
if ( a_Mode > 0 )
2012-06-14 09:06:06 -04:00
{
// If we got more left, find first empty slot
2014-12-05 06:56:53 -05:00
for ( int i = 0 ; ( i < a_Size ) & & ( a_Item . m_ItemCount > 0 ) ; i + + )
2012-06-14 09:06:06 -04:00
{
2014-07-21 09:19:48 -04:00
if ( m_Slots [ i + a_Offset ] . m_ItemType = = - 1 )
2012-06-14 09:06:06 -04:00
{
m_Slots [ i + a_Offset ] = a_Item ;
a_Item . m_ItemCount = 0 ;
a_bChangedSlots [ i + a_Offset ] = true ;
}
}
}
return true ;
}
2013-05-24 03:30:39 -04:00
# endif
2012-06-14 09:06:06 -04:00
2014-02-17 09:27:12 -05:00
void cInventory : : UpdateItems ( void )
{
const cItem & Slot = GetEquippedItem ( ) ;
2015-06-30 10:50:15 -04:00
if ( ! Slot . IsEmpty ( ) )
2014-02-17 09:27:12 -05:00
{
2015-06-30 10:50:15 -04:00
ItemHandler ( Slot . m_ItemType ) - > OnUpdate ( m_Owner . GetWorld ( ) , & m_Owner , Slot ) ;
2014-02-17 09:27:12 -05:00
}
}
2012-06-14 09:06:06 -04:00
void cInventory : : SaveToJson ( Json : : Value & a_Value )
{
2013-05-24 03:30:39 -04:00
// The JSON originally included the 4 crafting slots and the result, so we have to put empty items there, too:
cItem EmptyItem ;
Json : : Value EmptyItemJson ;
EmptyItem . GetJson ( EmptyItemJson ) ;
for ( int i = 0 ; i < 5 ; i + + )
{
a_Value . append ( EmptyItemJson ) ;
}
2016-02-05 16:45:45 -05:00
2013-05-24 03:30:39 -04:00
// The 4 armor slots follow:
for ( int i = 0 ; i < invArmorCount ; i + + )
2012-06-14 09:06:06 -04:00
{
Json : : Value JSON_Item ;
2013-05-24 03:30:39 -04:00
m_ArmorSlots . GetSlot ( i ) . GetJson ( JSON_Item ) ;
a_Value . append ( JSON_Item ) ;
}
// Next comes the main inventory:
for ( int i = 0 ; i < invInventoryCount ; i + + )
{
Json : : Value JSON_Item ;
m_InventorySlots . GetSlot ( i ) . GetJson ( JSON_Item ) ;
a_Value . append ( JSON_Item ) ;
}
2017-05-24 02:09:58 -04:00
// The hotbar:
2013-05-24 03:30:39 -04:00
for ( int i = 0 ; i < invHotbarCount ; i + + )
{
Json : : Value JSON_Item ;
m_HotbarSlots . GetSlot ( i ) . GetJson ( JSON_Item ) ;
a_Value . append ( JSON_Item ) ;
2012-06-14 09:06:06 -04:00
}
2017-05-24 02:09:58 -04:00
// Shield slot is the last
Json : : Value JSON_Item ;
m_ShieldSlots . GetSlot ( 0 ) . GetJson ( JSON_Item ) ;
a_Value . append ( JSON_Item ) ;
2012-06-14 09:06:06 -04:00
}
bool cInventory : : LoadFromJson ( Json : : Value & a_Value )
{
int SlotIdx = 0 ;
2016-02-05 16:45:45 -05:00
2013-05-24 03:30:39 -04:00
for ( Json : : Value : : iterator itr = a_Value . begin ( ) ; itr ! = a_Value . end ( ) ; + + itr , SlotIdx + + )
2012-06-14 09:06:06 -04:00
{
2013-05-24 03:30:39 -04:00
cItem Item ;
Item . FromJson ( * itr ) ;
2016-02-05 16:45:45 -05:00
2013-05-24 03:30:39 -04:00
// The JSON originally included the 4 crafting slots and the result slot, so we need to skip the first 5 items:
if ( SlotIdx < 5 )
{
continue ;
}
2016-02-05 16:45:45 -05:00
2013-05-24 03:30:39 -04:00
// If we loaded all the slots, stop now, even if the JSON has more:
if ( SlotIdx - 5 > = invNumSlots )
2013-05-19 14:22:37 -04:00
{
break ;
}
2016-02-05 16:45:45 -05:00
2013-05-24 03:30:39 -04:00
int GridSlotNum = 0 ;
cItemGrid * Grid = GetGridForSlotNum ( SlotIdx - 5 , GridSlotNum ) ;
2014-10-20 16:55:07 -04:00
ASSERT ( Grid ! = nullptr ) ;
2013-05-24 03:30:39 -04:00
Grid - > SetSlot ( GridSlotNum , Item ) ;
} // for itr - a_Value[]
2012-06-14 09:06:06 -04:00
return true ;
}
2013-05-24 03:30:39 -04:00
const cItemGrid * cInventory : : GetGridForSlotNum ( int a_SlotNum , int & a_GridSlotNum ) const
{
ASSERT ( a_SlotNum > = 0 ) ;
2016-02-05 16:45:45 -05:00
2013-05-24 03:30:39 -04:00
if ( a_SlotNum < invArmorCount )
{
a_GridSlotNum = a_SlotNum ;
return & m_ArmorSlots ;
}
a_SlotNum - = invArmorCount ;
if ( a_SlotNum < invInventoryCount )
{
a_GridSlotNum = a_SlotNum ;
return & m_InventorySlots ;
}
2017-05-24 02:09:58 -04:00
a_SlotNum - = invInventoryCount ;
if ( a_SlotNum < invHotbarCount )
{
a_GridSlotNum = a_SlotNum ;
return & m_HotbarSlots ;
}
a_GridSlotNum = a_SlotNum - invHotbarCount ;
return & m_ShieldSlots ;
2013-05-24 03:30:39 -04:00
}
cItemGrid * cInventory : : GetGridForSlotNum ( int a_SlotNum , int & a_GridSlotNum )
{
ASSERT ( a_SlotNum > = 0 ) ;
2016-02-05 16:45:45 -05:00
2013-05-24 03:30:39 -04:00
if ( a_SlotNum < invArmorCount )
{
a_GridSlotNum = a_SlotNum ;
return & m_ArmorSlots ;
}
a_SlotNum - = invArmorCount ;
if ( a_SlotNum < invInventoryCount )
{
a_GridSlotNum = a_SlotNum ;
return & m_InventorySlots ;
}
2017-05-24 02:09:58 -04:00
a_SlotNum - = invInventoryCount ;
if ( a_SlotNum < invHotbarCount )
{
a_GridSlotNum = a_SlotNum ;
return & m_HotbarSlots ;
}
a_GridSlotNum = a_SlotNum - invHotbarCount ;
return & m_ShieldSlots ;
2013-05-24 03:30:39 -04:00
}
void cInventory : : OnSlotChanged ( cItemGrid * a_ItemGrid , int a_SlotNum )
{
// Send the neccessary updates to whoever needs them
2016-02-05 16:45:45 -05:00
2016-02-07 12:07:14 -05:00
if ( ! m_Owner . IsTicking ( ) )
2013-05-24 03:30:39 -04:00
{
// Owner is not (yet) valid, skip for now
return ;
}
2016-02-05 16:45:45 -05:00
2013-05-24 03:30:39 -04:00
// Armor update needs broadcast to other players:
cWorld * World = m_Owner . GetWorld ( ) ;
2014-10-20 16:55:07 -04:00
if ( ( a_ItemGrid = = & m_ArmorSlots ) & & ( World ! = nullptr ) )
2013-05-24 03:30:39 -04:00
{
World - > BroadcastEntityEquipment (
2015-08-04 18:24:59 -04:00
m_Owner , static_cast < short > ( ArmorSlotNumToEntityEquipmentID ( static_cast < short > ( a_SlotNum ) ) ) ,
2013-05-24 03:30:39 -04:00
m_ArmorSlots . GetSlot ( a_SlotNum ) , m_Owner . GetClientHandle ( )
) ;
}
2014-07-23 10:32:09 -04:00
// Broadcast the Equipped Item, if the Slot is changed.
if ( ( a_ItemGrid = = & m_HotbarSlots ) & & ( m_EquippedSlotNum = = a_SlotNum ) )
{
m_Owner . GetWorld ( ) - > BroadcastEntityEquipment ( m_Owner , 0 , GetEquippedItem ( ) , m_Owner . GetClientHandle ( ) ) ;
}
2016-02-05 16:45:45 -05:00
2013-05-24 03:30:39 -04:00
// Convert the grid-local a_SlotNum to our global SlotNum:
int Base = 0 ;
if ( a_ItemGrid = = & m_ArmorSlots )
{
Base = invArmorOffset ;
}
else if ( a_ItemGrid = = & m_InventorySlots )
{
Base = invInventoryOffset ;
}
else if ( a_ItemGrid = = & m_HotbarSlots )
{
Base = invHotbarOffset ;
}
2017-12-21 11:01:24 -05:00
else if ( a_ItemGrid = = & m_ShieldSlots )
2017-12-21 06:55:23 -05:00
{
Base = invShieldOffset ;
}
2013-05-24 03:30:39 -04:00
else
{
ASSERT ( ! " Unknown ItemGrid calling OnSlotChanged() " ) ;
return ;
}
2016-02-05 16:45:45 -05:00
2013-05-24 03:30:39 -04:00
SendSlot ( Base + a_SlotNum ) ;
}