diff --git a/bukkit/pom.xml b/bukkit/pom.xml index 39ca1f92..0151a804 100644 --- a/bukkit/pom.xml +++ b/bukkit/pom.xml @@ -376,8 +376,8 @@ io.netty netty-transport ${nettyVersion} - test - + provided + io.netty diff --git a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/FastLoginBukkit.java b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/FastLoginBukkit.java index b2bc397c..63de673b 100644 --- a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/FastLoginBukkit.java +++ b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/FastLoginBukkit.java @@ -30,7 +30,6 @@ import com.github.games647.fastlogin.bukkit.command.CrackedCommand; import com.github.games647.fastlogin.bukkit.command.PremiumCommand; import com.github.games647.fastlogin.bukkit.listener.ConnectionListener; import com.github.games647.fastlogin.bukkit.listener.PaperCacheListener; -import com.github.games647.fastlogin.bukkit.listener.protocollib.ManualNameChange; import com.github.games647.fastlogin.bukkit.listener.protocollib.ProtocolLibListener; import com.github.games647.fastlogin.bukkit.listener.protocollib.SkinApplyListener; import com.github.games647.fastlogin.bukkit.listener.protocolsupport.ProtocolSupportListener; @@ -119,10 +118,6 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin - * This is used as a workaround, because Floodgate fails to inject - * the prefixes when it's used together with ProtocolLib and FastLogin. - *
- * For more information visit: ... - */ -public class ManualNameChange extends PacketAdapter { - - private final FloodgateService floodgate; - - public ManualNameChange(FastLoginBukkit plugin, FloodgateService floodgate) { - super(params() - .plugin(plugin) - .types(START)); - - this.plugin = plugin; - this.floodgate = floodgate; - } - - public static void register(FastLoginBukkit plugin, FloodgateService floodgate) { - // they will be created with a static builder, because otherwise it will throw a NoClassDefFoundError - ProtocolLibrary.getProtocolManager() - .getAsynchronousManager() - .registerAsyncHandler(new ManualNameChange(plugin, floodgate)) - .start(); - } - - @Override - public void onPacketReceiving(PacketEvent packetEvent) { - PacketContainer packet = packetEvent.getPacket(); - String username = readUsername(packet); - - if (floodgate.getBedrockPlayer(username) == null) { - //not a Floodgate player, no need to add a prefix - return; - } - - packet.setMeta("original_name", username); - String prefixedName = FloodgateApi.getInstance().getPlayerPrefix() + username; - setUsername(packet, prefixedName); - } - - private void setUsername(PacketContainer packet, String name) { - if (packet.getGameProfiles().size() > 0) { - WrappedGameProfile updatedProfile = new WrappedGameProfile(UUID.randomUUID(), name); - packet.getGameProfiles().write(0, updatedProfile); - } else { - packet.getStrings().write(0, name); - } - } - - private String readUsername(PacketContainer packet) { - if (packet.getGameProfiles().size() > 0) { - return packet.getGameProfiles().read(0).getName(); - } else { - return packet.getStrings().read(0); - } - } -} diff --git a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocollib/ProtocolLibListener.java b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocollib/ProtocolLibListener.java index 18322389..bdc64021 100644 --- a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocollib/ProtocolLibListener.java +++ b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocollib/ProtocolLibListener.java @@ -30,6 +30,8 @@ import com.comphenix.protocol.ProtocolLibrary; import com.comphenix.protocol.events.PacketAdapter; import com.comphenix.protocol.events.PacketContainer; import com.comphenix.protocol.events.PacketEvent; +import com.comphenix.protocol.injector.PacketFilterManager; +import com.comphenix.protocol.injector.player.PlayerInjectionHandler; import com.comphenix.protocol.reflect.FuzzyReflection; import com.comphenix.protocol.utility.MinecraftVersion; import com.comphenix.protocol.wrappers.BukkitConverters; @@ -42,6 +44,7 @@ import com.github.games647.fastlogin.core.antibot.AntiBotService; import com.github.games647.fastlogin.core.antibot.AntiBotService.Action; import com.mojang.datafixers.util.Either; +import java.lang.reflect.Field; import java.net.InetSocketAddress; import java.security.InvalidKeyException; import java.security.KeyPair; @@ -58,8 +61,12 @@ import javax.crypto.BadPaddingException; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandler; +import io.netty.util.AttributeKey; import lombok.val; import org.bukkit.entity.Player; +import org.geysermc.floodgate.api.player.FloodgatePlayer; import static com.comphenix.protocol.PacketType.Login.Client.ENCRYPTION_BEGIN; import static com.comphenix.protocol.PacketType.Login.Client.START; @@ -67,6 +74,7 @@ import static com.comphenix.protocol.PacketType.Login.Client.START; public class ProtocolLibListener extends PacketAdapter { private final FastLoginBukkit plugin; + private final PlayerInjectionHandler handler; //just create a new once on plugin enable. This used for verify token generation private final SecureRandom random = new SecureRandom(); @@ -85,6 +93,7 @@ public class ProtocolLibListener extends PacketAdapter { this.plugin = plugin; this.antiBotService = antiBotService; this.verifyClientKeys = verifyClientKeys; + this.handler = getHandler(); } public static void register(FastLoginBukkit plugin, AntiBotService antiBotService, boolean verifyClientKeys) { @@ -109,6 +118,15 @@ public class ProtocolLibListener extends PacketAdapter { Player sender = packetEvent.getPlayer(); PacketType packetType = packetEvent.getPacketType(); if (packetType == START) { + + if (plugin.getFloodgateService() != null) { + boolean success = processFloodgateTasks(packetEvent); + // don't continue execution if the player was kicked by Floodgate + if (!success) { + return; + } + } + PacketContainer packet = packetEvent.getPacket(); InetSocketAddress address = sender.getAddress(); @@ -201,11 +219,6 @@ public class ProtocolLibListener extends PacketAdapter { //remove old data every time on a new login in order to keep the session only for one person plugin.removeSession(player.getAddress()); - if (packetEvent.getPacket().getMeta("original_name").isPresent()) { - //username has been injected by ManualNameChange.java - username = (String) packetEvent.getPacket().getMeta("original_name").get(); - } - PacketContainer packet = packetEvent.getPacket(); val profileKey = packet.getOptionals(BukkitConverters.getWrappedPublicKeyDataConverter()) .optionRead(0); @@ -254,4 +267,65 @@ public class ProtocolLibListener extends PacketAdapter { //player.getName() won't work at this state return profile.getName(); } + + private static PlayerInjectionHandler getHandler() { + try { + PacketFilterManager manager = (PacketFilterManager) ProtocolLibrary.getProtocolManager(); + Field f = manager.getClass().getDeclaredField("playerInjectionHandler"); + f.setAccessible(true); + PlayerInjectionHandler handler = (PlayerInjectionHandler) f.get(manager); + f.setAccessible(false); + return handler; + } catch (NoSuchFieldException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + private FloodgatePlayer getFloodgatePlayer(Player player) { + Channel channel = handler.getChannel(player); + AttributeKey floodgateAttribute = AttributeKey.valueOf("floodgate-player"); + return channel.attr(floodgateAttribute).get(); + } + + /** + * Reimplementation of the tasks injected Floodgate in ProtocolLib that are not run due to a bug + * @see Issue Floodgate#143 + * @see Floodgate/SpigotDataHandler + * @param packetEvent the PacketEvent that won't be processed by Floodgate + * @return false if the player was kicked + */ + private boolean processFloodgateTasks(PacketEvent packetEvent) { + PacketContainer packet = packetEvent.getPacket(); + Player player = packetEvent.getPlayer(); + FloodgatePlayer floodgatePlayer = getFloodgatePlayer(player); + if (floodgatePlayer == null) { + return true; + } + + // kick the player, if necessary + Channel channel = handler.getChannel(packetEvent.getPlayer()); + AttributeKey kickMessageAttribute = AttributeKey.valueOf("floodgate-kick-message"); + String kickMessage = channel.attr(kickMessageAttribute).get(); + if (kickMessage != null) { + player.kickPlayer(kickMessage); + return false; + } + + // add prefix + String username = floodgatePlayer.getCorrectUsername(); + if (packet.getGameProfiles().size() > 0) { + packet.getGameProfiles().write(0, + new WrappedGameProfile(floodgatePlayer.getCorrectUniqueId(), username)); + } else { + packet.getStrings().write(0, username); + } + + // remove real Floodgate data handler + ChannelHandler floodgateHandler = channel.pipeline().get("floodgate_data_handler"); + channel.pipeline().remove(floodgateHandler); + + return true; + } } diff --git a/checkstyle.xml b/checkstyle.xml index f38f8615..0a882add 100644 --- a/checkstyle.xml +++ b/checkstyle.xml @@ -101,6 +101,7 @@ + diff --git a/core/src/main/java/com/github/games647/fastlogin/core/hooks/bedrock/FloodgateService.java b/core/src/main/java/com/github/games647/fastlogin/core/hooks/bedrock/FloodgateService.java index 9ef8985c..267a0267 100644 --- a/core/src/main/java/com/github/games647/fastlogin/core/hooks/bedrock/FloodgateService.java +++ b/core/src/main/java/com/github/games647/fastlogin/core/hooks/bedrock/FloodgateService.java @@ -99,23 +99,11 @@ public class FloodgateService extends BedrockService { * The FloodgateApi does not support querying players by name, so this function * iterates over every online FloodgatePlayer and checks if the requested * username can be found - *
- * Falls back to non-prefixed name checks, if ProtocolLib is installed * * @param prefixedUsername the name of the player with the prefix appended * @return FloodgatePlayer if found, null otherwise */ public FloodgatePlayer getBedrockPlayer(String prefixedUsername) { - //prefixes are broken with ProtocolLib, so fall back to name checks without prefixes - //this should be removed if #493 gets fixed - if (core.getPlugin().isPluginInstalled("ProtocolLib")) { - for (FloodgatePlayer floodgatePlayer : floodgate.getPlayers()) { - if (floodgatePlayer.getUsername().equals(prefixedUsername)) { - return floodgatePlayer; - } - } - return null; - } for (FloodgatePlayer floodgatePlayer : floodgate.getPlayers()) { if (floodgatePlayer.getCorrectUsername().equals(prefixedUsername)) { return floodgatePlayer; diff --git a/core/src/main/resources/config.yml b/core/src/main/resources/config.yml index 8ac92822..5132bb2b 100644 --- a/core/src/main/resources/config.yml +++ b/core/src/main/resources/config.yml @@ -236,8 +236,6 @@ autoLoginFloodgate: false # # To prevent conflicts from two different players having the same name, it is highly recommended using a # 'username-prefix' in floodgate/config.yml -# Note: 'username-prefix' is currently broken when used with FastLogin and ProtocolLib. -# A solution to this is to enable 'floodgatePrefixWorkaround' below. # # Possible values: # false: Kick Bedrock players, if they are using an existing Premium Java account's name @@ -264,14 +262,6 @@ allowFloodgateNameConflict: false # Enabling this might lead to people gaining unauthorized access to other's accounts! autoRegisterFloodgate: false -# Make FastLogin inject the Floodgate name prefixes, instead of Floodgate. -# This can fix prefixes, if you are using Floodgate alongside ProtocolLib. -# If either of those plugins are not installed, this option will have no effect. -# For more information visit: https://github.com/games647/FastLogin/issues/493 -# !!!!!!!! WARNING: FLOODGATE SUPPORT IS AN EXPERIMENTAL FEATURE !!!!!!!! -# Enabling this might lead to people gaining unauthorized access to other's accounts! -floodgatePrefixWorkaround: false - # This option resembles the vanilla configuration option 'enforce-secure-profile' in the 'server.properties' file. # It verifies if the incoming cryptographic key in the login request from the player is signed by Mojang. This key # is necessary for servers where you or other in-game players want to verify that a chat message sent and signed by