mirror of
https://github.com/GeyserMC/Floodgate.git
synced 2025-12-19 14:59:20 +00:00
Updated a few dependencies and made it easier to run on Geyser
This commit is contained in:
@@ -56,7 +56,7 @@ public class BungeePlatform extends FloodgatePlatform {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isProxy() {
|
||||
public boolean isProxy() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,8 +34,8 @@ import jakarta.inject.Named;
|
||||
import jakarta.inject.Singleton;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
import org.geysermc.floodgate.core.connection.FloodgateCommandPreprocessor;
|
||||
import org.geysermc.floodgate.core.connection.UserAudience;
|
||||
import org.geysermc.floodgate.core.connection.audience.FloodgateCommandPreprocessor;
|
||||
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
||||
import org.geysermc.floodgate.core.platform.command.CommandUtil;
|
||||
|
||||
@Factory
|
||||
|
||||
@@ -34,9 +34,9 @@ import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.api.GeyserApiBase;
|
||||
import org.geysermc.floodgate.core.connection.UserAudience;
|
||||
import org.geysermc.floodgate.core.connection.UserAudience.ConsoleAudience;
|
||||
import org.geysermc.floodgate.core.connection.UserAudience.PlayerAudience;
|
||||
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
||||
import org.geysermc.floodgate.core.connection.audience.UserAudience.ConsoleAudience;
|
||||
import org.geysermc.floodgate.core.connection.audience.UserAudience.PlayerAudience;
|
||||
import org.geysermc.floodgate.core.platform.command.CommandUtil;
|
||||
import org.geysermc.floodgate.core.util.LanguageManager;
|
||||
import org.geysermc.floodgate.core.util.Utils;
|
||||
|
||||
@@ -124,7 +124,7 @@ public abstract class FloodgatePlatform {
|
||||
context.close();
|
||||
}
|
||||
|
||||
abstract protected boolean isProxy();
|
||||
abstract public boolean isProxy();
|
||||
|
||||
public <T> T getBean(Class<T> clazz) {
|
||||
return context.getBean(clazz);
|
||||
|
||||
@@ -38,7 +38,7 @@ import org.geysermc.floodgate.core.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.core.connection.FloodgateHandshakeHandler;
|
||||
import org.geysermc.floodgate.core.connection.FloodgateHandshakeHandler.HandshakeResult;
|
||||
import org.geysermc.floodgate.core.connection.HostnameSeparationResult;
|
||||
import org.geysermc.floodgate.core.crypto.FloodgateDataCodec;
|
||||
import org.geysermc.floodgate.core.crypto.FloodgateFormatCodec;
|
||||
import org.geysermc.floodgate.core.util.Constants;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@@ -76,11 +76,11 @@ public abstract class CommonDataHandler extends ChannelInboundHandlerAdapter {
|
||||
return;
|
||||
}
|
||||
|
||||
if (separation.headerVersion() != FloodgateDataCodec.VERSION) {
|
||||
if (separation.headerVersion() != FloodgateFormatCodec.VERSION) {
|
||||
disablePacketQueue(true);
|
||||
setKickMessage(String.format(
|
||||
Constants.UNSUPPORTED_DATA_VERSION,
|
||||
FloodgateDataCodec.VERSION, separation.headerVersion()
|
||||
FloodgateFormatCodec.VERSION, separation.headerVersion()
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ public class HandshakeDataImpl implements HandshakeData {
|
||||
this.javaUniqueId = javaUniqueId;
|
||||
}
|
||||
|
||||
public FloodgateConnection applyChanges(FloodgateConnection connection, String hostname, FloodgateConfig config) {
|
||||
public FloodgateConnection applyChanges(FloodgateConnection connection, FloodgateConfig config) {
|
||||
var newLink = !Objects.equals(connection.linkedPlayer(), this.linkedPlayer) ? this.linkedPlayer : null;
|
||||
|
||||
var thisIp = convertIp(this.ip);
|
||||
@@ -94,7 +94,7 @@ public class HandshakeDataImpl implements HandshakeData {
|
||||
}
|
||||
|
||||
var builder = new FloodgateConnectionBuilder(config);
|
||||
connection.fillBuilder(builder);
|
||||
// connection.fillBuilder(builder); todo probably remove handshake handlers all together
|
||||
if (newLink != null) builder.linkedPlayer(newLink);
|
||||
if (newIp != null) builder.ip(newIp);
|
||||
return builder.build();
|
||||
|
||||
@@ -28,14 +28,14 @@ package org.geysermc.floodgate.core.api;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import org.geysermc.floodgate.core.crypto.FloodgateDataCodec;
|
||||
import org.geysermc.floodgate.core.crypto.FloodgateFormatCodec;
|
||||
import org.geysermc.floodgate.core.scope.ProxyOnly;
|
||||
import org.geysermc.floodgate.util.BedrockData;
|
||||
|
||||
@ProxyOnly
|
||||
@Singleton
|
||||
public final class ProxyFloodgateApi extends SimpleFloodgateApi {
|
||||
@Inject FloodgateDataCodec dataCodec;
|
||||
@Inject FloodgateFormatCodec dataCodec;
|
||||
|
||||
public byte[] createEncryptedData(BedrockData bedrockData) {
|
||||
try {
|
||||
|
||||
@@ -39,10 +39,10 @@ import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.core.api.SimpleFloodgateApi;
|
||||
import org.geysermc.floodgate.core.command.util.Permission;
|
||||
import org.geysermc.floodgate.core.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.core.connection.UserAudience;
|
||||
import org.geysermc.floodgate.core.connection.UserAudience.PlayerAudience;
|
||||
import org.geysermc.floodgate.core.connection.audience.ProfileAudience;
|
||||
import org.geysermc.floodgate.core.connection.audience.ProfileAudienceArgument;
|
||||
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
||||
import org.geysermc.floodgate.core.connection.audience.UserAudience.PlayerAudience;
|
||||
import org.geysermc.floodgate.core.link.CommonPlayerLink;
|
||||
import org.geysermc.floodgate.core.link.GlobalPlayerLinking;
|
||||
import org.geysermc.floodgate.core.link.LinkVerificationException;
|
||||
|
||||
@@ -31,7 +31,7 @@ import cloud.commandframework.context.CommandContext;
|
||||
import jakarta.inject.Singleton;
|
||||
import org.geysermc.api.Geyser;
|
||||
import org.geysermc.floodgate.core.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.core.connection.UserAudience;
|
||||
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
||||
import org.geysermc.floodgate.core.platform.command.FloodgateCommand;
|
||||
import org.geysermc.floodgate.core.util.Constants;
|
||||
|
||||
|
||||
@@ -34,8 +34,8 @@ import jakarta.inject.Singleton;
|
||||
import lombok.Getter;
|
||||
import org.geysermc.floodgate.core.command.util.Permission;
|
||||
import org.geysermc.floodgate.core.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.core.connection.UserAudience;
|
||||
import org.geysermc.floodgate.core.connection.UserAudience.PlayerAudience;
|
||||
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
||||
import org.geysermc.floodgate.core.connection.audience.UserAudience.PlayerAudience;
|
||||
import org.geysermc.floodgate.core.link.CommonPlayerLink;
|
||||
import org.geysermc.floodgate.core.link.GlobalPlayerLinking;
|
||||
import org.geysermc.floodgate.core.platform.command.FloodgateCommand;
|
||||
|
||||
@@ -38,9 +38,9 @@ import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.core.command.util.Permission;
|
||||
import org.geysermc.floodgate.core.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.core.config.ProxyFloodgateConfig;
|
||||
import org.geysermc.floodgate.core.connection.UserAudience;
|
||||
import org.geysermc.floodgate.core.connection.audience.ProfileAudience;
|
||||
import org.geysermc.floodgate.core.connection.audience.ProfileAudienceArgument;
|
||||
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
||||
import org.geysermc.floodgate.core.http.xbox.XboxClient;
|
||||
import org.geysermc.floodgate.core.platform.command.CommandUtil;
|
||||
import org.geysermc.floodgate.core.platform.command.FloodgateCommand;
|
||||
|
||||
@@ -35,7 +35,7 @@ import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import org.geysermc.floodgate.core.command.util.Permission;
|
||||
import org.geysermc.floodgate.core.connection.UserAudience;
|
||||
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
||||
import org.geysermc.floodgate.core.platform.command.FloodgateSubCommand;
|
||||
import org.geysermc.floodgate.core.util.Constants;
|
||||
import org.geysermc.floodgate.core.util.HttpClient;
|
||||
|
||||
@@ -35,7 +35,7 @@ import cloud.commandframework.context.CommandContext;
|
||||
import jakarta.inject.Singleton;
|
||||
import java.util.Locale;
|
||||
import org.geysermc.floodgate.core.command.util.Permission;
|
||||
import org.geysermc.floodgate.core.connection.UserAudience;
|
||||
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
||||
import org.geysermc.floodgate.core.platform.command.FloodgateCommand;
|
||||
import org.geysermc.floodgate.core.platform.command.FloodgateSubCommand;
|
||||
import org.geysermc.floodgate.core.platform.command.SubCommands;
|
||||
|
||||
@@ -33,7 +33,7 @@ import jakarta.inject.Inject;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.core.command.WhitelistCommand.Message;
|
||||
import org.geysermc.floodgate.core.command.util.Permission;
|
||||
import org.geysermc.floodgate.core.connection.UserAudience;
|
||||
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
||||
import org.geysermc.floodgate.core.platform.command.FloodgateSubCommand;
|
||||
import org.geysermc.floodgate.core.util.Constants;
|
||||
import org.geysermc.floodgate.core.util.HttpClient;
|
||||
|
||||
@@ -37,7 +37,6 @@ import lombok.Getter;
|
||||
import org.geysermc.configutils.ConfigUtilities;
|
||||
import org.geysermc.configutils.file.codec.PathFileCodec;
|
||||
import org.geysermc.configutils.updater.change.Changes;
|
||||
import org.geysermc.floodgate.core.crypto.FloodgateDataCodec;
|
||||
import org.geysermc.floodgate.core.scope.ProxyOnly;
|
||||
import org.geysermc.floodgate.core.scope.ServerOnly;
|
||||
import org.geysermc.floodgate.core.util.GlobalBeanCache;
|
||||
@@ -47,12 +46,10 @@ import org.geysermc.floodgate.core.util.GlobalBeanCache;
|
||||
@BootstrapContextCompatible
|
||||
public final class ConfigLoader {
|
||||
private final Path dataDirectory;
|
||||
private final FloodgateDataCodec dataCodec;
|
||||
|
||||
@Inject
|
||||
ConfigLoader(@Named("dataDirectory") Path dataDirectory, FloodgateDataCodec dataCodec) {
|
||||
ConfigLoader(@Named("dataDirectory") Path dataDirectory) {
|
||||
this.dataDirectory = dataDirectory;
|
||||
this.dataCodec = dataCodec;
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -27,17 +27,11 @@ package org.geysermc.floodgate.core.connection;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.UUID;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.checkerframework.common.value.qual.IntRange;
|
||||
import org.geysermc.api.Geyser;
|
||||
import org.geysermc.api.connection.Connection;
|
||||
import org.geysermc.api.util.BedrockPlatform;
|
||||
import org.geysermc.api.util.InputMode;
|
||||
import org.geysermc.api.util.UiProfile;
|
||||
import org.geysermc.cumulus.form.Form;
|
||||
import org.geysermc.cumulus.form.util.FormBuilder;
|
||||
import org.geysermc.floodgate.core.api.legacy.LegacyPlayerWrapper;
|
||||
@@ -45,87 +39,19 @@ import org.geysermc.floodgate.core.api.legacy.PropertyGlue;
|
||||
import org.geysermc.floodgate.util.BedrockData;
|
||||
import org.geysermc.floodgate.util.LinkedPlayer;
|
||||
|
||||
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
|
||||
public final class FloodgateConnection implements Connection {
|
||||
private final String version;
|
||||
private final String username;
|
||||
private final UUID identifier;
|
||||
private final String xuid;
|
||||
private final String javaUsername;
|
||||
private final UUID javaUniqueId;
|
||||
private final BedrockPlatform deviceOs;
|
||||
private final String languageCode;
|
||||
private final UiProfile uiProfile;
|
||||
private final InputMode inputMode;
|
||||
private final InetAddress ip;
|
||||
private final LinkedPlayer linkedPlayer;
|
||||
|
||||
private final int subscribeId;
|
||||
private final String verifyCode;
|
||||
|
||||
public abstract class FloodgateConnection implements Connection {
|
||||
private final PropertyGlue propertyGlue = new PropertyGlue();
|
||||
private LegacyPlayerWrapper legacyPlayer;
|
||||
|
||||
@Override
|
||||
public @NonNull String bedrockUsername() {
|
||||
return username;
|
||||
}
|
||||
public abstract @NonNull UUID identity();
|
||||
|
||||
public @NonNull UUID identifier() {
|
||||
return identifier;
|
||||
}
|
||||
public abstract @NonNull InetAddress ip();
|
||||
|
||||
@Override
|
||||
public @NonNull String xuid() {
|
||||
return xuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @MonotonicNonNull String javaUsername() {
|
||||
return linkedPlayer != null ? linkedPlayer.getJavaUsername() : javaUsername;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @MonotonicNonNull UUID javaUuid() {
|
||||
return linkedPlayer != null ? linkedPlayer.getJavaUniqueId() : javaUniqueId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull String version() {
|
||||
return version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull BedrockPlatform platform() {
|
||||
return deviceOs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull String languageCode() {
|
||||
return languageCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull UiProfile uiProfile() {
|
||||
return uiProfile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull InputMode inputMode() {
|
||||
return inputMode;
|
||||
}
|
||||
|
||||
public @NonNull InetAddress ip() {
|
||||
return ip;
|
||||
}
|
||||
public abstract @MonotonicNonNull LinkedPlayer linkedPlayer();
|
||||
|
||||
@Override
|
||||
public boolean isLinked() {
|
||||
return linkedPlayer != null;
|
||||
}
|
||||
|
||||
public @Nullable LinkedPlayer linkedPlayer() {
|
||||
return linkedPlayer;
|
||||
return linkedPlayer() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -143,29 +69,16 @@ public final class FloodgateConnection implements Connection {
|
||||
return Geyser.api().transfer(javaUuid(), address, port);
|
||||
}
|
||||
|
||||
public void fillBuilder(FloodgateConnectionBuilder builder) {
|
||||
builder.version(version)
|
||||
.username(username)
|
||||
.identifier(identifier)
|
||||
.xuid(xuid)
|
||||
.deviceOs(deviceOs)
|
||||
.languageCode(languageCode)
|
||||
.uiProfile(uiProfile)
|
||||
.inputMode(inputMode)
|
||||
.ip(ip)
|
||||
.linkedPlayer(linkedPlayer);
|
||||
}
|
||||
|
||||
public BedrockData toBedrockData() {
|
||||
return BedrockData.of(
|
||||
version, username, xuid, deviceOs.ordinal(), languageCode, uiProfile.ordinal(),
|
||||
inputMode.ordinal(), ip.getHostAddress(), linkedPlayer, false, subscribeId, verifyCode
|
||||
version(), bedrockUsername(), xuid(), platform().ordinal(), languageCode(), uiProfile().ordinal(),
|
||||
inputMode().ordinal(), ip().getHostAddress(), linkedPlayer(), false, 0, null
|
||||
);
|
||||
}
|
||||
|
||||
public LegacyPlayerWrapper legacySelf() {
|
||||
if (legacyPlayer == null) {
|
||||
legacyPlayer = new LegacyPlayerWrapper(this, javaUsername, javaUniqueId);
|
||||
legacyPlayer = new LegacyPlayerWrapper(this, javaUsername(), javaUuid());
|
||||
}
|
||||
return legacyPlayer;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ public class FloodgateConnectionBuilder {
|
||||
private final FloodgateConfig config;
|
||||
private String version;
|
||||
private String username;
|
||||
private UUID identifier;
|
||||
private UUID identity;
|
||||
private String xuid;
|
||||
private BedrockPlatform deviceOs;
|
||||
private String languageCode;
|
||||
@@ -64,8 +64,8 @@ public class FloodgateConnectionBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public @This FloodgateConnectionBuilder identifier(UUID identifier) {
|
||||
this.identifier = Objects.requireNonNull(identifier);
|
||||
public @This FloodgateConnectionBuilder identity(UUID identity) {
|
||||
this.identity = Objects.requireNonNull(identity);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -108,10 +108,10 @@ public class FloodgateConnectionBuilder {
|
||||
// todo add an option to use identity instead of xuid
|
||||
UUID javaUniqueId = Utils.getJavaUuid(xuid);
|
||||
|
||||
return new FloodgateConnection(
|
||||
return new StandaloneFloodgateConnection(
|
||||
version,
|
||||
username,
|
||||
identifier,
|
||||
identity,
|
||||
xuid,
|
||||
javaUsername(),
|
||||
javaUniqueId,
|
||||
@@ -120,9 +120,7 @@ public class FloodgateConnectionBuilder {
|
||||
uiProfile,
|
||||
inputMode,
|
||||
ip,
|
||||
linkedPlayer,
|
||||
0,
|
||||
null
|
||||
linkedPlayer
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ import jakarta.inject.Inject;
|
||||
import jakarta.inject.Named;
|
||||
import jakarta.inject.Singleton;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionException;
|
||||
@@ -51,6 +50,8 @@ import org.geysermc.floodgate.core.api.SimpleFloodgateApi;
|
||||
import org.geysermc.floodgate.core.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.core.connection.codec.FloodgateConnectionCodec;
|
||||
import org.geysermc.floodgate.core.crypto.FloodgateDataCodec;
|
||||
import org.geysermc.floodgate.core.crypto.FloodgateFormatCodec;
|
||||
import org.geysermc.floodgate.core.crypto.exception.UnsupportedVersionException;
|
||||
import org.geysermc.floodgate.core.link.CommonPlayerLink;
|
||||
import org.geysermc.floodgate.core.skin.SkinUploadManager;
|
||||
import org.geysermc.floodgate.core.util.Constants;
|
||||
@@ -89,7 +90,7 @@ public final class FloodgateHandshakeHandler {
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (String value : hostnameItems) {
|
||||
int version = FloodgateDataCodec.version(value);
|
||||
int version = FloodgateFormatCodec.version(value);
|
||||
if (floodgateData == null && version != -1) {
|
||||
floodgateData = value;
|
||||
dataVersion = version;
|
||||
@@ -110,36 +111,32 @@ public final class FloodgateHandshakeHandler {
|
||||
@NonNull String floodgateDataString,
|
||||
@NonNull String hostname
|
||||
) {
|
||||
System.out.println("received: " + floodgateDataString);
|
||||
byte[] floodgateData = floodgateDataString.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
|
||||
ByteBuffer decoded;
|
||||
try {
|
||||
// the actual decryption of the data
|
||||
decoded = dataCodec.decode(floodgateData);
|
||||
} catch (InvalidFormatException e) {
|
||||
// when the Floodgate format couldn't be found
|
||||
throw callHandlerAndReturnResult(NOT_FLOODGATE_DATA, channel, hostname);
|
||||
} catch (Exception exception) {
|
||||
// all the other exceptions are caused by invalid/tempered Floodgate data
|
||||
if (config.debug()) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
|
||||
throw callHandlerAndReturnResult(ResultType.DECRYPT_ERROR, channel, hostname);
|
||||
}
|
||||
|
||||
FloodgateConnection connection;
|
||||
try {
|
||||
connection = connectionCodec.decode(decoded);
|
||||
} catch (Exception exception) {
|
||||
// todo probably add a format version as that's the most likely reason for this error
|
||||
// the actual decrypt/verify of the data
|
||||
connection = dataCodec.decode(floodgateData);
|
||||
} catch (InvalidFormatException exception) {
|
||||
// when the Floodgate format couldn't be found
|
||||
throw callHandlerAndReturnResult(NOT_FLOODGATE_DATA, channel, hostname);
|
||||
} catch (UnsupportedVersionException exception) {
|
||||
// unsupported format version
|
||||
if (config.debug()) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
|
||||
throw callHandlerAndReturnResult(INVALID_DATA, channel, hostname);
|
||||
} catch (Exception exception) {
|
||||
// all the other exceptions are caused by invalid/tempered Floodgate data
|
||||
if (config.debug() || true) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
|
||||
throw callHandlerAndReturnResult(ResultType.DECRYPT_ERROR, channel, hostname);
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -206,9 +203,11 @@ public final class FloodgateHandshakeHandler {
|
||||
// bedrockData.getVerifyCode());
|
||||
// }
|
||||
|
||||
connection = handshakeData.applyChanges(connection, hostname, config);
|
||||
connection = handshakeData.applyChanges(connection, config);
|
||||
|
||||
connectionManager.addConnection(connection);
|
||||
//todo when splitting up between netty and non-netty make a NettyConnectionManager which
|
||||
// uses the channel as argument to set the attribute
|
||||
channel.attr(playerAttribute).set(connection);
|
||||
|
||||
return new HandshakeResult(ResultType.SUCCESS, handshakeData, connection);
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
package org.geysermc.floodgate.core.connection;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.UUID;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.api.util.BedrockPlatform;
|
||||
import org.geysermc.api.util.InputMode;
|
||||
import org.geysermc.api.util.UiProfile;
|
||||
import org.geysermc.floodgate.util.LinkedPlayer;
|
||||
|
||||
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
|
||||
public final class StandaloneFloodgateConnection extends FloodgateConnection {
|
||||
private final String version;
|
||||
private final String username;
|
||||
private final UUID identity;
|
||||
private final String xuid;
|
||||
private final String javaUsername;
|
||||
private final UUID javaUniqueId;
|
||||
private final BedrockPlatform deviceOs;
|
||||
private final String languageCode;
|
||||
private final UiProfile uiProfile;
|
||||
private final InputMode inputMode;
|
||||
private final InetAddress ip;
|
||||
private final LinkedPlayer linkedPlayer;
|
||||
|
||||
@Override
|
||||
public @NonNull String bedrockUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public @NonNull UUID identity() {
|
||||
return identity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull String xuid() {
|
||||
return xuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @MonotonicNonNull String javaUsername() {
|
||||
return linkedPlayer != null ? linkedPlayer.getJavaUsername() : javaUsername;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @MonotonicNonNull UUID javaUuid() {
|
||||
return linkedPlayer != null ? linkedPlayer.getJavaUniqueId() : javaUniqueId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull String version() {
|
||||
return version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull BedrockPlatform platform() {
|
||||
return deviceOs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull String languageCode() {
|
||||
return languageCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull UiProfile uiProfile() {
|
||||
return uiProfile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull InputMode inputMode() {
|
||||
return inputMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull InetAddress ip() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable LinkedPlayer linkedPlayer() {
|
||||
return linkedPlayer;
|
||||
}
|
||||
|
||||
public void fillBuilder(FloodgateConnectionBuilder builder) {
|
||||
builder.version(version)
|
||||
.username(username)
|
||||
.identity(identity)
|
||||
.xuid(xuid)
|
||||
.deviceOs(deviceOs)
|
||||
.languageCode(languageCode)
|
||||
.uiProfile(uiProfile)
|
||||
.inputMode(inputMode)
|
||||
.ip(ip)
|
||||
.linkedPlayer(linkedPlayer);
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@
|
||||
* @link https://github.com/GeyserMC/Floodgate
|
||||
*/
|
||||
|
||||
package org.geysermc.floodgate.core.connection;
|
||||
package org.geysermc.floodgate.core.connection.audience;
|
||||
|
||||
import cloud.commandframework.execution.preprocessor.CommandPreprocessingContext;
|
||||
import cloud.commandframework.execution.preprocessor.CommandPreprocessor;
|
||||
@@ -37,7 +37,6 @@ import java.util.Queue;
|
||||
import java.util.UUID;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.floodgate.core.connection.UserAudience;
|
||||
import org.geysermc.floodgate.core.platform.command.CommandUtil;
|
||||
import org.geysermc.floodgate.core.platform.util.PlayerType;
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
* @link https://github.com/GeyserMC/Floodgate
|
||||
*/
|
||||
|
||||
package org.geysermc.floodgate.core.connection;
|
||||
package org.geysermc.floodgate.core.connection.audience;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
@@ -42,6 +42,7 @@ final class CodecUtils {
|
||||
|
||||
public static String readString(ByteBuffer buffer) {
|
||||
var bytes = new byte[readVarInt(buffer)];
|
||||
buffer.get(bytes);
|
||||
return new String(bytes, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ public final class FloodgateConnectionCodec {
|
||||
private void encode0(FloodgateConnection connection, DataOutputStream stream) throws IOException {
|
||||
writeString(stream, connection.version());
|
||||
writeString(stream, connection.bedrockUsername());
|
||||
writeUniqueId(stream, connection.identifier());
|
||||
writeUniqueId(stream, connection.identity());
|
||||
writeUnsignedLong(stream, connection.xuid());
|
||||
stream.writeByte(connection.platform().ordinal());
|
||||
writeString(stream, connection.languageCode());
|
||||
@@ -84,7 +84,7 @@ public final class FloodgateConnectionCodec {
|
||||
var builder = new FloodgateConnectionBuilder(config)
|
||||
.version(readString(buffer))
|
||||
.username(readString(buffer))
|
||||
.identifier(readUniqueId(buffer))
|
||||
.identity(readUniqueId(buffer))
|
||||
.xuid(readUnsignedLong(buffer))
|
||||
.deviceOs(BedrockPlatform.fromId(buffer.get()))
|
||||
.languageCode(readString(buffer))
|
||||
|
||||
@@ -1,141 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2023 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.core.crypto;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import jakarta.inject.Named;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Objects;
|
||||
import org.geysermc.floodgate.core.crypto.topping.Topping;
|
||||
import org.geysermc.floodgate.core.util.InvalidFormatException;
|
||||
import jakarta.inject.Singleton;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import org.geysermc.floodgate.core.connection.FloodgateConnection;
|
||||
import org.geysermc.floodgate.core.connection.codec.FloodgateConnectionCodec;
|
||||
|
||||
@Singleton
|
||||
public final class FloodgateDataCodec {
|
||||
public static final int VERSION = 2;
|
||||
public static final byte[] IDENTIFIER = "^Floodgate^".getBytes(UTF_8);
|
||||
public static final byte[] HEADER = (new String(IDENTIFIER, UTF_8) + (char) (VERSION + 0x3D)).getBytes(UTF_8);
|
||||
private final FloodgateFormatCodec formatCodec;
|
||||
private final FloodgateConnectionCodec connectionCodec;
|
||||
|
||||
private final DataCodec codec;
|
||||
|
||||
private final Topping topping;
|
||||
|
||||
public FloodgateDataCodec(
|
||||
DataCodecType type,
|
||||
Topping topping,
|
||||
@Named("dataDirectory") Path dataDirectory
|
||||
) throws IOException {
|
||||
Objects.requireNonNull(type);
|
||||
this.codec = type.dataCodec();
|
||||
this.topping = topping;
|
||||
|
||||
var keyCodecBase = type.keyCodec();
|
||||
if (type.asymmetrical()) {
|
||||
var keyPair = ((KeyCodecPair) keyCodecBase).decode(dataDirectory);
|
||||
((DataCodecKeyPair) codec).init(keyPair);
|
||||
} else {
|
||||
var key = ((KeyCodecSingle) keyCodecBase).decode(dataDirectory);
|
||||
codec.init(key);
|
||||
}
|
||||
public FloodgateDataCodec(FloodgateFormatCodec formatCodec, FloodgateConnectionCodec connectionCodec) {
|
||||
this.formatCodec = formatCodec;
|
||||
this.connectionCodec = connectionCodec;
|
||||
}
|
||||
|
||||
public static int version(String data) {
|
||||
if (data.length() < HEADER.length) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < IDENTIFIER.length; i++) {
|
||||
if (IDENTIFIER[i] != data.charAt(i)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return data.charAt(IDENTIFIER.length) - 0x3D;
|
||||
public byte[] encode(FloodgateConnection connection) throws Exception {
|
||||
return formatCodec.encode(connectionCodec.encode(connection));
|
||||
}
|
||||
|
||||
public byte[] encode(ByteBuffer data) throws Exception {
|
||||
var encryptedSections = codec.encode(data);
|
||||
var encodedData = topping.encode(encryptedSections);
|
||||
|
||||
return ByteBuffer.allocate(HEADER.length + encodedData.remaining())
|
||||
.put(HEADER)
|
||||
.put(encodedData)
|
||||
.array();
|
||||
public String encodeToString(FloodgateConnection connection) throws Exception {
|
||||
return new String(encode(connection), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public byte[] encodeFromString(String data) throws Exception {
|
||||
return encode(ByteBuffer.wrap(data.getBytes(UTF_8)));
|
||||
}
|
||||
|
||||
public ByteBuffer decode(byte[] data) throws Exception {
|
||||
checkHeader(data);
|
||||
|
||||
int bufferLength = data.length - HEADER.length;
|
||||
ByteBuffer buffer = ByteBuffer.wrap(data, HEADER.length, bufferLength);
|
||||
|
||||
var encryptedSections = topping.decode(buffer);
|
||||
return codec.decode(encryptedSections);
|
||||
}
|
||||
|
||||
public String decodeToString(byte[] data) throws Exception {
|
||||
ByteBuffer decrypted = decode(data);
|
||||
|
||||
byte[] decryptedBytes = new byte[decrypted.remaining()];
|
||||
decrypted.get(decryptedBytes);
|
||||
|
||||
return new String(decryptedBytes, UTF_8);
|
||||
}
|
||||
|
||||
public ByteBuffer decodeFromString(String data) throws Exception {
|
||||
return decode(data.getBytes(UTF_8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the header is valid
|
||||
*
|
||||
* @param data the data to check
|
||||
* @throws InvalidFormatException when the header is invalid
|
||||
*/
|
||||
public void checkHeader(byte[] data) throws InvalidFormatException {
|
||||
if (data.length < HEADER.length) {
|
||||
throw new InvalidFormatException(
|
||||
"Data length is smaller then header." +
|
||||
"Needed " + HEADER.length + ", got " + data.length
|
||||
);
|
||||
}
|
||||
|
||||
for (int i = 0; i < IDENTIFIER.length; i++) {
|
||||
if (IDENTIFIER[i] != data[i]) {
|
||||
String identifier = new String(IDENTIFIER, UTF_8);
|
||||
String received = new String(data, 0, IDENTIFIER.length, UTF_8);
|
||||
throw new InvalidFormatException(
|
||||
"Expected identifier " + identifier + ", got " + received
|
||||
);
|
||||
}
|
||||
}
|
||||
public FloodgateConnection decode(byte[] data) throws Exception {
|
||||
return connectionCodec.decode(formatCodec.decode(data));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2023 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.core.crypto;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import jakarta.inject.Named;
|
||||
import jakarta.inject.Singleton;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Objects;
|
||||
import org.geysermc.floodgate.core.crypto.exception.UnsupportedVersionException;
|
||||
import org.geysermc.floodgate.core.crypto.topping.Topping;
|
||||
import org.geysermc.floodgate.core.util.InvalidFormatException;
|
||||
|
||||
@Singleton
|
||||
public final class FloodgateFormatCodec {
|
||||
public static final int VERSION = 2;
|
||||
public static final byte[] IDENTIFIER = "^Floodgate^".getBytes(UTF_8);
|
||||
public static final byte[] HEADER = (new String(IDENTIFIER, UTF_8) + (char) (VERSION + 0x3D)).getBytes(UTF_8);
|
||||
|
||||
private final DataCodec codec;
|
||||
|
||||
private final Topping topping;
|
||||
|
||||
public FloodgateFormatCodec(
|
||||
DataCodecType type,
|
||||
Topping topping,
|
||||
@Named("dataDirectory") Path dataDirectory
|
||||
) throws IOException {
|
||||
Objects.requireNonNull(type);
|
||||
this.codec = type.dataCodec();
|
||||
this.topping = topping;
|
||||
|
||||
var keyCodecBase = type.keyCodec();
|
||||
if (type.asymmetrical()) {
|
||||
var keyPair = ((KeyCodecPair) keyCodecBase).decode(dataDirectory);
|
||||
((DataCodecKeyPair) codec).init(keyPair);
|
||||
} else {
|
||||
var key = ((KeyCodecSingle) keyCodecBase).decode(dataDirectory);
|
||||
codec.init(key);
|
||||
}
|
||||
}
|
||||
|
||||
public static int version(String data) {
|
||||
if (data.length() < HEADER.length) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < IDENTIFIER.length; i++) {
|
||||
if (IDENTIFIER[i] != data.charAt(i)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return data.charAt(IDENTIFIER.length) - 0x3D;
|
||||
}
|
||||
|
||||
public byte[] encode(ByteBuffer data) throws Exception {
|
||||
var encryptedSections = codec.encode(data);
|
||||
var encodedData = topping.encode(encryptedSections);
|
||||
|
||||
return ByteBuffer.allocate(HEADER.length + encodedData.remaining())
|
||||
.put(HEADER)
|
||||
.put(encodedData)
|
||||
.array();
|
||||
}
|
||||
|
||||
public byte[] encodeFromString(String data) throws Exception {
|
||||
return encode(ByteBuffer.wrap(data.getBytes(UTF_8)));
|
||||
}
|
||||
|
||||
public ByteBuffer decode(byte[] data) throws Exception {
|
||||
validateHeader(data);
|
||||
|
||||
int bufferLength = data.length - HEADER.length;
|
||||
ByteBuffer buffer = ByteBuffer.wrap(data, HEADER.length, bufferLength);
|
||||
|
||||
var encryptedSections = topping.decode(buffer);
|
||||
return codec.decode(encryptedSections);
|
||||
}
|
||||
|
||||
public String decodeToString(byte[] data) throws Exception {
|
||||
ByteBuffer decrypted = decode(data);
|
||||
|
||||
byte[] decryptedBytes = new byte[decrypted.remaining()];
|
||||
decrypted.get(decryptedBytes);
|
||||
|
||||
return new String(decryptedBytes, UTF_8);
|
||||
}
|
||||
|
||||
public ByteBuffer decodeFromString(String data) throws Exception {
|
||||
return decode(data.getBytes(UTF_8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the header is valid
|
||||
*
|
||||
* @param data the data to check
|
||||
* @throws InvalidFormatException when the header is invalid
|
||||
*/
|
||||
public void validateHeader(byte[] data) throws InvalidFormatException, UnsupportedVersionException {
|
||||
if (data.length < HEADER.length) {
|
||||
throw new InvalidFormatException(
|
||||
"Data length is smaller then header." +
|
||||
"Needed " + HEADER.length + ", got " + data.length
|
||||
);
|
||||
}
|
||||
|
||||
for (int i = 0; i < IDENTIFIER.length; i++) {
|
||||
if (IDENTIFIER[i] != data[i]) {
|
||||
String identifier = new String(IDENTIFIER, UTF_8);
|
||||
String received = new String(data, 0, IDENTIFIER.length, UTF_8);
|
||||
throw new InvalidFormatException(
|
||||
"Expected identifier " + identifier + ", got " + received
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
var receivedVersion = data[IDENTIFIER.length] - 0x3D;
|
||||
|
||||
if (VERSION != receivedVersion) {
|
||||
throw new UnsupportedVersionException(VERSION, receivedVersion);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.geysermc.floodgate.core.crypto.exception;
|
||||
|
||||
public final class UnsupportedVersionException extends Exception {
|
||||
public UnsupportedVersionException(int expected, int received) {
|
||||
super("Expected Floodgate data version " + expected + ", received version " + received);
|
||||
}
|
||||
}
|
||||
@@ -41,6 +41,8 @@ import org.geysermc.floodgate.core.database.PlayerLinkRepository;
|
||||
import org.geysermc.floodgate.core.database.entity.LinkRequest;
|
||||
import org.geysermc.floodgate.core.database.entity.LinkedPlayer;
|
||||
|
||||
@Requires(property = "config.database.enabled", value = "true")
|
||||
@Requires(property = "config.playerLink.enabled", value = "true")
|
||||
@Requires(property = "config.playerLink.enableOwnLinking", value = "true")
|
||||
@Replaces(DisabledPlayerLink.class)
|
||||
@Named("localLinking")
|
||||
|
||||
@@ -31,7 +31,6 @@ import io.micronaut.context.annotation.Factory;
|
||||
import io.netty.util.AttributeKey;
|
||||
import jakarta.inject.Named;
|
||||
import jakarta.inject.Singleton;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
@@ -42,7 +41,6 @@ import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.geysermc.api.connection.Connection;
|
||||
import org.geysermc.floodgate.core.crypto.DataCodecType;
|
||||
import org.geysermc.floodgate.core.crypto.FloodgateDataCodec;
|
||||
import org.geysermc.floodgate.core.crypto.topping.Base64Topping;
|
||||
import org.geysermc.floodgate.core.crypto.topping.Topping;
|
||||
import org.geysermc.floodgate.core.util.Constants;
|
||||
@@ -91,24 +89,6 @@ public class CommonModule {
|
||||
return GlobalBeanCache.cacheIfAbsent("topping", Base64Topping::new);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@BootstrapContextCompatible
|
||||
@Singleton
|
||||
public FloodgateDataCodec dataCodec(
|
||||
DataCodecType type,
|
||||
Topping topping,
|
||||
@Named("dataDirectory") Path dataDirectory
|
||||
) {
|
||||
//todo find a way to not use bootstrap context, yuk
|
||||
return GlobalBeanCache.cacheIfAbsent("dataCodec", () -> {
|
||||
try {
|
||||
return new FloodgateDataCodec(type, topping, dataDirectory);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Singleton
|
||||
@Named("gitBranch")
|
||||
|
||||
@@ -38,8 +38,8 @@ import lombok.RequiredArgsConstructor;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.api.GeyserApiBase;
|
||||
import org.geysermc.floodgate.core.connection.UserAudience;
|
||||
import org.geysermc.floodgate.core.connection.audience.ProfileAudience;
|
||||
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
||||
import org.geysermc.floodgate.core.platform.util.PlayerType;
|
||||
import org.geysermc.floodgate.core.util.LanguageManager;
|
||||
import org.geysermc.floodgate.core.util.Utils;
|
||||
|
||||
@@ -29,7 +29,7 @@ import cloud.commandframework.Command;
|
||||
import cloud.commandframework.CommandManager;
|
||||
import cloud.commandframework.context.CommandContext;
|
||||
import org.geysermc.floodgate.core.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.core.connection.UserAudience;
|
||||
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
||||
|
||||
/** The base class for every Floodgate command. */
|
||||
public interface FloodgateCommand {
|
||||
|
||||
@@ -27,7 +27,7 @@ package org.geysermc.floodgate.core.platform.command;
|
||||
|
||||
import cloud.commandframework.context.CommandContext;
|
||||
import org.geysermc.floodgate.core.command.util.Permission;
|
||||
import org.geysermc.floodgate.core.connection.UserAudience;
|
||||
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
||||
|
||||
public abstract class FloodgateSubCommand {
|
||||
public abstract Class<?> parent();
|
||||
|
||||
@@ -30,7 +30,7 @@ import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import java.util.Set;
|
||||
import org.geysermc.floodgate.core.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.core.connection.UserAudience;
|
||||
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
||||
import org.geysermc.floodgate.core.platform.command.FloodgateCommand;
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
package org.geysermc.floodgate.core.util;
|
||||
|
||||
public class InvalidFormatException extends Exception {
|
||||
public final class InvalidFormatException extends Exception {
|
||||
public InvalidFormatException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
package org.geysermc.floodgate.core.crypto;
|
||||
|
||||
import static org.geysermc.floodgate.core.crypto.FloodgateDataCodec.VERSION;
|
||||
import static org.geysermc.floodgate.core.crypto.FloodgateFormatCodec.VERSION;
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
@@ -35,6 +35,7 @@ import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Path;
|
||||
import org.geysermc.floodgate.core.crypto.exception.UnsupportedVersionException;
|
||||
import org.geysermc.floodgate.core.crypto.topping.Base64Topping;
|
||||
import org.geysermc.floodgate.core.util.InvalidFormatException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -43,7 +44,7 @@ import org.junit.jupiter.params.aggregator.ArgumentsAccessor;
|
||||
import org.junit.jupiter.params.provider.CsvSource;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
final class FloodgateDataCodecTest {
|
||||
final class FloodgateFormatCodecTest {
|
||||
@ParameterizedTest
|
||||
@CsvSource({
|
||||
"^Floodgate^, -1",
|
||||
@@ -53,7 +54,7 @@ final class FloodgateDataCodecTest {
|
||||
"^Floodgate^A, 4",
|
||||
})
|
||||
void version(ArgumentsAccessor arguments) {
|
||||
assertEquals(arguments.getInteger(1), FloodgateDataCodec.version(arguments.getString(0)));
|
||||
assertEquals(arguments.getInteger(1), FloodgateFormatCodec.version(arguments.getString(0)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -63,7 +64,7 @@ final class FloodgateDataCodecTest {
|
||||
|
||||
@Test
|
||||
void createWithSymmetricalKey() {
|
||||
assertDoesNotThrow(() -> new FloodgateDataCodec(
|
||||
assertDoesNotThrow(() -> new FloodgateFormatCodec(
|
||||
DataCodecType.AES,
|
||||
new Base64Topping(),
|
||||
Path.of("src/test/resources/crypto")
|
||||
@@ -115,31 +116,42 @@ final class FloodgateDataCodecTest {
|
||||
assertEquals(payloadExpected, payload);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {
|
||||
"^Floodgate^" + (VERSION - 1),
|
||||
"^Floodgate^" + VERSION,
|
||||
"^Floodgate^" + (VERSION + 1)
|
||||
})
|
||||
void headerValid(String value) throws IOException {
|
||||
var codec = createFloodgateDataCodec();
|
||||
assertDoesNotThrow(() -> codec.checkHeader(value.getBytes(StandardCharsets.UTF_8)));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {
|
||||
"^Floodgate^",
|
||||
"^Flootgate^="
|
||||
})
|
||||
void headerInvalid(String value) throws IOException {
|
||||
void headerInvalidFormat(String content) throws IOException {
|
||||
var codec = createFloodgateDataCodec();
|
||||
|
||||
assertThrowsExactly(
|
||||
InvalidFormatException.class,
|
||||
() -> codec.checkHeader(value.getBytes(StandardCharsets.UTF_8))
|
||||
() -> codec.validateHeader(content.getBytes(StandardCharsets.UTF_8))
|
||||
);
|
||||
}
|
||||
|
||||
private FloodgateDataCodec createFloodgateDataCodec() throws IOException {
|
||||
return new FloodgateDataCodec(DataCodecType.ED25519, new Base64Topping(), Path.of("src/test/resources/crypto"));
|
||||
@ParameterizedTest
|
||||
@CsvSource({
|
||||
(VERSION - 1) + ", false",
|
||||
VERSION + ", true",
|
||||
(VERSION + 1) + ", false"
|
||||
})
|
||||
void headerVersionValidation(ArgumentsAccessor arguments) throws IOException {
|
||||
var codec = createFloodgateDataCodec();
|
||||
|
||||
var version = arguments.getInteger(0);
|
||||
var content = ("^Floodgate^" + (char) (version + 0x3D)).getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
var valid = arguments.getBoolean(1);
|
||||
|
||||
if (valid) {
|
||||
assertDoesNotThrow(() -> codec.validateHeader(content));
|
||||
} else {
|
||||
assertThrowsExactly(UnsupportedVersionException.class, () -> codec.validateHeader(content));
|
||||
}
|
||||
}
|
||||
|
||||
private FloodgateFormatCodec createFloodgateDataCodec() throws IOException {
|
||||
return new FloodgateFormatCodec(DataCodecType.ED25519, new Base64Topping(), Path.of("src/test/resources/crypto"));
|
||||
}
|
||||
}
|
||||
@@ -4,4 +4,4 @@ org.gradle.parallel=true
|
||||
systemProp.org.gradle.unsafe.kotlin.assignment=true
|
||||
|
||||
version=2.2.2-SNAPSHOT
|
||||
micronautVersion=4.0.3
|
||||
micronautVersion=4.1.3
|
||||
@@ -1,6 +1,6 @@
|
||||
[versions]
|
||||
# parent
|
||||
micronaut-gradle = "4.0.2"
|
||||
micronaut-gradle = "4.1.1"
|
||||
lombok = "8.0.1"
|
||||
|
||||
# api
|
||||
@@ -29,8 +29,8 @@ authlib = "1.5.21"
|
||||
velocity = "3.1.1"
|
||||
|
||||
# buildSrc
|
||||
indra = "3.0.1"
|
||||
shadow = "7.1.1"
|
||||
indra = "3.1.3"
|
||||
shadow = "8.1.1"
|
||||
gradle-idea-ext = "1.1.7"
|
||||
checkerframework = "3.19.0"
|
||||
|
||||
@@ -96,7 +96,7 @@ checker-qual = { module = "org.checkerframework:checker-qual", version.ref = "ch
|
||||
# plugins
|
||||
indra-common = { module = "net.kyori:indra-common", version.ref = "indra" }
|
||||
indra-git = { module = "net.kyori:indra-git", version.ref = "indra" }
|
||||
shadow = { module = "gradle.plugin.com.github.johnrengelman:shadow", version.ref = "shadow" }
|
||||
shadow = { module = "com.github.johnrengelman:shadow", version.ref = "shadow" }
|
||||
gradle-idea-ext = { module = "gradle.plugin.org.jetbrains.gradle.plugin.idea-ext:gradle-idea-ext", version.ref = "gradle-idea-ext" }
|
||||
|
||||
[plugins]
|
||||
|
||||
@@ -69,7 +69,7 @@ public class SpigotPlatform extends FloodgatePlatform {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isProxy() {
|
||||
public boolean isProxy() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,8 +39,8 @@ import org.bukkit.permissions.PermissionDefault;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.geysermc.floodgate.core.command.util.Permission;
|
||||
import org.geysermc.floodgate.core.connection.FloodgateCommandPreprocessor;
|
||||
import org.geysermc.floodgate.core.connection.UserAudience;
|
||||
import org.geysermc.floodgate.core.connection.audience.FloodgateCommandPreprocessor;
|
||||
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
||||
import org.geysermc.floodgate.core.platform.command.CommandUtil;
|
||||
|
||||
@Factory
|
||||
|
||||
@@ -34,9 +34,9 @@ import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.api.GeyserApiBase;
|
||||
import org.geysermc.floodgate.core.connection.UserAudience;
|
||||
import org.geysermc.floodgate.core.connection.UserAudience.ConsoleAudience;
|
||||
import org.geysermc.floodgate.core.connection.UserAudience.PlayerAudience;
|
||||
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
||||
import org.geysermc.floodgate.core.connection.audience.UserAudience.ConsoleAudience;
|
||||
import org.geysermc.floodgate.core.connection.audience.UserAudience.PlayerAudience;
|
||||
import org.geysermc.floodgate.core.platform.command.CommandUtil;
|
||||
import org.geysermc.floodgate.core.util.LanguageManager;
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ public class VelocityPlatform extends FloodgatePlatform {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isProxy() {
|
||||
public boolean isProxy() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,8 +35,8 @@ import io.micronaut.context.annotation.Bean;
|
||||
import io.micronaut.context.annotation.Factory;
|
||||
import jakarta.inject.Named;
|
||||
import jakarta.inject.Singleton;
|
||||
import org.geysermc.floodgate.core.connection.FloodgateCommandPreprocessor;
|
||||
import org.geysermc.floodgate.core.connection.UserAudience;
|
||||
import org.geysermc.floodgate.core.connection.audience.FloodgateCommandPreprocessor;
|
||||
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
||||
import org.geysermc.floodgate.core.platform.command.CommandUtil;
|
||||
|
||||
@Factory
|
||||
|
||||
@@ -36,9 +36,9 @@ import java.util.UUID;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.api.GeyserApiBase;
|
||||
import org.geysermc.floodgate.core.connection.UserAudience;
|
||||
import org.geysermc.floodgate.core.connection.UserAudience.ConsoleAudience;
|
||||
import org.geysermc.floodgate.core.connection.UserAudience.PlayerAudience;
|
||||
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
||||
import org.geysermc.floodgate.core.connection.audience.UserAudience.ConsoleAudience;
|
||||
import org.geysermc.floodgate.core.connection.audience.UserAudience.PlayerAudience;
|
||||
import org.geysermc.floodgate.core.platform.command.CommandUtil;
|
||||
import org.geysermc.floodgate.core.util.LanguageManager;
|
||||
import org.geysermc.floodgate.core.util.Utils;
|
||||
|
||||
Reference in New Issue
Block a user