diff options
Diffstat (limited to 'platform-paper')
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. */ |
