Mangos源码分析(一):DBC文件分析

 

(2008-01-24 22:57:57)

一、DBC文件结构

文件头      文件头(4字节“WDBC”)|记录数(4字节)|记录字段数(4字节)|每条记录字节数(4字节)|字符串表总字节数(4字节)
记录1       字段1|字段2|...|字段N
记录2       字段1|字段2|...|字段N
字符串表    字符串1|字符串2|...|字符串N

示例:打开从中国WOW客户端2.3.2解出来的DBC文件Weather.dbc,图1、图2是UE的截图(16进制),图3为DBC工具的截图(10进制)


图1、文件头及记录
55 44 42 43 | 15 00 00 00 | 07 00 00 00 | 1C 00 00 00 | 39 00 00 00
文件头“WDBC”| 记录数20  | 字段数7     | 每记录字节数28 | 字符串表总字节数57
5B 00 00 00 | 00 00 00 00 | 01 00 00 00 | 00 00 80 3F | 00 00 80 3F | 00 00 80 3F | 01 00 00 00
91          | 0           | 1           | 1065353216  | 1065353216  | 1065353216  | 1
......


图2、字符串表,以NULL(/0)即00分割字符串,记录所含有的字符串字段保存的数据是在字符串表中的偏移值


图3、用DBC工具打开文件的数据显示,Index列为DBC工具自动加入的索引

二、DBC文件分析

1、DBC文件的字段类型
在Mangos项目的dbcfile.h文件枚举了DBC文件的常见字段类型:
enum
{
FT_NA='x',      //没有使用或者未知类型,4字节
FT_NA_BYTE='X', //没有使用或者未知类型,单字节
FT_STRING='s',  //sizeof(char*),字符串指针32位机4字节
FT_FLOAT='f',   //float,4字节
FT_INT='i',     //uint32,4字节
FT_BYTE='b',    //uint8,单字节
FT_SORT='d',    //索引字段,但不计入记录字段,4字节
FT_IND='n',     //记录的索引字段,4字节
...
};

2、DBC文件的记录格式
DBCfmt.cpp文件中定义了DBC文件中的记录保存格式:
...
const char DurabilityCostsfmt[]="niiiiiiiiiiiiiiiiiiiiiiiiiiiii";
const char DurabilityQualityfmt[]="nf";//表示DurabilityQualityfmt.dbc中包含2个字段,类型为n和f,程序加载DBC文件时以该格式解析数据然后保存到数组
const char EmoteEntryfmt[]="nxixxxxxxxxxxxxxxxx";
...

3、加载数据库和DBC文件初始化WOW模拟服务端示例
(1)World.cpp中:
...
objmgr.LoadSpellLearnSkills();//可以学习的技能
...
(2)ObjectMgr.cpp的LoadSpellLearnSkills()函数:
//从mangos数据库的spell_learn_skill数据表先加载到mSpellLearnSkills(类型std::map)
QueryResult *result = WorldDatabase.PQuery("SELECT `entry`, `SkillID`, `Value`, `MaxValue` FROM `spell_learn_skill`");
//将从数据库取得全部数据逐个检查
Field *fields = result->Fetch();
uint32 spell_id = fields[0].GetUInt32();//0表示数据库的entry字段
//从DBC文件中检查是否存在此数据不存在则报错
 if(!sSpellStore.LookupEntry(spell_id))
{
    sLog.outErrorDb("Spell %u listed in `spell_learn_skill` does not exist",spell_id);
    continue;
}
(3)sSpellStore对象加载Spell.dbc
·DBCStores.cpp文件中:
LoadDBC(bar,bad_dbc_files,sSpellStore, dataPath+"dbc/Spell.dbc");
LoadDBC(...){...}该函数调用了storage.Load(filename.c_str()),storage为传入的sSpellStore,filename.c_str()则是Spell.dbc的完整文件名
·找到DBCStores.h中的Load函数定义:
 bool Load(char const* fn)
{
    dbc = new DBCFile; //DBC文件类,见dbcfile.h和dbcfile.cpp文件
    bool res = dbc->Load(fn, fmt);//fn为DBC文件名,fmt为DBC文件字段格式,这里是//SpellEntryfmt="niixii...";
    if (res)
    {
        fieldCount = dbc->GetCols();
        indexTable=(T **) dbc->AutoProduceData(fmt,&nCount,data);//返回每条记录的地址表
    }
    ...
    return res;
}

示例说明:从上面的代码分析可以看到在运行服务端mangosd.exe从控制台看到“Loading Spell Learn Skills...”时,Spell.dbc文件已经加载到内存,并且在把从mangos数据库取得的技能数组mSpellLearnSkills和Spell.dbc文件中对应的数据比较,如果数据库和DBC文件的数据不一样,则提示出错如:“Spell 技能ID listed in `spell_learn_skill` does not exist”。
 
附在线源代码:http://www.mangosproject.org/trac/browser/trunk/src

待续...(time) 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
mangos不是一个魔兽私服模拟器,它是一个开源的自由软件项目,是用c++和C#编程语言,实现的一个支持大型多人在线角色扮演游戏服务器的程序框架,在这个框架下,它理论上应该支持任何客户端的网络游戏,由于现在很多人使用魔兽世界来对它进行测试,所以针对魔兽世界的脚本和数据库文件比较完善,很多人就利用这个开源项目来实现魔兽私服。   首先,mangos项目是一个开源的自由软件(如同linux或者firefox),并且遵守其中最为严格的GPL协议,也就是保证源代码绝对的自由,要了解什么是开源软件,自由软件请自己搜索这方面的资料。   其次开发小组一再强调,这是个研究,教育性质的对怎样开发大型网游的服务器端有好处的项目,是一个技术细节毫无保留向公众开放的软件,是一件很有意义的事情,如果你使用它作为盈利目的,那你本身就违反了软件的协议。所以任何利用mangos项目进行私服活动的组织和个人都违反了mangos的宗旨,mangos项目也不会对它们负责。   mangos的技术细节上是这样的,核心部分是个和特定游戏没有关系的核心框架程序,主要是进行进程调度,创造世界,建立心跳机制,处理网络接入等。数据库也是使用的开源数据库软件MySQL,编译器使用的是GCC。至于游戏内容数据库,游戏人物,时间,世界脚本,都是由这个核心程序所支持的扩展脚本来实现,所以有一些独立出来的项目专门模拟魔兽世界来开发支持mangos的核心程序。现在mangos的核心程序已经放到著名的协同开发网站sourceforge上开发了,使用的版本控制工具是subversion,(目前已经迁移到GIT)。大家都可以从sourceforge的subversion数据库中下载最新的源代码程序。   另外有点要注意的是,开源项目是很容易被利用的,有时候有的公司开发了一个软件说是自己做的其实内核都是别人的开源内核,但是公司又不承认,利用了别人的劳动成果赚钱不说,既不回报社区,也对开源自由软件造成了很大的伤害。所以大家注意了,如果看到一个和魔兽世界很像的什么网络游戏?要想想是不是利用的mangos的核心程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值