DELPHI版传奇引擎学习菜鸟篇(applem2)-01

1.传奇服务端结构:

大部分名字都叫MirServer,基本结构包含八个文件夹和一个GAMECENTER.EXE文件和一个CONFIG.INI文件,以下按照启动顺序说明.

名称 说明 描述
GAMECENTER 控制中心 引导所有服务端程序启动,早期的端我没看到过
DBServer 数据库服务器 管理人物\怪物\物品\魔法数据
LoginSrv 登录服务器 控制账号登录
LogServer 日志服务器 记录玩家操作日志
Mir200 游戏主引擎 管理游戏庞大的脚本和设置
RunGate 游戏网关 呵呵,现在我还不知道什么是网关
SelGate 角色网关 好像进入游戏与角色选择有关吧
LoginGate 登录网关 好像是登录控制和玩家状态检测的
Mud2 数据文件夹 物品\魔法\怪物数据,应该是paradox的

applem2的还有个排行榜的,我想大部分端应该集成在M2里边了吧.

能够看到的就这些,既然从头开始,就先把目录硬记下来,虽然后边在"抄写"的过程中会改变一些设置.

2.源代码结构

源代码和上述结构一样,除了MUD2,每个都对应一个工程文件,用了好多插件,准备把不需要的都去掉,把所有的服务端程序集中到一个进程里边,暂时不考虑性能如何,尽量用不带插件的DELPHI完整编译,版本以2007为基准吧.先写完了一个GAMECENTER和DBServer,效果如下:

360截图20151213130625731

服务端只有一个Server.exe程序,其他服务都集成到一个父窗口中,然后根据主程序设置决定需要启动那些服务,毕竟传奇架设的时候有些服务可能不在一个服务器上,虽然是菜鸟,但是咱也得考虑远一点,学习前辈们的一些先进理念,也是拓展了自己的学习思路.

3.GAMECENTER

先说说启动中心,不说别的,光是主窗口4000多行的代码就让我眼花缭乱了,这对我来说太难了,有的过程或函数快300行了,阅读比较困难,还是先从自己的角度去理解吧.

GAMECENTER工程架构如下(名字都是从自己理解的角度起的):

//本身包含的单元
ugamecenter.pas     // 主窗口单元
GShare.pas          // 全局常量单元
DataBackUp.pas      // 数据备份单元
//引用的单元
DBShare.pas         // 共享数据单元
HUtil32.pas         // 人物操作单元
MD5Unit.pas         // 数据校验单元
Common.pas          // 通用常量单元

3.1 GShare.pas单元

单元之间的引用很复杂,也许是因为早起代码的原因吧,先说说GShare.pas单元,这个单元包含了服务器的配置常量,如文件夹名字\服务状态\配置文件等全局常量和服务的启动\停止函数以及消息处理过程,先记录一点自己能够理解的.

unit GShare;

interface
uses
  Windows, Messages, Classes, SysUtils, INIFiles, DataBackUp, ComCtrls;

const
  MAXRUNGATECOUNT = 8;  // 最大游戏网关数量
  {以下0-9是每个服务的消息编号常量}
  tDBServer = 0;
  tLoginSrv = 1;
  tLogServer = 2;
  tM2Server = 3;
  tLoginGate = 4;
  tSelGate = 6;
  tRunGate = 8;
  tPlugTop = 9;
  {不言而喻,这里是服务配置INI文件的节名称常量}
  BasicSectionName = 'GameConfig';
  DBServerSectionName = 'DBServer';
  LoginSrvSectionName = 'LoginSrv';
  M2ServerSectionName = 'M2Server';
  LogServerSectionName = 'LogServer';
  RunGateSectionName = 'RunGate';
  SelGateSectionName = 'SelGate';
  LoginGateSectionName = 'LoginGate';
  PlugTopSectionName='PlugTop';
  {IP设置,APPLEM2自带一机双IP设置}
  sAllIPaddr = '0.0.0.0';
  sLocalIPaddr = '127.0.0.1';
  sLocalIPaddr2 = '127.0.0.2';
  nLimitOnlineUser = 2000;    //服务器最高上线人数(源码自带注释)
  {以下是各个服务的配置路径和文件常量}
  SERVERCONFIGDIR = 'Config\';
  SERVERCONFIGFILE = 'Config.ini';
  SERVERGAMEDATADIR = 'GameData\';
  SERVERLOGDIR = 'Log\';

  DBSERVERSECTIONNAME2 = 'DBServer';
  DBSERVERDBDIR = 'DB\';
  DBSERVERALLOWADDR = 'AllowAddr.txt';
  DBSERVERGATEINFO = 'GateInfo.txt';

  LOGINSRVSECTIONNAME2 = 'LoginSrv';
  LOGINSRVCHRLOGNAME = SERVERLOGDIR + 'ChrLog\';
  LOGINSRVALLOWADDR = 'LoginSrv_AllowAddr.txt';
  LOGINSRVGETINFO = 'LoginSrv_GateInfo.txt';
  LOGINSRVUSERLIMIT = 'LoginSrv_UserLimit.txt';

  M2SERVERCONFIGFILE = '!Setup.txt';
  M2SERVERSECTIONNAME1 = 'Server';
  M2SERVERSECTIONNAME2 = 'Share';
  M2SERVERSEGuildBase = SERVERGAMEDATADIR + 'GuildBase\';
  M2SERVERSEGuildDir = M2SERVERSEGuildBase + 'Guilds\';
  M2SERVERSEGuildFile = M2SERVERSEGuildBase + 'GuildList.txt';
  M2SERVERSEConLogDir = SERVERLOGDIR + 'M2ConLog\';
  M2SERVERSECastleDir = SERVERGAMEDATADIR + 'Castle\';
  M2SERVERSECastleFile = SERVERGAMEDATADIR + 'Castle\List.txt';
  M2SERVERSELogDir = SERVERLOGDIR + 'M2Log\';
  M2SERVERSEEMailDir = SERVERLOGDIR + 'M2Log\';
  M2SERVERSEnvirDir = 'Envir\';
  M2SERVERSMapDir = 'Map\';
  M2SERVERSALLOWADDR = 'M2Server_AllowAddr.txt';
  M2SERVERSEmailDir = SERVERGAMEDATADIR + 'EMail\';

  LOGSERVERSECTIONNAME2 = 'LogDataServer';
  LOGSERVERBaseDir = SERVERGAMEDATADIR + 'GameLog\';
  RunGateSectionName2 = 'RunGate';
  SelGateSectionName2 = 'SelGate';
  LoginGateSectionName2 = 'LoginGate';
  PlugTopDIR=SERVERGAMEDATADIR +'\mir200\';

type
  {定义每个服务的应用程序状态结构指针}
  pTProgram = ^TProgram;
  TProgram = packed record
    boGetStart: Boolean; //DBServer启动标志 (源码自带注释)
    boReStart: Boolean; //程序异常停止,是否重新启动 (源码自带注释)
    btStartStatus: Byte;//0,1,2,3 未启动,正在启动,已启动,正在关闭 (源码自带注释)
    sProgramFile: string[50];
    sDirectory: string[100];
    ProcessInfo: TProcessInformation; //服务的进程信息(进程,线程,进程ID,线程ID)
    ProcessHandle: THandle;           //进程句柄
    MainFormHandle: THandle;          //主窗口句柄,后续改为每个服务对应的活动窗口句柄
    nMainFormX: Integer;  //服务端启动后窗口位置
    nMainFormY: Integer;
  end;
  {应该是加载地图文件的结构指针}
  pTDataListInfo = ^TDataListInfo;
  TDataListInfo = packed record
    sFileName: string[255];
    MapFileHandle: THandle;
    MapFileBuffer: PChar;
    DateTime: TDateTime;
    Data: PChar;
    DataSize: Integer;
    Item: TListItem;
  end;
  {检测服务运行状态}
  TCheckCode = packed record
    dwThread0: LongWord;
    sThread0: string;
  end;
  {下边的一堆CONFIG是对应的每个服务状态的结构}
  TDBServerConfig = packed record
    MainFormX: Integer;
    MainFormY: Integer;
    GatePort: Integer;
    ServerPort: Integer;
    GetStart: Boolean;
    ProgramFile: string[50];
  end;

  TLoginSrvConfig = packed record
    MainFormX: Integer;
    MainFormY: Integer;
    GatePort: Integer;
    ServerPort: Integer;
    MonPort: Integer;
    GetStart: Boolean;
    ProgramFile: string[50];
  end;

  TM2ServerConfig = packed record
    MainFormX: Integer;
    MainFormY: Integer;
    GatePort: Integer;
    MsgSrvPort: Integer;
    GetStart: Boolean;
    ProgramFile: string[50];
  end;

  TLogServerConfig = packed record
    MainFormX: Integer;
    MainFormY: Integer;
    Port: Integer;
    GetStart: Boolean;
    ProgramFile: string[50];
  end;

    TPlugTopConfig = packed record
    MainFormX: Integer;
    MainFormY: Integer;
    Port: Integer;
    GetStart: Boolean;
    ProgramFile: string[50];
  end;

  TRunGateConfig = packed record
    MainFormX: Integer;
    MainFormY: Integer;
    GetStart: array[0..MAXRUNGATECOUNT - 1] of Boolean;
    GatePort: array[0..MAXRUNGATECOUNT - 1] of Integer;
    ProgramFile: string[50];
  end;

  TSelGateConfig = packed record
    MainFormX: Integer;
    MainFormY: Integer;
    GatePort: array[0..1] of Integer;
    GetStart1: Boolean;
    GetStart2: Boolean;
    ProgramFile: string[50];
  end;

  TLoginGateConfig = packed record
    MainFormX: Integer;
    MainFormY: Integer;
    GatePort: Integer;
    GetStart: Boolean;
    ProgramFile: string[50];
  end;
  {将所有的服务状态声明为一个结构指针}
  pTConfig = ^TConfig;
  TConfig = packed record
    DBServer: TDBServerConfig;
    LoginSrv: TLoginSrvConfig;
    M2Server: TM2ServerConfig;
    LogServer: TLogServerConfig;
    RunGate: TRunGateConfig;
    SelGate: TSelGateConfig;
    LoginGate: TLoginGateConfig;
    PlugTop: TPlugTopConfig;
  end;

  procedure LoadConfig();  //加载启动设置
  procedure SaveConfig();  //保存启动设置
  {下边2个是启动和停止每个服务的函数}
  function RunProgram(var ProgramInfo: TProgram; sHandle: string; dwWaitTime: LongWord): LongWord;
  function StopProgram(var ProgramInfo: TProgram; dwWaitTime: LongWord): Integer;
  {发送每个服务当前状态的消息处理过程}
  procedure SendProgramMsg(DesForm: THandle; wIdent: Word; sSendMsg: string);

先将学习过的温习一下,然后再将服务器的状态处理连贯做一下记录. 

关注过程,不知不觉就发现了结果原来如此...

posted @ 2016-09-08 10:45  冰刀_txj  阅读(775)  评论(0)    收藏  举报