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