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