📄 worldkernel.cpp
字号:
// WorldKernel.cpp: implementation of the CWorldKernel class.
//
//////////////////////////////////////////////////////////////////////
#define _WINSOCKAPI_ // 阻止加载winsock.h
#include "inifile.h"
#include "protocol.h"
#include "windows.h"
#include "Winuser.h"
#include "BaseFunc.h"
#include "I_MessagePort.h"
#include "AllMsg.h"
#include "NetMsg.h"
#include "MessageBoard.h"
#include "WorldKernel.h"
#include "ClientSocket.h"
#include "MsgAccount_A.h"
#include "MsgConnect_A.h"
#include "MsgLogin_A.h"
#include "MsgFee_A.h"
#include "MsgQueryFee_A.h"
#include "SynWorldManager.h"
#include "SupermanList.h"
#include "AutoPtr.h"
#include "ChatRoomManager.h"
using namespace world_kernel;
//////////////////////////////////////////////////////////////////////
CWorldKernel* CWorldKernel::m_pWorld = NULL;
//extern CChatRoomManager g_objChatRoomManager;
//////////////////////////////////////////////////////////////////////
// interface
//////////////////////////////////////////////////////////////////////
bool CWorldKernel::Create(IMessagePort* pPort)
{
m_pMsgPort = pPort;
m_idProcess = m_pMsgPort->GetID(); // process id == msg_port_id
m_pMsgPort->Open();
ASSERT(m_idProcess == MSGPORT_WORLD);
m_idNpcSocket = SOCKET_NONE;
// 初始化数据库
char DB_IP [DBSTR_SIZE] = "";
char DB_USER [DBSTR_SIZE] = "";
char DB_PW [DBSTR_SIZE] = "";
char DB_DB [DBSTR_SIZE] = "";
CIniFile ini(CONFIG_FILENAME, "Database");
ini.GetString(DB_IP, "DB_IP", DBSTR_SIZE);
ini.GetString(DB_USER, "DB_USER", DBSTR_SIZE);
ini.GetString(DB_PW, "DB_PW", DBSTR_SIZE);
ini.GetString(DB_DB, "DB_DB", DBSTR_SIZE);
m_pDb = ::CreateDatabase(DB_IP, DB_USER, DB_PW, DB_DB);
if(!m_pDb)
{
LOGERROR("数据库连接失败!");
return false;
}
// TODO: 请在此添加初始化代码
m_pUserList = CUserList::CreateNew();
if(!m_pUserList)
return false;
m_pUserList->Create(GetSocketInterface(), m_pDb);
m_pMapList = CMapList::CreateNew();
if(!m_pMapList)
return false;
m_pMapList->Create(m_pDb);
m_pWorld = this;
m_pSynManager = new CSynWorldManager;
CHECKF(m_pSynManager);
m_pSynManager->Create(m_pDb);
m_setConnectClient = CConnectSet::CreateNew(true);
m_setConnectAccount = CConnectSet::CreateNew(true);
// account server
// CIniFile ini(CONFIG_FILENAME, "AccountServer");
ini.SetSection("AccountServer");
NAMESTR ACCOUNT_IP;
int ACCOUNT_PORT;
ini.GetString(ACCOUNT_IP, "ACCOUNT_IP", _MAX_NAMESIZE);
ACCOUNT_PORT = ini.GetInt("ACCOUNT_PORT");
ini.GetString(m_szServer, "SERVERNAME", _MAX_NAMESIZE);
ini.GetString(m_szAccount, "LOGINNAME", _MAX_NAMESIZE);
ini.GetString(m_szPassword, "PASSWORD", _MAX_NAMESIZE);
if(ACCOUNT_PORT == 0)
{
LOGERROR("INI配置错误!");
return false;
}
if(m_sock.Open(ACCOUNT_IP, ACCOUNT_PORT, 0, SOCKET_ACCOUNTBUFSIZE, SOCKET_ACCOUNTBUFSIZE))
m_nState = STATE_CONNECTOK;
m_ptrTradeMsgBd = CMessageBoard::CreateNew(_TXTATR_MSG_TRADE);
m_ptrFriendMsgBd = CMessageBoard::CreateNew(_TXTATR_MSG_FRIEND);
m_ptrTeamMsgBd = CMessageBoard::CreateNew(_TXTATR_MSG_TEAM);
m_ptrOtherMsgBd = CMessageBoard::CreateNew(_TXTATR_MSG_OTHER);
m_ptrSystemMsgBd = CMessageBoard::CreateNew(_TXTATR_MSG_SYSTEM);
LoadConfig(m_pDb);
// g_objChatRoomManager.Init();
return true; // return false : 创建失败,程序关闭。
}
//////////////////////////////////////////////////////////////////////
bool CWorldKernel::ProcessMsg(OBJID idPacket, void* buf, int nType, int nFrom)
{
switch(idPacket)
{
case KERNEL_CLIENTMSG:
{
CLIENTMSG_PACKET0* pMsg = (CLIENTMSG_PACKET0*)buf;
SOCKET_ID idSocket= pMsg->idSocket;
OBJID idMsg = pMsg->idPacket;
char* pBuf = pMsg->buf;
int nMsgLen = pMsg->nSize;
ProcessClientMsg(idSocket, idMsg, pBuf, nMsgLen);
}
break;
case WORLD_TRANSMITMSG:
{
TRANSMSG_PACKET0* pMsg = (TRANSMSG_PACKET0*)buf;
SOCKET_ID idSocket= pMsg->idSocket;
OBJID idNpc = pMsg->idNpc;
OBJID idMsg = pMsg->idPacket;
char* pBuf = pMsg->buf;
int nMsgLen = pMsg->nSize;
int nTrans = pMsg->nTrans;
if(idSocket == SOCKET_NONE)
ProcessNpcMsg(idNpc, idMsg, pBuf, nMsgLen, nTrans);
else
ProcessClientMsg(idSocket, idMsg, pBuf, nMsgLen, nTrans);
}
break;
case KERNEL_NPCMSG:
{
NPCMSG_PACKET0* pMsg = (NPCMSG_PACKET0*)buf;
OBJID idNpc = pMsg->idNpc;
OBJID idMsg = pMsg->idPacket;
char* pBuf = pMsg->buf;
int nMsgLen = pMsg->nSize;
ProcessNpcMsg(idNpc, idMsg, pBuf, nMsgLen);
}
break;
case WORLD_SHELLTALK:
{
char* pText = (char*)buf;
// TODO: 请在此添加外壳输入文本的处理代码
m_pMsgPort->Send(MSGPORT_SHELL, SHELL_PRINTTEXT, STRING_TYPE(pText), pText);
char szCmd[256] = "";
if (sscanf(pText, "%s", szCmd) == 1)
{
if (0 == stricmp(szCmd, "setmaxplayer"))
{
int nMaxPlayers = 0;
if (2 == sscanf(pText, "%s %d", szCmd, &nMaxPlayers))
{
extern DWORD g_dwMaxPlayer;
InterlockedExchange((long*)&g_dwMaxPlayer, nMaxPlayers);
{
char szMsg[256] = "";
sprintf(szMsg, "Set max player limit to %d", g_dwMaxPlayer);
m_pMsgPort->Send(MSGPORT_SHELL, SHELL_PRINTTEXT, STRING_TYPE(szMsg), szMsg);
}
}
}
else if (0 == stricmp(szCmd, "kickoutcheat"))
{
int nData = 0;
if (2 == sscanf(pText, "%s %d", szCmd, &nData))
{
extern long g_sKickoutCheat;
long nOld = InterlockedExchange(&g_sKickoutCheat, nData);
}
}
else if (0 == stricmp(szCmd, "kickoutall"))
{
OBJID idGmSocket = -1; // -1: for console
m_pMsgPort->Send(MSGPORT_SOCKET, SOCKET_BREAKALLCONNECT, VARTYPE_INT, &idGmSocket);
}
else if (0 == stricmp(szCmd, "broadcast"))
{
char* pCmd = pText + strlen(szCmd);
if(*pCmd == ' ')
pCmd++;
GameWorld()->QueryUserList()->BroadcastMsg(pCmd, NULL, NULL, 0x00FF0000, _TXTATR_GM);
}
else if (0 == stricmp(szCmd, "shutdown"))
{
GameWorld()->QueryUserList()->BroadcastMsg(STR_SHUTDOWN_NOTIFY, NULL, NULL, 0x00FF0000, _TXTATR_GM);
char* pMsg = "Send shut down broadcast message.";
m_pMsgPort->Send(MSGPORT_SHELL, SHELL_PRINTTEXT, STRING_TYPE(pMsg), pMsg);
}
else if (0 == stricmp(szCmd, "restartserver"))
{
extern long g_nServerClosed;
if(g_nServerClosed)
{
extern long g_nRestart;
g_nRestart = true;
}
else
{
LPCTSTR pMsg = "Please <kickoutall> before <restartserver>!";
m_pMsgPort->Send(MSGPORT_SHELL, SHELL_PRINTTEXT, STRING_TYPE(pMsg), pMsg);
}
}
else if (0 == stricmp(szCmd, "restartwindows"))
{
extern long g_nServerClosed;
if(g_nServerClosed)
{
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
// Get a token for this process.
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
{
LOGERROR("OpenProcessToken");
break;
}
// Get the LUID for the shutdown privilege.
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
tkp.PrivilegeCount = 1; // one privilege to set
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// Get the shutdown privilege for this process.
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
// Cannot test the return value of AdjustTokenPrivileges.
if (GetLastError() != ERROR_SUCCESS)
{
LOGERROR("AdjustTokenPrivileges");
break;
}
// Shut down the system and force all applications to close.
#define EWX_FORCEIFHUNG 0x00000010
if (!ExitWindowsEx(EWX_REBOOT | EWX_FORCEIFHUNG, 0))
{
LOGERROR("ExitWindowsEx");
break;
}
// ::ExitWindowsEx(EWX_REBOOT, 0); // | EWX_FORCEIFHUNG
}
else
{
LPCTSTR pMsg = "Please <kickoutall> before <restartserver>!";
m_pMsgPort->Send(MSGPORT_SHELL, SHELL_PRINTTEXT, STRING_TYPE(pMsg), pMsg);
}
}
}
}
break;
// TODO: 请在此添加其它内部消息处理代码
case KERNEL_CLOSEKERNEL:
{
SOCKET_ID idSocket = *(SOCKET_ID*)buf;
LOGDEBUG("DEBUG:世界核心收到关闭核心消息,SOCKET_ID[%u]", idSocket);
#ifdef NEW_LOGOUT
g_UserList.LogoutUser(idSocket);
m_pMsgPort->Send(MSGPORT_SOCKET, SOCKET_CLOSESOCKET, VARTYPE_INT, &idSocket); // readme.txt(2-1)
#else
if(g_UserList.IsLoginMapGroup(idSocket))
{
for(int i = MSGPORT_MAPGROUP_FIRST; i < m_pMsgPort->GetSize(); i++)
m_pMsgPort->Send(i, KERNEL_CLOSEKERNEL, VARTYPE_INT, &idSocket); // readme.txt(2-2)
}
else
m_pMsgPort->Send(MSGPORT_SOCKET, SOCKET_CLOSESOCKET, VARTYPE_INT, &idSocket); // readme.txt(2-1)
#endif
}
break;
case WORLD_CLOSESOCKET: // 由MAPGROUP发过来
{
#ifdef NEW_LOGOUT
ASSERT(!"WORLD_CLOSESOCKET");
#else
SOCKET_ID idSocket = *(SOCKET_ID*)buf;
LOGDEBUG("DEBUG:世界核心收到关闭网络消息,SOCKET_ID[%u]", idSocket);
g_UserList.LogoutUser(idSocket);
m_pMsgPort->Send(MSGPORT_SOCKET, SOCKET_CLOSESOCKET, VARTYPE_INT, &idSocket); // readme.txt(2-6)
#endif
}
break;
case WORLD_SETPROCESSID:
{
CHANGE_USERDATA* pPakcet = (CHANGE_USERDATA*)buf;
g_UserList.ChangeProcessID(pPakcet->idSocket, pPakcet->nData);
}
break;
case WORLD_USERNAMEMSG:
{
USERNAMEMSG_PACKET0* pMsg = (USERNAMEMSG_PACKET0*)buf;
SOCKET_ID idSocket= pMsg->idSocket;
OBJID idMsg = pMsg->idPacket;
char* pBuf = pMsg->buf;
int nMsgLen = pMsg->nSize;
// if (idMsg == _MSG_TALK)
// {
// // 服务频道判断
// typedef struct {
// DWORD dwWordsColor;
// USHORT unTxtAttribute;
// // ... 其它定义没必要写了
// }MSG_Info;
// MSG_Info* pInfo = (MSG_Info*)pBuf;
// if (pInfo->unTxtAttribute == _TXTATR_SERVE)
// {
// CPlayer* pTarget = UserList()->GetGM();
// if (pTarget)
// {
// SendMsg(pTarget->idSocket, idMsg, pBuf, nMsgLen);
// break;
// }
// }
// }
CPlayer* pPlayer = UserList()->GetPlayer(pMsg->szName);
if(pPlayer)
{
if(!pPlayer->IsAgent())
SendMsg(pPlayer->idSocket, idMsg, pBuf, nMsgLen);
else
SendNpcMsg(pPlayer->GetID(), idMsg, pBuf, nMsgLen);
}
else if(idMsg == _MSG_TALK && idSocket != SOCKET_NONE) // SOCKET_NONE : agent talk to user (BUG :)
{
// 私聊
CPlayer* pSender = UserList()->GetPlayerBySocket(idSocket);
if(pSender)
{
CMsgTalk msg;
IF_OK(msg.Create(SYSTEM_NAME, pSender->szName, STR_TARGET_OFFLINE))
pSender->SendMsg(&msg);
}
}
}
break;
case WORLD_USERIDMSG:
{
USERIDMSG_PACKET0* pMsg = (USERIDMSG_PACKET0*)buf;
SOCKET_ID idSocket= pMsg->idSocket;
OBJID idMsg = pMsg->idPacket;
char* pBuf = pMsg->buf;
int nMsgLen = pMsg->nSize;
CPlayer* pPlayer = UserList()->GetPlayer(pMsg->idUser);
if(pPlayer)
{
if(!pPlayer->IsAgent())
SendMsg(pPlayer->idSocket, idMsg, pBuf, nMsgLen);
else
SendNpcMsg(pPlayer->GetID(), idMsg, pBuf, nMsgLen);
}
}
break;
// syndicate -------------------------------------------------------------------------------
case KERNEL_CREATESYNDICATE:
{
CreateSyndicateInfo* pPacket = (CreateSyndicateInfo*)buf;
GameWorld()->QuerySynManager()->QueryModify()->CreateSyndicate(pPacket);
}
break;
case KERNEL_DESTROYSYNDICATE:
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -