1
0
mirror of https://github.com/GeyserMC/Floodgate.git synced 2025-12-19 14:59:20 +00:00

SkinApplier now only applies a skin if a player doesn't already have one (#330)

* SkinApplier now only applies a skin if a player doesn't already have one

* add `hasSkin` method to SkinApplier and check for exising skins before overwriting

* remove the use of Streams and Optionals

* correct delay in SpigotSkinApplier to use ticks instead of milliseconds

* Minor changes

Co-authored-by: Tim203 <mctim203@gmail.com>
This commit is contained in:
Alex
2022-08-31 10:32:20 -07:00
committed by GitHub
parent 0f152141a2
commit 359484b3be
7 changed files with 100 additions and 10 deletions

View File

@@ -130,7 +130,7 @@ public final class BungeeListener implements Listener {
// To fix the February 2 2022 Mojang authentication changes // To fix the February 2 2022 Mojang authentication changes
if (!config.isSendFloodgateData()) { if (!config.isSendFloodgateData()) {
FloodgatePlayer player = api.getPlayer(event.getPlayer().getUniqueId()); FloodgatePlayer player = api.getPlayer(event.getPlayer().getUniqueId());
if (player != null && !player.isLinked()) { if (player != null && !player.isLinked() && !skinApplier.hasSkin(player)) {
skinApplier.applySkin(player, new SkinData("", "")); skinApplier.applySkin(player, new SkinData("", ""));
} }
} }

View File

@@ -39,6 +39,7 @@ import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.connection.InitialHandler; import net.md_5.bungee.connection.InitialHandler;
import net.md_5.bungee.connection.LoginResult; import net.md_5.bungee.connection.LoginResult;
import net.md_5.bungee.protocol.Property;
import org.geysermc.floodgate.api.logger.FloodgateLogger; import org.geysermc.floodgate.api.logger.FloodgateLogger;
import org.geysermc.floodgate.api.player.FloodgatePlayer; import org.geysermc.floodgate.api.player.FloodgatePlayer;
import org.geysermc.floodgate.skin.SkinApplier; import org.geysermc.floodgate.skin.SkinApplier;
@@ -85,11 +86,8 @@ public final class BungeeSkinApplier implements SkinApplier {
return; return;
} }
InitialHandler handler; InitialHandler handler = getHandler(player);
try { if (handler == null) {
handler = (InitialHandler) player.getPendingConnection();
} catch (Exception exception) {
logger.error("Incompatible Bungeecord fork detected", exception);
return; return;
} }
@@ -114,4 +112,40 @@ public final class BungeeSkinApplier implements SkinApplier {
ReflectionUtils.invoke(loginResult, SET_PROPERTIES_METHOD, propertyArray); ReflectionUtils.invoke(loginResult, SET_PROPERTIES_METHOD, propertyArray);
} }
@Override
public boolean hasSkin(FloodgatePlayer fPlayer) {
ProxiedPlayer player = ProxyServer.getInstance().getPlayer(fPlayer.getCorrectUniqueId());
if (player == null) {
return false;
}
InitialHandler handler = getHandler(player);
if (handler == null) {
return false;
}
LoginResult loginResult = handler.getLoginProfile();
if (loginResult == null) {
return false;
}
for (Property property : loginResult.getProperties()) {
if (property.getName().equals("textures")) {
if (!property.getValue().isEmpty()) {
return true;
}
}
}
return false;
}
private InitialHandler getHandler(ProxiedPlayer player) {
try {
return (InitialHandler) player.getPendingConnection();
} catch (Exception exception) {
logger.error("Incompatible Bungeecord fork detected", exception);
return null;
}
}
} }

View File

@@ -89,7 +89,7 @@ public class SkinChannel implements PluginMessageChannel {
return Result.kick("Got invalid skin data"); return Result.kick("Got invalid skin data");
} }
if (floodgatePlayer.isLinked()) { if (floodgatePlayer.isLinked() || skinApplier.hasSkin(floodgatePlayer)) {
return Result.handled(); return Result.handled();
} }

View File

@@ -28,5 +28,20 @@ package org.geysermc.floodgate.skin;
import org.geysermc.floodgate.api.player.FloodgatePlayer; import org.geysermc.floodgate.api.player.FloodgatePlayer;
public interface SkinApplier { public interface SkinApplier {
/**
* Apply a skin to a {@link FloodgatePlayer player}
*
* @param floodgatePlayer player to apply skin to
* @param skinData data for skin to apply to player
*/
void applySkin(FloodgatePlayer floodgatePlayer, SkinData skinData); void applySkin(FloodgatePlayer floodgatePlayer, SkinData skinData);
/**
* Check if a {@link FloodgatePlayer player} currently
* has a skin applied.
*
* @param floodgatePlayer player to check skin of
* @return if player has a skin
*/
boolean hasSkin(FloodgatePlayer floodgatePlayer);
} }

View File

@@ -114,7 +114,7 @@ final class SkinUploadSocket extends WebSocketClient {
player.getCorrectUsername()); player.getCorrectUsername());
return; return;
} }
if (!player.isLinked()) { if (!player.isLinked() && !applier.hasSkin(player)) {
SkinData skinData = SkinData.from(message.getAsJsonObject("data")); SkinData skinData = SkinData.from(message.getAsJsonObject("data"));
player.addProperty(PropertyKey.SKIN_UPLOADED, skinData); player.addProperty(PropertyKey.SKIN_UPLOADED, skinData);
applier.applySkin(player, skinData); applier.applySkin(player, skinData);

View File

@@ -25,6 +25,7 @@
package org.geysermc.floodgate.pluginmessage; package org.geysermc.floodgate.pluginmessage;
import com.destroystokyo.paper.profile.ProfileProperty;
import com.mojang.authlib.GameProfile; import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property; import com.mojang.authlib.properties.Property;
import com.mojang.authlib.properties.PropertyMap; import com.mojang.authlib.properties.PropertyMap;
@@ -54,6 +55,24 @@ public final class SpigotSkinApplier implements SkinApplier {
applySkin0(floodgatePlayer, skinData, true); applySkin0(floodgatePlayer, skinData, true);
} }
@Override
public boolean hasSkin(FloodgatePlayer floodgatePlayer) {
Player player = Bukkit.getPlayer(floodgatePlayer.getCorrectUniqueId());
if (player == null) {
return false;
}
for (ProfileProperty property : player.getPlayerProfile().getProperties()) {
if (property.getName().equals("textures")) {
if (!property.getValue().isEmpty()) {
return true;
}
}
}
return false;
}
private void applySkin0(FloodgatePlayer floodgatePlayer, SkinData skinData, boolean firstTry) { private void applySkin0(FloodgatePlayer floodgatePlayer, SkinData skinData, boolean firstTry) {
Player player = Bukkit.getPlayer(floodgatePlayer.getCorrectUniqueId()); Player player = Bukkit.getPlayer(floodgatePlayer.getCorrectUniqueId());
@@ -61,8 +80,12 @@ public final class SpigotSkinApplier implements SkinApplier {
if (player == null) { if (player == null) {
if (firstTry) { if (firstTry) {
Bukkit.getScheduler().runTaskLater(plugin, Bukkit.getScheduler().runTaskLater(plugin,
() -> applySkin0(floodgatePlayer, skinData, false), () -> {
10 * 1000); if (hasSkin(floodgatePlayer)) {
applySkin0(floodgatePlayer, skinData, false);
}
},
10 * 20);
} }
return; return;
} }

View File

@@ -25,10 +25,12 @@
package org.geysermc.floodgate.util; package org.geysermc.floodgate.util;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ProxyServer; import com.velocitypowered.api.proxy.ProxyServer;
import com.velocitypowered.api.util.GameProfile.Property; import com.velocitypowered.api.util.GameProfile.Property;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Optional;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.geysermc.floodgate.api.player.FloodgatePlayer; import org.geysermc.floodgate.api.player.FloodgatePlayer;
import org.geysermc.floodgate.skin.SkinApplier; import org.geysermc.floodgate.skin.SkinApplier;
@@ -46,4 +48,20 @@ public class VelocitySkinApplier implements SkinApplier {
player.setGameProfileProperties(properties); player.setGameProfileProperties(properties);
}); });
} }
@Override
public boolean hasSkin(FloodgatePlayer floodgatePlayer) {
Optional<Player> player = server.getPlayer(floodgatePlayer.getCorrectUniqueId());
if (player.isPresent()) {
for (Property property : player.get().getGameProfileProperties()) {
if (property.getName().equals("textures")) {
if (!property.getValue().isEmpty()) {
return true;
}
}
}
}
return false;
}
} }