How to Call Sync Event from Async?

Discussion in 'Plugin Development' started by ShapeLayer, Sep 16, 2020 at 9:30 AM.

  1. Offline

    ShapeLayer

    I am making function that exchanges player items to score, "Item Drain". But as I'm just starting Kotlin and Java now, I cannot open (virtual) inventory. Console said InventoryOpenEvent may only be triggered synchronously.. (This is my first try to make plugin. I usually made website or simple python applications.)

    How to call sync from async?

    Here's my code:

    EventListener.kt
    Code:
        @EventHandler(ignoreCancelled = true)
        fun onAsyncPlayerChat(event: AsyncPlayerChatEvent) {
            event.isCancelled = true
    
            val message = event.message
            val player = event.player
            val playerName = player.name
            val emote = Emote.emoteBy(message)
    
    (... Other Functions...)
    
            if (message == "d") {
                ItemDrain.openInventory(player)
            }
            val isCenter = player.location.blockX in -30..30 && player.location.blockZ in -30..30
    (...Other Functions...)
            }
        }
    ItemDrain.kt
    Code:
    object ItemDrain {
        private var drain: Inventory = Bukkit.createInventory(null, 9, "drain")
    
        fun openInventory(player: Player) {
            player.openInventory(drain)
        }
    
        @EventHandler
        fun InventoryOpenEvent(event: InventoryOpenEvent) {
        }
        @EventHandler
        fun InventoryCloseEvent(event: InventoryCloseEvent) {
            var contents = event.inventory.contents
            for (content in contents) {
                println(content.toString())
            }
        }
    }
     
  2. Online

    timtower Moderator Moderator

    @ShapeLayer Make a BukkitRunnable, call runTask on it. Then it will go sync
     
  3. Offline

    ShapeLayer

    Oh, thanks. I'll try tomorrow.
     
    Last edited: Sep 17, 2020 at 3:08 AM
  4. Offline

    ShapeLayer

    @timtower
    Thank you! I can open inventory successfully.

    ...And can you let me know how to add InventoryCloseEvent?
    I added that event, But it looks like doesn't work..

    Code:
    @EventHandler
        fun onInventoryClose(event: InventoryCloseEvent) {
            println('a')
        }
     
  5. Online

    timtower Moderator Moderator

    I am not going to check why Kotlin stuff isn't working.
     
  6. Offline

    ShapeLayer

    Oh, I solved. It was just typing error on the other part. Thanks a lot.

    @timtower
    Uh... sorry. I thought solved it, but it wasn't.
    I added close event to two parts, #1 and #2, on OnAsyncPlayerChat.kt, But it works only at #1 and it works when normal chest had been closed too.

    I tried to inherit Listener Class from ItemDrain Class and add "if (event.inventory == drain) ~" to #2. However, As ItemDrain Class takes Player as argument, It cannot be registered to events.

    I want to catch only "Drain" Close Event. How can I do?

    AimlessPlugin.kt
    Code:
    package com.github.shapelayer.aimless.plugin
    
    import com.github.shapelayer.aimless.plugin.eventlistener.*
    import org.bukkit.Bukkit
    import org.bukkit.GameRule
    import org.bukkit.Location
    import org.bukkit.plugin.java.JavaPlugin
    
    class AimlessPlugin : JavaPlugin() {
        override fun onEnable() {
            for (world in Bukkit.getWorlds()) {
                world.setGameRule(GameRule.ANNOUNCE_ADVANCEMENTS, false)
                world.setGameRule(GameRule.SHOW_DEATH_MESSAGES, true)
                world.setGameRule(GameRule.SEND_COMMAND_FEEDBACK, false)
                world.setGameRule(GameRule.LOG_ADMIN_COMMANDS, false)
                world.setGameRule(GameRule.REDUCED_DEBUG_INFO, true)
            }
    
            Bukkit.getWorlds().first().apply {
                val border = worldBorder
                border.center = Location(this, 0.0, 0.0, 0.0)
                border.size = 16384.0
                spawnLocation = getHighestBlockAt(0, 0).location
            }
    
            server.pluginManager.registerEvents(EventListener(), this)
            server.pluginManager.registerEvents(OnAsyncPlayerChat(this), this)
        }
    }
    
    eventlistener.OnAsyncPlayerChat.kt
    Code:
    package com.github.shapelayer.aimless.plugin.eventlistener
    
    import com.github.shapelayer.aimless.plugin.Emote
    import net.md_5.bungee.api.ChatColor
    import net.md_5.bungee.api.chat.ClickEvent
    import net.md_5.bungee.api.chat.TextComponent
    import org.bukkit.Bukkit
    import org.bukkit.entity.Player
    import org.bukkit.event.EventHandler
    import org.bukkit.event.Listener
    import org.bukkit.event.inventory.InventoryCloseEvent
    import org.bukkit.event.inventory.InventoryOpenEvent
    import org.bukkit.event.player.AsyncPlayerChatEvent
    import org.bukkit.inventory.Inventory
    import org.bukkit.plugin.Plugin
    import org.bukkit.scheduler.BukkitRunnable
    
    class OnAsyncPlayerChat(private val plugin: Plugin) : Listener {
    
        @EventHandler(ignoreCancelled = true)
        fun onAsyncPlayerChat(event: AsyncPlayerChatEvent) {
            event.isCancelled = true
    
            val message = event.message
            val player = event.player
            val playerName = player.name
            val emote = Emote.emoteBy(message)
    
            if (emote != null) {
                emote.invoke(event.player.location)
    
                val component = TextComponent()
                component.text = "[$message]"
                component.color = ChatColor.RED
                component.clickEvent = ClickEvent(ClickEvent.Action.RUN_COMMAND, "/$message")
                event.player.sendMessage(component)
            }
    
            if (message == "d") {
                val InventoryTask = ItemDrain(event.player).runTask(this.plugin)
            }
            val isCenter = player.location.blockX in -30..30 && player.location.blockZ in -30..30
            for (onlinePlayer in Bukkit.getOnlinePlayers()) {
                val component = TextComponent()
                var sayer = playerName
                var reduced = message
                if (isCenter) {
                    sayer = "${playerName}: on center"
                } else {
                    val eachDistance = playersDistance(player, onlinePlayer)!!
                    if (eachDistance < 300) {
                        when {
                            eachDistance < 30 -> {
                            }
                            eachDistance < 75 -> {
                                sayer = volReduction(playerName, 0.9)
                                reduced = volReduction(message, 0.75)
                            }
                            eachDistance < 100 -> {
                                sayer = "???"
                                reduced = volReduction(message, 0.9)
                            }
                            eachDistance < 150 -> {
                                sayer = "???"
                                reduced = volReduction(message, 0.99)
                            }
                            else -> {
                                sayer = "???"
                                reduced = "???"
                            }
                        }
                    }
                }
                component.text = "<$sayer> $reduced"
                onlinePlayer.sendMessage(component)
            }
        }
        @EventHandler //#1
        fun onInventoryClose(event: InventoryCloseEvent) {
            println('a')
        }
    }
    
    class ItemDrain(private val player: Player) : BukkitRunnable() {
        private var drain: Inventory = Bukkit.createInventory(null, 9, "drain")
    
        private fun openInventory(player: Player) {
            player.openInventory(drain)
        }
    
        @EventHandler //#2
        fun onInventoryClose(event: InventoryCloseEvent) {
            println('a')
        }
    
        override fun run() {
            this.openInventory(this.player)
        }
    }
    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Sep 18, 2020 at 6:59 AM

Share This Page