|
@@ -34,6 +34,14 @@ internal interface EventDispatcher {
|
|
*/
|
|
*/
|
|
fun broadcastAsync(event: Event, additionalContext: CoroutineContext = EmptyCoroutineContext): EventBroadcastJob
|
|
fun broadcastAsync(event: Event, additionalContext: CoroutineContext = EmptyCoroutineContext): EventBroadcastJob
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Implementor must call `event.broadcast()` within a coroutine with [EventDispatcherScopeFlag]
|
|
|
|
+ */
|
|
|
|
+ fun broadcastAsync(
|
|
|
|
+ additionalContext: CoroutineContext = EmptyCoroutineContext,
|
|
|
|
+ event: suspend () -> Event?,
|
|
|
|
+ ): EventBroadcastJob
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* Join all jobs. Joins also jobs launched during this call.
|
|
* Join all jobs. Joins also jobs launched during this call.
|
|
*/
|
|
*/
|
|
@@ -58,6 +66,13 @@ internal value class EventBroadcastJob(
|
|
if (it == null) action()
|
|
if (it == null) action()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ inline fun thenBroadcast(eventDispatcher: EventDispatcher, crossinline event: suspend () -> Event?) {
|
|
|
|
+ eventDispatcher.broadcastAsync {
|
|
|
|
+ job.join()
|
|
|
|
+ event()
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -93,6 +108,18 @@ internal open class EventDispatcherImpl(
|
|
return EventBroadcastJob(job)
|
|
return EventBroadcastJob(job)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ override fun broadcastAsync(additionalContext: CoroutineContext, event: suspend () -> Event?): EventBroadcastJob {
|
|
|
|
+ val job = launch(
|
|
|
|
+ additionalContext + EventDispatcherScopeFlag,
|
|
|
|
+ start = CoroutineStart.UNDISPATCHED
|
|
|
|
+ ) {
|
|
|
|
+ event()?.let { broadcast(it) }
|
|
|
|
+ }
|
|
|
|
+ // UNDISPATCHED: starts the coroutine NOW in the current thread until its first suspension point,
|
|
|
|
+ // so that after `broadcastAsync` the job is always already started and `joinBroadcast` will work normally.
|
|
|
|
+ return EventBroadcastJob(job)
|
|
|
|
+ }
|
|
|
|
+
|
|
protected fun optimizeEventToString(event: Event): String {
|
|
protected fun optimizeEventToString(event: Event): String {
|
|
val qualified = event::class.java.canonicalName ?: return event.toString()
|
|
val qualified = event::class.java.canonicalName ?: return event.toString()
|
|
return qualified.substringAfter("net.mamoe.mirai.event.events.", "").ifEmpty { event.toString() }
|
|
return qualified.substringAfter("net.mamoe.mirai.event.events.", "").ifEmpty { event.toString() }
|