mirror of
https://github.com/GeyserMC/Floodgate.git
synced 2026-01-04 15:31:48 +00:00
GeyserDump and legacy Spigot versions support. Made proxy data flexible
This commit is contained in:
@@ -52,31 +52,31 @@ public final class HandshakeHandler {
|
||||
try {
|
||||
String[] dataArray = handshakeData.split("\0");
|
||||
|
||||
boolean isBungeeData = dataArray.length == 5;
|
||||
// this can be Bungee data (without skin) or Floodgate data
|
||||
if (dataArray.length == 4) {
|
||||
isBungeeData = FloodgateCipher.hasHeader(dataArray[3]);
|
||||
String data = null;
|
||||
for (String value : dataArray) {
|
||||
if (FloodgateCipher.hasHeader(value)) {
|
||||
data = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
boolean proxy = configHolder.get().isProxy();
|
||||
//todo remove this check
|
||||
if (proxy && isBungeeData || !isBungeeData && dataArray.length != 2) {
|
||||
if (data == null) {
|
||||
return ResultType.NOT_FLOODGATE_DATA.getCachedResult();
|
||||
}
|
||||
|
||||
// calculate the expected Base64 encoded IV length.
|
||||
int expectedIvLength = 4 * ((AesCipher.IV_LENGTH + 2) / 3);
|
||||
int lastSplitIndex = dataArray[1].lastIndexOf(0x21);
|
||||
int lastSplitIndex = data.lastIndexOf(0x21);
|
||||
|
||||
byte[] floodgateData;
|
||||
byte[] rawSkinData = null;
|
||||
|
||||
// if it has a RawSkin
|
||||
if (lastSplitIndex - expectedIvLength != 0) {
|
||||
floodgateData = dataArray[1].substring(0, lastSplitIndex).getBytes(Charsets.UTF_8);
|
||||
rawSkinData = dataArray[1].substring(lastSplitIndex + 1).getBytes(Charsets.UTF_8);
|
||||
floodgateData = data.substring(0, lastSplitIndex).getBytes(Charsets.UTF_8);
|
||||
rawSkinData = data.substring(lastSplitIndex + 1).getBytes(Charsets.UTF_8);
|
||||
} else {
|
||||
floodgateData = dataArray[1].getBytes(Charsets.UTF_8);
|
||||
floodgateData = data.getBytes(Charsets.UTF_8);
|
||||
}
|
||||
|
||||
// actual decryption
|
||||
@@ -137,9 +137,5 @@ public final class HandshakeHandler {
|
||||
private final String[] handshakeData;
|
||||
private final BedrockData bedrockData;
|
||||
private final FloodgatePlayer floodgatePlayer;
|
||||
|
||||
public boolean isBungeeData() {
|
||||
return handshakeData.length == 4 || handshakeData.length == 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,5 +51,7 @@ public class FloodgateConfigHolder {
|
||||
|
||||
public void set(FloodgateConfig config) {
|
||||
this.config = config;
|
||||
// for Geyser dump
|
||||
org.geysermc.floodgate.util.FloodgateConfigHolder.setConfig(config);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ package org.geysermc.floodgate.addon.data;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.geysermc.floodgate.util.ReflectionUtils.getCastedValue;
|
||||
import static org.geysermc.floodgate.util.ReflectionUtils.getField;
|
||||
import static org.geysermc.floodgate.util.ReflectionUtils.getFieldOfType;
|
||||
import static org.geysermc.floodgate.util.ReflectionUtils.getMethod;
|
||||
import static org.geysermc.floodgate.util.ReflectionUtils.getPrefixedClass;
|
||||
@@ -53,6 +54,7 @@ import org.geysermc.floodgate.util.ReflectionUtils;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public final class SpigotDataHandler extends SimpleChannelInboundHandler<Object> {
|
||||
private static final Field IS_BUNGEE_DATA;
|
||||
private static final Field SOCKET_ADDRESS;
|
||||
private static final Class<?> HANDSHAKE_PACKET;
|
||||
private static final Field HANDSHAKE_HOST;
|
||||
@@ -74,6 +76,10 @@ public final class SpigotDataHandler extends SimpleChannelInboundHandler<Object>
|
||||
private static final Object READY_TO_ACCEPT_PROTOCOL_STATE;
|
||||
|
||||
static {
|
||||
Class<?> spigotConfig = ReflectionUtils.getClass("org.spigotmc.SpigotConfig");
|
||||
IS_BUNGEE_DATA = getField(spigotConfig, "bungee");
|
||||
checkNotNull(IS_BUNGEE_DATA, "bungee field cannot be null. Are you using CraftBukkit?");
|
||||
|
||||
Class<?> networkManager = getPrefixedClass("NetworkManager");
|
||||
checkNotNull(networkManager, "NetworkManager class cannot be null");
|
||||
|
||||
@@ -155,7 +161,7 @@ public final class SpigotDataHandler extends SimpleChannelInboundHandler<Object>
|
||||
private final FloodgateLogger logger;
|
||||
private Object networkManager;
|
||||
private FloodgatePlayer fPlayer;
|
||||
private boolean bungee;
|
||||
private boolean bungeeData;
|
||||
private boolean done;
|
||||
|
||||
@Override
|
||||
@@ -194,9 +200,11 @@ public final class SpigotDataHandler extends SimpleChannelInboundHandler<Object>
|
||||
|
||||
fPlayer = result.getFloodgatePlayer();
|
||||
BedrockData bedrockData = result.getBedrockData();
|
||||
String[] data = result.getHandshakeData();
|
||||
|
||||
if (bungee = result.isBungeeData()) {
|
||||
String[] data = result.getHandshakeData();
|
||||
bungeeData = isBungeeData();
|
||||
|
||||
if (bungeeData) {
|
||||
setValue(packet, HANDSHAKE_HOST, data[0] + '\0' +
|
||||
bedrockData.getIp() + '\0' +
|
||||
fPlayer.getCorrectUniqueId() +
|
||||
@@ -213,7 +221,7 @@ public final class SpigotDataHandler extends SimpleChannelInboundHandler<Object>
|
||||
setValue(networkManager, SOCKET_ADDRESS, newAddress);
|
||||
}
|
||||
} else if (isLogin) {
|
||||
if (!bungee) {
|
||||
if (!bungeeData) {
|
||||
// we have to fake the offline player (login) cycle
|
||||
Object loginListener = PACKET_LISTENER.get(networkManager);
|
||||
|
||||
@@ -249,7 +257,7 @@ public final class SpigotDataHandler extends SimpleChannelInboundHandler<Object>
|
||||
ctx.fireChannelRead(packet);
|
||||
}
|
||||
|
||||
if (isHandshake && bungee || isLogin && !bungee || fPlayer == null) {
|
||||
if (isHandshake && bungeeData || isLogin && !bungeeData || fPlayer == null) {
|
||||
// we're done, we'll just wait for the loginSuccessCall
|
||||
done = true;
|
||||
}
|
||||
@@ -261,4 +269,9 @@ public final class SpigotDataHandler extends SimpleChannelInboundHandler<Object>
|
||||
super.exceptionCaught(ctx, cause);
|
||||
cause.printStackTrace();
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
private boolean isBungeeData() {
|
||||
return ReflectionUtils.getCastedValue(null, IS_BUNGEE_DATA);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,13 +36,17 @@ import org.geysermc.floodgate.platform.command.Command;
|
||||
import org.geysermc.floodgate.platform.command.CommandRegistration;
|
||||
import org.geysermc.floodgate.platform.command.CommandUtil;
|
||||
import org.geysermc.floodgate.util.ReflectionUtils;
|
||||
import org.geysermc.floodgate.util.SpigotVersionSpecificMethods;
|
||||
|
||||
public final class SpigotCommandRegistration implements CommandRegistration {
|
||||
private final SpigotVersionSpecificMethods versionSpecificMethods;
|
||||
private final JavaPlugin plugin;
|
||||
private final CommandUtil commandUtil;
|
||||
private final CommandMap commandMap;
|
||||
|
||||
public SpigotCommandRegistration(JavaPlugin plugin, CommandUtil commandUtil) {
|
||||
public SpigotCommandRegistration(SpigotVersionSpecificMethods versionSpecificMethods,
|
||||
JavaPlugin plugin, CommandUtil commandUtil) {
|
||||
this.versionSpecificMethods = versionSpecificMethods;
|
||||
this.plugin = plugin;
|
||||
this.commandUtil = commandUtil;
|
||||
this.commandMap = ReflectionUtils.getCastedValue(Bukkit.getPluginManager(), "commandMap");
|
||||
@@ -50,16 +54,21 @@ public final class SpigotCommandRegistration implements CommandRegistration {
|
||||
|
||||
@Override
|
||||
public void register(Command command) {
|
||||
commandMap.register("floodgate", new SpigotCommand(plugin, commandUtil, command));
|
||||
SpigotCommand spigotCommand =
|
||||
new SpigotCommand(versionSpecificMethods, plugin, commandUtil, command);
|
||||
commandMap.register("floodgate", spigotCommand);
|
||||
}
|
||||
|
||||
protected static class SpigotCommand extends org.bukkit.command.Command {
|
||||
private final SpigotVersionSpecificMethods versionSpecificMethods;
|
||||
private final JavaPlugin plugin;
|
||||
private final CommandUtil commandUtil;
|
||||
private final Command command;
|
||||
|
||||
protected SpigotCommand(JavaPlugin plugin, CommandUtil commandUtil, Command command) {
|
||||
protected SpigotCommand(SpigotVersionSpecificMethods versionSpecificMethods,
|
||||
JavaPlugin plugin, CommandUtil commandUtil, Command command) {
|
||||
super(command.getName(), command.getDescription(), "", Collections.emptyList());
|
||||
this.versionSpecificMethods = versionSpecificMethods;
|
||||
this.plugin = plugin;
|
||||
this.commandUtil = commandUtil;
|
||||
this.command = command;
|
||||
@@ -90,13 +99,7 @@ public final class SpigotCommandRegistration implements CommandRegistration {
|
||||
}
|
||||
|
||||
Player player = (Player) sender;
|
||||
String locale;
|
||||
try {
|
||||
locale = player.getLocale();
|
||||
} catch (Exception exception) {
|
||||
// server is older then 1.12.0
|
||||
locale = player.spigot().getLocale();
|
||||
}
|
||||
String locale = versionSpecificMethods.getLocale(player);
|
||||
|
||||
command.execute(sender, player.getUniqueId(), sender.getName(), locale, args);
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ import org.geysermc.floodgate.pluginmessage.SpigotSkinHandler;
|
||||
import org.geysermc.floodgate.skin.SkinHandler;
|
||||
import org.geysermc.floodgate.util.LanguageManager;
|
||||
import org.geysermc.floodgate.util.SpigotCommandUtil;
|
||||
import org.geysermc.floodgate.util.SpigotVersionSpecificMethods;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public final class SpigotPlatformModule extends AbstractModule {
|
||||
@@ -87,8 +88,10 @@ public final class SpigotPlatformModule extends AbstractModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public CommandRegistration commandRegistration(CommandUtil commandUtil) {
|
||||
return new SpigotCommandRegistration(plugin, commandUtil);
|
||||
public CommandRegistration commandRegistration(
|
||||
SpigotVersionSpecificMethods versionSpecificMethods,
|
||||
CommandUtil commandUtil) {
|
||||
return new SpigotCommandRegistration(versionSpecificMethods, plugin, commandUtil);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@@ -114,8 +117,11 @@ public final class SpigotPlatformModule extends AbstractModule {
|
||||
@Provides
|
||||
@Singleton
|
||||
public SkinHandler skinHandler(PluginMessageHandler messageHandler, FloodgateLogger logger,
|
||||
SpigotVersionSpecificMethods versionSpecificMethods,
|
||||
FloodgateConfigHolder configHolder) {
|
||||
return new SpigotSkinHandler(messageHandler, logger, plugin, configHolder);
|
||||
return new SpigotSkinHandler(
|
||||
messageHandler, logger, versionSpecificMethods, plugin, configHolder
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -40,6 +40,7 @@ import org.geysermc.floodgate.platform.pluginmessage.PluginMessageHandler;
|
||||
import org.geysermc.floodgate.skin.SkinHandler;
|
||||
import org.geysermc.floodgate.skin.SkinUploader.UploadResult;
|
||||
import org.geysermc.floodgate.util.ReflectionUtils;
|
||||
import org.geysermc.floodgate.util.SpigotVersionSpecificMethods;
|
||||
|
||||
public class SpigotSkinHandler extends SkinHandler {
|
||||
private static final Method GET_PROFILE_METHOD;
|
||||
@@ -51,12 +52,15 @@ public class SpigotSkinHandler extends SkinHandler {
|
||||
GET_PROFILE_METHOD = ReflectionUtils.getMethod(craftPlayerClass, "getProfile");
|
||||
}
|
||||
|
||||
private final SpigotVersionSpecificMethods versionSpecificMethods;
|
||||
private final SpigotPlugin plugin;
|
||||
private final FloodgateConfigHolder configHolder;
|
||||
|
||||
public SpigotSkinHandler(PluginMessageHandler messageHandler, FloodgateLogger logger,
|
||||
SpigotVersionSpecificMethods versionSpecificMethods,
|
||||
SpigotPlugin plugin, FloodgateConfigHolder configHolder) {
|
||||
super(messageHandler, logger);
|
||||
this.versionSpecificMethods = versionSpecificMethods;
|
||||
this.plugin = plugin;
|
||||
this.configHolder = configHolder;
|
||||
}
|
||||
@@ -86,8 +90,8 @@ public class SpigotSkinHandler extends SkinHandler {
|
||||
plugin.getServer().getScheduler().runTask(plugin, () -> {
|
||||
for (Player p : Bukkit.getOnlinePlayers()) {
|
||||
if (p != player) {
|
||||
p.hidePlayer(plugin, player);
|
||||
p.showPlayer(plugin, player);
|
||||
versionSpecificMethods.hidePlayer(p, player);
|
||||
versionSpecificMethods.showPlayer(p, player);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020 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.util;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.geysermc.floodgate.SpigotPlugin;
|
||||
|
||||
public final class SpigotVersionSpecificMethods {
|
||||
private static final boolean NEW_GET_LOCALE;
|
||||
private static final boolean NEW_VISIBILITY;
|
||||
|
||||
static {
|
||||
NEW_GET_LOCALE = ReflectionUtils.getMethod(Player.class, "getLocale") != null;
|
||||
NEW_VISIBILITY = null != ReflectionUtils.getMethod(
|
||||
Player.class, "hidePlayer",
|
||||
Plugin.class, Player.class
|
||||
);
|
||||
}
|
||||
|
||||
private final SpigotPlugin plugin;
|
||||
|
||||
public SpigotVersionSpecificMethods(SpigotPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public String getLocale(Player player) {
|
||||
if (NEW_GET_LOCALE) {
|
||||
return player.getLocale();
|
||||
}
|
||||
return player.spigot().getLocale();
|
||||
}
|
||||
|
||||
public void hidePlayer(Player hideFor, Player playerToHide) {
|
||||
if (NEW_VISIBILITY) {
|
||||
hideFor.hidePlayer(plugin, playerToHide);
|
||||
return;
|
||||
}
|
||||
hideFor.hidePlayer(playerToHide);
|
||||
}
|
||||
|
||||
public void showPlayer(Player showFor, Player playerToShow) {
|
||||
if (NEW_VISIBILITY) {
|
||||
showFor.hidePlayer(plugin, playerToShow);
|
||||
return;
|
||||
}
|
||||
showFor.hidePlayer(playerToShow);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user