diff options
29 files changed, 510 insertions, 43 deletions
diff --git a/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/chat/ChatMode.kt b/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/chat/ChatMode.kt new file mode 100644 index 0000000..98bb79d --- /dev/null +++ b/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/chat/ChatMode.kt @@ -0,0 +1,43 @@ +package dev.m1sk9.lunaticChat.engine.chat + +/** + * Represents the chat mode for a player. + * + * Chat mode determines where messages are sent by default: + * - GLOBAL: All messages go to global chat (visible to everyone) + * - CHANNEL: All messages go to the active channel (visible to channel members only) + * + * Players can temporarily override their mode by prefixing messages with '!'. + * Chat mode is persisted and maintains its state across server restarts. + * Default mode is GLOBAL. + */ +enum class ChatMode { + /** + * Global chat mode - messages visible to all players. + */ + GLOBAL, + + /** + * Channel chat mode - messages visible only to channel members. + * Requires player to be in an active channel. + */ + CHANNEL, + ; + + /** + * Returns the opposite chat mode. + * Used when player prefixes message with '!'. + */ + fun toggle(): ChatMode = + when (this) { + GLOBAL -> CHANNEL + CHANNEL -> GLOBAL + } + + companion object { + /** + * Default chat mode for all players. + */ + val DEFAULT = GLOBAL + } +} diff --git a/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/chat/ChatModeData.kt b/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/chat/ChatModeData.kt new file mode 100644 index 0000000..b462ede --- /dev/null +++ b/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/chat/ChatModeData.kt @@ -0,0 +1,14 @@ +package dev.m1sk9.lunaticChat.engine.chat + +import dev.m1sk9.lunaticChat.engine.settings.UUIDSerializer +import kotlinx.serialization.Serializable +import java.util.UUID + +@Serializable +data class ChatModeData( + val modes: Map< + @Serializable(with = UUIDSerializer::class) + UUID, + ChatMode, + > = emptyMap(), +) diff --git a/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/channel/modal/Channel.kt b/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/chat/channel/Channel.kt index 427e526..cc1f743 100644 --- a/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/channel/modal/Channel.kt +++ b/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/chat/channel/Channel.kt @@ -1,4 +1,4 @@ -package dev.m1sk9.lunaticChat.engine.channel.modal +package dev.m1sk9.lunaticChat.engine.chat.channel import dev.m1sk9.lunaticChat.engine.settings.UUIDSerializer import kotlinx.serialization.Serializable diff --git a/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/channel/modal/ChannelData.kt b/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/chat/channel/ChannelData.kt index 67e86ec..de942f7 100644 --- a/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/channel/modal/ChannelData.kt +++ b/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/chat/channel/ChannelData.kt @@ -1,4 +1,4 @@ -package dev.m1sk9.lunaticChat.engine.channel.modal +package dev.m1sk9.lunaticChat.engine.chat.channel import kotlinx.serialization.Serializable diff --git a/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/channel/modal/ChannelMember.kt b/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/chat/channel/ChannelMember.kt index 3bc2b67..1eb49f4 100644 --- a/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/channel/modal/ChannelMember.kt +++ b/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/chat/channel/ChannelMember.kt @@ -1,4 +1,4 @@ -package dev.m1sk9.lunaticChat.engine.channel.modal +package dev.m1sk9.lunaticChat.engine.chat.channel import dev.m1sk9.lunaticChat.engine.settings.UUIDSerializer import kotlinx.serialization.Serializable diff --git a/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/channel/modal/ChannelRole.kt b/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/chat/channel/ChannelRole.kt index 6a3309a..be7bf58 100644 --- a/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/channel/modal/ChannelRole.kt +++ b/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/chat/channel/ChannelRole.kt @@ -1,4 +1,4 @@ -package dev.m1sk9.lunaticChat.engine.channel.modal +package dev.m1sk9.lunaticChat.engine.chat.channel import kotlinx.serialization.Serializable diff --git a/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/exception/ChatModeStorageException.kt b/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/exception/ChatModeStorageException.kt new file mode 100644 index 0000000..85c1e69 --- /dev/null +++ b/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/exception/ChatModeStorageException.kt @@ -0,0 +1,6 @@ +package dev.m1sk9.lunaticChat.engine.exception + +class ChatModeStorageException( + message: String, + cause: Throwable? = null, +) : Exception(message, cause) 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 b615fb7..838a48b 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 @@ -29,6 +29,10 @@ sealed class LunaticChatPermissionNode( object ChannelDelete : LunaticChatPermissionNode("lunaticchat.command.lc.channel.delete") + object ChatMode : LunaticChatPermissionNode("lunaticchat.command.lc.chatmode") + + object ChatModeToggle : LunaticChatPermissionNode("lunaticchat.command.lc.chatmode.toggle") + object Spy : LunaticChatPermissionNode("lunaticchat.spy") object NoticeUpdate : LunaticChatPermissionNode("lunaticchat.noticeUpdate") 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 046d61f..2473f49 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,7 +1,8 @@ package dev.m1sk9.lunaticChat.paper -import dev.m1sk9.lunaticChat.paper.channel.ChannelManager -import dev.m1sk9.lunaticChat.paper.channel.ChannelMembershipManager +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.command.core.CommandRegistry import dev.m1sk9.lunaticChat.paper.command.handler.DirectMessageHandler import dev.m1sk9.lunaticChat.paper.command.impl.ReplyCommand @@ -31,6 +32,7 @@ class LunaticChat : lateinit var languageManager: LanguageManager var channelManager: ChannelManager? = null var channelMembershipManager: ChannelMembershipManager? = null + var chatModeManager: ChatModeManager? = null // Private services private lateinit var services: ServiceContainer @@ -66,6 +68,7 @@ class LunaticChat : languageManager = services.languageManager channelManager = services.channelManager channelMembershipManager = services.channelMembershipManager + chatModeManager = services.chatModeManager // Schedule periodic tasks serviceInitializer.schedulePeriodicTasks() 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 636ccfb..c4e56cd 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,7 +1,8 @@ package dev.m1sk9.lunaticChat.paper -import dev.m1sk9.lunaticChat.paper.channel.ChannelManager -import dev.m1sk9.lunaticChat.paper.channel.ChannelMembershipManager +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.command.handler.DirectMessageHandler import dev.m1sk9.lunaticChat.paper.converter.RomanjiConverter import dev.m1sk9.lunaticChat.paper.i18n.LanguageManager @@ -19,6 +20,7 @@ import dev.m1sk9.lunaticChat.paper.settings.PlayerSettingsManager * @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) */ data class ServiceContainer( val languageManager: LanguageManager, @@ -27,4 +29,5 @@ data class ServiceContainer( val romajiConverter: RomanjiConverter? = null, val channelManager: ChannelManager? = null, val channelMembershipManager: ChannelMembershipManager? = null, + val chatModeManager: ChatModeManager? = 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 17d99f6..7865c9c 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,9 +1,11 @@ package dev.m1sk9.lunaticChat.paper import dev.m1sk9.lunaticChat.engine.converter.GoogleIMEClient -import dev.m1sk9.lunaticChat.paper.channel.ChannelManager -import dev.m1sk9.lunaticChat.paper.channel.ChannelMembershipManager -import dev.m1sk9.lunaticChat.paper.channel.ChannelStorage +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.ChannelStorage import dev.m1sk9.lunaticChat.paper.command.handler.DirectMessageHandler import dev.m1sk9.lunaticChat.paper.config.LunaticChatConfiguration import dev.m1sk9.lunaticChat.paper.converter.ConversionCache @@ -31,6 +33,7 @@ class ServiceInitializer( private var conversionCache: ConversionCache? = null private var channelManager: ChannelManager? = null private var channelMembershipManager: ChannelMembershipManager? = null + private var chatModeManager: ChatModeManager? = null /** * Initializes all services in dependency order. @@ -66,12 +69,12 @@ class ServiceInitializer( null } - // 4. Initialize channel manager and membership manager - val (channelManager, channelMembershipManager) = + // 4. Initialize channel manager, membership manager, and chat mode manager + val (channelManager, channelMembershipManager, chatModeManager) = if (configuration.features.channelChat.enabled) { initializeChannelManager() } else { - Pair(null, null) + Triple(null, null, null) } // 5. Initialize handlers @@ -88,6 +91,7 @@ class ServiceInitializer( romajiConverter = romajiConverter, channelManager = channelManager, channelMembershipManager = channelMembershipManager, + chatModeManager = chatModeManager, ) } @@ -152,9 +156,9 @@ class ServiceInitializer( } /** - * Initializes channel manager and membership manager with storage. + * Initializes channel manager, membership manager, and chat mode manager with storage. */ - private fun initializeChannelManager(): Pair<ChannelManager, ChannelMembershipManager> { + private fun initializeChannelManager(): Triple<ChannelManager, ChannelMembershipManager, ChatModeManager> { val channelsFile = plugin.dataFolder.resolve("channels.json").toPath() val storage = ChannelStorage( @@ -178,8 +182,23 @@ class ServiceInitializer( ) channelMembershipManager = membershipManager - logger.info("Channel manager and membership manager initialized successfully.") - return Pair(manager, 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 + + logger.info("Channel manager, membership manager, and chat mode manager initialized successfully.") + return Triple(manager, membershipManager, chatMode) } /** @@ -206,5 +225,6 @@ class ServiceInitializer( services.playerSettingsManager.saveToDisk() conversionCache?.saveToDisk() services.channelManager?.saveToDisk() + services.chatModeManager?.saveToDisk() } } 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 new file mode 100644 index 0000000..5f92f21 --- /dev/null +++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/ChatModeManager.kt @@ -0,0 +1,94 @@ +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) + } +} 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 new file mode 100644 index 0000000..77fcdb3 --- /dev/null +++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/ChatModeStorage.kt @@ -0,0 +1,98 @@ +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/channel/ChannelManager.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/channel/ChannelManager.kt index d18c2a5..ff3b5d8 100644 --- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/channel/ChannelManager.kt +++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/channel/ChannelManager.kt @@ -1,9 +1,9 @@ -package dev.m1sk9.lunaticChat.paper.channel +package dev.m1sk9.lunaticChat.paper.chat.channel -import dev.m1sk9.lunaticChat.engine.channel.modal.Channel -import dev.m1sk9.lunaticChat.engine.channel.modal.ChannelData -import dev.m1sk9.lunaticChat.engine.channel.modal.ChannelMember -import dev.m1sk9.lunaticChat.engine.channel.modal.ChannelRole +import dev.m1sk9.lunaticChat.engine.chat.channel.Channel +import dev.m1sk9.lunaticChat.engine.chat.channel.ChannelData +import dev.m1sk9.lunaticChat.engine.chat.channel.ChannelMember +import dev.m1sk9.lunaticChat.engine.chat.channel.ChannelRole import dev.m1sk9.lunaticChat.engine.exception.ChannelNoOwnerPermissionException import dev.m1sk9.lunaticChat.engine.exception.ChannelNotFoundException import java.util.UUID diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/channel/ChannelMembershipManager.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/channel/ChannelMembershipManager.kt index 41c96c4..6d6ad8d 100644 --- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/channel/ChannelMembershipManager.kt +++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/channel/ChannelMembershipManager.kt @@ -1,6 +1,6 @@ -package dev.m1sk9.lunaticChat.paper.channel +package dev.m1sk9.lunaticChat.paper.chat.channel -import dev.m1sk9.lunaticChat.engine.channel.modal.ChannelRole +import dev.m1sk9.lunaticChat.engine.chat.channel.ChannelRole import dev.m1sk9.lunaticChat.engine.exception.ChannelAlreadyActiveException import dev.m1sk9.lunaticChat.engine.exception.ChannelMemberAlreadyException import dev.m1sk9.lunaticChat.engine.exception.ChannelNotFoundException diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/channel/ChannelStorage.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/channel/ChannelStorage.kt index ac7d180..7176014 100644 --- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/channel/ChannelStorage.kt +++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/channel/ChannelStorage.kt @@ -1,6 +1,6 @@ -package dev.m1sk9.lunaticChat.paper.channel +package dev.m1sk9.lunaticChat.paper.chat.channel -import dev.m1sk9.lunaticChat.engine.channel.modal.ChannelData +import dev.m1sk9.lunaticChat.engine.chat.channel.ChannelData import dev.m1sk9.lunaticChat.engine.exception.ChannelStorageLoadException import dev.m1sk9.lunaticChat.engine.exception.ChannelStorageSaveException import kotlinx.serialization.json.Json @@ -33,7 +33,7 @@ class ChannelStorage( * Loads channel data from disk. * * @return The loaded ChannelData. - * @throws dev.m1sk9.lunaticChat.engine.exception.ChannelStorageLoadException if there is an error loading the data. + * @throws ChannelStorageLoadException if there is an error loading the data. */ fun loadFromDisk(): ChannelData { if (!channelsFile.exists()) { @@ -61,7 +61,7 @@ class ChannelStorage( * Saves channel data to disk. * * @param data The ChannelData to save. - * @throws dev.m1sk9.lunaticChat.engine.exception.ChannelStorageSaveException if there is an error saving the data. + * @throws ChannelStorageSaveException if there is an error saving the data. */ fun saveToDisk(data: ChannelData) { try { diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/ChannelCommand.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/ChannelCommand.kt index dfa7e9c..3e47c7e 100644 --- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/ChannelCommand.kt +++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/ChannelCommand.kt @@ -4,8 +4,8 @@ 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.channel.ChannelManager -import dev.m1sk9.lunaticChat.paper.channel.ChannelMembershipManager +import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelManager +import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelMembershipManager import dev.m1sk9.lunaticChat.paper.command.annotation.Permission import dev.m1sk9.lunaticChat.paper.command.annotation.PlayerOnly import dev.m1sk9.lunaticChat.paper.command.core.CommandContext 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 new file mode 100644 index 0000000..73a50e5 --- /dev/null +++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/ChatModeCommand.kt @@ -0,0 +1,84 @@ +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 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( + Component + .text(languageManager.getMessage("chatmode.current") + ": ", NamedTextColor.GRAY) + .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 c89f579..af08089 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 @@ -62,6 +62,17 @@ 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/channel/ChannelCreateCommand.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelCreateCommand.kt index 14254c8..29da990 100644 --- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelCreateCommand.kt +++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelCreateCommand.kt @@ -3,11 +3,11 @@ package dev.m1sk9.lunaticChat.paper.command.impl.lc.channel import com.mojang.brigadier.arguments.BoolArgumentType import com.mojang.brigadier.arguments.StringArgumentType import com.mojang.brigadier.builder.LiteralArgumentBuilder -import dev.m1sk9.lunaticChat.engine.channel.modal.Channel +import dev.m1sk9.lunaticChat.engine.chat.channel.Channel 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.channel.ChannelManager +import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelManager import dev.m1sk9.lunaticChat.paper.command.annotation.Permission import dev.m1sk9.lunaticChat.paper.command.annotation.PlayerOnly import dev.m1sk9.lunaticChat.paper.command.core.CommandContext diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelDeleteCommand.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelDeleteCommand.kt index 4d547ea..9d39c70 100644 --- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelDeleteCommand.kt +++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelDeleteCommand.kt @@ -7,7 +7,7 @@ import dev.m1sk9.lunaticChat.engine.exception.ChannelNoOwnerPermissionException import dev.m1sk9.lunaticChat.engine.exception.ChannelNotFoundException import dev.m1sk9.lunaticChat.engine.permission.LunaticChatPermissionNode import dev.m1sk9.lunaticChat.paper.LunaticChat -import dev.m1sk9.lunaticChat.paper.channel.ChannelManager +import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelManager import dev.m1sk9.lunaticChat.paper.command.annotation.Permission import dev.m1sk9.lunaticChat.paper.command.annotation.PlayerOnly import dev.m1sk9.lunaticChat.paper.command.core.CommandContext diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelJoinCommand.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelJoinCommand.kt index 4f40ad2..2a73199 100644 --- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelJoinCommand.kt +++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelJoinCommand.kt @@ -8,8 +8,8 @@ import dev.m1sk9.lunaticChat.engine.exception.ChannelMemberAlreadyException import dev.m1sk9.lunaticChat.engine.exception.ChannelNotFoundException import dev.m1sk9.lunaticChat.engine.permission.LunaticChatPermissionNode import dev.m1sk9.lunaticChat.paper.LunaticChat -import dev.m1sk9.lunaticChat.paper.channel.ChannelManager -import dev.m1sk9.lunaticChat.paper.channel.ChannelMembershipManager +import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelManager +import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelMembershipManager import dev.m1sk9.lunaticChat.paper.command.annotation.Permission import dev.m1sk9.lunaticChat.paper.command.annotation.PlayerOnly import dev.m1sk9.lunaticChat.paper.command.core.CommandContext diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelLeaveCommand.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelLeaveCommand.kt index 7b09bde..299ad47 100644 --- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelLeaveCommand.kt +++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelLeaveCommand.kt @@ -5,8 +5,8 @@ import dev.m1sk9.lunaticChat.engine.command.CommandResult import dev.m1sk9.lunaticChat.engine.exception.ChannelNotMemberException import dev.m1sk9.lunaticChat.engine.permission.LunaticChatPermissionNode import dev.m1sk9.lunaticChat.paper.LunaticChat -import dev.m1sk9.lunaticChat.paper.channel.ChannelManager -import dev.m1sk9.lunaticChat.paper.channel.ChannelMembershipManager +import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelManager +import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelMembershipManager import dev.m1sk9.lunaticChat.paper.command.annotation.Permission import dev.m1sk9.lunaticChat.paper.command.annotation.PlayerOnly import dev.m1sk9.lunaticChat.paper.command.core.CommandContext diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelListCommand.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelListCommand.kt index e2cdbb5..aaf05af 100644 --- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelListCommand.kt +++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelListCommand.kt @@ -4,7 +4,7 @@ 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.channel.ChannelManager +import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelManager import dev.m1sk9.lunaticChat.paper.command.annotation.Permission import dev.m1sk9.lunaticChat.paper.command.annotation.PlayerOnly import dev.m1sk9.lunaticChat.paper.command.core.CommandContext diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelStatusCommand.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelStatusCommand.kt index 7b5cabd..fa03965 100644 --- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelStatusCommand.kt +++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelStatusCommand.kt @@ -4,8 +4,8 @@ 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.channel.ChannelManager -import dev.m1sk9.lunaticChat.paper.channel.ChannelMembershipManager +import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelManager +import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelMembershipManager import dev.m1sk9.lunaticChat.paper.command.annotation.Permission import dev.m1sk9.lunaticChat.paper.command.annotation.PlayerOnly import dev.m1sk9.lunaticChat.paper.command.core.CommandContext diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelSwitchCommand.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelSwitchCommand.kt index ca62baf..13d44d2 100644 --- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelSwitchCommand.kt +++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/channel/ChannelSwitchCommand.kt @@ -8,8 +8,8 @@ import dev.m1sk9.lunaticChat.engine.exception.ChannelNotFoundException import dev.m1sk9.lunaticChat.engine.exception.ChannelNotMemberException import dev.m1sk9.lunaticChat.engine.permission.LunaticChatPermissionNode import dev.m1sk9.lunaticChat.paper.LunaticChat -import dev.m1sk9.lunaticChat.paper.channel.ChannelManager -import dev.m1sk9.lunaticChat.paper.channel.ChannelMembershipManager +import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelManager +import dev.m1sk9.lunaticChat.paper.chat.channel.ChannelMembershipManager import dev.m1sk9.lunaticChat.paper.command.annotation.Permission import dev.m1sk9.lunaticChat.paper.command.annotation.PlayerOnly import dev.m1sk9.lunaticChat.paper.command.core.CommandContext 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 new file mode 100644 index 0000000..cea1814 --- /dev/null +++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/lc/chatmode/ChatModeToggleCommand.kt @@ -0,0 +1,71 @@ +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) + } + + private 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/resources/languages/en.yml b/platform-paper/src/main/resources/languages/en.yml index 6834428..91a4f3b 100644 --- a/platform-paper/src/main/resources/languages/en.yml +++ b/platform-paper/src/main/resources/languages/en.yml @@ -86,6 +86,14 @@ channel: clickToSwitch: "Click to switch" error: "Failed to retrieve channel status" +chatmode: + current: "Current chat mode" + mode: + global: "GLOBAL" + channel: "CHANNEL" + toggle: + success: "Chat mode switched to" + 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 77be961..9e93ce9 100644 --- a/platform-paper/src/main/resources/languages/ja.yml +++ b/platform-paper/src/main/resources/languages/ja.yml @@ -86,6 +86,14 @@ channel: clickToSwitch: "クリックして切り替え" error: "チャンネルステータスの取得に失敗しました" +chatmode: + current: "現在のチャットモード" + mode: + global: "グローバル" + channel: "チャンネル" + toggle: + success: "チャットモードを切り替えました" + general: playerOnlyCommand: "このコマンドはプレイヤーのみが実行できます" newUpdateAvailable: "LunaticChat の新しいバージョンが利用可能です。GitHubまたはModrinthからダウンロードできます" |
