remove InternalMessageReceiveEvent, restructure some chat receiving parts

This commit is contained in:
Bixilon 2023-01-09 15:14:06 +01:00
parent b76cb75758
commit c6b26796bf
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
20 changed files with 104 additions and 92 deletions

View File

@ -1,6 +1,6 @@
/* /*
* Minosoft * Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger * Copyright (C) 2020-2023 Moritz Zwerger
* *
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
* *
@ -13,10 +13,12 @@
package de.bixilon.minosoft.data.chat package de.bixilon.minosoft.data.chat
import de.bixilon.kutil.string.WhitespaceUtil.trimWhitespaces
import de.bixilon.minosoft.data.chat.sender.* import de.bixilon.minosoft.data.chat.sender.*
import de.bixilon.minosoft.data.entities.entities.player.PlayerEntity import de.bixilon.minosoft.data.entities.entities.player.PlayerEntity
import de.bixilon.minosoft.data.text.formatting.color.ChatColors import de.bixilon.minosoft.data.text.formatting.color.ChatColors
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import java.util.* import java.util.*
object ChatUtil { object ChatUtil {
@ -33,4 +35,20 @@ object ChatUtil {
} }
return PlayerEntityMessageSender(uuid, entity.name, entity) return PlayerEntityMessageSender(uuid, entity.name, entity)
} }
fun validateChatMessage(connection: PlayConnection, message: String) {
if (message.isBlank()) {
throw IllegalArgumentException("Chat message can not be blank!")
}
if (ProtocolDefinition.TEXT_COMPONENT_FORMATTING_PREFIX in message) {
throw IllegalArgumentException("Chat message must not contain formatting (${ProtocolDefinition.TEXT_COMPONENT_FORMATTING_PREFIX}): $message")
}
if (message.length > connection.version.maxChatMessageSize) {
throw IllegalArgumentException("Message length (${message.length} can not exceed ${connection.version.maxChatMessageSize})")
}
}
fun trimChatMessage(message: String): String {
return message.trimWhitespaces()
}
} }

View File

@ -1,6 +1,6 @@
/* /*
* Minosoft * Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger * Copyright (C) 2020-2023 Moritz Zwerger
* *
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
* *
@ -15,8 +15,13 @@ package de.bixilon.minosoft.data.chat.message
import de.bixilon.minosoft.data.registries.chat.ChatMessageType import de.bixilon.minosoft.data.registries.chat.ChatMessageType
import de.bixilon.minosoft.data.text.ChatComponent import de.bixilon.minosoft.data.text.ChatComponent
import de.bixilon.minosoft.data.text.formatting.TextFormattable
interface ChatMessage { interface ChatMessage : TextFormattable {
val text: ChatComponent val text: ChatComponent
val type: ChatMessageType val type: ChatMessageType
override fun toText(): Any? {
return text
}
} }

View File

@ -1,6 +1,6 @@
/* /*
* Minosoft * Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger * Copyright (C) 2020-2023 Moritz Zwerger
* *
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
* *
@ -10,14 +10,12 @@
* *
* This software is not affiliated with Mojang AB, the original developer of Minecraft. * This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/ */
package de.bixilon.minosoft.modding.event.events
import de.bixilon.minosoft.data.chat.message.InternalChatMessage package de.bixilon.minosoft.data.chat.message.internal
import de.bixilon.minosoft.modding.event.events.connection.play.PlayConnectionEvent
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
@Deprecated("message receive event: InternalMessage") import de.bixilon.minosoft.data.text.BaseComponent
class InternalMessageReceiveEvent( import de.bixilon.minosoft.data.text.ChatComponent
connection: PlayConnection, import de.bixilon.minosoft.data.text.formatting.color.ChatColors
val message: InternalChatMessage, import de.bixilon.minosoft.gui.rendering.RenderConstants
) : PlayConnectionEvent(connection), CancelableEvent
class DebugChatMessage(message: ChatComponent) : InternalChatMessage(BaseComponent(RenderConstants.DEBUG_MESSAGES_PREFIX, ChatComponent.of(message).apply { this.setFallbackColor(ChatColors.BLUE) }))

View File

@ -11,26 +11,31 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft. * This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/ */
package de.bixilon.minosoft.data.chat.message package de.bixilon.minosoft.data.chat.message.internal
import de.bixilon.minosoft.data.chat.ChatTextPositions import de.bixilon.minosoft.data.chat.ChatTextPositions
import de.bixilon.minosoft.data.chat.ChatUtil import de.bixilon.minosoft.data.chat.ChatUtil
import de.bixilon.minosoft.data.chat.message.ChatMessage
import de.bixilon.minosoft.data.registries.chat.ChatMessageType import de.bixilon.minosoft.data.registries.chat.ChatMessageType
import de.bixilon.minosoft.data.registries.chat.ChatParameter import de.bixilon.minosoft.data.registries.chat.ChatParameter
import de.bixilon.minosoft.data.registries.chat.TypeProperties import de.bixilon.minosoft.data.registries.chat.TypeProperties
import de.bixilon.minosoft.data.registries.identified.Namespaces.minosoft import de.bixilon.minosoft.data.registries.identified.Namespaces.minosoft
import de.bixilon.minosoft.data.text.BaseComponent
import de.bixilon.minosoft.data.text.ChatComponent import de.bixilon.minosoft.data.text.ChatComponent
import de.bixilon.minosoft.gui.rendering.RenderConstants
class InternalChatMessage( open class InternalChatMessage(
override val text: ChatComponent, val raw: ChatComponent,
) : ChatMessage { ) : ChatMessage {
override val type: ChatMessageType get() = TYPE override val type: ChatMessageType get() = TYPE
init { init {
text.setFallbackColor(ChatUtil.DEFAULT_CHAT_COLOR) raw.setFallbackColor(ChatUtil.DEFAULT_CHAT_COLOR)
} }
override val text: ChatComponent = BaseComponent(RenderConstants.INTERNAL_MESSAGES_PREFIX, raw)
companion object { companion object {
val TYPE = ChatMessageType(minosoft("internal"), TypeProperties("%s", listOf(ChatParameter.CONTENT), mapOf()), narration = null, position = ChatTextPositions.CHAT) val TYPE = ChatMessageType(minosoft("internal_message"), TypeProperties("%s", listOf(ChatParameter.CONTENT), mapOf()), narration = null, position = ChatTextPositions.CHAT)
} }
} }

View File

@ -1,6 +1,6 @@
/* /*
* Minosoft * Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger * Copyright (C) 2020-2023 Moritz Zwerger
* *
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
* *
@ -110,7 +110,7 @@ class BaseComponent : ChatComponent {
} }
while (char != CharacterIterator.DONE) { while (char != CharacterIterator.DONE) {
if (char != ProtocolDefinition.TEXT_COMPONENT_SPECIAL_PREFIX_CHAR) { if (char != ProtocolDefinition.TEXT_COMPONENT_FORMATTING_PREFIX) {
currentText.append(char) currentText.append(char)
char = iterator.next() char = iterator.next()
continue continue
@ -156,7 +156,7 @@ class BaseComponent : ChatComponent {
} }
json["text"]?.nullCast<String>()?.let { json["text"]?.nullCast<String>()?.let {
if (it.indexOf(ProtocolDefinition.TEXT_COMPONENT_SPECIAL_PREFIX_CHAR) != -1) { if (it.indexOf(ProtocolDefinition.TEXT_COMPONENT_FORMATTING_PREFIX) != -1) {
this += ChatComponent.of(it, translator, parent, restrictedMode) this += ChatComponent.of(it, translator, parent, restrictedMode)
parseExtra() parseExtra()
return return

View File

@ -1,6 +1,6 @@
/* /*
* Minosoft * Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger * Copyright (C) 2020-2023 Moritz Zwerger
* *
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
* *
@ -37,7 +37,7 @@ open class TextComponent(
var clickEvent: ClickEvent? = null, var clickEvent: ClickEvent? = null,
var hoverEvent: HoverEvent? = null, var hoverEvent: HoverEvent? = null,
) : ChatComponent, TextStyle { ) : ChatComponent, TextStyle {
override var message: String = message.toString().replace(ProtocolDefinition.TEXT_COMPONENT_SPECIAL_PREFIX_CHAR, '&') override var message: String = message.toString().replace(ProtocolDefinition.TEXT_COMPONENT_FORMATTING_PREFIX, '&')
override fun obfuscate(): TextComponent { override fun obfuscate(): TextComponent {
formatting.add(PreChatFormattingCodes.OBFUSCATED); return this formatting.add(PreChatFormattingCodes.OBFUSCATED); return this
@ -106,15 +106,15 @@ open class TextComponent(
color?.let { color?.let {
val colorChar = ChatCode.FORMATTING_CODES_ID.indexOf(it) val colorChar = ChatCode.FORMATTING_CODES_ID.indexOf(it)
if (colorChar != -1) { if (colorChar != -1) {
stringBuilder.append(ProtocolDefinition.TEXT_COMPONENT_SPECIAL_PREFIX_CHAR).append(Integer.toHexString(colorChar)) stringBuilder.append(ProtocolDefinition.TEXT_COMPONENT_FORMATTING_PREFIX).append(Integer.toHexString(colorChar))
} }
} }
for (formattingCode in this.formatting) { for (formattingCode in this.formatting) {
stringBuilder.append(ProtocolDefinition.TEXT_COMPONENT_SPECIAL_PREFIX_CHAR) stringBuilder.append(ProtocolDefinition.TEXT_COMPONENT_FORMATTING_PREFIX)
stringBuilder.append(formattingCode.char) stringBuilder.append(formattingCode.char)
} }
stringBuilder.append(this.message) stringBuilder.append(this.message)
stringBuilder.append(ProtocolDefinition.TEXT_COMPONENT_SPECIAL_PREFIX_CHAR).append(PostChatFormattingCodes.RESET.char) // ToDo: This should not always be appended stringBuilder.append(ProtocolDefinition.TEXT_COMPONENT_FORMATTING_PREFIX).append(PostChatFormattingCodes.RESET.char) // ToDo: This should not always be appended
return stringBuilder.toString() return stringBuilder.toString()
} }

View File

@ -20,6 +20,7 @@ import de.bixilon.minosoft.config.key.KeyActions
import de.bixilon.minosoft.config.key.KeyBinding import de.bixilon.minosoft.config.key.KeyBinding
import de.bixilon.minosoft.config.key.KeyCodes import de.bixilon.minosoft.config.key.KeyCodes
import de.bixilon.minosoft.data.chat.ChatTextPositions import de.bixilon.minosoft.data.chat.ChatTextPositions
import de.bixilon.minosoft.data.chat.message.internal.InternalChatMessage
import de.bixilon.minosoft.data.registries.identified.Namespaces.minosoft import de.bixilon.minosoft.data.registries.identified.Namespaces.minosoft
import de.bixilon.minosoft.data.registries.identified.ResourceLocation import de.bixilon.minosoft.data.registries.identified.ResourceLocation
import de.bixilon.minosoft.gui.rendering.font.Font import de.bixilon.minosoft.gui.rendering.font.Font
@ -33,8 +34,7 @@ import de.bixilon.minosoft.gui.rendering.gui.hud.elements.HUDBuilder
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions
import de.bixilon.minosoft.gui.rendering.system.window.KeyChangeTypes import de.bixilon.minosoft.gui.rendering.system.window.KeyChangeTypes
import de.bixilon.minosoft.modding.event.events.InternalMessageReceiveEvent import de.bixilon.minosoft.modding.event.events.chat.ChatMessageEvent
import de.bixilon.minosoft.modding.event.events.chat.ChatMessageReceiveEvent
import de.bixilon.minosoft.modding.event.listener.CallbackEventListener.Companion.listen import de.bixilon.minosoft.modding.event.listener.CallbackEventListener.Companion.listen
import de.bixilon.minosoft.util.KUtil.toResourceLocation import de.bixilon.minosoft.util.KUtil.toResourceLocation
import de.bixilon.minosoft.util.delegate.RenderingDelegate.observeRendering import de.bixilon.minosoft.util.delegate.RenderingDelegate.observeRendering
@ -82,16 +82,15 @@ class ChatElement(guiRenderer: GUIRenderer) : AbstractChatElement(guiRenderer),
override fun init() { override fun init() {
connection.events.listen<ChatMessageReceiveEvent> { connection.events.listen<ChatMessageEvent> {
if (it.message.type.position == ChatTextPositions.HOTBAR) { if (it.message.type.position == ChatTextPositions.HOTBAR) {
return@listen return@listen
} }
DefaultThreadPool += { messages += it.message.text } if (it.message is InternalChatMessage && !profile.chat.internal.hidden) {
} // message will be displayed in internal chat
connection.events.listen<InternalMessageReceiveEvent> {
if (!profile.chat.internal.hidden) {
return@listen return@listen
} }
DefaultThreadPool += { messages += it.message.text } DefaultThreadPool += { messages += it.message.text }
} }

View File

@ -1,6 +1,6 @@
/* /*
* Minosoft * Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger * Copyright (C) 2020-2023 Moritz Zwerger
* *
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
* *
@ -15,9 +15,10 @@ package de.bixilon.minosoft.gui.rendering.gui.hud.elements.chat
import de.bixilon.kotlinglm.vec2.Vec2i import de.bixilon.kotlinglm.vec2.Vec2i
import de.bixilon.kutil.concurrent.pool.DefaultThreadPool import de.bixilon.kutil.concurrent.pool.DefaultThreadPool
import de.bixilon.minosoft.data.chat.message.internal.InternalChatMessage
import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
import de.bixilon.minosoft.gui.rendering.gui.elements.Element import de.bixilon.minosoft.gui.rendering.gui.elements.Element
import de.bixilon.minosoft.modding.event.events.InternalMessageReceiveEvent import de.bixilon.minosoft.modding.event.events.chat.ChatMessageEvent
import de.bixilon.minosoft.modding.event.listener.CallbackEventListener.Companion.listen import de.bixilon.minosoft.modding.event.listener.CallbackEventListener.Companion.listen
import de.bixilon.minosoft.util.delegate.RenderingDelegate.observeRendering import de.bixilon.minosoft.util.delegate.RenderingDelegate.observeRendering
@ -47,11 +48,11 @@ class InternalChatElement(guiRenderer: GUIRenderer) : AbstractChatElement(guiRen
override fun init() { override fun init() {
connection.events.listen<InternalMessageReceiveEvent> { connection.events.listen<ChatMessageEvent> {
if (profile.chat.internal.hidden) { if (it.message !is InternalChatMessage || profile.chat.internal.hidden) {
return@listen return@listen
} }
DefaultThreadPool += { messages += it.message.text } DefaultThreadPool += { messages += it.message.raw }
} }
} }

View File

@ -34,7 +34,7 @@ import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions
import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.EMPTY import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.EMPTY
import de.bixilon.minosoft.gui.rendering.util.vec.vec4.Vec4iUtil.left import de.bixilon.minosoft.gui.rendering.util.vec.vec4.Vec4iUtil.left
import de.bixilon.minosoft.gui.rendering.util.vec.vec4.Vec4iUtil.right import de.bixilon.minosoft.gui.rendering.util.vec.vec4.Vec4iUtil.right
import de.bixilon.minosoft.modding.event.events.chat.ChatMessageReceiveEvent import de.bixilon.minosoft.modding.event.events.chat.ChatMessageEvent
import de.bixilon.minosoft.modding.event.listener.CallbackEventListener.Companion.listen import de.bixilon.minosoft.modding.event.listener.CallbackEventListener.Companion.listen
import de.bixilon.minosoft.util.KUtil.toResourceLocation import de.bixilon.minosoft.util.KUtil.toResourceLocation
import de.bixilon.minosoft.util.delegate.RenderingDelegate.observeRendering import de.bixilon.minosoft.util.delegate.RenderingDelegate.observeRendering
@ -178,7 +178,7 @@ class HotbarElement(guiRenderer: GUIRenderer) : Element(guiRenderer), LayoutedEl
player::selectedHotbarSlot.observeRendering(this) { core.base.apply() } player::selectedHotbarSlot.observeRendering(this) { core.base.apply() }
connection.events.listen<ChatMessageReceiveEvent> { connection.events.listen<ChatMessageEvent> {
if (it.message.type.position != ChatTextPositions.HOTBAR) { if (it.message.type.position != ChatTextPositions.HOTBAR) {
return@listen return@listen
} }

View File

@ -1,6 +1,6 @@
/* /*
* Minosoft * Minosoft
* Copyright (C) 2020 Moritz Zwerger * Copyright (C) 2020-2023 Moritz Zwerger
* *
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
* *
@ -14,6 +14,7 @@ package de.bixilon.minosoft.modding.event.events
import de.bixilon.kutil.collections.CollectionUtil.synchronizedSetOf import de.bixilon.kutil.collections.CollectionUtil.synchronizedSetOf
@Deprecated("field")
interface CancelableEvent { interface CancelableEvent {
var cancelled: Boolean var cancelled: Boolean
get() = CANCELLED_EVENTS.contains(this) get() = CANCELLED_EVENTS.contains(this)

View File

@ -1,6 +1,6 @@
/* /*
* Minosoft * Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger * Copyright (C) 2020-2023 Moritz Zwerger
* *
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
* *
@ -17,7 +17,7 @@ import de.bixilon.minosoft.modding.event.events.CancelableEvent
import de.bixilon.minosoft.modding.event.events.connection.play.PlayConnectionEvent import de.bixilon.minosoft.modding.event.events.connection.play.PlayConnectionEvent
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
class ChatMessageReceiveEvent( class ChatMessageEvent(
connection: PlayConnection, connection: PlayConnection,
val message: ChatMessage, val message: ChatMessage,
) : PlayConnectionEvent(connection), CancelableEvent ) : PlayConnectionEvent(connection), CancelableEvent

View File

@ -45,7 +45,7 @@ import de.bixilon.minosoft.data.text.ChatComponent
import de.bixilon.minosoft.data.world.World import de.bixilon.minosoft.data.world.World
import de.bixilon.minosoft.gui.eros.dialog.ErosErrorReport.Companion.report import de.bixilon.minosoft.gui.eros.dialog.ErosErrorReport.Companion.report
import de.bixilon.minosoft.gui.rendering.Rendering import de.bixilon.minosoft.gui.rendering.Rendering
import de.bixilon.minosoft.modding.event.events.chat.ChatMessageReceiveEvent import de.bixilon.minosoft.modding.event.events.chat.ChatMessageEvent
import de.bixilon.minosoft.modding.event.events.connection.play.PlayConnectionCreateEvent import de.bixilon.minosoft.modding.event.events.connection.play.PlayConnectionCreateEvent
import de.bixilon.minosoft.modding.event.events.loading.RegistriesLoadEvent import de.bixilon.minosoft.modding.event.events.loading.RegistriesLoadEvent
import de.bixilon.minosoft.modding.event.listener.CallbackEventListener import de.bixilon.minosoft.modding.event.listener.CallbackEventListener
@ -58,6 +58,7 @@ import de.bixilon.minosoft.protocol.network.connection.play.channel.ConnectionCh
import de.bixilon.minosoft.protocol.network.connection.play.channel.DefaultChannelHandlers import de.bixilon.minosoft.protocol.network.connection.play.channel.DefaultChannelHandlers
import de.bixilon.minosoft.protocol.network.connection.play.settings.ClientSettingsManager import de.bixilon.minosoft.protocol.network.connection.play.settings.ClientSettingsManager
import de.bixilon.minosoft.protocol.network.connection.play.tick.ConnectionTicker import de.bixilon.minosoft.protocol.network.connection.play.tick.ConnectionTicker
import de.bixilon.minosoft.protocol.network.connection.play.util.ConnectionUtil
import de.bixilon.minosoft.protocol.packets.c2s.handshaking.HandshakeC2SP import de.bixilon.minosoft.protocol.packets.c2s.handshaking.HandshakeC2SP
import de.bixilon.minosoft.protocol.packets.c2s.login.StartC2SP import de.bixilon.minosoft.protocol.packets.c2s.login.StartC2SP
import de.bixilon.minosoft.protocol.protocol.ProtocolStates import de.bixilon.minosoft.protocol.protocol.ProtocolStates
@ -155,7 +156,7 @@ class PlayConnection(
CLI.connection = this CLI.connection = this
} }
events.register(CallbackEventListener.of<ChatMessageReceiveEvent> { events.register(CallbackEventListener.of<ChatMessageEvent> {
val additionalPrefix = when (it.message.type.position) { val additionalPrefix = when (it.message.type.position) {
ChatTextPositions.SYSTEM -> "[SYSTEM] " ChatTextPositions.SYSTEM -> "[SYSTEM] "
ChatTextPositions.HOTBAR -> "[HOTBAR] " ChatTextPositions.HOTBAR -> "[HOTBAR] "

View File

@ -11,34 +11,31 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft. * This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/ */
package de.bixilon.minosoft.protocol.network.connection.play package de.bixilon.minosoft.protocol.network.connection.play.util
import de.bixilon.kotlinglm.vec3.Vec3d import de.bixilon.kotlinglm.vec3.Vec3d
import de.bixilon.kutil.string.WhitespaceUtil.trimWhitespaces
import de.bixilon.minosoft.commands.nodes.ChatNode import de.bixilon.minosoft.commands.nodes.ChatNode
import de.bixilon.minosoft.commands.stack.CommandStack import de.bixilon.minosoft.commands.stack.CommandStack
import de.bixilon.minosoft.commands.util.CommandReader import de.bixilon.minosoft.commands.util.CommandReader
import de.bixilon.minosoft.data.chat.message.InternalChatMessage import de.bixilon.minosoft.data.chat.ChatUtil
import de.bixilon.minosoft.data.chat.message.internal.DebugChatMessage
import de.bixilon.minosoft.data.chat.message.internal.InternalChatMessage
import de.bixilon.minosoft.data.chat.signature.Acknowledgement import de.bixilon.minosoft.data.chat.signature.Acknowledgement
import de.bixilon.minosoft.data.chat.signature.signer.MessageSigner import de.bixilon.minosoft.data.chat.signature.signer.MessageSigner
import de.bixilon.minosoft.data.entities.entities.player.local.HealthCondition import de.bixilon.minosoft.data.entities.entities.player.local.HealthCondition
import de.bixilon.minosoft.data.text.BaseComponent
import de.bixilon.minosoft.data.text.ChatComponent import de.bixilon.minosoft.data.text.ChatComponent
import de.bixilon.minosoft.data.text.formatting.color.ChatColors
import de.bixilon.minosoft.data.world.time.WorldTime import de.bixilon.minosoft.data.world.time.WorldTime
import de.bixilon.minosoft.data.world.weather.WorldWeather import de.bixilon.minosoft.data.world.weather.WorldWeather
import de.bixilon.minosoft.gui.rendering.RenderConstants
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3dUtil.EMPTY import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3dUtil.EMPTY
import de.bixilon.minosoft.modding.event.events.InternalMessageReceiveEvent import de.bixilon.minosoft.modding.event.events.chat.ChatMessageEvent
import de.bixilon.minosoft.modding.event.events.chat.ChatMessageSendEvent import de.bixilon.minosoft.modding.event.events.chat.ChatMessageSendEvent
import de.bixilon.minosoft.modding.event.events.container.ContainerCloseEvent import de.bixilon.minosoft.modding.event.events.container.ContainerCloseEvent
import de.bixilon.minosoft.protocol.ProtocolUtil.encodeNetwork import de.bixilon.minosoft.protocol.ProtocolUtil.encodeNetwork
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
import de.bixilon.minosoft.protocol.packets.c2s.play.chat.ChatMessageC2SP import de.bixilon.minosoft.protocol.packets.c2s.play.chat.ChatMessageC2SP
import de.bixilon.minosoft.protocol.packets.c2s.play.chat.CommandC2SP import de.bixilon.minosoft.protocol.packets.c2s.play.chat.CommandC2SP
import de.bixilon.minosoft.protocol.packets.c2s.play.chat.SignedChatMessageC2SP import de.bixilon.minosoft.protocol.packets.c2s.play.chat.SignedChatMessageC2SP
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import de.bixilon.minosoft.util.logging.Log import de.bixilon.minosoft.util.logging.Log
import de.bixilon.minosoft.util.logging.LogLevels
import de.bixilon.minosoft.util.logging.LogMessageType import de.bixilon.minosoft.util.logging.LogMessageType
import java.security.PrivateKey import java.security.PrivateKey
import java.security.SecureRandom import java.security.SecureRandom
@ -50,38 +47,23 @@ class ConnectionUtil(
val signer = MessageSigner.forVersion(connection.version, connection) val signer = MessageSigner.forVersion(connection.version, connection)
private val random = SecureRandom() private val random = SecureRandom()
fun sendDebugMessage(message: Any) { fun sendDebugMessage(raw: Any) {
val component = BaseComponent(RenderConstants.DEBUG_MESSAGES_PREFIX, ChatComponent.of(message).apply { this.setFallbackColor(ChatColors.BLUE) }) val message = DebugChatMessage(ChatComponent.of(raw))
connection.events.fire(InternalMessageReceiveEvent(connection, InternalChatMessage(component))) connection.events.fire(ChatMessageEvent(connection, message))
Log.log(LogMessageType.CHAT_IN, LogLevels.INFO) { component }
} }
fun sendInternal(message: Any) { fun sendInternal(raw: Any) {
val component = ChatComponent.of(message) val message = InternalChatMessage(ChatComponent.of(raw))
val prefixed = BaseComponent(RenderConstants.INTERNAL_MESSAGES_PREFIX, component) connection.events.fire(ChatMessageEvent(connection, message))
connection.events.fire(InternalMessageReceiveEvent(connection, InternalChatMessage(if (connection.profiles.gui.chat.internal.hidden) prefixed else component)))
Log.log(LogMessageType.CHAT_IN, LogLevels.INFO) { prefixed }
} }
fun typeChat(message: String) { fun typeChat(message: String) {
ChatNode("", allowCLI = false).execute(CommandReader(message), CommandStack(connection)) ChatNode("", allowCLI = false).execute(CommandReader(message), CommandStack(connection))
} }
private fun validateChatMessage(message: String) {
if (message.isBlank()) {
throw IllegalArgumentException("Chat message can not be blank!")
}
if (message.contains(ProtocolDefinition.TEXT_COMPONENT_SPECIAL_PREFIX_CHAR)) {
throw IllegalArgumentException("Chat message must not contain chat formatting (${ProtocolDefinition.TEXT_COMPONENT_SPECIAL_PREFIX_CHAR}): $message")
}
if (message.length > connection.version.maxChatMessageSize) {
throw IllegalArgumentException("Message length (${message.length} can not exceed ${connection.version.maxChatMessageSize})")
}
}
fun sendChatMessage(message: String) { fun sendChatMessage(message: String) {
val trimmed = message.trimWhitespaces() val trimmed = ChatUtil.trimChatMessage(message)
validateChatMessage(trimmed) ChatUtil.validateChatMessage(connection, message)
if (connection.events.fire(ChatMessageSendEvent(connection, trimmed))) { if (connection.events.fire(ChatMessageSendEvent(connection, trimmed))) {
return return
} }
@ -113,10 +95,10 @@ class ConnectionUtil(
if (!connection.version.requiresSignedChat || connection.profiles.connection.signature.sendCommandAsMessage) { if (!connection.version.requiresSignedChat || connection.profiles.connection.signature.sendCommandAsMessage) {
return sendChatMessage(command) return sendChatMessage(command)
} }
val trimmed = command.trimWhitespaces().removePrefix("/") val trimmed = ChatUtil.trimChatMessage(command).removePrefix("/")
validateChatMessage(trimmed) ChatUtil.validateChatMessage(connection, trimmed)
if (stack.size == 0) { if (stack.size == 0) {
throw IllegalArgumentException("Empty command stack! Did the command failed to parse?") throw IllegalArgumentException("Empty command stack! Did the command fail to parse?")
} }
val salt = SecureRandom().nextLong() val salt = SecureRandom().nextLong()
val time = Instant.now() val time = Instant.now()

View File

@ -19,7 +19,7 @@ import de.bixilon.minosoft.data.chat.message.SimpleChatMessage
import de.bixilon.minosoft.data.chat.type.DefaultMessageTypes import de.bixilon.minosoft.data.chat.type.DefaultMessageTypes
import de.bixilon.minosoft.data.registries.chat.ChatMessageType import de.bixilon.minosoft.data.registries.chat.ChatMessageType
import de.bixilon.minosoft.data.text.ChatComponent import de.bixilon.minosoft.data.text.ChatComponent
import de.bixilon.minosoft.modding.event.events.chat.ChatMessageReceiveEvent import de.bixilon.minosoft.modding.event.events.chat.ChatMessageEvent
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
import de.bixilon.minosoft.protocol.packets.factory.LoadPacket import de.bixilon.minosoft.protocol.packets.factory.LoadPacket
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
@ -64,7 +64,7 @@ class ChatMessageS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
} else { } else {
PlayerChatMessage(text, type, connection.getMessageSender(sender)) PlayerChatMessage(text, type, connection.getMessageSender(sender))
} }
connection.events.fire(ChatMessageReceiveEvent(connection, message)) connection.events.fire(ChatMessageEvent(connection, message))
} }
override fun log(reducedLog: Boolean) { override fun log(reducedLog: Boolean) {

View File

@ -22,7 +22,7 @@ import de.bixilon.minosoft.data.chat.signature.verifyer.MessageVerifyUtil
import de.bixilon.minosoft.data.registries.chat.ChatParameter import de.bixilon.minosoft.data.registries.chat.ChatParameter
import de.bixilon.minosoft.data.text.ChatComponent import de.bixilon.minosoft.data.text.ChatComponent
import de.bixilon.minosoft.data.text.TextComponent import de.bixilon.minosoft.data.text.TextComponent
import de.bixilon.minosoft.modding.event.events.chat.ChatMessageReceiveEvent import de.bixilon.minosoft.modding.event.events.chat.ChatMessageEvent
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
import de.bixilon.minosoft.protocol.packets.factory.LoadPacket import de.bixilon.minosoft.protocol.packets.factory.LoadPacket
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
@ -144,7 +144,7 @@ class SignedChatMessageS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
return return
} }
} }
connection.events.fire(ChatMessageReceiveEvent(connection, message)) connection.events.fire(ChatMessageEvent(connection, message))
} }
override fun log(reducedLog: Boolean) { override fun log(reducedLog: Boolean) {

View File

@ -15,7 +15,7 @@ package de.bixilon.minosoft.protocol.packets.s2c.play.chat
import de.bixilon.minosoft.data.chat.message.FormattedChatMessage import de.bixilon.minosoft.data.chat.message.FormattedChatMessage
import de.bixilon.minosoft.data.registries.chat.ChatParameter import de.bixilon.minosoft.data.registries.chat.ChatParameter
import de.bixilon.minosoft.data.text.ChatComponent import de.bixilon.minosoft.data.text.ChatComponent
import de.bixilon.minosoft.modding.event.events.chat.ChatMessageReceiveEvent import de.bixilon.minosoft.modding.event.events.chat.ChatMessageEvent
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
import de.bixilon.minosoft.protocol.packets.factory.LoadPacket import de.bixilon.minosoft.protocol.packets.factory.LoadPacket
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
@ -35,7 +35,7 @@ class UnsignedChatMessageS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
override fun handle(connection: PlayConnection) { override fun handle(connection: PlayConnection) {
val message = FormattedChatMessage(connection, type, parameters) val message = FormattedChatMessage(connection, type, parameters)
connection.events.fire(ChatMessageReceiveEvent(connection, message)) connection.events.fire(ChatMessageEvent(connection, message))
} }
override fun log(reducedLog: Boolean) { override fun log(reducedLog: Boolean) {

View File

@ -15,7 +15,7 @@ package de.bixilon.minosoft.protocol.packets.s2c.play.title
import de.bixilon.minosoft.data.chat.message.SimpleChatMessage import de.bixilon.minosoft.data.chat.message.SimpleChatMessage
import de.bixilon.minosoft.data.chat.type.DefaultMessageTypes import de.bixilon.minosoft.data.chat.type.DefaultMessageTypes
import de.bixilon.minosoft.modding.event.events.chat.ChatMessageReceiveEvent import de.bixilon.minosoft.modding.event.events.chat.ChatMessageEvent
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
import de.bixilon.minosoft.protocol.packets.factory.LoadPacket import de.bixilon.minosoft.protocol.packets.factory.LoadPacket
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
@ -34,6 +34,6 @@ class HotbarTextS2CP(buffer: PlayInByteBuffer) : TitleS2CP {
override fun handle(connection: PlayConnection) { override fun handle(connection: PlayConnection) {
Log.log(LogMessageType.CHAT_IN) { "[HOTBAR] $text" } Log.log(LogMessageType.CHAT_IN) { "[HOTBAR] $text" }
val message = SimpleChatMessage(text, connection.registries.messageType[DefaultMessageTypes.GAME]!!) val message = SimpleChatMessage(text, connection.registries.messageType[DefaultMessageTypes.GAME]!!)
connection.events.fire(ChatMessageReceiveEvent(connection, message)) connection.events.fire(ChatMessageEvent(connection, message))
} }
} }

View File

@ -30,7 +30,7 @@ public final class ProtocolDefinition {
public static final int QUERY_PROTOCOL_VERSION_ID = -1; public static final int QUERY_PROTOCOL_VERSION_ID = -1;
public static final char TEXT_COMPONENT_SPECIAL_PREFIX_CHAR = '§'; public static final char TEXT_COMPONENT_FORMATTING_PREFIX = '§';
public static final int AIR_BLOCK_ID = 0; public static final int AIR_BLOCK_ID = 0;

View File

@ -1,6 +1,6 @@
/* /*
* Minosoft * Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger * Copyright (C) 2020-2023 Moritz Zwerger
* *
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
* *
@ -41,7 +41,7 @@ object ChatComponentColorSerializer : SimpleModule() {
object Serializer : StdSerializer<ChatComponent>(ChatComponent::class.java) { object Serializer : StdSerializer<ChatComponent>(ChatComponent::class.java) {
override fun serialize(value: ChatComponent?, generator: JsonGenerator, provider: SerializerProvider?) { override fun serialize(value: ChatComponent?, generator: JsonGenerator, provider: SerializerProvider?) {
generator.writeString(value?.legacyText?.removeSuffix(ProtocolDefinition.TEXT_COMPONENT_SPECIAL_PREFIX_CHAR.toString() + PostChatFormattingCodes.RESET.char.toString())) generator.writeString(value?.legacyText?.removeSuffix(ProtocolDefinition.TEXT_COMPONENT_FORMATTING_PREFIX.toString() + PostChatFormattingCodes.RESET.char.toString()))
} }
} }
} }

View File

@ -1,6 +1,6 @@
/* /*
* Minosoft * Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger * Copyright (C) 2020-2023 Moritz Zwerger
* *
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
* *
@ -18,6 +18,7 @@ import de.bixilon.minosoft.config.profile.profiles.other.OtherProfileSelectEvent
import de.bixilon.minosoft.data.text.BaseComponent import de.bixilon.minosoft.data.text.BaseComponent
import de.bixilon.minosoft.data.text.ChatComponent import de.bixilon.minosoft.data.text.ChatComponent
import de.bixilon.minosoft.data.text.TextComponent import de.bixilon.minosoft.data.text.TextComponent
import de.bixilon.minosoft.data.text.formatting.TextFormattable
import de.bixilon.minosoft.modding.event.listener.CallbackEventListener import de.bixilon.minosoft.modding.event.listener.CallbackEventListener
import de.bixilon.minosoft.modding.event.master.GlobalEventMaster import de.bixilon.minosoft.modding.event.master.GlobalEventMaster
import de.bixilon.minosoft.terminal.RunConfiguration import de.bixilon.minosoft.terminal.RunConfiguration
@ -125,6 +126,7 @@ object Log {
} }
val formattedMessage = when (message) { val formattedMessage = when (message) {
is ChatComponent -> message is ChatComponent -> message
is TextFormattable -> ChatComponent.of(message.toText())
is Throwable -> { is Throwable -> {
val stringWriter = StringWriter() val stringWriter = StringWriter()
message.printStackTrace(PrintWriter(stringWriter)) message.printStackTrace(PrintWriter(stringWriter))