Commit fdd9db65 authored by Him188's avatar Him188

Update docs

parent 93607e49
...@@ -30,7 +30,7 @@ Mirai 的所有模块均开源 ...@@ -30,7 +30,7 @@ Mirai 的所有模块均开源
inline fun <reified E: Event> subscribeAlways(handler: (E) -> Unit) inline fun <reified E: Event> subscribeAlways(handler: (E) -> Unit)
subscribeAlways<FriendMessageEvent>{ subscribeAlways<FriendMessageEvent>{
//it: MessageChain //it: FriendMessageEvent
} }
``` ```
...@@ -41,28 +41,17 @@ inline fun <reified E: Event> subscribeAll(builder: ListenerBuilder.() -> Unit) ...@@ -41,28 +41,17 @@ inline fun <reified E: Event> subscribeAll(builder: ListenerBuilder.() -> Unit)
subscribe<FriendMessageEvent>{ subscribe<FriendMessageEvent>{
always{ always{
//it: MessageChain //it: FriendMessageEvent
//coroutineContext: EventScope.coroutineContext //coroutineContext: EventScope.coroutineContext
} }
//可同时开始多个监听。 //可同时开始多个监听。
always{ always{
//it: MessageChain //it: FriendMessageEvent
//coroutineContext: EventScope.coroutineContext //coroutineContext: EventScope.coroutineContext
} }
} }
``` ```
##### KClass extension
更推荐使用 Top-level reified
```kotlin
fun <E : Event> KClass<E>.subscribeAlways(listener: suspend (E) -> Unit)
FriendMessageEvent::class.subscribeAlways{
if(it.message eq "你好")
it.reply("你好!")
}
```
![AYWVE86P](.github/A%7DYWVE860U%28%25YQD%24R1GB1%5BP.png) ![AYWVE86P](.github/A%7DYWVE860U%28%25YQD%24R1GB1%5BP.png)
### 图片测试 ### 图片测试
......
...@@ -3,9 +3,7 @@ ...@@ -3,9 +3,7 @@
package net.mamoe.mirai.event package net.mamoe.mirai.event
import net.mamoe.mirai.event.internal.Handler import net.mamoe.mirai.event.internal.Handler
import net.mamoe.mirai.event.internal.listeners
import net.mamoe.mirai.event.internal.subscribeInternal import net.mamoe.mirai.event.internal.subscribeInternal
import kotlin.jvm.Synchronized
import kotlin.reflect.KClass import kotlin.reflect.KClass
enum class ListeningStatus { enum class ListeningStatus {
...@@ -13,26 +11,6 @@ enum class ListeningStatus { ...@@ -13,26 +11,6 @@ enum class ListeningStatus {
STOPPED STOPPED
} }
/* KClass 的扩展方法 */
@Synchronized
fun <E : Event> KClass<E>.subscribe(handler: suspend (E) -> ListeningStatus) = this.listeners.add(Handler(handler))
fun <E : Event> KClass<E>.subscribeAlways(listener: suspend (E) -> Unit) = this.subscribeInternal(Handler { listener(it); ListeningStatus.LISTENING })
fun <E : Event> KClass<E>.subscribeOnce(listener: suspend (E) -> Unit) = this.subscribeInternal(Handler { listener(it); ListeningStatus.STOPPED })
fun <E : Event, T> KClass<E>.subscribeUntil(valueIfStop: T, listener: suspend (E) -> T) = subscribeInternal(Handler { if (listener(it) === valueIfStop) ListeningStatus.STOPPED else ListeningStatus.LISTENING })
fun <E : Event> KClass<E>.subscribeUntilFalse(listener: suspend (E) -> Boolean) = subscribeUntil(false, listener)
fun <E : Event> KClass<E>.subscribeUntilTrue(listener: suspend (E) -> Boolean) = subscribeUntil(true, listener)
fun <E : Event> KClass<E>.subscribeUntilNull(listener: suspend (E) -> Any?) = subscribeUntil(null, listener)
fun <E : Event, T> KClass<E>.subscribeWhile(valueIfContinue: T, listener: suspend (E) -> T) = subscribeInternal(Handler { if (listener(it) !== valueIfContinue) ListeningStatus.STOPPED else ListeningStatus.LISTENING })
fun <E : Event> KClass<E>.subscribeWhileFalse(listener: suspend (E) -> Boolean) = subscribeWhile(false, listener)
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> subscribe(noinline handler: suspend (E) -> ListeningStatus) = E::class.subscribe(handler)
...@@ -52,6 +30,26 @@ inline fun <reified E : Event> subscribeWhileFalse(noinline listener: suspend (E ...@@ -52,6 +30,26 @@ inline fun <reified E : Event> subscribeWhileFalse(noinline listener: suspend (E
inline fun <reified E : Event> subscribeWhileTrue(noinline listener: suspend (E) -> Boolean) = E::class.subscribeWhileTrue(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) inline fun <reified E : Event> subscribeWhileNull(noinline listener: suspend (E) -> Any?) = E::class.subscribeWhileNull(listener)
/* KClass 的扩展方法, 不推荐 */
fun <E : Event> KClass<E>.subscribe(handler: suspend (E) -> ListeningStatus) = this.subscribeInternal(Handler(handler))
fun <E : Event> KClass<E>.subscribeAlways(listener: suspend (E) -> Unit) = this.subscribeInternal(Handler { listener(it); ListeningStatus.LISTENING })
fun <E : Event> KClass<E>.subscribeOnce(listener: suspend (E) -> Unit) = this.subscribeInternal(Handler { listener(it); ListeningStatus.STOPPED })
fun <E : Event, T> KClass<E>.subscribeUntil(valueIfStop: T, listener: suspend (E) -> T) = subscribeInternal(Handler { if (listener(it) === valueIfStop) ListeningStatus.STOPPED else ListeningStatus.LISTENING })
fun <E : Event> KClass<E>.subscribeUntilFalse(listener: suspend (E) -> Boolean) = subscribeUntil(false, listener)
fun <E : Event> KClass<E>.subscribeUntilTrue(listener: suspend (E) -> Boolean) = subscribeUntil(true, listener)
fun <E : Event> KClass<E>.subscribeUntilNull(listener: suspend (E) -> Any?) = subscribeUntil(null, listener)
fun <E : Event, T> KClass<E>.subscribeWhile(valueIfContinue: T, listener: suspend (E) -> T) = subscribeInternal(Handler { if (listener(it) !== valueIfContinue) ListeningStatus.STOPPED else ListeningStatus.LISTENING })
fun <E : Event> KClass<E>.subscribeWhileFalse(listener: suspend (E) -> Boolean) = subscribeWhile(false, listener)
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)
/* ListenerBuilder DSL */
/** /**
* 监听一个事件. 可同时进行多种方式的监听 * 监听一个事件. 可同时进行多种方式的监听
......
...@@ -4,6 +4,7 @@ import kotlinx.coroutines.sync.Mutex ...@@ -4,6 +4,7 @@ import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
import net.mamoe.mirai.event.Event import net.mamoe.mirai.event.Event
import net.mamoe.mirai.event.ListeningStatus import net.mamoe.mirai.event.ListeningStatus
import net.mamoe.mirai.utils.removeIfInlined
import kotlin.reflect.KClass import kotlin.reflect.KClass
/** /**
...@@ -11,7 +12,7 @@ import kotlin.reflect.KClass ...@@ -11,7 +12,7 @@ import kotlin.reflect.KClass
* *
* @author Him188moe * @author Him188moe
*/ */
internal fun <E : Event> KClass<E>.subscribeInternal(listener: Listener<E>) = this.listeners.add(listener) internal fun <E : Event> KClass<E>.subscribeInternal(listener: Listener<E>) = this.listeners.add(listener)//TODO lock or sth else
/** /**
* 事件监听器 * 事件监听器
...@@ -19,7 +20,6 @@ internal fun <E : Event> KClass<E>.subscribeInternal(listener: Listener<E>) = th ...@@ -19,7 +20,6 @@ internal fun <E : Event> KClass<E>.subscribeInternal(listener: Listener<E>) = th
* @author Him188moe * @author Him188moe
*/ */
internal interface Listener<in E : Event> { internal interface Listener<in E : Event> {
suspend fun onEvent(event: E): ListeningStatus suspend fun onEvent(event: E): ListeningStatus
} }
...@@ -58,12 +58,7 @@ internal object EventListenerManger { ...@@ -58,12 +58,7 @@ internal object EventListenerManger {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
internal suspend fun <E : Event> E.broadcastInternal(): E { internal suspend fun <E : Event> E.broadcastInternal(): E {
suspend fun callListeners(listeners: EventListeners<in E>) = listeners.lock.withLock { suspend fun callListeners(listeners: EventListeners<in E>) = listeners.lock.withLock {
val iterator = listeners.iterator() listeners.removeIfInlined { it.onEvent(this) == ListeningStatus.STOPPED }
while (iterator.hasNext()) {
if (iterator.next().onEvent(this) == ListeningStatus.STOPPED) {
iterator.remove()
}
}
} }
callListeners(this::class.listeners as EventListeners<in E>) callListeners(this::class.listeners as EventListeners<in E>)
......
...@@ -10,7 +10,7 @@ import net.mamoe.mirai.network.protocol.tim.packet.* ...@@ -10,7 +10,7 @@ import net.mamoe.mirai.network.protocol.tim.packet.*
import net.mamoe.mirai.network.protocol.tim.packet.login.ClientSKeyRefreshmentRequestPacket import net.mamoe.mirai.network.protocol.tim.packet.login.ClientSKeyRefreshmentRequestPacket
import net.mamoe.mirai.network.protocol.tim.packet.login.LoginResult import net.mamoe.mirai.network.protocol.tim.packet.login.LoginResult
import net.mamoe.mirai.utils.LoginConfiguration import net.mamoe.mirai.utils.LoginConfiguration
import net.mamoe.mirai.utils.MiraiDatagramChannel import net.mamoe.mirai.utils.PlatformDatagramChannel
/** /**
* Mirai 的网络处理器, 它承担所有数据包([Packet])的处理任务. * Mirai 的网络处理器, 它承担所有数据包([Packet])的处理任务.
...@@ -33,7 +33,7 @@ interface BotNetworkHandler<Socket : DataPacketSocket> : Closeable { ...@@ -33,7 +33,7 @@ interface BotNetworkHandler<Socket : DataPacketSocket> : Closeable {
* 所有 [BotNetworkHandler] 的协程均启动在此作用域下. * 所有 [BotNetworkHandler] 的协程均启动在此作用域下.
* *
* [BotNetworkHandler] 的协程包含: * [BotNetworkHandler] 的协程包含:
* - UDP 包接收: [MiraiDatagramChannel.read] * - UDP 包接收: [PlatformDatagramChannel.read]
* - 心跳 Job [ClientHeartbeatPacket] * - 心跳 Job [ClientHeartbeatPacket]
* - SKey 刷新 [ClientSKeyRefreshmentRequestPacket] * - SKey 刷新 [ClientSKeyRefreshmentRequestPacket]
* - 所有数据包处理和发送 * - 所有数据包处理和发送
......
...@@ -24,7 +24,7 @@ import net.mamoe.mirai.utils.* ...@@ -24,7 +24,7 @@ import net.mamoe.mirai.utils.*
* *
* @see BotNetworkHandler * @see BotNetworkHandler
*/ */
internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler<TIMBotNetworkHandler.BotSocket>, PacketHandlerList() { internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) : BotNetworkHandler<TIMBotNetworkHandler.BotSocket>, PacketHandlerList() {
override val NetworkScope: CoroutineScope = CoroutineScope(Dispatchers.Default) override val NetworkScope: CoroutineScope = CoroutineScope(Dispatchers.Default)
override lateinit var socket: BotSocket override lateinit var socket: BotSocket
...@@ -92,7 +92,7 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler<TI ...@@ -92,7 +92,7 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler<TI
override suspend fun sendPacket(packet: ClientPacket) = socket.sendPacket(packet) override suspend fun sendPacket(packet: ClientPacket) = socket.sendPacket(packet)
internal inner class BotSocket(override val serverIp: String, val configuration: LoginConfiguration) : DataPacketSocket { internal inner class BotSocket(override val serverIp: String, val configuration: LoginConfiguration) : DataPacketSocket {
override val channel: MiraiDatagramChannel = MiraiDatagramChannel(serverIp, 8000) override val channel: PlatformDatagramChannel = PlatformDatagramChannel(serverIp, 8000)
override val isOpen: Boolean get() = channel.isOpen override val isOpen: Boolean get() = channel.isOpen
...@@ -104,7 +104,7 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler<TI ...@@ -104,7 +104,7 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler<TI
try { try {
channel.read(buffer)//JVM: withContext(IO) channel.read(buffer)//JVM: withContext(IO)
} catch (e: ClosedChannelException) { } catch (e: ReadPacketInternalException) {
} catch (e: Exception) { } catch (e: Exception) {
e.log() e.log()
......
...@@ -7,7 +7,7 @@ import net.mamoe.mirai.network.LoginSession ...@@ -7,7 +7,7 @@ import net.mamoe.mirai.network.LoginSession
import net.mamoe.mirai.network.protocol.tim.TIMBotNetworkHandler import net.mamoe.mirai.network.protocol.tim.TIMBotNetworkHandler
import net.mamoe.mirai.network.protocol.tim.packet.ClientPacket import net.mamoe.mirai.network.protocol.tim.packet.ClientPacket
import net.mamoe.mirai.network.protocol.tim.packet.ServerPacket import net.mamoe.mirai.network.protocol.tim.packet.ServerPacket
import net.mamoe.mirai.utils.MiraiDatagramChannel import net.mamoe.mirai.utils.PlatformDatagramChannel
/** /**
* 网络接口. * 网络接口.
...@@ -24,7 +24,7 @@ interface DataPacketSocket : Closeable { ...@@ -24,7 +24,7 @@ interface DataPacketSocket : Closeable {
/** /**
* UDP 通道 * UDP 通道
*/ */
val channel: MiraiDatagramChannel val channel: PlatformDatagramChannel
/** /**
* 是否开启 * 是否开启
......
...@@ -4,13 +4,27 @@ import kotlinx.io.core.Closeable ...@@ -4,13 +4,27 @@ import kotlinx.io.core.Closeable
import kotlinx.io.core.IoBuffer import kotlinx.io.core.IoBuffer
import kotlinx.io.errors.IOException import kotlinx.io.errors.IOException
expect class MiraiDatagramChannel(serverHost: String, serverPort: Short) : Closeable { /**
* 多平台适配的 DatagramChannel.
*/
expect class PlatformDatagramChannel(serverHost: String, serverPort: Short) : Closeable {
suspend fun read(buffer: IoBuffer): Int suspend fun read(buffer: IoBuffer): Int
suspend fun send(buffer: IoBuffer): Int suspend fun send(buffer: IoBuffer): Int
val isOpen: Boolean val isOpen: Boolean
} }
/**
* Channel 被关闭
*/
expect class ClosedChannelException : IOException expect class ClosedChannelException : IOException
expect class SendPacketInternalException(cause: Throwable?) : Exception /**
\ No newline at end of file * 在 [PlatformDatagramChannel.send] 或 [PlatformDatagramChannel.read] 时出现的错误.
*/
expect class SendPacketInternalException(cause: Throwable?) : IOException
/**
* 在 [PlatformDatagramChannel.send] 或 [PlatformDatagramChannel.read] 时出现的错误.
*/
expect class ReadPacketInternalException(cause: Throwable?) : IOException
\ No newline at end of file
...@@ -4,16 +4,24 @@ import kotlinx.coroutines.Dispatchers ...@@ -4,16 +4,24 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import kotlinx.io.core.Closeable import kotlinx.io.core.Closeable
import kotlinx.io.core.IoBuffer import kotlinx.io.core.IoBuffer
import kotlinx.io.errors.IOException
import kotlinx.io.nio.read import kotlinx.io.nio.read
import java.net.InetSocketAddress import java.net.InetSocketAddress
import java.nio.channels.DatagramChannel import java.nio.channels.DatagramChannel
import java.nio.channels.ReadableByteChannel import java.nio.channels.ReadableByteChannel
actual class MiraiDatagramChannel actual constructor(serverHost: String, serverPort: Short) : Closeable { actual class PlatformDatagramChannel actual constructor(serverHost: String, serverPort: Short) : Closeable {
private val serverAddress: InetSocketAddress = InetSocketAddress(serverHost, serverPort.toInt()) private val serverAddress: InetSocketAddress = InetSocketAddress(serverHost, serverPort.toInt())
private val channel: DatagramChannel = DatagramChannel.open().connect(serverAddress) private val channel: DatagramChannel = DatagramChannel.open().connect(serverAddress)
actual suspend fun read(buffer: IoBuffer) = withContext(Dispatchers.IO) { (channel as ReadableByteChannel).read(buffer) } actual suspend fun read(buffer: IoBuffer) = withContext(Dispatchers.IO) {
try {
(channel as ReadableByteChannel).read(buffer)
} catch (e: Exception) {
throw ReadPacketInternalException(e)
}
}
actual suspend fun send(buffer: IoBuffer) = withContext(Dispatchers.IO) { actual suspend fun send(buffer: IoBuffer) = withContext(Dispatchers.IO) {
buffer.readDirect { buffer.readDirect {
try { try {
...@@ -33,4 +41,6 @@ actual class MiraiDatagramChannel actual constructor(serverHost: String, serverP ...@@ -33,4 +41,6 @@ actual class MiraiDatagramChannel actual constructor(serverHost: String, serverP
actual typealias ClosedChannelException = java.nio.channels.ClosedChannelException actual typealias ClosedChannelException = java.nio.channels.ClosedChannelException
actual class SendPacketInternalException actual constructor(cause: Throwable?) : Exception(cause) actual class SendPacketInternalException actual constructor(cause: Throwable?) : IOException(cause)
\ No newline at end of file
actual class ReadPacketInternalException actual constructor(cause: Throwable?) : IOException(cause)
\ 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