程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> DELPHI版傳奇引擎學習菜鳥篇(applem2)-01,applem2-01

DELPHI版傳奇引擎學習菜鳥篇(applem2)-01,applem2-01

編輯:Delphi

DELPHI版傳奇引擎學習菜鳥篇(applem2)-01,applem2-01


一點廢話:因為非工科出身,又對編程有點興趣,雜亂的學習了好多(C,C++,PYTHON…)等好多語言,最後發現DEKLPI上手比較快,對於不知道線代和高數等是什麼的我來說也許是較好的選擇了,畢竟只是興趣而已,對於DELPHI的資料不是沒有,就是覺得沒有自己可以漸進入門的.因為以前玩過一個叫傳奇的游戲,所以知道最早的傳奇是DELPHI開發的,感覺還好,這就找了不少服務端學習(呵呵,研究說不上,因為咱沒到那層次),自己動手架設修改,有時還提供給網友玩公益.然後就找傳奇的DELPHI源碼,不算很多,畢竟現在大部分還是用C寫的,也不會開源給大家看,後來聽網友說APPLEM2引擎不知道因為什麼開源了,就找到一個比較全的(當然還是少了很多東西,比如三方VLC),看著前輩們寫的東西,在佩服的同時也覺得自己對照寫一遍也許會得到點什麼,於是就開始了這個過程,決心從頭開始把代碼都敲一遍,盡管時間很長,也有點"盜用"(雖說APPLEM2開源了,但是架構模式也還是有知識產權的)嫌疑,呵呵…,不管怎麼說,我發現這樣學習東西很快,至少對我來說是這樣的,這樣的過程讓我知道了什麼是記錄,什麼是類,什麼是SOCKET,對於初學的我來說,收獲還是頗豐的,當然也發現了早期代碼有不少的不妥之處,函數和過程的繁雜讓我一貫找不著北,在試著將一些繁雜的代碼簡化後,突然發現有的函數被我重新寫過了,也許這也是一種提高的方式吧,希望我能堅持下去.正題開始.

後續所有內容都是我自己學習DELPHI過程中對程序設計的一點淺顯的了解,有的也許會引發前輩門笑噴,但是這恰是我學習的成長過程,也是我提高的途徑.

 

1.傳奇服務端結構:

大部分名字都叫MirServer,基本結構包含八個文件夾和一個GAMECENTER.EXE文件和一個CONFIG.INI文件,以下按照啟動順序說明.

名稱 說明 描述 GAMECENTER 控制中心 引導所有服務端程序啟動,早期的端我沒看到過 DBServer 數據庫服務器 管理人物\怪物\物品\魔法數據 LoginSrv 登錄服務器 控制賬號登錄 LogServer 日志服務器 記錄玩家操作日志 Mir200 游戲主引擎 管理游戲龐大的腳本和設置 RunGate 游戲網關 呵呵,現在我還不知道什麼是網關 SelGate 角色網關 好像進入游戲與角色選擇有關吧 LoginGate 登錄網關 好像是登錄控制和玩家狀態檢測的 Mud2 數據文件夾 物品\魔法\怪物數據,應該是paradox的

applem2的還有個排行榜的,我想大部分端應該集成在M2裡邊了吧.

能夠看到的就這些,既然從頭開始,就先把目錄硬記下來,雖然後邊在"抄寫"的過程中會改變一些設置.

2.源代碼結構

源代碼和上述結構一樣,除了MUD2,每個都對應一個工程文件,用了好多插件,准備把不需要的都去掉,把所有的服務端程序集中到一個進程裡邊,暫時不考慮性能如何,盡量用不帶插件的DELPHI完整編譯,版本以2007為基准吧.先寫完了一個GAMECENTER和DBServer,效果如下:

//本身包含的單元 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);

先將學習過的溫習一下,然後再將服務器的狀態處理連貫做一下記錄.

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved