171 lines
5.6 KiB
C#
171 lines
5.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Unity.Netcode;
|
|
using UnityEngine;
|
|
|
|
public class PlayerInventory : NetworkBehaviour
|
|
{
|
|
[Header("Inventory Settings")]
|
|
[Range(1, 10)] // 인스펙터에서 슬라이더로 조절 가능
|
|
public int slotCount = 5;
|
|
public float maxWeight = 50f;
|
|
|
|
[System.Serializable]
|
|
public struct DefaultItem
|
|
{
|
|
public ItemData item; // 인스펙터에서 아이템 에셋 드래그
|
|
public int amount; // 초기 개수
|
|
}
|
|
|
|
[Header("Starting Loadout")]
|
|
[SerializeField] private List<DefaultItem> startingItems; // 기본 지급 아이템 리스트
|
|
|
|
// 1. 실제 데이터 저장소 (Private)
|
|
private NetworkVariable<int> _selectedSlotIndex = new NetworkVariable<int>(0,
|
|
NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Server);
|
|
|
|
// 2. 외부에서 읽기 전용으로 값에 접근 (기존 유지)
|
|
public int SelectedSlotIndex => _selectedSlotIndex.Value;
|
|
|
|
// 3. [핵심] 외부에서 이벤트에 함수를 등록(+=)할 수 있도록 델리게이트 노출
|
|
public NetworkVariable<int>.OnValueChangedDelegate OnSlotChanged
|
|
{
|
|
get => _selectedSlotIndex.OnValueChanged;
|
|
set => _selectedSlotIndex.OnValueChanged = value;
|
|
}
|
|
|
|
public struct InventorySlot : INetworkSerializable, IEquatable<InventorySlot>
|
|
{
|
|
public int ItemID; // string에서 int로 변경
|
|
public int Amount;
|
|
|
|
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
|
|
{
|
|
serializer.SerializeValue(ref ItemID);
|
|
serializer.SerializeValue(ref Amount);
|
|
}
|
|
|
|
public bool Equals(InventorySlot other) => ItemID == other.ItemID && Amount == other.Amount;
|
|
}
|
|
|
|
[Header("References")]
|
|
[SerializeField] private ItemDatabase database;
|
|
|
|
public NetworkList<InventorySlot> Slots;
|
|
// 무게 정보는 서버에서만 쓰고 나머지는 읽기만 가능 (네트워크 보안)
|
|
private NetworkVariable<float> _currentWeight = new NetworkVariable<float>(0f, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Server);
|
|
|
|
public float CurrentWeight => _currentWeight.Value;
|
|
|
|
void Awake()
|
|
{
|
|
Slots = new NetworkList<InventorySlot>();
|
|
}
|
|
|
|
public override void OnNetworkSpawn()
|
|
{
|
|
if (IsServer)
|
|
{
|
|
InitializeInventory();
|
|
}
|
|
|
|
// 로컬 플레이어라면 UI 연결
|
|
if (IsOwner)
|
|
{
|
|
QuickslotUI ui = FindFirstObjectByType<QuickslotUI>();
|
|
if (ui != null) ui.BindInventory(this);
|
|
}
|
|
}
|
|
|
|
// PlayerInventory.cs 내의 AddItemRpc 예시
|
|
[Rpc(SendTo.Server, InvokePermission = RpcInvokePermission.Everyone)]
|
|
public void AddItemRpc(int itemID, int amount)
|
|
{
|
|
// 이제 필드 변수 없이 바로 접근 가능!
|
|
ItemData data = ItemDatabase.Instance.GetItemByID(itemID);
|
|
if (data == null) return;
|
|
|
|
float addedWeight = data.weight * amount;
|
|
bool added = false;
|
|
|
|
for (int i = 0; i < Slots.Count; i++)
|
|
{
|
|
// 기존에 같은 아이템이 있거나(-1은 빈 슬롯을 의미) 빈 슬롯인 경우
|
|
if (Slots[i].ItemID == itemID || Slots[i].ItemID == -1)
|
|
{
|
|
Slots[i] = new InventorySlot
|
|
{
|
|
ItemID = itemID,
|
|
Amount = Slots[i].Amount + amount
|
|
};
|
|
added = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (added)
|
|
{
|
|
_currentWeight.Value += addedWeight;
|
|
}
|
|
}
|
|
|
|
// 슬롯 선택 요청 (최신 RPC 방식 적용)
|
|
[Rpc(SendTo.Server, InvokePermission = RpcInvokePermission.Everyone)]
|
|
public void ChangeSelectedSlotRpc(int index)
|
|
{
|
|
if (index >= 0 && index < slotCount)
|
|
{
|
|
Debug.Log($"<color=green>[PlayerInventory] 슬롯 선택 변경 요청: {index}</color>");
|
|
_selectedSlotIndex.Value = index;
|
|
}
|
|
}
|
|
|
|
// 현재 선택된 슬롯의 아이템 데이터를 가져오는 편의 기능
|
|
public ItemData GetSelectedItemData()
|
|
{
|
|
var slot = Slots[SelectedSlotIndex];
|
|
if (slot.ItemID == -1) return null;
|
|
return ItemDatabase.Instance.GetItemByID(slot.ItemID);
|
|
}
|
|
|
|
private void InitializeInventory()
|
|
{
|
|
// 슬롯을 깨끗하게 비우고 시작 (이미 데이터가 있을 경우를 대비)
|
|
if (Slots.Count > 0) Slots.Clear();
|
|
_currentWeight.Value = 0;
|
|
|
|
// 전체 슬롯 개수만큼 빈 슬롯(-1) 먼저 생성
|
|
for (int i = 0; i < slotCount; i++)
|
|
{
|
|
Slots.Add(new InventorySlot { ItemID = -1, Amount = 0 });
|
|
}
|
|
|
|
// 설정된 기본 아이템들을 순서대로 채워 넣음
|
|
for (int i = 0; i < startingItems.Count && i < slotCount; i++)
|
|
{
|
|
if (startingItems[i].item != null)
|
|
{
|
|
ItemData data = startingItems[i].item;
|
|
int amount = startingItems[i].amount;
|
|
|
|
Slots[i] = new InventorySlot
|
|
{
|
|
ItemID = data.itemID,
|
|
Amount = amount
|
|
};
|
|
|
|
// 초기 무게 합산
|
|
_currentWeight.Value += data.weight * amount;
|
|
}
|
|
}
|
|
}
|
|
|
|
// PlayerInventory.cs에 추가
|
|
public ItemData GetItemDataInSlot(int index)
|
|
{
|
|
if (index < 0 || index >= Slots.Count) return null;
|
|
var slot = Slots[index];
|
|
if (slot.ItemID == -1) return null;
|
|
return ItemDatabase.Instance.GetItemByID(slot.ItemID);
|
|
}
|
|
} |