diff options
| author | Sho Sakuma <me@m1sk9.dev> | 2026-01-17 16:13:34 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-01-17 16:13:34 +0900 |
| commit | f43e3825d9d4eb0168f637d9a96078787860bd4a (patch) | |
| tree | d5911a0fab08dbe99e518081f3b271cab3742028 | |
| parent | d264ed43434f4bc294e38b7aced813cafd48b152 (diff) | |
| parent | 866eb45abd2ed2175ab9c65faa3a064e5eaf8405 (diff) | |
| download | LunaticChat-0.4.0.tar.gz LunaticChat-0.4.0.tar.bz2 LunaticChat-0.4.0.zip | |
Merge pull request #46 from m1sk9/feat/direct-message-noticev0.4.0
feat: Added direct message notification settings
13 files changed, 197 insertions, 9 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 5532b20..7d5ffca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,6 @@ - Change so that Japanese input settings are enabled by default. - Improved certain modules to eliminate Paper dependencies. - Added notification feature for receiving direct messages via `/tell` and `/reply`. -- Fixed an issue where the internal API documentation for LunaticChat published at `lc.api.m1sk9.dev` only referenced the `platform-paper` module. ### v0.3.1 diff --git a/docs/src/guide/permissions.md b/docs/src/guide/permissions.md index f5c27b9..3042e6f 100644 --- a/docs/src/guide/permissions.md +++ b/docs/src/guide/permissions.md @@ -39,3 +39,9 @@ LunaticChat のアップデート通知を受け取ります. - Default: `non OP` [`/jp`](../reference/commands/jp.md) コマンドの使用を切り替えます. + +### `lunaticchat.command.notice` + +- Default: `non OP` + +[`/notice`](../reference/commands/notice.md) コマンドの使用を切り替えます. diff --git a/docs/src/reference/commands/jp.md b/docs/src/reference/commands/jp.md index 04fed27..8f77b12 100644 --- a/docs/src/reference/commands/jp.md +++ b/docs/src/reference/commands/jp.md @@ -1,6 +1,6 @@ # /jp <Badge type="tip" text="v0.1.0" /> <Badge type="tip" text="Paper / Velocity" /> -### /jp [on | off] +### `/jp [on | off]` | パーミッション | |--------------------------| @@ -9,5 +9,3 @@ ローマ字変換の設定を切り替えます. この設定は UUID で保存されるため, MCID を切り替えても設定が消えることはありません. - - diff --git a/docs/src/reference/commands/notice.md b/docs/src/reference/commands/notice.md new file mode 100644 index 0000000..5cd1a2c --- /dev/null +++ b/docs/src/reference/commands/notice.md @@ -0,0 +1,11 @@ +# /notice <Badge type="tip" text="v0.4.0" /> <Badge type="tip" text="Paper / Velocity" /> + +### `/notice [on | off]` + +| パーミッション | エイリアス | +|-----------------------------|-------------| +| `lunaticchat.command.notice` | `/dmnotice` | + +[`/tell`](./tell.md) や [`/reply`](./reply.md) コマンドで送信されるダイレクトメッセージの通知をオンまたはオフに切り替えます. + +この設定は UUID で保存されるため, MCID を切り替えても設定が消えることはありません. 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 052e2ee..eab7d45 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 @@ -9,6 +9,8 @@ sealed class LunaticChatPermissionNode( object JapaneseToggle : LunaticChatPermissionNode("lunaticchat.command.jp") + object NoticeToggle : LunaticChatPermissionNode("lunaticchat.command.notice") + object Spy : LunaticChatPermissionNode("lunaticchat.spy") object NoticeUpdate : LunaticChatPermissionNode("lunaticchat.noticeUpdate") diff --git a/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/settings/PlayerChatSettings.kt b/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/settings/PlayerChatSettings.kt index 12eda6a..e970ae9 100644 --- a/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/settings/PlayerChatSettings.kt +++ b/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/settings/PlayerChatSettings.kt @@ -8,10 +8,12 @@ import java.util.UUID * * @property uuid The unique identifier of the player * @property japaneseConversionEnabled Whether romaji-to-Japanese conversion is enabled for this player + * @property directMessageNotificationEnabled Whether direct message notifications are enabled for this player */ @Serializable data class PlayerChatSettings( @Serializable(with = UUIDSerializer::class) val uuid: UUID, val japaneseConversionEnabled: Boolean = true, + val directMessageNotificationEnabled: Boolean = true, ) diff --git a/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/settings/PlayerSettingsData.kt b/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/settings/PlayerSettingsData.kt index 1fc3699..3916bbf 100644 --- a/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/settings/PlayerSettingsData.kt +++ b/engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/settings/PlayerSettingsData.kt @@ -13,10 +13,14 @@ import java.util.UUID * japaneseConversion: * ceaea267-39dd-3bac-931c-761ada671ebe: true * another-uuid-here: false + * directMessageNotification: + * ceaea267-39dd-3bac-931c-761ada671ebe: true + * another-uuid-here: false * ``` * * @property version The schema version for future compatibility * @property japaneseConversion Map of player UUIDs to their Japanese conversion enabled status + * @property directMessageNotification Map of player UUIDs to their direct message notification enabled status */ @Serializable data class PlayerSettingsData( @@ -26,4 +30,9 @@ data class PlayerSettingsData( UUID, Boolean, > = emptyMap(), + val directMessageNotification: Map< + @Serializable(with = UUIDASStringSerializer::class) + UUID, + Boolean, + > = emptyMap(), ) 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 25bf33f..7ee2fbd 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 @@ -3,6 +3,7 @@ package dev.m1sk9.lunaticChat.paper import dev.m1sk9.lunaticChat.engine.converter.GoogleIMEClient import dev.m1sk9.lunaticChat.paper.command.core.CommandRegistry import dev.m1sk9.lunaticChat.paper.command.handler.DirectMessageHandler +import dev.m1sk9.lunaticChat.paper.command.impl.DirectMessageNoticeToggleCommand import dev.m1sk9.lunaticChat.paper.command.impl.ReplyCommand import dev.m1sk9.lunaticChat.paper.command.impl.RomajiConvertToggleCommand import dev.m1sk9.lunaticChat.paper.command.impl.TellCommand @@ -167,9 +168,9 @@ class LunaticChat : private fun registerCommands(configuration: LunaticChatConfiguration) { commandRegistry = CommandRegistry(this) - // Always register /tell command commandRegistry.registerAll( TellCommand(this, directMessageHandler), + DirectMessageNoticeToggleCommand(this, playerSettingsManager!!), ) // Register /reply command if quick replies are enabled diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/handler/DirectMessageHandler.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/handler/DirectMessageHandler.kt index 60adb7e..4683c08 100644 --- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/handler/DirectMessageHandler.kt +++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/handler/DirectMessageHandler.kt @@ -1,6 +1,8 @@ package dev.m1sk9.lunaticChat.paper.command.handler import dev.m1sk9.lunaticChat.paper.common.SpyPermissionManager +import dev.m1sk9.lunaticChat.paper.common.playDirectMessageNotification +import dev.m1sk9.lunaticChat.paper.common.playDirectMessageSendNotification import dev.m1sk9.lunaticChat.paper.config.ConfigManager import dev.m1sk9.lunaticChat.paper.converter.RomanjiConverter import dev.m1sk9.lunaticChat.paper.settings.PlayerSettingsManager @@ -78,6 +80,8 @@ class DirectMessageHandler( recordMessage(sender, recipient) val senderSettings = settingsManager?.getSettings(sender.uniqueId) + val recipientSettings = settingsManager?.getSettings(recipient.uniqueId) + val displayMessage = senderSettings ?.takeIf { it.japaneseConversionEnabled } @@ -98,8 +102,16 @@ class DirectMessageHandler( .forEach { it.sendMessage(spyMessage) } val userMessage = formatMessage(format, sender.name, recipient.name, displayMessage) - sender.sendMessage(userMessage) - recipient.sendMessage(userMessage) + sender.apply { + sendMessage(userMessage) + takeIf { senderSettings?.directMessageNotificationEnabled == true } + ?.playDirectMessageSendNotification() + } + recipient.apply { + sendMessage(userMessage) + takeIf { recipientSettings?.directMessageNotificationEnabled == true } + ?.playDirectMessageNotification() + } return true } diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/DirectMessageNoticeToggleCommand.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/DirectMessageNoticeToggleCommand.kt new file mode 100644 index 0000000..7906ca9 --- /dev/null +++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/DirectMessageNoticeToggleCommand.kt @@ -0,0 +1,89 @@ +package dev.m1sk9.lunaticChat.paper.command.impl + +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.command.annotation.Command +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.settings.PlayerSettingsManager +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 + +@Command( + name = "notice", + aliases = ["dmnotice"], + description = "Toggle direct message notification", +) +@Permission(LunaticChatPermissionNode.NoticeToggle::class) +@PlayerOnly +class DirectMessageNoticeToggleCommand( + plugin: LunaticChat, + private val settingsManager: PlayerSettingsManager, +) : LunaticCommand(plugin) { + override fun buildCommand(): LiteralArgumentBuilder<CommandSourceStack> = + Commands + .literal(name) + .then( + Commands + .literal("on") + .executes { ctx -> + val context = wrapContext(ctx) + checkPlayerOnly(context)?.let { return@executes handleResult(context, it) } + val result = execute(context, true) + handleResult(context, result) + }, + ).then( + Commands + .literal("off") + .executes { ctx -> + val context = wrapContext(ctx) + checkPlayerOnly(context)?.let { return@executes handleResult(context, it) } + val result = execute(context, false) + handleResult(context, result) + }, + ).executes { ctx -> + val context = wrapContext(ctx) + checkPlayerOnly(context)?.let { return@executes handleResult(context, it) } + val result = showStatus(context) + handleResult(context, result) + } + + private fun execute( + ctx: CommandContext, + enable: Boolean, + ): CommandResult { + val player = ctx.requirePlayer() + val currentSettings = settingsManager.getSettings(player.uniqueId) + val updatedSettings = currentSettings.copy(directMessageNotificationEnabled = enable) + settingsManager.updateSettings(updatedSettings) + + val statusText = if (enable) "enabled" else "disabled" + val message = + Component + .text("Direct message notification has been $statusText.") + .color(NamedTextColor.GREEN) + + player.sendMessage(message) + return CommandResult.Success + } + + private fun showStatus(ctx: CommandContext): CommandResult { + val player = ctx.requirePlayer() + val settings = settingsManager.getSettings(player.uniqueId) + + val statusText = if (settings.directMessageNotificationEnabled) "enabled" else "disabled" + val message = + Component + .text("Direct message notification is currently $statusText.") + .color(NamedTextColor.YELLOW) + + player.sendMessage(message) + return CommandResult.Success + } +} diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/common/SoundCollector.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/common/SoundCollector.kt new file mode 100644 index 0000000..16c8d75 --- /dev/null +++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/common/SoundCollector.kt @@ -0,0 +1,48 @@ +package dev.m1sk9.lunaticChat.paper.common + +import net.kyori.adventure.key.Key +import net.kyori.adventure.sound.Sound +import org.bukkit.entity.Player + +/** + * Collection of sounds used in LunaticChat. + */ +object SoundCollector { + val LUNATIC_CLEAR_SOUND: Sound = + Sound.sound( + Key.key("block.note_block.chime"), + Sound.Source.PLAYER, + 0.8f, + 1.5f, + ) + + val LUNATIC_POP_SOUND: Sound = + Sound.sound( + Key.key("entity.experience_orb.pickup"), + Sound.Source.PLAYER, + 0.9f, + 1.4f, + ) + + val LUNATIC_SOFT_SOUND: Sound = + Sound.sound( + Key.key("block.note_block.pling"), + Sound.Source.PLAYER, + 0.6f, + 2.0f, + ) +} + +/** + * Plays the direct message notification sound to the player. + */ +fun Player.playDirectMessageNotification() { + playSound(SoundCollector.LUNATIC_CLEAR_SOUND) +} + +/** + * Plays the message sent sound to the player. + */ +fun Player.playDirectMessageSendNotification() { + playSound(SoundCollector.LUNATIC_POP_SOUND) +} diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/settings/PlayerSettingsManager.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/settings/PlayerSettingsManager.kt index 76d5776..a30618b 100644 --- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/settings/PlayerSettingsManager.kt +++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/settings/PlayerSettingsManager.kt @@ -18,6 +18,7 @@ class PlayerSettingsManager( private val logger: Logger, ) { private val japaneseConversionCache = ConcurrentHashMap<UUID, Boolean>() + private val directMessageNotificationCache = ConcurrentHashMap<UUID, Boolean>() private lateinit var settingsData: PlayerSettingsData /** @@ -27,6 +28,7 @@ class PlayerSettingsManager( fun initialize() { settingsData = storage.loadFromDisk() japaneseConversionCache.putAll(settingsData.japaneseConversion) + directMessageNotificationCache.putAll(settingsData.directMessageNotification) logger.info("Loaded settings for ${japaneseConversionCache.size} players") } @@ -38,8 +40,13 @@ class PlayerSettingsManager( * @return The player's settings */ fun getSettings(uuid: UUID): PlayerChatSettings { - val enabled = japaneseConversionCache.getOrDefault(uuid, true) - return PlayerChatSettings(uuid = uuid, japaneseConversionEnabled = enabled) + val japaneseConversionEnabled = japaneseConversionCache.getOrDefault(uuid, true) + val directMessageNotificationEnabled = directMessageNotificationCache.getOrDefault(uuid, true) + return PlayerChatSettings( + uuid = uuid, + japaneseConversionEnabled = japaneseConversionEnabled, + directMessageNotificationEnabled = directMessageNotificationEnabled, + ) } /** @@ -49,10 +56,12 @@ class PlayerSettingsManager( */ fun updateSettings(settings: PlayerChatSettings) { japaneseConversionCache[settings.uuid] = settings.japaneseConversionEnabled + directMessageNotificationCache[settings.uuid] = settings.directMessageNotificationEnabled settingsData = settingsData.copy( japaneseConversion = japaneseConversionCache.toMap(), + directMessageNotification = directMessageNotificationCache.toMap(), ) storage.queueAsyncSave(settingsData) diff --git a/platform-paper/src/main/resources/paper-plugin.yml b/platform-paper/src/main/resources/paper-plugin.yml index 3121051..af90681 100644 --- a/platform-paper/src/main/resources/paper-plugin.yml +++ b/platform-paper/src/main/resources/paper-plugin.yml @@ -15,6 +15,8 @@ permissions: default: true lunaticchat.command.jp: default: true + lunaticchat.command.notice: + default: true lunaticchat.spy: default: op |
