diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/ItemStackTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/ItemStackTranslator.java index 356dcf982..423ffd390 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/ItemStackTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/ItemStackTranslator.java @@ -126,7 +126,7 @@ public abstract class ItemStackTranslator { if (tag instanceof StringTag) { StringTag stringTag = (StringTag) tag; - return new com.nukkitx.nbt.tag.StringTag(stringTag.getName(), MessageUtils.getBedrockMessage(Message.fromString(stringTag.getValue()))); + return new com.nukkitx.nbt.tag.StringTag(stringTag.getName(), stringTag.getValue()); } if (tag instanceof ListTag) { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java index 5e0361c06..f59b82ba0 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java @@ -45,8 +45,8 @@ public class ItemTranslator { private Int2ObjectMap itemTranslators = new Int2ObjectOpenHashMap(); private List nbtItemTranslators; private Map javaIdentifierMap = new HashMap<>(); - - // Shield ID, used in Entity.java + + // Shield ID, used in Entity.java public static final int SHIELD = 829; public void init() { @@ -91,7 +91,6 @@ public class ItemTranslator { ItemEntry javaItem = getItem(data); ItemStack itemStack; - ItemStackTranslator itemStackTranslator = itemTranslators.get(javaItem.getJavaId()); if (itemStackTranslator != null) { itemStack = itemStackTranslator.translateToJava(data, javaItem); @@ -116,19 +115,21 @@ public class ItemTranslator { ItemEntry bedrockItem = getItem(stack); - if (stack != null && stack.getNbt() != null) { + ItemStack itemStack = new ItemStack(stack.getId(), stack.getAmount(), stack.getNbt() != null ? stack.getNbt().clone() : null); + + if (itemStack.getNbt() != null) { for (NbtItemStackTranslator translator : nbtItemTranslators) { if (translator.acceptItem(bedrockItem)) { - translator.translateToBedrock(stack.getNbt(), bedrockItem); + translator.translateToBedrock(itemStack.getNbt(), bedrockItem); } } } ItemStackTranslator itemStackTranslator = itemTranslators.get(bedrockItem.getJavaId()); if (itemStackTranslator != null) { - return itemStackTranslator.translateToBedrock(stack, bedrockItem); + return itemStackTranslator.translateToBedrock(itemStack, bedrockItem); } else { - return DEFAULT_TRANSLATOR.translateToBedrock(stack, bedrockItem); + return DEFAULT_TRANSLATOR.translateToBedrock(itemStack, bedrockItem); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BasicItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BasicItemTranslator.java new file mode 100644 index 000000000..9458ec4f1 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BasicItemTranslator.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.item.translators.nbt; + +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.ListTag; +import com.github.steveice10.opennbt.tag.builtin.StringTag; +import com.github.steveice10.opennbt.tag.builtin.Tag; +import net.kyori.text.Component; +import net.kyori.text.TextComponent; +import net.kyori.text.serializer.gson.GsonComponentSerializer; +import net.kyori.text.serializer.legacy.LegacyComponentSerializer; +import org.geysermc.connector.network.translators.ItemRemapper; +import org.geysermc.connector.network.translators.NbtItemStackTranslator; +import org.geysermc.connector.network.translators.item.ItemEntry; +import org.geysermc.connector.utils.MessageUtils; + +import java.util.ArrayList; +import java.util.List; + +@ItemRemapper(priority = -1) +public class BasicItemTranslator extends NbtItemStackTranslator { + + @Override + public void translateToBedrock(CompoundTag itemTag, ItemEntry itemEntry) { + if (itemTag.contains("display")) { + CompoundTag displayTag = itemTag.get("display"); + if (displayTag.contains("Name")) { + StringTag nameTag = displayTag.get("Name"); + try { + displayTag.put(new StringTag("Name", toBedrockMessage(nameTag))); + } catch (Exception ex) { + } + } + + if (displayTag.contains("Lore")) { + ListTag loreTag = displayTag.get("Lore"); + List lore = new ArrayList<>(); + for (Tag tag : loreTag.getValue()) { + if (!(tag instanceof StringTag)) return; + try { + lore.add(new StringTag("", toBedrockMessage((StringTag) tag))); + } catch (Exception ex) { + } + } + displayTag.put(new ListTag("Lore", lore)); + } + } + } + + @Override + public void translateToJava(CompoundTag itemTag, ItemEntry itemEntry) { + if (itemTag.contains("display")) { + CompoundTag displayTag = itemTag.get("display"); + if (displayTag.contains("Name")) { + StringTag nameTag = displayTag.get("Name"); + displayTag.put(new StringTag("Name", toJavaMessage(nameTag))); + } + + if (displayTag.contains("Lore")) { + ListTag loreTag = displayTag.get("Lore"); + List lore = new ArrayList<>(); + for (Tag tag : loreTag.getValue()) { + if (!(tag instanceof StringTag)) return; + lore.add(new StringTag("", "§r" + toJavaMessage((StringTag) tag))); + } + displayTag.put(new ListTag("Lore", lore)); + } + } + } + + private String toJavaMessage(StringTag tag) { + String message = tag.getValue(); + if (message == null) return null; + if (message.startsWith("§r")) { + message = message.replaceFirst("§r", ""); + } + Component component = TextComponent.of(message); + return GsonComponentSerializer.INSTANCE.serialize(component); + } + + private String toBedrockMessage(StringTag tag) { + String message = tag.getValue(); + if (message == null) return null; + TextComponent component = (TextComponent) MessageUtils.phraseJavaMessage(message); + String legacy = LegacyComponentSerializer.legacy().serialize(component); + if (hasFormatting(LegacyComponentSerializer.legacy().deserialize(legacy))) { + return "§r" + legacy; + } + return legacy; + } + + private boolean hasFormatting(Component component) { + if (component.hasStyling()) return true; + for (Component child : component.children()) { + if (hasFormatting(child)) { + return true; + } + } + return false; + } +} diff --git a/connector/src/main/java/org/geysermc/connector/utils/MessageUtils.java b/connector/src/main/java/org/geysermc/connector/utils/MessageUtils.java index ac111c71e..478e42d1b 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/MessageUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/MessageUtils.java @@ -27,6 +27,7 @@ package org.geysermc.connector.utils; import com.github.steveice10.mc.protocol.data.game.scoreboard.TeamColor; import com.github.steveice10.mc.protocol.data.message.*; +import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; @@ -121,20 +122,22 @@ public class MessageUtils { } public static String getBedrockMessage(Message message) { - Component component; if (isMessage(message.getText())) { - component = GsonComponentSerializer.INSTANCE.deserialize(message.getText()); + return getBedrockMessage(message.getText()); } else { - component = GsonComponentSerializer.INSTANCE.deserialize(message.toJsonString()); + return getBedrockMessage(message.toJsonString()); } - return LegacyComponentSerializer.legacy().serialize(component); } public static String getBedrockMessage(String message) { - Component component = GsonComponentSerializer.INSTANCE.deserialize(message); + Component component = phraseJavaMessage(message); return LegacyComponentSerializer.legacy().serialize(component); } + public static Component phraseJavaMessage(String message) { + return GsonComponentSerializer.INSTANCE.deserialize(message); + } + public static String getJavaMessage(String message) { Component component = LegacyComponentSerializer.legacy().deserialize(message); return GsonComponentSerializer.INSTANCE.serialize(component);