From 82179797ab872896ffd303ac25d9f69e85f31db4 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Wed, 16 Dec 2020 12:50:16 -0500 Subject: [PATCH 1/5] Add proper ominous banner translation (#1692) The ominous banner is a separate banner type in Bedrock. If we detect the ominous banner pattern, then we set the ominous banner type in NBT. This process is also checked vice-versa, allowing the ominous banner to be pulled from the Bedrock creative menu. --- .../item/translators/BannerTranslator.java | 50 +++++++++++++++++-- .../entity/BannerBlockEntityTranslator.java | 8 ++- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/BannerTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/BannerTranslator.java index 14b934362..5e5bc3542 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/BannerTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/BannerTranslator.java @@ -45,8 +45,39 @@ import java.util.stream.Collectors; @ItemRemapper public class BannerTranslator extends ItemTranslator { + /** + * Holds what a Java ominous banner pattern looks like. + * + * Translating the patterns over to Bedrock does not work effectively, but Bedrock has a dedicated type for + * ominous banners that we set instead. This variable is used to detect Java ominous banner patterns, and apply + * the correct ominous banner pattern if Bedrock pulls the item from creative. + */ + public static final ListTag OMINOUS_BANNER_PATTERN; + private final List appliedItems; + static { + OMINOUS_BANNER_PATTERN = new ListTag("Patterns"); + // Construct what an ominous banner is supposed to look like + OMINOUS_BANNER_PATTERN.add(getPatternTag("mr", 9)); + OMINOUS_BANNER_PATTERN.add(getPatternTag("bs", 8)); + OMINOUS_BANNER_PATTERN.add(getPatternTag("cs", 7)); + OMINOUS_BANNER_PATTERN.add(getPatternTag("bo", 8)); + OMINOUS_BANNER_PATTERN.add(getPatternTag("ms", 15)); + OMINOUS_BANNER_PATTERN.add(getPatternTag("hh", 8)); + OMINOUS_BANNER_PATTERN.add(getPatternTag("mc", 8)); + OMINOUS_BANNER_PATTERN.add(getPatternTag("bo", 15)); + } + + private static CompoundTag getPatternTag(String pattern, int color) { + StringTag patternType = new StringTag("Pattern", pattern); + IntTag colorTag = new IntTag("Color", color); + CompoundTag tag = new CompoundTag(""); + tag.put(patternType); + tag.put(colorTag); + return tag; + } + public BannerTranslator() { appliedItems = ItemRegistry.ITEM_ENTRIES.values() .stream() @@ -62,7 +93,7 @@ public class BannerTranslator extends ItemTranslator { */ public static NbtList convertBannerPattern(ListTag patterns) { List tagsList = new ArrayList<>(); - for (com.github.steveice10.opennbt.tag.builtin.Tag patternTag : patterns.getValue()) { + for (Tag patternTag : patterns.getValue()) { NbtMap newPatternTag = getBedrockBannerPattern((CompoundTag) patternTag); if (newPatternTag != null) { tagsList.add(newPatternTag); @@ -134,7 +165,13 @@ public class BannerTranslator extends ItemTranslator { ListTag patterns = blockEntityTag.get("Patterns"); NbtMapBuilder builder = itemData.getTag().toBuilder(); - builder.put("Patterns", convertBannerPattern(patterns)); + if (patterns.equals(OMINOUS_BANNER_PATTERN)) { + // Remove the current patterns and set the ominous banner type + builder.remove("Patterns"); + builder.putInt("Type", 1); + } else { + builder.put("Patterns", convertBannerPattern(patterns)); + } itemData = ItemData.of(itemData.getId(), itemData.getDamage(), itemData.getCount(), builder.build()); } @@ -151,7 +188,14 @@ public class BannerTranslator extends ItemTranslator { ItemStack itemStack = super.translateToJava(itemData, itemEntry); NbtMap nbtTag = itemData.getTag(); - if (nbtTag.containsKey("Patterns", NbtType.COMPOUND)) { + if (nbtTag.containsKey("Type", NbtType.INT) && nbtTag.getInt("Type") == 1) { + // Ominous banner pattern + itemStack.getNbt().remove("Type"); + CompoundTag blockEntityTag = new CompoundTag("BlockEntityTag"); + blockEntityTag.put(OMINOUS_BANNER_PATTERN); + + itemStack.getNbt().put(blockEntityTag); + } else if (nbtTag.containsKey("Patterns", NbtType.COMPOUND)) { List patterns = nbtTag.getList("Patterns", NbtType.COMPOUND); CompoundTag blockEntityTag = new CompoundTag("BlockEntityTag"); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BannerBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BannerBlockEntityTranslator.java index f5e1d5948..b59794796 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BannerBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BannerBlockEntityTranslator.java @@ -47,7 +47,13 @@ public class BannerBlockEntityTranslator extends BlockEntityTranslator implement if (tag.contains("Patterns")) { ListTag patterns = tag.get("Patterns"); - builder.put("Patterns", BannerTranslator.convertBannerPattern(patterns)); + if (patterns.equals(BannerTranslator.OMINOUS_BANNER_PATTERN)) { + // This is an ominous banner; don't try to translate the raw patterns (it doesn't translate correctly) + // and tell the Bedrock client that this is an ominous banner + builder.putInt("Type", 1); + } else { + builder.put("Patterns", BannerTranslator.convertBannerPattern(patterns)); + } } if (tag.contains("CustomName")) { From 02d99380d3b2af566d8a509ac1798dd3d8ca0bd1 Mon Sep 17 00:00:00 2001 From: Kooldude183 <33386263+Kooldude183@users.noreply.github.com> Date: Thu, 17 Dec 2020 08:58:25 -0800 Subject: [PATCH 2/5] Add info about clickable links in "What can't be fixed" (#1687) * Add info about clickable links in "What can't be fixed" * Add "Glowing effect" --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 2033a66ed..4f6a6d434 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,8 @@ Take a look [here](https://github.com/GeyserMC/Geyser/wiki#Setup) for how to set The following things can't be fixed because of Bedrock limitations. They might be fixable in the future, but not as of now. - Custom heads in inventories +- Clickable links in chat +- Glowing effect ## Compiling 1. Clone the repo to your computer From 9f6182f8df9dbf9d162cf05316221770699cfede Mon Sep 17 00:00:00 2001 From: qlow <20094418+qlow@users.noreply.github.com> Date: Thu, 17 Dec 2020 17:58:49 +0100 Subject: [PATCH 3/5] Added a simple way to get a player by their xuid (#1642) * Added IGeyserPingPassthrough#getPingInformation(InetSocketAddress) to make logging of the pinging IPs possible * Added GeyserConnector#getPlayerByXboxUuid * Added GeyserConnector#getPlayerByUuid and added some javadocs * Update connector/src/main/java/org/geysermc/connector/GeyserConnector.java Co-authored-by: rtm516 * Update connector/src/main/java/org/geysermc/connector/GeyserConnector.java Co-authored-by: rtm516 * Update GeyserConnector.java * Update SkinManager.java * Update SkinProvider.java * Renamed getPlayerByXboxUuid to getPlayerByXuid Co-authored-by: qlow Co-authored-by: rtm516 --- .../geysermc/connector/GeyserConnector.java | 39 ++++++++++++++++--- .../geysermc/connector/skin/SkinManager.java | 18 ++++----- .../geysermc/connector/skin/SkinProvider.java | 10 ++--- 3 files changed, 46 insertions(+), 21 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java index 1bfa700fb..05040a86f 100644 --- a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java +++ b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java @@ -44,6 +44,7 @@ import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.BiomeTranslator; import org.geysermc.connector.network.translators.EntityIdentifierRegistry; import org.geysermc.connector.network.translators.PacketTranslatorRegistry; +import org.geysermc.connector.network.translators.collision.CollisionTranslator; import org.geysermc.connector.network.translators.effect.EffectRegistry; import org.geysermc.connector.network.translators.item.ItemRegistry; import org.geysermc.connector.network.translators.item.ItemTranslator; @@ -54,7 +55,6 @@ import org.geysermc.connector.network.translators.sound.SoundRegistry; import org.geysermc.connector.network.translators.world.WorldManager; import org.geysermc.connector.network.translators.world.block.BlockTranslator; import org.geysermc.connector.network.translators.world.block.entity.BlockEntityTranslator; -import org.geysermc.connector.network.translators.collision.CollisionTranslator; import org.geysermc.connector.network.translators.world.block.entity.SkullBlockEntityTranslator; import org.geysermc.connector.utils.DimensionUtils; import org.geysermc.connector.utils.LanguageUtils; @@ -67,10 +67,7 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -326,6 +323,38 @@ public class GeyserConnector { players.remove(player); } + /** + * Gets a player by their current UUID + * + * @param uuid the uuid + * @return the player or null if there is no player online with this UUID + */ + public GeyserSession getPlayerByUuid(UUID uuid) { + for (GeyserSession session : players) { + if (session.getPlayerEntity().getUuid().equals(uuid)) { + return session; + } + } + + return null; + } + + /** + * Gets a player by their Xbox user identifier + * + * @param xboxUuid the Xbox user identifier + * @return the player or null if there is no player online with this xuid + */ + public GeyserSession getPlayerByXuid(String xuid) { + for (GeyserSession session : players) { + if (session.getAuthData() != null && session.getAuthData().getXboxUUID().equals(xuid)) { + return session; + } + } + + return null; + } + public static GeyserConnector start(PlatformType platformType, GeyserBootstrap bootstrap) { return new GeyserConnector(platformType, bootstrap); } diff --git a/connector/src/main/java/org/geysermc/connector/skin/SkinManager.java b/connector/src/main/java/org/geysermc/connector/skin/SkinManager.java index db8f25929..a08f567a3 100644 --- a/connector/src/main/java/org/geysermc/connector/skin/SkinManager.java +++ b/connector/src/main/java/org/geysermc/connector/skin/SkinManager.java @@ -81,11 +81,10 @@ public class SkinManager { // This attempts to find the xuid of the player so profile images show up for xbox accounts String xuid = ""; - for (GeyserSession player : GeyserConnector.getInstance().getPlayers()) { - if (player.getPlayerEntity().getUuid().equals(uuid)) { - xuid = player.getAuthData().getXboxUUID(); - break; - } + GeyserSession player = GeyserConnector.getInstance().getPlayerByUuid(uuid); + + if (player != null) { + xuid = player.getAuthData().getXboxUUID(); } PlayerListPacket.Entry entry; @@ -268,11 +267,10 @@ public class SkinManager { // return default skin with default cape when texture data is invalid String skinUrl = isAlex ? SkinProvider.EMPTY_SKIN_ALEX.getTextureUrl() : SkinProvider.EMPTY_SKIN.getTextureUrl(); if ("steve".equals(skinUrl) || "alex".equals(skinUrl)) { - for (GeyserSession session : GeyserConnector.getInstance().getPlayers()) { - if (session.getPlayerEntity().getUuid().equals(profile.getId())) { - skinUrl = session.getClientData().getSkinId(); - break; - } + GeyserSession session = GeyserConnector.getInstance().getPlayerByUuid(profile.getId()); + + if (session != null) { + skinUrl = session.getClientData().getSkinId(); } } return new GameProfileData(skinUrl, SkinProvider.EMPTY_CAPE.getTextureUrl(), isAlex); diff --git a/connector/src/main/java/org/geysermc/connector/skin/SkinProvider.java b/connector/src/main/java/org/geysermc/connector/skin/SkinProvider.java index 117198685..948e4b374 100644 --- a/connector/src/main/java/org/geysermc/connector/skin/SkinProvider.java +++ b/connector/src/main/java/org/geysermc/connector/skin/SkinProvider.java @@ -144,12 +144,10 @@ public class SkinProvider { String newSkinUrl = skinUrl; if ("steve".equals(skinUrl) || "alex".equals(skinUrl)) { - // TODO: Don't have a for loop for this? Have a proper map? - for (GeyserSession session : GeyserConnector.getInstance().getPlayers()) { - if (session.getPlayerEntity().getUuid().equals(playerId)) { - newSkinUrl = session.getClientData().getSkinId(); - break; - } + GeyserSession session = GeyserConnector.getInstance().getPlayerByUuid(playerId); + + if (session != null) { + newSkinUrl = session.getClientData().getSkinId(); } } From ce9cd92b2e1790e7d9dfd1f67791847d35886608 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Thu, 17 Dec 2020 17:25:38 +0000 Subject: [PATCH 4/5] Update GeyserConnector.java to fix JavaDoc (#1701) --- .../src/main/java/org/geysermc/connector/GeyserConnector.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java index 05040a86f..5b447b266 100644 --- a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java +++ b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java @@ -342,7 +342,7 @@ public class GeyserConnector { /** * Gets a player by their Xbox user identifier * - * @param xboxUuid the Xbox user identifier + * @param xuid the Xbox user identifier * @return the player or null if there is no player online with this xuid */ public GeyserSession getPlayerByXuid(String xuid) { From c92150013f01a99ff36470eb67a7aa86d0ddb243 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Thu, 17 Dec 2020 14:10:58 -0500 Subject: [PATCH 5/5] Allow /help to work even if command suggestions are disabled (#1703) * Allow /help to work even if command suggestions are disabled This sends a minimal available commands packet to permit /help sending to the server. * Fix whitespace * Just send an empty packet * Change variable name --- .../bedrock/BedrockTextTranslator.java | 2 +- .../java/JavaDeclareCommandsTranslator.java | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockTextTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockTextTranslator.java index e4a765694..955a9a539 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockTextTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockTextTranslator.java @@ -38,7 +38,7 @@ public class BedrockTextTranslator extends PacketTranslator { @Override public void translate(TextPacket packet, GeyserSession session) { - String message = packet.getMessage().replaceAll("^\\.", "/").trim(); + String message = packet.getMessage(); if (MessageTranslator.isTooLong(message, session)) { return; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareCommandsTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareCommandsTranslator.java index 8f5243366..2247b55be 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareCommandsTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareCommandsTranslator.java @@ -52,9 +52,14 @@ public class JavaDeclareCommandsTranslator extends PacketTranslator commandData = new ArrayList<>(); Int2ObjectMap commands = new Int2ObjectOpenHashMap<>(); Int2ObjectMap> commandArgs = new Int2ObjectOpenHashMap<>(); @@ -83,14 +88,14 @@ public class JavaDeclareCommandsTranslator extends PacketTranslator flags = new ArrayList<>(); + List flags = Collections.emptyList(); // Loop through all the found commands for (int commandID : commands.keySet()) { String commandName = commands.get(commandID); // Create a basic alias - CommandEnumData aliases = new CommandEnumData( commandName + "Aliases", new String[] { commandName.toLowerCase() }, false); + CommandEnumData aliases = new CommandEnumData(commandName + "Aliases", new String[] { commandName.toLowerCase() }, false); // Get and parse all params CommandParamData[][] params = getParams(packet.getNodes()[commandID], packet.getNodes()); @@ -102,9 +107,7 @@ public class JavaDeclareCommandsTranslator extends PacketTranslator