From f95c6701e5e455abccd9befa2aa7c2f48effa43c Mon Sep 17 00:00:00 2001 From: 3944Realms Date: Mon, 22 Sep 2025 10:49:01 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E5=AE=8C=E5=96=84banmodule=EF=BC=8C?= =?UTF-8?q?=E5=88=9D=E6=AD=A5=E7=BC=96=E5=86=99dglab=E6=A8=A1=E5=9D=97):?= =?UTF-8?q?=20=E6=9B=B4=E6=96=B0=E7=89=88=E6=9C=AC=E5=A5=BD=EF=BC=8C?= =?UTF-8?q?=E5=AE=8C=E5=96=84BanModule=EF=BC=8C=E5=88=9D=E6=AD=A5=E7=BC=96?= =?UTF-8?q?=E5=86=99dglab=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/uiDesigner.xml | 124 +++++++ build.gradle.kts | 16 +- gradle.properties | 3 +- libs/DgLab-common-4.2.11.18.jar | Bin 0 -> 140037 bytes .../ltdmanager/core/config/DgLabConfig.kt | 130 ++++++++ .../core/config/YamlConfigLoader.kt | 3 + .../ltdmanager/dglab/manager/ClientManager.kt | 51 +++ .../ltdmanager/dglab/manager/DgLabManager.kt | 102 ++++++ .../ltdmanager/dglab/manager/IManager.kt | 7 + .../ltdmanager/dglab/manager/ServerManager.kt | 43 +++ .../dglab/model/game/GameClientOperation.kt | 61 ++++ .../dglab/model/game/GameServerOperation.kt | 5 + .../ltdmanager/dglab/model/game/Player.kt | 8 + .../pulseware/CustomPulseDataConverter.kt | 56 ++++ .../dglab/model/pulseware/DefaultPulseData.kt | 313 ++++++++++++++++++ .../pulseware/PulseWaveClassTransform.kt | 4 + .../dglab/model/pulseware/PulseWaveJsonIO.kt | 29 ++ .../pulseware/PulseWaveListSerializable.kt | 9 + .../model/pulseware/PulseWaveSerializable.kt | 9 + .../kotlin/top/r3944realms/ltdmanager/main.kt | 21 +- .../ltdmanager/module/BanModule.kt | 198 +++++++++-- .../ltdmanager/module/DGLabModule.kt | 14 + .../module/ModGroupHandlerModule.kt | 4 +- .../ltdmanager/module/RconPlayerListModule.kt | 5 + .../common/filter/type/KeywordFilter.kt | 4 +- .../common/filter/type/MultiCommandFilter.kt | 17 + .../ltdmanager/utils/QRCodeUtil.kt | 60 ++++ src/main/resources/application.yaml | 60 +++- .../ltdmanagertest/help/helpTest.kt | 32 ++ .../r394realms/ltdmanagertest/mod/ModTest.kt | 7 +- .../ltdmanagertest/msg/NapCatMsgTest.kt | 118 ++++--- 31 files changed, 1425 insertions(+), 88 deletions(-) create mode 100644 .idea/uiDesigner.xml create mode 100644 libs/DgLab-common-4.2.11.18.jar create mode 100644 src/main/kotlin/top/r3944realms/ltdmanager/core/config/DgLabConfig.kt create mode 100644 src/main/kotlin/top/r3944realms/ltdmanager/dglab/manager/ClientManager.kt create mode 100644 src/main/kotlin/top/r3944realms/ltdmanager/dglab/manager/DgLabManager.kt create mode 100644 src/main/kotlin/top/r3944realms/ltdmanager/dglab/manager/IManager.kt create mode 100644 src/main/kotlin/top/r3944realms/ltdmanager/dglab/manager/ServerManager.kt create mode 100644 src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/game/GameClientOperation.kt create mode 100644 src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/game/GameServerOperation.kt create mode 100644 src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/game/Player.kt create mode 100644 src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/pulseware/CustomPulseDataConverter.kt create mode 100644 src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/pulseware/DefaultPulseData.kt create mode 100644 src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/pulseware/PulseWaveClassTransform.kt create mode 100644 src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/pulseware/PulseWaveJsonIO.kt create mode 100644 src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/pulseware/PulseWaveListSerializable.kt create mode 100644 src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/pulseware/PulseWaveSerializable.kt create mode 100644 src/main/kotlin/top/r3944realms/ltdmanager/module/DGLabModule.kt create mode 100644 src/main/kotlin/top/r3944realms/ltdmanager/module/common/filter/type/MultiCommandFilter.kt create mode 100644 src/main/kotlin/top/r3944realms/ltdmanager/utils/QRCodeUtil.kt diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml new file mode 100644 index 0000000..2b63946 --- /dev/null +++ b/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 0c6b2d8..5e3b662 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,7 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +fun k(v: String) = project.property(v) as String + plugins { kotlin("jvm") version "1.9.23" kotlin("plugin.serialization") version "1.9.23" // 添加序列化插件 @@ -7,8 +9,8 @@ plugins { id("com.github.johnrengelman.shadow") version "8.0.0" // fat jar } -group = project.property("project_group") as String -version = project.property("project_version") as String +group = k("project_group") +version = k("project_version") repositories { @@ -58,6 +60,16 @@ repositories { // 协程 implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") + implementation("org.apache.commons:commons-lang3:3.17.0") + implementation("com.google.guava:guava:33.3.0-jre") + + //DG_Lab 依赖库导入 + implementation("io.netty:netty-all:4.1.109.Final") + implementation("com.google.code.gson:gson:2.10.1") + implementation(files("libs/DgLab-common-${k("dg_lab_version")}.jar")) + + //生成 二维码 + implementation("com.google.zxing:core:[3.5.3,)") // 测试 testImplementation(kotlin("test")) diff --git a/gradle.properties b/gradle.properties index 60a346b..28b6dbe 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,4 +3,5 @@ org.gradle.downloadSources=false org.gradle.parallel=true org.gradle.degree_of_parallelism=16 project_group=top.r3944realms.ltdmanager -project_version=1.6-SNAPSHOT +project_version=1.10-SNAPSHOT +dg_lab_version=4.2.11.18 diff --git a/libs/DgLab-common-4.2.11.18.jar b/libs/DgLab-common-4.2.11.18.jar new file mode 100644 index 0000000000000000000000000000000000000000..548593c59f448750c6304e7ac1d0bec1ef1ba56f GIT binary patch literal 140037 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 0) { "localServerPort 必须大于 0" } + require(localServerPublishUrl.isNotBlank()) { "localServerPublishUrl 未配置" } + if (localServerSecure) { + require(localServerSslCert.isNotBlank()) { "启用 SSL 时必须配置 localServerSslCert" } + require(localServerSslKey.isNotBlank()) { "启用 SSL 时必须配置 localServerSslKey" } + } + } + } + + data class DgLabClientConfig( + var bindTimeout: Double = 90.0, + var registerTimeout: Double = 30.0 + ) + + data class PulseDataConfig( + var customPulseData: String = "data/dg-lab-play/customPulseData.json", + var durationPerPost: Double = 8.0, + var postInterval: Double = 1.0, + var sleepAfterClear: Double = 0.5 + ) { + fun validate(maxLength: Double) { + require(durationPerPost <= maxLength * 0.1) { "PulseDataConfig.durationPerPost 超出最大时长" } + } + } + + data class CommandTextConfig( + var appendPulse: String = "增加波形", + var currentPulse: String = "当前波形", + var currentStrength: String = "当前强度", + var decreaseStrength: String = "减小强度", + var dgLabDeviceJoin: String = "绑定郊狼", + var exitGame: String = "退出游戏", + var increaseStrength: String = "加大强度", + var randomPulse: String = "随机波形", + var randomStrength: String = "随机强度", + var resetPulse: String = "重置波形", + var showPlayers: String = "当前玩家", + var showPulses: String = "可用波形", + var usage: String = "郊狼玩法" + ) + + data class ReplyTextConfig( + var bindTimeout: String = "绑定超时", + var currentPlayers: String = "当前玩家:", + var currentPulse: String = "当前波形循环为:【{}】", + var currentStrength: String = "A通道:{0}/{1} B通道:{2}/{3}", + var failedToCreateClient: String = "创建 DG-Lab 控制终端失败", + var failedToFetchStrengthInfo: String = "获取通道强度状态失败", + var failedToFetchStrengthLimit: String = "获取通道强度上限失败,控制失败", + var gameExited: String = "已退出游戏", + var invalidPulseParam: String = "波形参数错误,控制失败", + var invalidStrengthParam: String = "强度参数错误,控制失败", + var invalidTarget: String = "目标玩家不存在或郊狼 App 未绑定", + var noAvailablePulse: String = "无可用波形", + var noPlayer: String = "当前没有已连接的玩家,你可以绑定试试~", + var notBindYet: String = "你目前没有绑定 DG-Lab App", + var pleaseAtTarget: String = "使用命令的同时请 @ 想要控制的玩家", + var pleaseScanQrcode: String = "请用 DG-Lab App 扫描二维码以连接", + var pleaseSetPulseFirst: String = "请先设置郊狼波形:{}", + var pulsesEmpty: String = "当前波形循环为空", + var successfullyBind: String = "绑定成功,可以开始色色了!", + var successfullyDecreased: String = "郊狼强度减小了 {}%", + var successfullyIncreased: String = "郊狼强度加强了 {}%!", + var successfullySetPulse: String = "郊狼波形成功设置为【{}】!", + var successfullySetToStrength: String = "郊狼强度成功设置为 {}%!" + ) + + data class DebugConfig( + var enableDebug: Boolean = false, + var ideHost: String = "127.0.0.1", + var idePort: Int = 5678 + ) +} \ No newline at end of file diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/core/config/YamlConfigLoader.kt b/src/main/kotlin/top/r3944realms/ltdmanager/core/config/YamlConfigLoader.kt index 4847206..306ce2a 100644 --- a/src/main/kotlin/top/r3944realms/ltdmanager/core/config/YamlConfigLoader.kt +++ b/src/main/kotlin/top/r3944realms/ltdmanager/core/config/YamlConfigLoader.kt @@ -34,6 +34,7 @@ object YamlConfigLoader { config?.mail?.encryptPassword() config?.tools?.rcon?.encryptPassword() config?.blessingSkinServer?.invitationApi?.encryptToken() + config?.dgLab?.wsServer?.encryptPassword() } private fun loadConfig(): ConfigWrapper { if (!Files.exists(configFilePath)) { @@ -76,6 +77,7 @@ object YamlConfigLoader { fun loadToolConfig(): ToolConfig = config.tools fun loadMailConfig(): MailConfig = config.mail fun loadBlessingSkinServerConfig(): BlessingSkinServerConfig = config.blessingSkinServer + fun loadDgLabConfig(): DgLabConfig = config.dgLab data class ConfigWrapper( var database: DatabaseConfig = DatabaseConfig(), var crypto: CryptoConfig = CryptoConfig(), @@ -85,6 +87,7 @@ object YamlConfigLoader { var tools: ToolConfig = ToolConfig(), var mail: MailConfig = MailConfig(), var blessingSkinServer: BlessingSkinServerConfig = BlessingSkinServerConfig(), + var dgLab: DgLabConfig = DgLabConfig(), ) } \ No newline at end of file diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/dglab/manager/ClientManager.kt b/src/main/kotlin/top/r3944realms/ltdmanager/dglab/manager/ClientManager.kt new file mode 100644 index 0000000..faff82f --- /dev/null +++ b/src/main/kotlin/top/r3944realms/ltdmanager/dglab/manager/ClientManager.kt @@ -0,0 +1,51 @@ +package top.r3944realms.ltdmanager.dglab.manager + +import com.r3944realms.dg_lab.manager.DGPBClientManager + +class ClientManager( + private val clients: MutableMap = mutableMapOf(), +) : IManager> { + + /** + * 添加单例客户端管理示例 + * @param key 唯一标识客户端管理的 key,比如 ID 或 name + */ + fun addClient(key: String, client: DGPBClientManager) { + clients[key] = client + } + + /** + * 移除单例客户端管理实例 + */ + fun removeClient(key: String) { + clients.remove(key)?.stop() + } + + /** + * 根据 key 获取客户端 + */ + fun getClient(key: String): DGPBClientManager? { + return clients[key] + } + + /** + * 启动所有客户端 + */ + override fun startAll() { + clients.values.forEach { it.start() } + } + + /** + * 停止所有客户端 + */ + override fun stopAll() { + clients.values.forEach { it.stop() } + } + + /** + * 获取内部 Map 实例 + */ + override fun getInstance(): MutableMap { + return clients + } +} diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/dglab/manager/DgLabManager.kt b/src/main/kotlin/top/r3944realms/ltdmanager/dglab/manager/DgLabManager.kt new file mode 100644 index 0000000..81147d5 --- /dev/null +++ b/src/main/kotlin/top/r3944realms/ltdmanager/dglab/manager/DgLabManager.kt @@ -0,0 +1,102 @@ +package top.r3944realms.ltdmanager.dglab.manager + +import com.r3944realms.dg_lab.api.operation.ClientOperation +import com.r3944realms.dg_lab.api.operation.ServerOperation +import com.r3944realms.dg_lab.api.websocket.message.role.WebSocketClientRole +import com.r3944realms.dg_lab.api.websocket.message.role.WebSocketServerRole +import com.r3944realms.dg_lab.manager.DGPBClientManager +import com.r3944realms.dg_lab.manager.DGPBServerManager +import com.r3944realms.dg_lab.websocket.PowerBoxWSClient +import com.r3944realms.dg_lab.websocket.PowerBoxWSServer +import com.r3944realms.dg_lab.websocket.sharedData.ClientPowerBoxSharedData +import com.r3944realms.dg_lab.websocket.sharedData.ServerPowerBoxSharedData +import top.r3944realms.ltdmanager.core.config.YamlConfigLoader +import kotlin.io.path.Path + +/** + * 全局DG_Lab单例管理器 + */ +object DgLabManager { + // 可空,延迟初始化 + var serverManager: ServerManager? = null + private set + + var clientManager: ClientManager? = null + private set + + + fun createServerManager(operation: ServerOperation): DGPBServerManager { + val loadDgLabConfig = YamlConfigLoader.loadDgLabConfig() + val boxWSServer = PowerBoxWSServer.Builder.getBuilder() + .port(loadDgLabConfig.wsServer.localServerPort) + .role(WebSocketServerRole("Se-IC")) + .operation(operation) + .sharedData(ServerPowerBoxSharedData()) + .build() + if (loadDgLabConfig.wsServer.localServerSecure) { + boxWSServer.enableSSL(Path(loadDgLabConfig.wsServer.localServerSslCert).toFile(), Path(loadDgLabConfig.wsServer.localServerSslKey).toFile(), loadDgLabConfig.wsServer.decryptedLocalServerSslPassword) + } + val dgpbServerManager = DGPBServerManager(boxWSServer) + return dgpbServerManager + } + + /** + * 初始化 服务器管理类 + */ + fun initServerManager(server: DGPBServerManager) { + serverManager = ServerManager(server) + } + /** + * 初始化 客户端管理类 + */ + fun initClientManager() { + clientManager = ClientManager() + } + + /** + * 添加 客户端管理类 + */ + fun addClient(key: String, client: DGPBClientManager) { + clientManager?.addClient(key, client) + } + + /** + * 移除 客户端管理类 + */ + fun removeClient(key: String) { + clientManager?.removeClient(key) + } + + /** + * 获取 客户端管理类 + */ + fun getClient(key: String): DGPBClientManager? { + return clientManager?.getClient(key) + } + /** + * 获取 & 创建 客户端管理类 + */ + fun getClientOrCreate(key: String, operation: ClientOperation): DGPBClientManager { + val client = getClient(key) + if (client == null) { + val loadDgLabConfig = YamlConfigLoader.loadDgLabConfig() + val boxWSClient = PowerBoxWSClient.Builder.getBuilder() + .address(loadDgLabConfig.wsServer.localServerUrl) + .port(loadDgLabConfig.wsServer.localServerPort) + .role(WebSocketClientRole("QQ-$key")) + .operation(operation) + .sharedData(ClientPowerBoxSharedData()) + .build() + + if (loadDgLabConfig.wsServer.localServerSecure) { + boxWSClient.enableSSL() + } + val clientManager = DGPBClientManager( + boxWSClient + ) + this.clientManager?.addClient(key, clientManager) + return clientManager + } + return client + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/dglab/manager/IManager.kt b/src/main/kotlin/top/r3944realms/ltdmanager/dglab/manager/IManager.kt new file mode 100644 index 0000000..a6555f9 --- /dev/null +++ b/src/main/kotlin/top/r3944realms/ltdmanager/dglab/manager/IManager.kt @@ -0,0 +1,7 @@ +package top.r3944realms.ltdmanager.dglab.manager + +interface IManager { + fun startAll() + fun stopAll() + fun getInstance(): T? +} \ No newline at end of file diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/dglab/manager/ServerManager.kt b/src/main/kotlin/top/r3944realms/ltdmanager/dglab/manager/ServerManager.kt new file mode 100644 index 0000000..1971e10 --- /dev/null +++ b/src/main/kotlin/top/r3944realms/ltdmanager/dglab/manager/ServerManager.kt @@ -0,0 +1,43 @@ +package top.r3944realms.ltdmanager.dglab.manager + +import com.r3944realms.dg_lab.api.manager.IDGLabManager +import com.r3944realms.dg_lab.api.manager.Status +import com.r3944realms.dg_lab.api.websocket.sharedData.ISharedData +import com.r3944realms.dg_lab.manager.DGPBServerManager + +class ServerManager( + private val server: DGPBServerManager +) : IManager, IDGLabManager { + + override fun startAll() { + start() + } + + override fun stopAll() { + stop() + } + + override fun start() { + server.start() + } + + override fun stop() { + server.stop() + } + + override fun getSharedData(): ISharedData { + return server.sharedData + } + + override fun getStatus(): Status { + return server.status + } + + override fun setStatus(p0: Status?) { + server.status = p0 + } + + override fun getInstance(): DGPBServerManager { + return server + } +} diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/game/GameClientOperation.kt b/src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/game/GameClientOperation.kt new file mode 100644 index 0000000..1d5cc11 --- /dev/null +++ b/src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/game/GameClientOperation.kt @@ -0,0 +1,61 @@ +package top.r3944realms.ltdmanager.dglab.model.game + +import com.r3944realms.dg_lab.api.operation.ClientOperation +import com.r3944realms.dg_lab.api.websocket.message.data.PowerBoxData + +class GameClientOperation( + val player: Player +) : ClientOperation { + + override fun ClientStartingHandler() { + println("Player ${player.id} is starting the client...") + } + + override fun ClientStartedHandler() { + println("Player ${player.id} client started successfully.") + } + + override fun ClientStartingErrorHandler() { + println("Player ${player.id} failed to start client!") + } + + override fun ClientStoppingHandler() { + println("Player ${player.id} is stopping the client...") + } + + override fun ClientStoppingErrorHandler() { + println("Player ${player.id} encountered an error while stopping.") + } + + override fun ClientStoppedHandler() { + println("Player ${player.id} client stopped.") + } + + override fun QrCodeUrlHandler(p0: String?) { + println("Player ${player.id} QR code received: $p0") + } + + override fun ShowQrCodeHandler() { + println("Player ${player.id} should display QR code.") + } + + override fun ConnectSuccessfulNoticeHandler() { + println("Player ${player.id} connected successfully.") + } + + override fun DisconnectHandler(p0: PowerBoxData?) { + println("Player ${player.id} disconnected: $p0") + } + + override fun ErrorHandler(p0: PowerBoxData?) { + println("Player ${player.id} error occurred: $p0") + } + + override fun HeartBeatHandler(p0: PowerBoxData?) { + println("Heartbeat from player ${player.id}: $p0") + } + + override fun OtherMessageHandler(p0: PowerBoxData?) { + println("Other message for player ${player.id}: $p0") + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/game/GameServerOperation.kt b/src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/game/GameServerOperation.kt new file mode 100644 index 0000000..e5a46ac --- /dev/null +++ b/src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/game/GameServerOperation.kt @@ -0,0 +1,5 @@ +package top.r3944realms.ltdmanager.dglab.model.game + +import com.r3944realms.dg_lab.websocket.handler.server.DefaultServerOperation + +class GameServerOperation : DefaultServerOperation() \ No newline at end of file diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/game/Player.kt b/src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/game/Player.kt new file mode 100644 index 0000000..7defc55 --- /dev/null +++ b/src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/game/Player.kt @@ -0,0 +1,8 @@ +package top.r3944realms.ltdmanager.dglab.model.game + +/** + * 玩家类,目前仅包含一个 ID + */ +data class Player( + val id: String +) \ No newline at end of file diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/pulseware/CustomPulseDataConverter.kt b/src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/pulseware/CustomPulseDataConverter.kt new file mode 100644 index 0000000..39f0dd8 --- /dev/null +++ b/src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/pulseware/CustomPulseDataConverter.kt @@ -0,0 +1,56 @@ +package top.r3944realms.ltdmanager.dglab.model.pulseware + +import com.r3944realms.dg_lab.api.message.data.PulseWave +import com.r3944realms.dg_lab.api.message.data.PulseWaveList + + +object CustomPulseDataConverter { + /** + * 将自定义波形数据转换为 PulseWaveList + * + * @param customPulseData Map, List[][]>> + * 每个 int[][] 包含两个长度为 4 的 int 数组,第一个是 frequencies,第二个是 strengths + * @return Map, PulseWaveList> + */ + fun convert(customPulseData: Map>>): Map { + val pulseWaveLists: MutableMap = HashMap() + + for ((name, operations) in customPulseData) { + val waveList = PulseWaveList() + waveList.name = name + + for (op in operations) { + val freqs = op[0] + val strengths = op[1] + + // 确保每个数组长度为4 + require(!(freqs.size != 4 || strengths.size != 4)) { "每个波形段必须包含 4 个频率和 4 个强度值" } + + val wave = PulseWave.fromArrays(freqs, strengths) + waveList.add(wave) + } + + pulseWaveLists[name] = waveList + } + + return pulseWaveLists + } + fun PulseWave.toSerializable(): PulseWaveSerializable = + PulseWaveSerializable(f1(), f2(), f3(), f4(), s1(), s2(), s3(), s4()) + + fun PulseWaveSerializable.toPulseWave(): PulseWave = + PulseWave.fromArrays( + intArrayOf(f1, f2, f3, f4), + intArrayOf(s1, s2, s3, s4) + ) + + fun PulseWaveList.toSerializable(): PulseWaveListSerializable = + PulseWaveListSerializable(name, list.map { it.toSerializable() }.toMutableList()) + + fun PulseWaveListSerializable.toPulseWaveList(): PulseWaveList { + val listObj = PulseWaveList() + listObj.setName(name) + list.forEach { listObj.add(it.toPulseWave()) } + return listObj + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/pulseware/DefaultPulseData.kt b/src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/pulseware/DefaultPulseData.kt new file mode 100644 index 0000000..c4266a9 --- /dev/null +++ b/src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/pulseware/DefaultPulseData.kt @@ -0,0 +1,313 @@ +package top.r3944realms.ltdmanager.dglab.model.pulseware + +import com.r3944realms.dg_lab.api.message.data.PulseWave +import com.r3944realms.dg_lab.api.message.data.PulseWaveList + +object DefaultPulseData { + + fun allPulseWaveLists(): Map { + return mapOf( + "呼吸" to Breath, + "潮汐" to Tide, + "连击" to Combo, + "快速按捏" to FastPinch, + "按捏渐强" to PinchGradual, + "心跳节奏" to Heartbeat, + "压缩" to Compress, + "节奏步伐" to RhythmStep, + "颗粒摩擦" to GranularFriction, + "渐变弹跳" to GradualBounce, + "波浪涟漪" to WaveRipple, + "雨水冲刷" to RainWash, + "变速敲击" to SpeedHit, + "信号灯" to SignalLight, + "挑逗1" to Tease1, + "挑逗2" to Tease2 + ) + } + + val Breath: PulseWaveList by lazy { + val list = PulseWaveList() + list.name = "呼吸" + + // 每段频率和强度 + val segments = listOf( + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 5, 10, 20)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(20, 25, 30, 40)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(40, 45, 50, 60)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(60, 65, 70, 80)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(0, 0, 0, 0), intArrayOf(0, 0, 0, 0)), + arrayOf(intArrayOf(0, 0, 0, 0), intArrayOf(0, 0, 0, 0)), + arrayOf(intArrayOf(0, 0, 0, 0), intArrayOf(0, 0, 0, 0)) + ) + + // 转成 PulseWave 并加入列表 + for (seg in segments) { + list.add(PulseWave.fromArrays(seg[0], seg[1])) + } + + list + } + val Tide: PulseWaveList by lazy { + val list = PulseWaveList() + list.name = "潮汐" + val segments = listOf( + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 4, 8, 17)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(17, 21, 25, 33)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(50, 50, 50, 50)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(50, 54, 58, 67)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(67, 71, 75, 83)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 98, 96, 92)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(92, 90, 88, 84)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(84, 82, 80, 76)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(68, 68, 68, 68)) + ) + segments.forEach { list.add(PulseWave.fromArrays(it[0], it[1])) } + list + } + + val Combo: PulseWaveList by lazy { + val list = PulseWaveList() + list.name = "连击" + val segments = listOf( + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 92, 84, 67)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(67, 58, 50, 33)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 1)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(2, 2, 2, 2)) + ) + segments.forEach { list.add(PulseWave.fromArrays(it[0], it[1])) } + list + } + val FastPinch: PulseWaveList by lazy { + val list = PulseWaveList() + list.name = "快速按捏" + val segments = listOf( + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(0, 0, 0, 0), intArrayOf(0, 0, 0, 0)) + ) + segments.forEach { list.add(PulseWave.fromArrays(it[0], it[1])) } + list + } + val PinchGradual: PulseWaveList by lazy { + val list = PulseWaveList() + list.name = "按捏渐强" + val segments = listOf( + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(29, 29, 29, 29)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(52, 52, 52, 52)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(2, 2, 2, 2)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(73, 73, 73, 73)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(87, 87, 87, 87)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)) + ) + segments.forEach { list.add(PulseWave.fromArrays(it[0], it[1])) } + list + } + + val Heartbeat: PulseWaveList by lazy { + val list = PulseWaveList() + list.name = "心跳节奏" + val segments = listOf( + arrayOf(intArrayOf(110, 110, 110, 110), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(110, 110, 110, 110), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(75, 75, 75, 75)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(75, 77, 79, 83)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(83, 85, 88, 92)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)) + ) + segments.forEach { list.add(PulseWave.fromArrays(it[0], it[1])) } + list + } + val Compress: PulseWaveList by lazy { + val list = PulseWaveList() + list.name = "压缩" + val segments = listOf( + arrayOf(intArrayOf(25, 25, 24, 24), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(24, 23, 23, 23), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(22, 22, 22, 21), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(21, 21, 20, 20), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(20, 19, 19, 19), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(18, 18, 18, 17), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(17, 16, 16, 16), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(15, 15, 15, 14), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(14, 14, 13, 13), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(13, 12, 12, 12), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(11, 11, 11, 10), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)) + ) + segments.forEach { list.add(PulseWave.fromArrays(it[0], it[1])) } + list + } + val RhythmStep: PulseWaveList by lazy { + val list = PulseWaveList() + list.name = "节奏步伐" + val segments = listOf( + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 5, 10, 20)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(20, 25, 30, 40)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(40, 45, 50, 60)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(60, 65, 70, 80)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 6, 12, 25)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(25, 31, 38, 50)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(50, 56, 62, 75)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 8, 16, 33)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(33, 42, 50, 67)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 12, 25, 50)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)) + ) + segments.forEach { list.add(PulseWave.fromArrays(it[0], it[1])) } + list + } + + val GranularFriction: PulseWaveList by lazy { + val list = PulseWaveList() + list.name = "颗粒摩擦" + val segments = listOf( + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)) + ) + segments.forEach { list.add(PulseWave.fromArrays(it[0], it[1])) } + list + } + + val GradualBounce: PulseWaveList by lazy { + val list = PulseWaveList() + list.name = "渐变弹跳" + val segments = listOf( + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(1, 1, 1, 1)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(1, 9, 18, 34)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(34, 42, 50, 67)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(0, 0, 0, 0), intArrayOf(0, 0, 0, 0)), + arrayOf(intArrayOf(0, 0, 0, 0), intArrayOf(0, 0, 0, 0)) + ) + segments.forEach { list.add(PulseWave.fromArrays(it[0], it[1])) } + list + } + val WaveRipple: PulseWaveList by lazy { + val list = PulseWaveList() + list.name = "波浪涟漪" + val segments = listOf( + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(1, 1, 1, 1)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(1, 3, 7, 13)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(13, 25, 40, 60)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(60, 75, 90, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(50, 50, 50, 50)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)) + ) + segments.forEach { list.add(PulseWave.fromArrays(it[0], it[1])) } + list + } + + val RainWash: PulseWaveList by lazy { + val list = PulseWaveList() + list.name = "雨水冲刷" + val segments = listOf( + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 5, 15, 30)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(40, 50, 60, 70)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(80, 90, 100, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)) + ) + segments.forEach { list.add(PulseWave.fromArrays(it[0], it[1])) } + list + } + + val SpeedHit: PulseWaveList by lazy { + val list = PulseWaveList() + list.name = "变速敲击" + val segments = listOf( + arrayOf(intArrayOf(15, 15, 15, 15), intArrayOf(0, 0, 0, 0)), + arrayOf(intArrayOf(20, 20, 20, 20), intArrayOf(50, 50, 50, 50)), + arrayOf(intArrayOf(25, 25, 25, 25), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(20, 20, 20, 20), intArrayOf(50, 50, 50, 50)), + arrayOf(intArrayOf(15, 15, 15, 15), intArrayOf(0, 0, 0, 0)) + ) + segments.forEach { list.add(PulseWave.fromArrays(it[0], it[1])) } + list + } + val SignalLight: PulseWaveList by lazy { + val list = PulseWaveList() + list.name = "信号灯" + val segments = listOf( + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 0, 0, 0)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 100, 100, 100)) + ) + segments.forEach { list.add(PulseWave.fromArrays(it[0], it[1])) } + list + } + + val Tease1: PulseWaveList by lazy { + val list = PulseWaveList() + list.name = "挑逗1" + val segments = listOf( + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 30, 60, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 70, 40, 0)) + ) + segments.forEach { list.add(PulseWave.fromArrays(it[0], it[1])) } + list + } + + val Tease2: PulseWaveList by lazy { + val list = PulseWaveList() + list.name = "挑逗2" + val segments = listOf( + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(0, 50, 100, 100)), + arrayOf(intArrayOf(10, 10, 10, 10), intArrayOf(100, 50, 0, 0)) + ) + segments.forEach { list.add(PulseWave.fromArrays(it[0], it[1])) } + list + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/pulseware/PulseWaveClassTransform.kt b/src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/pulseware/PulseWaveClassTransform.kt new file mode 100644 index 0000000..5f1d25e --- /dev/null +++ b/src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/pulseware/PulseWaveClassTransform.kt @@ -0,0 +1,4 @@ +package top.r3944realms.ltdmanager.dglab.model.pulseware + +class PulseWaveClassTransform { +} \ No newline at end of file diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/pulseware/PulseWaveJsonIO.kt b/src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/pulseware/PulseWaveJsonIO.kt new file mode 100644 index 0000000..187e7c9 --- /dev/null +++ b/src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/pulseware/PulseWaveJsonIO.kt @@ -0,0 +1,29 @@ +package top.r3944realms.ltdmanager.dglab.model.pulseware + +import com.r3944realms.dg_lab.api.message.data.PulseWaveList +import kotlinx.serialization.builtins.MapSerializer +import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json +import top.r3944realms.ltdmanager.dglab.model.pulseware.CustomPulseDataConverter.toPulseWaveList +import top.r3944realms.ltdmanager.dglab.model.pulseware.CustomPulseDataConverter.toSerializable +import java.io.File + +object PulseWaveJsonIO { + private val json = Json { + prettyPrint = true + encodeDefaults = true + } + + fun saveToFile(map: Map, file: File) { + val serializableMap = map.mapValues { it.value.toSerializable() } + file.writeText(json.encodeToString(serializableMap)) + } + + fun loadFromFile(file: File): Map { + if (!file.exists()) return emptyMap() + val type = MapSerializer(String.serializer(), PulseWaveListSerializable.serializer()) + val data: Map = json.decodeFromString(type, file.readText()) + return data.mapValues { it.value.toPulseWaveList() } + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/pulseware/PulseWaveListSerializable.kt b/src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/pulseware/PulseWaveListSerializable.kt new file mode 100644 index 0000000..faa5bb2 --- /dev/null +++ b/src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/pulseware/PulseWaveListSerializable.kt @@ -0,0 +1,9 @@ +package top.r3944realms.ltdmanager.dglab.model.pulseware + +import kotlinx.serialization.Serializable + +@Serializable +data class PulseWaveListSerializable( + var name: String = "", + val list: MutableList = mutableListOf() +) \ No newline at end of file diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/pulseware/PulseWaveSerializable.kt b/src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/pulseware/PulseWaveSerializable.kt new file mode 100644 index 0000000..af912d4 --- /dev/null +++ b/src/main/kotlin/top/r3944realms/ltdmanager/dglab/model/pulseware/PulseWaveSerializable.kt @@ -0,0 +1,9 @@ +package top.r3944realms.ltdmanager.dglab.model.pulseware + +import kotlinx.serialization.Serializable + +@Serializable +data class PulseWaveSerializable( + val f1: Int, val f2: Int, val f3: Int, val f4: Int, + val s1: Int, val s2: Int, val s3: Int, val s4: Int +) \ No newline at end of file diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/main.kt b/src/main/kotlin/top/r3944realms/ltdmanager/main.kt index e655696..525a10e 100644 --- a/src/main/kotlin/top/r3944realms/ltdmanager/main.kt +++ b/src/main/kotlin/top/r3944realms/ltdmanager/main.kt @@ -23,6 +23,7 @@ fun main() = GlobalManager.runBlockingMain { ) val helpModule = HelpModule( moduleName = "WhiteListGroup", + keywords = listOf("help", "帮助"), groupMessagePollingModule = groupMsgPollingModule, selfId = selfQQId, selfNickName = selfNickName, @@ -83,16 +84,18 @@ fun main() = GlobalManager.runBlockingMain { moduleName = "WhiteListGroup", groupMessagePollingModule = groupMsgPollingModule, selfId = selfQQId, - commandPrefixList = listOf("口球", "mute", "杂鱼三九"), + adminsId = listOf(1283411677), + muteCommandPrefixList = listOf("口球", "mute", "Mute", "禁言"), + unmuteCommandPrefixList = listOf("解禁", "unmute", "Unmute", "解除禁言"), minBanMinutes = 1, maxBanMinutes = 15, ) - val modGroupHandlerModule = ModGroupHandlerModule( - moduleName = "ModGroup", - targetGroupId = 339340846, - answers = listOf("戏鸢", "一只戏鸢", "折戏鸢", "LostInLinearPast", "lostinlinearpast"), - pollIntervalMillis = 15_000L, - ) +// val modGroupHandlerModule = ModGroupHandlerModule( +// moduleName = "ModGroup", +// targetGroupId = 339340846, +// answers = listOf("戏鸢", "一只戏鸢", "折戏鸢", "LostInLinearPast", "lostinlinearpast"), +// pollIntervalMillis = 15_000L, +// ) // 注册模块到全局模块管理器 GlobalManager.moduleManager.registerModule(groupModule) @@ -103,7 +106,7 @@ fun main() = GlobalManager.runBlockingMain { GlobalManager.moduleManager.registerModule(invitationCodesModule) GlobalManager.moduleManager.registerModule(helpModule) GlobalManager.moduleManager.registerModule(banModule) - GlobalManager.moduleManager.registerModule(modGroupHandlerModule) +// GlobalManager.moduleManager.registerModule(modGroupHandlerModule) // 加载模块 GlobalManager.moduleManager.loadModule(groupModule.name) @@ -114,5 +117,5 @@ fun main() = GlobalManager.runBlockingMain { GlobalManager.moduleManager.loadModule(invitationCodesModule.name) GlobalManager.moduleManager.loadModule(helpModule.name) GlobalManager.moduleManager.loadModule(banModule.name) - GlobalManager.moduleManager.loadModule(modGroupHandlerModule.name) +// GlobalManager.moduleManager.loadModule(modGroupHandlerModule.name) } \ No newline at end of file diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/module/BanModule.kt b/src/main/kotlin/top/r3944realms/ltdmanager/module/BanModule.kt index 3aac270..c61f853 100644 --- a/src/main/kotlin/top/r3944realms/ltdmanager/module/BanModule.kt +++ b/src/main/kotlin/top/r3944realms/ltdmanager/module/BanModule.kt @@ -6,12 +6,15 @@ import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import top.r3944realms.ltdmanager.module.common.CommandParser import top.r3944realms.ltdmanager.module.common.filter.TriggerMessageFilter -import top.r3944realms.ltdmanager.module.common.filter.type.CommandFilter import top.r3944realms.ltdmanager.module.common.filter.type.IgnoreSelfFilter +import top.r3944realms.ltdmanager.module.common.filter.type.MultiCommandFilter import top.r3944realms.ltdmanager.module.common.filter.type.NewMessageFilter import top.r3944realms.ltdmanager.napcat.data.ID import top.r3944realms.ltdmanager.napcat.data.MessageElement +import top.r3944realms.ltdmanager.napcat.data.MessageType +import top.r3944realms.ltdmanager.napcat.event.group.GetGroupShutListEvent import top.r3944realms.ltdmanager.napcat.event.message.GetFriendMsgHistoryEvent +import top.r3944realms.ltdmanager.napcat.request.group.GetGroupShutListRequest import top.r3944realms.ltdmanager.napcat.request.group.SetGroupBanRequest import top.r3944realms.ltdmanager.napcat.request.other.SendGroupMsgRequest import top.r3944realms.ltdmanager.utils.LoggerUtil @@ -25,13 +28,18 @@ class BanModule( moduleName: String, private val groupMessagePollingModule : GroupMessagePollingModule, private val selfId: Long, - commandPrefixList: List = listOf("/mute"), // 默认命令前缀 + private val adminsId: List = listOf(), + muteCommandPrefixList: List = listOf("mute"), // 默认命令前缀 + unmuteCommandPrefixList: List = listOf("unmute"), private val minBanMinutes: Int = 1, - private val maxBanMinutes: Int = 15 + private val maxBanMinutes: Int = 15, + private val factorX: Int = 2, // 系数 x,禁言倍数 + ) : BaseModule("BanModule", moduleName), PersistentState { - private val commandParser = CommandParser(commandPrefixList) - private val commandFilter = CommandFilter(commandParser) + private val banCommandParse = CommandParser(muteCommandPrefixList) + private val pardonCommandParse = CommandParser(unmuteCommandPrefixList) + private val multiCommandFilter = MultiCommandFilter(listOf(banCommandParse, pardonCommandParse)) private val stateFile: File = getStateFileInternal("command_ban_state.json", name) private val stateBackupFile: File = getStateFileInternal("command_ban_state.json.bak", name) private var banState = loadState() @@ -44,7 +52,7 @@ class BanModule( NewMessageFilter { userId -> banState.getLastTriggerTime(userId) to banState.getLastTriggerRealId(userId) }, - commandFilter + multiCommandFilter ) ) } @@ -75,6 +83,7 @@ class BanModule( val filtered = triggerFilter.filter(messages) for (msg in filtered) { processBanCommand(msg) + processUnBanCommand(msg) } } /** @@ -88,45 +97,160 @@ class BanModule( seg.data.qq?.let { "@${it}" } ?: (seg.data.text ?: "") }.trim() } + /** + * 从消息段中提取所有被 @ 的用户 ID + */ + private fun GetFriendMsgHistoryEvent.SpecificMsg.getMentionedUserIds(): List { + return this.message + .filter { it.type == MessageType.At && it.data.qq != null } + .mapNotNull { it.data.qq } + .distinctBy { + when (it) { + is ID.StringValue -> it.value + is ID.LongValue -> it.value + } + } + } + private suspend fun processUnBanCommand(msg: GetFriendMsgHistoryEvent.SpecificMsg) { + try { + pardonCommandParse.parseCommand(msg.plainText()) ?: return + // 获取所有被 @ 的用户 + val mentionedUserIds = msg.getMentionedUserIds().map { + when (it) { + is ID.StringValue -> it.value.toLong() + is ID.LongValue -> it.value + } + } // List + val send = + napCatClient.send(GetGroupShutListRequest(ID.long(groupMessagePollingModule.targetGroupId))) + val muteList = send.data.map { it.uin.toLong() } + for (target in mentionedUserIds) { + if(target !in muteList) { + sendGroupMessage("❌ 目标用户未被禁言", + msg.realId + ) + } else { + banUser(ID.long(target), groupMessagePollingModule.targetGroupId, 0) + sendGroupMessage( + "✅ 已解禁对方@(${target})", + msg.realId + ) + } + + } + + // 更新状态 + banState = banState.updateLastTrigger(msg.userId, msg.realId, msg.time) + saveState(banState) + } catch (e: Exception) { + LoggerUtil.logger.error("[$name] 执行解禁言指令失败", e) + sendGroupMessage("❌ 执行解禁言失败,请检查解指令格式或权限", msg.realId) + banState = banState.updateLastTrigger(msg.sender.userId, msg.realId, msg.time) + saveState(banState) + } + } private suspend fun processBanCommand(msg: GetFriendMsgHistoryEvent.SpecificMsg) { try { - val parsed = commandParser.parseCommand(msg.plainText()) ?: return - val (command, argument) = parsed + val parsed = banCommandParse.parseCommand(msg.plainText()) ?: return + val (_, argument) = parsed - // 参数格式: [分钟] - // 示例:/mute 5 → 自己禁言 5 分钟 - // /mute → 自己随机禁言 val parts = argument.split(" ").filter { it.isNotBlank() } + // 解析禁言时间 val durationMinutes = parts.getOrNull(0)?.toIntOrNull() ?: Random.nextInt(minBanMinutes, maxBanMinutes + 1) val durationSeconds = durationMinutes.coerceIn(minBanMinutes, maxBanMinutes) * 60 - val targetUserId = msg.sender.userId + // 获取所有被 @ 的用户 + val mentionedUserIds = msg.getMentionedUserIds() // List + val targets = mentionedUserIds.ifEmpty { listOf(ID.long(msg.sender.userId)) } - banUser(targetUserId, groupMessagePollingModule.targetGroupId, durationSeconds) - sendGroupMessage("✅ 你已被禁言 $durationMinutes 分钟", msg.realId) + for (target in targets) { + val targetLongId = when (target) { + is ID.StringValue -> target.value.toLong() + is ID.LongValue -> target.value + } - // 更新状态(保证状态保存正确) - // 禁言成功后更新状态 - banState = banState.updateLastTrigger(targetUserId, msg.realId, msg.time) + // 权限检查:非管理员不能禁言他人 + if (mentionedUserIds.isNotEmpty() && mentionedUserIds.size != 1 && msg.sender.userId !in adminsId) { + sendGroupMessage("❌ 你没有权限禁言使用禁言多用户功能", msg.realId) + continue + } + + // 禁言机器人跳过 + if (targetLongId == selfId) { + sendGroupMessage("❌ 你没有权限禁言机器人", msg.realId) + continue + } + if (targetLongId in adminsId) { + sendGroupMessage("❌ 不支持禁言管理员", msg.realId) + continue + } + + // 单 @ 且非自己,可能触发反禁自己 + if (mentionedUserIds.size == 1 && targetLongId != msg.sender.userId && msg.sender.userId !in adminsId) { + val dice = Random.nextInt(1, 7) // 1~6 + val chance = when (dice) { + 6 -> 100 + 5 -> 80 + 4 -> 60 + 3 -> 50 + 2 -> 20 + 1 -> 0 + else -> 0 + } + + val selfDuration = durationSeconds * factorX + if (Random.nextInt(100) < chance) { + // 触发反禁自己 + banUser(ID.long(msg.sender.userId), groupMessagePollingModule.targetGroupId, selfDuration) + sendGroupMessage( + "⚠️ 骰子点数: $dice, 成功概率: ${chance}% → 失败,你触发了反禁,禁言 ${selfDuration / 60} 分钟", + msg.realId + ) + } else { + // 未触发反禁自己,禁言目标 + banUser(target, groupMessagePollingModule.targetGroupId, durationSeconds) + sendGroupMessage( + "✅ 骰子点数: $dice, 成功概率: ${chance}% → 成功禁言 <@${targetLongId}>", + msg.realId + ) + } + } else { + // 多 @ 或管理员操作,直接禁言目标 + banUser(target, groupMessagePollingModule.targetGroupId, durationSeconds) + sendGroupMessage( + if (targetLongId == msg.sender.userId) { + "✅ 你已被禁言 ${durationSeconds/ 60} 分钟" + } else { + "✅ 已禁言 <@${targetLongId}> ${durationSeconds/ 60} 分钟" + }, + msg.realId + ) + } + + + } + // 更新状态 + banState = banState.updateLastTrigger(msg.userId, msg.realId, msg.time) saveState(banState) - } catch (e: Exception) { LoggerUtil.logger.error("[$name] 执行禁言指令失败", e) sendGroupMessage("❌ 执行禁言失败,请检查指令格式或权限", msg.realId) + banState = banState.updateLastTrigger(msg.sender.userId, msg.realId, msg.time) + saveState(banState) } } - private suspend fun banUser(userId: Long, groupId: Long, seconds: Int) { + + private suspend fun banUser(userId: ID, groupId: Long, seconds: Int) { val request = SetGroupBanRequest( duration = seconds.toDouble(), groupId = ID.long(groupId), - userId = ID.long(userId) + userId = userId ) napCatClient.sendUnit(request) LoggerUtil.logger.info("[$name] 已对用户 $userId 执行 $seconds 秒禁言") } - private suspend fun sendGroupMessage(text: String, replyTo: Long? = null) { val request = SendGroupMsgRequest( MessageElement.reply(ID.long(replyTo ?: 0), text), @@ -136,20 +260,36 @@ class BanModule( } override fun info(): String { - return "[$name] 指令禁言模块:用户发送 ${commandParser.getCommands().joinToString("、")} 来禁言自己," + - "支持指定分钟数或随机分钟数,范围 $minBanMinutes-$maxBanMinutes 分钟。" + return buildString { + append("[$name] 指令禁言模块:\n") + append(" - 用户发送 ${banCommandParse.getCommands().joinToString("、")} 来禁言自己或指定其他用户(需管理员权限)。\n") + append(" - 支持指定禁言分钟数或随机分钟数,范围 $minBanMinutes-$maxBanMinutes 分钟。\n") + append(" - 支持对单个 @ 用户禁言,有概率反禁自己(骰子点数决定概率)。\n") + append(" - 管理员可以禁言其他用户;非管理员尝试多个禁言对象会收到无权限提示。\n") + append(" - 用户发送 ${pardonCommandParse.getCommands().joinToString("、")} 来解禁指定用户。\n") + append(" - 仅支持对单个 @ 用户解禁言。\n") + } } override fun help(): String { return buildString { appendLine("📖 [$name] 使用帮助:") - appendLine(" - ${commandParser.getCommands().joinToString("、")} [分钟]") - appendLine(" · 不写分钟数 → 随机禁言 (范围 $minBanMinutes-$maxBanMinutes 分钟)") - appendLine(" · 写分钟数 → 自己禁言指定分钟数") - appendLine() + appendLine("指令格式:${banCommandParse.getCommands().joinToString("、")} [分钟] [@用户...]") appendLine("示例:") - appendLine(" - /mute → 随机禁言自己") - appendLine(" - /mute 5 → 禁言自己 5 分钟") + appendLine(" - <指令> → 随机禁言自己") + appendLine(" - <指令> 5 → 禁言自己 5 分钟") + appendLine(" - <指令> 4 @User123 → 禁言指定用户 4 分钟(可能失败)") + appendLine(" - <指令> 4 @User123 @User22 → 禁言指定多用户 4 分钟(需在程序管理员列表中)") + appendLine() + appendLine("⚠️ 特殊说明:") + appendLine(" - 如果 @ 单个用户且执行者非需在程序管理员,有 y% 概率触发反禁自己,") + appendLine(" 骰子点数决定概率:6 → 100%, 5 → 80%, 4 → 60%, 3 → 50%, 2 → 20%, 1 → 0%") + appendLine(" - 禁言机器人自身不会生效") + appendLine(" - 禁言状态会自动保存以便下次使用") + appendLine() + appendLine("指令格式:${pardonCommandParse.getCommands().joinToString("、")} [@用户]") + appendLine("示例:") + appendLine(" - <指令> @User123 → 解禁指定用户") } } diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/module/DGLabModule.kt b/src/main/kotlin/top/r3944realms/ltdmanager/module/DGLabModule.kt new file mode 100644 index 0000000..35950ac --- /dev/null +++ b/src/main/kotlin/top/r3944realms/ltdmanager/module/DGLabModule.kt @@ -0,0 +1,14 @@ +package top.r3944realms.ltdmanager.module + +class DGLabModule( + moduleName: String, +): + BaseModule("DGLabModule", moduleName) { + override fun onLoad() { + + } + + override suspend fun onUnload() { + + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/module/ModGroupHandlerModule.kt b/src/main/kotlin/top/r3944realms/ltdmanager/module/ModGroupHandlerModule.kt index b972695..cf5d0ae 100644 --- a/src/main/kotlin/top/r3944realms/ltdmanager/module/ModGroupHandlerModule.kt +++ b/src/main/kotlin/top/r3944realms/ltdmanager/module/ModGroupHandlerModule.kt @@ -187,7 +187,7 @@ class ModGroupHandlerModule( 📝 尝试答案: ${ "\n" + record.reason.joinToString("\n") { " • $it" }} - ⚠️ 提示:请仔细阅读文档后再在群里提问,否则你会失去你的大脑🧠 + ⚠️ 提示:请仔细阅读群文档后再在群里提问,否则你会失去你的大脑🧠 """.trimIndent() } else { """ @@ -198,7 +198,7 @@ class ModGroupHandlerModule( 🔹 最终评分:SSS ⭐ 💡 该用户尚未有审核记录 - ⚠️ 提示:请仔细阅读文档后再在群里提问,否则你会失去你的大脑🧠 + ⚠️ 提示:请仔细阅读群文档后再在群里提问,否则你会失去你的大脑🧠 """.trimIndent() } } diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/module/RconPlayerListModule.kt b/src/main/kotlin/top/r3944realms/ltdmanager/module/RconPlayerListModule.kt index f474eb0..08bc764 100644 --- a/src/main/kotlin/top/r3944realms/ltdmanager/module/RconPlayerListModule.kt +++ b/src/main/kotlin/top/r3944realms/ltdmanager/module/RconPlayerListModule.kt @@ -153,6 +153,11 @@ class RconPlayerListModule( LoggerUtil.logger.error("[$name] RCON 查询失败", ex) if (ex is TimeoutException) { sendFailedMessage(napCatClient, msg.realId, msg.time, "⏳ RCON 连接超时") + // ✅ 更新触发状态 & 持久化 + lastTriggerState.lastTriggeredRealId = msg.realId + lastTriggerState.lastTriggerTime = msg.time + saveState(lastTriggerState) + return } throw ex }.onSuccess { output -> diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/module/common/filter/type/KeywordFilter.kt b/src/main/kotlin/top/r3944realms/ltdmanager/module/common/filter/type/KeywordFilter.kt index c4690bd..a4a39c2 100644 --- a/src/main/kotlin/top/r3944realms/ltdmanager/module/common/filter/type/KeywordFilter.kt +++ b/src/main/kotlin/top/r3944realms/ltdmanager/module/common/filter/type/KeywordFilter.kt @@ -8,7 +8,9 @@ import top.r3944realms.ltdmanager.napcat.event.message.GetFriendMsgHistoryEvent class KeywordFilter(private val keywords: Set) : MessageFilter { override suspend fun test(msg: GetFriendMsgHistoryEvent.SpecificMsg): Boolean { return msg.message.any { seg -> - seg.type == MessageType.Text && seg.data.text?.let { it in keywords } == true + seg.type == MessageType.Text && seg.data.text?.let { text -> + keywords.any { keyword -> text.startsWith(keyword) } + } == true } } } \ No newline at end of file diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/module/common/filter/type/MultiCommandFilter.kt b/src/main/kotlin/top/r3944realms/ltdmanager/module/common/filter/type/MultiCommandFilter.kt new file mode 100644 index 0000000..c049489 --- /dev/null +++ b/src/main/kotlin/top/r3944realms/ltdmanager/module/common/filter/type/MultiCommandFilter.kt @@ -0,0 +1,17 @@ +package top.r3944realms.ltdmanager.module.common.filter.type + +import top.r3944realms.ltdmanager.module.common.CommandParser +import top.r3944realms.ltdmanager.module.common.filter.MessageFilter +import top.r3944realms.ltdmanager.napcat.data.MessageType +import top.r3944realms.ltdmanager.napcat.event.message.GetFriendMsgHistoryEvent + +/** 多命令解析器匹配 */ +class MultiCommandFilter(private val parsers: List) : MessageFilter { + override suspend fun test(msg: GetFriendMsgHistoryEvent.SpecificMsg): Boolean { + return msg.message.any { seg -> + seg.type == MessageType.Text && seg.data.text?.let { text -> + parsers.any { parser -> parser.containsCommand(text) } + } == true + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/r3944realms/ltdmanager/utils/QRCodeUtil.kt b/src/main/kotlin/top/r3944realms/ltdmanager/utils/QRCodeUtil.kt new file mode 100644 index 0000000..f77ee74 --- /dev/null +++ b/src/main/kotlin/top/r3944realms/ltdmanager/utils/QRCodeUtil.kt @@ -0,0 +1,60 @@ +package top.r3944realms.ltdmanager.utils + +import com.google.zxing.BarcodeFormat +import com.google.zxing.EncodeHintType +import com.google.zxing.MultiFormatWriter +import com.google.zxing.WriterException +import com.google.zxing.common.BitArray +import com.google.zxing.common.BitMatrix +import java.awt.image.BufferedImage +import java.io.ByteArrayInputStream +import java.io.ByteArrayOutputStream +import java.io.IOException +import java.io.InputStream +import java.util.* +import javax.imageio.ImageIO + +object QRCodeUtil { + private const val CHARSET = "utf-8" + private const val FORMAT = "png" + @Throws(IOException::class, WriterException::class) + fun generateQRCode(string: String?): InputStream { + return generateQRCode(string, 256, 256) + } + + @Throws(IOException::class, WriterException::class) + fun generateQRCode(text: String?, width: Int, height: Int): ByteArrayInputStream { + val hints: MutableMap = EnumMap(EncodeHintType::class.java) + hints[EncodeHintType.CHARACTER_SET] = CHARSET + + // 创建二维码编码器 + val bitMatrix: BitMatrix = + MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, width, height, hints) + + // 将BitMatrix转换为BufferedImage + val image = toBufferedImage(bitMatrix) + + val outputStream = ByteArrayOutputStream() + ImageIO.write(image, FORMAT, outputStream) + + return ByteArrayInputStream(outputStream.toByteArray()) // 返回 ByteArrayInputStream + } + + fun toBufferedImage(matrix: BitMatrix): BufferedImage { + val width: Int = matrix.width + val height: Int = matrix.height + val image = BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY) + val onColor = -0x1000000 + val offColor = -0x1 + val rowPixels = IntArray(width) + var row: BitArray = BitArray(width) + for (y in 0 until height) { + row = matrix.getRow(y, row) + for (x in 0 until width) { + rowPixels[x] = if (row.get(x)) onColor else offColor + } + image.setRGB(0, y, width, 1, rowPixels, 0, width) + } + return image + } +} \ No newline at end of file diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index c23e1b6..10c0551 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -42,4 +42,62 @@ blessing-skin-server: path: "/api/invitation-codes/generate" # 格式为 ENC(XXX),若不是则会在加载完成配置后自动加密 encrypted-token: "your-secret-token" - +dg-lab: + ws-server: + local-server-url: "0.0.0.0" + local-server-port: 4567 + local-server-publish-url: "ws://127.0.0.1:4567" + local-server-secure: false + local-server-ssl-cert: "config/cert.p12" + local-server-ssl-key: "config/key.p12" + encrypted-local-server-ssl-password: "ENC(xxxxx)" + dg-lab-client: + bind-timeout: 90.0 + register-timeout: 30.0 + pulse-data: + custom-pulse-data: "data/dg-lab-play/customPulseData.json" + duration-per-post: 8.0 + post-interval: 1.0 + sleep-after-clear: 0.5 + command-text: + append-pulse: "增加波形" + current-pulse: "当前波形" + current-strength: "当前强度" + decrease-strength: "减小强度" + dg-lab-device-join: "绑定郊狼" + exit-game: "退出游戏" + increase-strength: "加大强度" + random-pulse: "随机波形" + random-strength: "随机强度" + reset-pulse: "重置波形" + show-players: "当前玩家" + show-pulses: "可用波形" + usage: "郊狼玩法" + reply-text: + bind-timeout: "绑定超时" + current-players: "当前玩家:" + current-pulse: "当前波形循环为:【{}】" + current-strength: "A通道:{0}/{1} B通道:{2}/{3}" + failed-to-create-client: "创建 DG-Lab 控制终端失败" + failed-to-fetch-strength-info: "获取通道强度状态失败" + failed-to-fetch-strength-limit: "获取通道强度上限失败,控制失败" + game-exited: "已退出游戏" + invalid-pulse-param: "波形参数错误,控制失败" + invalid-strength-param: "强度参数错误,控制失败" + invalid-target: "目标玩家不存在或郊狼 App 未绑定" + no-available-pulse: "无可用波形" + no-player: "当前没有已连接的玩家,你可以绑定试试~" + not-bind-yet: "你目前没有绑定 DG-Lab App" + please-at-target: "使用命令的同时请 @ 想要控制的玩家" + please-scan-qrcode: "请用 DG-Lab App 扫描二维码以连接" + please-set-pulse-first: "请先设置郊狼波形:{}" + pulses-empty: "当前波形循环为空" + successfully-bind: "绑定成功,可以开始色色了!" + successfully-decreased: "郊狼强度减小了 {}%" + successfully-increased: "郊狼强度加强了 {}%!" + successfully-set-pulse: "郊狼波形成功设置为【{}】!" + successfully-set-to-strength: "郊狼强度成功设置为 {}%!" + debug: + enable-debug: false + ide-host: "127.0.0.1" + ide-port: 5678 diff --git a/src/test/kotlin/top/r394realms/ltdmanagertest/help/helpTest.kt b/src/test/kotlin/top/r394realms/ltdmanagertest/help/helpTest.kt index e2d368f..1c31bd3 100644 --- a/src/test/kotlin/top/r394realms/ltdmanagertest/help/helpTest.kt +++ b/src/test/kotlin/top/r394realms/ltdmanagertest/help/helpTest.kt @@ -1,7 +1,39 @@ package top.r394realms.ltdmanagertest.help import top.r3944realms.ltdmanager.GlobalManager +import top.r3944realms.ltdmanager.module.BanModule +import top.r3944realms.ltdmanager.module.GroupMessagePollingModule +import top.r3944realms.ltdmanager.module.HelpModule fun main() = GlobalManager.runBlockingMain { + val groupId:Long = 920719236 + val selfQQId = 3327379836 + val selfNickName = "闲趣老土豆" + // 创建模块实例 + val groupMsgPollingModule = GroupMessagePollingModule( + moduleName = "TestGroup", + targetGroupId = groupId, + pollIntervalMillis = 5_000L, + msgHistoryCheck = 15 + ) + val helpModule = HelpModule( + moduleName = "TestGroup", + groupMessagePollingModule = groupMsgPollingModule, + selfId = selfQQId, + selfNickName = selfNickName, + ) + val banModule = BanModule( + moduleName = "TestGroup", + groupMessagePollingModule = groupMsgPollingModule, + selfId = selfQQId, + adminsId = listOf(2561098830), + muteCommandPrefixList = listOf("禁言", "口球", "mute", "Mute", "闭嘴") + ) + GlobalManager.moduleManager.registerModule(groupMsgPollingModule) + GlobalManager.moduleManager.registerModule(helpModule) + GlobalManager.moduleManager.registerModule(banModule) + GlobalManager.moduleManager.loadModule(groupMsgPollingModule.name) + GlobalManager.moduleManager.loadModule(helpModule.name) + GlobalManager.moduleManager.loadModule(banModule.name) } \ No newline at end of file diff --git a/src/test/kotlin/top/r394realms/ltdmanagertest/mod/ModTest.kt b/src/test/kotlin/top/r394realms/ltdmanagertest/mod/ModTest.kt index 78b4075..2534075 100644 --- a/src/test/kotlin/top/r394realms/ltdmanagertest/mod/ModTest.kt +++ b/src/test/kotlin/top/r394realms/ltdmanagertest/mod/ModTest.kt @@ -1,7 +1,12 @@ package top.r394realms.ltdmanagertest.mod +import kotlinx.coroutines.delay import top.r3944realms.ltdmanager.GlobalManager +import top.r3944realms.ltdmanager.GlobalManager.napCatClient import top.r3944realms.ltdmanager.module.ModGroupHandlerModule +import top.r3944realms.ltdmanager.napcat.data.ID +import top.r3944realms.ltdmanager.napcat.data.MessageType +import top.r3944realms.ltdmanager.napcat.request.message.SendForwardMsgRequest fun main() = GlobalManager.runBlockingMain { @@ -22,4 +27,4 @@ fun main() = GlobalManager.runBlockingMain { // 加载模块 GlobalManager.moduleManager.loadModule(modGroupHandlerModule.name) -} \ No newline at end of file +} diff --git a/src/test/kotlin/top/r394realms/ltdmanagertest/msg/NapCatMsgTest.kt b/src/test/kotlin/top/r394realms/ltdmanagertest/msg/NapCatMsgTest.kt index fcb7a70..88191f8 100644 --- a/src/test/kotlin/top/r394realms/ltdmanagertest/msg/NapCatMsgTest.kt +++ b/src/test/kotlin/top/r394realms/ltdmanagertest/msg/NapCatMsgTest.kt @@ -1,51 +1,85 @@ package top.r394realms.ltdmanagertest.msg +import kotlinx.coroutines.delay import top.r3944realms.ltdmanager.GlobalManager +import top.r3944realms.ltdmanager.module.ModGroupHandlerModule import top.r3944realms.ltdmanager.napcat.NapCatClient import top.r3944realms.ltdmanager.napcat.data.ID -import top.r3944realms.ltdmanager.napcat.data.MessageElement -import top.r3944realms.ltdmanager.napcat.request.other.SendGroupMsgRequest +import top.r3944realms.ltdmanager.napcat.data.MessageType +import top.r3944realms.ltdmanager.napcat.request.message.SendForwardMsgRequest + fun main() = GlobalManager.runBlockingMain { val napCatClient = NapCatClient.create() - - // 生成9x9乘法表字符串 - val multiplicationTable = buildString { - for (i in 1..9) { - for (j in 1..i) { - append("$j×$i=${i * j}\t") - } - appendLine() // 换行 - } - } - - // 生成对齐检查字符 - val alignmentCheck = buildString { - appendLine("📏 对齐检查(每个数字占位):") - appendLine("1234567890") // 数字标尺 - appendLine("─".repeat(20)) // 分隔线 - - for (i in 1..9) { - for (j in 1..i) { - val product = i * j - val placeholder = "X".repeat("$j×$i=$product".length) - append("$placeholder\t") - } - appendLine() - } - } - - napCatClient.sendUnit( - SendGroupMsgRequest( - listOf( - MessageElement.at(ID.long(2561098830), "幸福亮亮"), - MessageElement.text("\n"), - MessageElement.text("9×9乘法表:\n"), - MessageElement.text(multiplicationTable), - MessageElement.text("\n────────────────────\n"), - MessageElement.text(alignmentCheck), - MessageElement.text("\n提问前,请看文档,不看文档就提问直接肘击(") - ), - ID.long(339340846) - ) + formatAndSendForwardMessage(napCatClient, 2561098830L, "幸福亮亮") +} +private suspend fun formatAndSendForwardMessage(napCatClient: NapCatClient ,userId: Long, requesterNick: String) { + // 虚拟数据 - 模拟有审核记录的情况 + val virtualRecord = ModGroupHandlerModule.RejectRecord( + userId = userId, + reason = mutableListOf( + "模组作者是张三", + "作者是李四", + "制作人是王五", + "我不知道", + "可能是赵六吧" + ), + rejectCount = 5 ) + + // 虚拟数据 - 模拟无审核记录的情况(注释掉下面这行来测试) + // val virtualRecord = null + + val record = virtualRecord + val content = """ + 📊 用户审核记录 + ────────────────── + 🔹 用户QQ号:${record.userId} + 🔹 尝试次数:${record.rejectCount} + 🔹 最终评分:${rate(record.rejectCount)} + + 📝 尝试答案: + ${"\n" + record.reason.joinToString("\n") { " • $it" }} + + ⚠️ 提示:请仔细阅读文档后再在群里提问,否则你会失去你的大脑🧠 + """.trimIndent() + + // 创建合并转发消息 + val forwardRequest = SendForwardMsgRequest( + groupId = ID.long(339340846), + messages = listOf( + SendForwardMsgRequest.TopForwardMsg( + data = SendForwardMsgRequest.MessageData( + content = listOf( + SendForwardMsgRequest.Message( + data = SendForwardMsgRequest.PurpleData( + text = content + ), + type = MessageType.Text + ) + ), + nickname = "审核系统", + userId = ID.long(0) // 系统ID + ), + type = MessageType.Text + ) + ), + news = listOf( + SendForwardMsgRequest.ForwardModelNews("用户审核记录详情") + ), + prompt = "📋 ${requesterNick}入群审核评分${rate(record.rejectCount ?: 0)}", + source = "审核系统", + summary = "点击查看用户 $requesterNick 的审核详情" + ) + + // 发送合并转发消息 + napCatClient.sendUnit(forwardRequest) +} + +private fun rate(count: Int): String = when (count) { + 0 -> "SSS" + 1 -> "A" + 2 -> "B" + 3 -> "C" + 4 -> "D" + else -> "F" } \ No newline at end of file