[JAVA] [Minecraft] Time operation with Bukkit / Spigot plugin


Make a note of the stumbling block at the beginning of creating the Bukkit plugin.

What you want to do

When you enter a specific word in the chat field of Minecraft, a trigger will be triggered to set the in-game time. Here, as an example, if you enter "morning", create a plug-in that changes to time 0 (morning).

Bad example

main.java


//Package statement and import statement omitted
public class main extends JavaPlugin{
    @Override
    public void onEnable() {
        getServer().getPluginManager().registerEvents(new eventListener(this), this);
    }
}

eventListener.java


//Package statement and import statement omitted
public class eventListener implements Listener {
    private final main m;
    public eventListener(main m_){m=m_;}

    @EventHandler
    public void onPlayerChat(AsyncPlayerChatEvent event){
        if(event.getMessage().equals("Morning")){
            event.getPlayer().getWorld().setTime(0L);
            event.getPlayer().sendMessage("The word "morning" has been detected.");
            m.getLogger().info(event.getPlayer().getName()+"Said the word "morning"");
        }
    }
}

Chats sent by players can be caught with ʻAsyncPlayerChatEventand can be operated freely on the plugin side. Also, [written here](https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/World.html), World is ʻevent.getPlayer (). getWorld () in the event handler. You can get it with).

The trouble is that this will compile.

Why not

The compilation was successful, and no error occurred when I actually installed it. However, when I actually type "morning", I get two errors on the server side.

[00:00:00 ERROR]: Could not pass event AsyncPlayerChatEvent to hogehoge_plugin v1.0.0
org.bukkit.event.EventException: null
	at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:312) ~[craftbukkit-1.15.2.jar:git-Bukkit-8160e29]
	at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:70) ~[craftbukkit-1.15.2.jar:git-Bukkit-8160e29]
~ Abbreviation ~
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:461) [craftbukkit-1.15.2.jar:git-Bukkit-8160e29]
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884) [craftbukkit-1.15.2.jar:git-Bukkit-8160e29]
	at java.lang.Thread.run(Thread.java:830) [?:?]
Caused by: java.lang.IllegalStateException: TimeSkipEvent cannot be triggered asynchronously from another thread.
	at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:510) ~[craftbukkit-1.15.2.jar:git-Bukkit-8160e29]
	at org.bukkit.craftbukkit.v1_15_R1.CraftWorld.setFullTime(CraftWorld.java:803) ~[craftbukkit-1.15.2.jar:git-Bukkit-8160e29]
~ Abbreviation ~

As described in this document, ʻAsyncPlayerChatEvent is basically executed asynchronously. However, ʻevent.getPlayer (). GetWorld (). SetTime (0L); must be executed synchronously.

Solution

There are several solutions, but the simplest implementation of anonymous classes avoids the error.

main.java


//You can leave it as it is

eventListener.java


//Package statement and import statement omitted
public class eventListener implements Listener {
    private final main m;
    public eventListener(main m_){m=m_;}

    @EventHandler
    public void onPlayerChat(AsyncPlayerChatEvent event){
        if(event.getMessage().equals("Morning")){
            m.getServer().getScheduler().runTask(m, new Runnable() {
                @Override
                public void run() {event.getPlayer().getWorld().setTime(0L);}
            });
            event.getPlayer().sendMessage("The word "morning" has been detected.");
            m.getLogger().info(event.getPlayer().getName()+"Said the word "morning"");
        }
    }
}

I am using the scheduler of ʻorg.bukkit.scheduler to call synchronous processing from the asynchronous ʻAsyncPlayerChatEvent. runTask executes the registered class on the next tick (server tick). If you want to wait a bit, use runTaskLater instead.



that's all.

Recommended Posts

[Minecraft] Time operation with Bukkit / Spigot plugin
Plugin development with ImageJ