2022-06-21 21:01:24 +02:00
/ *
* This file is part of ViaVersion - https : //github.com/ViaVersion/ViaVersion
2024-01-01 12:39:45 +01:00
* Copyright ( C ) 2016 - 2024 ViaVersion and contributors
2022-06-21 21:01:24 +02:00
*
* 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 distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
* /
package com.viaversion.viaversion.protocols.protocol1_19_1to1_19 ;
2023-10-08 10:44:54 +02:00
import com.github.steveice10.opennbt.stringified.SNBT ;
2023-12-26 23:38:02 +01:00
import com.github.steveice10.opennbt.tag.builtin.ByteTag ;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag ;
import com.github.steveice10.opennbt.tag.builtin.ListTag ;
import com.github.steveice10.opennbt.tag.builtin.NumberTag ;
import com.github.steveice10.opennbt.tag.builtin.StringTag ;
import com.github.steveice10.opennbt.tag.builtin.Tag ;
2022-07-28 12:38:51 +02:00
import com.google.common.base.Preconditions ;
2022-06-30 20:00:55 +02:00
import com.google.gson.JsonElement ;
2022-07-28 12:38:51 +02:00
import com.viaversion.viaversion.api.Via ;
import com.viaversion.viaversion.api.connection.UserConnection ;
2022-07-15 21:01:55 +02:00
import com.viaversion.viaversion.api.minecraft.ProfileKey ;
2023-10-24 02:04:54 +02:00
import com.viaversion.viaversion.api.minecraft.signature.SignableCommandArgumentsProvider ;
2023-10-22 11:33:59 +02:00
import com.viaversion.viaversion.api.minecraft.signature.model.DecoratableMessage ;
import com.viaversion.viaversion.api.minecraft.signature.model.MessageMetadata ;
import com.viaversion.viaversion.api.minecraft.signature.storage.ChatSession1_19_0 ;
2022-06-21 21:01:24 +02:00
import com.viaversion.viaversion.api.protocol.AbstractProtocol ;
2022-06-30 10:44:29 +02:00
import com.viaversion.viaversion.api.protocol.packet.State ;
2023-02-12 10:54:47 +01:00
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers ;
2022-06-30 10:44:29 +02:00
import com.viaversion.viaversion.api.type.Type ;
2022-07-15 21:01:55 +02:00
import com.viaversion.viaversion.protocols.base.ClientboundLoginPackets ;
2022-06-30 10:44:29 +02:00
import com.viaversion.viaversion.protocols.base.ServerboundLoginPackets ;
2022-07-28 12:38:51 +02:00
import com.viaversion.viaversion.protocols.protocol1_19_1to1_19.storage.ChatTypeStorage ;
2022-07-15 21:01:55 +02:00
import com.viaversion.viaversion.protocols.protocol1_19_1to1_19.storage.NonceStorage ;
2022-06-21 21:01:24 +02:00
import com.viaversion.viaversion.protocols.protocol1_19to1_18_2.ClientboundPackets1_19 ;
import com.viaversion.viaversion.protocols.protocol1_19to1_18_2.ServerboundPackets1_19 ;
2022-07-15 21:01:55 +02:00
import com.viaversion.viaversion.util.CipherUtil ;
2023-10-24 02:04:54 +02:00
import com.viaversion.viaversion.util.Pair ;
2022-07-28 14:56:35 +02:00
import java.util.ArrayList ;
import java.util.List ;
2023-12-26 23:38:02 +01:00
import java.util.Map ;
2023-10-22 11:33:59 +02:00
import java.util.UUID ;
2023-12-26 23:38:02 +01:00
import net.lenni0451.mcstructs.core.TextFormatting ;
import net.lenni0451.mcstructs.text.ATextComponent ;
import net.lenni0451.mcstructs.text.Style ;
import net.lenni0451.mcstructs.text.components.TranslationComponent ;
import net.lenni0451.mcstructs.text.serializer.TextComponentSerializer ;
import org.checkerframework.checker.nullness.qual.Nullable ;
2022-06-30 20:00:55 +02:00
2022-07-15 16:26:58 +02:00
public final class Protocol1_19_1To1_19 extends AbstractProtocol < ClientboundPackets1_19 , ClientboundPackets1_19_1 , ServerboundPackets1_19 , ServerboundPackets1_19_1 > {
2022-06-30 10:44:29 +02:00
2024-01-26 15:48:10 +01:00
private static final String CHAT_REGISTRY_SNBT = " { " +
" \" minecraft:chat_type \" : { " +
" \" type \" : \" minecraft:chat_type \" , " +
" \" value \" : [ " +
" { " +
" \" name \" : \" minecraft:chat \" , " +
" \" id \" :1, " +
" \" element \" :{ " +
" \" chat \" :{ " +
" \" translation_key \" : \" chat.type.text \" , " +
" \" parameters \" :[ " +
" \" sender \" , " +
" \" content \" " +
" ] " +
" }, " +
" \" narration \" :{ " +
" \" translation_key \" : \" chat.type.text.narrate \" , " +
" \" parameters \" :[ " +
" \" sender \" , " +
" \" content \" " +
" ] " +
" } " +
" } " +
2022-06-30 20:00:55 +02:00
" } " +
2024-01-26 15:48:10 +01:00
" ] " +
" } " +
2022-06-30 20:00:55 +02:00
" } " ;
private static final CompoundTag CHAT_REGISTRY ;
static {
2024-03-09 12:57:55 +01:00
CHAT_REGISTRY = SNBT . deserializeCompoundTag ( CHAT_REGISTRY_SNBT ) . getCompoundTag ( " minecraft:chat_type " ) ;
2022-06-30 20:00:55 +02:00
}
2022-07-06 17:47:47 +02:00
public Protocol1_19_1To1_19 ( ) {
2022-07-15 16:26:58 +02:00
super ( ClientboundPackets1_19 . class , ClientboundPackets1_19_1 . class , ServerboundPackets1_19 . class , ServerboundPackets1_19_1 . class ) ;
2022-07-06 17:47:47 +02:00
}
2022-06-30 10:44:29 +02:00
@Override
protected void registerPackets ( ) {
2023-02-12 10:54:47 +01:00
registerClientbound ( ClientboundPackets1_19 . SYSTEM_CHAT , new PacketHandlers ( ) {
2022-06-30 10:44:29 +02:00
@Override
2023-02-12 10:54:47 +01:00
public void register ( ) {
2022-06-30 20:00:55 +02:00
map ( Type . COMPONENT ) ; // Content
2022-06-30 10:44:29 +02:00
handler ( wrapper - > {
2022-06-30 20:00:55 +02:00
final int type = wrapper . read ( Type . VAR_INT ) ;
final boolean overlay = type = = 2 ;
wrapper . write ( Type . BOOLEAN , overlay ) ;
} ) ;
}
} ) ;
2023-02-12 10:54:47 +01:00
registerClientbound ( ClientboundPackets1_19 . PLAYER_CHAT , ClientboundPackets1_19_1 . SYSTEM_CHAT , new PacketHandlers ( ) {
2022-06-30 20:00:55 +02:00
@Override
2023-02-12 10:54:47 +01:00
public void register ( ) {
2022-06-30 20:00:55 +02:00
handler ( wrapper - > {
2022-07-28 12:38:51 +02:00
// Back to system chat
2022-07-15 21:33:55 +02:00
final JsonElement signedContent = wrapper . read ( Type . COMPONENT ) ;
2022-07-08 16:20:54 +02:00
final JsonElement unsignedContent = wrapper . read ( Type . OPTIONAL_COMPONENT ) ;
2022-08-04 16:23:21 +02:00
final int chatTypeId = wrapper . read ( Type . VAR_INT ) ;
2022-07-28 12:38:51 +02:00
wrapper . read ( Type . UUID ) ; // Sender UUID
final JsonElement senderName = wrapper . read ( Type . COMPONENT ) ;
final JsonElement teamName = wrapper . read ( Type . OPTIONAL_COMPONENT ) ;
2022-08-04 16:23:21 +02:00
final CompoundTag chatType = wrapper . user ( ) . get ( ChatTypeStorage . class ) . chatType ( chatTypeId ) ;
final ChatDecorationResult decorationResult = decorateChatMessage ( chatType , chatTypeId , senderName , teamName , unsignedContent ! = null ? unsignedContent : signedContent ) ;
if ( decorationResult = = null ) {
2022-07-28 12:38:51 +02:00
wrapper . cancel ( ) ;
2022-08-04 16:23:21 +02:00
return ;
2022-07-28 12:38:51 +02:00
}
2022-08-04 16:23:21 +02:00
wrapper . write ( Type . COMPONENT , decorationResult . content ( ) ) ;
wrapper . write ( Type . BOOLEAN , decorationResult . overlay ( ) ) ;
2022-06-30 10:44:29 +02:00
} ) ;
2022-07-08 16:20:54 +02:00
read ( Type . LONG ) ; // Timestamp
read ( Type . LONG ) ; // Salt
read ( Type . BYTE_ARRAY_PRIMITIVE ) ; // Signature
2022-06-30 10:44:29 +02:00
}
} ) ;
2023-02-12 10:54:47 +01:00
registerServerbound ( ServerboundPackets1_19_1 . CHAT_MESSAGE , new PacketHandlers ( ) {
2022-07-15 21:01:55 +02:00
@Override
2023-02-12 10:54:47 +01:00
public void register ( ) {
2022-07-15 21:01:55 +02:00
map ( Type . STRING ) ; // Message
map ( Type . LONG ) ; // Timestamp
map ( Type . LONG ) ; // Salt
2023-10-23 02:28:44 +02:00
map ( Type . BYTE_ARRAY_PRIMITIVE ) ; // Signature
map ( Type . BOOLEAN ) ; // Signed preview
2023-10-22 11:33:59 +02:00
handler ( wrapper - > {
final ChatSession1_19_0 chatSession = wrapper . user ( ) . get ( ChatSession1_19_0 . class ) ;
if ( chatSession ! = null ) {
final UUID sender = wrapper . user ( ) . getProtocolInfo ( ) . getUuid ( ) ;
final String message = wrapper . get ( Type . STRING , 0 ) ;
final long timestamp = wrapper . get ( Type . LONG , 0 ) ;
final long salt = wrapper . get ( Type . LONG , 1 ) ;
final MessageMetadata metadata = new MessageMetadata ( sender , timestamp , salt ) ;
final DecoratableMessage decoratableMessage = new DecoratableMessage ( message ) ;
final byte [ ] signature = chatSession . signChatMessage ( metadata , decoratableMessage ) ;
2023-10-23 02:28:44 +02:00
wrapper . set ( Type . BYTE_ARRAY_PRIMITIVE , 0 , signature ) ; // Signature
wrapper . set ( Type . BOOLEAN , 0 , decoratableMessage . isDecorated ( ) ) ; // Signed preview
2023-10-22 11:33:59 +02:00
}
} ) ;
2022-07-15 21:01:55 +02:00
read ( Type . PLAYER_MESSAGE_SIGNATURE_ARRAY ) ; // Last seen messages
read ( Type . OPTIONAL_PLAYER_MESSAGE_SIGNATURE ) ; // Last received message
}
} ) ;
2023-02-12 10:54:47 +01:00
registerServerbound ( ServerboundPackets1_19_1 . CHAT_COMMAND , new PacketHandlers ( ) {
2022-07-15 21:01:55 +02:00
@Override
2023-02-12 10:54:47 +01:00
public void register ( ) {
2022-07-15 21:01:55 +02:00
map ( Type . STRING ) ; // Command
map ( Type . LONG ) ; // Timestamp
map ( Type . LONG ) ; // Salt
handler ( wrapper - > {
2023-10-24 02:04:54 +02:00
final ChatSession1_19_0 chatSession = wrapper . user ( ) . get ( ChatSession1_19_0 . class ) ;
final SignableCommandArgumentsProvider argumentsProvider = Via . getManager ( ) . getProviders ( ) . get ( SignableCommandArgumentsProvider . class ) ;
final int signatures = wrapper . read ( Type . VAR_INT ) ;
2022-07-15 21:01:55 +02:00
for ( int i = 0 ; i < signatures ; i + + ) {
2023-10-24 02:04:54 +02:00
wrapper . read ( Type . STRING ) ; // Argument name
wrapper . read ( Type . BYTE_ARRAY_PRIMITIVE ) ; // Signature
}
if ( chatSession ! = null & & argumentsProvider ! = null ) {
final UUID sender = wrapper . user ( ) . getProtocolInfo ( ) . getUuid ( ) ;
final String message = wrapper . get ( Type . STRING , 0 ) ;
final long timestamp = wrapper . get ( Type . LONG , 0 ) ;
final long salt = wrapper . get ( Type . LONG , 1 ) ;
final List < Pair < String , String > > arguments = argumentsProvider . getSignableArguments ( message ) ;
wrapper . write ( Type . VAR_INT , arguments . size ( ) ) ; // Signature count
for ( Pair < String , String > argument : arguments ) {
final MessageMetadata metadata = new MessageMetadata ( sender , timestamp , salt ) ;
final DecoratableMessage decoratableMessage = new DecoratableMessage ( argument . value ( ) ) ;
final byte [ ] signature = chatSession . signChatMessage ( metadata , decoratableMessage ) ;
wrapper . write ( Type . STRING , argument . key ( ) ) ; // Argument name
wrapper . write ( Type . BYTE_ARRAY_PRIMITIVE , signature ) ; // Signature
}
} else {
wrapper . write ( Type . VAR_INT , 0 ) ; // Signature count
2022-07-15 21:01:55 +02:00
}
} ) ;
map ( Type . BOOLEAN ) ; // Signed preview
read ( Type . PLAYER_MESSAGE_SIGNATURE_ARRAY ) ; // Last seen messages
read ( Type . OPTIONAL_PLAYER_MESSAGE_SIGNATURE ) ; // Last received message
}
} ) ;
cancelServerbound ( ServerboundPackets1_19_1 . CHAT_ACK ) ;
2022-06-30 10:44:29 +02:00
2023-02-12 10:54:47 +01:00
registerClientbound ( ClientboundPackets1_19 . JOIN_GAME , new PacketHandlers ( ) {
2022-06-30 20:00:55 +02:00
@Override
2023-02-12 10:54:47 +01:00
public void register ( ) {
2022-06-30 20:00:55 +02:00
map ( Type . INT ) ; // Entity ID
map ( Type . BOOLEAN ) ; // Hardcore
2023-12-03 18:35:19 +01:00
map ( Type . BYTE ) ; // Gamemode
2022-06-30 20:00:55 +02:00
map ( Type . BYTE ) ; // Previous Gamemode
map ( Type . STRING_ARRAY ) ; // World List
handler ( wrapper - > {
2022-07-28 12:38:51 +02:00
final ChatTypeStorage chatTypeStorage = wrapper . user ( ) . get ( ChatTypeStorage . class ) ;
chatTypeStorage . clear ( ) ;
2023-10-06 13:37:52 +02:00
final CompoundTag registry = wrapper . passthrough ( Type . NAMED_COMPOUND_TAG ) ;
2024-03-07 12:08:27 +01:00
final ListTag < CompoundTag > chatTypes = registry . getCompoundTag ( " minecraft:chat_type " ) . getListTag ( " value " , CompoundTag . class ) ;
for ( final CompoundTag chatType : chatTypes ) {
2024-03-09 12:57:55 +01:00
final NumberTag idTag = chatType . getNumberTag ( " id " ) ;
2024-03-07 12:08:27 +01:00
chatTypeStorage . addChatType ( idTag . asInt ( ) , chatType ) ;
2022-07-28 12:38:51 +02:00
}
// Replace chat types - they won't actually be used
2023-12-31 13:38:14 +01:00
registry . put ( " minecraft:chat_type " , CHAT_REGISTRY . copy ( ) ) ;
2022-06-30 20:00:55 +02:00
} ) ;
}
} ) ;
2022-07-15 16:26:58 +02:00
2023-02-12 10:54:47 +01:00
registerClientbound ( ClientboundPackets1_19 . SERVER_DATA , new PacketHandlers ( ) {
2022-07-21 18:53:03 +02:00
@Override
2023-02-12 10:54:47 +01:00
public void register ( ) {
2022-07-21 18:53:03 +02:00
map ( Type . OPTIONAL_COMPONENT ) ; // Motd
map ( Type . OPTIONAL_STRING ) ; // Encoded icon
map ( Type . BOOLEAN ) ; // Previews chat
create ( Type . BOOLEAN , false ) ; // Enforces secure chat
}
} ) ;
2023-02-12 10:54:47 +01:00
registerServerbound ( State . LOGIN , ServerboundLoginPackets . HELLO . getId ( ) , ServerboundLoginPackets . HELLO . getId ( ) , new PacketHandlers ( ) {
2022-07-15 16:26:58 +02:00
@Override
2023-02-12 10:54:47 +01:00
public void register ( ) {
2022-07-15 16:26:58 +02:00
map ( Type . STRING ) ; // Name
2022-07-15 21:01:55 +02:00
handler ( wrapper - > {
2023-10-22 11:33:59 +02:00
final ProfileKey profileKey = wrapper . read ( Type . OPTIONAL_PROFILE_KEY ) ; // Profile Key
final ChatSession1_19_0 chatSession = wrapper . user ( ) . get ( ChatSession1_19_0 . class ) ;
wrapper . write ( Type . OPTIONAL_PROFILE_KEY , chatSession = = null ? null : chatSession . getProfileKey ( ) ) ; // Profile Key
if ( profileKey = = null | | chatSession ! = null ) {
2022-07-15 21:01:55 +02:00
// Modified client that doesn't include the profile key, or already done in 1.18->1.19 protocol; no need to map it
wrapper . user ( ) . put ( new NonceStorage ( null ) ) ;
}
} ) ;
2022-07-15 16:26:58 +02:00
read ( Type . OPTIONAL_UUID ) ; // Profile uuid
}
} ) ;
2023-02-12 10:54:47 +01:00
registerClientbound ( State . LOGIN , ClientboundLoginPackets . HELLO . getId ( ) , ClientboundLoginPackets . HELLO . getId ( ) , new PacketHandlers ( ) {
2022-07-15 16:26:58 +02:00
@Override
2023-02-12 10:54:47 +01:00
public void register ( ) {
2022-07-15 21:01:55 +02:00
map ( Type . STRING ) ; // Server id
handler ( wrapper - > {
if ( wrapper . user ( ) . has ( NonceStorage . class ) ) {
return ;
}
final byte [ ] publicKey = wrapper . passthrough ( Type . BYTE_ARRAY_PRIMITIVE ) ;
final byte [ ] nonce = wrapper . passthrough ( Type . BYTE_ARRAY_PRIMITIVE ) ;
2022-07-15 21:33:55 +02:00
wrapper . user ( ) . put ( new NonceStorage ( CipherUtil . encryptNonce ( publicKey , nonce ) ) ) ;
2022-07-15 21:01:55 +02:00
} ) ;
2022-07-15 16:26:58 +02:00
}
} ) ;
2023-02-12 10:54:47 +01:00
registerServerbound ( State . LOGIN , ServerboundLoginPackets . ENCRYPTION_KEY . getId ( ) , ServerboundLoginPackets . ENCRYPTION_KEY . getId ( ) , new PacketHandlers ( ) {
2022-07-15 16:26:58 +02:00
@Override
2023-02-12 10:54:47 +01:00
public void register ( ) {
2022-07-15 21:01:55 +02:00
map ( Type . BYTE_ARRAY_PRIMITIVE ) ; // Keys
2022-07-15 16:26:58 +02:00
handler ( wrapper - > {
2022-07-15 21:01:55 +02:00
final NonceStorage nonceStorage = wrapper . user ( ) . remove ( NonceStorage . class ) ;
if ( nonceStorage . nonce ( ) = = null ) {
return ;
}
final boolean isNonce = wrapper . read ( Type . BOOLEAN ) ;
wrapper . write ( Type . BOOLEAN , true ) ;
if ( ! isNonce ) { // Should never be true at this point, but /shrug otherwise
wrapper . read ( Type . LONG ) ; // Salt
wrapper . read ( Type . BYTE_ARRAY_PRIMITIVE ) ; // Signature
wrapper . write ( Type . BYTE_ARRAY_PRIMITIVE , nonceStorage . nonce ( ) ) ;
2022-07-15 16:26:58 +02:00
}
} ) ;
}
} ) ;
2023-02-12 10:54:47 +01:00
registerClientbound ( State . LOGIN , ClientboundLoginPackets . CUSTOM_QUERY . getId ( ) , ClientboundLoginPackets . CUSTOM_QUERY . getId ( ) , new PacketHandlers ( ) {
2022-08-03 16:17:52 +02:00
@Override
2023-02-12 10:54:47 +01:00
public void register ( ) {
2022-08-03 16:17:52 +02:00
map ( Type . VAR_INT ) ;
map ( Type . STRING ) ;
handler ( wrapper - > {
String identifier = wrapper . get ( Type . STRING , 0 ) ;
if ( identifier . equals ( " velocity:player_info " ) ) {
byte [ ] data = wrapper . passthrough ( Type . REMAINING_BYTES ) ;
// Velocity modern forwarding version above 1 includes the players public key.
// This is an issue because the server will expect a 1.19 key and receive a 1.19.1 key.
// Velocity modern forwarding versions: https://github.com/PaperMC/Velocity/blob/1a3fba4250553702d9dcd05731d04347bfc24c9f/proxy/src/main/java/com/velocitypowered/proxy/connection/VelocityConstants.java#L27-L29
// And the version can be specified with a single byte: https://github.com/PaperMC/Velocity/blob/1a3fba4250553702d9dcd05731d04347bfc24c9f/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/LoginSessionHandler.java#L88
if ( data . length = = 1 & & data [ 0 ] > 1 ) {
data [ 0 ] = 1 ;
} else if ( data . length = = 0 ) { // Or the version is omitted (default version would be used)
2022-08-04 16:23:21 +02:00
data = new byte [ ] { 1 } ;
2022-08-03 16:17:52 +02:00
wrapper . set ( Type . REMAINING_BYTES , 0 , data ) ;
} else {
Via . getPlatform ( ) . getLogger ( ) . warning ( " Received unexpected data in velocity:player_info (length= " + data . length + " ) " ) ;
}
}
} ) ;
}
} ) ;
2022-06-30 10:44:29 +02:00
}
2022-07-28 12:38:51 +02:00
@Override
public void init ( final UserConnection connection ) {
connection . put ( new ChatTypeStorage ( ) ) ;
}
2023-12-27 11:40:45 +01:00
public static @Nullable ChatDecorationResult decorateChatMessage (
final CompoundTag chatType ,
final int chatTypeId ,
final JsonElement senderName ,
@Nullable final JsonElement teamName ,
final JsonElement message
) {
2022-07-28 12:38:51 +02:00
if ( chatType = = null ) {
Via . getPlatform ( ) . getLogger ( ) . warning ( " Chat message has unknown chat type id " + chatTypeId + " . Message: " + message ) ;
2022-08-04 16:23:21 +02:00
return null ;
2022-07-28 12:38:51 +02:00
}
2024-02-10 23:28:36 +01:00
CompoundTag chatData = chatType . getCompoundTag ( " element " ) . getCompoundTag ( " chat " ) ;
2022-07-28 12:38:51 +02:00
boolean overlay = false ;
if ( chatData = = null ) {
2024-02-10 23:28:36 +01:00
chatData = chatType . getCompoundTag ( " element " ) . getCompoundTag ( " overlay " ) ;
2022-07-28 12:38:51 +02:00
if ( chatData = = null ) {
// Either narration or something we don't know
2022-08-04 16:23:21 +02:00
return null ;
2022-07-28 12:38:51 +02:00
}
overlay = true ;
}
2024-02-10 23:28:36 +01:00
final CompoundTag decoration = chatData . getCompoundTag ( " decoration " ) ;
2023-12-26 23:59:48 +01:00
if ( decoration = = null ) {
2022-08-04 16:23:21 +02:00
return new ChatDecorationResult ( message , overlay ) ;
2022-07-28 12:38:51 +02:00
}
2023-12-26 23:59:48 +01:00
return new ChatDecorationResult ( translatabaleComponentFromTag ( decoration , senderName , teamName , message ) , overlay ) ;
}
2023-12-27 11:40:45 +01:00
public static JsonElement translatabaleComponentFromTag (
final CompoundTag tag ,
final JsonElement senderName ,
@Nullable final JsonElement targetName ,
final JsonElement message
) {
2024-02-10 23:28:36 +01:00
final String translationKey = tag . getStringTag ( " translation_key " ) . getValue ( ) ;
2023-12-26 23:38:02 +01:00
final Style style = new Style ( ) ;
2022-07-28 12:38:51 +02:00
2022-07-28 14:56:35 +02:00
// Add the style
2024-02-10 23:28:36 +01:00
final CompoundTag styleTag = tag . getCompoundTag ( " style " ) ;
2023-12-26 23:38:02 +01:00
if ( styleTag ! = null ) {
2024-02-10 23:28:36 +01:00
final StringTag color = styleTag . getStringTag ( " color " ) ;
2022-07-28 14:56:35 +02:00
if ( color ! = null ) {
2023-12-26 23:38:02 +01:00
final TextFormatting textColor = TextFormatting . getByName ( color . getValue ( ) ) ;
2022-07-28 14:56:35 +02:00
if ( textColor ! = null ) {
2023-12-26 23:38:02 +01:00
style . setFormatting ( textColor ) ;
2022-07-28 14:56:35 +02:00
}
2022-07-28 12:38:51 +02:00
}
2022-07-28 14:56:35 +02:00
2023-12-26 23:38:02 +01:00
for ( final Map . Entry < String , TextFormatting > entry : TextFormatting . FORMATTINGS . entrySet ( ) ) {
2024-02-10 23:28:36 +01:00
final NumberTag formattingTag = styleTag . getNumberTag ( entry . getKey ( ) ) ;
2023-12-26 23:59:48 +01:00
if ( ! ( formattingTag instanceof ByteTag ) ) {
2023-12-26 23:38:02 +01:00
continue ;
}
2024-02-10 23:28:36 +01:00
final boolean value = formattingTag . asBoolean ( ) ;
2023-12-26 23:38:02 +01:00
final TextFormatting formatting = entry . getValue ( ) ;
if ( formatting = = TextFormatting . OBFUSCATED ) {
style . setObfuscated ( value ) ;
} else if ( formatting = = TextFormatting . BOLD ) {
style . setBold ( value ) ;
} else if ( formatting = = TextFormatting . STRIKETHROUGH ) {
style . setStrikethrough ( value ) ;
} else if ( formatting = = TextFormatting . UNDERLINE ) {
style . setUnderlined ( value ) ;
} else if ( formatting = = TextFormatting . ITALIC ) {
style . setItalic ( value ) ;
2022-07-28 12:38:51 +02:00
}
}
}
2022-07-28 14:56:35 +02:00
// Add the replacements
2024-03-07 12:08:27 +01:00
final ListTag < StringTag > parameters = tag . getListTag ( " parameters " , StringTag . class ) ;
2023-12-26 23:38:02 +01:00
final List < ATextComponent > arguments = new ArrayList < > ( ) ;
2022-07-28 18:48:33 +02:00
if ( parameters ! = null ) {
2024-03-07 12:08:27 +01:00
for ( final StringTag element : parameters ) {
2022-07-28 18:48:33 +02:00
JsonElement argument = null ;
2024-03-07 12:08:27 +01:00
switch ( element . getValue ( ) ) {
2022-07-28 18:48:33 +02:00
case " sender " :
argument = senderName ;
break ;
case " content " :
argument = message ;
break ;
case " team_name " :
2023-12-26 23:59:48 +01:00
case " target " : // So that this method can also be used in VB
Preconditions . checkNotNull ( targetName , " Team name is null " ) ;
argument = targetName ;
2022-07-28 18:48:33 +02:00
break ;
default :
Via . getPlatform ( ) . getLogger ( ) . warning ( " Unknown parameter for chat decoration: " + element . getValue ( ) ) ;
}
if ( argument ! = null ) {
2023-12-27 11:40:45 +01:00
arguments . add ( TextComponentSerializer . V1_18 . deserialize ( argument ) ) ;
2022-07-28 18:48:33 +02:00
}
2022-07-28 14:56:35 +02:00
}
2022-07-28 12:38:51 +02:00
}
2023-12-26 23:38:02 +01:00
2023-12-27 11:40:45 +01:00
return TextComponentSerializer . V1_18 . serializeJson ( new TranslationComponent ( translationKey , arguments ) ) ;
2022-07-28 12:38:51 +02:00
}
2022-06-21 21:01:24 +02:00
}