Move git root from Client/ to src/ to track all source code: - Client: Game client source (moved to Client/Client/) - Server: Game server source - GameTools: Development tools - CryptoSource: Encryption utilities - database: Database scripts - Script: Game scripts - rylCoder_16.02.2008_src: Legacy coder tools - GMFont, Game: Additional resources 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
465 lines
13 KiB
C++
465 lines
13 KiB
C++
#include "stdafx.h"
|
|
|
|
#include <Log/ServerLog.h>
|
|
#include <Pattern/Singleton.h>
|
|
#include <Utility/Math/Math.h>
|
|
|
|
#include "Item.h"
|
|
#include "ItemFactory.h"
|
|
#include "ItemContainer.h"
|
|
|
|
namespace Item
|
|
{
|
|
class CNullItem : public CItem, public CSingleton<CNullItem>
|
|
{
|
|
public:
|
|
virtual ~CNullItem() { }
|
|
private:
|
|
|
|
CNullItem(const ItemInfo& itemInfo) : CItem(0, itemInfo) { }
|
|
|
|
static ItemInfo ms_thisiteminfo;
|
|
static CNullItem ms_this;
|
|
};
|
|
};
|
|
|
|
Item::ItemInfo Item::CNullItem::ms_thisiteminfo(0xFFFF);
|
|
Item::CNullItem Item::CNullItem::ms_this(Item::CNullItem::ms_thisiteminfo);
|
|
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
// CItemContainer
|
|
|
|
Item::CItemContainer::CItemContainer()
|
|
: m_dwCID(0), m_nMaxSize(0), m_lpNullItem(&CNullItem::GetInstance()),
|
|
m_lppItems(NULL), m_usFlags(0)
|
|
{
|
|
|
|
}
|
|
|
|
Item::CItemContainer::~CItemContainer()
|
|
{
|
|
Destroy();
|
|
}
|
|
|
|
|
|
bool Item::CItemContainer::Initialize(unsigned long dwCID, unsigned short nMaxSize)
|
|
{
|
|
m_dwCID = dwCID;
|
|
m_nMaxSize = nMaxSize;
|
|
|
|
m_lppItems = new CItem*[m_nMaxSize];
|
|
if(NULL != m_lppItems)
|
|
{
|
|
std::fill_n(m_lppItems, m_nMaxSize, reinterpret_cast<CItem*>(NULL));
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void Item::CItemContainer::Destroy()
|
|
{
|
|
if(NULL != m_lppItems)
|
|
{
|
|
CItem** lppItem = m_lppItems;
|
|
CItem** lppItemPastEnd = m_lppItems + m_nMaxSize;
|
|
|
|
for(; lppItem != lppItemPastEnd; ++lppItem)
|
|
{
|
|
CItem* lpItem = *lppItem;
|
|
if(NULL != lpItem && m_lpNullItem != lpItem)
|
|
{
|
|
delete lpItem;
|
|
}
|
|
}
|
|
|
|
delete [] m_lppItems;
|
|
m_lppItems = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
void Item::CItemContainer::DumpItemInfo()
|
|
{
|
|
const int MIN_BUFFER = 32;
|
|
const int MAX_BUFFER = 256;
|
|
char szUID[MIN_BUFFER];
|
|
char szBuffer[MAX_BUFFER];
|
|
|
|
CItem** lppItem = m_lppItems;
|
|
CItem** lppItemPastEnd = m_lppItems + m_nMaxSize;
|
|
|
|
for(; lppItem != lppItemPastEnd; ++lppItem)
|
|
{
|
|
const CItem* lpItem = *lppItem;
|
|
|
|
if(NULL != lpItem && m_lpNullItem != lpItem)
|
|
{
|
|
Math::Convert::Hex64ToStr(szUID, lpItem->GetUID());
|
|
|
|
const ItemPos itemPos = lpItem->GetPos();
|
|
const DetailData& detailData = lpItem->GetItemInfo().m_DetailData;
|
|
|
|
unsigned char cX, cY, cTab;
|
|
itemPos.GetPos(cX, cY, cTab);
|
|
|
|
_snprintf(szBuffer, MAX_BUFFER, "CID:0x%08x 의 아이템입니다. UID: %s 종류ID : %5d,"
|
|
" 좌표:(%d - %2d,%2d,%2d), 크기:(%2d, %2d), 현재 개수(내구도):%2d",
|
|
m_dwCID, szUID, lpItem->GetPrototypeID(), itemPos.m_cIndex, cX, cY, cTab,
|
|
detailData.m_cXSize, detailData.m_cXSize, lpItem->GetNumOrDurability());
|
|
|
|
ERRLOG1(g_Log, "%s", szBuffer);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
bool Item::CItemContainer::SerializeOut(char* szItemBuffer_Out, unsigned long& dwBufferSize_InOut) const
|
|
{
|
|
CItem** lppItem = m_lppItems;
|
|
CItem** lppItemPastEnd = m_lppItems + m_nMaxSize;
|
|
|
|
size_t nRemainBufferSize = static_cast<size_t>(dwBufferSize_InOut);
|
|
size_t nWritten = 0;
|
|
|
|
for(; lppItem != lppItemPastEnd; ++lppItem)
|
|
{
|
|
CItem* lpItem = *lppItem;
|
|
if(NULL != lpItem && m_lpNullItem != lpItem)
|
|
{
|
|
size_t nItemSize = nRemainBufferSize;
|
|
if(!lpItem->SerializeOut(szItemBuffer_Out + nWritten, nItemSize))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
nWritten += nItemSize;
|
|
nRemainBufferSize -= nItemSize;
|
|
}
|
|
}
|
|
|
|
dwBufferSize_InOut = static_cast<unsigned long>(nWritten);
|
|
return true;
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
// CArrayContainer
|
|
|
|
Item::CArrayContainer::CArrayContainer()
|
|
{
|
|
|
|
}
|
|
|
|
Item::CArrayContainer::~CArrayContainer()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
bool Item::CArrayContainer::Initialize(unsigned long dwCID, unsigned char nXSize, unsigned char nYSize, unsigned char nTabNum)
|
|
{
|
|
m_dwCID = dwCID;
|
|
m_nXSize = nXSize;
|
|
m_nYSize = nYSize;
|
|
m_nTabNum = nTabNum;
|
|
|
|
m_nSizePerTab = nXSize * nYSize;
|
|
return CItemContainer::Initialize(dwCID, nXSize * nYSize * nTabNum);
|
|
}
|
|
|
|
|
|
Item::CItem* Item::CArrayContainer::GetItem(Item::ItemPos itemPos)
|
|
{
|
|
unsigned char cX, cY, cTab;
|
|
itemPos.GetPos(cX, cY, cTab);
|
|
|
|
if(m_nXSize <= cX || m_nYSize <= cY || m_nTabNum <= cTab)
|
|
{
|
|
ERRLOG7(g_Log, "CID:0x%08x 아이템 위치가 올바르지 않습니다. X:%d/%d, Y:%d/%d, Tab:%d/%d",
|
|
m_dwCID, cX, m_nXSize, cY, m_nYSize, cTab, m_nTabNum);
|
|
return NULL;
|
|
}
|
|
|
|
CItem* lpItem = m_lppItems[m_nSizePerTab * cTab + m_nXSize * cY + cX];
|
|
return (lpItem != m_lpNullItem) ? lpItem : NULL;
|
|
}
|
|
|
|
|
|
bool Item::CArrayContainer::SetItem(Item::ItemPos itemPos, Item::CItem* lpItem)
|
|
{
|
|
if(NULL == lpItem)
|
|
{
|
|
ERRLOG1(g_Log, "CID:0x%08x 아이템이 NULL입니다.", m_dwCID);
|
|
return false;
|
|
}
|
|
|
|
unsigned char cX, cY, cTab;
|
|
itemPos.GetPos(cX, cY, cTab);
|
|
|
|
unsigned char cXSize = lpItem->GetItemInfo().m_DetailData.m_cXSize;
|
|
unsigned char cYSize = lpItem->GetItemInfo().m_DetailData.m_cYSize;
|
|
|
|
if(m_nXSize < static_cast<size_t>(cX + cXSize) ||
|
|
m_nYSize < static_cast<size_t>(cY + cYSize) || m_nTabNum <= cTab)
|
|
{
|
|
ERRLOG9(g_Log, "CID:0x%08x 아이템 위치 및 크기가 올바르지 않습니다. "
|
|
"X:%d/%d, Y:%d/%d, Tab:%d/%d, X크기:%d, Y크기:%d",
|
|
m_dwCID, cX, m_nXSize, cY, m_nYSize, cTab, m_nTabNum, cXSize, cYSize);
|
|
return false;
|
|
}
|
|
|
|
CItem** lppItemYIndexPastEnd = m_lppItems + m_nSizePerTab * cTab + m_nXSize * (cY + cYSize);
|
|
CItem **lppItemYIndex, **lppItemXIndex, **lppItemXIndexPastEnd;
|
|
|
|
for(lppItemYIndex = m_lppItems + m_nSizePerTab * cTab + cY * m_nXSize;
|
|
lppItemYIndex != lppItemYIndexPastEnd; lppItemYIndex += m_nXSize)
|
|
{
|
|
lppItemXIndexPastEnd = lppItemYIndex + cX + cXSize;
|
|
|
|
for(lppItemXIndex = lppItemYIndex + cX;
|
|
lppItemXIndex != lppItemXIndexPastEnd; ++lppItemXIndex)
|
|
{
|
|
if(0 != *lppItemXIndex)
|
|
{
|
|
ERRLOG4(g_Log, "CID:0x%08x (%d,%d,%d) 이미 그 장소에 아이템이 있습니다.",
|
|
m_dwCID, cX, cY, cTab);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
for(lppItemYIndex = m_lppItems + m_nSizePerTab * cTab + cY * m_nXSize;
|
|
lppItemYIndex != lppItemYIndexPastEnd; lppItemYIndex += m_nXSize)
|
|
{
|
|
lppItemXIndexPastEnd = lppItemYIndex + cX + cXSize;
|
|
|
|
for(lppItemXIndex = lppItemYIndex + cX;
|
|
lppItemXIndex != lppItemXIndexPastEnd; ++lppItemXIndex)
|
|
{
|
|
*lppItemXIndex = m_lpNullItem;
|
|
}
|
|
}
|
|
|
|
m_lppItems[m_nSizePerTab * cTab + m_nXSize * cY + cX] = lpItem;
|
|
lpItem->MoveItem(itemPos);
|
|
return true;
|
|
}
|
|
|
|
|
|
bool Item::CArrayContainer::RemoveItem(Item::ItemPos itemPos)
|
|
{
|
|
unsigned char cX, cY, cTab;
|
|
itemPos.GetPos(cX, cY, cTab);
|
|
|
|
if(m_nXSize <= cX || m_nYSize <= cY || m_nTabNum <= cTab)
|
|
{
|
|
ERRLOG7(g_Log, "CID:0x%08x 아이템 위치 및 크기가 올바르지 않습니다. X:%d/%d, Y:%d/%d, Tab:%d/%d",
|
|
m_dwCID, cX, m_nXSize, cY, m_nYSize, cTab, m_nTabNum);
|
|
return false;
|
|
}
|
|
|
|
CItem* lpItem = m_lppItems[m_nSizePerTab * cTab + m_nXSize * cY + cX];
|
|
if(NULL == lpItem)
|
|
{
|
|
ERRLOG4(g_Log, "CID:0x%08x 그 위치에 아이템이 없습니다. X:%d, Y:%d, Tab:%d", m_dwCID, cX, cY, cTab);
|
|
return false;
|
|
}
|
|
|
|
unsigned char cXSize = lpItem->GetItemInfo().m_DetailData.m_cXSize;
|
|
unsigned char cYSize = lpItem->GetItemInfo().m_DetailData.m_cYSize;
|
|
|
|
if(m_nXSize < static_cast<size_t>(cX + cXSize) ||
|
|
m_nYSize < static_cast<size_t>(cY + cYSize))
|
|
{
|
|
ERRLOG9(g_Log, "CID:0x%08x 아이템 위치 및 크기가 올바르지 않습니다. "
|
|
"X:%d/%d, Y:%d/%d, Tab:%d/%d, X크기:%d, Y크기:%d",
|
|
m_dwCID, cX, m_nXSize, cY, m_nYSize, cTab, m_nTabNum, cXSize, cYSize);
|
|
return false;
|
|
}
|
|
|
|
CItem** lppItemYIndexPastEnd = m_lppItems + m_nSizePerTab * cTab + m_nXSize * (cY + cYSize);
|
|
CItem **lppItemYIndex, **lppItemXIndex, **lppItemXIndexPastEnd;
|
|
|
|
for(lppItemYIndex = m_lppItems + m_nSizePerTab * cTab + cY * m_nXSize;
|
|
lppItemYIndex != lppItemYIndexPastEnd; lppItemYIndex += m_nXSize)
|
|
{
|
|
lppItemXIndexPastEnd = lppItemYIndex + cX + cXSize;
|
|
|
|
for(lppItemXIndex = lppItemYIndex + cX;
|
|
lppItemXIndex != lppItemXIndexPastEnd; ++lppItemXIndex)
|
|
{
|
|
*lppItemXIndex = NULL;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void Item::CArrayContainer::DumpItemInfo()
|
|
{
|
|
const int MAX_LINE = 128;
|
|
char szLine[MAX_LINE];
|
|
|
|
int nBufferPos = 0;
|
|
|
|
ERRLOG1(g_Log, "CID:0x%08x 의 아이템 로그를 시작합니다.", m_dwCID);
|
|
|
|
for(unsigned short nTab = 0; nTab < m_nTabNum; ++nTab)
|
|
{
|
|
const unsigned short usTabPos = m_nSizePerTab * nTab;
|
|
|
|
ERRLOG2(g_Log, "CID:0x%08x 의 탭 %d의 아이템입니다.", m_dwCID, nTab);
|
|
|
|
for(unsigned short nHeight = 0; nHeight < m_nYSize; ++nHeight)
|
|
{
|
|
const unsigned short nHeightPos = m_nXSize * nHeight + usTabPos;
|
|
|
|
nBufferPos = _snprintf(szLine, MAX_LINE, "CID:0x%08x 의 아이템입니다. ", m_dwCID);
|
|
|
|
for(unsigned short nWidth = 0; nWidth < m_nXSize; ++nWidth)
|
|
{
|
|
const CItem* lpItem = m_lppItems[nHeightPos + nWidth];
|
|
|
|
nBufferPos += _snprintf(szLine + nBufferPos, MAX_LINE, " %5d ",
|
|
((0 != lpItem) ? lpItem->GetPrototypeID() : 0));
|
|
}
|
|
|
|
ERRLOG0(g_Log, szLine);
|
|
}
|
|
}
|
|
|
|
CItemContainer::DumpItemInfo();
|
|
}
|
|
|
|
|
|
bool Item::CArrayContainer::SerializeIn(const char* szItemBuffer_In, unsigned long dwBufferSize_In)
|
|
{
|
|
size_t nBufferSize = static_cast<size_t>(dwBufferSize_In);
|
|
size_t nUsed = 0;
|
|
|
|
Item::CItemFactory& ItemFactory = CItemFactory::GetInstance();
|
|
|
|
while(nBufferSize > 0)
|
|
{
|
|
size_t nItemSize = nBufferSize;
|
|
Item::CItem* lpItem = ItemFactory.CreateItem(szItemBuffer_In + nUsed, nItemSize);
|
|
|
|
if(NULL == lpItem)
|
|
{
|
|
nItemSize = reinterpret_cast<const Item::ItemData*>(szItemBuffer_In + nUsed)->m_cItemSize;
|
|
ERRLOG1(g_Log, "CID:0x%08x 아이템 생성에 실패했습니다.", m_dwCID);
|
|
}
|
|
else if(!CArrayContainer::SetItem(lpItem->GetPos(), lpItem))
|
|
{
|
|
nItemSize = reinterpret_cast<const Item::ItemData*>(szItemBuffer_In + nUsed)->m_cItemSize;
|
|
ERRLOG1(g_Log, "CID:0x%08x 아이템 놓기를 실패했습니다.", m_dwCID);
|
|
delete lpItem;
|
|
}
|
|
|
|
nUsed += nItemSize;
|
|
nBufferSize -= nItemSize;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
// CListContainer
|
|
|
|
Item::CListContainer::CListContainer()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
Item::CListContainer::~CListContainer()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
Item::CItem* Item::CListContainer::GetItem(Item::ItemPos itemPos)
|
|
{
|
|
if(itemPos.m_cIndex < m_nMaxSize)
|
|
{
|
|
CItem* lpItem = m_lppItems[itemPos.m_cIndex];
|
|
return (lpItem != m_lpNullItem) ? lpItem : NULL;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
bool Item::CListContainer::SetItem(Item::ItemPos itemPos, Item::CItem* lpItem)
|
|
{
|
|
if(itemPos.m_cIndex < m_nMaxSize)
|
|
{
|
|
if(NULL == m_lppItems[itemPos.m_cIndex])
|
|
{
|
|
m_lppItems[itemPos.m_cIndex] = lpItem;
|
|
lpItem->MoveItem(itemPos);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
ERRLOG1(g_Log, "CID:0x%08x 아이템이 이미 존재합니다.", m_dwCID);
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
bool Item::CListContainer::RemoveItem(Item::ItemPos itemPos)
|
|
{
|
|
if(itemPos.m_cIndex < m_nMaxSize)
|
|
{
|
|
if(NULL != m_lppItems[itemPos.m_cIndex])
|
|
{
|
|
m_lppItems[itemPos.m_cIndex] = NULL;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
ERRLOG1(g_Log, "CID:0x%08x 아이템이 존재하지 않습니다.", m_dwCID);
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
bool Item::CListContainer::SerializeIn(const char* szItemBuffer_In, unsigned long dwBufferSize_In)
|
|
{
|
|
size_t nBufferSize = static_cast<size_t>(dwBufferSize_In);
|
|
size_t nUsed = 0;
|
|
|
|
Item::CItemFactory& ItemFactory = CItemFactory::GetInstance();
|
|
|
|
while(nBufferSize > 0)
|
|
{
|
|
size_t nItemSize = nBufferSize;
|
|
Item::CItem* lpItem = ItemFactory.CreateItem(szItemBuffer_In + nUsed, nItemSize);
|
|
|
|
if(NULL == lpItem)
|
|
{
|
|
nItemSize = reinterpret_cast<const Item::ItemData*>(szItemBuffer_In + nUsed)->m_cItemSize;
|
|
ERRLOG1(g_Log, "CID:0x%08x 아이템 생성에 실패했습니다.", m_dwCID);
|
|
}
|
|
else if(!CListContainer::SetItem(lpItem->GetPos(), lpItem))
|
|
{
|
|
nItemSize = reinterpret_cast<const Item::ItemData*>(szItemBuffer_In + nUsed)->m_cItemSize;
|
|
ERRLOG1(g_Log, "CID:0x%08x 아이템 놓기를 실패했습니다.", m_dwCID);
|
|
delete lpItem;
|
|
}
|
|
|
|
nUsed += nItemSize;
|
|
nBufferSize -= nItemSize;
|
|
}
|
|
|
|
return true;
|
|
} |