diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ClimbingPick.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ClimbingPick.java index ac0aa93d7..486d698d3 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ClimbingPick.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/tools/ClimbingPick.java @@ -13,6 +13,7 @@ import java.util.concurrent.ThreadLocalRandom; import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; +import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.GameMode; @@ -49,9 +50,9 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; */ public class ClimbingPick extends SimpleSlimefunItem implements DamageableItem, RecipeDisplayItem { - private static final double MAX_DISTANCE = 4.4; private static final double STRONG_SURFACE_DEFAULT = 1.0; private static final double WEAK_SURFACE_DEFAULT = 0.6; + private static final double MAX_DISTANCE = 4.4; private static final double EFFICIENCY_MODIFIER = 0.125; private static final long COOLDOWN = 4; @@ -118,11 +119,33 @@ public class ClimbingPick extends SimpleSlimefunItem implements * * @return The climbing speed for this {@link Material} or 0. */ - private double getClimbingSpeed(@Nonnull Material type) { + public double getClimbingSpeed(@Nonnull Material type) { + Validate.notNull(type, "The surface cannot be null"); ClimbableSurface surface = surfaces.get(type); return surface != null ? surface.getValue() : 0; } + /** + * This returns the climbing speed for a given {@link Material} and the used {@link ItemStack}. + * + * @param item + * the {@link ClimbingPick}'s {@link ItemStack} + * @param type + * The {@link Material} + * + * @return The climbing speed or 0. + */ + public double getClimbingSpeed(@Nonnull ItemStack item, @Nonnull Material type) { + double speed = getClimbingSpeed(type); + int efficiencyLevel = item.getEnchantmentLevel(Enchantment.DIG_SPEED); + + if (efficiencyLevel > 0) { + speed += efficiencyLevel * EFFICIENCY_MODIFIER; + } + + return speed; + } + @Override public ItemUseHandler getItemHandler() { return e -> { @@ -166,17 +189,11 @@ public class ClimbingPick extends SimpleSlimefunItem implements @ParametersAreNonnullByDefault private void climb(Player p, EquipmentSlot hand, ItemStack item, Block block) { - double power = getClimbingSpeed(block.getType()); + double power = getClimbingSpeed(item, block.getType()); if (power > 0.05) { - // Prevent players from spamming this + // Prevent players from spamming this item by enforcing a cooldown if (users.add(p.getUniqueId())) { - int efficiencyLevel = item.getEnchantmentLevel(Enchantment.DIG_SPEED); - - if (efficiencyLevel > 0) { - power += efficiencyLevel * EFFICIENCY_MODIFIER; - } - SlimefunPlugin.runSync(() -> users.remove(p.getUniqueId()), COOLDOWN); Vector velocity = new Vector(0, power, 0); ClimbingPickLaunchEvent event = new ClimbingPickLaunchEvent(p, velocity, this, item, block); diff --git a/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/items/implementations/tools/TestClimbingPick.java b/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/items/implementations/tools/TestClimbingPick.java index c5bf82f09..19a5ac00e 100644 --- a/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/items/implementations/tools/TestClimbingPick.java +++ b/src/test/java/io/github/thebusybiscuit/slimefun4/testing/tests/items/implementations/tools/TestClimbingPick.java @@ -1,30 +1,43 @@ package io.github.thebusybiscuit.slimefun4.testing.tests.items.implementations.tools; +import java.util.stream.Stream; + +import javax.annotation.Nonnull; + import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.BlockFace; +import org.bukkit.enchantments.Enchantment; import org.bukkit.inventory.ItemStack; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.EnumSource; +import org.junit.jupiter.params.provider.MethodSource; import be.seeseemelk.mockbukkit.MockBukkit; import be.seeseemelk.mockbukkit.ServerMock; import be.seeseemelk.mockbukkit.block.BlockMock; import be.seeseemelk.mockbukkit.entity.PlayerMock; import io.github.thebusybiscuit.slimefun4.api.events.ClimbingPickLaunchEvent; +import io.github.thebusybiscuit.slimefun4.api.exceptions.TagMisconfigurationException; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.items.tools.ClimbingPick; import io.github.thebusybiscuit.slimefun4.testing.TestUtilities; import io.github.thebusybiscuit.slimefun4.testing.interfaces.SlimefunItemTest; +import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag; import me.mrCookieSlime.Slimefun.Lists.RecipeType; import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; class TestClimbingPick implements SlimefunItemTest { + private static final double STRONG_SURFACE_DEFAULT = 1.0; + private static final double WEAK_SURFACE_DEFAULT = 0.6; + private static ServerMock server; private static SlimefunPlugin plugin; @@ -57,9 +70,51 @@ class TestClimbingPick implements SlimefunItemTest { return pick; } + @ParameterizedTest + @DisplayName("Test Climbing Pick on strong surfaces") + @MethodSource("getStrongSurfaces") + void testStrongSurfaces(Material surface) { + Assertions.assertFalse(SlimefunTag.CLIMBING_PICK_STRONG_SURFACES.getValues().isEmpty()); + ClimbingPick pick = registerSlimefunItem(plugin, "STRONG_CLIMBING_PICK_" + surface.name()); + double speed = pick.getClimbingSpeed(surface); + + Assertions.assertEquals(STRONG_SURFACE_DEFAULT, speed); + Assertions.assertEquals(1, pick.getClimbableSurfaces().stream().filter(s -> s.getType() == surface).count()); + } + + private static Stream getStrongSurfaces() throws TagMisconfigurationException { + SlimefunTag.CLIMBING_PICK_STRONG_SURFACES.reload(); + return SlimefunTag.CLIMBING_PICK_STRONG_SURFACES.getValues().stream().map(Arguments::of); + } + + @ParameterizedTest + @DisplayName("Test Climbing Pick on weak surfaces") + @MethodSource("getWeakSurfaces") + void testWeakSurfaces(Material surface) { + Assertions.assertFalse(SlimefunTag.CLIMBING_PICK_WEAK_SURFACES.getValues().isEmpty()); + ClimbingPick pick = registerSlimefunItem(plugin, "WEAK_CLIMBING_PICK_" + surface.name()); + double speed = pick.getClimbingSpeed(surface); + + Assertions.assertEquals(WEAK_SURFACE_DEFAULT, speed); + Assertions.assertEquals(1, pick.getClimbableSurfaces().stream().filter(s -> s.getType() == surface).count()); + } + + private static Stream getWeakSurfaces() throws TagMisconfigurationException { + SlimefunTag.CLIMBING_PICK_WEAK_SURFACES.reload(); + return SlimefunTag.CLIMBING_PICK_WEAK_SURFACES.getValues().stream().map(Arguments::of); + } + + @Test + @DisplayName("Test Climbing Pick on non-climbable surface") + void testNonClimbable() { + ClimbingPick pick = registerSlimefunItem(plugin, "NOT_CLIMBING_PICK"); + double speed = pick.getClimbingSpeed(Material.DRAGON_EGG); + Assertions.assertEquals(0, speed); + } + @ParameterizedTest @DisplayName("Test Climbing Pick on various Block Faces") - @EnumSource(value = BlockFace.class) + @EnumSource(value = BlockFace.class, names = { "UP", "DOWN", "NORTH", "EAST", "SOUTH", "WEST" }) void testItemUse(BlockFace face) { server.getPluginManager().clearEvents(); PlayerMock player = server.addPlayer(); @@ -72,11 +127,35 @@ class TestClimbingPick implements SlimefunItemTest { simulateRightClickBlock(player, pick, block, face); if (shouldFireEvent) { - server.getPluginManager().assertEventFired(ClimbingPickLaunchEvent.class); + Assertions.assertTrue(pick.getClimbingSpeed(block.getType()) > 0); Assertions.assertTrue(player.getVelocity().length() > 0); + server.getPluginManager().assertEventFired(ClimbingPickLaunchEvent.class); } else { Assertions.assertEquals(0, player.getVelocity().length()); } } + + @Test + @DisplayName("Test Climbing Pick Efficiency modifier") + void testEfficiency() { + Material surface = Material.ICE; + + ClimbingPick pick = registerSlimefunItem(plugin, "TEST_CLIMBING_PICK_EFFICIENCY"); + ItemStack efficiency0 = pick.getItem().clone(); + ItemStack efficiency1 = getPickWithEfficiency(pick, 1); + ItemStack efficiency2 = getPickWithEfficiency(pick, 2); + ItemStack efficiency3 = getPickWithEfficiency(pick, 3); + + Assertions.assertEquals(pick.getClimbingSpeed(surface), pick.getClimbingSpeed(efficiency0, surface)); + Assertions.assertTrue(pick.getClimbingSpeed(efficiency1, surface) > pick.getClimbingSpeed(efficiency0, surface)); + Assertions.assertTrue(pick.getClimbingSpeed(efficiency2, surface) > pick.getClimbingSpeed(efficiency1, surface)); + Assertions.assertTrue(pick.getClimbingSpeed(efficiency3, surface) > pick.getClimbingSpeed(efficiency2, surface)); + } + + private ItemStack getPickWithEfficiency(@Nonnull ClimbingPick pick, int level) { + ItemStack item = pick.getItem().clone(); + item.addUnsafeEnchantment(Enchantment.DIG_SPEED, level); + return item; + } }