首页 > 代码库 > MMORPG大型游戏设计与开发(part6 of net)
MMORPG大型游戏设计与开发(part6 of net)
上一部分,讲述了一个服务器与服务器之间的通信实例,客户端其实原理大同小异。网络部分准备就暂时讲到这里,不过我们不妨再回头过来想想在这过程中有没有优化和改进的地方。这部分讲解的是以网络包代码作分析,实现自动生成其代码的功能。
网络包代码
/** * PAP Engine ( -- ) * $Id connect.h * @link -- for the canonical source repository * @copyright Copyright (c) 2013-2013 viticm( viticm@126.com ) * @license * @user viticm<viticm@126.com> * @date 2014-01-16 17:20:14 * @uses packet Connect class */#ifndef PAP_SERVER_COMMON_NET_PACKETS_SERVERSERVER_CONNECT_H_#define PAP_SERVER_COMMON_NET_PACKETS_SERVERSERVER_CONNECT_H_#include "server/common/net/config.h"#include "server/common/net/connection/base.h"#include "common/net/packet/base.h"#include "common/net/packet/factory.h"#include "server/common/game/define/all.h"namespace pap_server_common_net {namespace packets {namespace serverserver {class Connect : public pap_common_net::packet::Base { public: Connect(); virtual ~Connect() {}; public: virtual bool read(pap_common_net::socket::InputStream& inputstream); virtual bool write(pap_common_net::socket::OutputStream& outputstream) const; virtual uint32_t execute(connection::Base* connection); virtual uint16_t getid() const; virtual uint32_t getsize() const; public: int16_t get_serverid(); void set_serverid(int16_t serverid); int16_t get_worldid(); void set_worldid(int16_t worldid); int16_t get_zoneid(); void set_zoneid(int16_t zoneid); private: int16_t serverid_; //服务器ID int16_t worldid_; //世界ID int16_t zoneid_; //区域ID};class ConnectFactory : public pap_common_net::packet::Factory { public: pap_common_net::packet::Base* createpacket(); uint16_t get_packetid() const; uint32_t get_packet_maxsize() const;};class ConnectHandler { public: static uint32_t execute(Connect* packet, connection::Base* connection);};}; //namespace serverserver}; //namespace packets}; //namespace pap_server_common_net#endif //PAP_SERVER_COMMON_NET_PACKETS_SERVERSERVER_CONNECT_H_
#include "server/common/net/packets/serverserver/connect.h"namespace pap_server_common_net {namespace packets {namespace serverserver {Connect::Connect() { __ENTER_FUNCTION __LEAVE_FUNCTION}bool Connect::read(pap_common_net::socket::InputStream& inputstream) { __ENTER_FUNCTION inputstream.read((char*)(&serverid_), sizeof(serverid_)); inputstream.read((char*)(&worldid_), sizeof(worldid_)); inputstream.read((char*)(&zoneid_), sizeof(zoneid_)); __LEAVE_FUNCTION return false;}bool Connect::write(pap_common_net::socket::OutputStream& outputstream) const { __ENTER_FUNCTION outputstream.write((char*)(&serverid_), sizeof(serverid_)); outputstream.write((char*)(&worldid_), sizeof(worldid_)); outputstream.write((char*)(&zoneid_), sizeof(zoneid_)); __LEAVE_FUNCTION return false;}uint32_t Connect::execute(connection::Base* connection) { __ENTER_FUNCTION uint32_t result = 0; result = ConnectHandler::execute(this, connection); return result; __LEAVE_FUNCTION return 0;}uint16_t Connect::getid() const { using namespace pap_server_common_game::define; return id::packet::serverserver::kConnect;}uint32_t Connect::getsize() const { uint32_t result = sizeof(serverid_) + sizeof(worldid_) + sizeof(zoneid_); return result;}int16_t Connect::get_serverid() { return serverid_;}void Connect::set_serverid(int16_t serverid) { serverid_ = serverid;}int16_t Connect::get_worldid() { return worldid_;}void Connect::set_worldid(int16_t worldid) { worldid_ = worldid;}int16_t Connect::get_zoneid() { return zoneid_;}void Connect::set_zoneid(int16_t zoneid) { zoneid_ = zoneid;}pap_common_net::packet::Base* ConnectFactory::createpacket() { __ENTER_FUNCTION return new Connect(); __LEAVE_FUNCTION return NULL;}uint16_t ConnectFactory::get_packetid() const { using namespace pap_server_common_game::define; return id::packet::serverserver::kConnect;}uint32_t ConnectFactory::get_packet_maxsize() const { uint32_t result = sizeof(int16_t) + sizeof(int16_t) + sizeof(int16_t); return result;}} //namespace serverserver} //namespace packets} //namespace pap_server_common_net
这个网络包代码,即是上一部分服务器连接服务器的包,其他网络包都大同小异。所以我们不妨实现一个代码自动实现的工具,让大部分的代码通过工具自动实现。因为网络包在编程中可能会根据不同的游戏非常的多,有了这样的工具那么我们开发时间和精力上就不必费事了。
网络包文本
/** 注释行 可以用来描述该文件的作用 **//* author: viticm *//* date: 2014-1-16 10:36:39 *//* desc: 服务器与服务器之间的连接包 */ModelType: Server /* Server 服务器专用 Common 客户端与服务器公用 */ModelName: serverserver /* 模块名 */PacketName: Connect /* 包名 将作为类名使用 */FileName: connect /* 文件名 *//* 0 不用包含 1 服务器与公用 2 服务器 3 公用 --包括定义文件define/all.h * 服务器为pap_server_game_common::define 公用为pap_game_common::define */ IncludeDefineFile: 2 /* 数据名称将作为变量名,数据类型可用c99所有整型以及字符和数组,不允许使用指针 不使用指针的原因是在32位与64位之间长度大小有区别 *//** [数据名称] [数据类型] [长度] [描述?]如果长度为0,对于字符和float等来说就只是单纯的字符或者float,否则为对应的数组,多维数组以逗号分开。多维数组的示例:[account] [char] [10,20] 长度可以为数字也可以为相应的宏或者枚举,不过你要确保它的存在描述将作为注释生成在头文件中如 uint16_t playerid_; //玩家ID,描述可以为空**//*packet define begin {*/ [serverid] [int16_t] [0] [服务器ID][worldid] [int16_t] [0] [世界ID][zoneid] [int16_t] [0] [区域ID]/*packet define end }*/
有了这样的文本,我们就可以用工具实现上面的代码。
工具
<?phpinclude_once ‘../include/base.php‘;// $packetcode = new PacketCode();// $codecontent = file_get_contents(‘example_packetcode.txt‘);// $packetcode->get_formatcode($codecontent);// $packetcode->create_codefile();/** * 从目录生成包的代码 * @param string $indir * @param string $outdir */function createcode_fromdir($indir = NULL, $outdir = NULL) { if (NULL == $indir || NULL == $outdir) return false; $starttime = time(); $totalfile = 0; $successfile = 0; $formatcode_files = glob($indir.‘*.txt‘); $totalfile = count($formatcode_files); if (0 === $totalfile) return false; $packetcode = new PacketCode(); foreach ($formatcode_files as $file) { $codecontent = file_get_contents($file); $packetcode->get_formatcode($codecontent); $result = $packetcode->create_codefile($outdir); if (true === $result) ++$successfile; } $endtime = time(); echo ‘create code completed, use time: ‘,$endtime - $starttime,‘s‘,LF; echo ‘toalfile: ‘,$totalfile,‘ success file: ‘,$successfile,LF; unset($packetcode);}/** * enter function * @param void * @return void */function main() { $argc = $GLOBALS[‘argc‘]; $argv = $GLOBALS[‘argv‘]; $outputdir = ‘./packet/code‘; $indir = ‘./packet/txt‘; if (3 === $argc) { list($indir, $outputdir) = $argv; } createcode_fromdir(complementpath($indir), complementpath($outputdir));}main();
这是主代码,使用PHP实现,大家不妨用其他语言实现也可。
MMORPG大型游戏设计与开发(part6 of net)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。