mirror of
https://github.com/GeyserMC/Floodgate.git
synced 2025-12-29 11:39:16 +00:00
Adds experimental Velocity support, fixed bugs and changed some class names
This commit is contained in:
@@ -1,12 +1,10 @@
|
||||
package org.geysermc.floodgate;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
class FloodgateAPI {
|
||||
abstract class AbstractFloodgateAPI {
|
||||
static final Map<UUID, FloodgatePlayer> players = new HashMap<>();
|
||||
|
||||
/**
|
||||
@@ -33,27 +31,4 @@ class FloodgateAPI {
|
||||
public static UUID createJavaPlayerId(long xuid) {
|
||||
return new UUID(0, xuid);
|
||||
}
|
||||
|
||||
public enum DeviceOS {
|
||||
@JsonEnumDefaultValue
|
||||
UNKOWN,
|
||||
ANDROID,
|
||||
IOS,
|
||||
OSX,
|
||||
FIREOS,
|
||||
GEARVR,
|
||||
HOLOLENS,
|
||||
WIN10,
|
||||
WIN32,
|
||||
DEDICATED,
|
||||
ORBIS,
|
||||
NX,
|
||||
SWITCH;
|
||||
|
||||
private static final DeviceOS[] VALUES = values();
|
||||
|
||||
public static DeviceOS getById(int id) {
|
||||
return id < VALUES.length ? VALUES[id] : VALUES[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,7 +80,10 @@ public class FloodgateConfig {
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Error while loading config", e);
|
||||
}
|
||||
if (config == null) return null;
|
||||
|
||||
if (config == null) {
|
||||
throw new RuntimeException("Failed to load config file! Try to delete the data folder of Floodgate");
|
||||
}
|
||||
|
||||
try {
|
||||
config.privateKey = EncryptionUtil.getKeyFromFile(
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.geysermc.floodgate;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.geysermc.floodgate.util.BedrockData;
|
||||
import org.geysermc.floodgate.util.DeviceOS;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -26,7 +27,7 @@ public class FloodgatePlayer {
|
||||
/**
|
||||
* The operation system of the bedrock client
|
||||
*/
|
||||
private FloodgateAPI.DeviceOS deviceOS;
|
||||
private DeviceOS deviceOS;
|
||||
/**
|
||||
* The language code of the bedrock client
|
||||
*/
|
||||
@@ -41,8 +42,8 @@ public class FloodgatePlayer {
|
||||
username = data.getUsername();
|
||||
javaUsername = "*" + data.getUsername().substring(0, Math.min(data.getUsername().length(), 15));
|
||||
xuid = data.getXuid();
|
||||
deviceOS = FloodgateAPI.DeviceOS.getById(data.getDeviceId());
|
||||
deviceOS = DeviceOS.getById(data.getDeviceId());
|
||||
languageCode = data.getLanguageCode();
|
||||
javaUniqueId = FloodgateAPI.createJavaPlayerId(Long.parseLong(data.getXuid()));
|
||||
javaUniqueId = AbstractFloodgateAPI.createJavaPlayerId(Long.parseLong(data.getXuid()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
package org.geysermc.floodgate;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import org.geysermc.floodgate.util.BedrockData;
|
||||
import org.geysermc.floodgate.util.EncryptionUtil;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
|
||||
import static org.geysermc.floodgate.util.BedrockData.EXPECTED_LENGTH;
|
||||
import static org.geysermc.floodgate.util.BedrockData.FLOODGATE_IDENTIFIER;
|
||||
|
||||
public class HandshakeHandler {
|
||||
private PrivateKey privateKey;
|
||||
private boolean bungee;
|
||||
|
||||
public HandshakeHandler(@NonNull PrivateKey privateKey, boolean bungee) {
|
||||
this.privateKey = privateKey;
|
||||
this.bungee = bungee;
|
||||
}
|
||||
|
||||
public HandshakeResult handle(@NonNull String handshakeData) {
|
||||
try {
|
||||
String[] data = handshakeData.split("\0");
|
||||
boolean isBungeeData = data.length == 6 || data.length == 7;
|
||||
|
||||
if (bungee && isBungeeData || !isBungeeData && data.length != 4 || !data[1].equals(FLOODGATE_IDENTIFIER)) {
|
||||
return ResultType.NOT_FLOODGATE_DATA.getCachedResult();
|
||||
}
|
||||
|
||||
BedrockData bedrockData = EncryptionUtil.decryptBedrockData(
|
||||
privateKey, data[2] + '\0' + data[3]
|
||||
);
|
||||
|
||||
if (bedrockData.getDataLength() != EXPECTED_LENGTH) {
|
||||
return ResultType.INVALID_DATA_LENGTH.getCachedResult();
|
||||
}
|
||||
|
||||
FloodgatePlayer player = new FloodgatePlayer(bedrockData);
|
||||
AbstractFloodgateAPI.players.put(player.getJavaUniqueId(), player);
|
||||
return new HandshakeResult(ResultType.SUCCESS, data, bedrockData, player);
|
||||
} catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
|
||||
e.printStackTrace();
|
||||
return ResultType.EXCEPTION.getCachedResult();
|
||||
}
|
||||
}
|
||||
|
||||
@AllArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
@Getter
|
||||
public static class HandshakeResult {
|
||||
private ResultType resultType;
|
||||
private String[] handshakeData;
|
||||
private BedrockData bedrockData;
|
||||
private FloodgatePlayer floodgatePlayer;
|
||||
}
|
||||
|
||||
public enum ResultType {
|
||||
EXCEPTION,
|
||||
NOT_FLOODGATE_DATA,
|
||||
INVALID_DATA_LENGTH,
|
||||
SUCCESS;
|
||||
|
||||
@Getter private HandshakeResult cachedResult;
|
||||
|
||||
ResultType() {
|
||||
cachedResult = new HandshakeResult(this, null, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package org.geysermc.floodgate.util;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
|
||||
|
||||
public enum DeviceOS {
|
||||
@JsonEnumDefaultValue
|
||||
UNKNOWN,
|
||||
ANDROID,
|
||||
IOS,
|
||||
OSX,
|
||||
FIREOS,
|
||||
GEARVR,
|
||||
HOLOLENS,
|
||||
WIN10,
|
||||
WIN32,
|
||||
DEDICATED,
|
||||
ORBIS,
|
||||
NX,
|
||||
SWITCH;
|
||||
|
||||
private static final DeviceOS[] VALUES = values();
|
||||
|
||||
public static DeviceOS getById(int id) {
|
||||
return id < VALUES.length ? VALUES[id] : VALUES[0];
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,24 @@
|
||||
package org.geysermc.floodgate.util;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.lang.reflect.AccessibleObject;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class ReflectionUtil {
|
||||
/*
|
||||
* Used in the Bukkit version
|
||||
/**
|
||||
* Prefix without dot<br>
|
||||
* Example net.minecraft.server.v1_8R3.PacketHandhakingInSetProtocol will become:<br>
|
||||
* net.minecraft.server.v1_8R3
|
||||
*/
|
||||
private static String nmsPackage = null;
|
||||
@Getter @Setter
|
||||
private static String prefix = null;
|
||||
|
||||
public static Class<?> getNMSClass(String className) {
|
||||
return getClass(nmsPackage + className);
|
||||
}
|
||||
|
||||
public static void setServerVersion(String serverVersion) {
|
||||
nmsPackage = "net.minecraft.server." + serverVersion + ".";
|
||||
public static Class<?> getPrefixedClass(String className) {
|
||||
return getClass(prefix +"."+ className);
|
||||
}
|
||||
|
||||
public static Class<?> getClass(String className) {
|
||||
@@ -101,8 +103,27 @@ public class ReflectionUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static Object invokeStatic(Class<?> clazz, String method) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
||||
return clazz.getDeclaredMethod(method).invoke(null);
|
||||
public static Object invoke(Object instance, Method method) {
|
||||
try {
|
||||
return method.invoke(instance);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T invokeCasted(Object instance, Method method, Class<T> cast) {
|
||||
return (T) invoke(instance, method);
|
||||
}
|
||||
|
||||
public static Object invokeStatic(Class<?> clazz, String method) {
|
||||
try {
|
||||
return getMethod(clazz, method).invoke(null);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static <T extends AccessibleObject> T makeAccessible(T accessibleObject) {
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
# In Floodgate bedrock player data is send encrypted
|
||||
# The following value should point to the key Floodgate generated.
|
||||
# The public key should be used for the Geyser(s) and the private key for
|
||||
# - bungeecord
|
||||
# - bukkit (craftbukkit, spigot etc.)
|
||||
# The public key should be used for the Geyser(s) and the private key for the Floodgate(s)
|
||||
key-file-name: key.pem
|
||||
|
||||
disconnect:
|
||||
|
||||
Reference in New Issue
Block a user