Open Eu4ng opened 1 year ago
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class Inventory : MonoBehaviour, IInventory
{
// 돈
[SerializeField] int m_Money;
// 아이템 인벤토리
[SerializeField] List<InventoryItem> m_Inventories;
[SerializeField] int m_MaxInventoryNum = 5;
List<int> m_AvailableIndices;
void Awake()
{
m_Inventories = new List<InventoryItem>(m_MaxInventoryNum);
m_AvailableIndices = Enumerable.Range(0, m_MaxInventoryNum).ToList();
}
/* IInventory 인터페이스 구현 시작 */
public int Money
{
get => m_Money;
set => m_Money = value;
}
bool IInventory.AddItem(in IItem _item, out int _remainder)
{
_remainder = _item.Count;
// 인벤토리에 이미 들어있는 아이템인 경우
foreach(IItem inventoryItem in m_Inventories)
{
if (_item.Equals(inventoryItem) && !inventoryItem.IsFull())
{
inventoryItem.Add(_item);
}
}
// 인벤토리 빈 공간에 새로 추가
int offset;
InventoryItem newInventoryItem;
while (m_Inventories.Count < m_MaxInventoryNum && !_item.IsEmpty())
{
// 아이템 복사
newInventoryItem = new InventoryItem()
{
Index = m_AvailableIndices.Min(),
Item = _item.Clone() as IItem
};
// 아이템 개수 나누기
offset = _item.Count - _item.MaxStack;
if (offset > 0)
{
newInventoryItem.Count = newInventoryItem.MaxStack;
_item.Count -= newInventoryItem.MaxStack;
}
else
_item.Count = 0;
// 인벤토리 추가
m_Inventories.Add(newInventoryItem);
}
if (_remainder == _item.Count) return false;
return true;
}
void IInventory.GetAvailableItem(IItem _item)
{
int countBuffer = 0;
IItem inventoryItem;
// 인벤토리 탐색
for (int i = m_Inventories.Count() - 1; i >= 0; i--)
{
inventoryItem = m_Inventories[i];
if (_item.Equals(inventoryItem))
{
// 인벤토리에 들어있는 아이템의 개수가 목표치보다 큰 경우
if (inventoryItem.Count >= _item.Count)
{
countBuffer = _item.Count;
inventoryItem.Count -= _item.Count;
}
else // 인벤토리에 들어있는 아이템의 개수가 목표치보다 작은 경우
{
countBuffer += inventoryItem.Count;
m_AvailableIndices.Add(m_Inventories[i].Index); // Available Index 반환
m_Inventories.Remove(m_Inventories[i]); // 인벤토리에서 아이템 제거
}
// 아이템 개수가 목표치에 도달하면 탐색 종료
if (countBuffer == _item.Count) break;
}
}
// 가지고 있는 아이템 건네주기
_item.Count = countBuffer;
}
int IInventory.CountItem(IItem _item)
{
int count = 0;
// 인벤토리 탐색
foreach (IItem inventoryItem in m_Inventories)
{
if (_item.Equals(inventoryItem))
count += inventoryItem.Count;
}
// 아이템 개수 갱신
return count;
}
/* IInventory 인터페이스 구현 종료 */
// Inventory Item 정의
[Serializable]
class InventoryItem : IItem
{
public int Index { get; set; }
[field : SerializeField, SerializeReference]
public IItem Item { get; set; }
/* IItem 인터페이스 구현 시작 */
public int Count
{
get => Item.Count;
set => Item.Count = value;
}
public int MaxStack => Item.MaxStack;
public bool Equals(IItem _other) => Item.Equals(_other);
public IItem Clone() => MemberwiseClone() as IItem;
/* IItem 인터페이스 구현 종료 */
}
}
public interface IInventory
{
public int Money { get; set; }
bool AddItem(in IItem _item, out int _remainder);
void GetAvailableItem(IItem _item);
int CountItem(IItem _item);
bool CheckItem(IItem _item)
{
if (CountItem(_item) >= _item.Count)
return true;
return false;
}
bool GetItem(IItem _item)
{
if (CheckItem(_item))
{
GetAvailableItem(_item);
return true;
}
return false;
}
}
public interface IItem
{
public int Count { get; set; }
public int MaxStack { get; }
public bool Equals(IItem _other);
public IItem Clone();
// 구현 x
public bool IsFull() => Count >= MaxStack;
public bool IsEmpty() => Count <= 0;
public void Add(IItem _other)
{
var thisItem = this as IItem;
if (!thisItem.Equals(_other)) return; // 같은 아이템만 더한다
int remainder = thisItem.MaxStack - thisItem.Count;
int countToAdd = _other.Count >= remainder ? remainder : _other.Count;
thisItem.Count += countToAdd;
_other.Count -= countToAdd;
}
}
ItemDefinition