Files
Client/Server/DBProcess/ConvertBinaryToRow/ConvertBinaryToRow.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

1214 lines
46 KiB
C++

// ConvertBinaryToRow.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
// RebalanceConverter.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
#include "stdafx.h"
#include <Log/ServerLog.h>
#include <Item/ItemMgr.h>
#include <Item/ItemStructure.h>
#include <RylDBLibrary/RylDBLibrary.h>
#include <RylDBLibrary/RylDBCharCommand.h>
#include <RylDBLibrary/RylDBStoreCommand.h>
#include <Network/Packet/PacketStruct/CharQuestPacket.h>
#include <Network/Packet/PacketStruct/FriendPacket.h>
#include <Network/Packet/PacketStruct/UnifiedCharPacket.h>
#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)); }
namespace ConvertDB
{
struct CharItem
{
INT64 m_ItemUID;
INT32 m_OwnerUID;
INT32 m_OwnerCID;
INT32 m_PrototypeID;
BYTE m_ItemContainerID;
BYTE m_ItemContainerPos;
BYTE m_NumOrDurability;
BYTE m_OldServerGroupID;
DBSTATUSENUM m_ItemUIDStatus;
DBSTATUSENUM m_OwnerUIDStatus;
DBSTATUSENUM m_OwnerCIDStatus;
DBSTATUSENUM m_PrototypeIDStatus;
DBSTATUSENUM m_ItemContainerIDStatus;
DBSTATUSENUM m_ItemContainerPosStatus;
DBSTATUSENUM m_NumOrDurabilityStatus;
DBSTATUSENUM m_OldServerGroupIDStatus;
BEGIN_PARAM_MAP(CharItem)
COLUMN_ENTRY_STATUS(1, m_ItemUID, m_ItemUIDStatus)
COLUMN_ENTRY_STATUS(2, m_OwnerUID, m_OwnerUIDStatus)
COLUMN_ENTRY_STATUS(3, m_OldServerGroupID, m_OldServerGroupIDStatus)
COLUMN_ENTRY_STATUS(4, m_OwnerCID, m_OwnerCIDStatus)
COLUMN_ENTRY_STATUS(5, m_PrototypeID, m_PrototypeIDStatus)
COLUMN_ENTRY_STATUS(6, m_ItemContainerID, m_ItemContainerIDStatus)
COLUMN_ENTRY_STATUS(7, m_ItemContainerPos, m_ItemContainerPosStatus)
COLUMN_ENTRY_STATUS(8, m_NumOrDurability, m_NumOrDurabilityStatus)
END_PARAM_MAP()
};
struct CharEquipItem
{
enum
{
MAX_RUNE = 2
};
INT64 m_ItemUID;
BYTE m_SocketValue[Item::EquipmentInfo::MAX_SOCKET_NUM];
BYTE m_UpgradeLevel;
BYTE m_SeasonRecord;
SHORT m_MaxDurability;
SHORT m_Attribute[Item::Attribute::MAX_DB_ATTRIBUTE_NUM];
SHORT m_Rune[MAX_RUNE];
DBLENGTH m_SocketValueLen;
DBSTATUSENUM m_ItemUIDStatus;
DBSTATUSENUM m_SocketValueStatus;
DBSTATUSENUM m_UpgradeLevelStatus;
DBSTATUSENUM m_SeasonRecordStatus;
DBSTATUSENUM m_MaxDurabilityStatus;
DBSTATUSENUM m_AttributeStatus[Item::Attribute::MAX_DB_ATTRIBUTE_NUM];
DBSTATUSENUM m_RuneStatus[MAX_RUNE];
BEGIN_PARAM_MAP(CharEquipItem)
COLUMN_ENTRY_STATUS( 1, m_ItemUID, m_ItemUIDStatus)
COLUMN_ENTRY_LENGTH_STATUS(2, m_SocketValue, m_SocketValueLen, m_SocketValueStatus)
COLUMN_ENTRY_STATUS( 3, m_UpgradeLevel, m_UpgradeLevelStatus)
COLUMN_ENTRY_STATUS( 4, m_SeasonRecord, m_SeasonRecordStatus)
COLUMN_ENTRY_STATUS( 5, m_MaxDurability, m_MaxDurabilityStatus)
COLUMN_ENTRY_STATUS( 6, m_Attribute[Item::Attribute::MIN_DAMAGE], m_AttributeStatus[Item::Attribute::MIN_DAMAGE])
COLUMN_ENTRY_STATUS( 7, m_Attribute[Item::Attribute::MAX_DAMAGE], m_AttributeStatus[Item::Attribute::MAX_DAMAGE])
COLUMN_ENTRY_STATUS( 8, m_Attribute[Item::Attribute::ARMOR], m_AttributeStatus[Item::Attribute::ARMOR])
COLUMN_ENTRY_STATUS( 9, m_Attribute[Item::Attribute::HIT_RATE], m_AttributeStatus[Item::Attribute::HIT_RATE])
COLUMN_ENTRY_STATUS(10, m_Attribute[Item::Attribute::EVADE], m_AttributeStatus[Item::Attribute::EVADE])
COLUMN_ENTRY_STATUS(11, m_Attribute[Item::Attribute::MAX_HP], m_AttributeStatus[Item::Attribute::MAX_HP])
COLUMN_ENTRY_STATUS(12, m_Attribute[Item::Attribute::HP_REGEN], m_AttributeStatus[Item::Attribute::HP_REGEN])
COLUMN_ENTRY_STATUS(13, m_Attribute[Item::Attribute::MAX_MP], m_AttributeStatus[Item::Attribute::MAX_MP])
COLUMN_ENTRY_STATUS(14, m_Attribute[Item::Attribute::MP_REGEN], m_AttributeStatus[Item::Attribute::MP_REGEN])
COLUMN_ENTRY_STATUS(15, m_Attribute[Item::Attribute::CRITICAL], m_AttributeStatus[Item::Attribute::CRITICAL])
COLUMN_ENTRY_STATUS(16, m_Attribute[Item::Attribute::BLOCK], m_AttributeStatus[Item::Attribute::BLOCK])
COLUMN_ENTRY_STATUS(17, m_Attribute[Item::Attribute::SPEED], m_AttributeStatus[Item::Attribute::SPEED])
COLUMN_ENTRY_STATUS(18, m_Attribute[Item::Attribute::MAGIC_POWER], m_AttributeStatus[Item::Attribute::MAGIC_POWER])
COLUMN_ENTRY_STATUS(19, m_Attribute[Item::Attribute::MAGIC_RESIST], m_AttributeStatus[Item::Attribute::MAGIC_RESIST])
COLUMN_ENTRY_STATUS(20, m_Rune[0], m_RuneStatus[0])
COLUMN_ENTRY_STATUS(21, m_Rune[1], m_RuneStatus[1])
END_PARAM_MAP()
};
struct CharSkillData
{
INT32 m_OwnerCID;
INT32 m_Skill_ID;
BYTE m_LockCount;
BYTE m_Level;
DBSTATUSENUM m_OwnerCIDStatus;
DBSTATUSENUM m_Skill_IDStatus;
DBSTATUSENUM m_LockCountStatus;
DBSTATUSENUM m_LevelStatus;
BEGIN_PARAM_MAP(CharSkillData)
COLUMN_ENTRY_STATUS(1, m_OwnerCID, m_OwnerCIDStatus)
COLUMN_ENTRY_STATUS(2, m_Skill_ID, m_Skill_IDStatus)
COLUMN_ENTRY_STATUS(3, m_LockCount, m_LockCountStatus)
COLUMN_ENTRY_STATUS(4, m_Level, m_LevelStatus)
END_PARAM_MAP()
};
struct CharQuestExisting
{
INT32 m_OwnerCID;
INT32 m_QuestID;
BYTE m_CurrentPhase;
BYTE m_TriggerCounts[PktQuestDB::MAX_TRIGGER];
DBLENGTH m_TriggerCountsLen;
DBSTATUSENUM m_OwnerCIDStatus;
DBSTATUSENUM m_QuestIDStatus;
DBSTATUSENUM m_CurrentPhaseStatus;
DBSTATUSENUM m_TriggerCountsStatus;
BEGIN_PARAM_MAP(CharQuestExisting)
COLUMN_ENTRY_STATUS(1, m_OwnerCID, m_OwnerCIDStatus)
COLUMN_ENTRY_STATUS(2, m_QuestID, m_QuestIDStatus)
COLUMN_ENTRY_STATUS(3, m_CurrentPhase, m_CurrentPhaseStatus)
COLUMN_ENTRY_LENGTH_STATUS(4, m_TriggerCounts, m_TriggerCountsLen, m_TriggerCountsStatus)
END_PARAM_MAP()
};
struct CharQuestHistory
{
INT32 m_OwnerCID;
INT32 m_QuestID;
DBSTATUSENUM m_OwnerCIDStatus;
DBSTATUSENUM m_QuestIDStatus;
BEGIN_PARAM_MAP(CharQuestHistory)
COLUMN_ENTRY_STATUS(1, m_OwnerCID, m_OwnerCIDStatus)
COLUMN_ENTRY_STATUS(2, m_QuestID, m_QuestIDStatus)
END_PARAM_MAP()
};
struct CharFriend
{
INT32 m_OwnerCID;
INT32 m_FriendCID;
DBSTATUSENUM m_OwnerCIDStatus;
DBSTATUSENUM m_FriendCIDStatus;
BEGIN_PARAM_MAP(CharFriend)
COLUMN_ENTRY_STATUS(1, m_OwnerCID, m_OwnerCIDStatus)
COLUMN_ENTRY_STATUS(2, m_FriendCID, m_FriendCIDStatus)
END_PARAM_MAP()
};
struct CharBan
{
INT32 m_OwnerCID;
INT32 m_BanCID;
DBSTATUSENUM m_OwnerCIDStatus;
DBSTATUSENUM m_BanCIDStatus;
BEGIN_PARAM_MAP(CharBan)
COLUMN_ENTRY_STATUS(1, m_OwnerCID, m_OwnerCIDStatus)
COLUMN_ENTRY_STATUS(2, m_BanCID, m_BanCIDStatus)
END_PARAM_MAP()
};
struct CharParty
{
INT32 m_PID;
INT32 m_GID;
DBSTATUSENUM m_PIDStatus;
DBSTATUSENUM m_GIDStatus;
BEGIN_PARAM_MAP(CharParty)
COLUMN_ENTRY_STATUS(1, m_PID, m_PIDStatus)
COLUMN_ENTRY_STATUS(2, m_GID, m_GIDStatus)
END_PARAM_MAP()
};
struct CharPartyMember
{
INT32 m_PID;
INT32 m_MemberCID;
DBSTATUSENUM m_PIDStatus;
DBSTATUSENUM m_MemberCIDStatus;
BEGIN_PARAM_MAP(CharPartyMember)
COLUMN_ENTRY_STATUS(1, m_PID, m_PIDStatus)
COLUMN_ENTRY_STATUS(2, m_MemberCID, m_MemberCIDStatus)
END_PARAM_MAP()
};
}
class CBinaryParse :
public IDBCharSkillProcess,
public IDBCharItemProcess,
public IDBCharItemExProcess,
public IDBCharQuestProcess,
public IDBStoreProcess,
public IDBPartyProcess,
public IDBFriendProcess,
public IDBUnifiedCharInfoProcess
{
public:
enum Nation
{
KOREA = 0,
OTHER = 1
};
CBinaryParse(ATL::CSession& writeSession, Nation nation);
HRESULT DropAndCreateTables();
ConvertResult operator() (RylDBCommand::CCharItem& charItem_InOut);
ConvertResult operator() (RylDBCommand::CCharItemEx& charItemEx_InOut);
ConvertResult operator() (RylDBCommand::CUnifiedStore1& unifiedStore1_InOut);
ConvertResult operator() (RylDBCommand::CUnifiedStore2& unifiedStore2_InOut);
ConvertResult operator() (RylDBCommand::CSkillData& charSkillData_InOut);
ConvertResult operator() (RylDBCommand::CCharQuest& charQuest_InOut);
ConvertResult operator() (RylDBCommand::CPartyData& partyData);
ConvertResult operator() (RylDBCommand::CFriendData& friendData);
ConvertResult operator() (RylDBCommand::CUnifiedCharList& unifiedCharList);
private:
BYTE GetOldServerGroupID(DWORD dwCID)
{
OldServerIDMap::iterator pos = m_CIDMap.find(dwCID);
return pos != m_CIDMap.end() ? static_cast<BYTE>(pos->second) : UCHAR_MAX;
}
bool IsPart2Data(BYTE cOldServerGroupID)
{
switch(cOldServerGroupID)
{
case UnifiedConst::Part2:
case UnifiedConst::Part2Unified:
case UnifiedConst::Part2Selectable:
return true;
}
// 한국 외 통합은, 전부 Part2로 아이템이 컨버팅 되어 있음.
// Part1으로 명시되어 있지 않은 경우만 제외하고 전부 컨버팅함.
return (m_Nation == OTHER &&
0 < cOldServerGroupID &&
cOldServerGroupID < UnifiedConst::Part1);
}
void ParseItemAndInsert(DWORD dwOwnerUID, BYTE cOldServerGroupID,
DWORD dwOwnerCID, const char* szData, unsigned long dwDataLen);
// Key : CID / Value : OldServerGroupID
typedef std::map<unsigned long, unsigned long> OldServerIDMap;
ATL::CSession& m_WriteSession;
ATL::CDBPropSet m_DBRowset;
ATL::CCommand<CAccessor<ConvertDB::CharItem>, CNoRowset> m_InsertItemCmd;
ATL::CCommand<CAccessor<ConvertDB::CharEquipItem>, CNoRowset> m_InsertEquipItemCmd;
ATL::CCommand<CAccessor<ConvertDB::CharSkillData>, CNoRowset> m_InsertSkillData;
ATL::CCommand<CAccessor<ConvertDB::CharQuestExisting>, CNoRowset> m_InsertQuestExisting;
ATL::CCommand<CAccessor<ConvertDB::CharQuestHistory>, CNoRowset> m_InsertQuestHistory;
ATL::CCommand<CAccessor<ConvertDB::CharFriend>, CNoRowset> m_InsertFriend;
ATL::CCommand<CAccessor<ConvertDB::CharBan>, CNoRowset> m_InsertBan;
ATL::CCommand<CAccessor<ConvertDB::CharParty>, CNoRowset> m_InsertParty;
ATL::CCommand<CAccessor<ConvertDB::CharPartyMember>, CNoRowset> m_InsertPartyMember;
OldServerIDMap m_CIDMap;
Nation m_Nation;
};
HRESULT CreateAndPrepareCmd(ATL::CSession& writeSession, ATL::CCommandBase& command,
const char* szQuery, const char* szCommandName)
{
HRESULT hr = S_OK;
if (FAILED(hr = command.Create(writeSession, szQuery)))
{
LOG_CONVERT2("Create %s command failed : HRESULT(0x%08x)", szCommandName, hr);
}
else if (FAILED(hr = command.Prepare()))
{
LOG_CONVERT2("Prepare %s command failed : HRESULT(0x%08x)", szCommandName, hr);
}
return hr;
}
void PrintUsage()
{
printf("usage : ConvertBinaryToRow SrcDBAddr SrcDBName SrcDBAccount SrcDBPassword \n"
"DstDBAddr DstDBName DstDBAccount DstDBPassword NationType(0:Korea / 1:Other)");
}
int _tmain(int argc, _TCHAR* argv[])
{
if (10 != argc)
{
PrintUsage();
return -1;
}
if(!Item::CItemMgr::GetInstance().LoadItemProtoType("./ItemScript.txt"))
{
printf("ItemScript.txt load failed\n");
return -1;
}
CoInitialize(0);
HRESULT hr = S_OK;
ATL::CDataSource readSource;
ATL::CSession readSession;
ATL::CDataSource writeSource;
ATL::CSession writeSession;
if (FAILED(hr = CRylDBProcess::ConnectDB(readSource, argv[1], argv[2], argv[3], argv[4])))
{
LOG_CONVERT1("Connect ReadDB failed : hr:0x%08X", hr);
}
else if (FAILED(hr = readSession.Open(readSource)))
{
LOG_CONVERT1("Open ReadSession failed : hr:0x%08X", hr);
}
if (FAILED(hr = CRylDBProcess::ConnectDB(writeSource, argv[5], argv[6], argv[7], argv[8])))
{
LOG_CONVERT1("Connect WriteDB failed : hr:0x%08X", hr);
}
else if (FAILED(hr = writeSession.Open(writeSource)))
{
LOG_CONVERT1("Open WriteSession failed : hr:0x%08X", hr);
}
else
{
CRylDBProcess rylDBProcess(readSession);
CConsoleCounter consoleCounter(1000);
CBinaryParse binaryParse(writeSession,
(0 == atoi(argv[9])) ? CBinaryParse::KOREA : CBinaryParse::OTHER);
if (SUCCEEDED(binaryParse.DropAndCreateTables()) &&
rylDBProcess.UnifiedCharList(binaryParse, consoleCounter) && // 제일 먼저 해야 함
rylDBProcess.CharItem(binaryParse, consoleCounter) &&
rylDBProcess.CharItemEx(binaryParse, consoleCounter) &&
rylDBProcess.UnifiedStore1(binaryParse, consoleCounter) &&
rylDBProcess.UnifiedStore2(binaryParse, consoleCounter) &&
rylDBProcess.CharSkill(binaryParse, consoleCounter) &&
rylDBProcess.CharQuest(binaryParse, consoleCounter) &&
rylDBProcess.Friend(binaryParse, consoleCounter) &&
rylDBProcess.Party(binaryParse, consoleCounter))
{
LOG_CONVERT0("Convert Succeeded");
}
else
{
LOG_CONVERT0("Convert Failed");
}
}
readSession.Close();
writeSession.Close();
readSource.Close();
writeSource.Close();
CoUninitialize();
return 0;
}
CBinaryParse::CBinaryParse(ATL::CSession& writeSession, Nation nation)
: m_WriteSession(writeSession), m_DBRowset(DBPROPSET_ROWSET), m_Nation(nation)
{
}
HRESULT CBinaryParse::DropAndCreateTables()
{
HRESULT hr = S_OK;
ATL::CCommand<> CmdCreateTable;
// 만들 테이블
// 아이템, 스킬, 퀘스트, 프렌드, 파티
// 아이템
if (FAILED(hr = CmdCreateTable.Open(m_WriteSession, "DROP TABLE dbo.TblCharItemEquipInfo")))
{
LOG_CONVERT1("Drop dbo.TblCharItemEquipInfo table failed : HRESULT(0x%08x)", hr);
}
if (FAILED(hr = CmdCreateTable.Open(m_WriteSession, "DROP TABLE dbo.TblCharItem")))
{
LOG_CONVERT1("Drop dbo.TblCharItem table failed : HRESULT(0x%08x)", hr);
}
if (FAILED(hr = CmdCreateTable.Open(m_WriteSession,
"CREATE TABLE dbo.TblCharItem ( "
" ItemUID bigint PRIMARY KEY, "
" OwnerUID int, "
" OldServerGroupID tinyint, "
" OwnerCID int, "
" PrototypeID int NOT NULL, "
" ItemContainerID tinyint NOT NULL, "
" ItemContainerPos tinyint NOT NULL, "
" NumOrDurability tinyint NOT NULL, "
" FOREIGN KEY (OwnerCID) REFERENCES CharInfo(CID), "
" FOREIGN KEY (OwnerUID, OldServerGroupID) REFERENCES UserInfo(UID, OldServerGroupID))")))
{
LOG_CONVERT1("Create dbo.TblCharItem table failed : HRESULT(0x%08x)", hr);
return hr;
}
if (FAILED(hr = CmdCreateTable.Open(m_WriteSession,
"CREATE TABLE dbo.TblCharItemEquipInfo ("
" ItemUID bigint FOREIGN KEY REFERENCES dbo.TblCharItem(ItemUID),"
" SocketValue varbinary(8),"
" UpgradeLevel tinyint NOT NULL default(0),"
" SeasonRecord tinyint NOT NULL default(0),"
" MaxDurability smallint NOT NULL default(0),"
" Attr_MinDamage smallint NOT NULL default(0),"
" Attr_MaxDamage smallint NOT NULL default(0),"
" Attr_Armour smallint NOT NULL default(0),"
" Attr_HitRate smallint NOT NULL default(0),"
" Attr_Evade smallint NOT NULL default(0),"
" Attr_MaxHP smallint NOT NULL default(0),"
" Attr_HPRegen smallint NOT NULL default(0),"
" Attr_MaxMP smallint NOT NULL default(0),"
" Attr_MPRegen smallint NOT NULL default(0),"
" Attr_Critical smallint NOT NULL default(0),"
" Attr_Block smallint NOT NULL default(0),"
" Attr_Speed smallint NOT NULL default(0),"
" Attr_MagicPower smallint NOT NULL default(0),"
" Attr_MagicResist smallint NOT NULL default(0),"
" Attr_Rune1 smallint NOT NULL default(0),"
" Attr_Rune2 smallint NOT NULL default(0))")))
{
LOG_CONVERT1("Create dbo.TblCharItemEquipInfo table failed : HRESULT(0x%08x)", hr);
return hr;
}
// 스킬
if (FAILED(hr = CmdCreateTable.Open(m_WriteSession, "DROP TABLE dbo.TblCharSkill")))
{
LOG_CONVERT1("Drop dbo.TblCharSkill table failed : HRESULT(0x%08x)", hr);
}
if (FAILED(hr = CmdCreateTable.Open(m_WriteSession,
"CREATE TABLE dbo.TblCharSkill ("
" OwnerCID int FOREIGN KEY REFERENCES CharInfo(CID),"
" Skill_ID int NOT NULL,"
" Lockcount tinyint NOT NULL,"
" Level tinyint NOT NULL)")))
{
LOG_CONVERT1("Create dbo.TblCharSkill table failed : HRESULT(0x%08x)", hr);
return hr;
}
// 퀘스트, 히스토리 테이블
if (FAILED(hr = CmdCreateTable.Open(m_WriteSession, "DROP TABLE dbo.TblCharQuestExisting")))
{
LOG_CONVERT1("Drop dbo.TblCharQuestExisting table failed : HRESULT(0x%08x)", hr);
}
if (FAILED(hr = CmdCreateTable.Open(m_WriteSession, "DROP TABLE dbo.TblCharQuestHistory")))
{
LOG_CONVERT1("Drop dbo.TblCharQuestHistory table failed : HRESULT(0x%08x)", hr);
}
if (FAILED(hr = CmdCreateTable.Open(m_WriteSession,
"CREATE TABLE dbo.TblCharQuestExisting ("
" OwnerCID int FOREIGN KEY REFERENCES CharInfo(CID),"
" QuestID int NOT NULL,"
" CurrentPhase tinyint NOT NULL default(0),"
" TriggerCounts varbinary(10) NOT NULL)")))
{
LOG_CONVERT1("Create dbo.TblCharQuestExisting table failed : HRESULT(0x%08x)", hr);
return hr;
}
if (FAILED(hr = CmdCreateTable.Open(m_WriteSession,
"CREATE TABLE dbo.TblCharQuestHistory ("
" OwnerCID int FOREIGN KEY REFERENCES CharInfo(CID),"
" QuestID int NOT NULL)")))
{
LOG_CONVERT1("Create dbo.TblCharQuestHistory table failed : HRESULT(0x%08x)", hr);
return hr;
}
// 프렌드/밴
if (FAILED(hr = CmdCreateTable.Open(m_WriteSession, "DROP TABLE dbo.TblCharFriend")))
{
LOG_CONVERT1("Drop dbo.TblCharFriend table failed : HRESULT(0x%08x)", hr);
}
if (FAILED(hr = CmdCreateTable.Open(m_WriteSession, "DROP TABLE dbo.TblCharBan")))
{
LOG_CONVERT1("Drop dbo.TblCharBan table failed : HRESULT(0x%08x)", hr);
}
if (FAILED(hr = CmdCreateTable.Open(m_WriteSession,
"CREATE TABLE dbo.TblCharFriend ("
"OwnerCID int NOT NULL FOREIGN KEY REFERENCES CharInfo(CID), "
"FriendCID int NOT NULL FOREIGN KEY REFERENCES CharInfo(CID))")))
{
LOG_CONVERT1("Create dbo.TblCharFriend table failed : HRESULT(0x%08x)", hr);
return hr;
}
if (FAILED(hr = CmdCreateTable.Open(m_WriteSession,
"CREATE TABLE dbo.TblCharBan ("
"OwnerCID int NOT NULL FOREIGN KEY REFERENCES CharInfo(CID), "
"BanCID int NOT NULL FOREIGN KEY REFERENCES CharInfo(CID))")))
{
LOG_CONVERT1("Create dbo.TblCharBan table failed : HRESULT(0x%08x)", hr);
return hr;
}
// 파티
if (FAILED(hr = CmdCreateTable.Open(m_WriteSession, "DROP TABLE dbo.TblCharPartyMember")))
{
LOG_CONVERT1("Drop dbo.TblCharPartyMember table failed : HRESULT(0x%08x)", hr);
}
if (FAILED(hr = CmdCreateTable.Open(m_WriteSession, "DROP TABLE dbo.TblCharParty")))
{
LOG_CONVERT1("Drop dbo.TblCharParty table failed : HRESULT(0x%08x)", hr);
}
if (FAILED(hr = CmdCreateTable.Open(m_WriteSession,
"CREATE TABLE dbo.TblCharParty("
" PID int PRIMARY KEY IDENTITY,"
" GID int)")))
{
LOG_CONVERT1("Create dbo.TblCharParty table failed : HRESULT(0x%08x)", hr);
return hr;
}
if (FAILED(hr = CmdCreateTable.Open(m_WriteSession,
"CREATE TABLE dbo.TblCharPartyMember("
" PID int FOREIGN KEY REFERENCES dbo.TblCharParty(PID),"
" MemberCID int NOT NULL FOREIGN KEY REFERENCES CharInfo(CID))")))
{
LOG_CONVERT1("Create dbo.TblCharPartyMember table failed : HRESULT(0x%08x)", hr);
return hr;
}
m_DBRowset.AddProperty(DBPROP_IRowsetChange, true);
m_DBRowset.AddProperty(DBPROP_UPDATABILITY,
DBPROPVAL_UP_INSERT | DBPROPVAL_UP_CHANGE | DBPROPVAL_UP_DELETE);
if (FAILED(hr = CreateAndPrepareCmd(m_WriteSession, m_InsertItemCmd,
"INSERT INTO dbo.TblCharItem "
"(ItemUID, OwnerUID, OldServerGroupID, OwnerCID, PrototypeID, "
"ItemContainerID, ItemContainerPos, NumOrDurability) "
"VALUES (?,?,?,?,?,?,?,?)", "InsertItem")))
{
return hr;
}
if (FAILED(hr = CreateAndPrepareCmd(m_WriteSession, m_InsertEquipItemCmd,
"INSERT INTO dbo.TblCharItemEquipInfo "
"(ItemUID, SocketValue, UpgradeLevel, SeasonRecord, MaxDurability, "
" Attr_MinDamage, Attr_MaxDamage, Attr_Armour, Attr_HitRate, Attr_Evade, "
" Attr_MaxHP, Attr_HPRegen, Attr_MaxMP, Attr_MPRegen, Attr_Critical, Attr_Block, "
" Attr_Speed, Attr_MagicPower, Attr_MagicResist, Attr_Rune1, Attr_Rune2) "
" VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", "InsertEquipItem")))
{
return hr;
}
if (FAILED(hr = CreateAndPrepareCmd(m_WriteSession, m_InsertSkillData,
"INSERT INTO dbo.TblCharSkill (OwnerCID, Skill_ID, Lockcount, Level) VALUES (?,?,?,?)",
"InsertSkillData")))
{
return hr;
}
if (FAILED(hr = CreateAndPrepareCmd(m_WriteSession, m_InsertQuestExisting,
"INSERT INTO dbo.TblCharQuestExisting (OwnerCID, QuestID, CurrentPhase, TriggerCounts) "
"VALUES (?, ?, ?, ?)", "InsertQuestExisting")))
{
return hr;
}
if (FAILED(hr = CreateAndPrepareCmd(m_WriteSession, m_InsertQuestHistory,
"INSERT INTO dbo.TblCharQuestHistory (OwnerCID, QuestID) VALUES (?, ?)",
"InsertQuestHistory")))
{
return hr;
}
if (FAILED(hr = CreateAndPrepareCmd(m_WriteSession, m_InsertFriend,
"INSERT INTO dbo.TblCharFriend (OwnerCID, FriendCID) VALUES (?, ?)",
"InsertFriend")))
{
return hr;
}
if (FAILED(hr = CreateAndPrepareCmd(m_WriteSession, m_InsertBan,
"INSERT INTO dbo.TblCharBan (OwnerCID, BanCID) VALUES (?, ?)",
"InsertBan")))
{
return hr;
}
if (FAILED(hr = CreateAndPrepareCmd(m_WriteSession, m_InsertParty,
"INSERT INTO dbo.TblCharParty (PID, GID) VALUES (?,?)",
"InsertParty")))
{
return hr;
}
if (FAILED(hr = CreateAndPrepareCmd(m_WriteSession, m_InsertPartyMember,
"INSERT INTO dbo.TblCharPartyMember (PID, MemberCID) VALUES (?,?)", "InsertPartyMember")))
{
return hr;
}
ATL::CCommand<> partyIdentityCmd;
if (FAILED(hr = partyIdentityCmd.Open(m_WriteSession, "SET IDENTITY_INSERT dbo.TblCharParty ON")))
{
return hr;
}
return hr;
}
ConvertResult CBinaryParse::operator() (RylDBCommand::CCharItem& charItem_InOut)
{
DWORD dwCID = charItem_InOut.GetCID();
BYTE cOldServerGroupID = GetOldServerGroupID(dwCID);
if (IsPart2Data(cOldServerGroupID))
{
const EQUIP& equip = charItem_InOut.GetEquip();
const INVEN& inven = charItem_InOut.GetInven();
const EXTRA& extra = charItem_InOut.GetExtra();
ParseItemAndInsert(0, 0, dwCID, equip.Data, equip.dwSize);
ParseItemAndInsert(0, 0, dwCID, inven.Data, inven.dwSize);
ParseItemAndInsert(0, 0, dwCID, extra.Data, extra.dwSize);
}
// 삭제된 캐릭터면 로그도 찍지 않음
else if (UCHAR_MAX != cOldServerGroupID)
{
DETLOG2(g_Log, "CID:%10u/OldServerGroupID:%2d/CharItem 파싱하지 않음 : 파트2 데이터 아님",
dwCID, cOldServerGroupID);
}
return CONVERT_DO_NOT_WRITE;
}
ConvertResult CBinaryParse::operator() (RylDBCommand::CCharItemEx& charItemEx_InOut)
{
DWORD dwCID = charItemEx_InOut.GetCID();
BYTE cOldServerGroupID = GetOldServerGroupID(dwCID);
if (IsPart2Data(cOldServerGroupID))
{
const EXCHANGE& exchange = charItemEx_InOut.GetExchange();
const TEMPINVEN& tempinven = charItemEx_InOut.GetTempInven();
ParseItemAndInsert(0, 0, dwCID, exchange.Data, exchange.dwSize);
ParseItemAndInsert(0, 0, dwCID, tempinven.Data, tempinven.dwSize);
}
// 삭제된 캐릭터면 로그도 찍지 않음
else if (UCHAR_MAX != cOldServerGroupID)
{
DETLOG2(g_Log, "CID:%10u/OldServerGroupID:%2d/CharItemEx 파싱하지 않음 : 파트2 데이터 아님",
dwCID, cOldServerGroupID);
}
return CONVERT_DO_NOT_WRITE;
}
ConvertResult CBinaryParse::operator() (RylDBCommand::CUnifiedStore1& unifiedStore1_InOut)
{
BYTE cOldServerGroupID = unifiedStore1_InOut.GetOldServerGroupID();
if (IsPart2Data(cOldServerGroupID))
{
const STORE& store = unifiedStore1_InOut.GetStore();
ParseItemAndInsert(unifiedStore1_InOut.GetUID(),
cOldServerGroupID, 0, store.Data, store.dwSize);
}
// 삭제된 캐릭터면 로그도 찍지 않음
else if (UCHAR_MAX != cOldServerGroupID)
{
DETLOG2(g_Log, "UID:%10u/OldServerGroupID:%2d/UnifiedStore1 파싱하지 않음 : 파트2 데이터 아님",
unifiedStore1_InOut.GetUID(), cOldServerGroupID);
}
return CONVERT_DO_NOT_WRITE;
}
ConvertResult CBinaryParse::operator() (RylDBCommand::CUnifiedStore2& unifiedStore2_InOut)
{
BYTE cOldServerGroupID = unifiedStore2_InOut.GetOldServerGroupID();
if (IsPart2Data(cOldServerGroupID))
{
const STORE& store = unifiedStore2_InOut.GetStore();
ParseItemAndInsert(unifiedStore2_InOut.GetUID(),
cOldServerGroupID, 0, store.Data, store.dwSize);
}
// 삭제된 캐릭터면 로그도 찍지 않음
else if (UCHAR_MAX != cOldServerGroupID)
{
DETLOG2(g_Log, "UID:%10u/OldServerGroupID:%2d/UnifiedStore2 파싱하지 않음 : 파트2 데이터 아님",
unifiedStore2_InOut.GetUID(), cOldServerGroupID);
}
return CONVERT_DO_NOT_WRITE;
}
ConvertResult CBinaryParse::operator() (RylDBCommand::CSkillData& charSkillData_InOut)
{
DWORD dwCID = charSkillData_InOut.GetCID();
BYTE cOldServerGroupID = GetOldServerGroupID(dwCID);
if (IsPart2Data(cOldServerGroupID))
{
HRESULT hr = S_OK;
const SKILL& skill = charSkillData_InOut.GetSkill();
for (int nCount = 0; nCount < skill.wSlotNum; ++nCount)
{
const SKILLSLOT& slot = skill.SSlot[nCount];
m_InsertSkillData.m_OwnerCID = dwCID;
m_InsertSkillData.m_Skill_ID = slot.SKILLINFO.wSkill;
m_InsertSkillData.m_LockCount = slot.SKILLINFO.cLockCount;
m_InsertSkillData.m_Level = slot.SKILLINFO.cSkillLevel;
m_InsertSkillData.m_OwnerCIDStatus = DBSTATUS_S_OK;
m_InsertSkillData.m_Skill_IDStatus = DBSTATUS_S_OK;
m_InsertSkillData.m_LockCountStatus = DBSTATUS_S_OK;
m_InsertSkillData.m_LevelStatus = DBSTATUS_S_OK;
if (0 != slot.SKILLINFO.wSkill && FAILED(hr = m_InsertSkillData.Open(&m_DBRowset)))
{
ERRLOG7(g_Log, "CID:%10u/Skill_ID:0x%04x/"
"OwnerCIDStatus(0x%08x)/Skill_IDStatus(0x%08x)/"
"LockCountStatus(0x%08x)/LevelStatus(0x%08x)/HRESULT:0x%08x/스킬 삽입 실패",
dwCID, slot.SKILLINFO.wSkill,
m_InsertSkillData.m_OwnerCIDStatus, m_InsertSkillData.m_Skill_IDStatus,
m_InsertSkillData.m_LockCountStatus, m_InsertSkillData.m_LevelStatus, hr);
}
}
}
// 삭제된 캐릭터면 로그도 찍지 않음
else if (UCHAR_MAX != cOldServerGroupID)
{
DETLOG2(g_Log, "CID:%10u/OldServerGroupID:%2d/SkillData 파싱하지 않음 : 파트2 데이터 아님",
dwCID, cOldServerGroupID);
}
return CONVERT_DO_NOT_WRITE;
}
ConvertResult CBinaryParse::operator() (RylDBCommand::CCharQuest& charQuest_InOut)
{
DWORD dwCID = charQuest_InOut.GetCID();
BYTE cOldServerGroupID = GetOldServerGroupID(dwCID);
if (IsPart2Data(cOldServerGroupID))
{
HRESULT hr = S_OK;
const QUEST& quest = charQuest_InOut.GetQuest();
const HISTORY& history = charQuest_InOut.GetHistory();
const PktQuestDB::ExecutingQuest* lpQuestPos =
reinterpret_cast<const PktQuestDB::ExecutingQuest*>(quest.Data);
const PktQuestDB::ExecutingQuest* lpQuestEnd =
reinterpret_cast<const PktQuestDB::ExecutingQuest*>(quest.Data + quest.dwSize);
for (; lpQuestPos < lpQuestEnd; ++lpQuestPos)
{
m_InsertQuestExisting.m_OwnerCID = dwCID;
m_InsertQuestExisting.m_QuestID = lpQuestPos->m_wQuestID;
m_InsertQuestExisting.m_CurrentPhase = lpQuestPos->m_cPhase;
memcpy(m_InsertQuestExisting.m_TriggerCounts,
lpQuestPos->m_cTriggerCount, sizeof(BYTE) * PktQuestDB::MAX_TRIGGER);
m_InsertQuestExisting.m_OwnerCIDStatus = DBSTATUS_S_OK;
m_InsertQuestExisting.m_QuestIDStatus = DBSTATUS_S_OK;
m_InsertQuestExisting.m_CurrentPhaseStatus = DBSTATUS_S_OK;
m_InsertQuestExisting.m_TriggerCountsStatus = DBSTATUS_S_OK;
if (0 != lpQuestPos->m_wQuestID && FAILED(hr = m_InsertQuestExisting.Open(&m_DBRowset)))
{
ERRLOG7(g_Log, "CID:%10u/QuestID:0x%04x/"
"OwnerCIDStatus(0x%08x)/QuestIDStatus(0x%08x)/CurrentPhaseStatus(0x%08x)/"
"TriggerCountsStatus(0x%08x)/HRESULT:0x%08x/수행중인 퀘스트 삽입 실패",
dwCID, lpQuestPos->m_wQuestID,
m_InsertQuestExisting.m_OwnerCIDStatus,
m_InsertQuestExisting.m_QuestIDStatus,
m_InsertQuestExisting.m_CurrentPhaseStatus,
m_InsertQuestExisting.m_TriggerCountsStatus, hr);
}
}
const unsigned short* lpHistoryPos =
reinterpret_cast<const unsigned short*>(history.Data);
const unsigned short* lpHistoryEnd =
reinterpret_cast<const unsigned short*>(history.Data + history.dwSize);
for (; lpHistoryPos < lpHistoryEnd; ++lpHistoryPos)
{
m_InsertQuestHistory.m_OwnerCID = dwCID;
m_InsertQuestHistory.m_QuestID = *lpHistoryPos;
m_InsertQuestHistory.m_OwnerCIDStatus = DBSTATUS_S_OK;
m_InsertQuestHistory.m_QuestIDStatus = DBSTATUS_S_OK;
if (0 != m_InsertQuestHistory.m_QuestID &&
FAILED(hr = m_InsertQuestHistory.Open(&m_DBRowset)))
{
ERRLOG5(g_Log, "CID:%10u/QuestID:0x%04x/"
"OwnerCIDStatus(0x%08x)/QuestIDStatus(0x%08x)/HRESULT:0x%08x/수행 완료된 퀘스트 넣기 실패",
dwCID, m_InsertQuestHistory.m_QuestID,
m_InsertQuestHistory.m_OwnerCIDStatus,
m_InsertQuestHistory.m_QuestIDStatus, hr);
}
}
}
// 삭제된 캐릭터면 로그도 찍지 않음
else if (UCHAR_MAX != cOldServerGroupID)
{
DETLOG2(g_Log, "CID:%10u/OldServerGroupID:%2d/QuestData 파싱하지 않음 : 파트2 데이터 아님",
dwCID, cOldServerGroupID);
}
return CONVERT_DO_NOT_WRITE;
}
ConvertResult CBinaryParse::operator() (RylDBCommand::CPartyData& partyData)
{
HRESULT hr = S_OK;
const PARTY_DB_INFO& party = partyData.GetParty();
DWORD dwPID = partyData.GetPID();
m_InsertParty.m_PID = dwPID;
m_InsertParty.m_GID = partyData.GetGID();
m_InsertParty.m_PIDStatus = DBSTATUS_S_OK;
m_InsertParty.m_GIDStatus = DBSTATUS_S_OK;
if (FAILED(hr = m_InsertParty.Open(&m_DBRowset)))
{
ERRLOG4(g_Log, "PID:%10u/PIDStatus(0x%08x)/GIDStatus(0x%08x)/"
"HRESULT:0x%08x/파티 생성 실패",
m_InsertParty.m_PID,
m_InsertParty.m_PIDStatus,
m_InsertParty.m_GIDStatus, hr);
}
else
{
for(int nCount = 0; nCount < party.PartyInfo.MAX_MEM; ++nCount)
{
m_InsertPartyMember.m_PID = dwPID;
m_InsertPartyMember.m_MemberCID = party.PartyInfo.MemberCID[nCount];
m_InsertPartyMember.m_PIDStatus = DBSTATUS_S_OK;
m_InsertPartyMember.m_MemberCIDStatus = DBSTATUS_S_OK;
BYTE cOldServerGroupID = GetOldServerGroupID(m_InsertPartyMember.m_MemberCID);
if (0 != m_InsertPartyMember.m_MemberCID &&
IsPart2Data(cOldServerGroupID) &&
FAILED(hr = m_InsertPartyMember.Open(&m_DBRowset)))
{
ERRLOG5(g_Log, "PID:%10u/CID:%10u/PIDStatus(0x%08x)/CIDStatus(0x%08x)/"
"HRESULT:0x%08x/파티 멤버 삽입 실패",
m_InsertPartyMember.m_PID, m_InsertPartyMember.m_MemberCID,
m_InsertPartyMember.m_PIDStatus, m_InsertPartyMember.m_MemberCIDStatus, hr);
}
}
}
return CONVERT_DO_NOT_WRITE;
}
ConvertResult CBinaryParse::operator() (RylDBCommand::CFriendData& friendData)
{
DWORD dwCID = friendData.GetCID();
BYTE cOldServerGroupID = GetOldServerGroupID(dwCID);
if (IsPart2Data(cOldServerGroupID))
{
HRESULT hr = S_OK;
FRIEND myfriend = friendData.GetFriend();
BAN myBan = friendData.GetBan();
const DBFriend* lpFriendPos =
reinterpret_cast<const DBFriend*>(myfriend.Data);
const DBFriend* lpFriendEnd =
reinterpret_cast<const DBFriend*>(myfriend.Data + myfriend.dwSize);
for (; lpFriendPos < lpFriendEnd; ++lpFriendPos)
{
m_InsertFriend.m_OwnerCID = dwCID;
m_InsertFriend.m_FriendCID = lpFriendPos->m_dwCID;
m_InsertFriend.m_OwnerCIDStatus = DBSTATUS_S_OK;
m_InsertFriend.m_FriendCIDStatus = DBSTATUS_S_OK;
if (FAILED(hr = m_InsertFriend.Open(&m_DBRowset)))
{
ERRLOG4(g_Log, "CID:%10u/OwnerCIDStatus(0x%08x)/"
"FriendCIDStatus(0x%08x)/HRESULT:0x%08x/친구 추가 실패",
dwCID, m_InsertFriend.m_OwnerCIDStatus,
m_InsertFriend.m_FriendCIDStatus, hr);
}
}
const DBBan* lpBanPos = reinterpret_cast<const DBBan*>(myBan.Data);
const DBBan* lpBanEnd = reinterpret_cast<const DBBan*>(myBan.Data + myBan.dwSize);
for (; lpBanPos < lpBanEnd; ++lpBanPos)
{
m_InsertBan.m_OwnerCID = dwCID;
m_InsertBan.m_BanCID = lpBanPos->m_dwCID;
m_InsertBan.m_OwnerCIDStatus = DBSTATUS_S_OK;
m_InsertBan.m_BanCIDStatus = DBSTATUS_S_OK;
if (FAILED(hr = m_InsertBan.Open(&m_DBRowset)))
{
ERRLOG6(g_Log, "CID:%10u/BanCID:%10u/BanName:%16s/OwnerCIDStatus(0x%08x)/"
"BanCIDStatus(0x%08x)/HRESULT:0x%08x/거부 추가 실패",
dwCID, lpBanPos->m_dwCID, lpBanPos->m_szName,
m_InsertBan.m_OwnerCIDStatus, m_InsertBan.m_BanCIDStatus, hr);
}
}
}
// 삭제된 캐릭터면 로그도 찍지 않음
else if (UCHAR_MAX != cOldServerGroupID)
{
DETLOG2(g_Log, "CID:%10u/OldServerGroupID:%2d/FriendData, BanData 파싱하지 않음 : 파트2 데이터 아님",
dwCID, cOldServerGroupID);
}
return CONVERT_DO_NOT_WRITE;
}
ConvertResult CBinaryParse::operator() (RylDBCommand::CUnifiedCharList& unifiedCharList)
{
DWORD dwNewCID = unifiedCharList.GetNewCID();
BYTE cOldServerGroupID = unifiedCharList.GetOldServerGroupID();
OldServerIDMap::iterator pos = m_CIDMap.lower_bound(dwNewCID);
if (pos != m_CIDMap.end() && pos->first == dwNewCID)
{
pos->second = cOldServerGroupID;
}
else
{
m_CIDMap.insert(pos, OldServerIDMap::value_type(dwNewCID, cOldServerGroupID));
}
return CONVERT_DO_NOT_WRITE;
}
void CBinaryParse::ParseItemAndInsert(DWORD dwOwnerUID, BYTE cOldServerGroupID,
DWORD dwOwnerCID, const char* szData, unsigned long dwDataLen)
{
const char* szDataPos = szData;
const char* szDataEnd = szData + dwDataLen;
HRESULT hr = S_OK;
bool bInsert = false;
const int MAX_LOG_BUFFER = 1024;
char szParams[MAX_LOG_BUFFER];
for (; szDataPos < szDataEnd; )
{
const Item::ItemData* lpItemData = reinterpret_cast<const Item::ItemData*>(szDataPos);
m_InsertItemCmd.m_ItemUID = lpItemData->m_dwUID;
m_InsertItemCmd.m_OwnerUID = dwOwnerUID;
m_InsertItemCmd.m_OldServerGroupID = cOldServerGroupID;
m_InsertItemCmd.m_OwnerCID = dwOwnerCID;
m_InsertItemCmd.m_PrototypeID = lpItemData->m_usProtoTypeID;
m_InsertItemCmd.m_ItemContainerID = lpItemData->m_ItemPos.m_cPos;
m_InsertItemCmd.m_ItemContainerPos = lpItemData->m_ItemPos.m_cIndex;
m_InsertItemCmd.m_NumOrDurability = lpItemData->m_cNumOrDurability;
m_InsertItemCmd.m_ItemUIDStatus =
m_InsertItemCmd.m_PrototypeIDStatus =
m_InsertItemCmd.m_ItemContainerIDStatus =
m_InsertItemCmd.m_ItemContainerPosStatus =
m_InsertItemCmd.m_NumOrDurabilityStatus = DBSTATUS_S_OK;
if (0 != dwOwnerUID && 0 != cOldServerGroupID)
{
m_InsertItemCmd.m_OwnerUIDStatus = DBSTATUS_S_OK;
m_InsertItemCmd.m_OldServerGroupIDStatus = DBSTATUS_S_OK;
m_InsertItemCmd.m_OwnerCIDStatus = DBSTATUS_S_ISNULL;
bInsert = true;
}
else if (0 != dwOwnerCID)
{
m_InsertItemCmd.m_OwnerUIDStatus = DBSTATUS_S_ISNULL;
m_InsertItemCmd.m_OldServerGroupIDStatus = DBSTATUS_S_ISNULL;
m_InsertItemCmd.m_OwnerCIDStatus = DBSTATUS_S_OK;
bInsert = true;
}
else
{
// 삽입 실패
ERRLOG5(g_Log, "OldServerGroupID:%2d/UID:%10u/CID:%10u/ItemUID:0x%016I64X/PrototypeID:%5u/"
"Item insert failed : invalid UID or CID",
cOldServerGroupID, dwOwnerUID, dwOwnerCID,
lpItemData->m_dwUID, lpItemData->m_usProtoTypeID);
bInsert = false;
}
if (bInsert)
{
if (FAILED(hr = m_InsertItemCmd.Open(&m_DBRowset)))
{
_snprintf(szParams, MAX_LOG_BUFFER,
"ItemUIDStatus(0x%08x), OwnerUIDStatus(0x%08x), OldServerGroupIDStatus(0x%08x), "
"OwnerCIDStatus(0x%08x), PrototypeIDStatus(0x%08x), ItemContainerIDStatus(0x%08x), "
"ItemContainerPosStatus(0x%08x), NumOrDurabilityStatus(0x%08x) ",
m_InsertItemCmd.m_ItemUIDStatus,
m_InsertItemCmd.m_OwnerUIDStatus,
m_InsertItemCmd.m_OldServerGroupIDStatus,
m_InsertItemCmd.m_OwnerCIDStatus,
m_InsertItemCmd.m_PrototypeIDStatus,
m_InsertItemCmd.m_ItemContainerIDStatus,
m_InsertItemCmd.m_ItemContainerPosStatus,
m_InsertItemCmd.m_NumOrDurabilityStatus);
szParams[MAX_LOG_BUFFER - 1] = 0;
ERRLOG7(g_Log, "OldServerGroupID:%2d/UID:%10u/CID:%10u/ItemUID:0x%016I64X/PrototypeID:%5u/"
"Item insert failed : HRESULT : 0x%08X / %s",
cOldServerGroupID, dwOwnerUID, dwOwnerCID,
lpItemData->m_dwUID, lpItemData->m_usProtoTypeID, hr, szParams);
}
else if (sizeof(Item::ItemData) < lpItemData->m_cItemSize)
{
const Item::EquipmentInfo* lpEquipmentInfo =
reinterpret_cast<const Item::EquipmentInfo*>(lpItemData + 1);
const BYTE* lpSocket =
reinterpret_cast<const BYTE*>(lpEquipmentInfo + 1);
const Item::ItemAttribute* lpAttribute =
reinterpret_cast<const Item::ItemAttribute*>(lpSocket + lpEquipmentInfo->m_cSocketNum);
// 초기화 및 데이터 세팅
m_InsertEquipItemCmd.m_ItemUID = lpItemData->m_dwUID;
memset(m_InsertEquipItemCmd.m_SocketValue, 0,
sizeof(BYTE) * Item::EquipmentInfo::MAX_SOCKET_NUM);
for (int nCount = 0; nCount < lpEquipmentInfo->m_cSocketNum; ++nCount)
{
m_InsertEquipItemCmd.m_SocketValue[nCount] = lpSocket[nCount];
}
m_InsertEquipItemCmd.m_UpgradeLevel = lpEquipmentInfo->m_cUpgradeLevel;
m_InsertEquipItemCmd.m_SeasonRecord = lpEquipmentInfo->m_cSeasonRecord;
m_InsertEquipItemCmd.m_MaxDurability = lpEquipmentInfo->m_cDiffMaxDurability;
memset(m_InsertEquipItemCmd.m_Attribute, 0,
sizeof(SHORT) * Item::Attribute::MAX_DB_ATTRIBUTE_NUM);
memset(m_InsertEquipItemCmd.m_Rune, 0,
sizeof(SHORT) * ConvertDB::CharEquipItem::MAX_RUNE);
for (int nCount = 0, nRuneCount = 0;
nCount < lpEquipmentInfo->m_cAttributeNum; ++nCount)
{
if (0 < lpAttribute[nCount].m_cType &&
lpAttribute[nCount].m_cType < Item::Attribute::MAX_ATTRIBUTE_NUM)
{
if (lpAttribute[nCount].m_cType == Item::Attribute::RUNE && nRuneCount < 2)
{
m_InsertEquipItemCmd.m_Rune[nRuneCount] =
lpAttribute[nCount].m_usValue;
++nRuneCount;
}
else
{
m_InsertEquipItemCmd.m_Attribute[lpAttribute[nCount].m_cType] =
lpAttribute[nCount].m_usValue;
}
}
}
m_InsertEquipItemCmd.m_SocketValueLen = Item::EquipmentInfo::MAX_SOCKET_NUM;
m_InsertEquipItemCmd.m_ItemUIDStatus =
m_InsertEquipItemCmd.m_SocketValueStatus =
m_InsertEquipItemCmd.m_UpgradeLevelStatus =
m_InsertEquipItemCmd.m_SeasonRecordStatus =
m_InsertEquipItemCmd.m_MaxDurabilityStatus = DBSTATUS_S_OK;
std::fill_n(m_InsertEquipItemCmd.m_AttributeStatus,
size_t(Item::Attribute::MAX_DB_ATTRIBUTE_NUM), DBSTATUS_S_OK);
std::fill_n(m_InsertEquipItemCmd.m_RuneStatus,
size_t(ConvertDB::CharEquipItem::MAX_RUNE), DBSTATUS_S_OK);
if (FAILED(hr = m_InsertEquipItemCmd.Open(&m_DBRowset)))
{
_snprintf(szParams, MAX_LOG_BUFFER,
"ItemUIDStatus(0x%08x), SocketValueStatus(0x%08x), UpgradeLevelStatus(0x%08x), "
"SeasonRecordStatus(0x%08x), MaxDurabilityStatus(0x%08x), "
"Attr_MinDamage(0x%08x), Attr_MaxDamage(0x%08x), "
"Attr_Armour(0x%08x), Attr_HitRate(0x%08x), "
"Attr_Evade(0x%08x), Attr_MaxHP(0x%08x), "
"Attr_HPRegen(0x%08x), Attr_MaxMP(0x%08x), "
"Attr_MPRegen(0x%08x), Attr_Critical(0x%08x), "
"Attr_Block(0x%08x), Attr_Speed(0x%08x), "
"Attr_MagicPower(0x%08x), Attr_MagicResist(0x%08x), "
"Attr_Rune1(0x%08x), Attr_Rune2(0x%08x)",
m_InsertEquipItemCmd.m_ItemUIDStatus,
m_InsertEquipItemCmd.m_SocketValueStatus,
m_InsertEquipItemCmd.m_UpgradeLevelStatus,
m_InsertEquipItemCmd.m_SeasonRecordStatus,
m_InsertEquipItemCmd.m_MaxDurabilityStatus,
m_InsertEquipItemCmd.m_AttributeStatus[Item::Attribute::MIN_DAMAGE],
m_InsertEquipItemCmd.m_AttributeStatus[Item::Attribute::MAX_DAMAGE],
m_InsertEquipItemCmd.m_AttributeStatus[Item::Attribute::ARMOR],
m_InsertEquipItemCmd.m_AttributeStatus[Item::Attribute::HIT_RATE],
m_InsertEquipItemCmd.m_AttributeStatus[Item::Attribute::EVADE],
m_InsertEquipItemCmd.m_AttributeStatus[Item::Attribute::MAX_HP],
m_InsertEquipItemCmd.m_AttributeStatus[Item::Attribute::HP_REGEN],
m_InsertEquipItemCmd.m_AttributeStatus[Item::Attribute::MAX_MP],
m_InsertEquipItemCmd.m_AttributeStatus[Item::Attribute::MP_REGEN],
m_InsertEquipItemCmd.m_AttributeStatus[Item::Attribute::CRITICAL],
m_InsertEquipItemCmd.m_AttributeStatus[Item::Attribute::BLOCK],
m_InsertEquipItemCmd.m_AttributeStatus[Item::Attribute::SPEED],
m_InsertEquipItemCmd.m_AttributeStatus[Item::Attribute::MAGIC_POWER],
m_InsertEquipItemCmd.m_AttributeStatus[Item::Attribute::MAGIC_RESIST],
m_InsertEquipItemCmd.m_RuneStatus[0],
m_InsertEquipItemCmd.m_RuneStatus[1]);
szParams[MAX_LOG_BUFFER - 1] = 0;
ERRLOG7(g_Log, "OldServerGroupID:%2d/UID:%10u/CID:%10u/ItemUID:0x%016I64X/PrototypeID:%5u/"
"EquipItem insert failed : HRESULT : 0x%08X / %s",
cOldServerGroupID, dwOwnerUID, dwOwnerCID,
lpItemData->m_dwUID, lpItemData->m_usProtoTypeID, hr, szParams);
}
}
}
szDataPos += lpItemData->m_cItemSize;
}
}