279 lines
8.5 KiB
C#
279 lines
8.5 KiB
C#
using Unity.Netcode;
|
|
using UnityEngine;
|
|
using System.Collections.Generic;
|
|
|
|
namespace Northbound
|
|
{
|
|
/// <summary>
|
|
/// 상호작용 대상 - 자원 채집
|
|
/// </summary>
|
|
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;
|
|
|
|
[Header("Worker Assignment")]
|
|
public bool allowWorkerAssignment = true;
|
|
|
|
[Header("Multi-worker")]
|
|
public bool allowMultipleWorkers = false; // 한 자원에 여러 워커 허용 여부
|
|
|
|
public bool HasResourcesAvailable()
|
|
{
|
|
return _currentResources.Value > 0;
|
|
}
|
|
|
|
public bool CanWorkerMineResource(ulong workerId)
|
|
{
|
|
if (!HasResourcesAvailable())
|
|
return false;
|
|
|
|
if (allowMultipleWorkers)
|
|
return true;
|
|
|
|
if (_currentWorkerId.Value == ulong.MaxValue)
|
|
return true;
|
|
|
|
return _currentWorkerId.Value == workerId;
|
|
}
|
|
|
|
public void TakeResourcesForWorker(int amount, ulong workerId)
|
|
{
|
|
if (!IsServer) return;
|
|
|
|
if (!allowMultipleWorkers)
|
|
{
|
|
if (_currentWorkerId.Value != ulong.MaxValue && _currentWorkerId.Value != workerId)
|
|
return;
|
|
}
|
|
|
|
int availableResources = _currentResources.Value;
|
|
int actualAmount = Mathf.Min(amount, availableResources);
|
|
|
|
if (actualAmount <= 0)
|
|
return;
|
|
|
|
_currentResources.Value -= actualAmount;
|
|
_lastGatheringTime = Time.time;
|
|
|
|
if (!allowMultipleWorkers && actualAmount > 0)
|
|
{
|
|
_currentWorkerId.Value = workerId;
|
|
}
|
|
|
|
if (_currentResources.Value <= 0 && !allowMultipleWorkers)
|
|
{
|
|
_currentWorkerId.Value = ulong.MaxValue;
|
|
}
|
|
|
|
ShowGatheringEffectClientRpc();
|
|
}
|
|
|
|
private NetworkVariable<int> _currentResources = new NetworkVariable<int>(
|
|
0,
|
|
NetworkVariableReadPermission.Everyone,
|
|
NetworkVariableWritePermission.Server
|
|
);
|
|
|
|
private NetworkVariable<ulong> _currentWorkerId = new NetworkVariable<ulong>(
|
|
ulong.MaxValue,
|
|
NetworkVariableReadPermission.Everyone,
|
|
NetworkVariableWritePermission.Server
|
|
);
|
|
|
|
private float _lastGatheringTime;
|
|
private float _lastRechargeTime;
|
|
|
|
public override void OnNetworkSpawn()
|
|
{
|
|
if (IsServer)
|
|
{
|
|
_currentResources.Value = maxResources;
|
|
_lastRechargeTime = Time.time;
|
|
_lastGatheringTime = Time.time - gatheringCooldown;
|
|
}
|
|
}
|
|
|
|
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;
|
|
|
|
var resourceManager = ServerResourceManager.Instance;
|
|
if (resourceManager != null)
|
|
{
|
|
if (resourceManager.GetAvailableSpace(playerId) <= 0)
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public void Interact(ulong playerId)
|
|
{
|
|
AssignOrGatherResourceServerRpc(playerId, NetworkObject.NetworkObjectId);
|
|
}
|
|
|
|
[Rpc(SendTo.Server, InvokePermission = RpcInvokePermission.Everyone)]
|
|
private void AssignOrGatherResourceServerRpc(ulong playerId, ulong resourceId)
|
|
{
|
|
var playerObject = NetworkManager.Singleton.ConnectedClients[playerId].PlayerObject;
|
|
if (playerObject == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var playerInteraction = playerObject.GetComponent<PlayerInteraction>();
|
|
|
|
bool workerAssigned = false;
|
|
|
|
if (allowWorkerAssignment && playerInteraction != null && playerInteraction.assignedWorker != null)
|
|
{
|
|
var worker = playerInteraction.assignedWorker;
|
|
|
|
if (worker.OwnerPlayerId == playerId && (int)worker.CurrentState == 1)
|
|
{
|
|
worker.AssignMiningTargetServerRpc(resourceId);
|
|
workerAssigned = true;
|
|
|
|
ShowGatheringEffectClientRpc();
|
|
}
|
|
}
|
|
|
|
if (!workerAssigned)
|
|
{
|
|
if (!CanInteract(playerId))
|
|
{
|
|
return;
|
|
}
|
|
|
|
GatherResource(playerId);
|
|
}
|
|
}
|
|
|
|
private void GatherResource(ulong playerId)
|
|
{
|
|
if (!CanInteract(playerId))
|
|
return;
|
|
|
|
var resourceManager = ServerResourceManager.Instance;
|
|
if (resourceManager == null)
|
|
return;
|
|
|
|
int playerAvailableSpace = resourceManager.GetAvailableSpace(playerId);
|
|
|
|
int gatheredAmount = Mathf.Min(
|
|
resourcesPerGathering,
|
|
_currentResources.Value,
|
|
playerAvailableSpace
|
|
);
|
|
|
|
if (gatheredAmount <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_currentResources.Value -= gatheredAmount;
|
|
_lastGatheringTime = Time.time;
|
|
|
|
resourceManager.AddResource(playerId, gatheredAmount);
|
|
UpdatePlayerResourcesClientRpc(playerId);
|
|
|
|
ShowGatheringEffectClientRpc();
|
|
}
|
|
|
|
[Rpc(SendTo.ClientsAndHost)]
|
|
private void UpdatePlayerResourcesClientRpc(ulong playerId)
|
|
{
|
|
var playerObject = NetworkManager.Singleton.ConnectedClients[playerId].PlayerObject;
|
|
if (playerObject != null)
|
|
{
|
|
var playerInventory = playerObject.GetComponent<PlayerResourceInventory>();
|
|
if (playerInventory != null)
|
|
{
|
|
playerInventory.RequestResourceUpdateServerRpc();
|
|
}
|
|
}
|
|
}
|
|
|
|
[Rpc(SendTo.NotServer)]
|
|
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;
|
|
}
|
|
}
|
|
}
|