Event.kt 4.9 KB

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