From 0216b6d79821ef861445ff8cc7cdc0431d3e80f1 Mon Sep 17 00:00:00 2001 From: Tim203 Date: Mon, 5 Jul 2021 15:34:40 +0200 Subject: [PATCH] Fixed a bug where linked accounts would get their Bedrock skin --- .../floodgate/api/player/FloodgatePlayer.java | 5 ++ .../floodgate/api/player/PropertyKey.java | 2 +- .../pluginmessage/BungeeSkinApplier.java | 10 ++-- .../floodgate/player/FloodgatePlayerImpl.java | 5 ++ .../pluginmessage/channel/SkinChannel.java | 11 ++++- .../geysermc/floodgate/skin/SkinApplier.java | 3 +- .../org/geysermc/floodgate/skin/SkinData.java | 47 +++++++++++++++++++ .../floodgate/skin/SkinUploadSocket.java | 7 ++- .../pluginmessage/SpigotSkinApplier.java | 15 +++--- .../floodgate/util/VelocitySkinApplier.java | 10 ++-- 10 files changed, 86 insertions(+), 29 deletions(-) create mode 100644 common/src/main/java/org/geysermc/floodgate/skin/SkinData.java diff --git a/api/src/main/java/org/geysermc/floodgate/api/player/FloodgatePlayer.java b/api/src/main/java/org/geysermc/floodgate/api/player/FloodgatePlayer.java index 75bc5a21..07290cff 100644 --- a/api/src/main/java/org/geysermc/floodgate/api/player/FloodgatePlayer.java +++ b/api/src/main/java/org/geysermc/floodgate/api/player/FloodgatePlayer.java @@ -106,6 +106,11 @@ public interface FloodgatePlayer { */ LinkedPlayer getLinkedPlayer(); + /** + * Returns true if the player is linked to a Java account + */ + boolean isLinked(); + default boolean sendForm(Form form) { return FloodgateApi.getInstance().sendForm(getCorrectUniqueId(), form); } diff --git a/api/src/main/java/org/geysermc/floodgate/api/player/PropertyKey.java b/api/src/main/java/org/geysermc/floodgate/api/player/PropertyKey.java index ae25b75d..64f03a34 100644 --- a/api/src/main/java/org/geysermc/floodgate/api/player/PropertyKey.java +++ b/api/src/main/java/org/geysermc/floodgate/api/player/PropertyKey.java @@ -36,7 +36,7 @@ public class PropertyKey { new PropertyKey("socket_address", false, false); /** - * Skin Uploaded returns a JsonObject containing the value and signature of the Skin + * Skin Uploaded returns a SkinData object containing the value and signature of the Skin */ public static final PropertyKey SKIN_UPLOADED = new PropertyKey("skin_uploaded", false, false); diff --git a/bungee/src/main/java/org/geysermc/floodgate/pluginmessage/BungeeSkinApplier.java b/bungee/src/main/java/org/geysermc/floodgate/pluginmessage/BungeeSkinApplier.java index dc6cc58d..8629cf22 100644 --- a/bungee/src/main/java/org/geysermc/floodgate/pluginmessage/BungeeSkinApplier.java +++ b/bungee/src/main/java/org/geysermc/floodgate/pluginmessage/BungeeSkinApplier.java @@ -25,7 +25,6 @@ package org.geysermc.floodgate.pluginmessage; -import com.google.gson.JsonObject; import lombok.RequiredArgsConstructor; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.connection.ProxiedPlayer; @@ -35,13 +34,14 @@ import net.md_5.bungee.connection.LoginResult.Property; import org.geysermc.floodgate.api.logger.FloodgateLogger; import org.geysermc.floodgate.api.player.FloodgatePlayer; import org.geysermc.floodgate.skin.SkinApplier; +import org.geysermc.floodgate.skin.SkinData; @RequiredArgsConstructor public final class BungeeSkinApplier implements SkinApplier { private final FloodgateLogger logger; @Override - public void applySkin(FloodgatePlayer uuid, JsonObject skinResult) { + public void applySkin(FloodgatePlayer uuid, SkinData skinData) { ProxiedPlayer player = ProxyServer.getInstance().getPlayer(uuid.getCorrectUniqueId()); if (player == null) { return; @@ -63,11 +63,7 @@ public final class BungeeSkinApplier implements SkinApplier { loginResult = new LoginResult(null, null, null); } - Property property = new Property( - "textures", - skinResult.get("value").getAsString(), - skinResult.get("signature").getAsString() - ); + Property property = new Property("textures", skinData.getValue(), skinData.getSignature()); loginResult.setProperties(new Property[]{property}); } diff --git a/common/src/main/java/org/geysermc/floodgate/player/FloodgatePlayerImpl.java b/common/src/main/java/org/geysermc/floodgate/player/FloodgatePlayerImpl.java index 9ad79485..08593093 100644 --- a/common/src/main/java/org/geysermc/floodgate/player/FloodgatePlayerImpl.java +++ b/common/src/main/java/org/geysermc/floodgate/player/FloodgatePlayerImpl.java @@ -107,6 +107,11 @@ public final class FloodgatePlayerImpl implements FloodgatePlayer { return linkedPlayer != null ? linkedPlayer.getJavaUsername() : javaUsername; } + @Override + public boolean isLinked() { + return linkedPlayer != null; + } + public BedrockData toBedrockData() { TimeSyncer timeSyncer = TimeSyncerHolder.get(); diff --git a/common/src/main/java/org/geysermc/floodgate/pluginmessage/channel/SkinChannel.java b/common/src/main/java/org/geysermc/floodgate/pluginmessage/channel/SkinChannel.java index b621ba48..e95827ec 100644 --- a/common/src/main/java/org/geysermc/floodgate/pluginmessage/channel/SkinChannel.java +++ b/common/src/main/java/org/geysermc/floodgate/pluginmessage/channel/SkinChannel.java @@ -36,6 +36,7 @@ import org.geysermc.floodgate.config.FloodgateConfig; import org.geysermc.floodgate.config.ProxyFloodgateConfig; import org.geysermc.floodgate.pluginmessage.PluginMessageChannel; import org.geysermc.floodgate.skin.SkinApplier; +import org.geysermc.floodgate.skin.SkinData; public class SkinChannel implements PluginMessageChannel { @Inject private FloodgateApi api; @@ -91,6 +92,10 @@ public class SkinChannel implements PluginMessageChannel { return Result.kick("Got invalid skin data"); } + if (floodgatePlayer.isLinked()) { + return Result.handled(); + } + String value = split[0]; String signature = split[1]; @@ -98,8 +103,10 @@ public class SkinChannel implements PluginMessageChannel { result.addProperty("value", value); result.addProperty("signature", signature); - floodgatePlayer.addProperty(PropertyKey.SKIN_UPLOADED, result); - skinApplier.applySkin(floodgatePlayer, result); + SkinData skinData = new SkinData(value, signature); + + floodgatePlayer.addProperty(PropertyKey.SKIN_UPLOADED, skinData); + skinApplier.applySkin(floodgatePlayer, skinData); return Result.handled(); } diff --git a/common/src/main/java/org/geysermc/floodgate/skin/SkinApplier.java b/common/src/main/java/org/geysermc/floodgate/skin/SkinApplier.java index a8366675..6e6075bc 100644 --- a/common/src/main/java/org/geysermc/floodgate/skin/SkinApplier.java +++ b/common/src/main/java/org/geysermc/floodgate/skin/SkinApplier.java @@ -25,9 +25,8 @@ package org.geysermc.floodgate.skin; -import com.google.gson.JsonObject; import org.geysermc.floodgate.api.player.FloodgatePlayer; public interface SkinApplier { - void applySkin(FloodgatePlayer floodgatePlayer, JsonObject skinResult); + void applySkin(FloodgatePlayer floodgatePlayer, SkinData skinData); } diff --git a/common/src/main/java/org/geysermc/floodgate/skin/SkinData.java b/common/src/main/java/org/geysermc/floodgate/skin/SkinData.java new file mode 100644 index 00000000..b68c9cad --- /dev/null +++ b/common/src/main/java/org/geysermc/floodgate/skin/SkinData.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2019-2021 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/Floodgate + */ + +package org.geysermc.floodgate.skin; + +import com.google.gson.JsonObject; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public class SkinData { + private final String value; + private final String signature; + + public static SkinData from(JsonObject data) { + if (data.has("signature") && !data.get("signature").isJsonNull()) { + return new SkinData( + data.get("value").getAsString(), + data.get("signature").getAsString() + ); + } + return new SkinData(data.get("value").getAsString(), null); + } +} diff --git a/common/src/main/java/org/geysermc/floodgate/skin/SkinUploadSocket.java b/common/src/main/java/org/geysermc/floodgate/skin/SkinUploadSocket.java index 9035762d..5eb70204 100644 --- a/common/src/main/java/org/geysermc/floodgate/skin/SkinUploadSocket.java +++ b/common/src/main/java/org/geysermc/floodgate/skin/SkinUploadSocket.java @@ -37,6 +37,7 @@ import lombok.Getter; import org.geysermc.floodgate.api.FloodgateApi; import org.geysermc.floodgate.api.logger.FloodgateLogger; import org.geysermc.floodgate.api.player.FloodgatePlayer; +import org.geysermc.floodgate.api.player.PropertyKey; import org.geysermc.floodgate.util.Utils; import org.geysermc.floodgate.util.WebsocketEventType; import org.java_websocket.client.WebSocketClient; @@ -113,7 +114,11 @@ final class SkinUploadSocket extends WebSocketClient { player.getCorrectUsername()); return; } - applier.applySkin(player, message.getAsJsonObject("data")); + if (!player.isLinked()) { + SkinData skinData = SkinData.from(message.getAsJsonObject("data")); + player.addProperty(PropertyKey.SKIN_UPLOADED, skinData); + applier.applySkin(player, skinData); + } } break; case LOG_MESSAGE: diff --git a/spigot/src/main/java/org/geysermc/floodgate/pluginmessage/SpigotSkinApplier.java b/spigot/src/main/java/org/geysermc/floodgate/pluginmessage/SpigotSkinApplier.java index b4cc0bd8..e6f17f70 100644 --- a/spigot/src/main/java/org/geysermc/floodgate/pluginmessage/SpigotSkinApplier.java +++ b/spigot/src/main/java/org/geysermc/floodgate/pluginmessage/SpigotSkinApplier.java @@ -25,7 +25,6 @@ package org.geysermc.floodgate.pluginmessage; -import com.google.gson.JsonObject; import com.mojang.authlib.GameProfile; import com.mojang.authlib.properties.Property; import com.mojang.authlib.properties.PropertyMap; @@ -34,6 +33,7 @@ import org.bukkit.entity.Player; import org.geysermc.floodgate.SpigotPlugin; import org.geysermc.floodgate.api.player.FloodgatePlayer; import org.geysermc.floodgate.skin.SkinApplier; +import org.geysermc.floodgate.skin.SkinData; import org.geysermc.floodgate.util.ClassNames; import org.geysermc.floodgate.util.ReflectionUtils; import org.geysermc.floodgate.util.SpigotVersionSpecificMethods; @@ -50,18 +50,18 @@ public final class SpigotSkinApplier implements SkinApplier { } @Override - public void applySkin(FloodgatePlayer floodgatePlayer, JsonObject skinResult) { - applySkin0(floodgatePlayer, skinResult, true); + public void applySkin(FloodgatePlayer floodgatePlayer, SkinData skinData) { + applySkin0(floodgatePlayer, skinData, true); } - private void applySkin0(FloodgatePlayer floodgatePlayer, JsonObject result, boolean firstTry) { + private void applySkin0(FloodgatePlayer floodgatePlayer, SkinData skinData, boolean firstTry) { Player player = Bukkit.getPlayer(floodgatePlayer.getCorrectUniqueId()); // player is probably not logged in yet if (player == null) { if (firstTry) { Bukkit.getScheduler().runTaskLater(plugin, - () -> applySkin0(floodgatePlayer, result, false), + () -> applySkin0(floodgatePlayer, skinData, false), 10 * 1000); } return; @@ -76,10 +76,7 @@ public final class SpigotSkinApplier implements SkinApplier { PropertyMap properties = profile.getProperties(); properties.removeAll("textures"); - Property property = new Property( - "textures", - result.get("value").getAsString(), - result.get("signature").getAsString()); + Property property = new Property("textures", skinData.getValue(), skinData.getSignature()); properties.put("textures", property); // By running as a task, we don't run into async issues diff --git a/velocity/src/main/java/org/geysermc/floodgate/util/VelocitySkinApplier.java b/velocity/src/main/java/org/geysermc/floodgate/util/VelocitySkinApplier.java index f4a1a25e..0e37b450 100644 --- a/velocity/src/main/java/org/geysermc/floodgate/util/VelocitySkinApplier.java +++ b/velocity/src/main/java/org/geysermc/floodgate/util/VelocitySkinApplier.java @@ -25,7 +25,6 @@ package org.geysermc.floodgate.util; -import com.google.gson.JsonObject; import com.velocitypowered.api.proxy.ProxyServer; import com.velocitypowered.api.util.GameProfile.Property; import java.util.ArrayList; @@ -33,20 +32,17 @@ import java.util.List; import lombok.RequiredArgsConstructor; import org.geysermc.floodgate.api.player.FloodgatePlayer; import org.geysermc.floodgate.skin.SkinApplier; +import org.geysermc.floodgate.skin.SkinData; @RequiredArgsConstructor public class VelocitySkinApplier implements SkinApplier { private final ProxyServer server; @Override - public void applySkin(FloodgatePlayer floodgatePlayer, JsonObject skinResult) { + public void applySkin(FloodgatePlayer floodgatePlayer, SkinData skinData) { server.getPlayer(floodgatePlayer.getCorrectUniqueId()).ifPresent(player -> { List properties = new ArrayList<>(player.getGameProfileProperties()); - properties.add(new Property( - "textures", - skinResult.get("value").getAsString(), - skinResult.get("signature").getAsString() - )); + properties.add(new Property("textures", skinData.getValue(), skinData.getSignature())); player.setGameProfileProperties(properties); }); }