#3774: Minecraft 25w04a chat component changes
This commit is contained in:
parent
4fded9828f
commit
80bb237289
@ -3,7 +3,9 @@ package net.md_5.bungee.api.chat;
|
|||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@ToString
|
@ToString
|
||||||
@ -23,6 +25,13 @@ public final class ClickEvent
|
|||||||
*/
|
*/
|
||||||
private final String value;
|
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
|
public enum Action
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -14,6 +14,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.Item;
|
||||||
import net.md_5.bungee.api.chat.hover.content.Text;
|
import net.md_5.bungee.api.chat.hover.content.Text;
|
||||||
import net.md_5.bungee.chat.ComponentSerializer;
|
import net.md_5.bungee.chat.ComponentSerializer;
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@ToString
|
@ToString
|
||||||
@ -34,8 +35,33 @@ public final class HoverEvent
|
|||||||
* Returns whether this hover event is prior to 1.16
|
* Returns whether this hover event is prior to 1.16
|
||||||
*/
|
*/
|
||||||
@Setter
|
@Setter
|
||||||
|
@ApiStatus.Internal
|
||||||
private boolean legacy = false;
|
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.
|
* Creates event with an action and a list of contents.
|
||||||
*
|
*
|
||||||
|
@ -7,6 +7,7 @@ import lombok.NonNull;
|
|||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import net.md_5.bungee.api.chat.BaseComponent;
|
import net.md_5.bungee.api.chat.BaseComponent;
|
||||||
import net.md_5.bungee.api.chat.HoverEvent;
|
import net.md_5.bungee.api.chat.HoverEvent;
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@ -15,6 +16,18 @@ import net.md_5.bungee.api.chat.HoverEvent;
|
|||||||
public class Entity extends Content
|
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.
|
* Namespaced entity ID.
|
||||||
*
|
*
|
||||||
@ -35,6 +48,12 @@ public class Entity extends Content
|
|||||||
*/
|
*/
|
||||||
private BaseComponent name;
|
private BaseComponent name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if this entity is for 1.21.5 or later
|
||||||
|
*/
|
||||||
|
@ApiStatus.Internal
|
||||||
|
private boolean v1_21_5;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HoverEvent.Action requiredAction()
|
public HoverEvent.Action requiredAction()
|
||||||
{
|
{
|
||||||
|
@ -19,20 +19,23 @@ public class EntitySerializer implements JsonSerializer<Entity>, JsonDeserialize
|
|||||||
{
|
{
|
||||||
JsonObject value = element.getAsJsonObject();
|
JsonObject value = element.getAsJsonObject();
|
||||||
|
|
||||||
|
boolean newEntity = value.has( "uuid" );
|
||||||
|
|
||||||
String idString;
|
String idString;
|
||||||
JsonElement id = value.get( "id" );
|
JsonElement uuid = value.get( newEntity ? "uuid" : "id" );
|
||||||
if ( id.isJsonArray() )
|
if ( uuid.isJsonArray() )
|
||||||
{
|
{
|
||||||
idString = parseUUID( context.deserialize( id, int[].class ) ).toString();
|
idString = parseUUID( context.deserialize( uuid, int[].class ) ).toString();
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
idString = id.getAsString();
|
idString = uuid.getAsString();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Entity(
|
return new Entity(
|
||||||
( value.has( "type" ) ) ? value.get( "type" ).getAsString() : null,
|
( value.has( newEntity ? "id" : "type" ) ) ? value.get( newEntity ? "id" : "type" ).getAsString() : null,
|
||||||
idString,
|
idString,
|
||||||
( value.has( "name" ) ) ? context.deserialize( value.get( "name" ), BaseComponent.class ) : null
|
( value.has( "name" ) ) ? context.deserialize( value.get( "name" ), BaseComponent.class ) : null,
|
||||||
|
newEntity
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,8 +43,9 @@ public class EntitySerializer implements JsonSerializer<Entity>, JsonDeserialize
|
|||||||
public JsonElement serialize(Entity content, Type type, JsonSerializationContext context)
|
public JsonElement serialize(Entity content, Type type, JsonSerializationContext context)
|
||||||
{
|
{
|
||||||
JsonObject object = new JsonObject();
|
JsonObject object = new JsonObject();
|
||||||
object.addProperty( "type", ( content.getType() != null ) ? content.getType() : "minecraft:pig" );
|
|
||||||
object.addProperty( "id", content.getId() );
|
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() );
|
||||||
if ( content.getName() != null )
|
if ( content.getName() != null )
|
||||||
{
|
{
|
||||||
object.add( "name", context.serialize( content.getName() ) );
|
object.add( "name", context.serialize( content.getName() ) );
|
||||||
|
@ -30,42 +30,65 @@ public class BaseComponentSerializer
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Events
|
//Events
|
||||||
JsonObject clickEvent = object.getAsJsonObject( "clickEvent" );
|
JsonObject clickEvent;
|
||||||
|
boolean newClickEvent = ( clickEvent = object.getAsJsonObject( "click_event" ) ) != null;
|
||||||
|
if ( !newClickEvent )
|
||||||
|
{
|
||||||
|
clickEvent = object.getAsJsonObject( "clickEvent" );
|
||||||
|
}
|
||||||
if ( clickEvent != null )
|
if ( clickEvent != null )
|
||||||
{
|
{
|
||||||
component.setClickEvent( new ClickEvent(
|
ClickEvent.Action action = ClickEvent.Action.valueOf( clickEvent.get( "action" ).getAsString().toUpperCase( Locale.ROOT ) );
|
||||||
ClickEvent.Action.valueOf( clickEvent.get( "action" ).getAsString().toUpperCase( Locale.ROOT ) ),
|
if ( newClickEvent )
|
||||||
( clickEvent.has( "value" ) ) ? clickEvent.get( "value" ).getAsString() : "" ) );
|
{
|
||||||
|
switch ( action )
|
||||||
|
{
|
||||||
|
case OPEN_URL:
|
||||||
|
component.setClickEvent( new ClickEvent( action, clickEvent.get( "url" ).getAsString() ) );
|
||||||
|
break;
|
||||||
|
case RUN_COMMAND:
|
||||||
|
case SUGGEST_COMMAND:
|
||||||
|
component.setClickEvent( new ClickEvent( action, clickEvent.get( "command" ).getAsString() ) );
|
||||||
|
break;
|
||||||
|
case CHANGE_PAGE:
|
||||||
|
int page = clickEvent.get( "page" ).getAsInt();
|
||||||
|
Preconditions.checkArgument( page >= 0, "Page number has to be positive" );
|
||||||
|
component.setClickEvent( new ClickEvent( action, Integer.toString( page ) ) );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
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() : "" ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
JsonObject hoverEventJson = object.getAsJsonObject( "hoverEvent" );
|
|
||||||
|
JsonObject hoverEventJson;
|
||||||
|
boolean newHoverEvent = ( hoverEventJson = object.getAsJsonObject( "hover_event" ) ) != null;
|
||||||
|
if ( !newHoverEvent )
|
||||||
|
{
|
||||||
|
hoverEventJson = object.getAsJsonObject( "hoverEvent" );
|
||||||
|
}
|
||||||
|
|
||||||
if ( hoverEventJson != null )
|
if ( hoverEventJson != null )
|
||||||
{
|
{
|
||||||
HoverEvent hoverEvent = null;
|
HoverEvent hoverEvent = null;
|
||||||
HoverEvent.Action action = HoverEvent.Action.valueOf( hoverEventJson.get( "action" ).getAsString().toUpperCase( Locale.ROOT ) );
|
HoverEvent.Action action = HoverEvent.Action.valueOf( hoverEventJson.get( "action" ).getAsString().toUpperCase( Locale.ROOT ) );
|
||||||
|
|
||||||
JsonElement value = hoverEventJson.get( "value" );
|
if ( newHoverEvent || hoverEventJson.has( "contents" ) )
|
||||||
if ( value != null )
|
|
||||||
{
|
{
|
||||||
|
// value is only used for text in >= 1.21.5 (its inlined now)
|
||||||
// Plugins previously had support to pass BaseComponent[] into any action.
|
JsonElement contents = hoverEventJson.get( newHoverEvent ? "value" : "contents" );
|
||||||
// If the GSON is possible to be parsed as BaseComponent, attempt to parse as so.
|
if ( contents != null || ( newHoverEvent && ( action == HoverEvent.Action.SHOW_ITEM || action == HoverEvent.Action.SHOW_ENTITY ) ) )
|
||||||
BaseComponent[] components;
|
|
||||||
if ( value.isJsonArray() )
|
|
||||||
{
|
{
|
||||||
components = context.deserialize( value, BaseComponent[].class );
|
if ( contents == null )
|
||||||
} else
|
|
||||||
{
|
|
||||||
components = new BaseComponent[]
|
|
||||||
{
|
{
|
||||||
context.deserialize( value, BaseComponent.class )
|
// this is the new inline for SHOW_ITEM and SHOW_ENTITY
|
||||||
};
|
contents = hoverEventJson;
|
||||||
}
|
}
|
||||||
hoverEvent = new HoverEvent( action, components );
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
JsonElement contents = hoverEventJson.get( "contents" );
|
|
||||||
if ( contents != null )
|
|
||||||
{
|
|
||||||
Content[] list;
|
Content[] list;
|
||||||
if ( contents.isJsonArray() )
|
if ( contents.isJsonArray() )
|
||||||
{
|
{
|
||||||
@ -78,6 +101,27 @@ public class BaseComponentSerializer
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
hoverEvent = new HoverEvent( action, new ArrayList<>( Arrays.asList( list ) ) );
|
hoverEvent = new HoverEvent( action, new ArrayList<>( Arrays.asList( list ) ) );
|
||||||
|
hoverEvent.setV1_21_5( newHoverEvent );
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
JsonElement value = hoverEventJson.get( "value" );
|
||||||
|
if ( value != null )
|
||||||
|
{
|
||||||
|
// 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 ( value.isJsonArray() )
|
||||||
|
{
|
||||||
|
components = context.deserialize( value, BaseComponent[].class );
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
components = new BaseComponent[]
|
||||||
|
{
|
||||||
|
context.deserialize( value, BaseComponent.class )
|
||||||
|
};
|
||||||
|
}
|
||||||
|
hoverEvent = new HoverEvent( action, components );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,23 +162,65 @@ public class BaseComponentSerializer
|
|||||||
if ( component.getClickEvent() != null )
|
if ( component.getClickEvent() != null )
|
||||||
{
|
{
|
||||||
JsonObject clickEvent = new JsonObject();
|
JsonObject clickEvent = new JsonObject();
|
||||||
clickEvent.addProperty( "action", component.getClickEvent().getAction().toString().toLowerCase( Locale.ROOT ) );
|
String actionName = component.getClickEvent().getAction().toString().toLowerCase( Locale.ROOT );
|
||||||
clickEvent.addProperty( "value", component.getClickEvent().getValue() );
|
clickEvent.addProperty( "action", actionName.toLowerCase( Locale.ROOT ) );
|
||||||
object.add( "clickEvent", clickEvent );
|
if ( component.getClickEvent().isV1_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 );
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
clickEvent.addProperty( "value", component.getClickEvent().getValue() );
|
||||||
|
object.add( "clickEvent", clickEvent );
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if ( component.getHoverEvent() != null )
|
if ( component.getHoverEvent() != null )
|
||||||
{
|
{
|
||||||
JsonObject hoverEvent = new JsonObject();
|
JsonObject hoverEvent = new JsonObject();
|
||||||
hoverEvent.addProperty( "action", component.getHoverEvent().getAction().toString().toLowerCase( Locale.ROOT ) );
|
hoverEvent.addProperty( "action", component.getHoverEvent().getAction().toString().toLowerCase( Locale.ROOT ) );
|
||||||
|
boolean newFormat = component.getHoverEvent().isV1_21_5();
|
||||||
if ( component.getHoverEvent().isLegacy() )
|
if ( component.getHoverEvent().isLegacy() )
|
||||||
{
|
{
|
||||||
hoverEvent.add( "value", context.serialize( component.getHoverEvent().getContents().get( 0 ) ) );
|
hoverEvent.add( "value", context.serialize( component.getHoverEvent().getContents().get( 0 ) ) );
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
hoverEvent.add( "contents", context.serialize( ( component.getHoverEvent().getContents().size() == 1 )
|
if ( newFormat )
|
||||||
? component.getHoverEvent().getContents().get( 0 ) : component.getHoverEvent().getContents() ) );
|
{
|
||||||
|
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() ) );
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
hoverEvent.add( "contents", context.serialize( ( component.getHoverEvent().getContents().size() == 1 )
|
||||||
|
? component.getHoverEvent().getContents().get( 0 ) : component.getHoverEvent().getContents() ) );
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
object.add( "hoverEvent", hoverEvent );
|
object.add( newFormat ? "hover_event" : "hoverEvent", hoverEvent );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( component.getExtra() != null )
|
if ( component.getExtra() != null )
|
||||||
|
@ -50,6 +50,20 @@ public final class ChatComponentTransformer
|
|||||||
next.getHoverEvent().getContents().clear();
|
next.getHoverEvent().getContents().clear();
|
||||||
next.getHoverEvent().getContents().add( exception );
|
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;
|
return next;
|
||||||
|
Loading…
Reference in New Issue
Block a user