123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400 |
- using CommonAI.RTS;
- using CommonAI.Zone;
- using CommonAI.Zone.Helper;
- using CommonAI.Zone.Instance;
- using CommonAI.Zone.ZoneEditor;
- using CommonAI.ZoneClient;
- using CommonLang;
- using CommonLang.ByteOrder;
- using CommonLang.IO;
- using CommonLang.IO.Attribute;
- using CommonLang.Log;
- using CommonLang.Property;
- using CommonLang.Protocol;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using CommonAI.ZoneServer;
- using System.Threading;
- using CommonLang.Concurrent;
- using System.Diagnostics;
- using CommonAIServer.Node.Interface;
- using CommonLang.Vector;
- using CommonAI.Data;
- namespace CommonAIServer.Node
- {
- public class BaseZoneNode : InstanceZoneListener
- {
- protected readonly static Logger log = LoggerFactory.GetLogger("ZoneNode");
- protected readonly object locker = new object();
- private readonly EditorTemplates mDataRoot;
- private readonly TemplateManager mTemplates;
- private readonly ZoneNodeConfig mConfig;
- private readonly int mUpdateInterval;
- private readonly int mUpdateIntervalLimit;
- //private readonly TimeInterval<ServerStatusB2C> mSyncServerStatus;
- protected SceneData mSceneData;
- private EditorScene mZone;
- private System.Threading.Timer mTimer;
- private long mLastUpdateTime;
- private long mProfileItemsTime;
- private bool mStarted = false;
- private bool mShutDown = false;
- private bool mIsDisposed = false;
- private bool mIsRunning = false;
- //更新次数,用于非重要数据慢刷新逻辑
- private int mTotalUpdateTimes = 0;
- //------------------------------------------------------------------------------------------------------------
- // 当前帧发送的消息队列 //
- private Queue<Event> mPostZoneEvents = new Queue<Event>();
- // 内部主线程命令 //
- private SyncMessageQueue<Task> mTasks = new SyncMessageQueue<Task>();
- //------------------------------------------------------------------------------------------------------------
- public BaseZoneNode(EditorTemplates data_root, ZoneNodeConfig cfg)
- {
- this.mDataRoot = data_root;
- this.mTemplates = data_root.Templates;
- this.mConfig = cfg.Clone();
- this.mUpdateInterval = mConfig.GAME_UPDATE_INTERVAL_MS;
- this.mUpdateIntervalLimit = mUpdateInterval * 2;
- //this.mSyncServerStatus = new TimeInterval<ServerStatusB2C>(new ServerStatusB2C(), cfg.TEST_POST_SERVER_INFO_INTERVAL_MS);
- this.EnableTimer = true;
- }
- public string Name { get { return (mSceneData != null) ? mSceneData.ToString() : "null"; } }
- public SceneData SceneData { get { return mSceneData; } }
- public EditorTemplates DataRoot { get { return mDataRoot; } }
- public TemplateManager Templates { get { return mTemplates; } }
- public int SceneID { get { return mSceneData.ID; } }
- public EditorScene Zone { get { return mZone; } }
- public bool IsStarted { get { return mStarted; } }
- public bool IsRunning { get { return mIsRunning; } }
- public bool IsDisposed { get { lock (this) { return mIsDisposed; } } }
- public bool EnableTimer { get; set; }
- protected ZoneNodeConfig Config { get { return mConfig; } }
- protected int UpdateInterval { get { return mUpdateInterval; } }
- protected IEnumerable<Event> PostZoneEvents { get { return mPostZoneEvents; } }
- //------------------------------------------------------------------------------------------------------------
- public override string ToString()
- {
- if (mSceneData != null)
- {
- return mSceneData.Name + "(" + mSceneData.ID + ")";
- }
- return "Unable to load scene";
- }
- public virtual bool CheckDropItem()
- {
- return false;
- }
- /// <summary>
- /// 获得指定名称的路点坐标
- /// </summary>
- /// <param name="name"></param>
- /// <returns></returns>
- public PointData GetScenePointData(string name)
- {
- foreach (PointData p in mSceneData.Points)
- {
- if (p.Name == name)
- {
- return p;
- }
- }
- return null;
- }
- //------------------------------------------------------------------------------------------------------------
- /// <summary>
- /// 房间初始化
- /// </summary>
- public void Start(SceneData data, GSCreateAreaData gsData, string bindGameSrvId)
- {
- lock (locker)
- {
- if (mStarted) { return; }
- this.mStarted = true;
- // 解析游戏服创建房间信息 //
- this.mSceneData = data;
- {
- // 构造战斗场景 //
- this.mZone = TemplateManager.Factory.CreateEditorScene(this.Templates, this, mSceneData, gsData, bindGameSrvId);
- // 非全屏同步,每个Client负责维护自己需要的队列 //
- this.mZone.SyncPos = false;
- this.mZone.IsSyncZ = false;
- // 半同步,场景不能大于255 //
- this.mZone.IsHalfSync = true;
- }
- // 创建游戏主循环Timer //
- this.mLastUpdateTime = CUtils.CurrentTimeMS;
- this.mProfileItemsTime = this.mLastUpdateTime + 60000;
- this.mIsRunning = true;
- this.timer_start();
- this.QueueTask(() =>
- {
- OnStarted();
- if (event_OnZoneStart != null)
- {
- event_OnZoneStart.Invoke(this);
- }
- });
- }
- }
- /// <summary>
- /// 开始异步关闭房间
- /// </summary>
- public void Stop()
- {
- lock (locker)
- {
- mShutDown = true;
- }
- }
- //------------------------------------------------------------------------------------------------------------
- protected virtual void OnStarted() { }
- protected virtual void OnStopped() { }
- protected virtual void OnZoneUpdate(bool slowRefresh) { }
- //protected virtual void OnTestUpdate(int intervalMS)
- //{
- // if (mSyncServerStatus.Update(intervalMS))
- // {
- // mSyncServerStatus.Tag.Update(Process.GetCurrentProcess());
- // mPostZoneEvents.Enqueue(mSyncServerStatus.Tag);
- // }
- //}
- protected virtual void OnBeginUpdate() { }
- protected virtual void OnEndUpdate() { }
- protected virtual void OnError(Exception err)
- {
- if (mConfig.TEST)
- {
- mPostZoneEvents.Enqueue(new ServerExceptionB2C(err.Message + " : " + this.ToString(), err.StackTrace));
- }
- }
- protected virtual void OnDispose() { }
- /// <summary>
- /// 当收到从场景来的消息(预过滤发送给客户端)
- /// </summary>
- /// <param name="e"></param>
- /// <returns>True截断消息</returns>
- protected virtual bool OnMessageHandlerFromInstanceZone(Event e) { return false; }
- //------------------------------------------------------------------------------------------------------------
- private void timer_start()
- {
- if (EnableTimer)
- {
- this.mTimer = new System.Threading.Timer(do_update, this, this.mUpdateInterval, this.mUpdateInterval);
- }
- }
- // private void timer_update(object obj)
- // {
- // ThreadPool.QueueUserWorkItem(do_update, this);
- // }
- private void timer_exit()
- {
- if (this.mTimer != null)
- {
- this.mTimer.Dispose();
- this.mTimer = null;
- }
- }
- private void do_update(object obj)
- {
- lock (locker)
- {
- bool slowUpdate = true;
- if (!mIsRunning) return;
- Stopwatch stopwatch = Stopwatch.StartNew();
- try
- {
- CommonLang.CUtils.localTimeMS = CommonLang.CUtils.CurrentTimeMS;
- CommonLang.CUtils.S_LOCAL_TIMESTAMPMS = CommonLang.TimeUtil.GetTimestampMS();
- if (mLastUpdateTime == 0)
- {
- mLastUpdateTime = CommonLang.CUtils.localTimeMS;
- }
- int intervalMS = (int)(CommonLang.CUtils.localTimeMS - mLastUpdateTime);
- mLastUpdateTime = CommonLang.CUtils.localTimeMS;
- intervalMS = Math.Min(intervalMS, mUpdateIntervalLimit);
- slowUpdate = this.ZoneUpdate(intervalMS);
- }
- catch (Exception err)
- {
- log.Error(err.Message, err);
- OnError(err);
- }
- finally
- {
- stopwatch.Stop();
- if (mIsRunning && stopwatch.ElapsedMilliseconds > mUpdateIntervalLimit)
- {
- log.WarnFormat("update overload at scene[{0}] : stopwatch time {1} units = {2} spells = {3} items = {4}, UUID = {5}, {6}",
- mSceneData, stopwatch.ElapsedMilliseconds, mZone.AllUnitsCount, mZone.AllSpellsCount, mZone.AllItemsCount, mZone.UUID, mZone.GetInfo());
- }
- //else if(mZone != null && slowUpdate & this.mProfileItemsTime < CommonLang.CUtils.localTimeMS && (mZone.AllUnitsCount > 200 || mZone.AllSpellsCount > 200 || mZone.AllItemsCount > 200))
- //{
- // log.WarnFormat("场景单位数量预警[{0}] : stopwatch time {1} units = {2} spells = {3} items = {4}, UUID = {5}",
- // mSceneData, stopwatch.ElapsedMilliseconds, mZone.AllUnitsCount, mZone.AllSpellsCount, mZone.AllItemsCount, mZone.UUID);
- //}
- }
- }
- }
- /// <summary>
- /// 战斗场景主逻辑更新//
- /// </summary>
- /// <param name="intervalMS"></param>
- public virtual bool ZoneUpdate(int intervalMS)
- {
- bool slowUpdate = false;
- //从效率出发,Unit位置更新,及时推送到客户端,AOI进出则不需要每帧检测
- lock (locker)
- {
- if (mIsRunning)
- {
- mTasks.ProcessMessages(do_task);
- mPostZoneEvents.Clear();
- OnBeginUpdate();
- if (intervalMS > 0)
- {
- try
- {
- mTotalUpdateTimes++;
- if(mTotalUpdateTimes > GlobalData.ZONE_UPDATE_SLOW)
- {
- mTotalUpdateTimes = 0;
- slowUpdate = true;
- }
- mZone.Update(intervalMS, slowUpdate);
- }
- catch (Exception err)
- {
- log.Error("zoneUpdateCatch: " + mZone.GetSceneID() + ", " + err.Message, err);
- OnError(err);
- }
- finally
- {
- this.OnZoneUpdate(slowUpdate);
- }
- }
- //if (mConfig.TEST)
- //{
- // OnTestUpdate(intervalMS);
- //}
- OnEndUpdate();
- if (mShutDown)
- {
- this.mIsRunning = false;
- try
- {
- timer_exit();
- OnStopped();
- if (event_OnZoneStop != null)
- {
- event_OnZoneStop.Invoke(this);
- }
- }
- catch (Exception err)
- {
- log.Error(err.Message, err);
- OnError(err);
- }
- try
- {
- this.OnDispose();
- if (mZone != null)
- {
- this.mZone.Dispose();
- }
- if (event_OnZoneDisposed != null)
- {
- event_OnZoneDisposed.Invoke(this);
- }
- }
- catch (Exception err)
- {
- log.Error(err.Message, err);
- OnError(err);
- }
- finally
- {
- this.DisposeEvents();
- this.mIsDisposed = true;
- }
- }
- }
- }
- return slowUpdate;
- }
- //---------------------------------------------------------------------------------------
- void InstanceZoneListener.onEventHandler(Event e)
- {
- if (!OnMessageHandlerFromInstanceZone(e))
- {
- mPostZoneEvents.Enqueue(e);
- }
- }
- protected internal delegate void Task();
- /// <summary>
- /// 保证在Task内部执行的代码线程安全
- /// </summary>
- /// <param name="task"></param>
- protected internal void QueueTask(Task task)
- {
- mTasks.Enqueue(task);
- }
- private void do_task(Task task)
- {
- if (task != null)
- {
- task.Invoke();
- }
- }
- //---------------------------------------------------------------------------------------------------
- protected virtual void DisposeEvents()
- {
- this.event_OnZoneStart = null;
- this.event_OnZoneStop = null;
- this.event_OnZoneDisposed = null;
- }
- private Action<BaseZoneNode> event_OnZoneStart;
- private Action<BaseZoneNode> event_OnZoneStop;
- private Action<BaseZoneNode> event_OnZoneDisposed;
- public event Action<BaseZoneNode> OnZoneStart { add { event_OnZoneStart += value; } remove { event_OnZoneStart -= value; } }
- public event Action<BaseZoneNode> OnZoneStop { add { event_OnZoneStop += value; } remove { event_OnZoneStop -= value; } }
- public event Action<BaseZoneNode> OnZoneDisposed { add { event_OnZoneDisposed += value; } remove { event_OnZoneDisposed -= value; } }
- //---------------------------------------------------------------------------------------------------
- }
- }
|