#pragma once
#include "MServer.h"
#include "MUID.h"
#include "MMatchObjectList.h"
#include "MAsyncJob.h"
#include "MAsyncProxy.h"
#include "MMatchChannelMap.h"
#include "MSafeUDP.h"
#include "MMatchStageMap.h"
//! Global functions
void CopyCharInfoForTrans(MTD_CharInfo* pDest, MMatchCharInfo* pSrc);
void CopyChannelPlayerListNodeForTrans(MTD_ChannelPlayerListNode* pDest, MMatchObject* pSrc);
void Make_MTDItemNode(MTD_ItemNode* pOutItem, MUID& uidItem, DWORD nItemId, int nRentMinutePeriodReminder);
bool IsSuitableItemSlot(MMatchItemSlotType nSlotType, MMatchCharItemParts nParts);
bool IsEquipableItem(int nItemId, int nPlayerLevel, MMatchSex nSex);
class MMatchServer : public MServer
{
public:
MMatchServer(void);
~MMatchServer(void);
bool Create(int nPort);
bool InitDB();
void OnRegisterCommand(MCommandManager*);
bool LoadInitFile();
bool LoadChannelPreset();
void GetServerConnectionInfo(int& nClientCount, int& nSessionCount, int&nAgentCount);
MUID UseUID();
void OnRun();
void OnPrepareRun();
bool OnCommand(MCommand*);
int ValidateMakingName(const char* szCharName, int nMinLength, int nMaxLength);
void ParseUDPPacket(char *pData, MPacketHeader* pPacketHeader, unsigned int dwIP, unsigned int nRawPort);
MMatchChannelMap GetChannelMap() { return m_ChannelMap; }
//! Packet sending.
void RouteToListener(MObject* pObject, MCommand* pCmd);
void RouteResponseToListener(MObject* pObject, int nCmdID, int nResult);
void RouteToChannelLobby(MUID& uidChannel, MCommand* pCommand);
//! Login Extentions.
bool CheckOnLoginPre(MUID& uidComm, const int& nCmdVersion, const bool& bFreeIP, const string& strCountryCode);
bool AddObjectOnMatchLogin(MUID& uidComm, MMatchAccountInfo* pAccountInfo, bool bFreeLoginIP, string strCountryCode3, DWORD nChecksumPack);
MCommand* CreateCmdMatchResponseLoginFailed(MUID& uidComm, int nErrorcode);
MCommand* CreateCmdMatchResponseLoginOK(MUID& uidComm, MUID& uidPlayer, const char* szUserID, MMatchUserGradeID nUGradeID, MMatchPremiumGradeID nPGradeID, const char* szRandomValue);
void SetClientClockSynchronize(MUID& uidClient);
//! General Player Handlers
MMatchObject* GetPlayerByAID(DWORD nAID);
MMatchObject* ObjectAdd(MUID& uidObject);
MMatchObject* GetObject(MUID& uidObject);
bool CharFinalize(MUID& uidPlayer);
bool CharInitialize(MUID& uidPlayer);
void DisconnectObject(MUID& uidPlayer);
void UpdateCharDBCachingData(MMatchObject* pObject);
bool CorrectEquipmentByLevel(MMatchObject* pObject, MMatchCharItemParts nParts, int nLegalItemLevelDiff);
//! Channel Handlers
bool ChannelAdd(const char* pszChannelName, const char* pszRuleName, MUID* pAllocUID, MCHANNEL_TYPE nType, int nMaxPlayers, int nLevelMin, int nLevelMax);
int ValidateChannelJoin(MUID& uidPlayer, MUID& uidChannel);
MMatchChannel* FindChannel(MUID& uidChannel);
void ChannelChat(MUID& uidPlayer, MUID& uidChannel, const char* pszChat);
void OnStartChannelList(MUID& uidPlayer, MCHANNEL_TYPE nChannelType);
void OnStopChannelList(MUID& uidPlayer);
void ChannelList(MUID& uidPlayer, MCHANNEL_TYPE nChannelType);
void ChannelJoin(MUID& uidPlayer, MCHANNEL_TYPE nChannelType, const char* pszChannelName);
//! Item Handlers
void OnRequestCharacterItemList(MUID& uidPlayer);
void OnRequestShopItemList(MUID& uidPlayer, int nFirstItemIndex, int nItemCount);
void OnRequestBuyItem(MUID& uidPlayer, int nItemId);
void OnRequestSellItem(MUID& uidPlayer, MUID& uidItem);
int ValidateEquipItem(MMatchObject* pObject, MMatchItem* pItem, MMatchCharItemParts nParts);
void OnRequestEquipItem(MUID& uidPlayer, MUID& uidItem, int nSlot);
void OnRequestTakeOffItem(MUID& uidPlayer, int nSlot);
//! Stage Handlers
//! Asynchronous database jobs.
void PostAsyncJob(MAsyncJob* pJob);
void ProcessAsyncJob();
void OnAsyncGetAccountCharList(MAsyncJob* pJob);
void OnAsyncGetAccountCharInfo(MAsyncJob* pJob);
void OnAsyncCreateCharacter(MAsyncJob* pJob);
void OnAsyncDeleteChar(MAsyncJob* pJob);
void OnAsyncGetCharInfo(MAsyncJob* pJob);
void OnAsyncUpdateCharInfoData(MAsyncJob* pJob);
//! Response packets.
bool ResponseCreateChar(MUID& uidPlayer, int nCharIndex, const char* szCharName, MMatchSex nSex, unsigned int nHair, unsigned int nFace, unsigned int nCostume);
bool ResponseDeleteChar(MUID& uidPlayer, int nCharIndex, const char* szCharName);
bool ChannelJoin(MUID& uidPlayer, MUID& uidChannel);
bool ChannelResponsePlayerList(MUID& uidPlayer, MUID& uidChannel, int nPage);
void ResponseCharacterItemList(MUID& uidPlayer);
void ResponseShopItemList(MUID& uidPlayer, int nFirstItemIndex, int nItemCount);
void BuyItem(MMatchObject* pObject, int nItemId, bool bRentItem, int nRentHourPeriod);
void ResponseSellItem(MUID& uidPlayer, MUID& uidItem);
void ResponseEquipItem(MUID& uidPlayer, MUID& uidItem, MMatchCharItemParts nParts);
void ResponseTakeOffItem(MUID& uidPlayer, MMatchCharItemParts nParts);
//! Packet Handlers.
void OnMatchLogin(MUID& uidPlayer, const char* szUser, const char* szPassword, const int& nCommandVersion, const DWORD& nChecksum, const unsigned char* pMD5);
void OnRequestAccountCharList(MUID& uidPlayer, char* szXTrapSerialKey, unsigned char* pbyGuidAckMsg);
void OnRequestAccountCharInfo(MUID& uidPlayer, int nCharNum);
void OnRequestCreateChar(MUID& uidPlayer, int nCharIndex, const char* szCharName, unsigned int nSex, unsigned int nHair, unsigned int nFace, unsigned int nCostume);
void OnRequestDeleteChar(MUID& uidPlayer, int nCharIndex, const char* szCharName);
void OnRequestSelectChar(MUID& uidPlayer, int nCharIndex);
void OnRequestRecommendedChannel(MUID& uidPlayer);
void OnRequestChannelJoin(MUID& uidPlayer, MUID& uidChannel);
void OnChannelRequestPlayerList(MUID& uidPlayer, MUID& uidChannel, int nPage);
void OnChannelChat(MUID& uidPlayer, MUID& uidChannel, const char* pszChat);
void OnStageCreate(MUID& uidPlayer, const char* pszStageName, bool bPrivate, const char* pszPassword);
//! Singleton
static MMatchServer* GetInstance();
private:
static MMatchServer* m_pInstance;
MCriticalSection m_csUIDGenerateLock;
MUID m_NextUseUID;
MMatchObjectList m_Objects;
MAsyncProxy m_AsyncProxy;
char m_szDefaultChannelName[64];
char m_szDefaultChannelRuleName[64];
MMatchChannelMap m_ChannelMap;
MSafeUDP m_SafeUDP;
MMatchStageMap m_StageMap;
};