summaryrefslogtreecommitdiff
path: root/source/game/components/items/Inventory.cs
blob: 4309f5d13335465f8461538492986588a28aaf42 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
using System;
using Celesteia.Resources;

namespace Celesteia.Game.Components.Items {
    public class Inventory {
        private ItemStack[] items;
        public readonly int Capacity;

        public Inventory(int slots = 27, params ItemStack[] startingItems) {
            Capacity = slots;
            items = new ItemStack[slots];
            
            for (int i = 0; i < startingItems.Length; i++ ) items[i] = startingItems[i];
        }

        // Try adding an item to the inventory, return false if the inventory has no capacity for this action.
        public bool AddItem(ItemStack stack) {
            ItemStack existingStack = GetLastItemStack(stack.Key);

            // If an item stack with this ID already exists, add the amount to that stack.
            if (existingStack != null) {
                existingStack.Amount += stack.Amount;

                // If the max stack size was exceeded and a new stack has to be created, create it.
                ItemStack newStack = existingStack.NewStack();
                if (newStack != null) {
                    if (!HasCapacity()) return false;
                    existingStack.Amount = existingStack.Type.MaxStackSize;
                    AddItemStack(newStack);
                }
            } else AddItemStack(stack);

            return true;
        }

        public ItemStack GetItemStackWithID(byte id) {
            return Array.FindLast(items, x => x != null && x.ID == id && x.Amount < x.Type.MaxStackSize);
        }

        public ItemStack GetLastItemStack(NamespacedKey key) {
            return Array.FindLast(items, x => x != null && x.Key.Equals(key) && x.Amount < x.Type.MaxStackSize);
        }

        public ItemStack GetSlot(int slot) {
            if (slot < 0 || slot > Capacity - 1) throw new ArgumentException($"Slot {slot} falls outside of the inventory's capacity.");
            return items[slot];
        }

        public void SetSlot(int slot, ItemStack stack) {
            if (slot < 0 || slot > Capacity - 1) throw new ArgumentException($"Slot {slot} falls outside of the inventory's capacity.");
            items[slot] = stack;
        }

        public bool ContainsAmount(NamespacedKey key, int amount) {
            return GetAmount(key) >= amount;
        }

        public int GetAmount(NamespacedKey key) {
            int amount = 0;

            ItemStack[] stacksOfItem = Array.FindAll(items, x => x != null && x.Key.Equals(key));
            foreach (ItemStack stackOfItem in stacksOfItem) amount += stackOfItem.Amount;
            
            return amount;
        }

        public void RemoveAmount(NamespacedKey key, int amount) {
            int amountToGo = amount;
            
            ItemStack lastStack;
            while (amountToGo > 0) {
                lastStack = Array.FindLast(items, x => x != null && x.Key.Equals(key));
                int toRemove = Math.Min(lastStack.Amount, amountToGo);

                lastStack.Amount -= toRemove;
                amountToGo -= toRemove;
                
                AssertAmounts();
            }
        }

        private void AddItemStack(ItemStack newStack) {
            if (!HasCapacity()) return;
            int i = Array.FindIndex(items, x => x == null);
            items[i] = newStack;
        }

        private bool HasCapacity() {
            return Array.Exists(items, x => x == null);
        }

        public void AssertAmounts() {
            for (int i = 0; i < items.Length; i++) if (items[i] != null && items[i].Amount <= 0) items[i] = null;
        }
    }
}