diff --git a/gradle.properties b/gradle.properties index a0ebebd69..0dcc4523c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ group=taboolib -version=6.2.2-test-1 +version=6.2.2 kotlin.incremental=true kotlin.incremental.java=true kotlin.caching.enabled=true diff --git a/platform/platform-bukkit-impl/src/main/kotlin/taboolib/platform/bukkit/ParallelSystem.kt b/platform/platform-bukkit-impl/src/main/kotlin/taboolib/platform/bukkit/ParallelSystem.kt index e8ee951d1..defd106c9 100644 --- a/platform/platform-bukkit-impl/src/main/kotlin/taboolib/platform/bukkit/ParallelSystem.kt +++ b/platform/platform-bukkit-impl/src/main/kotlin/taboolib/platform/bukkit/ParallelSystem.kt @@ -1,6 +1,7 @@ package taboolib.platform.bukkit import org.bukkit.Bukkit +import org.bukkit.event.player.AsyncPlayerPreLoginEvent import org.tabooproject.reflex.ClassMethod import org.tabooproject.reflex.ReflexClass import taboolib.common.Inject @@ -8,6 +9,8 @@ import taboolib.common.LifeCycle import taboolib.common.TabooLib import taboolib.common.inject.ClassVisitor import taboolib.common.platform.Awake +import taboolib.common.platform.function.pluginId +import taboolib.common.platform.function.registerBukkitListener import taboolib.common.util.t import java.util.* import java.util.concurrent.CompletableFuture @@ -54,8 +57,8 @@ import java.util.concurrent.Executors * 同时,为了解决并行数据加载完成之前,玩家提前进入服务器的问题 * 将会借助 Exchanges 系统选举出一个主插件,负责在所有并行任务完成之前阻止玩家进入服务器 * - * 注意别引用到别个插件的 parallel 函数。 - * 这个工具仅适用于 Bukkit 插件环境,不适用于 BungeeCord 插件环境。 + * 注意别引用到其他插件的 parallel 函数。 + * 这个工具仅适用于 Bukkit 插件环境,不适用于 BungeeCord 及其他环境。 * * 还有一种 @Parallel 注解,可以直接使一个方法成为并行任务 * ``` @@ -79,7 +82,7 @@ object ParallelSystem : ClassVisitor(0) { fun registerTask(id: String, dependOn: List, lifeCycle: LifeCycle, block: () -> Unit): CompletableFuture { // 不允许在 INIT 之后注册 - if (TabooLib.getCurrentLifeCycle() >= LifeCycle.INIT) { + if (TabooLib.getCurrentLifeCycle() > LifeCycle.INIT) { error( """ 并行任务必须在 INIT 或更早的生命周期下注册。 @@ -113,24 +116,36 @@ object ParallelSystem : ClassVisitor(0) { try { task.block() task.future.complete(null) - } catch (e: Exception) { + } catch (e: Throwable) { + e.printStackTrace() task.future.completeExceptionally(e) } } } else { // 有依赖的任务,等待依赖完成后执行 val dependencies = task.dependOn.map { dependTaskId -> - globalTaskMap[dependTaskId] ?: CompletableFuture.completedFuture(null) + // 软依赖 + if (dependTaskId.endsWith('?')) { + val id = dependTaskId.substring(0, dependTaskId.length - 1) + globalTaskMap[id] ?: CompletableFuture.completedFuture(null) + } else { + globalTaskMap[dependTaskId] ?: error( + """ + 并行任务 ${task.id} 的依赖不存在:$dependTaskId + Parallel task ${task.id} depends not found: $dependTaskId + """.t() + ) + } } - CompletableFuture.allOf(*dependencies.toTypedArray()) - .thenRunAsync({ - try { - task.block() - task.future.complete(null) - } catch (e: Exception) { - task.future.completeExceptionally(e) - } - }, executorService) + CompletableFuture.allOf(*dependencies.toTypedArray()).thenRunAsync({ + try { + task.block() + task.future.complete(null) + } catch (e: Throwable) { + e.printStackTrace() + task.future.completeExceptionally(e) + } + }, executorService) } } } @@ -163,6 +178,25 @@ object ParallelSystem : ClassVisitor(0) { TabooLib.registerLifeCycleTask(LifeCycle.ACTIVE, 0) { runTask(LifeCycle.ACTIVE) } } + @Awake(LifeCycle.ENABLE) + private fun onEnable() { + // 首个执行到 ENABLE 阶段的插件负责拦截玩家进入 + if (Exchanges.contains("parallel_main_plugin")) { + return + } + Exchanges["parallel_main_plugin"] = pluginId + registerBukkitListener(AsyncPlayerPreLoginEvent::class.java) { + if (globalTaskMap.values.any { !it.isDone }) { + it.disallow( + AsyncPlayerPreLoginEvent.Result.KICK_OTHER, """ + 服务器正在启动。 + Server is starting. + """.t() + ) + } + } + } + class Task(val id: String, val dependOn: List, val lifeCycle: LifeCycle, val block: () -> Any?) { val future = CompletableFuture() @@ -171,7 +205,7 @@ object ParallelSystem : ClassVisitor(0) { @Target(AnnotationTarget.FUNCTION) @Retention(AnnotationRetention.RUNTIME) -annotation class Parallel(val id: String = "", val dependOn: Array = [], val lifeCycle: LifeCycle = LifeCycle.ENABLE) +annotation class Parallel(val id: String = "", val dependOn: Array = [], val runOn: LifeCycle = LifeCycle.ENABLE) /** * 注册一个并行任务