Ascent代码分析4-World之地图管理及实现结构

来源:互联网 发布:mac 如何设置桌面图标 编辑:程序博客网 时间:2024/06/05 23:46

 

 

Wow世界中的地图有两种:场景地图和副本地图.

              场景地图只有一个实体,一般比较大。如东部王国、卡里姆多和外域分别是一个整张的地图(各个地图间传送的港口也是单独的地图)。

              副本地图是同样的地图场景,但却有多个不同的实体。比如各种副本和战场,都属于副本地图。

InstanceMgr:将负责整个世界的地图创建和保持。每个地图(以及每个副本)将以MapMgr的形式创建,MapMgr主要负责地图中玩家和npc怪物的逻辑管理和运算。世界地图的MapMgr放在m_singleMaps,副本的MapMgr则在每个Instance:: m_mapMgr中(也就是说每个副本都会有一个MapMgr,但是当没有副本存在时也不会有副本的MapMgr。而世界地图则固定有一个MapMgr)。 Map中的_terrain则加载了地图文件中的地形信息,包括水体深度和地面高度信息等。而Map也将主要负责地图信息和地形信息的管理。下面分别描述:

注:如上图,MapMgr派生自CThread,也就是说每个地图和副本都会有一个线程。这样使不同的地图的运算分离,也能充分利用多cpu的性能,但是当用户量大的时候可能会产生大量的线程,不太确定这种方法的优劣。不过如果线程在可以承受的范围内的话,这样也可以避免一个玩家操作卡时导致整个服务器都卡的情况,至多也就是当前地图副本的玩家卡。

    MapMgr:

              MapMgr派生自CThreadCellHandler<MapCell>,在创建时会加入到线程池中运行,当终止线程时,MapMgr会删除自己释放内存。父类CellHandler是个模板类,把地图分为多个单元格MapCell,将地图上的npc和玩家划分为多个小子集分别处理.当当前单元格和相邻的单元个都没有玩家的时候,会将单元格设置一个

延迟unload事件:

sEventMgr.AddEvent(_mapmgr, &MapMgr::UnloadCell,(uint32)_x,(uint32)_y,MAKE_CELL_EVENT(_x,_y),sWorld.map_unload_time * 1000,1,0);

在一定时间后如果还没有玩家进入就unload该单元格以及其中的npc,以节省资源。

              MapMgr则在Do函数(实际上是运行在run()函数执行线程中)中循环调用_PerformObjectDuties()函数,以间隔时间刷新该地图中所有对象(npc,宠物,玩家,gameObject,session等)的状态和逻辑运算。

      Map:

              成员TerrainMgr同样将地图的地形分为单元格(成员CellInformation),实现了地形的动态加载和卸载(这个与MapCell的加载和卸载是一起的,但是没有设置延时,是立即释放的。当玩家在两个格子间频繁切换时会影响性能。)

         Map本身则负责了怪物刷新点(spawns)的载入和维护管理。

      InstanceMgr:

         InstanceMgr初始化时将为每一个地图创建一个Map,为每一个非副本地图创建一个MapMgr

void InstanceMgr::_CreateMap(uint32 mapid)

{

     if( mapid >= NUM_MAPS )

         return;

     MapInfo * inf;

     inf = WorldMapInfoStorage.LookupEntry(mapid);

     if(inf==NULL)

         return;

     if(m_maps[mapid]!=NULL)

         return;

     //初始化一个map,并将指针放入数组

     m_maps[mapid] = new Map(mapid, inf);

     if(inf->type == INSTANCE_NULL)

     {

         //如果不是副本地图则创建世界地图副本(实际的实现是为其创建一个MapMgr并放入线程池执行)

         _CreateInstance(mapid, GenerateInstanceID());

     }

}

副本的MapMgr将在创建副本对象时动态创建,

//跟创建世界地图副本的函数是不同的两个重载函数

MapMgr * InstanceMgr::_CreateInstance(Instance * in)

{

     in->m_mapMgr = new MapMgr(m_maps[in->m_mapId], in->m_mapId, in->m_instanceId);

     in->m_mapMgr->pInstance = in;

     in->m_mapMgr->iInstanceMode = in->m_difficulty;

     in->m_mapMgr->InactiveMoveTime = 60+UNIXTIME;

     ThreadPool.ExecuteTask(in->m_mapMgr);

     return in->m_mapMgr;

}

         Instance的创建在InstanceMgr::GetInstance(Object* obj)时动态创建,当instance绑定到一个MapMgr以后,就以MapMgr的形式单独运行,直到_DeleteInstance时,将设置MapMgr终止线程。