cItemGrid: Allocate storage lazily (#4083)
* cItemGrid: Allocate storage lazily * cItemGrid: Fix spelling, Prioritary -> Priority
This commit is contained in:
190
src/ItemGrid.cpp
190
src/ItemGrid.cpp
@@ -12,11 +12,10 @@
|
||||
|
||||
|
||||
|
||||
cItemGrid::cItemGrid(int a_Width, int a_Height) :
|
||||
cItemGrid::cItemGrid(int a_Width, int a_Height):
|
||||
m_Width(a_Width),
|
||||
m_Height(a_Height),
|
||||
m_NumSlots(a_Width * a_Height),
|
||||
m_Slots(new cItem[a_Width * a_Height]),
|
||||
m_Slots(a_Width * a_Height),
|
||||
m_IsInTriggerListeners(false)
|
||||
{
|
||||
}
|
||||
@@ -25,19 +24,9 @@ cItemGrid::cItemGrid(int a_Width, int a_Height) :
|
||||
|
||||
|
||||
|
||||
cItemGrid::~cItemGrid()
|
||||
{
|
||||
delete[] m_Slots;
|
||||
m_Slots = nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cItemGrid::IsValidSlotNum(int a_SlotNum) const
|
||||
{
|
||||
return ((a_SlotNum >= 0) && (a_SlotNum < m_NumSlots));
|
||||
return ((a_SlotNum >= 0) && (a_SlotNum < m_Slots.size()));
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +66,7 @@ void cItemGrid::GetSlotCoords(int a_SlotNum, int & a_X, int & a_Y) const
|
||||
if (!IsValidSlotNum(a_SlotNum))
|
||||
{
|
||||
LOGWARNING("%s: SlotNum out of range: %d in grid of range %d",
|
||||
__FUNCTION__, a_SlotNum, m_NumSlots
|
||||
__FUNCTION__, a_SlotNum, m_Slots.size()
|
||||
);
|
||||
a_X = -1;
|
||||
a_Y = -1;
|
||||
@@ -93,12 +82,9 @@ void cItemGrid::GetSlotCoords(int a_SlotNum, int & a_X, int & a_Y) const
|
||||
|
||||
void cItemGrid::CopyFrom(const cItemGrid & a_Src)
|
||||
{
|
||||
ASSERT(m_Width == a_Src.m_Width);
|
||||
ASSERT(m_Height == a_Src.m_Height);
|
||||
for (int i = m_NumSlots - 1; i >= 0; --i)
|
||||
{
|
||||
m_Slots[i] = a_Src.m_Slots[i];
|
||||
}
|
||||
m_Width = a_Src.m_Width;
|
||||
m_Height = a_Src.m_Height;
|
||||
m_Slots = a_Src.m_Slots;
|
||||
|
||||
// The listeners are not copied
|
||||
}
|
||||
@@ -121,11 +107,11 @@ const cItem & cItemGrid::GetSlot(int a_SlotNum) const
|
||||
if (!IsValidSlotNum(a_SlotNum))
|
||||
{
|
||||
LOGWARNING("%s: Invalid slot number, %d out of %d slots",
|
||||
__FUNCTION__, a_SlotNum, m_NumSlots
|
||||
__FUNCTION__, a_SlotNum, m_Slots.size()
|
||||
);
|
||||
return m_Slots[0];
|
||||
a_SlotNum = 0;
|
||||
}
|
||||
return m_Slots[a_SlotNum];
|
||||
return m_Slots.GetAt(a_SlotNum);
|
||||
}
|
||||
|
||||
|
||||
@@ -155,11 +141,15 @@ void cItemGrid::SetSlot(int a_SlotNum, const cItem & a_Item)
|
||||
if (!IsValidSlotNum(a_SlotNum))
|
||||
{
|
||||
LOGWARNING("%s: Invalid slot number %d out of %d slots",
|
||||
__FUNCTION__, a_SlotNum, m_NumSlots
|
||||
__FUNCTION__, a_SlotNum, m_Slots.size()
|
||||
);
|
||||
return;
|
||||
}
|
||||
m_Slots[a_SlotNum] = a_Item;
|
||||
|
||||
if (!a_Item.IsEmpty() || m_Slots.IsStorageAllocated())
|
||||
{
|
||||
m_Slots[a_SlotNum] = a_Item;
|
||||
}
|
||||
TriggerListeners(a_SlotNum);
|
||||
}
|
||||
|
||||
@@ -190,13 +180,13 @@ void cItemGrid::EmptySlot(int a_SlotNum)
|
||||
if (!IsValidSlotNum(a_SlotNum))
|
||||
{
|
||||
LOGWARNING("%s: Invalid slot number %d out of %d slots",
|
||||
__FUNCTION__, a_SlotNum, m_NumSlots
|
||||
__FUNCTION__, a_SlotNum, m_Slots.size()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if already empty:
|
||||
if (m_Slots[a_SlotNum].IsEmpty())
|
||||
if (m_Slots.GetAt(a_SlotNum).IsEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -215,11 +205,11 @@ bool cItemGrid::IsSlotEmpty(int a_SlotNum) const
|
||||
if (!IsValidSlotNum(a_SlotNum))
|
||||
{
|
||||
LOGWARNING("%s: Invalid slot number %d out of %d slots",
|
||||
__FUNCTION__, a_SlotNum, m_NumSlots
|
||||
__FUNCTION__, a_SlotNum, m_Slots.size()
|
||||
);
|
||||
return true;
|
||||
}
|
||||
return m_Slots[a_SlotNum].IsEmpty();
|
||||
return m_Slots.GetAt(a_SlotNum).IsEmpty();
|
||||
}
|
||||
|
||||
|
||||
@@ -237,7 +227,12 @@ bool cItemGrid::IsSlotEmpty(int a_X, int a_Y) const
|
||||
|
||||
void cItemGrid::Clear(void)
|
||||
{
|
||||
for (int i = 0; i < m_NumSlots; i++)
|
||||
if (!m_Slots.IsStorageAllocated())
|
||||
{
|
||||
return; // Already clear
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_Slots.size(); i++)
|
||||
{
|
||||
m_Slots[i].Empty();
|
||||
TriggerListeners(i);
|
||||
@@ -250,27 +245,34 @@ void cItemGrid::Clear(void)
|
||||
|
||||
int cItemGrid::HowManyCanFit(const cItem & a_ItemStack, bool a_AllowNewStacks)
|
||||
{
|
||||
char NumLeft = a_ItemStack.m_ItemCount;
|
||||
int NumLeft = a_ItemStack.m_ItemCount;
|
||||
int MaxStack = ItemHandler(a_ItemStack.m_ItemType)->GetMaxStackSize();
|
||||
for (int i = m_NumSlots - 1; i >= 0; i--)
|
||||
|
||||
if (!m_Slots.IsStorageAllocated())
|
||||
{
|
||||
if (m_Slots[i].IsEmpty())
|
||||
// Grid is empty, all slots are available
|
||||
return a_AllowNewStacks ? std::min(NumLeft, m_Slots.size() * MaxStack) : 0;
|
||||
}
|
||||
|
||||
for (const auto & Slot : m_Slots)
|
||||
{
|
||||
if (Slot.IsEmpty())
|
||||
{
|
||||
if (a_AllowNewStacks)
|
||||
{
|
||||
NumLeft -= MaxStack;
|
||||
}
|
||||
}
|
||||
else if (m_Slots[i].IsEqual(a_ItemStack))
|
||||
else if (Slot.IsEqual(a_ItemStack))
|
||||
{
|
||||
NumLeft -= MaxStack - m_Slots[i].m_ItemCount;
|
||||
NumLeft -= MaxStack - Slot.m_ItemCount;
|
||||
}
|
||||
if (NumLeft <= 0)
|
||||
{
|
||||
// All items fit
|
||||
return a_ItemStack.m_ItemCount;
|
||||
}
|
||||
} // for i - m_Slots[]
|
||||
} // for Slot - m_Slots[]
|
||||
return a_ItemStack.m_ItemCount - NumLeft;
|
||||
}
|
||||
|
||||
@@ -283,7 +285,7 @@ int cItemGrid::AddItemToSlot(const cItem & a_ItemStack, int a_Slot, int a_Num, i
|
||||
if (!IsValidSlotNum(a_Slot))
|
||||
{
|
||||
LOGWARNING("%s: Invalid slot number %d out of %d slots",
|
||||
__FUNCTION__, a_Slot, m_NumSlots
|
||||
__FUNCTION__, a_Slot, m_Slots.size()
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
@@ -308,33 +310,38 @@ int cItemGrid::AddItemToSlot(const cItem & a_ItemStack, int a_Slot, int a_Num, i
|
||||
|
||||
|
||||
|
||||
int cItemGrid::AddItem(cItem & a_ItemStack, bool a_AllowNewStacks, int a_PrioritarySlot)
|
||||
int cItemGrid::AddItem(cItem & a_ItemStack, bool a_AllowNewStacks, int a_PrioritySlot)
|
||||
{
|
||||
int NumLeft = a_ItemStack.m_ItemCount;
|
||||
int MaxStack = a_ItemStack.GetMaxStackSize();
|
||||
|
||||
if ((a_PrioritarySlot != -1) && !IsValidSlotNum(a_PrioritarySlot))
|
||||
if ((a_PrioritySlot != -1) && !IsValidSlotNum(a_PrioritySlot))
|
||||
{
|
||||
LOGWARNING("%s: Invalid slot number %d out of %d slots",
|
||||
__FUNCTION__, a_PrioritarySlot, m_NumSlots
|
||||
__FUNCTION__, a_PrioritySlot, m_Slots.size()
|
||||
);
|
||||
a_PrioritarySlot = -1;
|
||||
a_PrioritySlot = -1;
|
||||
}
|
||||
|
||||
// Try prioritarySlot first:
|
||||
if (!a_AllowNewStacks && !m_Slots.IsStorageAllocated())
|
||||
{
|
||||
return 0; // No existing stacks to add to
|
||||
}
|
||||
|
||||
// Try prioritySlot first:
|
||||
if (
|
||||
(a_PrioritarySlot != -1) &&
|
||||
(a_PrioritySlot != -1) &&
|
||||
(
|
||||
m_Slots[a_PrioritarySlot].IsEmpty() ||
|
||||
m_Slots[a_PrioritarySlot].IsEqual(a_ItemStack)
|
||||
m_Slots[a_PrioritySlot].IsEmpty() ||
|
||||
m_Slots[a_PrioritySlot].IsEqual(a_ItemStack)
|
||||
)
|
||||
)
|
||||
{
|
||||
NumLeft -= AddItemToSlot(a_ItemStack, a_PrioritarySlot, NumLeft, MaxStack);
|
||||
NumLeft -= AddItemToSlot(a_ItemStack, a_PrioritySlot, NumLeft, MaxStack);
|
||||
}
|
||||
|
||||
// Scan existing stacks:
|
||||
for (int i = 0; i < m_NumSlots; i++)
|
||||
for (int i = 0; i < m_Slots.size(); i++)
|
||||
{
|
||||
if (m_Slots[i].IsEqual(a_ItemStack))
|
||||
{
|
||||
@@ -352,7 +359,7 @@ int cItemGrid::AddItem(cItem & a_ItemStack, bool a_AllowNewStacks, int a_Priorit
|
||||
return (a_ItemStack.m_ItemCount - NumLeft);
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_NumSlots; i++)
|
||||
for (int i = 0; i < m_Slots.size(); i++)
|
||||
{
|
||||
if (m_Slots[i].IsEmpty())
|
||||
{
|
||||
@@ -371,12 +378,12 @@ int cItemGrid::AddItem(cItem & a_ItemStack, bool a_AllowNewStacks, int a_Priorit
|
||||
|
||||
|
||||
|
||||
int cItemGrid::AddItems(cItems & a_ItemStackList, bool a_AllowNewStacks, int a_PrioritarySlot)
|
||||
int cItemGrid::AddItems(cItems & a_ItemStackList, bool a_AllowNewStacks, int a_PrioritySlot)
|
||||
{
|
||||
int TotalAdded = 0;
|
||||
for (cItems::iterator itr = a_ItemStackList.begin(); itr != a_ItemStackList.end();)
|
||||
{
|
||||
int NumAdded = AddItem(*itr, a_AllowNewStacks, a_PrioritarySlot);
|
||||
int NumAdded = AddItem(*itr, a_AllowNewStacks, a_PrioritySlot);
|
||||
if (itr->m_ItemCount == NumAdded)
|
||||
{
|
||||
itr = a_ItemStackList.erase(itr);
|
||||
@@ -399,7 +406,12 @@ int cItemGrid::RemoveItem(const cItem & a_ItemStack)
|
||||
{
|
||||
int NumLeft = a_ItemStack.m_ItemCount;
|
||||
|
||||
for (int i = 0; i < m_NumSlots; i++)
|
||||
if (!m_Slots.IsStorageAllocated())
|
||||
{
|
||||
return 0; // No items to remove
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_Slots.size(); i++)
|
||||
{
|
||||
if (NumLeft <= 0)
|
||||
{
|
||||
@@ -433,12 +445,12 @@ int cItemGrid::ChangeSlotCount(int a_SlotNum, int a_AddToCount)
|
||||
if (!IsValidSlotNum(a_SlotNum))
|
||||
{
|
||||
LOGWARNING("%s: Invalid slot number %d out of %d slots, ignoring the call, returning -1",
|
||||
__FUNCTION__, a_SlotNum, m_NumSlots
|
||||
__FUNCTION__, a_SlotNum, m_Slots.size()
|
||||
);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (m_Slots[a_SlotNum].IsEmpty())
|
||||
if (m_Slots.GetAt(a_SlotNum).IsEmpty())
|
||||
{
|
||||
// The item is empty, it's not gonna change
|
||||
return 0;
|
||||
@@ -482,13 +494,13 @@ cItem cItemGrid::RemoveOneItem(int a_SlotNum)
|
||||
if (!IsValidSlotNum(a_SlotNum))
|
||||
{
|
||||
LOGWARNING("%s: Invalid slot number %d out of %d slots, ignoring the call, returning empty item",
|
||||
__FUNCTION__, a_SlotNum, m_NumSlots
|
||||
__FUNCTION__, a_SlotNum, m_Slots.size()
|
||||
);
|
||||
return cItem();
|
||||
}
|
||||
|
||||
// If the slot is empty, return an empty item
|
||||
if (m_Slots[a_SlotNum].IsEmpty())
|
||||
if (m_Slots.GetAt(a_SlotNum).IsEmpty())
|
||||
{
|
||||
return cItem();
|
||||
}
|
||||
@@ -526,12 +538,17 @@ cItem cItemGrid::RemoveOneItem(int a_X, int a_Y)
|
||||
|
||||
int cItemGrid::HowManyItems(const cItem & a_Item)
|
||||
{
|
||||
int res = 0;
|
||||
for (int i = 0; i < m_NumSlots; i++)
|
||||
if (!m_Slots.IsStorageAllocated())
|
||||
{
|
||||
if (m_Slots[i].IsEqual(a_Item))
|
||||
return 0;
|
||||
}
|
||||
|
||||
int res = 0;
|
||||
for (auto & Slot : m_Slots)
|
||||
{
|
||||
if (Slot.IsEqual(a_Item))
|
||||
{
|
||||
res += m_Slots[i].m_ItemCount;
|
||||
res += Slot.m_ItemCount;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
@@ -571,9 +588,9 @@ int cItemGrid::GetFirstUsedSlot(void) const
|
||||
|
||||
int cItemGrid::GetLastEmptySlot(void) const
|
||||
{
|
||||
for (int i = m_NumSlots - 1; i >= 0; i--)
|
||||
for (int i = m_Slots.size() - 1; i >= 0; i--)
|
||||
{
|
||||
if (m_Slots[i].IsEmpty())
|
||||
if (m_Slots.GetAt(i).IsEmpty())
|
||||
{
|
||||
return i;
|
||||
}
|
||||
@@ -587,9 +604,14 @@ int cItemGrid::GetLastEmptySlot(void) const
|
||||
|
||||
int cItemGrid::GetLastUsedSlot(void) const
|
||||
{
|
||||
for (int i = m_NumSlots - 1; i >= 0; i--)
|
||||
if (!m_Slots.IsStorageAllocated())
|
||||
{
|
||||
if (!m_Slots[i].IsEmpty())
|
||||
return -1; // No slots are used
|
||||
}
|
||||
|
||||
for (int i = m_Slots.size() - 1; i >= 0; i--)
|
||||
{
|
||||
if (!m_Slots.GetAt(i).IsEmpty())
|
||||
{
|
||||
return i;
|
||||
}
|
||||
@@ -606,14 +628,14 @@ int cItemGrid::GetNextEmptySlot(int a_StartFrom) const
|
||||
if ((a_StartFrom != -1) && !IsValidSlotNum(a_StartFrom))
|
||||
{
|
||||
LOGWARNING("%s: Invalid slot number %d out of %d slots",
|
||||
__FUNCTION__, a_StartFrom, m_NumSlots
|
||||
__FUNCTION__, a_StartFrom, m_Slots.size()
|
||||
);
|
||||
a_StartFrom = -1;
|
||||
}
|
||||
|
||||
for (int i = a_StartFrom + 1; i < m_NumSlots; i++)
|
||||
for (int i = a_StartFrom + 1; i < m_Slots.size(); i++)
|
||||
{
|
||||
if (m_Slots[i].IsEmpty())
|
||||
if (m_Slots.GetAt(i).IsEmpty())
|
||||
{
|
||||
return i;
|
||||
}
|
||||
@@ -630,14 +652,19 @@ int cItemGrid::GetNextUsedSlot(int a_StartFrom) const
|
||||
if ((a_StartFrom != -1) && !IsValidSlotNum(a_StartFrom))
|
||||
{
|
||||
LOGWARNING("%s: Invalid slot number %d out of %d slots",
|
||||
__FUNCTION__, a_StartFrom, m_NumSlots
|
||||
__FUNCTION__, a_StartFrom, m_Slots.size()
|
||||
);
|
||||
a_StartFrom = -1;
|
||||
}
|
||||
|
||||
for (int i = a_StartFrom + 1; i < m_NumSlots; i++)
|
||||
if (!m_Slots.IsStorageAllocated())
|
||||
{
|
||||
if (!m_Slots[i].IsEmpty())
|
||||
return -1; // No slots are used
|
||||
}
|
||||
|
||||
for (int i = a_StartFrom + 1; i < m_Slots.size(); i++)
|
||||
{
|
||||
if (!m_Slots.GetAt(i).IsEmpty())
|
||||
{
|
||||
return i;
|
||||
}
|
||||
@@ -651,13 +678,18 @@ int cItemGrid::GetNextUsedSlot(int a_StartFrom) const
|
||||
|
||||
void cItemGrid::CopyToItems(cItems & a_Items) const
|
||||
{
|
||||
for (int i = 0; i < m_NumSlots; i++)
|
||||
if (!m_Slots.IsStorageAllocated())
|
||||
{
|
||||
if (!m_Slots[i].IsEmpty())
|
||||
return; // Nothing to copy
|
||||
}
|
||||
|
||||
for (const auto & Slot : m_Slots)
|
||||
{
|
||||
if (!Slot.IsEmpty())
|
||||
{
|
||||
a_Items.push_back(m_Slots[i]);
|
||||
a_Items.push_back(Slot);
|
||||
}
|
||||
} // for i - m_Slots[]
|
||||
} // for Slot - m_Slots[]
|
||||
}
|
||||
|
||||
|
||||
@@ -668,9 +700,15 @@ bool cItemGrid::DamageItem(int a_SlotNum, short a_Amount)
|
||||
{
|
||||
if (!IsValidSlotNum(a_SlotNum))
|
||||
{
|
||||
LOGWARNING("%s: invalid slot number %d out of %d slots, ignoring.", __FUNCTION__, a_SlotNum, m_NumSlots);
|
||||
LOGWARNING("%s: invalid slot number %d out of %d slots, ignoring.", __FUNCTION__, a_SlotNum, m_Slots.size());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_Slots.IsStorageAllocated())
|
||||
{
|
||||
return false; // Nothing to damage
|
||||
}
|
||||
|
||||
return m_Slots[a_SlotNum].DamageItem(a_Amount);
|
||||
}
|
||||
|
||||
@@ -736,7 +774,7 @@ void cItemGrid::GenerateRandomLootWithBooks(const cLootProbab * a_LootProbabs, s
|
||||
break;
|
||||
}
|
||||
} // for j - a_LootProbabs[]
|
||||
SetSlot(Rnd % m_NumSlots, CurrentLoot);
|
||||
SetSlot(Rnd % m_Slots.size(), CurrentLoot);
|
||||
} // for i - NumSlots
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user