diff options
| author | Sho Sakuma <me@m1sk9.dev> | 2026-02-07 16:56:41 +0900 |
|---|---|---|
| committer | Sho Sakuma <me@m1sk9.dev> | 2026-02-07 16:56:55 +0900 |
| commit | 76198199c24b0d1d31d0dfa74825d1ea0cdfb097 (patch) | |
| tree | 112c6c20abd69af5c3e6d669419d8d2045044fbb | |
| parent | 40c9d18e4747e23977618e17bafcd64cd0ffa6b4 (diff) | |
| download | LunaticChat-76198199c24b0d1d31d0dfa74825d1ea0cdfb097.tar.gz LunaticChat-76198199c24b0d1d31d0dfa74825d1ea0cdfb097.tar.bz2 LunaticChat-76198199c24b0d1d31d0dfa74825d1ea0cdfb097.zip | |
fix: Fix copilot review
7 files changed, 116 insertions, 94 deletions
diff --git a/docs/src/reference/commands/lc/settings.md b/docs/src/reference/commands/lc/settings.md index d9b59db..209879d 100644 --- a/docs/src/reference/commands/lc/settings.md +++ b/docs/src/reference/commands/lc/settings.md @@ -15,5 +15,5 @@ LunaticChat のプレイヤー設定を管理します.値を指定しなか | キー | 説明 | デフォルト値 | |------------|----------------------------------------------------------|--------| | `japanese` | ローマ字変換の有効化・無効化を切り替えます. | `true` | -| `notice` | `/tell` や `/reply` でダイレクトメッセージを受信した際に通知を受け取るかどうかを切り替えます. | `true` | +| `notice` | `/tell` や `/reply` でダイレクトメッセージを受信した際に通知を受け取るかどうかを切り替えます. | `true` | | `chNotice` | チャンネルチャットを受信した際に通知を受け取るかどうかを切り替えます. | `true` | 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}" |
