1
0
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:
Tim203
2020-02-22 16:32:20 +01:00
parent 580ae0dcf0
commit 7edff139cc
26 changed files with 702 additions and 214 deletions

View File

@@ -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];
}
}
}

View File

@@ -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(

View File

@@ -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()));
}
}

View File

@@ -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);
}
}
}

View File

@@ -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];
}
}

View File

@@ -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) {

View File

@@ -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: