summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSho Sakuma <me@m1sk9.dev>2026-01-17 16:13:34 +0900
committerGitHub <noreply@github.com>2026-01-17 16:13:34 +0900
commitf43e3825d9d4eb0168f637d9a96078787860bd4a (patch)
treed5911a0fab08dbe99e518081f3b271cab3742028
parentd264ed43434f4bc294e38b7aced813cafd48b152 (diff)
parent866eb45abd2ed2175ab9c65faa3a064e5eaf8405 (diff)
downloadLunaticChat-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
-rw-r--r--CHANGELOG.md1
-rw-r--r--docs/src/guide/permissions.md6
-rw-r--r--docs/src/reference/commands/jp.md4
-rw-r--r--docs/src/reference/commands/notice.md11
-rw-r--r--engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/permission/LunaticChatPermissionNode.kt2
-rw-r--r--engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/settings/PlayerChatSettings.kt2
-rw-r--r--engine/src/main/kotlin/dev/m1sk9/lunaticChat/engine/settings/PlayerSettingsData.kt9
-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/command/handler/DirectMessageHandler.kt16
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/command/impl/DirectMessageNoticeToggleCommand.kt89
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/common/SoundCollector.kt48
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/settings/PlayerSettingsManager.kt13
-rw-r--r--platform-paper/src/main/resources/paper-plugin.yml2
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