mangos几个类的设计

来源:互联网 发布:c语言的自定义函数 编辑:程序博客网 时间:2024/06/08 16:00

10月份校招季节,十一假期回来之后一直在断断续续的笔试,面试,在笔试,在面试。虽然签了家还不错的公司,但是毕竟做的方向并不是我最希望的,所以还想着能继续找找看。

2009年的形式不好,2012年的形式也不好,算是命途多舛吗?但是庆幸的是还是有不错的一家公司签了我,总算是有些许欣慰,也没有那么大的压力了。

最近网上找到一篇pdf,介绍了mangos中的几个类结构,学习学习,只是出处未知。

转载内容如下

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

1 . Object 类主要功能
1) InWorld 判断和操作
2) GUID
Mangos 的每个对象都有唯一的 GUID ,每类 GUID 的最大值是保存在数据库中,初始化时候从数据库加载 。
Mangos 这样做还是很奢侈的,国内服务器可能都存在合服需求,所以国内服务器操持角色 ID 不同即可。
可能要合服的服务器在开服的时候要把的角 色 I D 范围要规划好 ( 天龙八部的角 色 I D 的最大值是保存在数据
库中的 ) 。国内服务器中对于重要物品、宠物可能需要唯一的 ID ,可以考虑角色 ID + 物品、宠物 id 来实
现。 uint32 应该够用了,但是也要限制重要物品的种类和数量。
3) Object 类型 TypeId
enum TypeID
{
TYPEID_OBJECT = 0,
TYPEID_ITEM = 1,
TYPEID_CONTAINER = 2,
TYPEID_UNIT = 3,
TYPEID_PLAYER = 4,
TYPEID_GAMEOBJECT = 5,
TYPEID_DYNAMICOBJECT = 6,
TYPEID_CORPSE = 7
};
4) 网络包发送 SendUpdateToPlayer
5) 基本状态组包 Values 、 OutOfRange 、 Movement UpdateBlock 等
6) Int, UInt, float 等标记 数据设置、加载、访问 Get /SetXXX Value 、 SetFlag
union
{
int32 * m_int32Values ;
uint32 * m_uint32Values ;
float * m_floatValues ;
};
Object 有很多数据、状态以数组形式存储,访问时候通过类型和标记定位。
7) 任务判断接口 hasQuest
2 . Item 类主要功能
1) 创建和复制 Create /Clone Item
2) 所有者 Owner(Player)
3) 数据库存取 SaveTo/LoadFromDB
Mangos 的每个 Item 在数据中是作为一条记录保存的,一般国内网游是打包保存在玩家记录里面,国内网游的做法在数据库效率上要高很多。
4) 绑定 Binding 、损坏 Broken 、是否可交易 CanBeTrade 、叠放数量、是否装备等一般道具属性
5) 在包中的位置 Bag 、 Slot
6) 增强状态和时效 Enhancement
7) Timer 更新
8) 状态更新和广播 State
9) 技能和魔法相关 Skill/Spell
10) 任务相关 hasQuest
3 . Bag 类主要功能
1) 增加、删除、得到某位置的道具 Store/RemoveItem
2) 空间 IsEmpty 、 GetFreeSlots
3) 数据库存取 SaveTo/LoadFromDB
4) 组包更新 BuildCreateUpdateBlockForPlayer
4 . WorldObject 类主要功能
1) 位置和朝向 Relocate 、 SetOrientation
2) 附近空间位置 GetClosePoint
3) 所在地图、区域和地区 GetMapId 、 GetZoneId 、 GetAreaId
4) 名字 GetName
5) 和其它 WorldObject 位置、角度等关系 IsWithinDist 、 IsInRange
6) 发送网络消息 SendMessageToSet
7) 发送聊天、喊叫等消息 MonsterSay 、 MonsterYellToZone
8) 对玩家来说是否可见 isVisibleFor
9) 召唤 Creature , SummonCreature
5 . Unit 类主要功能
Unit 类是很复杂的一个类,改类具有很多属性和方法,实现了游戏中 Player , Creature 等主要功能。
1) 渐变状态 GetDiminishing
2) 战斗相关 ( 计时器 、 攻击对象 、 停止等 ) setAttackTimer 、 Attack 、 getVictim 、 SendMeleeAttackStop
3) 单元状态 addUnitState
4) 等级 、 种族 、 职业 、 装甲 、 血量 、 伤害能力等属性 getLevel 、 getGender 、 getRace 、 GetArmor 、 GetHealth 、
GetPower
5) 友好、敌对等阵营关系 IsHostileTo 、 IsFriendlyTo
6) 站立、行走、骑乘、战斗、飞行、水下、恐惧、死亡等状态 getStandState 、 IsMounted 、 DeathState
7) 技能和伤害处理 DealDamage 、 MeleeSpellHitResult 、 GetWeaponSkillValue
8) 类型(商店、银行、飞行点、行会、拍卖行等) isVendor 、 isBanker
9) 施展法术 CastSpell
10) 光环状态和特效以及数值影响 HasAura 、 RemoveAura
11) 广播伤害、攻击状态等消息 SendAttackStateUpdate 、 SendSpellMiss
12) 主人、召唤者、宠物等信息 GetOwnerGUID 、 SetCharmerGUID 、 GetPet13) 状态更新广播 stat system
14) 可见性处理 Visibility system
15) 威胁值处理 Threat related methods
16) DynamicObject 对象和 GameObject 对象的附加 GetDynObject
17) event 处理 m_Events
18) MotionMaster
Unit 类设计得过大,还包含了战斗、技能、伤害处理、光环状态影响等这些比较复杂的功能模块。
6 . Creature 类主要功能
1) 加入到世界
2) 加载装备
3) 数据库存取
4) 类型,是否是车辆、宠物、图腾、精英等
5) 能力,能否行走、游泳、飞行
6) 对技能免疫
7) AI 和脚本
8) 售卖的道具
9) 状态更新
10) 对话内容
11) 聊天、喊叫
12) 战斗行为,寻求帮助
13) 重生处理
14) 任务相关
7 . Player 类主要功能
1) 加入到世界
2) 传送
3) 更新
4) 社会关系
5) 飞机
6) 位置
7) 宠物
8) 聊天
9) 装备、背包和仓库
10) 增强状态
11) 完整的任务处理
12) 数据库存取
13) 邮件
14) 技能
15) 天赋
16) 声望
17) 战场18) 战斗状态和模式更新
19) 竞技场
20) 移动处理
21) 副本
22) 组队
Player 类是继 Unit 类后另外一个很大的类 , 实现和很多功能 。 我现在很佩服 Mangos 服务器的程序员的水
平了,这么多功能,居然一个类搞定。这样的代码对后继维护和修改者绝对是噩梦。
其它类比较小,略过。
三、 CreatureAI
CreatureAI 这个类并不大,构造函数要传达一个 Creature 的指针,然后就是 20 来个接口函数。
构造函数:
explicit CreatureAI ( Creature * creature ) : m_creature ( creature ) {}
接口函数不多,可以全部列出来:
// Called if IsVisible(Unit *who) is true at each *who move, reaction at visibility zone enter
virtual void MoveInLineOfSight ( Unit *) {}
// Called for reaction at enter to combat if not in combat yet (enemy can be NULL)
virtual void EnterCombat ( Unit * /*enemy*/ ) {}
// Called for reaction at stopping attack at no attackers or targets
virtual void EnterEvadeMode () {}
// Called at reaching home after evade
virtual void JustReachedHome () {}
// Called at any heal cast/item used (call non implemented)
virtual void HealBy ( Unit * /*healer*/ , uint32 /*amount_healed*/ ) {}
// Called at any Damage to any victim (before damage apply)
virtual void DamageDeal ( Unit * /*done_to*/ , uint32 & /*damage*/ ) {}
// Called at any Damage from any attacker (before damage apply)
// Note: it for recalculation damage or special reaction at damage
// for attack reaction use AttackedBy called for not DOT damage in Unit::DealDamage also
virtual void DamageTaken ( Unit * /*done_by*/ , uint32 & /*damage*/ ) {}
// Called when the creature is killed
virtual void JustDied ( Unit *) {}
// Called when the creature kills a unit
virtual void KilledUnit ( Unit *) {}
// Called when the creature summon successfully other creature
virtual void JustSummoned ( Creature * ) {}
virtual void SummonedCreatureDespawn ( Creature * /*unit*/ ) {}
// Called when hit by a spell
virtual void SpellHit ( Unit *, const SpellEntry *) {}
// Called when spell hits creature's target
virtual void SpellHitTarget ( Unit *, const SpellEntry *) {}
// Called when the creature is target of hostile action: swing, hostile spell landed, fear/etc)
virtual void AttackedBy ( Unit * attacker );
// Called when creature is spawned or respawned (for reseting variables)
virtual void JustRespawned () {}
// Called at waypoint reached or point movement finished
virtual void MovementInform ( uint32 /*MovementType*/ , uint32 /*Data*/ ) {}
// Called at text emote receive from player
virtual void ReceiveEmote ( Player * /*pPlayer*/ , uint32 /*text_emote*/ ) {}
// Called when creature attack expected (if creature can and no have current victim)// Note: for reaction at hostile action must be called AttackedBy function.
virtual void AttackStart ( Unit *) {}
// Is unit visible for MoveInLineOfSight
virtual bool IsVisible ( Unit *) const { return false ; }
// Called when victim entered water and creature can not enter water
virtual bool canReachByRangeAttack ( Unit *) { return false ; }
// Called at World update tick
virtual void UpdateAI ( const uint32 /*diff*/ ) {}
可以看到,大部分接口是事件触发和消息通知。 UpdateAI 我放到最后,这个和别的接口函数不同 , 是
负责 AI 状态的更新处理。
以 CreatureAI 为基类 , 派生出了 PetAI 、 CreatureEventAI 、 GuardAI 、 ReactorAI 、 AggressAI 、 TotemAI
和 NullCreatureAI 7 类基本 AI 。 Creature 的 AIM_Initialize () 函数,对 AI 进行初始化,根据 Creature 的类型选
择不同的 AI 。值得提出的是, Mangos 还支持 ScriptAI ,对于非宠物类的生物支持扩展脚本 AI 。 Mangos 的脚
本系统我还没有怎么看,有空研究下。
可以看到 Mangos 的 AI 设计还是比较传统的, Creature 类相当于身体和物理存在,干很多 “ 傻大粗 ” 的
事情; AI 相当于 Creature 的大脑,对事件进行响应和处理,指挥着身体物理存在进行反应。
下面可以看下宠物 AI 的一段代码:
void PetAI :: MoveInLineOfSight ( Unit * u ) // 有单位进入宠物视野
{
if ( ! m_creature -> getVictim () && m_creature -> GetCharmInfo () &&
m_creature -> GetCharmInfo ()-> HasReactState ( REACT_AGGRESSIVE ) &&
u -> isTargetableForAttack () && m_creature -> IsHostileTo ( u ) &&
u -> isInAccessablePlaceFor ( m_creature ))
{ // 好多判断:不是我已有的攻击目标,并且我是攻击性的,并且我可以攻击此单位,并且单位是我的敌对方,并且我能
够得着它
float attackRadius = m_creature -> GetAttackDistance ( u );
if ( m_creature -> IsWithinDistInMap ( u , attackRadius ) && m_creature -> GetDistanceZ ( u ) <=
CREATURE_Z_ATTACK_RANGE ) // 在我的攻击范围内
{
if ( m_creature -> IsWithinLOSInMap ( u )) // 在我的视野中
{
AttackStart ( u ); // 攻击开始消息
u -> RemoveSpellsCausingAura ( SPELL_AURA_MOD_STEALTH ); // 去掉我的有隐身状态(有的话)
}
}
}
}
下面看看 AttackStart 干了什么:
void PetAI :: AttackStart ( Unit * u )
{
if (! u || ( m_creature -> isPet () && (( Pet *) m_creature )-> getPetType () == MINI_PET )) // 一些保护
return ;
if ( m_creature -> Attack ( u , true )) // 攻击成功
{m_creature -> clearUnitState ( UNIT_STAT_FOLLOW ); // 清除我的跟随状态
m_creature -> GetMotionMaster ()-> MoveChase ( u ); // 通过 MotionMaster 修改移动类型为 Chase ,并开始追。
MotionMaster 的分析见下面
inCombat = true ;
}
}
四、 MotionMaster
在 Unit 类中还有个 MotionMaster 成员, Creature 在初始化 AI 的时候,对 MotionMaster 进行初始化。
MotionMaster 维护一个移动的列表并负责不同移动类型的生成。具体的移动类型控制 Creature 的移动。
下面是 MotionMaster 生成不同移动类型的接口函数:
void MoveIdle ();
void MoveTargetedHome ();
void MoveFollow ( Unit * target , float dist , float angle );
void MoveChase ( Unit * target , float dist = 0.0f, float angle = 0.0f);
void MoveConfused ();
void MoveFleeing ( Unit * enemy , uint32 time = 0);
void MovePoint ( uint32 id , float x , float y , float z );
void MoveSeekAssistance ( float x , float y , float z );
void MoveSeekAssistanceDistract ( uint32 timer );
void MoveTaxiFlight ( uint32 path , uint32 pathnode );
void MoveDistract ( uint32 time );
Mangos 对移动进行了单独的处理,这个是它的一个亮点和优点。
五、 结论
1. 网游服务器 AI 的 基本结构还是体现出来了 , 一个网游服务器 AI 系统确实主要是由游戏对象 、 AI 和移
动组成;
2. 关键类设计得过于复杂 , 需要进一步细化和模块化 ; 像 Unit 和 Player 里面的战斗和技能很必要作为
一个独立模块来设计和实现。 Creature 和 Player 等复杂的类,需要划分出状态,否则太多状态变量
和条件判断,很容易出错,而且不容易修改和扩充。
3. 代码复杂度比较高,一般程序员难于驾驭;如有人员替换,维护和修改比较困难;
4. 无内存池和对象池,大量使用 new 和 delete 。 长时间运行后,服务器效率是个问题;
5. 重用性很差 , 很难在上面搞出个其它不是 “ WOW ” 的游戏 。 听说国内有公司打算用 Mangos 搞其它网游 ,
肯定修改不动,不了了之。

原创粉丝点击