diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/CustomAnvilRecipeApi.java b/src/main/java/xyz/alexcrea/cuanvil/api/CustomAnvilRecipeApi.java index 32db73b..8f80aa3 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/api/CustomAnvilRecipeApi.java +++ b/src/main/java/xyz/alexcrea/cuanvil/api/CustomAnvilRecipeApi.java @@ -78,6 +78,7 @@ public class CustomAnvilRecipeApi { return true; } + // TODO remove by name and/or by builder (as name is keept) (and maybe create a get by name) /** * Remove a custom anvil recipe. * @@ -86,7 +87,8 @@ public class CustomAnvilRecipeApi { */ public static boolean removeRecipe(@NotNull AnvilCustomRecipe recipe){ // Remove from registry - ConfigHolder.CUSTOM_RECIPE_HOLDER.getRecipeManager().cleanRemove(recipe); + boolean result = ConfigHolder.CUSTOM_RECIPE_HOLDER.getRecipeManager().cleanRemove(recipe); + if(!result) return false; // Delete and save to file ConfigHolder.CUSTOM_RECIPE_HOLDER.delete(recipe.getName()); diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt index 4ba12ca..68370d4 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt @@ -11,13 +11,11 @@ import io.delilaheve.util.ItemUtil.setEnchantmentsUnsafe import io.delilaheve.util.ItemUtil.unitRepair import org.bukkit.ChatColor import org.bukkit.entity.HumanEntity -import org.bukkit.entity.Player import org.bukkit.event.EventHandler import org.bukkit.event.EventPriority import org.bukkit.event.Listener import org.bukkit.event.inventory.PrepareAnvilEvent import org.bukkit.inventory.AnvilInventory -import org.bukkit.inventory.InventoryView import org.bukkit.inventory.ItemStack import xyz.alexcrea.cuanvil.dependency.DependencyManager import xyz.alexcrea.cuanvil.util.AnvilColorUtil diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/recipe/CustomAnvilRecipeManager.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/recipe/CustomAnvilRecipeManager.kt index 8f9dece..f271d90 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/recipe/CustomAnvilRecipeManager.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/recipe/CustomAnvilRecipeManager.kt @@ -9,17 +9,17 @@ class CustomAnvilRecipeManager { lateinit var recipeList: ArrayList - lateinit var recipeByMat: LinkedHashMap> + lateinit var recipeByMat: HashMap> fun prepareRecipes(config: FileConfiguration) { recipeList = ArrayList() - recipeByMat = LinkedHashMap() + recipeByMat = HashMap() // read all configs val keys = config.getKeys(false) for (key in keys) { val recipe = AnvilCustomRecipe.getFromConfig(key) - if(recipe == null){ + if (recipe == null) { CustomAnvil.log("Can't load recipe $key") continue } @@ -30,34 +30,34 @@ class CustomAnvilRecipeManager { } - fun cleanAddNew(recipe: AnvilCustomRecipe){ + fun cleanAddNew(recipe: AnvilCustomRecipe) { recipeList.add(recipe) val leftItem = recipe.leftItem - if(leftItem != null){ + if (leftItem != null) { addToMatMap(recipe, leftItem) } } - fun cleanSetLeftItem(recipe: AnvilCustomRecipe, leftItem: ItemStack?){ + fun cleanSetLeftItem(recipe: AnvilCustomRecipe, leftItem: ItemStack?) { // Remove left item mat if exist val oldLeftItem = recipe.leftItem - if(oldLeftItem != null){ + if (oldLeftItem != null) { val oldMat = oldLeftItem.type val test = recipeByMat[oldMat] test!!.remove(recipe) } - if(leftItem != null){ + if (leftItem != null) { addToMatMap(recipe, leftItem) } recipe.leftItem = leftItem } - private fun addToMatMap(recipe: AnvilCustomRecipe, leftItem: ItemStack){ + private fun addToMatMap(recipe: AnvilCustomRecipe, leftItem: ItemStack) { var recipeList = recipeByMat[leftItem.type] - if(recipeList == null){ + if (recipeList == null) { recipeList = ArrayList() recipeByMat[leftItem.type] = recipeList } @@ -65,11 +65,14 @@ class CustomAnvilRecipeManager { } - fun cleanRemove(recipe: AnvilCustomRecipe) { + fun cleanRemove(recipe: AnvilCustomRecipe): Boolean { - recipeList.remove(recipe) - cleanSetLeftItem(recipe, null) + val exist = recipeList.remove(recipe) + if (exist) { + cleanSetLeftItem(recipe, null) + } + return exist; } } \ No newline at end of file diff --git a/src/test/java/xyz/alexcrea/cuanvil/api/AnvilRecipeBuilderTest.java b/src/test/java/xyz/alexcrea/cuanvil/api/AnvilRecipeBuilderTest.java new file mode 100644 index 0000000..2b57bda --- /dev/null +++ b/src/test/java/xyz/alexcrea/cuanvil/api/AnvilRecipeBuilderTest.java @@ -0,0 +1,85 @@ +package xyz.alexcrea.cuanvil.api; + + +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import xyz.alexcrea.cuanvil.tests.SharedOnlyMockBukkit; + +import static org.junit.jupiter.api.Assertions.*; + +public class AnvilRecipeBuilderTest extends SharedOnlyMockBukkit { + + private AnvilRecipeBuilder builder; + + @BeforeEach + public void setup() { + builder = new AnvilRecipeBuilder("test"); + } + + @Test + void createBuilder_NoLeftItem(){ + builder.setResultItem(new ItemStack(Material.STICK)); + + assertNull(builder.build()); + } + + @Test + void createBuilder_NoResultItem(){ + builder.setLeftItem(new ItemStack(Material.STICK)); + + assertNull(builder.build()); + } + + @Test + void createBuilder_minimalist(){ + builder.setLeftItem(new ItemStack(Material.STICK)) + .setResultItem(new ItemStack(Material.STICK)); + + assertNotNull(builder.build()); + } + + @Test + void setLeftItem(){ + assertNull(builder.getLeftItem()); + builder.setLeftItem(new ItemStack(Material.STICK)); + assertNotNull(builder.getLeftItem()); + } + + @Test + void setRightItem(){ + assertNull(builder.getRightItem()); + builder.setRightItem(new ItemStack(Material.STICK)); + assertNotNull(builder.getRightItem()); + } + + @Test + void setResultItem(){ + assertNull(builder.getResultItem()); + builder.setResultItem(new ItemStack(Material.STICK)); + assertNotNull(builder.getResultItem()); + } + + @Test + void setXpCostPerCraft(){ + assertEquals(1, builder.getXpCostPerCraft()); + builder.setXpCostPerCraft(2); + assertEquals(2, builder.getXpCostPerCraft()); + } + + @Test + void setExactCount(){ + assertTrue(builder.isExactCount()); + builder.setExactCount(false); + assertFalse(builder.isExactCount()); + } + + @Test + void setName(){ + assertEquals("test", builder.getName()); + builder.setName("other"); + assertEquals("other", builder.getName()); + } + +} diff --git a/src/test/java/xyz/alexcrea/cuanvil/api/ConflictApiTests.java b/src/test/java/xyz/alexcrea/cuanvil/api/ConflictApiTests.java index 3a4b48e..1d4249f 100644 --- a/src/test/java/xyz/alexcrea/cuanvil/api/ConflictApiTests.java +++ b/src/test/java/xyz/alexcrea/cuanvil/api/ConflictApiTests.java @@ -58,8 +58,9 @@ public class ConflictApiTests extends ConfigResetCustomAnvilTest { AnvilFuseTestData legalResultData = new AnvilFuseTestData( sharpness1, arthropods1, - illegalResult + illegalResult, // TODO add expected price + null ); CAEnchantment sharpness = EnchantmentApi.getByKey(Enchantment.SHARPNESS.getKey()); diff --git a/src/test/java/xyz/alexcrea/cuanvil/api/CustomAnvilRecipeApiTests.java b/src/test/java/xyz/alexcrea/cuanvil/api/CustomAnvilRecipeApiTests.java new file mode 100644 index 0000000..5b53f0e --- /dev/null +++ b/src/test/java/xyz/alexcrea/cuanvil/api/CustomAnvilRecipeApiTests.java @@ -0,0 +1,151 @@ +package xyz.alexcrea.cuanvil.api; + +import org.bukkit.Material; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.AnvilInventory; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.Nullable; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockbukkit.mockbukkit.entity.PlayerMock; +import org.mockbukkit.mockbukkit.inventory.ItemStackMock; +import xyz.alexcrea.cuanvil.config.ConfigHolder; +import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe; +import xyz.alexcrea.cuanvil.tests.ConfigResetCustomAnvilTest; +import xyz.alexcrea.cuanvil.util.AnvilFuseTestData; +import xyz.alexcrea.cuanvil.util.AnvilFuseTestUtil; + +import static org.junit.jupiter.api.Assertions.*; + +public class CustomAnvilRecipeApiTests extends ConfigResetCustomAnvilTest { + + private AnvilInventory anvil; + private PlayerMock player; + + @Override + @BeforeEach + public void setUp() { + super.setUp(); + // Mock used player & open anvil + player = server.addPlayer(); + + Inventory anvil = server.createInventory(player, InventoryType.ANVIL); + + this.anvil = (AnvilInventory) anvil; + player.openInventory(anvil); + + ConfigHolder.DEFAULT_CONFIG.getConfig().set("debug_log", true); + ConfigHolder.DEFAULT_CONFIG.getConfig().set("debug_log_verbose", true); + } + + @Test + public void testBasicRecipe() { + String recipeName = "stick_recipe"; + ItemStack stick = new ItemStackMock(Material.STICK); + + AnvilFuseTestData nullResultData = new AnvilFuseTestData( + stick, stick, + null + ); + + AnvilFuseTestData legalResultData = new AnvilFuseTestData( + stick, stick, + null, stick, null, + // TODO add expected price + null, + null, null + ); + + // Testing default conflict (no recipe exist) + AnvilFuseTestUtil.executeAnvilTest(anvil, player, nullResultData); + + // Add and test recipe + AnvilRecipeBuilder builder = new AnvilRecipeBuilder(recipeName); + builder.setExactCount(true).setLeftItem(stick).setResultItem(stick).setXpCostPerCraft(2); + + assertTrue(builder.registerIfAbsent()); + AnvilFuseTestUtil.executeAnvilTest(anvil, player, legalResultData); + + AnvilCustomRecipe recipe = getByName(recipeName); + assertNotNull(recipe); + + // Remove recipe + assertTrue(CustomAnvilRecipeApi.removeRecipe(recipe)); + assertFalse(CustomAnvilRecipeApi.removeRecipe(recipe)); + AnvilFuseTestUtil.executeAnvilTest(anvil, player, nullResultData); + + recipe = getByName(recipeName); + assertNull(recipe); + + // Try to add deleted recipe with no override (should not add) + assertFalse(CustomAnvilRecipeApi.addRecipe(builder, false)); + AnvilFuseTestUtil.executeAnvilTest(anvil, player, nullResultData); + + recipe = getByName(recipeName); + assertNull(recipe); + + // Try to add deleted recipe with override (should add) + assertTrue(CustomAnvilRecipeApi.addRecipe(builder, true)); + AnvilFuseTestUtil.executeAnvilTest(anvil, player, legalResultData); + + recipe = getByName(recipeName); + assertNotNull(recipe); + } + + @Test + public void testUnitRecipe() { + String recipeName = "stick_recipe"; + ItemStack stick = new ItemStackMock(Material.STICK); + ItemStack stick2 = new ItemStackMock(Material.STICK, 2); + ItemStack stick5 = new ItemStackMock(Material.STICK, 5); + ItemStack stick10 = new ItemStackMock(Material.STICK, 10); + + AnvilFuseTestData nullResultData = new AnvilFuseTestData( + stick, stick, + null + ); + + AnvilFuseTestData legalResultData1 = new AnvilFuseTestData( + stick, stick, + null, stick2, null, + // TODO add expected price + null, + null, null + ); + + AnvilFuseTestData legalResultData2 = new AnvilFuseTestData( + stick5, stick, + null, stick10, null, + // TODO add expected price + null, + null, null + ); + + AnvilFuseTestUtil.executeAnvilTest(anvil, player, nullResultData); + + AnvilRecipeBuilder builder = new AnvilRecipeBuilder(recipeName); + builder.setExactCount(false) + .setLeftItem(stick) + .setResultItem(stick2) + .setXpCostPerCraft(2); + + assertTrue(builder.registerIfAbsent()); + + // Now working test + AnvilFuseTestUtil.executeAnvilTest(anvil, player, legalResultData1); + AnvilFuseTestUtil.executeAnvilTest(anvil, player, legalResultData2); + } + + @Nullable + public static AnvilCustomRecipe getByName(String name){ + for (AnvilCustomRecipe registeredRecipe : CustomAnvilRecipeApi.getRegisteredRecipes()) { + if(registeredRecipe.getName().contentEquals(name)){ + return registeredRecipe; + } + } + + return null; + } + +} diff --git a/src/test/java/xyz/alexcrea/cuanvil/tests/SharedOnlyMockBukkit.java b/src/test/java/xyz/alexcrea/cuanvil/tests/SharedOnlyMockBukkit.java new file mode 100644 index 0000000..0f38239 --- /dev/null +++ b/src/test/java/xyz/alexcrea/cuanvil/tests/SharedOnlyMockBukkit.java @@ -0,0 +1,24 @@ +package xyz.alexcrea.cuanvil.tests; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.mockbukkit.mockbukkit.MockBukkit; +import org.mockbukkit.mockbukkit.ServerMock; + +public class SharedOnlyMockBukkit { + + protected static ServerMock server; + + @BeforeAll + public static void setUp() { + // Start the mock server + server = MockBukkit.mock(); + } + + @AfterAll + public static void tearDown() { + // Stop the mock server + MockBukkit.unmock(); + } + +} diff --git a/src/test/java/xyz/alexcrea/cuanvil/util/AnvilFuseTestUtil.java b/src/test/java/xyz/alexcrea/cuanvil/util/AnvilFuseTestUtil.java index c161497..de8a706 100644 --- a/src/test/java/xyz/alexcrea/cuanvil/util/AnvilFuseTestUtil.java +++ b/src/test/java/xyz/alexcrea/cuanvil/util/AnvilFuseTestUtil.java @@ -132,6 +132,7 @@ public class AnvilFuseTestUtil { @Nullable ItemStack toPlace, @Nullable ItemStack expectedResult){ anvil.setItem(slot, toPlace); + anvil.setItem(2, null); AnvilFuseTestUtil.imitateAnvilUpdate(player, anvil); ItemStack result = anvil.getItem(2);