mangosd 之 CliRunnable
启动的控制台线程,该线程从stdin读入用户命令,解析后通过command打包后由LockedQueue传到
WorldRunnable Thread执行,在WorldRunnable中,每次调用update的最后都会对用户的命令进行处理。
和MysqlDelayThread中的SqlOperation类似,此处在LockedQueue中存放的依然是对command进行包裹后的类的指针(CliCommandHolder*),在WorldRunnable中,要做的事情很简单,只需要调用一下
CliCommandHolder的Execute函数,而这个函数会自动的执行CliCommand自己的回调函数。
class CliCommandHolder
{
private:
const CliCommand *cmd;
char *args;
pPrintf m_zprintf;
public:
CliCommandHolder(const CliCommand *command, const char *arguments, pPrintf p_zprintf)
: cmd(command), m_zprintf(p_zprintf)
{
size_t len = strlen(arguments)+1;
args = new char[len];
memcpy(args, arguments, len);
}
~CliCommandHolder() { delete[] args; }
void Execute() const { cmd->Func(args, m_zprintf); }
pPrintf GetOutputMethod() const {return (m_zprintf);}
};
typedef int(* pPrintf)(const char*,...);
typedef void(* pCliFunc)(char *,pPrintf);
/// Command Template class
struct CliCommand
{
char const * cmd;
pCliFunc Func;
char const * description;
};
而各种Client Command对应的回调函数,早就准备妥当了:
/// Table of known commands
const CliCommand Commands[]=
{
{"help", & CliHelp,"Display this help message"},
{"broadcast", & CliBroadcast,"Announce in-game message"},
{"create", & CliCreate,"Create account"},
{"delete", & CliDelete,"Delete account and characters"},
{"info", & CliInfo,"Display Server infomation"},
{"uptime", & CliUpTime, "Displays the server uptime"},
{"motd", & CliMotd,"Change or display motd"},
{"kick", & CliKick,"Kick user"},
{"ban", & CliBan,"Ban account|ip"},
{"listbans", & CliBanList,"List bans"},
{"unban", & CliRemoveBan,"Remove ban from account|ip"},
{"setgm", & CliSetGM,"Edit user privileges"},
{"setbc", & CliSetTBC,"Set user expansion allowed"},
{"listgm", & CliListGM,"Display user privileges"},
{"loadscripts", & CliLoadScripts,"Load script library"},
{"setloglevel", & CliSetLogLevel,"Set Log Level"},
{"corpses", & CliCorpses,"Manually call corpses erase global even code"},
{"version", & CliVersion,"Display server version"},
{"idleshutdown", & CliIdleShutdown,"Shutdown server with some delay when not active connections at server"},
{"shutdown", & CliShutdown,"Shutdown server with some delay"},
{"exit", & CliExit,"Shutdown server NOW"},
{"writepdump", &CliWritePlayerDump,"Write a player dump to a file"},
{"loadpdump", &CliLoadPlayerDump,"Load a player dump from a file"},
{"saveall", &CliSave,"Save all players"},
{"send", &CliSend,"Send message to a player"},
{"tele", &CliTele,"Teleport player to location"},
{"plimit", &CliPLimit,"Show or set player login limitations"}
};
个人感觉这样设计真的是挺好的,首先,对于WorldRunnable来说,不需要关系具体的CliCommand怎么处理,CliRunnable只需要告诉他一个句柄和这个句柄的调用接口,具体的数据和逻辑都在这个接口中实现好了;这样一来,WorldRunnable就很符合KISS原则了。其次,对于CliRunnable来说,它需要关注每个CliCommand的细节和处理方式,如果处理逻辑发生变化或者增加了新的CliCommand,做的任何修改都在CliRunnable中,对WorldRunnable来说都是透明的,它只是一个任务的执行者,他们互相有很好的隔离性;而建立起这个防火墙的正是上面这样的针对接口编程的机制。
阅读(974) | 评论(0) | 转发(0) |