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>
1214 lines
46 KiB
C++
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;
|
|
}
|
|
}
|
|
|