Update MCProtocolLib to Adventure migration (#1572)

* Use raw message data instead of converting the message

* Update MCProtocolLib to Adventure

* Ignore MCProtocolLib Adventure depend

* Remove unused dependency

* Fix isMessage handling `null` wrong.

* Update to adventure 4.2.0

* Clean-up isMessage

* Fix tests

* Clean-up of catch statements
This commit is contained in:
rtm516 2020-11-27 23:28:08 +00:00 committed by GitHub
parent 11d9d30050
commit da2dc69441
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 148 additions and 169 deletions

View File

@ -110,13 +110,17 @@
<dependency>
<groupId>com.github.steveice10</groupId>
<artifactId>mcprotocollib</artifactId>
<version>86e1901be5</version>
<version>26201a4</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
</exclusion>
<exclusion>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-serializer-gson</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
@ -136,21 +140,21 @@
<version>2.1.3</version>
</dependency>
<dependency>
<groupId>com.github.kyoripowered.adventure</groupId>
<groupId>net.kyori</groupId>
<artifactId>adventure-api</artifactId>
<version>7acd956</version>
<version>4.2.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.github.kyoripowered.adventure</groupId>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-serializer-gson</artifactId>
<version>7acd956</version>
<version>4.2.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.github.kyoripowered.adventure</groupId>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-serializer-legacy</artifactId>
<version>7acd956</version>
<version>4.2.0</version>
<scope>compile</scope>
</dependency>
<dependency>

View File

@ -28,6 +28,7 @@ package org.geysermc.connector.entity;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import net.kyori.adventure.text.Component;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
@ -50,7 +51,7 @@ public class CommandBlockMinecartEntity extends DefaultBlockMinecartEntity {
metadata.put(EntityData.COMMAND_BLOCK_COMMAND, entityMetadata.getValue());
}
if (entityMetadata.getId() == 14) {
metadata.put(EntityData.COMMAND_BLOCK_LAST_OUTPUT, MessageTranslator.convertMessage(entityMetadata.getValue().toString()));
metadata.put(EntityData.COMMAND_BLOCK_LAST_OUTPUT, MessageTranslator.convertMessage((Component) entityMetadata.getValue()));
}
super.updateBedrockMetadata(entityMetadata, session);
}

View File

@ -32,7 +32,6 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction;
import com.github.steveice10.mc.protocol.data.game.world.block.BlockFace;
import com.github.steveice10.mc.protocol.data.message.Message;
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerActionPacket;
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerUseItemPacket;
import com.nukkitx.math.vector.Vector3f;
@ -45,6 +44,7 @@ import com.nukkitx.protocol.bedrock.packet.*;
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
import lombok.Getter;
import lombok.Setter;
import net.kyori.adventure.text.Component;
import org.geysermc.connector.entity.attribute.Attribute;
import org.geysermc.connector.entity.attribute.AttributeType;
import org.geysermc.connector.entity.living.ArmorStandEntity;
@ -313,11 +313,11 @@ public class Entity {
}
break;
case 2: // custom name
if (entityMetadata.getValue() instanceof Message) {
Message message = (Message) entityMetadata.getValue();
if (entityMetadata.getValue() instanceof Component) {
Component message = (Component) entityMetadata.getValue();
if (message != null)
// Always translate even if it's a TextMessage since there could be translatable parameters
metadata.put(EntityData.NAMETAG, MessageTranslator.convertMessage(message.toString(), session.getLocale()));
metadata.put(EntityData.NAMETAG, MessageTranslator.convertMessage(message, session.getLocale()));
}
break;
case 3: // is custom name visible

View File

@ -27,7 +27,6 @@ package org.geysermc.connector.entity.player;
import com.github.steveice10.mc.auth.data.GameProfile;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
import com.github.steveice10.mc.protocol.data.message.TextMessage;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.math.vector.Vector3i;
@ -43,6 +42,7 @@ import com.nukkitx.protocol.bedrock.packet.SetEntityLinkPacket;
import com.nukkitx.protocol.bedrock.packet.UpdateAttributesPacket;
import lombok.Getter;
import lombok.Setter;
import net.kyori.adventure.text.Component;
import org.geysermc.connector.entity.Entity;
import org.geysermc.connector.entity.LivingEntity;
import org.geysermc.connector.entity.attribute.Attribute;
@ -252,9 +252,9 @@ public class PlayerEntity extends LivingEntity {
if (entityMetadata.getId() == 2) {
String username = this.username;
TextMessage name = (TextMessage) entityMetadata.getValue();
Component name = (Component) entityMetadata.getValue();
if (name != null) {
username = MessageTranslator.convertMessage(name.toString());
username = MessageTranslator.convertMessage(name);
}
Team team = session.getWorldCache().getScoreboard().getTeamFor(username);
if (team != null) {

View File

@ -25,13 +25,13 @@
package org.geysermc.connector.network.session.cache;
import com.github.steveice10.mc.protocol.data.message.Message;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.packet.AddEntityPacket;
import com.nukkitx.protocol.bedrock.packet.BossEventPacket;
import com.nukkitx.protocol.bedrock.packet.RemoveEntityPacket;
import lombok.AllArgsConstructor;
import net.kyori.adventure.text.Component;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.chat.MessageTranslator;
@ -41,7 +41,7 @@ public class BossBar {
private GeyserSession session;
private long entityId;
private Message title;
private Component title;
private float health;
private int color;
private int overlay;
@ -58,7 +58,7 @@ public class BossBar {
BossEventPacket bossEventPacket = new BossEventPacket();
bossEventPacket.setBossUniqueEntityId(entityId);
bossEventPacket.setAction(BossEventPacket.Action.CREATE);
bossEventPacket.setTitle(MessageTranslator.convertMessage(title.toString(), session.getLocale()));
bossEventPacket.setTitle(MessageTranslator.convertMessage(title, session.getLocale()));
bossEventPacket.setHealthPercentage(health);
bossEventPacket.setColor(color); //ignored by client
bossEventPacket.setOverlay(overlay);
@ -67,12 +67,12 @@ public class BossBar {
session.sendUpstreamPacket(bossEventPacket);
}
public void updateTitle(Message title) {
public void updateTitle(Component title) {
this.title = title;
BossEventPacket bossEventPacket = new BossEventPacket();
bossEventPacket.setBossUniqueEntityId(entityId);
bossEventPacket.setAction(BossEventPacket.Action.UPDATE_NAME);
bossEventPacket.setTitle(MessageTranslator.convertMessage(title.toString(), session.getLocale()));
bossEventPacket.setTitle(MessageTranslator.convertMessage(title, session.getLocale()));
session.sendUpstreamPacket(bossEventPacket);
}

View File

@ -26,12 +26,13 @@
package org.geysermc.connector.network.translators.chat;
import com.github.steveice10.mc.protocol.data.game.scoreboard.TeamColor;
import com.github.steveice10.mc.protocol.data.message.style.ChatColor;
import com.github.steveice10.mc.protocol.data.message.style.ChatFormat;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextDecoration;
import net.kyori.adventure.text.renderer.TranslatableComponentRenderer;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.utils.LanguageUtils;
@ -42,30 +43,24 @@ public class MessageTranslator {
// These are used for handling the translations of the messages
private static final TranslatableComponentRenderer<Locale> RENDERER = TranslatableComponentRenderer.usingTranslationSource(new MinecraftTranslationRegistry());
// Construct our own {@link GsonComponentSerializer} encase we need to change anything
private static final GsonComponentSerializer GSON_SERIALIZER = GsonComponentSerializer.builder()
.build();
// Store team colors for player names
private static final Map<TeamColor, String> TEAM_COLORS = new HashMap<>();
private static final Map<TeamColor, TextDecoration> TEAM_FORMATS = new HashMap<>();
// Legacy formatting character
private static final String BASE = "\u00a7";
// Reset character
private static final String RESET = BASE + "r";
static {
TEAM_COLORS.put(TeamColor.BLACK, getColor(ChatColor.BLACK));
TEAM_COLORS.put(TeamColor.DARK_BLUE, getColor(ChatColor.DARK_BLUE));
TEAM_COLORS.put(TeamColor.DARK_GREEN, getColor(ChatColor.DARK_GREEN));
TEAM_COLORS.put(TeamColor.DARK_AQUA, getColor(ChatColor.DARK_AQUA));
TEAM_COLORS.put(TeamColor.DARK_RED, getColor(ChatColor.DARK_RED));
TEAM_COLORS.put(TeamColor.DARK_PURPLE, getColor(ChatColor.DARK_PURPLE));
TEAM_COLORS.put(TeamColor.GOLD, getColor(ChatColor.GOLD));
TEAM_COLORS.put(TeamColor.GRAY, getColor(ChatColor.GRAY));
TEAM_COLORS.put(TeamColor.DARK_GRAY, getColor(ChatColor.DARK_GRAY));
TEAM_COLORS.put(TeamColor.BLUE, getColor(ChatColor.BLUE));
TEAM_COLORS.put(TeamColor.GREEN, getColor(ChatColor.GREEN));
TEAM_COLORS.put(TeamColor.AQUA, getColor(ChatColor.AQUA));
TEAM_COLORS.put(TeamColor.RED, getColor(ChatColor.RED));
TEAM_COLORS.put(TeamColor.LIGHT_PURPLE, getColor(ChatColor.LIGHT_PURPLE));
TEAM_COLORS.put(TeamColor.YELLOW, getColor(ChatColor.YELLOW));
TEAM_COLORS.put(TeamColor.WHITE, getColor(ChatColor.WHITE));
TEAM_COLORS.put(TeamColor.OBFUSCATED, getFormat(ChatFormat.OBFUSCATED));
TEAM_COLORS.put(TeamColor.BOLD, getFormat(ChatFormat.BOLD));
TEAM_COLORS.put(TeamColor.STRIKETHROUGH, getFormat(ChatFormat.STRIKETHROUGH));
TEAM_COLORS.put(TeamColor.ITALIC, getFormat(ChatFormat.ITALIC));
TEAM_FORMATS.put(TeamColor.OBFUSCATED, TextDecoration.OBFUSCATED);
TEAM_FORMATS.put(TeamColor.BOLD, TextDecoration.BOLD);
TEAM_FORMATS.put(TeamColor.STRIKETHROUGH, TextDecoration.STRIKETHROUGH);
TEAM_FORMATS.put(TeamColor.ITALIC, TextDecoration.ITALIC);
}
/**
@ -75,30 +70,43 @@ public class MessageTranslator {
* @param locale Locale to use for translation strings
* @return Parsed and formatted message for bedrock
*/
public static String convertMessage(Component message, String locale) {
try {
// Get a Locale from the given locale string
Locale localeCode = Locale.forLanguageTag(locale.replace('_', '-'));
message = RENDERER.render(message, localeCode);
String legacy = LegacyComponentSerializer.legacySection().serialize(message);
// Strip strikethrough and underline as they are not supported on bedrock
legacy = legacy.replaceAll("\u00a7[mn]", "");
// Make color codes reset formatting like Java
// See https://minecraft.gamepedia.com/Formatting_codes#Usage
legacy = legacy.replaceAll("\u00a7([0-9a-f])", "\u00a7r\u00a7$1");
legacy = legacy.replaceAll("\u00a7r\u00a7r", "\u00a7r");
return legacy;
} catch (Exception e) {
GeyserConnector.getInstance().getLogger().debug(GSON_SERIALIZER.serialize(message));
GeyserConnector.getInstance().getLogger().error("Failed to parse message", e);
return "";
}
}
public static String convertMessage(String message, String locale) {
Component component = GsonComponentSerializer.gson().deserialize(message);
// Get a Locale from the given locale string
Locale localeCode = Locale.forLanguageTag(locale.replace('_', '-'));
component = RENDERER.render(component, localeCode);
String legacy = LegacyComponentSerializer.legacySection().serialize(component);
// Strip strikethrough and underline as they are not supported on bedrock
legacy = legacy.replaceAll("\u00a7[mn]", "");
// Make color codes reset formatting like Java
// See https://minecraft.gamepedia.com/Formatting_codes#Usage
legacy = legacy.replaceAll("\u00a7([0-9a-f])", "\u00a7r\u00a7$1");
legacy = legacy.replaceAll("\u00a7r\u00a7r", "\u00a7r");
return legacy;
return convertMessage(GSON_SERIALIZER.deserialize(message), locale);
}
public static String convertMessage(String message) {
return convertMessage(message, LanguageUtils.getDefaultLocale());
}
public static String convertMessage(Component message) {
return convertMessage(message, LanguageUtils.getDefaultLocale());
}
/**
* Verifies the message is valid JSON in case it's plaintext. Works around GsonComponentSeraializer not using lenient mode.
* See https://wiki.vg/Chat for messages sent in lenient mode, and for a description on leniency.
@ -108,14 +116,18 @@ public class MessageTranslator {
* @return Bedrock formatted message
*/
public static String convertMessageLenient(String message, String locale) {
if (isMessage(message)) {
if (message.trim().isEmpty()) {
return message;
}
try {
return convertMessage(message, locale);
} else {
} catch (Exception ignored) {
String convertedMessage = convertMessage(convertToJavaMessage(message), locale);
// We have to do this since Adventure strips the starting reset character
if (message.startsWith(getColor(ChatColor.RESET)) && !convertedMessage.startsWith(getColor(ChatColor.RESET))) {
convertedMessage = getColor(ChatColor.RESET) + convertedMessage;
if (message.startsWith(RESET) && !convertedMessage.startsWith(RESET)) {
convertedMessage = RESET + convertedMessage;
}
return convertedMessage;
@ -134,138 +146,100 @@ public class MessageTranslator {
*/
public static String convertToJavaMessage(String message) {
Component component = LegacyComponentSerializer.legacySection().deserialize(message);
return GsonComponentSerializer.gson().serialize(component);
return GSON_SERIALIZER.serialize(component);
}
/**
* Checks if the given text string is a JSON message
* Convert a {@link NamedTextColor} into a string for inserting into messages
*
* @param text String to test
* @return True if its a valid message JSON string, false if not
*/
public static boolean isMessage(String text) {
if (text.trim().isEmpty()) {
return false;
}
try {
GsonComponentSerializer.gson().deserialize(text);
} catch (Exception ex) {
return false;
}
return true;
}
/**
* Convert a {@link ChatColor} into a string for inserting into messages
*
* @param color {@link ChatColor} to convert
* @param color {@link NamedTextColor} to convert
* @return The converted color string
*/
private static String getColor(String color) {
String base = "\u00a7";
switch (color) {
case ChatColor.BLACK:
base += "0";
break;
case ChatColor.DARK_BLUE:
base += "1";
break;
case ChatColor.DARK_GREEN:
base += "2";
break;
case ChatColor.DARK_AQUA:
base += "3";
break;
case ChatColor.DARK_RED:
base += "4";
break;
case ChatColor.DARK_PURPLE:
base += "5";
break;
case ChatColor.GOLD:
base += "6";
break;
case ChatColor.GRAY:
base += "7";
break;
case ChatColor.DARK_GRAY:
base += "8";
break;
case ChatColor.BLUE:
base += "9";
break;
case ChatColor.GREEN:
base += "a";
break;
case ChatColor.AQUA:
base += "b";
break;
case ChatColor.RED:
base += "c";
break;
case ChatColor.LIGHT_PURPLE:
base += "d";
break;
case ChatColor.YELLOW:
base += "e";
break;
case ChatColor.WHITE:
base += "f";
break;
case ChatColor.RESET:
base += "r";
break;
default:
return "";
private static String getColor(NamedTextColor color) {
StringBuilder str = new StringBuilder(BASE);
if (color.equals(NamedTextColor.BLACK)) {
str.append("0");
} else if (color.equals(NamedTextColor.DARK_BLUE)) {
str.append("1");
} else if (color.equals(NamedTextColor.DARK_GREEN)) {
str.append("2");
} else if (color.equals(NamedTextColor.DARK_AQUA)) {
str.append("3");
} else if (color.equals(NamedTextColor.DARK_RED)) {
str.append("4");
} else if (color.equals(NamedTextColor.DARK_PURPLE)) {
str.append("5");
} else if (color.equals(NamedTextColor.GOLD)) {
str.append("6");
} else if (color.equals(NamedTextColor.GRAY)) {
str.append("7");
} else if (color.equals(NamedTextColor.DARK_GRAY)) {
str.append("8");
} else if (color.equals(NamedTextColor.BLUE)) {
str.append("9");
} else if (color.equals(NamedTextColor.GREEN)) {
str.append("a");
} else if (color.equals(NamedTextColor.AQUA)) {
str.append("b");
} else if (color.equals(NamedTextColor.RED)) {
str.append("c");
} else if (color.equals(NamedTextColor.LIGHT_PURPLE)) {
str.append("d");
} else if (color.equals(NamedTextColor.YELLOW)) {
str.append("e");
} else if (color.equals(NamedTextColor.WHITE)) {
str.append("f");
} else {
return "";
}
return base;
return str.toString();
}
/**
* Convert a {@link ChatFormat} into a string for inserting into messages
* Convert a {@link TextDecoration} into a string for inserting into messages
*
* @param format {@link ChatFormat} to convert
* @param format {@link TextDecoration} to convert
* @return The converted chat formatting string
*/
private static String getFormat(ChatFormat format) {
StringBuilder str = new StringBuilder();
String base = "\u00a7";
private static String getFormat(TextDecoration format) {
StringBuilder str = new StringBuilder(BASE);
switch (format) {
case OBFUSCATED:
base += "k";
str.append("k");
break;
case BOLD:
base += "l";
str.append("l");
break;
case STRIKETHROUGH:
base += "m";
str.append("m");
break;
case UNDERLINED:
base += "n";
str.append("n");
break;
case ITALIC:
base += "o";
str.append("o");
break;
default:
return "";
}
str.append(base);
return str.toString();
}
/**
* Convert a team color to a chat color
*
* @param teamColor
* @param teamColor Color or format to convert
* @return The chat color character
*/
public static String toChatColor(TeamColor teamColor) {
return TEAM_COLORS.getOrDefault(teamColor, "");
NamedTextColor textColor = NamedTextColor.NAMES.value(teamColor.name().toLowerCase());
if (textColor != null) {
return getColor(textColor);
}
return getFormat(TEAM_FORMATS.get(teamColor));
}
/**

View File

@ -57,7 +57,7 @@ public class JavaChatTranslator extends PacketTranslator<ServerChatPacket> {
}
textPacket.setNeedsTranslation(false);
textPacket.setMessage(MessageTranslator.convertMessage(packet.getMessage().toString(), session.getLocale()));
textPacket.setMessage(MessageTranslator.convertMessage(packet.getMessage(), session.getLocale()));
session.sendUpstreamPacket(textPacket);
}

View File

@ -36,6 +36,6 @@ public class JavaDisconnectPacket extends PacketTranslator<ServerDisconnectPacke
@Override
public void translate(ServerDisconnectPacket packet, GeyserSession session) {
session.disconnect(MessageTranslator.convertMessage(packet.getReason().toString(), session.getLocale()));
session.disconnect(MessageTranslator.convertMessage(packet.getReason(), session.getLocale()));
}
}

View File

@ -37,6 +37,6 @@ public class JavaLoginDisconnectTranslator extends PacketTranslator<LoginDisconn
@Override
public void translate(LoginDisconnectPacket packet, GeyserSession session) {
// The client doesn't manually get disconnected so we have to do it ourselves
session.disconnect(MessageTranslator.convertMessage(packet.getReason().toString(), session.getLocale()));
session.disconnect(MessageTranslator.convertMessage(packet.getReason(), session.getLocale()));
}
}

View File

@ -45,7 +45,7 @@ public class JavaTitleTranslator extends PacketTranslator<ServerTitlePacket> {
if (packet.getTitle() == null) {
text = " ";
} else {
text = MessageTranslator.convertMessage(packet.getTitle().toString(), locale);
text = MessageTranslator.convertMessage(packet.getTitle(), locale);
}
switch (packet.getAction()) {

View File

@ -54,7 +54,7 @@ public class JavaScoreboardObjectiveTranslator extends PacketTranslator<ServerSc
switch (packet.getAction()) {
case ADD:
case UPDATE:
objective.setDisplayName(MessageTranslator.convertMessage(packet.getDisplayName().toString()))
objective.setDisplayName(MessageTranslator.convertMessage(packet.getDisplayName()))
.setType(packet.getType().ordinal());
break;
case REMOVE:

View File

@ -59,11 +59,11 @@ public class JavaTeamTranslator extends PacketTranslator<ServerTeamPacket> {
switch (packet.getAction()) {
case CREATE:
scoreboard.registerNewTeam(packet.getTeamName(), toPlayerSet(packet.getPlayers()))
.setName(MessageTranslator.convertMessage(packet.getDisplayName().toString()))
.setName(MessageTranslator.convertMessage(packet.getDisplayName()))
.setColor(packet.getColor())
.setNameTagVisibility(packet.getNameTagVisibility())
.setPrefix(MessageTranslator.convertMessage(packet.getPrefix().toString(), session.getLocale()))
.setSuffix(MessageTranslator.convertMessage(packet.getSuffix().toString(), session.getLocale()));
.setPrefix(MessageTranslator.convertMessage(packet.getPrefix(), session.getLocale()))
.setSuffix(MessageTranslator.convertMessage(packet.getSuffix(), session.getLocale()));
break;
case UPDATE:
if (team == null) {
@ -74,11 +74,11 @@ public class JavaTeamTranslator extends PacketTranslator<ServerTeamPacket> {
return;
}
team.setName(MessageTranslator.convertMessage(packet.getDisplayName().toString()))
team.setName(MessageTranslator.convertMessage(packet.getDisplayName()))
.setColor(packet.getColor())
.setNameTagVisibility(packet.getNameTagVisibility())
.setPrefix(MessageTranslator.convertMessage(packet.getPrefix().toString(), session.getLocale()))
.setSuffix(MessageTranslator.convertMessage(packet.getSuffix().toString(), session.getLocale()))
.setPrefix(MessageTranslator.convertMessage(packet.getPrefix(), session.getLocale()))
.setSuffix(MessageTranslator.convertMessage(packet.getSuffix(), session.getLocale()))
.setUpdateType(UpdateType.UPDATE);
break;
case ADD_PLAYER: