using UnityEngine;
using CommonAIClient.Client;
using System;
using CommonAI.ZoneClient;
using CommonLang;
using CommonLang.Concurrent;
using CommonAI.Zone;
using CommonAIClient.Unity.Utils;
using CommonAI.Zone.ZoneEditor;
namespace CommonAIClient.Unity.Battle
{
public partial class BattleScene : IDisposable
{
#region RefCount
private static AtomicInteger s_alloc_count = new AtomicInteger(0);
private static AtomicInteger s_active_count = new AtomicInteger(0);
///
/// 分配实例数量
///
public static int AllocCount { get { return s_alloc_count.Value; } }
///
/// 未释放实例数量
///
public static int ActiveCount { get { return s_active_count.Value; } }
#endregion
private bool mDisposed = false;
private AbstractBattle mBattle;
protected GameObject mMapRoot;
///
/// 不绑定任何东西的特效会存在在这里
///
private GameObject mEffectRoot;
public bool IsDisposed { get { return mDisposed; } }
protected AbstractBattle Battle { get { return mBattle; } }
protected GameObject MapRoot { get { return mMapRoot; } }
public GameObject EffectRoot { get { return mEffectRoot; } }
public EditorTemplates DataRoot { get { return mBattle.DataRoot; } }
public ZoneInfo Terrain { get { return mBattle.Layer.Terrain; } }
public SceneData SceneData { get { return this.Battle.Layer.Data; } }
public int SceneID { get { return this.Battle.Layer.SceneID; } }
protected BattleScene(AbstractBattle client)
{
s_alloc_count++;
s_active_count++;
mBattle = client;
mBattle.Layer.LayerInit += Layer_LayerInit;
mBattle.Layer.ObjectEnter += Layer_ObjectEnter;
mBattle.Layer.ObjectLeave += Layer_ObjectLeave;
mBattle.Layer.MessageReceived += Layer_MessageReceived;
mBattle.Layer.DecorationChanged += Layer_DecorationChanged;
mBattle.Layer.OnChangeBGM += Layer_OnChangeBGM;
mEffectRoot = new GameObject("EffectNode");
RegistAllZoneEvent();
}
~BattleScene()
{
s_alloc_count--;
}
protected virtual void OnLoadMapFinish()
{
}
private void OnMapLoadFinish(bool success, GameObject o)
{
if (success)
{
mMapRoot = o;
InitDecoration();
}
}
public void Dispose()
{
if (!mDisposed)
{
OnDispose();
OnDisposeMapRoot();
mDisposed = true;
s_active_count--;
}
}
protected virtual void OnDisposeMapRoot()
{
GameObject.DestroyObject(mMapRoot);
}
protected virtual void OnDispose()
{
foreach (var elem in mBattleObjects)
{
elem.Value.Dispose();
}
mBattleObjects.Clear();
mBattle.Layer.LayerInit -= Layer_LayerInit;
mBattle.Layer.ObjectEnter -= Layer_ObjectEnter;
mBattle.Layer.ObjectLeave -= Layer_ObjectLeave;
mBattle.Layer.DecorationChanged -= Layer_DecorationChanged;
AssetObjectExt[] aoes = mEffectRoot.GetComponentsInChildren();
foreach (var elem in aoes)
{
EffectAutoDestroy[] scripts = elem.gameObject.GetComponents();
if (scripts.Length > 0)
{
foreach (var script in scripts)
{
script.DoDestroy();
}
}
else
{
BattleFactroy.Instance.GameObjectAdapter.Unload(elem);
}
}
GameObject.DestroyObject(mEffectRoot);
}
public void Update(float deltaTime)
{
if (!mDisposed)
{
OnUpdate(deltaTime);
}
}
protected virtual void OnUpdate(float deltaTime)
{
foreach (var elem in mBattleObjects)
{
elem.Value.Update(deltaTime);
}
}
#region Objects
private HashMap mBattleObjects = new HashMap();
private IComAIActor mActor;
public ComAICell GetBattleObject(uint id)
{
ComAICell outVal = null;
mBattleObjects.TryGetValue(id, out outVal);
return outVal;
}
public IComAIActor GetActor()
{
return mActor;
}
private void AddBattleObject(ComAICell obj)
{
if (obj != null)
{
mBattleObjects.Add(obj.ObjectID, obj);
if (obj is ComAIActor)
{
mActor = obj as ComAIActor;
}
OnComAICellAdded(obj);
}
}
private void RemoveBattleObject(uint id)
{
ComAICell outVal = mBattleObjects.RemoveByKey(id);
if (outVal != null)
{
OnComAICellRemoved(outVal);
outVal.Dispose();
}
}
protected virtual void OnComAICellAdded(ComAICell o) { }
protected virtual void OnComAICellRemoved(ComAICell o) { }
protected virtual void Layer_LayerInit(ZoneLayer layer)
{
BattleFactroy.Instance.TerrainAdapter.Load(layer.Data.FileName, OnMapLoadFinish);
BattleFactroy.Instance.SoundAdapter.PlayBGM(layer.Data.BGM);
}
private void Layer_ObjectEnter(CommonAI.ZoneClient.ZoneLayer layer, CommonAI.ZoneClient.ZoneObject obj)
{
AddBattleObject(BattleFactroy.Instance.CreateComAICell(this, obj));
}
private void Layer_ObjectLeave(CommonAI.ZoneClient.ZoneLayer layer, CommonAI.ZoneClient.ZoneObject obj)
{
RemoveBattleObject(obj.ObjectID);
}
#endregion
private void Layer_MessageReceived(ZoneLayer layer, CommonLang.Protocol.IMessage msg)
{
if (msg is CommonAI.Zone.ZoneEvent)
{
Action action = null;
if (mZoneEvens.TryGetValue(msg.GetType(), out action))
{
action(msg as CommonAI.Zone.ZoneEvent);
}
}
else if (msg is CommonAI.Zone.ObjectEvent)
{
var obj = GetBattleObject((msg as CommonAI.Zone.ObjectEvent).object_id);
if (obj != null)
{
obj.DoObjectEvent(msg as CommonAI.Zone.ObjectEvent);
}
}
}
private void Layer_OnChangeBGM(ZoneLayer layer, string filename)
{
BattleFactroy.Instance.SoundAdapter.PlayBGM(filename);
}
public virtual void PlayEffectWithZoneCoord(LaunchEffect eff
, float x, float y, float direct)
{
Vector3 pos = Extensions.ZonePos2NavPos(mBattle.Layer.Terrain.TotalHeight
, x, y, 0);
Quaternion rot = Extensions.ZoneRot2UnityRot(direct);
if (eff != null)
{
if (!string.IsNullOrEmpty(eff.SoundName))
{
if (eff.IsLoop)
{
BattleFactroy.Instance.SoundAdapter.PlaySound(eff.SoundName, eff.EffectTimeMS, pos);
}
else
{
BattleFactroy.Instance.SoundAdapter.PlaySound(eff.SoundName, pos);
}
}
//特效
if (!string.IsNullOrEmpty(eff.Name))
{
BattleFactroy.Instance.GameObjectAdapter.Load(eff.Name
, System.IO.Path.GetFileNameWithoutExtension(eff.Name)
, (succ, aoe) =>
{
if (succ)
{
if (IsDisposed && eff.BindBody)
{
BattleFactroy.Instance.GameObjectAdapter.Unload(aoe);
return;
}
OnLoadEffectSuccess(aoe, eff, pos, rot);
}
});
}
}
}
///
///
///
///
/// unity pos
/// unity rot
public virtual void PlayEffect(LaunchEffect eff, Vector3 pos, Quaternion rot)
{
if (eff != null)
{
//特效
if (!string.IsNullOrEmpty(eff.Name))
{
BattleFactroy.Instance.GameObjectAdapter.Load(eff.Name
, System.IO.Path.GetFileNameWithoutExtension(eff.Name)
, (succ, aoe) =>
{
if (succ)
{
if (IsDisposed && eff.BindBody)
{
BattleFactroy.Instance.GameObjectAdapter.Unload(aoe);
return;
}
OnLoadEffectSuccess(aoe, eff, pos, rot);
}
});
}
}
}
protected virtual void OnLoadEffectSuccess(AssetObjectExt aoe
, LaunchEffect eff, Vector3 pos, Quaternion rot)
{
aoe.gameObject.Parent(mEffectRoot);
aoe.gameObject.Position(pos);
aoe.gameObject.Rotation(rot);
var script = aoe.gameObject.AddComponent();
script.aoeHandler = aoe;
script.duration = eff.IsLoop ? eff.EffectTimeMS / 1000f : 0f;
}
}
}