Commit 2b02121b authored by Him188moe's avatar Him188moe

Kotlin coroutine

parent b10e0104
...@@ -23,7 +23,7 @@ abstract class Contact internal constructor(val bot: Bot, val number: Long) { ...@@ -23,7 +23,7 @@ abstract class Contact internal constructor(val bot: Bot, val number: Long) {
/** /**
* 上传图片 * 上传图片
*/ */
suspend fun uploadImage(session: LoginSession, image: UnsolvedImage): CompletableFuture<Unit> { fun uploadImage(session: LoginSession, image: UnsolvedImage): CompletableFuture<Unit> {
return image.upload(session, this) return image.upload(session, this)
} }
......
package net.mamoe.mirai.event package net.mamoe.mirai.event
import kotlinx.coroutines.runBlocking
import java.util.function.Consumer import java.util.function.Consumer
import java.util.function.Predicate import java.util.function.Predicate
...@@ -7,12 +8,20 @@ import java.util.function.Predicate ...@@ -7,12 +8,20 @@ import java.util.function.Predicate
* @author Him188moe * @author Him188moe
*/ */
class MiraiEventHookKt<E : MiraiEvent>(eventClass: Class<E>) : MiraiEventHook<E>(eventClass) { class MiraiEventHookKt<E : MiraiEvent>(eventClass: Class<E>) : MiraiEventHook<E>(eventClass) {
fun onEvent(handler: (E) -> Unit) { fun onEvent(handler: suspend (E) -> Unit) {
this@MiraiEventHookKt.handler = Consumer(handler) this@MiraiEventHookKt.handler = Consumer {
runBlocking {
handler(it)
}
}
} }
fun validChecker(predicate: (E) -> Boolean) { fun validChecker(predicate: suspend (E) -> Boolean) {//todo 把 mirai event 变为 suspend, 而不是在这里 run blocking
this@MiraiEventHookKt.validChecker = Predicate(predicate) this@MiraiEventHookKt.validChecker = Predicate {
runBlocking {
predicate(it)
}
}
} }
} }
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
package net.mamoe.mirai.event package net.mamoe.mirai.event
import kotlinx.coroutines.runBlocking
import kotlin.reflect.KClass import kotlin.reflect.KClass
/** /**
...@@ -18,21 +19,29 @@ object EventManager : MiraiEventManager() ...@@ -18,21 +19,29 @@ object EventManager : MiraiEventManager()
/** /**
* 每次事件触发时都会调用 hook * 每次事件触发时都会调用 hook
*/ */
fun <C : Class<E>, E : MiraiEvent> C.hookAlways(hook: (E) -> Unit) { fun <C : Class<E>, E : MiraiEvent> C.hookAlways(hook: suspend (E) -> Unit) {
MiraiEventManager.getInstance().hookAlways(MiraiEventHook<E>(this, hook)) MiraiEventManager.getInstance().hookAlways(MiraiEventHook<E>(this) {
runBlocking {
hook(it)
}
})
} }
/** /**
* 当下一次事件触发时调用 hook * 当下一次事件触发时调用 hook
*/ */
fun <C : Class<E>, E : MiraiEvent> C.hookOnce(hook: (E) -> Unit) { fun <C : Class<E>, E : MiraiEvent> C.hookOnce(hook: suspend (E) -> Unit) {
MiraiEventManager.getInstance().hookOnce(MiraiEventHook<E>(this, hook)) MiraiEventManager.getInstance().hookOnce(MiraiEventHook<E>(this) {
runBlocking {
hook(it)
}
})
} }
/** /**
* 每次事件触发时都会调用 hook, 直到 hook 返回 false 时停止 hook * 每次事件触发时都会调用 hook, 直到 hook 返回 false 时停止 hook
*/ */
fun <C : Class<E>, E : MiraiEvent> C.hookWhile(hook: (E) -> Boolean) { fun <C : Class<E>, E : MiraiEvent> C.hookWhile(hook: suspend (E) -> Boolean) {
MiraiEventManager.getInstance().hookAlways(MiraiEventHookSimple(this, hook)) MiraiEventManager.getInstance().hookAlways(MiraiEventHookSimple(this, hook))
} }
...@@ -40,28 +49,30 @@ fun <C : Class<E>, E : MiraiEvent> C.hookWhile(hook: (E) -> Boolean) { ...@@ -40,28 +49,30 @@ fun <C : Class<E>, E : MiraiEvent> C.hookWhile(hook: (E) -> Boolean) {
/** /**
* 每次事件触发时都会调用 hook * 每次事件触发时都会调用 hook
*/ */
fun <C : KClass<E>, E : MiraiEvent> C.hookAlways(hook: (E) -> Unit) { fun <C : KClass<E>, E : MiraiEvent> C.hookAlways(hook: suspend (E) -> Unit) {
this.java.hookAlways(hook) this.java.hookAlways(hook)
} }
/** /**
* 当下一次事件触发时调用 hook * 当下一次事件触发时调用 hook
*/ */
fun <C : KClass<E>, E : MiraiEvent> C.hookOnce(hook: (E) -> Unit) { fun <C : KClass<E>, E : MiraiEvent> C.hookOnce(hook: suspend (E) -> Unit) {
this.java.hookOnce(hook) this.java.hookOnce(hook)
} }
/** /**
* 每次事件触发时都会调用 hook, 直到 hook 返回 false 时停止 hook * 每次事件触发时都会调用 hook, 直到 hook 返回 false 时停止 hook
*/ */
fun <C : KClass<E>, E : MiraiEvent> C.hookWhile(hook: (E) -> Boolean) { fun <C : KClass<E>, E : MiraiEvent> C.hookWhile(hook: suspend (E) -> Boolean) {
this.java.hookWhile(hook) this.java.hookWhile(hook)
} }
private class MiraiEventHookSimple<E : MiraiEvent>(clazz: Class<E>, val hook: (E) -> Boolean) : MiraiEventHook<E>(clazz) { private class MiraiEventHookSimple<E : MiraiEvent>(clazz: Class<E>, val hook: suspend (E) -> Boolean) : MiraiEventHook<E>(clazz) {
override fun accept(event: MiraiEvent?): Boolean { override fun accept(event: MiraiEvent?): Boolean {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
return !hook.invoke(event as E) return runBlocking {
return@runBlocking !hook.invoke(event as E)
}
} }
} }
\ No newline at end of file
...@@ -26,7 +26,7 @@ class UnsolvedImage(filename: String, val image: BufferedImage) : Image(getImage ...@@ -26,7 +26,7 @@ class UnsolvedImage(filename: String, val image: BufferedImage) : Image(getImage
constructor(imageFile: File) : this(imageFile.name, ImageIO.read(imageFile)) constructor(imageFile: File) : this(imageFile.name, ImageIO.read(imageFile))
constructor(url: URL) : this(File(url.file)) constructor(url: URL) : this(File(url.file))
suspend fun upload(session: LoginSession, contact: Contact): CompletableFuture<Unit> {//todo be suspend fun upload(session: LoginSession, contact: Contact): CompletableFuture<Unit> {
return session.expectPacket<ServerTryGetImageIDResponsePacket> { return session.expectPacket<ServerTryGetImageIDResponsePacket> {
toSend { ClientTryGetImageIDPacket(session.bot.account.qqNumber, session.sessionKey, contact.number, image) } toSend { ClientTryGetImageIDPacket(session.bot.account.qqNumber, session.sessionKey, contact.number, image) }
......
...@@ -117,8 +117,10 @@ internal class BotNetworkHandlerImpl(private val bot: Bot) : BotNetworkHandler { ...@@ -117,8 +117,10 @@ internal class BotNetworkHandlerImpl(private val bot: Bot) : BotNetworkHandler {
if (!packet.javaClass.name.endsWith("Encrypted") && !packet.javaClass.name.endsWith("Raw")) { if (!packet.javaClass.name.endsWith("Encrypted") && !packet.javaClass.name.endsWith("Raw")) {
bot.notice("Packet received: $packet") bot.notice("Packet received: $packet")
} }
}
if (packet is ServerEventPacket) { if (packet is ServerEventPacket) {
NetworkScope.launch {
sendPacket(ClientEventResponsePacket(bot.account.qqNumber, packet.packetId, sessionKey, packet.eventIdentity)) sendPacket(ClientEventResponsePacket(bot.account.qqNumber, packet.packetId, sessionKey, packet.eventIdentity))
} }
} }
...@@ -127,10 +129,18 @@ internal class BotNetworkHandlerImpl(private val bot: Bot) : BotNetworkHandler { ...@@ -127,10 +129,18 @@ internal class BotNetworkHandlerImpl(private val bot: Bot) : BotNetworkHandler {
return return
} }
login.onPacketReceived(packet) withContext(NetworkScope.coroutineContext) {
packetHandlers.forEach { launch {
it.instance.onPacketReceived(packet) login.onPacketReceived(packet)
} }
packetHandlers.forEach {
launch {
it.instance.onPacketReceived(packet)
}
}
}//awaits all coroutines launched in this block
} }
private var socket: DatagramSocket? = null private var socket: DatagramSocket? = null
......
package net.mamoe.mirai.network package net.mamoe.mirai.network
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.asCoroutineDispatcher import kotlinx.coroutines.Dispatchers
import java.util.concurrent.SynchronousQueue
import java.util.concurrent.ThreadPoolExecutor
import java.util.concurrent.TimeUnit
import kotlin.coroutines.CoroutineContext
object NetworkScope : CoroutineScope { object NetworkScope : CoroutineScope by CoroutineScope(Dispatchers.Default)
override val coroutineContext: CoroutineContext \ No newline at end of file
get() = lazy {
ThreadPoolExecutor(
1,
4,
8000, TimeUnit.MILLISECONDS,
SynchronousQueue()
).asCoroutineDispatcher()
}.value//todo improve
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment