Solved AsyncPlayerChatEvent

Discussion in 'Spigot Plugin Development' started by aufgosh, Mar 3, 2020.

  1. Hello,

    I am trying to execute a command from the Console when player is typing a certain word, but it wont let me and i cant figure out why

    Code (Text):
    Could not pass event AsyncPlayerChatEvent to Core v1.0
    java.lang.IllegalStateException: Asynchronous command dispatch!
        at org.spigotmc.AsyncCatcher.catchOp(AsyncCatcher.java:15) ~[patched_1.15.2.jar:git-Paper-118]
        at org.bukkit.craftbukkit.v1_15_R1.CraftServer.dispatchCommand(CraftServer.java:717) ~[patched_1.15.2.jar:git-Paper-118]
        at org.bukkit.Bukkit.dispatchCommand(Bukkit.java:660) ~[patched_1.15.2.jar:git-Paper-118]
        at listener.JoinListener.asyncEvent(JoinListener.java:194) ~[?:?]
        at com.destroystokyo.paper.event.executor.asm.generated.GeneratedEventExecutor1.execute(Unknown Source) ~[?:?]
        at org.bukkit.plugin.EventExecutor.lambda$create$1(EventExecutor.java:69) ~[patched_1.15.2.jar:git-Paper-118]
        at co.aikar.timings.TimedEventExecutor.execute(TimedEventExecutor.java:76) ~[patched_1.15.2.jar:git-Paper-118]
        at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:70) ~[patched_1.15.2.jar:git-Paper-118]
        at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:559) ~[patched_1.15.2.jar:git-Paper-118]
        at net.minecraft.server.v1_15_R1.PlayerConnection.chat(PlayerConnection.java:1734) ~[patched_1.15.2.jar:git-Paper-118]
        at net.minecraft.server.v1_15_R1.PlayerConnection.a(PlayerConnection.java:1649) ~[patched_1.15.2.jar:git-Paper-118]
        at net.minecraft.server.v1_15_R1.PacketPlayInChat$1.run(PacketPlayInChat.java:41) ~[patched_1.15.2.jar:git-Paper-118]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) ~[?:?]
        at java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[?:?]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) [?:?]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) [?:?]
        at java.lang.Thread.run(Thread.java:830) [?:?]


    Code (Text):
        @EventHandler
        public void asyncEvent(AsyncPlayerChatEvent e) {
         
            String[] m = e.getMessage().split(" ");
         
            Player p =e.getPlayer();
         
         
            switch(m[0]) {

            case "woof":
                e.setCancelled(true);
                ConsoleCommandSender console = Bukkit.getServer().getConsoleSender();
    Line 194:Bukkit.dispatchCommand(console, "say " + p.getName() + " is epic");
                break;
            default:
                break;
         
            }
         
         
         
        }

    help is much appreciated, thanks in advance!
     
  2. Code (Text):
    java.lang.IllegalStateException: Asynchronous command dispatch!
    Say's it right here,you cant do async commands,instead try making a method outside of the event to do it
     
  3. drives_a_ford

    Moderator

    As the name suggests, the AsyncPlayerChatEvent is called on an async thread. That means it will be handled on a thread that is not the server's main thread. This is great because you get to see chat even when the server is struggling.

    However, most of the Bukkit API is not thread safe. Thus it should not be used from this async thread you've found yourself in.
    What you want to do is schedule a task that will send this message on the next tick in sync. Use BukkitScheduler#runTask.
     
  4. Choco

    Moderator

    Alternatively, don't hard-execute commands from within a plugin. The ONLY time you should be executing commands in a plugin is if your configuration file allows users to specify commands to run. That's it. If you want the console to broadcast something, use Bukkit.broadcastMessage().

    There will ALWAYS be a programmatic alternative to using commands. They're not meant for developers to use in code as a shortcut.
     
    • Agree Agree x 1
  5. drives_a_ford

    Moderator

    For some reason I thought they were broadcasting instead of executing a command (that's what I would do at least). But you're absolutely correct, obviously.
     
  6. Choco

    Moderator

    Worth noting that your response was not inherently wrong. It is still an asynchronous event and one should be mindful in what gets executed in its listeners but in this case it's best not to execute a command to begin with. Bukkit#broadcastMessage() is thread safe and does not require a synchronous execution.
     
  7. Commands can also be aliased or disabled which makes them unreliable.
     
  8. how would i get the taskid which runTask wants? or like how would i execute a function(void)?
     
  9. Choco

    Moderator

    Please read my response(s).
     
  10. drives_a_ford

    Moderator

    The method does not require an id. It requires a plugin instance and a Runnable.

    With that said, I'd recommend doing what Choco said:
    And perhaps more importantly:
    EDIT:
    Oh well, sniped as usual...
     
    • Like Like x 1
  11. I do not want to Broadcast, i want to be able to execute every function which i have created and for example this is one:

    Code (Text):
        public static void suicideEvent(Player p) {
           
            p.getWorld().createExplosion(p.getLocation(), 1.0F);
           
        }
    How would i call this synchronized?
     
  12. drives_a_ford

    Moderator

    The Scheduler programming would be a good start for you, it seems.
     
    • Like Like x 1
  13. got it working, thanks