using System; using System.Collections; using System.Collections.Generic; using BITFALL.GameMode; using BITKit; using BITKit.Probability; using Cysharp.Threading.Tasks; using Quadtree; using Quadtree.Items; using UnityEngine; using YooAsset; using Random = UnityEngine.Random; namespace BITFALL.LootSystem { public class LootService : MonoBehaviour,ILootSystem { private class LootQuad:IItem> { public int Id { get; set; } public Bounds GetBounds() => Bounds; public Bounds Bounds { get; set; } public Node ParentNode { get; set; } public void QuadTree_Root_Initialized(IQuadtreeRoot> root) { } } private readonly QuadtreeRoot> _quadtreeRoot = new(default,Vector3.one*2048); [SerializeReference, SubclassSelector] private ITicker ticker; [SerializeField, ReadOnly] private int tickCount; [SerializeField, ReadOnly] private int count; private readonly Dictionary _lootQuads = new(); private bool _isBusy; private readonly List _lootTables = new(); private async void Start() { NodeQuery.AddRegisterListener(typeof(InfoLootSpawn), OnLootSpawnRegister); foreach (var x in NodeQuery.Query()) { OnLootSpawnRegister(x); } foreach (var x in YooAssets.GetAssetInfos(nameof(ScriptableLootTable))) { var assetHandle = YooAssets.LoadAssetAsync(x.Address); await assetHandle; if (destroyCancellationToken.IsCancellationRequested) return; _lootTables.Add(assetHandle.AssetObject.As()); } destroyCancellationToken.Register(Dispose); ticker.Add(OnTick); } private async void OnTick(float obj) { if (_isBusy||enabled is false) return; _isBusy = true; tickCount++; var cameraPosition = Camera.main.transform.position; await UniTask.SwitchToThreadPool(); var quads = _quadtreeRoot.Find(new Bounds(cameraPosition,Vector3.one*32)); await UniTask.SwitchToMainThread(); if (destroyCancellationToken.IsCancellationRequested) return; foreach (var quad in quads) { foreach (var item in GetValues()) { var so = item.GetAssetable(); var instance = Instantiate(so.GetPrefab(),quad.Bounds.center,Quaternion.identity); } } foreach (var x in quads) { _quadtreeRoot.Remove(x); } _isBusy = false; } private void OnLootSpawnRegister(object obj) { var info = (InfoLootSpawn) obj; var quad = new LootQuad() { Id = count++, Bounds = new Bounds(info.Position,info.Size) }; _quadtreeRoot.Insert(quad); _lootQuads.Add(quad.Id,quad); } private void Dispose() { ticker.Remove(OnTick); } public object GetValueObject(params IProbabilityProperty[] properties) { throw new System.NotImplementedException(); } public object[] GetValuesObject(params IProbabilityProperty[] properties) { throw new System.NotImplementedException(); } public IBasicItem GetValue(params IProbabilityProperty[] properties) { throw new System.NotImplementedException(); } public IBasicItem[] GetValues(params IProbabilityProperty[] properties) { var list = new List(); foreach (var table in _lootTables.Random().Tables) { if (table.Probability > Random.Range(0, 100)) { list.Add(table.Item); } } return list.ToArray(); } } }