using System;
using System.Collections.Generic;
using System.Reflection;
using CombatLibrary.CombatLibrary.CombatCore.Utility;
using Fort23.Core;
#if !COMBAT_SERVER
using Core.Pool.GPool;
using UnityEngine;
using Object = UnityEngine.Object;
#endif
namespace Fort23.UTool
{
public class GameObjectQueue
{
public string poolName
{
get { return _poolName; }
}
private bool _isDis;
private string _poolName;
private string _prefabName;
private int maxCount = -1;
#if !COMBAT_SERVER
///
/// 池子的父亲
///
private AssetHandle _PoolObjectFather;
public bool isOne;
private readonly List _usePool = new List();
private readonly List _queue = new List();
private readonly List _destroyPool = new List();
private readonly List _delayHide = new List();
public int initCopunt;
private bool _isSetMaxCount;
public void Init(string poolName, string prefabName)
{
_poolName = poolName;
_prefabName = prefabName;
}
public async CTask Enqueue(IGObjectPoolInterface poolInterface, bool isNotAwaitDelay = false)
{
if (poolInterface == null || poolInterface.own == null)
{
return;
}
if (_queue.Contains(poolInterface))
{
return;
}
if (_delayHide.Contains(poolInterface))
{
return;
}
_delayHide.Add(poolInterface);
if (!isNotAwaitDelay)
{
await poolInterface.DelayHide();
}
if (_isDis)
{
return;
}
_delayHide.Remove(poolInterface);
poolInterface.isUse = false;
_usePool.Remove(poolInterface);
if (poolInterface.own != null)
{
poolInterface.DormancyObj();
this._queue.Add(poolInterface);
}
}
public void AddDestroy(IGObjectPoolInterface poolInterface, bool immediately = false)
{
if (poolInterface.own == null)
{
return;
}
if (!_destroyPool.Contains(poolInterface))
{
if (immediately)
{
poolInterface.DestroyTimer = null;
GameObjectDestroyPool.Instance.DestroyObject(poolInterface.own);
}
else
{
TimerComponent.Instance.Remove(poolInterface.DestroyTimer);
poolInterface.DestroyTimer =
TimerComponent.Instance.AddTimer(6000, delegate
{
_destroyPool.Remove(poolInterface);
poolInterface.DestroyTimer = null;
GameObjectDestroyPool.Instance.DestroyObject(poolInterface.own);
});
_destroyPool.Add(poolInterface);
}
}
}
public void DormancyPool()
{
List alliG = new List();
IGObjectPoolInterface[] all = _usePool.ToArray();
if (all != null)
{
alliG.AddRange(all);
}
for (int i = 0; i < alliG.Count; i++)
{
IGObjectPoolInterface poolInterface = alliG[i];
Enqueue(poolInterface);
}
// _usePool.Clear();
}
public async CTask Preset(Clock clock, bool isUseSynchronous) where T : IGObjectPoolInterface
{
DormancyPool();
for (int i = 0; i < Count; i++)
{
IGObjectPoolInterface poolInterface = _queue[i];
DisposePoolEntity(poolInterface);
poolInterface.Preset();
}
for (int i = 0; i < _usePool.Count; i++)
{
IGObjectPoolInterface poolInterface = _usePool[i];
DisposePoolEntity(poolInterface);
poolInterface.Preset();
}
for (int i = 0; i < _destroyPool.Count; i++)
{
DisposePoolEntity(_destroyPool[i]);
}
_destroyPool.Clear();
T OBJ = await Dequeue(true, clock, isUseSynchronous);
Enqueue(OBJ, true);
}
private async CTask LoadAsset(Clock clock, bool isUseSynchronous)
{
if (AssetBundleLoadManager.Instance != null)
{
CTask cTask =
AssetBundleLoadManager.Instance.LoadAssetAsyncTask(_prefabName, clock: clock,
isUseSynchronous: isUseSynchronous);
AssetHandle assetHandle = await cTask;
return assetHandle;
}
return null;
}
public T DequeuForSynchronize(GameObject gameObject, bool isActive) where T : IGObjectPoolInterface
{
if (_queue.Count <= 0)
{
return CreateInstance(isActive, gameObject);
}
if (_destroyPool.Count > 0)
{
for (int i = 0; i < _destroyPool.Count; i++)
{
DisposePoolEntity(_destroyPool[i]);
}
_destroyPool.Clear();
}
for (int i = 0; i < _queue.Count; i++)
{
if (_queue[i].own == null)
{
_queue.RemoveAt(i);
i--;
continue;
}
else
{
IGObjectPoolInterface objectPoolInterface = this._queue[0];
_queue.RemoveAt(0);
UseObject(objectPoolInterface, isActive);
return (T)objectPoolInterface;
}
}
return CreateInstance(isActive, gameObject);
}
public async CTask Dequeue(bool isActive, Clock clock, bool isUseSynchronous)
where T : IGObjectPoolInterface
{
if (maxCount > 0 && _usePool.Count > maxCount)
{
return default;
}
for (int i = 0; i < _queue.Count; i++)
{
if (_queue[i].own == null)
{
_queue.RemoveAt(i);
i--;
continue;
}
else
{
IGObjectPoolInterface objectPoolInterface = this._queue[i];
if (objectPoolInterface.own == null)
{
continue;
}
_queue.RemoveAt(i);
UseObject(objectPoolInterface, isActive);
return (T)objectPoolInterface;
}
}
bool isUsePoolObject = false;
if ((_PoolObjectFather == null || _PoolObjectFather.IsNull()) && !string.IsNullOrEmpty(_prefabName))
{
using (await CoroutineLockComponent.Instance.Wait(poolName, 20000))
{
if (_PoolObjectFather == null)
{
_PoolObjectFather = await LoadAsset(clock, isUseSynchronous);
isUsePoolObject = true;
}
}
}
// if (clock != null && clock.isBreak)
// {
// if (isUsePoolObject)
// {
// Debug.LogError("已打断,但是有初始化数据" + _PoolObjectFather);
// }
// // return default;
// }
if (_queue.Count <= 0)
{
AssetHandle assetHandle = _PoolObjectFather;
if (!isUsePoolObject)
{
assetHandle = await _PoolObjectFather.InstantiateSync(isUseSynchronous);
}
// AssetHandle assetHandle = isUsePoolObject ? _PoolObjectFather : _PoolObjectFather;
return CreateInstance(isActive, assetHandle);
}
if (_destroyPool.Count > 0)
{
for (int i = 0; i < _destroyPool.Count; i++)
{
DisposePoolEntity(_destroyPool[i]);
}
_destroyPool.Clear();
}
AssetHandle assetHandle2 = _PoolObjectFather;
if (!isUsePoolObject)
{
assetHandle2 = await _PoolObjectFather.InstantiateSync(isUseSynchronous);
}
assetHandle2 = await assetHandle2.InstantiateSync(isUseSynchronous);
return CreateInstance(isActive, assetHandle2);
}
private T CreateInstance(bool isActive, AssetHandle assetHandle) where T : IGObjectPoolInterface
{
if (assetHandle == null)
{
return default;
}
T poolInerface = Activator.CreateInstance();
GameObject go = assetHandle.AssetObject();
GameObjectEntity objectEntity = go.GetComponent();
if (objectEntity == null)
{
objectEntity = go.AddComponent();
}
objectEntity.IgObjectPoolInterface = poolInerface;
objectEntity.OnDestroyCallBack = DestroyEntity;
poolInerface.SetGameObject(go);
poolInerface.poolObjName = _poolName;
poolInerface.AssetHandle = assetHandle;
UseObject(poolInerface, isActive);
initCopunt++;
return poolInerface;
}
private T CreateInstance(bool isActive, GameObject gameObject) where T : IGObjectPoolInterface
{
if (gameObject == null)
{
return default;
}
T poolInerface = Activator.CreateInstance();
GameObject go = GameObject.Instantiate(gameObject);
GameObjectEntity objectEntity = go.GetComponent();
if (objectEntity == null)
{
objectEntity = go.AddComponent();
}
objectEntity.IgObjectPoolInterface = poolInerface;
objectEntity.OnDestroyCallBack = DestroyEntity;
poolInerface.SetGameObject(go);
poolInerface.poolObjName = _poolName;
poolInerface.AssetHandle = null;
UseObject(poolInerface, isActive);
initCopunt++;
return poolInerface;
}
private void DestroyEntity(IGObjectPoolInterface poolInterface)
{
if (poolInterface != null)
{
_queue.Remove(poolInterface);
_usePool.Remove(poolInterface);
}
else
{
return;
}
DisposePoolEntity(poolInterface);
// poolInterface.DormancyObj();
poolInterface.DestroyObj();
poolInterface.AssetHandle?.Release();
if (poolInterface.AssetHandle == _PoolObjectFather)
{
_PoolObjectFather = null;
if (_queue.Count > 0)
{
_PoolObjectFather = _queue[0].AssetHandle;
}
}
if (_queue.Count <= 0 && _usePool.Count <= 0) //池子已经被释放完,把父物体也释掉
{
GObjectPool.Instance.DestroyPool(poolName);
}
}
private void UseObject(IGObjectPoolInterface objectPoolInterface, bool isActive)
{
if (!_isSetMaxCount)
{
_isSetMaxCount = true;
GObjectPoolMaxConfig gObjectPoolMaxConfig =
objectPoolInterface.own.GetComponent();
if (gObjectPoolMaxConfig != null)
{
maxCount = gObjectPoolMaxConfig.maxCount;
}
}
_usePool.Add(objectPoolInterface);
DisposePoolEntity(objectPoolInterface);
// TimerComponent.Instance.Remove(objectPoolInterface.DestroyTimer);
// GameObjectDestroyPool.Instance.RomoveDestroyObject(objectPoolInterface.own);
objectPoolInterface.isUse = true;
objectPoolInterface.ResetData();
if (isActive)
{
objectPoolInterface.ActiveObj();
}
}
public int Count => this._queue.Count;
public void Dispose()
{
_isDis = true;
for (int i = 0; i < Count; i++)
{
IGObjectPoolInterface poolInterface = _queue[i];
DisposePoolEntity(poolInterface);
if (poolInterface.own != null)
{
GameObjectEntity gameObjectEntity = poolInterface.own.GetComponent();
if (gameObjectEntity != null)
{
gameObjectEntity.IgObjectPoolInterface = null;
gameObjectEntity.OnDestroyCallBack = null;
}
poolInterface.own.SetActive(false);
poolInterface.DormancyObj();
poolInterface.DestroyObj();
poolInterface.AssetHandle?.Release();
GameObjectDestroyPool.Instance.DestroyObject(poolInterface.own);
}
}
for (int i = 0; i < _delayHide.Count; i++)
{
IGObjectPoolInterface poolInterface = _delayHide[i];
DisposePoolEntity(poolInterface);
if (poolInterface.own != null)
{
GameObjectEntity gameObjectEntity = poolInterface.own.GetComponent();
if (gameObjectEntity != null)
{
gameObjectEntity.IgObjectPoolInterface = null;
gameObjectEntity.OnDestroyCallBack = null;
}
poolInterface.own.SetActive(false);
poolInterface.DormancyObj();
poolInterface.DestroyObj();
poolInterface.AssetHandle?.Release();
GameObjectDestroyPool.Instance.DestroyObject(poolInterface.own);
}
}
for (int i = 0; i < _usePool.Count; i++)
{
IGObjectPoolInterface poolInterface = _usePool[i];
DisposePoolEntity(poolInterface);
if (poolInterface.own != null)
{
GameObjectEntity gameObjectEntity = poolInterface.own.GetComponent();
if (gameObjectEntity != null)
{
gameObjectEntity.IgObjectPoolInterface = null;
gameObjectEntity.OnDestroyCallBack = null;
}
poolInterface.own.SetActive(false);
poolInterface.DormancyObj();
poolInterface.DestroyObj();
GameObjectDestroyPool.Instance.DestroyObject(poolInterface.own);
}
}
_PoolObjectFather = null;
_delayHide.Clear();
_queue.Clear();
_destroyPool.Clear();
_usePool.Clear();
}
private void DisposePoolEntity(IGObjectPoolInterface poolInterface)
{
_destroyPool.Remove(poolInterface);
TimerComponent.Instance.Remove(poolInterface.DestroyTimer);
GameObjectDestroyPool.Instance.RomoveDestroyObject(poolInterface.own);
poolInterface.DestroyTimer = null;
}
#endif
}
public class GObjectPool
{
private static GObjectPool _instance;
public static GObjectPool Instance
{
get
{
if (_instance == null)
{
_instance = new GObjectPool();
}
return _instance;
}
}
///
/// key是gameObject.name.GetHashCode();
///
private readonly Dictionary _dictionary = new Dictionary();
///
/// 在ab包里面的东西,都可以通过这个方法获取
///
///
///
///
///
///
///
///
public async CTask FetchAsync(string prefabName, System.Action callBack = null, Clock clock = null,
bool Prestore = false, string poolName = null, bool isUseSynchronous = false)
where T : IGObjectPoolInterface
{
if (!prefabName.Contains(".prefab"))
{
prefabName += ".prefab";
}
T poolInerface = await FetchObjectAsync(prefabName, clock, Prestore, poolName,
isUseSynchronous: isUseSynchronous);
if (Prestore)
{
callBack?.Invoke(default);
return default;
}
if (poolInerface == null)
{
callBack?.Invoke(default);
return default;
}
if (clock != null && clock.isBreak)
{
Recycle(poolInerface);
callBack?.Invoke(default);
return default;
}
callBack?.Invoke(poolInerface);
return poolInerface;
}
private string GetPoolName(string name)
{
return name + typeof(T);
}
#if !COMBAT_SERVER
public T FetchAsyncForGameObject(GameObject gameObject, string poolName
) where T : IGObjectPoolInterface
{
T poolInerface = Fetch(poolName, gameObject);
if (poolInerface == null)
{
return default;
}
return poolInerface;
}
public T Fetch(string poolName, GameObject gameObject, bool isActive = true) where T : IGObjectPoolInterface
{
string newPoolName = GetPoolName(poolName);
GameObjectQueue gameObjectQueue = null;
if (!this._dictionary.TryGetValue(newPoolName, out gameObjectQueue))
{
gameObjectQueue = EnterPool(newPoolName, null);
}
return gameObjectQueue.DequeuForSynchronize(gameObject, isActive);
}
#endif
private async CTask FetchObjectAsync(string prefabName, Clock clock, bool Prestore, string poolName,
bool isActive = true, bool isUseSynchronous = false) where T : IGObjectPoolInterface
{
#if !COMBAT_SERVER
try
{
GameObjectQueue gameObjectQueue = null;
poolName = poolName == null ? prefabName : poolName;
poolName = GetPoolName(poolName);
// 加一个协程锁,让同时加载资源的时候lock住
// using (await CoroutineLockComponent.Instance.Wait(poolName,20000))
{
if (clock != null && clock.isBreak)
{
return default;
}
if (this._dictionary.TryGetValue(poolName, out gameObjectQueue))
{
if (Prestore)
{
await gameObjectQueue.Preset(clock, isUseSynchronous);
return default;
}
return await gameObjectQueue.Dequeue(isActive, clock, isUseSynchronous);
}
if (!this._dictionary.TryGetValue(poolName, out gameObjectQueue))
{
gameObjectQueue = EnterPool(poolName, prefabName);
}
if (gameObjectQueue == null)
{
return default;
}
if (Prestore)
{
await gameObjectQueue.Preset(clock, isUseSynchronous);
return default;
}
return await gameObjectQueue.Dequeue(isActive, clock, isUseSynchronous);
}
}
catch (Exception e)
{
LogTool.Exception(e);
return default;
}
#else
return default;
#endif
}
#if !COMBAT_SERVER
private Transform _parent;
private GameObjectQueue EnterPool(string poolName, string prefabName) where T : IGObjectPoolInterface
{
if (_parent == null)
{
_parent = new GameObject().transform;
_parent.gameObject.name = "Pool";
}
GameObjectQueue queue = new GameObjectQueue();
queue.Init(poolName, prefabName);
_dictionary.Add(poolName, queue);
return queue;
}
#endif
public void Recycle(IGObjectPoolInterface poolInterface)
{
if (poolInterface == null)
{
return;
}
#if !COMBAT_SERVER
GameObjectQueue queue;
if (!this._dictionary.TryGetValue(poolInterface.poolObjName, out queue))
{
LogTool.Error("不再池子之中 " + poolInterface.poolObjName);
return;
}
queue.Enqueue(poolInterface);
#endif
}
public async CTask Recycle(IGObjectPoolInterface poolInterface, bool isNotAwaitDelay)
{
if (poolInterface == null)
{
return;
}
#if !COMBAT_SERVER
GameObjectQueue queue;
if (!this._dictionary.TryGetValue(poolInterface.poolObjName, out queue))
{
LogTool.Error("不再池子之中 " + poolInterface.poolObjName);
return;
}
await queue.Enqueue(poolInterface, isNotAwaitDelay);
#endif
}
public void RecycleForDestroy(IGObjectPoolInterface poolInterface, bool immediately = false)
{
if (poolInterface == null)
{
return;
}
#if !COMBAT_SERVER
GameObjectQueue queue;
if (!this._dictionary.TryGetValue(poolInterface.poolObjName, out queue))
{
LogTool.Error("不再池子之中 " + poolInterface.poolObjName);
return;
}
queue.Enqueue(poolInterface);
queue.AddDestroy(poolInterface, immediately);
#endif
}
public void DestroyPool(string poolObjName)
{
#if !COMBAT_SERVER
GameObjectQueue queue;
if (!this._dictionary.TryGetValue(poolObjName, out queue))
{
// LogTool.Warning("没有这个池子 " + poolObjName);
return;
}
_dictionary.Remove(poolObjName);
queue.Dispose();
#endif
}
///
/// 休眠一个池子
///
///
public void DormancyPool(string poolName)
{
#if !COMBAT_SERVER
GameObjectQueue queue;
if (!this._dictionary.TryGetValue(poolName, out queue))
{
string poolObjName = GetPoolName(poolName);
if (!this._dictionary.TryGetValue(poolObjName, out queue))
{
// LogTool.Warning("没有这个池子 " + poolObjName);
return;
}
}
queue?.DormancyPool();
#endif
}
///
/// 清除所有池子
///
public void Clear()
{
Dispose();
}
///
/// 清除所有池子
///
public void Dispose()
{
#if !COMBAT_SERVER
foreach (KeyValuePair kv in this._dictionary)
{
kv.Value.Dispose();
}
this._dictionary.Clear();
_instance = null;
#endif
}
}
}