Cuberite
A lightweight, fast and extensible game server for Minecraft
ItemGrid.cpp
Go to the documentation of this file.
1 
2 // ItemGrid.cpp
3 
4 // Implements the cItemGrid class representing a storage for items in a XY grid (chests, dispensers, inventory etc.)
5 
6 #include "Globals.h"
7 #include "ItemGrid.h"
8 #include "Items/ItemHandler.h"
9 #include "Noise/Noise.h"
10 
11 
12 
13 
14 
15 cItemGrid::cItemGrid(int a_Width, int a_Height):
16  m_Width(a_Width),
17  m_Height(a_Height),
18  m_Slots(a_Width * a_Height),
19  m_IsInTriggerListeners(false)
20 {
21 }
22 
23 
24 
25 
26 
27 bool cItemGrid::IsValidSlotNum(int a_SlotNum) const
28 {
29  return ((a_SlotNum >= 0) && (a_SlotNum < m_Slots.size()));
30 }
31 
32 
33 
34 
35 
36 bool cItemGrid::IsValidSlotCoords(int a_X, int a_Y) const
37 {
38  return (
39  (a_X >= 0) && (a_X < m_Width) &&
40  (a_Y >= 0) && (a_Y < m_Height)
41  );
42 }
43 
44 
45 
46 
47 
48 int cItemGrid::GetSlotNum(int a_X, int a_Y) const
49 {
50  if (!IsValidSlotCoords(a_X, a_Y))
51  {
52  LOGWARNING("%s: coords out of range: (%d, %d) in grid of size (%d, %d)",
53  __FUNCTION__, a_X, a_Y, m_Width, m_Height
54  );
55  return -1;
56  }
57  return a_X + m_Width * a_Y;
58 }
59 
60 
61 
62 
63 
64 void cItemGrid::GetSlotCoords(int a_SlotNum, int & a_X, int & a_Y) const
65 {
66  if (!IsValidSlotNum(a_SlotNum))
67  {
68  LOGWARNING("%s: SlotNum out of range: %d in grid of range %d",
69  __FUNCTION__, a_SlotNum, m_Slots.size()
70  );
71  a_X = -1;
72  a_Y = -1;
73  return;
74  }
75  a_X = a_SlotNum % m_Width;
76  a_Y = a_SlotNum / m_Width;
77 }
78 
79 
80 
81 
82 
83 void cItemGrid::CopyFrom(const cItemGrid & a_Src)
84 {
85  m_Width = a_Src.m_Width;
86  m_Height = a_Src.m_Height;
87  m_Slots = a_Src.m_Slots;
88 
89  // The listeners are not copied
90 }
91 
92 
93 
94 
95 
96 const cItem & cItemGrid::GetSlot(int a_X, int a_Y) const
97 {
98  return GetSlot(GetSlotNum(a_X, a_Y));
99 }
100 
101 
102 
103 
104 
105 const cItem & cItemGrid::GetSlot(int a_SlotNum) const
106 {
107  if (!IsValidSlotNum(a_SlotNum))
108  {
109  LOGWARNING("%s: Invalid slot number, %d out of %d slots",
110  __FUNCTION__, a_SlotNum, m_Slots.size()
111  );
112  a_SlotNum = 0;
113  }
114  return m_Slots.GetAt(a_SlotNum);
115 }
116 
117 
118 
119 
120 
121 void cItemGrid::SetSlot(int a_X, int a_Y, const cItem & a_Item)
122 {
123  SetSlot(GetSlotNum(a_X, a_Y), a_Item);
124 }
125 
126 
127 
128 
129 
130 void cItemGrid::SetSlot(int a_X, int a_Y, short a_ItemType, char a_ItemCount, short a_ItemDamage)
131 {
132  SetSlot(GetSlotNum(a_X, a_Y), cItem(a_ItemType, a_ItemCount, a_ItemDamage));
133 }
134 
135 
136 
137 
138 
139 void cItemGrid::SetSlot(int a_SlotNum, const cItem & a_Item)
140 {
141  if (!IsValidSlotNum(a_SlotNum))
142  {
143  LOGWARNING("%s: Invalid slot number %d out of %d slots",
144  __FUNCTION__, a_SlotNum, m_Slots.size()
145  );
146  return;
147  }
148 
149  if (!a_Item.IsEmpty() || m_Slots.IsStorageAllocated())
150  {
151  m_Slots[a_SlotNum] = a_Item;
152  }
153  TriggerListeners(a_SlotNum);
154 }
155 
156 
157 
158 
159 
160 void cItemGrid::SetSlot(int a_SlotNum, short a_ItemType, char a_ItemCount, short a_ItemDamage)
161 {
162  SetSlot(a_SlotNum, cItem(a_ItemType, a_ItemCount, a_ItemDamage));
163 }
164 
165 
166 
167 
168 
169 void cItemGrid::EmptySlot(int a_X, int a_Y)
170 {
171  EmptySlot(GetSlotNum(a_X, a_Y));
172 }
173 
174 
175 
176 
177 
178 void cItemGrid::EmptySlot(int a_SlotNum)
179 {
180  if (!IsValidSlotNum(a_SlotNum))
181  {
182  LOGWARNING("%s: Invalid slot number %d out of %d slots",
183  __FUNCTION__, a_SlotNum, m_Slots.size()
184  );
185  return;
186  }
187 
188  // Check if already empty:
189  if (m_Slots.GetAt(a_SlotNum).IsEmpty())
190  {
191  return;
192  }
193 
194  // Empty and notify
195  m_Slots[a_SlotNum].Empty();
196  TriggerListeners(a_SlotNum);
197 }
198 
199 
200 
201 
202 
203 bool cItemGrid::IsSlotEmpty(int a_SlotNum) const
204 {
205  if (!IsValidSlotNum(a_SlotNum))
206  {
207  LOGWARNING("%s: Invalid slot number %d out of %d slots",
208  __FUNCTION__, a_SlotNum, m_Slots.size()
209  );
210  return true;
211  }
212  return m_Slots.GetAt(a_SlotNum).IsEmpty();
213 }
214 
215 
216 
217 
218 
219 bool cItemGrid::IsSlotEmpty(int a_X, int a_Y) const
220 {
221  return IsSlotEmpty(GetSlotNum(a_X, a_Y));
222 }
223 
224 
225 
226 
227 
229 {
231  {
232  return; // Already clear
233  }
234 
235  for (int i = 0; i < m_Slots.size(); i++)
236  {
237  m_Slots[i].Empty();
238  TriggerListeners(i);
239  }
240 }
241 
242 
243 
244 
245 
246 int cItemGrid::HowManyCanFit(const cItem & a_ItemStack, bool a_AllowNewStacks)
247 {
248  int NumLeft = a_ItemStack.m_ItemCount;
249  int MaxStack = a_ItemStack.GetMaxStackSize();
250 
252  {
253  // Grid is empty, all slots are available
254  return a_AllowNewStacks ? std::min(NumLeft, m_Slots.size() * MaxStack) : 0;
255  }
256 
257  for (const auto & Slot : m_Slots)
258  {
259  if (Slot.IsEmpty())
260  {
261  if (a_AllowNewStacks)
262  {
263  NumLeft -= MaxStack;
264  }
265  }
266  else if (Slot.IsEqual(a_ItemStack))
267  {
268  NumLeft -= MaxStack - Slot.m_ItemCount;
269  }
270  if (NumLeft <= 0)
271  {
272  // All items fit
273  return a_ItemStack.m_ItemCount;
274  }
275  } // for Slot - m_Slots[]
276  return a_ItemStack.m_ItemCount - NumLeft;
277 }
278 
279 
280 
281 
282 
283 char cItemGrid::AddItemToSlot(const cItem & a_ItemStack, int a_Slot, int a_Num, int a_MaxStack)
284 {
285  if (!IsValidSlotNum(a_Slot))
286  {
287  LOGWARNING("%s: Invalid slot number %d out of %d slots",
288  __FUNCTION__, a_Slot, m_Slots.size()
289  );
290  return 0;
291  }
292 
293  char PrevCount = 0;
294  if (m_Slots[a_Slot].IsEmpty())
295  {
296  m_Slots[a_Slot] = a_ItemStack;
297  PrevCount = 0;
298  }
299  else
300  {
301  PrevCount = m_Slots[a_Slot].m_ItemCount;
302  }
303  m_Slots[a_Slot].m_ItemCount = static_cast<char>(std::min(a_MaxStack, PrevCount + a_Num));
304  char toReturn = m_Slots[a_Slot].m_ItemCount - PrevCount;
305  TriggerListeners(a_Slot);
306  return toReturn;
307 }
308 
309 
310 
311 
312 
313 char cItemGrid::AddItem(cItem & a_ItemStack, bool a_AllowNewStacks, int a_PrioritySlot)
314 {
315  char NumLeft = a_ItemStack.m_ItemCount;
316  char MaxStack = a_ItemStack.GetMaxStackSize();
317 
318  if ((a_PrioritySlot != -1) && !IsValidSlotNum(a_PrioritySlot))
319  {
320  LOGWARNING("%s: Invalid slot number %d out of %d slots",
321  __FUNCTION__, a_PrioritySlot, m_Slots.size()
322  );
323  a_PrioritySlot = -1;
324  }
325 
326  if (!a_AllowNewStacks && !m_Slots.IsStorageAllocated())
327  {
328  return 0; // No existing stacks to add to
329  }
330 
331  // Try prioritySlot first:
332  if (
333  (a_PrioritySlot != -1) &&
334  (
335  m_Slots[a_PrioritySlot].IsEmpty() ||
336  m_Slots[a_PrioritySlot].IsEqual(a_ItemStack)
337  )
338  )
339  {
340  NumLeft -= AddItemToSlot(a_ItemStack, a_PrioritySlot, NumLeft, MaxStack);
341  }
342 
343  // Scan existing stacks:
344  for (int i = 0; i < m_Slots.size(); i++)
345  {
346  if (m_Slots[i].IsEqual(a_ItemStack))
347  {
348  NumLeft -= AddItemToSlot(a_ItemStack, i, NumLeft, MaxStack);
349  }
350  if (NumLeft <= 0)
351  {
352  // All items fit
353  return a_ItemStack.m_ItemCount;
354  }
355  } // for i - m_Slots[]
356 
357  if (!a_AllowNewStacks)
358  {
359  return (a_ItemStack.m_ItemCount - NumLeft);
360  }
361 
362  for (int i = 0; i < m_Slots.size(); i++)
363  {
364  if (m_Slots[i].IsEmpty())
365  {
366  NumLeft -= AddItemToSlot(a_ItemStack, i, NumLeft, MaxStack);
367  }
368  if (NumLeft <= 0)
369  {
370  // All items fit
371  return a_ItemStack.m_ItemCount;
372  }
373  } // for i - m_Slots[]
374  return (a_ItemStack.m_ItemCount - NumLeft);
375 }
376 
377 
378 
379 
380 
381 char cItemGrid::AddItems(cItems & a_ItemStackList, bool a_AllowNewStacks, int a_PrioritySlot)
382 {
383  char TotalAdded = 0;
384  for (cItems::iterator itr = a_ItemStackList.begin(); itr != a_ItemStackList.end();)
385  {
386  char NumAdded = AddItem(*itr, a_AllowNewStacks, a_PrioritySlot);
387  if (itr->m_ItemCount == NumAdded)
388  {
389  itr = a_ItemStackList.erase(itr);
390  }
391  else
392  {
393  itr->m_ItemCount -= NumAdded;
394  ++itr;
395  }
396  TotalAdded += NumAdded;
397  }
398  return TotalAdded;
399 }
400 
401 
402 
403 
404 
405 char cItemGrid::RemoveItem(const cItem & a_ItemStack)
406 {
407  char NumLeft = a_ItemStack.m_ItemCount;
408 
410  {
411  return 0; // No items to remove
412  }
413 
414  for (int i = 0; i < m_Slots.size(); i++)
415  {
416  if (NumLeft <= 0)
417  {
418  break;
419  }
420 
421  if (m_Slots[i].IsEqual(a_ItemStack))
422  {
423  char NumToRemove = std::min<char>(NumLeft, m_Slots[i].m_ItemCount);
424  NumLeft -= NumToRemove;
425  m_Slots[i].m_ItemCount -= NumToRemove;
426 
427  if (m_Slots[i].m_ItemCount <= 0)
428  {
429  m_Slots[i].Empty();
430  }
431 
432  TriggerListeners(i);
433  }
434  }
435 
436  return (a_ItemStack.m_ItemCount - NumLeft);
437 }
438 
439 
440 
441 
442 
443 cItem * cItemGrid::FindItem(const cItem & a_RecipeItem)
444 {
446  {
447  return nullptr;
448  }
449 
450  for (int i = 0; i < m_Slots.size(); i++)
451  {
452  // Items are equal if none is greater the other
453  auto compare = cItem::sItemCompare{};
454  if (!compare(a_RecipeItem, m_Slots[i]) &&
455  !compare(m_Slots[i], a_RecipeItem))
456  {
457  return &m_Slots[i];
458  }
459  }
460 
461  return nullptr;
462 }
463 
464 
465 
466 
467 
468 char cItemGrid::ChangeSlotCount(int a_SlotNum, char a_AddToCount)
469 {
470  if (!IsValidSlotNum(a_SlotNum))
471  {
472  LOGWARNING("%s: Invalid slot number %d out of %d slots, ignoring the call, returning -1",
473  __FUNCTION__, a_SlotNum, m_Slots.size()
474  );
475  return -1;
476  }
477 
478  if (m_Slots.GetAt(a_SlotNum).IsEmpty())
479  {
480  // The item is empty, it's not gonna change
481  return 0;
482  }
483 
484  if (m_Slots[a_SlotNum].m_ItemCount <= -a_AddToCount)
485  {
486  // Trying to remove more items than there already are, make the item empty
487  m_Slots[a_SlotNum].Empty();
488  TriggerListeners(a_SlotNum);
489  return 0;
490  }
491 
492  m_Slots[a_SlotNum].m_ItemCount += a_AddToCount;
493 
494  if (m_Slots[a_SlotNum].m_ItemCount > m_Slots[a_SlotNum].GetMaxStackSize())
495  {
496  m_Slots[a_SlotNum].m_ItemCount = m_Slots[a_SlotNum].GetMaxStackSize();
497  }
498 
499  TriggerListeners(a_SlotNum);
500  return m_Slots[a_SlotNum].m_ItemCount;
501 }
502 
503 
504 
505 
506 
507 char cItemGrid::ChangeSlotCount(int a_X, int a_Y, char a_AddToCount)
508 {
509  return ChangeSlotCount(GetSlotNum(a_X, a_Y), a_AddToCount);
510 }
511 
512 
513 
514 
515 
517 {
518  if (!IsValidSlotNum(a_SlotNum))
519  {
520  LOGWARNING("%s: Invalid slot number %d out of %d slots, ignoring the call, returning empty item",
521  __FUNCTION__, a_SlotNum, m_Slots.size()
522  );
523  return cItem();
524  }
525 
526  // If the slot is empty, return an empty item
527  if (m_Slots.GetAt(a_SlotNum).IsEmpty())
528  {
529  return cItem();
530  }
531 
532  // Make a copy of the item in slot, set count to 1 and remove one from the slot
533  cItem res = m_Slots[a_SlotNum];
534  res.m_ItemCount = 1;
535  m_Slots[a_SlotNum].m_ItemCount -= 1;
536 
537  // Emptying the slot correctly if appropriate
538  if (m_Slots[a_SlotNum].m_ItemCount == 0)
539  {
540  m_Slots[a_SlotNum].Empty();
541  }
542 
543  // Notify everyone of the change
544  TriggerListeners(a_SlotNum);
545 
546  // Return the stored one item
547  return res;
548 }
549 
550 
551 
552 
553 
555 {
556  return RemoveOneItem(GetSlotNum(a_X, a_Y));
557 }
558 
559 
560 
561 
562 
563 int cItemGrid::HowManyItems(const cItem & a_Item)
564 {
566  {
567  return 0;
568  }
569 
570  int res = 0;
571  for (auto & Slot : m_Slots)
572  {
573  if (Slot.IsEqual(a_Item))
574  {
575  res += Slot.m_ItemCount;
576  }
577  }
578  return res;
579 }
580 
581 
582 
583 
584 
585 bool cItemGrid::HasItems(const cItem & a_ItemStack)
586 {
587  int CurrentlyHave = HowManyItems(a_ItemStack);
588  return (CurrentlyHave >= a_ItemStack.m_ItemCount);
589 }
590 
591 
592 
593 
594 
596 {
597  return GetNextEmptySlot(-1);
598 }
599 
600 
601 
602 
603 
605 {
606  return GetNextUsedSlot(-1);
607 }
608 
609 
610 
611 
612 
614 {
615  for (int i = m_Slots.size() - 1; i >= 0; i--)
616  {
617  if (m_Slots.GetAt(i).IsEmpty())
618  {
619  return i;
620  }
621  }
622  return -1;
623 }
624 
625 
626 
627 
628 
630 {
632  {
633  return -1; // No slots are used
634  }
635 
636  for (int i = m_Slots.size() - 1; i >= 0; i--)
637  {
638  if (!m_Slots.GetAt(i).IsEmpty())
639  {
640  return i;
641  }
642  }
643  return -1;
644 }
645 
646 
647 
648 
649 
650 int cItemGrid::GetNextEmptySlot(int a_StartFrom) const
651 {
652  if ((a_StartFrom != -1) && !IsValidSlotNum(a_StartFrom))
653  {
654  LOGWARNING("%s: Invalid slot number %d out of %d slots",
655  __FUNCTION__, a_StartFrom, m_Slots.size()
656  );
657  a_StartFrom = -1;
658  }
659 
660  for (int i = a_StartFrom + 1; i < m_Slots.size(); i++)
661  {
662  if (m_Slots.GetAt(i).IsEmpty())
663  {
664  return i;
665  }
666  }
667  return -1;
668 }
669 
670 
671 
672 
673 
674 int cItemGrid::GetNextUsedSlot(int a_StartFrom) const
675 {
676  if ((a_StartFrom != -1) && !IsValidSlotNum(a_StartFrom))
677  {
678  LOGWARNING("%s: Invalid slot number %d out of %d slots",
679  __FUNCTION__, a_StartFrom, m_Slots.size()
680  );
681  a_StartFrom = -1;
682  }
683 
685  {
686  return -1; // No slots are used
687  }
688 
689  for (int i = a_StartFrom + 1; i < m_Slots.size(); i++)
690  {
691  if (!m_Slots.GetAt(i).IsEmpty())
692  {
693  return i;
694  }
695  }
696  return -1;
697 }
698 
699 
700 
701 
702 
703 void cItemGrid::CopyToItems(cItems & a_Items) const
704 {
706  {
707  return; // Nothing to copy
708  }
709 
710  for (const auto & Slot : m_Slots)
711  {
712  if (!Slot.IsEmpty())
713  {
714  a_Items.push_back(Slot);
715  }
716  } // for Slot - m_Slots[]
717 }
718 
719 
720 
721 
722 
723 bool cItemGrid::DamageItem(int a_SlotNum, short a_Amount)
724 {
725  if (!IsValidSlotNum(a_SlotNum))
726  {
727  LOGWARNING("%s: invalid slot number %d out of %d slots, ignoring.", __FUNCTION__, a_SlotNum, m_Slots.size());
728  return false;
729  }
730 
732  {
733  return false; // Nothing to damage
734  }
735 
736  return m_Slots[a_SlotNum].DamageItem(a_Amount);
737 }
738 
739 
740 
741 
742 
743 bool cItemGrid::DamageItem(int a_X, int a_Y, short a_Amount)
744 {
745  return DamageItem(GetSlotNum(a_X, a_Y), a_Amount);
746 }
747 
748 
749 
750 
751 
752 void cItemGrid::GenerateRandomLootWithBooks(const cLootProbab * a_LootProbabs, size_t a_CountLootProbabs, int a_NumSlots, int a_Seed)
753 {
754  // Calculate the total weight:
755  int TotalProbab = 1;
756  for (size_t i = 0; i < a_CountLootProbabs; i++)
757  {
758  TotalProbab += a_LootProbabs[i].m_Weight;
759  }
760 
761  // Pick the loot items:
762  cNoise Noise(a_Seed);
763  for (int i = 0; i < a_NumSlots; i++)
764  {
765  int Rnd = (Noise.IntNoise1DInt(i) / 7);
766  int LootRnd = Rnd % TotalProbab;
767  Rnd >>= 8;
768  cItem CurrentLoot = cItem(E_ITEM_ENCHANTED_BOOK, 1, 0);
769 
770  // Choose the enchantments
771  cWeightedEnchantments Enchantments;
772  cEnchantments::AddItemEnchantmentWeights(Enchantments, E_ITEM_BOOK, static_cast<unsigned>(24 + Noise.IntNoise2DInt(a_Seed, TotalProbab) % 7));
773  int NumEnchantments = Noise.IntNoise3DInt(TotalProbab, Rnd, a_Seed) % 5; // The number of enchantments this book wil get.
774 
775  for (int j = 0; j <= NumEnchantments; j++)
776  {
777  cEnchantments Enchantment = cEnchantments::SelectEnchantmentFromVector(Enchantments, Noise.IntNoise2DInt(NumEnchantments, i));
778  CurrentLoot.m_Enchantments.Add(Enchantment);
779  cEnchantments::RemoveEnchantmentWeightFromVector(Enchantments, Enchantment);
780  cEnchantments::CheckEnchantmentConflictsFromVector(Enchantments, Enchantment);
781  }
782 
783  for (size_t j = 0; j < a_CountLootProbabs; j++)
784  {
785  LootRnd -= a_LootProbabs[j].m_Weight;
786  if (LootRnd < 0)
787  {
788  CurrentLoot = a_LootProbabs[j].m_Item;
789  if ((a_LootProbabs[j].m_MaxAmount - a_LootProbabs[j].m_MinAmount) > 0)
790  {
791  CurrentLoot.m_ItemCount = static_cast<char>(a_LootProbabs[j].m_MinAmount + (Rnd % (a_LootProbabs[j].m_MaxAmount - a_LootProbabs[j].m_MinAmount)));
792  }
793  else
794  {
795  CurrentLoot.m_ItemCount = static_cast<char>(a_LootProbabs[j].m_MinAmount);
796  }
797  Rnd >>= 8;
798  break;
799  }
800  } // for j - a_LootProbabs[]
801  SetSlot(Rnd % m_Slots.size(), CurrentLoot);
802  } // for i - NumSlots
803 }
804 
805 
806 
807 
808 
810 {
811  cCSLock Lock(m_CSListeners);
812  ASSERT(!m_IsInTriggerListeners); // Must not call this while in TriggerListeners()
813  m_Listeners.push_back(&a_Listener);
814 }
815 
816 
817 
818 
819 
821 {
822  cCSLock Lock(m_CSListeners);
823  ASSERT(!m_IsInTriggerListeners); // Must not call this while in TriggerListeners()
824  for (cListeners::iterator itr = m_Listeners.begin(), end = m_Listeners.end(); itr != end; ++itr)
825  {
826  if (*itr == &a_Listener)
827  {
828  m_Listeners.erase(itr);
829  return;
830  }
831  } // for itr - m_Listeners[]
832 }
833 
834 
835 
836 
837 
838 void cItemGrid::TriggerListeners(int a_SlotNum)
839 {
840  cListeners Listeners;
841  {
842  cCSLock Lock(m_CSListeners);
843  m_IsInTriggerListeners = true;
844  Listeners = m_Listeners;
845  }
846  for (cListeners::iterator itr = Listeners.begin(), end = Listeners.end(); itr != end; ++itr)
847  {
848  (*itr)->OnSlotChanged(this, a_SlotNum);
849  } // for itr - m_Listeners[]
850  m_IsInTriggerListeners = false;
851 }
@ E_ITEM_BOOK
Definition: BlockType.h:385
@ E_ITEM_ENCHANTED_BOOK
Definition: BlockType.h:449
std::vector< cWeightedEnchantment > cWeightedEnchantments
Definition: Enchantments.h:23
#define ASSERT(x)
Definition: Globals.h:276
void LOGWARNING(std::string_view a_Format, const Args &... args)
Definition: LoggerSimple.h:67
Class that stores item enchantments or stored-enchantments The enchantments may be serialized to a st...
Definition: Enchantments.h:42
void Add(const cEnchantments &a_Other)
Adds the enchantments contained in a_Other into this object.
static cEnchantments SelectEnchantmentFromVector(const cWeightedEnchantments &a_Enchantments, int a_Seed)
Selects one enchantment from a Vector using cNoise.
static void RemoveEnchantmentWeightFromVector(cWeightedEnchantments &a_Enchantments, int a_EnchantmentID)
Remove the entire enchantment (with weight) from the vector.
static void CheckEnchantmentConflictsFromVector(cWeightedEnchantments &a_Enchantments, const cEnchantments &a_FirstEnchantment)
Check enchantment conflicts from enchantments from the vector.
static void AddItemEnchantmentWeights(cWeightedEnchantments &a_Enchantments, short a_ItemType, unsigned a_EnchantmentLevel)
Add enchantment weights from item to the vector.
Definition: Item.h:37
cEnchantments m_Enchantments
Definition: Item.h:166
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
Compares two items for the same type or category.
Definition: Item.h:183
This class bridges a vector of cItem for safe access via Lua.
Definition: Item.h:215
Used to store loot probability tables.
Definition: Item.h:260
int m_MinAmount
Definition: Item.h:263
cItem m_Item
Definition: Item.h:262
int m_Weight
Definition: Item.h:265
int m_MaxAmount
Definition: Item.h:264
int GetFirstEmptySlot(void) const
Returns the index of the first empty slot; -1 if all full.
Definition: ItemGrid.cpp:595
void GetSlotCoords(int a_SlotNum, int &a_X, int &a_Y) const
Converts slot number into XY coords; sets coords to -1 on invalid slot number.
Definition: ItemGrid.cpp:64
char AddItems(cItems &a_ItemStackList, bool a_AllowNewStacks=true, int a_PrioritySlot=-1)
Same as AddItem, but works on an entire list of item stacks.
Definition: ItemGrid.cpp:381
bool IsSlotEmpty(int a_SlotNum) const
Returns true if the specified slot is empty or the slot doesn't exist.
Definition: ItemGrid.cpp:203
bool IsValidSlotCoords(int a_X, int a_Y) const
Returns true if slot coordinates lie within the grid.
Definition: ItemGrid.cpp:36
void CopyFrom(const cItemGrid &a_Src)
Copies all items from a_Src to this grid.
Definition: ItemGrid.cpp:83
char ChangeSlotCount(int a_SlotNum, char a_AddToCount)
Adds (or subtracts, if a_AddToCount is negative) to the count of items in the specified slot.
Definition: ItemGrid.cpp:468
cItemGrid(int a_Width, int a_Height)
Definition: ItemGrid.cpp:15
cCriticalSection m_CSListeners
CS that guards the m_Listeners against multi-thread access.
Definition: ItemGrid.h:192
void TriggerListeners(int a_SlotNum)
Calls all m_Listeners for the specified slot number.
Definition: ItemGrid.cpp:838
int GetLastEmptySlot(void) const
Returns the index of the last empty slot; -1 if all full.
Definition: ItemGrid.cpp:613
void SetSlot(int a_X, int a_Y, const cItem &a_Item)
Definition: ItemGrid.cpp:121
int GetFirstUsedSlot(void) const
Returns the index of the first non-empty slot; -1 if all empty.
Definition: ItemGrid.cpp:604
std::vector< cListener * > cListeners
Definition: ItemGrid.h:33
int GetLastUsedSlot(void) const
Returns the index of the last used slot; -1 if all empty.
Definition: ItemGrid.cpp:629
char AddItemToSlot(const cItem &a_ItemStack, int a_Slot, int a_Num, int a_MaxStack)
Adds up to a_Num items out of a_ItemStack, as many as can fit, in specified slot Returns the number o...
Definition: ItemGrid.cpp:283
cLazyArray< cItem > m_Slots
Definition: ItemGrid.h:189
cItem * FindItem(const cItem &a_RecipeItem)
Finds an item based on ItemType and ItemDamage (<- defines the itemType, too)
Definition: ItemGrid.cpp:443
const cItem & GetSlot(int a_X, int a_Y) const
Definition: ItemGrid.cpp:96
int GetNextUsedSlot(int a_StartFrom) const
Returns the index of the first used slot following a_StartFrom (a_StartFrom is not checked)
Definition: ItemGrid.cpp:674
void Clear(void)
Sets all items as empty.
Definition: ItemGrid.cpp:228
void EmptySlot(int a_X, int a_Y)
Definition: ItemGrid.cpp:169
bool HasItems(const cItem &a_ItemStack)
Returns true if there are at least as many items of type a_ItemStack as in a_ItemStack.
Definition: ItemGrid.cpp:585
void GenerateRandomLootWithBooks(const cLootProbab *a_LootProbabs, size_t a_CountLootProbabs, int a_NumSlots, int a_Seed)
Generates random loot from the specified loot probability table, with a chance of enchanted books add...
Definition: ItemGrid.cpp:752
int m_Width
Definition: ItemGrid.h:187
int GetNextEmptySlot(int a_StartFrom) const
Returns the index of the first empty slot following a_StartFrom (a_StartFrom is not checked)
Definition: ItemGrid.cpp:650
bool IsValidSlotNum(int a_SlotNum) const
Returns true if slot number is within the grid.
Definition: ItemGrid.cpp:27
bool m_IsInTriggerListeners
Set to true while TriggerListeners is running, to detect attempts to manipulate listener list while t...
Definition: ItemGrid.h:193
cListeners m_Listeners
Listeners which should be notified on slot changes; the pointers are not owned by this object.
Definition: ItemGrid.h:191
void AddListener(cListener &a_Listener)
Adds a callback that gets called whenever a slot changes.
Definition: ItemGrid.cpp:809
int GetSlotNum(int a_X, int a_Y) const
Converts XY coords into slot number; returns -1 on invalid coords.
Definition: ItemGrid.cpp:48
int HowManyItems(const cItem &a_Item)
Returns the number of items of type a_Item that are stored.
Definition: ItemGrid.cpp:563
int HowManyCanFit(const cItem &a_ItemStack, bool a_AllowNewStacks=true)
Returns number of items out of a_ItemStack that can fit in the storage.
Definition: ItemGrid.cpp:246
char RemoveItem(const cItem &a_ItemStack)
Removes the specified item from the grid, as many as possible, up to a_ItemStack.m_ItemCount.
Definition: ItemGrid.cpp:405
void RemoveListener(cListener &a_Listener)
Removes a slot-change-callback.
Definition: ItemGrid.cpp:820
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...
Definition: ItemGrid.cpp:723
cItem RemoveOneItem(int a_SlotNum)
Removes one item from the stack in the specified slot, and returns it.
Definition: ItemGrid.cpp:516
char AddItem(cItem &a_ItemStack, bool a_AllowNewStacks=true, int a_PrioritySlot=-1)
Adds as many items out of a_ItemStack as can fit.
Definition: ItemGrid.cpp:313
void CopyToItems(cItems &a_Items) const
Copies the contents into a cItems object; preserves the original a_Items contents.
Definition: ItemGrid.cpp:703
int m_Height
Definition: ItemGrid.h:188
This class is used as a callback for when a slot changes.
Definition: ItemGrid.h:26
bool IsStorageAllocated() const noexcept
Returns true if the array has already been allocated.
Definition: LazyArray.h:127
const T & GetAt(size_type a_Idx) const
A const view of an element of the array.
Definition: LazyArray.h:112
size_type size() const noexcept
Definition: LazyArray.h:80
Definition: Noise.h:20
int IntNoise1DInt(int a_X) const
Definition: Noise.h:233
int IntNoise3DInt(int a_X, int a_Y, int a_Z) const
Definition: Noise.h:254
int IntNoise2DInt(int a_X, int a_Y) const
Definition: Noise.h:243
RAII for cCriticalSection - locks the CS on creation, unlocks on destruction.