summaryrefslogtreecommitdiff
path: root/platform-paper
diff options
context:
space:
mode:
authorSho Sakuma <me@m1sk9.dev>2026-02-07 16:56:41 +0900
committerSho Sakuma <me@m1sk9.dev>2026-02-07 16:56:55 +0900
commit76198199c24b0d1d31d0dfa74825d1ea0cdfb097 (patch)
tree112c6c20abd69af5c3e6d669419d8d2045044fbb /platform-paper
parent40c9d18e4747e23977618e17bafcd64cd0ffa6b4 (diff)
downloadLunaticChat-76198199c24b0d1d31d0dfa74825d1ea0cdfb097.tar.gz
LunaticChat-76198199c24b0d1d31d0dfa74825d1ea0cdfb097.tar.bz2
LunaticChat-76198199c24b0d1d31d0dfa74825d1ea0cdfb097.zip
fix: Fix copilot review
Diffstat (limited to 'platform-paper')
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lcv/VelocityStatusCommand.kt79
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/EventListenerRegistry.kt1
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/PlayerChatListener.kt63
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/velocity/CrossServerChatManager.kt63
-rw-r--r--platform-paper/src/main/resources/languages/en.yml1
-rw-r--r--platform-paper/src/main/resources/languages/ja.yml1
6 files changed, 115 insertions, 93 deletions
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lcv/VelocityStatusCommand.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lcv/VelocityStatusCommand.kt
index a535314..a4fb838 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lcv/VelocityStatusCommand.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lcv/VelocityStatusCommand.kt
@@ -11,6 +11,7 @@ import dev.m1sk9.lunaticChat.paper.command.annotation.PlayerOnly
import dev.m1sk9.lunaticChat.paper.command.core.CommandContext
import dev.m1sk9.lunaticChat.paper.command.core.LunaticCommand
import dev.m1sk9.lunaticChat.paper.i18n.LanguageManager
+import dev.m1sk9.lunaticChat.paper.i18n.MessageFormatter
import dev.m1sk9.lunaticChat.paper.velocity.VelocityConnectionManager
import io.papermc.paper.command.brigadier.CommandSourceStack
import io.papermc.paper.command.brigadier.Commands
@@ -56,22 +57,6 @@ class VelocityStatusCommand(
val sender = ctx.requirePlayer()
val meta = plugin.pluginMeta
- // Paper plugin version
- sender.sendMessage(
- languageManager.getMessage(
- "velocity.status.paperVersion",
- mapOf("version" to meta.version),
- ),
- )
-
- // Protocol version
- sender.sendMessage(
- languageManager.getMessage(
- "velocity.status.protocolVersion",
- mapOf("version" to ProtocolVersion.version),
- ),
- )
-
// Connection state
val state = velocityConnectionManager.getState()
val stateMessage =
@@ -90,20 +75,44 @@ class VelocityStatusCommand(
}
}
+ // Header
+ sender.sendMessage(
+ MessageFormatter.format(
+ languageManager.getMessage("velocity.status.header"),
+ ),
+ )
+
+ // Paper plugin version
+ sender.sendMessage(
+ Component
+ .text(" • ", NamedTextColor.GRAY)
+ .append(Component.text("Paper Version: ", NamedTextColor.GRAY))
+ .append(Component.text(meta.version, NamedTextColor.AQUA)),
+ )
+
+ // Protocol version
+ sender.sendMessage(
+ Component
+ .text(" • ", NamedTextColor.GRAY)
+ .append(Component.text("Protocol Version: ", NamedTextColor.GRAY))
+ .append(Component.text(ProtocolVersion.version, NamedTextColor.AQUA)),
+ )
+
+ // Connection state
sender.sendMessage(
Component
- .text(languageManager.getMessage("velocity.status.connectionState"))
- .append(Component.text(": "))
+ .text(" • ", NamedTextColor.GRAY)
+ .append(Component.text("Connection State: ", NamedTextColor.GRAY))
.append(stateMessage),
)
// Velocity version (if connected)
velocityConnectionManager.getVelocityVersion()?.let { velocityVersion ->
sender.sendMessage(
- languageManager.getMessage(
- "velocity.status.velocityVersion",
- mapOf("version" to velocityVersion),
- ),
+ Component
+ .text(" • ", NamedTextColor.GRAY)
+ .append(Component.text("Velocity Version: ", NamedTextColor.GRAY))
+ .append(Component.text(velocityVersion, NamedTextColor.AQUA)),
)
}
@@ -111,8 +120,8 @@ class VelocityStatusCommand(
velocityConnectionManager.getLastError()?.let { error ->
sender.sendMessage(
Component
- .text(languageManager.getMessage("velocity.status.error"))
- .append(Component.text(": ", NamedTextColor.RED))
+ .text(" • ", NamedTextColor.GRAY)
+ .append(Component.text("Error: ", NamedTextColor.GRAY))
.append(Component.text(error, NamedTextColor.RED)),
)
}
@@ -120,28 +129,26 @@ class VelocityStatusCommand(
// Live status check (if connected)
if (state == VelocityConnectionManager.ConnectionState.CONNECTED) {
sender.sendMessage(
- languageManager.getMessage("velocity.status.checkingLiveStatus"),
+ Component
+ .text(" • ", NamedTextColor.GRAY)
+ .append(Component.text("Checking live status...", NamedTextColor.YELLOW)),
)
velocityConnectionManager
.requestStatus(sender)
.thenAccept { response ->
sender.sendMessage(
- languageManager.getMessage(
- "velocity.status.liveStatusSuccess",
- mapOf(
- "version" to response.velocityVersion,
- "protocol" to response.protocolVersion,
- "online" to response.online.toString(),
- ),
- ),
+ Component
+ .text(" ✓ ", NamedTextColor.GREEN)
+ .append(Component.text("Online Players: ", NamedTextColor.GRAY))
+ .append(Component.text(response.online.toString(), NamedTextColor.YELLOW)),
)
}.exceptionally { throwable ->
sender.sendMessage(
Component
- .text(languageManager.getMessage("velocity.status.liveStatusFailed"))
- .color(NamedTextColor.RED)
- .append(Component.text(": ${throwable.message}", NamedTextColor.RED)),
+ .text(" ✗ ", NamedTextColor.RED)
+ .append(Component.text("Live status check failed: ", NamedTextColor.GRAY))
+ .append(Component.text(throwable.message ?: "Unknown error", NamedTextColor.RED)),
)
null
}
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/EventListenerRegistry.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/EventListenerRegistry.kt
index b9999bc..2bdca37 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/EventListenerRegistry.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/EventListenerRegistry.kt
@@ -65,7 +65,6 @@ object EventListenerRegistry {
channelMessageHandler = services.channelMessageHandler,
romajiConverter = services.romajiConverter,
settingsManager = services.playerSettingsManager,
- languageManager = services.languageManager,
configuration = configuration,
crossServerChatManager = services.crossServerChatManager,
),
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/PlayerChatListener.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/PlayerChatListener.kt
index c17dba2..4df4889 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/PlayerChatListener.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/PlayerChatListener.kt
@@ -6,14 +6,12 @@ import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelManager
import dev.m1sk9.lunaticChat.paper.chat.handler.ChannelMessageHandler
import dev.m1sk9.lunaticChat.paper.config.LunaticChatConfiguration
import dev.m1sk9.lunaticChat.paper.converter.RomanjiConverter
-import dev.m1sk9.lunaticChat.paper.i18n.LanguageManager
import dev.m1sk9.lunaticChat.paper.settings.PlayerSettingsManager
import dev.m1sk9.lunaticChat.paper.velocity.CrossServerChatManager
import io.papermc.paper.event.player.AsyncChatEvent
import kotlinx.coroutines.runBlocking
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer
-import org.bukkit.Bukkit
import org.bukkit.event.EventHandler
import org.bukkit.event.EventPriority
import org.bukkit.event.Listener
@@ -24,12 +22,38 @@ class PlayerChatListener(
private val channelMessageHandler: ChannelMessageHandler?,
private val romajiConverter: RomanjiConverter?,
private val settingsManager: PlayerSettingsManager,
- private val languageManager: LanguageManager,
private val configuration: LunaticChatConfiguration,
private val crossServerChatManager: CrossServerChatManager?,
) : Listener {
private val plainTextSerializer = PlainTextComponentSerializer.plainText()
+ /**
+ * Handles global chat message routing.
+ * Checks if Velocity cross-server chat is enabled and routes accordingly.
+ */
+ private fun handleGlobalChat(
+ event: AsyncChatEvent,
+ displayMessage: String,
+ ) {
+ val velocityIntegrationEnabled = configuration.features.velocityIntegration.enabled
+ val crossServerChatEnabled = configuration.features.velocityIntegration.crossServerGlobalChat
+
+ if (velocityIntegrationEnabled && crossServerChatEnabled && crossServerChatManager != null) {
+ // Send to Velocity for cross-server broadcast
+ crossServerChatManager.sendGlobalMessage(
+ event.player.uniqueId,
+ event.player.name,
+ displayMessage,
+ )
+
+ // Display as normal chat on the sender's server (no special formatting)
+ event.message(Component.text(displayMessage))
+ } else {
+ // Existing behavior: normal Minecraft chat
+ event.message(Component.text(displayMessage))
+ }
+ }
+
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
fun onChat(event: AsyncChatEvent) {
val player = event.player
@@ -85,30 +109,7 @@ class PlayerChatListener(
// Route message based on chat mode
when (effectiveMode) {
ChatMode.GLOBAL -> {
- val velocityIntegrationEnabled = configuration.features.velocityIntegration.enabled
- val crossServerChatEnabled = configuration.features.velocityIntegration.crossServerGlobalChat
-
- Bukkit.getLogger().info(
- "[LunaticChat DEBUG] Chat mode: GLOBAL, " +
- "velocityEnabled=$velocityIntegrationEnabled, " +
- "crossServerEnabled=$crossServerChatEnabled, " +
- "managerNull=${crossServerChatManager == null}",
- )
-
- if (velocityIntegrationEnabled && crossServerChatEnabled && crossServerChatManager != null) {
- // Send to Velocity for cross-server broadcast
- crossServerChatManager.sendGlobalMessage(
- player.uniqueId,
- player.name,
- displayMessage,
- )
-
- // Display as normal chat on the sender's server (no special formatting)
- event.message(Component.text(displayMessage))
- } else {
- // Existing behavior: normal Minecraft chat
- event.message(Component.text(displayMessage))
- }
+ handleGlobalChat(event, displayMessage)
}
ChatMode.CHANNEL -> {
// Channel chat requires channelManager and channelMessageHandler
@@ -125,12 +126,12 @@ class PlayerChatListener(
event.message(Component.empty())
channelMessageHandler.sendChannelMessage(player, messageWithoutPrefix)
} else {
- // Auto-fallback to global chat
- event.message(Component.text(displayMessage))
+ // Auto-fallback to global chat (with Velocity support if enabled)
+ handleGlobalChat(event, displayMessage)
}
} else {
- // Channel chat not available, fallback to normal chat
- event.message(Component.text(displayMessage))
+ // Channel chat not available, fallback to global chat (with Velocity support if enabled)
+ handleGlobalChat(event, displayMessage)
}
}
}
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/velocity/CrossServerChatManager.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/velocity/CrossServerChatManager.kt
index 0f4c34e..53eced1 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/velocity/CrossServerChatManager.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/velocity/CrossServerChatManager.kt
@@ -7,6 +7,7 @@ import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer
import org.bukkit.plugin.Plugin
import java.util.UUID
import java.util.concurrent.ConcurrentHashMap
+import java.util.logging.Level
import java.util.logging.Logger
/**
@@ -61,27 +62,36 @@ class CrossServerChatManager(
message = message,
)
- // Send to Velocity
- val player = plugin.server.getPlayer(playerId)
- if (player != null) {
- player.sendPluginMessage(
- plugin,
- "lunaticchat:main",
- dev.m1sk9.lunaticChat.engine.protocol.PluginMessageCodec
- .encode(globalChatMessage),
- )
- logger.info("Sent global chat message to Velocity: messageId=$messageId, player=$playerName")
- } else {
- logger.warning("Cannot send global chat message: player $playerId not found")
- }
+ // Schedule Bukkit API calls on the main server thread
+ plugin.server.scheduler.runTask(
+ plugin,
+ Runnable {
+ try {
+ // Send to Velocity
+ val player = plugin.server.getPlayer(playerId)
+ if (player != null) {
+ player.sendPluginMessage(
+ plugin,
+ "lunaticchat:main",
+ dev.m1sk9.lunaticChat.engine.protocol.PluginMessageCodec
+ .encode(globalChatMessage),
+ )
+ logger.info("Sent global chat message to Velocity: messageId=$messageId, player=$playerName")
+ } else {
+ logger.warning("Cannot send global chat message: player $playerId not found")
+ }
+ } catch (e: Exception) {
+ logger.log(Level.SEVERE, "Failed to send plugin message on main thread", e)
+ }
+ },
+ )
// Cleanup old messages if cache is too large
if (processedMessages.size > cacheSize) {
cleanupOldMessages()
}
} catch (e: Exception) {
- logger.severe("Failed to send global chat message: ${e.message}")
- e.printStackTrace()
+ logger.log(Level.SEVERE, "Failed to send global chat message", e)
}
}
@@ -123,8 +133,7 @@ class CrossServerChatManager(
cleanupOldMessages()
}
} catch (e: Exception) {
- logger.severe("Failed to handle incoming global chat message: ${e.message}")
- e.printStackTrace()
+ logger.log(Level.SEVERE, "Failed to handle incoming global chat message", e)
}
}
@@ -162,17 +171,21 @@ class CrossServerChatManager(
val currentTime = System.currentTimeMillis()
val cutoffTime = currentTime - CLEANUP_THRESHOLD_MILLIS
- val iterator = processedMessages.entries.iterator()
- var removedCount = 0
-
- while (iterator.hasNext()) {
- val entry = iterator.next()
+ // Collect keys to remove (ConcurrentHashMap iterator doesn't support remove())
+ val keysToRemove = mutableListOf<String>()
+ processedMessages.entries.forEach { entry ->
if (entry.value < cutoffTime) {
- iterator.remove()
- removedCount++
+ keysToRemove.add(entry.key)
}
}
+ // Remove expired entries
+ keysToRemove.forEach { key ->
+ processedMessages.remove(key)
+ }
+ var removedCount = keysToRemove.size
+
+ // If still over cache size, remove oldest entries
if (processedMessages.size > cacheSize) {
val sortedEntries = processedMessages.entries.sortedBy { it.value }
val toRemove = processedMessages.size - cacheSize
@@ -187,7 +200,7 @@ class CrossServerChatManager(
logger.fine("Cleaned up $removedCount old messages from deduplication cache")
}
} catch (e: Exception) {
- logger.warning("Failed to cleanup old messages: ${e.message}")
+ logger.log(Level.WARNING, "Failed to cleanup old messages", e)
}
}
}
diff --git a/platform-paper/src/main/resources/languages/en.yml b/platform-paper/src/main/resources/languages/en.yml
index 81cd0e8..f19c494 100644
--- a/platform-paper/src/main/resources/languages/en.yml
+++ b/platform-paper/src/main/resources/languages/en.yml
@@ -199,6 +199,7 @@ toggle:
velocity:
status:
+ header: "--- LunaticChat Velocity Cooperation Status ---"
paperVersion: "Paper Plugin Version: v{version}"
velocityVersion: "Velocity Plugin Version: v{version}"
protocolVersion: "Protocol Version: v{version}"
diff --git a/platform-paper/src/main/resources/languages/ja.yml b/platform-paper/src/main/resources/languages/ja.yml
index 7ca7ed1..ed02f5a 100644
--- a/platform-paper/src/main/resources/languages/ja.yml
+++ b/platform-paper/src/main/resources/languages/ja.yml
@@ -199,6 +199,7 @@ toggle:
velocity:
status:
+ header: "--- LunaticChat Velocity 連携ステータス ---"
paperVersion: "Paper プラグインバージョン: v{version}"
velocityVersion: "Velocity プラグインバージョン: v{version}"
protocolVersion: "プロトコルバージョン: v{version}"