Project-Cepi/KStom

Kotlinx Coroutines

arslanarm opened this issue · 6 comments

Adding support for coroutines would be nice. First of all, the new KItem class contains a list of callbacks, with coroutines and flows KItem would look

  public sealed class ClickEvent
  public data class LeftClick(val player: Player, val hand: Player.Hand): ClickEvent()
  public data class RightClick(val player: Player, val hand: Player.Hand): ClickEvent()
  
  public class KItem(material: Material, amount: Byte = 1, damage: Int = 0): ItemStack(material, amount, damage) {
      private val _events = MutableSharedFlow<ClickEvent>()
  
      public val clicks = _events.asSharedFlow()
      public val leftClicks get() = clicks.filterIsInstance<LeftClick>()
      public val rightClick get() = clicks.filterIsInstance<RightClick>()
  
      override fun onLeftClick(player: Player, hand: Player.Hand) {
          GlobalScope.launch { _events.emit(LeftClick(player, hand)) } // in most cases
      }
  
      override fun onRightClick(player: Player, hand: Player.Hand) {
          GlobalScope.launch { _events.emit(RightClick(player, hand)) }
      }
  }

from the call site, it would look like

  item.leftClicks.collect { (player, hand) ->
     // do something
  }

Flow API allows doing a lot of stuff as rxjava does. https://kotlinlang.org/docs/reference/coroutines/flow.html

Wow! I did not know about the Flow API -- will take this into consideration. I'll see what I can do 👍

Actually, it won't work sadly -- Minestom calls it via the override.

Strange, this example works perfectly well. Are you adding suspend modifier to the function? We can't add suspend modifier because it changes the function signature, so that's why there is GlobalScope.launch. In our case, runBlocking can be used, because we emit the value and immediately return from the function.

public sealed class ClickEvent
public data class LeftClick(val player: Player, val hand: Player.Hand): ClickEvent()
public data class RightClick(val player: Player, val hand: Player.Hand): ClickEvent()

public class KItem(material: Material, amount: Byte = 1, damage: Int = 0): ItemStack(material, amount, damage) {
    private val _events = MutableSharedFlow<ClickEvent>()

    public val clicks = _events.asSharedFlow()
    public val leftClicks get() = clicks.filterIsInstance<LeftClick>()
    public val rightClick get() = clicks.filterIsInstance<RightClick>()

    override fun onLeftClick(player: Player, hand: Player.Hand): Unit = runBlocking {
        _events.emit(LeftClick(player, hand))
    }

    override fun onRightClick(player: Player, hand: Player.Hand): Unit = runBlocking {
        _events.emit(RightClick(player, hand))
    }
}

How would we add left/right clicks?

if we have a click event we can just emit that click event to the _events. On the other side, if someone wants to listen to the events it can be done as

val item = KItem(Material.STICK)

item.leftClicks
    .onEach { println("${it.player.name} used left click") }
    .launch(GlobalScope)

Yeah, left/right click triggering already happens natively through Minestom -- that does seem like an interesting way to add them.