218 lines
5.2 KiB
C#
218 lines
5.2 KiB
C#
|
|
using System;
|
||
|
|
using System.Collections.Generic;
|
||
|
|
using System.Text;
|
||
|
|
using UnityEngine;
|
||
|
|
|
||
|
|
public class Inventory : MonoBehaviour
|
||
|
|
{
|
||
|
|
public List<InventorySlot> slots = new List<InventorySlot>();
|
||
|
|
public int maxSlots = 32;
|
||
|
|
public List<InventorySlot> testResources = new List<InventorySlot>();
|
||
|
|
|
||
|
|
public event Action OnInventoryChanged;
|
||
|
|
|
||
|
|
public InventorySlot GetSlot(int index)
|
||
|
|
{
|
||
|
|
if (index < 0 || index >= slots.Count)
|
||
|
|
{
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
InventorySlot slot = slots[index];
|
||
|
|
return slot == null || slot.IsEmpty() ? null : slot;
|
||
|
|
}
|
||
|
|
|
||
|
|
public bool HasItem(ItemData item, int amount)
|
||
|
|
{
|
||
|
|
if (item == null || amount <= 0)
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
return GetItemAmount(item) >= amount;
|
||
|
|
}
|
||
|
|
|
||
|
|
public int GetItemAmount(ItemData item)
|
||
|
|
{
|
||
|
|
if (item == null)
|
||
|
|
{
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int total = 0;
|
||
|
|
for (int i = 0; i < slots.Count; i++)
|
||
|
|
{
|
||
|
|
InventorySlot slot = slots[i];
|
||
|
|
if (slot != null && slot.item == item && slot.amount > 0)
|
||
|
|
{
|
||
|
|
total += slot.amount;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return total;
|
||
|
|
}
|
||
|
|
|
||
|
|
public bool AddItem(ItemData item, int amount)
|
||
|
|
{
|
||
|
|
if (!CanAddItem(item, amount))
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
AddItemInternal(item, amount);
|
||
|
|
RaiseChanged();
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
public bool RemoveItem(ItemData item, int amount)
|
||
|
|
{
|
||
|
|
if (item == null || amount <= 0 || !HasItem(item, amount))
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
int remaining = amount;
|
||
|
|
for (int i = slots.Count - 1; i >= 0 && remaining > 0; i--)
|
||
|
|
{
|
||
|
|
InventorySlot slot = slots[i];
|
||
|
|
if (slot == null || slot.item != item || slot.amount <= 0)
|
||
|
|
{
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
int removed = Mathf.Min(slot.amount, remaining);
|
||
|
|
slot.amount -= removed;
|
||
|
|
remaining -= removed;
|
||
|
|
|
||
|
|
if (slot.IsEmpty())
|
||
|
|
{
|
||
|
|
slots.RemoveAt(i);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
RaiseChanged();
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
public bool RemoveFromSlot(int slotIndex, int amount)
|
||
|
|
{
|
||
|
|
InventorySlot slot = GetSlot(slotIndex);
|
||
|
|
if (slot == null || amount <= 0 || slot.amount < amount)
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
slot.amount -= amount;
|
||
|
|
if (slot.IsEmpty())
|
||
|
|
{
|
||
|
|
slots.RemoveAt(slotIndex);
|
||
|
|
}
|
||
|
|
|
||
|
|
RaiseChanged();
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
public void Clear()
|
||
|
|
{
|
||
|
|
slots.Clear();
|
||
|
|
RaiseChanged();
|
||
|
|
}
|
||
|
|
|
||
|
|
public void AddTestResources()
|
||
|
|
{
|
||
|
|
slots.Clear();
|
||
|
|
for (int i = 0; i < testResources.Count; i++)
|
||
|
|
{
|
||
|
|
InventorySlot resource = testResources[i];
|
||
|
|
if (resource != null && resource.item != null && resource.amount > 0)
|
||
|
|
{
|
||
|
|
AddItemInternal(resource.item, resource.amount);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
RaiseChanged();
|
||
|
|
}
|
||
|
|
|
||
|
|
public string GetInventoryDebugText()
|
||
|
|
{
|
||
|
|
if (slots.Count == 0)
|
||
|
|
{
|
||
|
|
return "Инвентарь пуст";
|
||
|
|
}
|
||
|
|
|
||
|
|
StringBuilder builder = new StringBuilder();
|
||
|
|
for (int i = 0; i < slots.Count; i++)
|
||
|
|
{
|
||
|
|
InventorySlot slot = slots[i];
|
||
|
|
if (slot == null || slot.IsEmpty())
|
||
|
|
{
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
builder.AppendLine(slot.GetDisplayText());
|
||
|
|
}
|
||
|
|
|
||
|
|
return builder.ToString();
|
||
|
|
}
|
||
|
|
|
||
|
|
// Used by CraftingSystem to prevent losing ingredients when the result has no room.
|
||
|
|
public bool CanAddItem(ItemData item, int amount)
|
||
|
|
{
|
||
|
|
if (item == null || amount <= 0)
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
int remaining = amount;
|
||
|
|
int maxStack = Mathf.Max(1, item.maxStack);
|
||
|
|
|
||
|
|
for (int i = 0; i < slots.Count; i++)
|
||
|
|
{
|
||
|
|
InventorySlot slot = slots[i];
|
||
|
|
if (slot != null && slot.item == item && slot.amount > 0 && slot.amount < maxStack)
|
||
|
|
{
|
||
|
|
remaining -= maxStack - slot.amount;
|
||
|
|
if (remaining <= 0)
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
int freeSlots = Mathf.Max(0, maxSlots - slots.Count);
|
||
|
|
int requiredSlots = Mathf.CeilToInt(remaining / (float)maxStack);
|
||
|
|
return requiredSlots <= freeSlots;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void AddItemInternal(ItemData item, int amount)
|
||
|
|
{
|
||
|
|
int remaining = amount;
|
||
|
|
int maxStack = Mathf.Max(1, item.maxStack);
|
||
|
|
|
||
|
|
for (int i = 0; i < slots.Count && remaining > 0; i++)
|
||
|
|
{
|
||
|
|
InventorySlot slot = slots[i];
|
||
|
|
if (slot == null || slot.item != item || slot.amount >= maxStack)
|
||
|
|
{
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
int added = Mathf.Min(maxStack - slot.amount, remaining);
|
||
|
|
slot.amount += added;
|
||
|
|
remaining -= added;
|
||
|
|
}
|
||
|
|
|
||
|
|
while (remaining > 0 && slots.Count < maxSlots)
|
||
|
|
{
|
||
|
|
int added = Mathf.Min(maxStack, remaining);
|
||
|
|
slots.Add(new InventorySlot(item, added));
|
||
|
|
remaining -= added;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void RaiseChanged()
|
||
|
|
{
|
||
|
|
OnInventoryChanged?.Invoke();
|
||
|
|
}
|
||
|
|
}
|