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(static_cast<char>((++m_WindowIDCounter) % 127)),
32 m_WindowType(a_WindowType),
33 m_WindowTitle(a_WindowTitle),
68 case wtChest:
return "minecraft:chest";
69 case wtWorkbench:
return "minecraft:crafting_table";
70 case wtFurnace:
return "minecraft:furnace";
73 case wtBrewery:
return "minecraft:brewing_stand";
75 case wtBeacon:
return "minecraft:beacon";
76 case wtAnvil:
return "minecraft:anvil";
77 case wtHopper:
return "minecraft:hopper";
78 case wtDropper:
return "minecraft:dropper";
82 ASSERT(!
"Unknown inventory type!");
97 res += itr->GetNumSlots();
109 int LocalSlotNum = 0;
113 LOGWARNING(
"%s: requesting item from an invalid SlotArea (SlotNum %d), returning nullptr.", __FUNCTION__, a_SlotNum);
116 return Area->
GetSlot(LocalSlotNum, a_Player);
126 int LocalSlotNum = 0;
130 LOGWARNING(
"%s: requesting write to an invalid SlotArea (SlotNum %d), ignoring.", __FUNCTION__, a_SlotNum);
133 Area->
SetSlot(LocalSlotNum, a_Player, a_Item);
176 a_Slots.reserve(static_cast<size_t>(
GetNumSlots()));
179 int NumSlots = (*itr)->GetNumSlots();
180 for (
int i = 0; i < NumSlots; i++)
182 const cItem * Item = (*itr)->GetSlot(i, a_Player);
185 a_Slots.push_back(
cItem());
189 a_Slots.push_back(*Item);
201 int a_WindowID,
short a_SlotNum,
eClickAction a_ClickAction,
202 const cItem & a_ClickedItem
208 LOGWARNING(
"%s: Wrong window ID (exp %d, got %d) received from \"%s\"; ignoring click.", __FUNCTION__,
m_WindowID, a_WindowID, a_Player.
GetName().c_str());
212 switch (a_ClickAction)
266 int LocalSlotNum = a_SlotNum;
271 itr->Clicked(a_Player, LocalSlotNum, a_ClickAction, a_ClickedItem);
274 LocalSlotNum -= itr->GetNumSlots();
277 LOGWARNING(
"Slot number higher than available window slots: %d, max %d received from \"%s\"; ignoring.",
297 (*itr)->OnPlayerAdded(a_Player);
313 LOGD(
"Player is holding an item while closing their window, dropping it as a pickup...");
318 if (ClientHandle !=
nullptr)
328 (*itr)->OnPlayerRemoved(a_Player);
372 if (a_Callback(*Player))
389 if (a_Callback(*Player->GetClientHandle()))
406 for (
size_t Pass = 0; Pass < 2; Pass++)
408 for (
auto SlotArea : a_AreasInOrder)
410 SlotArea->DistributeStack(a_ItemStack, a_Player, a_ShouldApply, (Pass == 0), a_BackFill);
429 if (Area->CollectItemsToHand(a_Dragging, a_Player, a_CollectFullStacks))
447 if (*itr == a_SlotArea)
452 SlotBase += (*itr)->GetNumSlots();
456 LOGERROR(
"cWindow::SendSlot(): unknown a_SlotArea");
457 ASSERT(!
"cWindow::SendSlot(): unknown a_SlotArea");
462 m_WindowID, static_cast<short>(a_RelativeSlotNum + SlotBase), *(a_SlotArea->
GetSlot(a_RelativeSlotNum, a_Player))
486 if ((a_GlobalSlotNum < 0) || (a_GlobalSlotNum >=
GetNumSlots()))
488 LOGWARNING(
"%s: requesting an invalid SlotNum: %d out of %d slots", __FUNCTION__, a_GlobalSlotNum,
GetNumSlots() - 1);
489 ASSERT(!
"Invalid SlotNum");
494 int LocalSlotNum = a_GlobalSlotNum;
497 if (LocalSlotNum < (*itr)->GetNumSlots())
499 a_LocalSlotNum = LocalSlotNum;
502 LocalSlotNum -= (*itr)->GetNumSlots();
506 LOGWARNING(
"%s: GetNumSlots() is out of sync: %d; LocalSlotNum = %d", __FUNCTION__,
GetNumSlots(), LocalSlotNum);
507 ASSERT(!
"Invalid GetNumSlots");
517 if ((a_GlobalSlotNum < 0) || (a_GlobalSlotNum >=
GetNumSlots()))
519 LOGWARNING(
"%s: requesting an invalid SlotNum: %d out of %d slots", __FUNCTION__, a_GlobalSlotNum,
GetNumSlots() - 1);
520 ASSERT(!
"Invalid SlotNum");
525 int LocalSlotNum = a_GlobalSlotNum;
528 if (LocalSlotNum < (*itr)->GetNumSlots())
530 a_LocalSlotNum = LocalSlotNum;
533 LocalSlotNum -= (*itr)->GetNumSlots();
537 LOGWARNING(
"%s: GetNumSlots() is out of sync: %d; LocalSlotNum = %d", __FUNCTION__,
GetNumSlots(), LocalSlotNum);
538 ASSERT(!
"Invalid GetNumSlots");
573 int ToEachSlot =
static_cast<int>(ToDistribute.m_ItemCount) / static_cast<int>(SlotNums.size());
649 if (a_LimitItems && (static_cast<size_t>(a_Item.
m_ItemCount) < a_SlotNums.size()))
651 LOGWARNING(
"%s: Distributing less items (%d) than slots (%zu)", __FUNCTION__, static_cast<int>(a_Item.
m_ItemCount), a_SlotNums.size());
657 int NumDistributed = 0;
658 for (cSlotNums::const_iterator itr = a_SlotNums.begin(), end = a_SlotNums.end(); itr != end; ++itr)
660 int LocalSlotNum = 0;
664 LOGWARNING(
"%s: Bad SlotArea for slot %d", __FUNCTION__, *itr);
671 if (AtSlot.IsEmpty())
674 cItem ToStore(a_Item);
675 ToStore.
m_ItemCount =
static_cast<char>(std::min(a_NumToEachSlot, static_cast<int>(MaxStack)));
676 Area->
SetSlot(LocalSlotNum, a_Player, ToStore);
679 else if (AtSlot.IsEqual(a_Item))
682 int CanStore = std::min(a_NumToEachSlot, static_cast<int>(MaxStack) - AtSlot.m_ItemCount);
683 AtSlot.m_ItemCount += CanStore;
684 Area->
SetSlot(LocalSlotNum, a_Player, AtSlot);
685 NumDistributed += CanStore;
688 return NumDistributed;
699 bool HasFound =
false;
704 SlotNum += a_LocalSlotNum;
708 SlotNum += (*itr)->GetNumSlots();
712 LOGWARNING(
"%s: Invalid slot area parameter", __FUNCTION__);
713 ASSERT(!
"Invalid slot area");
721 (*itr)->GetClientHandle()->SendInventorySlot(
m_WindowID, static_cast<short>(SlotNum), *a_Area->
GetSlot(a_LocalSlotNum, **itr));
756 (*itr)->GetClientHandle()->SendWindowProperty(*
this, a_Property, a_Value);
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...
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 ...
bool IsSlotInPlayerMainInventory(int a_SlotNum) const
Returns true if the specified slot is in the Player Main Inventory 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 IsSlotInPlayerInventory(int a_SlotNum) const
Returns true if the specified slot is in the Player Main Inventory or Hotbar slotareas.
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.
const AString GetWindowTypeName(void) const
Returns the textual representation of the window's type, such as "minecraft:chest".
void GetSlots(cPlayer &a_Player, cItems &a_Slots) const
Fills a_Slots with the slots read from m_SlotAreas[], for the specified player.
virtual char GetMaxStackSize(void)
Returns the maximum stack size for a given item.
void SendInventorySlot(char a_WindowID, short a_SlotNum, const cItem &a_Item)
cItem & GetDraggingItem(void)
In UI windows, get the item that the player is dragging.
void OwnerDestroyed(void)
void TossHeldItem(char a_Amount=1)
tosses the item held in hand (when in UI windows)
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...
void SendWholeInventory(const cWindow &a_Window)
const AString & GetName(void) const
void SendWindowProperty(const cWindow &a_Window, short a_Property, short a_Value)
void LOGERROR(const char *a_Format, fmt::ArgList a_ArgList)
static Byte m_WindowIDCounter
void AddInventoryPaintSlot(int a_SlotNum)
Adds a slot to the list for inventory painting.
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.
eClickAction
Individual actions sent in the WindowClick packet.
const cSlotNums & GetInventoryPaintSlots(void) const
Returns the list of slots currently stored for inventory painting.
void OnPaintBegin(cPlayer &a_Player)
Prepares the internal structures for inventory painting from the specified player.
std::vector< cSlotArea * > cSlotAreas
virtual void OpenedByPlayer(cPlayer &a_Player)
bool CallHookPlayerTossingItem(cPlayer &a_Player)
void LOGWARNING(const char *a_Format, fmt::ArgList a_ArgList)
bool ForEachPlayer(cPlayerListCallback a_Callback)
Calls the callback safely for each player that has this window open; returns true if all players have...
void SendWindowOpen(const cWindow &a_Window)
int GetNumSlots(void) const
Returns the total number of slots.
void ClearInventoryPaintSlots(void)
Clears the list of slots that are being inventory-painted.
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.
virtual bool ClosedByPlayer(cPlayer &a_Player, bool a_CanRefuse)
Called when a player closes this window; notifies all slot areas.
int DistributeItemToSlots(cPlayer &a_Player, const cItem &a_Item, int 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...
void OnPaintProgress(cPlayer &a_Player, int a_SlotNum)
Adds the slot to the internal structures for inventory painting by the specified player.
virtual void SetProperty(short a_Property, short a_Value)
Updates a numerical property associated with the window.
char GetMaxStackSize(void) const
Returns the maximum amount of stacked items of this type.
void TossPickup(const cItem &a_Item)
tosses a pickup newly created from a_Item
bool IsSlotInPlayerHotbar(int a_SlotNum) const
Returns true if the specified slot is in the Player Hotbar slotarea.
RAII for cCriticalSection - locks the CS on creation, unlocks on destruction.
void SendWindowClose(const cWindow &a_Window)
cWindow(WindowType a_WindowType, const AString &a_WindowTitle)
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.
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.
bool IsGameModeCreative(void) const
Returns true if the player is in Creative mode, either explicitly, or by inheriting from current worl...
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.
const cItem * GetSlot(cPlayer &a_Player, int a_SlotNum) const
Returns the item at the specified slot for the specified player.
void OnMiddlePaintEnd(cPlayer &a_Player)
Processes the entire action stored in the internal structures for inventory painting; distributes a f...
void SetSlot(cPlayer &a_Player, int a_SlotNum, const cItem &a_Item)
Sets the item to the specified slot for the specified player.
cItemHandler * ItemHandler(int a_ItemType)
cClientHandle * GetClientHandle(void) const
Returns the raw client handle associated with the player.
This class bridges a vector of cItem for safe access via Lua.
void OnLeftPaintEnd(cPlayer &a_Player)
Processes the entire action stored in the internal structures for inventory painting; distributes as ...
cPluginManager * GetPluginManager(void)
std::vector< int > cSlotNums
List of slot numbers, used for inventory-painting.
void BroadcastWholeWindow(void)
Sends the contents of the whole window to all clients of this window.