上一部分,讲述了一个服务器与服务器之间的通信实例,客户端其实原理大同小异。网络部分准备就暂时讲到这里,不过我们不妨再回头过来想想在这过程中有没有优化和改进的地方。这部分讲解的是以网络包代码作分析,实现自动生成其代码的功能。

网络包代码

/**
* 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 = ;
result = ConnectHandler::execute(this, connection);
return result;
__LEAVE_FUNCTION
return ;
} 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 }*/

  有了这样的文本,我们就可以用工具实现上面的代码。

工具

<?php
include_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)的更多相关文章

  1. MMORPG大型游戏设计与开发(概述)updated

    1.定义 MMORPG,是英文Massive(或Massively)Multiplayer Online Role-PlayingGame的缩写,即大型多人在线角色扮演游戏. 2.技术与知识 在这系列 ...

  2. MMORPG大型游戏设计与开发(UI SYSTEM SHOW)

    接下来一段时间,这些文件可能不再更新,期间我会学习和掌握一些前端知识.虽然我非常欣赏剑侠网络版叁和九阴真经的画面,但是那是一个庞大的游戏引擎,一般人是无法窥伺的,除非你是天才而且要拥有机器毫无中断的毅 ...

  3. MMORPG大型游戏设计与开发(服务器 游戏场景 核心详述)

    核心这个词来的是多么的高深,可能我们也因为这个字眼望而却步,也就很难去掌握这部分的知识.之所以将核心放在最前面讲解,也可以看出它真的很重要,希望朋友们不会错过这个一直以来让大家不熟悉的知识,同我一起进 ...

  4. MMORPG大型游戏设计与开发(游戏服务器 游戏场景 概述 updated)

    我们在玩游戏的时候,我们进入游戏后第一眼往往都是看到游戏世界中的场景,当然除了个别例外,因为那些游戏将游戏场景隐藏了起来,如文字游戏中的地点一样.既然我们接触了游戏世界的核心,那么作为核心的场景又包括 ...

  5. MMORPG大型游戏设计与开发(客户端架构 part8 of vegine)

    脚本模块是游戏设计中争论比较多的话题,那是因为作为脚本本身所带来的利弊.其实这都无关紧要,取舍是人必须学会的一项技能,如果你不会取舍那么就让趋势给你一个满意的答复.自从魔兽世界以及传奇(世界)问世以来 ...

  6. MMORPG大型游戏设计与开发(客户端架构 part6 of vegine)

    客户端的变量模块部分主要是将一些常用可变的值集中管理,如窗口的大小,是否开启音乐,音量的大小等等.这些变量通常会应该到客户端的操作,一般来说变量改变的时候会调用一个回调进行处理.下面我们就看看该模块的 ...

  7. MMORPG大型游戏设计与开发(客户端架构 part12 of vegine)

    在游戏中的交互过程中输入是一个必不可少的过程,比如登陆的时候需要用户输入用户名与密码,就算是单机游戏很多时候也要求用户输入一个用户名作为存档的依据.网络游戏中没有了输入,只用鼠标来交互是不切实际的,因 ...

  8. MMORPG大型游戏设计与开发(part1 of net)

    网络模块的设计,是大型多人在线游戏中比较重要的一部分.我之所以将网络模块放到最前面,是因为许许多多的开发者面对这一块的时候充满了疑惑,而且也觉得很神秘和深奥.这些我们面对到的困难,其实是由于我们对这方 ...

  9. MMORPG大型游戏设计与开发(规范)

    一件事如果没有规范.章法,那么做这件事起来往往会遇到许多难题,特别是在多人协作的时候,没有到规范通常让每个人多多少少都面临着头疼的困难.举个例子,多个人要做一桌美味的饺子,有买材料.做面皮.弄肉(菜) ...

随机推荐

  1. i++,++i,Math.max,hasOwnPrototype.ajax,indexOf(),firefox的一些东西,jquery的contains函数,window.open

    一.i++与++i的区别 1 var i=0;3 console.log(i++)5 0 1 var j=0; 2 3 console.log(++j) 4 1 a=++i;相当于i=i+1;a=i; ...

  2. 用Microsoft.Solver.Foundation进行线性规划,为WPF应用添加智能

    在管理信息系统的开发过程中,往往会涉及到一些线性规划数学模型,例如资源配置优化.微软的Microsoft.Solver.Foundation是一个数学库,可以很好的对线性规划问题进行求解.关于它的细节 ...

  3. 20个优秀的 JavaScript 键盘事件处理库

    键盘事件是 Web 开发中最常用的事件之一,通过对键盘事件的捕获和处理可以提高网站的易用性和交互体验.下面,我们向大家介绍收集的20款优秀的 JavaScript 键盘事件处理库,帮助开发人员轻松处理 ...

  4. 推荐25款很棒的 HTML5 开发框架和开发工具【上篇】

    HTML5 在不同的领域让网页设计更强大的.快速,安全,响应式,互动和美丽,这些优点吸引更多的 Web 开发人员使用 HTML5.HTML5 有许多新的特性功能,允许开发人员和设计师创建应用程序和网站 ...

  5. 【2015上半年总结】js开源组件开发系列索引

    js开源组件开发系列一索引 2015.8 by 田想兵 个人网站 从3月份进入新公司以来,时经五个月,我以平均每周1个小组件的速度,已经完成的js组件有22个之余了,已基本上全部用到实际项目中,这些小 ...

  6. 删除oracle表报ORA-24005错误

    请先执行:alter   session   set   events'10851   trace   name   context   forever,level   1'; 然后再删除表.

  7. 转使用chrome命令行:disable-web-security 实现浏览器跨域

    注意chrome 48 版本后此方法就不能用了 推荐一个新方式来实现本地跨域调试线上资源,搜索chrome插件 Allow-Control-Allow-Origin: *.https://chrome ...

  8. 使用mac 终端利用alias设置快捷命令

    在终端中输入快捷命令可以提高工作效率,同时可以少记很多命令 如何做: 首先在~/目录下编辑 .bash_profile这个隐藏文件,如果你想直接双击此文件打开编辑的话请在终端输入 Mac 显示隐藏文件 ...

  9. 网络初见&网络监测

    这里需要下载一个第三方 Reachability-master 大家可以百度一下 下载之后把 Reachability拖进来 具体代码如下 #import "ViewController.h ...

  10. django 微信企业号 返回text消息

    from django.template import Context,Template textTemplate=""" <xml> <ToUserN ...