//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;
}
}
}
}
teşekürler
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; } } } }