From 4ef3d5bf3b998beada4ad8fe741fd8d3448ca115 Mon Sep 17 00:00:00 2001 From: Joseph Hale Date: Fri, 4 Jun 2021 20:08:04 -0700 Subject: [PATCH] Refactor onProjectileHit + Particle Trails Abstracted the common components of the onProjectileHit method into the PowerArrow parent class. Also added particles to the trails of Power Arrows. --- build.gradle | 2 +- .../jhale1805/powerarrow/ExplosiveArrow.java | 23 +++----- .../jhale1805/powerarrow/ForestFireArrow.java | 58 +++++++++---------- .../jhale1805/powerarrow/PowerArrow.java | 57 ++++++++++++++++++ .../jhale1805/powerarrow/TorchArrow.java | 8 +-- .../io/github/jhale1805/util/Utilities.java | 31 ++++++++++ src/main/resources/plugin.yml | 2 +- 7 files changed, 130 insertions(+), 51 deletions(-) create mode 100644 src/main/java/io/github/jhale1805/util/Utilities.java diff --git a/build.gradle b/build.gradle index dc189e3..fe9c177 100644 --- a/build.gradle +++ b/build.gradle @@ -39,5 +39,5 @@ dependencies { } jar { - archiveVersion = '1.3.0' + archiveVersion = '1.3.1' } \ No newline at end of file diff --git a/src/main/java/io/github/jhale1805/powerarrow/ExplosiveArrow.java b/src/main/java/io/github/jhale1805/powerarrow/ExplosiveArrow.java index 4cd4aab..ebffb09 100644 --- a/src/main/java/io/github/jhale1805/powerarrow/ExplosiveArrow.java +++ b/src/main/java/io/github/jhale1805/powerarrow/ExplosiveArrow.java @@ -2,10 +2,11 @@ package io.github.jhale1805.powerarrow; import org.bukkit.Location; import org.bukkit.Material; -import org.bukkit.event.EventHandler; import org.bukkit.event.entity.ProjectileHitEvent; import org.bukkit.inventory.ShapedRecipe; +import io.github.jhale1805.util.Utilities; + public class ExplosiveArrow extends PowerArrow { public ExplosiveArrow() { @@ -38,28 +39,22 @@ public class ExplosiveArrow extends PowerArrow { return recipe; } - @EventHandler - public void onProjectileHit(ProjectileHitEvent event) { + @Override + protected void onThisProjectileHit(ProjectileHitEvent event) { // Check preconditions for explosion - if (!(this.isSimilar(event.getEntity()) - && event.getEntity().getFireTicks() > 0)) + if (!(event.getEntity().getFireTicks() > 0)) return; - Location impactSite = null; - if (event.getHitBlock() != null) { - impactSite = event.getHitBlock().getLocation(); - } else if (event.getHitEntity() != null) { - impactSite = event.getHitEntity().getLocation(); - } - if (impactSite != null) { + + Location impactLocation = Utilities.getImpactLocation(event); + if (impactLocation != null) { event.getEntity().getWorld().createExplosion( - impactSite, // Cause the explosion where the arrow hit. + impactLocation, // Cause the explosion where the arrow hit. 1F, // Cause an explosion of 1/4th the power of TNT false, // Don't start fires true, // Do break blocks. event.getEntity() ); } - event.getEntity().remove(); } } diff --git a/src/main/java/io/github/jhale1805/powerarrow/ForestFireArrow.java b/src/main/java/io/github/jhale1805/powerarrow/ForestFireArrow.java index 780f5c3..8c4fe97 100644 --- a/src/main/java/io/github/jhale1805/powerarrow/ForestFireArrow.java +++ b/src/main/java/io/github/jhale1805/powerarrow/ForestFireArrow.java @@ -2,11 +2,13 @@ package io.github.jhale1805.powerarrow; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.Particle; import org.bukkit.block.Block; -import org.bukkit.event.EventHandler; import org.bukkit.event.entity.ProjectileHitEvent; import org.bukkit.inventory.ShapedRecipe; +import io.github.jhale1805.util.Utilities; + public class ForestFireArrow extends PowerArrow { public ForestFireArrow() { @@ -40,40 +42,36 @@ public class ForestFireArrow extends PowerArrow { return recipe; } - @EventHandler - public void onProjectileHit(ProjectileHitEvent event) { - // Check preconditions for explosion - if ( !this.isSimilar(event.getEntity()) ) - return; - // Get the impact site - Location impactSite = null; - if (event.getHitBlock() != null) { - impactSite = event.getHitBlock().getLocation(); - } else if (event.getHitEntity() != null) { - impactSite = event.getHitEntity().getLocation(); - event.getHitEntity().setFireTicks(20); // ignite a hit entity + @Override + public Particle getTrailParticle() { + return Particle.LAVA; + } + + @Override + protected void onThisProjectileHit(ProjectileHitEvent event) { + Location impactLocation = Utilities.getImpactLocation(event); + if (impactLocation != null) { + startForestFire(impactLocation); } - // Start the forest fire around the impact site - if (impactSite != null) { - for (double x = -1; x <= 1; x++) { - for (double y = 0; y <= 2; y++) { - for (double z = -1; z <= 1; z++) { - Location toCheck = new Location( - event.getEntity().getWorld(), - impactSite.getX() + x, - impactSite.getY() + y, - impactSite.getZ() + z - ); - Block toIgnite = event.getEntity().getWorld() - .getBlockAt(toCheck); - if (toIgnite.getType() == Material.AIR) { - toIgnite.setType(Material.FIRE); - } + } + + private void startForestFire(Location location) { + for (double x = -1; x <= 1; x++) { + for (double y = 0; y <= 2; y++) { + for (double z = -1; z <= 1; z++) { + Location toCheck = new Location( + location.getWorld(), + location.getX() + x, + location.getY() + y, + location.getZ() + z + ); + Block toIgnite = location.getWorld().getBlockAt(toCheck); + if (toIgnite.getType() == Material.AIR) { + toIgnite.setType(Material.FIRE); } } } } - event.getEntity().remove(); } } diff --git a/src/main/java/io/github/jhale1805/powerarrow/PowerArrow.java b/src/main/java/io/github/jhale1805/powerarrow/PowerArrow.java index 63df201..c9726d7 100644 --- a/src/main/java/io/github/jhale1805/powerarrow/PowerArrow.java +++ b/src/main/java/io/github/jhale1805/powerarrow/PowerArrow.java @@ -7,12 +7,14 @@ import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.NamespacedKey; +import org.bukkit.Particle; import org.bukkit.advancement.Advancement; import org.bukkit.entity.Arrow; import org.bukkit.entity.Entity; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityShootBowEvent; +import org.bukkit.event.entity.ProjectileHitEvent; import org.bukkit.event.player.PlayerAdvancementDoneEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.inventory.ItemStack; @@ -20,6 +22,7 @@ import org.bukkit.inventory.ShapedRecipe; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.metadata.FixedMetadataValue; import org.bukkit.metadata.MetadataValue; +import org.bukkit.scheduler.BukkitRunnable; import io.github.jhale1805.PowerProjectilePlugin; @@ -48,8 +51,24 @@ public abstract class PowerArrow extends ItemStack implements Listener { */ public abstract String[] getUsageInstructions(); + /** + * Returns the crafting recipe for this Power Arrow. + * @return the crafting recipe for this Power Arrow. + */ public abstract ShapedRecipe getRecipe(); + /** + * Returns the type of particle used in the trail of this Power Arrow. + * + * Defaults to `null` which will use the default arrow particle trail. + * Override this method in a subclass to specify your desired particle. + * + * @return the type of particle used in the trail of this Power Arrow. + */ + public Particle getTrailParticle() { + return null; + } + public NamespacedKey getRecipeKey() { return new NamespacedKey(PowerProjectilePlugin.instance, "recipe/" + this.getName()); } @@ -85,9 +104,47 @@ public abstract class PowerArrow extends ItemStack implements Listener { if (event.getConsumable().getItemMeta().equals(this.getItemMetadata())) { event.getProjectile().setMetadata("effect", this.getEntityMetadata()); event.setConsumeItem(true); // Ignore the effects of Infinity + if (this.getTrailParticle() != null) { + this.drawTrail(event.getProjectile(), this.getTrailParticle()); + } } } + @EventHandler + public void onProjectileHit(ProjectileHitEvent event) { + if ( !this.isSimilar(event.getEntity()) ) + return; + + this.onThisProjectileHit(event); + event.getEntity().remove(); + } + + /** + * Creates the effect caused when this Power Arrow hits something. + * + * This method is guaranteed to only be called when the Projectile is + * a power arrow of this type. + * + * @param event The ProjectileHitEvent to process. + */ + protected abstract void onThisProjectileHit(ProjectileHitEvent event); + + private void drawTrail(Entity arrow, Particle particle) { + new BukkitRunnable(){ + @Override + public void run() { + if (arrow.isDead() || arrow.isOnGround()) + this.cancel(); + + arrow.getLocation().getWorld().spawnParticle( + particle, + arrow.getLocation(), + 5 + ); + } + }.runTaskTimer(PowerProjectilePlugin.instance, 0, 4); + } + @EventHandler public void onPlayerAdvancementDone(PlayerAdvancementDoneEvent event) { // Show the Torch Arrow in the recipe book upon completing the Enchanter advancement. diff --git a/src/main/java/io/github/jhale1805/powerarrow/TorchArrow.java b/src/main/java/io/github/jhale1805/powerarrow/TorchArrow.java index 4266505..b8f423e 100644 --- a/src/main/java/io/github/jhale1805/powerarrow/TorchArrow.java +++ b/src/main/java/io/github/jhale1805/powerarrow/TorchArrow.java @@ -5,7 +5,6 @@ import org.bukkit.Tag; import org.bukkit.block.BlockFace; import org.bukkit.block.data.BlockData; import org.bukkit.block.data.Directional; -import org.bukkit.event.EventHandler; import org.bukkit.event.entity.ProjectileHitEvent; import org.bukkit.inventory.RecipeChoice.MaterialChoice; import org.bukkit.inventory.ShapedRecipe; @@ -42,11 +41,10 @@ public class TorchArrow extends PowerArrow { return recipe; } - @EventHandler - public void onProjectileHit(ProjectileHitEvent event) { + @Override + public void onThisProjectileHit(ProjectileHitEvent event) { // Check preconditions for torch placement - if (!(this.isSimilar(event.getEntity()) - && event.getEntity().getFireTicks() > 0 + if (!(event.getEntity().getFireTicks() > 0 && event.getHitBlock() != null && event.getHitBlockFace() != null)) return; diff --git a/src/main/java/io/github/jhale1805/util/Utilities.java b/src/main/java/io/github/jhale1805/util/Utilities.java new file mode 100644 index 0000000..1500015 --- /dev/null +++ b/src/main/java/io/github/jhale1805/util/Utilities.java @@ -0,0 +1,31 @@ +package io.github.jhale1805.util; + +import org.bukkit.Location; +import org.bukkit.Particle; +import org.bukkit.event.entity.ProjectileHitEvent; +import org.bukkit.util.Vector; + +public class Utilities { + + public static void drawParticles(Location from, Location to, Particle particle){ + if (!from.getWorld().equals(to.getWorld())) return; + + Vector direction = to.toVector().subtract(from.toVector()).normalize().multiply(0.4); + Location particleLocation = from.clone(); + while(particleLocation.distanceSquared(to) > 1){ + particleLocation = particleLocation.add(direction); + particleLocation.getWorld().spawnParticle(particle, particleLocation, 1); + } + } + + public static Location getImpactLocation(ProjectileHitEvent event) { + Location loc = null; + if (event.getHitBlock() != null) { + loc = event.getHitBlock().getLocation(); + } else if (event.getHitEntity() != null) { + loc = event.getHitEntity().getLocation(); + } + return loc; + } + +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 7687973..ffde158 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,4 +1,4 @@ name: PowerProjectile main: io.github.jhale1805.PowerProjectilePlugin -version: 1.3.0 +version: 1.3.1 api-version: 1.16 \ No newline at end of file -- 2.51.2