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:
2025-11-29 20:17:20 +09:00
parent 5d3cd64a25
commit dd97ddec92
11602 changed files with 1446576 additions and 0 deletions

View File

@@ -0,0 +1,32 @@
========================================================================
콘솔 응용 프로그램 : RebalanceConverter 프로젝트 개요
========================================================================
응용 프로그램 마법사에서 이 RebalanceConverter 응용 프로그램을 만들었습니다.
이 파일에는 RebalanceConverter 응용 프로그램을 구성하는 각각의 파일에
들어 있는 요약 설명이 포함되어 있습니다.
RebalanceConverter.vcproj
응용 프로그램 마법사를 사용하여 생성한 VC++ 프로젝트의 기본 프로젝트 파일입니다.
해당 파일을 생성한 Visual C++의 버전 정보를 비롯하여
응용 프로그램 마법사에서 선택한 플랫폼, 구성 및
프로젝트 기능에 대한 정보가 들어 있습니다.
RebalanceConverter.cpp
기본 응용 프로그램 소스 파일입니다.
/////////////////////////////////////////////////////////////////////////////
기타 표준 파일:
StdAfx.h 및 StdAfx.cpp는
RebalanceConverter.pch라는 이름의 PCH(미리 컴파일된 헤더) 파일과
StdAfx.obj라는 이름의 미리 컴파일된 형식 파일을 빌드하는 데 사용됩니다.
/////////////////////////////////////////////////////////////////////////////
기타 참고:
응용 프로그램 마법사에서 사용하는 "TODO:" 주석은 사용자가 추가하거나 사용자 지정해야 하는
소스 코드 부분을 나타냅니다.
/////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,721 @@
#include "stdafx.h"
#include "Rebalance.h"
#include <Item/ItemMgr.h>
#include <Item/Container/ContainerConstant.h>
#include <Item/RebalanceConvert/RebalanceItem.h>
#include <Item/RebalanceConvert/ContainerChecker.h>
#include <Item/RebalanceConvert/OldItemMgr.h>
#include <Network/Packet/PacketStruct/ServerInfo.h>
#include <Log/ServerLog.h>
#include <Skill/SkillMgr.h>
#include <RylDBLibrary/RylDBCharCommand.h>
#include <RylDBLibrary/RylDBStoreCommand.h>
namespace RebalanceLib
{
CServerLog g_ItemLog("ItemUID");
CServerLog g_GoldLog("GivenGold");
CServerLog g_SkillBookLog("GivenSkillBook");
// 스킬 읽기
CDBReadSkill::CDBReadSkill(SkillDataMap& CIDSkillDataMap, bool bClearSkill)
: m_CIDSkillDataMap(CIDSkillDataMap), m_bClearSkill(bClearSkill)
{
}
ConvertResult CDBReadSkill::operator()(RylDBCommand::CSkillData& charSkillData_InOut)
{
SkillBookInfo skillData;
memset(&skillData, 0, sizeof(SkillBookInfo));
const SKILL& skill_In = charSkillData_InOut.GetSkill();
for(int nSkillCount = 0; nSkillCount < skill_In.wSlotNum; ++nSkillCount)
{
const SKILLSLOT& skillSlot = skill_In.SSlot[nSkillCount];
if (skillSlot.SKILLINFO.cLockCount < CSkillMgr::MAX_SKILL_LOCKCOUNT &&
skillSlot.SKILLINFO.cSkillLevel <= CSkillMgr::MAX_SKILL_LEVEL)
{
// 스킬의 종류에 관계 없이 지급
for(int nLockCount = 0; nLockCount < skillSlot.SKILLINFO.cLockCount; ++nLockCount)
{
skillData.m_dwBookNum[nLockCount] += CSkillMgr::MAX_SKILL_LEVEL;
}
skillData.m_dwBookNum[skillSlot.SKILLINFO.cLockCount] +=
skillSlot.SKILLINFO.cSkillLevel;
}
else
{
ERRLOG4(g_Log, "CID:%10u / Skill_ID:0x%04X / LockCount:%6d / Level:%6d / 알 수 없는 스킬입니다.",
charSkillData_InOut.GetCID(), skillSlot.SKILLINFO.wSkill,
skillSlot.SKILLINFO.cLockCount, skillSlot.SKILLINFO.cSkillLevel);
}
}
if(m_bClearSkill)
{
SKILL skill_Out;
memset(&skill_Out, 0, sizeof(SKILL));
charSkillData_InOut.SetSkill(skill_Out);
}
m_CIDSkillDataMap.insert(std::make_pair(charSkillData_InOut.GetCID(), skillData));
return m_bClearSkill ? CONVERT_SUCCEEDED : CONVERT_DO_NOT_WRITE;
}
// 스킬북 제거 및 카운팅 / 장비 컨버팅
CDBItemConvert::CDBItemConvert(CDBItemSerialMgr& dbItemSerialMgr,
Item::CItemMgr& newItemMgr, OldItem::CItemMgr& oldItemMgr,
SkillDataMap* lpUIDSkillDataMap, SkillDataMap* lpCIDSkillDataMap,
bool bConvertRebalanceItem, bool bRenumberingItemUID)
: m_DBItemSerialMgr(dbItemSerialMgr),
m_newItemMgr(newItemMgr), m_oldItemMgr(oldItemMgr),
m_lpUIDSkillDataMap(lpUIDSkillDataMap), m_lpCIDSkillDataMap(lpCIDSkillDataMap),
m_bConvertRebalanceItem(bConvertRebalanceItem),
m_bRenumberingItemUID(bRenumberingItemUID)
{
}
ConvertResult CDBItemConvert::operator()(RylDBCommand::CCharItem& charItem_InOut)
{
CItemArrayChecker<
ContainerConstant::INVENTORY_WIDTH,
ContainerConstant::INVENTORY_HEIGHT,
ContainerConstant::MAX_INVENTORY_TAB> invenChecker(TakeType::TS_INVEN);
unsigned long dwCID = charItem_InOut.GetCID();
const EQUIP& equip_In = charItem_InOut.GetEquip();
const INVEN& inven_In = charItem_InOut.GetInven();
const EXTRA& extra_In = charItem_InOut.GetExtra();
EQUIP equip_Out;
INVEN inven_Out;
EXTRA extra_Out;
memset(&equip_Out, 0, sizeof(EQUIP));
memset(&inven_Out, 0, sizeof(INVEN));
memset(&extra_Out, 0, sizeof(EXTRA));
equip_Out.dwSize = EQUIP::MAX_EQUIP_SIZE;
inven_Out.dwSize = INVEN::MAX_INVEN_SIZE;
extra_Out.dwSize = EXTRA::MAX_EXTRA_SIZE;
if(!ConvertData(0, dwCID, 0,
equip_In.Data, equip_In.dwSize, equip_Out.Data, equip_Out.dwSize))
{
ERRLOG1(g_Log, "CID:%10u / Equip convert failed", dwCID);
}
else if(!ConvertData(0, dwCID, 0,
extra_In.Data, extra_In.dwSize, extra_Out.Data, extra_Out.dwSize))
{
ERRLOG1(g_Log, "CID:%10u / Extra convert failed", dwCID);
}
else if(!ConvertData(0, dwCID, &invenChecker,
inven_In.Data, inven_In.dwSize, inven_Out.Data, inven_Out.dwSize))
{
ERRLOG1(g_Log, "CID:%10u / Inventory convert failed", dwCID);
}
else
{
if(0 != m_lpCIDSkillDataMap)
{
SkillDataMap::iterator pos = m_lpCIDSkillDataMap->find(dwCID);
SkillDataMap::iterator end = m_lpCIDSkillDataMap->end();
// 인벤, 창고, Temp창인 경우에, 3, 4단계 스킬북을 아이템으로 넣어 준다.
if(pos != end)
{
unsigned long dwDataSize = INVEN::MAX_INVEN_SIZE - inven_Out.dwSize;
GiveSkillBook(0, dwCID, m_DBItemSerialMgr, pos->second,
invenChecker, "[INVEN]", inven_Out.Data + inven_Out.dwSize, dwDataSize);
inven_Out.dwSize += dwDataSize;
}
}
charItem_InOut.SetEquip(equip_Out);
charItem_InOut.SetInven(inven_Out);
charItem_InOut.SetExtra(extra_Out);
return CONVERT_SUCCEEDED;
}
return CONVERT_FAILED;
}
ConvertResult CDBItemConvert::operator()(RylDBCommand::CCharItemEx& charItemEx_InOut)
{
CItemListChecker<Item::MAX_TEMP_INVEN_ITEM_NUM> tempInvenChecker(TakeType::TS_TEMPINVEN);
unsigned long dwCID = charItemEx_InOut.GetCID();
const EXCHANGE& exchange_In = charItemEx_InOut.GetExchange();
const TEMPINVEN& tempInven_In = charItemEx_InOut.GetTempInven();
EXCHANGE exchange_Out;
TEMPINVEN tempInven_Out;
memset(&exchange_Out, 0, sizeof(EXCHANGE));
memset(&tempInven_Out, 0, sizeof(TEMPINVEN));
exchange_Out.dwSize = EXCHANGE::MAX_EXCHANGE_SIZE;
tempInven_Out.dwSize = TEMPINVEN::MAX_TEMPINVEN_SIZE;
if(!ConvertData(0, dwCID, 0,
exchange_In.Data, exchange_In.dwSize, exchange_Out.Data, exchange_Out.dwSize))
{
ERRLOG1(g_Log, "CID:%10u / Exchange convert failed", dwCID);
}
else if(!ConvertData(0, dwCID, &tempInvenChecker,
tempInven_In.Data, tempInven_In.dwSize, tempInven_Out.Data, tempInven_Out.dwSize))
{
ERRLOG1(g_Log, "CID:%10u / TempInven convert failed", dwCID);
}
else
{
if(0 != m_lpCIDSkillDataMap)
{
SkillDataMap::iterator pos = m_lpCIDSkillDataMap->find(dwCID);
SkillDataMap::iterator end = m_lpCIDSkillDataMap->end();
// 인벤, 창고, Temp창인 경우에, 3, 4단계 스킬북을 아이템으로 넣어 준다.
if(pos != end)
{
unsigned long dwDataSize = TEMPINVEN::MAX_TEMPINVEN_SIZE - tempInven_Out.dwSize;
GiveSkillBook(0, dwCID, m_DBItemSerialMgr, pos->second,
tempInvenChecker, "[TEMPINVEN]",
tempInven_Out.Data + tempInven_Out.dwSize, dwDataSize);
tempInven_Out.dwSize += dwDataSize;
}
}
charItemEx_InOut.SetExchange(exchange_Out);
charItemEx_InOut.SetTempInven(tempInven_Out);
return CONVERT_SUCCEEDED;
}
return CONVERT_FAILED;
}
ConvertResult CDBItemConvert::operator()(RylDBCommand::CUnifiedStore1& unifiedStore1_InOut)
{
CItemArrayChecker<
ContainerConstant::DEPOSIT_WIDTH,
ContainerConstant::DEPOSIT_HEIGHT,
ContainerConstant::MAX_DEPOSIT_TAB> storeChecker(TakeType::TS_DEPOSIT);
storeChecker.FillTab(2);
storeChecker.FillTab(3);
unsigned long dwUID = unifiedStore1_InOut.GetUID();
const STORE& store_In = unifiedStore1_InOut.GetStore();
STORE store_Out;
memset(&store_Out, 0, sizeof(STORE));
store_Out.dwSize = STORE::MAX_STORE_SIZE;
if(!ConvertData(dwUID, 0, &storeChecker,
store_In.Data, store_In.dwSize, store_Out.Data, store_Out.dwSize))
{
ERRLOG2(g_Log, "UID:%10u / OldServerGroupID:%d / UnifiedStore convert failed",
dwUID, unifiedStore1_InOut.GetOldServerGroupID());
}
else
{
if(0 != m_lpUIDSkillDataMap)
{
SkillDataMap::iterator pos = m_lpUIDSkillDataMap->find(dwUID);
SkillDataMap::iterator end = m_lpUIDSkillDataMap->end();
// 인벤, 창고, Temp창인 경우에, 3, 4단계 스킬북을 아이템으로 넣어 준다.
if(pos != end)
{
unsigned long dwDataSize = STORE::MAX_STORE_SIZE - store_Out.dwSize;
GiveSkillBook(dwUID, 0, m_DBItemSerialMgr, pos->second,
storeChecker, "[UNIFIED_STORE1]", store_Out.Data + store_Out.dwSize, dwDataSize);
store_Out.dwSize += dwDataSize;
}
}
unifiedStore1_InOut.SetStore(store_Out);
return CONVERT_SUCCEEDED;
}
return CONVERT_FAILED;
}
ConvertResult CDBItemConvert::operator()(RylDBCommand::CUnifiedStore2& unifiedStore2_InOut)
{
CItemArrayChecker<
ContainerConstant::DEPOSIT_WIDTH,
ContainerConstant::DEPOSIT_HEIGHT,
ContainerConstant::MAX_DEPOSIT_TAB> storeChecker(TakeType::TS_DEPOSIT);
storeChecker.FillTab(0);
storeChecker.FillTab(1);
unsigned long dwUID = unifiedStore2_InOut.GetUID();
const STORE& store_In = unifiedStore2_InOut.GetStore();
STORE store_Out;
memset(&store_Out, 0, sizeof(STORE));
store_Out.dwSize = STORE::MAX_STORE_SIZE;
if(!ConvertData(dwUID, 0, &storeChecker,
store_In.Data, store_In.dwSize, store_Out.Data, store_Out.dwSize))
{
ERRLOG2(g_Log, "UID:%10u / OldServerGroupID:%d / Store convert failed",
dwUID, unifiedStore2_InOut.GetOldServerGroupID());
}
else
{
if(0 != m_lpUIDSkillDataMap)
{
SkillDataMap::iterator pos = m_lpUIDSkillDataMap->find(dwUID);
SkillDataMap::iterator end = m_lpUIDSkillDataMap->end();
// 인벤, 창고, Temp창인 경우에, 3, 4단계 스킬북을 아이템으로 넣어 준다.
if(pos != end)
{
unsigned long dwDataSize = STORE::MAX_STORE_SIZE - store_Out.dwSize;
GiveSkillBook(dwUID, 0, m_DBItemSerialMgr, pos->second,
storeChecker, "[UNIFIED_STORE2]", store_Out.Data + store_Out.dwSize, dwDataSize);
store_Out.dwSize += dwDataSize;
}
}
unifiedStore2_InOut.SetStore(store_Out);
return CONVERT_SUCCEEDED;
}
return CONVERT_FAILED;
}
bool CDBItemConvert::ConvertData(unsigned long dwUID, unsigned long dwCID, CItemChecker* lpItemChecker,
const char* szOriginalData, unsigned long dwOriginalSize,
char* szChangedData, unsigned long& dwChangedSize_InOut)
{
const char* szPos = szOriginalData;
const char* szEnd = szOriginalData + dwOriginalSize;
char* szResultPos = szChangedData;
char* szResultEnd = szChangedData + dwChangedSize_InOut;
Item::Grade::GradeInfo convertedGrade;
if(0 != dwUID || 0 != dwCID)
{
unsigned long dwKey = (0 != dwUID) ? dwUID : dwCID;
SkillDataMap* lpSkillDataMap = (0 != dwUID) ? m_lpUIDSkillDataMap : m_lpCIDSkillDataMap;
SkillDataMap::iterator pos;
SkillDataMap::iterator end;
if(0 != lpSkillDataMap)
{
pos = lpSkillDataMap->find(dwKey);
if(pos == lpSkillDataMap->end())
{
SkillBookInfo skillData;
memset(&skillData, 0, sizeof(SkillBookInfo));
pos = lpSkillDataMap->insert(std::make_pair(dwKey, skillData)).first;
}
}
for(; szPos < szEnd && szResultPos < szResultEnd; )
{
const Item::ItemData* lpItemData = reinterpret_cast<const Item::ItemData*>(szPos);
Item::ItemData* lpResultItemData = reinterpret_cast<Item::ItemData*>(szResultPos);
const Item::ItemInfo* lpNewItemInfo = m_newItemMgr.GetItemInfo(lpItemData->m_usProtoTypeID);
const OldItem::ItemInfo* lpOldItemInfo = m_oldItemMgr.GetItemInfo(lpItemData->m_usProtoTypeID);
if(0 == lpNewItemInfo || 0 == lpOldItemInfo)
{
ERRLOG4(g_Log, "UID:%10u / CID:%10u / Serial:0x%016I64X / ProtoType:%6d / Script has not this item",
dwUID, dwCID, lpItemData->m_dwUID, lpItemData->m_usProtoTypeID);
}
else if(m_bConvertRebalanceItem &&
0 != (lpNewItemInfo->m_DetailData.m_dwFlags & Item::DetailData::EQUIP) &&
sizeof(Item::ItemData) + sizeof(Item::EquipmentInfo) <= lpItemData->m_cItemSize)
{
// 장비인 경우 아이템 컨버팅을 한다.
unsigned long dwDataSize_InOut =
static_cast<unsigned long>(szResultEnd - szResultPos);
if(ConvertRebalanceItem(dwUID, dwCID, lpItemData, *lpNewItemInfo, *lpOldItemInfo,
szResultPos, dwDataSize_InOut, convertedGrade))
{
CItemGrade::GetInstance().AddGradeItemNum(convertedGrade.m_eItemGrade);
// 아이템 위치를 세팅한다.
if(0 != lpItemChecker)
{
lpItemChecker->Set(reinterpret_cast<Item::ItemData*>(szResultPos)->m_ItemPos,
lpNewItemInfo->m_DetailData.m_cXSize, lpNewItemInfo->m_DetailData.m_cYSize);
}
if(m_bRenumberingItemUID)
{
// 아이템 시리얼 수정
unsigned __int64 dwNewItemSerial = m_DBItemSerialMgr.GetNewItemSerial();
INFLOG4(g_ItemLog, "UID:%10u / CID:%10u / OldItemSerial:0x%016I64X / NewItemSerial:0x%016I64X / Changed item serial",
dwUID, dwCID, lpItemData->m_dwUID, dwNewItemSerial);
lpResultItemData->m_dwUID = dwNewItemSerial;
}
// 복사 위치 증가
szResultPos += dwDataSize_InOut;
}
else
{
ERRLOG4(g_Log, "UID:%10u / CID:%10u / Serial:0x%016I64X / ProtoType:%6d / Item recreation failed",
dwUID, dwCID, lpItemData->m_dwUID, lpItemData->m_usProtoTypeID);
}
}
else if(0 != lpSkillDataMap &&
Item::ItemType::SKILL_BOOK == lpNewItemInfo->m_DetailData.m_cItemType)
{
// 교환권 배열에 카운팅하고, 아이템을 복사하지 않는다.
pos->second.m_dwBookNum[lpNewItemInfo->m_UseItemInfo.m_usSkill_LockCount] +=
lpItemData->m_cNumOrDurability;
}
else
{
// 아이템 위치를 세팅한다.
if(0 != lpItemChecker)
{
lpItemChecker->Set(lpItemData->m_ItemPos,
lpNewItemInfo->m_DetailData.m_cXSize, lpNewItemInfo->m_DetailData.m_cYSize);
}
// 그냥 아이템을 복사한다.
memcpy(szResultPos, lpItemData, lpItemData->m_cItemSize);
szResultPos += lpItemData->m_cItemSize;
// 아이템 시리얼 수정
if(m_bRenumberingItemUID)
{
unsigned __int64 dwNewItemSerial = m_DBItemSerialMgr.GetNewItemSerial();
INFLOG4(g_ItemLog, "UID:%10u / CID:%10u / OldItemSerial:0x%016I64X / NewItemSerial:0x%016I64X / Changed item serial",
dwUID, dwCID, lpItemData->m_dwUID, dwNewItemSerial);
lpResultItemData->m_dwUID = dwNewItemSerial;
}
}
szPos += lpItemData->m_cItemSize;
}
}
dwChangedSize_InOut = static_cast<unsigned long>(szResultPos - szChangedData);
return true;
}
void CDBItemConvert::ChangeSkillBookToGold(SkillDataMap& skillDataMap, GoldDataMap& goldDataMap)
{
const unsigned long dw1stSkillBookGold = 1000;
const unsigned long dw2ndSkillBookGold = 10000;
SkillDataMap::iterator skill_pos = skillDataMap.begin();
SkillDataMap::iterator skill_end = skillDataMap.end();
GoldDataMap::iterator gold_pos;
GoldDataMap::iterator gold_end;
for(; skill_pos != skill_end; ++skill_pos)
{
unsigned long dwKey = skill_pos->first;
SkillBookInfo& skillData = skill_pos->second;
unsigned long dwGold =
skillData.m_dwBookNum[0] * dw1stSkillBookGold +
skillData.m_dwBookNum[1] * dw2ndSkillBookGold;
// 변환한 스킬북은 0으로 초기화.
skillData.m_dwBookNum[0] = 0;
skillData.m_dwBookNum[1] = 0;
if(0 < dwGold)
{
gold_pos = goldDataMap.lower_bound(dwKey);
gold_end = goldDataMap.end();
if(gold_pos != gold_end && gold_pos->first == dwKey)
{
// 이미 있다.
gold_pos->second += dwGold;
}
else
{
// 없으므로 새로 삽입.
goldDataMap.insert(gold_pos, std::make_pair(dwKey, dwGold));
}
}
}
}
void CDBItemConvert::GiveSkillBook(unsigned long dwUID, unsigned long dwCID,
CDBItemSerialMgr& DBItemSerialMgr, SkillBookInfo& skillData,
CItemChecker& itemChecker, const char* szPosition,
char* szData_InOut, unsigned long& dwDataSize_InOut)
{
// 이미 ItemChecker에 아이템이 전부 세팅되어 있는 상황이다.
Item::ItemPos itemPos;
char* szDataPos = szData_InOut;
const char* szDataEnd = szData_InOut + dwDataSize_InOut;
// 3단계 아이템 삽입
while (0 < skillData.m_dwBookNum[2] &&
szDataPos + sizeof(Item::ItemData) < szDataEnd &&
itemChecker.FindEmptyPos(itemPos, 1, 1))
{
Item::ItemData skillBook3rd;
memset(&skillBook3rd, 0, sizeof(Item::ItemData));
unsigned char cAmount = 0;
if (100 < skillData.m_dwBookNum[2])
{
cAmount = 100;
skillData.m_dwBookNum[2] -= 100;
}
else
{
cAmount = static_cast<unsigned char>(skillData.m_dwBookNum[2]);
skillData.m_dwBookNum[2] = 0;
}
skillBook3rd.m_dwUID = DBItemSerialMgr.GetNewItemSerial();
skillBook3rd.m_usProtoTypeID = 3401;
skillBook3rd.m_ItemPos = itemPos;
skillBook3rd.m_cNumOrDurability = static_cast<unsigned char>(cAmount);
skillBook3rd.m_cItemSize = sizeof(Item::ItemData);
memcpy(szDataPos, &skillBook3rd, sizeof(Item::ItemData));
szDataPos += sizeof(Item::ItemData);
itemChecker.Set(itemPos, 1, 1);
INFLOG8(g_SkillBookLog, "%s / UID:%10u / CID:%10u / ItemUID:0x%016I64X / PrototypeID:%6d / "
"ItemPos:(%d:0x%03X) / Num:%3d / 아이템 삽입 성공",
szPosition, dwUID, dwCID, skillBook3rd.m_dwUID, skillBook3rd.m_usProtoTypeID,
skillBook3rd.m_ItemPos.m_cPos, skillBook3rd.m_ItemPos.m_cIndex,
skillBook3rd.m_cNumOrDurability);
}
// 4단계 스킬북 삽입
while (0 < skillData.m_dwBookNum[3] &&
szDataPos + sizeof(Item::ItemData) < szDataEnd &&
itemChecker.FindEmptyPos(itemPos, 1, 1))
{
Item::ItemData skillBook4th;
memset(&skillBook4th, 0, sizeof(Item::ItemData));
unsigned char cAmount = 0;
if (100 < skillData.m_dwBookNum[3])
{
cAmount = 100;
skillData.m_dwBookNum[3] -= 100;
}
else
{
cAmount = static_cast<unsigned char>(skillData.m_dwBookNum[3]);
skillData.m_dwBookNum[3] = 0;
}
skillBook4th.m_dwUID = DBItemSerialMgr.GetNewItemSerial();
skillBook4th.m_usProtoTypeID = 3402;
skillBook4th.m_ItemPos = itemPos;
skillBook4th.m_cNumOrDurability = static_cast<unsigned char>(cAmount);
skillBook4th.m_cItemSize = sizeof(Item::ItemData);
memcpy(szDataPos, &skillBook4th, sizeof(Item::ItemData));
szDataPos += sizeof(Item::ItemData);
itemChecker.Set(itemPos, 1, 1);
INFLOG8(g_SkillBookLog, "%s / UID:%10u / CID:%10u / ItemUID:0x%016I64X / PrototypeID:%6d / "
"ItemPos:(%d:0x%03X) / Num:%3d / 아이템 삽입 성공",
szPosition, dwUID, dwCID, skillBook4th.m_dwUID, skillBook4th.m_usProtoTypeID,
skillBook4th.m_ItemPos.m_cPos, skillBook4th.m_ItemPos.m_cIndex,
skillBook4th.m_cNumOrDurability);
}
dwDataSize_InOut = static_cast<unsigned long>(szDataPos - szData_InOut);
}
// 캐릭터에 돈 넣어주기
CDBAddCharGold::CDBAddCharGold(GoldDataMap& CIDGoldDataMap)
: m_CIDGoldDataMap(CIDGoldDataMap)
{
}
ConvertResult CDBAddCharGold::operator()(RylDBCommand::CCharData& charData_InOut)
{
GoldDataMap::iterator pos = m_CIDGoldDataMap.find(charData_InOut.GetCID());
GoldDataMap::iterator end = m_CIDGoldDataMap.end();
if(pos != end)
{
unsigned long dwGold = pos->second;
unsigned long dwOldGold = charData_InOut.GetGold();
unsigned long dwNewGold = dwOldGold;
if(dwOldGold < ULONG_MAX - dwGold)
{
dwNewGold += dwGold;
}
else
{
INFLOG4(g_Log, "CID:%10u / Gold:%10u / AddGold:%10u / AddGold Overflow. Gold To %10u",
charData_InOut.GetCID(), dwOldGold, dwGold, ULONG_MAX);
dwNewGold = ULONG_MAX;
}
INFLOG4(g_GoldLog, "CID:%10u / OldGold:%10u / NewGold:%10u / AddGold:%10u / Added inventory gold",
charData_InOut.GetCID(), dwOldGold, dwNewGold, dwGold);
charData_InOut.SetGold(dwNewGold);
pos->second = 0;
return CONVERT_SUCCEEDED;
}
return CONVERT_DO_NOT_WRITE;
}
// 통합서버 창고에 돈 넣어주기
CDBAddUnifiedStoreGold::CDBAddUnifiedStoreGold(GoldDataMap& UIDGoldDataMap)
: m_UIDGoldDataMap(UIDGoldDataMap)
{
}
ConvertResult CDBAddUnifiedStoreGold::operator()(RylDBCommand::CUnifiedStore1& unifiedStore1_InOut)
{
GoldDataMap::iterator pos = m_UIDGoldDataMap.find(unifiedStore1_InOut.GetUID());
GoldDataMap::iterator end = m_UIDGoldDataMap.end();
if(pos != end)
{
unsigned long dwGold = pos->second;
unsigned long dwOldGold = unifiedStore1_InOut.GetGold();
unsigned long dwNewGold = dwOldGold;
if(dwOldGold < ULONG_MAX - dwGold)
{
dwNewGold += dwGold;
}
else
{
INFLOG5(g_Log, "UID:%10u / ServerGroupID:%d / Gold:%10u / AddGold:%10u / AddGold Overflow. Gold To %10u",
unifiedStore1_InOut.GetUID(), unifiedStore1_InOut.GetOldServerGroupID(),
dwOldGold, dwGold, ULONG_MAX);
dwNewGold = ULONG_MAX;
}
INFLOG5(g_GoldLog, "UID:%10u / ServerGroupID:%d / OldGold:%10u / NewGold:%10u / AddGold:%10u / Added store gold",
unifiedStore1_InOut.GetUID(), unifiedStore1_InOut.GetOldServerGroupID(),
dwOldGold, dwNewGold, dwGold);
unifiedStore1_InOut.SetGold(dwNewGold);
pos->second = 0;
return CONVERT_SUCCEEDED;
}
return CONVERT_DO_NOT_WRITE;
}
ConvertResult CDBAddUnifiedStoreGold::operator()(RylDBCommand::CUnifiedStore2& unifiedStore2_InOut)
{
return CONVERT_DO_NOT_WRITE;
}
// 남은 스킬북 로그로 남기기
void LogRemainSkillBook(SkillDataMap& SkillDataMap, const char* szHeader)
{
SkillDataMap::iterator pos = SkillDataMap.begin();
SkillDataMap::iterator end = SkillDataMap.end();
for(; pos != end; ++pos)
{
unsigned long dwKey = pos->first;
SkillBookInfo& data = pos->second;
if (0 != data.m_dwBookNum[0] || 0 != data.m_dwBookNum[1] ||
0 != data.m_dwBookNum[2] || 0 != data.m_dwBookNum[3])
{
INFLOG6(g_Log, "Remain skillBook(%s/%10u) : %3d / %3d / %3d / %3d",
szHeader, dwKey, data.m_dwBookNum[0], data.m_dwBookNum[1],
data.m_dwBookNum[2], data.m_dwBookNum[3]);
}
}
}
// 남은 스킬북 로그로 남기기
void LogRemainGold(GoldDataMap& GoldDataMap, const char* szHeader)
{
GoldDataMap::iterator pos = GoldDataMap.begin();
GoldDataMap::iterator end = GoldDataMap.end();
for(; pos != end; ++pos)
{
unsigned long dwKey = pos->first;
unsigned long dwGold = pos->second;
if (0 != dwGold)
{
INFLOG3(g_Log, "Remain Gold(%s/%10u) : %10u",
szHeader, dwKey, dwGold);
}
}
}
}

View File

@@ -0,0 +1,147 @@
#ifndef _RYL_REBALANCE_LIB_REBALANCE_H_
#define _RYL_REBALANCE_LIB_REBALANCE_H_
#pragma once
#pragma warning(disable:4800)
#include <map>
#include <boost/pool/pool_alloc.hpp>
#include <RylDBLibrary/RylDBLibrary.h>
#include <Item/RebalanceConvert/RebalanceItem.h>
// forward decl.
class CSkillMgr;
namespace Item
{
// forward decl.
class CItemMgr;
}
namespace OldItem
{
// forward decl.
class CItemMgr;
}
namespace RebalanceLib
{
// forward decl.
class CItemChecker;
// Key 는 UID 혹은 CID
// Value 는 스킬 개수
typedef std::map<unsigned long, SkillBookInfo, std::less<unsigned long>,
boost::fast_pool_allocator<std::pair<unsigned long, SkillBookInfo> > > SkillDataMap;
// Key 는 UID 혹은 CID
// Value 는 추가할 금액
typedef std::map<unsigned long, unsigned long, std::less<unsigned long>,
boost::fast_pool_allocator<std::pair<unsigned long, unsigned long> > > GoldDataMap;
// 스킬 읽기
class CDBReadSkill : public IDBCharSkillProcess
{
public:
CDBReadSkill(SkillDataMap& CIDSkillDataMap, bool bClearSkill = false);
virtual ConvertResult operator()(RylDBCommand::CSkillData& charSkillData_InOut);
private:
SkillDataMap& m_CIDSkillDataMap;
bool m_bClearSkill;
};
// 남은 스킬북 로그로 남기기
void LogRemainSkillBook(SkillDataMap& SkillDataMap, const char* szHeader);
// 남은 돈 로그로 남기기
void LogRemainGold(GoldDataMap& GoldDataMap, const char* szHeader);
// 스킬북 제거 및 카운팅 / 장비 컨버팅
class CDBItemConvert :
public IDBCharItemProcess,
public IDBCharItemExProcess,
public IDBStoreProcess
{
public:
// SkillDataMap을 넣으면, 스킬북을 제거하고 컨버팅한다.
CDBItemConvert(
CDBItemSerialMgr& dbItemSerialMgr,
Item::CItemMgr& newItemMgr, OldItem::CItemMgr& oldItemMgr,
SkillDataMap* lpUIDSkillDataMap, SkillDataMap* lpCIDSkillDataMap,
bool bConvertRebalanceItem = true, bool bRenumberingItemUID = true);
virtual ConvertResult operator()(RylDBCommand::CCharItem& charItem_InOut);
virtual ConvertResult operator()(RylDBCommand::CCharItemEx& charItemEx_InOut);
virtual ConvertResult operator()(RylDBCommand::CUnifiedStore1& unifiedStore1_InOut);
virtual ConvertResult operator()(RylDBCommand::CUnifiedStore2& unifiedStore2_InOut);
// 컨테이너를 컨버트한다.
bool ConvertData(unsigned long dwUID, unsigned long dwCID,
CItemChecker* lpItemChecker,
const char* szOriginalData, unsigned long dwOriginalSize,
char* szChangedData, unsigned long& dwChangedSize_InOut);
// 1/2단계 스킬북을 돈으로 바꿔 준다.
static void ChangeSkillBookToGold(SkillDataMap& skillDataMap, GoldDataMap& goldDataMap);
// 3/4단계 스킬북을 빈 컨테이너에 삽입한다.
static void GiveSkillBook(unsigned long dwUID, unsigned long dwCID,
CDBItemSerialMgr& DBItemSerialMgr, SkillBookInfo& skillData,
CItemChecker& itemChecker, const char* szPosition,
char* szData_InOut, unsigned long& dwDataSize_InOut);
private:
CDBItemSerialMgr& m_DBItemSerialMgr;
Item::CItemMgr& m_newItemMgr;
OldItem::CItemMgr& m_oldItemMgr;
SkillDataMap* m_lpUIDSkillDataMap;
SkillDataMap* m_lpCIDSkillDataMap;
bool m_bConvertRebalanceItem;
bool m_bRenumberingItemUID;
};
// 캐릭터에 돈 넣어주기
class CDBAddCharGold : public IDBCharInfoProcess
{
public:
CDBAddCharGold(GoldDataMap& CIDGoldDataMap);
virtual ConvertResult operator()(RylDBCommand::CCharData& charData_InOut);
private:
GoldDataMap& m_CIDGoldDataMap;
};
// 통합서버 창고에 돈 넣어주기
class CDBAddUnifiedStoreGold : public IDBStoreProcess
{
public:
CDBAddUnifiedStoreGold(GoldDataMap& UIDGoldDataMap);
virtual ConvertResult operator()(RylDBCommand::CUnifiedStore1& unifiedStore1_InOut);
virtual ConvertResult operator()(RylDBCommand::CUnifiedStore2& unifiedStore2_InOut);
private:
GoldDataMap& m_UIDGoldDataMap;
};
}
#endif

View File

@@ -0,0 +1,170 @@
// RebalanceConverter.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//
#include "stdafx.h"
#include "Rebalance.h"
#include <RylDBLibrary/RylDBLibrary.h>
#include <Item/RebalanceConvert/RebalanceItem.h>
#include <Item/ItemMgr.h>
#include <Skill/SkillMgr.h>
#include <Item/RebalanceConvert/OldItemMgr.h>
#include <Network/Packet/PacketStruct/ServerInfo.h>
#include <Utility/Setup/ServerSetup.h>
#include <Log/ServerLog.h>
void PrintUsage()
{
printf("usage : RebalanceConverter DBAddress DBName DBAccount DBPassword "
"ServerGroupNum(0~9) RenumberingUID(0/1)\n");
}
int _tmain(int argc, _TCHAR* argv[])
{
if(7 != argc)
{
PrintUsage();
return -1;
}
if(!Item::CItemMgr::GetInstance().LoadItemProtoType("./NewItemScript.txt"))
{
printf("NewItemScript.txt load failed\n");
return -1;
}
else if(!OldItem::CItemMgr::GetInstance().LoadItemProtoType("./OldItemScript.txt"))
{
printf("OldItemScript.txt load failed\n");
return -1;
}
using namespace RebalanceLib;
CoInitialize(0);
int nServerGroup = atoi(argv[5]);
bool bRenumberingUID = (1 == atoi(argv[6]));
SERVER_ID serverID;
serverID.sID.Type = CServerSetup::AuthServer;
serverID.sID.Group = nServerGroup;
serverID.sID.Channel = 0;
serverID.sID.ID = 0;
HRESULT hr = S_OK;
ATL::CDataSource dataSource;
ATL::CSession Session;
CDBItemSerialMgr dbItemSerialMgr;
#define LOG_CONVERT0(str) { ERRLOG0(g_Log, (str)); printf(str "\n"); }
#define LOG_CONVERT1(str, arg1) { ERRLOG1(g_Log, (str), (arg1)); printf(str "\n", (arg1)); }
#define LOG_CONVERT2(str, arg1, arg2) { ERRLOG2(g_Log, (str), (arg1), (arg2)); printf(str "\n", (arg1), (arg2)); }
if(FAILED(hr = CRylDBProcess::ConnectDB(dataSource, argv[1], argv[2], argv[3], argv[4])))
{
LOG_CONVERT1("Connect DB failed : hr:0x%08X", hr);
}
else if(FAILED(hr = Session.Open(dataSource)))
{
LOG_CONVERT1("Open session failed : hr:0x%08X", hr);
}
else if(FAILED(hr = dbItemSerialMgr.ClearAllSerialDB(Session)))
{
LOG_CONVERT1("Clear itemSerial failed : hr:0x%08X", hr);
}
else if(FAILED(hr = dbItemSerialMgr.LoadItemSerialDB(Session, serverID.dwID)))
{
LOG_CONVERT1("Insert itemSerial failed : hr:0x%08X", hr);
}
else
{
CRylDBProcess rylDBProcess(Session);
CConsoleCounter consoleCounter(1000);
SkillDataMap UIDSkillDataMap;
SkillDataMap CIDSkillDataMap;
CDBReadSkill readDBSkill(CIDSkillDataMap, true);
CDBItemConvert convertDBItem(dbItemSerialMgr,
Item::CItemMgr::GetInstance(), OldItem::CItemMgr::GetInstance(),
&UIDSkillDataMap, &CIDSkillDataMap, true, bRenumberingUID);
// 스킬 읽기
if(FAILED(hr = rylDBProcess.CharSkill(readDBSkill, consoleCounter)))
{
LOG_CONVERT1("Skill process failed : hr:0x%08X", hr);
}
// CharItem컨버트
else if(FAILED(hr = rylDBProcess.CharItem(convertDBItem, consoleCounter)))
{
LOG_CONVERT1("CharItem process failed : hr:0x%08X", hr);
}
// CharItemEx컨버트
else if(FAILED(hr = rylDBProcess.CharItemEx(convertDBItem, consoleCounter)))
{
LOG_CONVERT1("CharItemEx process failed : hr:0x%08X", hr);
}
// 통합서버 창고 컨버트
else if(FAILED(hr = rylDBProcess.UnifiedStore1(convertDBItem, consoleCounter)))
{
LOG_CONVERT1("UnifiedStore1 process failed : hr:0x%08X", hr);
}
else if(FAILED(hr = rylDBProcess.UnifiedStore2(convertDBItem, consoleCounter)))
{
LOG_CONVERT1("UnifiedStore2 process failed : hr:0x%08X", hr);
}
else
{
GoldDataMap UIDGoldDataMap;
GoldDataMap CIDGoldDataMap;
CDBItemConvert::ChangeSkillBookToGold(UIDSkillDataMap, UIDGoldDataMap);
CDBItemConvert::ChangeSkillBookToGold(CIDSkillDataMap, CIDGoldDataMap);
CDBAddUnifiedStoreGold addUnifiedStoreGold(UIDGoldDataMap);
CDBAddCharGold addCharGold(CIDGoldDataMap);
if(FAILED(hr = rylDBProcess.UnifiedStore1(addUnifiedStoreGold, consoleCounter)))
{
LOG_CONVERT1("Add store gold process failed : hr:0x%08X", hr);
}
else if(FAILED(hr = rylDBProcess.CharInfo(addCharGold, consoleCounter)))
{
LOG_CONVERT1("Add character gold process failed : hr:0x%08X", hr);
}
// 남은 스킬북 양을 확인.
LogRemainSkillBook(UIDSkillDataMap, "UIDBook");
LogRemainSkillBook(CIDSkillDataMap, "CIDBook");
// 남은 돈 양을 확인.
LogRemainGold(UIDGoldDataMap, "UIDGold");
LogRemainGold(CIDGoldDataMap, "CIDGold");
// 최종 아이템 시리얼 저장.
if(FAILED(hr = dbItemSerialMgr.SaveItemSerialDB(Session, serverID.dwID)))
{
LOG_CONVERT1("ItemSerial save failed : hr:0x%08X", hr);
}
// 아이템 등급 출력
CItemGrade::GetInstance().WriteGradeNum();
INFLOG2(g_Log, "MaxUID : (0x%08X / %016I64X)",
serverID.dwID, dbItemSerialMgr.GetItemSerial());
}
}
INFLOG0(g_Log, "Convert Complete");
Session.Close();
dataSource.Close();
CoUninitialize();
return 0;
}

View File

@@ -0,0 +1,169 @@
<?xml version="1.0" encoding="ks_c_5601-1987"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="RebalanceConverter"
ProjectGUID="{4AEC21B2-025C-421E-AB4E-BC93E6B191AF}"
SccProjectName="SAK"
SccAuxPath="SAK"
SccLocalPath="SAK"
SccProvider="SAK"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../Executable/$(ConfigurationName)"
IntermediateDirectory="../Intermediate/$(ProjectName)/$(ConfigurationName)"
ConfigurationType="1"
UseOfATL="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../;../../RylServerProject;../../RylServerProject/BaseLibrary;../../RylServerProject/RylServerLibrary;../../RylServerProject/RylGameLibrary"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="2"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="ws2_32.lib"
OutputFile="$(OutDir)/RebalanceConverter.exe"
LinkIncremental="2"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/RebalanceConverter.pdb"
SubSystem="1"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../Executable/$(ConfigurationName)"
IntermediateDirectory="../Intermediate/$(ProjectName)/$(ConfigurationName)"
ConfigurationType="1"
UseOfATL="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../;../../RylServerProject;../../RylServerProject/BaseLibrary;../../RylServerProject/RylServerLibrary;../../RylServerProject/RylGameLibrary"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="0"
UsePrecompiledHeader="2"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="ws2_32.lib"
OutputFile="$(OutDir)/RebalanceConverter.exe"
LinkIncremental="1"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="소스 파일"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
<File
RelativePath=".\Rebalance.cpp">
</File>
<File
RelativePath=".\RebalanceConverter.cpp">
</File>
<File
RelativePath=".\stdafx.cpp">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"/>
</FileConfiguration>
</File>
</Filter>
<Filter
Name="헤더 파일"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
<File
RelativePath=".\Rebalance.h">
</File>
<File
RelativePath=".\stdafx.h">
</File>
</Filter>
<Filter
Name="리소스 파일"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
</Filter>
<File
RelativePath=".\ReadMe.txt">
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,8 @@
// stdafx.cpp : 표준 포함 파일만 들어 있는 소스 파일입니다.
// RebalanceConverter.pch는 미리 컴파일된 헤더가 됩니다.
// stdafx.obj에는 미리 컴파일된 형식 정보가 포함됩니다.
#include "stdafx.h"
// TODO: 필요한 추가 헤더는
// 이 파일이 아닌 STDAFX.H에서 참조합니다.

View File

@@ -0,0 +1,15 @@
// stdafx.h : 자주 사용하지만 자주 변경되지는 않는
// 표준 시스템 포함 파일 및 프로젝트 관련 포함 파일이
// 들어 있는 포함 파일입니다.
//
#pragma once
#include <iostream>
#include <tchar.h>
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // 일부 CString 생성자는 명시적으로 선언됩니다.
#include <atlbase.h>
// TODO: 프로그램에 필요한 추가 헤더는 여기에서 참조합니다.