From c3464cbd9997fca1fe4ab0aea60d07a47975445a Mon Sep 17 00:00:00 2001 From: TONY_All Date: Wed, 9 Feb 2022 13:56:54 +0800 Subject: [PATCH] add Message spam optimize Converter fix Error while shutdown --- build.gradle.kts | 3 +- .../kotlin/cc/maxmc/invite/BiliInviteCode.kt | 16 ++++--- .../invite/command/InviteCodeCommands.kt | 26 +++++++++-- .../kotlin/cc/maxmc/invite/data/Converter.kt | 43 +++++++++++++------ .../cc/maxmc/invite/data/InviteCodeData.kt | 1 + .../maxmc/invite/listener/InvitedListener.kt | 36 ++++++++++++---- 6 files changed, 93 insertions(+), 32 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 62df41d..d051a03 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -20,6 +20,7 @@ taboolib { install("common") install("platform-bukkit") + install("module-chat") version = "6.0.7-26" } @@ -39,5 +40,5 @@ dependencies { } tasks.withType { - kotlinOptions.jvmTarget = "16" + kotlinOptions.jvmTarget = "11" } \ No newline at end of file diff --git a/src/main/kotlin/cc/maxmc/invite/BiliInviteCode.kt b/src/main/kotlin/cc/maxmc/invite/BiliInviteCode.kt index 3267b9f..7af1cac 100644 --- a/src/main/kotlin/cc/maxmc/invite/BiliInviteCode.kt +++ b/src/main/kotlin/cc/maxmc/invite/BiliInviteCode.kt @@ -3,15 +3,14 @@ package cc.maxmc.invite import cc.maxmc.invite.command.InviteCodeCommands import cc.maxmc.invite.data.convert import cc.maxmc.invite.data.initDatabase -import kotlinx.coroutines.CoroutineExceptionHandler -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob -import kotlinx.coroutines.asCoroutineDispatcher +import cc.maxmc.invite.listener.InvitedListener +import kotlinx.coroutines.* import org.bukkit.Bukkit import taboolib.common.env.RuntimeDependencies import taboolib.common.env.RuntimeDependency import taboolib.common.platform.Plugin import taboolib.common.platform.function.console +import taboolib.common.platform.function.info import taboolib.platform.BukkitPlugin import java.util.concurrent.Executor @@ -27,16 +26,22 @@ object BiliInviteCode : Plugin() { override fun onEnable() { initDatabase() InviteCodeCommands - convert() // cc.maxmc.invite.command.DebugCommands.debug() } + + override fun onDisable() { + PluginScope.cancel("Server Shutdown") + info("Plugin Scope Down") + } } val bukkitSyncContext = Executor { + if (!BukkitPlugin.getInstance().isEnabled) return@Executor Bukkit.getScheduler().runTask(BukkitPlugin.getInstance(), it) }.asCoroutineDispatcher() val bukkitAsyncContext = Executor { + if (!BukkitPlugin.getInstance().isEnabled) return@Executor Bukkit.getScheduler().runTaskAsynchronously(BukkitPlugin.getInstance(), it) }.asCoroutineDispatcher() @@ -46,4 +51,5 @@ val PluginScope = CoroutineScope(bukkitAsyncContext + SupervisorJob() + Coroutin except.stackTrace.forEach { console().sendMessage("§c位于 $it") } + except.printStackTrace() }) \ No newline at end of file diff --git a/src/main/kotlin/cc/maxmc/invite/command/InviteCodeCommands.kt b/src/main/kotlin/cc/maxmc/invite/command/InviteCodeCommands.kt index 529290b..d5969e3 100644 --- a/src/main/kotlin/cc/maxmc/invite/command/InviteCodeCommands.kt +++ b/src/main/kotlin/cc/maxmc/invite/command/InviteCodeCommands.kt @@ -17,10 +17,16 @@ import org.bukkit.command.ConsoleCommandSender import org.bukkit.entity.Player import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction import org.jetbrains.exposed.sql.transactions.transaction +import taboolib.common.platform.ProxyCommandSender import taboolib.common.platform.command.CommandBuilder +import taboolib.common.platform.command.PermissionDefault import taboolib.common.platform.command.command +import taboolib.common.platform.function.adaptCommandSender import taboolib.common.platform.function.getDataFolder import taboolib.common.platform.function.info +import taboolib.module.chat.TellrawJson +import taboolib.platform.type.BukkitCommandSender +import taboolib.platform.type.BukkitPlayer import java.io.File import java.text.SimpleDateFormat import java.util.* @@ -28,7 +34,7 @@ import java.util.* object InviteCodeCommands { init { - command("inviteCode", aliases = listOf("code", "icode", "ic")) { + command("inviteCode", aliases = listOf("code", "icode", "ic"), permissionDefault = PermissionDefault.TRUE) { cmdUse() cmdGenerate() cmdEdit() @@ -43,7 +49,10 @@ object InviteCodeCommands { tailrec suspend fun requireQQNumber(player: Player): String? { val input = chatInput(player, "§e| §7请输入您的QQ号进行绑定 (输入 §ecancel §7取消)") if (input == "cancel") return null - if (input.length > 13) return requireQQNumber(player) + if (input.length > 10) { + player.sendMessage("§c| §7您的QQ号长度有误(最长10位),请重试.") + return requireQQNumber(player) + } if (input.toLongOrNull() == null) return requireQQNumber(player) return input } @@ -74,7 +83,10 @@ object InviteCodeCommands { .let { null } return@newSuspendedTransaction inviteCode } ?: return@launch - val qqNum = requireQQNumber(sender) ?: return@launch sender.sendMessage("§e| §7已取消激活验证码.") + InvitedListener.send.remove(sender.uniqueId) + val qqNum = runCatching { + requireQQNumber(sender) ?: return@launch sender.sendMessage("§e| §7已取消激活验证码.").also { InvitedListener.send.add(sender.uniqueId) } + }.getOrNull() ?: return@launch InvitedListener.cache.remove(sender.uniqueId).let { } sender.sendMessage("§a| §7该激活码成功绑定至QQ: §a${qqNum}") InvitedListener.cache.remove(sender.uniqueId) transaction { @@ -241,7 +253,13 @@ object InviteCodeCommands { newSuspendedTransaction { val code = InviteCode.find { InviteCodes.name eq arg }.firstOrNull() ?: return@newSuspendedTransaction sender.sendMessage("§c| §7该玩家不存在") - sender.sendMessage("§a| §7该玩家绑定的QQ为: §a${code.qq}") + if (code.qq == null) { + return@newSuspendedTransaction sender.sendMessage("§e| §7该玩家暂未绑定QQ.") + } + TellrawJson().run { + append("§a| §7该玩家绑定的QQ为: ") + append("§a${code.qq}").hoverText("(§e点击复制§r)").copyToClipboard(code.qq!!) + }.sendTo(adaptCommandSender(sender)) } } } diff --git a/src/main/kotlin/cc/maxmc/invite/data/Converter.kt b/src/main/kotlin/cc/maxmc/invite/data/Converter.kt index 5f13d88..de24212 100644 --- a/src/main/kotlin/cc/maxmc/invite/data/Converter.kt +++ b/src/main/kotlin/cc/maxmc/invite/data/Converter.kt @@ -1,16 +1,25 @@ + package cc.maxmc.invite.data import cc.maxmc.invite.PluginScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext +import kotlinx.coroutines.* import org.bukkit.Bukkit +import org.bukkit.OfflinePlayer import org.bukkit.configuration.file.YamlConfiguration -import org.jetbrains.exposed.sql.transactions.transaction +import org.jetbrains.exposed.sql.batchInsert +import org.jetbrains.exposed.sql.transactions.experimental.suspendedTransactionAsync import taboolib.common.platform.function.getDataFolder import taboolib.common.platform.function.info import java.io.File import java.nio.file.Files +import java.time.Duration +import java.util.* +import java.util.concurrent.CopyOnWriteArrayList +import java.util.concurrent.ExecutorService +import java.util.concurrent.ThreadPoolExecutor +import java.util.concurrent.TimeUnit + +val convertDispatcher = newFixedThreadPoolContext(200, "Convert") fun convert() { val file = File("./plugins/InviteCode/config.yml") @@ -22,17 +31,25 @@ fun convert() { .toList() .associate { it.first to it.second!! } PluginScope.launch { - transaction { - usable.forEach { (code, player) -> - val uuid = Bukkit.getOfflinePlayer(player).uniqueId - InviteCode.new { - inviteCode = code - uid = uuid - name = player - } + info("§a| §7开始转换") + val start = System.nanoTime() + val defData = CopyOnWriteArrayList>>() + usable.forEach { (k, v) -> + val deferred = async(convertDispatcher) { Bukkit.getOfflinePlayer(v).also { info("§b| §7在线程 ${Thread.currentThread().name} 加载 ${it.name} 的数据") } to k } + defData.add(deferred) + } + val data = defData.map { Triple(it.await().first.name, it.await().first.uniqueId, it.await().second) } + info("§a| §7UID转换成功! (耗时: ${TimeUnit.MILLISECONDS.convert(Duration.ofNanos(System.nanoTime() - start))} ms)") + val suspendedTransactionAsync = suspendedTransactionAsync { + InviteCodes.batchInsert(data) { + this[InviteCodes.name] = it.first + this[InviteCodes.uid] = it.second + this[InviteCodes.inviteCode] = it.third } } - info("§a| §7转换成功!") + suspendedTransactionAsync.await() + + info("§a| §7转换成功! (耗时: ${TimeUnit.MILLISECONDS.convert(Duration.ofNanos(System.nanoTime() - start))} ms)") withContext(Dispatchers.IO) { Files.move(file.toPath(), File(getDataFolder(), "legacy.yml.deprecated").toPath()) } diff --git a/src/main/kotlin/cc/maxmc/invite/data/InviteCodeData.kt b/src/main/kotlin/cc/maxmc/invite/data/InviteCodeData.kt index 2bd81b4..352be94 100644 --- a/src/main/kotlin/cc/maxmc/invite/data/InviteCodeData.kt +++ b/src/main/kotlin/cc/maxmc/invite/data/InviteCodeData.kt @@ -35,6 +35,7 @@ fun initDatabase() { SchemaUtils.create(InviteCodes, TimeTable) info("§a| §7成功读取数据库信息.") } + convert() } } diff --git a/src/main/kotlin/cc/maxmc/invite/listener/InvitedListener.kt b/src/main/kotlin/cc/maxmc/invite/listener/InvitedListener.kt index ece2e01..e01acd2 100644 --- a/src/main/kotlin/cc/maxmc/invite/listener/InvitedListener.kt +++ b/src/main/kotlin/cc/maxmc/invite/listener/InvitedListener.kt @@ -6,14 +6,15 @@ import cc.maxmc.invite.concurrent.chatInput import cc.maxmc.invite.data.InviteCode import cc.maxmc.invite.data.InviteCodes import cc.maxmc.invite.data.LastLogout -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext +import kotlinx.coroutines.* +import org.bukkit.Bukkit import org.bukkit.Location import org.bukkit.entity.Player import org.bukkit.event.player.* import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction import taboolib.common.platform.event.SubscribeEvent import taboolib.common.platform.function.console +import taboolib.common.platform.function.info import java.time.LocalDate import java.util.* import java.util.concurrent.ConcurrentHashMap @@ -21,12 +22,21 @@ import java.util.concurrent.ConcurrentHashMap object InvitedListener { val cache = ConcurrentHashMap() + val send = ArrayList() + + val job = PluginScope.launch { + while (isActive) { + delay(1500) + send.forEach { uid -> + val player = Bukkit.getPlayer(uid) ?: return@launch send.remove(uid).let { } + player.sendMessage("§c| §7您的账号未激活, 请输入 §c/ic use <邀请码> §7来进行激活.") + } + } + } + @SubscribeEvent fun onMove(e: PlayerMoveEvent) { - if (!cache.containsKey(e.player.uniqueId)) return - if (e.player.location.distance(cache[e.player.uniqueId]!!) > 5) { - e.player.teleport(cache[e.player.uniqueId]!!) - } + cache[e.player.uniqueId]?.let { e.player.teleport(it) } } @SubscribeEvent @@ -63,7 +73,10 @@ object InvitedListener { tailrec suspend fun requireQQNumber(player: Player): String? { val input = chatInput(player, "§e| §7请输入您的QQ号进行绑定 (输入 §ecancel §7取消)") if (input == "cancel") return null - if (input.length > 13) return requireQQNumber(player) + if (input.length > 10) { + player.sendMessage("§c| §7您的QQ号长度有误(最长10位),请重试.") + return requireQQNumber(player) + } if (input.toLongOrNull() == null) return requireQQNumber(player) return input } @@ -85,7 +98,8 @@ object InvitedListener { newSuspendedTransaction { val playerInviteCode = InviteCode.find { InviteCodes.uid eq e.player.uniqueId } .firstOrNull() - ?: return@newSuspendedTransaction e.player.sendMessage("§c| §7您的账号未激活, 请输入 §c/ic use <激活码> §7来进行激活.") + ?: return@newSuspendedTransaction e.player.sendMessage("§c| §7您的账号未激活, 请输入 §c/ic use <邀请码> §7来进行激活.") + .also { send.add(e.player.uniqueId) } if (!checkTime(e.player.uniqueId)) { withContext(bukkitSyncContext) { e.player.kickPlayer("§c| §7由于超过3个月未登录游戏, 您的邀请码已失效.") @@ -94,7 +108,11 @@ object InvitedListener { return@newSuspendedTransaction } if (playerInviteCode.qq == null) { - playerInviteCode.qq = requireQQNumber(e.player) + runCatching { + playerInviteCode.qq = requireQQNumber(e.player) ?: return@newSuspendedTransaction withContext(bukkitSyncContext) { + e.player.kickPlayer("§e| §7您需要绑定QQ号以正常进行游戏.") + } + }.exceptionOrNull()?.run { cache.remove(e.player.uniqueId) } } e.player.sendMessage("§a| §7检查通过, 您可以正常进行游戏.") cache.remove(e.player.uniqueId)