From 959ab68b4d64e9745e116142e3e7e496087fa967 Mon Sep 17 00:00:00 2001 From: cblech Date: Tue, 25 Mar 2025 19:39:00 +0100 Subject: [PATCH] Added basic inventory system --- prefabs/UI/Inventory/Inventory.tscn | 8 ++ project.godot | 3 +- resources/items/axe.tres | 9 ++ resources/items/bucket.tres | 9 ++ resources/items/hoe.tres | 9 ++ resources/items/pickaxe.tres | 9 ++ scenes/testing/babushka_tests_inventory.tscn | 47 ++++++++++ .../Common/Inventory/InventoryActionResult.cs | 10 +++ .../Common/Inventory/InventoryInstance.cs | 85 +++++++++++++++++++ .../Common/Inventory/InventoryInstance.cs.uid | 1 + .../Common/Inventory/InventoryManager.cs | 63 ++++++++++++++ .../Common/Inventory/InventoryManager.cs.uid | 1 + .../CSharp/Common/Inventory/InventorySlot.cs | 12 +++ .../CSharp/Common/Inventory/InventoryUI.cs | 6 ++ .../Common/Inventory/InventoryUI.cs.uid | 1 + .../CSharp/Common/Inventory/ItemInstance.cs | 6 ++ .../CSharp/Common/Inventory/ItemResource.cs | 18 ++++ .../Common/Inventory/ItemResource.cs.uid | 1 + scripts/CSharp/Common/InventoryManager.cs.uid | 1 + 19 files changed, 298 insertions(+), 1 deletion(-) create mode 100644 prefabs/UI/Inventory/Inventory.tscn create mode 100644 resources/items/axe.tres create mode 100644 resources/items/bucket.tres create mode 100644 resources/items/hoe.tres create mode 100644 resources/items/pickaxe.tres create mode 100644 scenes/testing/babushka_tests_inventory.tscn create mode 100644 scripts/CSharp/Common/Inventory/InventoryActionResult.cs create mode 100644 scripts/CSharp/Common/Inventory/InventoryInstance.cs create mode 100644 scripts/CSharp/Common/Inventory/InventoryInstance.cs.uid create mode 100644 scripts/CSharp/Common/Inventory/InventoryManager.cs create mode 100644 scripts/CSharp/Common/Inventory/InventoryManager.cs.uid create mode 100644 scripts/CSharp/Common/Inventory/InventorySlot.cs create mode 100644 scripts/CSharp/Common/Inventory/InventoryUI.cs create mode 100644 scripts/CSharp/Common/Inventory/InventoryUI.cs.uid create mode 100644 scripts/CSharp/Common/Inventory/ItemInstance.cs create mode 100644 scripts/CSharp/Common/Inventory/ItemResource.cs create mode 100644 scripts/CSharp/Common/Inventory/ItemResource.cs.uid create mode 100644 scripts/CSharp/Common/InventoryManager.cs.uid diff --git a/prefabs/UI/Inventory/Inventory.tscn b/prefabs/UI/Inventory/Inventory.tscn new file mode 100644 index 0000000..24645b2 --- /dev/null +++ b/prefabs/UI/Inventory/Inventory.tscn @@ -0,0 +1,8 @@ +[gd_scene load_steps=2 format=3 uid="uid://cgjc4wurbgimy"] + +[ext_resource type="Script" uid="uid://b7vlkecrn0t5c" path="res://scripts/CSharp/Common/Inventory/InventoryUI.cs" id="1_6wusm"] + +[node name="Inventory" type="Control"] +layout_mode = 3 +anchors_preset = 0 +script = ExtResource("1_6wusm") diff --git a/project.godot b/project.godot index b9813d3..e955fed 100644 --- a/project.godot +++ b/project.godot @@ -11,13 +11,14 @@ config_version=5 [application] config/name="Babushka" -run/main_scene="res://scenes/testing/abandoned_street_3d.tscn" +run/main_scene="uid://mhtcm8daava5" config/features=PackedStringArray("4.4", "C#", "Forward Plus") config/icon="res://icon.svg" [autoload] Dialogic="*res://addons/dialogic/Core/DialogicGameHandler.gd" +InventoryManager="*res://scripts/CSharp/Common/Inventory/InventoryManager.cs" [dialogic] diff --git a/resources/items/axe.tres b/resources/items/axe.tres new file mode 100644 index 0000000..0770130 --- /dev/null +++ b/resources/items/axe.tres @@ -0,0 +1,9 @@ +[gd_resource type="Resource" script_class="ItemResource" load_steps=2 format=3 uid="uid://c7viddcd3kywp"] + +[ext_resource type="Script" uid="uid://cbskymrxs6ksu" path="res://scripts/CSharp/Common/Inventory/ItemResource.cs" id="1_t485b"] + +[resource] +script = ExtResource("1_t485b") +name = "Axe Deo" +color = Color(0.643898, 0.4587, 0.294335, 1) +metadata/_custom_type_script = "uid://cbskymrxs6ksu" diff --git a/resources/items/bucket.tres b/resources/items/bucket.tres new file mode 100644 index 0000000..b323f49 --- /dev/null +++ b/resources/items/bucket.tres @@ -0,0 +1,9 @@ +[gd_resource type="Resource" script_class="ItemResource" load_steps=2 format=3 uid="uid://cndd64batns31"] + +[ext_resource type="Script" uid="uid://cbskymrxs6ksu" path="res://scripts/CSharp/Common/Inventory/ItemResource.cs" id="1_8k5aa"] + +[resource] +script = ExtResource("1_8k5aa") +name = "Buck the Bucket" +color = Color(0.336269, 0.489145, 0.825324, 1) +metadata/_custom_type_script = "uid://cbskymrxs6ksu" diff --git a/resources/items/hoe.tres b/resources/items/hoe.tres new file mode 100644 index 0000000..e7c0e27 --- /dev/null +++ b/resources/items/hoe.tres @@ -0,0 +1,9 @@ +[gd_resource type="Resource" script_class="ItemResource" load_steps=2 format=3 uid="uid://c5yg3lx756v4v"] + +[ext_resource type="Script" uid="uid://cbskymrxs6ksu" path="res://scripts/CSharp/Common/Inventory/ItemResource.cs" id="1_06nef"] + +[resource] +script = ExtResource("1_06nef") +name = "Your Mom" +color = Color(0.751421, 0.329615, 0.570911, 1) +metadata/_custom_type_script = "uid://cbskymrxs6ksu" diff --git a/resources/items/pickaxe.tres b/resources/items/pickaxe.tres new file mode 100644 index 0000000..185e49e --- /dev/null +++ b/resources/items/pickaxe.tres @@ -0,0 +1,9 @@ +[gd_resource type="Resource" script_class="ItemResource" load_steps=2 format=3 uid="uid://datee0flk1e84"] + +[ext_resource type="Script" uid="uid://cbskymrxs6ksu" path="res://scripts/CSharp/Common/Inventory/ItemResource.cs" id="1_07aya"] + +[resource] +script = ExtResource("1_07aya") +name = "Pick Axe" +color = Color(0.226361, 0.573832, 0.480633, 1) +metadata/_custom_type_script = "uid://cbskymrxs6ksu" diff --git a/scenes/testing/babushka_tests_inventory.tscn b/scenes/testing/babushka_tests_inventory.tscn new file mode 100644 index 0000000..e275232 --- /dev/null +++ b/scenes/testing/babushka_tests_inventory.tscn @@ -0,0 +1,47 @@ +[gd_scene load_steps=3 format=3 uid="uid://mhtcm8daava5"] + +[ext_resource type="PackedScene" uid="uid://cgjc4wurbgimy" path="res://prefabs/UI/Inventory/Inventory.tscn" id="1_5dyk0"] + +[sub_resource type="BoxMesh" id="BoxMesh_5dyk0"] + +[node name="BabushkaTestsInventory" type="Node3D"] + +[node name="Inventory" parent="." instance=ExtResource("1_5dyk0")] + +[node name="MockScene" type="Node3D" parent="."] + +[node name="MeshInstance3D" type="MeshInstance3D" parent="MockScene"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2.52591, 0, 1.26963) +mesh = SubResource("BoxMesh_5dyk0") +skeleton = NodePath("../..") + +[node name="MeshInstance3D2" type="MeshInstance3D" parent="MockScene"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.48916, 0, -0.762378) +mesh = SubResource("BoxMesh_5dyk0") +skeleton = NodePath("../..") + +[node name="MeshInstance3D3" type="MeshInstance3D" parent="MockScene"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.58762, -2.38419e-07, -1.76688) +mesh = SubResource("BoxMesh_5dyk0") +skeleton = NodePath("../..") + +[node name="MeshInstance3D4" type="MeshInstance3D" parent="MockScene"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2.59247, -4.76837e-07, -0.0171926) +mesh = SubResource("BoxMesh_5dyk0") +skeleton = NodePath("../..") + +[node name="MeshInstance3D5" type="MeshInstance3D" parent="MockScene"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.696733, -4.76837e-07, 1.49587) +mesh = SubResource("BoxMesh_5dyk0") +skeleton = NodePath("../..") + +[node name="MeshInstance3D6" type="MeshInstance3D" parent="MockScene"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -4.7007, -4.76837e-07, -1.52457) +mesh = SubResource("BoxMesh_5dyk0") +skeleton = NodePath("../..") + +[node name="Camera3D" type="Camera3D" parent="MockScene"] +transform = Transform3D(1, 0, 0, 0, 0.633826, 0.773475, 0, -0.773475, 0.633826, -0.833954, 3.04237, 2.8418) + +[node name="DirectionalLight3D" type="DirectionalLight3D" parent="MockScene"] +transform = Transform3D(0.255314, 0.801032, -0.541445, -0.00609746, 0.561328, 0.827571, 0.966839, -0.207989, 0.148199, -1.99366, 2.88871, 2.87262) diff --git a/scripts/CSharp/Common/Inventory/InventoryActionResult.cs b/scripts/CSharp/Common/Inventory/InventoryActionResult.cs new file mode 100644 index 0000000..be9c0e5 --- /dev/null +++ b/scripts/CSharp/Common/Inventory/InventoryActionResult.cs @@ -0,0 +1,10 @@ +namespace Babushka.scripts.CSharp.Common.Inventory; + +public enum InventoryActionResult +{ + Success, + DestinationDoesNotExists, + DestinationFull, + SourceDoesNotExists, + SourceIsEmpty +} diff --git a/scripts/CSharp/Common/Inventory/InventoryInstance.cs b/scripts/CSharp/Common/Inventory/InventoryInstance.cs new file mode 100644 index 0000000..0991199 --- /dev/null +++ b/scripts/CSharp/Common/Inventory/InventoryInstance.cs @@ -0,0 +1,85 @@ +#nullable enable +using System; +using Godot; +using System.Collections.Generic; + +namespace Babushka.scripts.CSharp.Common.Inventory; + +public partial class InventoryInstance : Node +{ + private List _slots = new(); + public IReadOnlyList Slots => _slots; + + [Signal] + public delegate void SlotAmountChangedEventHandler(); + [Signal] + public delegate void InventoryContentsChangedEventHandler(); + + [Export] + public int SlotAmount + { + get => _slots.Count; + set + { + if (value < _slots.Count) + { + _slots.RemoveRange(value, _slots.Count - value); + } + else if (value > _slots.Count) + { + for (var i = _slots.Count; i < value; i++) + { + _slots.Add(new InventorySlot()); + } + } + EmitSignal(SignalName.SlotAmountChanged); + } + } + + public InventoryActionResult AddItem(ItemInstance newItem, int inventorySlot = -1) + { + if (inventorySlot < 0) + { + inventorySlot = _slots.FindIndex(slot => slot.IsEmpty()); + } + + if (inventorySlot < 0 || !_slots[inventorySlot].IsEmpty()) + { + return InventoryActionResult.DestinationFull; + } + + if (inventorySlot >= _slots.Count) + { + return InventoryActionResult.DestinationDoesNotExists; + } + + _slots[inventorySlot].itemInstance = newItem; + EmitSignal(SignalName.InventoryContentsChanged); + return InventoryActionResult.Success; + } + + public InventoryActionResult RemoveItem(int inventorySlot, out ItemInstance? itemInstance ) + { + if (inventorySlot < 0 || inventorySlot >= _slots.Count) + { + itemInstance = null; + return InventoryActionResult.SourceDoesNotExists; + } + + if (_slots[inventorySlot].IsEmpty()) + { + itemInstance = null; + return InventoryActionResult.SourceIsEmpty; + } + + itemInstance = _slots[inventorySlot].itemInstance; + _slots[inventorySlot].itemInstance = null; + EmitSignal(SignalName.InventoryContentsChanged); + return InventoryActionResult.Success; + } + + public InventoryActionResult RemoveItem(int inventorySlot) + { + return RemoveItem(inventorySlot, out _); + } +} diff --git a/scripts/CSharp/Common/Inventory/InventoryInstance.cs.uid b/scripts/CSharp/Common/Inventory/InventoryInstance.cs.uid new file mode 100644 index 0000000..b5cd17f --- /dev/null +++ b/scripts/CSharp/Common/Inventory/InventoryInstance.cs.uid @@ -0,0 +1 @@ +uid://36ui8g5gu0lb diff --git a/scripts/CSharp/Common/Inventory/InventoryManager.cs b/scripts/CSharp/Common/Inventory/InventoryManager.cs new file mode 100644 index 0000000..61c209d --- /dev/null +++ b/scripts/CSharp/Common/Inventory/InventoryManager.cs @@ -0,0 +1,63 @@ +#nullable enable +using Godot; + +namespace Babushka.scripts.CSharp.Common.Inventory; + +public partial class InventoryManager : Node +{ + public InventoryManager Instance { get; private set; } + + public InventoryInstance playerInventory; + + public override void _EnterTree() + { + Instance = this; + } + + public override void _Ready() + { + playerInventory = new InventoryInstance(); + playerInventory.SlotAmount = 30; + } + + public InventoryActionResult CreateItem( + ItemResource itemBlueprint, + InventoryInstance inventory, + int inventorySlot = -1) + { + var newItem = new ItemInstance { blueprint = itemBlueprint }; + var addResult = inventory.AddItem(newItem, inventorySlot); + return addResult; + } + + public InventoryActionResult MoveItem( + InventoryInstance sourceInventory, + int sourceSlot, + InventoryInstance destinationInventory, + int destinationSlot) + { + var remResult = sourceInventory.RemoveItem(sourceSlot, out var item); + if (remResult != InventoryActionResult.Success) return remResult; + + var addResult = destinationInventory.AddItem(item!, destinationSlot); + if(addResult == InventoryActionResult.Success) return InventoryActionResult.Success; + + sourceInventory.AddItem(item!, sourceSlot); // can not fail ... in theory + return addResult; + } + + public InventoryActionResult RemoveItem( + InventoryInstance inventory, + int inventorySlot, + out ItemInstance? itemInstance) + { + return inventory.RemoveItem(inventorySlot, out itemInstance); + } + + public InventoryActionResult RemoveItem( + InventoryInstance inventory, + int inventorySlot) + { + return inventory.RemoveItem(inventorySlot); + } +} diff --git a/scripts/CSharp/Common/Inventory/InventoryManager.cs.uid b/scripts/CSharp/Common/Inventory/InventoryManager.cs.uid new file mode 100644 index 0000000..7034511 --- /dev/null +++ b/scripts/CSharp/Common/Inventory/InventoryManager.cs.uid @@ -0,0 +1 @@ +uid://701bitgfepjc diff --git a/scripts/CSharp/Common/Inventory/InventorySlot.cs b/scripts/CSharp/Common/Inventory/InventorySlot.cs new file mode 100644 index 0000000..9ee5a5a --- /dev/null +++ b/scripts/CSharp/Common/Inventory/InventorySlot.cs @@ -0,0 +1,12 @@ +#nullable enable +namespace Babushka.scripts.CSharp.Common.Inventory; + +public class InventorySlot +{ + public ItemInstance? itemInstance; + public bool IsEmpty() + { + return itemInstance == null; + } +} + diff --git a/scripts/CSharp/Common/Inventory/InventoryUI.cs b/scripts/CSharp/Common/Inventory/InventoryUI.cs new file mode 100644 index 0000000..1851f2d --- /dev/null +++ b/scripts/CSharp/Common/Inventory/InventoryUI.cs @@ -0,0 +1,6 @@ +using Godot; +using System; + +public partial class InventoryUI : Control +{ +} diff --git a/scripts/CSharp/Common/Inventory/InventoryUI.cs.uid b/scripts/CSharp/Common/Inventory/InventoryUI.cs.uid new file mode 100644 index 0000000..8b727e9 --- /dev/null +++ b/scripts/CSharp/Common/Inventory/InventoryUI.cs.uid @@ -0,0 +1 @@ +uid://b7vlkecrn0t5c diff --git a/scripts/CSharp/Common/Inventory/ItemInstance.cs b/scripts/CSharp/Common/Inventory/ItemInstance.cs new file mode 100644 index 0000000..83eed75 --- /dev/null +++ b/scripts/CSharp/Common/Inventory/ItemInstance.cs @@ -0,0 +1,6 @@ +namespace Babushka.scripts.CSharp.Common.Inventory; + +public class ItemInstance +{ + public ItemResource blueprint; +} diff --git a/scripts/CSharp/Common/Inventory/ItemResource.cs b/scripts/CSharp/Common/Inventory/ItemResource.cs new file mode 100644 index 0000000..f696046 --- /dev/null +++ b/scripts/CSharp/Common/Inventory/ItemResource.cs @@ -0,0 +1,18 @@ +using Godot; +namespace Babushka.scripts.CSharp.Common.Inventory; + +[GlobalClass] +public partial class ItemResource: Resource +{ + [Export] + public string name; + + [Export] + public Color color; + + public ItemResource() + { + name = ""; + color = Colors.Red; + } +} diff --git a/scripts/CSharp/Common/Inventory/ItemResource.cs.uid b/scripts/CSharp/Common/Inventory/ItemResource.cs.uid new file mode 100644 index 0000000..fed7714 --- /dev/null +++ b/scripts/CSharp/Common/Inventory/ItemResource.cs.uid @@ -0,0 +1 @@ +uid://cbskymrxs6ksu diff --git a/scripts/CSharp/Common/InventoryManager.cs.uid b/scripts/CSharp/Common/InventoryManager.cs.uid new file mode 100644 index 0000000..e1005b2 --- /dev/null +++ b/scripts/CSharp/Common/InventoryManager.cs.uid @@ -0,0 +1 @@ +uid://csgctygxnj3bc