using System; using System.Collections; using System.Collections.Generic; using System.Linq; using BlueWater.Npcs.Customers; using BlueWater.Utility; using Sirenix.OdinInspector; using UnityEngine; using Random = UnityEngine.Random; namespace BlueWater.Tycoons { public class CustomerManager : Singleton { [Title("손님 데이터")] [field: SerializeField, Required] public CustomerDataSo CustomerDataSo { get; private set; } [SerializeField, Required] private Customer _customerPrefab; [SerializeField, Required] private Transform _customerSpawnTransform; [Title("대기중인 손님 정보")] [SerializeField] private float _checkEmptySeatInterval = 0.5f; [field: SerializeField] public List InstanceCustomers { get; private set; } = new(); [ShowInInspector] private Queue _waitingCustomers = new(); private CustomerTableController _customerTableController; private Coroutine _findEmptySeatCoroutineInstance; public Action OnInstantiateCustomer; private void Start() { _customerTableController = TycoonManager.Instance.CustomerTableController; } public void InstantiateCustomer() { var newCustomer = Instantiate(_customerPrefab, _customerSpawnTransform.position, Quaternion.identity); newCustomer.Initialize(); RegisterCustomer(newCustomer); OnInstantiateCustomer?.Invoke(newCustomer); } public void TryFindEmptySeat(Customer customer) { // 이미 대기열에 사람들이 있는 경우, 새로운 손님도 바로 대기열에 넣는다. if (_waitingCustomers.Count > 0) { _waitingCustomers.Enqueue(customer); return; } // 대기열에는 아무도 없는 경우 var emptySeat = _customerTableController.FindEmptySeat(); if (emptySeat == null) { // 내가 첫 대기열 손님이 된다. _waitingCustomers.Enqueue(customer); Utils.StartUniqueCoroutine(this, ref _findEmptySeatCoroutineInstance, CheckEmptySeatCoroutine()); return; } customer.SetTableSeat(emptySeat); emptySeat.ReserveSeat(); customer.AIMovement.Move(emptySeat.SeatTransform.position); } private IEnumerator CheckEmptySeatCoroutine() { var checkEmptySeatInterval = new WaitForSeconds(_checkEmptySeatInterval); while (_waitingCustomers.Count > 0) { var emptySeat = _customerTableController.FindEmptySeat(); if (emptySeat != null) { var customer = _waitingCustomers.Dequeue(); customer.SetTableSeat(emptySeat); emptySeat.ReserveSeat(); customer.AIMovement.Move(emptySeat.SeatTransform.position); continue; } yield return checkEmptySeatInterval; } _findEmptySeatCoroutineInstance = null; } public void RegisterCustomer(Customer customer) { Utils.RegisterList(InstanceCustomers, customer); } public void UnregisterCustomer(Customer customer) { Utils.UnregisterList(InstanceCustomers, customer); } public CustomerData GetRandomCustomerData() { var customerDataCount = CustomerDataSo.GetDataCount(); if (customerDataCount == 0) { Debug.LogError($"{CustomerDataSo}의 값이 비어있습니다."); return null; } return CustomerDataSo.GetRandomValue(); } public List GetCurrentCustomers() => InstanceCustomers; } }