Files
Northbound/Assets/Scripts/Core.cs
dal4segno aa086a7a2b 자원 채집 및 반환 기능
텍스트 기능 및 폰트 추가
2026-01-26 02:29:07 +09:00

223 lines
7.6 KiB
C#

using Unity.Netcode;
using UnityEngine;
namespace Northbound
{
/// <summary>
/// 플레이어가 자원을 건내받아 게임의 전역 자원으로 관리하는 중앙 허브
/// </summary>
public class Core : NetworkBehaviour, IInteractable
{
[Header("Core Settings")]
public int maxStorageCapacity = 1000; // 코어의 최대 저장 용량
public bool unlimitedStorage = false; // 무제한 저장소
[Header("Deposit Settings")]
public bool depositAll = true; // true: 전부 건네기, false: 일부만 건네기
public int depositAmountPerInteraction = 10; // depositAll이 false일 때 한 번에 건네는 양
[Header("Animation")]
public string interactionAnimationTrigger = "Deposit"; // 플레이어 애니메이션 트리거
[Header("Equipment")]
public InteractionEquipmentData equipmentData = null; // 도구 필요 없음
[Header("Visual")]
public GameObject depositEffectPrefab;
public Transform effectSpawnPoint;
private NetworkVariable<int> _totalResources = new NetworkVariable<int>(
0,
NetworkVariableReadPermission.Everyone,
NetworkVariableWritePermission.Server
);
public int TotalResources => _totalResources.Value;
public int MaxStorageCapacity => maxStorageCapacity;
public override void OnNetworkSpawn()
{
if (IsServer)
{
_totalResources.Value = 0;
}
}
public bool CanInteract(ulong playerId)
{
// 저장소가 가득 찼는지 확인 (무제한이 아닐 때)
if (!unlimitedStorage && _totalResources.Value >= maxStorageCapacity)
return false;
// 플레이어가 자원을 가지고 있는지 확인
if (NetworkManager.Singleton != null &&
NetworkManager.Singleton.ConnectedClients.TryGetValue(playerId, out var client))
{
if (client.PlayerObject != null)
{
var playerInventory = client.PlayerObject.GetComponent<PlayerResourceInventory>();
if (playerInventory != null)
{
// 플레이어가 자원을 가지고 있어야 함
return playerInventory.CurrentResourceAmount > 0;
}
}
}
return false;
}
public void Interact(ulong playerId)
{
if (!CanInteract(playerId))
return;
DepositResourceServerRpc(playerId);
}
[Rpc(SendTo.Server, InvokePermission = RpcInvokePermission.Everyone)]
private void DepositResourceServerRpc(ulong playerId)
{
if (!CanInteract(playerId))
return;
// 플레이어 인벤토리 가져오기
var playerObject = NetworkManager.Singleton.ConnectedClients[playerId].PlayerObject;
if (playerObject == null)
return;
var playerInventory = playerObject.GetComponent<PlayerResourceInventory>();
if (playerInventory == null)
{
Debug.LogWarning($"플레이어 {playerId}에게 PlayerResourceInventory 컴포넌트가 없습니다.");
return;
}
int playerResourceAmount = playerInventory.CurrentResourceAmount;
if (playerResourceAmount <= 0)
{
Debug.Log($"플레이어 {playerId}가 건낼 자원이 없습니다.");
return;
}
int depositAmount;
if (depositAll)
{
// 전부 건네기
depositAmount = playerResourceAmount;
}
else
{
// 일부만 건네기
depositAmount = Mathf.Min(depositAmountPerInteraction, playerResourceAmount);
}
// 무제한 저장소가 아니면 용량 제한 확인
if (!unlimitedStorage)
{
int availableSpace = maxStorageCapacity - _totalResources.Value;
depositAmount = Mathf.Min(depositAmount, availableSpace);
}
if (depositAmount <= 0)
{
Debug.Log($"코어의 저장 공간이 부족합니다.");
return;
}
// 플레이어로부터 자원 차감
playerInventory.RemoveResourceServerRpc(depositAmount);
// 코어에 자원 추가
_totalResources.Value += depositAmount;
Debug.Log($"플레이어 {playerId}가 {depositAmount} 자원을 코어에 건넸습니다. 코어 총 자원: {_totalResources.Value}" +
(unlimitedStorage ? "" : $"/{maxStorageCapacity}"));
ShowDepositEffectClientRpc();
}
[Rpc(SendTo.ClientsAndHost)]
private void ShowDepositEffectClientRpc()
{
if (depositEffectPrefab != null && effectSpawnPoint != null)
{
GameObject effect = Instantiate(depositEffectPrefab, effectSpawnPoint.position, effectSpawnPoint.rotation);
Destroy(effect, 2f);
}
}
/// <summary>
/// 게임 시스템이 코어의 자원을 사용 (건물 건설 등)
/// </summary>
[Rpc(SendTo.Server, InvokePermission = RpcInvokePermission.Everyone)]
public void ConsumeResourceServerRpc(int amount)
{
if (amount <= 0) return;
int actualAmount = Mathf.Min(amount, _totalResources.Value);
_totalResources.Value -= actualAmount;
Debug.Log($"코어에서 {actualAmount} 자원을 사용했습니다. 남은 자원: {_totalResources.Value}");
}
/// <summary>
/// 자원을 사용할 수 있는지 확인
/// </summary>
public bool CanConsumeResource(int amount)
{
return _totalResources.Value >= amount;
}
/// <summary>
/// 코어에 자원 추가 (디버그/관리자 기능)
/// </summary>
[Rpc(SendTo.Server, InvokePermission = RpcInvokePermission.Everyone)]
public void AddResourceServerRpc(int amount)
{
if (amount <= 0) return;
if (!unlimitedStorage)
{
int availableSpace = maxStorageCapacity - _totalResources.Value;
amount = Mathf.Min(amount, availableSpace);
}
_totalResources.Value += amount;
Debug.Log($"코어에 {amount} 자원이 추가되었습니다. 현재: {_totalResources.Value}");
}
public string GetInteractionPrompt()
{
if (unlimitedStorage)
{
return depositAll ?
$"[E] 자원 모두 건네기" :
$"[E] 자원 건네기 ({depositAmountPerInteraction}개씩)";
}
if (_totalResources.Value >= maxStorageCapacity)
return "코어 저장소 가득 찼음";
return depositAll ?
$"[E] 자원 모두 건네기 ({_totalResources.Value}/{maxStorageCapacity})" :
$"[E] 자원 건네기 ({_totalResources.Value}/{maxStorageCapacity})";
}
public string GetInteractionAnimation()
{
return interactionAnimationTrigger;
}
public InteractionEquipmentData GetEquipmentData()
{
return equipmentData;
}
public Transform GetTransform()
{
return transform;
}
}
}