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;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import java.util.UUID;
|
||||
import org.geysermc.floodgate.util.BedrockData;
|
||||
import org.geysermc.floodgate.util.LinkedPlayer;
|
||||
import org.geysermc.floodgate.util.RawSkin;
|
||||
@@ -54,6 +55,14 @@ public interface HandshakeData {
|
||||
*/
|
||||
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
|
||||
* not a Floodgate player.
|
||||
|
||||
@@ -26,25 +26,63 @@
|
||||
package org.geysermc.floodgate.addon.data;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import java.util.UUID;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.geysermc.floodgate.api.handshake.HandshakeData;
|
||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.util.BedrockData;
|
||||
import org.geysermc.floodgate.util.LinkedPlayer;
|
||||
import org.geysermc.floodgate.util.RawSkin;
|
||||
import org.geysermc.floodgate.util.Utils;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class HandshakeDataImpl implements HandshakeData {
|
||||
private final Channel channel;
|
||||
private final boolean floodgatePlayer;
|
||||
private final BedrockData bedrockData;
|
||||
private final String javaUsername;
|
||||
private final UUID javaUniqueId;
|
||||
|
||||
@Setter private LinkedPlayer linkedPlayer;
|
||||
@Setter private RawSkin rawSkin;
|
||||
@Setter private String hostname;
|
||||
@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()));
|
||||
}
|
||||
|
||||
HandshakeData handshakeData = new HandshakeDataImpl(channel, true, bedrockData.clone(),
|
||||
linkedPlayer != null ? linkedPlayer.clone() : null, rawSkin, hostname, null);
|
||||
HandshakeData handshakeData = new HandshakeDataImpl(
|
||||
channel, true, bedrockData.clone(), configHolder.get(),
|
||||
linkedPlayer != null ? linkedPlayer.clone() : null, rawSkin, hostname);
|
||||
handshakeHandlers.callHandshakeHandlers(handshakeData);
|
||||
|
||||
UUID javaUuid = Utils.getJavaUuid(bedrockData.getXuid());
|
||||
@@ -141,7 +142,7 @@ public final class FloodgateHandshakeHandler {
|
||||
));
|
||||
|
||||
FloodgatePlayer player =
|
||||
FloodgatePlayerImpl.from(bedrockData, handshakeData, configHolder);
|
||||
FloodgatePlayerImpl.from(bedrockData, handshakeData);
|
||||
|
||||
api.addPlayer(player.getJavaUniqueId(), player);
|
||||
|
||||
@@ -184,7 +185,7 @@ public final class FloodgateHandshakeHandler {
|
||||
String hostname) {
|
||||
|
||||
HandshakeData handshakeData = new HandshakeDataImpl(channel, bedrockData != null,
|
||||
bedrockData, null, null, hostname, null);
|
||||
bedrockData, configHolder.get(), null, null, hostname);
|
||||
handshakeHandlers.callHandshakeHandlers(handshakeData);
|
||||
|
||||
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.PropertyKey;
|
||||
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.DeviceOs;
|
||||
import org.geysermc.floodgate.util.InputMode;
|
||||
@@ -83,18 +81,9 @@ public final class FloodgatePlayerImpl implements FloodgatePlayer {
|
||||
|
||||
protected static FloodgatePlayerImpl from(
|
||||
BedrockData data,
|
||||
HandshakeData handshakeData,
|
||||
FloodgateConfigHolder configHolder) {
|
||||
HandshakeData handshakeData) {
|
||||
|
||||
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());
|
||||
|
||||
@@ -106,9 +95,10 @@ public final class FloodgatePlayerImpl implements FloodgatePlayer {
|
||||
RawSkin skin = handshakeData.getRawSkin();
|
||||
|
||||
FloodgatePlayerImpl player = new FloodgatePlayerImpl(
|
||||
data.getVersion(), data.getUsername(), javaUsername, javaUniqueId, data.getXuid(),
|
||||
deviceOs, data.getLanguageCode(), uiProfile, inputMode, data.getIp(),
|
||||
data.isFromProxy(), api instanceof ProxyFloodgateApi, linkedPlayer, skin);
|
||||
data.getVersion(), data.getUsername(), handshakeData.getJavaUsername(),
|
||||
javaUniqueId, data.getXuid(), deviceOs, data.getLanguageCode(), uiProfile,
|
||||
inputMode, data.getIp(), data.isFromProxy(), api instanceof ProxyFloodgateApi,
|
||||
linkedPlayer, skin);
|
||||
|
||||
// RawSkin should be removed, fromProxy should be changed
|
||||
// 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.Injector;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.geysermc.floodgate.api.InstanceHolder;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.module.ServerCommonModule;
|
||||
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.SpigotPlatformModule;
|
||||
import org.geysermc.floodgate.util.ReflectionUtils;
|
||||
import org.geysermc.floodgate.util.SpigotProtocolSupportHandler;
|
||||
import org.geysermc.floodgate.util.SpigotProtocolSupportListener;
|
||||
|
||||
public final class SpigotPlugin extends JavaPlugin {
|
||||
private SpigotPlatform platform;
|
||||
@@ -64,6 +67,13 @@ public final class SpigotPlugin extends JavaPlugin {
|
||||
new SpigotListenerModule(),
|
||||
new SpigotAddonModule()
|
||||
);
|
||||
|
||||
// add ProtocolSupport support (hack)
|
||||
if (getServer().getPluginManager().getPlugin("ProtocolSupport") != null) {
|
||||
InstanceHolder.getHandshakeHandlers()
|
||||
.addHandshakeHandler(new SpigotProtocolSupportHandler());
|
||||
SpigotProtocolSupportListener.registerHack(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -27,7 +27,6 @@ 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;
|
||||
@@ -52,10 +51,10 @@ import org.geysermc.floodgate.player.FloodgateHandshakeHandler;
|
||||
import org.geysermc.floodgate.player.FloodgateHandshakeHandler.HandshakeResult;
|
||||
import org.geysermc.floodgate.util.BedrockData;
|
||||
import org.geysermc.floodgate.util.ReflectionUtils;
|
||||
import org.geysermc.floodgate.util.SpigotUtils;
|
||||
|
||||
@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;
|
||||
@@ -77,10 +76,6 @@ 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");
|
||||
|
||||
@@ -204,7 +199,7 @@ public final class SpigotDataHandler extends SimpleChannelInboundHandler<Object>
|
||||
}
|
||||
|
||||
player = result.getFloodgatePlayer();
|
||||
bungeeData = isBungeeData();
|
||||
bungeeData = SpigotUtils.isBungeeData();
|
||||
|
||||
setValue(packet, HANDSHAKE_HOST, handshakeData.getHostname());
|
||||
|
||||
@@ -265,9 +260,4 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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