Cuberite
A lightweight, fast and extensible game server for Minecraft
Window.cpp
Go to the documentation of this file.
1 #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
2 
3 #include "Window.h"
4 #include "WindowOwner.h"
5 #include "SlotArea.h"
6 #include "../Item.h"
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"
18 #include "../Root.h"
19 #include "../Bindings/PluginManager.h"
20 
21 
22 
23 
25 
26 
27 
28 
29 
30 cWindow::cWindow(WindowType a_WindowType, const AString & a_WindowTitle) :
31  m_WindowID(((++m_WindowIDCounter) % 127) + 1),
32  m_WindowType(a_WindowType),
33  m_WindowTitle(a_WindowTitle),
34  m_IsDestroyed(false),
35  m_Owner(nullptr)
36 {
37  ASSERT((m_WindowID > 0) && (m_WindowID <= 127));
38 
39  if (a_WindowType == wtInventory)
40  {
41  m_WindowID = 0;
42  }
43 }
44 
45 
46 
47 
48 
50 {
51  for (cSlotAreas::iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr)
52  {
53  delete *itr;
54  }
55  m_SlotAreas.clear();
56 }
57 
58 
59 
60 
61 
63 {
64  switch (m_WindowType)
65  {
66  case wtChest: return "minecraft:chest";
67  case wtWorkbench: return "minecraft:crafting_table";
68  case wtFurnace: return "minecraft:furnace";
69  case wtDropSpenser: return "minecraft:dispenser";
70  case wtEnchantment: return "minecraft:enchanting_table";
71  case wtBrewery: return "minecraft:brewing_stand";
72  case wtNPCTrade: return "minecraft:villager";
73  case wtBeacon: return "minecraft:beacon";
74  case wtAnvil: return "minecraft:anvil";
75  case wtHopper: return "minecraft:hopper";
76  case wtDropper: return "minecraft:dropper";
77  case wtAnimalChest: return "EntityHorse";
78  default:
79  {
80  ASSERT(!"Unknown inventory type!");
81  return "";
82  }
83  }
84 }
85 
86 
87 
88 
89 
90 int cWindow::GetNumSlots(void) const
91 {
92  int res = 0;
93  for (const auto & itr : m_SlotAreas)
94  {
95  res += itr->GetNumSlots();
96  } // for itr - m_SlotAreas[]
97  return res;
98 }
99 
100 
101 
102 
103 
104 const cItem * cWindow::GetSlot(cPlayer & a_Player, int a_SlotNum) const
105 {
106  // Return the item at the specified slot for the specified player
107  int LocalSlotNum = 0;
108  const cSlotArea * Area = GetSlotArea(a_SlotNum, LocalSlotNum);
109  if (Area == nullptr)
110  {
111  LOGWARNING("%s: requesting item from an invalid SlotArea (SlotNum %d), returning nullptr.", __FUNCTION__, a_SlotNum);
112  return nullptr;
113  }
114  return Area->GetSlot(LocalSlotNum, a_Player);
115 }
116 
117 
118 
119 
120 
121 void cWindow::SetSlot(cPlayer & a_Player, int a_SlotNum, const cItem & a_Item)
122 {
123  // Set the item to the specified slot for the specified player
124  int LocalSlotNum = 0;
125  cSlotArea * Area = GetSlotArea(a_SlotNum, LocalSlotNum);
126  if (Area == nullptr)
127  {
128  LOGWARNING("%s: requesting write to an invalid SlotArea (SlotNum %d), ignoring.", __FUNCTION__, a_SlotNum);
129  return;
130  }
131  Area->SetSlot(LocalSlotNum, a_Player, a_Item);
132 }
133 
134 
135 
136 
137 
138 bool cWindow::IsSlotInPlayerMainInventory(int a_SlotNum) const
139 {
140  // Returns true if the specified slot is in the Player Main Inventory slotarea
141  // The player main inventory is always 27 slots, 9 slots from the end of the inventory
142  return ((a_SlotNum >= GetNumSlots() - 36) && (a_SlotNum < GetNumSlots() - 9));
143 }
144 
145 
146 
147 
148 
149 bool cWindow::IsSlotInPlayerHotbar(int a_SlotNum) const
150 {
151  // Returns true if the specified slot is in the Player Hotbar slotarea
152  // The hotbar is always the last 9 slots
153  return ((a_SlotNum >= GetNumSlots() - 9) && (a_SlotNum < GetNumSlots()));
154 }
155 
156 
157 
158 
159 
160 bool cWindow::IsSlotInPlayerInventory(int a_SlotNum) const
161 {
162  // Returns true if the specified slot is in the Player Main Inventory or Hotbar slotareas. Note that returns false for Armor.
163  // The player combined inventory is always the last 36 slots
164  return ((a_SlotNum >= GetNumSlots() - 36) && (a_SlotNum < GetNumSlots()));
165 }
166 
167 
168 
169 
170 
171 void cWindow::GetSlots(cPlayer & a_Player, cItems & a_Slots) const
172 {
173  a_Slots.clear();
174  a_Slots.reserve(static_cast<size_t>(GetNumSlots()));
175  for (cSlotAreas::const_iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr)
176  {
177  int NumSlots = (*itr)->GetNumSlots();
178  for (int i = 0; i < NumSlots; i++)
179  {
180  const cItem * Item = (*itr)->GetSlot(i, a_Player);
181  if (Item == nullptr)
182  {
183  a_Slots.push_back(cItem());
184  }
185  else
186  {
187  a_Slots.push_back(*Item);
188  }
189  }
190  } // for itr - m_SlotAreas[]
191 }
192 
193 
194 
195 
196 
198  cPlayer & a_Player,
199  int a_WindowID, short a_SlotNum, eClickAction a_ClickAction,
200  const cItem & a_ClickedItem
201 )
202 {
204  if (a_WindowID != m_WindowID)
205  {
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());
207  return;
208  }
209 
210  switch (a_ClickAction)
211  {
212  case caLeftClickOutside:
213  case caRightClickOutside:
214  {
215  if (PlgMgr->CallHookPlayerTossingItem(a_Player))
216  {
217  // A plugin doesn't agree with the tossing. The plugin itself is responsible for handling the consequences (possible inventory mismatch)
218  return;
219  }
220  if (a_Player.IsGameModeCreative())
221  {
222  a_Player.TossPickup(a_ClickedItem);
223  }
224 
225  if (a_ClickAction == caLeftClickOutside)
226  {
227  // Toss all dragged items:
228  a_Player.TossHeldItem(a_Player.GetDraggingItem().m_ItemCount);
229  }
230  else
231  {
232  // Toss one of the dragged items:
233  a_Player.TossHeldItem();
234  }
235  return;
236  }
239  {
240  // Nothing needed
241  return;
242  }
243  case caLeftPaintBegin: OnPaintBegin (a_Player); return;
244  case caRightPaintBegin: OnPaintBegin (a_Player); return;
245  case caMiddlePaintBegin: OnPaintBegin (a_Player); return;
246  case caLeftPaintProgress: OnPaintProgress (a_Player, a_SlotNum); return;
247  case caRightPaintProgress: OnPaintProgress (a_Player, a_SlotNum); return;
248  case caMiddlePaintProgress: OnPaintProgress (a_Player, a_SlotNum); return;
249  case caLeftPaintEnd: OnLeftPaintEnd (a_Player); return;
250  case caRightPaintEnd: OnRightPaintEnd (a_Player); return;
251  case caMiddlePaintEnd: OnMiddlePaintEnd(a_Player); return;
252  default:
253  {
254  break;
255  }
256  }
257 
258  if (a_SlotNum < 0)
259  {
260  // TODO: Other click actions with irrelevant slot number (FS #371)
261  return;
262  }
263 
264  int LocalSlotNum = a_SlotNum;
265  for (const auto & itr : m_SlotAreas)
266  {
267  if (LocalSlotNum < itr->GetNumSlots())
268  {
269  itr->Clicked(a_Player, LocalSlotNum, a_ClickAction, a_ClickedItem);
270  return;
271  }
272  LocalSlotNum -= itr->GetNumSlots();
273  }
274 
275  LOGWARNING("Slot number higher than available window slots: %d, max %d received from \"%s\"; ignoring.",
276  a_SlotNum, GetNumSlots(), a_Player.GetName().c_str()
277  );
278 }
279 
280 
281 
282 
283 
285 {
286  {
287  cCSLock Lock(m_CS);
288  // If player is already in OpenedBy remove player first
289  m_OpenedBy.remove(&a_Player);
290  // Then add player
291  m_OpenedBy.push_back(&a_Player);
292 
293  for (cSlotAreas::iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr)
294  {
295  (*itr)->OnPlayerAdded(a_Player);
296  } // for itr - m_SlotAreas[]
297  }
298 
299  a_Player.GetClientHandle()->SendWindowOpen(*this);
300 }
301 
302 
303 
304 
305 
306 bool cWindow::ClosedByPlayer(cPlayer & a_Player, bool a_CanRefuse)
307 {
308  // Checks whether the player is still holding an item
309  if (!a_Player.GetDraggingItem().IsEmpty())
310  {
311  LOGD("Player is holding an item while closing their window, dropping it as a pickup...");
312  a_Player.TossHeldItem(a_Player.GetDraggingItem().m_ItemCount);
313  }
314 
315  cClientHandle * ClientHandle = a_Player.GetClientHandle();
316  if (ClientHandle != nullptr)
317  {
318  ClientHandle->SendWindowClose(*this);
319  }
320 
321  {
322  cCSLock Lock(m_CS);
323 
324  for (cSlotAreas::iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr)
325  {
326  (*itr)->OnPlayerRemoved(a_Player);
327  } // for itr - m_SlotAreas[]
328 
329  if (m_WindowType != wtInventory)
330  {
331  m_OpenedBy.remove(&a_Player);
332  if (m_OpenedBy.empty())
333  {
334  Destroy();
335  }
336  }
337  }
338  if (m_IsDestroyed)
339  {
340  delete this;
341  }
342 
343  return true;
344 }
345 
346 
347 
348 
349 
350 void cWindow::BroadcastSlot(cSlotArea * a_Area, int a_LocalSlotNum)
351 {
352  // Translate local slot num into global slot num:
353  int SlotNum = 0;
354  bool HasFound = false;
355  for (cSlotAreas::const_iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr)
356  {
357  if (a_Area == *itr)
358  {
359  SlotNum += a_LocalSlotNum;
360  HasFound = true;
361  break;
362  }
363  SlotNum += (*itr)->GetNumSlots();
364  } // for itr - m_SlotAreas[]
365  if (!HasFound)
366  {
367  LOGWARNING("%s: Invalid slot area parameter", __FUNCTION__);
368  ASSERT(!"Invalid slot area");
369  return;
370  }
371 
372  // Broadcast the update packet:
373  cCSLock Lock(m_CS);
374  for (cPlayerList::iterator itr = m_OpenedBy.begin(); itr != m_OpenedBy.end(); ++itr)
375  {
376  (*itr)->GetClientHandle()->SendInventorySlot(m_WindowID, static_cast<short>(SlotNum), *a_Area->GetSlot(a_LocalSlotNum, **itr));
377  } // for itr - m_OpenedBy[]
378 }
379 
380 
381 
382 
383 
385 {
386  a_Client.SendWholeInventory(*this);
387 }
388 
389 
390 
391 
392 
394 {
395  cCSLock Lock(m_CS);
396  for (auto Player : m_OpenedBy)
397  {
398  SendWholeWindow(*Player->GetClientHandle());
399  }
400 }
401 
402 
403 
404 
405 
406 void cWindow::SetProperty(size_t a_Property, short a_Value)
407 {
408  cCSLock Lock(m_CS);
409  for (auto Player : m_OpenedBy)
410  {
411  Player->GetClientHandle()->SendWindowProperty(*this, a_Property, a_Value);
412  }
413 }
414 
415 
416 
417 
418 
420 {
421  // Close window for each player. Note that the last one needs special handling
422  while (m_OpenedBy.size() > 1)
423  {
424  (*m_OpenedBy.begin())->CloseWindow();
425  }
426  (*m_OpenedBy.begin())->CloseWindow();
427 }
428 
429 
430 
431 
432 
434 {
435  cCSLock Lock(m_CS);
436  for (auto & Player : m_OpenedBy)
437  {
438  if (a_Callback(*Player))
439  {
440  return false;
441  }
442  } // for itr - m_OpenedBy[]
443  return true;
444 }
445 
446 
447 
448 
449 
451 {
452  cCSLock Lock(m_CS);
453  for (auto & Player : m_OpenedBy)
454  {
455  if (a_Callback(*Player->GetClientHandle()))
456  {
457  return false;
458  }
459  } // for itr - m_OpenedBy[]
460  return true;
461 }
462 
463 
464 
465 
466 
467 void cWindow::DistributeStackToAreas(cItem & a_ItemStack, cPlayer & a_Player, cSlotAreas & a_AreasInOrder, bool a_ShouldApply, bool a_BackFill)
468 {
469  /* Ask each slot area to take as much of the stack as it can.
470  First ask only slots that already have the same kind of item
471  Then ask any remaining slots */
472  for (size_t Pass = 0; Pass < 2; Pass++)
473  {
474  for (auto SlotArea : a_AreasInOrder)
475  {
476  SlotArea->DistributeStack(a_ItemStack, a_Player, a_ShouldApply, (Pass == 0), a_BackFill);
477  if (a_ItemStack.IsEmpty())
478  {
479  // Distributed it all
480  return;
481  }
482  }
483  }
484 }
485 
486 
487 
488 
489 
490 bool cWindow::CollectItemsToHand(cItem & a_Dragging, cSlotArea & a_Area, cPlayer & a_Player, bool a_CollectFullStacks)
491 {
492  // Ask to collect items from each slot area in order:
493  for (auto Area : m_SlotAreas)
494  {
495  if (Area->CollectItemsToHand(a_Dragging, a_Player, a_CollectFullStacks))
496  {
497  return true; // a_Dragging is full
498  }
499  }
500  return false; // All areas processed
501 }
502 
503 
504 
505 
506 
507 void cWindow::SendSlot(cPlayer & a_Player, cSlotArea * a_SlotArea, int a_RelativeSlotNum)
508 {
509  int SlotBase = 0;
510  bool Found = false;
511  for (cSlotAreas::iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr)
512  {
513  if (*itr == a_SlotArea)
514  {
515  Found = true;
516  break;
517  }
518  SlotBase += (*itr)->GetNumSlots();
519  } // for itr - m_SlotAreas[]
520  if (!Found)
521  {
522  LOGERROR("cWindow::SendSlot(): unknown a_SlotArea");
523  ASSERT(!"cWindow::SendSlot(): unknown a_SlotArea");
524  return;
525  }
526 
528  m_WindowID, static_cast<short>(a_RelativeSlotNum + SlotBase), *(a_SlotArea->GetSlot(a_RelativeSlotNum, a_Player))
529  );
530 }
531 
532 
533 
534 
535 
537 {
538  if (m_Owner != nullptr)
539  {
540  m_Owner->CloseWindow();
541  m_Owner = nullptr;
542  }
543  m_IsDestroyed = true;
544 }
545 
546 
547 
548 
549 
550 cSlotArea * cWindow::GetSlotArea(int a_GlobalSlotNum, int & a_LocalSlotNum)
551 {
552  if ((a_GlobalSlotNum < 0) || (a_GlobalSlotNum >= GetNumSlots()))
553  {
554  LOGWARNING("%s: requesting an invalid SlotNum: %d out of %d slots", __FUNCTION__, a_GlobalSlotNum, GetNumSlots() - 1);
555  ASSERT(!"Invalid SlotNum");
556  return nullptr;
557  }
558 
559  // Iterate through all the SlotAreas, find the correct one
560  int LocalSlotNum = a_GlobalSlotNum;
561  for (cSlotAreas::iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr)
562  {
563  if (LocalSlotNum < (*itr)->GetNumSlots())
564  {
565  a_LocalSlotNum = LocalSlotNum;
566  return *itr;
567  }
568  LocalSlotNum -= (*itr)->GetNumSlots();
569  } // for itr - m_SlotAreas[]
570 
571  // We shouldn't be here - the check at the beginnning should prevent this. Log and assert
572  LOGWARNING("%s: GetNumSlots() is out of sync: %d; LocalSlotNum = %d", __FUNCTION__, GetNumSlots(), LocalSlotNum);
573  ASSERT(!"Invalid GetNumSlots");
574  return nullptr;
575 }
576 
577 
578 
579 
580 
581 const cSlotArea * cWindow::GetSlotArea(int a_GlobalSlotNum, int & a_LocalSlotNum) const
582 {
583  if ((a_GlobalSlotNum < 0) || (a_GlobalSlotNum >= GetNumSlots()))
584  {
585  LOGWARNING("%s: requesting an invalid SlotNum: %d out of %d slots", __FUNCTION__, a_GlobalSlotNum, GetNumSlots() - 1);
586  ASSERT(!"Invalid SlotNum");
587  return nullptr;
588  }
589 
590  // Iterate through all the SlotAreas, find the correct one
591  int LocalSlotNum = a_GlobalSlotNum;
592  for (cSlotAreas::const_iterator itr = m_SlotAreas.begin(), end = m_SlotAreas.end(); itr != end; ++itr)
593  {
594  if (LocalSlotNum < (*itr)->GetNumSlots())
595  {
596  a_LocalSlotNum = LocalSlotNum;
597  return *itr;
598  }
599  LocalSlotNum -= (*itr)->GetNumSlots();
600  } // for itr - m_SlotAreas[]
601 
602  // We shouldn't be here - the check at the beginnning should prevent this. Log and assert
603  LOGWARNING("%s: GetNumSlots() is out of sync: %d; LocalSlotNum = %d", __FUNCTION__, GetNumSlots(), LocalSlotNum);
604  ASSERT(!"Invalid GetNumSlots");
605  return nullptr;
606 }
607 
608 
609 
610 
611 
613 {
614  // Prepares the internal structures for inventory painting from the specified player
615  a_Player.ClearInventoryPaintSlots();
616 }
617 
618 
619 
620 
621 
622 void cWindow::OnPaintProgress(cPlayer & a_Player, int a_SlotNum)
623 {
624  // Add the slot to the internal structures for inventory painting by the specified player
625  a_Player.AddInventoryPaintSlot(a_SlotNum);
626 }
627 
628 
629 
630 
631 
633 {
634  // Process the entire action stored in the internal structures for inventory painting
635  // distribute as many items as possible
636 
637  const cSlotNums & SlotNums = a_Player.GetInventoryPaintSlots();
638  cItem ToDistribute(a_Player.GetDraggingItem());
639  char ToEachSlot = ToDistribute.m_ItemCount / static_cast<char>(SlotNums.size());
640 
641  char NumDistributed = DistributeItemToSlots(a_Player, ToDistribute, ToEachSlot, SlotNums);
642 
643  // Remove the items distributed from the dragging item:
644  a_Player.GetDraggingItem().m_ItemCount -= NumDistributed;
645  if (a_Player.GetDraggingItem().m_ItemCount == 0)
646  {
647  a_Player.GetDraggingItem().Empty();
648  }
649 
650  SendWholeWindow(*a_Player.GetClientHandle());
651 
652  // To fix #2345 (custom recipes don't work when inventory-painting), we send the result slot explicitly once again
653  // This is a fix for what seems like a client-side bug
654  a_Player.GetClientHandle()->SendInventorySlot(m_WindowID, 0, *GetSlot(a_Player, 0));
655 }
656 
657 
658 
659 
660 
662 {
663  // Process the entire action stored in the internal structures for inventory painting
664  // distribute one item into each slot
665 
666  const cSlotNums & SlotNums = a_Player.GetInventoryPaintSlots();
667  cItem ToDistribute(a_Player.GetDraggingItem());
668 
669  char NumDistributed = DistributeItemToSlots(a_Player, ToDistribute, 1, SlotNums);
670 
671  // Remove the items distributed from the dragging item:
672  a_Player.GetDraggingItem().m_ItemCount -= NumDistributed;
673  if (a_Player.GetDraggingItem().m_ItemCount == 0)
674  {
675  a_Player.GetDraggingItem().Empty();
676  }
677 
678  SendWholeWindow(*a_Player.GetClientHandle());
679 
680  // To fix #2345 (custom recipes don't work when inventory-painting), we send the result slot explicitly once again
681  // This is a fix for what seems like a client-side bug
682  a_Player.GetClientHandle()->SendInventorySlot(m_WindowID, 0, *GetSlot(a_Player, 0));
683 }
684 
685 
686 
687 
688 
690 {
691  if (!a_Player.IsGameModeCreative())
692  {
693  // Midle click paint is only valid for creative mode
694  return;
695  }
696 
697  // Fill available slots with full stacks of the dragging item
698  const auto & DraggingItem = a_Player.GetDraggingItem();
699  auto StackSize = DraggingItem.GetMaxStackSize();
700  if (0 < DistributeItemToSlots(a_Player, DraggingItem, StackSize, a_Player.GetInventoryPaintSlots(), false))
701  {
702  // If any items were distibuted, set dragging item empty
703  a_Player.GetDraggingItem().Empty();
704  }
705 
706  SendWholeWindow(*a_Player.GetClientHandle());
707 }
708 
709 
710 
711 
712 
713 char cWindow::DistributeItemToSlots(cPlayer & a_Player, const cItem & a_Item, char a_NumToEachSlot, const cSlotNums & a_SlotNums, bool a_LimitItems)
714 {
715  if (a_LimitItems && (static_cast<size_t>(a_Item.m_ItemCount) < a_SlotNums.size()))
716  {
717  LOGWARNING("%s: Distributing less items (%d) than slots (%zu)", __FUNCTION__, static_cast<int>(a_Item.m_ItemCount), a_SlotNums.size());
718  // This doesn't seem to happen with the 1.5.1 client, so we don't worry about it for now
719  return 0;
720  }
721 
722  // Distribute to individual slots, keep track of how many items were actually distributed (full stacks etc.)
723  char NumDistributed = 0;
724  for (cSlotNums::const_iterator itr = a_SlotNums.begin(), end = a_SlotNums.end(); itr != end; ++itr)
725  {
726  int LocalSlotNum = 0;
727  cSlotArea * Area = GetSlotArea(*itr, LocalSlotNum);
728  if (Area == nullptr)
729  {
730  LOGWARNING("%s: Bad SlotArea for slot %d", __FUNCTION__, *itr);
731  continue;
732  }
733 
734  // Modify the item at the slot
735  cItem AtSlot(*Area->GetSlot(LocalSlotNum, a_Player));
736  char MaxStack = AtSlot.GetMaxStackSize();
737  if (AtSlot.IsEmpty())
738  {
739  // Empty, just move all of it there:
740  cItem ToStore(a_Item);
741  ToStore.m_ItemCount = std::min<char>(a_NumToEachSlot, MaxStack);
742  Area->SetSlot(LocalSlotNum, a_Player, ToStore);
743  NumDistributed += ToStore.m_ItemCount;
744  }
745  else if (AtSlot.IsEqual(a_Item))
746  {
747  // Occupied, add and cap at MaxStack:
748  char CanStore = std::min<char>(a_NumToEachSlot, MaxStack - AtSlot.m_ItemCount);
749  AtSlot.m_ItemCount += CanStore;
750  Area->SetSlot(LocalSlotNum, a_Player, AtSlot);
751  NumDistributed += CanStore;
752  }
753  } // for itr - SlotNums[]
754  return NumDistributed;
755 }
eClickAction
Individual actions sent in the WindowClick packet.
Definition: Defines.h:82
@ caRightPaintProgress
Definition: Defines.h:108
@ caLeftPaintProgress
Definition: Defines.h:107
@ caLeftPaintEnd
Definition: Defines.h:110
@ caLeftClickOutside
Definition: Defines.h:100
@ caMiddlePaintEnd
Definition: Defines.h:112
@ caLeftClickOutsideHoldNothing
Definition: Defines.h:102
@ caMiddlePaintBegin
Definition: Defines.h:106
@ caMiddlePaintProgress
Definition: Defines.h:109
@ caLeftPaintBegin
Definition: Defines.h:104
@ caRightClickOutsideHoldNothing
Definition: Defines.h:103
@ caRightPaintEnd
Definition: Defines.h:111
@ caRightClickOutside
Definition: Defines.h:101
@ caRightPaintBegin
Definition: Defines.h:105
std::vector< int > cSlotNums
List of slot numbers, used for inventory-painting.
Definition: Defines.h:9
#define ASSERT(x)
Definition: Globals.h:276
unsigned char Byte
Definition: Globals.h:161
void LOGERROR(std::string_view a_Format, const Args &... args)
Definition: LoggerSimple.h:73
void LOGWARNING(std::string_view a_Format, const Args &... args)
Definition: LoggerSimple.h:67
#define LOGD
Definition: LoggerSimple.h:83
Item
Definition: Items.h:4
std::string AString
Definition: StringUtils.h:11
std::vector< cSlotArea * > cSlotAreas
Definition: Window.h:34
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)
Definition: Player.h:29
cClientHandle * GetClientHandle(void) const
Definition: Player.h:276
const AString & GetName(void) const
Definition: Player.cpp:1299
const cSlotNums & GetInventoryPaintSlots(void) const
Returns the list of slots currently stored for inventory painting.
Definition: Player.cpp:581
void ClearInventoryPaintSlots(void)
Clears the list of slots that are being inventory-painted.
Definition: Player.cpp:561
void AddInventoryPaintSlot(int a_SlotNum)
Adds a slot to the list for inventory painting.
Definition: Player.cpp:571
void TossPickup(const cItem &a_Item)
tosses a pickup newly created from a_Item
Definition: Player.cpp:1791
bool IsGameModeCreative(void) const
Returns true if the player is in Creative mode, either explicitly, or by inheriting from current worl...
Definition: Player.cpp:1025
void TossHeldItem(char a_Amount=1)
tosses the item held in hand (when in UI windows)
Definition: Player.cpp:1764
cItem & GetDraggingItem(void)
In UI windows, get the item that the player is dragging.
Definition: Player.h:448
Definition: Item.h:37
char m_ItemCount
Definition: Item.h:164
char GetMaxStackSize(void) const
Returns the maximum amount of stacked items of this type.
Definition: Item.cpp:207
bool IsEmpty(void) const
Returns true if the item represents an empty stack - either the type is invalid, or count is zero.
Definition: Item.h:69
bool IsEqual(const cItem &a_Item) const
Definition: Item.h:76
void Empty(void)
Empties the item and frees up any dynamic storage used by the internals.
Definition: Item.cpp:63
This class bridges a vector of cItem for safe access via Lua.
Definition: Item.h:215
RAII for cCriticalSection - locks the CS on creation, unlocks on destruction.
static cRoot * Get()
Definition: Root.h:52
cPluginManager * GetPluginManager(void)
Definition: Root.h:111
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)
Definition: Window.cpp:284
void OnPaintBegin(cPlayer &a_Player)
Prepares the internal structures for inventory painting from the specified player.
Definition: Window.cpp:612
virtual void SetProperty(size_t a_Property, short a_Value)
Updates a numerical property associated with the window.
Definition: Window.cpp:406
bool m_IsDestroyed
Definition: Window.h:188
virtual bool ClosedByPlayer(cPlayer &a_Player, bool a_CanRefuse)
Called when a player closes this window; notifies all slot areas.
Definition: Window.cpp:306
void SetSlot(cPlayer &a_Player, int a_SlotNum, const cItem &a_Item)
Sets the item to the specified slot for the specified player.
Definition: Window.cpp:121
void OnLeftPaintEnd(cPlayer &a_Player)
Processes the entire action stored in the internal structures for inventory painting; distributes as ...
Definition: Window.cpp:632
static Byte m_WindowIDCounter
Definition: Window.h:192
cWindowOwner * m_Owner
Definition: Window.h:190
void BroadcastWholeWindow(void)
Sends the contents of the whole window to all clients of this window.
Definition: Window.cpp:393
WindowType
Definition: Window.h:57
@ wtDropSpenser
Definition: Window.h:62
@ wtNPCTrade
Definition: Window.h:65
@ wtDropper
Definition: Window.h:69
@ wtWorkbench
Definition: Window.h:60
@ wtFurnace
Definition: Window.h:61
@ wtAnvil
Definition: Window.h:67
@ wtHopper
Definition: Window.h:68
@ wtBeacon
Definition: Window.h:66
@ wtAnimalChest
Definition: Window.h:70
@ wtInventory
Definition: Window.h:58
@ wtEnchantment
Definition: Window.h:63
@ wtBrewery
Definition: Window.h:64
@ wtChest
Definition: Window.h:59
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...
Definition: Window.cpp:713
const cItem * GetSlot(cPlayer &a_Player, int a_SlotNum) const
Returns the item at the specified slot for the specified player.
Definition: Window.cpp:104
void GetSlots(cPlayer &a_Player, cItems &a_Slots) const
Fills a_Slots with the slots read from m_SlotAreas[], for the specified player.
Definition: Window.cpp:171
virtual ~cWindow()
Definition: Window.cpp:49
cPlayerList m_OpenedBy
Definition: Window.h:186
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.
Definition: Window.cpp:490
bool ForEachPlayer(cPlayerListCallback a_Callback)
Calls the callback safely for each player that has this window open; returns true if all players have...
Definition: Window.cpp:433
int GetNumSlots(void) const
Returns the total number of slots.
Definition: Window.cpp:90
void OnMiddlePaintEnd(cPlayer &a_Player)
Processes the entire action stored in the internal structures for inventory painting; distributes a f...
Definition: Window.cpp:689
bool IsSlotInPlayerHotbar(int a_SlotNum) const
Returns true if the specified slot is in the Player Hotbar slotarea.
Definition: Window.cpp:149
char m_WindowID
Definition: Window.h:181
int m_WindowType
Definition: Window.h:182
bool ForEachClient(cClientHandleCallback a_Callback)
Calls the callback safely for each client that has this window open; returns true if all clients have...
Definition: Window.cpp:450
bool IsSlotInPlayerMainInventory(int a_SlotNum) const
Returns true if the specified slot is in the Player Main Inventory slotarea.
Definition: Window.cpp:138
void OwnerDestroyed(void)
Definition: Window.cpp:419
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...
Definition: Window.cpp:507
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...
Definition: Window.cpp:550
virtual void Destroy(void)
Sets the internal flag as "destroyed"; notifies the owner that the window is destroying.
Definition: Window.cpp:536
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.
Definition: Window.cpp:197
void OnRightPaintEnd(cPlayer &a_Player)
Processes the entire action stored in the internal structures for inventory painting; distributes one...
Definition: Window.cpp:661
void SendWholeWindow(cClientHandle &a_Client)
Sends the contents of the whole window to the specified client.
Definition: Window.cpp:384
bool IsSlotInPlayerInventory(int a_SlotNum) const
Returns true if the specified slot is in the Player Main Inventory or Hotbar slotareas.
Definition: Window.cpp:160
cCriticalSection m_CS
Definition: Window.h:185
cWindow(WindowType a_WindowType, const AString &a_WindowTitle)
Definition: Window.cpp:30
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...
Definition: Window.cpp:467
const AString GetWindowTypeName(void) const
Returns the textual representation of the window's type, such as "minecraft:chest".
Definition: Window.cpp:62
void OnPaintProgress(cPlayer &a_Player, int a_SlotNum)
Adds the slot to the internal structures for inventory painting by the specified player.
Definition: Window.cpp:622
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 ...
Definition: Window.cpp:350
cSlotAreas m_SlotAreas
Definition: Window.h:179
void CloseWindow(void)
Definition: WindowOwner.h:29