diff --git a/chat/src/main/java/net/md_5/bungee/api/chat/ClickEvent.java b/chat/src/main/java/net/md_5/bungee/api/chat/ClickEvent.java index 1389c4b2..1f643599 100644 --- a/chat/src/main/java/net/md_5/bungee/api/chat/ClickEvent.java +++ b/chat/src/main/java/net/md_5/bungee/api/chat/ClickEvent.java @@ -3,9 +3,7 @@ package net.md_5.bungee.api.chat; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.RequiredArgsConstructor; -import lombok.Setter; import lombok.ToString; -import org.jetbrains.annotations.ApiStatus; @Getter @ToString @@ -25,13 +23,6 @@ public final class ClickEvent */ private final String value; - /** - * Returns whether this click event is used for version above 1.21.4 - */ - @Setter - @ApiStatus.Internal - private boolean v1_21_5 = false; - public enum Action { diff --git a/chat/src/main/java/net/md_5/bungee/api/chat/HoverEvent.java b/chat/src/main/java/net/md_5/bungee/api/chat/HoverEvent.java index 9149ee0d..3408b887 100644 --- a/chat/src/main/java/net/md_5/bungee/api/chat/HoverEvent.java +++ b/chat/src/main/java/net/md_5/bungee/api/chat/HoverEvent.java @@ -13,7 +13,7 @@ import net.md_5.bungee.api.chat.hover.content.Content; import net.md_5.bungee.api.chat.hover.content.Entity; import net.md_5.bungee.api.chat.hover.content.Item; import net.md_5.bungee.api.chat.hover.content.Text; -import net.md_5.bungee.chat.ComponentSerializer; +import net.md_5.bungee.chat.VersionedComponentSerializer; import org.jetbrains.annotations.ApiStatus; @Getter @@ -38,30 +38,6 @@ public final class HoverEvent @ApiStatus.Internal private boolean legacy = false; - /** - * Returns whether this hover event is used for version above 1.21.4 - */ - @ApiStatus.Internal - private boolean v1_21_5 = false; - - /** - * Set the compatibility to 1.21.5, also modifies the underlying entities. - * - * @param v1_21_5 the compatibility to set - */ - @ApiStatus.Internal - public void setV1_21_5(boolean v1_21_5) - { - this.v1_21_5 = v1_21_5; - for ( Content content : contents ) - { - if ( content instanceof Entity ) - { - ( (Entity) content ).setV1_21_5( v1_21_5 ); - } - } - } - /** * Creates event with an action and a list of contents. * @@ -106,7 +82,7 @@ public final class HoverEvent return (BaseComponent[]) ( (Text) content ).getValue(); } - TextComponent component = new TextComponent( ComponentSerializer.toString( content ) ); + TextComponent component = new TextComponent( VersionedComponentSerializer.getDefault().toString( content ) ); return new BaseComponent[] { component diff --git a/chat/src/main/java/net/md_5/bungee/api/chat/hover/content/Entity.java b/chat/src/main/java/net/md_5/bungee/api/chat/hover/content/Entity.java index 0ae5c228..bbe708e9 100644 --- a/chat/src/main/java/net/md_5/bungee/api/chat/hover/content/Entity.java +++ b/chat/src/main/java/net/md_5/bungee/api/chat/hover/content/Entity.java @@ -7,7 +7,6 @@ import lombok.NonNull; import lombok.ToString; import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.HoverEvent; -import org.jetbrains.annotations.ApiStatus; @Data @AllArgsConstructor @@ -16,18 +15,6 @@ import org.jetbrains.annotations.ApiStatus; public class Entity extends Content { - /** - * Required for backwards compatibility. - * - * @param type the type of the entity, for example 'minecraft:pig' - * @param id for example '6cb1b229-ce5c-4179-af8d-eea185c25963' - * @param name the name of the entity - */ - public Entity(String type, @NonNull String id, BaseComponent name) - { - this( type, id, name, false ); - } - /** * Namespaced entity ID. * @@ -48,12 +35,6 @@ public class Entity extends Content */ private BaseComponent name; - /** - * True if this entity is for 1.21.5 or later - */ - @ApiStatus.Internal - private boolean v1_21_5; - @Override public HoverEvent.Action requiredAction() { diff --git a/chat/src/main/java/net/md_5/bungee/api/chat/hover/content/EntitySerializer.java b/chat/src/main/java/net/md_5/bungee/api/chat/hover/content/EntitySerializer.java index 0bac2d35..ad5ad0f9 100644 --- a/chat/src/main/java/net/md_5/bungee/api/chat/hover/content/EntitySerializer.java +++ b/chat/src/main/java/net/md_5/bungee/api/chat/hover/content/EntitySerializer.java @@ -10,10 +10,17 @@ import com.google.gson.JsonSerializer; import java.lang.reflect.Type; import java.util.UUID; import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.chat.BaseComponentSerializer; +import net.md_5.bungee.chat.VersionedComponentSerializer; -public class EntitySerializer implements JsonSerializer, JsonDeserializer +public class EntitySerializer extends BaseComponentSerializer implements JsonSerializer, JsonDeserializer { + public EntitySerializer(VersionedComponentSerializer serializer) + { + super( serializer ); + } + @Override public Entity deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException { @@ -34,8 +41,7 @@ public class EntitySerializer implements JsonSerializer, JsonDeserialize return new Entity( ( value.has( newEntity ? "id" : "type" ) ) ? value.get( newEntity ? "id" : "type" ).getAsString() : null, idString, - ( value.has( "name" ) ) ? context.deserialize( value.get( "name" ), BaseComponent.class ) : null, - newEntity + ( value.has( "name" ) ) ? context.deserialize( value.get( "name" ), BaseComponent.class ) : null ); } @@ -44,8 +50,20 @@ public class EntitySerializer implements JsonSerializer, JsonDeserialize { JsonObject object = new JsonObject(); - object.addProperty( content.isV1_21_5() ? "id" : "type", ( content.getType() != null ) ? content.getType() : "minecraft:pig" ); - object.addProperty( content.isV1_21_5() ? "uuid" : "id", content.getId() ); + switch ( serializer.getVersion() ) + { + case V1_21_5: + object.addProperty( "id", ( content.getType() != null ) ? content.getType() : "minecraft:pig" ); + object.addProperty( "uuid", content.getId() ); + break; + case V1_16: + object.addProperty( "type", ( content.getType() != null ) ? content.getType() : "minecraft:pig" ); + object.addProperty( "id", content.getId() ); + break; + default: + throw new IllegalArgumentException( "Unknown version " + serializer.getVersion() ); + } + if ( content.getName() != null ) { object.add( "name", context.serialize( content.getName() ) ); diff --git a/chat/src/main/java/net/md_5/bungee/chat/BaseComponentSerializer.java b/chat/src/main/java/net/md_5/bungee/chat/BaseComponentSerializer.java index 9d53b60f..e36e0009 100644 --- a/chat/src/main/java/net/md_5/bungee/chat/BaseComponentSerializer.java +++ b/chat/src/main/java/net/md_5/bungee/chat/BaseComponentSerializer.java @@ -10,15 +10,19 @@ import java.util.Arrays; import java.util.Collections; import java.util.IdentityHashMap; import java.util.Locale; +import lombok.RequiredArgsConstructor; import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.ClickEvent; import net.md_5.bungee.api.chat.ComponentStyle; import net.md_5.bungee.api.chat.HoverEvent; import net.md_5.bungee.api.chat.hover.content.Content; +@RequiredArgsConstructor public class BaseComponentSerializer { + protected final VersionedComponentSerializer serializer; + protected void deserialize(JsonObject object, BaseComponent component, JsonDeserializationContext context) { component.applyStyle( context.deserialize( object, ComponentStyle.class ) ); @@ -59,7 +63,6 @@ public class BaseComponentSerializer component.setClickEvent( new ClickEvent( action, ( clickEvent.has( "value" ) ) ? clickEvent.get( "value" ).getAsString() : "" ) ); break; } - component.getClickEvent().setV1_21_5( true ); } else { component.setClickEvent( new ClickEvent( action, ( clickEvent.has( "value" ) ) ? clickEvent.get( "value" ).getAsString() : "" ) ); @@ -101,7 +104,6 @@ public class BaseComponentSerializer }; } hoverEvent = new HoverEvent( action, new ArrayList<>( Arrays.asList( list ) ) ); - hoverEvent.setV1_21_5( newHoverEvent ); } } else { @@ -141,15 +143,15 @@ public class BaseComponentSerializer protected void serialize(JsonObject object, BaseComponent component, JsonSerializationContext context) { boolean first = false; - if ( ComponentSerializer.serializedComponents.get() == null ) + if ( VersionedComponentSerializer.serializedComponents.get() == null ) { first = true; - ComponentSerializer.serializedComponents.set( Collections.newSetFromMap( new IdentityHashMap() ) ); + VersionedComponentSerializer.serializedComponents.set( Collections.newSetFromMap( new IdentityHashMap() ) ); } try { - Preconditions.checkArgument( !ComponentSerializer.serializedComponents.get().contains( component ), "Component loop" ); - ComponentSerializer.serializedComponents.get().add( component ); + Preconditions.checkArgument( !VersionedComponentSerializer.serializedComponents.get().contains( component ), "Component loop" ); + VersionedComponentSerializer.serializedComponents.get().add( component ); ComponentStyleSerializer.serializeTo( component.getStyle(), object ); @@ -164,30 +166,34 @@ public class BaseComponentSerializer JsonObject clickEvent = new JsonObject(); String actionName = component.getClickEvent().getAction().toString().toLowerCase( Locale.ROOT ); clickEvent.addProperty( "action", actionName.toLowerCase( Locale.ROOT ) ); - if ( component.getClickEvent().isV1_21_5() ) + switch ( serializer.getVersion() ) { - ClickEvent.Action action = ClickEvent.Action.valueOf( actionName.toUpperCase( Locale.ROOT ) ); - switch ( action ) - { - case OPEN_URL: - clickEvent.addProperty( "url", component.getClickEvent().getValue() ); - break; - case RUN_COMMAND: - case SUGGEST_COMMAND: - clickEvent.addProperty( "command", component.getClickEvent().getValue() ); - break; - case CHANGE_PAGE: - clickEvent.addProperty( "page", Integer.parseInt( component.getClickEvent().getValue() ) ); - break; - default: - clickEvent.addProperty( "value", component.getClickEvent().getValue() ); - break; - } - object.add( "click_event", clickEvent ); - } else - { - clickEvent.addProperty( "value", component.getClickEvent().getValue() ); - object.add( "clickEvent", clickEvent ); + case V1_21_5: + ClickEvent.Action action = ClickEvent.Action.valueOf( actionName.toUpperCase( Locale.ROOT ) ); + switch ( action ) + { + case OPEN_URL: + clickEvent.addProperty( "url", component.getClickEvent().getValue() ); + break; + case RUN_COMMAND: + case SUGGEST_COMMAND: + clickEvent.addProperty( "command", component.getClickEvent().getValue() ); + break; + case CHANGE_PAGE: + clickEvent.addProperty( "page", Integer.parseInt( component.getClickEvent().getValue() ) ); + break; + default: + clickEvent.addProperty( "value", component.getClickEvent().getValue() ); + break; + } + object.add( "click_event", clickEvent ); + break; + case V1_16: + clickEvent.addProperty( "value", component.getClickEvent().getValue() ); + object.add( "clickEvent", clickEvent ); + break; + default: + throw new IllegalArgumentException( "Unknown version " + serializer.getVersion() ); } } @@ -195,32 +201,44 @@ public class BaseComponentSerializer { JsonObject hoverEvent = new JsonObject(); hoverEvent.addProperty( "action", component.getHoverEvent().getAction().toString().toLowerCase( Locale.ROOT ) ); - boolean newFormat = component.getHoverEvent().isV1_21_5(); if ( component.getHoverEvent().isLegacy() ) { hoverEvent.add( "value", context.serialize( component.getHoverEvent().getContents().get( 0 ) ) ); } else { - if ( newFormat ) + switch ( serializer.getVersion() ) { - if ( component.getHoverEvent().getAction() == HoverEvent.Action.SHOW_ITEM || component.getHoverEvent().getAction() == HoverEvent.Action.SHOW_ENTITY ) - { - JsonObject inlined = context.serialize( ( component.getHoverEvent().getContents().size() == 1 ) - ? component.getHoverEvent().getContents().get( 0 ) : component.getHoverEvent().getContents() ).getAsJsonObject(); - inlined.entrySet().forEach( entry -> hoverEvent.add( entry.getKey(), entry.getValue() ) ); - } else - { - hoverEvent.add( "value", context.serialize( ( component.getHoverEvent().getContents().size() == 1 ) + case V1_21_5: + if ( component.getHoverEvent().getAction() == HoverEvent.Action.SHOW_ITEM || component.getHoverEvent().getAction() == HoverEvent.Action.SHOW_ENTITY ) + { + JsonObject inlined = context.serialize( ( component.getHoverEvent().getContents().size() == 1 ) + ? component.getHoverEvent().getContents().get( 0 ) : component.getHoverEvent().getContents() ).getAsJsonObject(); + inlined.entrySet().forEach( entry -> hoverEvent.add( entry.getKey(), entry.getValue() ) ); + } else + { + hoverEvent.add( "value", context.serialize( ( component.getHoverEvent().getContents().size() == 1 ) + ? component.getHoverEvent().getContents().get( 0 ) : component.getHoverEvent().getContents() ) ); + } + break; + case V1_16: + hoverEvent.add( "contents", context.serialize( ( component.getHoverEvent().getContents().size() == 1 ) ? component.getHoverEvent().getContents().get( 0 ) : component.getHoverEvent().getContents() ) ); - } - } else - { - hoverEvent.add( "contents", context.serialize( ( component.getHoverEvent().getContents().size() == 1 ) - ? component.getHoverEvent().getContents().get( 0 ) : component.getHoverEvent().getContents() ) ); + break; + default: + throw new IllegalArgumentException( "Unknown version " + serializer.getVersion() ); } - } - object.add( newFormat ? "hover_event" : "hoverEvent", hoverEvent ); + switch ( serializer.getVersion() ) + { + case V1_21_5: + object.add( "hover_event", hoverEvent ); + break; + case V1_16: + object.add( "hoverEvent", hoverEvent ); + break; + default: + throw new IllegalArgumentException( "Unknown version " + serializer.getVersion() ); + } } if ( component.getExtra() != null ) @@ -229,10 +247,10 @@ public class BaseComponentSerializer } } finally { - ComponentSerializer.serializedComponents.get().remove( component ); + VersionedComponentSerializer.serializedComponents.get().remove( component ); if ( first ) { - ComponentSerializer.serializedComponents.set( null ); + VersionedComponentSerializer.serializedComponents.set( null ); } } } diff --git a/chat/src/main/java/net/md_5/bungee/chat/ChatVersion.java b/chat/src/main/java/net/md_5/bungee/chat/ChatVersion.java new file mode 100644 index 00000000..1e0a3dd1 --- /dev/null +++ b/chat/src/main/java/net/md_5/bungee/chat/ChatVersion.java @@ -0,0 +1,10 @@ +package net.md_5.bungee.chat; + +import org.jetbrains.annotations.ApiStatus; + +@ApiStatus.Internal +public enum ChatVersion +{ + V1_16, + V1_21_5; +} diff --git a/chat/src/main/java/net/md_5/bungee/chat/ComponentSerializer.java b/chat/src/main/java/net/md_5/bungee/chat/ComponentSerializer.java index 15ffc1ee..bfb27152 100644 --- a/chat/src/main/java/net/md_5/bungee/chat/ComponentSerializer.java +++ b/chat/src/main/java/net/md_5/bungee/chat/ComponentSerializer.java @@ -1,52 +1,17 @@ package net.md_5.bungee.chat; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonArray; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; -import com.google.gson.JsonObject; import com.google.gson.JsonParseException; -import com.google.gson.JsonParser; -import com.google.gson.JsonPrimitive; import java.lang.reflect.Type; -import java.util.Set; import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.ComponentStyle; -import net.md_5.bungee.api.chat.ItemTag; -import net.md_5.bungee.api.chat.KeybindComponent; -import net.md_5.bungee.api.chat.ScoreComponent; -import net.md_5.bungee.api.chat.SelectorComponent; -import net.md_5.bungee.api.chat.TextComponent; -import net.md_5.bungee.api.chat.TranslatableComponent; import net.md_5.bungee.api.chat.hover.content.Content; -import net.md_5.bungee.api.chat.hover.content.Entity; -import net.md_5.bungee.api.chat.hover.content.EntitySerializer; -import net.md_5.bungee.api.chat.hover.content.Item; -import net.md_5.bungee.api.chat.hover.content.ItemSerializer; -import net.md_5.bungee.api.chat.hover.content.Text; -import net.md_5.bungee.api.chat.hover.content.TextSerializer; public class ComponentSerializer implements JsonDeserializer { - private static final Gson gson = new GsonBuilder(). - registerTypeAdapter( BaseComponent.class, new ComponentSerializer() ). - registerTypeAdapter( TextComponent.class, new TextComponentSerializer() ). - registerTypeAdapter( TranslatableComponent.class, new TranslatableComponentSerializer() ). - registerTypeAdapter( KeybindComponent.class, new KeybindComponentSerializer() ). - registerTypeAdapter( ScoreComponent.class, new ScoreComponentSerializer() ). - registerTypeAdapter( SelectorComponent.class, new SelectorComponentSerializer() ). - registerTypeAdapter( ComponentStyle.class, new ComponentStyleSerializer() ). - registerTypeAdapter( Entity.class, new EntitySerializer() ). - registerTypeAdapter( Text.class, new TextSerializer() ). - registerTypeAdapter( Item.class, new ItemSerializer() ). - registerTypeAdapter( ItemTag.class, new ItemTag.Serializer() ). - create(); - - public static final ThreadLocal> serializedComponents = new ThreadLocal>(); - /** * Parse a JSON-compliant String as an array of base components. The input * can be one of either an array of components, or a single component @@ -66,18 +31,7 @@ public class ComponentSerializer implements JsonDeserializer */ public static BaseComponent[] parse(String json) { - JsonElement jsonElement = JsonParser.parseString( json ); - - if ( jsonElement.isJsonArray() ) - { - return gson.fromJson( jsonElement, BaseComponent[].class ); - } else - { - return new BaseComponent[] - { - gson.fromJson( jsonElement, BaseComponent.class ) - }; - } + return VersionedComponentSerializer.getDefault().parse( json ); } /** @@ -90,9 +44,7 @@ public class ComponentSerializer implements JsonDeserializer */ public static BaseComponent deserialize(String json) { - JsonElement jsonElement = JsonParser.parseString( json ); - - return deserialize( jsonElement ); + return VersionedComponentSerializer.getDefault().deserialize( json ); } /** @@ -105,20 +57,7 @@ public class ComponentSerializer implements JsonDeserializer */ public static BaseComponent deserialize(JsonElement jsonElement) { - if ( jsonElement instanceof JsonPrimitive ) - { - JsonPrimitive primitive = (JsonPrimitive) jsonElement; - if ( primitive.isString() ) - { - return new TextComponent( primitive.getAsString() ); - } - } else if ( jsonElement instanceof JsonArray ) - { - BaseComponent[] array = gson.fromJson( jsonElement, BaseComponent[].class ); - return TextComponent.fromArray( array ); - } - - return gson.fromJson( jsonElement, BaseComponent.class ); + return VersionedComponentSerializer.getDefault().deserialize( jsonElement ); } /** @@ -131,9 +70,7 @@ public class ComponentSerializer implements JsonDeserializer */ public static ComponentStyle deserializeStyle(String json) { - JsonElement jsonElement = JsonParser.parseString( json ); - - return deserializeStyle( jsonElement ); + return VersionedComponentSerializer.getDefault().deserializeStyle( json ); } /** @@ -146,17 +83,17 @@ public class ComponentSerializer implements JsonDeserializer */ public static ComponentStyle deserializeStyle(JsonElement jsonElement) { - return gson.fromJson( jsonElement, ComponentStyle.class ); + return VersionedComponentSerializer.getDefault().deserializeStyle( jsonElement ); } public static JsonElement toJson(BaseComponent component) { - return gson.toJsonTree( component ); + return VersionedComponentSerializer.getDefault().toJson( component ); } public static JsonElement toJson(ComponentStyle style) { - return gson.toJsonTree( style ); + return VersionedComponentSerializer.getDefault().toJson( style ); } /** @@ -167,7 +104,7 @@ public class ComponentSerializer implements JsonDeserializer @Deprecated public static String toString(Object object) { - return gson.toJson( object ); + return VersionedComponentSerializer.getDefault().toString( object ); } /** @@ -178,54 +115,27 @@ public class ComponentSerializer implements JsonDeserializer @Deprecated public static String toString(Content content) { - return gson.toJson( content ); + return VersionedComponentSerializer.getDefault().toString( content ); } public static String toString(BaseComponent component) { - return gson.toJson( component ); + return VersionedComponentSerializer.getDefault().toString( component ); } public static String toString(BaseComponent... components) { - if ( components.length == 1 ) - { - return gson.toJson( components[0] ); - } else - { - return gson.toJson( new TextComponent( components ) ); - } + return VersionedComponentSerializer.getDefault().toString( components ); } public static String toString(ComponentStyle style) { - return gson.toJson( style ); + return VersionedComponentSerializer.getDefault().toString( style ); } @Override public BaseComponent deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - if ( json.isJsonPrimitive() ) - { - return new TextComponent( json.getAsString() ); - } - JsonObject object = json.getAsJsonObject(); - if ( object.has( "translate" ) ) - { - return context.deserialize( json, TranslatableComponent.class ); - } - if ( object.has( "keybind" ) ) - { - return context.deserialize( json, KeybindComponent.class ); - } - if ( object.has( "score" ) ) - { - return context.deserialize( json, ScoreComponent.class ); - } - if ( object.has( "selector" ) ) - { - return context.deserialize( json, SelectorComponent.class ); - } - return context.deserialize( json, TextComponent.class ); + return VersionedComponentSerializer.getDefault().deserialize( json, typeOfT, context ); } } diff --git a/chat/src/main/java/net/md_5/bungee/chat/KeybindComponentSerializer.java b/chat/src/main/java/net/md_5/bungee/chat/KeybindComponentSerializer.java index 6c97aec3..a481f3b0 100644 --- a/chat/src/main/java/net/md_5/bungee/chat/KeybindComponentSerializer.java +++ b/chat/src/main/java/net/md_5/bungee/chat/KeybindComponentSerializer.java @@ -13,6 +13,11 @@ import net.md_5.bungee.api.chat.KeybindComponent; public class KeybindComponentSerializer extends BaseComponentSerializer implements JsonSerializer, JsonDeserializer { + public KeybindComponentSerializer(VersionedComponentSerializer serializer) + { + super( serializer ); + } + @Override public KeybindComponent deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { diff --git a/chat/src/main/java/net/md_5/bungee/chat/ScoreComponentSerializer.java b/chat/src/main/java/net/md_5/bungee/chat/ScoreComponentSerializer.java index fc7aad50..907f8708 100644 --- a/chat/src/main/java/net/md_5/bungee/chat/ScoreComponentSerializer.java +++ b/chat/src/main/java/net/md_5/bungee/chat/ScoreComponentSerializer.java @@ -13,6 +13,11 @@ import net.md_5.bungee.api.chat.ScoreComponent; public class ScoreComponentSerializer extends BaseComponentSerializer implements JsonSerializer, JsonDeserializer { + public ScoreComponentSerializer(VersionedComponentSerializer serializer) + { + super( serializer ); + } + @Override public ScoreComponent deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException { diff --git a/chat/src/main/java/net/md_5/bungee/chat/SelectorComponentSerializer.java b/chat/src/main/java/net/md_5/bungee/chat/SelectorComponentSerializer.java index 86815dae..e991a081 100644 --- a/chat/src/main/java/net/md_5/bungee/chat/SelectorComponentSerializer.java +++ b/chat/src/main/java/net/md_5/bungee/chat/SelectorComponentSerializer.java @@ -13,6 +13,11 @@ import net.md_5.bungee.api.chat.SelectorComponent; public class SelectorComponentSerializer extends BaseComponentSerializer implements JsonSerializer, JsonDeserializer { + public SelectorComponentSerializer(VersionedComponentSerializer serializer) + { + super( serializer ); + } + @Override public SelectorComponent deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException { @@ -27,7 +32,7 @@ public class SelectorComponentSerializer extends BaseComponentSerializer impleme JsonElement separator = object.get( "separator" ); if ( separator != null ) { - component.setSeparator( ComponentSerializer.deserialize( separator.getAsString() ) ); + component.setSeparator( serializer.deserialize( separator.getAsString() ) ); } deserialize( object, component, context ); @@ -43,7 +48,7 @@ public class SelectorComponentSerializer extends BaseComponentSerializer impleme if ( component.getSeparator() != null ) { - object.addProperty( "separator", ComponentSerializer.toString( component.getSeparator() ) ); + object.addProperty( "separator", serializer.toString( component.getSeparator() ) ); } return object; } diff --git a/chat/src/main/java/net/md_5/bungee/chat/TextComponentSerializer.java b/chat/src/main/java/net/md_5/bungee/chat/TextComponentSerializer.java index 445239ef..02ad94d4 100644 --- a/chat/src/main/java/net/md_5/bungee/chat/TextComponentSerializer.java +++ b/chat/src/main/java/net/md_5/bungee/chat/TextComponentSerializer.java @@ -13,6 +13,11 @@ import net.md_5.bungee.api.chat.TextComponent; public class TextComponentSerializer extends BaseComponentSerializer implements JsonSerializer, JsonDeserializer { + public TextComponentSerializer(VersionedComponentSerializer serializer) + { + super( serializer ); + } + @Override public TextComponent deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { diff --git a/chat/src/main/java/net/md_5/bungee/chat/TranslatableComponentSerializer.java b/chat/src/main/java/net/md_5/bungee/chat/TranslatableComponentSerializer.java index fac2023e..623923bd 100644 --- a/chat/src/main/java/net/md_5/bungee/chat/TranslatableComponentSerializer.java +++ b/chat/src/main/java/net/md_5/bungee/chat/TranslatableComponentSerializer.java @@ -15,6 +15,11 @@ import net.md_5.bungee.api.chat.TranslatableComponent; public class TranslatableComponentSerializer extends BaseComponentSerializer implements JsonSerializer, JsonDeserializer { + public TranslatableComponentSerializer(VersionedComponentSerializer serializer) + { + super( serializer ); + } + @Override public TranslatableComponent deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { diff --git a/chat/src/main/java/net/md_5/bungee/chat/VersionedComponentSerializer.java b/chat/src/main/java/net/md_5/bungee/chat/VersionedComponentSerializer.java new file mode 100644 index 00000000..a46adc17 --- /dev/null +++ b/chat/src/main/java/net/md_5/bungee/chat/VersionedComponentSerializer.java @@ -0,0 +1,269 @@ +package net.md_5.bungee.chat; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonParser; +import com.google.gson.JsonPrimitive; +import java.lang.reflect.Type; +import java.util.Set; +import lombok.Getter; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.ComponentStyle; +import net.md_5.bungee.api.chat.ItemTag; +import net.md_5.bungee.api.chat.KeybindComponent; +import net.md_5.bungee.api.chat.ScoreComponent; +import net.md_5.bungee.api.chat.SelectorComponent; +import net.md_5.bungee.api.chat.TextComponent; +import net.md_5.bungee.api.chat.TranslatableComponent; +import net.md_5.bungee.api.chat.hover.content.Content; +import net.md_5.bungee.api.chat.hover.content.Entity; +import net.md_5.bungee.api.chat.hover.content.EntitySerializer; +import net.md_5.bungee.api.chat.hover.content.Item; +import net.md_5.bungee.api.chat.hover.content.ItemSerializer; +import net.md_5.bungee.api.chat.hover.content.Text; +import net.md_5.bungee.api.chat.hover.content.TextSerializer; +import org.jetbrains.annotations.ApiStatus; + +@ApiStatus.Experimental +public class VersionedComponentSerializer implements JsonDeserializer +{ + + @Getter + @ApiStatus.Internal + private final Gson gson; + @Getter + @ApiStatus.Internal + private final ChatVersion version; + + public VersionedComponentSerializer(ChatVersion version) + { + this.version = version; + this.gson = new GsonBuilder(). + registerTypeAdapter( BaseComponent.class, this ). + registerTypeAdapter( TextComponent.class, new TextComponentSerializer( this ) ). + registerTypeAdapter( TranslatableComponent.class, new TranslatableComponentSerializer( this ) ). + registerTypeAdapter( KeybindComponent.class, new KeybindComponentSerializer( this ) ). + registerTypeAdapter( ScoreComponent.class, new ScoreComponentSerializer( this ) ). + registerTypeAdapter( SelectorComponent.class, new SelectorComponentSerializer( this ) ). + registerTypeAdapter( ComponentStyle.class, new ComponentStyleSerializer() ). + registerTypeAdapter( Entity.class, new EntitySerializer( this ) ). + registerTypeAdapter( Text.class, new TextSerializer() ). + registerTypeAdapter( Item.class, new ItemSerializer() ). + registerTypeAdapter( ItemTag.class, new ItemTag.Serializer() ). + create(); + } + + private static final VersionedComponentSerializer v1_16 = new VersionedComponentSerializer( ChatVersion.V1_16 ); + private static final VersionedComponentSerializer v1_21_5 = new VersionedComponentSerializer( ChatVersion.V1_21_5 ); + + public static VersionedComponentSerializer forVersion(ChatVersion version) + { + switch ( version ) + { + case V1_16: + return v1_16; + case V1_21_5: + return v1_21_5; + default: + throw new IllegalArgumentException( "Unknown version " + version ); + } + } + + @Deprecated + @ApiStatus.Internal + public static VersionedComponentSerializer getDefault() + { + return v1_16; + } + + @ApiStatus.Internal + public static final ThreadLocal> serializedComponents = new ThreadLocal>(); + + /** + * Parse a JSON-compliant String as an array of base components. The input + * can be one of either an array of components, or a single component + * object. If the input is an array, each component will be parsed + * individually and returned in the order that they were parsed. If the + * input is a single component object, a single-valued array with the + * component will be returned. + *

+ * NOTE: {@link #deserialize(String)} is preferred as it + * will parse only one component as opposed to an array of components which + * is non- standard behavior. This method is still appropriate for parsing + * multiple components at once, although such use case is rarely (if at all) + * exhibited in vanilla Minecraft. + * + * @param json the component json to parse + * @return an array of all parsed components + */ + public BaseComponent[] parse(String json) + { + JsonElement jsonElement = JsonParser.parseString( json ); + + if ( jsonElement.isJsonArray() ) + { + return gson.fromJson( jsonElement, BaseComponent[].class ); + } else + { + return new BaseComponent[] + { + gson.fromJson( jsonElement, BaseComponent.class ) + }; + } + } + + /** + * Deserialize a JSON-compliant String as a single component. + * + * @param json the component json to parse + * @return the deserialized component + * @throws IllegalArgumentException if anything other than a valid JSON + * component string is passed as input + */ + public BaseComponent deserialize(String json) + { + JsonElement jsonElement = JsonParser.parseString( json ); + + return deserialize( jsonElement ); + } + + /** + * Deserialize a JSON element as a single component. + * + * @param jsonElement the component json to parse + * @return the deserialized component + * @throws IllegalArgumentException if anything other than a valid JSON + * component is passed as input + */ + public BaseComponent deserialize(JsonElement jsonElement) + { + if ( jsonElement instanceof JsonPrimitive ) + { + JsonPrimitive primitive = (JsonPrimitive) jsonElement; + if ( primitive.isString() ) + { + return new TextComponent( primitive.getAsString() ); + } + } else if ( jsonElement instanceof JsonArray ) + { + BaseComponent[] array = gson.fromJson( jsonElement, BaseComponent[].class ); + return TextComponent.fromArray( array ); + } + + return gson.fromJson( jsonElement, BaseComponent.class ); + } + + /** + * Deserialize a JSON-compliant String as a component style. + * + * @param json the component style json to parse + * @return the deserialized component style + * @throws IllegalArgumentException if anything other than a valid JSON + * component style string is passed as input + */ + public ComponentStyle deserializeStyle(String json) + { + JsonElement jsonElement = JsonParser.parseString( json ); + + return deserializeStyle( jsonElement ); + } + + /** + * Deserialize a JSON element as a component style. + * + * @param jsonElement the component style json to parse + * @return the deserialized component style + * @throws IllegalArgumentException if anything other than a valid JSON + * component style is passed as input + */ + public ComponentStyle deserializeStyle(JsonElement jsonElement) + { + return gson.fromJson( jsonElement, ComponentStyle.class ); + } + + public JsonElement toJson(BaseComponent component) + { + return gson.toJsonTree( component ); + } + + public JsonElement toJson(ComponentStyle style) + { + return gson.toJsonTree( style ); + } + + /** + * @param object the object to serialize + * @return the JSON string representation of the object + * @deprecated Error-prone, be careful which object you input here + */ + @Deprecated + public String toString(Object object) + { + return gson.toJson( object ); + } + + /** + * @param content the content to serialize + * @return the JSON string representation of the object + * @deprecated for legacy internal use only + */ + @Deprecated + public String toString(Content content) + { + return gson.toJson( content ); + } + + public String toString(BaseComponent component) + { + return gson.toJson( component ); + } + + public String toString(BaseComponent... components) + { + if ( components.length == 1 ) + { + return gson.toJson( components[0] ); + } else + { + return gson.toJson( new TextComponent( components ) ); + } + } + + public String toString(ComponentStyle style) + { + return gson.toJson( style ); + } + + @Override + public BaseComponent deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException + { + if ( json.isJsonPrimitive() ) + { + return new TextComponent( json.getAsString() ); + } + JsonObject object = json.getAsJsonObject(); + if ( object.has( "translate" ) ) + { + return context.deserialize( json, TranslatableComponent.class ); + } + if ( object.has( "keybind" ) ) + { + return context.deserialize( json, KeybindComponent.class ); + } + if ( object.has( "score" ) ) + { + return context.deserialize( json, ScoreComponent.class ); + } + if ( object.has( "selector" ) ) + { + return context.deserialize( json, SelectorComponent.class ); + } + return context.deserialize( json, TextComponent.class ); + } +} diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/ChatSerializer.java b/protocol/src/main/java/net/md_5/bungee/protocol/ChatSerializer.java new file mode 100644 index 00000000..c415106c --- /dev/null +++ b/protocol/src/main/java/net/md_5/bungee/protocol/ChatSerializer.java @@ -0,0 +1,19 @@ +package net.md_5.bungee.protocol; + +import net.md_5.bungee.chat.ChatVersion; +import net.md_5.bungee.chat.VersionedComponentSerializer; + +public class ChatSerializer +{ + + public static VersionedComponentSerializer forVersion(int protocolVersion) + { + if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_21_5 ) + { + return VersionedComponentSerializer.forVersion( ChatVersion.V1_21_5 ); + } else + { + return VersionedComponentSerializer.forVersion( ChatVersion.V1_16 ); + } + } +} diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/DefinedPacket.java b/protocol/src/main/java/net/md_5/bungee/protocol/DefinedPacket.java index c0940352..b2a4729c 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/DefinedPacket.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/DefinedPacket.java @@ -21,7 +21,6 @@ import java.util.function.BiConsumer; import lombok.RequiredArgsConstructor; import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.ComponentStyle; -import net.md_5.bungee.chat.ComponentSerializer; import se.llbit.nbt.ErrorTag; import se.llbit.nbt.NamedTag; import se.llbit.nbt.SpecificTag; @@ -120,12 +119,12 @@ public abstract class DefinedPacket SpecificTag nbt = (SpecificTag) readTag( buf, protocolVersion ); JsonElement json = TagUtil.toJson( nbt ); - return ComponentSerializer.deserialize( json ); + return ChatSerializer.forVersion( protocolVersion ).deserialize( json ); } else { String string = readString( buf, maxStringLength ); - return ComponentSerializer.deserialize( string ); + return ChatSerializer.forVersion( protocolVersion ).deserialize( string ); } } @@ -134,7 +133,7 @@ public abstract class DefinedPacket SpecificTag nbt = (SpecificTag) readTag( buf, protocolVersion ); JsonElement json = TagUtil.toJson( nbt ); - return ComponentSerializer.deserializeStyle( json ); + return ChatSerializer.forVersion( protocolVersion ).deserializeStyle( json ); } public static void writeEitherBaseComponent(Either message, ByteBuf buf, int protocolVersion) @@ -152,13 +151,13 @@ public abstract class DefinedPacket { if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_3 ) { - JsonElement json = ComponentSerializer.toJson( message ); + JsonElement json = ChatSerializer.forVersion( protocolVersion ).toJson( message ); SpecificTag nbt = TagUtil.fromJson( json ); writeTag( nbt, buf, protocolVersion ); } else { - String string = ComponentSerializer.toString( message ); + String string = ChatSerializer.forVersion( protocolVersion ).toString( message ); writeString( string, buf ); } @@ -166,7 +165,7 @@ public abstract class DefinedPacket public static void writeComponentStyle(ComponentStyle style, ByteBuf buf, int protocolVersion) { - JsonElement json = ComponentSerializer.toJson( style ); + JsonElement json = ChatSerializer.forVersion( protocolVersion ).toJson( style ); SpecificTag nbt = TagUtil.fromJson( json ); writeTag( nbt, buf, protocolVersion ); diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/Kick.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/Kick.java index 14539b4b..32bf00de 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/Kick.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/Kick.java @@ -6,8 +6,8 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import net.md_5.bungee.api.chat.BaseComponent; -import net.md_5.bungee.chat.ComponentSerializer; import net.md_5.bungee.protocol.AbstractPacketHandler; +import net.md_5.bungee.protocol.ChatSerializer; import net.md_5.bungee.protocol.DefinedPacket; import net.md_5.bungee.protocol.Protocol; import net.md_5.bungee.protocol.ProtocolConstants; @@ -26,7 +26,7 @@ public class Kick extends DefinedPacket { if ( protocol == Protocol.LOGIN ) { - message = ComponentSerializer.deserialize( readString( buf ) ); + message = ChatSerializer.forVersion( protocolVersion ).deserialize( readString( buf ) ); } else { message = readBaseComponent( buf, protocolVersion ); @@ -38,7 +38,7 @@ public class Kick extends DefinedPacket { if ( protocol == Protocol.LOGIN ) { - writeString( ComponentSerializer.toString( message ), buf ); + writeString( ChatSerializer.forVersion( protocolVersion ).toString( message ), buf ); } else { writeBaseComponent( message, buf, protocolVersion ); diff --git a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java index c39239bc..849662a7 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java @@ -6,8 +6,6 @@ import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.google.common.util.concurrent.ThreadFactoryBuilder; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Channel; @@ -52,31 +50,17 @@ import lombok.Getter; import lombok.Setter; import lombok.Synchronized; import net.md_5.bungee.api.CommandSender; -import net.md_5.bungee.api.Favicon; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.ReconnectHandler; -import net.md_5.bungee.api.ServerPing; import net.md_5.bungee.api.Title; import net.md_5.bungee.api.chat.BaseComponent; -import net.md_5.bungee.api.chat.ComponentStyle; -import net.md_5.bungee.api.chat.KeybindComponent; -import net.md_5.bungee.api.chat.ScoreComponent; -import net.md_5.bungee.api.chat.SelectorComponent; import net.md_5.bungee.api.chat.TextComponent; -import net.md_5.bungee.api.chat.TranslatableComponent; import net.md_5.bungee.api.config.ConfigurationAdapter; import net.md_5.bungee.api.config.ListenerInfo; import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.plugin.Plugin; import net.md_5.bungee.api.plugin.PluginManager; -import net.md_5.bungee.chat.ComponentSerializer; -import net.md_5.bungee.chat.ComponentStyleSerializer; -import net.md_5.bungee.chat.KeybindComponentSerializer; -import net.md_5.bungee.chat.ScoreComponentSerializer; -import net.md_5.bungee.chat.SelectorComponentSerializer; -import net.md_5.bungee.chat.TextComponentSerializer; -import net.md_5.bungee.chat.TranslatableComponentSerializer; import net.md_5.bungee.command.CommandBungee; import net.md_5.bungee.command.CommandEnd; import net.md_5.bungee.command.CommandIP; @@ -165,16 +149,6 @@ public class BungeeCord extends ProxyServer private final ConsoleReader consoleReader; @Getter private final Logger logger; - public final Gson gson = new GsonBuilder() - .registerTypeAdapter( BaseComponent.class, new ComponentSerializer() ) - .registerTypeAdapter( TextComponent.class, new TextComponentSerializer() ) - .registerTypeAdapter( TranslatableComponent.class, new TranslatableComponentSerializer() ) - .registerTypeAdapter( KeybindComponent.class, new KeybindComponentSerializer() ) - .registerTypeAdapter( ScoreComponent.class, new ScoreComponentSerializer() ) - .registerTypeAdapter( SelectorComponent.class, new SelectorComponentSerializer() ) - .registerTypeAdapter( ComponentStyle.class, new ComponentStyleSerializer() ) - .registerTypeAdapter( ServerPing.PlayerInfo.class, new PlayerInfoSerializer() ) - .registerTypeAdapter( Favicon.class, Favicon.getFaviconTypeAdapter() ).create(); @Getter private ConnectionThrottle connectionThrottle; private final ModuleManager moduleManager = new ModuleManager(); diff --git a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java index 8f52c50e..5583a1b3 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java @@ -25,7 +25,6 @@ import net.md_5.bungee.api.score.Objective; import net.md_5.bungee.api.score.Score; import net.md_5.bungee.api.score.Scoreboard; import net.md_5.bungee.api.score.Team; -import net.md_5.bungee.chat.ComponentSerializer; import net.md_5.bungee.connection.CancelSendSignal; import net.md_5.bungee.connection.DownstreamBridge; import net.md_5.bungee.connection.LoginResult; @@ -118,7 +117,7 @@ public class ServerConnector extends PacketHandler LoginResult profile = user.getPendingConnection().getLoginProfile(); if ( profile != null && profile.getProperties() != null && profile.getProperties().length > 0 ) { - newHost += "\00" + BungeeCord.getInstance().gson.toJson( profile.getProperties() ); + newHost += "\00" + LoginResult.GSON.toJson( profile.getProperties() ); } copiedHandshake.setHost( newHost ); } else if ( !user.getExtraDataInHandshake().isEmpty() ) @@ -302,7 +301,7 @@ public class ServerConnector extends PacketHandler { user.unsafe().sendPacket( new ScoreboardObjective( objective.getName(), - ( user.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_13 ) ? Either.right( ComponentSerializer.deserialize( objective.getValue() ) ) : Either.left( objective.getValue() ), + ( user.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_13 ) ? Either.right( user.getChatSerializer().deserialize( objective.getValue() ) ) : Either.left( objective.getValue() ), ScoreboardObjective.HealthDisplay.fromString( objective.getType() ), (byte) 1, null ) ); diff --git a/proxy/src/main/java/net/md_5/bungee/UserConnection.java b/proxy/src/main/java/net/md_5/bungee/UserConnection.java index 74ca0ac4..2c9f55c9 100644 --- a/proxy/src/main/java/net/md_5/bungee/UserConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/UserConnection.java @@ -38,7 +38,7 @@ import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.event.PermissionCheckEvent; import net.md_5.bungee.api.event.ServerConnectEvent; import net.md_5.bungee.api.score.Scoreboard; -import net.md_5.bungee.chat.ComponentSerializer; +import net.md_5.bungee.chat.VersionedComponentSerializer; import net.md_5.bungee.connection.InitialHandler; import net.md_5.bungee.entitymap.EntityMap; import net.md_5.bungee.forge.ForgeClientHandler; @@ -47,6 +47,7 @@ import net.md_5.bungee.forge.ForgeServerHandler; import net.md_5.bungee.netty.ChannelWrapper; import net.md_5.bungee.netty.HandlerBoss; import net.md_5.bungee.netty.PipelineUtils; +import net.md_5.bungee.protocol.ChatSerializer; import net.md_5.bungee.protocol.DefinedPacket; import net.md_5.bungee.protocol.PacketWrapper; import net.md_5.bungee.protocol.Protocol; @@ -133,6 +134,8 @@ public final class UserConnection implements ProxiedPlayer private String displayName; @Getter private EntityMap entityRewrite; + @Getter + private VersionedComponentSerializer chatSerializer; private Locale locale; /*========================================================================*/ @Getter @@ -167,6 +170,7 @@ public final class UserConnection implements ProxiedPlayer public boolean init() { this.entityRewrite = EntityMap.getEntityMap( getPendingConnection().getVersion() ); + this.chatSerializer = ChatSerializer.forVersion( getPendingConnection().getVersion() ); this.displayName = name; @@ -556,7 +560,7 @@ public final class UserConnection implements ProxiedPlayer sendPacketQueued( new SystemChat( message, position.ordinal() ) ); } else { - sendPacketQueued( new Chat( ComponentSerializer.toString( message ), (byte) position.ordinal(), sender ) ); + sendPacketQueued( new Chat( chatSerializer.toString( message ), (byte) position.ordinal(), sender ) ); } } diff --git a/proxy/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java b/proxy/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java index 64e9a764..10f7ba99 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java @@ -46,7 +46,6 @@ import net.md_5.bungee.api.score.Position; import net.md_5.bungee.api.score.Score; import net.md_5.bungee.api.score.Scoreboard; import net.md_5.bungee.api.score.Team; -import net.md_5.bungee.chat.ComponentSerializer; import net.md_5.bungee.entitymap.EntityMap; import net.md_5.bungee.netty.ChannelWrapper; import net.md_5.bungee.netty.PacketHandler; @@ -196,7 +195,7 @@ public class DownstreamBridge extends PacketHandler switch ( objective.getAction() ) { case 0: - serverScoreboard.addObjective( new Objective( objective.getName(), ( objective.getValue().isLeft() ) ? objective.getValue().getLeft() : ComponentSerializer.toString( objective.getValue().getRight() ), objective.getType().toString() ) ); + serverScoreboard.addObjective( new Objective( objective.getName(), ( objective.getValue().isLeft() ) ? objective.getValue().getLeft() : con.getChatSerializer().toString( objective.getValue().getRight() ), objective.getType().toString() ) ); break; case 1: serverScoreboard.removeObjective( objective.getName() ); @@ -205,7 +204,7 @@ public class DownstreamBridge extends PacketHandler Objective oldObjective = serverScoreboard.getObjective( objective.getName() ); if ( oldObjective != null ) { - oldObjective.setValue( ( objective.getValue().isLeft() ) ? objective.getValue().getLeft() : ComponentSerializer.toString( objective.getValue().getRight() ) ); + oldObjective.setValue( ( objective.getValue().isLeft() ) ? objective.getValue().getLeft() : con.getChatSerializer().toString( objective.getValue().getRight() ) ); oldObjective.setType( objective.getType().toString() ); } break; @@ -279,9 +278,9 @@ public class DownstreamBridge extends PacketHandler { if ( team.getMode() == 0 || team.getMode() == 2 ) { - t.setDisplayName( team.getDisplayName().getLeftOrCompute( ComponentSerializer::toString ) ); - t.setPrefix( team.getPrefix().getLeftOrCompute( ComponentSerializer::toString ) ); - t.setSuffix( team.getSuffix().getLeftOrCompute( ComponentSerializer::toString ) ); + t.setDisplayName( team.getDisplayName().getLeftOrCompute( (component) -> con.getChatSerializer().toString( component ) ) ); + t.setPrefix( team.getPrefix().getLeftOrCompute( (component) -> con.getChatSerializer().toString( component ) ) ); + t.setSuffix( team.getSuffix().getLeftOrCompute( (component) -> con.getChatSerializer().toString( component ) ) ); t.setFriendlyFire( team.getFriendlyFire() ); t.setNameTagVisibility( team.getNameTagVisibility().getKey() ); t.setColor( team.getColor() ); @@ -556,7 +555,7 @@ public class DownstreamBridge extends PacketHandler case "MessageRaw": { String target = in.readUTF(); - BaseComponent[] message = ComponentSerializer.parse( in.readUTF() ); + BaseComponent[] message = con.getChatSerializer().parse( in.readUTF() ); if ( target.equals( "ALL" ) ) { for ( ProxiedPlayer player : bungee.getPlayers() ) @@ -623,7 +622,7 @@ public class DownstreamBridge extends PacketHandler ProxiedPlayer player = bungee.getPlayer( in.readUTF() ); if ( player != null ) { - BaseComponent[] kickReason = ComponentSerializer.parse( in.readUTF() ); + BaseComponent[] kickReason = con.getChatSerializer().parse( in.readUTF() ); player.disconnect( kickReason ); } break; diff --git a/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java b/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java index 6fef2696..7c0c2a02 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java @@ -305,7 +305,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection @Override public void done(ProxyPingEvent pingResult, Throwable error) { - Gson gson = BungeeCord.getInstance().gson; + Gson gson = PingHandler.gson; unsafe.sendPacket( new StatusResponse( gson.toJson( pingResult.getResponse() ) ) ); if ( bungee.getConnectionThrottle() != null ) { @@ -532,7 +532,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection { if ( error == null ) { - LoginResult obj = BungeeCord.getInstance().gson.fromJson( result, LoginResult.class ); + LoginResult obj = LoginResult.GSON.fromJson( result, LoginResult.class ); if ( obj != null && obj.getId() != null ) { loginProfile = obj; diff --git a/proxy/src/main/java/net/md_5/bungee/connection/LoginResult.java b/proxy/src/main/java/net/md_5/bungee/connection/LoginResult.java index 5dc8a220..59ce81e9 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/LoginResult.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/LoginResult.java @@ -1,5 +1,6 @@ package net.md_5.bungee.connection; +import com.google.gson.Gson; import lombok.AllArgsConstructor; import lombok.Data; import net.md_5.bungee.protocol.Property; @@ -9,6 +10,8 @@ import net.md_5.bungee.protocol.Property; public class LoginResult { + public static final Gson GSON = new Gson(); + // private String id; private String name; private Property[] properties; diff --git a/proxy/src/main/java/net/md_5/bungee/connection/PingHandler.java b/proxy/src/main/java/net/md_5/bungee/connection/PingHandler.java index ae97f799..0cddf41f 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/PingHandler.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/PingHandler.java @@ -3,12 +3,14 @@ package net.md_5.bungee.connection; import com.google.gson.Gson; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import lombok.RequiredArgsConstructor; -import net.md_5.bungee.BungeeCord; import net.md_5.bungee.BungeeServerInfo; +import net.md_5.bungee.PlayerInfoSerializer; import net.md_5.bungee.api.Callback; +import net.md_5.bungee.api.Favicon; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.ServerPing; import net.md_5.bungee.api.config.ServerInfo; +import net.md_5.bungee.chat.VersionedComponentSerializer; import net.md_5.bungee.netty.ChannelWrapper; import net.md_5.bungee.netty.PacketHandler; import net.md_5.bungee.netty.PipelineUtils; @@ -26,6 +28,9 @@ import net.md_5.bungee.util.QuietException; public class PingHandler extends PacketHandler { + static final Gson gson = VersionedComponentSerializer.getDefault().getGson().newBuilder() + .registerTypeAdapter( ServerPing.PlayerInfo.class, new PlayerInfoSerializer() ) + .registerTypeAdapter( Favicon.class, Favicon.getFaviconTypeAdapter() ).create(); private final ServerInfo target; private final Callback callback; private final int protocol; @@ -65,7 +70,6 @@ public class PingHandler extends PacketHandler @SuppressFBWarnings("UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR") public void handle(StatusResponse statusResponse) throws Exception { - Gson gson = BungeeCord.getInstance().gson; ServerPing serverPing = gson.fromJson( statusResponse.getResponse(), ServerPing.class ); ( (BungeeServerInfo) target ).cachePing( serverPing ); callback.done( serverPing, null ); diff --git a/proxy/src/main/java/net/md_5/bungee/util/ChatComponentTransformer.java b/proxy/src/main/java/net/md_5/bungee/util/ChatComponentTransformer.java index e4cbb9fd..298e4118 100644 --- a/proxy/src/main/java/net/md_5/bungee/util/ChatComponentTransformer.java +++ b/proxy/src/main/java/net/md_5/bungee/util/ChatComponentTransformer.java @@ -50,20 +50,6 @@ public final class ChatComponentTransformer next.getHoverEvent().getContents().clear(); next.getHoverEvent().getContents().add( exception ); } - } else if ( player.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_21_5 ) - { - if ( next.getHoverEvent() != null && !next.getHoverEvent().isV1_21_5() ) - { - next = next.duplicate(); - next.getHoverEvent().setV1_21_5( true ); - } - - if ( next.getClickEvent() != null && !next.getClickEvent().isV1_21_5() ) - { - next = next.duplicate(); - next.getClickEvent().setV1_21_5( true ); - } - } return next;