mirror of
https://github.com/TuxCoding/FastLogin.git
synced 2025-07-29 18:27:36 +02:00
Merge pull request #876 from Smart123s/fix/floodgate/plib-chnext
Fix Floodgate prefix with ProtocolLib
This commit is contained in:
@ -376,8 +376,8 @@
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-transport</artifactId>
|
||||
<version>${nettyVersion}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
|
@ -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<Comman
|
||||
} else if (pluginManager.isPluginEnabled("ProtocolLib")) {
|
||||
ProtocolLibListener.register(this, core.getAntiBot(), core.getConfig().getBoolean("verifyClientKeys"));
|
||||
|
||||
if (isPluginInstalled("floodgate")) {
|
||||
printFloodgateWarning();
|
||||
}
|
||||
|
||||
//if server is using paper - we need to set the skin at pre login anyway, so no need for this listener
|
||||
if (!PaperLib.isPaper() && getConfig().getBoolean("forwardSkin")) {
|
||||
pluginManager.registerEvents(new SkinApplyListener(this), this);
|
||||
@ -152,23 +147,6 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
||||
premiumPlaceholder = new PremiumPlaceholder(this);
|
||||
premiumPlaceholder.register();
|
||||
}
|
||||
|
||||
dependencyWarnings();
|
||||
}
|
||||
|
||||
private void printFloodgateWarning() {
|
||||
if (getConfig().getBoolean("floodgatePrefixWorkaround")) {
|
||||
ManualNameChange.register(this, floodgateService);
|
||||
logger.info("Floodgate prefix injection workaround has been enabled.");
|
||||
logger.info("If you have problems joining the server, try disabling it in the configuration.");
|
||||
} else {
|
||||
logger.warn("We have detected that you are running FastLogin alongside Floodgate and ProtocolLib.");
|
||||
logger.warn("Currently there is an issue with FastLogin that prevents Floodgate name prefixes from "
|
||||
+ "showing up when it is together used with ProtocolLib.");
|
||||
logger.warn("If you would like to use Floodgate name prefixes, you can enable an experimental "
|
||||
+ "workaround by changing the value 'floodgatePrefixWorkaround' to true in config.yml.");
|
||||
logger.warn("For more information visit https://github.com/games647/FastLogin/issues/493");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean initializeFloodgate() {
|
||||
@ -326,18 +304,4 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
||||
}
|
||||
return geyserService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send warning messages to log if incompatible plugins are used
|
||||
*/
|
||||
private void dependencyWarnings() {
|
||||
if (isPluginInstalled("floodgate-bukkit")) {
|
||||
logger.warn("We have detected that you are running Floodgate 1.0 which is not supported by the Bukkit "
|
||||
+ "version of FastLogin.");
|
||||
logger.warn("If you would like to use FastLogin with Floodgate, you can download development builds of "
|
||||
+ "Floodgate 2.0 from https://ci.opencollab.dev/job/GeyserMC/job/Floodgate/job/dev%252F2.0/");
|
||||
logger.warn("Don't forget to update Geyser to a supported version as well from "
|
||||
+ "https://ci.opencollab.dev/job/GeyserMC/job/Geyser/job/floodgate-2.0/");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,102 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2022 games647 and contributors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package com.github.games647.fastlogin.bukkit.listener.protocollib;
|
||||
|
||||
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.wrappers.WrappedGameProfile;
|
||||
import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
|
||||
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
|
||||
import static com.comphenix.protocol.PacketType.Login.Client.START;
|
||||
|
||||
/**
|
||||
* Manually inject Floodgate player name prefixes.
|
||||
* <br>
|
||||
* This is used as a workaround, because Floodgate fails to inject
|
||||
* the prefixes when it's used together with ProtocolLib and FastLogin.
|
||||
* <br>
|
||||
* For more information visit: <a href="https://github.com/games647/FastLogin/issues/493">...</a>
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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<FloodgatePlayer> 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 <a href="https://github.com/GeyserMC/Floodgate/issues/143">Issue Floodgate#143</a>
|
||||
* @see <a href="https://github.com/GeyserMC/Floodgate/blob/5d5713ed9e9eeab0f4abdaa9cf5cd8619dc1909b/spigot/src/main/java/org/geysermc/floodgate/addon/data/SpigotDataHandler.java#L121-L175">Floodgate/SpigotDataHandler</a>
|
||||
* @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<String> 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;
|
||||
}
|
||||
}
|
||||
|
@ -101,6 +101,7 @@
|
||||
<module name="LineLength">
|
||||
<property name="max" value="120"/>
|
||||
<property name="fileExtensions" value="java"/>
|
||||
<property name="ignorePattern" value="^ *\* *@see.+$"/>
|
||||
</module>
|
||||
|
||||
<!-- Checks for whitespace -->
|
||||
|
@ -99,23 +99,11 @@ public class FloodgateService extends BedrockService<FloodgatePlayer> {
|
||||
* 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
|
||||
* <br>
|
||||
* <i>Falls back to non-prefixed name checks, if ProtocolLib is installed</i>
|
||||
*
|
||||
* @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;
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user