Fixed event listening

This commit is contained in:
Him188 2019-10-09 17:40:39 +08:00
parent c69f2ab31e
commit b9720385f0
9 changed files with 67 additions and 70 deletions

View File

@ -10,6 +10,8 @@ enum class ListeningStatus {
STOPPED
}
/* KClass 的扩展方法 */
@Synchronized
fun <E : Event> KClass<E>.subscribe(handler: suspend (E) -> ListeningStatus) = this.listeners.add(Handler(handler))
@ -28,6 +30,25 @@ fun <E : Event> KClass<E>.subscribeWhileFalse(listener: suspend (E) -> Boolean)
fun <E : Event> KClass<E>.subscribeWhileTrue(listener: suspend (E) -> Boolean) = subscribeWhile(true, listener)
fun <E : Event> KClass<E>.subscribeWhileNull(listener: suspend (E) -> Any?) = subscribeWhile(null, listener)
/* 顶层方法 */
inline fun <reified E : Event> subscribe(noinline handler: suspend (E) -> ListeningStatus) = E::class.subscribe(handler)
inline fun <reified E : Event> subscribeAlways(noinline listener: suspend (E) -> Unit) = E::class.subscribeAlways(listener)
inline fun <reified E : Event> subscribeOnce(noinline listener: suspend (E) -> Unit) = E::class.subscribeOnce(listener)
inline fun <reified E : Event, T> subscribeUntil(valueIfStop: T, noinline listener: suspend (E) -> T) = E::class.subscribeUntil(valueIfStop, listener)
inline fun <reified E : Event> subscribeUntilFalse(noinline listener: suspend (E) -> Boolean) = E::class.subscribeUntilFalse(listener)
inline fun <reified E : Event> subscribeUntilTrue(noinline listener: suspend (E) -> Boolean) = E::class.subscribeUntilTrue(listener)
inline fun <reified E : Event> subscribeUntilNull(noinline listener: suspend (E) -> Any?) = E::class.subscribeUntilNull(listener)
inline fun <reified E : Event, T> subscribeWhile(valueIfContinue: T, noinline listener: suspend (E) -> T) = E::class.subscribeWhile(valueIfContinue, listener)
inline fun <reified E : Event> subscribeWhileFalse(noinline listener: suspend (E) -> Boolean) = E::class.subscribeWhileFalse(listener)
inline fun <reified E : Event> subscribeWhileTrue(noinline listener: suspend (E) -> Boolean) = E::class.subscribeWhileTrue(listener)
inline fun <reified E : Event> subscribeWhileNull(noinline listener: suspend (E) -> Any?) = E::class.subscribeWhileNull(listener)
/**
* 监听一个事件. 可同时进行多种方式的监听

View File

@ -2,13 +2,10 @@ package net.mamoe.mirai.event.events
import net.mamoe.mirai.Bot
import net.mamoe.mirai.event.Event
import kotlin.reflect.KClass
/**
* @author Him188moe
*/
abstract class BotEvent(val bot: Bot) : Event()
class BotLoginSucceedEvent(bot: Bot) : BotEvent(bot) {
companion object : KClass<BotLoginSucceedEvent> by BotLoginSucceedEvent::class
}
class BotLoginSucceedEvent(bot: Bot) : BotEvent(bot)

View File

@ -4,7 +4,6 @@ import net.mamoe.mirai.Bot
import net.mamoe.mirai.contact.QQ
import net.mamoe.mirai.message.Message
import net.mamoe.mirai.message.defaults.MessageChain
import kotlin.reflect.KClass
/**
* @author Him188moe
@ -17,8 +16,6 @@ abstract class FriendEvent(bot: Bot, val sender: QQ) : BotEvent(bot)
* @author Him188moe
*/
class FriendMessageEvent(bot: Bot, sender: QQ, val message: MessageChain) : FriendEvent(bot, sender) {
companion object : KClass<FriendMessageEvent> by FriendMessageEvent::class
@JvmSynthetic
suspend inline fun reply(message: Message) = sender.sendMessage(message)

View File

@ -5,7 +5,6 @@ import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.contact.QQ
import net.mamoe.mirai.message.Message
import net.mamoe.mirai.message.defaults.MessageChain
import kotlin.reflect.KClass
/**
* @author Him188moe
@ -16,8 +15,6 @@ abstract class GroupEvent(bot: Bot, val group: Group) : BotEvent(bot)
* @author Him188moe
*/
class GroupMessageEvent(bot: Bot, group: Group, val sender: QQ, val message: MessageChain) : GroupEvent(bot, group) {
companion object : KClass<GroupMessageEvent> by GroupMessageEvent::class
@JvmSynthetic
suspend inline fun reply(message: Message) = group.sendMessage(message)

View File

@ -5,7 +5,6 @@ import net.mamoe.mirai.event.Cancellable
import net.mamoe.mirai.network.protocol.tim.packet.ClientPacket
import net.mamoe.mirai.network.protocol.tim.packet.Packet
import net.mamoe.mirai.network.protocol.tim.packet.ServerPacket
import kotlin.reflect.KClass
/* Abstract */
@ -22,22 +21,16 @@ sealed class ClientPacketEvent<out P : ClientPacket>(bot: Bot, packet: P) : Pack
/**
* 包已发送. 不可被取消
*/
class PacketSentEvent<P : ClientPacket>(bot: Bot, packet: P) : ClientPacketEvent<P>(bot, packet) {
companion object : KClass<PacketSentEvent<*>> by PacketSentEvent::class
}
class PacketSentEvent<P : ClientPacket>(bot: Bot, packet: P) : ClientPacketEvent<P>(bot, packet)
/**
* 包发送前. 可被取消
*/
class BeforePacketSendEvent<P : ClientPacket>(bot: Bot, packet: P) : ClientPacketEvent<P>(bot, packet), Cancellable {
companion object : KClass<BeforePacketSendEvent<*>> by BeforePacketSendEvent::class
}
class BeforePacketSendEvent<P : ClientPacket>(bot: Bot, packet: P) : ClientPacketEvent<P>(bot, packet), Cancellable
/* Server to Client */
sealed class ServerPacketEvent<out P : ServerPacket>(bot: Bot, packet: P) : PacketEvent<P>(bot, packet)
class ServerPacketReceivedEvent(bot: Bot, packet: ServerPacket) : ServerPacketEvent<ServerPacket>(bot, packet) {
companion object : KClass<ServerPacketReceivedEvent> by ServerPacketReceivedEvent::class
}
class ServerPacketReceivedEvent(bot: Bot, packet: ServerPacket) : ServerPacketEvent<ServerPacket>(bot, packet)

View File

@ -1,7 +1,16 @@
package net.mamoe.mirai.event.internal
import kotlinx.coroutines.delay
import net.mamoe.mirai.Bot
import net.mamoe.mirai.event.Event
import net.mamoe.mirai.event.ListeningStatus
import net.mamoe.mirai.event.broadcast
import net.mamoe.mirai.event.events.ServerPacketReceivedEvent
import net.mamoe.mirai.event.subscribeAlways
import net.mamoe.mirai.network.protocol.tim.packet.ServerPacket
import net.mamoe.mirai.network.protocol.tim.packet.dataInputStream
import net.mamoe.mirai.utils.BotAccount
import net.mamoe.mirai.utils.Console
import kotlin.reflect.KClass
import kotlin.reflect.full.allSuperclasses
@ -10,7 +19,6 @@ import kotlin.reflect.full.allSuperclasses
*
* @author Him188moe
*/
internal fun <E : Event> KClass<E>.subscribeInternal(listener: Listener<E>) = this.listeners.add(listener)
/**
@ -36,16 +44,16 @@ internal val <E : Event> KClass<E>.listeners: EventListeners<E> get() = EventLis
internal class EventListeners<E : Event> : MutableList<Listener<E>> by mutableListOf()
internal object EventListenerManger {
private val REGISTRIES: MutableMap<KClass<out Event>, EventListeners<out Event>> = mutableMapOf()
private val registries: MutableMap<KClass<out Event>, EventListeners<out Event>> = mutableMapOf()
@Suppress("UNCHECKED_CAST")
internal fun <E : Event> get(clazz: KClass<E>): EventListeners<E> {
synchronized(clazz) {
if (REGISTRIES.containsKey(clazz)) {
return REGISTRIES[clazz] as EventListeners<E>
if (registries.containsKey(clazz)) {
return registries[clazz] as EventListeners<E>
} else {
EventListeners<E>().let {
REGISTRIES[clazz] = it
registries[clazz] = it
return it
}
}
@ -64,13 +72,25 @@ internal suspend fun <E : Event> E.broadcastInternal(): E {
}
}
callListeners(this::class.listeners as EventListeners<E>)
callListeners(this::class.listeners as EventListeners<in E>)
this::class.allSuperclasses.forEach {
//println("super: " + it.simpleName)
//todo multi platform
if (Event::class.java.isAssignableFrom(it.java)) {
callListeners((it as KClass<out Event>).listeners as EventListeners<in E>)
}
}
return this
}
suspend fun main() {
ServerPacketReceivedEvent::class.subscribeAlways {
println("got it")
}
println(ServerPacketReceivedEvent::class.listeners.size)
ServerPacketReceivedEvent(Bot(BotAccount(1, ""), Console()), object : ServerPacket(byteArrayOf().dataInputStream()) {}).broadcast()
delay(1000)
}

View File

@ -188,7 +188,7 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
// loginResult?.complete(LoginState.TIMEOUT)
//}
val received = AtomicBoolean(false)
ServerPacketReceivedEvent.subscribe {
ServerPacketReceivedEvent::class.subscribe {
if (it.packet is ServerTouchResponsePacket && it.bot === bot) {
received.set(true)
ListeningStatus.STOPPED

View File

@ -2,13 +2,6 @@
package net.mamoe.mirai.network.protocol.tim.packet
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import net.mamoe.mirai.Bot
import net.mamoe.mirai.event.events.ServerPacketReceivedEvent
import net.mamoe.mirai.event.subscribeWhileTrue
import net.mamoe.mirai.network.protocol.tim.packet.PacketNameFormatter.adjustName
import net.mamoe.mirai.network.protocol.tim.packet.action.ServerCanAddFriendResponsePacket
import net.mamoe.mirai.network.protocol.tim.packet.action.ServerSendFriendMessageResponsePacket
@ -18,7 +11,6 @@ import net.mamoe.mirai.network.protocol.tim.packet.login.*
import net.mamoe.mirai.utils.*
import java.io.DataInputStream
import java.io.EOFException
import kotlin.reflect.KClass
/**
* @author Him188moe
@ -334,25 +326,4 @@ fun DataInputStream.gotoWhere(matcher: ByteArray): DataInputStream {
return this
}
} while (true)
}
@Suppress("UNCHECKED_CAST")
internal fun <P : ServerPacket> Bot.waitForPacket(packetClass: KClass<P>, timeoutMillis: Long = Long.MAX_VALUE, timeout: () -> Unit = {}) {
var got = false
ServerPacketReceivedEvent.subscribeWhileTrue {
if (packetClass.isInstance(it.packet) && it.bot === this) {
got = true
false
} else {
true
}
}
GlobalScope.launch(Dispatchers.Unconfined) {
delay(timeoutMillis)
if (!got) {
timeout.invoke()
}
}
}

View File

@ -33,18 +33,8 @@ suspend fun main() {
}
//DSL 监听
FriendMessageEvent.subscribeAll {
always {
//获取第一个纯文本消息
val firstText = it.message[PlainText]
}
}
//监听事件:
FriendMessageEvent.subscribeAlways {
//提供泛型以监听事件
subscribeAlways<FriendMessageEvent> {
//获取第一个纯文本消息
val firstText = it.message[PlainText]
@ -76,11 +66,22 @@ suspend fun main() {
}
}
//通过 KClass 扩展方式监听事件
GroupMessageEvent::class.subscribeAlways {
when {
it.message.contains("复读") -> it.reply(it.message)
}
}
//DSL 监听
FriendMessageEvent::class.subscribeAll {
always {
//获取第一个纯文本消息
val firstText = it.message[PlainText]
}
}
}
@ -90,9 +91,9 @@ suspend fun main() {
* 对机器人说 "停止", 机器人停止
*/
fun demo2() {
FriendMessageEvent.subscribeAlways { event ->
subscribeAlways<FriendMessageEvent> { event ->
if (event.message eq "记笔记") {
FriendMessageEvent.subscribeUntilFalse {
FriendMessageEvent::class.subscribeUntilFalse {
it.reply("你发送了 ${it.message}")
it.message eq "停止"