diff options
| author | Sho Sakuma <me@m1sk9.dev> | 2026-02-01 01:12:16 +0900 |
|---|---|---|
| committer | Sho Sakuma <me@m1sk9.dev> | 2026-02-01 01:12:16 +0900 |
| commit | 4793b23aaa6bdcbd24498e0af37c4ba0ba06f6dd (patch) | |
| tree | 6485ce8c545caab8537569283817ea258c481047 | |
| parent | 14dc6dc4d29b6612f1e5fda5ceda187bc1df9d4d (diff) | |
| download | LunaticChat-4793b23aaa6bdcbd24498e0af37c4ba0ba06f6dd.tar.gz LunaticChat-4793b23aaa6bdcbd24498e0af37c4ba0ba06f6dd.tar.bz2 LunaticChat-4793b23aaa6bdcbd24498e0af37c4ba0ba06f6dd.zip | |
feat: Add Velocity protocol
4 files changed, 193 insertions, 0 deletions
diff --git a/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/permission/LunaticChatPermissionNode.kt b/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/permission/LunaticChatPermissionNode.kt index 9b6c3c6..72b7246 100644 --- a/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/permission/LunaticChatPermissionNode.kt +++ b/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/permission/LunaticChatPermissionNode.kt @@ -47,6 +47,8 @@ sealed class LunaticChatPermissionNode( object ChatModeToggle : LunaticChatPermissionNode("lunaticchat.command.lc.chatmode.toggle") + object VelocityStatus : LunaticChatPermissionNode("lunaticchat.command.lcv.status") + object Spy : LunaticChatPermissionNode("lunaticchat.spy") object NoticeUpdate : LunaticChatPermissionNode("lunaticchat.noticeupdate") diff --git a/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/protocol/PluginMessage.kt b/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/protocol/PluginMessage.kt new file mode 100644 index 0000000..4f3a572 --- /dev/null +++ b/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/protocol/PluginMessage.kt @@ -0,0 +1,58 @@ +package dev.m1sk9.lunaticChat.engine.protocol + +import kotlinx.serialization.Serializable + +/** + * Plugin message definitions for Paper-Velocity communication + */ +sealed interface PluginMessage { + /** + * Handshake message (Paper → Velocity) + * + * @property pluginVersion Plugin version (e.g., "0.7.0") + * @property protocolMajor Protocol major version + * @property protocolMinor Protocol minor version + * @property protocolPatch Protocol patch version + */ + @Serializable + data class Handshake( + val pluginVersion: String, + val protocolMajor: Int, + val protocolMinor: Int, + val protocolPatch: Int, + ) : PluginMessage + + /** + * Handshake response message (Velocity → Paper) + * + * @property compatible true if compatible + * @property velocityVersion Velocity plugin version + * @property error Error message (when incompatible) + */ + @Serializable + data class HandshakeResponse( + val compatible: Boolean, + val velocityVersion: String, + val error: String? = null, + ) : PluginMessage + + /** + * Status request message (Paper → Velocity) + */ + @Serializable + data object StatusRequest : PluginMessage + + /** + * Status response message (Velocity → Paper) + * + * @property velocityVersion Velocity plugin version + * @property protocolVersion Protocol version + * @property online true if connection is active + */ + @Serializable + data class StatusResponse( + val velocityVersion: String, + val protocolVersion: String, + val online: Boolean, + ) : PluginMessage +} diff --git a/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/protocol/PluginMessageCodec.kt b/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/protocol/PluginMessageCodec.kt new file mode 100644 index 0000000..042a7dc --- /dev/null +++ b/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/protocol/PluginMessageCodec.kt @@ -0,0 +1,90 @@ +package dev.m1sk9.lunaticChat.engine.protocol + +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json +import java.io.ByteArrayInputStream +import java.io.ByteArrayOutputStream +import java.io.DataInputStream +import java.io.DataOutputStream + +/** + * Plugin message encoding/decoding + * + * Format: [subChannel: UTF][messageJson: UTF] + */ +object PluginMessageCodec { + private val json = Json { ignoreUnknownKeys = true } + + /** + * Sub-channel names + */ + object SubChannel { + const val HANDSHAKE = "handshake" + const val HANDSHAKE_RESPONSE = "handshake_response" + const val STATUS_REQUEST = "status_request" + const val STATUS_RESPONSE = "status_response" + } + + /** + * Encodes message + * + * @param message Message to encode + * @return Encoded byte array + */ + fun encode(message: PluginMessage): ByteArray { + val out = ByteArrayOutputStream() + val dataOut = DataOutputStream(out) + + val (subChannel, messageJson) = + when (message) { + is PluginMessage.Handshake -> { + SubChannel.HANDSHAKE to json.encodeToString(message) + } + is PluginMessage.HandshakeResponse -> { + SubChannel.HANDSHAKE_RESPONSE to json.encodeToString(message) + } + is PluginMessage.StatusRequest -> { + SubChannel.STATUS_REQUEST to "{}" + } + is PluginMessage.StatusResponse -> { + SubChannel.STATUS_RESPONSE to json.encodeToString(message) + } + } + + dataOut.writeUTF(subChannel) + dataOut.writeUTF(messageJson) + + return out.toByteArray() + } + + /** + * Decodes message + * + * @param data Byte array to decode + * @return Decoded message + * @throws IllegalArgumentException Invalid message format + */ + fun decode(data: ByteArray): PluginMessage { + val input = ByteArrayInputStream(data) + val dataIn = DataInputStream(input) + + val subChannel = dataIn.readUTF() + val messageJson = dataIn.readUTF() + + return when (subChannel) { + SubChannel.HANDSHAKE -> { + json.decodeFromString<PluginMessage.Handshake>(messageJson) + } + SubChannel.HANDSHAKE_RESPONSE -> { + json.decodeFromString<PluginMessage.HandshakeResponse>(messageJson) + } + SubChannel.STATUS_REQUEST -> { + PluginMessage.StatusRequest + } + SubChannel.STATUS_RESPONSE -> { + json.decodeFromString<PluginMessage.StatusResponse>(messageJson) + } + else -> throw IllegalArgumentException("Unknown sub-channel: $subChannel") + } + } +} diff --git a/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/protocol/ProtocolVersion.kt b/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/protocol/ProtocolVersion.kt new file mode 100644 index 0000000..a57d3a7 --- /dev/null +++ b/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/protocol/ProtocolVersion.kt @@ -0,0 +1,43 @@ +package dev.m1sk9.lunaticChat.engine.protocol + +/** + * LunaticChat protocol version definition + * + * Manages version of communication protocol between Paper and Velocity. + * MAJOR.MINOR must match; differences in PATCH are compatible. + */ +object ProtocolVersion { + const val MAJOR = 1 + const val MINOR = 0 + const val PATCH = 0 + + val version: String = "$MAJOR.$MINOR.$PATCH" + + /** + * Checks if specified protocol version is compatible + * + * @param major Major version + * @param minor Minor version + * @return true if MAJOR and MINOR match + */ + fun isCompatible( + major: Int, + minor: Int, + ): Boolean = MAJOR == major && MINOR == minor + + /** + * Checks compatibility from version string + * + * @param version Version string in "MAJOR.MINOR.PATCH" format + * @return true if compatible + */ + fun isCompatible(version: String): Boolean { + val parts = version.split(".") + if (parts.size != 3) return false + + val major = parts[0].toIntOrNull() ?: return false + val minor = parts[1].toIntOrNull() ?: return false + + return isCompatible(major, minor) + } +} |
