7 #include "../ClientHandle.h"
8 #include "../Entities/Player.h"
9 #include "../Entities/Pickup.h"
10 #include "../Inventory.h"
11 #include "../Items/ItemHandler.h"
12 #include "../BlockEntities/BeaconEntity.h"
13 #include "../BlockEntities/ChestEntity.h"
14 #include "../BlockEntities/DropSpenserEntity.h"
15 #include "../BlockEntities/EnderChestEntity.h"
16 #include "../BlockEntities/HopperEntity.h"
17 #include "../Entities/Minecart.h"
19 #include "../Bindings/PluginManager.h"
31 m_WindowID(((++m_WindowIDCounter) % 127) + 1),
32 m_WindowType(a_WindowType),
33 m_WindowTitle(a_WindowTitle),
66 case wtChest:
return "minecraft:chest";
67 case wtWorkbench:
return "minecraft:crafting_table";
68 case wtFurnace:
return "minecraft:furnace";
71 case wtBrewery:
return "minecraft:brewing_stand";
73 case wtBeacon:
return "minecraft:beacon";
74 case wtAnvil:
return "minecraft:anvil";
75 case wtHopper:
return "minecraft:hopper";
76 case wtDropper:
return "minecraft:dropper";
80 ASSERT(!
"Unknown inventory type!");
95 res += itr->GetNumSlots();
107 int LocalSlotNum = 0;
111 LOGWARNING(
"%s: requesting item from an invalid SlotArea (SlotNum %d), returning nullptr.", __FUNCTION__, a_SlotNum);
114 return Area->
GetSlot(LocalSlotNum, a_Player);
124 int LocalSlotNum = 0;
128 LOGWARNING(
"%s: requesting write to an invalid SlotArea (SlotNum %d), ignoring.", __FUNCTION__, a_SlotNum);
131 Area->
SetSlot(LocalSlotNum, a_Player, a_Item);
174 a_Slots.reserve(
static_cast<size_t>(
GetNumSlots()));
177 int NumSlots = (*itr)->GetNumSlots();
178 for (
int i = 0; i < NumSlots; i++)
180 const cItem *
Item = (*itr)->GetSlot(i, a_Player);
183 a_Slots.push_back(
cItem());
187 a_Slots.push_back(*
Item);
199 int a_WindowID,
short a_SlotNum,
eClickAction a_ClickAction,
200 const cItem & a_ClickedItem
206 LOGWARNING(
"%s: Wrong window ID (exp %d, got %d) received from \"%s\"; ignoring click.", __FUNCTION__,
m_WindowID, a_WindowID, a_Player.
GetName().c_str());
210 switch (a_ClickAction)
264 int LocalSlotNum = a_SlotNum;
269 itr->Clicked(a_Player, LocalSlotNum, a_ClickAction, a_ClickedItem);
272 LocalSlotNum -= itr->GetNumSlots();
275 LOGWARNING(
"Slot number higher than available window slots: %d, max %d received from \"%s\"; ignoring.",
295 (*itr)->OnPlayerAdded(a_Player);
311 LOGD(
"Player is holding an item while closing their window, dropping it as a pickup...");
316 if (ClientHandle !=
nullptr)
326 (*itr)->OnPlayerRemoved(a_Player);
354 bool HasFound =
false;
359 SlotNum += a_LocalSlotNum;
363 SlotNum += (*itr)->GetNumSlots();
367 LOGWARNING(
"%s: Invalid slot area parameter", __FUNCTION__);
368 ASSERT(!
"Invalid slot area");
376 (*itr)->GetClientHandle()->SendInventorySlot(
m_WindowID,
static_cast<short>(SlotNum), *a_Area->
GetSlot(a_LocalSlotNum, **itr));
411 Player->GetClientHandle()->SendWindowProperty(*
this, a_Property, a_Value);
438 if (a_Callback(*Player))
455 if (a_Callback(*Player->GetClientHandle()))
472 for (
size_t Pass = 0; Pass < 2; Pass++)
474 for (
auto SlotArea : a_AreasInOrder)
476 SlotArea->DistributeStack(a_ItemStack, a_Player, a_ShouldApply, (Pass == 0), a_BackFill);
495 if (Area->CollectItemsToHand(a_Dragging, a_Player, a_CollectFullStacks))
513 if (*itr == a_SlotArea)
518 SlotBase += (*itr)->GetNumSlots();
522 LOGERROR(
"cWindow::SendSlot(): unknown a_SlotArea");
523 ASSERT(!
"cWindow::SendSlot(): unknown a_SlotArea");
528 m_WindowID,
static_cast<short>(a_RelativeSlotNum + SlotBase), *(a_SlotArea->
GetSlot(a_RelativeSlotNum, a_Player))
552 if ((a_GlobalSlotNum < 0) || (a_GlobalSlotNum >=
GetNumSlots()))
554 LOGWARNING(
"%s: requesting an invalid SlotNum: %d out of %d slots", __FUNCTION__, a_GlobalSlotNum,
GetNumSlots() - 1);
555 ASSERT(!
"Invalid SlotNum");
560 int LocalSlotNum = a_GlobalSlotNum;
563 if (LocalSlotNum < (*itr)->GetNumSlots())
565 a_LocalSlotNum = LocalSlotNum;
568 LocalSlotNum -= (*itr)->GetNumSlots();
572 LOGWARNING(
"%s: GetNumSlots() is out of sync: %d; LocalSlotNum = %d", __FUNCTION__,
GetNumSlots(), LocalSlotNum);
573 ASSERT(!
"Invalid GetNumSlots");
583 if ((a_GlobalSlotNum < 0) || (a_GlobalSlotNum >=
GetNumSlots()))
585 LOGWARNING(
"%s: requesting an invalid SlotNum: %d out of %d slots", __FUNCTION__, a_GlobalSlotNum,
GetNumSlots() - 1);
586 ASSERT(!
"Invalid SlotNum");
591 int LocalSlotNum = a_GlobalSlotNum;
594 if (LocalSlotNum < (*itr)->GetNumSlots())
596 a_LocalSlotNum = LocalSlotNum;
599 LocalSlotNum -= (*itr)->GetNumSlots();
603 LOGWARNING(
"%s: GetNumSlots() is out of sync: %d; LocalSlotNum = %d", __FUNCTION__,
GetNumSlots(), LocalSlotNum);
604 ASSERT(!
"Invalid GetNumSlots");
639 char ToEachSlot = ToDistribute.
m_ItemCount /
static_cast<char>(SlotNums.size());
715 if (a_LimitItems && (
static_cast<size_t>(a_Item.
m_ItemCount) < a_SlotNums.size()))
717 LOGWARNING(
"%s: Distributing less items (%d) than slots (%zu)", __FUNCTION__,
static_cast<int>(a_Item.
m_ItemCount), a_SlotNums.size());
723 char NumDistributed = 0;
724 for (cSlotNums::const_iterator itr = a_SlotNums.begin(), end = a_SlotNums.end(); itr != end; ++itr)
726 int LocalSlotNum = 0;
730 LOGWARNING(
"%s: Bad SlotArea for slot %d", __FUNCTION__, *itr);
740 cItem ToStore(a_Item);
741 ToStore.
m_ItemCount = std::min<char>(a_NumToEachSlot, MaxStack);
742 Area->
SetSlot(LocalSlotNum, a_Player, ToStore);
745 else if (AtSlot.
IsEqual(a_Item))
748 char CanStore = std::min<char>(a_NumToEachSlot, MaxStack - AtSlot.
m_ItemCount);
750 Area->
SetSlot(LocalSlotNum, a_Player, AtSlot);
751 NumDistributed += CanStore;
754 return NumDistributed;
eClickAction
Individual actions sent in the WindowClick packet.
@ caLeftClickOutsideHoldNothing
@ caRightClickOutsideHoldNothing
std::vector< int > cSlotNums
List of slot numbers, used for inventory-painting.
void LOGERROR(std::string_view a_Format, const Args &... args)
void LOGWARNING(std::string_view a_Format, const Args &... args)
std::vector< cSlotArea * > cSlotAreas
bool CallHookPlayerTossingItem(cPlayer &a_Player)
void SendInventorySlot(char a_WindowID, short a_SlotNum, const cItem &a_Item)
void SendWindowOpen(const cWindow &a_Window)
void SendWindowClose(const cWindow &a_Window)
void SendWholeInventory(const cWindow &a_Window)
cClientHandle * GetClientHandle(void) const
const AString & GetName(void) const
const cSlotNums & GetInventoryPaintSlots(void) const
Returns the list of slots currently stored for inventory painting.
void ClearInventoryPaintSlots(void)
Clears the list of slots that are being inventory-painted.
void AddInventoryPaintSlot(int a_SlotNum)
Adds a slot to the list for inventory painting.
void TossPickup(const cItem &a_Item)
tosses a pickup newly created from a_Item
bool IsGameModeCreative(void) const
Returns true if the player is in Creative mode, either explicitly, or by inheriting from current worl...
void TossHeldItem(char a_Amount=1)
tosses the item held in hand (when in UI windows)
cItem & GetDraggingItem(void)
In UI windows, get the item that the player is dragging.
char GetMaxStackSize(void) const
Returns the maximum amount of stacked items of this type.
bool IsEmpty(void) const
Returns true if the item represents an empty stack - either the type is invalid, or count is zero.
bool IsEqual(const cItem &a_Item) const
void Empty(void)
Empties the item and frees up any dynamic storage used by the internals.
This class bridges a vector of cItem for safe access via Lua.
RAII for cCriticalSection - locks the CS on creation, unlocks on destruction.
cPluginManager * GetPluginManager(void)
virtual void SetSlot(int a_SlotNum, cPlayer &a_Player, const cItem &a_Item)=0
Called to set an item in the specified slot for the specified player.
virtual const cItem * GetSlot(int a_SlotNum, cPlayer &a_Player) const =0
Called to retrieve an item in the specified slot for the specified player.
virtual void OpenedByPlayer(cPlayer &a_Player)
void OnPaintBegin(cPlayer &a_Player)
Prepares the internal structures for inventory painting from the specified player.
virtual void SetProperty(size_t a_Property, short a_Value)
Updates a numerical property associated with the window.
virtual bool ClosedByPlayer(cPlayer &a_Player, bool a_CanRefuse)
Called when a player closes this window; notifies all slot areas.
void SetSlot(cPlayer &a_Player, int a_SlotNum, const cItem &a_Item)
Sets the item to the specified slot for the specified player.
void OnLeftPaintEnd(cPlayer &a_Player)
Processes the entire action stored in the internal structures for inventory painting; distributes as ...
static Byte m_WindowIDCounter
void BroadcastWholeWindow(void)
Sends the contents of the whole window to all clients of this window.
char DistributeItemToSlots(cPlayer &a_Player, const cItem &a_Item, char a_NumToEachSlot, const cSlotNums &a_SlotNums, bool a_LimitItems=true)
Distributes a_NumToEachSlot items into the slots specified in a_SlotNums; returns the total number of...
const cItem * GetSlot(cPlayer &a_Player, int a_SlotNum) const
Returns the item at the specified slot for the specified player.
void GetSlots(cPlayer &a_Player, cItems &a_Slots) const
Fills a_Slots with the slots read from m_SlotAreas[], for the specified player.
bool CollectItemsToHand(cItem &a_Dragging, cSlotArea &a_Area, cPlayer &a_Player, bool a_CollectFullStacks)
Called on DblClicking to collect all stackable items from all areas into hand.
bool ForEachPlayer(cPlayerListCallback a_Callback)
Calls the callback safely for each player that has this window open; returns true if all players have...
int GetNumSlots(void) const
Returns the total number of slots.
void OnMiddlePaintEnd(cPlayer &a_Player)
Processes the entire action stored in the internal structures for inventory painting; distributes a f...
bool IsSlotInPlayerHotbar(int a_SlotNum) const
Returns true if the specified slot is in the Player Hotbar slotarea.
bool ForEachClient(cClientHandleCallback a_Callback)
Calls the callback safely for each client that has this window open; returns true if all clients have...
bool IsSlotInPlayerMainInventory(int a_SlotNum) const
Returns true if the specified slot is in the Player Main Inventory slotarea.
void OwnerDestroyed(void)
void SendSlot(cPlayer &a_Player, cSlotArea *a_SlotArea, int a_RelativeSlotNum)
Used by cSlotAreas to send individual slots to clients, a_RelativeSlotNum is the slot number relative...
cSlotArea * GetSlotArea(int a_GlobalSlotNum, int &a_LocalSlotNum)
Returns the correct slot area for the specified window-global SlotNum Also returns the area-local Slo...
virtual void Destroy(void)
Sets the internal flag as "destroyed"; notifies the owner that the window is destroying.
virtual void Clicked(cPlayer &a_Player, int a_WindowID, short a_SlotNum, eClickAction a_ClickAction, const cItem &a_ClickedItem)
Handles a click event from a player.
void OnRightPaintEnd(cPlayer &a_Player)
Processes the entire action stored in the internal structures for inventory painting; distributes one...
void SendWholeWindow(cClientHandle &a_Client)
Sends the contents of the whole window to the specified client.
bool IsSlotInPlayerInventory(int a_SlotNum) const
Returns true if the specified slot is in the Player Main Inventory or Hotbar slotareas.
cWindow(WindowType a_WindowType, const AString &a_WindowTitle)
void DistributeStackToAreas(cItem &a_ItemStack, cPlayer &a_Player, cSlotAreas &a_AreasInOrder, bool a_ShouldApply, bool a_BackFill)
Called from DistributeStack() to distribute the stack into a_AreasInOrder; Modifies a_ItemStack as it...
const AString GetWindowTypeName(void) const
Returns the textual representation of the window's type, such as "minecraft:chest".
void OnPaintProgress(cPlayer &a_Player, int a_SlotNum)
Adds the slot to the internal structures for inventory painting by the specified player.
void BroadcastSlot(cSlotArea *a_Area, int a_LocalSlotNum)
Sends the specified slot's contents to all clients of this window; the slot is specified as local in ...