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 = ItemHandler(a_ItemStack.m_ItemType)->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 int 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  int 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  int toReturn = m_Slots[a_Slot].m_ItemCount - PrevCount;
305  TriggerListeners(a_Slot);
306  return toReturn;
307 }
308 
309 
310 
311 
312 
313 int cItemGrid::AddItem(cItem & a_ItemStack, bool a_AllowNewStacks, int a_PrioritySlot)
314 {
315  int NumLeft = a_ItemStack.m_ItemCount;
316  int 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 int cItemGrid::AddItems(cItems & a_ItemStackList, bool a_AllowNewStacks, int a_PrioritySlot)
382 {
383  int TotalAdded = 0;
384  for (cItems::iterator itr = a_ItemStackList.begin(); itr != a_ItemStackList.end();)
385  {
386  int 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 int cItemGrid::RemoveItem(const cItem & a_ItemStack)
406 {
407  int 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  int NumToRemove = std::min(NumLeft, static_cast<int>(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 int cItemGrid::ChangeSlotCount(int a_SlotNum, int a_AddToCount)
444 {
445  if (!IsValidSlotNum(a_SlotNum))
446  {
447  LOGWARNING("%s: Invalid slot number %d out of %d slots, ignoring the call, returning -1",
448  __FUNCTION__, a_SlotNum, m_Slots.size()
449  );
450  return -1;
451  }
452 
453  if (m_Slots.GetAt(a_SlotNum).IsEmpty())
454  {
455  // The item is empty, it's not gonna change
456  return 0;
457  }
458 
459  if (m_Slots[a_SlotNum].m_ItemCount <= -a_AddToCount)
460  {
461  // Trying to remove more items than there already are, make the item empty
462  m_Slots[a_SlotNum].Empty();
463  TriggerListeners(a_SlotNum);
464  return 0;
465  }
466 
467  m_Slots[a_SlotNum].m_ItemCount += a_AddToCount;
468 
469  cItemHandler * Handler = cItemHandler::GetItemHandler(m_Slots[a_SlotNum].m_ItemType);
470  if (m_Slots[a_SlotNum].m_ItemCount > Handler->GetMaxStackSize())
471  {
472  m_Slots[a_SlotNum].m_ItemCount = Handler->GetMaxStackSize();
473  }
474 
475  TriggerListeners(a_SlotNum);
476  return m_Slots[a_SlotNum].m_ItemCount;
477 }
478 
479 
480 
481 
482 
483 int cItemGrid::ChangeSlotCount(int a_X, int a_Y, int a_AddToCount)
484 {
485  return ChangeSlotCount(GetSlotNum(a_X, a_Y), a_AddToCount);
486 }
487 
488 
489 
490 
491 
493 {
494  if (!IsValidSlotNum(a_SlotNum))
495  {
496  LOGWARNING("%s: Invalid slot number %d out of %d slots, ignoring the call, returning empty item",
497  __FUNCTION__, a_SlotNum, m_Slots.size()
498  );
499  return cItem();
500  }
501 
502  // If the slot is empty, return an empty item
503  if (m_Slots.GetAt(a_SlotNum).IsEmpty())
504  {
505  return cItem();
506  }
507 
508  // Make a copy of the item in slot, set count to 1 and remove one from the slot
509  cItem res = m_Slots[a_SlotNum];
510  res.m_ItemCount = 1;
511  m_Slots[a_SlotNum].m_ItemCount -= 1;
512 
513  // Emptying the slot correctly if appropriate
514  if (m_Slots[a_SlotNum].m_ItemCount == 0)
515  {
516  m_Slots[a_SlotNum].Empty();
517  }
518 
519  // Notify everyone of the change
520  TriggerListeners(a_SlotNum);
521 
522  // Return the stored one item
523  return res;
524 }
525 
526 
527 
528 
529 
531 {
532  return RemoveOneItem(GetSlotNum(a_X, a_Y));
533 }
534 
535 
536 
537 
538 
539 int cItemGrid::HowManyItems(const cItem & a_Item)
540 {
542  {
543  return 0;
544  }
545 
546  int res = 0;
547  for (auto & Slot : m_Slots)
548  {
549  if (Slot.IsEqual(a_Item))
550  {
551  res += Slot.m_ItemCount;
552  }
553  }
554  return res;
555 }
556 
557 
558 
559 
560 
561 bool cItemGrid::HasItems(const cItem & a_ItemStack)
562 {
563  int CurrentlyHave = HowManyItems(a_ItemStack);
564  return (CurrentlyHave >= a_ItemStack.m_ItemCount);
565 }
566 
567 
568 
569 
570 
572 {
573  return GetNextEmptySlot(-1);
574 }
575 
576 
577 
578 
579 
581 {
582  return GetNextUsedSlot(-1);
583 }
584 
585 
586 
587 
588 
590 {
591  for (int i = m_Slots.size() - 1; i >= 0; i--)
592  {
593  if (m_Slots.GetAt(i).IsEmpty())
594  {
595  return i;
596  }
597  }
598  return -1;
599 }
600 
601 
602 
603 
604 
606 {
608  {
609  return -1; // No slots are used
610  }
611 
612  for (int i = m_Slots.size() - 1; i >= 0; i--)
613  {
614  if (!m_Slots.GetAt(i).IsEmpty())
615  {
616  return i;
617  }
618  }
619  return -1;
620 }
621 
622 
623 
624 
625 
626 int cItemGrid::GetNextEmptySlot(int a_StartFrom) const
627 {
628  if ((a_StartFrom != -1) && !IsValidSlotNum(a_StartFrom))
629  {
630  LOGWARNING("%s: Invalid slot number %d out of %d slots",
631  __FUNCTION__, a_StartFrom, m_Slots.size()
632  );
633  a_StartFrom = -1;
634  }
635 
636  for (int i = a_StartFrom + 1; i < m_Slots.size(); 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::GetNextUsedSlot(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 
661  {
662  return -1; // No slots are used
663  }
664 
665  for (int i = a_StartFrom + 1; i < m_Slots.size(); i++)
666  {
667  if (!m_Slots.GetAt(i).IsEmpty())
668  {
669  return i;
670  }
671  }
672  return -1;
673 }
674 
675 
676 
677 
678 
679 void cItemGrid::CopyToItems(cItems & a_Items) const
680 {
682  {
683  return; // Nothing to copy
684  }
685 
686  for (const auto & Slot : m_Slots)
687  {
688  if (!Slot.IsEmpty())
689  {
690  a_Items.push_back(Slot);
691  }
692  } // for Slot - m_Slots[]
693 }
694 
695 
696 
697 
698 
699 bool cItemGrid::DamageItem(int a_SlotNum, short a_Amount)
700 {
701  if (!IsValidSlotNum(a_SlotNum))
702  {
703  LOGWARNING("%s: invalid slot number %d out of %d slots, ignoring.", __FUNCTION__, a_SlotNum, m_Slots.size());
704  return false;
705  }
706 
708  {
709  return false; // Nothing to damage
710  }
711 
712  return m_Slots[a_SlotNum].DamageItem(a_Amount);
713 }
714 
715 
716 
717 
718 
719 bool cItemGrid::DamageItem(int a_X, int a_Y, short a_Amount)
720 {
721  return DamageItem(GetSlotNum(a_X, a_Y), a_Amount);
722 }
723 
724 
725 
726 
727 
728 void cItemGrid::GenerateRandomLootWithBooks(const cLootProbab * a_LootProbabs, size_t a_CountLootProbabs, int a_NumSlots, int a_Seed)
729 {
730  // Calculate the total weight:
731  int TotalProbab = 1;
732  for (size_t i = 0; i < a_CountLootProbabs; i++)
733  {
734  TotalProbab += a_LootProbabs[i].m_Weight;
735  }
736 
737  // Pick the loot items:
738  cNoise Noise(a_Seed);
739  for (int i = 0; i < a_NumSlots; i++)
740  {
741  int Rnd = (Noise.IntNoise1DInt(i) / 7);
742  int LootRnd = Rnd % TotalProbab;
743  Rnd >>= 8;
744  cItem CurrentLoot = cItem(E_ITEM_ENCHANTED_BOOK, 1, 0);
745 
746  // Choose the enchantments
747  cWeightedEnchantments Enchantments;
748  cEnchantments::AddItemEnchantmentWeights(Enchantments, E_ITEM_BOOK, 24 + Noise.IntNoise2DInt(a_Seed, TotalProbab) % 7);
749  int NumEnchantments = Noise.IntNoise3DInt(TotalProbab, Rnd, a_Seed) % 5; // The number of enchantments this book wil get.
750 
751  for (int j = 0; j <= NumEnchantments; j++)
752  {
753  cEnchantments Enchantment = cEnchantments::SelectEnchantmentFromVector(Enchantments, Noise.IntNoise2DInt(NumEnchantments, i));
754  CurrentLoot.m_Enchantments.Add(Enchantment);
755  cEnchantments::RemoveEnchantmentWeightFromVector(Enchantments, Enchantment);
756  cEnchantments::CheckEnchantmentConflictsFromVector(Enchantments, Enchantment);
757  }
758 
759  for (size_t j = 0; j < a_CountLootProbabs; j++)
760  {
761  LootRnd -= a_LootProbabs[j].m_Weight;
762  if (LootRnd < 0)
763  {
764  CurrentLoot = a_LootProbabs[j].m_Item;
765  if ((a_LootProbabs[j].m_MaxAmount - a_LootProbabs[j].m_MinAmount) > 0)
766  {
767  CurrentLoot.m_ItemCount = static_cast<char>(a_LootProbabs[j].m_MinAmount + (Rnd % (a_LootProbabs[j].m_MaxAmount - a_LootProbabs[j].m_MinAmount)));
768  }
769  else
770  {
771  CurrentLoot.m_ItemCount = static_cast<char>(a_LootProbabs[j].m_MinAmount);
772  }
773  Rnd >>= 8;
774  break;
775  }
776  } // for j - a_LootProbabs[]
777  SetSlot(Rnd % m_Slots.size(), CurrentLoot);
778  } // for i - NumSlots
779 }
780 
781 
782 
783 
784 
786 {
787  cCSLock Lock(m_CSListeners);
788  ASSERT(!m_IsInTriggerListeners); // Must not call this while in TriggerListeners()
789  m_Listeners.push_back(&a_Listener);
790 }
791 
792 
793 
794 
795 
797 {
798  cCSLock Lock(m_CSListeners);
799  ASSERT(!m_IsInTriggerListeners); // Must not call this while in TriggerListeners()
800  for (cListeners::iterator itr = m_Listeners.begin(), end = m_Listeners.end(); itr != end; ++itr)
801  {
802  if (*itr == &a_Listener)
803  {
804  m_Listeners.erase(itr);
805  return;
806  }
807  } // for itr - m_Listeners[]
808 }
809 
810 
811 
812 
813 
814 void cItemGrid::TriggerListeners(int a_SlotNum)
815 {
816  cListeners Listeners;
817  {
818  cCSLock Lock(m_CSListeners);
819  m_IsInTriggerListeners = true;
820  Listeners = m_Listeners;
821  }
822  for (cListeners::iterator itr = Listeners.begin(), end = Listeners.end(); itr != end; ++itr)
823  {
824  (*itr)->OnSlotChanged(this, a_SlotNum);
825  } // for itr - m_Listeners[]
826  m_IsInTriggerListeners = false;
827 }
828 
829 
830 
831 
int GetSlotNum(int a_X, int a_Y) const
Converts XY coords into slot number; returns -1 on invalid coords.
Definition: ItemGrid.cpp:48
std::vector< cListener * > cListeners
Definition: ItemGrid.h:33
void TriggerListeners(int a_SlotNum)
Calls all m_Listeners for the specified slot number.
Definition: ItemGrid.cpp:814
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:728
int GetFirstUsedSlot(void) const
Returns the index of the first non-empty slot; -1 if all empty.
Definition: ItemGrid.cpp:580
int m_MinAmount
Definition: Item.h:282
int IntNoise2DInt(int a_X, int a_Y) const
Definition: Noise.h:243
void EmptySlot(int a_X, int a_Y)
Definition: ItemGrid.cpp:169
void CopyFrom(const cItemGrid &a_Src)
Copies all items from a_Src to this grid.
Definition: ItemGrid.cpp:83
int HowManyItems(const cItem &a_Item)
Returns the number of items of type a_Item that are stored.
Definition: ItemGrid.cpp:539
int 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
cItemGrid(int a_Width, int a_Height)
Definition: ItemGrid.cpp:15
virtual char GetMaxStackSize(void)
Returns the maximum stack size for a given item.
int ChangeSlotCount(int a_SlotNum, int a_AddToCount)
Adds (or subtracts, if a_AddToCount is negative) to the count of items in the specified slot...
Definition: ItemGrid.cpp:443
static void RemoveEnchantmentWeightFromVector(cWeightedEnchantments &a_Enchantments, int a_EnchantmentID)
Remove the entire enchantment (with weight) from the vector.
bool IsEmpty(void) const
Definition: Item.h:116
static cItemHandler * GetItemHandler(int a_ItemType)
Definition: ItemHandler.cpp:74
int IntNoise3DInt(int a_X, int a_Y, int a_Z) const
Definition: Noise.h:254
int GetFirstEmptySlot(void) const
Returns the index of the first empty slot; -1 if all full.
Definition: ItemGrid.cpp:571
void CopyToItems(cItems &a_Items) const
Copies the contents into a cItems object; preserves the original a_Items contents.
Definition: ItemGrid.cpp:679
static void AddItemEnchantmentWeights(cWeightedEnchantments &a_Enchantments, short a_ItemType, int a_EnchantmentLevel)
Add enchantment weights from item to the vector.
cItem RemoveOneItem(int a_SlotNum)
Removes one item from the stack in the specified slot, and returns it.
Definition: ItemGrid.cpp:492
void Clear(void)
Sets all items as empty.
Definition: ItemGrid.cpp:228
This class is used as a callback for when a slot changes.
Definition: ItemGrid.h:25
cListeners m_Listeners
Listeners which should be notified on slot changes; the pointers are not owned by this object...
Definition: ItemGrid.h:188
void AddListener(cListener &a_Listener)
Adds a callback that gets called whenever a slot changes.
Definition: ItemGrid.cpp:785
bool IsSlotEmpty(int a_SlotNum) const
Returns true if the specified slot is empty or the slot doesn&#39;t exist.
Definition: ItemGrid.cpp:203
cEnchantments m_Enchantments
Definition: Item.h:212
int IntNoise1DInt(int a_X) const
Definition: Noise.h:233
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:561
std::vector< cWeightedEnchantment > cWeightedEnchantments
Definition: Enchantments.h:23
void RemoveListener(cListener &a_Listener)
Removes a slot-change-callback.
Definition: ItemGrid.cpp:796
bool m_IsInTriggerListeners
Set to true while TriggerListeners is running, to detect attempts to manipulate listener list while t...
Definition: ItemGrid.h:190
void Add(const cEnchantments &a_Other)
Adds the enchantments contained in a_Other into this object.
char m_ItemCount
Definition: Item.h:210
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
int m_Height
Definition: ItemGrid.h:185
int 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
#define ASSERT(x)
Definition: Globals.h:335
void LOGWARNING(const char *a_Format, fmt::ArgList a_ArgList)
Definition: Logger.cpp:174
int GetLastEmptySlot(void) const
Returns the index of the last empty slot; -1 if all full.
Definition: ItemGrid.cpp:589
size_type size() const NOEXCEPT
Definition: LazyArray.h:80
Definition: Noise.h:19
int GetLastUsedSlot(void) const
Returns the index of the last used slot; -1 if all empty.
Definition: ItemGrid.cpp:605
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:650
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
int m_MaxAmount
Definition: Item.h:283
cLazyArray< cItem > m_Slots
Definition: ItemGrid.h:186
char GetMaxStackSize(void) const
Returns the maximum amount of stacked items of this type.
Definition: Item.cpp:128
cCriticalSection m_CSListeners
CS that guards the m_Listeners against multi-thread access.
Definition: ItemGrid.h:189
bool IsValidSlotNum(int a_SlotNum) const
Returns true if slot number is within the grid.
Definition: ItemGrid.cpp:27
RAII for cCriticalSection - locks the CS on creation, unlocks on destruction.
Used to store loot probability tables.
Definition: Item.h:278
int m_Width
Definition: ItemGrid.h:184
int m_Weight
Definition: Item.h:284
bool IsValidSlotCoords(int a_X, int a_Y) const
Returns true if slot coordinates lie within the grid.
Definition: ItemGrid.cpp:36
Class that stores item enchantments or stored-enchantments The enchantments may be serialized to a st...
Definition: Enchantments.h:40
short m_ItemType
Definition: Item.h:209
const cItem & GetSlot(int a_X, int a_Y) const
Definition: ItemGrid.cpp:96
static void CheckEnchantmentConflictsFromVector(cWeightedEnchantments &a_Enchantments, cEnchantments a_FirstEnchantment)
Check enchantment conflicts from enchantments from the vector.
int 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
Definition: Item.h:36
int 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
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:626
cItemHandler * ItemHandler(int a_ItemType)
Definition: ItemHandler.h:174
cItem m_Item
Definition: Item.h:281
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
static cEnchantments SelectEnchantmentFromVector(const cWeightedEnchantments &a_Enchantments, int a_Seed)
Selects one enchantment from a Vector using cNoise.
This class bridges a vector of cItem for safe access via Lua.
Definition: Item.h:234
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:699
void SetSlot(int a_X, int a_Y, const cItem &a_Item)
Definition: ItemGrid.cpp:121