using Unity.Netcode;
using UnityEngine;
namespace Northbound
{
///
/// 상호작용 대상 - 자원 채집
///
public class Resource : NetworkBehaviour, IInteractable
{
[Header("Resource Settings")]
public int maxResources = 100;
public int resourcesPerGathering = 10;
public float gatheringCooldown = 2f;
public string resourceName = "광석";
[Header("Resource Recharge")]
public float rechargeInterval = 5f; // 충전 주기 (초)
public int rechargeAmount = 10; // 주기당 충전량
[Header("Animation")]
public string interactionAnimationTrigger = "Mining"; // 플레이어 애니메이션 트리거
[Header("Equipment")]
public EquipmentData equipmentData = new EquipmentData
{
socketName = "RightHand",
equipmentPrefab = null, // Inspector에서 곡괭이 프리팹 할당
attachOnStart = true,
detachOnEnd = true
};
[Header("Visual")]
public GameObject gatheringEffectPrefab;
public Transform effectSpawnPoint;
private NetworkVariable _currentResources = new NetworkVariable(
0,
NetworkVariableReadPermission.Everyone,
NetworkVariableWritePermission.Server
);
private float _lastGatheringTime;
private float _lastRechargeTime;
public override void OnNetworkSpawn()
{
if (IsServer)
{
_currentResources.Value = maxResources;
_lastRechargeTime = Time.time;
}
}
private void Update()
{
if (!IsServer)
return;
// 자원 충전 로직
if (Time.time - _lastRechargeTime >= rechargeInterval)
{
if (_currentResources.Value < maxResources)
{
int rechargeAmountToAdd = Mathf.Min(rechargeAmount, maxResources - _currentResources.Value);
_currentResources.Value += rechargeAmountToAdd;
// Debug.Log($"{resourceName} {rechargeAmountToAdd} 충전됨. 현재: {_currentResources.Value}/{maxResources}");
}
_lastRechargeTime = Time.time;
}
}
public bool CanInteract(ulong playerId)
{
// 자원 노드에 자원이 없으면 상호작용 불가
if (_currentResources.Value <= 0)
return false;
// 쿨다운 확인
if (Time.time - _lastGatheringTime < gatheringCooldown)
return false;
// 플레이어 인벤토리 확인
if (NetworkManager.Singleton != null &&
NetworkManager.Singleton.ConnectedClients.TryGetValue(playerId, out var client))
{
if (client.PlayerObject != null)
{
var playerInventory = client.PlayerObject.GetComponent();
if (playerInventory != null)
{
// 플레이어가 받을 수 있는 공간이 없으면 상호작용 불가
if (playerInventory.GetAvailableSpace() <= 0)
return false;
}
}
}
return true;
}
public void Interact(ulong playerId)
{
if (!CanInteract(playerId))
return;
GatherResourceServerRpc(playerId);
}
[Rpc(SendTo.Server, InvokePermission = RpcInvokePermission.Everyone)]
private void GatherResourceServerRpc(ulong playerId)
{
if (!CanInteract(playerId))
return;
// 플레이어의 인벤토리 확인
var playerObject = NetworkManager.Singleton.ConnectedClients[playerId].PlayerObject;
if (playerObject == null)
return;
var playerInventory = playerObject.GetComponent();
if (playerInventory == null)
{
Debug.LogWarning($"플레이어 {playerId}에게 PlayerResourceInventory 컴포넌트가 없습니다.");
return;
}
// 플레이어가 받을 수 있는 최대량 계산
int playerAvailableSpace = playerInventory.GetAvailableSpace();
// 자원 노드가 줄 수 있는 양과 플레이어가 받을 수 있는 양 중 작은 값 선택
int gatheredAmount = Mathf.Min(
resourcesPerGathering,
_currentResources.Value,
playerAvailableSpace
);
if (gatheredAmount <= 0)
{
Debug.Log($"플레이어 {playerId}의 인벤토리가 가득 찼습니다.");
return;
}
// 자원 차감
_currentResources.Value -= gatheredAmount;
_lastGatheringTime = Time.time;
// 플레이어에게 자원 추가
playerInventory.AddResourceServerRpc(gatheredAmount);
Debug.Log($"플레이어 {playerId}가 {gatheredAmount} {resourceName}을(를) 채집했습니다. 남은 자원: {_currentResources.Value}");
ShowGatheringEffectClientRpc();
}
[Rpc(SendTo.ClientsAndHost)]
private void ShowGatheringEffectClientRpc()
{
if (gatheringEffectPrefab != null && effectSpawnPoint != null)
{
GameObject effect = Instantiate(gatheringEffectPrefab, effectSpawnPoint.position, effectSpawnPoint.rotation);
Destroy(effect, 2f);
}
}
public string GetInteractionPrompt()
{
if (_currentResources.Value <= 0)
return "자원 충전 중...";
return $"[E] {resourceName} 채집 ({_currentResources.Value}/{maxResources})";
}
public string GetInteractionAnimation()
{
return interactionAnimationTrigger;
}
public EquipmentData GetEquipmentData()
{
return equipmentData;
}
public Transform GetTransform()
{
return transform;
}
}
}