mirror of
https://github.com/GeyserMC/Floodgate.git
synced 2025-12-19 14:59:20 +00:00
Add ProtocolSupport support
Based of the work done by Camotoy on the 1.0 co-authored-by: Camotoy <20743703+camotoy@users.noreply.github.com>
This commit is contained in:
@@ -26,6 +26,7 @@
|
|||||||
package org.geysermc.floodgate.api.handshake;
|
package org.geysermc.floodgate.api.handshake;
|
||||||
|
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
|
import java.util.UUID;
|
||||||
import org.geysermc.floodgate.util.BedrockData;
|
import org.geysermc.floodgate.util.BedrockData;
|
||||||
import org.geysermc.floodgate.util.LinkedPlayer;
|
import org.geysermc.floodgate.util.LinkedPlayer;
|
||||||
import org.geysermc.floodgate.util.RawSkin;
|
import org.geysermc.floodgate.util.RawSkin;
|
||||||
@@ -54,6 +55,14 @@ public interface HandshakeData {
|
|||||||
*/
|
*/
|
||||||
BedrockData getBedrockData();
|
BedrockData getBedrockData();
|
||||||
|
|
||||||
|
String getJavaUsername();
|
||||||
|
|
||||||
|
String getCorrectUsername();
|
||||||
|
|
||||||
|
UUID getJavaUniqueId();
|
||||||
|
|
||||||
|
UUID getCorrectUniqueId();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the linked account associated with the client or null if the player isn't linked or
|
* Returns the linked account associated with the client or null if the player isn't linked or
|
||||||
* not a Floodgate player.
|
* not a Floodgate player.
|
||||||
|
|||||||
@@ -26,25 +26,63 @@
|
|||||||
package org.geysermc.floodgate.addon.data;
|
package org.geysermc.floodgate.addon.data;
|
||||||
|
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import lombok.AllArgsConstructor;
|
import java.util.UUID;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import org.geysermc.floodgate.api.handshake.HandshakeData;
|
import org.geysermc.floodgate.api.handshake.HandshakeData;
|
||||||
|
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||||
import org.geysermc.floodgate.util.BedrockData;
|
import org.geysermc.floodgate.util.BedrockData;
|
||||||
import org.geysermc.floodgate.util.LinkedPlayer;
|
import org.geysermc.floodgate.util.LinkedPlayer;
|
||||||
import org.geysermc.floodgate.util.RawSkin;
|
import org.geysermc.floodgate.util.RawSkin;
|
||||||
|
import org.geysermc.floodgate.util.Utils;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@RequiredArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class HandshakeDataImpl implements HandshakeData {
|
public class HandshakeDataImpl implements HandshakeData {
|
||||||
private final Channel channel;
|
private final Channel channel;
|
||||||
private final boolean floodgatePlayer;
|
private final boolean floodgatePlayer;
|
||||||
private final BedrockData bedrockData;
|
private final BedrockData bedrockData;
|
||||||
|
private final String javaUsername;
|
||||||
|
private final UUID javaUniqueId;
|
||||||
|
|
||||||
@Setter private LinkedPlayer linkedPlayer;
|
@Setter private LinkedPlayer linkedPlayer;
|
||||||
@Setter private RawSkin rawSkin;
|
@Setter private RawSkin rawSkin;
|
||||||
@Setter private String hostname;
|
@Setter private String hostname;
|
||||||
@Setter private String disconnectReason;
|
@Setter private String disconnectReason;
|
||||||
|
|
||||||
|
public HandshakeDataImpl(
|
||||||
|
Channel channel,
|
||||||
|
boolean floodgatePlayer,
|
||||||
|
BedrockData bedrockData,
|
||||||
|
FloodgateConfig config,
|
||||||
|
LinkedPlayer linkedPlayer,
|
||||||
|
RawSkin rawSkin,
|
||||||
|
String hostname) {
|
||||||
|
|
||||||
|
this.channel = channel;
|
||||||
|
this.floodgatePlayer = floodgatePlayer;
|
||||||
|
this.bedrockData = bedrockData;
|
||||||
|
this.linkedPlayer = linkedPlayer;
|
||||||
|
this.rawSkin = rawSkin;
|
||||||
|
this.hostname = hostname;
|
||||||
|
|
||||||
|
String prefix = config.getUsernamePrefix();
|
||||||
|
int usernameLength = Math.min(bedrockData.getUsername().length(), 16 - prefix.length());
|
||||||
|
String javaUsername = prefix + bedrockData.getUsername().substring(0, usernameLength);
|
||||||
|
if (config.isReplaceSpaces()) {
|
||||||
|
javaUsername = javaUsername.replaceAll(" ", "_");
|
||||||
|
}
|
||||||
|
this.javaUsername = javaUsername;
|
||||||
|
|
||||||
|
this.javaUniqueId = Utils.getJavaUuid(bedrockData.getXuid());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCorrectUsername() {
|
||||||
|
return linkedPlayer != null ? linkedPlayer.getJavaUsername() : javaUsername;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UUID getCorrectUniqueId() {
|
||||||
|
return linkedPlayer != null ? linkedPlayer.getJavaUniqueId() : javaUniqueId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,8 +131,9 @@ public final class FloodgateHandshakeHandler {
|
|||||||
linkedPlayer = fetchLinkedPlayer(Utils.getJavaUuid(bedrockData.getXuid()));
|
linkedPlayer = fetchLinkedPlayer(Utils.getJavaUuid(bedrockData.getXuid()));
|
||||||
}
|
}
|
||||||
|
|
||||||
HandshakeData handshakeData = new HandshakeDataImpl(channel, true, bedrockData.clone(),
|
HandshakeData handshakeData = new HandshakeDataImpl(
|
||||||
linkedPlayer != null ? linkedPlayer.clone() : null, rawSkin, hostname, null);
|
channel, true, bedrockData.clone(), configHolder.get(),
|
||||||
|
linkedPlayer != null ? linkedPlayer.clone() : null, rawSkin, hostname);
|
||||||
handshakeHandlers.callHandshakeHandlers(handshakeData);
|
handshakeHandlers.callHandshakeHandlers(handshakeData);
|
||||||
|
|
||||||
UUID javaUuid = Utils.getJavaUuid(bedrockData.getXuid());
|
UUID javaUuid = Utils.getJavaUuid(bedrockData.getXuid());
|
||||||
@@ -141,7 +142,7 @@ public final class FloodgateHandshakeHandler {
|
|||||||
));
|
));
|
||||||
|
|
||||||
FloodgatePlayer player =
|
FloodgatePlayer player =
|
||||||
FloodgatePlayerImpl.from(bedrockData, handshakeData, configHolder);
|
FloodgatePlayerImpl.from(bedrockData, handshakeData);
|
||||||
|
|
||||||
api.addPlayer(player.getJavaUniqueId(), player);
|
api.addPlayer(player.getJavaUniqueId(), player);
|
||||||
|
|
||||||
@@ -184,7 +185,7 @@ public final class FloodgateHandshakeHandler {
|
|||||||
String hostname) {
|
String hostname) {
|
||||||
|
|
||||||
HandshakeData handshakeData = new HandshakeDataImpl(channel, bedrockData != null,
|
HandshakeData handshakeData = new HandshakeDataImpl(channel, bedrockData != null,
|
||||||
bedrockData, null, null, hostname, null);
|
bedrockData, configHolder.get(), null, null, hostname);
|
||||||
handshakeHandlers.callHandshakeHandlers(handshakeData);
|
handshakeHandlers.callHandshakeHandlers(handshakeData);
|
||||||
|
|
||||||
if (bedrockData != null) {
|
if (bedrockData != null) {
|
||||||
|
|||||||
@@ -42,8 +42,6 @@ import org.geysermc.floodgate.api.link.PlayerLink;
|
|||||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||||
import org.geysermc.floodgate.api.player.PropertyKey;
|
import org.geysermc.floodgate.api.player.PropertyKey;
|
||||||
import org.geysermc.floodgate.api.player.PropertyKey.Result;
|
import org.geysermc.floodgate.api.player.PropertyKey.Result;
|
||||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
|
||||||
import org.geysermc.floodgate.config.FloodgateConfigHolder;
|
|
||||||
import org.geysermc.floodgate.util.BedrockData;
|
import org.geysermc.floodgate.util.BedrockData;
|
||||||
import org.geysermc.floodgate.util.DeviceOs;
|
import org.geysermc.floodgate.util.DeviceOs;
|
||||||
import org.geysermc.floodgate.util.InputMode;
|
import org.geysermc.floodgate.util.InputMode;
|
||||||
@@ -83,18 +81,9 @@ public final class FloodgatePlayerImpl implements FloodgatePlayer {
|
|||||||
|
|
||||||
protected static FloodgatePlayerImpl from(
|
protected static FloodgatePlayerImpl from(
|
||||||
BedrockData data,
|
BedrockData data,
|
||||||
HandshakeData handshakeData,
|
HandshakeData handshakeData) {
|
||||||
FloodgateConfigHolder configHolder) {
|
|
||||||
|
|
||||||
FloodgateApi api = FloodgateApi.getInstance();
|
FloodgateApi api = FloodgateApi.getInstance();
|
||||||
FloodgateConfig config = configHolder.get();
|
|
||||||
|
|
||||||
String prefix = config.getUsernamePrefix();
|
|
||||||
int usernameLength = Math.min(data.getUsername().length(), 16 - prefix.length());
|
|
||||||
String javaUsername = prefix + data.getUsername().substring(0, usernameLength);
|
|
||||||
if (config.isReplaceSpaces()) {
|
|
||||||
javaUsername = javaUsername.replaceAll(" ", "_");
|
|
||||||
}
|
|
||||||
|
|
||||||
UUID javaUniqueId = Utils.getJavaUuid(data.getXuid());
|
UUID javaUniqueId = Utils.getJavaUuid(data.getXuid());
|
||||||
|
|
||||||
@@ -106,9 +95,10 @@ public final class FloodgatePlayerImpl implements FloodgatePlayer {
|
|||||||
RawSkin skin = handshakeData.getRawSkin();
|
RawSkin skin = handshakeData.getRawSkin();
|
||||||
|
|
||||||
FloodgatePlayerImpl player = new FloodgatePlayerImpl(
|
FloodgatePlayerImpl player = new FloodgatePlayerImpl(
|
||||||
data.getVersion(), data.getUsername(), javaUsername, javaUniqueId, data.getXuid(),
|
data.getVersion(), data.getUsername(), handshakeData.getJavaUsername(),
|
||||||
deviceOs, data.getLanguageCode(), uiProfile, inputMode, data.getIp(),
|
javaUniqueId, data.getXuid(), deviceOs, data.getLanguageCode(), uiProfile,
|
||||||
data.isFromProxy(), api instanceof ProxyFloodgateApi, linkedPlayer, skin);
|
inputMode, data.getIp(), data.isFromProxy(), api instanceof ProxyFloodgateApi,
|
||||||
|
linkedPlayer, skin);
|
||||||
|
|
||||||
// RawSkin should be removed, fromProxy should be changed
|
// RawSkin should be removed, fromProxy should be changed
|
||||||
// and encrypted data can be changed after fetching the linkedPlayer
|
// and encrypted data can be changed after fetching the linkedPlayer
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ package org.geysermc.floodgate;
|
|||||||
import com.google.inject.Guice;
|
import com.google.inject.Guice;
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
import org.geysermc.floodgate.api.InstanceHolder;
|
||||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||||
import org.geysermc.floodgate.module.ServerCommonModule;
|
import org.geysermc.floodgate.module.ServerCommonModule;
|
||||||
import org.geysermc.floodgate.module.SpigotAddonModule;
|
import org.geysermc.floodgate.module.SpigotAddonModule;
|
||||||
@@ -35,6 +36,8 @@ import org.geysermc.floodgate.module.SpigotCommandModule;
|
|||||||
import org.geysermc.floodgate.module.SpigotListenerModule;
|
import org.geysermc.floodgate.module.SpigotListenerModule;
|
||||||
import org.geysermc.floodgate.module.SpigotPlatformModule;
|
import org.geysermc.floodgate.module.SpigotPlatformModule;
|
||||||
import org.geysermc.floodgate.util.ReflectionUtils;
|
import org.geysermc.floodgate.util.ReflectionUtils;
|
||||||
|
import org.geysermc.floodgate.util.SpigotProtocolSupportHandler;
|
||||||
|
import org.geysermc.floodgate.util.SpigotProtocolSupportListener;
|
||||||
|
|
||||||
public final class SpigotPlugin extends JavaPlugin {
|
public final class SpigotPlugin extends JavaPlugin {
|
||||||
private SpigotPlatform platform;
|
private SpigotPlatform platform;
|
||||||
@@ -64,6 +67,13 @@ public final class SpigotPlugin extends JavaPlugin {
|
|||||||
new SpigotListenerModule(),
|
new SpigotListenerModule(),
|
||||||
new SpigotAddonModule()
|
new SpigotAddonModule()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// add ProtocolSupport support (hack)
|
||||||
|
if (getServer().getPluginManager().getPlugin("ProtocolSupport") != null) {
|
||||||
|
InstanceHolder.getHandshakeHandlers()
|
||||||
|
.addHandshakeHandler(new SpigotProtocolSupportHandler());
|
||||||
|
SpigotProtocolSupportListener.registerHack(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ package org.geysermc.floodgate.addon.data;
|
|||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static org.geysermc.floodgate.util.ReflectionUtils.getCastedValue;
|
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.getFieldOfType;
|
||||||
import static org.geysermc.floodgate.util.ReflectionUtils.getMethod;
|
import static org.geysermc.floodgate.util.ReflectionUtils.getMethod;
|
||||||
import static org.geysermc.floodgate.util.ReflectionUtils.getPrefixedClass;
|
import static org.geysermc.floodgate.util.ReflectionUtils.getPrefixedClass;
|
||||||
@@ -52,10 +51,10 @@ import org.geysermc.floodgate.player.FloodgateHandshakeHandler;
|
|||||||
import org.geysermc.floodgate.player.FloodgateHandshakeHandler.HandshakeResult;
|
import org.geysermc.floodgate.player.FloodgateHandshakeHandler.HandshakeResult;
|
||||||
import org.geysermc.floodgate.util.BedrockData;
|
import org.geysermc.floodgate.util.BedrockData;
|
||||||
import org.geysermc.floodgate.util.ReflectionUtils;
|
import org.geysermc.floodgate.util.ReflectionUtils;
|
||||||
|
import org.geysermc.floodgate.util.SpigotUtils;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public final class SpigotDataHandler extends SimpleChannelInboundHandler<Object> {
|
public final class SpigotDataHandler extends SimpleChannelInboundHandler<Object> {
|
||||||
private static final Field IS_BUNGEE_DATA;
|
|
||||||
private static final Field SOCKET_ADDRESS;
|
private static final Field SOCKET_ADDRESS;
|
||||||
private static final Class<?> HANDSHAKE_PACKET;
|
private static final Class<?> HANDSHAKE_PACKET;
|
||||||
private static final Field HANDSHAKE_HOST;
|
private static final Field HANDSHAKE_HOST;
|
||||||
@@ -77,10 +76,6 @@ public final class SpigotDataHandler extends SimpleChannelInboundHandler<Object>
|
|||||||
private static final Object READY_TO_ACCEPT_PROTOCOL_STATE;
|
private static final Object READY_TO_ACCEPT_PROTOCOL_STATE;
|
||||||
|
|
||||||
static {
|
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");
|
Class<?> networkManager = getPrefixedClass("NetworkManager");
|
||||||
checkNotNull(networkManager, "NetworkManager class cannot be null");
|
checkNotNull(networkManager, "NetworkManager class cannot be null");
|
||||||
|
|
||||||
@@ -204,7 +199,7 @@ public final class SpigotDataHandler extends SimpleChannelInboundHandler<Object>
|
|||||||
}
|
}
|
||||||
|
|
||||||
player = result.getFloodgatePlayer();
|
player = result.getFloodgatePlayer();
|
||||||
bungeeData = isBungeeData();
|
bungeeData = SpigotUtils.isBungeeData();
|
||||||
|
|
||||||
setValue(packet, HANDSHAKE_HOST, handshakeData.getHostname());
|
setValue(packet, HANDSHAKE_HOST, handshakeData.getHostname());
|
||||||
|
|
||||||
@@ -265,9 +260,4 @@ public final class SpigotDataHandler extends SimpleChannelInboundHandler<Object>
|
|||||||
super.exceptionCaught(ctx, cause);
|
super.exceptionCaught(ctx, cause);
|
||||||
cause.printStackTrace();
|
cause.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("ConstantConditions")
|
|
||||||
private boolean isBungeeData() {
|
|
||||||
return ReflectionUtils.getCastedValue(null, IS_BUNGEE_DATA);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2021 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 io.netty.channel.Channel;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.UUID;
|
||||||
|
import org.geysermc.floodgate.api.handshake.HandshakeData;
|
||||||
|
import org.geysermc.floodgate.api.handshake.HandshakeHandler;
|
||||||
|
|
||||||
|
public class SpigotProtocolSupportHandler implements HandshakeHandler {
|
||||||
|
private static final Method getFromChannel;
|
||||||
|
private static final Method getLoginProfile;
|
||||||
|
|
||||||
|
private static final Method setName;
|
||||||
|
private static final Method setOriginalName;
|
||||||
|
private static final Method setUuid;
|
||||||
|
private static final Method setOriginalUuid;
|
||||||
|
|
||||||
|
private static final Method getNetworkManagerWrapper;
|
||||||
|
private static final Method getPacketListener;
|
||||||
|
private static final Method handleLoginStart;
|
||||||
|
|
||||||
|
static {
|
||||||
|
Class<?> connectionImpl =
|
||||||
|
ReflectionUtils.getClass("protocolsupport.protocol.ConnectionImpl");
|
||||||
|
|
||||||
|
getFromChannel = ReflectionUtils.getMethod(connectionImpl, "getFromChannel", Channel.class);
|
||||||
|
getLoginProfile = ReflectionUtils.getMethod(connectionImpl, "getLoginProfile");
|
||||||
|
|
||||||
|
Class<?> profile = ReflectionUtils.getClass("protocolsupport.api.utils.Profile");
|
||||||
|
|
||||||
|
setName = ReflectionUtils.getMethod(profile, "setName", String.class);
|
||||||
|
setOriginalName = ReflectionUtils.getMethod(profile, "setOriginalName", String.class);
|
||||||
|
setUuid = ReflectionUtils.getMethod(profile, "setUUID", UUID.class);
|
||||||
|
setOriginalUuid = ReflectionUtils.getMethod(profile, "setOriginalUUID", UUID.class);
|
||||||
|
|
||||||
|
getNetworkManagerWrapper =
|
||||||
|
ReflectionUtils.getMethod(connectionImpl, "getNetworkManagerWrapper");
|
||||||
|
|
||||||
|
Class<?> networkManagerWrapper =
|
||||||
|
ReflectionUtils.getClass("protocolsupport.zplatform.network.NetworkManagerWrapper");
|
||||||
|
|
||||||
|
getPacketListener = ReflectionUtils.getMethod(networkManagerWrapper, "getPacketListener");
|
||||||
|
|
||||||
|
Class<?> loginListener = ReflectionUtils.getClass(
|
||||||
|
"protocolsupport.protocol.packet.handler.AbstractLoginListener");
|
||||||
|
|
||||||
|
handleLoginStart = ReflectionUtils.getMethod(loginListener, "handleLoginStart", UUID.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(HandshakeData data) {
|
||||||
|
if (data.isFloodgatePlayer() && SpigotUtils.isBungeeData()) {
|
||||||
|
Object connection = ReflectionUtils.invoke(null, getFromChannel, data.getChannel());
|
||||||
|
Object profile = ReflectionUtils.invoke(connection, getLoginProfile);
|
||||||
|
|
||||||
|
// set correct uuid and name on ProtocolSupport's end, since we skip the LoginStart
|
||||||
|
ReflectionUtils.invoke(profile, setName, data.getCorrectUsername());
|
||||||
|
ReflectionUtils.invoke(profile, setOriginalName, data.getCorrectUsername());
|
||||||
|
ReflectionUtils.invoke(profile, setUuid, data.getCorrectUniqueId());
|
||||||
|
ReflectionUtils.invoke(profile, setOriginalUuid, data.getCorrectUniqueId());
|
||||||
|
|
||||||
|
Object temp = ReflectionUtils.invoke(connection, getNetworkManagerWrapper);
|
||||||
|
temp = ReflectionUtils.invoke(temp, getPacketListener);
|
||||||
|
ReflectionUtils.invoke(temp, handleLoginStart, data.getCorrectUsername());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2021 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 static org.geysermc.floodgate.util.ReflectionUtils.getMethod;
|
||||||
|
import static org.geysermc.floodgate.util.ReflectionUtils.getPrefixedClass;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.UUID;
|
||||||
|
import org.bukkit.event.Event;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.geysermc.floodgate.api.FloodgateApi;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public final class SpigotProtocolSupportListener {
|
||||||
|
public static void registerHack(Plugin plugin) {
|
||||||
|
String prefix = ReflectionUtils.getPrefix();
|
||||||
|
ReflectionUtils.setPrefix("protocolsupport.api");
|
||||||
|
|
||||||
|
Class<? extends Event> playerLoginStartEvent =
|
||||||
|
(Class<? extends Event>) getPrefixedClass("events.PlayerLoginStartEvent");
|
||||||
|
|
||||||
|
Method setOnlineMode = getMethod(playerLoginStartEvent, "setOnlineMode", boolean.class);
|
||||||
|
|
||||||
|
Class<?> connectionEvent = getPrefixedClass("events.ConnectionEvent");
|
||||||
|
Method getConnection = getMethod(connectionEvent, "getConnection");
|
||||||
|
|
||||||
|
Class<?> connection = getPrefixedClass("Connection");
|
||||||
|
Method getProfile = getMethod(connection, "getProfile");
|
||||||
|
|
||||||
|
Class<?> profile = getPrefixedClass("utils.Profile");
|
||||||
|
Method getUuid = getMethod(profile, "getUUID");
|
||||||
|
|
||||||
|
plugin.getServer().getPluginManager().registerEvent(
|
||||||
|
playerLoginStartEvent, new Listener() {}, EventPriority.MONITOR,
|
||||||
|
(listener, event) -> {
|
||||||
|
Object temp = ReflectionUtils.invoke(event, getConnection);
|
||||||
|
temp = ReflectionUtils.invoke(temp, getProfile);
|
||||||
|
|
||||||
|
UUID uuid = ReflectionUtils.castedInvoke(temp, getUuid);
|
||||||
|
|
||||||
|
// a normal player that doesn't have a UUID set
|
||||||
|
if (uuid == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FloodgateApi.getInstance().isFloodgatePlayer(uuid)) {
|
||||||
|
// otherwise ProtocolSupport attempts to connect with online mode
|
||||||
|
ReflectionUtils.invoke(event, setOnlineMode, false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
plugin);
|
||||||
|
|
||||||
|
ReflectionUtils.setPrefix(prefix);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2021 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 static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static org.geysermc.floodgate.util.ReflectionUtils.getField;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
|
@SuppressWarnings("ConstantConditions")
|
||||||
|
public final class SpigotUtils {
|
||||||
|
private static final Field IS_BUNGEE_DATA;
|
||||||
|
|
||||||
|
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?");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isBungeeData() {
|
||||||
|
return ReflectionUtils.getCastedValue(null, IS_BUNGEE_DATA);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user