fix: 修复图片上传、郊狼模块
This commit is contained in:
parent
81e1237635
commit
a36c44a63e
|
|
@ -3,5 +3,5 @@ org.gradle.downloadSources=false
|
|||
org.gradle.parallel=true
|
||||
org.gradle.degree_of_parallelism=16
|
||||
project_group=top.r3944realms.ltdmanager
|
||||
project_version=1.16-SNAPSHOT
|
||||
dg_lab_version=4.4.14.18
|
||||
project_version=1.17-SNAPSHOT
|
||||
dg_lab_version=4.4.14.19
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import io.ktor.client.call.*
|
|||
import io.ktor.client.engine.cio.*
|
||||
import io.ktor.client.plugins.*
|
||||
import io.ktor.client.request.*
|
||||
import io.ktor.client.request.forms.*
|
||||
import io.ktor.http.*
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
|
|
@ -104,17 +105,62 @@ class CheveretoClient private constructor() :
|
|||
method = request.method()
|
||||
|
||||
|
||||
when (request) {
|
||||
is CheveretoUploadRequest -> {
|
||||
// 使用 multipart/form-data 格式上传文件
|
||||
setBody(MultiPartFormDataContent(
|
||||
formData {
|
||||
// API Key
|
||||
append("key", apiKey)
|
||||
|
||||
// 处理 source
|
||||
when (val source = request.source) {
|
||||
is CheveretoSource.ByteArraySource -> {
|
||||
LoggerUtil.logger.debug("上传文件: ${source.fileName}, 大小: ${source.bytes.size} bytes")
|
||||
|
||||
append("source", source.bytes, Headers.build {
|
||||
append(HttpHeaders.ContentType, "image/png")
|
||||
append(HttpHeaders.ContentDisposition, "form-data; name=\"source\"; filename=\"${source.fileName}\"")
|
||||
})
|
||||
}
|
||||
is CheveretoSource.UrlSource -> {
|
||||
append("source", source.url)
|
||||
}
|
||||
}
|
||||
|
||||
// 添加所有参数
|
||||
request.title?.let { append("title", it) }
|
||||
request.description?.let { append("description", it) }
|
||||
request.tags?.let { append("tags", it) }
|
||||
request.albumId?.let { append("album_id", it) }
|
||||
request.categoryId?.let { append("category_id", it) }
|
||||
request.width?.let { append("width", it.toString()) }
|
||||
request.expiration?.let { append("expiration", it) }
|
||||
request.nsfw?.let { append("nsfw", it.toString()) }
|
||||
append("format", request.format)
|
||||
request.useFileDate?.let { append("use_file_date", it.toString()) }
|
||||
}
|
||||
))
|
||||
|
||||
// 设置请求头
|
||||
headers {
|
||||
append(HttpHeaders.Accept, "application/json")
|
||||
append("X-API-Key", apiKey)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
// 其他请求使用 JSON 格式
|
||||
headers {
|
||||
request.headers().invoke(this)
|
||||
header("X-API-Key", apiKey)
|
||||
}
|
||||
|
||||
// 对于非GET请求,设置请求体
|
||||
if (request.method() != HttpMethod.Get) {
|
||||
setBody(request.toJSON())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
val responseText: String = response.body()
|
||||
|
||||
if (!Environment.isProduction()) {
|
||||
|
|
@ -173,7 +219,7 @@ class CheveretoClient private constructor() :
|
|||
maxRetries: Int = 3
|
||||
|
||||
): CheveretoResponse {
|
||||
upload(CheveretoUploadRequest(
|
||||
return upload(CheveretoUploadRequest(
|
||||
source = CheveretoSource.ByteArraySource(file.readBytes(), file.name),
|
||||
format = format,
|
||||
title = title,
|
||||
|
|
@ -186,7 +232,6 @@ class CheveretoClient private constructor() :
|
|||
nsfw = nsfw,
|
||||
useFileDate = useFileDate
|
||||
), priority, maxRetries).getRetResponse()
|
||||
throw Exception("Never Reach")
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -209,8 +254,24 @@ class CheveretoClient private constructor() :
|
|||
priority: Int = 5,
|
||||
maxRetries: Int = 3
|
||||
): CheveretoResponse {
|
||||
upload(CheveretoUploadRequest(
|
||||
source = CheveretoSource.ByteArraySource(inputStream.readBytes(), fileName),
|
||||
val bytes = if (inputStream.markSupported()) {
|
||||
inputStream.mark(Integer.MAX_VALUE)
|
||||
val b = inputStream.readBytes()
|
||||
inputStream.reset()
|
||||
b
|
||||
} else {
|
||||
// 如果不支持 mark,直接读取
|
||||
inputStream.readBytes()
|
||||
}
|
||||
|
||||
if (bytes.isEmpty()) {
|
||||
throw IllegalStateException("InputStream is empty for file: $fileName")
|
||||
}
|
||||
|
||||
LoggerUtil.logger.debug("Uploading ${bytes.size} bytes for $fileName")
|
||||
|
||||
return upload(CheveretoUploadRequest(
|
||||
source = CheveretoSource.ByteArraySource(bytes, fileName),
|
||||
format = format,
|
||||
title = title,
|
||||
description = description,
|
||||
|
|
@ -222,7 +283,6 @@ class CheveretoClient private constructor() :
|
|||
nsfw = nsfw,
|
||||
useFileDate = useFileDate
|
||||
), priority, maxRetries).getRetResponse()
|
||||
throw Exception("Never Reach")
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -243,7 +303,7 @@ class CheveretoClient private constructor() :
|
|||
priority: Int = 5,
|
||||
maxRetries: Int = 3
|
||||
): CheveretoResponse {
|
||||
upload(CheveretoUploadRequest(
|
||||
return upload(CheveretoUploadRequest(
|
||||
source = CheveretoSource.UrlSource(url),
|
||||
format = format,
|
||||
title = title,
|
||||
|
|
@ -256,7 +316,6 @@ class CheveretoClient private constructor() :
|
|||
nsfw = nsfw,
|
||||
useFileDate = useFileDate
|
||||
), priority, maxRetries).getRetResponse()
|
||||
throw Exception("Never Reach")
|
||||
}
|
||||
|
||||
suspend fun upload(
|
||||
|
|
|
|||
|
|
@ -19,7 +19,10 @@ data class CheveretoImage(
|
|||
val nsfw: Int,
|
||||
@SerialName("storage_mode")
|
||||
val storageMode: String,
|
||||
val md5: String,
|
||||
val checksum: String? = null,
|
||||
@SerialName("source_checksum")
|
||||
val sourceChecksum: String? = null,
|
||||
val md5: String? = null,
|
||||
@SerialName("source_md5")
|
||||
val sourceMd5: String? = null,
|
||||
@SerialName("original_filename")
|
||||
|
|
|
|||
|
|
@ -13,20 +13,17 @@ import top.r3944realms.ltdmanager.core.client.response.ResponseResult
|
|||
|
||||
@Serializable
|
||||
data class CheveretoUploadRequest(
|
||||
private val source: CheveretoSource,
|
||||
private val title: String? = null,
|
||||
private val description: String? = null,
|
||||
private val tags: String? = null,
|
||||
@SerialName("album_id")
|
||||
private val albumId: String? = null,
|
||||
@SerialName("category_id")
|
||||
private val categoryId: String? = null,
|
||||
private val width: Int? = null,
|
||||
private val expiration: String? = null,
|
||||
private val nsfw: Int? = null,
|
||||
private val format: String = "json",
|
||||
@SerialName("use_file_date")
|
||||
private val useFileDate: Int? = null
|
||||
val source: CheveretoSource,
|
||||
val title: String? = null,
|
||||
val description: String? = null,
|
||||
val tags: String? = null,
|
||||
@SerialName("album_id") val albumId: String? = null,
|
||||
@SerialName("category_id") val categoryId: String? = null,
|
||||
val width: Int? = null,
|
||||
val expiration: String? = null,
|
||||
val nsfw: Int? = null,
|
||||
val format: String = "json",
|
||||
@SerialName("use_file_date") val useFileDate: Int? = null
|
||||
) : CheveretoRequest() {
|
||||
override fun path(): String = "api/1/upload"
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import top.r3944realms.ltdmanager.utils.YamlUpdater
|
|||
|
||||
data class DgLabConfig(
|
||||
var wsServer: WsServerConfig = WsServerConfig(),
|
||||
var imgAlbumsId: String = "",
|
||||
var dgLabClient: DgLabClientConfig = DgLabClientConfig(),
|
||||
var pulseData: PulseDataConfig = PulseDataConfig(),
|
||||
var commandText: CommandTextConfig = CommandTextConfig(),
|
||||
|
|
|
|||
|
|
@ -160,14 +160,22 @@ data class ModuleConfig(
|
|||
fun float(paramName: String): Float = get<Float>(paramName)
|
||||
|
||||
// 可选值方法
|
||||
inline fun <reified T> getOrNull(paramName: String): T? =
|
||||
config[paramName] as? T ?: run {
|
||||
val value = config[paramName]
|
||||
if (value == null) null
|
||||
else if (value is T) value
|
||||
else null
|
||||
}
|
||||
inline fun <reified T> getOrNull(paramName: String): T? {
|
||||
val value = config[paramName] ?: return null
|
||||
|
||||
return when {
|
||||
value is T -> value
|
||||
T::class == Long::class && value is Int -> value.toLong() as T
|
||||
T::class == Long::class && value is String -> value.toLongOrNull() as? T
|
||||
T::class == Int::class && value is Long -> value.toInt() as T
|
||||
T::class == Int::class && value is String -> value.toIntOrNull() as? T
|
||||
T::class == String::class -> value.toString() as T
|
||||
T::class == Boolean::class && value is String -> value.toBoolean() as T
|
||||
T::class == Double::class && value is Number -> value.toDouble() as T
|
||||
T::class == Float::class && value is Number -> value.toFloat() as T
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
inline fun <reified T> getOrDefault(paramName: String, defaultValue: T): T =
|
||||
getOrNull<T>(paramName) ?: defaultValue
|
||||
|
||||
|
|
|
|||
|
|
@ -121,12 +121,12 @@ class DgLab {
|
|||
fun getClient(key: String): DGPBClientManager? {
|
||||
return clientManager?.getClient(key)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 & 创建 客户端管理类
|
||||
* 创建 客户端管理类
|
||||
*/
|
||||
fun getClientOrCreate(key: String, operation: ClientOperation): DGPBClientManager {
|
||||
val client = getClient(key)
|
||||
if (client == null) {
|
||||
fun createClient(key: String, operation: ClientOperation): DGPBClientManager {
|
||||
getClient(key)?.stop()
|
||||
val loadDgLabConfig = YamlConfigLoader.loadDgLabConfig()
|
||||
val boxWSClient = PowerBoxWSClient.Builder.getBuilder()
|
||||
.address(loadDgLabConfig.wsServer.localServerUrl)
|
||||
|
|
@ -143,9 +143,7 @@ class DgLab {
|
|||
val clientManager = DGPBClientManager(
|
||||
boxWSClient
|
||||
)
|
||||
this.clientManager?.addClient(key, clientManager)
|
||||
addClient(key, clientManager)
|
||||
return clientManager
|
||||
}
|
||||
return client
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,51 @@ class ClientManager(
|
|||
private val clients: MutableMap<String, DGPBClientManager> = mutableMapOf(),
|
||||
) : IManager<MutableMap<String, DGPBClientManager>> {
|
||||
|
||||
/**
|
||||
* 强度信息数据类
|
||||
*/
|
||||
data class ClientStrengthInfo(
|
||||
val aValue: Int,
|
||||
val aMax: Int,
|
||||
val bValue: Int,
|
||||
val bMax: Int,
|
||||
val timestamp: Long = System.currentTimeMillis()
|
||||
) {
|
||||
fun getAStrength(): Int = aValue
|
||||
fun getBStrength(): Int = bValue
|
||||
fun getAStrengthPercent(): Double = if (aMax > 0) (aValue.toDouble() / aMax) * 100 else 0.0
|
||||
fun getBStrengthPercent(): Double = if (bMax > 0) (bValue.toDouble() / bMax) * 100 else 0.0
|
||||
|
||||
override fun toString(): String {
|
||||
return "A: $aValue/$aMax (${String.format("%.1f", getAStrengthPercent())}%), B: $bValue/$bMax (${String.format("%.1f", getBStrengthPercent())}%)"
|
||||
}
|
||||
}
|
||||
|
||||
// 存储每个客户端的强度信息
|
||||
private val clientStrengths: MutableMap<String, ClientStrengthInfo> = mutableMapOf()
|
||||
|
||||
// 存储每个客户端最后更新时间
|
||||
private val lastUpdateTime: MutableMap<String, Long> = mutableMapOf()
|
||||
|
||||
/**
|
||||
* 获取客户端的强度信息
|
||||
* @param key 客户端标识
|
||||
* @return 强度信息,如果不存在则返回 null
|
||||
*/
|
||||
fun getClientStrength(key: String): ClientStrengthInfo? {
|
||||
return clientStrengths[key]
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新客户端的强度信息
|
||||
* @param key 客户端标识
|
||||
* @param strengthInfo 强度信息
|
||||
*/
|
||||
fun updateClientStrength(key: String, strengthInfo: ClientStrengthInfo) {
|
||||
clientStrengths[key] = strengthInfo
|
||||
lastUpdateTime[key] = System.currentTimeMillis()
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加单例客户端管理示例
|
||||
* @param key 唯一标识客户端管理的 key,比如 ID 或 name
|
||||
|
|
@ -19,6 +64,8 @@ class ClientManager(
|
|||
*/
|
||||
fun removeClient(key: String) {
|
||||
clients.remove(key)?.stop()
|
||||
clientStrengths.remove(key)
|
||||
lastUpdateTime.remove(key)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -40,6 +87,7 @@ class ClientManager(
|
|||
*/
|
||||
override fun stopAll() {
|
||||
clients.values.forEach { it.stop() }
|
||||
clients.clear()
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,16 +1,26 @@
|
|||
package top.r3944realms.ltdmanager.dglab.model.game
|
||||
|
||||
import com.r3944realms.dg_lab.api.dataType.PowerBoxMsgType
|
||||
import com.r3944realms.dg_lab.api.exception.NoMatchDataTypeException
|
||||
import com.r3944realms.dg_lab.api.message.IPowerBoxMsg
|
||||
import com.r3944realms.dg_lab.api.message.argType.ChangePolicy
|
||||
import com.r3944realms.dg_lab.api.operation.ClientOperation
|
||||
import com.r3944realms.dg_lab.api.websocket.message.MessageDirection
|
||||
import com.r3944realms.dg_lab.api.websocket.message.PowerBoxMessage
|
||||
import com.r3944realms.dg_lab.api.websocket.message.data.PowerBoxData
|
||||
import com.r3944realms.dg_lab.api.websocket.message.data.type.PowerBoxDataType
|
||||
import com.r3944realms.dg_lab.manager.DGPBClientManager
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import org.apache.logging.log4j.core.util.UuidUtil
|
||||
import top.r3944realms.ltdmanager.GlobalManager
|
||||
import top.r3944realms.ltdmanager.chevereto.response.FailedCheveretoResponse
|
||||
import top.r3944realms.ltdmanager.chevereto.response.v1.CheveretoUploadResponse
|
||||
import top.r3944realms.ltdmanager.core.config.DgLabConfig
|
||||
import top.r3944realms.ltdmanager.core.config.YamlConfigLoader
|
||||
import top.r3944realms.ltdmanager.dglab.DgLab
|
||||
import top.r3944realms.ltdmanager.dglab.manager.ClientManager
|
||||
import top.r3944realms.ltdmanager.napcat.NapCatClient
|
||||
import top.r3944realms.ltdmanager.napcat.data.ID
|
||||
import top.r3944realms.ltdmanager.napcat.data.MessageElement
|
||||
|
|
@ -19,6 +29,7 @@ import top.r3944realms.ltdmanager.napcat.request.other.SendPrivateMsgRequest
|
|||
import top.r3944realms.ltdmanager.utils.LoggerUtil
|
||||
import top.r3944realms.ltdmanager.utils.QRCodeUtil
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.util.UUID
|
||||
|
||||
|
||||
class GameClientOperation(
|
||||
|
|
@ -28,10 +39,11 @@ class GameClientOperation(
|
|||
private val playerId: Long
|
||||
) : ClientOperation {
|
||||
private val scope = CoroutineScope(Dispatchers.IO)
|
||||
private var qrcode:ByteArrayInputStream? = null;
|
||||
private var qrcode:ByteArrayInputStream? = null
|
||||
var clientSelf: DGPBClientManager? = null
|
||||
private var hasBinding = false
|
||||
private var bindingTimeoutJob: kotlinx.coroutines.Job? = null // 保存倒计时任务
|
||||
|
||||
override fun ClientStartingHandler() {
|
||||
LoggerUtil.logger.debug("Player $playerId is starting the client...")
|
||||
scope.launch {
|
||||
|
|
@ -124,12 +136,13 @@ class GameClientOperation(
|
|||
|
||||
scope.launch {
|
||||
// 上传二维码图片
|
||||
try {
|
||||
val response = GlobalManager.cheveretoClient.uploadStream(
|
||||
qrcode!!,
|
||||
"$playerId-Qrcode-${System.currentTimeMillis()}.png",
|
||||
"Qrcode-$playerId-${System.currentTimeMillis()}",
|
||||
"5min后将会自动删除",
|
||||
albumId = "BFx",
|
||||
albumId = YamlConfigLoader.loadDgLabConfig().imgAlbumsId,
|
||||
expiration = "PT5M"
|
||||
)
|
||||
if (response is CheveretoUploadResponse){
|
||||
|
|
@ -151,7 +164,20 @@ class GameClientOperation(
|
|||
ID.long(playerId)
|
||||
)
|
||||
)
|
||||
clientSelf?.stop()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
napCatClient.sendUnit(
|
||||
SendPrivateMsgRequest(
|
||||
listOf(
|
||||
MessageElement.text("无法上传图片,请联系管理员:${e.message}"),
|
||||
),
|
||||
ID.long(playerId)
|
||||
)
|
||||
)
|
||||
clientSelf?.stop()
|
||||
}
|
||||
|
||||
// 启动 60 秒倒计时任务
|
||||
bindingTimeoutJob = launch {
|
||||
kotlinx.coroutines.delay(60_000)
|
||||
|
|
@ -218,11 +244,35 @@ class GameClientOperation(
|
|||
// napCatClient.sendUnit(SendPrivateMsgRequest(listOf(MessageElement.text("连接断开, $p0")), ID.long(playerId)))
|
||||
// }
|
||||
when (p0?.commandType) {
|
||||
PowerBoxDataType.STRENGTH -> TODO()
|
||||
PowerBoxDataType.PULSE -> TODO()
|
||||
PowerBoxDataType.CLEAR -> TODO()
|
||||
PowerBoxDataType.FEEDBACK -> TODO()
|
||||
PowerBoxDataType.STRENGTH -> scope.launch {
|
||||
// val strengthInfo : IPowerBoxMsg.StrengthInfo
|
||||
//
|
||||
// strengthInfo = IPowerBoxMsg.StrengthInfo.read(
|
||||
// PowerBoxMessage.createPowerBoxMessage(
|
||||
// p0,
|
||||
// MessageDirection.of(
|
||||
// MessageDirection.DirectType.PLACEHOLDER_TO_PLACEHOLDER,
|
||||
// ROM_UUID,
|
||||
// ROM_UUID
|
||||
// )
|
||||
// )
|
||||
// )
|
||||
|
||||
// napCatClient.sendUnit(SendPrivateMsgRequest(listOf(MessageElement.text("强度信息:\n A:${strengthInfo.aValue}/${strengthInfo.aMax} \n B:${strengthInfo.bValue}/${strengthInfo.bMax}")), ID.long(playerId)))
|
||||
}
|
||||
PowerBoxDataType.PULSE -> scope.launch {
|
||||
|
||||
}
|
||||
PowerBoxDataType.CLEAR -> scope.launch {
|
||||
|
||||
}
|
||||
PowerBoxDataType.FEEDBACK -> scope.launch {
|
||||
|
||||
}
|
||||
else -> return
|
||||
}
|
||||
}
|
||||
companion object {
|
||||
val ROM_UUID = "00001101-0000-1000-8000-00805f9b34fb"
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,31 @@ import com.r3944realms.dg_lab.api.message.data.PulseWave
|
|||
import com.r3944realms.dg_lab.api.message.data.PulseWaveList
|
||||
|
||||
object DefaultPulseData {
|
||||
/**
|
||||
* 循环次数配置,可以根据需要调整
|
||||
*/
|
||||
private const val DEFAULT_CYCLES = 3
|
||||
|
||||
/**
|
||||
* 创建带循环的 PulseWaveList
|
||||
*/
|
||||
private fun createCyclicWaveList(
|
||||
baseSegments: List<Array<IntArray>>,
|
||||
cycles: Int = DEFAULT_CYCLES,
|
||||
name: String = ""
|
||||
): PulseWaveList {
|
||||
val list = PulseWaveList()
|
||||
list.name = name
|
||||
|
||||
repeat(cycles) {
|
||||
baseSegments.forEach { seg ->
|
||||
list.add(createWaveSegment(seg[0], seg[1]))
|
||||
}
|
||||
}
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
/**
|
||||
* 将频率转换为 Dg-Lab 格式
|
||||
*
|
||||
|
|
@ -77,12 +102,7 @@ object DefaultPulseData {
|
|||
arrayOf(intArrayOf(0, 0, 0, 0), intArrayOf(0, 0, 0, 0))
|
||||
)
|
||||
|
||||
// 转成 PulseWave 并加入列表
|
||||
for (seg in segments) {
|
||||
list.add(createWaveSegment(seg[0], seg[1]))
|
||||
}
|
||||
|
||||
list
|
||||
createCyclicWaveList(segments)
|
||||
}
|
||||
val Tide: PulseWaveList by lazy {
|
||||
val list = PulseWaveList()
|
||||
|
|
@ -100,8 +120,7 @@ object DefaultPulseData {
|
|||
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(createWaveSegment(it[0], it[1])) }
|
||||
list
|
||||
createCyclicWaveList(segments)
|
||||
}
|
||||
|
||||
val Combo: PulseWaveList by lazy {
|
||||
|
|
@ -117,8 +136,7 @@ object DefaultPulseData {
|
|||
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(createWaveSegment(it[0], it[1])) }
|
||||
list
|
||||
createCyclicWaveList(segments)
|
||||
}
|
||||
val FastPinch: PulseWaveList by lazy {
|
||||
val list = PulseWaveList()
|
||||
|
|
@ -128,8 +146,7 @@ object DefaultPulseData {
|
|||
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(createWaveSegment(it[0], it[1])) }
|
||||
list
|
||||
createCyclicWaveList(segments)
|
||||
}
|
||||
val PinchGradual: PulseWaveList by lazy {
|
||||
val list = PulseWaveList()
|
||||
|
|
@ -147,8 +164,7 @@ object DefaultPulseData {
|
|||
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(createWaveSegment(it[0], it[1])) }
|
||||
list
|
||||
createCyclicWaveList(segments)
|
||||
}
|
||||
|
||||
val Heartbeat: PulseWaveList by lazy {
|
||||
|
|
@ -172,8 +188,7 @@ object DefaultPulseData {
|
|||
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(createWaveSegment(it[0], it[1])) }
|
||||
list
|
||||
createCyclicWaveList(segments)
|
||||
}
|
||||
val Compress: PulseWaveList by lazy {
|
||||
val list = PulseWaveList()
|
||||
|
|
@ -201,8 +216,7 @@ object DefaultPulseData {
|
|||
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(createWaveSegment(it[0], it[1])) }
|
||||
list
|
||||
createCyclicWaveList(segments)
|
||||
}
|
||||
val RhythmStep: PulseWaveList by lazy {
|
||||
val list = PulseWaveList()
|
||||
|
|
@ -235,8 +249,7 @@ object DefaultPulseData {
|
|||
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(createWaveSegment(it[0], it[1])) }
|
||||
list
|
||||
createCyclicWaveList(segments)
|
||||
}
|
||||
|
||||
val GranularFriction: PulseWaveList by lazy {
|
||||
|
|
@ -248,8 +261,7 @@ object DefaultPulseData {
|
|||
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(createWaveSegment(it[0], it[1])) }
|
||||
list
|
||||
createCyclicWaveList(segments)
|
||||
}
|
||||
|
||||
val GradualBounce: PulseWaveList by lazy {
|
||||
|
|
@ -263,8 +275,7 @@ object DefaultPulseData {
|
|||
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(createWaveSegment(it[0], it[1])) }
|
||||
list
|
||||
createCyclicWaveList(segments)
|
||||
}
|
||||
val WaveRipple: PulseWaveList by lazy {
|
||||
val list = PulseWaveList()
|
||||
|
|
@ -278,8 +289,7 @@ object DefaultPulseData {
|
|||
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(createWaveSegment(it[0], it[1])) }
|
||||
list
|
||||
createCyclicWaveList(segments)
|
||||
}
|
||||
|
||||
val RainWash: PulseWaveList by lazy {
|
||||
|
|
@ -291,8 +301,7 @@ object DefaultPulseData {
|
|||
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(createWaveSegment(it[0], it[1])) }
|
||||
list
|
||||
createCyclicWaveList(segments)
|
||||
}
|
||||
|
||||
val SpeedHit: PulseWaveList by lazy {
|
||||
|
|
@ -305,8 +314,7 @@ object DefaultPulseData {
|
|||
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(createWaveSegment(it[0], it[1])) }
|
||||
list
|
||||
createCyclicWaveList(segments)
|
||||
}
|
||||
val SignalLight: PulseWaveList by lazy {
|
||||
val list = PulseWaveList()
|
||||
|
|
@ -317,8 +325,7 @@ object DefaultPulseData {
|
|||
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(createWaveSegment(it[0], it[1])) }
|
||||
list
|
||||
createCyclicWaveList(segments)
|
||||
}
|
||||
|
||||
val Tease1: PulseWaveList by lazy {
|
||||
|
|
@ -328,8 +335,7 @@ object DefaultPulseData {
|
|||
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(createWaveSegment(it[0], it[1])) }
|
||||
list
|
||||
createCyclicWaveList(segments)
|
||||
}
|
||||
|
||||
val Tease2: PulseWaveList by lazy {
|
||||
|
|
@ -339,7 +345,6 @@ object DefaultPulseData {
|
|||
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(createWaveSegment(it[0], it[1])) }
|
||||
list
|
||||
createCyclicWaveList(segments)
|
||||
}
|
||||
}
|
||||
|
|
@ -54,74 +54,296 @@ class DGLabModule(
|
|||
var dgLabManager: DgLab? = null
|
||||
private var scope: CoroutineScope? = null
|
||||
private var dglabCommandDispatcher: CommandDispatcher<Player> = CommandDispatcher<Player>().apply {
|
||||
/*
|
||||
dglab (命令头)
|
||||
│
|
||||
├── server (管理员)
|
||||
│ ├── start - 启动 DG-LAB 服务器
|
||||
│ ├── stop - 停止 DG-LAB 服务器
|
||||
│ └── clients
|
||||
│ └── stopAll - 停止所有客户端
|
||||
│
|
||||
├── client
|
||||
│ ├── start - 启动自己的客户端
|
||||
│ └── stop - 停止自己的客户端
|
||||
│
|
||||
├── strength
|
||||
│ ├── self - 对自己的操作
|
||||
│ │ ├── a
|
||||
│ │ │ ├── add <value> - A通道增加强度 (-200~200)
|
||||
│ │ │ └── set <value> - A通道设置强度 (0~200)
|
||||
│ │ ├── b
|
||||
│ │ │ ├── add <value> - B通道增加强度 (-200~200)
|
||||
│ │ │ └── set <value> - B通道设置强度 (0~200)
|
||||
│ │ └── ab
|
||||
│ │ ├── add <value> - 双通道增加强度 (-200~200)
|
||||
│ │ └── set <value> - 双通道设置强度 (0~200)
|
||||
│ │
|
||||
│ └── target - 对他人的操作
|
||||
│ └── <player> (QQ号)
|
||||
│ ├── a
|
||||
│ │ ├── add <value> - A通道增加强度 (-200~200)
|
||||
│ │ └── set <value> - A通道设置强度 (0~200)
|
||||
│ ├── b
|
||||
│ │ ├── add <value> - B通道增加强度 (-200~200)
|
||||
│ │ └── set <value> - B通道设置强度 (0~200)
|
||||
│ └── ab
|
||||
│ ├── add <value> - 双通道增加强度 (-200~200)
|
||||
│ └── set <value> - 双通道设置强度 (0~200)
|
||||
│
|
||||
├── pulse
|
||||
│ ├── self - 对自己的操作
|
||||
│ │ ├── a
|
||||
│ │ │ ├── clear - 清除A通道脉冲
|
||||
│ │ │ └── set <pulseName> <timer> - 设置A通道脉冲
|
||||
│ │ ├── b
|
||||
│ │ │ ├── clear - 清除B通道脉冲
|
||||
│ │ │ └── set <pulseName> <timer> - 设置B通道脉冲
|
||||
│ │ └── ab
|
||||
│ │ ├── clear - 清除双通道脉冲
|
||||
│ │ └── set <pulseName> <timer> - 设置双通道脉冲
|
||||
│ │
|
||||
│ └── target - 对他人的操作
|
||||
│ └── <player> (QQ号)
|
||||
│ ├── a
|
||||
│ │ ├── clear - 清除A通道脉冲
|
||||
│ │ └── set <pulseName> <timer> - 设置A通道脉冲
|
||||
│ ├── b
|
||||
│ │ ├── clear - 清除B通道脉冲
|
||||
│ │ └── set <pulseName> <timer> - 设置B通道脉冲
|
||||
│ └── ab
|
||||
│ ├── clear - 清除双通道脉冲
|
||||
│ └── set <pulseName> <timer> - 设置双通道脉冲
|
||||
│
|
||||
├── add - 快捷增加强度
|
||||
│ ├── a <value> - A通道增加强度
|
||||
│ ├── b <value> - B通道增加强度
|
||||
│ └── ab <value> - 双通道增加强度
|
||||
│
|
||||
├── set - 快捷设置强度
|
||||
│ ├── a <value> - A通道设置强度
|
||||
│ ├── b <value> - B通道设置强度
|
||||
│ └── ab <value> - 双通道设置强度
|
||||
│
|
||||
└── clear - 快捷清除脉冲
|
||||
├── a - 清除A通道脉冲
|
||||
├── b - 清除B通道脉冲
|
||||
└── ab - 清除双通道脉冲
|
||||
*/
|
||||
for (command in commandHead) register(
|
||||
literal<Player>(command)
|
||||
// ========== 服务器管理(管理员) ==========
|
||||
.then(literal<Player?>("server").requires { adminIds.contains(it.id) }
|
||||
.then(literal<Player?>("start").executes { startDgLab() })
|
||||
.then(literal<Player?>("stop").executes { stopDgLab() })
|
||||
.then(literal<Player?>("stopAllClient").executes { stopAllDgLabClient() })
|
||||
.then(literal<Player?>("clients")
|
||||
.then(literal<Player?>("stopAll").executes { stopAllDgLabClient() })
|
||||
)
|
||||
)
|
||||
|
||||
// ========== 客户端管理 ==========
|
||||
.then(literal<Player?>("client")
|
||||
.then(literal<Player?>("start").executes { startClient(it.source.id) })
|
||||
.then(literal<Player?>("stop").executes { stopClient(it.source.id) })
|
||||
)
|
||||
.then(literal<Player?>("strength")
|
||||
.then(argument<Player?, String>("channel", StringArgumentType.string())
|
||||
.then(literal<Player?>("add")
|
||||
.then(argument<Player?, Int>("value", IntegerArgumentType.integer(-200, 200))
|
||||
.executes { strengthAdd(it.source.id, StringArgumentType.getString(it, "channel"), IntegerArgumentType.getInteger(it, "value")) }
|
||||
)
|
||||
)
|
||||
.then(literal<Player?>("set")
|
||||
.then(argument<Player?, Int>("value", IntegerArgumentType.integer(0, 200))
|
||||
.executes { strengthSet(it.source.id, StringArgumentType.getString(it, "channel"), IntegerArgumentType.getInteger(it, "value")) }
|
||||
)
|
||||
)
|
||||
)
|
||||
.then(argument<Player?, Long>("player", LongArgumentType.longArg())
|
||||
.then(argument<Player?, String>("channel", StringArgumentType.string())
|
||||
.then(literal<Player?>("add")
|
||||
.then(argument<Player?, Int>("value", IntegerArgumentType.integer(-200, 200))
|
||||
.executes { strengthAdd(LongArgumentType.getLong(it, "player"), StringArgumentType.getString(it, "channel"), IntegerArgumentType.getInteger(it, "value")) }
|
||||
)
|
||||
)
|
||||
.then(literal<Player?>("set")
|
||||
.then(argument<Player?, Int>("value", IntegerArgumentType.integer(0, 200))
|
||||
.executes { strengthSet(LongArgumentType.getLong(it, "player"), StringArgumentType.getString(it, "channel"), IntegerArgumentType.getInteger(it, "value")) }
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
.then(literal<Player?>("pulse")
|
||||
.then(argument<Player?, String>("channel", StringArgumentType.string())
|
||||
.then(literal<Player?>("clear").executes { pulseClear(it.source.id, StringArgumentType.getString(it, "channel")) })
|
||||
.then(literal<Player?>("set")
|
||||
.then(argument<Player?, String>("pulseName", StringArgumentType.string())
|
||||
.then(argument<Player?, Int>("timer", IntegerArgumentType.integer(0, Int.MAX_VALUE))
|
||||
.executes { pulseSet(it.source.id, StringArgumentType.getString(it, "channel"), StringArgumentType.getString(it, "pulseName"), IntegerArgumentType.getInteger(it, "timer")) }
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
.then(argument<Player?, Long>("player", LongArgumentType.longArg())
|
||||
.then(argument<Player?, String>("channel", StringArgumentType.string())
|
||||
.then(literal<Player?>("clear").executes { pulseClear(LongArgumentType.getLong(it, "player"), StringArgumentType.getString(it, "channel")) })
|
||||
.then(literal<Player?>("set")
|
||||
.then(argument<Player?, String>("pulseName", StringArgumentType.string())
|
||||
.then(argument<Player?, Int>("timer", IntegerArgumentType.integer(0, Int.MAX_VALUE))
|
||||
.executes { pulseSet(LongArgumentType.getLong(it, "player"), StringArgumentType.getString(it, "channel"), StringArgumentType.getString(it, "pulseName"), IntegerArgumentType.getInteger(it, "timer")) }
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
// .then(literal<Player?>("info").executes {}
|
||||
// .then(argument<Player?, String>("player", StringArgumentType.string()).executes {})
|
||||
// )
|
||||
|
||||
// ========== 强度控制(统一结构) ==========
|
||||
.then(literal<Player?>("strength")
|
||||
// 对自己的操作
|
||||
.then(literal<Player?>("self")
|
||||
.then(literal<Player?>("a")
|
||||
.then(literal<Player?>("add")
|
||||
.then(argument<Player?, Int>("value", IntegerArgumentType.integer(-200, 200))
|
||||
.executes { strengthAdd(it.source.id, "a", IntegerArgumentType.getInteger(it, "value")) }
|
||||
)
|
||||
)
|
||||
.then(literal<Player?>("set")
|
||||
.then(argument<Player?, Int>("value", IntegerArgumentType.integer(0, 200))
|
||||
.executes { strengthSet(it.source.id, "a", IntegerArgumentType.getInteger(it, "value")) }
|
||||
)
|
||||
)
|
||||
)
|
||||
.then(literal<Player?>("b")
|
||||
.then(literal<Player?>("add")
|
||||
.then(argument<Player?, Int>("value", IntegerArgumentType.integer(-200, 200))
|
||||
.executes { strengthAdd(it.source.id, "b", IntegerArgumentType.getInteger(it, "value")) }
|
||||
)
|
||||
)
|
||||
.then(literal<Player?>("set")
|
||||
.then(argument<Player?, Int>("value", IntegerArgumentType.integer(0, 200))
|
||||
.executes { strengthSet(it.source.id, "b", IntegerArgumentType.getInteger(it, "value")) }
|
||||
)
|
||||
)
|
||||
)
|
||||
.then(literal<Player?>("ab")
|
||||
.then(literal<Player?>("add")
|
||||
.then(argument<Player?, Int>("value", IntegerArgumentType.integer(-200, 200))
|
||||
.executes { strengthAdd(it.source.id, "ab", IntegerArgumentType.getInteger(it, "value")) }
|
||||
)
|
||||
)
|
||||
.then(literal<Player?>("set")
|
||||
.then(argument<Player?, Int>("value", IntegerArgumentType.integer(0, 200))
|
||||
.executes { strengthSet(it.source.id, "ab", IntegerArgumentType.getInteger(it, "value")) }
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
// 对他人的操作
|
||||
.then(literal<Player?>("target")
|
||||
.then(argument<Player?, Long>("player", LongArgumentType.longArg())
|
||||
.then(literal<Player?>("a")
|
||||
.then(literal<Player?>("add")
|
||||
.then(argument<Player?, Int>("value", IntegerArgumentType.integer(-200, 200))
|
||||
.executes { strengthAdd(LongArgumentType.getLong(it, "player"), "a", IntegerArgumentType.getInteger(it, "value")) }
|
||||
)
|
||||
)
|
||||
.then(literal<Player?>("set")
|
||||
.then(argument<Player?, Int>("value", IntegerArgumentType.integer(0, 200))
|
||||
.executes { strengthSet(LongArgumentType.getLong(it, "player"), "a", IntegerArgumentType.getInteger(it, "value")) }
|
||||
)
|
||||
)
|
||||
)
|
||||
.then(literal<Player?>("b")
|
||||
.then(literal<Player?>("add")
|
||||
.then(argument<Player?, Int>("value", IntegerArgumentType.integer(-200, 200))
|
||||
.executes { strengthAdd(LongArgumentType.getLong(it, "player"), "b", IntegerArgumentType.getInteger(it, "value")) }
|
||||
)
|
||||
)
|
||||
.then(literal<Player?>("set")
|
||||
.then(argument<Player?, Int>("value", IntegerArgumentType.integer(0, 200))
|
||||
.executes { strengthSet(LongArgumentType.getLong(it, "player"), "b", IntegerArgumentType.getInteger(it, "value")) }
|
||||
)
|
||||
)
|
||||
)
|
||||
.then(literal<Player?>("ab")
|
||||
.then(literal<Player?>("add")
|
||||
.then(argument<Player?, Int>("value", IntegerArgumentType.integer(-200, 200))
|
||||
.executes { strengthAdd(LongArgumentType.getLong(it, "player"), "ab", IntegerArgumentType.getInteger(it, "value")) }
|
||||
)
|
||||
)
|
||||
.then(literal<Player?>("set")
|
||||
.then(argument<Player?, Int>("value", IntegerArgumentType.integer(0, 200))
|
||||
.executes { strengthSet(LongArgumentType.getLong(it, "player"), "ab", IntegerArgumentType.getInteger(it, "value")) }
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
// ========== 脉冲控制(统一结构) ==========
|
||||
.then(literal<Player?>("pulse")
|
||||
// 对自己的操作
|
||||
.then(literal<Player?>("self")
|
||||
.then(literal<Player?>("a")
|
||||
.then(literal<Player?>("clear").executes { pulseClear(it.source.id, "a") })
|
||||
.then(literal<Player?>("set")
|
||||
.then(argument<Player?, String>("pulseName", StringArgumentType.string())
|
||||
.then(argument<Player?, Int>("timer", IntegerArgumentType.integer(0, Int.MAX_VALUE))
|
||||
.executes { pulseSet(it.source.id, "a", StringArgumentType.getString(it, "pulseName"), IntegerArgumentType.getInteger(it, "timer")) }
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
.then(literal<Player?>("b")
|
||||
.then(literal<Player?>("clear").executes { pulseClear(it.source.id, "b") })
|
||||
.then(literal<Player?>("set")
|
||||
.then(argument<Player?, String>("pulseName", StringArgumentType.string())
|
||||
.then(argument<Player?, Int>("timer", IntegerArgumentType.integer(0, Int.MAX_VALUE))
|
||||
.executes { pulseSet(it.source.id, "b", StringArgumentType.getString(it, "pulseName"), IntegerArgumentType.getInteger(it, "timer")) }
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
.then(literal<Player?>("ab")
|
||||
.then(literal<Player?>("clear").executes { pulseClear(it.source.id, "ab") })
|
||||
.then(literal<Player?>("set")
|
||||
.then(argument<Player?, String>("pulseName", StringArgumentType.string())
|
||||
.then(argument<Player?, Int>("timer", IntegerArgumentType.integer(0, Int.MAX_VALUE))
|
||||
.executes { pulseSet(it.source.id, "ab", StringArgumentType.getString(it, "pulseName"), IntegerArgumentType.getInteger(it, "timer")) }
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
// 对他人的操作
|
||||
.then(literal<Player?>("target")
|
||||
.then(argument<Player?, Long>("player", LongArgumentType.longArg())
|
||||
.then(literal<Player?>("a")
|
||||
.then(literal<Player?>("clear").executes { pulseClear(LongArgumentType.getLong(it, "player"), "a") })
|
||||
.then(literal<Player?>("set")
|
||||
.then(argument<Player?, String>("pulseName", StringArgumentType.string())
|
||||
.then(argument<Player?, Int>("timer", IntegerArgumentType.integer(0, Int.MAX_VALUE))
|
||||
.executes { pulseSet(LongArgumentType.getLong(it, "player"), "a", StringArgumentType.getString(it, "pulseName"), IntegerArgumentType.getInteger(it, "timer")) }
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
.then(literal<Player?>("b")
|
||||
.then(literal<Player?>("clear").executes { pulseClear(LongArgumentType.getLong(it, "player"), "b") })
|
||||
.then(literal<Player?>("set")
|
||||
.then(argument<Player?, String>("pulseName", StringArgumentType.string())
|
||||
.then(argument<Player?, Int>("timer", IntegerArgumentType.integer(0, Int.MAX_VALUE))
|
||||
.executes { pulseSet(LongArgumentType.getLong(it, "player"), "b", StringArgumentType.getString(it, "pulseName"), IntegerArgumentType.getInteger(it, "timer")) }
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
.then(literal<Player?>("ab")
|
||||
.then(literal<Player?>("clear").executes { pulseClear(LongArgumentType.getLong(it, "player"), "ab") })
|
||||
.then(literal<Player?>("set")
|
||||
.then(argument<Player?, String>("pulseName", StringArgumentType.string())
|
||||
.then(argument<Player?, Int>("timer", IntegerArgumentType.integer(0, Int.MAX_VALUE))
|
||||
.executes { pulseSet(LongArgumentType.getLong(it, "player"), "ab", StringArgumentType.getString(it, "pulseName"), IntegerArgumentType.getInteger(it, "timer")) }
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
// ========== 快捷操作(简化版) ==========
|
||||
.then(literal<Player?>("add")
|
||||
.then(literal<Player?>("a")
|
||||
.then(argument<Player?, Int>("value", IntegerArgumentType.integer(-200, 200))
|
||||
.executes { strengthAdd(it.source.id, "a", IntegerArgumentType.getInteger(it, "value")) }
|
||||
)
|
||||
)
|
||||
.then(literal<Player?>("b")
|
||||
.then(argument<Player?, Int>("value", IntegerArgumentType.integer(-200, 200))
|
||||
.executes { strengthAdd(it.source.id, "b", IntegerArgumentType.getInteger(it, "value")) }
|
||||
)
|
||||
)
|
||||
.then(literal<Player?>("ab")
|
||||
.then(argument<Player?, Int>("value", IntegerArgumentType.integer(-200, 200))
|
||||
.executes { strengthAdd(it.source.id, "ab", IntegerArgumentType.getInteger(it, "value")) }
|
||||
)
|
||||
)
|
||||
)
|
||||
.then(literal<Player?>("set")
|
||||
.then(literal<Player?>("a")
|
||||
.then(argument<Player?, Int>("value", IntegerArgumentType.integer(0, 200))
|
||||
.executes { strengthSet(it.source.id, "a", IntegerArgumentType.getInteger(it, "value")) }
|
||||
)
|
||||
)
|
||||
.then(literal<Player?>("b")
|
||||
.then(argument<Player?, Int>("value", IntegerArgumentType.integer(0, 200))
|
||||
.executes { strengthSet(it.source.id, "b", IntegerArgumentType.getInteger(it, "value")) }
|
||||
)
|
||||
)
|
||||
.then(literal<Player?>("ab")
|
||||
.then(argument<Player?, Int>("value", IntegerArgumentType.integer(0, 200))
|
||||
.executes { strengthSet(it.source.id, "ab", IntegerArgumentType.getInteger(it, "value")) }
|
||||
)
|
||||
)
|
||||
)
|
||||
.then(literal<Player?>("clear")
|
||||
.then(literal<Player?>("a").executes { pulseClear(it.source.id, "a") })
|
||||
.then(literal<Player?>("b").executes { pulseClear(it.source.id, "b") })
|
||||
.then(literal<Player?>("ab").executes { pulseClear(it.source.id, "ab") })
|
||||
)
|
||||
)
|
||||
}
|
||||
private val stateFile: File = getStateFileInternal("dg_lab_state.json", name)
|
||||
private val stateBackupFile: File = getStateFileInternal("dg_lab_state.json.bak", name)
|
||||
|
|
@ -184,11 +406,22 @@ class DGLabModule(
|
|||
triggerMsgs.forEach { (msg, userId, processedText) ->
|
||||
refMsg = msg
|
||||
LoggerUtil.logger.info("[$name] 原始消息用户: $userId")
|
||||
LoggerUtil.logger.info("[$name] 处理后的命令: $processedText")
|
||||
var result = processedText.replace(Regex("\\s+"), " ")
|
||||
result = result.replace("“", "\"")
|
||||
.replace("”", "\"")
|
||||
.replace("‘", "'")
|
||||
.replace("’", "'")
|
||||
.replace("『", "\"")
|
||||
.replace("』", "\"")
|
||||
.replace("【", "[")
|
||||
.replace("】", "]")
|
||||
.replace("(", "(")
|
||||
.replace(")", ")")
|
||||
LoggerUtil.logger.info("[$name] 处理后的命令: $result")
|
||||
|
||||
refPlayer = dgLabManager?.getPlayerManager()?.getPlayer(userId)
|
||||
dgLabState = dgLabState.updateOrCreate(userId, msg.realId, msg.time)
|
||||
val execute = dglabCommandDispatcher.execute(processedText, refPlayer)
|
||||
val execute = dglabCommandDispatcher.execute(result, refPlayer)
|
||||
scope?.launch {
|
||||
GlobalManager.napCatClient.sendUnit(
|
||||
SetMsgEmojiLikeRequest(
|
||||
|
|
@ -300,7 +533,7 @@ class DGLabModule(
|
|||
dgLabManager!!.getPlayerManager(),
|
||||
qq
|
||||
)
|
||||
val dgpbClientManager = dgLabManager?.getClientOrCreate(
|
||||
val dgpbClientManager = dgLabManager?.createClient(
|
||||
qq.toString(),
|
||||
operation
|
||||
)
|
||||
|
|
@ -310,7 +543,7 @@ class DGLabModule(
|
|||
return 1
|
||||
}
|
||||
private fun stopClient(qq: Long): Int {
|
||||
dgLabManager?.getClient(qq.toString())?.stop()
|
||||
dgLabManager?.removeClient(qq.toString())
|
||||
return 1
|
||||
}
|
||||
private fun strengthAdd(qq: Long, channel: String, value: Int): Int {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,165 @@
|
|||
package top.r394realms.ltdmanagertest
|
||||
|
||||
import kotlin.random.Random
|
||||
|
||||
fun main() {
|
||||
for(item in 1..100){
|
||||
println(Random.nextInt(100))
|
||||
val startTime = System.currentTimeMillis()
|
||||
|
||||
// 生成1~9的所有排列并检查是否是幻方
|
||||
val numbers = arrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9)
|
||||
val magicSquares = mutableListOf<Array<Array<Int>>>()
|
||||
val used = BooleanArray(9)
|
||||
val current = Array(3) { Array(3) { 0 } }
|
||||
|
||||
fun backtrack(index: Int) {
|
||||
if (index == 9) {
|
||||
if (isMagicSquare(current)) {
|
||||
// 深拷贝当前矩阵
|
||||
val copy = Array(3) { i -> Array(3) { j -> current[i][j] } }
|
||||
magicSquares.add(copy)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
for (i in numbers.indices) {
|
||||
if (!used[i]) {
|
||||
used[i] = true
|
||||
current[index / 3][index % 3] = numbers[i]
|
||||
backtrack(index + 1)
|
||||
used[i] = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
backtrack(0)
|
||||
|
||||
// 去重(排除旋转和镜像对称的重复解)
|
||||
val uniqueSquares = removeDuplicates(magicSquares)
|
||||
|
||||
println("找到 ${uniqueSquares.size} 个独特的3阶幻方:")
|
||||
println("=".repeat(30))
|
||||
|
||||
uniqueSquares.forEachIndexed { idx, square ->
|
||||
println("幻方 ${idx + 1}:")
|
||||
printMagicSquare(square)
|
||||
println("-".repeat(20))
|
||||
}
|
||||
|
||||
val endTime = System.currentTimeMillis()
|
||||
println("总排列数: ${factorial(9)}")
|
||||
println("有效幻方数: ${magicSquares.size}")
|
||||
println("独特幻方数: ${uniqueSquares.size}")
|
||||
println("运行时间: ${endTime - startTime}ms")
|
||||
}
|
||||
|
||||
fun isMagicSquare(square: Array<Array<Int>>): Boolean {
|
||||
// 检查所有行、列、对角线之和是否为15
|
||||
return (square[0][0] + square[0][1] + square[0][2] == 15) &&
|
||||
(square[1][0] + square[1][1] + square[1][2] == 15) &&
|
||||
(square[2][0] + square[2][1] + square[2][2] == 15) &&
|
||||
|
||||
(square[0][0] + square[1][0] + square[2][0] == 15) &&
|
||||
(square[0][1] + square[1][1] + square[2][1] == 15) &&
|
||||
(square[0][2] + square[1][2] + square[2][2] == 15) &&
|
||||
|
||||
(square[0][0] + square[1][1] + square[2][2] == 15) &&
|
||||
(square[0][2] + square[1][1] + square[2][0] == 15)
|
||||
}
|
||||
|
||||
fun removeDuplicates(squares: List<Array<Array<Int>>>): List<Array<Array<Int>>> {
|
||||
val unique = mutableListOf<Array<Array<Int>>>()
|
||||
val seen = mutableSetOf<String>()
|
||||
|
||||
for (square in squares) {
|
||||
// 获取所有旋转和镜像变换
|
||||
val transformations = getAllTransformations(square)
|
||||
var isNew = true
|
||||
|
||||
for (transform in transformations) {
|
||||
val key = transformToString(transform)
|
||||
if (key in seen) {
|
||||
isNew = false
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (isNew) {
|
||||
val key = transformToString(square)
|
||||
seen.add(key)
|
||||
unique.add(square)
|
||||
}
|
||||
}
|
||||
|
||||
return unique
|
||||
}
|
||||
|
||||
fun getAllTransformations(square: Array<Array<Int>>): List<Array<Array<Int>>> {
|
||||
val transformations = mutableListOf<Array<Array<Int>>>()
|
||||
var current = square
|
||||
|
||||
// 4个旋转方向
|
||||
repeat(4) {
|
||||
transformations.add(current)
|
||||
// 添加镜像
|
||||
transformations.add(mirrorHorizontal(current))
|
||||
transformations.add(mirrorVertical(current))
|
||||
transformations.add(mirrorDiagonal(current))
|
||||
|
||||
current = rotate90(current)
|
||||
}
|
||||
|
||||
return transformations.distinctBy { transformToString(it) }
|
||||
}
|
||||
|
||||
fun rotate90(square: Array<Array<Int>>): Array<Array<Int>> {
|
||||
val result = Array(3) { Array(3) { 0 } }
|
||||
for (i in 0..2) {
|
||||
for (j in 0..2) {
|
||||
result[j][2 - i] = square[i][j]
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fun mirrorHorizontal(square: Array<Array<Int>>): Array<Array<Int>> {
|
||||
val result = Array(3) { Array(3) { 0 } }
|
||||
for (i in 0..2) {
|
||||
for (j in 0..2) {
|
||||
result[i][2 - j] = square[i][j]
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fun mirrorVertical(square: Array<Array<Int>>): Array<Array<Int>> {
|
||||
val result = Array(3) { Array(3) { 0 } }
|
||||
for (i in 0..2) {
|
||||
for (j in 0..2) {
|
||||
result[2 - i][j] = square[i][j]
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fun mirrorDiagonal(square: Array<Array<Int>>): Array<Array<Int>> {
|
||||
val result = Array(3) { Array(3) { 0 } }
|
||||
for (i in 0..2) {
|
||||
for (j in 0..2) {
|
||||
result[j][i] = square[i][j]
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fun transformToString(square: Array<Array<Int>>): String {
|
||||
return square.joinToString("") { row -> row.joinToString("") }
|
||||
}
|
||||
|
||||
fun printMagicSquare(square: Array<Array<Int>>) {
|
||||
for (row in square) {
|
||||
println(row.joinToString(" ") { "%d".format(it) })
|
||||
}
|
||||
}
|
||||
|
||||
fun factorial(n: Long): Long {
|
||||
return if (n <= 1) 1
|
||||
else n * factorial(n - 1)
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user