From 05d8c170c47e2efa5f4b6b0cd87ad78a148043bf Mon Sep 17 00:00:00 2001 From: LP Date: Sun, 27 Apr 2025 14:52:51 +0100 Subject: [PATCH] Added fix for equipment extension bug Also added test cases --- .../Builders/CharacterBuilder.cs | 22 ++++-- .../Extensions/EquipmentExtensions.cs | 8 +- .../Equippables/EquipmentExtensionsTests.cs | 74 +++++++++++++++++++ 3 files changed, 90 insertions(+), 14 deletions(-) create mode 100644 src/OpenRpg.UnitTests/Items/Equippables/EquipmentExtensionsTests.cs diff --git a/src/OpenRpg.Genres/Builders/CharacterBuilder.cs b/src/OpenRpg.Genres/Builders/CharacterBuilder.cs index 08d1b34..61bb723 100644 --- a/src/OpenRpg.Genres/Builders/CharacterBuilder.cs +++ b/src/OpenRpg.Genres/Builders/CharacterBuilder.cs @@ -151,6 +151,14 @@ protected virtual RaceData ProcessRace() protected virtual void PreProcessCharacter() {} protected virtual void PostProcessCharacter(Character character) {} + + /// + /// Allows you to override the creation of the character instance + /// + /// This is useful for creating a character with a custom inherited type + /// + protected virtual Character CreateCharacterInstance() + { return new Character() { }; } public virtual Character CreateCharacter() { @@ -160,14 +168,12 @@ public virtual Character CreateCharacter() _variables.Inventory(ProcessInventory()); _variables.Gender(_genderId); - var character = new Character() - { - UniqueId = Guid.NewGuid(), - NameLocaleId = _name, - DescriptionLocaleId = _description, - Variables = _variables, - State = new EntityStateVariables(_state) - }; + var character = CreateCharacterInstance(); + character.UniqueId = Guid.NewGuid(); + character.NameLocaleId = _name; + character.DescriptionLocaleId = _description; + character.Variables = _variables; + character.State = new EntityStateVariables(_state); var needsStateRefresh = _state.Count == 0; CharacterPopulator.Populate(character, needsStateRefresh); diff --git a/src/OpenRpg.Items/Extensions/EquipmentExtensions.cs b/src/OpenRpg.Items/Extensions/EquipmentExtensions.cs index 78e1e04..9918ed6 100644 --- a/src/OpenRpg.Items/Extensions/EquipmentExtensions.cs +++ b/src/OpenRpg.Items/Extensions/EquipmentExtensions.cs @@ -1,7 +1,3 @@ -using System.Collections.Generic; -using System.Linq; -using OpenRpg.Core.Templates; -using OpenRpg.Entities.Effects; using OpenRpg.Items.Equippables; using OpenRpg.Items.Equippables.Slots; using OpenRpg.Items.Templates; @@ -38,8 +34,8 @@ public static ItemData AttemptUnequipSlot(this Equipment equipment, int slotType public static bool AttemptEquipSlot(this Equipment equipment, IEquipmentSlotValidator slotValidator, int slotType, ItemData itemData, ItemTemplate template) { if(!equipment.HasSlot(slotType)) { return false; } - if(!equipment.HasItemEquipped(slotType)) { return false; } - if(slotValidator.CanEquipItemType(slotType, template.ItemType)) { return false; } + if(equipment.HasItemEquipped(slotType)) { return false; } + if(!slotValidator.CanEquipItemType(slotType, template.ItemType)) { return false; } equipment.Slots[slotType] = itemData; return true; } diff --git a/src/OpenRpg.UnitTests/Items/Equippables/EquipmentExtensionsTests.cs b/src/OpenRpg.UnitTests/Items/Equippables/EquipmentExtensionsTests.cs new file mode 100644 index 0000000..dede4f9 --- /dev/null +++ b/src/OpenRpg.UnitTests/Items/Equippables/EquipmentExtensionsTests.cs @@ -0,0 +1,74 @@ +using Moq; +using OpenRpg.Items.Equippables; +using OpenRpg.Items.Equippables.Slots; +using OpenRpg.Items.Extensions; +using OpenRpg.Items.Templates; +using Xunit; + +namespace OpenRpg.UnitTests.Items.Equippables +{ + public class EquipmentExtensionsTests + { + [Fact] + public void should_equip_item_when_all_criteria_met() + { + var equipmentSlot = 1; + var equipment = new Equipment(); + equipment.Slots[equipmentSlot] = null; + + var item = new ItemData(); + var itemTemplate = new ItemTemplate(); + + var mockEquipmentValidator = new Mock(); + mockEquipmentValidator + .Setup(x => x.CanEquipItemType(It.IsAny(), It.IsAny())) + .Returns(true); + + var result = equipment.AttemptEquipSlot(mockEquipmentValidator.Object, equipmentSlot, item, itemTemplate); + + Assert.True(result); + Assert.Equal(equipment.Slots[equipmentSlot], item); + } + + [Fact] + public void should_not_equip_item_when_slot_doesnt_exist() + { + var equipmentSlot = 1; + var equipment = new Equipment(); + + var item = new ItemData(); + var itemTemplate = new ItemTemplate(); + + var mockEquipmentValidator = new Mock(); + mockEquipmentValidator + .Setup(x => x.CanEquipItemType(It.IsAny(), It.IsAny())) + .Returns(true); + + var result = equipment.AttemptEquipSlot(mockEquipmentValidator.Object, equipmentSlot, item, itemTemplate); + + Assert.False(result); + Assert.Empty(equipment.Slots); + } + + [Fact] + public void should_not_equip_item_when_slot_exists_but_validation_fails() + { + var equipmentSlot = 1; + var equipment = new Equipment(); + equipment.Slots[equipmentSlot] = null; + + var item = new ItemData(); + var itemTemplate = new ItemTemplate(); + + var mockEquipmentValidator = new Mock(); + mockEquipmentValidator + .Setup(x => x.CanEquipItemType(It.IsAny(), It.IsAny())) + .Returns(false); + + var result = equipment.AttemptEquipSlot(mockEquipmentValidator.Object, equipmentSlot, item, itemTemplate); + + Assert.False(result); + Assert.Null(equipment.Slots[equipmentSlot]); + } + } +} \ No newline at end of file