using System; using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; using Sirenix.OdinInspector; namespace DDD { public static class RestaurantInteractionSubsystems { public static Dictionary TypeToSubsystem = new() { {InteractionType.RestaurantOrder, typeof(RestaurantOrderInteractionSubsystem)}, {InteractionType.RestaurantManagement, typeof(RestaurantManagementInteractionSubsystem)} }; } public class RestaurantInteractionComponent : MonoBehaviour, IInteractable, IInteractionSubsystemOwner { // Single interaction type [ValueDropdown("GetAllInteractionTypes")] [SerializeField] protected InteractionType _interactionType = InteractionType.None; [SerializeField] protected InteractionExecutionParameters _executionParameters = new InteractionExecutionParameters(1f); [SerializeField] protected InteractionDisplayParameters _displayParameters = new InteractionDisplayParameters(""); [SerializeField] protected GameFlowState _interactionAvailableFlows; [SerializeField] private Transform[] _aiInteractionPoints; [SerializeField] private bool autoInitialize = true; private Dictionary _subsystems = new(); private void Start() { if (autoInitialize) { InitializeInteraction(_interactionType); } } private static IEnumerable GetAllInteractionTypes() { return System.Enum.GetValues(typeof(InteractionType)) .Cast() .Where(x => x != InteractionType.All); // All은 제외 } public virtual bool CanInteract() { bool isInteractionVisible = !IsInteractionHidden(); bool hasValidSubsystem = true; if (HasSubsystem(_interactionType)) { hasValidSubsystem = GetSubsystem(_interactionType).CanInteract(); } return isInteractionVisible && hasValidSubsystem; } public virtual bool IsInteractionHidden() { var currentGameFlowState = GameFlowManager.Instance.GameFlowDataSo.CurrentGameState; var flowDisabled = (currentGameFlowState & _interactionAvailableFlows) == 0; return flowDisabled; } public virtual bool OnInteracted(IInteractor interactor, ScriptableObject payloadSo = null) { if (CanInteract() == false) { return false; } bool interactionResult = RestaurantInteractionEvents.RestaurantInteraction.RequestInteraction(interactor.GetInteractorGameObject(), GetInteractableGameObject(), GetInteractionType(), payloadSo, true); if (HasSubsystem(_interactionType)) { interactionResult &= GetSubsystem(_interactionType).OnInteracted(interactor, payloadSo); } return interactionResult; } public virtual InteractionType GetInteractionType() { return _interactionType; } public GameObject GetInteractableGameObject() { return gameObject; } public virtual void InitializeInteraction(InteractionType interactionType) { _interactionType = interactionType; InitializeSubsystems(); } private void InitializeSubsystems() { // Initialize Interaction Subsystems bool hasSubsystemType = RestaurantInteractionSubsystems.TypeToSubsystem.TryGetValue(_interactionType, out var subsystemType); if (!hasSubsystemType) return; var subsystem = gameObject.GetComponent(subsystemType) as IInteractionSubsystemObject; if (subsystem == null) { subsystem = gameObject.AddComponent(subsystemType) as IInteractionSubsystemObject; } _subsystems.Add(_interactionType, subsystem); subsystem?.InitializeSubsystem(); } private bool HasSubsystem(InteractionType interactionType) { return _subsystems.ContainsKey(interactionType); } private IInteractionSubsystemObject GetSubsystem(InteractionType interactionType) { return _subsystems.GetValueOrDefault(interactionType) as IInteractionSubsystemObject; } // 새로운 스트럭트 기반 메서드들 public virtual InteractionExecutionParameters GetExecutionParameters() { return _executionParameters; } public virtual InteractionDisplayParameters GetDisplayParameters() { return _displayParameters; } // 하위 호환성을 위한 기존 메서드들 public float GetRequiredHoldTime() { return _executionParameters.HoldTime; } public string GetInteractionMessageKey() { return _displayParameters.MessageKey; } public Vector3[] GetInteractionPoints() { if (_aiInteractionPoints == null || _aiInteractionPoints.Length == 0) { return new Vector3[] { transform.position }; } Vector3[] positions = new Vector3[_aiInteractionPoints.Length]; for (int i = 0; i < _aiInteractionPoints.Length; i++) { if (_aiInteractionPoints[i] != null) { positions[i] = _aiInteractionPoints[i].position; } else { positions[i] = transform.position; } } return positions; } public bool TryGetSubsystemObject(out IInteractionSubsystemObject subsystemObject) where T : Enum { foreach (var interactionSubsystemObject in _subsystems.Values) { if (interactionSubsystemObject is IInteractionSubsystemObject subsystem) { subsystemObject = subsystem; return true; } } subsystemObject = null; return false; } } }