Files
Client/Server/ToolProject/NewItemMapMaker/NewItemMapMaker.cpp
LGram16 dd97ddec92 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>
2025-11-29 20:17:20 +09:00

663 lines
20 KiB
C++

// NewItemMapMaker.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//
#include <BaseLibrary/Log/ServerLog.h>
#include <BaseLibrary/Utility/Math/Math.h>
#include <RylServerLibrary/DB/DBComponent.h>
#include <RylGameLibrary/Item/ItemMgr.h>
#include <RylGameLibrary/Item/Item.h>
#include <RylGameLibrary/Item/Container/ContainerConstant.h>
#include <RylGameLibrary/Item/Container/ItemContainer.h>
#include <Network/Packet/PacketStruct/UnifiedCharPacket.h>
#include <list>
#include <map>
#include <string>
#include <ctime>
#include <fstream>
#include <iostream>
using namespace std;
// 함수
const char* szItemMapLog = "ItemMapLog.Log";
const char* szScriptFileName = "ItemScript.txt";
#include <GameGuardLib/ggsrv.h>
// edith 2009.08.11 게임가드 2.5 업그레이드
GGAUTHS_API void NpLog(int mode, char* msg)
{
}
GGAUTHS_API void GGAuthUpdateCallback(PGG_UPREPORT report)
{
}
class CMakeItemMap
{
public:
CMakeItemMap()
: m_dwUserNum(0),
m_eAgentServerType(UnifiedConst::ROW)
{
}
bool Initialize(const char* szDBServerName, const char* szDBName,
const char* szDBAccount, const char* szDBPass, UnifiedConst::AgentServerType agentServerType);
bool Process();
protected:
enum
{
MAX_TABLE_NAME = 256,
MAX_QUERY_LENGTH = 8192
};
bool CreateItemMapTable();
bool ConstructUIDCIDMap();
bool ProcessStore();
bool ProcessCharacterItems();
bool LogItemInfoToDB(unsigned long dwUID, unsigned long dwCID, Item::CItem* lpItem);
typedef map<unsigned long, unsigned long> CIDUIDMap; // Key = CID, Value = UID
CDBComponent m_ReadDB;
CDBComponent m_WriteDB;
CIDUIDMap m_CIDUIDMap;
unsigned long m_dwUserNum;
char m_szTableName[MAX_TABLE_NAME];
char m_szQuery[MAX_QUERY_LENGTH];
UnifiedConst::AgentServerType m_eAgentServerType;
};
int main(int argc, char *argv[])
{
CMakeItemMap Make;
if (argc != 6)
{
cout << "Usage : NewItemMapMaker.exe DB서버주소 DB이름 DB계정 DB패스워드 "
"서버타입(ROW:22/Part2통합(한국):23/Part2통합(중국):24)" << endl;
return 0;
}
UnifiedConst::AgentServerType eAgentServerType =
static_cast<UnifiedConst::AgentServerType>(atoi(argv[5]));
switch(eAgentServerType)
{
case UnifiedConst::ROW:
case UnifiedConst::Part2Unified:
case UnifiedConst::Part2Selectable:
break;
default:
cout << "[알 수 없는 서버타입]" << endl;
return -1;
}
if (!Make.Initialize(argv[1], argv[2], argv[3], argv[4], eAgentServerType))
{
cout << "[DB 연결 실패]" << endl;
return -1;
}
cout << "[DB 연결 성공]" << endl;
time_t CurrentTime = time(NULL);
DETLOG1(g_Log, "현재시간 : %s", ctime(&CurrentTime));
// 스크립트 읽기
if (!Item::CItemMgr::GetInstance().LoadItemProtoType(szScriptFileName))
{
cout << "[스크립트 로드 실패]" << endl;
return -1;
}
cout << "[스크립트 로드 성공]" << endl;
Make.Process();
CurrentTime = time(NULL);
DETLOG1(g_Log, "종료시간 : %s", ctime(&CurrentTime));
cout << "Press Enter Key" << endl;
string temp;
getline(cin, temp);
return 0;
}
bool CMakeItemMap::Initialize(const char* szDBServerName,
const char* szDBName,
const char* szDBAccount,
const char* szDBPass,
UnifiedConst::AgentServerType eAgentServerType)
{
// DB 연결
if(!m_ReadDB.Connect(szDBServerName, szDBName, szDBAccount, szDBPass))
{
cout << "[ReadDB 연결 실패]" << endl;
return false;
}
if(!m_WriteDB.Connect(szDBServerName, szDBName, szDBAccount, szDBPass))
{
cout << "[WriteDB 연결 실패]" << endl;
return false;
}
m_eAgentServerType = eAgentServerType;
return true;
}
bool CMakeItemMap::Process()
{
if(CreateItemMapTable() && ConstructUIDCIDMap())
{
if(ProcessStore())
{
return ProcessCharacterItems();
}
}
return false;
}
bool CMakeItemMap::CreateItemMapTable()
{
SYSTEMTIME sysTime;
GetLocalTime(&sysTime);
_snprintf(m_szTableName, MAX_TABLE_NAME, "ItemMap%04d%02d%02d%02d%02d%02d",
sysTime.wYear, sysTime.wMonth, sysTime.wDay,
sysTime.wHour, sysTime.wMinute, sysTime.wSecond);
int nResult = _snprintf(m_szQuery, MAX_QUERY_LENGTH,
"CREATE TABLE %s ("
"ITEM_SERIAL BIGINT NULL DEFAULT(0),"
"OWNER_UID INT NULL DEFAULT(0),"
"OWNER_CID INT NULL DEFAULT(0),"
"PROTOTYPE_ID SMALLINT NULL DEFAULT(0),"
"RUNE_SOCKET SMALLINT NULL DEFAULT(0),"
"UPGRADE_LEVEL TINYINT NULL DEFAULT(0),"
"NUM_OR_DURABILITY TINYINT NULL DEFAULT(0),"
"MAX_NUM_OR_DURABILITY TINYINT NULL DEFAULT(0),"
"ITEM_GRADE TINYINT NULL DEFAULT(0),"
"ITEM_GRADE_PLUS TINYINT NULL DEFAULT(0),"
"MAX_SOCKET_NUM TINYINT NULL DEFAULT(0),"
"SOCKET_01 TINYINT NULL DEFAULT(0),"
"SOCKET_02 TINYINT NULL DEFAULT(0),"
"SOCKET_03 TINYINT NULL DEFAULT(0),"
"SOCKET_04 TINYINT NULL DEFAULT(0),"
"SOCKET_05 TINYINT NULL DEFAULT(0),"
"SOCKET_06 TINYINT NULL DEFAULT(0),"
"SOCKET_07 TINYINT NULL DEFAULT(0),"
"SOCKET_08 TINYINT NULL DEFAULT(0),"
"ATT_MIN_DAMAGE SMALLINT NULL DEFAULT(0),"
"ATT_MAX_DAMAGE SMALLINT NULL DEFAULT(0),"
"ATT_ARMOUR SMALLINT NULL DEFAULT(0),"
"ATT_HIT_RATE SMALLINT NULL DEFAULT(0),"
"ATT_EVADE SMALLINT NULL DEFAULT(0),"
"ATT_MAX_HP SMALLINT NULL DEFAULT(0),"
"ATT_HP_REGEN SMALLINT NULL DEFAULT(0),"
"ATT_MAX_MP SMALLINT NULL DEFAULT(0),"
"ATT_MP_REGEN SMALLINT NULL DEFAULT(0),"
"ATT_CRITICAL SMALLINT NULL DEFAULT(0),"
"ATT_BLOCK SMALLINT NULL DEFAULT(0),"
"ATT_SPEED SMALLINT NULL DEFAULT(0),"
"ATT_MAGIC_POWER SMALLINT NULL DEFAULT(0),"
"ATT_MAGIC_RESIST SMALLINT NULL DEFAULT(0))"
, m_szTableName);
if(0 < nResult)
{
if(m_WriteDB.ExecuteQuery(m_szQuery))
{
return true;
}
else
{
ERRLOG1(g_Log, "쿼리 실패 : 테이블 생성 실패 : %s", m_szQuery);
}
}
else
{
ERRLOG0(g_Log, "쿼리 만들기 : 테이블 생성 실패");
}
return false;
}
bool CMakeItemMap::ConstructUIDCIDMap()
{
char szQuery[OleDB::MaxQueryTextLen];
switch(m_eAgentServerType)
{
case UnifiedConst::ROW:
case UnifiedConst::Part2Unified:
_snprintf(szQuery, OleDB::MaxQueryTextLen,
"Select UID, NewCID From TblUnifiedCharList where OldServerGroupID = %d", m_eAgentServerType);
break;
case UnifiedConst::Part2Selectable:
_snprintf(szQuery, OleDB::MaxQueryTextLen, "Select UID, NewCID From TblUnifiedCharList");
break;
default:
cout << "[알 수 없는 서버 타입입니다 : " << m_eAgentServerType << endl;
return false;
}
szQuery[OleDB::MaxQueryTextLen - 1] = 0;
cout << "[UIDCID맵 제작 시작]" << endl;
if(!m_ReadDB.ExecuteQuery(szQuery))
{
cout << "[UIDCID맵 쿼리 실패]" << endl;
return false;
}
#pragma pack(1)
struct UserInfoData
{
unsigned long m_dwUID;
unsigned long m_dwCID;
};
#pragma pack()
const int MAX_ROWS = 1024;
int nGetRows = 0;
UserInfoData userInfoData[MAX_ROWS];
memset(&userInfoData, 0, sizeof(UserInfoData) * MAX_ROWS);
while (m_ReadDB.GetData((void**)&userInfoData, sizeof(UserInfoData), MAX_ROWS, &nGetRows))
{
if(0 == nGetRows)
{
break;
}
for(UserInfoData* lpUserInfoData = userInfoData;
0 < nGetRows; --nGetRows, ++lpUserInfoData)
{
if(0 != lpUserInfoData->m_dwCID)
{
m_CIDUIDMap.insert(std::make_pair(
lpUserInfoData->m_dwCID, lpUserInfoData->m_dwUID));
}
++m_dwUserNum;
}
memset(&userInfoData, 0, sizeof(UserInfoData) * MAX_ROWS);
}
cout << "[맵 제작 완료]" << endl;
return true;
}
bool CMakeItemMap::ProcessStore()
{
const int MAX_QUERY = 2;
char szQuery[MAX_QUERY][OleDB::MaxQueryTextLen];
switch(m_eAgentServerType)
{
case UnifiedConst::ROW:
case UnifiedConst::Part2Unified:
_snprintf(szQuery[0], OleDB::MaxQueryTextLen,
"SELECT UID, Store FROM TblUnifiedItemStore1 WHERE OldServerGroupID = %d", m_eAgentServerType);
_snprintf(szQuery[1], OleDB::MaxQueryTextLen,
"SELECT UID, Store FROM TblUnifiedItemStore2 WHERE OldServerGroupID = %d", m_eAgentServerType);
break;
case UnifiedConst::Part2Selectable:
_snprintf(szQuery[0], OleDB::MaxQueryTextLen, "SELECT UID, Store FROM TblUnifiedItemStore1");
_snprintf(szQuery[1], OleDB::MaxQueryTextLen, "SELECT UID, Store FROM TblUnifiedItemStore2");
break;
default:
cout << "[알 수 없는 서버 타입입니다 : " << m_eAgentServerType << endl;
return false;
}
#pragma pack(1)
struct StoreData
{
unsigned long m_dwUID;
STORE m_StoreData;
};
#pragma pack()
cout << "[StoreInfo] 컨버팅 시작" << endl;
DETLOG0(g_Log, "창고 컨버팅 시작(에러시 CID대신 UID기록)");
Item::CArrayContainer StoreContainer;
Item::CArrayContainer::iterator begin, end;
StoreContainer.Initialize(0,
ContainerConstant::DEPOSIT_WIDTH,
ContainerConstant::DEPOSIT_HEIGHT,
ContainerConstant::MAX_DEPOSIT_TAB);
unsigned long dwCurrentUserNum = 0;
for(int nQueryCount = 0; nQueryCount < MAX_QUERY; ++nQueryCount)
{
if(!m_ReadDB.ExecuteQuery(szQuery[nQueryCount]))
{
cout << "[ItemStore맵 쿼리 실패] : "
<< szQuery[nQueryCount] << " : " << m_ReadDB.GetErrorString() << endl;
return false;
}
const int MAX_ROWS = 10240;
int nGetRows = 0;
StoreData* storeData = new StoreData[MAX_ROWS];
memset(storeData, 0, sizeof(StoreData) * MAX_ROWS);
while (m_ReadDB.GetData((void**)storeData, sizeof(StoreData), MAX_ROWS, &nGetRows))
{
if(0 == nGetRows)
{
break;
}
dwCurrentUserNum += nGetRows;
for(StoreData* lpStoreData = storeData;
0 < nGetRows; --nGetRows, ++lpStoreData)
{
unsigned long dwUID = lpStoreData->m_dwUID;
StoreContainer.ClearItems();
StoreContainer.SetCID(dwUID);
if(sizeof(DWORD) <= lpStoreData->m_StoreData.dwSize)
{
lpStoreData->m_StoreData.dwSize -= sizeof(DWORD);
}
if(0 < lpStoreData->m_StoreData.dwSize)
{
if (!StoreContainer.SerializeIn(
lpStoreData->m_StoreData.Data,
lpStoreData->m_StoreData.dwSize))
{
cout << "[UID:" << dwUID << "] 창고 : " << nQueryCount + 1 << "작성 실패" << endl;
}
else
{
begin = StoreContainer.begin();
end = StoreContainer.end();
for(; begin != end; ++begin)
{
Item::CItem* lpItem = *begin;
if(NULL != lpItem)
{
LogItemInfoToDB(dwUID, 0, lpItem);
}
}
}
}
}
cout << dwCurrentUserNum << "/" << m_dwUserNum << endl;
memset(storeData, 0, sizeof(StoreData) * MAX_ROWS);
}
delete [] storeData;
}
cout << endl << "[StoreInfo] 컨버팅 끝" << endl;
DETLOG0(g_Log, "창고 컨버팅 끝");
return true;
}
bool CMakeItemMap::ProcessCharacterItems()
{
const char* szQuery = "Select a.CID, a.Equip, a.Inventory, a.Extra, b.Exchange, b.TempInven "
"From CharItem a join CharItemEX b on a.CID = b.CID";
#pragma pack(1)
struct CharData
{
unsigned long m_dwCID;
EQUIP m_Equip;
INVEN m_Inventory;
EXTRA m_Extra;
EXCHANGE m_Exchange;
TEMPINVEN m_TempInven;
};
#pragma pack()
struct ContainerData
{
unsigned long m_dwSize;
char* m_lpData;
};
cout << "[CharItemInfo] 컨버팅 시작" << endl;
DETLOG0(g_Log, "캐릭터 아이템 컨버팅 시작");
Item::CListContainer Equip;
Item::CListContainer Extra;
Item::CArrayContainer Inventory;
Item::CArrayContainer Exchange;
Item::CListContainer TempInven;
Item::CItemContainer::iterator first, last;
Equip.Initialize(0, Item::EquipmentPos::MAX_EQUPMENT_POS);
Extra.Initialize(0, Item::ExtraSpacePos::MAX_EXTRA_SPACE_NUM);
Inventory.Initialize(0,
ContainerConstant::INVENTORY_WIDTH,
ContainerConstant::INVENTORY_HEIGHT,
ContainerConstant::MAX_INVENTORY_TAB);
Exchange.Initialize(0,
ContainerConstant::EXCHANGE_WIDTH,
ContainerConstant::EXCHANGE_HEIGHT, 1);
TempInven.Initialize(0, Item::MAX_TEMP_INVEN_ITEM_NUM);
const int MAX_CONTAINER = 5;
Item::CItemContainer* lpItemContainers[MAX_CONTAINER] =
{ &Equip, &Inventory, &Extra, &Exchange, &TempInven };
if(!m_ReadDB.ExecuteQuery(szQuery))
{
cout << "[ItemStore맵 쿼리 실패] : " << m_ReadDB.GetErrorString() << endl;
return false;
}
CIDUIDMap::iterator uiditr;
CIDUIDMap::iterator enditr = m_CIDUIDMap.end();
const int MAX_ROWS = 10240;
int nGetRows = 0;
CharData* charData = new CharData[MAX_ROWS];
memset(charData, 0, sizeof(CharData) * MAX_ROWS);
unsigned long dwCharNum = 0;
while(m_ReadDB.GetData((void**)charData, sizeof(CharData), MAX_ROWS, &nGetRows))
{
if(0 == nGetRows)
{
break;
}
for(CharData* lpCharData = charData;
0 < nGetRows; --nGetRows, ++lpCharData)
{
unsigned long dwCID = lpCharData->m_dwCID;
uiditr = m_CIDUIDMap.find(dwCID);
unsigned long dwUID = uiditr != enditr ? uiditr->second : 0;
if(0 != dwUID)
{
++dwCharNum;
ContainerData containerData[MAX_CONTAINER] =
{
{ lpCharData->m_Equip.dwSize, lpCharData->m_Equip.Data },
{ lpCharData->m_Inventory.dwSize, lpCharData->m_Inventory.Data },
{ lpCharData->m_Extra.dwSize, lpCharData->m_Extra.Data },
{ lpCharData->m_Exchange.dwSize, lpCharData->m_Exchange.Data },
{ lpCharData->m_TempInven.dwSize, lpCharData->m_TempInven.Data }
};
for(int nCount = 0; nCount < MAX_CONTAINER; ++nCount)
{
if(sizeof(DWORD) <= containerData[nCount].m_dwSize)
{
containerData[nCount].m_dwSize -= sizeof(DWORD);
}
if(0 < containerData[nCount].m_dwSize)
{
lpItemContainers[nCount]->ClearItems();
lpItemContainers[nCount]->SetCID(dwCID);
if(!lpItemContainers[nCount]->SerializeIn(
containerData[nCount].m_lpData, containerData[nCount].m_dwSize))
{
cout << "[UID:" << dwUID << "]" << "[CID:" << dwCID << "]" << "아이템 데이터 작성 실패" << endl;
}
else
{
first = lpItemContainers[nCount]->begin();
last = lpItemContainers[nCount]->end();
for(; first != last; ++first)
{
Item::CItem* lpItem = *first;
if(NULL != lpItem)
{
LogItemInfoToDB(dwUID, dwCID, lpItem);
}
}
}
}
}
}
}
cout << dwCharNum << "/" << static_cast<unsigned int>(m_CIDUIDMap.size()) << endl;
memset(charData, 0, sizeof(CharData) * MAX_ROWS);
}
delete [] charData;
cout << endl << "[CharItemInfo] 컨버팅 끝" << endl;
DETLOG0(g_Log, "캐릭터 아이템 컨버팅 끝");
return true;
}
bool CMakeItemMap::LogItemInfoToDB(unsigned long dwUID, unsigned long dwCID, Item::CItem* lpItem)
{
int nRuneSocket = 0;
int nUpgradeStep = 0;
int nMaxSocketNum = 0;
int nItemGrade = Item::EquipType::MAX_GRADE;
int nItemGradePlus = 0;
unsigned char cSocket[Item::EquipmentInfo::MAX_SOCKET_NUM];
short usAttribute[Item::Attribute::MAX_ATTRIBUTE_NUM];
std::fill_n(cSocket, size_t(Item::EquipmentInfo::MAX_SOCKET_NUM), 0);
std::fill_n(usAttribute, size_t(Item::Attribute::MAX_ATTRIBUTE_NUM), 0);
Item::CEquipment* lpEquipment = Item::CEquipment::DowncastToEquipment(lpItem);
if(NULL != lpEquipment)
{
//nRuneSocket = lpEquipment->GetRuneSocket();
nUpgradeStep = lpEquipment->GetUpgradeLevel();
nMaxSocketNum = lpEquipment->GetMaxSocketNum();
nItemGrade = lpEquipment->GetItemGrade().m_eItemGrade;
nItemGradePlus = lpEquipment->GetItemGrade().m_cPlus;
lpEquipment->GetSocket(cSocket, Item::EquipmentInfo::MAX_SOCKET_NUM);
lpEquipment->GetAttribute(usAttribute, Item::Attribute::MAX_ATTRIBUTE_NUM);
}
int nResult = _snprintf(m_szQuery, MAX_QUERY_LENGTH, "INSERT INTO %s "
" values (%I64d, %d, %d, %u, %u, %u, %u, %u, %u, %u, %u",
m_szTableName, lpItem->GetUID(), dwUID, dwCID, lpItem->GetPrototypeID(),
nRuneSocket, nUpgradeStep, lpItem->GetNumOrDurability(), lpItem->GetMaxNumOrDurability(),
nItemGrade, nItemGradePlus, nMaxSocketNum);
int nLength = nResult;
for(int nCount = 0; nCount < Item::EquipmentInfo::MAX_SOCKET_NUM && 0 < nResult; ++nCount)
{
nResult = _snprintf(m_szQuery + nLength, MAX_QUERY_LENGTH - nLength, ", %d", cSocket[nCount]);
nLength += nResult;
}
for(int nCount = Item::Attribute::MIN_DAMAGE;
nCount < Item::Attribute::MAX_ATTRIBUTE_NUM && 0 < nResult; ++nCount)
{
nResult = _snprintf(m_szQuery + nLength, MAX_QUERY_LENGTH - nLength, ", %d", usAttribute[nCount]);
nLength += nResult;
}
if(0 < nResult && 0 < nLength && nLength < MAX_QUERY_LENGTH - 3)
{
m_szQuery[nLength] = ')';
m_szQuery[nLength + 1] = '\0';
if(m_WriteDB.ExecuteQuery(m_szQuery))
{
return true;
}
else
{
ERRLOG5(g_Log, "UID:%d/CID:%d/ItemUID:0x%016I64X/ItemPrototype:%6d 쿼리 실패 : %s",
dwUID, dwCID, lpItem->GetUID(), lpItem->GetPrototypeID(), m_WriteDB.GetErrorString());
}
}
else
{
// Log
ERRLOG4(g_Log, "UID:%d/CID:%d/ItemUID:0x%016I64X/ItemPrototype:%6d 쿼리 만들기 실패",
dwUID, dwCID, lpItem->GetUID(), lpItem->GetPrototypeID());
}
return false;
}