summaryrefslogblamecommitdiffstats
path: root/src/ItemGrid.h
blob: 8d6544792be7ee29afb2219358ef7a3c44006a04 (plain) (tree)





















                                                                                                                  
                                                                       


                       


                                                     












                                                                                      
                                                                                



                                               
                                                                                                                            

















                                                                                                                       
                                                                                    

                                              
                                                                                    

                                                 
                                      

                         
                                                                                     
                                                                                   




















                                                                                                        
 

                                                                                                         
                                                  






















                                                                                                         
                                                                         

                                               
                                                                                                     

                                                 
                                                                        

                                          
                                                                             

                                         
                                                                       

                                         
                                                                       

                                        
                                                                                                           

                                                    
                                                                                                          

                                                   
                                                                                                

                                                 
                                                                                                                            

                                                       
                                                                                                                            








                                                                                                                                                           
                                                                                                                                   
        
                                                                                                                              

                                                 
                                                                                                    













                                                                                                                                                                      
                                                                  










                                                                                            

// ItemGrid.h

// Declares the cItemGrid class representing a storage for items in a XY grid (chests, dispensers, inventory etc.)




#pragma once

#include "Item.h"





// tolua_begin
class cItemGrid
{
public:
	// tolua_end
	
	/** This class is used as a callback for when a slot changes */
	class cListener
	{
	public:
		virtual ~cListener() {}
		
		/** Called whenever a slot changes */
		virtual void OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) = 0;
	} ;
	typedef std::vector<cListener *> cListeners;
	
	cItemGrid(int a_Width, int a_Height);
	
	~cItemGrid();
	
	// tolua_begin
	int GetWidth   (void) const { return m_Width; }
	int GetHeight  (void) const { return m_Height; }
	int GetNumSlots(void) const { return m_NumSlots; }
	
	/** Converts XY coords into slot number; returns -1 on invalid coords */
	int GetSlotNum(int a_X, int a_Y) const;
	
	// tolua_end

	/** Converts slot number into XY coords; sets coords to -1 on invalid slot number. Exported in ManualBindings.cpp */
	void GetSlotCoords(int a_SlotNum, int & a_X, int & a_Y) const;

	// tolua_begin
	
	// Retrieve slots by coords or slot number; Logs warning and returns the first slot on invalid coords / slotnum
	const cItem & GetSlot(int a_X, int a_Y) const;
	const cItem & GetSlot(int a_SlotNum) const;
	
	// Set slot by coords or slot number; Logs warning and doesn't set on invalid coords / slotnum
	void SetSlot(int a_X, int a_Y, const cItem & a_Item);
	void SetSlot(int a_X, int a_Y, short a_ItemType, char a_ItemCount, short a_ItemDamage);
	void SetSlot(int a_SlotNum, const cItem & a_Item);
	void SetSlot(int a_SlotNum, short a_ItemType, char a_ItemCount, short a_ItemDamage);
	
	// Empty the specified slot; Logs warning and doesn't set on invalid coords / slotnum
	void EmptySlot(int a_X, int a_Y);
	void EmptySlot(int a_SlotNum);
	
	/** Returns true if the specified slot is empty or the slot doesn't exist */
	bool IsSlotEmpty(int a_SlotNum) const;
	
	/** Returns true if the specified slot is empty or the slot doesn't exist */
	bool IsSlotEmpty(int a_X, int a_Y) const;
	
	/** Sets all items as empty */
	void Clear(void);
	
	/** Returns number of items out of a_ItemStack that can fit in the storage */
	int HowManyCanFit(const cItem & a_ItemStack, bool a_AllowNewStacks = true);
	
	/** Adds as many items out of a_ItemStack as can fit.
	If a_AllowNewStacks is set to false, only existing stacks can be topped up;
	if a_AllowNewStacks is set to true, empty slots can be used for the rest.
	If a_PrioritarySlot is set to a positive value, then the corresponding slot will be used in
	first (if empty or compatible with added items)
	if a_PrioritarySlot is set to -1, regular order apply
	Returns the number of items that fit.
	*/
	int AddItem(cItem & a_ItemStack, bool a_AllowNewStacks = true, int a_PrioritarySlot = -1);
	
	/** Same as AddItem, but works on an entire list of item stacks.
	The a_ItemStackList is modified to reflect the leftover items.
	If a_AllowNewStacks is set to false, only existing stacks can be topped up;
	if a_AllowNewStacks is set to true, empty slots can be used for the rest.
	If a_PrioritarySlot is set to a positive value, then the corresponding slot will be used in
	first (if empty or compatible with added items)
	if a_PrioritarySlot is set to -1, regular order apply
	Returns the total number of items that fit.
	*/
	int AddItems(cItems & a_ItemStackList, bool a_AllowNewStacks = true, int a_PrioritarySlot = -1);

	/** Removes the specified item from the grid, as many as possible, up to a_ItemStack.m_ItemCount.
	Returns the number of items that were removed. */
	int RemoveItem(const cItem & a_ItemStack);
	
	/** Adds (or subtracts, if a_AddToCount is negative) to the count of items in the specified slot.
	If the slot is empty, ignores the call.
	Returns the new count.
	*/
	int ChangeSlotCount(int a_SlotNum, int a_AddToCount);
	
	/** Adds (or subtracts, if a_AddToCount is negative) to the count of items in the specified slot.
	If the slot is empty, ignores the call.
	Returns the new count.
	*/
	int ChangeSlotCount(int a_X, int a_Y, int a_AddToCount);
	
	/** Removes one item from the stack in the specified slot, and returns it.
	If the slot was empty, returns an empty item
	*/
	cItem RemoveOneItem(int a_SlotNum);
	
	/** Removes one item from the stack in the specified slot, and returns it.
	If the slot was empty, returns an empty item
	*/
	cItem RemoveOneItem(int a_X, int a_Y);
	
	/** Returns the number of items of type a_Item that are stored */
	int HowManyItems(const cItem & a_Item);
	
	/** Returns true if there are at least as many items of type a_ItemStack as in a_ItemStack */
	bool HasItems(const cItem & a_ItemStack);
	
	/** Returns the index of the first empty slot; -1 if all full */
	int GetFirstEmptySlot(void) const;

	/** Returns the index of the first non-empty slot; -1 if all empty */
	int GetFirstUsedSlot(void) const;

	/** Returns the index of the last empty slot; -1 if all full */
	int GetLastEmptySlot(void) const;
	
	/** Returns the index of the last used slot; -1 if all empty */
	int GetLastUsedSlot(void) const;

	/** Returns the index of the first empty slot following a_StartFrom (a_StartFrom is not checked) */
	int GetNextEmptySlot(int a_StartFrom) const;
	
	/** Returns the index of the first used slot following a_StartFrom (a_StartFrom is not checked) */
	int GetNextUsedSlot(int a_StartFrom) const;
	
	/** Copies the contents into a cItems object; preserves the original a_Items contents */
	void CopyToItems(cItems & a_Items) const;

	/** Adds the specified damage to the specified item; returns true if the item broke (but the item is left intact) */
	bool DamageItem(int a_SlotNum, short a_Amount);
	
	/** Adds the specified damage to the specified item; returns true if the item broke (but the item is left intact) */
	bool DamageItem(int a_X, int a_Y, short a_Amount);
	
	// tolua_end
	
	
	/** Generates random loot from the specified loot probability table, with a chance of enchanted books added.
	A total of a_NumSlots are taken by the loot.
	Cannot export to Lua due to raw array a_LootProbabs. TODO: Make this exportable / export through ManualBindings.cpp with a Lua table as LootProbabs
	*/
	void GenerateRandomLootWithBooks(const cLootProbab * a_LootProbabs, size_t a_CountLootProbabs, int a_NumSlots, int a_Seed);
	
	/** Adds a callback that gets called whenever a slot changes. Must not be called from within the listener callback! */
	void AddListener(cListener & a_Listener);
	
	/** Removes a slot-change-callback. Must not be called from within the listener callback! */
	void RemoveListener(cListener & a_Listener);

	// tolua_begin

protected:
	int     m_Width;
	int     m_Height;
	int     m_NumSlots;  // m_Width * m_Height, for easier validity checking in the access functions
	cItem * m_Slots;     // x + m_Width * y
	
	cListeners       m_Listeners;    ///< Listeners which should be notified on slot changes; the pointers are not owned by this object
	cCriticalSection m_CSListeners;  ///< CS that guards the m_Listeners against multi-thread access
	bool             m_IsInTriggerListeners;  ///< Set to true while TriggerListeners is running, to detect attempts to manipulate listener list while triggerring
	
	/** Calls all m_Listeners for the specified slot number */
	void TriggerListeners(int a_SlotNum);

	/** Adds up to a_Num items out of a_ItemStack, as many as can fit, in specified slot
	Returns the number of items that did fit.
	*/
	int AddItemToSlot(const cItem & a_ItemStack, int a_Slot, int a_Num, int a_MaxStack);
} ;
// tolua_end