From c2f73d32b8798e7fa8a6697b7f0e28e66bdb5a09 Mon Sep 17 00:00:00 2001 From: Janmm14 Date: Sun, 31 Mar 2024 09:38:17 +1100 Subject: [PATCH] #3634: Micro-optimize chat deserialization --- .../java/net/md_5/bungee/api/ChatColor.java | 2 +- .../bungee/chat/BaseComponentSerializer.java | 60 ++++++++++--------- .../bungee/chat/ComponentStyleSerializer.java | 54 +++++++++-------- .../chat/KeybindComponentSerializer.java | 5 +- .../bungee/chat/ScoreComponentSerializer.java | 21 ++++--- .../chat/SelectorComponentSerializer.java | 10 ++-- .../bungee/chat/TextComponentSerializer.java | 5 +- .../chat/TranslatableComponentSerializer.java | 15 +++-- 8 files changed, 96 insertions(+), 76 deletions(-) diff --git a/chat/src/main/java/net/md_5/bungee/api/ChatColor.java b/chat/src/main/java/net/md_5/bungee/api/ChatColor.java index d7747deb3..dd0eccf60 100644 --- a/chat/src/main/java/net/md_5/bungee/api/ChatColor.java +++ b/chat/src/main/java/net/md_5/bungee/api/ChatColor.java @@ -244,7 +244,7 @@ public final class ChatColor public static ChatColor of(String string) { Preconditions.checkArgument( string != null, "string cannot be null" ); - if ( string.startsWith( "#" ) && string.length() == 7 ) + if ( string.length() == 7 && string.charAt( 0 ) == '#' ) { int rgb; try 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 86bb0cb5a..97514cbfc 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 @@ -23,59 +23,62 @@ public class BaseComponentSerializer { component.applyStyle( context.deserialize( object, ComponentStyle.class ) ); - if ( object.has( "insertion" ) ) + JsonElement insertion = object.get( "insertion" ); + if ( insertion != null ) { - component.setInsertion( object.get( "insertion" ).getAsString() ); + component.setInsertion( insertion.getAsString() ); } //Events - if ( object.has( "clickEvent" ) ) + JsonObject clickEvent = object.getAsJsonObject( "clickEvent" ); + if ( clickEvent != null ) { - JsonObject event = object.getAsJsonObject( "clickEvent" ); component.setClickEvent( new ClickEvent( - ClickEvent.Action.valueOf( event.get( "action" ).getAsString().toUpperCase( Locale.ROOT ) ), - ( event.has( "value" ) ) ? event.get( "value" ).getAsString() : "" ) ); + ClickEvent.Action.valueOf( clickEvent.get( "action" ).getAsString().toUpperCase( Locale.ROOT ) ), + ( clickEvent.has( "value" ) ) ? clickEvent.get( "value" ).getAsString() : "" ) ); } - if ( object.has( "hoverEvent" ) ) + JsonObject hoverEventJson = object.getAsJsonObject( "hoverEvent" ); + if ( hoverEventJson != null ) { - JsonObject event = object.getAsJsonObject( "hoverEvent" ); HoverEvent hoverEvent = null; - HoverEvent.Action action = HoverEvent.Action.valueOf( event.get( "action" ).getAsString().toUpperCase( Locale.ROOT ) ); + HoverEvent.Action action = HoverEvent.Action.valueOf( hoverEventJson.get( "action" ).getAsString().toUpperCase( Locale.ROOT ) ); - if ( event.has( "value" ) ) + JsonElement value = hoverEventJson.get( "value" ); + if ( value != null ) { - JsonElement contents = event.get( "value" ); // Plugins previously had support to pass BaseComponent[] into any action. // If the GSON is possible to be parsed as BaseComponent, attempt to parse as so. BaseComponent[] components; - if ( contents.isJsonArray() ) + if ( value.isJsonArray() ) { - components = context.deserialize( contents, BaseComponent[].class ); + components = context.deserialize( value, BaseComponent[].class ); } else { components = new BaseComponent[] { - context.deserialize( contents, BaseComponent.class ) + context.deserialize( value, BaseComponent.class ) }; } hoverEvent = new HoverEvent( action, components ); - } else if ( event.has( "contents" ) ) + } else { - JsonElement contents = event.get( "contents" ); - - Content[] list; - if ( contents.isJsonArray() ) + JsonElement contents = hoverEventJson.get( "contents" ); + if ( contents != null ) { - list = context.deserialize( contents, HoverEvent.getClass( action, true ) ); - } else - { - list = new Content[] + Content[] list; + if ( contents.isJsonArray() ) { - context.deserialize( contents, HoverEvent.getClass( action, false ) ) - }; + list = context.deserialize( contents, HoverEvent.getClass( action, true ) ); + } else + { + list = new Content[] + { + context.deserialize( contents, HoverEvent.getClass( action, false ) ) + }; + } + hoverEvent = new HoverEvent( action, new ArrayList<>( Arrays.asList( list ) ) ); } - hoverEvent = new HoverEvent( action, new ArrayList<>( Arrays.asList( list ) ) ); } if ( hoverEvent != null ) @@ -84,9 +87,10 @@ public class BaseComponentSerializer } } - if ( object.has( "extra" ) ) + JsonElement extra = object.get( "extra" ); + if ( extra != null ) { - component.setExtra( Arrays.asList( context.deserialize( object.get( "extra" ), BaseComponent[].class ) ) ); + component.setExtra( Arrays.asList( context.deserialize( extra, BaseComponent[].class ) ) ); } } diff --git a/chat/src/main/java/net/md_5/bungee/chat/ComponentStyleSerializer.java b/chat/src/main/java/net/md_5/bungee/chat/ComponentStyleSerializer.java index f3d1d026c..86f077941 100644 --- a/chat/src/main/java/net/md_5/bungee/chat/ComponentStyleSerializer.java +++ b/chat/src/main/java/net/md_5/bungee/chat/ComponentStyleSerializer.java @@ -9,6 +9,7 @@ import com.google.gson.JsonPrimitive; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; import java.lang.reflect.Type; +import java.util.Map; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.chat.ComponentStyle; import net.md_5.bungee.api.chat.ComponentStyleBuilder; @@ -77,33 +78,34 @@ public class ComponentStyleSerializer implements JsonSerializer, { ComponentStyleBuilder builder = ComponentStyle.builder(); JsonObject object = json.getAsJsonObject(); - if ( object.has( "bold" ) ) + for ( Map.Entry entry : object.entrySet() ) { - builder.bold( getAsBoolean( object.get( "bold" ) ) ); - } - if ( object.has( "italic" ) ) - { - builder.italic( getAsBoolean( object.get( "italic" ) ) ); - } - if ( object.has( "underlined" ) ) - { - builder.underlined( getAsBoolean( object.get( "underlined" ) ) ); - } - if ( object.has( "strikethrough" ) ) - { - builder.strikethrough( getAsBoolean( object.get( "strikethrough" ) ) ); - } - if ( object.has( "obfuscated" ) ) - { - builder.obfuscated( getAsBoolean( object.get( "obfuscated" ) ) ); - } - if ( object.has( "color" ) ) - { - builder.color( ChatColor.of( object.get( "color" ).getAsString() ) ); - } - if ( object.has( "font" ) ) - { - builder.font( object.get( "font" ).getAsString() ); + String name = entry.getKey(); + JsonElement value = entry.getValue(); + switch ( name ) + { + case "bold": + builder.bold( getAsBoolean( value ) ); + break; + case "italic": + builder.italic( getAsBoolean( value ) ); + break; + case "underlined": + builder.underlined( getAsBoolean( value ) ); + break; + case "strikethrough": + builder.strikethrough( getAsBoolean( value ) ); + break; + case "obfuscated": + builder.obfuscated( getAsBoolean( value ) ); + break; + case "color": + builder.color( ChatColor.of( value.getAsString() ) ); + break; + case "font": + builder.font( value.getAsString() ); + break; + } } return builder.build(); } 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 f9cfa20e4..6c97aec37 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 @@ -17,13 +17,14 @@ public class KeybindComponentSerializer extends BaseComponentSerializer implemen public KeybindComponent deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { JsonObject object = json.getAsJsonObject(); - if ( !object.has( "keybind" ) ) + JsonElement keybind = object.get( "keybind" ); + if ( keybind == null ) { throw new JsonParseException( "Could not parse JSON: missing 'keybind' property" ); } KeybindComponent component = new KeybindComponent(); deserialize( object, component, context ); - component.setKeybind( object.get( "keybind" ).getAsString() ); + component.setKeybind( keybind.getAsString() ); return component; } 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 e38bf94e2..fc7aad507 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 @@ -17,22 +17,29 @@ public class ScoreComponentSerializer extends BaseComponentSerializer implements public ScoreComponent deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException { JsonObject json = element.getAsJsonObject(); - if ( !json.has( "score" ) ) + JsonObject score = json.getAsJsonObject( "score" ); + if ( score == null ) { throw new JsonParseException( "Could not parse JSON: missing 'score' property" ); } - JsonObject score = json.get( "score" ).getAsJsonObject(); - if ( !score.has( "name" ) || !score.has( "objective" ) ) + JsonElement nameJson = score.get( "name" ); + if ( nameJson == null ) + { + throw new JsonParseException( "A score component needs at least a name (and an objective)" ); + } + JsonElement objectiveJson = score.get( "objective" ); + if ( objectiveJson == null ) { throw new JsonParseException( "A score component needs at least a name and an objective" ); } - String name = score.get( "name" ).getAsString(); - String objective = score.get( "objective" ).getAsString(); + String name = nameJson.getAsString(); + String objective = objectiveJson.getAsString(); ScoreComponent component = new ScoreComponent( name, objective ); - if ( score.has( "value" ) && !score.get( "value" ).getAsString().isEmpty() ) + JsonElement value = score.get( "value" ); + if ( value != null && !value.getAsString().isEmpty() ) { - component.setValue( score.get( "value" ).getAsString() ); + component.setValue( value.getAsString() ); } deserialize( json, component, context ); 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 4cdc463bf..86815dae0 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 @@ -17,15 +17,17 @@ public class SelectorComponentSerializer extends BaseComponentSerializer impleme public SelectorComponent deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException { JsonObject object = element.getAsJsonObject(); - if ( !object.has( "selector" ) ) + JsonElement selector = object.get( "selector" ); + if ( selector == null ) { throw new JsonParseException( "Could not parse JSON: missing 'selector' property" ); } - SelectorComponent component = new SelectorComponent( object.get( "selector" ).getAsString() ); + SelectorComponent component = new SelectorComponent( selector.getAsString() ); - if ( object.has( "separator" ) ) + JsonElement separator = object.get( "separator" ); + if ( separator != null ) { - component.setSeparator( ComponentSerializer.deserialize( object.get( "separator" ).getAsString() ) ); + component.setSeparator( ComponentSerializer.deserialize( separator.getAsString() ) ); } deserialize( object, component, context ); 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 2542ed571..445239efc 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 @@ -18,9 +18,10 @@ public class TextComponentSerializer extends BaseComponentSerializer implements { TextComponent component = new TextComponent(); JsonObject object = json.getAsJsonObject(); - if ( object.has( "text" ) ) + JsonElement text = object.get( "text" ); + if ( text != null ) { - component.setText( object.get( "text" ).getAsString() ); + component.setText( text.getAsString() ); } deserialize( object, component, context ); return component; 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 576f1ca12..fac2023e0 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 @@ -21,18 +21,21 @@ public class TranslatableComponentSerializer extends BaseComponentSerializer imp TranslatableComponent component = new TranslatableComponent(); JsonObject object = json.getAsJsonObject(); deserialize( object, component, context ); - if ( !object.has( "translate" ) ) + JsonElement translate = object.get( "translate" ); + if ( translate == null ) { throw new JsonParseException( "Could not parse JSON: missing 'translate' property" ); } - component.setTranslate( object.get( "translate" ).getAsString() ); - if ( object.has( "with" ) ) + component.setTranslate( translate.getAsString() ); + JsonElement with = object.get( "with" ); + if ( with != null ) { - component.setWith( Arrays.asList( context.deserialize( object.get( "with" ), BaseComponent[].class ) ) ); + component.setWith( Arrays.asList( context.deserialize( with, BaseComponent[].class ) ) ); } - if ( object.has( "fallback" ) ) + JsonElement fallback = object.get( "fallback" ); + if ( fallback != null ) { - component.setFallback( object.get( "fallback" ).getAsString() ); + component.setFallback( fallback.getAsString() ); } return component; }