当前位置: 首页 > 工具软件 > MaNGOS Game > 使用案例 >

mangos0.9源码解析学习笔记(三)游戏世界模型初始化

云伯寅
2023-12-01

      游戏世界的初始化发生在连接到数据库之后,和开始进行端口监听之前。服务端首先连接到三种数据库,然后根据配置文件和数据库中的信息对世界模型进行构建,构建完成之后才进行端口监听和世界更新的主循环。

       世界模型初始化要经过一下几个步骤:

1,载入配置文件,并且输出一些版本,警告等信息,这是惯例。

2,从配置文件中读取第一类信息,这里我将几类信息进行了区分,第一类信息应该描述为角色参数,获益参数,伤害参数等,主要包括血量比例,经验比例,爆率,伤害基数等信息。在私服中无比幸福的爆率和升级速度无非是修改了此种配置文件信息。

3,从配置文件中读取第二类信息,第二类信息主要是游戏世界的参数,服务器的一些参数,包括游戏更新时间等有关游戏世界的配置参数。2,3中所读取的参数全部来自于配置文件,如果紧紧是用于搭建私服,将源码编译,并且搭建svn和数据库环境等运行环境,然后只需要对配置文件进行解读并且做适当的修改就可以了。

4,然后读取data的信息,一开始没有搞明白data中保存的是什么东西,但是看它的使用感觉应该是一些地图信息,后来看系统搭建时有个细节,是使用makevmaps_SIMPLE.bat 和ad.exe在游戏安装目录中运行,我猜应该是从游戏文件中去解读出一些封装起来的信息,应该主要是地图贴图的信息。猜的,或许根本就不是这么回事。data路径中包括了Vmap地图信息,和DBC的路径。这一步是从data中读取地图信息,并且应该也进行了场景图片贴图还原的过程。

5,接着从loginDatabase数据库中更新游戏区域信息,然后从移除场景中的尸体,移除场景中的尸体的方法是使用CharacterDatabase数据库进行一次更新,我在这里做了大胆的设想,设想了一下网游的实质是什么,让我猜测一下,服务器端的主要工作是接受客户端的信息,并且,根据这些信息和自身逻辑对数据库进行操作,所有的世界模型和角色模型中的物体均来自数据库,均以数据库中的数据表示,然后,更新后的信息由服务器发送回客户端,在客户端进行重新的场景计算。以尸体为例,由服务器的逻辑控制尸体的存在时长,当存在时长超时之后,由专门操作数据库的线程或者服务来更改数据库中的数据,在服务器整体世界更新中,依据数据库中的值对对象进行更新,删除该尸体的数据。当客户端刷新世界模型时,尸体消失。 猜测,待验证。如果不对,请明白人指出,我只是第一次接触学习,有些东西肯定漏洞百出。

6,然后进行的是从DBC中加载各种游戏对象数据,包括加载生物环境,加载游戏对象,加载NPC,加载技能任务等众多的信息加载。DBC中应该详细保存了每种对象的参数,但是有一个疑问,人设模型这些东西是保存在data中的呢 还是保存在DBC中的呢?只能以后慢慢摸索。

7,进行游戏事件,游戏脚本,地图管理和AI的初始化。

8,最后进行的是对游戏事件的初始化,这里一直没想清楚什么是游戏事件,所以就重点分析了一下GameEvent类,

      游戏世界模型初始化的最后一步是开始对游戏事件进行初始化,游戏事件使用GameEvent类来描述,这里虽然不能明确的给出GameEvent用来具体描述一些什么东西,但是仔细分析其实现代码后可以发现,GameEvent描述的是一种类似游戏过程的东西,这个过程包括明确的起止时间,和发生的事情。每个事件都使用一个uint16来标识。

下面来详细说明一下GameEvent中的一个函数void GameEvent::LoadFromDB() , 该函数的实现让自己对游戏的实现有了进一步的了解,特别是对数据库和游戏事件的关系的理解。

GameEvent::LoadFromDB()函数通过多次读取数据库中的信息实现,这样看来,游戏的事件也是保存在数据库中的数值信息,通过读取这些信息,然后使用一定的逻辑对事件进行还原处理。

GameEvent::LoadFromDB()读取信息如下:

1, result = WorldDatabase.Query("SELECT MAX(`entry`) FROM `game_event`");     应该是读取数据库中game_event的最大值,我暂时把它理解成为数据库中所保存的game_event的数目,因为有一个判断是  if( !result )  输出Table game_event is empty。将读取到的信息保存,并清空result。

2,  result = WorldDatabase.Query(""SELECT `entry`,UNIX_TIMESTAMP(`start`),UNIX_TIMESTAMP(`end`),`occurence`,`length`,`description` FROM 'game_event');     

      这次是读取的游戏事件的起止事件和描述信息等。GameEvent使用一个专门的GameEventData 来保存读取到的数据,在记录读取到的所有数据后,同样清空result。

3,  result = WorldDatabase.Query("SELECT `creature`.`guid`,`game_event_creature`.`event` FROM `creature` JOIN `game_event_creature` ON `creature`.`guid` = `game_event_creature`.`guid`");  这次是读取和当前所有game_event相关的生物的信息。同样保存后 清空result。

4,  result = WorldDatabase.Query("SELECT `gameobject`.`guid`,`game_event_gameobject`.`event` FROM `gameobject` JOIN `game_event_gameobject` ON `gameobject`.`guid`=`game_event_gameobject`.`guid`");  然后是读取和当前所有事件有关的游戏对象的信息。

5, result = WorldDatabase.Query("SELECT`creature`.`guid`,`game_event_model_equip`.`event`,`game_event_model_equip`.`modelid`,       `game_event_model_equip`.`equipment_id` FROM `creature` JOIN `game_event_model_equip` ON `creature`.`guid`=`game_event_model_equip`.`guid`");

      接着还要从数据库中取出的是和当前事件有关的游戏装备信息。

6,最后result = WorldDatabase.Query("SELECT `id`,`quest`,`event` FROM `game_event_creature_quest`");  从数据库中取出任务信息

    经过以上6次对数据库的操作,取出了和GameEvent有关的信息,然后封装如GameEvent类中,并且结束游戏世界模型的初始化,如果此处对GameEvent的理解没有错误,那么后续游戏世界的更新会以这些游戏事件序列为基础,依次向前发展。但是如果是理解错误,这些游戏事件可能只是wow中的活动信息,比如哪天有那些活动一类的。。。看来需要对数据库中保存的信息进行了解了,至少哪个表是保存哪种信息的,哪个键值代表什么意思,数据库的信息对理解游戏世界的建立和更新有较大的影响。

  uint32 nextGameEvent = gameeventmgr.Initialize();  // 进过gameEvent的初始化返回事件的延迟.....这点没有搞懂,

 m_timers[WUPDATE_EVENTS].SetInterval(nextGameEvent);    //然后做什么没想清楚

 类似资料: