From d984955af38405097a5cc96248f6b1fa54d4168d Mon Sep 17 00:00:00 2001 From: BONNe Date: Tue, 14 Jun 2022 01:18:52 +0300 Subject: [PATCH] Fixes Range Display command crashes. Spigot in 1.18 introduce new way how block particles should be displayed. However, BentoBox never fully implemented it. To avoid such issues in-future, I added checks for each particle type that requires extra data object. Fixes #1989 --- .../admin/range/AdminRangeDisplayCommand.java | 9 +- .../bentobox/bentobox/api/user/User.java | 85 +++++++++++++++++-- 2 files changed, 81 insertions(+), 13 deletions(-) diff --git a/src/main/java/world/bentobox/bentobox/api/commands/admin/range/AdminRangeDisplayCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/admin/range/AdminRangeDisplayCommand.java index 8e0bed0b2..1b5135fb8 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/admin/range/AdminRangeDisplayCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/admin/range/AdminRangeDisplayCommand.java @@ -7,10 +7,9 @@ import java.util.Map; import org.bukkit.Bukkit; import org.bukkit.Color; import org.bukkit.Location; +import org.bukkit.Material; import org.bukkit.Particle; -import com.google.common.base.Enums; - import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.database.objects.Island; @@ -24,8 +23,6 @@ public class AdminRangeDisplayCommand extends CompositeCommand { private static final String DISPLAY = "display"; private static final String SHOW = "show"; private static final String HIDE = "hide"; - // Since 1.18, the Particle.BARRIER was replaced by BLOCK_MARKER - private static final Particle BARRIER = Enums.getIfPresent(Particle.class, "BARRIER").or(Enums.getIfPresent(Particle.class, "BLOCK_MARKER").or(Particle.LAVA)); // Map of users to which ranges must be displayed private final Map displayRanges = new HashMap<>(); @@ -75,7 +72,7 @@ public class AdminRangeDisplayCommand extends CompositeCommand { getIslands().getIslandAt(user.getLocation()).ifPresent(island -> { // Draw the island protected area - drawZone(user, BARRIER, null, island, island.getProtectionRange()); + drawZone(user, Particle.BLOCK_MARKER, Material.BARRIER.createBlockData(), island, island.getProtectionRange()); // Draw the default protected area if island protected zone is different if (island.getProtectionRange() != getPlugin().getIWM().getIslandProtectionRange(getWorld())) { @@ -94,7 +91,7 @@ public class AdminRangeDisplayCommand extends CompositeCommand { displayRanges.remove(user); } - private void drawZone(User user, Particle particle, Particle.DustOptions dustOptions, Island island, int range) { + private void drawZone(User user, Particle particle, Object dustOptions, Island island, int range) { Location center = island.getProtectionCenter(); // Get player Y coordinate int playerY = user.getPlayer().getLocation().getBlockY() + 1; diff --git a/src/main/java/world/bentobox/bentobox/api/user/User.java b/src/main/java/world/bentobox/bentobox/api/user/User.java index 2c241e453..2fd7ac70c 100644 --- a/src/main/java/world/bentobox/bentobox/api/user/User.java +++ b/src/main/java/world/bentobox/bentobox/api/user/User.java @@ -17,10 +17,13 @@ import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.OfflinePlayer; import org.bukkit.Particle; +import org.bukkit.Vibration; import org.bukkit.World; +import org.bukkit.block.data.BlockData; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; import org.bukkit.permissions.PermissionAttachment; import org.bukkit.permissions.PermissionAttachmentInfo; @@ -597,22 +600,90 @@ public class User implements MetaDataAble { * @param y Y coordinate of the particle to display. * @param z Z coordinate of the particle to display. */ - public void spawnParticle(Particle particle, Particle.DustOptions dustOptions, double x, double y, double z) { - if (particle.equals(Particle.REDSTONE) && dustOptions == null) { - // Security check that will avoid later unexpected exceptions. - throw new IllegalArgumentException("A non-null Particle.DustOptions must be provided when using Particle.REDSTONE as particle."); + public void spawnParticle(Particle particle, Object dustOptions, double x, double y, double z) + { + // Improve particle validation. + switch (particle) + { + case REDSTONE -> + { + if (!(dustOptions instanceof Particle.DustOptions)) + { + throw new IllegalArgumentException("A non-null Particle.DustOptions must be provided when using Particle.REDSTONE as particle."); + } + } + case ITEM_CRACK -> + { + if (!(dustOptions instanceof ItemStack)) + { + throw new IllegalArgumentException("A non-null ItemStack must be provided when using Particle.ITEM_CRACK as particle."); + } + } + case BLOCK_CRACK, BLOCK_DUST, FALLING_DUST, BLOCK_MARKER -> + { + if (!(dustOptions instanceof BlockData)) + { + throw new IllegalArgumentException("A non-null BlockData must be provided when using Particle." + particle + " as particle."); + } + } + case DUST_COLOR_TRANSITION -> + { + if (!(dustOptions instanceof Particle.DustTransition)) + { + throw new IllegalArgumentException("A non-null Particle.DustTransition must be provided when using Particle.DUST_COLOR_TRANSITION as particle."); + } + } + case VIBRATION -> + { + if (!(dustOptions instanceof Vibration)) + { + throw new IllegalArgumentException("A non-null Vibration must be provided when using Particle.VIBRATION as particle."); + } + } + case SCULK_CHARGE -> + { + if (!(dustOptions instanceof Float)) + { + throw new IllegalArgumentException("A non-null Float must be provided when using Particle.SCULK_CHARGE as particle."); + } + } + case SHRIEK -> + { + if (!(dustOptions instanceof Integer)) + { + throw new IllegalArgumentException("A non-null Integer must be provided when using Particle.SHRIEK as particle."); + } + } + case LEGACY_BLOCK_CRACK, LEGACY_BLOCK_DUST, LEGACY_FALLING_DUST -> + { + if (!(dustOptions instanceof BlockData)) + { + throw new IllegalArgumentException("A non-null MaterialData must be provided when using Particle." + particle + " as particle."); + } + } } // Check if this particle is beyond the viewing distance of the server - if (player.getLocation().toVector().distanceSquared(new Vector(x,y,z)) < (Bukkit.getServer().getViewDistance()*256*Bukkit.getServer().getViewDistance())) { - if (particle.equals(Particle.REDSTONE)) { + if (this.player != null && + this.player.getLocation().toVector().distanceSquared(new Vector(x, y, z)) < + (Bukkit.getServer().getViewDistance() * 256 * Bukkit.getServer().getViewDistance())) + { + if (particle.equals(Particle.REDSTONE)) + { player.spawnParticle(particle, x, y, z, 1, 0, 0, 0, 1, dustOptions); - } else { + } + else if (dustOptions != null) + { + player.spawnParticle(particle, x, y, z, 1, dustOptions); + } + else + { player.spawnParticle(particle, x, y, z, 1); } } } + /** * Spawn particles to the player. * They are only displayed if they are within the server's view distance.