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

网络包代码

  1. /**
  2. * PAP Engine ( -- )
  3. * $Id connect.h
  4. * @link -- for the canonical source repository
  5. * @copyright Copyright (c) 2013-2013 viticm( viticm@126.com )
  6. * @license
  7. * @user viticm<viticm@126.com>
  8. * @date 2014-01-16 17:20:14
  9. * @uses packet Connect class
  10. */
  11. #ifndef PAP_SERVER_COMMON_NET_PACKETS_SERVERSERVER_CONNECT_H_
  12. #define PAP_SERVER_COMMON_NET_PACKETS_SERVERSERVER_CONNECT_H_
  13.  
  14. #include "server/common/net/config.h"
  15. #include "server/common/net/connection/base.h"
  16. #include "common/net/packet/base.h"
  17. #include "common/net/packet/factory.h"
  18. #include "server/common/game/define/all.h"
  19.  
  20. namespace pap_server_common_net {
  21.  
  22. namespace packets {
  23.  
  24. namespace serverserver {
  25.  
  26. class Connect : public pap_common_net::packet::Base {
  27.  
  28. public:
  29. Connect();
  30. virtual ~Connect() {};
  31.  
  32. public:
  33. virtual bool read(pap_common_net::socket::InputStream& inputstream);
  34. virtual bool write(pap_common_net::socket::OutputStream& outputstream) const;
  35. virtual uint32_t execute(connection::Base* connection);
  36. virtual uint16_t getid() const;
  37. virtual uint32_t getsize() const;
  38.  
  39. public:
  40. int16_t get_serverid();
  41. void set_serverid(int16_t serverid);
  42. int16_t get_worldid();
  43. void set_worldid(int16_t worldid);
  44. int16_t get_zoneid();
  45. void set_zoneid(int16_t zoneid);
  46.  
  47. private:
  48. int16_t serverid_; //服务器ID
  49. int16_t worldid_; //世界ID
  50. int16_t zoneid_; //区域ID
  51.  
  52. };
  53.  
  54. class ConnectFactory : public pap_common_net::packet::Factory {
  55.  
  56. public:
  57. pap_common_net::packet::Base* createpacket();
  58. uint16_t get_packetid() const;
  59. uint32_t get_packet_maxsize() const;
  60.  
  61. };
  62.  
  63. class ConnectHandler {
  64.  
  65. public:
  66. static uint32_t execute(Connect* packet,
  67. connection::Base* connection);
  68.  
  69. };
  70.  
  71. }; //namespace serverserver
  72.  
  73. }; //namespace packets
  74.  
  75. }; //namespace pap_server_common_net
  76.  
  77. #endif //PAP_SERVER_COMMON_NET_PACKETS_SERVERSERVER_CONNECT_H_
  1. #include "server/common/net/packets/serverserver/connect.h"
  2.  
  3. namespace pap_server_common_net {
  4.  
  5. namespace packets {
  6.  
  7. namespace serverserver {
  8.  
  9. Connect::Connect() {
  10. __ENTER_FUNCTION
  11. __LEAVE_FUNCTION
  12. }
  13.  
  14. bool Connect::read(pap_common_net::socket::InputStream& inputstream) {
  15. __ENTER_FUNCTION
  16. inputstream.read((char*)(&serverid_), sizeof(serverid_));
  17. inputstream.read((char*)(&worldid_), sizeof(worldid_));
  18. inputstream.read((char*)(&zoneid_), sizeof(zoneid_));
  19. __LEAVE_FUNCTION
  20. return false;
  21. }
  22.  
  23. bool Connect::write(pap_common_net::socket::OutputStream& outputstream) const {
  24. __ENTER_FUNCTION
  25. outputstream.write((char*)(&serverid_), sizeof(serverid_));
  26. outputstream.write((char*)(&worldid_), sizeof(worldid_));
  27. outputstream.write((char*)(&zoneid_), sizeof(zoneid_));
  28. __LEAVE_FUNCTION
  29. return false;
  30. }
  31.  
  32. uint32_t Connect::execute(connection::Base* connection) {
  33. __ENTER_FUNCTION
  34. uint32_t result = ;
  35. result = ConnectHandler::execute(this, connection);
  36. return result;
  37. __LEAVE_FUNCTION
  38. return ;
  39. }
  40.  
  41. uint16_t Connect::getid() const {
  42. using namespace pap_server_common_game::define;
  43. return id::packet::serverserver::kConnect;
  44. }
  45.  
  46. uint32_t Connect::getsize() const {
  47. uint32_t result = sizeof(serverid_) +
  48. sizeof(worldid_) +
  49. sizeof(zoneid_);
  50. return result;
  51. }
  52.  
  53. int16_t Connect::get_serverid() {
  54. return serverid_;
  55. }
  56. void Connect::set_serverid(int16_t serverid) {
  57. serverid_ = serverid;
  58. }
  59. int16_t Connect::get_worldid() {
  60. return worldid_;
  61. }
  62. void Connect::set_worldid(int16_t worldid) {
  63. worldid_ = worldid;
  64. }
  65. int16_t Connect::get_zoneid() {
  66. return zoneid_;
  67. }
  68. void Connect::set_zoneid(int16_t zoneid) {
  69. zoneid_ = zoneid;
  70. }
  71.  
  72. pap_common_net::packet::Base* ConnectFactory::createpacket() {
  73. __ENTER_FUNCTION
  74. return new Connect();
  75. __LEAVE_FUNCTION
  76. return NULL;
  77. }
  78.  
  79. uint16_t ConnectFactory::get_packetid() const {
  80. using namespace pap_server_common_game::define;
  81. return id::packet::serverserver::kConnect;
  82. }
  83.  
  84. uint32_t ConnectFactory::get_packet_maxsize() const {
  85. uint32_t result = sizeof(int16_t) +
  86. sizeof(int16_t) +
  87. sizeof(int16_t);
  88. return result;
  89. }
  90.  
  91. } //namespace serverserver
  92.  
  93. } //namespace packets
  94.  
  95. } //namespace pap_server_common_net

  这个网络包代码,即是上一部分服务器连接服务器的包,其他网络包都大同小异。所以我们不妨实现一个代码自动实现的工具,让大部分的代码通过工具自动实现。因为网络包在编程中可能会根据不同的游戏非常的多,有了这样的工具那么我们开发时间和精力上就不必费事了。

网络包文本

  1. /** 注释行 可以用来描述该文件的作用 **/
  2. /* author: viticm */
  3. /* date: 2014-1-16 10:36:39 */
  4. /* desc: 服务器与服务器之间的连接包 */
  5.  
  6. ModelType: Server /* Server 服务器专用 Common 客户端与服务器公用 */
  7. ModelName: serverserver /* 模块名 */
  8. PacketName: Connect /* 包名 将作为类名使用 */
  9. FileName: connect /* 文件名 */
  10. /* 0 不用包含 1 服务器与公用 2 服务器 3 公用 --包括定义文件define/all.h
  11. * 服务器为pap_server_game_common::define 公用为pap_game_common::define
  12. */
  13. IncludeDefineFile: 2
  14.  
  15. /* 数据名称将作为变量名,数据类型可用c99所有整型以及字符和数组,不允许使用指针
  16. 不使用指针的原因是在32位与64位之间长度大小有区别
  17. */
  18. /**
  19. [数据名称] [数据类型] [长度] [描述?]
  20. 如果长度为0,对于字符和float等来说就只是单纯的字符或者float,
  21. 否则为对应的数组,多维数组以逗号分开。
  22. 多维数组的示例:[account] [char] [10,20]
  23. 长度可以为数字也可以为相应的宏或者枚举,不过你要确保它的存在
  24. 描述将作为注释生成在头文件中如 uint16_t playerid_; //玩家ID,描述可以为空
  25. **/
  26.  
  27. /*packet define begin {*/
  28. [serverid] [int16_t] [0] [服务器ID]
  29. [worldid] [int16_t] [0] [世界ID]
  30. [zoneid] [int16_t] [0] [区域ID]
  31. /*packet define end }*/

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

工具

  1. <?php
  2. include_once '../include/base.php';
  3.  
  4. // $packetcode = new PacketCode();
  5.  
  6. // $codecontent = file_get_contents('example_packetcode.txt');
  7. // $packetcode->get_formatcode($codecontent);
  8. // $packetcode->create_codefile();
  9.  
  10. /**
  11. * 从目录生成包的代码
  12. * @param string $indir
  13. * @param string $outdir
  14. */
  15. function createcode_fromdir($indir = NULL, $outdir = NULL) {
  16. if (NULL == $indir || NULL == $outdir) return false;
  17. $starttime = time();
  18. $totalfile = 0;
  19. $successfile = 0;
  20. $formatcode_files = glob($indir.'*.txt');
  21. $totalfile = count($formatcode_files);
  22. if (0 === $totalfile) return false;
  23. $packetcode = new PacketCode();
  24. foreach ($formatcode_files as $file) {
  25. $codecontent = file_get_contents($file);
  26. $packetcode->get_formatcode($codecontent);
  27. $result = $packetcode->create_codefile($outdir);
  28. if (true === $result) ++$successfile;
  29. }
  30. $endtime = time();
  31. echo 'create code completed, use time: ',$endtime - $starttime,'s',LF;
  32. echo 'toalfile: ',$totalfile,' success file: ',$successfile,LF;
  33. unset($packetcode);
  34. }
  35.  
  36. /**
  37. * enter function
  38. * @param void
  39. * @return void
  40. */
  41. function main() {
  42. $argc = $GLOBALS['argc'];
  43. $argv = $GLOBALS['argv'];
  44. $outputdir = './packet/code';
  45. $indir = './packet/txt';
  46. if (3 === $argc) {
  47. list($indir, $outputdir) = $argv;
  48. }
  49. createcode_fromdir(complementpath($indir), complementpath($outputdir));
  50. }
  51.  
  52. 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. HTML+AngularJS+Groovy如何实现登录功能

    AngularJS是一款优秀的前端JS框架,已经被用于Google的多款产品当中.AngularJS核心特性有:MVVM.模块化.自动化双向数据绑定.语义化标签.依赖注入等.AngularJS认为声明 ...

  2. Riot - 比 Facebook React 更轻量的 UI 库

    Riot 是一个类似 Facebook React 的用户界面库,只有3.5KB,非常轻量.支持IE8+浏览器的自定义标签,虚拟 DOM,语法简洁.Riot 给前端开发人员提供了除 React 和 P ...

  3. CSS之详解:active选择器

    Active的一段话 active的英文解释为"积极的",表现在鼠标上就是点击的意思.关于active选择器最多的示例恐怕就是应用在链接上面的,然而打开链接是一个一瞬间的动作,这不 ...

  4. eclipse提示:This tag and its children can be replaced by one <TextView/> and a compound drawable

    今天在学习android开发的时候,写了这样的一段代码: <?xml version="1.0" encoding="utf-8"?> <Li ...

  5. LAMP一键安装脚本 from:秋水逸冰

    Install LAMP(Linux + Apache + MySQL + PHP ) for CentOS/Redhat/Fedora 项目地址:https://github.com/teddysu ...

  6. css笔记图

    1.css3选择器 2.css3动画 3.flex 4.自适应 5.边距图

  7. Hexo部署到GitHub出现spawn ENOENT的解决办法

    最近用Hexo博客部署到GitHub时出现了这如下的错误: Error: spawn ENOENT at errnoException (child_process.js:980:11) at Pro ...

  8. 在Kali Linux下安装与配置OpenVas

    以下是我的Kali版本号: 执行安装命令: apt-get install openvas 安装完成后可以在漏洞分析菜单下查看到OpenVas相关选项. 以下为安装完成后需要用到的几个命令: open ...

  9. 如何在启用SharePoint浏览器功能的InfoPath 表单中添加托管代码以动态地加载并显示图片

    InfoPath 的浏览器表单不支持加载并显示图片,当然在模板中可以插入图片,但是如果想显示数据库的一幅图片,或是动态加载一张图片就无能为力了. 基实这个问题可以通过在浏览器表单中使用: " ...

  10. DevExpress 2015.2发布 看看有哪些更新

    下面是besy翻译的部分重要更新,要查看全部更新细节请访问英文官网. | 下载DevExpress 2015.2 Diagram Control 新的DevExpress Diagram Contro ...