using Unity.Netcode;
using Unity.Netcode.Components;
using UnityEngine;
using UnityEngine.InputSystem;
using System.Collections.Generic;
namespace Northbound
{
///
/// 상호작용 대상 없이 실행 가능한 액션들을 관리
///
public class PlayerActionSystem : NetworkBehaviour
{
[Header("Actions")]
public List actionComponents = new List();
[Header("Animation")]
public bool playAnimations = true;
private PlayerInputActions _inputActions;
private Dictionary _actions = new Dictionary();
private Animator _animator;
private NetworkAnimator _networkAnimator;
private NetworkPlayerController _networkPlayerController;
// 로컬 플레이어인지 확인
private bool IsLocalPlayer => _networkPlayerController != null && _networkPlayerController.IsLocalPlayer;
private ulong LocalPlayerId => _networkPlayerController != null ? _networkPlayerController.OwnerPlayerId : OwnerClientId;
private void Awake()
{
_animator = GetComponent();
_networkAnimator = GetComponent();
_networkPlayerController = GetComponent();
}
public override void OnNetworkSpawn()
{
// 액션 컴포넌트들을 딕셔너리에 등록 (모든 클라이언트에서)
foreach (var component in actionComponents)
{
if (component is IAction action)
{
_actions[action.GetActionName()] = action;
}
}
// _ownerPlayerId 변경 이벤트 구독
if (_networkPlayerController != null)
{
_networkPlayerController.OnOwnerChanged += OnOwnerPlayerIdChanged;
}
// 이미 로컬 플레이어면 입력 초기화
TryInitializeInput();
}
private void OnOwnerPlayerIdChanged(ulong newOwnerId)
{
TryInitializeInput();
}
private void TryInitializeInput()
{
if (!IsLocalPlayer) return;
if (_inputActions != null) return;
_inputActions = new PlayerInputActions();
_inputActions.Player.Attack.performed += OnAttack;
_inputActions.Enable();
}
public override void OnNetworkDespawn()
{
if (_networkPlayerController != null)
{
_networkPlayerController.OnOwnerChanged -= OnOwnerPlayerIdChanged;
}
if (_inputActions != null)
{
_inputActions.Player.Attack.performed -= OnAttack;
_inputActions.Disable();
_inputActions.Dispose();
}
}
private void OnAttack(InputAction.CallbackContext context)
{
ExecuteAction("Attack");
}
public void ExecuteAction(string actionName)
{
if (_actions.TryGetValue(actionName, out IAction action))
{
if (action.CanExecute(LocalPlayerId))
{
string animTrigger = action.GetActionAnimation();
// 서버에서 애니메이션 실행 (동기화를 위해)
if (playAnimations && !string.IsNullOrEmpty(animTrigger))
{
PlayAnimationServerRpc(animTrigger);
}
action.Execute(LocalPlayerId);
}
}
}
[Rpc(SendTo.Server)]
private void PlayAnimationServerRpc(string animTrigger)
{
if (_networkAnimator != null && !string.IsNullOrEmpty(animTrigger))
{
_networkAnimator.SetTrigger(animTrigger);
}
}
override public void OnDestroy()
{
if (_inputActions != null)
{
_inputActions.Dispose();
}
base.OnDestroy();
}
}
}