依星源码资源网,依星资源网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

【好消息,好消息,好消息】VIP会员可以发表文章赚积分啦 !
查看: 38|回复: 0

[游戏架设教程] DELPHI版传奇引擎学习菜鸟篇(applem2)-04

[复制链接] 主动推送

2043

主题

2050

帖子

3114

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
3114
发表于 2024-11-2 23:55:26 | 显示全部楼层 |阅读模式
DELPHI版传奇引擎学习菜鸟篇(applem2)-04
接着学习,从学习的过程中,我发现了这个引擎控制台的主要功能,这也是一行一行代码敲进去的结果,之前我对这个单元的功能了解的还是少,不知不觉中就发现了它主要实现的功能,对里边的代码理解也进了一步.
从我的理解它大概有如下功能:
a.实现整个服务端的启动配置.
b.进行数据更新,这里指的是对数据库(人物\物品\怪物…)的更新.
c.服务端初始化(清理数据和M2的变量复位)
d.启动所有服务并监控其运行状态.
e.备份数据.
除了d,其他的都还容易理解,基本上拖拉控件写上事件就可以完成,唯独对服务进程进行监控我一直找不到理解的方法,说明了我对WIN32API知道的太少了,对进程和线程的运行机理和消息处理机制还不明白,先用自己的话记下来,帮助理解,然后看API,了解处理方式.
从启动按钮点击,就可以发现一系列的调用,按照顺序如下:
  1. procedure TfrmMain.ButtonStartGameClick(Sender: TObject);
  2. begin
  3.   SetWindowPos(Self.Handle, Self.Handle, Self.Left, Self.Top, Self.Width, Self.Height, $40);
  4.   case m_nStartStatus of
  5.     0:
  6.       begin
  7.         if Application.MessageBox('是否确认启动游戏服务器 ?', '确认信息', MB_YESNO + MB_ICONQUESTION) = mrYes then
  8.         begin
  9.           StartGame();  //调用启动过程
  10.         end;
  11.       end;
  12.     1:
  13.       begin
  14.         if Application.MessageBox('是否确认中止启动游戏服务器 ?', '确认信息', MB_YESNO + MB_ICONQUESTION) = mrYes then
  15.         begin
  16.           TimerStartGame.Enabled := False;  //终止启动计时器
  17.           m_nStartStatus := 2;
  18.           ButtonStartGame.Caption := g_sButtonStopGame;
  19.         end;
  20.       end;
  21.     2:
  22.       begin
  23.         if Application.MessageBox('是否确认停止游戏服务器 ?', '确认信息', MB_YESNO + MB_ICONQUESTION) = mrYes then
  24.         begin
  25.           StopGame();    //停止服务
  26.         end;
  27.       end;
  28.     3:
  29.       begin
  30.         if Application.MessageBox('是否确认中止启动游戏服务器 ?', '确认信息', MB_YESNO + MB_ICONQUESTION) = mrYes then
  31.         begin
  32.           TimerStopGame.Enabled := False;    //终止停止计时器
  33.           m_nStartStatus := 2;
  34.           ButtonStartGame.Caption := g_sButtonStopGame;
  35.         end;
  36.       end;
  37.   end;
  38. end;
复制代码
启动过程实际上是调用启动计时器,其他的动作都是设置服务的初始状态:
  1. procedure TfrmMain.StartGame;
  2. var
  3.   I: Integer;
  4. begin
  5.   m_dwRunTick := GetTickCount;  //返回系统启动经历的毫秒数
  6.   FillChar(DBServer, SizeOf(TProgram), #0); //用指定的值填充连续的字节为进程启动做准备
  7.   //读取服务启动前的初始化状态,以下类似
  8.   DBServer.boGetStart := g_Config.DBServer.GetStart;
  9.   DBServer.boReStart := True;
  10.   DBServer.sDirectory := g_sGameDirectory + 'DBServer\';
  11.   DBServer.sProgramFile := g_Config.DBServer.ProgramFile;
  12.   DBServer.nMainFormX := g_Config.DBServer.MainFormX;
  13.   DBServer.nMainFormY := g_Config.DBServer.MainFormY;
  14.   ....

  15.   ButtonStartGame.Caption := g_sButtonStopStartGame;
  16.   m_nStartStatus := 1;
  17.   TimerStartGame.Enabled := True;//调用启动计时器按顺序启动所有服务
  18. end;
复制代码
  1. procedure TfrmMain.TimerStartGameTimer(Sender: TObject);
  2. var
  3.   nRetCode: Integer;
  4.   I: Integer;
  5.   boStartRunGateOK: Boolean;
  6.   wHour, wMin, wSec, wMSec: Word;
  7. begin
  8.   if DBServer.boGetStart then
  9.   begin
  10.     case DBServer.btStartStatus of
  11.       0:
  12.         begin
  13.           nRetCode := RunProgram(DBServer, IntToStr(Self.Handle), 0);
  14.           if nRetCode = 0 then
  15.           begin
  16.             DBServer.btStartStatus := 1;
  17.             DBServer.ProcessHandle := OpenProcess(PROCESS_ALL_ACCESS, False, DBServer.ProcessInfo.dwProcessId);
  18.             MainOutMessage('start DbServer:'+IntToStr(DBServer.ProcessInfo.dwProcessId));//-----------------------------
  19.           end
  20.           else
  21.           begin
  22.             DBServer.btStartStatus := 2;
  23.           end;
  24.           Exit;
  25.         end;
  26.       1:
  27.         begin
  28.           Exit;
  29.         end;
  30.     end;
  31.   end;
  32.   TimerStartGame.Enabled := False;//启动成功,终止启动计时器
  33.   TimerCheckRun.Enabled := True; //打开服务监测计时器,异常的服务会被重启
  34.   ButtonStartGame.Caption := g_sButtonStopGame;
  35.   m_nStartStatus := 2;//标志启动状态为2(已启动)
  36. end;
复制代码
上边的RunProgram(…)函数是调用外部程序的函数,对API我还需要加强学习,理解的很困难
  1. function RunProgram(var ProgramInfo: TProgram; sHandle: string; dwWaitTime: LongWord): LongWord;
  2. var
  3.   StartupInfo: TStartupInfo; //获取进程状态
  4.   sCommandLine: string;      //命令行参数
  5.   sCurDirectory: string;     //程序目录
  6. begin
  7.   Result := 0;//执行外部程序,失败返回0,成功返回进程句柄
  8.   FillChar(StartupInfo, SizeOf(TStartupInfo), #0);
  9.   GetStartupInfo(StartupInfo);//获取进程的启动信息
  10.   {设置命令行参数}
  11.   sCommandLine := format('%s%s %s %d %d', [ProgramInfo.sDirectory, ProgramInfo.sProgramFile, sHandle, ProgramInfo.nMainFormX, ProgramInfo.nMainFormY]);
  12.   sCurDirectory := ProgramInfo.sDirectory; //取得程序运行目录
  13.   if not CreateProcess(nil,  //如果启动服务失败返回错误代码
  14.     PChar(sCommandLine),
  15.     nil,
  16.     nil,
  17.     True,
  18.     0,
  19.     nil,
  20.     PChar(sCurDirectory),
  21.     StartupInfo,
  22.     ProgramInfo.ProcessInfo)
  23.   then
  24.   begin
  25.     Result := GetLastError();
  26.   end;
  27.   Sleep(dwWaitTime);  //挂起
  28. end;
复制代码
服务启动之后就开始调用监测计时器监测服务状态:
  1. procedure TfrmMain.TimerCheckRunTimer(Sender: TObject);
  2. var
  3.   dwExitCode: LongWord;
  4.   nRetCode: Integer;
  5.   I: Integer;
  6. begin
  7.   if DBServer.boGetStart then
  8.   begin
  9.     GetExitCodeProcess(DBServer.ProcessHandle, dwExitCode);
  10.     MainOutMessage('check DbServer:'+IntToStr(DBServer.ProcessHandle));
  11.     //如果监测到服务没有启动则重新启动程序,这里没有实现代码重用
  12.     if (dwExitCode <> STILL_ACTIVE) or (DBServer.ProcessHandle = 0) then
  13.     begin
  14.       nRetCode := RunProgram(DBServer, IntToStr(Self.Handle), 0);
  15.       if nRetCode = 0 then
  16.       begin
  17.         CloseHandle(DBServer.ProcessHandle);
  18.         DBServer.ProcessHandle := OpenProcess(PROCESS_ALL_ACCESS, False, DBServer.ProcessInfo.dwProcessId);
  19.         if DBServer.MainFormHandle <> 0 then
  20.           MainOutMessage('数据库异常关闭,已被重新启动...');
  21.         DBServer.MainFormHandle := 0;
  22.       end;
  23.     end;
  24.   end;
  25.   ...
  26. end;
复制代码
因为所有的服务启动有一定的依赖性,所以考虑是不是可以通过传递进程间消息实现其他服务的启动,这样写一大堆相似的过程有点凑代码的嫌疑O(∩_∩)O…,我不是业内之人,所以不知道代码越多,功能越多,就是感觉这些过程不如都写成通用的函数,然后通过传入服务结构变量实现服务的启动\监测\包括停止.
终于发现了,这样学习有点绕远,因为好多基本的概念我还没有入门,但是我还是要坚持让自己慢慢消化这些,写一遍不懂就写两遍甚至多变,总会有一些收获的.
今天先学到这里,先把消息处理机制和进程线程通讯的概念搞清楚再继续下边的学习.

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

相关帖子

扫码关注微信公众号,及时获取最新资源信息!下载附件优惠VIP会员5折;永久VIP免费
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

免责声明:
1、本站提供的所有资源仅供参考学习使用,版权归原著所有,禁止下载本站资源参与商业和非法行为,请在24小时之内自行删除!
2、本站所有内容均由互联网收集整理、网友上传,并且以计算机技术研究交流为目的,仅供大家参考、学习,请勿任何商业目的与商业用途。
3、若您需要商业运营或用于其他商业活动,请您购买正版授权并合法使用。
4、论坛的所有内容都不保证其准确性,完整性,有效性,由于源码具有复制性,一经售出,概不退换。阅读本站内容因误导等因素而造成的损失本站不承担连带责任。
5、用户使用本网站必须遵守适用的法律法规,对于用户违法使用本站非法运营而引起的一切责任,由用户自行承担
6、本站所有资源来自互联网转载,版权归原著所有,用户访问和使用本站的条件是必须接受本站“免责声明”,如果不遵守,请勿访问或使用本网站
7、本站使用者因为违反本声明的规定而触犯中华人民共和国法律的,一切后果自己负责,本站不承担任何责任。
8、凡以任何方式登陆本网站或直接、间接使用本网站资料者,视为自愿接受本网站声明的约束。
9、本站以《2013 中华人民共和国计算机软件保护条例》第二章 “软件著作权” 第十七条为原则:为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬。若有学员需要商用本站资源,请务必联系版权方购买正版授权!
10、本网站如无意中侵犯了某个企业或个人的知识产权,请来信【站长信箱312337667@qq.com】告之,本站将立即删除。
郑重声明:
本站所有资源仅供用户本地电脑学习源代码的内含设计思想和原理,禁止任何其他用途!
本站所有资源、教程来自互联网转载,仅供学习交流,不得商业运营资源,不确保资源完整性,图片和资源仅供参考,不提供任何技术服务。
本站资源仅供本地编辑研究学习参考,禁止未经资源商正版授权参与任何商业行为,违法行为!如需商业请购买各资源商正版授权
本站仅收集资源,提供用户自学研究使用,本站不存在私自接受协助用户架设游戏或资源,非法运营资源行为。
 
在线客服
点击这里给我发消息 点击这里给我发消息 点击这里给我发消息
售前咨询热线
312337667

微信扫一扫,私享最新原创实用干货

QQ|免责声明|小黑屋|依星资源网 ( 鲁ICP备2021043233号-3 )|网站地图

GMT+8, 2024-11-13 08:55

Powered by Net188.com X3.4

邮箱:312337667@qq.com 客服QQ:312337667(工作时间:9:00~21:00)

快速回复 返回顶部 返回列表