1
0
Fork 0
cuberite-2a/src/ItemGrid.h

204 lines
7.7 KiB
C
Raw Normal View History

// ItemGrid.h
// Declares the cItemGrid class representing a storage for items in a XY grid (chests, dispensers, inventory etc.)
#pragma once
#include "Item.h"
#include "LazyArray.h"
// tolua_begin
class cItemGrid
{
public:
// tolua_end
2016-02-05 21:45:45 +00:00
/** This class is used as a callback for when a slot changes */
class cListener
{
public:
virtual ~cListener() {}
2016-02-05 21:45:45 +00:00
/** Called whenever a slot changes */
virtual void OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) = 0;
} ;
typedef std::vector<cListener *> cListeners;
2016-02-05 21:45:45 +00:00
cItemGrid(int a_Width, int a_Height);
2016-02-05 21:45:45 +00:00
// tolua_begin
int GetWidth (void) const { return m_Width; }
int GetHeight (void) const { return m_Height; }
int GetNumSlots(void) const { return m_Slots.size(); }
2016-02-05 21:45:45 +00:00
/** Converts XY coords into slot number; returns -1 on invalid coords */
int GetSlotNum(int a_X, int a_Y) const;
2016-02-05 21:45:45 +00:00
// 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;
2017-06-15 13:32:33 +00:00
/** Copies all items from a_Src to this grid.
Doesn't copy the listeners. */
void CopyFrom(const cItemGrid & a_Src);
// tolua_begin
2016-02-05 21:45:45 +00:00
// 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;
2016-02-05 21:45:45 +00:00
// 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);
2016-02-05 21:45:45 +00:00
// 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);
2016-02-05 21:45:45 +00:00
/** Returns true if the specified slot is empty or the slot doesn't exist */
bool IsSlotEmpty(int a_SlotNum) const;
2016-02-05 21:45:45 +00:00
/** Returns true if the specified slot is empty or the slot doesn't exist */
bool IsSlotEmpty(int a_X, int a_Y) const;
2016-02-05 21:45:45 +00:00
/** Sets all items as empty */
void Clear(void);
2016-02-05 21:45:45 +00:00
/** Returns number of items out of a_ItemStack that can fit in the storage */
int HowManyCanFit(const cItem & a_ItemStack, bool a_AllowNewStacks = true);
2016-02-05 21:45:45 +00:00
/** 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;
2016-07-06 10:39:56 +00:00
If a_AllowNewStacks is set to true, empty slots can be used for the rest.
If a_PrioritySlot is set to a positive value, then the corresponding slot will be used first (if empty or compatible with added items).
If a_PrioritySlot is set to -1, regular order applies.
Returns the number of items that fit.
*/
int AddItem(cItem & a_ItemStack, bool a_AllowNewStacks = true, int a_PrioritySlot = -1);
2016-02-05 21:45:45 +00:00
/** 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;
2016-07-06 10:39:56 +00:00
If a_AllowNewStacks is set to true, empty slots can be used for the rest.
If a_PrioritySlot is set to a positive value, then the corresponding slot will be used first (if empty or compatible with added items).
If a_PrioritySlot is set to -1, regular order applies.
Returns the total number of items that fit.
*/
int AddItems(cItems & a_ItemStackList, bool a_AllowNewStacks = true, int a_PrioritySlot = -1);
2014-07-18 21:47:46 +00:00
/** 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);
2016-02-05 21:45:45 +00:00
Introduce recipe book functionality (#4493) * Introduce recipe book functionality The recipe book helps especially new players. Missing it gives the impression that cuberite is not as advanced as it is. The handling of the recipe book uses the following functions: - Unlock Recipes (https://wiki.vg/index.php?title=Protocol&oldid=14204#Unlock_Recipes) to make recipes available and show the notification for new recipes. Initialization is done on player login for known ones, the update is done when new items are discovered. - Craft Recipe Request (https://wiki.vg/index.php?title=Protocol&oldid=14204#Craft_Recipe_Request) when the user selects a recipe from the recipe book to fill the slots. Known recipes are initialized on player login via `Unlock Recipes` with `Action` 0. As soon as a new recipe is discovered this is added via `Unlock Recipes` with `Action` 1. To be able to know and recognize new recipes the player class is extended with `KnownItems` and `KnownRecipes`. As soon as a player touches an item this is compared to the list of `KnownItems`, if the item is unknown the recipes are checked for this item and the other ingredients are checked with the list of `KnownItems`. If a full match is discovered the recipe is unlocked with the client and stored in the `KnownRecipes`. To unlock recipes the recipe ID is sent to the client. A mapping file (for protocol 1.12.2) translated the minecraft recipe names to ids. The crafting.txt is extended with and minecraft recipe names is possible. Limitations: Only a single recipe is added to the crafting area. Multiple clicks or shift click does not increase the number of builds. Co-authored-by: peterbell10 <peterbell10@live.co.uk> * Address first issues mentioned by @peterbell10 - Some linting - Extract loading of recipe specific protocol mapping into a function - Build `RecipeNameMap` only once - Use `std::optional` - Extract `LoadRecipe` from `Window` * Start to implement new suggestions * Update with suggestions from @peterbell10 * Some minor cleanup * Update protocol packet IDs * Remove unused include * Include header in cmake * Change a vector to integer counter * Change dromedaryCase method names to PascalCase * Address suggestions from @madmaxoft * Read Protocol subdirectories to load recipe books To load all recipebooks iterate over the `Protocol` subdirectories to find mapping files. Co-authored-by: peterbell10 <peterbell10@live.co.uk>
2020-07-14 16:56:42 +00:00
/** Finds an item based on ItemType and ItemDamage (<- defines the itemType, too) */
cItem * FindItem(const cItem & a_RecipeItem);
/** 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);
2016-02-05 21:45:45 +00:00
/** 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);
2016-02-05 21:45:45 +00:00
/** 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);
2016-02-05 21:45:45 +00:00
/** 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);
2016-02-05 21:45:45 +00:00
/** Returns the number of items of type a_Item that are stored */
int HowManyItems(const cItem & a_Item);
2016-02-05 21:45:45 +00:00
/** Returns true if there are at least as many items of type a_ItemStack as in a_ItemStack */
bool HasItems(const cItem & a_ItemStack);
2016-02-05 21:45:45 +00:00
/** 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;
2016-02-05 21:45:45 +00:00
/** 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;
2016-02-05 21:45:45 +00:00
/** Returns the index of the first used slot following a_StartFrom (a_StartFrom is not checked) */
int GetNextUsedSlot(int a_StartFrom) const;
2016-02-05 21:45:45 +00:00
/** 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);
2016-02-05 21:45:45 +00:00
/** 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);
2016-02-05 21:45:45 +00:00
// tolua_end
2016-02-05 21:45:45 +00:00
2017-07-09 20:54:56 +00:00
/** Returns true if slot coordinates lie within the grid. */
bool IsValidSlotCoords(int a_X, int a_Y) const;
/** Returns true if slot number is within the grid. */
bool IsValidSlotNum(int a_SlotNum) const;
/** 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
*/
2013-12-22 14:33:43 +00:00
void GenerateRandomLootWithBooks(const cLootProbab * a_LootProbabs, size_t a_CountLootProbabs, int a_NumSlots, int a_Seed);
2016-02-05 21:45:45 +00:00
/** Adds a callback that gets called whenever a slot changes. Must not be called from within the listener callback! */
void AddListener(cListener & a_Listener);
2016-02-05 21:45:45 +00:00
/** 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;
cLazyArray<cItem> m_Slots;
2016-02-05 21:45:45 +00:00
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
2016-02-05 21:45:45 +00:00
/** 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