当前位置 : 145z游戏站 | 热血传奇 | 技术教程 | 

VC++6.0传奇2.0源码拆解:MMORPG多进程架构与编译调试实战链路

热度:
一、源码工程整体形态
传奇2.0服务端源码在VC++6.0下是多Workspace多Project结构,每个可执行体独立成工程,共享MirServer目录约定。核心工程清单:
-LoginGate.dsp→LoginGate.exe(登录网关)
•LoginSrv.dsp→LoginSrv.exe(ID验证服务)

•DBServer.dsp→DBServer.exe(角色/数据持久层)

-SelGate.dsp/Gate30.dsp→角色选择网关
•RunGate.dsp→RunGate.exe(游戏运行网关)

•M2Server.dsp→M2Server.exe(GameSvr主逻辑)

-LogDataSrv.dsp→物品/操作日志服务

工程间不静态链接游戏逻辑,靠TCP命名管道/共享内存做进程间通信,这是早期WindowsMMORPG典型“网关+逻辑+数据”三层分离架构。

二、各模块源码职责与调用链
1.LoginGate(LoginGate.cpp→WinMain→MainWndProc)
窗口消息驱动,WSAAsyncSelect绑定_IDM_CLIENTSOCK_MSG;本地监听7000收客户端,远端连LoginSrv5000。OnClientSockMsg里按FD_CONNECT/FD_READ/FD_CLOSE分发,启ThreadFuncForMsg线程用IOCP投递数据包。职责仅加解密转发,不做账号判定。

2.LoginSrv(LogSrv目录)
读ID.DB/ID.DB.idx(BDE/Paradox格式),校验账号密码、封禁、在线数;通过后回包LoginGate告知客户端该去哪个SelGate/DBServer地址端口。!AddrTable.txt/!ServerInfo.txt控制IP映射。

3.DBServer(DBSrv200/DBServer工程)
核心数据守护进程。FDB目录存人物自定义格式库(Hum.DB类),Mud2\DB下挂StdItems.DB/Monster.DB/Magic.DB由BDEHeroDB别名暴露。GameSvr要存读角色时发命名管道/Socket请求,DBSvr落盘后回ACK,避免M2直接碰DB拖慢主循环。

4.SelGate/Gate30
角色选择期中间件,透传角色列表、创建/删除请求到DBServer,验证完把玩家交给RunGate。

5.RunGate
多实例(7200/7300…),面向已进游戏玩家。收M2下发的坐标/血量/背包变更,转发玩家移动/施法/交易封包给M2。网关层可横向加实例分摊连接,M2单进程跑地图与战斗。

6.M2Server(Mir200主工程,代码量最大)
包含:
•Map加载:读Mir200\Map\*.map,二维Cell数组存可走/阻挡/物件层

•怪物AI:状态机(Idle/Patrol/Chase/Attack/Return),MonGen.txt驱动刷新

-战斗计算:DC/AC/MAC/命中/暴击公式,技能分支查Magic.DB
•物品系统:StdItems.txt与StdItems.DB双源,GIVE/TAKE改内存→通知DBSvr落盘

-脚本解析器:Envir\Market_Def、QuestDiary、QFunction-0.txt文本指令解释执行
•沙巴克/行会/排行榜:Castle\SabukW.txt、GuildBase\Guilds运行时维护

三、网络模型与线程结构
源码中可见两套并存:
•早期分支:WSAAsyncSelect+窗口消息(LoginGate典型写法,单线程可撑千连)

•主服务分支:IOCP完成端口(CheckAvailableIOCP判断NT/2000后启用),M2/RunGate用工作线程池收发包,逻辑帧在主线程Timer里跑

封包头含会话ID、序号、指令字(CM_LOGIN/CM_ATTACK/CM_DROPITEM…),M2里大switch分发到HandleXxx函数。

四、VC++6.0编译环境硬性条件
-宿主系统:Windows2000/XP32位实机或虚拟机(Win10+装VC6需兼容模式且易注册表报错)
•运行库:VC++6.0原版+SP6+VisualAssistX(老版10.x)+BDEAdministrator(Borland共享组件)

-数据库支撑:DBC2000装完在BDEAdministrator建STANDARDAlias改名HeroDB,PATH指D:\MirServer\Mud2\DB,Ctrl+S保存,否则DBServer起不来
-路径规矩:D:\MirServer纯英文无空格,源码工程放D:\MirServer\Src或平行目录,避免长路径中文导致rc/dsp加载失败

五、编译顺序与常见报错
1.打开MirServer.dsw(或逐工程OpenWorkspace)
2.Build顺序建议:先编译公共库(如有Share/Common.dsp)→LoginGate→LoginSrv→DBServer→SelGate→RunGate→M2Server
3.典型报错:
•cannotopenincludefile'winsock2.h'→PlatformSDK缺失,VC6原盘补装或拷Include/Lib

•unresolvedexternalsymbol__imp__WSAStartup@8→Link里没加ws2_32.lib

-BDE相关Variant/BDE.hpp找不到→没装BorlandBDEShared,重装DBC2000选Typical
•errorLNK2001Debug/M2Server.exe:unreachablecode→老代码开了/Ox优化与debug混用,关优化选DisableOptimization

-断点打不中→必须在Debug配置RebuildAll,Release去调试信息

六、调试实战做法
•单进程调试:VC6→BuildStartDebug→Go,把LoginGate设为ActiveProject,命令行参数留空,断点打在MainWndProc的WM_COMMAND分支看登录包流转

-多进程联调:依次启动DBServer→LoginSrv→LoginGate→SelGate→M2Server→RunGate,M2挂VC6调试器,客户端用配套登录器连127.0.0.1:7000;想跟战斗逻辑就在M2的HandleAttack入口下断,配合OutputDebugString打玩家坐标/目标ID到DebugView
-数据校验:改StdItems.DB某件装备DC后,DBServer不重启只重读会不一致,调试时直接重启DBSvr;M2里HumanItem结构下断看内存布局(常用TItemStd结构:wIdxbDurabDuraMaxbShapewLooks…)
-地图阻挡排查:MapCell结构下断,打印(xy)的bFlag位,确认服务端和客户端.map版本一致

七、源码阅读切入点建议(按价值排序)
1.LoginGate.cpp→理解封包转发与IOCP雏形
2.M2Server的MapUnit/MapMgr→地图格子与寻路基底
3.MonsterAI/MonsterInfo→Race状态机与Monster.DB字段映射
4.FightSystem/CalcPhysDamage→早期数值公式朴素逻辑
5.ScriptEngine→#if/#act/#say文本指令分词与执行(MerChant/QuestDiary底层)
6.DBServer的HumDB读写→自定义格式角色存档字段偏移

八、启动时序与进程依赖(源码外运行时约束)
DBServer(起HeroDB连接)→LoginSrv(连DBServer)→LoginGate(连LoginSrv)→SelGate(连LoginSrv/DBServer)→M2Server(读Envir、Mir200\Map、Castle,监听RunGate回连)→RunGate(连M2指定端口)
任意前置没起,后续进程报“连接失败”而非崩溃,排错按这条链倒推。

九、老代码特征与改造注意
•大量全局变量(g_xMapMgr、g_HumanList、g_MonList)无命名空间,多线程改需加临界区

-字符串多用char[]/AnsiString,直接接UTF-8客户端必乱码,脚本文件必须ANSI
•无现代日志框架,靠Log\目录写文本+OutputDebugString

-想加新指令:在CM_xxx枚举加值→M2的Dispatch表注册Handle→客户端封包对齐,缺一环就断连

VC++6.0下的传奇2.0源码本质是一套“网关分流+逻辑集中+数据隔离”的MMORPG基线架构,编译跑通的关键不在代码多复杂,而在BDE/HeroDB、VC6SP6、纯英文路径、进程启动顺序这四件事同时对齐;读懂LoginGate的IOCP转发再进M2的战斗与脚本内核,整条链路就清楚了。
[顶部]