Commit fdd9db65 authored by Him188's avatar Him188

Update docs

parent 93607e49
......@@ -30,7 +30,7 @@ Mirai 的所有模块均开源
inline fun <reified E: Event> subscribeAlways(handler: (E) -> Unit)
subscribeAlways<FriendMessageEvent>{
//it: MessageChain
//it: FriendMessageEvent
}
```
......@@ -41,28 +41,17 @@ inline fun <reified E: Event> subscribeAll(builder: ListenerBuilder.() -> Unit)
subscribe<FriendMessageEvent>{
always{
//it: MessageChain
//it: FriendMessageEvent
//coroutineContext: EventScope.coroutineContext
}
//可同时开始多个监听。
always{
//it: MessageChain
//it: FriendMessageEvent
//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)
### 图片测试
......
......@@ -3,9 +3,7 @@
package net.mamoe.mirai.event
import net.mamoe.mirai.event.internal.Handler
import net.mamoe.mirai.event.internal.listeners
import net.mamoe.mirai.event.internal.subscribeInternal
import kotlin.jvm.Synchronized
import kotlin.reflect.KClass
enum class ListeningStatus {
......@@ -13,26 +11,6 @@ enum class ListeningStatus {
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)
......@@ -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> 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
import kotlinx.coroutines.sync.withLock
import net.mamoe.mirai.event.Event
import net.mamoe.mirai.event.ListeningStatus
import net.mamoe.mirai.utils.removeIfInlined
import kotlin.reflect.KClass
/**
......@@ -11,7 +12,7 @@ import kotlin.reflect.KClass
*
* @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
* @author Him188moe
*/
internal interface Listener<in E : Event> {
suspend fun onEvent(event: E): ListeningStatus
}
......@@ -58,12 +58,7 @@ internal object EventListenerManger {
@Suppress("UNCHECKED_CAST")
internal suspend fun <E : Event> E.broadcastInternal(): E {
suspend fun callListeners(listeners: EventListeners<in E>) = listeners.lock.withLock {
val iterator = listeners.iterator()
while (iterator.hasNext()) {
if (iterator.next().onEvent(this) == ListeningStatus.STOPPED) {
iterator.remove()
}
}
listeners.removeIfInlined { it.onEvent(this) == ListeningStatus.STOPPED }
}
callListeners(this::class.listeners as EventListeners<in E>)
......
......@@ -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.LoginResult
import net.mamoe.mirai.utils.LoginConfiguration
import net.mamoe.mirai.utils.MiraiDatagramChannel
import net.mamoe.mirai.utils.PlatformDatagramChannel
/**
* Mirai 的网络处理器, 它承担所有数据包([Packet])的处理任务.
......@@ -33,7 +33,7 @@ interface BotNetworkHandler<Socket : DataPacketSocket> : Closeable {
* 所有 [BotNetworkHandler] 的协程均启动在此作用域下.
*
* [BotNetworkHandler] 的协程包含:
* - UDP 包接收: [MiraiDatagramChannel.read]
* - UDP 包接收: [PlatformDatagramChannel.read]
* - 心跳 Job [ClientHeartbeatPacket]
* - SKey 刷新 [ClientSKeyRefreshmentRequestPacket]
* - 所有数据包处理和发送
......
......@@ -24,7 +24,7 @@ import net.mamoe.mirai.utils.*
*
* @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 lateinit var socket: BotSocket
......@@ -92,7 +92,7 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler<TI
override suspend fun sendPacket(packet: ClientPacket) = socket.sendPacket(packet)
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
......@@ -104,7 +104,7 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler<TI
try {
channel.read(buffer)//JVM: withContext(IO)
} catch (e: ClosedChannelException) {
} catch (e: ReadPacketInternalException) {
} catch (e: Exception) {
e.log()
......
......@@ -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.packet.ClientPacket
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 {
/**
* UDP 通道
*/
val channel: MiraiDatagramChannel
val channel: PlatformDatagramChannel
/**
* 是否开启
......
......@@ -4,13 +4,27 @@ import kotlinx.io.core.Closeable
import kotlinx.io.core.IoBuffer
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 send(buffer: IoBuffer): Int
val isOpen: Boolean
}
/**
* Channel 被关闭
*/
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
import kotlinx.coroutines.withContext
import kotlinx.io.core.Closeable
import kotlinx.io.core.IoBuffer
import kotlinx.io.errors.IOException
import kotlinx.io.nio.read
import java.net.InetSocketAddress
import java.nio.channels.DatagramChannel
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 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) {
buffer.readDirect {
try {
......@@ -33,4 +41,6 @@ actual class MiraiDatagramChannel actual constructor(serverHost: String, serverP
actual typealias ClosedChannelException = java.nio.channels.ClosedChannelException
actual class SendPacketInternalException actual constructor(cause: Throwable?) : Exception(cause)
\ No newline at end of file
actual class SendPacketInternalException actual constructor(cause: Throwable?) : IOException(cause)
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