无法编辑符号 - Bukkit:org.bukkit.command.CommandException:插件 X 中执行命令 'sign' 时未处理的异常

Cannot edit sign - Bukkit: org.bukkit.command.CommandException: Unhandled exception executing command 'sign' in plugin X

我是 bukkit/spigot 的新手,我正在制作一个插件,玩家可以在其中键入命令“/sign”,然后会在玩家旁边创建一个附在木块上的标志。该标志将显示 'Hello PlayerName'。但是,我得到了错误:org.bukkit.command.CommandException: Unhandled exception executing command 'sign' in plugin.

这是我的部分代码:

        if (cmd.getName().equalsIgnoreCase("sign") && sender instanceof Player){

        Player player = (Player) sender;
        Location location = player.getLocation();
        World someWorld = Bukkit.getServer().getWorld("world");

        double playerx = location.getX();
        double playery = location.getY();
        double playerz = location.getZ();

        int px = (int)playerx;
        int py = (int)playery;
        int pz = (int)playerz;

        Location nLoc = new Location(someWorld, px+2, py+1, pz);

        Location sLoc = new Location(someWorld, px+1, py+1, pz);


        Block block = someWorld.getBlockAt(nLoc);
        block.setType(Material.WOOD);

        Block block1 = someWorld.getBlockAt(sLoc);
        block1.setType(Material.SIGN);
        Sign sign = (Sign) block1.getState();
        sign.setLine(0, "Hello\n"+player.getName());




    }

我该如何解决这个错误?

我在控制台上得到的完整错误是:

[17:46:00 ERROR]: null
org.bukkit.command.CommandException: Unhandled exception executing command 'sign' in plugin FirstPlugin v1.0
        at org.bukkit.command.PluginCommand.execute(PluginCommand.java:46) ~[spigot-1.9.jar:git-Spigot-d20369f-7fc5cd8]
        at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:141) ~[spigot-1.9.jar:git-Spigot-d20369f-7fc5cd8]
        at org.bukkit.craftbukkit.v1_9_R1.CraftServer.dispatchCommand(CraftServer.java:645) ~[spigot-1.9.jar:git-Spigot-d20369f-7fc5cd8]
        at net.minecraft.server.v1_9_R1.PlayerConnection.handleCommand(PlayerConnection.java:1350) [spigot-1.9.jar:git-Spigot-d20369f-7fc5cd8]
        at net.minecraft.server.v1_9_R1.PlayerConnection.a(PlayerConnection.java:1185) [spigot-1.9.jar:git-Spigot-d20369f-7fc5cd8]
        at net.minecraft.server.v1_9_R1.PacketPlayInChat.a(PacketPlayInChat.java:45) [spigot-1.9.jar:git-Spigot-d20369f-7fc5cd8]
        at net.minecraft.server.v1_9_R1.PacketPlayInChat.a(PacketPlayInChat.java:1) [spigot-1.9.jar:git-Spigot-d20369f-7fc5cd8]
        at net.minecraft.server.v1_9_R1.PlayerConnectionUtils.run(SourceFile:13) [spigot-1.9.jar:git-Spigot-d20369f-7fc5cd8]
        at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) [?:1.8.0_71]
        at java.util.concurrent.FutureTask.run(Unknown Source) [?:1.8.0_71]
        at net.minecraft.server.v1_9_R1.SystemUtils.a(SourceFile:45) [spigot-1.9.jar:git-Spigot-d20369f-7fc5cd8]
        at net.minecraft.server.v1_9_R1.MinecraftServer.D(MinecraftServer.java:721) [spigot-1.9.jar:git-Spigot-d20369f-7fc5cd8]
        at net.minecraft.server.v1_9_R1.DedicatedServer.D(DedicatedServer.java:400) [spigot-1.9.jar:git-Spigot-d20369f-7fc5cd8]
        at net.minecraft.server.v1_9_R1.MinecraftServer.C(MinecraftServer.java:660) [spigot-1.9.jar:git-Spigot-d20369f-7fc5cd8]
        at net.minecraft.server.v1_9_R1.MinecraftServer.run(MinecraftServer.java:559) [spigot-1.9.jar:git-Spigot-d20369f-7fc5cd8]
        at java.lang.Thread.run(Unknown Source) [?:1.8.0_71]
Caused by: java.lang.ClassCastException: org.bukkit.craftbukkit.v1_9_R1.block.CraftBlockState cannot be cast to org.bukkit.block.Sign
        at zak.firstplugin.FirstPlugin.onCommand(FirstPlugin.java:58) ~[?:?]
        at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44) ~[spigot-1.9.jar:git-Spigot-d20369f-7fc5cd8]
        ... 15 more

如果您将 BlockBlockState 转换为它不是其实例的子 class,则会抛出此错误(就像在您的堆栈跟踪中一样):org.bukkit.craftbukkit.[version].block.CraftBlockState cannot be cast to org.bukkit.block.[YourState]。换句话说,您的代码会抛出该错误,因为该块实际上不是 Sign,因为它的 BlockState 不是 Sign 的实例。将来,您可以随时检查使用 instanceof 以确保 superclass 可以转换为特定的 subclass:

if (block.getState() instanceof Sign) {
    Sign sign = (Sign) block.getState();
    // ... Your code
}

即使您将其 material 设置为 Material.SIGN,您的方块也不是符号的原因是 Material.SIGN 枚举器实际上指的是符号 item 类型,不是类型,实际上有两种(Material.SIGN_POSTMaterial.WALL_SIGN)。令人困惑的是,当您将 Block 的类型设置为项目类型时,Bukkit/Spigot 不会警告您,而是将 Block 的类型或 material 设置为空气(因此 ClassCastException 被抛出)。我猜既然你正在为标志生成一个实心块,你可能想要后者的枚举器或 Material.WALL_SIGN.

此外,为了确保标牌上的文字出现,您需要使用 state.update() 更新 BlockState(甚至可能使用 state.update(true) 强制更新)。

要在下一行写下玩家的名字,您需要使用 sign.setLine(1, player.getName())String 添加到第 2 行(索引 1),而不是使用 \n 换行符Minecraft 标志无法处理的角色。

最后但并非最不重要的一点是,您案例中的墙上标志将面向错误的方向,可以通过更改标志的旋转来解决。这当然取决于木块相对于标志的放置位置,因此在您的情况下,标志需要旋转面向西。要设置标志的旋转,我们可以对 Blocks 使用已弃用的 setData(byte data) 方法,但如果您想使用未弃用的、更易于阅读的方法,我们将不得不处理另一个小问题怪癖:有一个org.bukkit.block.Sign接口,还有一个org.bukkit.material.SignclassSign 的所有用法都指的是 org.bukkit.block.Sign 接口,它是 BlockState 的子类型。这用于例如设置标志的文本。 org.bukkit.material.SignMaterialData class 的子类型,我们可以使用 state.getData() 访问它并用于更改符号的方向,因为 class 实现了 Directional 接口(特别是 Attachable 接口)。因此,要设置文本 旋转符号,我们必须同时使用 class 和界面。这是一些示例代码:

Block sign = world.getBlockAt(signLoc); // Get the block
sign.setType(Material.WALL_SIGN); // Set the type to "WALL_SIGN", now it's BlockState is an instance of "Sign"

BlockState signState = sign.getState(); // Get the general state

if (signState instanceof org.bukkit.block.Sign) { // Make sure the sign block really does have the "Sign" BlockState (this isn't really necessary, more of a double check)
    org.bukkit.block.Sign signBlock = (org.bukkit.block.Sign) signState; // Note that this is the org.bukkit.block.Sign interface
    signBlock.setLine(0, "Hello"); // Set the first line
    signBlock.setLine(1, player.getName()); // Set the second line
    if (signState.getData() instanceof org.bukkit.material.Sign) { // Now get the "MaterialData" from the BlockState...
        org.bukkit.material.Sign signMaterialData = (org.bukkit.material.Sign) signState.getData(); // And cast it to org.bukkit.material.Sign
        signMaterialData.setFacingDirection(BlockFace.WEST); // Use this to change the direction of the sign, in this case WEST (sign is placed + X direction of player)
    }
    signBlock.update(); // Update the sign's state
}