Skip to content

SPIGOT-8024, #3811: Add versioned chat serialization #3812

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions chat/src/main/java/net/md_5/bungee/api/chat/ClickEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import org.jetbrains.annotations.ApiStatus;

@Getter
@ToString
Expand All @@ -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
{

Expand Down
28 changes: 2 additions & 26 deletions chat/src/main/java/net/md_5/bungee/api/chat/HoverEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
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
Expand All @@ -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.
*
Expand Down Expand Up @@ -106,7 +82,7 @@ public BaseComponent[] getValue()
return (BaseComponent[]) ( (Text) content ).getValue();
}

TextComponent component = new TextComponent( ComponentSerializer.toString( content ) );
TextComponent component = new TextComponent( VersionedComponentSerializer.getDefault().toString( content ) );
return new BaseComponent[]
{
component
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
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
Expand All @@ -16,18 +15,6 @@
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.
*
Expand All @@ -48,12 +35,6 @@ public Entity(String type, @NonNull String id, BaseComponent name)
*/
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()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,17 @@
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<Entity>, JsonDeserializer<Entity>
public class EntitySerializer extends BaseComponentSerializer implements JsonSerializer<Entity>, JsonDeserializer<Entity>
{

public EntitySerializer(VersionedComponentSerializer serializer)
{
super( serializer );
}

@Override
public Entity deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException
{
Expand All @@ -34,8 +41,7 @@ public Entity deserialize(JsonElement element, Type type, JsonDeserializationCon
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
);
}

Expand All @@ -44,8 +50,20 @@ public JsonElement serialize(Entity content, Type type, JsonSerializationContext
{
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() ) );
Expand Down
114 changes: 66 additions & 48 deletions chat/src/main/java/net/md_5/bungee/chat/BaseComponentSerializer.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,19 @@
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 ) );
Expand Down Expand Up @@ -59,7 +63,6 @@ protected void deserialize(JsonObject object, BaseComponent component, JsonDeser
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() : "" ) );
Expand Down Expand Up @@ -101,7 +104,6 @@ protected void deserialize(JsonObject object, BaseComponent component, JsonDeser
};
}
hoverEvent = new HoverEvent( action, new ArrayList<>( Arrays.asList( list ) ) );
hoverEvent.setV1_21_5( newHoverEvent );
}
} else
{
Expand Down Expand Up @@ -141,15 +143,15 @@ protected void deserialize(JsonObject object, BaseComponent component, JsonDeser
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<BaseComponent, Boolean>() ) );
VersionedComponentSerializer.serializedComponents.set( Collections.newSetFromMap( new IdentityHashMap<BaseComponent, Boolean>() ) );
}
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 );

Expand All @@ -164,63 +166,79 @@ protected void serialize(JsonObject object, BaseComponent component, JsonSeriali
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() );
}

}
if ( component.getHoverEvent() != null )
{
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 )
Expand All @@ -229,10 +247,10 @@ protected void serialize(JsonObject object, BaseComponent component, JsonSeriali
}
} finally
{
ComponentSerializer.serializedComponents.get().remove( component );
VersionedComponentSerializer.serializedComponents.get().remove( component );
if ( first )
{
ComponentSerializer.serializedComponents.set( null );
VersionedComponentSerializer.serializedComponents.set( null );
}
}
}
Expand Down
10 changes: 10 additions & 0 deletions chat/src/main/java/net/md_5/bungee/chat/ChatVersion.java
Original file line number Diff line number Diff line change
@@ -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;
}
Loading