Sorun:
Canavarlar,Simyalar, öğeler vb. için sabit boyutlu diziler içeren CHARACTER_POINT_INSTANT yapısını kullanılıyor. Her canavar için bu diziler bellek ayırıyor, ancak canavarlar bu belleği kullanmıyor.
Çözüm:
Sabit boyutlu dizileri std::map veya diğer veri türleri ile değiştirin
testlere göre, özel envanter sistemi ve aşağıda listelenen optimize edilmiş değişkenlerle bellek kullanımında %70'in üzerinde azalma görüldü.
C++:
//in char.cpp at the end of void CHARACTER::Initialize() function add
[HASH=2]#ifdef[/HASH] ENABLE_ITEM_GRID_MAP
m_pointsInstant.pItemsGridMap.clear();
[HASH=3]#endif[/HASH]
//in char.h after function LPITEM GetInventoryItem add
[HASH=2]#ifdef[/HASH] ENABLE_ITEM_GRID_MAP
BYTE ItemGridMapGetConst(BYTE cell_index) const;
[HASH=3]#endif[/HASH]
//in char.h replace BYTE bItemGrid[INVENTORY_AND_EQUIP_SLOT_MAX]; with
[HASH=2]#ifdef[/HASH] ENABLE_ITEM_GRID_MAP
std::map<BYTE, BYTE> pItemsGridMap;
[HASH=2311]#else[/HASH]
BYTE bItemGrid[INVENTORY_AND_EQUIP_SLOT_MAX];
[HASH=3]#endif[/HASH]
//in char_item.cpp replace function CHARACTER::SetItem with
void CHARACTER::SetItem(TItemPos Cell, LPITEM pItem)
{
WORD wCell = Cell.cell;
BYTE window_type = Cell.window_type;
if ((unsigned long)((CItem*)pItem) == 0xff || (unsigned long)((CItem*)pItem) == 0xffffffff)
{
sys_err("!!! FATAL ERROR !!! item == 0xff (char: %s cell: %u)", GetName(), wCell);
core_dump();
return;
}
if (pItem && pItem->GetOwner())
{
assert(!"GetOwner exist");
return;
}
switch(window_type)
{
case INVENTORY:
case EQUIPMENT:
{
if (wCell >= INVENTORY_AND_EQUIP_SLOT_MAX)
{
sys_err("CHARACTER::SetItem: invalid item cell %d", wCell);
return;
}
LPITEM pOld = m_pointsInstant.pItems[wCell];
if (pOld)
{
if (wCell < INVENTORY_MAX_NUM)
{
for (int i = 0; i < pOld->GetSize(); ++i)
{
int p = wCell + (i * 5);
if (p >= INVENTORY_MAX_NUM)
continue;
if (m_pointsInstant.pItems[p] && m_pointsInstant.pItems[p] != pOld)
continue;
[HASH=2]#ifdef[/HASH] ENABLE_ITEM_GRID_MAP
m_pointsInstant.pItemsGridMap[p] = 0;
[HASH=2311]#else[/HASH]
m_pointsInstant.bItemGrid[p] = 0;
[HASH=3]#endif[/HASH]
}
}
else
[HASH=2]#ifdef[/HASH] ENABLE_ITEM_GRID_MAP
m_pointsInstant.pItemsGridMap[wCell] = 0;
[HASH=2311]#else[/HASH]
m_pointsInstant.bItemGrid[wCell] = 0;
[HASH=3]#endif[/HASH]
}
if (pItem)
{
if (wCell < INVENTORY_MAX_NUM)
{
for (int i = 0; i < pItem->GetSize(); ++i)
{
int p = wCell + (i * 5);
if (p >= INVENTORY_MAX_NUM)
continue;
[HASH=2]#ifdef[/HASH] ENABLE_ITEM_GRID_MAP
m_pointsInstant.pItemsGridMap[p] = wCell + 1;
[HASH=2311]#else[/HASH]
m_pointsInstant.bItemGrid[p] = wCell + 1;
[HASH=3]#endif[/HASH]
}
}
else
[HASH=2]#ifdef[/HASH] ENABLE_ITEM_GRID_MAP
m_pointsInstant.pItemsGridMap[wCell] = wCell + 1;
[HASH=2311]#else[/HASH]
m_pointsInstant.bItemGrid[wCell] = wCell + 1;
[HASH=3]#endif[/HASH]
}
m_pointsInstant.pItems[wCell] = pItem;
}
break;
case DRAGON_SOUL_INVENTORY:
{
LPITEM pOld = m_pointsInstant.pDSItems[wCell];
if (pOld)
{
if (wCell < DRAGON_SOUL_INVENTORY_MAX_NUM)
{
for (int i = 0; i < pOld->GetSize(); ++i)
{
int p = wCell + (i * DRAGON_SOUL_BOX_COLUMN_NUM);
if (p >= DRAGON_SOUL_INVENTORY_MAX_NUM)
continue;
if (m_pointsInstant.pDSItems[p] && m_pointsInstant.pDSItems[p] != pOld)
continue;
m_pointsInstant.wDSItemGrid[p] = 0;
}
}
else
m_pointsInstant.wDSItemGrid[wCell] = 0;
}
if (pItem)
{
if (wCell >= DRAGON_SOUL_INVENTORY_MAX_NUM)
{
sys_err("CHARACTER::SetItem: invalid DS item cell %d", wCell);
return;
}
if (wCell < DRAGON_SOUL_INVENTORY_MAX_NUM)
{
for (int i = 0; i < pItem->GetSize(); ++i)
{
int p = wCell + (i * DRAGON_SOUL_BOX_COLUMN_NUM);
if (p >= DRAGON_SOUL_INVENTORY_MAX_NUM)
continue;
m_pointsInstant.wDSItemGrid[p] = wCell + 1;
}
}
else
m_pointsInstant.wDSItemGrid[wCell] = wCell + 1;
}
m_pointsInstant.pDSItems[wCell] = pItem;
}
break;
default:
sys_err ("Invalid Inventory type %d", window_type);
return;
}
if (GetDesc())
{
if (pItem)
{
TPacketGCItemSet pack;
pack.header = HEADER_GC_ITEM_SET;
pack.Cell = Cell;
pack.count = pItem->GetCount();
pack.vnum = pItem->GetVnum();
pack.flags = pItem->GetFlag();
pack.anti_flags = pItem->GetAntiFlag();
pack.highlight = (Cell.window_type == DRAGON_SOUL_INVENTORY);
thecore_memcpy(pack.alSockets, pItem->GetSockets(), sizeof(pack.alSockets));
thecore_memcpy(pack.aAttr, pItem->GetAttributes(), sizeof(pack.aAttr));
GetDesc()->Packet(&pack, sizeof(TPacketGCItemSet));
}
else
{
TPacketGCItemDelDeprecated pack;
pack.header = HEADER_GC_ITEM_DEL;
pack.Cell = Cell;
pack.count = 0;
pack.vnum = 0;
memset(pack.alSockets, 0, sizeof(pack.alSockets));
memset(pack.aAttr, 0, sizeof(pack.aAttr));
GetDesc()->Packet(&pack, sizeof(TPacketGCItemDelDeprecated));
}
}
if (pItem)
{
pItem->SetCell(this, wCell);
switch (window_type)
{
case INVENTORY:
case EQUIPMENT:
if ((wCell < INVENTORY_MAX_NUM) || (BELT_INVENTORY_SLOT_START <= wCell && BELT_INVENTORY_SLOT_END > wCell))
pItem->SetWindow(INVENTORY);
else
pItem->SetWindow(EQUIPMENT);
break;
case DRAGON_SOUL_INVENTORY:
pItem->SetWindow(DRAGON_SOUL_INVENTORY);
break;
}
}
}
[HASH=2]#ifdef[/HASH] ENABLE_ITEM_GRID_MAP
BYTE CHARACTER::ItemGridMapGetConst(BYTE cell_index) const
{
auto it = m_pointsInstant.pItemsGridMap.find(cell_index);
if (it != m_pointsInstant.pItemsGridMap.end())
{
return it->second;
}
else
{
return 0;
}
}
[HASH=3]#endif[/HASH]
//in char_item.cpp replace function CHARACTER::IsEmptyItemGrid with
bool CHARACTER::IsEmptyItemGrid(TItemPos Cell, BYTE bSize, int iExceptionCell) const
{
switch (Cell.window_type)
{
case INVENTORY:
{
BYTE bCell = Cell.cell;
++iExceptionCell;
if (Cell.IsBeltInventoryPosition())
{
LPITEM beltItem = GetWear(WEAR_BELT);
if (NULL == beltItem)
return false;
if (false == CBeltInventoryHelper::IsAvailableCell(bCell - BELT_INVENTORY_SLOT_START, beltItem->GetValue(0)))
return false;
[HASH=2]#ifdef[/HASH] ENABLE_ITEM_GRID_MAP
if (ItemGridMapGetConst(bCell))
{
if (ItemGridMapGetConst(bCell) == iExceptionCell)
return true;
return false;
}
[HASH=2311]#else[/HASH]
if (m_pointsInstant.bItemGrid[bCell])
{
if (m_pointsInstant.bItemGrid[bCell] == iExceptionCell)
return true;
return false;
}
[HASH=3]#endif[/HASH]
if (bSize == 1)
return true;
}
else if (bCell >= INVENTORY_MAX_NUM)
return false;
[HASH=2]#ifdef[/HASH] ENABLE_ITEM_GRID_MAP
if (ItemGridMapGetConst(bCell))
{
if (ItemGridMapGetConst(bCell) == iExceptionCell)
[HASH=2311]#else[/HASH]
if (m_pointsInstant.bItemGrid[bCell])
{
if (m_pointsInstant.bItemGrid[bCell] == iExceptionCell)
[HASH=3]#endif[/HASH]
{
if (bSize == 1)
return true;
int j = 1;
BYTE bPage = bCell / (INVENTORY_MAX_NUM / 2);
do
{
BYTE p = bCell + (5 * j);
if (p >= INVENTORY_MAX_NUM)
return false;
if (p / (INVENTORY_MAX_NUM / 2) != bPage)
return false;
[HASH=2]#ifdef[/HASH] ENABLE_ITEM_GRID_MAP
if (ItemGridMapGetConst(p))
if (ItemGridMapGetConst(p) != iExceptionCell)
return false;
[HASH=2311]#else[/HASH]
if (m_pointsInstant.bItemGrid[p])
if (m_pointsInstant.bItemGrid[p] != iExceptionCell)
return false;
[HASH=3]#endif[/HASH]
}
while (++j < bSize);
return true;
}
else
return false;
}
if (1 == bSize)
return true;
else
{
int j = 1;
BYTE bPage = bCell / (INVENTORY_MAX_NUM / 2);
do
{
BYTE p = bCell + (5 * j);
if (p >= INVENTORY_MAX_NUM)
return false;
if (p / (INVENTORY_MAX_NUM / 2) != bPage)
return false;
[HASH=2]#ifdef[/HASH] ENABLE_ITEM_GRID_MAP
if (ItemGridMapGetConst(p))
if (ItemGridMapGetConst(p) != iExceptionCell)
return false;
[HASH=2311]#else[/HASH]
if (m_pointsInstant.bItemGrid[p])
if (m_pointsInstant.bItemGrid[p] != iExceptionCell)
return false;
[HASH=3]#endif[/HASH]
}
while (++j < bSize);
return true;
}
}
break;
case DRAGON_SOUL_INVENTORY:
{
WORD wCell = Cell.cell;
if (wCell >= DRAGON_SOUL_INVENTORY_MAX_NUM)
return false;
iExceptionCell++;
if (m_pointsInstant.wDSItemGrid[wCell])
{
if (m_pointsInstant.wDSItemGrid[wCell] == iExceptionCell)
{
if (bSize == 1)
return true;
int j = 1;
do
{
BYTE p = wCell + (DRAGON_SOUL_BOX_COLUMN_NUM * j);
if (p >= DRAGON_SOUL_INVENTORY_MAX_NUM)
return false;
if (m_pointsInstant.wDSItemGrid[p])
if (m_pointsInstant.wDSItemGrid[p] != iExceptionCell)
return false;
}
while (++j < bSize);
return true;
}
else
return false;
}
if (1 == bSize)
return true;
else
{
int j = 1;
do
{
BYTE p = wCell + (DRAGON_SOUL_BOX_COLUMN_NUM * j);
if (p >= DRAGON_SOUL_INVENTORY_MAX_NUM)
return false;
[HASH=2]#ifdef[/HASH] ENABLE_ITEM_GRID_MAP
if (ItemGridMapGetConst(p))
[HASH=2311]#else[/HASH]
if (m_pointsInstant.bItemGrid[p])
[HASH=3]#endif[/HASH]
if (m_pointsInstant.wDSItemGrid[p] != iExceptionCell)
return false;
}
while (++j < bSize);
return true;
}
}
}
}