#3634: Micro-optimize chat deserialization

This commit is contained in:
Janmm14 2024-03-31 09:38:17 +11:00 committed by md_5
parent e642b9dde1
commit c2f73d32b8
No known key found for this signature in database
GPG Key ID: E8E901AC7C617C11
8 changed files with 96 additions and 76 deletions

View File

@ -244,7 +244,7 @@ public final class ChatColor
public static ChatColor of(String string) public static ChatColor of(String string)
{ {
Preconditions.checkArgument( string != null, "string cannot be null" ); Preconditions.checkArgument( string != null, "string cannot be null" );
if ( string.startsWith( "#" ) && string.length() == 7 ) if ( string.length() == 7 && string.charAt( 0 ) == '#' )
{ {
int rgb; int rgb;
try try

View File

@ -23,59 +23,62 @@ public class BaseComponentSerializer
{ {
component.applyStyle( context.deserialize( object, ComponentStyle.class ) ); 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 //Events
if ( object.has( "clickEvent" ) ) JsonObject clickEvent = object.getAsJsonObject( "clickEvent" );
if ( clickEvent != null )
{ {
JsonObject event = object.getAsJsonObject( "clickEvent" );
component.setClickEvent( new ClickEvent( component.setClickEvent( new ClickEvent(
ClickEvent.Action.valueOf( event.get( "action" ).getAsString().toUpperCase( Locale.ROOT ) ), ClickEvent.Action.valueOf( clickEvent.get( "action" ).getAsString().toUpperCase( Locale.ROOT ) ),
( event.has( "value" ) ) ? event.get( "value" ).getAsString() : "" ) ); ( 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 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. // 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. // If the GSON is possible to be parsed as BaseComponent, attempt to parse as so.
BaseComponent[] components; BaseComponent[] components;
if ( contents.isJsonArray() ) if ( value.isJsonArray() )
{ {
components = context.deserialize( contents, BaseComponent[].class ); components = context.deserialize( value, BaseComponent[].class );
} else } else
{ {
components = new BaseComponent[] components = new BaseComponent[]
{ {
context.deserialize( contents, BaseComponent.class ) context.deserialize( value, BaseComponent.class )
}; };
} }
hoverEvent = new HoverEvent( action, components ); hoverEvent = new HoverEvent( action, components );
} else if ( event.has( "contents" ) ) } else
{ {
JsonElement contents = event.get( "contents" ); JsonElement contents = hoverEventJson.get( "contents" );
if ( contents != null )
Content[] list;
if ( contents.isJsonArray() )
{ {
list = context.deserialize( contents, HoverEvent.getClass( action, true ) ); Content[] list;
} else if ( contents.isJsonArray() )
{
list = new Content[]
{ {
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 ) 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.<BaseComponent[]>deserialize( object.get( "extra" ), BaseComponent[].class ) ) ); component.setExtra( Arrays.asList( context.deserialize( extra, BaseComponent[].class ) ) );
} }
} }

View File

@ -9,6 +9,7 @@ import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer; import com.google.gson.JsonSerializer;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.Map;
import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.ComponentStyle; import net.md_5.bungee.api.chat.ComponentStyle;
import net.md_5.bungee.api.chat.ComponentStyleBuilder; import net.md_5.bungee.api.chat.ComponentStyleBuilder;
@ -77,33 +78,34 @@ public class ComponentStyleSerializer implements JsonSerializer<ComponentStyle>,
{ {
ComponentStyleBuilder builder = ComponentStyle.builder(); ComponentStyleBuilder builder = ComponentStyle.builder();
JsonObject object = json.getAsJsonObject(); JsonObject object = json.getAsJsonObject();
if ( object.has( "bold" ) ) for ( Map.Entry<String, JsonElement> entry : object.entrySet() )
{ {
builder.bold( getAsBoolean( object.get( "bold" ) ) ); String name = entry.getKey();
} JsonElement value = entry.getValue();
if ( object.has( "italic" ) ) switch ( name )
{ {
builder.italic( getAsBoolean( object.get( "italic" ) ) ); case "bold":
} builder.bold( getAsBoolean( value ) );
if ( object.has( "underlined" ) ) break;
{ case "italic":
builder.underlined( getAsBoolean( object.get( "underlined" ) ) ); builder.italic( getAsBoolean( value ) );
} break;
if ( object.has( "strikethrough" ) ) case "underlined":
{ builder.underlined( getAsBoolean( value ) );
builder.strikethrough( getAsBoolean( object.get( "strikethrough" ) ) ); break;
} case "strikethrough":
if ( object.has( "obfuscated" ) ) builder.strikethrough( getAsBoolean( value ) );
{ break;
builder.obfuscated( getAsBoolean( object.get( "obfuscated" ) ) ); case "obfuscated":
} builder.obfuscated( getAsBoolean( value ) );
if ( object.has( "color" ) ) break;
{ case "color":
builder.color( ChatColor.of( object.get( "color" ).getAsString() ) ); builder.color( ChatColor.of( value.getAsString() ) );
} break;
if ( object.has( "font" ) ) case "font":
{ builder.font( value.getAsString() );
builder.font( object.get( "font" ).getAsString() ); break;
}
} }
return builder.build(); return builder.build();
} }

View File

@ -17,13 +17,14 @@ public class KeybindComponentSerializer extends BaseComponentSerializer implemen
public KeybindComponent deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException public KeybindComponent deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
{ {
JsonObject object = json.getAsJsonObject(); 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" ); throw new JsonParseException( "Could not parse JSON: missing 'keybind' property" );
} }
KeybindComponent component = new KeybindComponent(); KeybindComponent component = new KeybindComponent();
deserialize( object, component, context ); deserialize( object, component, context );
component.setKeybind( object.get( "keybind" ).getAsString() ); component.setKeybind( keybind.getAsString() );
return component; return component;
} }

View File

@ -17,22 +17,29 @@ public class ScoreComponentSerializer extends BaseComponentSerializer implements
public ScoreComponent deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException public ScoreComponent deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException
{ {
JsonObject json = element.getAsJsonObject(); 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" ); throw new JsonParseException( "Could not parse JSON: missing 'score' property" );
} }
JsonObject score = json.get( "score" ).getAsJsonObject(); JsonElement nameJson = score.get( "name" );
if ( !score.has( "name" ) || !score.has( "objective" ) ) 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" ); throw new JsonParseException( "A score component needs at least a name and an objective" );
} }
String name = score.get( "name" ).getAsString(); String name = nameJson.getAsString();
String objective = score.get( "objective" ).getAsString(); String objective = objectiveJson.getAsString();
ScoreComponent component = new ScoreComponent( name, objective ); 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 ); deserialize( json, component, context );

View File

@ -17,15 +17,17 @@ public class SelectorComponentSerializer extends BaseComponentSerializer impleme
public SelectorComponent deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException public SelectorComponent deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException
{ {
JsonObject object = element.getAsJsonObject(); 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" ); 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 ); deserialize( object, component, context );

View File

@ -18,9 +18,10 @@ public class TextComponentSerializer extends BaseComponentSerializer implements
{ {
TextComponent component = new TextComponent(); TextComponent component = new TextComponent();
JsonObject object = json.getAsJsonObject(); 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 ); deserialize( object, component, context );
return component; return component;

View File

@ -21,18 +21,21 @@ public class TranslatableComponentSerializer extends BaseComponentSerializer imp
TranslatableComponent component = new TranslatableComponent(); TranslatableComponent component = new TranslatableComponent();
JsonObject object = json.getAsJsonObject(); JsonObject object = json.getAsJsonObject();
deserialize( object, component, context ); 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" ); throw new JsonParseException( "Could not parse JSON: missing 'translate' property" );
} }
component.setTranslate( object.get( "translate" ).getAsString() ); component.setTranslate( translate.getAsString() );
if ( object.has( "with" ) ) 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; return component;
} }