Restructure repository to include all source folders
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>
This commit is contained in:
380
GameTools/GLOBALSCRIPT/Item/ItemMgr.cpp
Normal file
380
GameTools/GLOBALSCRIPT/Item/ItemMgr.cpp
Normal file
@@ -0,0 +1,380 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include <Log/ServerLog.h>
|
||||
#include <Utility/Resource/EnsureCleanup.h>
|
||||
#include <Utility/Compress/MiniLZO/MiniLZOWrapper.h>
|
||||
#include <Network/XORCrypt/XORCrypt.h>
|
||||
#include "../Utility/TokenlizedFile.h"
|
||||
|
||||
#define DECODE_HEADER(Start_In, Length_In, PageVer_In, PageNum_In) CXORCrypt::GetInstance().DecodeHeader((Start_In),(Length_In),(PageVer_In),(PageNum_In))
|
||||
#define ENCODE_HEADER(Start_In, Length_In, PageVer_In, PageNum_In) CXORCrypt::GetInstance().EncodeHeader((Start_In),(Length_In),(PageVer_In),(PageNum_In))
|
||||
#define COMPRESS(In, In_len, Out, Out_len) CMiniLZOCompress::Compress((In), (In_len), (Out), (Out_len))
|
||||
#define DECOMPRESS(In, In_len, Out, Out_len) CMiniLZOCompress::Decompress((In), (In_len), (Out), (Out_len))
|
||||
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
|
||||
#include "ItemMgr.h"
|
||||
#include "ItemDataParser.h"
|
||||
|
||||
|
||||
|
||||
#ifdef _TEST_SERVER_
|
||||
const char* Item::CItemMgr::ms_szItemScriptFileName = "TestItemScript.txt";
|
||||
#else
|
||||
const char* Item::CItemMgr::ms_szItemScriptFileName = "ItemScript.txt";
|
||||
#endif
|
||||
|
||||
|
||||
Item::CItemMgr Item::CItemMgr::ms_this;
|
||||
|
||||
using namespace Item;
|
||||
|
||||
|
||||
class CParseDelimitedData
|
||||
{
|
||||
public:
|
||||
|
||||
CParseDelimitedData(CTokenlizedFile& TokenlizedFile) : m_TokenlizedFile(TokenlizedFile) { }
|
||||
|
||||
bool operator() (ItemDataParser::ParseDataArray& ParserArray, Item::ItemInfo& itemInfo)
|
||||
{
|
||||
for (ItemDataParser::ParseDataArray::iterator itr = ParserArray.begin();
|
||||
itr != ParserArray.end(); ++itr)
|
||||
{
|
||||
const char* szValue = m_TokenlizedFile.GetStringValue(itr->m_szColumnName);
|
||||
|
||||
if (NULL == szValue)
|
||||
{
|
||||
ERRLOG2(g_Log, "데이터를 읽어올 수 없습니다. Line:%d, ColumnName:%d",
|
||||
m_TokenlizedFile.GetCurrentLine(), itr->m_szColumnName);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!itr->m_fnParseFunc(itemInfo, szValue))
|
||||
{
|
||||
ERRLOG2(g_Log, "알맞은 데이터가 아닙니다. Line:%d, ColumnName:%d",
|
||||
m_TokenlizedFile.GetCurrentLine(), itr->m_szColumnName);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
CTokenlizedFile& m_TokenlizedFile;
|
||||
};
|
||||
|
||||
|
||||
CItemMgr::CItemMgr()
|
||||
: m_ItemInfoArray(NULL), m_nItemNum(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CItemMgr::~CItemMgr()
|
||||
{
|
||||
DestoryItemInfo();
|
||||
}
|
||||
|
||||
void CItemMgr::DestoryItemInfo()
|
||||
{
|
||||
if (NULL != m_ItemInfoArray)
|
||||
{
|
||||
delete [] m_ItemInfoArray;
|
||||
m_ItemInfoArray = NULL;
|
||||
}
|
||||
|
||||
m_nItemNum = 0;
|
||||
}
|
||||
|
||||
bool CItemMgr::LoadItemProtoType(const char* szFileName)
|
||||
{
|
||||
DestoryItemInfo();
|
||||
|
||||
Item::ItemInfo itemInfo;
|
||||
CTokenlizedFile TokenlizedFile; // 객체 소멸시, 자동 Close.
|
||||
|
||||
if (!TokenlizedFile.Open((NULL != szFileName) ? szFileName : ms_szItemScriptFileName))
|
||||
{
|
||||
ERRLOG0(g_Log, "아이템 스크립트 파일 로딩에 실패했습니다.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TokenlizedFile.ReadColumn())
|
||||
{
|
||||
ERRLOG0(g_Log, "아이템 스크립트 컬럼을 읽어오는 데 실패했습니다.");
|
||||
return false;
|
||||
}
|
||||
|
||||
ItemDataParser::ParseDataArray DefaultItemData;
|
||||
ItemDataParser::ParseDataArray EquipItemData;
|
||||
ItemDataParser::ParseDataArray UseItemData;
|
||||
ItemDataParser::ParseDataArray EtcItemData;
|
||||
|
||||
ItemDataParser::SetDefaultData(DefaultItemData);
|
||||
ItemDataParser::SetEquipData(EquipItemData);
|
||||
ItemDataParser::SetUseItemData(UseItemData);
|
||||
ItemDataParser::SetEtcItemData(EtcItemData);
|
||||
|
||||
Item::CItemType& ItemType = Item::CItemType::GetInstance();
|
||||
|
||||
std::vector<Item::ItemInfo> ItemInfoVector;
|
||||
|
||||
CParseDelimitedData ParseData(TokenlizedFile);
|
||||
|
||||
while(TokenlizedFile.ReadLine())
|
||||
{
|
||||
itemInfo.Initialize();
|
||||
|
||||
if (!ParseData(DefaultItemData, itemInfo)) { return false; }
|
||||
|
||||
if (ItemType.IsCorrectItemType(Item::CItemType::EQUIP_TYPE,
|
||||
itemInfo.m_DetailData.m_cItemType))
|
||||
{
|
||||
// 장비 아이템.
|
||||
if (!ParseData(EquipItemData, itemInfo)) { return false; }
|
||||
ItemType.SetEquipTypeFlags(itemInfo);
|
||||
}
|
||||
else if (ItemType.IsCorrectItemType(Item::CItemType::USE_ITEM_TYPE,
|
||||
itemInfo.m_DetailData.m_cItemType))
|
||||
{
|
||||
// 사용 아이템.
|
||||
if (!ParseData(UseItemData, itemInfo)) { return false; }
|
||||
ItemType.SetUseItemTypeFlags(itemInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 기타 아이템.
|
||||
if (!ParseData(EtcItemData, itemInfo)) { return false; }
|
||||
ItemType.SetEtcItemTypeFlags(itemInfo);
|
||||
}
|
||||
|
||||
ItemInfoVector.push_back(itemInfo);
|
||||
}
|
||||
|
||||
if (!TokenlizedFile.IsEOF())
|
||||
{
|
||||
ERRLOG0(g_Log, "아이템 스크립트 파일을 다 읽지 못하고 종료합니다.");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::sort(ItemInfoVector.begin(), ItemInfoVector.end());
|
||||
|
||||
for (std::vector<Item::ItemInfo>::iterator itr = ItemInfoVector.begin();
|
||||
itr != ItemInfoVector.end() - 1; ++itr)
|
||||
{
|
||||
if (itr->m_usProtoTypeID == (itr+1)->m_usProtoTypeID)
|
||||
{
|
||||
ERRLOG1(g_Log, "겹치는 아이템 종류 ID가 있습니다. 종류ID:%d", itr->m_usProtoTypeID);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
m_nItemNum = ItemInfoVector.size();
|
||||
m_ItemInfoArray = new Item::ItemInfo[m_nItemNum];
|
||||
if (NULL == m_ItemInfoArray)
|
||||
{
|
||||
ERRLOG0(g_Log, "아이템 스크립트 내용을 복사할 수 없습니다. 메모리가 부족합니다.");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::copy(ItemInfoVector.begin(), ItemInfoVector.end(), m_ItemInfoArray);
|
||||
return true;
|
||||
}
|
||||
|
||||
const Item::ItemInfo* CItemMgr::GetItemInfo(unsigned short usProtoTypeID)
|
||||
{
|
||||
Item::ItemInfo* lpFirst = m_ItemInfoArray;
|
||||
Item::ItemInfo* lpLast = m_ItemInfoArray + m_nItemNum;
|
||||
Item::ItemInfo* lpMid = NULL;
|
||||
|
||||
size_t nCount = m_nItemNum;
|
||||
size_t nCount2 = 0;
|
||||
|
||||
for (; 0 < nCount; )
|
||||
{
|
||||
nCount2 = nCount / 2;
|
||||
lpMid = lpFirst + nCount2;
|
||||
|
||||
if (lpMid->m_usProtoTypeID < usProtoTypeID)
|
||||
{
|
||||
lpFirst = ++lpMid, nCount -= nCount2 + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
nCount = nCount2;
|
||||
}
|
||||
}
|
||||
|
||||
return (lpFirst != lpLast && !(usProtoTypeID < lpFirst->m_usProtoTypeID)) ? lpFirst : NULL;
|
||||
}
|
||||
|
||||
const Item::ItemInfo* CItemMgr::GetItemInfoFromItemName(const char* szItemName)
|
||||
{
|
||||
Item::ItemInfo* lpFirst = m_ItemInfoArray;
|
||||
Item::ItemInfo* lpLast = m_ItemInfoArray + m_nItemNum;
|
||||
|
||||
for (; lpFirst != lpLast; ++lpFirst)
|
||||
{
|
||||
if (0 == strcmp(lpFirst->m_SpriteData.m_szName, szItemName))
|
||||
{
|
||||
return lpFirst;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const Item::ItemInfo* CItemMgr::GetItemInfoFromEquipName(const char* szEquipName)
|
||||
{
|
||||
Item::ItemInfo* lpFirst = m_ItemInfoArray;
|
||||
Item::ItemInfo* lpLast = m_ItemInfoArray + m_nItemNum;
|
||||
|
||||
for (; lpFirst != lpLast; ++lpFirst)
|
||||
{
|
||||
if (0 == strcmp(lpFirst->m_StringData.m_szEquipModelName, szEquipName))
|
||||
{
|
||||
return lpFirst;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
const char* Item::CItemMgr::GetEquipName(const unsigned short usItemProtoTypeID)
|
||||
{
|
||||
const Item::ItemInfo* pItemInfo = GetItemInfo(usItemProtoTypeID);
|
||||
|
||||
if(pItemInfo)
|
||||
{
|
||||
return pItemInfo->m_StringData.m_szEquipModelName;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
const unsigned short CItemMgr::GetItemIDFromSkillID(const unsigned short usSkill_ID, const unsigned short unSkill_LockCount)
|
||||
{
|
||||
Item::ItemInfo* lpFirst = m_ItemInfoArray;
|
||||
Item::ItemInfo* lpLast = m_ItemInfoArray + m_nItemNum;
|
||||
|
||||
for (; lpFirst != lpLast; ++lpFirst)
|
||||
{
|
||||
if (lpFirst->m_UseItemInfo.m_usSkill_ID == usSkill_ID &&
|
||||
lpFirst->m_UseItemInfo.m_usSkill_LockCount == unSkill_LockCount)
|
||||
{
|
||||
return lpFirst->m_usProtoTypeID;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool CItemMgr::LoadItemProtoTypeBinary(const char* szFileNameBinary)
|
||||
{
|
||||
using namespace Item;
|
||||
|
||||
HANDLE hFile = CreateFile((0 == szFileNameBinary) ? ms_szItemScriptFileName : szFileNameBinary,
|
||||
GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (hFile == INVALID_HANDLE_VALUE) { return false; }
|
||||
|
||||
CEnsureCloseHandle EnsureCloseHandle(hFile);
|
||||
|
||||
DWORD dwRead = 0;
|
||||
DWORD dwFileHighSize = 0;
|
||||
DWORD dwFileSize = GetFileSize(hFile, &dwFileHighSize);
|
||||
|
||||
char* lpAllocated = new char[dwFileSize];
|
||||
CEnsureDeleteArray<char> EnsureFileInfo(lpAllocated);
|
||||
|
||||
if (!ReadFile(hFile, lpAllocated, dwFileSize, &dwRead, NULL))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD dwHeaderSize = sizeof(DWORD) + *reinterpret_cast<DWORD*>(lpAllocated) + sizeof(DWORD);
|
||||
DWORD dwDecompressedSize = *reinterpret_cast<DWORD*>(lpAllocated + dwHeaderSize - sizeof(DWORD));
|
||||
|
||||
DestoryItemInfo();
|
||||
|
||||
m_nItemNum = dwDecompressedSize/sizeof(Item::ItemInfo);
|
||||
m_ItemInfoArray = new Item::ItemInfo[m_nItemNum];
|
||||
if (NULL == m_ItemInfoArray)
|
||||
{
|
||||
ERRLOG0(g_Log, "아이템 스크립트 내용을 불러올 수 없습니다. 메모리가 부족합니다.");
|
||||
return false;
|
||||
}
|
||||
|
||||
DECOMPRESS(lpAllocated + dwHeaderSize, dwFileSize - dwHeaderSize,
|
||||
reinterpret_cast<char*>(m_ItemInfoArray), &dwDecompressedSize);
|
||||
|
||||
DECODE_HEADER(reinterpret_cast<char*>(m_ItemInfoArray), dwDecompressedSize, 0, 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CItemMgr::SaveItemProtoTypeBinary(const char* szFileNameBinary, const char* szTrashFile)
|
||||
{
|
||||
HANDLE hFile = CreateFile((0 == szFileNameBinary) ? ms_szItemScriptFileName : szFileNameBinary,
|
||||
GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (hFile == INVALID_HANDLE_VALUE) { return false; }
|
||||
|
||||
CEnsureCloseHandle EnsureCloseSaveHandle(hFile);
|
||||
|
||||
DWORD nItemInfoSize = static_cast<DWORD>(sizeof(Item::ItemInfo) * m_nItemNum);
|
||||
DWORD nCompressedInfoSize = nItemInfoSize;
|
||||
|
||||
char* lpItemInfo = new char[nItemInfoSize];
|
||||
char* lpCompressedInfo = new char[nItemInfoSize];
|
||||
|
||||
CEnsureDeleteArray<char> EnsureDeleteItemInfo(lpItemInfo);
|
||||
CEnsureDeleteArray<char> EnsureDeleteCompressedInfo(lpCompressedInfo);
|
||||
|
||||
if (0 == lpItemInfo || 0 == lpCompressedInfo)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(lpItemInfo, m_ItemInfoArray, nItemInfoSize);
|
||||
ENCODE_HEADER(lpItemInfo, nItemInfoSize, 0, 2);
|
||||
COMPRESS(lpItemInfo, nItemInfoSize, lpCompressedInfo, &nCompressedInfoSize);
|
||||
|
||||
// 쓰레기(더미) 자료
|
||||
HANDLE hTrashFile = CreateFile(szTrashFile, GENERIC_READ, FILE_SHARE_READ,
|
||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (hTrashFile == INVALID_HANDLE_VALUE) { return false; }
|
||||
|
||||
CEnsureCloseHandle EnsureCloseTrashHandle(hTrashFile);
|
||||
|
||||
DWORD dwRead = 0;
|
||||
DWORD dwWritten = 0;
|
||||
DWORD dwFileHighSize = 0;
|
||||
DWORD dwTrashFileSize = GetFileSize(hTrashFile, &dwFileHighSize);
|
||||
|
||||
char* lpTrashFileData = new char[dwTrashFileSize];
|
||||
CEnsureDeleteArray<char> EnsureDeleteTrashFile(lpTrashFileData);
|
||||
|
||||
if (!ReadFile(hTrashFile, lpTrashFileData, dwTrashFileSize, &dwRead, NULL))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Trash File데이터
|
||||
WriteFile(hFile, &dwTrashFileSize, sizeof(DWORD), &dwWritten, 0); // Trash 파일의 크기
|
||||
WriteFile(hFile, lpTrashFileData, dwTrashFileSize, &dwWritten, 0); // Trash 파일 내용
|
||||
|
||||
// 올바른 자료
|
||||
WriteFile(hFile, &nItemInfoSize, sizeof(DWORD), &dwWritten, 0); // 원본 데이터 크기
|
||||
WriteFile(hFile, lpCompressedInfo, nCompressedInfoSize, &dwWritten, 0); // 압축된 데이터
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user