summaryrefslogtreecommitdiff
path: root/platform-paper
diff options
context:
space:
mode:
Diffstat (limited to 'platform-paper')
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/ServiceInitializer.kt1
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/handler/ChannelMessageHandler.kt18
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/handler/DirectMessageHandler.kt21
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/converter/ConversionCache.kt15
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/SpyPermissionManager.kt25
5 files changed, 44 insertions, 36 deletions
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 6d47788..fdfb9fa 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
@@ -186,7 +186,6 @@ class ServiceInitializer(
ConversionCache(
cacheFile = plugin.dataFolder.resolve(configuration.features.japaneseConversion.cacheFilePath).toPath(),
maxEntries = configuration.features.japaneseConversion.cacheMaxEntries,
- saver = DebouncedSaver(plugin),
logger = logger,
)
cache.loadFromDisk()
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/handler/ChannelMessageHandler.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/handler/ChannelMessageHandler.kt
index 4cfd061..4da0c1a 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/handler/ChannelMessageHandler.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/handler/ChannelMessageHandler.kt
@@ -12,7 +12,6 @@ import dev.m1sk9.lunaticChat.paper.i18n.withChatPlaceholders
import dev.m1sk9.lunaticChat.paper.settings.PlayerSettingsManager
import io.ktor.util.logging.Logger
import net.kyori.adventure.text.Component
-import net.kyori.adventure.text.event.HoverEvent
import org.bukkit.Bukkit
import org.bukkit.entity.Player
@@ -44,19 +43,10 @@ class ChannelMessageHandler(
// Send to spy players (exclude sender and channel members)
val memberIds = context.members.map { it.playerId }.toSet()
- SpyPermissionManager
- .getDirectMessageSpyPlayers()
- .values
- .filter { it.isOnline && it.uniqueId != playerId && it.uniqueId !in memberIds }
- .forEach {
- it.sendMessage(
- formattedMessage.hoverEvent(
- HoverEvent.showText(
- Component.text(languageManager.getMessage("general.spyMessage")),
- ),
- ),
- )
- }
+ SpyPermissionManager.notifySpies(
+ noticeText = languageManager.getMessage("general.spyMessage"),
+ exclude = { it.uniqueId == playerId || it.uniqueId in memberIds },
+ ) { formattedMessage }
context.members.forEach { member ->
Bukkit.getPlayer(member.playerId)?.let { memberPlayer ->
if (memberPlayer.isOnline) {
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/handler/DirectMessageHandler.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/handler/DirectMessageHandler.kt
index c3fc923..ba0b5f8 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/handler/DirectMessageHandler.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/handler/DirectMessageHandler.kt
@@ -12,7 +12,6 @@ import dev.m1sk9.lunaticChat.paper.settings.PlayerSettingsManager
import dev.m1sk9.lunaticChat.paper.velocity.RemotePlayerRegistry
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.event.ClickEvent
-import net.kyori.adventure.text.event.HoverEvent
import org.bukkit.Bukkit
import org.bukkit.entity.Player
import java.util.UUID
@@ -213,20 +212,12 @@ class DirectMessageHandler(
recipientName: String,
rawMessage: String,
) {
- val spyMessage = formatMessage(format, senderName, recipientName, rawMessage, replyTo = senderName)
- SpyPermissionManager
- .getDirectMessageSpyPlayers()
- .values
- .filter { it.isOnline && it.name !in setOf(senderName, recipientName) }
- .forEach {
- it.sendMessage(
- spyMessage.hoverEvent(
- HoverEvent.showText(
- Component.text(languageManager.getMessage("general.spyMessage")),
- ),
- ),
- )
- }
+ SpyPermissionManager.notifySpies(
+ noticeText = languageManager.getMessage("general.spyMessage"),
+ exclude = { it.name == senderName || it.name == recipientName },
+ ) {
+ formatMessage(format, senderName, recipientName, rawMessage, replyTo = senderName)
+ }
}
private fun formatMessage(
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/converter/ConversionCache.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/converter/ConversionCache.kt
index ad0a9e0..fb96ba1 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/converter/ConversionCache.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/converter/ConversionCache.kt
@@ -1,10 +1,10 @@
package dev.m1sk9.lunaticChat.paper.converter
import dev.m1sk9.lunaticChat.engine.converter.CacheData
-import dev.m1sk9.lunaticChat.paper.DebouncedSaver
import kotlinx.serialization.json.Json
import java.nio.file.Path
import java.util.concurrent.ConcurrentHashMap
+import java.util.concurrent.atomic.AtomicBoolean
import java.util.logging.Logger
import kotlin.io.path.bufferedReader
import kotlin.io.path.exists
@@ -13,10 +13,10 @@ import kotlin.io.path.writeText
class ConversionCache(
private val cacheFile: Path,
private val maxEntries: Int = 500,
- private val saver: DebouncedSaver,
private val logger: Logger,
) {
private val conversionMemoryCache = ConcurrentHashMap<String, String>()
+ private val dirty = AtomicBoolean(false)
companion object {
private const val CACHE_VERSION = "1"
@@ -81,16 +81,18 @@ class ConversionCache(
}
conversionMemoryCache[key] = value
- saver.request(::saveToDisk)
+ dirty.set(true)
}
/**
- * Saves the conversion cache from memory to disk.
- * This operation is performed asynchronously.
+ * Writes the cache to disk if anything changed since the last write.
*
- * @throws Exception if an error occurs during the save operation.
+ * Called from the periodic task and at shutdown. Skipping a clean cache matters because the
+ * task fires on a fixed interval whether or not anyone chatted.
*/
fun saveToDisk() {
+ if (!dirty.getAndSet(false)) return
+
try {
val data =
CacheData(
@@ -101,6 +103,7 @@ class ConversionCache(
cacheFile.writeText(jsonBuffer)
logger.info("Saved ${conversionMemoryCache.size} cache entries to disk.")
} catch (e: Exception) {
+ dirty.set(true)
logger.severe("Failed to save conversion cache to disk: ${e.message}")
}
}
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/SpyPermissionManager.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/SpyPermissionManager.kt
index 2c56219..2e50081 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/SpyPermissionManager.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/listener/SpyPermissionManager.kt
@@ -1,6 +1,8 @@
package dev.m1sk9.lunaticChat.paper.common
import dev.m1sk9.lunaticChat.engine.permission.LunaticChatPermissionNode
+import net.kyori.adventure.text.Component
+import net.kyori.adventure.text.event.HoverEvent
import org.bukkit.Bukkit
import org.bukkit.entity.Player
import org.bukkit.event.EventHandler
@@ -23,6 +25,29 @@ object SpyPermissionManager : Listener {
fun getDirectMessageSpyPlayers(): Map<UUID, Player> = directMessageSpyPlayers.toMap()
/**
+ * Sends a copy of a message to every online spy that [exclude] does not reject.
+ *
+ * [message] is only invoked when someone will actually read the result, and the "you are
+ * seeing this because you have spy permission" hover is built once for the whole audience
+ * rather than per recipient. Spies are rare, so both matter on the message path.
+ *
+ * @param noticeText Text shown on hover, explaining why the reader is seeing the message
+ * @param exclude Rejects players who are party to the message already
+ * @param message Builds the message body
+ */
+ fun notifySpies(
+ noticeText: String,
+ exclude: (Player) -> Boolean,
+ message: () -> Component,
+ ) {
+ val spies = directMessageSpyPlayers.values.filter { it.isOnline && !exclude(it) }
+ if (spies.isEmpty()) return
+
+ val withNotice = message().hoverEvent(HoverEvent.showText(Component.text(noticeText)))
+ spies.forEach { it.sendMessage(withNotice) }
+ }
+
+ /**
* Updates the cache of players with direct message spy permission.
* Call this on player join/quit/permission change events.
*/