Files
2026-04-25 23:37:10 +02:00

154 lines
5.3 KiB
C#

using System;
using System.Linq;
using RPGCore.BackpackEquipment.ObjectModules.Content;
using RPGCore.BackpackEquipment.ObjectModules.UnitBackpack.Events;
using RPGCore.BackpackEquipment.Objects;
using RPGCore.Core;
using RPGCore.Core.Objects;
using RPGCoreCommon.Helpers.PropertyAttributeDrawers;
using UnityEngine;
namespace RPGCore.BackpackEquipment.ObjectModules.UnitBackpack
{
[RequireComponent(typeof(UnitObject))]
[RequireComponent(typeof(ContentModule))]
[DisallowMultipleComponent]
public sealed class UnitBackpackModule : ObjectModule<UnitObject>, IContentOwner
{
// TODO: implementacja stackowania tutaj
[SerializeField] private ItemObject[] _serializedItems;
[SerializeField] public bool isLimited = true;
[SerializeField] public int itemsLimit = 5;
[SerializeField] public int itemsPerChunk = 5;
[SerializeField] public int minimumChunks = 3;
[SerializeField] public int additionalChunks = 1;
private ItemObject[] _items;
public ItemObject[] items => _items.ToArray();
private void Awake()
{
_items = _serializedItems.ToArray();
Resize();
}
private void Start()
{
InitializeItems();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void InitializeItems()
{
// TODO: inicjalizacja serializowanych itemkow + ich eventy
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public bool CanAdd(ItemObject item, int index)
{
return !isLimited || _items.Any(i => i == null);
}
bool IContentOwner.Add(ItemObject item, int index)
{
if (index < 0) index = Array.IndexOf(_items, false);
if (index < 0) return false;
if (isLimited && index >= itemsLimit) return false;
_items[index] = item;
Resize();
parent.events.Invoke(new BackpackAddEvent { unit = parent, item = item, index = index });
return true;
}
bool IContentOwner.Remove(ItemObject item)
{
var index = Array.IndexOf(_items, item);
if (index < 0) return false;
_items[index] = null;
Resize();
parent.events.Invoke(new BackpackRemoveEvent { unit = parent, item = item, index = index });
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public void Swap(int firstItemIndex, int secondItemIndex)
{
var wantedSize = Math.Max(firstItemIndex, secondItemIndex) + 1;
if (isLimited && wantedSize > itemsLimit) return;
Resize(wantedSize);
(items[firstItemIndex], items[secondItemIndex]) = (items[secondItemIndex], items[firstItemIndex]);
parent.events.Invoke(new BackpackSwapEvent
{
unit = parent,
firstSlotIndex = firstItemIndex,
firstItem = items[firstItemIndex],
secondSlotIndex = secondItemIndex,
secondItem = items[secondItemIndex],
});
}
private void Resize(int wantedSize = 0)
{
if (isLimited)
{
// TODO: obsłużyć itemki w miejscach, które zaraz zostaną "ucięte" (przy zmniejszaniu slotów) - TYLKO w limitowanym plecaku
if (_items.Length != itemsLimit)
{
Array.Resize(ref _items, itemsLimit);
}
return;
}
var limitBefore = items.Length;
var lastItemIndex = Array.FindLastIndex(items, item => item);
var limitMinimum = Mathf.Max(wantedSize, lastItemIndex, minimumChunks * itemsPerChunk);
var limitAfter = Mathf.CeilToInt((float)limitMinimum / itemsPerChunk + additionalChunks) * itemsPerChunk;
// Size not changed, do nothing
if (limitBefore == limitAfter) return;
// Resize backpack's arrays
Array.Resize(ref _items, limitAfter);
parent.events.Invoke(new BackpackResizeEvent
{
unit = parent,
beforeSlotCount = limitBefore,
afterSlotCount = limitAfter
});
}
public void Sort(Func<ItemObject, IComparable> valueGetter, bool sortDescending = false)
{
Array.Sort(items, (item1, item2) =>
{
// NULLS always to the end
if (!item1 && !item2) return 0;
if (!item1) return 1;
if (!item2) return -1;
// Existing items sort by given value getter with given sort direction
var result = valueGetter(item1).CompareTo(valueGetter(item2));
if (sortDescending) result *= - 1;
return result;
});
parent.events.Invoke(new BackpackSortEvent { unit = parent });
Resize();
}
}
}