From 6e6a9530091615f7701c9ad8c597e4d1d151879b Mon Sep 17 00:00:00 2001 From: TheBusyBiscuit Date: Wed, 26 Aug 2020 12:47:08 +0200 Subject: [PATCH] Fixes #2249 --- CHANGELOG.md | 1 + .../items/armor/StomperBoots.java | 93 ++++++++++++++ .../listeners/SlimefunBootsListener.java | 114 +++++++----------- .../setup/SlimefunItemSetup.java | 3 +- 4 files changed, 141 insertions(+), 70 deletions(-) create mode 100644 src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/armor/StomperBoots.java diff --git a/CHANGELOG.md b/CHANGELOG.md index e978fd9b8..59f2c2f60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -81,6 +81,7 @@ * Fixed Electric Press not working * Fixed #2240 * Fixed #2243 +* Fixed #2249 ## Release Candidate 15 (01 Aug 2020) diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/armor/StomperBoots.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/armor/StomperBoots.java new file mode 100644 index 000000000..4dc7fa842 --- /dev/null +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/items/armor/StomperBoots.java @@ -0,0 +1,93 @@ +package io.github.thebusybiscuit.slimefun4.implementation.items.armor; + +import org.bukkit.Bukkit; +import org.bukkit.Effect; +import org.bukkit.Location; +import org.bukkit.Sound; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; + +import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction; +import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; +import me.mrCookieSlime.Slimefun.Lists.RecipeType; +import me.mrCookieSlime.Slimefun.Objects.Category; +import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; +import me.mrCookieSlime.Slimefun.api.SlimefunItemStack; + +/** + * The Boots of the Stomper are boots which damage nearby enemies whenever the {@link Player} + * takes fall damage. + * + * @author TheBusyBiscuit + * + */ +public class StomperBoots extends SlimefunItem { + + public StomperBoots(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) { + super(category, item, recipeType, recipe); + } + + /** + * This will apply the "stomp" effect to the given {@link EntityDamageEvent}. + * + * @param fallDamageEvent + * The {@link EntityDamageEvent} in which the {@link Player} has taken fall damage + */ + public void stomp(EntityDamageEvent fallDamageEvent) { + Player p = (Player) fallDamageEvent.getEntity(); + p.getWorld().playSound(p.getLocation(), Sound.ENTITY_ZOMBIE_BREAK_WOODEN_DOOR, 1F, 2F); + p.setVelocity(new Vector(0, 0.7, 0)); + + for (Entity n : p.getNearbyEntities(4, 4, 4)) { + if (n instanceof LivingEntity && n.isValid() && !n.getUniqueId().equals(p.getUniqueId())) { + Vector velocity = getShockwave(p.getLocation(), n.getLocation()); + n.setVelocity(velocity); + + // Check if it's not a Player or if PvP is enabled + if (!(n instanceof Player) || (p.getWorld().getPVP() && SlimefunPlugin.getProtectionManager().hasPermission(p, n.getLocation(), ProtectableAction.PVP))) { + EntityDamageByEntityEvent event = new EntityDamageByEntityEvent(p, n, DamageCause.ENTITY_ATTACK, fallDamageEvent.getDamage() / 2); + Bukkit.getPluginManager().callEvent(event); + + if (!event.isCancelled()) { + ((LivingEntity) n).damage(event.getDamage()); + } + } + } + } + + for (BlockFace face : BlockFace.values()) { + Block b = p.getLocation().getBlock().getRelative(BlockFace.DOWN).getRelative(face); + p.getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, b.getType()); + } + } + + /** + * This gives us the "shockwave" {@link Vector} for a given target. + * + * @param origin + * The {@link Location} of our {@link Player} + * @param target + * The {@link Location} of the {@link Entity} we are pushing away + * + * @return A {@link Vector} to determine the velocity for our {@link Entity} + */ + private Vector getShockwave(Location origin, Location target) { + // As the distance approached zero we might slip into a "division by zero" when normalizing + if (origin.distanceSquared(target) < 0.05) { + return new Vector(0, 1, 0); + } + else { + Vector direction = target.toVector().subtract(origin.toVector()); + return direction.normalize().multiply(1.4); + } + } + +} diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunBootsListener.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunBootsListener.java index cc786d63e..8ed579c53 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunBootsListener.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/listeners/SlimefunBootsListener.java @@ -1,20 +1,9 @@ package io.github.thebusybiscuit.slimefun4.implementation.listeners; -import java.util.HashMap; -import java.util.Map; -import java.util.function.Predicate; - -import org.bukkit.Bukkit; -import org.bukkit.Effect; import org.bukkit.Material; -import org.bukkit.Sound; import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; import org.bukkit.entity.EnderPearl; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; -import org.bukkit.event.Event; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; @@ -24,20 +13,19 @@ import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemStack; -import org.bukkit.util.Vector; -import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems; import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin; import io.github.thebusybiscuit.slimefun4.implementation.items.armor.SlimefunArmorPiece; +import io.github.thebusybiscuit.slimefun4.implementation.items.armor.StomperBoots; import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem; import me.mrCookieSlime.Slimefun.api.Slimefun; /** * This {@link Listener} is responsible for handling all boots provided by - * Slimefun, such as the Boots of the Stomper or any {@link SlimefunArmorPiece} that - * is a pair of boots and needs to listen to an {@link Event}. + * Slimefun, such as the {@link StomperBoots} or any {@link SlimefunArmorPiece} that + * is a pair of boots and needs to listen to an {@link EntityDamageEvent}. * * @author TheBusyBiscuit * @author Walshy @@ -45,71 +33,55 @@ import me.mrCookieSlime.Slimefun.api.Slimefun; */ public class SlimefunBootsListener implements Listener { - private final Map> cancelledEvents = new HashMap<>(); - public SlimefunBootsListener(SlimefunPlugin plugin) { plugin.getServer().getPluginManager().registerEvents(this, plugin); - - cancelledEvents.put("ENDER_BOOTS", e -> e instanceof EntityDamageByEntityEvent && ((EntityDamageByEntityEvent) e).getDamager() instanceof EnderPearl); - - cancelledEvents.put("BOOTS_OF_THE_STOMPER", e -> { - if (e.getCause() == DamageCause.FALL) { - stomp(e); - return true; - } - - return false; - }); - - cancelledEvents.put("SLIME_BOOTS", e -> e.getCause() == DamageCause.FALL); - - cancelledEvents.put("SLIME_STEEL_BOOTS", e -> e.getCause() == DamageCause.FALL); - } - - private void stomp(EntityDamageEvent e) { - Player p = (Player) e.getEntity(); - p.getWorld().playSound(p.getLocation(), Sound.ENTITY_ZOMBIE_BREAK_WOODEN_DOOR, 1F, 2F); - p.setVelocity(new Vector(0.0, 0.7, 0.0)); - - for (Entity n : p.getNearbyEntities(4, 4, 4)) { - if (n instanceof LivingEntity && !n.getUniqueId().equals(p.getUniqueId())) { - Vector velocity = n.getLocation().toVector().subtract(p.getLocation().toVector()).normalize().multiply(1.4); - n.setVelocity(velocity); - - if (!(n instanceof Player) || (p.getWorld().getPVP() && SlimefunPlugin.getProtectionManager().hasPermission(p, n.getLocation(), ProtectableAction.PVP))) { - EntityDamageByEntityEvent event = new EntityDamageByEntityEvent(p, n, DamageCause.ENTITY_ATTACK, e.getDamage() / 2); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) ((LivingEntity) n).damage(e.getDamage() / 2); - } - } - } - - for (BlockFace face : BlockFace.values()) { - Block b = p.getLocation().getBlock().getRelative(BlockFace.DOWN).getRelative(face); - p.getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, b.getType()); - } } @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) public void onDamage(EntityDamageEvent e) { if (e.getEntity() instanceof Player) { - Player p = (Player) e.getEntity(); - SlimefunItem boots = SlimefunItem.getByItem(p.getInventory().getBoots()); + if (e.getCause() == DamageCause.FALL) { + onFallDamage(e); + } + else if (e instanceof EntityDamageByEntityEvent) { + EntityDamageByEntityEvent event = (EntityDamageByEntityEvent) e; - if (boots != null) { - for (Map.Entry> event : cancelledEvents.entrySet()) { - if (boots.getID().equals(event.getKey())) { - if (Slimefun.hasUnlocked(p, boots, true) && event.getValue().test(e)) { - e.setCancelled(true); - } - - break; - } + if (event.getDamager() instanceof EnderPearl) { + onEnderPearlDamage(e); } } } } + private void onFallDamage(EntityDamageEvent e) { + Player p = (Player) e.getEntity(); + SlimefunItem boots = SlimefunItem.getByItem(p.getInventory().getBoots()); + + if (boots != null) { + // Check if the boots were researched + if (!Slimefun.hasUnlocked(p, boots, true)) { + return; + } + + if (boots instanceof StomperBoots) { + e.setCancelled(true); + ((StomperBoots) boots).stomp(e); + } + else if (boots.getID().equals("SLIME_BOOTS") || boots.getID().equals("SLIME_STEEL_BOOTS")) { + e.setCancelled(true); + } + } + } + + private void onEnderPearlDamage(EntityDamageEvent e) { + Player p = (Player) e.getEntity(); + SlimefunItem boots = SlimefunItem.getByItem(p.getInventory().getBoots()); + + if (boots != null && boots.getID().equals("ENDER_BOOTS") && Slimefun.hasUnlocked(p, boots, true)) { + e.setCancelled(true); + } + } + @EventHandler public void onTrample(PlayerInteractEvent e) { if (e.getAction() == Action.PHYSICAL) { @@ -118,8 +90,12 @@ public class SlimefunBootsListener implements Listener { if (b != null && b.getType() == Material.FARMLAND) { ItemStack boots = e.getPlayer().getInventory().getBoots(); - if (SlimefunUtils.isItemSimilar(boots, SlimefunItems.FARMER_SHOES, true) && Slimefun.hasUnlocked(e.getPlayer(), boots, true)) { - e.setCancelled(true); + if (SlimefunUtils.isItemSimilar(boots, SlimefunItems.FARMER_SHOES, true)) { + SlimefunItem item = SlimefunItems.FARMER_SHOES.getItem(); + + if (Slimefun.hasUnlocked(e.getPlayer(), item, true)) { + e.setCancelled(true); + } } } } diff --git a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/setup/SlimefunItemSetup.java b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/setup/SlimefunItemSetup.java index eb55db291..2b72e0f0d 100644 --- a/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/setup/SlimefunItemSetup.java +++ b/src/main/java/io/github/thebusybiscuit/slimefun4/implementation/setup/SlimefunItemSetup.java @@ -34,6 +34,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.androids.Woodcutt import io.github.thebusybiscuit.slimefun4.implementation.items.armor.HazmatArmorPiece; import io.github.thebusybiscuit.slimefun4.implementation.items.armor.Parachute; import io.github.thebusybiscuit.slimefun4.implementation.items.armor.SlimefunArmorPiece; +import io.github.thebusybiscuit.slimefun4.implementation.items.armor.StomperBoots; import io.github.thebusybiscuit.slimefun4.implementation.items.backpacks.Cooler; import io.github.thebusybiscuit.slimefun4.implementation.items.backpacks.EnderBackpack; import io.github.thebusybiscuit.slimefun4.implementation.items.backpacks.RestoredBackpack; @@ -1063,7 +1064,7 @@ public final class SlimefunItemSetup { new IndustrialMiner(categories.basicMachines, SlimefunItems.INDUSTRIAL_MINER, Material.IRON_BLOCK, false, 3).register(plugin); new AdvancedIndustrialMiner(categories.basicMachines, SlimefunItems.ADVANCED_INDUSTRIAL_MINER).register(plugin); - new SlimefunItem(categories.magicalArmor, SlimefunItems.BOOTS_OF_THE_STOMPER, RecipeType.ARMOR_FORGE, + new StomperBoots(categories.magicalArmor, SlimefunItems.BOOTS_OF_THE_STOMPER, RecipeType.ARMOR_FORGE, new ItemStack[] {null, null, null, new ItemStack(Material.YELLOW_WOOL), null, new ItemStack(Material.YELLOW_WOOL), new ItemStack(Material.PISTON), null, new ItemStack(Material.PISTON)}) .register(plugin);