ProjectDDD/Assets/_DDD/_Scripts/RestaurantEvent/RestaurantInteractionComponent.cs

193 lines
6.7 KiB
C#

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<InteractionType, Type> 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<InteractionType, IInteractionSubsystemObject> _subsystems = new();
private void Start()
{
if (autoInitialize)
{
InitializeInteraction(_interactionType);
}
}
private static IEnumerable GetAllInteractionTypes()
{
return System.Enum.GetValues(typeof(InteractionType))
.Cast<InteractionType>()
.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 causerPayload = null)
{
if (CanInteract() == false)
{
return false;
}
bool interactionResult = RestaurantInteractionEvents.RestaurantInteraction.RequestInteraction(interactor.GetInteractorGameObject(),
GetInteractableGameObject(), GetInteractionType(), causerPayload, GetPayload(), true);
if (HasSubsystem(_interactionType))
{
interactionResult &= GetSubsystem(_interactionType).OnInteracted(interactor, causerPayload);
}
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;
}
private bool TryGetSubsystem(InteractionType interactionType, out IInteractionSubsystemObject subsystem)
{
return _subsystems.TryGetValue(interactionType, out subsystem);
}
// 새로운 스트럭트 기반 메서드들
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 ScriptableObject GetPayload()
{
return TryGetSubsystem(_interactionType, out var subsystem) ? subsystem.GetPayload() : null;
}
public bool TryGetSubsystemObject<T>(out IInteractionSubsystemObject<T> subsystemObject) where T : Enum
{
foreach (var interactionSubsystemObject in _subsystems.Values)
{
if (interactionSubsystemObject is IInteractionSubsystemObject<T> subsystem)
{
subsystemObject = subsystem;
return true;
}
}
subsystemObject = null;
return false;
}
}
}