简介:BLUEM2源码.rar是一份基于Delphi开发的BLUEM2项目完整源码包,适合传奇类游戏服务端技术研究者、私服开发者和对M2引擎实现原理感兴趣的开发者。包内文件对应2018年9月18日的版本快照,可据此研究当时项目的模块划分与代码组织。压缩包共19426个文件,约680.28MB;文件类型以pas、dcu、dfm、res等Delphi工程文件为主,同时包含dpr、dpk、bdsproj等工程管理文件,以及rc、bmp、ico等资源定义与界面素材,能较为完整地呈现一套服务端程序的编译、构建与资源体系。资源已有1291人学习下载。通过阅读源码可梳理登录服务、网关、M2主程序之间的调用关系,理解BLUEM2在登录验证、地图逻辑、脚本触发等环节的具体实现,为二次开发或排错提供直接参考资料。
1. 拿到 BLUEM2 源码包之后:先搞清它到底是哪一层
做过游戏服务端的朋友看到“BLUEM2源码”这几个字,第一反应大概和我一样:这是不是又是一堆只能在某个古董操作系统上跑的 Delphi 工程?说实话,第一次打开这个压缩包的时候我也没抱太大期望,但把目录铺开之后发现,它比想象中完整——登录服务、角色服务、游戏逻辑服务、网关、数据库脚本、配置模板全都在里面,基本是一条能跑通的服务端链路,不是那种缺胳膊少腿的演示代码。这篇笔记就按我自己的拆包顺序来写:先讲清楚包里的结构和每一块的职责,再讲怎么编译、怎么配库、怎么启动,接着挑几个高频修改点做参数级拆解,最后列一下我在架设过程中踩过的坑。如果你正准备用这份源码搭一个本地测试环境,或者想基于它改点玩法逻辑,这篇应该能帮你省掉不少试错时间。
2. 源码包目录大盘点:从启动器到网关的逐模块解读
2.1 服务端主程序:登录、角色、游戏三个核心进程
把压缩包解开之后,第一件事别急着找编译器,先把目录结构过一遍。BLUEM2 这套源码延续了经典 M2 架构的三进程布局:登录服务(LoginSrv)、角色网关(DBSrv)、游戏逻辑服务(GameSrv/GEE)。三个进程各管一段,彼此通过内存共享或 Socket 通信协作。你在目录里会看到对应的工程文件,后缀一般是 .dpr 或 .bpr,这是 Delphi 工程的入口。
三个进程的分工是这样:
登录服务负责客户端版本校验和账号密码验证,连接的是账号库;角色网关管角色数据的读写,也就是进入选人界面之后的所有操作;游戏逻辑服务是核心中的核心,刷怪、爆率、NPC 对话、技能计算、装备属性全部在这里。值得注意的是,角色网关与游戏服务之间不是简单的直连,中间通常还隔了一个独立的通信层,目录里那个 Gateway 或 MirGate 相关的工程就是干这个的。
编译顺序有讲究,不能乱来。我一般是先把 DBSrv 编译出来,再编 GameSrv,最后编登录服务和网关。原因很简单:游戏逻辑服务在启动的时候会尝试连接角色网关的端口,如果网关没起来,游戏服务直接报错退出,你根本来不及看日志。这个顺序我在第一次架设时吃过大亏,后面不少“启动失败”的问题其实都是顺序不对导致的。
编译器版本这里多说一句。BLUEM2 的源码是老 Delphi 工程,用新版 RAD Studio 打开会出现一堆兼容性报错,常见的坑集中在 ZLib 单元路径、Indy 组件版本、以及第三方加密库的引用路径上。我自己的环境是 RAD Studio 10.4,虽然能编过,但中间折腾了差不多一个下午去调整库路径。如果你手头只有新版编译器,建议先把所有第三方组件目录加进 Library 搜索路径,再逐个处理报错。
2.2 数据库与配置部分:白名单、怪物、掉落从哪改
数据库这块,BLUEM2 这类型的老引擎用的不是 MySQL,而是 DBC 或 SQLite 这类嵌入式数据库。目录里你会看到一堆 .db 或 .dbc 结尾的文件,这些就是数据库本体。不要试图用 Navicat 直接打开它们,有些是加密的,有些是自定义格式,老老实实用源码自带的数据库工具去读。
配置文件集中在服务端根目录的 Ini 或 Config 子目录下。最关键的三个文件是:
游戏服务配置(GameSrv.ini 或类似命名)里能改的东西非常多:经验倍率、金币爆率、装备掉落概率、怪物刷新间隔、PK 惩罚系数、摆摊税率等等。每个参数后面通常都有注释,不过很多是老式 GBK 编码的注释,在简体中文系统上打开如果显示乱码,用记事本换一下编码就能解决。
白名单配置管的是 GM 账号和管理员权限。要把某个账号设为管理员,需要在数据库的账号表里加一条记录,或者在配置文件的特权列表里填账号名。这里有个容易踩的坑:有些版本的 BLUEM2 需要同时在数据库和配置里各写一遍,只改一处不生效,而且改完必须重启游戏服务,热加载是不存在的。
2.3 网关与加密通讯:客户端连接的第一道关卡
网关模块在整套架构里容易被忽视,但恰恰是它决定了客户端能不能连上来。网关的职责是地址转发和封包加解密,它监听外网端口,把客户端发来的数据解密后转发给游戏逻辑服务,再把响应加密发回客户端。
源码包里网关工程的配置项集中在端口绑定和密钥设置上。端口绑定这个参数要特别注意:网关端口、登录服务端口、游戏服务端口必须是三个不同的端口,否则启动时会有冲突提示。密钥设置则要和服务端保持一致,如果改了密钥而客户端那边没同步,表现就是客户端卡在“正在连接服务器”然后超时,日志里能看到一堆解密失败记录。
网关这块的调试技巧是开日志级别。把日志级别调到调试模式,可以看到每个连接的握手过程、加密算法版本、封包长度。我第一次排查连不上服务器的问题时,就是靠这个日志发现握手时密钥长度对不上,而不是端口被封。
3. 本地编译与架设:把源码跑起来的三步走
3.1 编译环境准备与库路径修正
这一步的细节决定了你能不能在半小时内把服务端拉起来。先把 RAD Studio 装好,我这边用的是 10.4 版本,装完之后把源码包里 ThirdParty 或 Components 目录下的组件全部安装或加入搜索路径。
打开 GameSrv 工程后,第一件事是检查项目选项里的 Delphi Compiler 搜索路径,看看有没有红色警告。红色警告一般意味着某个源文件找不到,最常见的是 ZLibEx.pas 和 DSchVcl.pas 这类第三方控件。把缺失路径补上之后,编译一次看看输出窗口。
这里有一个我在多个版本里反复验证过的规律:老源码最容易报错的地方是字符串类型不匹配和 ANSI/Unicode 混用问题。如果编译时报了一堆“E2033 Types of actual and formal var parameters must be identical”,不要慌,找到报错行,把 string 改成 AnsiString 基本就能过。批量替换的时候注意别全局替换,只处理报错文件的头部声明。
编译成功后会生成几个 exe,放在 Release 或 Output 目录下。我习惯把编译产物统一拷贝到一个干净的运行目录里,保持源码目录整洁,后面排查问题也方便。
3.2 数据库初始化与账号库配置
数据库初始化这一步很多人会跳过,但跳过之后启动必炸。BLUEM2 的数据库不是空的,里面预置了基础表结构,比如角色表、物品表、技能表、怪物表。但账号表默认是空的,需要你自己插入管理员账号。
数据库工具一般在源码包的 ServerTools 或 DB 目录下,是一个单独的管理端 exe。启动它,先连接数据库文件,然后在账号表里插入一条记录。为了节省时间,我直接写 SQL 完成这个操作。下面的语句是一个典型的初始化逻辑:
INSERT INTO Account (LoginID, Passwd, GMLevel, Status) VALUES ('admin', 'admin888', 10, 0);逻辑说明:往 Account 表里插入一条账号数据,LoginID 是登录名,Passwd 是密码明文,GMLevel 是权限等级,10 通常代表最高权限,Status 为 0 表示正常状态。这只是示例字段,实际字段名以你的数据库结构为准,执行前先用 SELECT 语句查一下表结构,别直接照抄。
参数说明:GMLevel 这个字段在不同版本里取值范围不一样,有的是 0-10,有的是 0-3。如果你发现插入后没有管理员权限,把这个值改成对应版本的最大值再试一次。密码字段很多版本支持明文存储,但也有加密存储的,加密的话就需要用管理端工具来创建账号,不能走 SQL 直插。
3.3 配置文件修改与启动顺序验证
数据库初始化完成后,进入配置文件修改环节。这一步需要改的核心配置项包括数据库路径、网关地址、端口号、日志级别。数据库路径必须写绝对路径,或者保证服务端 exe 和数据文件在同一个目录下,否则会提示“无法打开数据库”。
我把一套常见的配置模板整理一下,配合启动流程来理解:
[DataBase] ; 数据库文件路径,相对路径基于服务端exe所在目录 DBName=.\Data\GameData.db DBSrvPort=5010 [Network] ; 游戏逻辑服务监听端口 GamePort=7000 ; 网关连接端口 GatePort=7100 [Log] LogLevel=1 LogSave=1逻辑说明:DBName 指定数据库文件位置;DBSrvPort 是角色网关的通信端口;GamePort 是游戏逻辑服务对外端口;GatePort 是网关模块的转发端口;LogLevel 设为 1 表示输出调试级别日志,排错阶段建议开着,稳定后可以调回 0 减少日志量。
参数说明:端口号不要和系统常用端口冲突,比如 7000 和 7100 本身没问题,但如果你本机跑了其他服务占用了这两个端口,启动时会报 bind 失败。改端口之后记得同步修改客户端配置或登录器配置,否则客户端连不上。
启动顺序我建议按这个流程走:
# 1. 启动角色网关(数据库服务) ./DBSrv.exe # 2. 启动游戏逻辑服务 ./GameSrv.exe # 3. 启动登录服务 ./LoginSrv.exe # 4. 启动网关 ./Gateway.exe每一步启动后看一眼进程窗口,有没有报错弹窗。如果 GameSrv 闪退,多半是连不上 DBSrv 的端口,检查防火墙和 IP 配置;如果 Gateway 报错,一般是配置文件里的端口没对上。全部启动后,再用客户端测试登录,这时重点看网关进程的窗口输出,它会显示客户端的连接建立和断开记录。
4. 核心逻辑改哪些:从刷怪、爆率到装备强化的参数位
4.1 刷怪配置与怪物 AI 行为参数
服务端跑起来之后,大部分人的第一个需求是改刷怪规则。刷怪配置一般不在数据库里,而是在 MapInfo 或 MonGen 这样的文本脚本文件里。打开这个文件,你会看到一行行这样的记录:
; 地图ID,X坐标,Y坐标,怪物ID,数量,刷新间隔(秒),范围半径 3, 120, 80, 1001, 10, 60, 5逻辑说明:这条记录的含义是在地图 3 的 (120,80) 坐标附近,每隔 60 秒刷新 10 只 ID 为 1001 的怪物,刷新点随机散布在以该坐标为中心、半径 5 格的范围内。最后一列范围半径会影响刷怪的散布密度,太小会导致怪物重叠在同一格,太大会刷到墙里面去。
参数说明:刷新间隔以秒为单位,改成 10 就是 10 秒一波,刷太快会让服务器压力比较大;数量一列控制在 20 以内比较合理,大量怪物同时刷出会带来寻路计算开销。修改完配置文件,需要重启游戏服务或者用控制台命令执行重载,BLUEM2 部分版本支持 GM 命令在线重载刷怪配置,但建议还是重启一次干净利落。
怪物 AI 行为参数通常不在这里,而是在数据库的怪物表里,字段包括攻击类型、攻击速度、移动速度、视野范围、仇恨范围、技能列表等。这里不展开细说,只提醒一点:视野范围和仇恨范围是两个概念,视野范围决定怪物能否看到你,仇恨范围决定看到你之后追多远放弃。很多改怪的人只调了移动速度,没调仇恨范围,导致怪物追到地图边缘就回头,非常出戏。
4.2 爆率与掉落表的常见改法
掉落系统是另一个高频修改点。BLUEM2 的掉落规则一般由两个部分组成:掉落概率和掉落列表。掉落列表文件里定义的是“这个怪物死了之后可能掉哪些东西、每种东西的权重和数量”。打开掉落文件,记录大概是这样的结构:
; 怪物ID,物品ID,最低数量,最高数量,权重 1001, 20001, 1, 3, 100 1001, 20002, 1, 1, 10 1001, 20003, 1, 1, 5逻辑说明:这个例子的含义是怪物 1001 死亡之后,按照权重比例从三条记录里抽取掉落。第一行权重 100,表示每次掉落时最有可能掉的是 20001 这个物品,数量在 1-3 之间随机;第二行权重 10,表示掉落稀有物品 20002 的概率约为 100/(100+10+5),约 87% 对应第一项,约 8.7% 对应第二项,约 4.3% 对应第三项。
参数说明:这个权重模型是相对概率而非绝对概率,所以想调整某个物品的爆率,要么改它的权重,要么改其他物品的权重来挤占概率空间。还有一种掉落表是按绝对概率设计的,即权重字段直接等于百分数,这种情况下各条记录的概率之和不能超过 100,否则后面记录永远不触发。拿到掉落文件先看一眼注释说明,确认是哪种模型再动手。
装备掉落这边有个容易被忽略的地方——极品属性生成规则。简单来说,同一件装备掉出来之后的附加属性是随机生成的,生成规则和概率在掉落配置或者装备配置里单独定义。如果你发现爆率调高之后满屏幕都是白板装备,那不是掉率没生效,而是极品生成概率太低。
4.3 装备强化与附加属性的配置入口
装备强化是 M2 引擎里一个比较有辨识度的玩法模块,BLUEM2 的实现方式是给物品表增加强化等级字段,并在服务端逻辑里定义每一级强化对属性的影响。改这个模块有两种路子:改数值模板和改逻辑代码。
数值模板在数据库的 EquipUpgrade 或 Strenthen 配置里,每一行定义了强化等级、成功率、失败惩罚、属性加成。想调整老板键成功率,直接改成功率字段即可。而逻辑代码的修改就复杂一些,牵扯到客户端和服务端的协议同步,改完之后客户端可能显示不了新加的属性条。
这里我通常会采取一种相对稳妥的做法:先改成功率,再改属性成长曲线。成功率字段直观,属性成长曲线决定强化到后期会不会数值崩坏。举例来说,原始配置里+10 的属性加成是+1 的两倍,如果你想拉长养成线,可以把成长曲线改成递增型,让每一级的加成逐步变大而不是线性翻倍。
改完这些配置后,需要清理客户端缓存。这可能是最玄学的一环——客户端会缓存一部分物品静态数据,服务端改了属性而不更新客户端,看到的还是旧数值。我的处理方式是清掉客户端目录下的补丁缓存文件,强制重新拉取一遍数据。
5. 架设和修改中的常见坑:现象、原因与对策
5.1 角色网关启动失败,提示“无法加载数据库”
现象:双击 DBSrv.exe 后闪退,或在控制台里看到数据库加载失败的红色报错。
原因:数据库路径配置错误。BLUEM2 的数据库路径有个特点,它把相对路径和绝对路径混着用,你配置文件里写的是相对路径 ./Data/GameData.db,但 exe 实际工作目录可能不在服务端根目录,导致找不到文件。另外有些版本对数据库文件有隐藏校验,文件被复制过或在传输过程中改过字节,就会报错。
解决:把数据库路径改成绝对路径,同时把数据库文件放在和 exe 同级的 Data 目录下。如果改完还报错,用二进制比较工具检查一下数据库文件和原始备份是否一致,不一致就重新解压原始文件覆盖。
5.2 游戏服务启动后自动断线,日志提示“Socket error”
现象:GameSrv 进程存活,但运行几十秒后报 Socket 错误,连接全部断开。
原因:网关和游戏服务的通信密钥不一致。BLUEM2 的网关与游戏逻辑服务之间有一段简单的加密握手,密钥写死在网关配置和游戏服务配置里,只有两者一致才能建立长连接。你在改配置文件时不小心只改了一边,就会反复握手失败。
解决:把网关配置里的 Key 字段和游戏服务配置里的 Key 字段设置成完全一致的值,重启网关和 GameSrv。这里值得多说一句:密钥不要用纯数字和纯字母,有些版本会做弱密钥检查,太弱的密钥直接拒绝启动。
5.3 怪物刷不出来,但查数据库里确实有数据
现象:Ini 里刷怪配置正确,数据库怪物表也有对应 ID 的记录,但地图上死活不见怪。
原因:地图坐标越界或落点在地图阻挡区域。很多地图的地表数据里包含不可行走标记,刷怪脚本把落点写在了阻挡格上,怪物一刷新出来就被寻路系统判死,或者直接进入了休眠状态。
解决:在配置里把范围半径调大一些,或者把坐标换到空旷区域验证一下。用 GM 命令或调试工具读取当前坐标的地表标记,确认不是阻挡格后再批量修改旧的刷怪点。
5.4 客户端连接时卡在“正在连接”,网关无日志
现象:客户端一直处于连接中状态,网关窗口没有任何新的连接记录。
原因:端口不通或网关监听地址绑定错误。BLUEM2 默认监听 0.0.0.0,但如果你在配置文件里写了 127.0.0.1,同一台机器本机连没问题,局域网其他机器就完全连不上。还有一种情况是系统防火墙拦截了网关端口的入站连接。
解决:先确认配置文件里监听地址是 0.0.0.0,再检查防火墙入站规则。最简单的验证方式是在另一台机器上 telnet 一下网关端口,能通再找其他原因。
5.5 修改爆率后不生效,重启也不行
现象:改了掉落文件的权重,重启服务端之后打怪掉的东西和原来一模一样。
原因:掉落数据被数据库二次覆盖。BLUEM2 的读取逻辑是先读配置文件,再读数据库里的覆盖项,如果数据库里存在同名配置或更高优先级的掉落表,文件里的修改就完全不生效。这个行为不是所有版本都有,但确实存在。
解决:先查出实际生效的掉落记录在数据库里还是文件里。一个排查办法是把文件里的权重改成一个极端值,比如 99999,重启后如果掉落变化明显,说明文件生效;没变化就去数据库的掉落表里直接 UPDATE 对应记录。
UPDATE DropList SET Weight = 500 WHERE MonsterID = 1001 AND ItemID = 20002;逻辑说明:直接修改数据库中的掉落权重记录,把怪物 1001 掉落物品 20002 的权重改为 500。这样能绕过配置文件的二次覆盖问题,直接作用于实际生效的数据源。
参数说明:执行前先用 SELECT 确认记录存在,如果查出来有多条记录,说明同一个怪物绑定了多条掉落规则,需要全量更新或按 ItemID 精确匹配。改完记得重启游戏服务,热加载掉落表在很多版本里并不真正生效。
6. 修改逻辑后的验证手法:编译期和运行期的两套验证
服务端改完代码逻辑之后,最怕的就是看着能编译过,运行起来数据不对。我习惯准备两套验证思路:静态层和动态层。
静态层验证在编译之后做,重点查协议结构体有没有改动。BLUEM2 的客户端和服务端共享一套封包结构,你在服务端改了消息定义,客户端没同步的话,轻则功能不可用,重则直接闪退。改完逻辑代码之后,打开客户端源码里的对应协议文件,逐字段比对偏移量。这条是血泪经验,有一回我调了一个装备附加属性的读取顺序,服务端没问题,客户端显示的属性全乱套了,最后定位到就是字段顺序不一致。
动态层验证是启动服务端后通过 GM 命令和日志线程来查。先开调试日志,再执行相关操作(比如刷一只特定怪物、呼出一个装备),观察日志里的关键输出节点。这里有个技巧——在逻辑代码里加临时输出,把关键变量的值打到日志里,看是否和预期一致。改完之后记得删掉这些临时调试代码,不然上线之后日志量会很大。
最后一个习惯分享给你:每次改配置或改代码之前,先把正在使用的版本做一份备份。压缩包就几十 MB,不占空间,但能省下无数后悔药的时间。我后来形成了一个固定的工作流:解压拿到源码后立刻打一个 clean 备份;每完成一个修改点且验证通过后,打一个 step 备份;最后把所有修改整理成 patch 说明文档,和源码包放在一起。从那以后,每次改翻车了都能快速回到上一个可用状态,不用从头再猜一遍,希望这些方法能帮你少走一些弯路。
本文还有配套的精品资源,点击获取