From 65fff766370e5dbab6c751ff9082174e3ab17a52 Mon Sep 17 00:00:00 2001 From: Saphire Date: Tue, 29 Apr 2025 22:58:37 +0600 Subject: [PATCH 1/5] Implement untested actions for dealing with chat timestamp, record them too Also fixes a Fabric-only bug where global messages get recorded only when someone doesn't have a prefix set up --- .../actions/strings/OpChatTimestamp.kt | 18 +++++++++++++ .../actions/strings/OpClearChatString.kt | 17 ++++++++++++ .../moreiotas/xplat/IXplatAbstractions.java | 4 +++ .../fabric/eventhandlers/ChatEventHandler.kt | 27 +++++++++++++++---- .../fabric/xplat/FabricXplatImpl.java | 10 +++++++ 5 files changed, 71 insertions(+), 5 deletions(-) create mode 100644 Common/src/main/java/ram/talia/moreiotas/common/casting/actions/strings/OpChatTimestamp.kt create mode 100644 Common/src/main/java/ram/talia/moreiotas/common/casting/actions/strings/OpClearChatString.kt diff --git a/Common/src/main/java/ram/talia/moreiotas/common/casting/actions/strings/OpChatTimestamp.kt b/Common/src/main/java/ram/talia/moreiotas/common/casting/actions/strings/OpChatTimestamp.kt new file mode 100644 index 00000000..1f9c9882 --- /dev/null +++ b/Common/src/main/java/ram/talia/moreiotas/common/casting/actions/strings/OpChatTimestamp.kt @@ -0,0 +1,18 @@ +package ram.talia.moreiotas.common.casting.actions.strings + +import at.petrak.hexcasting.api.casting.castables.ConstMediaAction +import at.petrak.hexcasting.api.casting.asActionResult +import at.petrak.hexcasting.api.casting.eval.CastingEnvironment +import at.petrak.hexcasting.api.casting.iota.Iota +import net.minecraft.world.entity.player.Player +import ram.talia.moreiotas.api.asActionResult +import ram.talia.moreiotas.xplat.IXplatAbstractions + +class OpChatTimestamp(private val allChat: Boolean) : ConstMediaAction { + override val argc = 0 + + override fun execute(args: List, env: CastingEnvironment): List { + return IXplatAbstractions.INSTANCE.lastMessageTimestamp(if (allChat) null else env.castingEntity as? Player)?.asActionResult ?: + null.asActionResult + } +} \ No newline at end of file diff --git a/Common/src/main/java/ram/talia/moreiotas/common/casting/actions/strings/OpClearChatString.kt b/Common/src/main/java/ram/talia/moreiotas/common/casting/actions/strings/OpClearChatString.kt new file mode 100644 index 00000000..a4fbe170 --- /dev/null +++ b/Common/src/main/java/ram/talia/moreiotas/common/casting/actions/strings/OpClearChatString.kt @@ -0,0 +1,17 @@ +package ram.talia.moreiotas.common.casting.actions.strings + +import at.petrak.hexcasting.api.casting.castables.ConstMediaAction +import at.petrak.hexcasting.api.casting.eval.CastingEnvironment +import at.petrak.hexcasting.api.casting.iota.Iota +import net.minecraft.world.entity.player.Player +import ram.talia.moreiotas.api.asActionResult +import ram.talia.moreiotas.xplat.IXplatAbstractions + +class OpClearChatString() : ConstMediaAction { + override val argc = 0 + + override fun execute(args: List, env: CastingEnvironment): List { + IXplatAbstractions.INSTANCE.resetMessage(env.castingEntity as Player); + return listOf() + } +} \ No newline at end of file diff --git a/Common/src/main/java/ram/talia/moreiotas/xplat/IXplatAbstractions.java b/Common/src/main/java/ram/talia/moreiotas/xplat/IXplatAbstractions.java index 2e62b80e..19722b8f 100644 --- a/Common/src/main/java/ram/talia/moreiotas/xplat/IXplatAbstractions.java +++ b/Common/src/main/java/ram/talia/moreiotas/xplat/IXplatAbstractions.java @@ -66,6 +66,10 @@ public interface IXplatAbstractions { @Nullable String lastMessage(@Nullable Player player); + void resetMessage(Player player); + + @Nullable long lastMessageTimestamp(@Nullable Player player); + void setChatPrefix(Player player, @Nullable String prefix); @Nullable String getChatPrefix(Player player); diff --git a/Fabric/src/main/java/ram/talia/moreiotas/fabric/eventhandlers/ChatEventHandler.kt b/Fabric/src/main/java/ram/talia/moreiotas/fabric/eventhandlers/ChatEventHandler.kt index 1148f3a2..bab87e2d 100644 --- a/Fabric/src/main/java/ram/talia/moreiotas/fabric/eventhandlers/ChatEventHandler.kt +++ b/Fabric/src/main/java/ram/talia/moreiotas/fabric/eventhandlers/ChatEventHandler.kt @@ -11,6 +11,9 @@ object ChatEventHandler { private val lastMessages: MutableMap = mutableMapOf() private var lastMessage: String? = null + private val lastMessageTimestamps: MutableMap = mutableMapOf() + private var lastMessageTimestamp: Long? = null + fun receiveChat(message: PlayerChatMessage, player: ServerPlayer, params: ChatType.Bound): Boolean { val text = message.signedBody.content + (message.unsignedContent?.string ?: "") @@ -19,17 +22,31 @@ object ChatEventHandler { if (prefix == null) { lastMessages[player.uuid] = text lastMessage = text + lastMessageTimestamp = player.serverLevel().gameTime + lastMessageTimestamps[player.uuid] = lastMessageTimestamp return true } - if (!text.startsWith(prefix)) - return true - - lastMessages[player.uuid] = text.substring(prefix.length) + if (text.startsWith(prefix)) { + lastMessages[player.uuid] = text.substring(prefix.length) + lastMessageTimestamps[player.uuid] = player.serverLevel().gameTime + return false + } - return false + lastMessage = text + lastMessageTimestamp = player.serverLevel().gameTime + return true } @JvmStatic fun lastMessage(player: Player?): String? = if (player != null) lastMessages[player.uuid] else lastMessage + + @JvmStatic + fun lastMessageTimestamp(player: Player?): Long? = if (player != null) lastMessageTimestamps[player.uuid] else lastMessageTimestamp + + @JvmStatic + fun resetMessage(player: Player): Unit { + lastMessages[player.uuid] = null + lastMessageTimestamps[player.uuid] = null + } } \ No newline at end of file diff --git a/Fabric/src/main/java/ram/talia/moreiotas/fabric/xplat/FabricXplatImpl.java b/Fabric/src/main/java/ram/talia/moreiotas/fabric/xplat/FabricXplatImpl.java index 72943eb0..0ff92950 100644 --- a/Fabric/src/main/java/ram/talia/moreiotas/fabric/xplat/FabricXplatImpl.java +++ b/Fabric/src/main/java/ram/talia/moreiotas/fabric/xplat/FabricXplatImpl.java @@ -79,6 +79,16 @@ public boolean isBreakingAllowed (Level level, BlockPos pos, BlockState state, P return ChatEventHandler.lastMessage(player); } + @Override + public void resetMessage(Player player) { + ChatEventHandler.resetMessage(player); + } + + @Override + public @Nullable long lastMessageTimestamp(@Nullable Player player) { + return ChatEventHandler.lastMessageTimestamp(player); + } + @Override public void setChatPrefix(Player player, String prefix) { MoreIotasCardinalComponents.CHAT_PREFIX_HOLDER.get(player).setPrefix(prefix); From dc9beceaa0e2e0cc10df00f7f9277593e49f2bbd Mon Sep 17 00:00:00 2001 From: Saphire Date: Wed, 30 Apr 2025 03:36:24 +0600 Subject: [PATCH 2/5] Add untested chatlog, make a mess of Kotlin and Java lists --- .../ram/talia/moreiotas/api/OperatorUtils.kt | 1 + .../talia/moreiotas/api/util/ChatEntry.java | 3 ++ .../casting/actions/strings/OpChatLog.kt | 33 ++++++++++++++ .../actions/strings/OpClearChatString.kt | 17 ------- .../common/lib/hex/MoreIotasActions.kt | 6 +++ .../moreiotas/xplat/IXplatAbstractions.java | 7 +-- .../en_us/entries/patterns/strings.json | 24 ++++++++++ .../assets/moreiotas/lang/en_us.json | 6 +++ .../fabric/eventhandlers/ChatEventHandler.kt | 45 ++++++++++++------- .../fabric/xplat/FabricXplatImpl.java | 12 +++-- 10 files changed, 113 insertions(+), 41 deletions(-) create mode 100644 Common/src/main/java/ram/talia/moreiotas/api/util/ChatEntry.java create mode 100644 Common/src/main/java/ram/talia/moreiotas/common/casting/actions/strings/OpChatLog.kt delete mode 100644 Common/src/main/java/ram/talia/moreiotas/common/casting/actions/strings/OpClearChatString.kt diff --git a/Common/src/main/java/ram/talia/moreiotas/api/OperatorUtils.kt b/Common/src/main/java/ram/talia/moreiotas/api/OperatorUtils.kt index 5e1b7a80..e70ab68b 100644 --- a/Common/src/main/java/ram/talia/moreiotas/api/OperatorUtils.kt +++ b/Common/src/main/java/ram/talia/moreiotas/api/OperatorUtils.kt @@ -15,6 +15,7 @@ import net.minecraft.world.phys.Vec3 import org.jblas.DoubleMatrix import ram.talia.moreiotas.api.casting.iota.* import ram.talia.moreiotas.api.util.Anyone +import ram.talia.moreiotas.api.util.ChatEntry operator fun Double.times(vec: Vec3): Vec3 = vec.scale(this) operator fun Vec3.times(d: Double): Vec3 = this.scale(d) diff --git a/Common/src/main/java/ram/talia/moreiotas/api/util/ChatEntry.java b/Common/src/main/java/ram/talia/moreiotas/api/util/ChatEntry.java new file mode 100644 index 00000000..e017695a --- /dev/null +++ b/Common/src/main/java/ram/talia/moreiotas/api/util/ChatEntry.java @@ -0,0 +1,3 @@ +package ram.talia.moreiotas.api.util; + +public record ChatEntry(String message, long worldTime, String username) { } \ No newline at end of file diff --git a/Common/src/main/java/ram/talia/moreiotas/common/casting/actions/strings/OpChatLog.kt b/Common/src/main/java/ram/talia/moreiotas/common/casting/actions/strings/OpChatLog.kt new file mode 100644 index 00000000..29e32f94 --- /dev/null +++ b/Common/src/main/java/ram/talia/moreiotas/common/casting/actions/strings/OpChatLog.kt @@ -0,0 +1,33 @@ +package ram.talia.moreiotas.common.casting.actions.strings + +import at.petrak.hexcasting.api.casting.castables.ConstMediaAction +import at.petrak.hexcasting.api.casting.eval.CastingEnvironment +import at.petrak.hexcasting.api.casting.getPositiveIntUnder +import at.petrak.hexcasting.api.casting.iota.Iota +import at.petrak.hexcasting.api.casting.iota.DoubleIota +import at.petrak.hexcasting.api.casting.iota.ListIota +import net.minecraft.world.entity.player.Player +import ram.talia.moreiotas.api.asActionResult +import ram.talia.moreiotas.api.casting.iota.StringIota as ApiStringIota +import ram.talia.moreiotas.xplat.IXplatAbstractions + +class OpChatLog() : ConstMediaAction { + override val argc = 1 + + override fun execute(args: List, env: CastingEnvironment): List { + val count = args.getPositiveIntUnder(0, 1024, argc) + //return IXplatAbstractions.INSTANCE.chatLog(count).asActionResult as List + var logs = IXplatAbstractions.INSTANCE.chatLog(count); + val messages = mutableListOf() + val timestamps = mutableListOf() + val names = mutableListOf() + + for (entry in logs) { + messages.add(ApiStringIota.make(entry.message)) + timestamps.add(DoubleIota(entry.worldTime as Double)) + names.add(ApiStringIota.make(entry.username)) + } + + return listOf(ListIota(messages), ListIota(timestamps), ListIota(names)) + } +} \ No newline at end of file diff --git a/Common/src/main/java/ram/talia/moreiotas/common/casting/actions/strings/OpClearChatString.kt b/Common/src/main/java/ram/talia/moreiotas/common/casting/actions/strings/OpClearChatString.kt deleted file mode 100644 index a4fbe170..00000000 --- a/Common/src/main/java/ram/talia/moreiotas/common/casting/actions/strings/OpClearChatString.kt +++ /dev/null @@ -1,17 +0,0 @@ -package ram.talia.moreiotas.common.casting.actions.strings - -import at.petrak.hexcasting.api.casting.castables.ConstMediaAction -import at.petrak.hexcasting.api.casting.eval.CastingEnvironment -import at.petrak.hexcasting.api.casting.iota.Iota -import net.minecraft.world.entity.player.Player -import ram.talia.moreiotas.api.asActionResult -import ram.talia.moreiotas.xplat.IXplatAbstractions - -class OpClearChatString() : ConstMediaAction { - override val argc = 0 - - override fun execute(args: List, env: CastingEnvironment): List { - IXplatAbstractions.INSTANCE.resetMessage(env.castingEntity as Player); - return listOf() - } -} \ No newline at end of file diff --git a/Common/src/main/java/ram/talia/moreiotas/common/lib/hex/MoreIotasActions.kt b/Common/src/main/java/ram/talia/moreiotas/common/lib/hex/MoreIotasActions.kt index bb3a71ac..0e9a784c 100644 --- a/Common/src/main/java/ram/talia/moreiotas/common/lib/hex/MoreIotasActions.kt +++ b/Common/src/main/java/ram/talia/moreiotas/common/lib/hex/MoreIotasActions.kt @@ -61,6 +61,12 @@ object MoreIotasActions { @JvmField val STRING_CHAT_ALL = make("string/chat/all", fromAngles("wded", EAST), OpChatString(true)) @JvmField + val STRING_CHAT_TIMESTAMP_CASTER = make("string/chat/timestamp/caster", fromAngles("waqawddw", EAST), OpChatTimestamp(false)) + @JvmField + val STRING_CHAT_TIMESTAMP_ALL = make("string/chat/timestamp/all", fromAngles("wdedwaaw", EAST), OpChatTimestamp(true)) + @JvmField + val STRING_CHAT_LOG = make("string/chat/log", fromAngles("wwwdwewdwwaawd", EAST), OpChatLog()) + @JvmField val STRING_CHAT_PREFIX_GET = make("string/chat/prefix/get", fromAngles("ewded", NORTH_EAST), OpGetChatPrefix) @JvmField val STRING_CHAT_PREFIX_SET = make("string/chat/prefix/set", fromAngles("qwaqa", SOUTH_EAST), OpSetChatPrefix) diff --git a/Common/src/main/java/ram/talia/moreiotas/xplat/IXplatAbstractions.java b/Common/src/main/java/ram/talia/moreiotas/xplat/IXplatAbstractions.java index 19722b8f..82ca5287 100644 --- a/Common/src/main/java/ram/talia/moreiotas/xplat/IXplatAbstractions.java +++ b/Common/src/main/java/ram/talia/moreiotas/xplat/IXplatAbstractions.java @@ -11,7 +11,9 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.Nullable; +import ram.talia.moreiotas.api.util.ChatEntry; +import java.util.List; import java.util.ServiceLoader; import java.util.stream.Collectors; @@ -66,10 +68,10 @@ public interface IXplatAbstractions { @Nullable String lastMessage(@Nullable Player player); - void resetMessage(Player player); - @Nullable long lastMessageTimestamp(@Nullable Player player); + List chatLog(int count); + void setChatPrefix(Player player, @Nullable String prefix); @Nullable String getChatPrefix(Player player); @@ -96,5 +98,4 @@ private static IXplatAbstractions find() { return provider.get(); } } - } diff --git a/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/strings.json b/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/strings.json index dbcbeef7..bf47be75 100644 --- a/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/strings.json +++ b/Common/src/main/resources/assets/hexcasting/patchouli_books/thehexbook/en_us/entries/patterns/strings.json @@ -105,6 +105,30 @@ "output": "str", "text": "moreiotas.page.strings.string/chat/all" }, + { + "type": "hexcasting:pattern", + "op_id": "moreiotas:string/chat/timestamp/caster", + "anchor": "moreiotas:string/chat/timestamp/caster", + "input": "", + "output": "str", + "text": "moreiotas.page.strings.string/chat/timestamp/caster" + }, + { + "type": "hexcasting:pattern", + "op_id": "moreiotas:string/chat/timestamp/all", + "anchor": "moreiotas:string/chat/timestamp/all", + "input": "", + "output": "str", + "text": "moreiotas.page.strings.string/chat/timestamp/all" + }, + { + "type": "hexcasting:pattern", + "op_id": "moreiotas:string/chat/log/all", + "anchor": "moreiotas:string/chat/log/all", + "input": "", + "output": "str", + "text": "moreiotas.page.strings.string/chat/log/all" + }, { "type": "hexcasting:pattern", "op_id": "moreiotas:string/chat/prefix/set", diff --git a/Common/src/main/resources/assets/moreiotas/lang/en_us.json b/Common/src/main/resources/assets/moreiotas/lang/en_us.json index b89b3159..7d650a71 100644 --- a/Common/src/main/resources/assets/moreiotas/lang/en_us.json +++ b/Common/src/main/resources/assets/moreiotas/lang/en_us.json @@ -23,6 +23,9 @@ "hexcasting.action.moreiotas:string/block/set": "Write", "hexcasting.action.moreiotas:string/chat/caster": "Whisper Reflection", "hexcasting.action.moreiotas:string/chat/all": "Listener's Reflection", + "hexcasting.action.moreiotas:string/chat/timestamp/caster": "Sandglass' Reflection", + "hexcasting.action.moreiotas:string/chat/timestamp/all": "Clocktower's Reflection", + "hexcasting.action.moreiotas:string/chat/log/all": "Stenographer's Reflection", "hexcasting.action.moreiotas:string/chat/prefix/get": "Sifter's Reflection", "hexcasting.action.moreiotas:string/chat/prefix/set": "Sifter's Gambit", "hexcasting.action.moreiotas:string/iota": "Scrivener's Purification", @@ -90,6 +93,9 @@ "moreiotas.page.strings.string/block/set": "Removes a vector and a string from the stack. If that vector is pointing at a sign or lectern, it writes that string to that sign or lectern. Costs a hundredth of an $(l:items/amethyst)$(item)Amethyst Dust/$.", "moreiotas.page.strings.string/chat/caster": "Adds the last message the caster sent to the stack as a string.", "moreiotas.page.strings.string/chat/all": "Adds the last message anyone sent to the stack as a string.", + "moreiotas.page.strings.string/chat/timestamp/caster": "Returns the time in 20th of a second since the world's beginning, to when the caster sent the last message.", + "moreiotas.page.strings.string/chat/timestamp/all": "Similar to $(l:moreiotas:patterns/strings#moreiotas:string/chat/timestamp/caster)$(action)Sandglass' Reflection/$, but gives back the time since anyone sent out a message for all to hear. Oddly, returns a count too. It's not like two people can speak at the same single instant, right?", + "moreiotas.page.strings.string/chat/log/all": "All that's spoken loudly enough gets recorded by the Nature, up to a limit. This pattern returns what was said, when, and by whom. The names are not what I see, but what Nature knows people by, though...", "moreiotas.page.strings.string/chat/prefix/set": "Accepts a string; All future chat messages starting with that string won't be seen by others, and only messages prefixed with that string can be read by $(l:patterns/strings#moreiotas:string/chat/caster)$(action)Whisper Reflection/$.", "moreiotas.page.strings.string/chat/prefix/get": "Returns the last string you passed to $(l:patterns/strings#moreiotas:string/chat/prefix/set)$(action)Sifter's Gambit/$.", "moreiotas.page.strings.string/iota": "Converts the iota on top of the stack into a string.", diff --git a/Fabric/src/main/java/ram/talia/moreiotas/fabric/eventhandlers/ChatEventHandler.kt b/Fabric/src/main/java/ram/talia/moreiotas/fabric/eventhandlers/ChatEventHandler.kt index bab87e2d..1bafad6a 100644 --- a/Fabric/src/main/java/ram/talia/moreiotas/fabric/eventhandlers/ChatEventHandler.kt +++ b/Fabric/src/main/java/ram/talia/moreiotas/fabric/eventhandlers/ChatEventHandler.kt @@ -4,49 +4,60 @@ import net.minecraft.network.chat.ChatType import net.minecraft.network.chat.PlayerChatMessage import net.minecraft.server.level.ServerPlayer import net.minecraft.world.entity.player.Player +import ram.talia.moreiotas.api.util.ChatEntry import ram.talia.moreiotas.fabric.cc.MoreIotasCardinalComponents -import java.util.* +import java.util.UUID +import kotlin.collections.ArrayDeque object ChatEventHandler { private val lastMessages: MutableMap = mutableMapOf() - private var lastMessage: String? = null + private val messageLog: ArrayDeque = ArrayDeque() + private var lastMessageTimestamp: Long? = null; + private var messagesHandled: Int = 0; private val lastMessageTimestamps: MutableMap = mutableMapOf() - private var lastMessageTimestamp: Long? = null fun receiveChat(message: PlayerChatMessage, player: ServerPlayer, params: ChatType.Bound): Boolean { val text = message.signedBody.content + (message.unsignedContent?.string ?: "") val prefix = MoreIotasCardinalComponents.CHAT_PREFIX_HOLDER.get(player).prefix + var timestamp = player.serverLevel().gameTime + + if (prefix != null && text.startsWith(prefix)) { + lastMessages[player.uuid] = text.substring(prefix.length) + lastMessageTimestamps[player.uuid] = timestamp + return false + } + if (prefix == null) { lastMessages[player.uuid] = text - lastMessage = text - lastMessageTimestamp = player.serverLevel().gameTime - lastMessageTimestamps[player.uuid] = lastMessageTimestamp - return true + lastMessageTimestamps[player.uuid] = timestamp } - if (text.startsWith(prefix)) { - lastMessages[player.uuid] = text.substring(prefix.length) - lastMessageTimestamps[player.uuid] = player.serverLevel().gameTime - return false + while (messageLog.size > 1023) { + // Just in case somehow we end up putting two "at once" even though this is only place this is touched + messageLog.removeFirst() } - lastMessage = text - lastMessageTimestamp = player.serverLevel().gameTime + messageLog.addLast(ChatEntry(text, timestamp, player.getName().getString())) + if (lastMessageTimestamp == timestamp) { + messagesHandled++ + } else { + messagesHandled = 1 + lastMessageTimestamp = timestamp + } return true } @JvmStatic - fun lastMessage(player: Player?): String? = if (player != null) lastMessages[player.uuid] else lastMessage + fun lastMessage(player: Player?): String? = if (player != null) lastMessages[player.uuid] else messageLog.last().message @JvmStatic fun lastMessageTimestamp(player: Player?): Long? = if (player != null) lastMessageTimestamps[player.uuid] else lastMessageTimestamp @JvmStatic - fun resetMessage(player: Player): Unit { - lastMessages[player.uuid] = null - lastMessageTimestamps[player.uuid] = null + fun chatLog(count: Int): List { + return messageLog.subList(messageLog.size - count, messageLog.size) } } \ No newline at end of file diff --git a/Fabric/src/main/java/ram/talia/moreiotas/fabric/xplat/FabricXplatImpl.java b/Fabric/src/main/java/ram/talia/moreiotas/fabric/xplat/FabricXplatImpl.java index 0ff92950..982b95a4 100644 --- a/Fabric/src/main/java/ram/talia/moreiotas/fabric/xplat/FabricXplatImpl.java +++ b/Fabric/src/main/java/ram/talia/moreiotas/fabric/xplat/FabricXplatImpl.java @@ -14,7 +14,11 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; + +import java.util.List; + import org.jetbrains.annotations.Nullable; +import ram.talia.moreiotas.api.util.ChatEntry; import ram.talia.moreiotas.fabric.cc.MoreIotasCardinalComponents; import ram.talia.moreiotas.fabric.eventhandlers.ChatEventHandler; import ram.talia.moreiotas.xplat.IXplatAbstractions; @@ -80,13 +84,13 @@ public boolean isBreakingAllowed (Level level, BlockPos pos, BlockState state, P } @Override - public void resetMessage(Player player) { - ChatEventHandler.resetMessage(player); + public @Nullable long lastMessageTimestamp(@Nullable Player player) { + return ChatEventHandler.lastMessageTimestamp(player); } @Override - public @Nullable long lastMessageTimestamp(@Nullable Player player) { - return ChatEventHandler.lastMessageTimestamp(player); + public List chatLog(int count) { + return ChatEventHandler.chatLog(count); } @Override From de6d75f25736a0795939ae0fca3abf9890303204 Mon Sep 17 00:00:00 2001 From: Saphire Date: Wed, 30 Apr 2025 05:02:22 +0600 Subject: [PATCH 3/5] Build, test and fix bunch of little things about chat timestamps, log --- .../moreiotas/api/mod/MoreIotasConfig.kt | 6 ++++++ .../casting/actions/strings/OpChatLog.kt | 15 ++++++------- .../actions/strings/OpChatTimestamp.kt | 9 ++++++-- .../common/lib/hex/MoreIotasActions.kt | 2 +- .../moreiotas/xplat/IXplatAbstractions.java | 4 +++- .../assets/moreiotas/lang/en_us.json | 4 ++-- .../fabric/FabricMoreIotasConfig.java | 7 +++++++ .../fabric/eventhandlers/ChatEventHandler.kt | 21 +++++++++++++------ .../fabric/xplat/FabricXplatImpl.java | 6 +++++- 9 files changed, 52 insertions(+), 22 deletions(-) diff --git a/Common/src/main/java/ram/talia/moreiotas/api/mod/MoreIotasConfig.kt b/Common/src/main/java/ram/talia/moreiotas/api/mod/MoreIotasConfig.kt index ae877fe9..c9181e28 100644 --- a/Common/src/main/java/ram/talia/moreiotas/api/mod/MoreIotasConfig.kt +++ b/Common/src/main/java/ram/talia/moreiotas/api/mod/MoreIotasConfig.kt @@ -15,6 +15,8 @@ object MoreIotasConfig { val setBlockStringCost: Long val nameCost: Long + val maxChatLog: Int + companion object { const val DEF_MIN_COST = 0.0001 const val DEF_MAX_COST = 10_000.0 @@ -29,6 +31,8 @@ object MoreIotasConfig { const val DEFAULT_SET_BLOCK_STRING_COST = 0.01 const val DEFAULT_NAME_COST = 0.01 + + const val DEFAULT_MAX_CHAT_LOG = 341 } } @@ -60,6 +64,8 @@ object MoreIotasConfig { get() = throw IllegalStateException("Attempted to access property of Dummy Config Object") override val nameCost: Long get() = throw IllegalStateException("Attempted to access property of Dummy Config Object") + override val maxChatLog: Int + get() = throw IllegalStateException("Attempted to access property of Dummy Config Object") } @JvmStatic diff --git a/Common/src/main/java/ram/talia/moreiotas/common/casting/actions/strings/OpChatLog.kt b/Common/src/main/java/ram/talia/moreiotas/common/casting/actions/strings/OpChatLog.kt index 29e32f94..c05e4cc1 100644 --- a/Common/src/main/java/ram/talia/moreiotas/common/casting/actions/strings/OpChatLog.kt +++ b/Common/src/main/java/ram/talia/moreiotas/common/casting/actions/strings/OpChatLog.kt @@ -2,29 +2,26 @@ package ram.talia.moreiotas.common.casting.actions.strings import at.petrak.hexcasting.api.casting.castables.ConstMediaAction import at.petrak.hexcasting.api.casting.eval.CastingEnvironment -import at.petrak.hexcasting.api.casting.getPositiveIntUnder -import at.petrak.hexcasting.api.casting.iota.Iota +import at.petrak.hexcasting.api.casting.getPositiveInt import at.petrak.hexcasting.api.casting.iota.DoubleIota +import at.petrak.hexcasting.api.casting.iota.Iota import at.petrak.hexcasting.api.casting.iota.ListIota -import net.minecraft.world.entity.player.Player -import ram.talia.moreiotas.api.asActionResult -import ram.talia.moreiotas.api.casting.iota.StringIota as ApiStringIota import ram.talia.moreiotas.xplat.IXplatAbstractions +import ram.talia.moreiotas.api.casting.iota.StringIota as ApiStringIota class OpChatLog() : ConstMediaAction { override val argc = 1 override fun execute(args: List, env: CastingEnvironment): List { - val count = args.getPositiveIntUnder(0, 1024, argc) - //return IXplatAbstractions.INSTANCE.chatLog(count).asActionResult as List - var logs = IXplatAbstractions.INSTANCE.chatLog(count); + val count = args.getPositiveInt(0, argc) + val logs = IXplatAbstractions.INSTANCE.chatLog(count) val messages = mutableListOf() val timestamps = mutableListOf() val names = mutableListOf() for (entry in logs) { messages.add(ApiStringIota.make(entry.message)) - timestamps.add(DoubleIota(entry.worldTime as Double)) + timestamps.add(DoubleIota(entry.worldTime.toDouble())) names.add(ApiStringIota.make(entry.username)) } diff --git a/Common/src/main/java/ram/talia/moreiotas/common/casting/actions/strings/OpChatTimestamp.kt b/Common/src/main/java/ram/talia/moreiotas/common/casting/actions/strings/OpChatTimestamp.kt index 1f9c9882..cc8514b8 100644 --- a/Common/src/main/java/ram/talia/moreiotas/common/casting/actions/strings/OpChatTimestamp.kt +++ b/Common/src/main/java/ram/talia/moreiotas/common/casting/actions/strings/OpChatTimestamp.kt @@ -3,6 +3,7 @@ package ram.talia.moreiotas.common.casting.actions.strings import at.petrak.hexcasting.api.casting.castables.ConstMediaAction import at.petrak.hexcasting.api.casting.asActionResult import at.petrak.hexcasting.api.casting.eval.CastingEnvironment +import at.petrak.hexcasting.api.casting.iota.DoubleIota import at.petrak.hexcasting.api.casting.iota.Iota import net.minecraft.world.entity.player.Player import ram.talia.moreiotas.api.asActionResult @@ -12,7 +13,11 @@ class OpChatTimestamp(private val allChat: Boolean) : ConstMediaAction { override val argc = 0 override fun execute(args: List, env: CastingEnvironment): List { - return IXplatAbstractions.INSTANCE.lastMessageTimestamp(if (allChat) null else env.castingEntity as? Player)?.asActionResult ?: - null.asActionResult + if (!allChat) + return IXplatAbstractions.INSTANCE.lastMessageTimestamp(env.castingEntity as? Player).asActionResult + return listOf( + DoubleIota(IXplatAbstractions.INSTANCE.lastMessageCount().toDouble()), + DoubleIota(IXplatAbstractions.INSTANCE.lastMessageTimestamp(null).toDouble()) + ) } } \ No newline at end of file diff --git a/Common/src/main/java/ram/talia/moreiotas/common/lib/hex/MoreIotasActions.kt b/Common/src/main/java/ram/talia/moreiotas/common/lib/hex/MoreIotasActions.kt index 0e9a784c..b0176e4a 100644 --- a/Common/src/main/java/ram/talia/moreiotas/common/lib/hex/MoreIotasActions.kt +++ b/Common/src/main/java/ram/talia/moreiotas/common/lib/hex/MoreIotasActions.kt @@ -65,7 +65,7 @@ object MoreIotasActions { @JvmField val STRING_CHAT_TIMESTAMP_ALL = make("string/chat/timestamp/all", fromAngles("wdedwaaw", EAST), OpChatTimestamp(true)) @JvmField - val STRING_CHAT_LOG = make("string/chat/log", fromAngles("wwwdwewdwwaawd", EAST), OpChatLog()) + val STRING_CHAT_LOG = make("string/chat/log/all", fromAngles("wawqwawww", SOUTH_WEST), OpChatLog()) @JvmField val STRING_CHAT_PREFIX_GET = make("string/chat/prefix/get", fromAngles("ewded", NORTH_EAST), OpGetChatPrefix) @JvmField diff --git a/Common/src/main/java/ram/talia/moreiotas/xplat/IXplatAbstractions.java b/Common/src/main/java/ram/talia/moreiotas/xplat/IXplatAbstractions.java index 82ca5287..bfd70c09 100644 --- a/Common/src/main/java/ram/talia/moreiotas/xplat/IXplatAbstractions.java +++ b/Common/src/main/java/ram/talia/moreiotas/xplat/IXplatAbstractions.java @@ -68,7 +68,9 @@ public interface IXplatAbstractions { @Nullable String lastMessage(@Nullable Player player); - @Nullable long lastMessageTimestamp(@Nullable Player player); + long lastMessageTimestamp(@Nullable Player player); + + int lastMessageCount(); List chatLog(int count); diff --git a/Common/src/main/resources/assets/moreiotas/lang/en_us.json b/Common/src/main/resources/assets/moreiotas/lang/en_us.json index 7d650a71..1bce9f29 100644 --- a/Common/src/main/resources/assets/moreiotas/lang/en_us.json +++ b/Common/src/main/resources/assets/moreiotas/lang/en_us.json @@ -93,8 +93,8 @@ "moreiotas.page.strings.string/block/set": "Removes a vector and a string from the stack. If that vector is pointing at a sign or lectern, it writes that string to that sign or lectern. Costs a hundredth of an $(l:items/amethyst)$(item)Amethyst Dust/$.", "moreiotas.page.strings.string/chat/caster": "Adds the last message the caster sent to the stack as a string.", "moreiotas.page.strings.string/chat/all": "Adds the last message anyone sent to the stack as a string.", - "moreiotas.page.strings.string/chat/timestamp/caster": "Returns the time in 20th of a second since the world's beginning, to when the caster sent the last message.", - "moreiotas.page.strings.string/chat/timestamp/all": "Similar to $(l:moreiotas:patterns/strings#moreiotas:string/chat/timestamp/caster)$(action)Sandglass' Reflection/$, but gives back the time since anyone sent out a message for all to hear. Oddly, returns a count too. It's not like two people can speak at the same single instant, right?", + "moreiotas.page.strings.string/chat/timestamp/caster": "Returns the time in 20ths of a second since the world's beginning, to when the caster sent the last message. Though sometimes it just gives back a zero...", + "moreiotas.page.strings.string/chat/timestamp/all": "Similar to $(l:moreiotas:patterns/strings#moreiotas:string/chat/timestamp/caster)$(action)Sandglass' Reflection/$, but tells when anyone sent a message for all to hear. Oddly, returns a count under that too. But it's not like two people would speak at the same single instant, right?", "moreiotas.page.strings.string/chat/log/all": "All that's spoken loudly enough gets recorded by the Nature, up to a limit. This pattern returns what was said, when, and by whom. The names are not what I see, but what Nature knows people by, though...", "moreiotas.page.strings.string/chat/prefix/set": "Accepts a string; All future chat messages starting with that string won't be seen by others, and only messages prefixed with that string can be read by $(l:patterns/strings#moreiotas:string/chat/caster)$(action)Whisper Reflection/$.", "moreiotas.page.strings.string/chat/prefix/get": "Returns the last string you passed to $(l:patterns/strings#moreiotas:string/chat/prefix/set)$(action)Sifter's Gambit/$.", diff --git a/Fabric/src/main/java/ram/talia/moreiotas/fabric/FabricMoreIotasConfig.java b/Fabric/src/main/java/ram/talia/moreiotas/fabric/FabricMoreIotasConfig.java index c5e031e0..7937cc7b 100644 --- a/Fabric/src/main/java/ram/talia/moreiotas/fabric/FabricMoreIotasConfig.java +++ b/Fabric/src/main/java/ram/talia/moreiotas/fabric/FabricMoreIotasConfig.java @@ -61,6 +61,8 @@ private static class Server implements ConfigData, MoreIotasConfig.ServerConfigA private double setBlockStringCost = DEFAULT_SET_BLOCK_STRING_COST; private double nameCost = DEFAULT_NAME_COST; + private int maxChatLog = DEFAULT_MAX_CHAT_LOG; + @Override public void validatePostLoad() throws ValidationException { this.maxMatrixSize = bound(this.maxMatrixSize, MIN_MAX_MATRIX_SIZE, MAX_MAX_MATRIX_SIZE); @@ -96,5 +98,10 @@ public long getSetBlockStringCost() { public long getNameCost() { return (long) (this.nameCost * MediaConstants.DUST_UNIT); } + + @Override + public int getMaxChatLog() { + return this.maxChatLog; + } } } diff --git a/Fabric/src/main/java/ram/talia/moreiotas/fabric/eventhandlers/ChatEventHandler.kt b/Fabric/src/main/java/ram/talia/moreiotas/fabric/eventhandlers/ChatEventHandler.kt index 1bafad6a..7a4ee693 100644 --- a/Fabric/src/main/java/ram/talia/moreiotas/fabric/eventhandlers/ChatEventHandler.kt +++ b/Fabric/src/main/java/ram/talia/moreiotas/fabric/eventhandlers/ChatEventHandler.kt @@ -4,6 +4,7 @@ import net.minecraft.network.chat.ChatType import net.minecraft.network.chat.PlayerChatMessage import net.minecraft.server.level.ServerPlayer import net.minecraft.world.entity.player.Player +import ram.talia.moreiotas.api.mod.MoreIotasConfig.server import ram.talia.moreiotas.api.util.ChatEntry import ram.talia.moreiotas.fabric.cc.MoreIotasCardinalComponents import java.util.UUID @@ -12,7 +13,7 @@ import kotlin.collections.ArrayDeque object ChatEventHandler { private val lastMessages: MutableMap = mutableMapOf() private val messageLog: ArrayDeque = ArrayDeque() - private var lastMessageTimestamp: Long? = null; + private var lastMessageTimestamp: Long = 0; private var messagesHandled: Int = 0; private val lastMessageTimestamps: MutableMap = mutableMapOf() @@ -35,12 +36,17 @@ object ChatEventHandler { lastMessageTimestamps[player.uuid] = timestamp } - while (messageLog.size > 1023) { + while (messageLog.isNotEmpty() && messageLog.size > server.maxChatLog) { // Just in case somehow we end up putting two "at once" even though this is only place this is touched messageLog.removeFirst() } - messageLog.addLast(ChatEntry(text, timestamp, player.getName().getString())) + // Just in case! People configure stuff in the weirdest ways + if (server.maxChatLog == 0) + return true + + messageLog.addLast(ChatEntry(text, timestamp, player.name.string)) + if (lastMessageTimestamp == timestamp) { messagesHandled++ } else { @@ -51,13 +57,16 @@ object ChatEventHandler { } @JvmStatic - fun lastMessage(player: Player?): String? = if (player != null) lastMessages[player.uuid] else messageLog.last().message + fun lastMessage(player: Player?): String? = if (player != null) lastMessages.getOrDefault(player.uuid, null) else if (lastMessageTimestamp != 0L) messageLog.last().message else null + + @JvmStatic + fun lastMessageTimestamp(player: Player?): Long = (if (player != null) lastMessageTimestamps.getOrDefault(player.uuid, 0) else lastMessageTimestamp) ?: 0 @JvmStatic - fun lastMessageTimestamp(player: Player?): Long? = if (player != null) lastMessageTimestamps[player.uuid] else lastMessageTimestamp + fun lastMessageCount(): Int = messagesHandled @JvmStatic fun chatLog(count: Int): List { - return messageLog.subList(messageLog.size - count, messageLog.size) + return messageLog.subList((messageLog.size - count).coerceAtLeast(0), messageLog.size) } } \ No newline at end of file diff --git a/Fabric/src/main/java/ram/talia/moreiotas/fabric/xplat/FabricXplatImpl.java b/Fabric/src/main/java/ram/talia/moreiotas/fabric/xplat/FabricXplatImpl.java index 982b95a4..825a1ff5 100644 --- a/Fabric/src/main/java/ram/talia/moreiotas/fabric/xplat/FabricXplatImpl.java +++ b/Fabric/src/main/java/ram/talia/moreiotas/fabric/xplat/FabricXplatImpl.java @@ -84,10 +84,14 @@ public boolean isBreakingAllowed (Level level, BlockPos pos, BlockState state, P } @Override - public @Nullable long lastMessageTimestamp(@Nullable Player player) { + public long lastMessageTimestamp(@Nullable Player player) { return ChatEventHandler.lastMessageTimestamp(player); } + public int lastMessageCount() { + return ChatEventHandler.lastMessageCount(); + } + @Override public List chatLog(int count) { return ChatEventHandler.chatLog(count); From 7198eb7d4b03b63ed6cc9b0604ab933bc7436d9f Mon Sep 17 00:00:00 2001 From: Saphire Date: Sat, 4 Oct 2025 05:41:27 +0600 Subject: [PATCH 4/5] Forge implementation for chat history/timestamps --- .../moreiotas/api/mod/MoreIotasConfig.kt | 4 +- .../fabric/FabricMoreIotasConfig.java | 1 + .../fabric/eventhandlers/ChatEventHandler.kt | 8 +-- .../moreiotas/forge/ForgeMoreIotasConfig.java | 9 +++ .../forge/eventhandlers/ChatEventHandler.java | 70 +++++++++++++++---- .../moreiotas/forge/xplat/ForgeXplatImpl.java | 19 ++++- 6 files changed, 92 insertions(+), 19 deletions(-) diff --git a/Common/src/main/java/ram/talia/moreiotas/api/mod/MoreIotasConfig.kt b/Common/src/main/java/ram/talia/moreiotas/api/mod/MoreIotasConfig.kt index c9181e28..b2dedd53 100644 --- a/Common/src/main/java/ram/talia/moreiotas/api/mod/MoreIotasConfig.kt +++ b/Common/src/main/java/ram/talia/moreiotas/api/mod/MoreIotasConfig.kt @@ -32,7 +32,9 @@ object MoreIotasConfig { const val DEFAULT_SET_BLOCK_STRING_COST = 0.01 const val DEFAULT_NAME_COST = 0.01 - const val DEFAULT_MAX_CHAT_LOG = 341 + const val DEFAULT_MAX_CHAT_LOG = 341 // 3 within 1024 + const val MIN_MAX_CHAT_LOG: Int = 0 + const val MAX_MAX_CHAT_LOG: Int = 341 // TODO: take into account the stack size config... } } diff --git a/Fabric/src/main/java/ram/talia/moreiotas/fabric/FabricMoreIotasConfig.java b/Fabric/src/main/java/ram/talia/moreiotas/fabric/FabricMoreIotasConfig.java index 7937cc7b..1023ec41 100644 --- a/Fabric/src/main/java/ram/talia/moreiotas/fabric/FabricMoreIotasConfig.java +++ b/Fabric/src/main/java/ram/talia/moreiotas/fabric/FabricMoreIotasConfig.java @@ -67,6 +67,7 @@ private static class Server implements ConfigData, MoreIotasConfig.ServerConfigA public void validatePostLoad() throws ValidationException { this.maxMatrixSize = bound(this.maxMatrixSize, MIN_MAX_MATRIX_SIZE, MAX_MAX_MATRIX_SIZE); this.maxStringLength = bound(this.maxStringLength, MIN_MAX_STRING_LENGTH, MAX_MAX_STRING_LENGTH); + this.maxChatLog = bound(this.maxChatLog, MIN_MAX_CHAT_LOG, MAX_MAX_CHAT_LOG); this.setBlockStringCost = bound(this.setBlockStringCost, DEF_MIN_COST, DEF_MAX_COST); this.nameCost = bound(this.nameCost, DEF_MIN_COST, DEF_MAX_COST); diff --git a/Fabric/src/main/java/ram/talia/moreiotas/fabric/eventhandlers/ChatEventHandler.kt b/Fabric/src/main/java/ram/talia/moreiotas/fabric/eventhandlers/ChatEventHandler.kt index 7a4ee693..6c8a7f34 100644 --- a/Fabric/src/main/java/ram/talia/moreiotas/fabric/eventhandlers/ChatEventHandler.kt +++ b/Fabric/src/main/java/ram/talia/moreiotas/fabric/eventhandlers/ChatEventHandler.kt @@ -36,15 +36,15 @@ object ChatEventHandler { lastMessageTimestamps[player.uuid] = timestamp } + // Just in case! People configure stuff in the weirdest ways + if (server.maxChatLog == 0) + return true + while (messageLog.isNotEmpty() && messageLog.size > server.maxChatLog) { // Just in case somehow we end up putting two "at once" even though this is only place this is touched messageLog.removeFirst() } - // Just in case! People configure stuff in the weirdest ways - if (server.maxChatLog == 0) - return true - messageLog.addLast(ChatEntry(text, timestamp, player.name.string)) if (lastMessageTimestamp == timestamp) { diff --git a/Forge/src/main/java/ram/talia/moreiotas/forge/ForgeMoreIotasConfig.java b/Forge/src/main/java/ram/talia/moreiotas/forge/ForgeMoreIotasConfig.java index eda796b9..cbb3dac1 100644 --- a/Forge/src/main/java/ram/talia/moreiotas/forge/ForgeMoreIotasConfig.java +++ b/Forge/src/main/java/ram/talia/moreiotas/forge/ForgeMoreIotasConfig.java @@ -19,6 +19,7 @@ public Client(ForgeConfigSpec.Builder builder) { public static class Server implements MoreIotasConfig.ServerConfigAccess { private static ForgeConfigSpec.IntValue maxMatrixSize; private static ForgeConfigSpec.IntValue maxStringLength; + private static ForgeConfigSpec.IntValue maxChatLog; private static ForgeConfigSpec.DoubleValue setBlockStringCost; private static ForgeConfigSpec.DoubleValue nameCost; @@ -30,6 +31,9 @@ public Server(ForgeConfigSpec.Builder builder) { maxStringLength = builder.comment("How long can strings be") .defineInRange("maxStringLength", DEFAULT_MAX_STRING_LENGTH, MIN_MAX_STRING_LENGTH, MAX_MAX_STRING_LENGTH); + maxChatLog = builder.comment("How many chat messages can be logged and returned at most?") + .defineInRange("maxChatLog", DEFAULT_MAX_CHAT_LOG, MIN_MAX_CHAT_LOG, MAX_MAX_CHAT_LOG); + setBlockStringCost = builder.comment("How much dust should string/block/set cost?") .defineInRange("setBlockStringCost", DEFAULT_SET_BLOCK_STRING_COST, DEF_MIN_COST, DEF_MAX_COST); nameCost = builder.comment("How much dust should string/name cost?") @@ -55,5 +59,10 @@ public long getSetBlockStringCost() { public long getNameCost() { return (long) (nameCost.get() * MediaConstants.DUST_UNIT); } + + @Override + public int getMaxChatLog() { + return maxChatLog.get(); + } } } diff --git a/Forge/src/main/java/ram/talia/moreiotas/forge/eventhandlers/ChatEventHandler.java b/Forge/src/main/java/ram/talia/moreiotas/forge/eventhandlers/ChatEventHandler.java index 36bb7990..e41fc589 100644 --- a/Forge/src/main/java/ram/talia/moreiotas/forge/eventhandlers/ChatEventHandler.java +++ b/Forge/src/main/java/ram/talia/moreiotas/forge/eventhandlers/ChatEventHandler.java @@ -4,8 +4,13 @@ import net.minecraftforge.event.ServerChatEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import org.jetbrains.annotations.Nullable; +import ram.talia.moreiotas.api.mod.MoreIotasConfig; +import ram.talia.moreiotas.api.util.ChatEntry; +import java.util.ArrayDeque; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.UUID; @@ -13,8 +18,12 @@ public class ChatEventHandler { private static final String TAG_CHAT_PREFIX = "moreiotas:prefix"; private static final Map lastMessages = new HashMap<>(); + private static final Map lastMessageTimestamps = new HashMap<>(); - private static @Nullable String lastMessage = null; + private static final ArrayDeque messageLog = new ArrayDeque<>(); + + private static Long lastMessageTimestamp = 0; + private static Int messagesHandled = 0; public static void setPrefix(Player player, @Nullable String prefix) { if (prefix == null) @@ -35,27 +44,64 @@ public static void setPrefix(Player player, @Nullable String prefix) { return lastMessages.get(player.getUUID()); } + + public static long lastMessageTimestamp(@Nullable Player player) { + if (player != null) + return lastMessageTimestamps.get(player.getUUID()); + return lastMessageTimestamp; + } + + public static int lastMessageCount() { + return messagesHandled; + } + + public static List chatLog(int count) { + var list = new ArrayList(); + var iter = messageLog.descendingIterator(); + for (int i = 1; i < count; i++) { + if (!iter.hasNext()) + break; + list.add(iter.next()); + } + return list; + } + @SubscribeEvent public static void chatMessageSent(ServerChatEvent event) { - var player = event.getPlayer(); - var uuid = player.getUUID(); + if (event.isCanceled()) + return; + + var uuid = event.getPlayer().getUUID(); var text = event.getRawText(); + var timestamp = event.getPlayer().serverLevel().gameTime; - if (event.isCanceled()) + var prefix = ChatEventHandler.getPrefix(player); + + if (prefix != null && text.startsWith(prefix)) { + lastMessages.put(uuid, text.substring(prefix.length())); + lastMessageTimestamps.put(uuid, timestamp); return; + } - if (!player.getPersistentData().contains(TAG_CHAT_PREFIX)) { + if (prefix == null) { lastMessages.put(uuid, text); - lastMessage = text; - return; + lastMessageTimestamps.put(uuid, timestamp); } - var prefix = player.getPersistentData().getString(TAG_CHAT_PREFIX); + if (MoreIotasConfig.server.maxChatLog == 0) + return true; - if (text.startsWith(prefix)) { - event.setCanceled(true); - lastMessages.put(uuid, text.substring(prefix.length())); - return; + while (!messageLog.isEmpty() && messageLog.size() > MoreIotasConfig.server.maxChatLog) { + messageLog.removeFirst(); + } + + messageLog.addLast(new ChatEntry(text, timestamp, event.getPlayer().name.string)); + + if (lastMessageTimestamp == timestamp) { + messagesHandled++; + } else { + messagesHandled = 1; + lastMessageTimestamp = timestamp; } lastMessage = text; diff --git a/Forge/src/main/java/ram/talia/moreiotas/forge/xplat/ForgeXplatImpl.java b/Forge/src/main/java/ram/talia/moreiotas/forge/xplat/ForgeXplatImpl.java index 4bffff54..ad18a03f 100644 --- a/Forge/src/main/java/ram/talia/moreiotas/forge/xplat/ForgeXplatImpl.java +++ b/Forge/src/main/java/ram/talia/moreiotas/forge/xplat/ForgeXplatImpl.java @@ -31,14 +31,14 @@ public boolean isPhysicalClient() { public void sendPacketToPlayer(ServerPlayer target, IMessage packet) { ForgePacketHandler.getNetwork().send(PacketDistributor.PLAYER.with(() -> target), packet); } - + @Override public void sendPacketNear(Vec3 pos, double radius, ServerLevel dimension, IMessage packet) { ForgePacketHandler.getNetwork().send(PacketDistributor.NEAR.with(() -> new PacketDistributor.TargetPoint( pos.x, pos.y, pos.z, radius * radius, dimension.dimension() )), packet); } - + @Override public Packet toVanillaClientboundPacket(IMessage message) { return ForgePacketHandler.getNetwork().toVanillaPacket(message, NetworkDirection.PLAY_TO_CLIENT); @@ -63,4 +63,19 @@ public void setChatPrefix(Player player, @Nullable String prefix) { public @Nullable String getChatPrefix(Player player) { return ChatEventHandler.getPrefix(player); } + + @Override + public long lastMessageTimestamp(@Nullable Player player) { + return ChatEventHandler.lastMessageTimestamp(player); + } + + @Override + public int lastMessageCount() { + return ChatEventHandler.lastMessageCount(); + } + + @Override + public List chatLog(int count) { + return ChatEventHandler.chatLog(count); + } } From 2a3afe890bc6becce2dcb4db11c4c9e8658b96e2 Mon Sep 17 00:00:00 2001 From: Saphire Date: Mon, 6 Oct 2025 22:15:29 +0600 Subject: [PATCH 5/5] Actually make it build, reverse fabric chat log --- .../fabric/eventhandlers/ChatEventHandler.kt | 2 +- .../forge/eventhandlers/ChatEventHandler.java | 32 ++++++++++--------- .../moreiotas/forge/xplat/ForgeXplatImpl.java | 3 ++ 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/Fabric/src/main/java/ram/talia/moreiotas/fabric/eventhandlers/ChatEventHandler.kt b/Fabric/src/main/java/ram/talia/moreiotas/fabric/eventhandlers/ChatEventHandler.kt index 6c8a7f34..3e23832b 100644 --- a/Fabric/src/main/java/ram/talia/moreiotas/fabric/eventhandlers/ChatEventHandler.kt +++ b/Fabric/src/main/java/ram/talia/moreiotas/fabric/eventhandlers/ChatEventHandler.kt @@ -67,6 +67,6 @@ object ChatEventHandler { @JvmStatic fun chatLog(count: Int): List { - return messageLog.subList((messageLog.size - count).coerceAtLeast(0), messageLog.size) + return messageLog.subList((messageLog.size - count).coerceAtLeast(0), messageLog.size).reverse() } } \ No newline at end of file diff --git a/Forge/src/main/java/ram/talia/moreiotas/forge/eventhandlers/ChatEventHandler.java b/Forge/src/main/java/ram/talia/moreiotas/forge/eventhandlers/ChatEventHandler.java index e41fc589..cfcbb396 100644 --- a/Forge/src/main/java/ram/talia/moreiotas/forge/eventhandlers/ChatEventHandler.java +++ b/Forge/src/main/java/ram/talia/moreiotas/forge/eventhandlers/ChatEventHandler.java @@ -18,12 +18,12 @@ public class ChatEventHandler { private static final String TAG_CHAT_PREFIX = "moreiotas:prefix"; private static final Map lastMessages = new HashMap<>(); - private static final Map lastMessageTimestamps = new HashMap<>(); + private static final Map lastMessageTimestamps = new HashMap<>(); private static final ArrayDeque messageLog = new ArrayDeque<>(); - private static Long lastMessageTimestamp = 0; - private static Int messagesHandled = 0; + private static long lastMessageTimestamp = 0; + private static int messagesHandled = 0; public static void setPrefix(Player player, @Nullable String prefix) { if (prefix == null) @@ -39,15 +39,17 @@ public static void setPrefix(Player player, @Nullable String prefix) { } public static @Nullable String getLastMessage(@Nullable Player player) { - if (player == null) - return lastMessage; - return lastMessages.get(player.getUUID()); + if (player != null) + return lastMessages.get(player.getUUID()); + if (!messageLog.isEmpty()) + return messageLog.peekLast().message(); + return null; } public static long lastMessageTimestamp(@Nullable Player player) { if (player != null) - return lastMessageTimestamps.get(player.getUUID()); + return lastMessageTimestamps.getOrDefault(player.getUUID(), 0l); return lastMessageTimestamp; } @@ -71,13 +73,15 @@ public static void chatMessageSent(ServerChatEvent event) { if (event.isCanceled()) return; - var uuid = event.getPlayer().getUUID(); + var player = event.getPlayer(); + var uuid = player.getUUID(); + var timestamp = player.serverLevel().getGameTime(); // Dunno why it wants closeable try var text = event.getRawText(); - var timestamp = event.getPlayer().serverLevel().gameTime; var prefix = ChatEventHandler.getPrefix(player); if (prefix != null && text.startsWith(prefix)) { + event.setCanceled(true); lastMessages.put(uuid, text.substring(prefix.length())); lastMessageTimestamps.put(uuid, timestamp); return; @@ -88,14 +92,14 @@ public static void chatMessageSent(ServerChatEvent event) { lastMessageTimestamps.put(uuid, timestamp); } - if (MoreIotasConfig.server.maxChatLog == 0) - return true; + if (MoreIotasConfig.getServer().getMaxChatLog() == 0) + return; - while (!messageLog.isEmpty() && messageLog.size() > MoreIotasConfig.server.maxChatLog) { + while (!messageLog.isEmpty() && messageLog.size() > MoreIotasConfig.getServer().getMaxChatLog()) { messageLog.removeFirst(); } - messageLog.addLast(new ChatEntry(text, timestamp, event.getPlayer().name.string)); + messageLog.addLast(new ChatEntry(text, timestamp, event.getPlayer().getName().getString())); if (lastMessageTimestamp == timestamp) { messagesHandled++; @@ -103,7 +107,5 @@ public static void chatMessageSent(ServerChatEvent event) { messagesHandled = 1; lastMessageTimestamp = timestamp; } - - lastMessage = text; } } diff --git a/Forge/src/main/java/ram/talia/moreiotas/forge/xplat/ForgeXplatImpl.java b/Forge/src/main/java/ram/talia/moreiotas/forge/xplat/ForgeXplatImpl.java index ad18a03f..872588cf 100644 --- a/Forge/src/main/java/ram/talia/moreiotas/forge/xplat/ForgeXplatImpl.java +++ b/Forge/src/main/java/ram/talia/moreiotas/forge/xplat/ForgeXplatImpl.java @@ -16,10 +16,13 @@ import net.minecraftforge.network.NetworkDirection; import net.minecraftforge.network.PacketDistributor; import org.jetbrains.annotations.Nullable; +import ram.talia.moreiotas.api.util.ChatEntry; import ram.talia.moreiotas.forge.eventhandlers.ChatEventHandler; import ram.talia.moreiotas.forge.network.ForgePacketHandler; import ram.talia.moreiotas.xplat.IXplatAbstractions; +import java.util.List; + public class ForgeXplatImpl implements IXplatAbstractions { @Override