魔兽世界私服Trinity,从源码开始

缘起因由

在一个无所事事的周末下午,突然想起魔兽世界,官方的账号很久没有上了,里面的大小号现在连满级都不是。以前曾经搭过传奇和星际争霸战网的私服自娱自乐,也听说过魔兽世界有开源的服务端模拟,既然兴致来了就小小的研究一下。

目前魔兽世界的私服比较流行的是MaNGOS和Trinity,二者都是模拟魔兽世界服务端。MaNGOS“号称”是一个研究型项目,目的是为了学习大规模的C++项目开发,有道理,不过我不信。Trinity是基于MaNGOS的代码开发的,以前主要是为了合并用户提交的补丁代码而设立的一个项目,不过现在已经单独独立出来了,主要开发成员包括以前MaNGOS的一些老人,现在的主要工作包括清理代码、优化、提供一个更好的服务端内核。

二者现在的代码提交和更新都很频繁,但是具体是否会合并对方的代码就不清楚了。总而言之,也就是说,我感觉Trinity大概也许应该是目前最好的一个魔兽世界服务端模拟了。作为一个程序员来说,玩游戏还在其次,看看代码才是件有意思的事情。整个过程记录在案 http://log4think.com/setup_wow_private_server,以便事后查询。

现在尝试一下从源码开始搭个魔兽世界的服务器,从源码开始主要还是想顺便看看代码的情况,基于Trinity来做。至于客户端的情况,截止到2011年6月12日,中国国服魔兽世界最新的版本是3.3.5 13930-巫妖王之怒。

安装基本工具

安装之前,需要准备几个要使用到的工具软件,用来下载、编译等等。

**版本控制工具 Git ** 由于 MaNGOS 和 Trinity 都是托管在 GitHub 上,所以得用 Git 才能下到源码:

编译工具和库

运行环境:

以下二者按需选择其一

以下非必需

生成项目文件

各个工具都下载、安装完毕(具体细节可Google之,不赘述了),准备工作做完之后,开始下代码编译。

  1. 建一个目录,譬如 D:\workspace\trinity

  2. 进入这个目录,右键 Git Clone... ,Url那里填入 https://github.com/TrinityCore/TrinityCore.git, 点OK。不喜欢图形化工具的可以直接进到新建的目录里面,命令行上运行 git clone https://github.com/TrinityCore/TrinityCore.git 。 会自动建立一个名为 TrinityCore 的源码目录,然后就是等着代码下完。

  3. 在 D:\workspace\trinity 下建一个目录是Build等下放编译结果文件
  4. 运行CMake的图形化工具(开始菜单里 CMake 下的 CMake (cmake-gui))
  5. 点 Browse Source... , 选 D:\workspace\trinity\TrinityCore
  6. Browse Build... ,选 D:\workspace\trinity\Build
  7. 点 Configure ,出一个对话框
  8. 确保勾选了 Use default native compilers,下拉框里面选 Visual Studio 10,至于是32位还是64位版本的,根据自己的情况选
  9. 点Finish,CMake 工具会搜索源码配置,分析出一些编译选项来。确保 cmake-gui 下面的信息提示里面没有 ERROR 字样,否则根据具体错误修正后重来。
    1. 在 cmake-gui 上面的编译选项里面选中 SCRIPTS、SERVERS、TOOLS、USE_COREPCH、USE_SCRIPTPCH ,不要选 USE_MYSQL_SOURCES 。
    2. 最后点 Generate , CMake 会在 D:\workspace\trinity\Build 下面生成 Visual Stdio 2010 的项目文件。

配置完成后,我的是这样:

enter image description here

可能出现的问题: 1. 第10步里面_GIT_EXEC应该是msysgit中git的绝对路径,如果没有则是msysgit安装的时候没有把自己加到系统路径里面去 2. 如果下面出现红色的ERROR提示,类似于

Could not copy from: D:/dev/cmake/share/cmake-2.8/Templates/CMakeVSMacros2.vsmacros to: C:/Documents and Settings/Administrator/ÎÒµÄÎĵµ/Visual Studio 2010/Projects/VSMacros80/CMakeMacros/CMakeVSMacros2.vsmacros

这个好像是因为 CMake 无法识别中文路径,把“我的文档”的位置改一下吧,改成路径不带中文的。或者直接自己把提示中的 CMak>eVSMacros2.vsmacros 拷到“我的文档”下的 Visual Studio 2010/Projects/VSMacros80/CMakeMacros/ 。

编译源码

注意以下几点:

  1. 如果你的魔兽世界客户端是3.3.5 13930,那么记得给代码打个认证补丁以支持13930,具体请参考另一篇文章 wow_3-3-5_13930_auth_patch
  2. 在 Visual Studio 里面打开 D:\workspace\trinity\Build\TrinityCore.sln ,先Build -> Clean Solution,然后Build -> Build Solution
  3. 默认是生成 Debug ,结果在 D:\Build\bin\Debug下面,从 MySQL 的安装目录下的Lib目录里面拷一个 libmySQL.dll 到这个目录下, libeay32.dll 和 ssleay32.dll 是 OpenSSL 的,应该默认加到系统路径下了,如果后面提示找不到就从 OpenSSL 的安装目录里面拷过来。



安装数据库

简短截说:

  1. 从 https://github.com/TrinityCore/TrinityCore/downloads 下载最新的(或者符合你的客户端版本号的)魔兽世界数据文件,
  2. 用MySQL图形化工具,导入 D:\workspace\trinity\TrinityCore\sql\create\create_mysql.sql 执行建立三个数据库

    auth 数据库中导入 D:\workspace\trinity\TrinityCore\sql\base\auth_database.sql 执行, characte 数据库中导入 D:\workspace\trinity\TrinityCore\sql\base\character_database.sql 执行, world 数据库中导入第一步中下载的 TDB_full_???.sql 文件执行, 最终建立 auth、character、world 三个数据库。

生成地图文件

  1. 在D:\Build\bin\Debug下面建一个makevmaps3_simple.bat文件,内容为

    vmap3extractor.exe
    md vmaps
    vmap3assembler.exe Buildings vmaps
    
    pause
    

    保存运行,会从魔兽世界的客户端目录里面解压缩服务端需要的地图出来。根据机器速度不同,大概需要20分钟到一个小时的时间。运行结束的时候会给个提示"Press any key...",按任意键结束。生成 vmaps 和 buildings 目录, buildings 目录无用可以删除。

  2. 假设魔兽世界的客户端目录在 D:\WOW 下面,在 D:\Build\bin\Debug 下运行

    mapextractor.exe -i "d:\WOW"
    

    这样会生成 maps 和 dbc 目录。这个工具会根据客户端的雨中在 dbc 目录下生成不同的 dbc 语言版本。如果是中文的客户端,会提取出中文的 dbc 数据。

配置服务器

  1. 在 D:\Build\bin\Debug 下有 worldserver.conf.dist 和 authserver.conf.dist 两个文件,分别是游戏服务器和认证服务器的配置模板文件。
  2. 复制一份 worldserver.conf.dist 并改名为 worldserver.conf ,配置游戏服务器

    LoginDatabaseInfo = "127.0.0.1;3306;root;trinity;auth"
    WorldDatabaseInfo = "127.0.0.1;3306;root;trinity;world"
    CharacterDatabaseInfo = "127.0.0.1;3306;root;trinity;characters"
    

    分别是认证数据库、世界数据库、玩家角色数据库的地址, root 后面的 trinity 是 MySQL 中 root 的密码,改成你在安装 MySQL 时设置 root 密码。

    之前生成了 vmap 文件,这个是地图的相关数据,服务器可以根据这个来判断怪物和玩家之间是否可见(是否有墙,是否在建筑物的同一层上)。没有这个的话,怪物会穿墙打你,或者从楼下直接漂上来打你... 服务器配置这里默认情况下是开启 vmap 数据检测的。如果不想开启 vmap 检测,则将下面这些配置的值改成0

    vmap.enableLOS = 1
    vmap.enableHeight = 1
    vmap.petLOS = 1
    vmap.enableIndoorCheck = 1
    DetectPosCollision = 1
    
  3. 复制一份 authserver.conf.dist 并改名为 authserver.conf ,配置认证服务器

    LoginDatabaseInfo = "127.0.0.1;3306;root;trinity;auth"
    

    同样,把 trinity 改成 MySQL 的 root 密码。

  4. 检查数据库 auth 里面 realmlist 表里面的记录,记录中 port 的值应该和 worldserver.conf 里面的 WorldServerPort = 8085 这一项的值一样(这里是8085)。同时, gamebuild 的值应该和你客户端的版本号是一致的(登陆界面右下角,当前最新的是 13930)。如果realmlist里面没有记录,则应该加一条。

修改客户端配置

客户端默认是去登陆官方服务器,需要修改一下地址改成让客户端登陆我们自己架设的游戏服务器。假设魔兽世界客户端安装在 D:\WOW 下面,到 D:\WOW\Data\zhCN 下面,备份 realmlist.wtf 文件。该文件原来的内容是

    set realmList cn.logon.warcraftchina.com
    set patchlist cn.version.warcraftchina.com
    set realmlistbn ""
    set portal cn

将其内容改成

    SET realmlist "127.0.0.1"
    SET patchlist "127.0.0.1"

注册用户账号

客户端后登录会发现没有账号可用,注册账号的办法有两种:

  1. 第一种方法是通过SQL语句直接在数据库里面加

    INSERT INTO account
    (username, sha_pass_hash, email)
    VALUES
    ('用户名',SHA1(CONCAT(UPPER('用户名'),':',UPPER('密码'))), '邮件地址')
    

    替换命令中的 用户名、密码、邮件地址 即可。

  2. 第二种方法最简单,后面启动游戏服务器worldserver之后,在这个命令窗口可以输入GM命令:

    create account 用户名 密码
    

启动游戏

  1. 运行D:\Build\bin\Debug\authserver.exe
  2. 运行D:\Build\bin\Debug\worldserver.exe
  3. 运行客户端wow.exe

如果运气好的话... 反正我运气不错...

相关的可能还需要一些配置和改动,不过目前我的这个版本能够正常运行,其它的未来再写吧。在此之前,至少可以先研究下源代码...

如何和朋友一起玩

如果想配个私服和朋友一起玩,那么需要一个公网 IP 地址。机房里面没有服务器没有关系,可以搭在自己家里的服务器上,然后去 ip138 上查到自己的IP地址,把 127.0.0.1 相关的地址都改成自己的IP地址就可以了。如果是通过ADSL路由上的网,去ADSL路由配置里面把自己的内外IP地址设置为DMZ主机地址开放给外网即可。

此外,如果是跑服务端的服务器有花生壳的动态域名或者自己的域名(比如我的 http://log4think.com),可以将 127.0.0.1 改成自己的域名。前面在 wowserver 和 authserver 中的地址中配置的 127.0.0.1 都要改,因为服务端要提供这个地址给客户端。 MySQL 相关的 127.0.0.1 地址不用改。非要改也可以,不过就是还得去配MySQL的外网访问的相关安全设置。

同时,如果是要搭在公网上对外提供服务,建议单独找个机器做 auth 服务器(配置不用太好),不同的游戏区跑在不同的服务器上(这个配置要好一点),每个服务器上都要跑worldserver。把服务器列表加到 auth 数据库里面的 realmlist 表里就是。

友情提示:提供公网服务小心被告。

相关的几个小问题:

  1. 连接服务器断开的话,到这里下个补丁覆盖安装。
  2. 登入后没有服务器列表的话,看看客户端的版本号(登陆界面的右下角),然后把auth数据库realmlist表里面的记录最后一项gamebuild改为看到的版本号(比如13930) 。

开发调试

既然是从源码编译的,因此如果中间出了任何问题都是可以通过调试的方式去解决的。调试方法很简单,几个简单的手段 1. 抓包,分析数据记录 2. 启动编译好的程序,开 Visual Studio ,附加到该进程上,下断点跟踪 3. 进入游戏,进行操作,Visual Studio 中如果下了正确的断点,就会在相关的位置停下

退而求其次

如果你觉得以上太复杂搞不定,如果只是想自己随便玩一下而已,那么可以下个别人做好的包,比如 TCCN-3.3.5-Trinity8400.exe ,安装好启动 web 服务器和 wow 服务器,注册个账号就可以进去玩了,简单的无需解释了。不过这个有人数限制,具体限制多少人我也不清楚,总之做公网服务是没戏的。

参考资料

二者的一些相关网站列举如下:

本站后续相关文章可以在 http://log4think.com/category/practice/fun/wow-trinity/ 找到

本文全文参考Trinity官方文档 http://www.trinitycore.info/How-to:Win

魔兽世界3.3.5 13930登录数据包分析

官方的Trinity认证服务器在对3.3.5 13930客户端登陆的时候有问题,下面这个是抓的一个能够正常登陆的私服认证服务器的数据包。
使用工具WPE抓的包,这个也是经常用来做游戏外挂的一个抓包工具。相关的项目是TrinityCore的authserver,之前的一篇Blog有关于如何下载代码的说明。

服务器端口配置情况说明如下
3306 MySQL
3724 认证服务器
10775 客户端与认证服务器通信的端口
10740 认证服务器与MySQL通信的端口

客户端登陆使用用户名passos,认证服务器、MySQL、客户端都在本地运行。数据包记录中加粗的是客户端与认证服务器的相关通信数据包。

1 127.0.0.1:10775 127.0.0.1:3724 40 Recv

0000  00 08 24 00 57 6F 57 00 03 03 05 6A 36 36 38 78    ..$.WoW....j668x
0010  00 6E 69 57 00 4E 43 68 7A E0 01 00 00 7F 00 00    .niW.NChz.......
0020  01 06 50 41 53 53 4F 53                            ..PASSOS

认证服务器接收到客户端发来的来源ip地址和用户名,以及客户端的一些信息
报文结构在AuthSocket.h的sAuthLogonChallenge_C,处理过程位于AuthSocket.cpp的AuthSocket::_HandleLogonChallenge()

2 127.0.0.1:10740 127.0.0.1:3306 51 Send

0000  2F 00 00 00 03 53 45 4C 45 43 54 20 2A 20 46 52    /....SELECT * FR
0010  4F 4D 20 69 70 5F 62 61 6E 6E 65 64 20 57 48 45    OM ip_banned WHE
0020  52 45 20 69 70 20 3D 20 27 31 32 37 2E 30 2E 30    RE ip = '127.0.0
0030  2E 31 27                                           .1'

认证服务器从MySQL中查询客户端ip是否被封

3 127.0.0.1:3306 127.0.0.1:10740 343 Recv

0000  01 00 00 01 05 32 00 00 02 03 64 65 66 06 72 65    .....2....def.re
0010  61 6C 6D 64 09 69 70 5F 62 61 6E 6E 65 64 09 69    almd.ip_banned.i
0020  70 5F 62 61 6E 6E 65 64 02 69 70 02 69 70 0C 21    p_banned.ip.ip.!
0030  00 60 00 00 00 FD 03 40 00 00 00 3C 00 00 03 03    .`.....@...<....
0040  64 65 66 06 72 65 61 6C 6D 64 09 69 70 5F 62 61    def.realmd.ip_ba
0050  6E 6E 65 64 09 69 70 5F 62 61 6E 6E 65 64 07 62    nned.ip_banned.b
0060  61 6E 64 61 74 65 07 62 61 6E 64 61 74 65 0C 3F    andate.bandate.?
0070  00 28 00 00 00 08 03 50 00 00 00 40 00 00 04 03    .(.....P...@....
0080  64 65 66 06 72 65 61 6C 6D 64 09 69 70 5F 62 61    def.realmd.ip_ba
0090  6E 6E 65 64 09 69 70 5F 62 61 6E 6E 65 64 09 75    nned.ip_banned.u
00A0  6E 62 61 6E 64 61 74 65 09 75 6E 62 61 6E 64 61    nbandate.unbanda
00B0  74 65 0C 3F 00 28 00 00 00 08 01 10 00 00 00 3E    te.?.(.........>
00C0  00 00 05 03 64 65 66 06 72 65 61 6C 6D 64 09 69    ....def.realmd.i
00D0  70 5F 62 61 6E 6E 65 64 09 69 70 5F 62 61 6E 6E    p_banned.ip_bann
00E0  65 64 08 62 61 6E 6E 65 64 62 79 08 62 61 6E 6E    ed.bannedby.bann
00F0  65 64 62 79 0C 21 00 96 00 00 00 FD 01 00 00 00    edby.!..........
0100  00 40 00 00 06 03 64 65 66 06 72 65 61 6C 6D 64    .@....def.realmd
0110  09 69 70 5F 62 61 6E 6E 65 64 09 69 70 5F 62 61    .ip_banned.ip_ba
0120  6E 6E 65 64 09 62 61 6E 72 65 61 73 6F 6E 09 62    nned.banreason.b
0130  61 6E 72 65 61 73 6F 6E 0C 21 00 FD 02 00 00 FD    anreason.!......
0140  01 00 00 00 00 05 00 00 07 FE 00 00 02 00 05 00    ................
0150  00 08 FE 00 00 02 00                               .......

MySQL返回的数据

4 127.0.0.1:10740 127.0.0.1:3306 83 Send

0000  4F 00 00 00 03 44 45 4C 45 54 45 20 46 52 4F 4D    O....DELETE FROM
0010  20 69 70 5F 62 61 6E 6E 65 64 20 57 48 45 52 45     ip_banned WHERE
0020  20 75 6E 62 61 6E 64 61 74 65 3C 3D 55 4E 49 58     unbandate<=UNIX
0030  5F 54 49 4D 45 53 54 41 4D 50 28 29 20 41 4E 44    _TIMESTAMP() AND
0040  20 75 6E 62 61 6E 64 61 74 65 3C 3E 62 61 6E 64     unbandate<>band
0050  61 74 65                                           ate

如果ip封锁已过期,解除封锁。

5 127.0.0.1:3306 127.0.0.1:10740 11 Recv

0000  07 00 00 01 00 00 00 22 00 00 00                   ......."...

MySQL返回的数据

6 127.0.0.1:10740 127.0.0.1:3306 159 Send

0000  9B 00 00 00 03 53 45 4C 45 43 54 20 61 2E 73 68    .....SELECT a.sh
0010  61 5F 70 61 73 73 5F 68 61 73 68 2C 61 2E 69 64    a_pass_hash,a.id
0020  2C 61 2E 6C 6F 63 6B 65 64 2C 61 2E 6C 61 73 74    ,a.locked,a.last
0030  5F 69 70 2C 61 61 2E 67 6D 6C 65 76 65 6C 2C 61    _ip,aa.gmlevel,a
0040  2E 76 2C 61 2E 73 20 46 52 4F 4D 20 61 63 63 6F    .v,a.s FROM acco
0050  75 6E 74 20 61 20 4C 45 46 54 20 4A 4F 49 4E 20    unt a LEFT JOIN
0060  61 63 63 6F 75 6E 74 5F 61 63 63 65 73 73 20 61    account_access a
0070  61 20 4F 4E 20 28 61 2E 69 64 20 3D 20 61 61 2E    a ON (a.id = aa.
0080  69 64 29 20 57 48 45 52 45 20 61 2E 75 73 65 72    id) WHERE a.user
0090  6E 61 6D 65 20 3D 20 27 50 41 53 53 4F 53 27       name = 'PASSOS'

认证服务器从MySQL数据库中取帐号相关信息

7 127.0.0.1:3306 127.0.0.1:10740 577 Recv

0000  01 00 00 01 07 3E 00 00 02 03 64 65 66 06 72 65    .....>....def.re
0010  61 6C 6D 64 01 61 07 61 63 63 6F 75 6E 74 0D 73    almd.a.account.s
0020  68 61 5F 70 61 73 73 5F 68 61 73 68 0D 73 68 61    ha_pass_hash.sha
0030  5F 70 61 73 73 5F 68 61 73 68 0C 21 00 78 00 00    _pass_hash.!.x..
0040  00 FD 01 00 00 00 00 28 00 00 03 03 64 65 66 06    .......(....def.
0050  72 65 61 6C 6D 64 01 61 07 61 63 63 6F 75 6E 74    realmd.a.account
0060  02 69 64 02 69 64 0C 3F 00 0B 00 00 00 03 23 42    .id.id.?......#B
0070  00 00 00 30 00 00 04 03 64 65 66 06 72 65 61 6C    ...0....def.real
0080  6D 64 01 61 07 61 63 63 6F 75 6E 74 06 6C 6F 63    md.a.account.loc
0090  6B 65 64 06 6C 6F 63 6B 65 64 0C 3F 00 03 00 00    ked.locked.?....
00A0  00 01 21 00 00 00 00 32 00 00 05 03 64 65 66 06    ..!....2....def.
00B0  72 65 61 6C 6D 64 01 61 07 61 63 63 6F 75 6E 74    realmd.a.account
00C0  07 6C 61 73 74 5F 69 70 07 6C 61 73 74 5F 69 70    .last_ip.last_ip
00D0  0C 21 00 5A 00 00 00 FD 01 00 00 00 00 3A 00 00    .!.Z.........:..
00E0  06 03 64 65 66 06 72 65 61 6C 6D 64 02 61 61 0E    ..def.realmd.aa.
00F0  61 63 63 6F 75 6E 74 5F 61 63 63 65 73 73 07 67    account_access.g
0100  6D 6C 65 76 65 6C 07 67 6D 6C 65 76 65 6C 0C 3F    mlevel.gmlevel.?
0110  00 03 00 00 00 01 21 10 00 00 00 26 00 00 07 03    ......!....&....
0120  64 65 66 06 72 65 61 6C 6D 64 01 61 07 61 63 63    def.realmd.a.acc
0130  6F 75 6E 74 01 76 01 76 0C 21 00 FD FF FF FF FC    ount.v.v.!......
0140  10 00 00 00 00 26 00 00 08 03 64 65 66 06 72 65    .....&....def.re
0150  61 6C 6D 64 01 61 07 61 63 63 6F 75 6E 74 01 73    almd.a.account.s
0160  01 73 0C 21 00 FD FF FF FF FC 10 00 00 00 00 05    .s.!............
0170  00 00 09 FE 00 00 02 00 BC 00 00 0A 28 65 63 38    ............(ec8
0180  37 31 63 61 62 61 65 66 37 65 36 39 36 38 35 65    71cabaef7e69685e
0190  65 39 34 35 38 39 30 36 39 37 62 66 35 63 33 64    e945890697bf5c3d
01A0  39 30 34 39 34 02 31 31 01 30 09 31 32 37 2E 30    90494.11.0.127.0
01B0  2E 30 2E 31 01 33 40 36 31 34 38 45 31 46 42 35    .0.1.3@6148E1FB5
01C0  33 43 38 38 34 46 37 43 37 34 37 38 39 39 43 35    3C884F7C747899C5
01D0  31 46 43 38 30 36 46 43 43 46 41 30 46 36 43 33    1FC806FCCFA0F6C3
01E0  34 36 33 46 35 42 41 45 33 37 43 46 32 33 35 39    463F5BAE37CF2359
01F0  44 38 33 30 46 32 38 40 42 37 45 35 37 33 32 31    D830F28@B7E57321
0200  33 43 44 34 30 44 34 31 32 43 44 46 44 35 42 41    3CD40D412CDFD5BA
0210  39 37 41 43 30 42 45 31 37 39 38 34 32 45 37 42    97AC0BE179842E7B
0220  43 43 35 45 32 43 45 44 30 30 43 44 46 31 31 35    CC5E2CED00CDF115
0230  35 41 31 32 35 39 43 46 05 00 00 0B FE 00 00 02    5A1259CF........
0240  00                                                 .

MYSQL返回的数据

8 127.0.0.1:10740 127.0.0.1:3306 78 Send

0000  4A 00 00 00 03 53 45 4C 45 43 54 20 62 61 6E 64    J....SELECT band
0010  61 74 65 2C 75 6E 62 61 6E 64 61 74 65 20 46 52    ate,unbandate FR
0020  4F 4D 20 61 63 63 6F 75 6E 74 5F 62 61 6E 6E 65    OM account_banne
0030  64 20 57 48 45 52 45 20 69 64 20 3D 20 31 31 20    d WHERE id = 11
0040  41 4E 44 20 61 63 74 69 76 65 20 3D 20 31          AND active = 1

认证服务器从MySQL查找帐号是否被封

9 127.0.0.1:3306 127.0.0.1:10740 175 Recv

0000  01 00 00 01 02 46 00 00 02 03 64 65 66 06 72 65    .....F....def.re
0010  61 6C 6D 64 0E 61 63 63 6F 75 6E 74 5F 62 61 6E    almd.account_ban
0020  6E 65 64 0E 61 63 63 6F 75 6E 74 5F 62 61 6E 6E    ned.account_bann
0030  65 64 07 62 61 6E 64 61 74 65 07 62 61 6E 64 61    ed.bandate.banda
0040  74 65 0C 3F 00 28 00 00 00 08 03 40 00 00 00 4A    te.?.(.....@...J
0050  00 00 03 03 64 65 66 06 72 65 61 6C 6D 64 0E 61    ....def.realmd.a
0060  63 63 6F 75 6E 74 5F 62 61 6E 6E 65 64 0E 61 63    ccount_banned.ac
0070  63 6F 75 6E 74 5F 62 61 6E 6E 65 64 09 75 6E 62    count_banned.unb
0080  61 6E 64 61 74 65 09 75 6E 62 61 6E 64 61 74 65    andate.unbandate
0090  0C 3F 00 28 00 00 00 08 01 00 00 00 00 05 00 00    .?.(............
00A0  04 FE 00 00 02 00 05 00 00 05 FE 00 00 02 00       ...............

MYSQL返回的数据

10 127.0.0.1:10740 127.0.0.1:3306 98 Send

0000  5E 00 00 00 03 55 50 44 41 54 45 20 61 63 63 6F    ^....UPDATE acco
0010  75 6E 74 5F 62 61 6E 6E 65 64 20 53 45 54 20 61    unt_banned SET a
0020  63 74 69 76 65 20 3D 20 30 20 57 48 45 52 45 20    ctive = 0 WHERE
0030  75 6E 62 61 6E 64 61 74 65 3C 3D 55 4E 49 58 5F    unbandate<=UNIX_
0040  54 49 4D 45 53 54 41 4D 50 28 29 20 41 4E 44 20    TIMESTAMP() AND
0050  75 6E 62 61 6E 64 61 74 65 3C 3E 62 61 6E 64 61    unbandate<>banda
0060  74 65                                              te

如果封号过期,取消封号

11 127.0.0.1:3306 127.0.0.1:10740 52 Recv

0000  30 00 00 01 00 00 00 22 00 00 00 28 52 6F 77 73    0......"...(Rows
0010  20 6D 61 74 63 68 65 64 3A 20 30 20 20 43 68 61     matched: 0  Cha
0020  6E 67 65 64 3A 20 30 20 20 57 61 72 6E 69 6E 67    nged: 0  Warning
0030  73 3A 20 30                                        s: 0

MYSQL返回的数据

12 127.0.0.1:3724 127.0.0.1:10775 119 Send

0000  00 00 00 BB 24 92 69 D7 23 87 F0 28 B5 A3 26 14    ....$.i.#..(..&.
0010  F9 36 DA B9 DF 83 13 35 35 38 4F E3 78 DA 93 9C    .6.....558O.x...
0020  59 A8 17 01 07 20 B7 9B 3E 2A 87 82 3C AB 8F 5E    Y.... ..>*..<..^
0030  BF BF 8E B1 01 08 53 50 06 29 8B 5B AD BD 5B 53    ......SP.).[..[S
0040  E1 89 5E 64 4B 89 CF 59 12 5A 15 F1 CD 00 ED 2C    ..^dK..Y.Z.....,
0050  5E CC 7B 2E 84 79 E1 0B AC 97 BA D5 DF 2C 41 0D    ^.{..y.......,A.
0060  D4 3C 21 73 E5 B7 B9 8A B1 1A 97 B6 58 32 7F 7F    .<!s........X2..
0070  4F 9D 23 9C 36 F8 00                               O.#.6..

返回给客户端的数据,第0个字节是包类型AUTH_LOGON_CHALLENGE, 第1个字节为00,第2个字节为认证结果WOW_SUCCESS为00,第3-6这四个字节是根据auth数据库account中v、s两个字段算出来的一个数值,之后是安全之类的信息。计算过程在AuthSocket.cpp的AuthSocket::_HandleLogonChallenge()中。

13 127.0.0.1:10775 127.0.0.1:3724 75 Recv

0000  01 2A 62 13 B7 8F 50 A3 69 78 C1 B1 CA 3B CE D8    .*b...P.ix...;..
0010  95 14 13 BA 21 A9 06 E5 60 B3 EC 1B 8E 51 48 20    ....!...`....QH
0020  20 38 E0 9D 9B AC 08 19 CD 15 8B 54 87 ED 30 64     8.........T..0d
0030  11 59 3C 8D 8F 9D CB 6C 0D 8E 90 16 7C 6F BE 22    .Y<....l....|o."
0040  A8 4C 5F 02 0A BC 04 F0 5F 00 00                   .L_....._..

客户端发给认证服务器的AUTH_LOGON_PROOF数据,结构定义在AuthSocket.cpp的sAuthLogonProof_C中。有一堆安全方面的计算,不知道Trinity这帮人怎么琢磨出来的。

14 127.0.0.1:3724 127.0.0.1:10775 32 Send

0000  01 00 1B F7 BE 50 54 84 8B B2 44 89 97 FD AA C3    .....PT...D.....
0010  44 AE 99 C9 4D A0 00 00 80 00 00 00 00 00 00 00    D...M...........

认证服务器返回给客户端的sAuthLogonProof_S结构数据

15 127.0.0.1:10740 127.0.0.1:3306 221 Send

0000  D9 00 00 00 03 55 50 44 41 54 45 20 61 63 63 6F    .....UPDATE acco
0010  75 6E 74 20 53 45 54 20 73 65 73 73 69 6F 6E 6B    unt SET sessionk
0020  65 79 20 3D 20 27 36 42 33 44 37 37 33 46 39 34    ey = '6B3D773F94
0030  39 30 43 42 41 42 38 36 31 30 41 34 45 37 34 37    90CBAB8610A4E747
0040  43 36 33 42 38 31 37 41 44 30 32 38 31 38 30 44    C63B817AD028180D
0050  32 37 46 41 42 42 41 41 46 43 35 32 42 30 37 37    27FABBAAFC52B077
0060  37 37 45 37 36 37 46 36 37 35 44 36 42 32 36 45    77E767F675D6B26E
0070  34 37 37 39 33 42 27 2C 20 6C 61 73 74 5F 69 70    47793B', last_ip
0080  20 3D 20 27 31 32 37 2E 30 2E 30 2E 31 27 2C 20     = '127.0.0.1',
0090  6C 61 73 74 5F 6C 6F 67 69 6E 20 3D 20 4E 4F 57    last_login = NOW
00A0  28 29 2C 20 6C 6F 63 61 6C 65 20 3D 20 27 34 27    (), locale = '4'
00B0  2C 20 66 61 69 6C 65 64 5F 6C 6F 67 69 6E 73 20    , failed_logins
00C0  3D 20 30 20 57 48 45 52 45 20 75 73 65 72 6E 61    = 0 WHERE userna
00D0  6D 65 20 3D 20 27 50 41 53 53 4F 53 27             me = 'PASSOS'

认证服务器向MySQL更新账户信息。

16 127.0.0.1:3306 127.0.0.1:10740 52 Recv

0000  30 00 00 01 00 01 00 02 00 00 00 28 52 6F 77 73    0..........(Rows
0010  20 6D 61 74 63 68 65 64 3A 20 31 20 20 43 68 61     matched: 1  Cha
0020  6E 67 65 64 3A 20 31 20 20 57 61 72 6E 69 6E 67    nged: 1  Warning
0030  73 3A 20 30                                        s: 0

MySQL返回的数据

17 127.0.0.1:10775 127.0.0.1:3724 5 Recv

0000  10 00 00 00 00                                     .....

客户端向认证服务器要求Realm登陆服务器列表,10为REALM_LIST命令,AuthSocket::_HandleRealmList()

18 127.0.0.1:10740 127.0.0.1:3306 53 Send

0000  31 00 00 00 03 53 45 4C 45 43 54 20 69 64 20 46    1....SELECT id F
0010  52 4F 4D 20 61 63 63 6F 75 6E 74 20 57 48 45 52    ROM account WHER
0020  45 20 75 73 65 72 6E 61 6D 65 20 3D 20 27 50 41    E username = 'PA
0030  53 53 4F 53 27                                     SSOS'

认证服务器从MySQL中查账户id

19 127.0.0.1:3306 127.0.0.1:10740 80 Recv

0000  01 00 00 01 01 2E 00 00 02 03 64 65 66 06 72 65    ..........def.re
0010  61 6C 6D 64 07 61 63 63 6F 75 6E 74 07 61 63 63    almd.account.acc
0020  6F 75 6E 74 02 69 64 02 69 64 0C 3F 00 0B 00 00    ount.id.id.?....
0030  00 03 23 42 00 00 00 05 00 00 03 FE 00 00 02 00    ..#B............
0040  03 00 00 04 02 31 31 05 00 00 05 FE 00 00 02 00    .....11.........

MySQL返回的数据

20 127.0.0.1:10740 127.0.0.1:3306 149 Send

0000  91 00 00 00 03 53 45 4C 45 43 54 20 69 64 2C 20    .....SELECT id,
0010  6E 61 6D 65 2C 20 61 64 64 72 65 73 73 2C 20 70    name, address, p
0020  6F 72 74 2C 20 69 63 6F 6E 2C 20 63 6F 6C 6F 72    ort, icon, color
0030  2C 20 74 69 6D 65 7A 6F 6E 65 2C 20 61 6C 6C 6F    , timezone, allo
0040  77 65 64 53 65 63 75 72 69 74 79 4C 65 76 65 6C    wedSecurityLevel
0050  2C 20 70 6F 70 75 6C 61 74 69 6F 6E 2C 20 67 61    , population, ga
0060  6D 65 62 75 69 6C 64 20 46 52 4F 4D 20 72 65 61    mebuild FROM rea
0070  6C 6D 6C 69 73 74 20 57 48 45 52 45 20 63 6F 6C    lmlist WHERE col
0080  6F 72 20 3C 3E 20 33 20 4F 52 44 45 52 20 42 59    or <> 3 ORDER BY
0090  20 6E 61 6D 65                                      name

认证服务器根据账户id从数据库中查找对应地区的登陆服务器信息

21 127.0.0.1:3306 127.0.0.1:10740 765 Recv

0000  01 00 00 01 0A 32 00 00 02 03 64 65 66 06 72 65    .....2....def.re
0010  61 6C 6D 64 09 72 65 61 6C 6D 6C 69 73 74 09 72    almd.realmlist.r
0020  65 61 6C 6D 6C 69 73 74 02 69 64 02 69 64 0C 3F    ealmlist.id.id.?
0030  00 0B 00 00 00 03 23 42 00 00 00 36 00 00 03 03    ......#B...6....
0040  64 65 66 06 72 65 61 6C 6D 64 09 72 65 61 6C 6D    def.realmd.realm
0050  6C 69 73 74 09 72 65 61 6C 6D 6C 69 73 74 04 6E    list.realmlist.n
0060  61 6D 65 04 6E 61 6D 65 0C 21 00 60 00 00 00 FD    ame.name.!.`....
0070  05 40 00 00 00 3C 00 00 04 03 64 65 66 06 72 65    .@...<....def.re
0080  61 6C 6D 64 09 72 65 61 6C 6D 6C 69 73 74 09 72    almd.realmlist.r
0090  65 61 6C 6D 6C 69 73 74 07 61 64 64 72 65 73 73    ealmlist.address
00A0  07 61 64 64 72 65 73 73 0C 21 00 60 00 00 00 FD    .address.!.`....
00B0  01 00 00 00 00 36 00 00 05 03 64 65 66 06 72 65    .....6....def.re
00C0  61 6C 6D 64 09 72 65 61 6C 6D 6C 69 73 74 09 72    almd.realmlist.r
00D0  65 61 6C 6D 6C 69 73 74 04 70 6F 72 74 04 70 6F    ealmlist.port.po
00E0  72 74 0C 3F 00 0B 00 00 00 03 01 00 00 00 00 36    rt.?...........6
00F0  00 00 06 03 64 65 66 06 72 65 61 6C 6D 64 09 72    ....def.realmd.r
0100  65 61 6C 6D 6C 69 73 74 09 72 65 61 6C 6D 6C 69    ealmlist.realmli
0110  73 74 04 69 63 6F 6E 04 69 63 6F 6E 0C 3F 00 03    st.icon.icon.?..
0120  00 00 00 01 21 00 00 00 00 38 00 00 07 03 64 65    ....!....8....de
0130  66 06 72 65 61 6C 6D 64 09 72 65 61 6C 6D 6C 69    f.realmd.realmli
0140  73 74 09 72 65 61 6C 6D 6C 69 73 74 05 63 6F 6C    st.realmlist.col
0150  6F 72 05 63 6F 6C 6F 72 0C 3F 00 03 00 00 00 01    or.color.?......
0160  21 00 00 00 00 3E 00 00 08 03 64 65 66 06 72 65    !....>....def.re
0170  61 6C 6D 64 09 72 65 61 6C 6D 6C 69 73 74 09 72    almd.realmlist.r
0180  65 61 6C 6D 6C 69 73 74 08 74 69 6D 65 7A 6F 6E    ealmlist.timezon
0190  65 08 74 69 6D 65 7A 6F 6E 65 0C 3F 00 03 00 00    e.timezone.?....
01A0  00 01 21 00 00 00 00 56 00 00 09 03 64 65 66 06    ..!....V....def.
01B0  72 65 61 6C 6D 64 09 72 65 61 6C 6D 6C 69 73 74    realmd.realmlist
01C0  09 72 65 61 6C 6D 6C 69 73 74 14 61 6C 6C 6F 77    .realmlist.allow
01D0  65 64 53 65 63 75 72 69 74 79 4C 65 76 65 6C 14    edSecurityLevel.
01E0  61 6C 6C 6F 77 65 64 53 65 63 75 72 69 74 79 4C    allowedSecurityL
01F0  65 76 65 6C 0C 3F 00 03 00 00 00 01 21 00 00 00    evel.?......!...
0200  00 42 00 00 0A 03 64 65 66 06 72 65 61 6C 6D 64    .B....def.realmd
0210  09 72 65 61 6C 6D 6C 69 73 74 09 72 65 61 6C 6D    .realmlist.realm
0220  6C 69 73 74 0A 70 6F 70 75 6C 61 74 69 6F 6E 0A    list.population.
0230  70 6F 70 75 6C 61 74 69 6F 6E 0C 3F 00 0C 00 00    population.?....
0240  00 04 21 00 1F 00 00 40 00 00 0B 03 64 65 66 06    ..!....@....def.
0250  72 65 61 6C 6D 64 09 72 65 61 6C 6D 6C 69 73 74    realmd.realmlist
0260  09 72 65 61 6C 6D 6C 69 73 74 09 67 61 6D 65 62    .realmlist.gameb
0270  75 69 6C 64 09 67 61 6D 65 62 75 69 6C 64 0C 3F    uild.gamebuild.?
0280  00 0B 00 00 00 03 21 00 00 00 00 05 00 00 0C FE    ......!.........
0290  00 00 22 00 2A 00 00 0D 01 31 07 54 72 69 6E 69    ..".*....1.Trini
02A0  74 79 09 31 32 37 2E 30 2E 30 2E 31 04 38 30 38    ty.127.0.0.1.808
02B0  39 01 31 01 30 02 31 36 01 30 01 30 05 31 33 39    9.1.0.16.0.0.139
02C0  33 30 2E 00 00 0E 01 32 0B 54 72 69 6E 69 74 79    30.....2.Trinity
02D0  63 6F 72 65 09 31 32 37 2E 30 2E 30 2E 31 04 38    core.127.0.0.1.8
02E0  30 38 39 01 31 01 30 02 31 36 01 30 01 30 05 31    089.1.0.16.0.0.1
02F0  33 39 33 30 05 00 00 0F FE 00 00 22 00             3930.......".

MySQL返回的数据

22 127.0.0.1:10740 127.0.0.1:3306 77 Send

0000  49 00 00 00 03 53 45 4C 45 43 54 20 6E 75 6D 63    I....SELECT numc
0010  68 61 72 73 20 46 52 4F 4D 20 72 65 61 6C 6D 63    hars FROM realmc
0020  68 61 72 61 63 74 65 72 73 20 57 48 45 52 45 20    haracters WHERE
0030  72 65 61 6C 6D 69 64 20 3D 20 27 31 27 20 41 4E    realmid = '1' AN
0040  44 20 61 63 63 74 69 64 3D 27 31 31 27             D acctid='11'

从数据库中取该登陆服务器上该账号realmid为1的角色数量

23 127.0.0.1:3306 127.0.0.1:10740 107 Recv

0000  01 00 00 01 01 4A 00 00 02 03 64 65 66 06 72 65    .....J....def.re
0010  61 6C 6D 64 0F 72 65 61 6C 6D 63 68 61 72 61 63    almd.realmcharac
0020  74 65 72 73 0F 72 65 61 6C 6D 63 68 61 72 61 63    ters.realmcharac
0030  74 65 72 73 08 6E 75 6D 63 68 61 72 73 08 6E 75    ters.numchars.nu
0040  6D 63 68 61 72 73 0C 3F 00 03 00 00 00 01 21 00    mchars.?......!.
0050  00 00 00 05 00 00 03 FE 00 00 02 00 02 00 00 04    ................
0060  01 33 05 00 00 05 FE 00 00 02 00                   .3.........

MySQL返回的数据

24 127.0.0.1:10740 127.0.0.1:3306 77 Send

0000  49 00 00 00 03 53 45 4C 45 43 54 20 6E 75 6D 63    I....SELECT numc
0010  68 61 72 73 20 46 52 4F 4D 20 72 65 61 6C 6D 63    hars FROM realmc
0020  68 61 72 61 63 74 65 72 73 20 57 48 45 52 45 20    haracters WHERE
0030  72 65 61 6C 6D 69 64 20 3D 20 27 32 27 20 41 4E    realmid = '2' AN
0040  44 20 61 63 63 74 69 64 3D 27 31 31 27             D acctid='11'

从数据库中查询该账户realmid为2的角色数量

25 127.0.0.1:3306 127.0.0.1:10740 101 Recv

0000  01 00 00 01 01 4A 00 00 02 03 64 65 66 06 72 65    .....J....def.re
0010  61 6C 6D 64 0F 72 65 61 6C 6D 63 68 61 72 61 63    almd.realmcharac
0020  74 65 72 73 0F 72 65 61 6C 6D 63 68 61 72 61 63    ters.realmcharac
0030  74 65 72 73 08 6E 75 6D 63 68 61 72 73 08 6E 75    ters.numchars.nu
0040  6D 63 68 61 72 73 0C 3F 00 03 00 00 00 01 21 00    mchars.?......!.
0050  00 00 00 05 00 00 03 FE 00 00 02 00 05 00 00 04    ................
0060  FE 00 00 02 00                                     .....

MySQL返回的数据

26 127.0.0.1:3724 127.0.0.1:10775 81 Send

0000  10 4E 00 00 00 00 00 02 00 01 00 00 54 72 69 6E    .N..........Trin
0010  69 74 79 00 31 32 37 2E 30 2E 30 2E 31 3A 38 30    ity.127.0.0.1:80
0020  38 39 00 00 00 00 00 03 10 2C 01 00 00 54 72 69    89.......,...Tri
0030  6E 69 74 79 63 6F 72 65 00 31 32 37 2E 30 2E 30    nitycore.127.0.0
0040  2E 31 3A 38 30 38 39 00 00 00 00 00 00 10 2C 10    .1:8089.......,.
0050  00                                                 .

认证服务器返回给客户端登陆服务器列表

            <p class="entry-meta"><span class="category"><span class="before">Posted in </span><a href="http://log4think.com/category/practice/fun/wow-trinity/" rel="tag">WoW/Trinity</a>, <a href="http://log4think.com/category/practice/code_reading/" rel="tag">读代码(code reading)</a></span> <span class="post_tag"><span class="before">| Tagged </span><a href="http://log4think.com/tag/source/" rel="tag">source</a>, <a href="http://log4think.com/tag/wow/" rel="tag">wow</a>, <a href="http://log4think.com/tag/%e6%95%b0%e6%8d%ae%e5%8c%85/" rel="tag">数据包</a>, <a href="http://log4think.com/tag/%e9%ad%94%e5%85%bd%e4%b8%96%e7%95%8c/" rel="tag">魔兽世界</a></span> | <a class="comments-link" href="http://log4think.com/wow_3-3-513930_login_packets/#respond" title="Comment on 魔兽世界3.3.5 13930登录数据包分析">Leave a response</a></p>