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
This commit is contained in:
BONNe 2022-06-14 01:18:52 +03:00
parent 85b52f4bfb
commit d984955af3
2 changed files with 81 additions and 13 deletions

View File

@ -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<User, Integer> 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;

View File

@ -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.