using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using Cysharp.Threading.Tasks; using kcp2k; using Quadtree; using Quadtree.Items; using UnityEngine; using UnityEngine.Pool; namespace BITKit.Sensors { public struct ClassicNoise{} public class AudioSensorService : MonoBehaviour { public static readonly HashSet LockHash = new(); public class AudioSensorData:IItem> { public int Id; public Vector3 Position; public float Radius; public Transform Transform; public Bounds Bounds; public ITag Tag; public object NoiseType; public float ExpirationTime; public Bounds GetBounds() => Bounds; public Node ParentNode { get; set; } public void QuadTree_Root_Initialized(IQuadtreeRoot> root){} } internal static readonly QuadtreeRoot> QuadtreeRoot = new(default, Vector3.one * 2048); private static readonly Pool pool = new(()=>new AudioSensorData(), x=>{}, 1000); private static readonly ConcurrentQueue registerQueue = new(); private static int count; private static readonly Queue freeIds = new(); private static readonly ConcurrentDictionary dictionary = new(); public static void MakeNoise(Vector3 position, Transform transform, float radius = 1, object noiseType = null) { var data = pool.Take(); data.Id = count++; data.Position = position; data.Transform = transform; data.Bounds = new Bounds(position, Vector3.one * 1); if (transform) data.Tag = transform.GetComponent(); data.Radius = radius; data.ExpirationTime = Time.time + 0.5f; registerQueue.Enqueue(data); } [SerializeReference, SubclassSelector] private ITicker ticker; private void Start() { ticker.Add(OnTick); destroyCancellationToken.Register(Dispose); pool.Clear(); } private void Dispose() { registerQueue.Clear(); ticker.Remove(OnTick); QuadtreeRoot.Clear(); } private void OnTick(float obj) { if (LockHash.Count > 0) return; while (registerQueue.TryDequeue(out var data)) { if (data.ExpirationTime < Time.time) { pool.Return(data); continue; } QuadtreeRoot.Insert(data); dictionary.TryAdd(data.Id, data); } var currentTime = Time.time; foreach (var (id, data) in dictionary) { if (data.ExpirationTime > currentTime) continue; freeIds.Enqueue(id); QuadtreeRoot.Remove(data); pool.Return(data); } while (freeIds.TryDequeue(out var id)) { dictionary.TryRemove(id, out _); } } } }