2
0

Event.kt 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /*
  2. * Copyright 2019-2020 Mamoe Technologies and contributors.
  3. *
  4. * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
  5. * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
  6. *
  7. * https://github.com/mamoe/mirai/blob/master/LICENSE
  8. */
  9. @file:Suppress("unused")
  10. package net.mamoe.mirai.event
  11. import kotlinx.coroutines.CoroutineScope
  12. import kotlinx.coroutines.sync.Mutex
  13. import kotlinx.coroutines.sync.withLock
  14. import net.mamoe.mirai.JavaFriendlyAPI
  15. import net.mamoe.mirai.event.internal.broadcastInternal
  16. import net.mamoe.mirai.utils.MiraiExperimentalApi
  17. import net.mamoe.mirai.utils.internal.runBlocking
  18. /**
  19. * 可被监听的类, 可以是任何 class 或 object.
  20. *
  21. * 若监听这个类, 监听器将会接收所有事件的广播.
  22. *
  23. * 所有 [Event] 都应继承 [AbstractEvent] 而不要直接实现 [Event]. 否则将无法广播也无法监听.
  24. *
  25. * ### 广播
  26. * 广播事件的唯一方式为 [broadcast].
  27. *
  28. * @see subscribeAlways
  29. * @see subscribeOnce
  30. *
  31. * @see subscribeMessages
  32. *
  33. * @see [broadcast] 广播事件
  34. * @see [CoroutineScope.subscribe] 监听事件
  35. *
  36. * @see CancellableEvent 可被取消的事件
  37. */
  38. public interface Event {
  39. /**
  40. * 事件是否已被拦截.
  41. *
  42. * 所有事件都可以被拦截, 拦截后低优先级的监听器将不会处理到这个事件.
  43. *
  44. * @see intercept 拦截事件
  45. */
  46. public val isIntercepted: Boolean
  47. /**
  48. * 拦截这个事件
  49. *
  50. * 当事件被 [拦截][Event.intercept] 后, 优先级较低 (靠右) 的监听器将不会被调用.
  51. *
  52. * 优先级为 [Listener.EventPriority.MONITOR] 的监听器不应该调用这个函数.
  53. *
  54. * @see Listener.EventPriority 查看优先级相关信息
  55. */
  56. public fun intercept()
  57. }
  58. /**
  59. * 所有实现了 [Event] 接口的类都应该继承的父类.
  60. *
  61. * 在使用事件时应使用类型 [Event]. 在实现自定义事件时应继承 [AbstractEvent].
  62. */
  63. public abstract class AbstractEvent : Event {
  64. /** 限制一个事件实例不能并行广播. (适用于 object 广播的情况) */
  65. @JvmField
  66. internal val broadCastLock = Mutex()
  67. @Suppress("PropertyName")
  68. @JvmField
  69. @Volatile
  70. internal var _intercepted = false
  71. @Volatile
  72. private var _cancelled = false
  73. // 实现 Event
  74. /**
  75. * @see Event.isIntercepted
  76. */
  77. public override val isIntercepted: Boolean
  78. get() = _intercepted
  79. /**
  80. * @see Event.intercept
  81. */
  82. public override fun intercept() {
  83. _intercepted = true
  84. }
  85. // 实现 CancellableEvent
  86. /**
  87. * @see CancellableEvent.isCancelled
  88. */
  89. public val isCancelled: Boolean get() = _cancelled
  90. /**
  91. * @see CancellableEvent.cancel
  92. */
  93. public fun cancel() {
  94. check(this is CancellableEvent) {
  95. "Event $this is not cancellable"
  96. }
  97. _cancelled = true
  98. }
  99. }
  100. /**
  101. * 可被取消的事件
  102. */
  103. public interface CancellableEvent : Event {
  104. /**
  105. * 事件是否已被取消.
  106. *
  107. * 事件需实现 [CancellableEvent] 接口才可以被取消,
  108. * 否则此属性固定返回 false.
  109. */
  110. public val isCancelled: Boolean
  111. /**
  112. * 取消这个事件.
  113. * 事件需实现 [CancellableEvent] 接口才可以被取消
  114. *
  115. * @throws IllegalStateException 当事件未实现接口 [CancellableEvent] 时抛出
  116. */
  117. public fun cancel()
  118. }
  119. /**
  120. * 广播一个事件的唯一途径.
  121. *
  122. * 当事件被实现为 Kotlin `object` 时, 同一时刻只能有一个 [广播][broadcast] 存在.
  123. * 较晚执行的 [广播][broadcast] 将会挂起协程并等待之前的广播任务结束.
  124. *
  125. * @see __broadcastJava Java 使用
  126. */
  127. @JvmSynthetic
  128. public suspend fun <E : Event> E.broadcast(): E = apply {
  129. check(this is AbstractEvent) {
  130. "Events must extend AbstractEvent"
  131. }
  132. if (this is BroadcastControllable && !this.shouldBroadcast) {
  133. return@apply
  134. }
  135. this.broadCastLock.withLock {
  136. this._intercepted = false
  137. this.broadcastInternal() // inline, no extra cost
  138. }
  139. }
  140. /**
  141. * 在 Java 广播一个事件的唯一途径.
  142. *
  143. * 调用方法: `EventKt.broadcast(event)`
  144. */
  145. @Suppress("FunctionName")
  146. @JvmName("broadcast")
  147. @JavaFriendlyAPI
  148. public fun <E : Event> E.__broadcastJava(): E = apply {
  149. if (this is BroadcastControllable && !this.shouldBroadcast) {
  150. return@apply
  151. }
  152. runBlocking { this@__broadcastJava.broadcast() }
  153. }
  154. /**
  155. * 设置为 `true` 以关闭事件.
  156. * 所有的 `subscribe` 都能正常添加到监听器列表, 但所有的广播都会直接返回.
  157. */
  158. @MiraiExperimentalApi
  159. public var EventDisabled: Boolean = false
  160. /**
  161. * 可控制是否需要广播这个事件
  162. */
  163. public interface BroadcastControllable : Event {
  164. /**
  165. * 返回 `false` 时将不会广播这个事件.
  166. */
  167. public val shouldBroadcast: Boolean
  168. get() = true
  169. }