名为 TWICE 的玩家互动活动

问题描述 投票:0回答:1

在 Minecraft 插件
PlayerInteractEvent
期间双重使用物品的问题

上下文:我正在为 Minecraft 版本 1.16.5 开发一个插件,其中添加了一个特殊项目

FlashDust
,使用时会对一定半径内的玩家产生影响。在代码中,我注册了
PlayerInteractEvent
事件,并尝试通过检查
event.getHand()
将项目的使用限制为手动过滤。

问题:当玩家使用该物品时,

PlayerInteractEvent
事件连续触发两次,导致该物品被使用两次,即使我手动过滤事件。我尝试过使用
EquipmentSlot.HAND
插槽检查,但这并不能解决问题。

我怀疑主手和副手都触发了该事件,但手动检查没有帮助。

这是代码

package so.max1soft.customitems.dusts;

import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.Particle;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class FlashDust implements Listener {

    private final JavaPlugin plugin;
    private final Map<Player, Long> lastUse = new HashMap<>();

    public FlashDust(JavaPlugin plugin) {
        this.plugin = plugin;
    }

    public static void register(JavaPlugin plugin) {
        plugin.getServer().getPluginManager().registerEvents(new FlashDust(plugin), plugin);
    }

    public static ItemStack createItem(JavaPlugin plugin) {
        FileConfiguration config = plugin.getConfig();
        ItemStack item = new ItemStack(Material.SUGAR);
        ItemMeta meta = item.getItemMeta();

        if (meta == null) {
            return item;
        }

        String name = config.getString("dusts.flash.name");
        List<String> lore = config.getStringList("dusts.flash.lore");
        meta.setDisplayName(name);
        meta.setLore(lore);

        List<String> enchantments = config.getStringList("dusts.flash.enchantments");

        for (String enchantString : enchantments) {
            String[] parts = enchantString.split(":");
            if (parts.length != 2) {
                plugin.getLogger().warning("Invalid enchantment format: " + enchantString);
                continue;
            }

            String enchantmentName = parts[0].toUpperCase();
            Enchantment enchantment = Enchantment.getByKey(NamespacedKey.minecraft(enchantmentName.toLowerCase()));

            if (enchantment == null) {
                plugin.getLogger().warning("Unknown enchantment: " + enchantmentName);
                continue;
            }

            try {
                int level = Integer.parseInt(parts[1]);
                meta.addEnchant(enchantment, level, true);
            } catch (NumberFormatException e) {
                plugin.getLogger().warning("Invalid enchantment level: " + parts[1] + " for enchantment " + enchantmentName);
            }
        }

        meta.addItemFlags(ItemFlag.HIDE_ENCHANTS);

        item.setItemMeta(meta);
        return item;
    }

    @EventHandler
    public void onPlayerUseFlasDust(PlayerInteractEvent event) {


            if (event.getHand() == EquipmentSlot.HAND) {
            if (event.getAction() != Action.RIGHT_CLICK_AIR && event.getAction() != Action.RIGHT_CLICK_BLOCK) {
                return;
            }


            Player player = event.getPlayer();
            ItemStack item = event.getItem();


            if (item == null || item.getType() != Material.SUGAR) {
                return;
            }

            ItemMeta meta = item.getItemMeta();
            if (meta == null || !meta.hasDisplayName() || !meta.getDisplayName().equals(plugin.getConfig().getString("dusts.flash.name"))) {
                return;
            }


            if (lastUse.containsKey(player) && lastUse.get(player) + 1000L > System.currentTimeMillis()) {
                return;
            }


            if (!isCooldownActive(player)) {
                player.sendMessage("You are on cooldown!");
                return;
            }


            setCooldown(player);


            event.setCancelled(true);


            processFlasDustUsage(player, item);
        }


    }




    private boolean isCooldownActive(Player player) {
        Long lastInteract = lastUse.get(player);
        if (lastInteract == null) {
            return true;
        }
        return System.currentTimeMillis() - lastInteract >= 20000L;
    }


    private void setCooldown(Player player) {
        lastUse.put(player, System.currentTimeMillis());
    }


    private void processFlasDustUsage(Player player, ItemStack item) {

        FileConfiguration config = plugin.getConfig();
        String itemName = config.getString("dusts.flash.name");
        List<String> expectedLore = config.getStringList("dusts.flash.lore");

        ItemMeta meta = item.getItemMeta();
        if (!meta.getDisplayName().equals(itemName) || !meta.hasLore() || !meta.getLore().equals(expectedLore)) {
            plugin.getLogger().info("Item does not match expected name or lore, cancelling event.");
            return;
        }


        if (item.getAmount() > 1) {
            item.setAmount(item.getAmount() - 1);
        } else {
            player.getInventory().remove(item);
        }


        applyEffectsAndParticles(player);
    }

    private void applyEffectsAndParticles(Player player) {
        Vector initialLocation = player.getLocation().toVector();
        double fixedY = player.getLocation().getY();

        new BukkitRunnable() {
            double radius = 0;
            final double maxRadius = 7;
            final double step = 0.5;

            @Override
            public void run() {
                radius += step;

                if (radius > maxRadius) {
                    cancel();
                    return;
                }

                for (double angle = 0; angle < 360; angle += 10) {
                    double radians = Math.toRadians(angle);
                    double x = radius * Math.cos(radians);
                    double z = radius * Math.sin(radians);

                    Vector particleLocation = initialLocation.clone().add(new Vector(x, 0, z));
                    player.getWorld().spawnParticle(Particle.CLOUD, particleLocation.getX(), fixedY + 0.5, particleLocation.getZ(), 1, 0, 0, 0, 0);
                }

                for (Player nearbyPlayer : player.getWorld().getPlayers()) {
                    if (nearbyPlayer.equals(player)) continue;
                    if (nearbyPlayer.getLocation().distance(initialLocation.toLocation(player.getWorld())) <= radius) {
                        if (!nearbyPlayer.hasPotionEffect(PotionEffectType.BLINDNESS)) {
                            nearbyPlayer.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 7 * 20, 0, false, false));
                            nearbyPlayer.addPotionEffect(new PotionEffect(PotionEffectType.POISON, 3 * 20, 0, false, false));
                            nearbyPlayer.addPotionEffect(new PotionEffect(PotionEffectType.SLOW, 7 * 20, 0, false, false));
                            nearbyPlayer.addPotionEffect(new PotionEffect(PotionEffectType.GLOWING, 7 * 20, 0, false, false));
                        }
                    }
                }
            }
        }.runTaskTimer(plugin, 0, 2);
    }
}

Main.java 类

public class Main extends JavaPlugin {

    @Override
    public void onEnable() {
        saveDefaultConfig();
        FileConfiguration config = getConfig();

        // Отладочная информация
        getLogger().info("Спавн Брейкер шанс: " + config.getDouble("spawnbreak.chance"));
        FlashDust.register(this);
        ZenithDust.register(this);
        RadiusPickaxe.register(this);
        AutoSmeltingPickaxe.register(this);
        MagnetPickaxe.register(this);
        CombinedPickaxe.register(this);
        AutoSmeltingShovel.register(this);
        SpawnerBreaker.register(this);
        getCommand("socustomitems").setExecutor(this);
        getCommand("socustomitems").setTabCompleter(new CustomTabCompleter());
    }




    @Override
    public void onDisable() {

    }

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
        if (command.getName().equalsIgnoreCase("socustomitems") && args.length == 3 && args[0].equalsIgnoreCase("give")) {
            if  (sender.hasPermission("socustomitems.give")) {
                Player target = getServer().getPlayer(args[1]);
                if (target != null) {
                    String pickaxeType = args[2];
                    if (pickaxeType.equalsIgnoreCase("radius")) {
                        target.getInventory().addItem(RadiusPickaxe.createItem(this));
                    } else if (pickaxeType.equalsIgnoreCase("flame")) {
                        target.getInventory().addItem(AutoSmeltingPickaxe.createItem(this));
                    } else if (pickaxeType.equalsIgnoreCase("magnet")) {
                        target.getInventory().addItem(MagnetPickaxe.createItem(this));
                    } else if (pickaxeType.equalsIgnoreCase("combo")) {
                        target.getInventory().addItem(CombinedPickaxe.createItem(this));
                    } else if (pickaxeType.equalsIgnoreCase("flameshovel")) {
                        target.getInventory().addItem(AutoSmeltingShovel.createItem(this));
                    } else if (pickaxeType.equalsIgnoreCase("spawnbreaker")) {
                        target.getInventory().addItem(SpawnerBreaker.createItem(this));
                    } else if (pickaxeType.equalsIgnoreCase("flashdust")) {
                        target.getInventory().addItem(FlashDust.createItem(this));
                    } else if (pickaxeType.equalsIgnoreCase("zenithdust")) {
                        target.getInventory().addItem(ZenithDust.createItem(this));
                    } else {
                        sender.sendMessage("Типы: radius, flame, magnet, combo, flameshovel, spawnbreaker, flashdust, zenithdust");
                    }
                    return true;
                } else {
                    sender.sendMessage("Такого кубхеда не существует!");
                }
            }
        }
        return false;
    }
}
events bukkit interaction spigot
1个回答
0
投票

您在手牌检查中嵌套了另一个条件,这意味着只有两个条件都为真时它才会返回。你检查这手牌的条件可以重构为:

if (event.getHand() == EquipmentSlot.HAND && (event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK)) {
    return
}

这意味着手必须是

HAND
并且动作必须是
RIGHT_CLICK_AIR
RIGHT_CLICK_BLOCK
才能返回。您可以拆分这些条件或对其进行修改,以便它们按您的预期工作。

拆分逻辑:

if (event.getHand() != EquipmentSlot.HAND) {
    // Return if the hand isn't HAND (e.g. OFF_HAND)
    return;
}
// Continue the rest of our logic
if (event.getAction()...

或者正确加入逻辑:

if (event.getHand() != EquipmentSlot.HAND || event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK) {
    return
}
© www.soinside.com 2019 - 2024. All rights reserved.