diff options
Diffstat (limited to 'src/main/kotlin/moe/nea/firmament')
13 files changed, 182 insertions, 81 deletions
diff --git a/src/main/kotlin/moe/nea/firmament/Firmament.kt b/src/main/kotlin/moe/nea/firmament/Firmament.kt index e4b874a..2ba54a8 100644 --- a/src/main/kotlin/moe/nea/firmament/Firmament.kt +++ b/src/main/kotlin/moe/nea/firmament/Firmament.kt @@ -14,8 +14,19 @@ import io.ktor.client.plugins.compression.* import io.ktor.client.plugins.contentnegotiation.* import io.ktor.client.plugins.logging.* import io.ktor.serialization.kotlinx.json.* -import java.nio.file.Files -import java.nio.file.Path +import kotlinx.coroutines.* +import kotlinx.serialization.json.Json +import moe.nea.firmament.commands.registerFirmamentCommand +import moe.nea.firmament.dbus.FirmamentDbusObject +import moe.nea.firmament.events.ItemTooltipEvent +import moe.nea.firmament.events.ScreenRenderPostEvent +import moe.nea.firmament.events.TickEvent +import moe.nea.firmament.events.registration.registerFirmamentChatEvents +import moe.nea.firmament.features.FeatureManager +import moe.nea.firmament.repo.HypixelStaticData +import moe.nea.firmament.repo.RepoManager +import moe.nea.firmament.util.SBData +import moe.nea.firmament.util.data.IDataHolder import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents @@ -25,30 +36,15 @@ import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents import net.fabricmc.loader.api.FabricLoader import net.fabricmc.loader.api.Version import net.fabricmc.loader.api.metadata.ModMetadata +import net.minecraft.command.CommandRegistryAccess +import net.minecraft.util.Identifier import org.apache.logging.log4j.LogManager import org.apache.logging.log4j.Logger import org.freedesktop.dbus.connections.impl.DBusConnectionBuilder import org.freedesktop.dbus.exceptions.DBusException -import kotlinx.coroutines.CoroutineName -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Job -import kotlinx.coroutines.SupervisorJob -import kotlinx.coroutines.plus -import kotlinx.coroutines.runBlocking -import kotlinx.serialization.json.Json +import java.nio.file.Files +import java.nio.file.Path import kotlin.coroutines.EmptyCoroutineContext -import net.minecraft.command.CommandRegistryAccess -import net.minecraft.util.Identifier -import moe.nea.firmament.commands.registerFirmamentCommand -import moe.nea.firmament.dbus.FirmamentDbusObject -import moe.nea.firmament.events.ItemTooltipEvent -import moe.nea.firmament.events.ScreenRenderPostEvent -import moe.nea.firmament.events.TickEvent -import moe.nea.firmament.features.FeatureManager -import moe.nea.firmament.repo.HypixelStaticData -import moe.nea.firmament.repo.RepoManager -import moe.nea.firmament.util.SBData -import moe.nea.firmament.util.data.IDataHolder object Firmament { const val MOD_ID = "firmament" @@ -134,6 +130,7 @@ object Firmament { globalJob.cancel() } }) + registerFirmamentChatEvents() ItemTooltipCallback.EVENT.register { a, b, c -> ItemTooltipEvent.publish(ItemTooltipEvent(a, b, c)) } @@ -145,5 +142,6 @@ object Firmament { }) } + fun identifier(path: String) = Identifier(MOD_ID, path) } diff --git a/src/main/kotlin/moe/nea/firmament/events/AllowChatEvent.kt b/src/main/kotlin/moe/nea/firmament/events/AllowChatEvent.kt new file mode 100644 index 0000000..4704217 --- /dev/null +++ b/src/main/kotlin/moe/nea/firmament/events/AllowChatEvent.kt @@ -0,0 +1,20 @@ +/* + * SPDX-FileCopyrightText: 2023 Linnea Gräf <nea@nea.moe> + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package moe.nea.firmament.events + +import moe.nea.firmament.util.unformattedString +import net.minecraft.text.Text + +/** + * Filter whether the user should see a chat message altogether. May or may not be called for every chat packet sent by + * the server. When that quality is desired, consider [ProcessChatEvent] instead. + */ +data class AllowChatEvent(val text: Text) : FirmamentEvent.Cancellable() { + val unformattedString = text.unformattedString + + companion object : FirmamentEventBus<AllowChatEvent>() +} diff --git a/src/main/kotlin/moe/nea/firmament/events/ClientChatLineReceivedEvent.kt b/src/main/kotlin/moe/nea/firmament/events/ClientChatLineReceivedEvent.kt deleted file mode 100644 index 0345afc..0000000 --- a/src/main/kotlin/moe/nea/firmament/events/ClientChatLineReceivedEvent.kt +++ /dev/null @@ -1,21 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023 Linnea Gräf <nea@nea.moe> - * - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -package moe.nea.firmament.events - -import net.minecraft.text.Text -import moe.nea.firmament.util.unformattedString - -/** - * Published just before a message is added to the chat gui. Cancelling only prevents rendering, not logging to the - * console. - */ -data class ClientChatLineReceivedEvent(val text: Text) : FirmamentEvent.Cancellable() { - val unformattedString = text.unformattedString - var replaceWith: Text = text - - companion object : FirmamentEventBus<ClientChatLineReceivedEvent>() -} diff --git a/src/main/kotlin/moe/nea/firmament/events/FirmamentEventBus.kt b/src/main/kotlin/moe/nea/firmament/events/FirmamentEventBus.kt index fcf9dcb..9bdcc26 100644 --- a/src/main/kotlin/moe/nea/firmament/events/FirmamentEventBus.kt +++ b/src/main/kotlin/moe/nea/firmament/events/FirmamentEventBus.kt @@ -20,10 +20,10 @@ open class FirmamentEventBus<T : FirmamentEvent> { private val toHandle: MutableList<Handler<T>> = CopyOnWriteArrayList() fun subscribe(handle: (T) -> Unit) { - subscribe(handle, false) + subscribe(false, handle) } - fun subscribe(handle: (T) -> Unit, receivesCancelled: Boolean) { + fun subscribe(receivesCancelled: Boolean, handle: (T) -> Unit) { toHandle.add(Handler(handle, receivesCancelled)) } diff --git a/src/main/kotlin/moe/nea/firmament/events/ModifyChatEvent.kt b/src/main/kotlin/moe/nea/firmament/events/ModifyChatEvent.kt new file mode 100644 index 0000000..b5a53bc --- /dev/null +++ b/src/main/kotlin/moe/nea/firmament/events/ModifyChatEvent.kt @@ -0,0 +1,25 @@ +/* + * SPDX-FileCopyrightText: 2023 Linnea Gräf <nea@nea.moe> + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package moe.nea.firmament.events + +import moe.nea.firmament.util.unformattedString +import net.minecraft.text.Text + +/** + * Allow modification of a chat message before it is sent off to the user. Intended for display purposes. + */ +data class ModifyChatEvent(val originalText: Text) : FirmamentEvent() { + var unformattedString = originalText.unformattedString + private set + var replaceWith: Text = originalText + set(value) { + field = value + unformattedString = value.unformattedString + } + + companion object : FirmamentEventBus<ModifyChatEvent>() +} diff --git a/src/main/kotlin/moe/nea/firmament/events/ProcessChatEvent.kt b/src/main/kotlin/moe/nea/firmament/events/ProcessChatEvent.kt new file mode 100644 index 0000000..413c209 --- /dev/null +++ b/src/main/kotlin/moe/nea/firmament/events/ProcessChatEvent.kt @@ -0,0 +1,25 @@ +/* + * SPDX-FileCopyrightText: 2023 Linnea Gräf <nea@nea.moe> + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package moe.nea.firmament.events + +import moe.nea.firmament.util.unformattedString +import net.minecraft.text.Text + +/** + * Behaves like [AllowChatEvent], but is triggered even when cancelled by other mods. Intended for data collection. + * Make sure to subscribe to cancellable events as well when using. + */ +data class ProcessChatEvent(val text: Text, val wasExternallyCancelled: Boolean) : FirmamentEvent.Cancellable() { + val unformattedString = text.unformattedString + + init { + if (wasExternallyCancelled) + cancelled = true + } + + companion object : FirmamentEventBus<ProcessChatEvent>() +} diff --git a/src/main/kotlin/moe/nea/firmament/events/ServerChatLineReceivedEvent.kt b/src/main/kotlin/moe/nea/firmament/events/ServerChatLineReceivedEvent.kt deleted file mode 100644 index b8b262d..0000000 --- a/src/main/kotlin/moe/nea/firmament/events/ServerChatLineReceivedEvent.kt +++ /dev/null @@ -1,19 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023 Linnea Gräf <nea@nea.moe> - * - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -package moe.nea.firmament.events - -import net.minecraft.text.Text -import moe.nea.firmament.util.unformattedString - -/** - * This event gets published whenever the client receives a chat message from the server. - * This event is cancellable, but should not get cancelled. Use [ClientChatLineReceivedEvent] for that instead. */ -data class ServerChatLineReceivedEvent(val text: Text) : FirmamentEvent.Cancellable() { - val unformattedString = text.unformattedString - - companion object : FirmamentEventBus<ServerChatLineReceivedEvent>() -} diff --git a/src/main/kotlin/moe/nea/firmament/events/registration/ChatEvents.kt b/src/main/kotlin/moe/nea/firmament/events/registration/ChatEvents.kt new file mode 100644 index 0000000..90a665a --- /dev/null +++ b/src/main/kotlin/moe/nea/firmament/events/registration/ChatEvents.kt @@ -0,0 +1,42 @@ +/* + * SPDX-FileCopyrightText: 2023 Linnea Gräf <nea@nea.moe> + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package moe.nea.firmament.events.registration + +import moe.nea.firmament.events.AllowChatEvent +import moe.nea.firmament.events.ModifyChatEvent +import moe.nea.firmament.events.ProcessChatEvent +import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents +import net.minecraft.text.Text + +private var lastReceivedMessage: Text? = null + +fun registerFirmamentChatEvents() { + ClientReceiveMessageEvents.ALLOW_CHAT.register(ClientReceiveMessageEvents.AllowChat { message, signedMessage, sender, params, receptionTimestamp -> + lastReceivedMessage = message + !ProcessChatEvent.publish(ProcessChatEvent(message, false)).cancelled + && !AllowChatEvent.publish(AllowChatEvent(message)).cancelled + }) + ClientReceiveMessageEvents.ALLOW_GAME.register(ClientReceiveMessageEvents.AllowGame { message, overlay -> + lastReceivedMessage = message + overlay || (!ProcessChatEvent.publish(ProcessChatEvent(message, false)).cancelled && + !AllowChatEvent.publish(AllowChatEvent(message)).cancelled) + }) + ClientReceiveMessageEvents.MODIFY_GAME.register(ClientReceiveMessageEvents.ModifyGame { message, overlay -> + if (overlay) message + else ModifyChatEvent.publish(ModifyChatEvent(message)).replaceWith + }) + ClientReceiveMessageEvents.GAME_CANCELED.register(ClientReceiveMessageEvents.GameCanceled { message, overlay -> + if (!overlay && lastReceivedMessage !== message) { + ProcessChatEvent.publish(ProcessChatEvent(message, true)) + } + }) + ClientReceiveMessageEvents.CHAT_CANCELED.register(ClientReceiveMessageEvents.ChatCanceled { message, signedMessage, sender, params, receptionTimestamp -> + if (lastReceivedMessage !== message) { + ProcessChatEvent.publish(ProcessChatEvent(message, true)) + } + }) +} diff --git a/src/main/kotlin/moe/nea/firmament/features/FeatureManager.kt b/src/main/kotlin/moe/nea/firmament/features/FeatureManager.kt index 91f5e03..781237e 100644 --- a/src/main/kotlin/moe/nea/firmament/features/FeatureManager.kt +++ b/src/main/kotlin/moe/nea/firmament/features/FeatureManager.kt @@ -12,6 +12,7 @@ import moe.nea.firmament.Firmament import moe.nea.firmament.features.chat.ChatLinks import moe.nea.firmament.features.debug.DebugView import moe.nea.firmament.features.debug.DeveloperFeatures +import moe.nea.firmament.features.debug.MinorTrolling import moe.nea.firmament.features.fixes.Fixes import moe.nea.firmament.features.inventory.CraftingOverlay import moe.nea.firmament.features.inventory.PriceData @@ -41,6 +42,7 @@ object FeatureManager : DataHolder<FeatureManager.Config>(serializer(), "feature fun autoload() { synchronized(this) { if (hasAutoloaded) return + loadFeature(MinorTrolling) loadFeature(FairySouls) // TODO: loadFeature(FishingWarning) loadFeature(SlotLocking) diff --git a/src/main/kotlin/moe/nea/firmament/features/chat/ChatLinks.kt b/src/main/kotlin/moe/nea/firmament/features/chat/ChatLinks.kt index 1ce5a1b..fb3c0c2 100644 --- a/src/main/kotlin/moe/nea/firmament/features/chat/ChatLinks.kt +++ b/src/main/kotlin/moe/nea/firmament/features/chat/ChatLinks.kt @@ -26,7 +26,7 @@ import net.minecraft.text.Text import net.minecraft.util.Formatting import net.minecraft.util.Identifier import moe.nea.firmament.Firmament -import moe.nea.firmament.events.ClientChatLineReceivedEvent +import moe.nea.firmament.events.ModifyChatEvent import moe.nea.firmament.events.ScreenRenderPostEvent import moe.nea.firmament.features.FirmamentFeature import moe.nea.firmament.gui.config.ManagedConfig @@ -98,9 +98,9 @@ object ChatLinks : FirmamentFeature { @OptIn(ExperimentalCoroutinesApi::class) override fun onLoad() { - ClientChatLineReceivedEvent.subscribe { + ModifyChatEvent.subscribe { if (TConfig.enableLinks) - it.replaceWith = it.text.transformEachRecursively { child -> + it.replaceWith = it.replaceWith.transformEachRecursively { child -> val text = child.string if ("://" !in text) return@transformEachRecursively child val s = Text.empty().setStyle(child.style) diff --git a/src/main/kotlin/moe/nea/firmament/features/debug/MinorTrolling.kt b/src/main/kotlin/moe/nea/firmament/features/debug/MinorTrolling.kt new file mode 100644 index 0000000..95c77ab --- /dev/null +++ b/src/main/kotlin/moe/nea/firmament/features/debug/MinorTrolling.kt @@ -0,0 +1,31 @@ +/* + * SPDX-FileCopyrightText: 2023 Linnea Gräf <nea@nea.moe> + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package moe.nea.firmament.features.debug + +import moe.nea.firmament.events.ModifyChatEvent +import moe.nea.firmament.features.FirmamentFeature +import net.minecraft.text.Text + + +// In memorian Dulkir +object MinorTrolling : FirmamentFeature { + override val identifier: String + get() = "minor-trolling" + + val trollers = listOf("nea89o", "lrg89") + val t = "From(?: \\[[^\\]]+])? ([^:]+): (.*)".toRegex() + + override fun onLoad() { + ModifyChatEvent.subscribe { + val m = t.matchEntire(it.unformattedString) ?: return@subscribe + val (_, name, text) = m.groupValues + if (name !in trollers) return@subscribe + if (!text.startsWith("c:")) return@subscribe + it.replaceWith = Text.literal(text.substring(2).replace("&", "§")) + } + } +} diff --git a/src/main/kotlin/moe/nea/firmament/features/world/FairySouls.kt b/src/main/kotlin/moe/nea/firmament/features/world/FairySouls.kt index c1ccfc4..462325e 100644 --- a/src/main/kotlin/moe/nea/firmament/features/world/FairySouls.kt +++ b/src/main/kotlin/moe/nea/firmament/features/world/FairySouls.kt @@ -17,7 +17,7 @@ import net.minecraft.client.render.VertexFormat import net.minecraft.client.render.VertexFormats import net.minecraft.text.Text import net.minecraft.util.math.Vec3d -import moe.nea.firmament.events.ServerChatLineReceivedEvent +import moe.nea.firmament.events.AllowChatEvent import moe.nea.firmament.events.SkyblockServerUpdateEvent import moe.nea.firmament.events.WorldRenderLastEvent import moe.nea.firmament.features.FirmamentFeature @@ -125,7 +125,7 @@ object FairySouls : FirmamentFeature { updateWorldSouls() updateMissingSouls() } - ServerChatLineReceivedEvent.subscribe { + AllowChatEvent.subscribe { when (it.text.unformattedString) { "You have already found that Fairy Soul!" -> { markNearestSoul() diff --git a/src/main/kotlin/moe/nea/firmament/util/SBData.kt b/src/main/kotlin/moe/nea/firmament/util/SBData.kt index 8af905e..fdec432 100644 --- a/src/main/kotlin/moe/nea/firmament/util/SBData.kt +++ b/src/main/kotlin/moe/nea/firmament/util/SBData.kt @@ -6,18 +6,17 @@ package moe.nea.firmament.util -import java.util.* import kotlinx.serialization.SerializationException import kotlinx.serialization.decodeFromString -import kotlin.time.Duration -import kotlin.time.Duration.Companion.seconds -import net.minecraft.network.packet.c2s.play.CommandExecutionC2SPacket import moe.nea.firmament.Firmament -import moe.nea.firmament.events.ClientChatLineReceivedEvent import moe.nea.firmament.events.OutgoingPacketEvent -import moe.nea.firmament.events.ServerChatLineReceivedEvent +import moe.nea.firmament.events.ProcessChatEvent import moe.nea.firmament.events.SkyblockServerUpdateEvent import moe.nea.firmament.events.WorldReadyEvent +import net.minecraft.network.packet.c2s.play.CommandExecutionC2SPacket +import java.util.* +import kotlin.time.Duration +import kotlin.time.Duration.Companion.seconds object SBData { private val profileRegex = "Profile ID: ([a-z0-9\\-]+)".toRegex() @@ -38,7 +37,7 @@ object SBData { anyLocrawSent.markNow() } } - ServerChatLineReceivedEvent.subscribe { event -> + ProcessChatEvent.subscribe(receivesCancelled = true) { event -> val profileMatch = profileRegex.matchEntire(event.unformattedString) if (profileMatch != null) { try { @@ -54,23 +53,22 @@ object SBData { } if (event.unformattedString.startsWith("{")) { if (tryReceiveLocraw(event.unformattedString)) { + if (lastLocrawSent.timePassed() < locrawRoundtripTime) { + lastLocrawSent.markFarPast() + event.cancel() + } if (!hasValidLocraw && !hasSentLocraw && hasReceivedProfile) { sendLocraw() } } } } - ClientChatLineReceivedEvent.subscribe { event -> - if (event.unformattedString.startsWith("{") && tryReceiveLocraw(event.unformattedString) && lastLocrawSent.timePassed() < locrawRoundtripTime) { - lastLocrawSent.markFarPast() - event.cancel() - } - } WorldReadyEvent.subscribe { locraw = null hasSentLocraw = false hasReceivedProfile = false + profileId = null } } |