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/mod/MoreIotasConfig.kt b/Common/src/main/java/ram/talia/moreiotas/api/mod/MoreIotasConfig.kt index ae877fe9..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 @@ -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,10 @@ 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 // 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... } } @@ -60,6 +66,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/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..c05e4cc1 --- /dev/null +++ b/Common/src/main/java/ram/talia/moreiotas/common/casting/actions/strings/OpChatLog.kt @@ -0,0 +1,30 @@ +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.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 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.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.toDouble())) + 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/OpChatTimestamp.kt b/Common/src/main/java/ram/talia/moreiotas/common/casting/actions/strings/OpChatTimestamp.kt new file mode 100644 index 00000000..cc8514b8 --- /dev/null +++ b/Common/src/main/java/ram/talia/moreiotas/common/casting/actions/strings/OpChatTimestamp.kt @@ -0,0 +1,23 @@ +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 +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 { + 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 bb3a71ac..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 @@ -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/all", fromAngles("wawqwawww", SOUTH_WEST), 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 2e62b80e..bfd70c09 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,6 +68,12 @@ public interface IXplatAbstractions { @Nullable String lastMessage(@Nullable Player player); + long lastMessageTimestamp(@Nullable Player player); + + int lastMessageCount(); + + List chatLog(int count); + void setChatPrefix(Player player, @Nullable String prefix); @Nullable String getChatPrefix(Player player); @@ -92,5 +100,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..1bce9f29 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 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/$.", "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/FabricMoreIotasConfig.java b/Fabric/src/main/java/ram/talia/moreiotas/fabric/FabricMoreIotasConfig.java index c5e031e0..1023ec41 100644 --- a/Fabric/src/main/java/ram/talia/moreiotas/fabric/FabricMoreIotasConfig.java +++ b/Fabric/src/main/java/ram/talia/moreiotas/fabric/FabricMoreIotasConfig.java @@ -61,10 +61,13 @@ 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); 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); @@ -96,5 +99,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 1148f3a2..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 @@ -4,32 +4,69 @@ 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.* +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 = 0; + private var messagesHandled: Int = 0; + + private val lastMessageTimestamps: MutableMap = mutableMapOf() 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 - return true + lastMessageTimestamps[player.uuid] = timestamp } - if (!text.startsWith(prefix)) + // Just in case! People configure stuff in the weirdest ways + if (server.maxChatLog == 0) return true - lastMessages[player.uuid] = text.substring(prefix.length) + 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.name.string)) - return false + 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.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 lastMessageCount(): Int = messagesHandled + + @JvmStatic + fun chatLog(count: Int): List { + return messageLog.subList((messageLog.size - count).coerceAtLeast(0), messageLog.size).reverse() + } } \ 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..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 @@ -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; @@ -79,6 +83,20 @@ public boolean isBreakingAllowed (Level level, BlockPos pos, BlockState state, P return ChatEventHandler.lastMessage(player); } + @Override + 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); + } + @Override public void setChatPrefix(Player player, String prefix) { MoreIotasCardinalComponents.CHAT_PREFIX_HOLDER.get(player).setPrefix(prefix); 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..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 @@ -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) @@ -30,34 +39,73 @@ 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.getOrDefault(player.getUUID(), 0l); + 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) { + if (event.isCanceled()) + return; + var player = event.getPlayer(); var uuid = player.getUUID(); + var timestamp = player.serverLevel().getGameTime(); // Dunno why it wants closeable try var text = event.getRawText(); - if (event.isCanceled()) - return; + var prefix = ChatEventHandler.getPrefix(player); - if (!player.getPersistentData().contains(TAG_CHAT_PREFIX)) { - lastMessages.put(uuid, text); - lastMessage = text; + if (prefix != null && text.startsWith(prefix)) { + event.setCanceled(true); + lastMessages.put(uuid, text.substring(prefix.length())); + lastMessageTimestamps.put(uuid, timestamp); return; } - var prefix = player.getPersistentData().getString(TAG_CHAT_PREFIX); + if (prefix == null) { + lastMessages.put(uuid, text); + lastMessageTimestamps.put(uuid, timestamp); + } - if (text.startsWith(prefix)) { - event.setCanceled(true); - lastMessages.put(uuid, text.substring(prefix.length())); + if (MoreIotasConfig.getServer().getMaxChatLog() == 0) return; + + while (!messageLog.isEmpty() && messageLog.size() > MoreIotasConfig.getServer().getMaxChatLog()) { + messageLog.removeFirst(); } - lastMessage = text; + messageLog.addLast(new ChatEntry(text, timestamp, event.getPlayer().getName().getString())); + + if (lastMessageTimestamp == timestamp) { + messagesHandled++; + } else { + messagesHandled = 1; + lastMessageTimestamp = timestamp; + } } } 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..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 @@ -31,14 +34,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 +66,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); + } }