summaryrefslogtreecommitdiff
path: root/platform-paper
diff options
context:
space:
mode:
authorSho Sakuma <me@m1sk9.dev>2026-03-17 20:34:18 +0900
committerSho Sakuma <me@m1sk9.dev>2026-03-17 20:34:18 +0900
commit634dd975038bb5b845c28ca6c96aa285ef94e965 (patch)
tree4eac57ae6533af6b5dc4c43cd5f4726aeb4f6a7a /platform-paper
parent8b806705aa3de33964a0924f9b528189b7004087 (diff)
downloadLunaticChat-634dd975038bb5b845c28ca6c96aa285ef94e965.tar.gz
LunaticChat-634dd975038bb5b845c28ca6c96aa285ef94e965.tar.bz2
LunaticChat-634dd975038bb5b845c28ca6c96aa285ef94e965.zip
feat!: Remove ChatMode feature, followback channel chat mode
Diffstat (limited to 'platform-paper')
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/LunaticChat.kt3
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/ServiceContainer.kt3
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/ServiceInitializer.kt29
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/ChatModeManager.kt103
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/ChatModeStorage.kt98
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/ChatModeCommand.kt86
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/LunaticChatCommand.kt11
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/chatmode/ChatModeToggleCommand.kt71
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/EventListenerRegistry.kt7
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/PlayerChatListener.kt55
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/PlayerPresenceListener.kt25
-rw-r--r--platform-paper/src/main/resources/languages/en.yml10
-rw-r--r--platform-paper/src/main/resources/languages/ja.yml10
-rw-r--r--platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/chat/ChatModeManagerTest.kt223
-rw-r--r--platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/chatmode/ChatModeToggleCommandTest.kt88
15 files changed, 20 insertions, 802 deletions
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/LunaticChat.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/LunaticChat.kt
index 880db16..addc3a3 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/LunaticChat.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/LunaticChat.kt
@@ -1,6 +1,5 @@
package dev.m1sk9.lunaticChat.paper
-import dev.m1sk9.lunaticChat.paper.chat.ChatModeManager
import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelManager
import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelMembershipManager
import dev.m1sk9.lunaticChat.paper.chat.handler.ChannelMessageHandler
@@ -36,7 +35,6 @@ class LunaticChat :
lateinit var languageManager: LanguageManager
var channelManager: ChannelManager? = null
var channelMembershipManager: ChannelMembershipManager? = null
- var chatModeManager: ChatModeManager? = null
var channelMessageHandler: ChannelMessageHandler? = null
var channelNotificationHandler: ChannelNotificationHandler? = null
var velocityConnectionManager: VelocityConnectionManager? = null
@@ -79,7 +77,6 @@ class LunaticChat :
languageManager = services.languageManager
channelManager = services.channelManager
channelMembershipManager = services.channelMembershipManager
- chatModeManager = services.chatModeManager
channelMessageHandler = services.channelMessageHandler
channelNotificationHandler = services.channelNotificationHandler
velocityConnectionManager = services.velocityConnectionManager
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/ServiceContainer.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/ServiceContainer.kt
index 5ca5e52..0607d82 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/ServiceContainer.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/ServiceContainer.kt
@@ -1,6 +1,5 @@
package dev.m1sk9.lunaticChat.paper
-import dev.m1sk9.lunaticChat.paper.chat.ChatModeManager
import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelManager
import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelMembershipManager
import dev.m1sk9.lunaticChat.paper.chat.handler.ChannelMessageHandler
@@ -24,7 +23,6 @@ import dev.m1sk9.lunaticChat.paper.velocity.VelocityConnectionManager
* @property romajiConverter Optional (only when Japanese conversion feature is enabled)
* @property channelManager Optional (only when channel chat feature is enabled)
* @property channelMembershipManager Optional (only when channel chat feature is enabled)
- * @property chatModeManager Optional (only when channel chat feature is enabled)
* @property channelMessageHandler Optional (only when channel chat feature is enabled)
* @property channelNotificationHandler Optional (only when channel chat feature is enabled)
* @property velocityConnectionManager Optional (only when Velocity integration is enabled)
@@ -37,7 +35,6 @@ data class ServiceContainer(
val romajiConverter: RomanjiConverter? = null,
val channelManager: ChannelManager? = null,
val channelMembershipManager: ChannelMembershipManager? = null,
- val chatModeManager: ChatModeManager? = null,
val channelMessageHandler: ChannelMessageHandler? = null,
val channelNotificationHandler: ChannelNotificationHandler? = null,
val velocityConnectionManager: VelocityConnectionManager? = null,
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/ServiceInitializer.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/ServiceInitializer.kt
index b732a9e..606273b 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/ServiceInitializer.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/ServiceInitializer.kt
@@ -1,8 +1,6 @@
package dev.m1sk9.lunaticChat.paper
import dev.m1sk9.lunaticChat.engine.converter.GoogleIMEClient
-import dev.m1sk9.lunaticChat.paper.chat.ChatModeManager
-import dev.m1sk9.lunaticChat.paper.chat.ChatModeStorage
import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelManager
import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelMembershipManager
import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelMessageLogger
@@ -34,7 +32,6 @@ import kotlin.time.Duration.Companion.milliseconds
private data class ChannelComponents(
val channelManager: ChannelManager,
val channelMembershipManager: ChannelMembershipManager,
- val chatModeManager: ChatModeManager,
val channelMessageHandler: ChannelMessageHandler,
val channelNotificationHandler: ChannelNotificationHandler,
)
@@ -54,7 +51,6 @@ class ServiceInitializer(
private var conversionCache: ConversionCache? = null
private var channelManager: ChannelManager? = null
private var channelMembershipManager: ChannelMembershipManager? = null
- private var chatModeManager: ChatModeManager? = null
private var channelMessageHandler: ChannelMessageHandler? = null
private var channelNotificationHandler: ChannelNotificationHandler? = null
private var channelMessageLogger: ChannelMessageLogger? = null
@@ -96,7 +92,7 @@ class ServiceInitializer(
null
}
- // 4. Initialize channel manager, membership manager, chat mode manager, channel message handler, and notification handler
+ // 4. Initialize channel manager, membership manager, channel message handler, and notification handler
val channelComponents =
if (configuration.features.channelChat.enabled) {
initializeChannelManager(playerSettingsManager, languageManager)
@@ -105,7 +101,6 @@ class ServiceInitializer(
}
val channelManager = channelComponents?.channelManager
val channelMembershipManager = channelComponents?.channelMembershipManager
- val chatModeManager = channelComponents?.chatModeManager
val channelMessageHandler = channelComponents?.channelMessageHandler
val channelNotificationHandler = channelComponents?.channelNotificationHandler
@@ -144,7 +139,6 @@ class ServiceInitializer(
romajiConverter = romajiConverter,
channelManager = channelManager,
channelMembershipManager = channelMembershipManager,
- chatModeManager = chatModeManager,
channelMessageHandler = channelMessageHandler,
channelNotificationHandler = channelNotificationHandler,
velocityConnectionManager = velocityManager,
@@ -213,7 +207,7 @@ class ServiceInitializer(
}
/**
- * Initializes channel manager, membership manager, chat mode manager, channel message handler, and notification handler with storage.
+ * Initializes channel manager, membership manager, channel message handler, and notification handler with storage.
*/
private fun initializeChannelManager(
settingsManager: PlayerSettingsManager,
@@ -244,21 +238,6 @@ class ServiceInitializer(
)
channelMembershipManager = membershipManager
- val chatModeFile = plugin.dataFolder.resolve("chatmodes.json").toPath()
- val chatModeStorage =
- ChatModeStorage(
- dataFile = chatModeFile,
- logger = logger,
- )
-
- val chatMode =
- ChatModeManager(
- storage = chatModeStorage,
- logger = logger,
- )
- chatMode.initialize()
- chatModeManager = chatMode
-
// Initialize channel message logger if enabled
val messageLogger =
if (configuration.features.channelChat.messageLogging.enabled) {
@@ -302,13 +281,12 @@ class ServiceInitializer(
channelNotificationHandler = notificationHandler
logger.info(
- "Channel manager, membership manager, chat mode manager, " +
+ "Channel manager, membership manager, " +
"channel message handler, and notification handler initialized successfully.",
)
return ChannelComponents(
channelManager = manager,
channelMembershipManager = membershipManager,
- chatModeManager = chatMode,
channelMessageHandler = messageHandler,
channelNotificationHandler = notificationHandler,
)
@@ -433,7 +411,6 @@ class ServiceInitializer(
services.playerSettingsManager.saveToDisk()
conversionCache?.saveToDisk()
services.channelManager?.saveToDisk()
- services.chatModeManager?.shutdown()
channelMessageLogger?.shutdown()
services.velocityConnectionManager?.shutdown()
}
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/ChatModeManager.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/ChatModeManager.kt
deleted file mode 100644
index 93a7f04..0000000
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/ChatModeManager.kt
+++ /dev/null
@@ -1,103 +0,0 @@
-package dev.m1sk9.lunaticChat.paper.chat
-
-import dev.m1sk9.lunaticChat.engine.chat.ChatMode
-import dev.m1sk9.lunaticChat.engine.chat.ChatModeData
-import java.util.UUID
-import java.util.concurrent.ConcurrentHashMap
-import java.util.logging.Logger
-
-/**
- * Manages player chat modes with persistence.
- *
- * Chat modes determine where player messages are sent by default.
- * Modes are persisted across server restarts.
- *
- * @property storage Chat mode storage layer
- * @property logger Logger for operations
- */
-class ChatModeManager(
- private val storage: ChatModeStorage,
- private val logger: Logger,
-) {
- private val chatModes = ConcurrentHashMap<UUID, ChatMode>()
-
- /**
- * Initializes the manager by loading data from storage.
- */
- fun initialize() {
- val data = storage.loadFromDisk()
- chatModes.putAll(data.modes)
- logger.info("ChatModeManager initialized with ${chatModes.size} saved modes")
- }
-
- /**
- * Gets a player's current chat mode.
- *
- * @param playerId The player's UUID
- * @return The player's chat mode, or DEFAULT if not set
- */
- fun getChatMode(playerId: UUID): ChatMode = chatModes.getOrDefault(playerId, ChatMode.Companion.DEFAULT)
-
- /**
- * Sets a player's chat mode.
- *
- * @param playerId The player's UUID
- * @param mode The chat mode to set
- */
- fun setChatMode(
- playerId: UUID,
- mode: ChatMode,
- ) {
- chatModes[playerId] = mode
- saveToStorage()
- }
-
- /**
- * Toggles a player's chat mode between GLOBAL and CHANNEL.
- *
- * @param playerId The player's UUID
- * @return The new chat mode after toggling
- */
- fun toggleChatMode(playerId: UUID): ChatMode {
- val currentMode = getChatMode(playerId)
- val newMode = currentMode.toggle()
- setChatMode(playerId, newMode)
- return newMode
- }
-
- /**
- * Removes a player's chat mode setting (reverts to default).
- *
- * @param playerId The player's UUID
- */
- fun removeChatMode(playerId: UUID) {
- chatModes.remove(playerId)
- saveToStorage()
- }
-
- /**
- * Saves current state to storage asynchronously.
- */
- private fun saveToStorage() {
- val data = ChatModeData(modes = chatModes.toMap())
- storage.queueAsyncSave(data)
- }
-
- /**
- * Forces a synchronous save to storage.
- * Should only be called during plugin shutdown.
- */
- fun saveToDisk() {
- val data = ChatModeData(modes = chatModes.toMap())
- storage.saveToDisk(data)
- }
-
- /**
- * Shuts down the chat mode manager and its storage executor.
- * Should be called during plugin disable to prevent thread leaks.
- */
- fun shutdown() {
- saveToDisk()
- storage.shutdown()
- }
-}
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/ChatModeStorage.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/ChatModeStorage.kt
deleted file mode 100644
index 77fcdb3..0000000
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/ChatModeStorage.kt
+++ /dev/null
@@ -1,98 +0,0 @@
-package dev.m1sk9.lunaticChat.paper.chat
-
-import dev.m1sk9.lunaticChat.engine.chat.ChatModeData
-import dev.m1sk9.lunaticChat.engine.exception.ChatModeStorageException
-import kotlinx.serialization.json.Json
-import java.nio.file.Path
-import java.util.concurrent.Executors
-import java.util.concurrent.TimeUnit
-import java.util.logging.Logger
-import kotlin.io.path.exists
-import kotlin.io.path.readText
-import kotlin.io.path.writeText
-
-/**
- * Handles JSON storage for chat mode data.
- * Provides async save queue and synchronous save for shutdown.
- *
- * @property dataFile Path to chatmodes.json
- * @property logger Logger for operations
- */
-class ChatModeStorage(
- private val dataFile: Path,
- private val logger: Logger,
-) {
- private val json =
- Json {
- prettyPrint = true
- ignoreUnknownKeys = true
- }
-
- private val saveExecutor = Executors.newSingleThreadExecutor()
-
- /**
- * Loads chat mode data from disk.
- *
- * @return ChatModeData loaded from file, or empty data if file doesn't exist
- * @throws ChatModeStorageException if loading fails
- */
- fun loadFromDisk(): ChatModeData {
- if (!dataFile.exists()) {
- logger.info("Chat mode data file not found, starting with empty data")
- return ChatModeData()
- }
-
- return try {
- val jsonContent = dataFile.readText()
- json.decodeFromString<ChatModeData>(jsonContent)
- } catch (e: Exception) {
- throw ChatModeStorageException("Failed to load chat mode data from ${dataFile.fileName}", e)
- }
- }
-
- /**
- * Queues an asynchronous save operation.
- *
- * @param data ChatModeData to save
- */
- fun queueAsyncSave(data: ChatModeData) {
- saveExecutor.submit {
- try {
- saveToDisk(data)
- } catch (e: Exception) {
- logger.severe("Failed to save chat mode data: ${e.message}")
- }
- }
- }
-
- /**
- * Saves chat mode data to disk synchronously.
- *
- * @param data ChatModeData to save
- * @throws ChatModeStorageException if saving fails
- */
- fun saveToDisk(data: ChatModeData) {
- try {
- val jsonContent = json.encodeToString(data)
- dataFile.writeText(jsonContent)
- } catch (e: Exception) {
- throw ChatModeStorageException("Failed to save chat mode data to ${dataFile.fileName}", e)
- }
- }
-
- /**
- * Shuts down the async save executor.
- * Should be called during plugin disable.
- */
- fun shutdown() {
- saveExecutor.shutdown()
- try {
- if (!saveExecutor.awaitTermination(5, TimeUnit.SECONDS)) {
- saveExecutor.shutdownNow()
- }
- } catch (e: InterruptedException) {
- saveExecutor.shutdownNow()
- Thread.currentThread().interrupt()
- }
- }
-}
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/ChatModeCommand.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/ChatModeCommand.kt
deleted file mode 100644
index d0357f6..0000000
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/ChatModeCommand.kt
+++ /dev/null
@@ -1,86 +0,0 @@
-package dev.m1sk9.lunaticChat.paper.command.impl.lc
-
-import com.mojang.brigadier.builder.LiteralArgumentBuilder
-import dev.m1sk9.lunaticChat.engine.command.CommandResult
-import dev.m1sk9.lunaticChat.engine.permission.LunaticChatPermissionNode
-import dev.m1sk9.lunaticChat.paper.LunaticChat
-import dev.m1sk9.lunaticChat.paper.chat.ChatModeManager
-import dev.m1sk9.lunaticChat.paper.command.annotation.Permission
-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.command.impl.lc.chatmode.ChatModeToggleCommand
-import dev.m1sk9.lunaticChat.paper.i18n.LanguageManager
-import dev.m1sk9.lunaticChat.paper.i18n.MessageFormatter
-import io.papermc.paper.command.brigadier.CommandSourceStack
-import io.papermc.paper.command.brigadier.Commands
-import net.kyori.adventure.text.Component
-import net.kyori.adventure.text.format.NamedTextColor
-
-@PlayerOnly
-class ChatModeCommand(
- plugin: LunaticChat,
- private val chatModeManager: ChatModeManager,
- private val languageManager: LanguageManager,
-) : LunaticCommand(plugin) {
- fun buildWithPermissionCheck(): LiteralArgumentBuilder<CommandSourceStack> {
- val builder = build()
- return applyMethodPermission("build", builder)
- }
-
- @Permission(LunaticChatPermissionNode.ChatMode::class)
- fun build(): LiteralArgumentBuilder<CommandSourceStack> {
- val chatModeCommand = Commands.literal("chatmode")
-
- // Add toggle subcommand
- chatModeCommand.then(
- ChatModeToggleCommand(
- plugin,
- chatModeManager,
- languageManager,
- ).buildWithPermissionCheck(),
- )
-
- // Default behavior: show current chat mode
- chatModeCommand.executes { ctx ->
- val context = wrapContext(ctx)
- checkPlayerOnly(context)?.let { return@executes handleResult(context, it) }
-
- val result = showCurrentMode(context)
- handleResult(context, result)
- }
-
- return chatModeCommand
- }
-
- private fun showCurrentMode(ctx: CommandContext): CommandResult {
- val sender = ctx.requirePlayer()
- val currentMode = chatModeManager.getChatMode(sender.uniqueId)
-
- val modeKey =
- when (currentMode) {
- dev.m1sk9.lunaticChat.engine.chat.ChatMode.GLOBAL -> "chatmode.mode.global"
- dev.m1sk9.lunaticChat.engine.chat.ChatMode.CHANNEL -> "chatmode.mode.channel"
- }
-
- val modeColor =
- when (currentMode) {
- dev.m1sk9.lunaticChat.engine.chat.ChatMode.GLOBAL -> NamedTextColor.GREEN
- dev.m1sk9.lunaticChat.engine.chat.ChatMode.CHANNEL -> NamedTextColor.AQUA
- }
-
- sender.sendMessage(
- MessageFormatter
- .format(
- languageManager.getMessage("chatmode.current") + ": ",
- ).append(Component.text(languageManager.getMessage(modeKey), modeColor)),
- )
-
- return CommandResult.Success
- }
-
- override fun buildCommand(): LiteralArgumentBuilder<CommandSourceStack> =
- throw UnsupportedOperationException(
- "Should use build() method instead of buildCommand()",
- )
-}
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/LunaticChatCommand.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/LunaticChatCommand.kt
index d945737..cd3b33d 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/LunaticChatCommand.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/LunaticChatCommand.kt
@@ -68,17 +68,6 @@ class LunaticChatCommand(
}
}
- // Add chatmode command if chat mode manager is available
- plugin.chatModeManager?.let { chatModeManager ->
- command.then(
- ChatModeCommand(
- plugin,
- chatModeManager,
- languageManager,
- ).buildWithPermissionCheck(),
- )
- }
-
return command
}
}
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/chatmode/ChatModeToggleCommand.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/chatmode/ChatModeToggleCommand.kt
deleted file mode 100644
index e447639..0000000
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/chatmode/ChatModeToggleCommand.kt
+++ /dev/null
@@ -1,71 +0,0 @@
-package dev.m1sk9.lunaticChat.paper.command.impl.lc.chatmode
-
-import com.mojang.brigadier.builder.LiteralArgumentBuilder
-import dev.m1sk9.lunaticChat.engine.command.CommandResult
-import dev.m1sk9.lunaticChat.engine.permission.LunaticChatPermissionNode
-import dev.m1sk9.lunaticChat.paper.LunaticChat
-import dev.m1sk9.lunaticChat.paper.chat.ChatModeManager
-import dev.m1sk9.lunaticChat.paper.command.annotation.Permission
-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 io.papermc.paper.command.brigadier.CommandSourceStack
-import io.papermc.paper.command.brigadier.Commands
-import net.kyori.adventure.text.Component
-import net.kyori.adventure.text.format.NamedTextColor
-
-@PlayerOnly
-class ChatModeToggleCommand(
- plugin: LunaticChat,
- private val chatModeManager: ChatModeManager,
- private val languageManager: LanguageManager,
-) : LunaticCommand(plugin) {
- fun buildWithPermissionCheck(): LiteralArgumentBuilder<CommandSourceStack> {
- val builder = build()
- return applyMethodPermission("build", builder)
- }
-
- @Permission(LunaticChatPermissionNode.ChatModeToggle::class)
- fun build(): LiteralArgumentBuilder<CommandSourceStack> =
- Commands.literal("toggle").executes { ctx ->
- val context = wrapContext(ctx)
- checkPlayerOnly(context)?.let { return@executes handleResult(context, it) }
-
- val result = execute(context)
- handleResult(context, result)
- }
-
- internal fun execute(ctx: CommandContext): CommandResult {
- val sender = ctx.requirePlayer()
- val newMode = chatModeManager.toggleChatMode(sender.uniqueId)
-
- val modeKey =
- when (newMode) {
- dev.m1sk9.lunaticChat.engine.chat.ChatMode.GLOBAL -> "chatmode.mode.global"
- dev.m1sk9.lunaticChat.engine.chat.ChatMode.CHANNEL -> "chatmode.mode.channel"
- }
-
- val modeColor =
- when (newMode) {
- dev.m1sk9.lunaticChat.engine.chat.ChatMode.GLOBAL -> NamedTextColor.GREEN
- dev.m1sk9.lunaticChat.engine.chat.ChatMode.CHANNEL -> NamedTextColor.AQUA
- }
-
- sender.sendMessage(
- Component
- .text()
- .append(MessageFormatter.formatSuccess(languageManager.getMessage("chatmode.toggle.success") + ": "))
- .append(Component.text(languageManager.getMessage(modeKey), modeColor))
- .build(),
- )
-
- return CommandResult.Success
- }
-
- override fun buildCommand(): LiteralArgumentBuilder<CommandSourceStack> =
- throw UnsupportedOperationException(
- "ChatModeToggleCommand should use build() method instead of buildCommand()",
- )
-}
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 2bdca37..84040b6 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
@@ -37,19 +37,15 @@ object EventListenerRegistry {
languageManager = services.languageManager,
updateCheckerFlag = updateAvailable,
playerSettingsManager = services.playerSettingsManager,
- chatModeManager = services.chatModeManager,
channelManager = services.channelManager,
),
plugin,
)
// Register chat listener when channel chat is enabled OR velocity cross-server chat is enabled
- // Channel-related services (chatModeManager, channelManager, channelMessageHandler) can be null
- // when channel chat is disabled, but cross-server chat can still work
val shouldRegisterChatListener =
(
- services.chatModeManager != null &&
- services.channelManager != null &&
+ services.channelManager != null &&
services.channelMessageHandler != null
) ||
(
@@ -60,7 +56,6 @@ object EventListenerRegistry {
if (shouldRegisterChatListener) {
pluginManager.registerEvents(
PlayerChatListener(
- chatModeManager = services.chatModeManager,
channelManager = services.channelManager,
channelMessageHandler = services.channelMessageHandler,
romajiConverter = services.romajiConverter,
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 8a07336..19b284b 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
@@ -1,7 +1,5 @@
package dev.m1sk9.lunaticChat.paper.listener
-import dev.m1sk9.lunaticChat.engine.chat.ChatMode
-import dev.m1sk9.lunaticChat.paper.chat.ChatModeManager
import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelManager
import dev.m1sk9.lunaticChat.paper.chat.handler.ChannelMessageHandler
import dev.m1sk9.lunaticChat.paper.config.LunaticChatConfiguration
@@ -17,7 +15,6 @@ import org.bukkit.event.EventPriority
import org.bukkit.event.Listener
class PlayerChatListener(
- private val chatModeManager: ChatModeManager?,
private val channelManager: ChannelManager?,
private val channelMessageHandler: ChannelMessageHandler?,
private val romajiConverter: RomanjiConverter?,
@@ -61,7 +58,7 @@ class PlayerChatListener(
val originalMessage = plainTextSerializer.serialize(event.message())
- // Handle chat mode switching with '!' prefix
+ // Handle '!' prefix for global chat override
val hasPrefix = originalMessage.startsWith('!')
val messageWithoutPrefix =
if (hasPrefix) {
@@ -75,19 +72,6 @@ class PlayerChatListener(
return
}
- val effectiveMode =
- if (chatModeManager != null) {
- if (hasPrefix) {
- val currentMode = chatModeManager.getChatMode(player.uniqueId)
- currentMode.toggle()
- } else {
- chatModeManager.getChatMode(player.uniqueId)
- }
- } else {
- // Default to GLOBAL when chatModeManager is not available
- ChatMode.GLOBAL
- }
-
val displayMessage =
if (settings.japaneseConversionEnabled && romajiConverter != null) {
convertWithRomaji(messageWithoutPrefix, romajiConverter)
@@ -95,34 +79,25 @@ class PlayerChatListener(
messageWithoutPrefix
}
- // Route message based on chat mode
- when (effectiveMode) {
- ChatMode.GLOBAL -> {
- handleGlobalChat(event, displayMessage)
- }
- ChatMode.CHANNEL -> {
- // Channel chat requires channelManager and channelMessageHandler
- if (channelManager != null && channelMessageHandler != null) {
- val hasActiveChannel = channelManager.getPlayerChannel(player.uniqueId) != null
+ // Determine if the player has an active channel
+ val hasActiveChannel = channelManager?.getPlayerChannel(player.uniqueId) != null
- if (hasActiveChannel) {
- // Cancel event and clear all data to prevent other plugins from capturing it
- // Even MONITOR priority listeners with ignoreCancelled=false won't get useful data
- // Message will be delivered by ChannelMessageHandler instead
- // Logging is handled by our own ChannelMessageLogger
- event.isCancelled = true
- event.viewers().clear()
- event.message(Component.empty())
- channelMessageHandler.sendChannelMessage(player, displayMessage)
- } else {
- // Auto-fallback to global chat (with Velocity support if enabled)
- handleGlobalChat(event, displayMessage)
- }
+ when {
+ hasActiveChannel && !hasPrefix -> {
+ // Channel chat: player is in a channel and no '!' prefix
+ if (channelManager != null && channelMessageHandler != null) {
+ event.isCancelled = true
+ event.viewers().clear()
+ event.message(Component.empty())
+ channelMessageHandler.sendChannelMessage(player, displayMessage)
} else {
- // Channel chat not available, fallback to global chat (with Velocity support if enabled)
handleGlobalChat(event, displayMessage)
}
}
+ else -> {
+ // Global chat: player has no active channel, or used '!' prefix to override
+ handleGlobalChat(event, displayMessage)
+ }
}
}
}
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/PlayerPresenceListener.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/PlayerPresenceListener.kt
index f4343b6..3979246 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/PlayerPresenceListener.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/PlayerPresenceListener.kt
@@ -1,9 +1,7 @@
package dev.m1sk9.lunaticChat.paper.listener
-import dev.m1sk9.lunaticChat.engine.chat.ChatMode
import dev.m1sk9.lunaticChat.engine.permission.LunaticChatPermissionNode
import dev.m1sk9.lunaticChat.paper.LunaticChat
-import dev.m1sk9.lunaticChat.paper.chat.ChatModeManager
import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelManager
import dev.m1sk9.lunaticChat.paper.common.hasAnyPermission
import dev.m1sk9.lunaticChat.paper.i18n.LanguageManager
@@ -21,7 +19,6 @@ class PlayerPresenceListener(
private val languageManager: LanguageManager,
private val updateCheckerFlag: AtomicBoolean,
private val playerSettingsManager: PlayerSettingsManager,
- private val chatModeManager: ChatModeManager? = null,
private val channelManager: ChannelManager? = null,
) : Listener {
@EventHandler(ignoreCancelled = true)
@@ -37,23 +34,6 @@ class PlayerPresenceListener(
)
}
- // Send chat mode notification
- chatModeManager?.let { manager ->
- val chatMode = manager.getChatMode(player.uniqueId)
- val modeKey =
- when (chatMode) {
- ChatMode.GLOBAL -> "chatmode.mode.global"
- ChatMode.CHANNEL -> "chatmode.mode.channel"
- }
- val modeText = languageManager.getMessage(modeKey)
- val notification =
- languageManager.getMessage(
- "chatmode.notification.login",
- mapOf("mode" to modeText),
- )
- player.sendMessage(MessageFormatter.format(notification))
- }
-
// Send channel notification if in a channel
channelManager?.let { manager ->
val context = manager.getPlayerChannelContext(player.uniqueId)
@@ -81,10 +61,7 @@ class PlayerPresenceListener(
// 2. Clear active channel for this player
channelManager?.setPlayerChannel(playerId, null)
- // 3. Trigger async save of chat mode data
- chatModeManager?.saveToDisk()
-
- // 4. Trigger async save of player settings
+ // 3. Trigger async save of player settings
playerSettingsManager.saveToDisk()
}
}
diff --git a/platform-paper/src/main/resources/languages/en.yml b/platform-paper/src/main/resources/languages/en.yml
index 1275ce5..d932105 100644
--- a/platform-paper/src/main/resources/languages/en.yml
+++ b/platform-paper/src/main/resources/languages/en.yml
@@ -195,16 +195,6 @@ channel:
receivedOwnership: "You are now the owner of {channel} (previously owned by {previousOwner})"
error: "Failed to transfer ownership"
-chatmode:
- current: "Current chat mode"
- mode:
- global: "GLOBAL"
- channel: "CHANNEL"
- toggle:
- success: "Chat mode switched to"
- notification:
- login: "Current chat mode: {mode}"
-
general:
playerOnlyCommand: "This command can only be executed by players."
newUpdateAvailable: "The new version of LunaticChat is now available! You can download it from GitHub or Modrinth."
diff --git a/platform-paper/src/main/resources/languages/ja.yml b/platform-paper/src/main/resources/languages/ja.yml
index f2d4ae6..fbf09f9 100644
--- a/platform-paper/src/main/resources/languages/ja.yml
+++ b/platform-paper/src/main/resources/languages/ja.yml
@@ -195,16 +195,6 @@ channel:
receivedOwnership: "チャンネル {channel} のオーナーになりました (前のオーナー: {previousOwner})"
error: "オーナー権限の譲渡に失敗しました"
-chatmode:
- current: "現在のチャットモード"
- mode:
- global: "グローバル"
- channel: "チャンネル"
- toggle:
- success: "チャットモードを切り替えました"
- notification:
- login: "現在のチャットモード: {mode}"
-
general:
playerOnlyCommand: "このコマンドはプレイヤーのみが実行できます"
newUpdateAvailable: "LunaticChat の新しいバージョンが利用可能です。GitHubまたはModrinthからダウンロードできます"
diff --git a/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/chat/ChatModeManagerTest.kt b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/chat/ChatModeManagerTest.kt
deleted file mode 100644
index d548f60..0000000
--- a/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/chat/ChatModeManagerTest.kt
+++ /dev/null
@@ -1,223 +0,0 @@
-package dev.m1sk9.lunaticChat.paper.chat
-
-import dev.m1sk9.lunaticChat.engine.chat.ChatMode
-import dev.m1sk9.lunaticChat.engine.chat.ChatModeData
-import dev.m1sk9.lunaticChat.paper.TestUtils
-import io.mockk.every
-import io.mockk.mockk
-import io.mockk.verify
-import java.util.UUID
-import kotlin.test.Test
-import kotlin.test.assertEquals
-
-/**
- * Tests for ChatModeManager.
- * Verifies chat mode management, toggling, and persistence.
- */
-class ChatModeManagerTest {
- private fun createChatModeManager(
- initialData: ChatModeData = ChatModeData(),
- ): Triple<ChatModeManager, ChatModeStorage, TestUtils.TestLogger> {
- val logger = TestUtils.TestLogger()
- val storage = mockk<ChatModeStorage>(relaxed = true)
-
- every { storage.loadFromDisk() } returns initialData
-
- val manager = ChatModeManager(storage, logger)
- return Triple(manager, storage, logger)
- }
-
- @Test
- fun `initialize should load data from storage`() {
- val playerId = UUID.randomUUID()
- val initialData = ChatModeData(modes = mapOf(playerId to ChatMode.CHANNEL))
- val (manager, _, logger) = createChatModeManager(initialData)
-
- manager.initialize()
-
- assertEquals(ChatMode.CHANNEL, manager.getChatMode(playerId))
- assert(logger.infoMessages.any { it.contains("ChatModeManager initialized with 1 saved modes") })
- }
-
- @Test
- fun `getChatMode should return DEFAULT for unknown player`() {
- val (manager, _, _) = createChatModeManager()
- manager.initialize()
-
- val playerId = UUID.randomUUID()
- val mode = manager.getChatMode(playerId)
-
- assertEquals(ChatMode.DEFAULT, mode)
- assertEquals(ChatMode.GLOBAL, mode) // DEFAULT is GLOBAL
- }
-
- @Test
- fun `getChatMode should return set mode`() {
- val (manager, _, _) = createChatModeManager()
- manager.initialize()
-
- val playerId = UUID.randomUUID()
- manager.setChatMode(playerId, ChatMode.CHANNEL)
-
- assertEquals(ChatMode.CHANNEL, manager.getChatMode(playerId))
- }
-
- @Test
- fun `setChatMode should save to storage`() {
- val (manager, storage, _) = createChatModeManager()
- manager.initialize()
-
- val playerId = UUID.randomUUID()
- manager.setChatMode(playerId, ChatMode.CHANNEL)
-
- verify(exactly = 1) { storage.queueAsyncSave(any()) }
- }
-
- @Test
- fun `toggleChatMode should switch from GLOBAL to CHANNEL`() {
- val (manager, _, _) = createChatModeManager()
- manager.initialize()
-
- val playerId = UUID.randomUUID()
- // Initial mode is GLOBAL (default)
- assertEquals(ChatMode.GLOBAL, manager.getChatMode(playerId))
-
- val newMode = manager.toggleChatMode(playerId)
-
- assertEquals(ChatMode.CHANNEL, newMode)
- assertEquals(ChatMode.CHANNEL, manager.getChatMode(playerId))
- }
-
- @Test
- fun `toggleChatMode should switch from CHANNEL to GLOBAL`() {
- val (manager, _, _) = createChatModeManager()
- manager.initialize()
-
- val playerId = UUID.randomUUID()
- manager.setChatMode(playerId, ChatMode.CHANNEL)
-
- val newMode = manager.toggleChatMode(playerId)
-
- assertEquals(ChatMode.GLOBAL, newMode)
- assertEquals(ChatMode.GLOBAL, manager.getChatMode(playerId))
- }
-
- @Test
- fun `toggleChatMode should persist changes`() {
- val (manager, storage, _) = createChatModeManager()
- manager.initialize()
-
- val playerId = UUID.randomUUID()
- manager.toggleChatMode(playerId)
-
- verify(atLeast = 1) { storage.queueAsyncSave(any()) }
- }
-
- @Test
- fun `removeChatMode should revert to default`() {
- val (manager, _, _) = createChatModeManager()
- manager.initialize()
-
- val playerId = UUID.randomUUID()
- manager.setChatMode(playerId, ChatMode.CHANNEL)
- assertEquals(ChatMode.CHANNEL, manager.getChatMode(playerId))
-
- manager.removeChatMode(playerId)
-
- assertEquals(ChatMode.GLOBAL, manager.getChatMode(playerId))
- }
-
- @Test
- fun `removeChatMode should save to storage`() {
- val (manager, storage, _) = createChatModeManager()
- manager.initialize()
-
- val playerId = UUID.randomUUID()
- manager.setChatMode(playerId, ChatMode.CHANNEL)
- manager.removeChatMode(playerId)
-
- verify(atLeast = 2) { storage.queueAsyncSave(any()) } // Once for set, once for remove
- }
-
- @Test
- fun `saveToDisk should synchronously save`() {
- val (manager, storage, _) = createChatModeManager()
- manager.initialize()
-
- val playerId = UUID.randomUUID()
- manager.setChatMode(playerId, ChatMode.CHANNEL)
- manager.saveToDisk()
-
- verify { storage.saveToDisk(any()) }
- }
-
- @Test
- fun `shutdown should save and shutdown storage`() {
- val (manager, storage, _) = createChatModeManager()
- manager.initialize()
-
- manager.shutdown()
-
- verify { storage.saveToDisk(any()) }
- verify { storage.shutdown() }
- }
-
- @Test
- fun `manager should handle multiple players independently`() {
- val (manager, _, _) = createChatModeManager()
- manager.initialize()
-
- val player1 = UUID.randomUUID()
- val player2 = UUID.randomUUID()
-
- manager.setChatMode(player1, ChatMode.CHANNEL)
- manager.setChatMode(player2, ChatMode.GLOBAL)
-
- assertEquals(ChatMode.CHANNEL, manager.getChatMode(player1))
- assertEquals(ChatMode.GLOBAL, manager.getChatMode(player2))
- }
-
- @Test
- fun `manager should support rapid mode changes`() {
- val (manager, storage, _) = createChatModeManager()
- manager.initialize()
-
- val playerId = UUID.randomUUID()
-
- // Toggle multiple times
- manager.toggleChatMode(playerId) // GLOBAL -> CHANNEL
- manager.toggleChatMode(playerId) // CHANNEL -> GLOBAL
- manager.toggleChatMode(playerId) // GLOBAL -> CHANNEL
-
- assertEquals(ChatMode.CHANNEL, manager.getChatMode(playerId))
- verify(atLeast = 3) { storage.queueAsyncSave(any()) }
- }
-
- @Test
- fun `manager should handle empty initial data`() {
- val (manager, _, logger) = createChatModeManager(ChatModeData())
- manager.initialize()
-
- assert(logger.infoMessages.any { it.contains("ChatModeManager initialized with 0 saved modes") })
- }
-
- @Test
- fun `manager should restore modes after initialization`() {
- val player1 = TestUtils.createTestUUID(1)
- val player2 = TestUtils.createTestUUID(2)
- val initialData =
- ChatModeData(
- modes =
- mapOf(
- player1 to ChatMode.CHANNEL,
- player2 to ChatMode.GLOBAL,
- ),
- )
-
- val (manager, _, _) = createChatModeManager(initialData)
- manager.initialize()
-
- assertEquals(ChatMode.CHANNEL, manager.getChatMode(player1))
- assertEquals(ChatMode.GLOBAL, manager.getChatMode(player2))
- }
-}
diff --git a/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/chatmode/ChatModeToggleCommandTest.kt b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/chatmode/ChatModeToggleCommandTest.kt
deleted file mode 100644
index d43c867..0000000
--- a/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/chatmode/ChatModeToggleCommandTest.kt
+++ /dev/null
@@ -1,88 +0,0 @@
-package dev.m1sk9.lunaticChat.paper.command.impl.lc.chatmode
-
-import dev.m1sk9.lunaticChat.engine.chat.ChatMode
-import dev.m1sk9.lunaticChat.engine.command.CommandResult
-import dev.m1sk9.lunaticChat.paper.LunaticChat
-import dev.m1sk9.lunaticChat.paper.TestUtils
-import dev.m1sk9.lunaticChat.paper.chat.ChatModeManager
-import dev.m1sk9.lunaticChat.paper.command.core.CommandContext
-import dev.m1sk9.lunaticChat.paper.i18n.LanguageManager
-import io.mockk.every
-import io.mockk.mockk
-import io.mockk.verify
-import net.kyori.adventure.text.Component
-import java.util.UUID
-import kotlin.test.Test
-import kotlin.test.assertIs
-
-class ChatModeToggleCommandTest {
- private val testUUID = UUID.fromString("00000001-0000-0000-0000-000000000000")
-
- private fun createDependencies(): TestDeps {
- val plugin = mockk<LunaticChat>(relaxed = true)
- val chatModeManager = mockk<ChatModeManager>(relaxed = true)
- val languageManager = mockk<LanguageManager>(relaxed = true)
- every { languageManager.getMessage(any(), any()) } returns "test message"
-
- val mockPlayer = TestUtils.createMockPlayer(uuid = testUUID, name = "Player1")
- val ctx = mockk<CommandContext>(relaxed = true)
- every { ctx.requirePlayer() } returns mockPlayer
-
- val command = ChatModeToggleCommand(plugin, chatModeManager, languageManager)
- return TestDeps(command, ctx, chatModeManager, languageManager, mockPlayer)
- }
-
- private data class TestDeps(
- val command: ChatModeToggleCommand,
- val ctx: CommandContext,
- val chatModeManager: ChatModeManager,
- val languageManager: LanguageManager,
- val mockPlayer: org.bukkit.entity.Player,
- )
-
- @Test
- fun `execute should toggle to CHANNEL mode`() {
- val deps = createDependencies()
-
- every { deps.chatModeManager.toggleChatMode(testUUID) } returns ChatMode.CHANNEL
-
- val result = deps.command.execute(deps.ctx)
-
- assertIs<CommandResult.Success>(result)
- verify { deps.chatModeManager.toggleChatMode(testUUID) }
- }
-
- @Test
- fun `execute should toggle to GLOBAL mode`() {
- val deps = createDependencies()
-
- every { deps.chatModeManager.toggleChatMode(testUUID) } returns ChatMode.GLOBAL
-
- val result = deps.command.execute(deps.ctx)
-
- assertIs<CommandResult.Success>(result)
- verify { deps.chatModeManager.toggleChatMode(testUUID) }
- }
-
- @Test
- fun `execute should send message to player`() {
- val deps = createDependencies()
-
- every { deps.chatModeManager.toggleChatMode(testUUID) } returns ChatMode.CHANNEL
-
- deps.command.execute(deps.ctx)
-
- verify { deps.mockPlayer.sendMessage(any<Component>()) }
- }
-
- @Test
- fun `execute should return Success`() {
- val deps = createDependencies()
-
- every { deps.chatModeManager.toggleChatMode(testUUID) } returns ChatMode.GLOBAL
-
- val result = deps.command.execute(deps.ctx)
-
- assertIs<CommandResult.Success>(result)
- }
-}