mirror of
https://github.com/GeyserMC/Floodgate.git
synced 2025-12-19 14:59:20 +00:00
Added PMD Plugin and changed isBedrockPlayer to isFloodgatePlayer
This commit is contained in:
@@ -36,7 +36,7 @@ public interface FloodgateApi {
|
|||||||
* Returns the Floodgate API instance.
|
* Returns the Floodgate API instance.
|
||||||
*/
|
*/
|
||||||
static FloodgateApi getInstance() {
|
static FloodgateApi getInstance() {
|
||||||
return InstanceHolder.getInstance();
|
return InstanceHolder.getApi();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -45,7 +45,7 @@ public interface FloodgateApi {
|
|||||||
* @param uuid The uuid of the <b>online</b> player
|
* @param uuid The uuid of the <b>online</b> player
|
||||||
* @return true if the given <b>online</b> player is a Bedrock player
|
* @return true if the given <b>online</b> player is a Bedrock player
|
||||||
*/
|
*/
|
||||||
boolean isBedrockPlayer(UUID uuid);
|
boolean isFloodgatePlayer(UUID uuid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get info about the given Bedrock player
|
* Get info about the given Bedrock player
|
||||||
@@ -66,7 +66,7 @@ public interface FloodgateApi {
|
|||||||
/**
|
/**
|
||||||
* Checks if the uuid of the player has the {@link #createJavaPlayerId(long)} format. This
|
* Checks if the uuid of the player has the {@link #createJavaPlayerId(long)} format. This
|
||||||
* method can't validate a linked player uuid, since that doesn't equal the format. Use {@link
|
* method can't validate a linked player uuid, since that doesn't equal the format. Use {@link
|
||||||
* #isBedrockPlayer(UUID)} if you want to include linked accounts.
|
* #isFloodgatePlayer(UUID)} if you want to include linked accounts.
|
||||||
*
|
*
|
||||||
* @param uuid the uuid to check
|
* @param uuid the uuid to check
|
||||||
* @return true if the given uuid has the correct format.
|
* @return true if the given uuid has the correct format.
|
||||||
|
|||||||
@@ -32,25 +32,28 @@ import org.geysermc.floodgate.api.inject.PlatformInjector;
|
|||||||
import org.geysermc.floodgate.api.link.PlayerLink;
|
import org.geysermc.floodgate.api.link.PlayerLink;
|
||||||
|
|
||||||
public final class InstanceHolder {
|
public final class InstanceHolder {
|
||||||
@Getter private static FloodgateApi instance;
|
@Getter private static FloodgateApi api;
|
||||||
@Getter private static PlayerLink playerLink;
|
@Getter private static PlayerLink playerLink;
|
||||||
@Getter private static PlatformInjector injector;
|
@Getter private static PlatformInjector injector;
|
||||||
@Getter private static HandshakeHandlers handshakeHandlers;
|
@Getter private static HandshakeHandlers handshakeHandlers;
|
||||||
private static UUID key;
|
private static UUID storedKey;
|
||||||
|
|
||||||
public static boolean setInstance(
|
public static boolean set(
|
||||||
FloodgateApi floodgateApi,
|
FloodgateApi floodgateApi,
|
||||||
PlayerLink link,
|
PlayerLink link,
|
||||||
PlatformInjector platformInjector,
|
PlatformInjector platformInjector,
|
||||||
HandshakeHandlers handshakeHandlers,
|
HandshakeHandlers handshakeHandlers,
|
||||||
UUID key
|
UUID key) {
|
||||||
) {
|
|
||||||
if (instance == null) {
|
if (storedKey != null) {
|
||||||
InstanceHolder.key = key;
|
if (!storedKey.equals(key)) {
|
||||||
} else if (!InstanceHolder.key.equals(key)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
instance = floodgateApi;
|
} else {
|
||||||
|
storedKey = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
api = floodgateApi;
|
||||||
playerLink = link;
|
playerLink = link;
|
||||||
injector = platformInjector;
|
injector = platformInjector;
|
||||||
InstanceHolder.handshakeHandlers = handshakeHandlers;
|
InstanceHolder.handshakeHandlers = handshakeHandlers;
|
||||||
@@ -59,6 +62,6 @@ public final class InstanceHolder {
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static <T extends FloodgateApi> T castApi(Class<T> cast) {
|
public static <T extends FloodgateApi> T castApi(Class<T> cast) {
|
||||||
return (T) instance;
|
return (T) api;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ package org.geysermc.floodgate.api.link;
|
|||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.geysermc.floodgate.util.LinkedPlayer;
|
import org.geysermc.floodgate.util.LinkedPlayer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -49,7 +50,8 @@ public interface PlayerLink {
|
|||||||
* @return a completable future with the {@link LinkedPlayer}. The future will have a null value
|
* @return a completable future with the {@link LinkedPlayer}. The future will have a null value
|
||||||
* if that Bedrock player isn't linked
|
* if that Bedrock player isn't linked
|
||||||
*/
|
*/
|
||||||
CompletableFuture<LinkedPlayer> getLinkedPlayer(UUID bedrockId);
|
@NonNull
|
||||||
|
CompletableFuture<LinkedPlayer> getLinkedPlayer(@NonNull UUID bedrockId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tells if the given player is a linked player
|
* Tells if the given player is a linked player
|
||||||
@@ -57,7 +59,8 @@ public interface PlayerLink {
|
|||||||
* @param playerId the uuid of the player to check, can be both a Java or a Bedrock uuid
|
* @param playerId the uuid of the player to check, can be both a Java or a Bedrock uuid
|
||||||
* @return true if the player is a linked player
|
* @return true if the player is a linked player
|
||||||
*/
|
*/
|
||||||
CompletableFuture<Boolean> isLinkedPlayer(UUID playerId);
|
@NonNull
|
||||||
|
CompletableFuture<Boolean> isLinkedPlayer(@NonNull UUID playerId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Links a Java account to a Bedrock account.
|
* Links a Java account to a Bedrock account.
|
||||||
@@ -67,7 +70,11 @@ public interface PlayerLink {
|
|||||||
* @param username the username of the Java player
|
* @param username the username of the Java player
|
||||||
* @return a future holding void on success or completed exceptionally when failed
|
* @return a future holding void on success or completed exceptionally when failed
|
||||||
*/
|
*/
|
||||||
CompletableFuture<Void> linkPlayer(UUID bedrockId, UUID javaId, String username);
|
@NonNull
|
||||||
|
CompletableFuture<Void> linkPlayer(
|
||||||
|
@NonNull UUID bedrockId,
|
||||||
|
@NonNull UUID javaId,
|
||||||
|
@NonNull String username);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unlinks a Java account from a Bedrock account.
|
* Unlinks a Java account from a Bedrock account.
|
||||||
@@ -75,7 +82,8 @@ public interface PlayerLink {
|
|||||||
* @param javaId the uuid of the Java player
|
* @param javaId the uuid of the Java player
|
||||||
* @return a future holding void on success or completed exceptionally when failed
|
* @return a future holding void on success or completed exceptionally when failed
|
||||||
*/
|
*/
|
||||||
CompletableFuture<Void> unlinkPlayer(UUID javaId);
|
@NonNull
|
||||||
|
CompletableFuture<Void> unlinkPlayer(@NonNull UUID javaId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a link request for the given Java player.
|
* Creates a link request for the given Java player.
|
||||||
@@ -86,10 +94,11 @@ public interface PlayerLink {
|
|||||||
* @return a future holding the result of the link request which will be a {@link
|
* @return a future holding the result of the link request which will be a {@link
|
||||||
* LinkRequestResult} on failure and the link code (string) on success
|
* LinkRequestResult} on failure and the link code (string) on success
|
||||||
*/
|
*/
|
||||||
|
@NonNull
|
||||||
CompletableFuture<?> createLinkRequest(
|
CompletableFuture<?> createLinkRequest(
|
||||||
UUID javaId,
|
@NonNull UUID javaId,
|
||||||
String javaUsername,
|
@NonNull String javaUsername,
|
||||||
String bedrockUsername
|
@NonNull String bedrockUsername
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -101,11 +110,12 @@ public interface PlayerLink {
|
|||||||
* @param code the code created in {@link #createLinkRequest(UUID, String, String)}
|
* @param code the code created in {@link #createLinkRequest(UUID, String, String)}
|
||||||
* @return a future holding the result of the link verification
|
* @return a future holding the result of the link verification
|
||||||
*/
|
*/
|
||||||
|
@NonNull
|
||||||
CompletableFuture<LinkRequestResult> verifyLinkRequest(
|
CompletableFuture<LinkRequestResult> verifyLinkRequest(
|
||||||
UUID bedrockId,
|
@NonNull UUID bedrockId,
|
||||||
String javaUsername,
|
@NonNull String javaUsername,
|
||||||
String bedrockUsername,
|
@NonNull String bedrockUsername,
|
||||||
String code
|
@NonNull String code
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -51,18 +51,6 @@ public class PropertyKey {
|
|||||||
this.removable = removable;
|
this.removable = removable;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (obj instanceof PropertyKey) {
|
|
||||||
return key.equals(((PropertyKey) obj).key);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj instanceof String) {
|
|
||||||
return key.equals(obj);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Result isAddAllowed(Object obj) { //todo use for add and remove
|
public Result isAddAllowed(Object obj) { //todo use for add and remove
|
||||||
if (obj instanceof PropertyKey) {
|
if (obj instanceof PropertyKey) {
|
||||||
PropertyKey propertyKey = (PropertyKey) obj;
|
PropertyKey propertyKey = (PropertyKey) obj;
|
||||||
|
|||||||
@@ -106,16 +106,19 @@ public final class BungeeDataHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (result.getResultType()) {
|
if (result.getResultType() == ResultType.EXCEPTION) {
|
||||||
case EXCEPTION:
|
|
||||||
event.setCancelReason(config.getDisconnect().getInvalidKey());
|
event.setCancelReason(config.getDisconnect().getInvalidKey());
|
||||||
break;
|
event.completeIntent(plugin);
|
||||||
case INVALID_DATA_LENGTH:
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.getResultType() == ResultType.INVALID_DATA_LENGTH) {
|
||||||
event.setCancelReason(TextComponent.fromLegacyText(String.format(
|
event.setCancelReason(TextComponent.fromLegacyText(String.format(
|
||||||
config.getDisconnect().getInvalidArgumentsLength(),
|
config.getDisconnect().getInvalidArgumentsLength(),
|
||||||
BedrockData.EXPECTED_LENGTH, result.getBedrockData().getDataLength()
|
BedrockData.EXPECTED_LENGTH, result.getBedrockData().getDataLength()
|
||||||
)));
|
)));
|
||||||
break;
|
event.completeIntent(plugin);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// only continue when SUCCESS
|
// only continue when SUCCESS
|
||||||
@@ -155,7 +158,7 @@ public final class BungeeDataHandler {
|
|||||||
|
|
||||||
public void handleServerConnect(ProxiedPlayer player) {
|
public void handleServerConnect(ProxiedPlayer player) {
|
||||||
// Passes the information through to the connecting server if enabled
|
// Passes the information through to the connecting server if enabled
|
||||||
if (config.isSendFloodgateData() && api.isBedrockPlayer(player.getUniqueId())) {
|
if (config.isSendFloodgateData() && api.isFloodgatePlayer(player.getUniqueId())) {
|
||||||
Handshake handshake = ReflectionUtils.getCastedValue(
|
Handshake handshake = ReflectionUtils.getCastedValue(
|
||||||
player.getPendingConnection(), CACHED_HANDSHAKE_PACKET
|
player.getPendingConnection(), CACHED_HANDSHAKE_PACKET
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -25,7 +25,9 @@
|
|||||||
|
|
||||||
package org.geysermc.floodgate.pluginmessage;
|
package org.geysermc.floodgate.pluginmessage;
|
||||||
|
|
||||||
|
import com.google.gson.JsonIOException;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonSyntaxException;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.name.Named;
|
import com.google.inject.name.Named;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
@@ -165,7 +167,7 @@ public final class BungeePluginMessageHandler extends PluginMessageHandler imple
|
|||||||
try {
|
try {
|
||||||
Reader reader = new InputStreamReader(new ByteArrayInputStream(responseData));
|
Reader reader = new InputStreamReader(new ByteArrayInputStream(responseData));
|
||||||
response = GSON.fromJson(reader, JsonObject.class);
|
response = GSON.fromJson(reader, JsonObject.class);
|
||||||
} catch (Throwable throwable) {
|
} catch (JsonIOException | JsonSyntaxException throwable) {
|
||||||
logger.error("Failed to read Skin response", throwable);
|
logger.error("Failed to read Skin response", throwable);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,14 +116,14 @@ public final class BungeeCommandUtil implements CommandUtil {
|
|||||||
break;
|
break;
|
||||||
case ONLY_JAVA:
|
case ONLY_JAVA:
|
||||||
for (ProxiedPlayer player : players) {
|
for (ProxiedPlayer player : players) {
|
||||||
if (!api.isBedrockPlayer(player.getUniqueId())) {
|
if (!api.isFloodgatePlayer(player.getUniqueId())) {
|
||||||
usernames.add(player.getName());
|
usernames.add(player.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ONLY_BEDROCK:
|
case ONLY_BEDROCK:
|
||||||
for (ProxiedPlayer player : players) {
|
for (ProxiedPlayer player : players) {
|
||||||
if (api.isBedrockPlayer(player.getUniqueId())) {
|
if (api.isFloodgatePlayer(player.getUniqueId())) {
|
||||||
usernames.add(player.getName());
|
usernames.add(player.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import com.google.inject.Inject;
|
|||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
import com.google.inject.name.Named;
|
import com.google.inject.name.Named;
|
||||||
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@@ -56,8 +57,12 @@ public class FloodgatePlatform {
|
|||||||
private Injector guice;
|
private Injector guice;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public FloodgatePlatform(FloodgateApi api, PlatformInjector platformInjector,
|
public FloodgatePlatform(
|
||||||
FloodgateLogger logger, Injector guice) {
|
FloodgateApi api,
|
||||||
|
PlatformInjector platformInjector,
|
||||||
|
FloodgateLogger logger,
|
||||||
|
Injector guice) {
|
||||||
|
|
||||||
this.api = api;
|
this.api = api;
|
||||||
this.injector = platformInjector;
|
this.injector = platformInjector;
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
@@ -69,15 +74,14 @@ public class FloodgatePlatform {
|
|||||||
@Named("dataDirectory") Path dataDirectory,
|
@Named("dataDirectory") Path dataDirectory,
|
||||||
ConfigLoader configLoader,
|
ConfigLoader configLoader,
|
||||||
FloodgateConfigHolder configHolder,
|
FloodgateConfigHolder configHolder,
|
||||||
HandshakeHandlers handshakeHandlers
|
HandshakeHandlers handshakeHandlers) {
|
||||||
) {
|
|
||||||
|
|
||||||
if (!Files.isDirectory(dataDirectory)) {
|
if (!Files.isDirectory(dataDirectory)) {
|
||||||
try {
|
try {
|
||||||
Files.createDirectory(dataDirectory);
|
Files.createDirectory(dataDirectory);
|
||||||
} catch (Exception exception) {
|
} catch (IOException exception) {
|
||||||
logger.error("Failed to create the data folder", exception);
|
logger.error("Failed to create the data folder", exception);
|
||||||
throw new RuntimeException("Failed to create the data folder");
|
throw new RuntimeException("Failed to create the data folder", exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,7 +94,7 @@ public class FloodgatePlatform {
|
|||||||
guice = guice.createChildInjector(new ConfigLoadedModule(config));
|
guice = guice.createChildInjector(new ConfigLoadedModule(config));
|
||||||
PlayerLink link = guice.getInstance(PlayerLinkLoader.class).load();
|
PlayerLink link = guice.getInstance(PlayerLinkLoader.class).load();
|
||||||
|
|
||||||
InstanceHolder.setInstance(api, link, this.injector, handshakeHandlers, KEY);
|
InstanceHolder.set(api, link, this.injector, handshakeHandlers, KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean enable(Module... postInitializeModules) {
|
public boolean enable(Module... postInitializeModules) {
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import io.netty.channel.ChannelHandlerContext;
|
|||||||
import io.netty.handler.codec.MessageToByteEncoder;
|
import io.netty.handler.codec.MessageToByteEncoder;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.geysermc.floodgate.inject.CommonPlatformInjector;
|
import org.geysermc.floodgate.inject.CommonPlatformInjector;
|
||||||
|
import org.geysermc.floodgate.util.Constants;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public final class AddonManagerHandler extends MessageToByteEncoder<ByteBuf> {
|
public final class AddonManagerHandler extends MessageToByteEncoder<ByteBuf> {
|
||||||
@@ -57,8 +58,7 @@ public final class AddonManagerHandler extends MessageToByteEncoder<ByteBuf> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int index = msg.readerIndex();
|
int index = msg.readerIndex();
|
||||||
// LoginSuccess packet = 2
|
if (readVarInt(msg) == Constants.LOGIN_SUCCESS_PACKET_ID) {
|
||||||
if (readVarInt(msg) == 2) {
|
|
||||||
loggedIn = true;
|
loggedIn = true;
|
||||||
injector.loginSuccessCall(channel);
|
injector.loginSuccessCall(channel);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public class SimpleFloodgateApi implements FloodgateApi {
|
|||||||
private final PluginMessageHandler pluginMessageHandler;
|
private final PluginMessageHandler pluginMessageHandler;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isBedrockPlayer(UUID uuid) {
|
public boolean isFloodgatePlayer(UUID uuid) {
|
||||||
return getPlayer(uuid) != null;
|
return getPlayer(uuid) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import cloud.commandframework.context.CommandContext;
|
|||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
import org.geysermc.floodgate.api.FloodgateApi;
|
import org.geysermc.floodgate.api.FloodgateApi;
|
||||||
import org.geysermc.floodgate.api.link.LinkRequestResult;
|
import org.geysermc.floodgate.api.link.LinkRequestResult;
|
||||||
import org.geysermc.floodgate.api.link.PlayerLink;
|
import org.geysermc.floodgate.api.link.PlayerLink;
|
||||||
@@ -74,7 +75,7 @@ public final class LinkAccountCommand implements FloodgateCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// when the player is a Bedrock player
|
// when the player is a Bedrock player
|
||||||
if (api.isBedrockPlayer(sender.uuid())) {
|
if (api.isFloodgatePlayer(sender.uuid())) {
|
||||||
if (!context.contains("code")) {
|
if (!context.contains("code")) {
|
||||||
sender.sendMessage(Message.BEDROCK_USAGE);
|
sender.sendMessage(Message.BEDROCK_USAGE);
|
||||||
return;
|
return;
|
||||||
@@ -107,6 +108,9 @@ public final class LinkAccountCommand implements FloodgateCommand {
|
|||||||
case LINK_COMPLETED:
|
case LINK_COMPLETED:
|
||||||
sender.disconnect(Message.LINK_REQUEST_COMPLETED, targetName);
|
sender.disconnect(Message.LINK_REQUEST_COMPLETED, targetName);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
sender.disconnect(Component.text("Invalid account linking result"));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public class FloodgateConfig {
|
|||||||
private boolean debug;
|
private boolean debug;
|
||||||
private int configVersion;
|
private int configVersion;
|
||||||
|
|
||||||
private Key key = null;
|
private Key key;
|
||||||
|
|
||||||
public void setKey(Key key) {
|
public void setKey(Key key) {
|
||||||
if (this.key == null) {
|
if (this.key == null) {
|
||||||
|
|||||||
@@ -43,8 +43,8 @@ public class ConfigInitializer {
|
|||||||
private static final Yaml YAML;
|
private static final Yaml YAML;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
Constructor constructor = new CustomClassLoaderConstructor(
|
Constructor constructor =
|
||||||
ConfigInitializer.class.getClassLoader());
|
new CustomClassLoaderConstructor(ConfigInitializer.class.getClassLoader());
|
||||||
|
|
||||||
constructor.setPropertyUtils(new PropertyUtils() {
|
constructor.setPropertyUtils(new PropertyUtils() {
|
||||||
@Override
|
@Override
|
||||||
@@ -54,8 +54,11 @@ public class ConfigInitializer {
|
|||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getPropertiesFromClass(Class<?> type, Class<?> stopAfter,
|
private void getPropertiesFromClass(
|
||||||
|
Class<?> type,
|
||||||
|
Class<?> stopAfter,
|
||||||
Map<String, Property> propertyMap) {
|
Map<String, Property> propertyMap) {
|
||||||
|
|
||||||
Class<?> current = type;
|
Class<?> current = type;
|
||||||
while (!Object.class.equals(current)) {
|
while (!Object.class.equals(current)) {
|
||||||
for (Field field : current.getDeclaredFields()) {
|
for (Field field : current.getDeclaredFields()) {
|
||||||
@@ -98,7 +101,8 @@ public class ConfigInitializer {
|
|||||||
YAML = new Yaml(constructor);
|
YAML = new Yaml(constructor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends FloodgateConfig> T initializeFrom(InputStream dataStream,
|
public static <T extends FloodgateConfig> T initializeFrom(
|
||||||
|
InputStream dataStream,
|
||||||
Class<T> configClass) {
|
Class<T> configClass) {
|
||||||
return YAML.loadAs(dataStream, configClass);
|
return YAML.loadAs(dataStream, configClass);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,7 +86,8 @@ public final class ConfigLoader {
|
|||||||
}
|
}
|
||||||
} catch (Exception exception) {
|
} catch (Exception exception) {
|
||||||
logger.error("Error while loading config", exception);
|
logger.error("Error while loading config", exception);
|
||||||
throw new RuntimeException("Failed to load the config! Try to delete the config file");
|
throw new RuntimeException(
|
||||||
|
"Failed to load the config! Try to delete the config file", exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
Path keyPath = dataFolder.resolve(configInstance.getKeyFileName());
|
Path keyPath = dataFolder.resolve(configInstance.getKeyFileName());
|
||||||
@@ -125,7 +126,7 @@ public final class ConfigLoader {
|
|||||||
configInstance.setKey(key);
|
configInstance.setKey(key);
|
||||||
} catch (IOException exception) {
|
} catch (IOException exception) {
|
||||||
logger.error("Error while reading the key", exception);
|
logger.error("Error while reading the key", exception);
|
||||||
throw new RuntimeException("Failed to read the key!");
|
throw new RuntimeException("Failed to read the key!", exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
return configInstance;
|
return configInstance;
|
||||||
|
|||||||
@@ -51,9 +51,13 @@ public final class ConfigFileUpdater {
|
|||||||
* @param defaultConfigLocation the location of the default Floodgate config
|
* @param defaultConfigLocation the location of the default Floodgate config
|
||||||
* @throws IOException if an I/O error occurs
|
* @throws IOException if an I/O error occurs
|
||||||
*/
|
*/
|
||||||
public void update(Path configLocation, Map<String, Object> currentVersion,
|
public void update(
|
||||||
Map<String, String> renames, String defaultConfigLocation)
|
Path configLocation,
|
||||||
|
Map<String, Object> currentVersion,
|
||||||
|
Map<String, String> renames,
|
||||||
|
String defaultConfigLocation)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
|
||||||
List<String> notFound = new ArrayList<>();
|
List<String> notFound = new ArrayList<>();
|
||||||
List<String> newConfig = defaultConfigHandler.loadDefaultConfig(defaultConfigLocation);
|
List<String> newConfig = defaultConfigHandler.loadDefaultConfig(defaultConfigLocation);
|
||||||
|
|
||||||
@@ -64,7 +68,7 @@ public final class ConfigFileUpdater {
|
|||||||
for (int i = 0; i < newConfig.size(); i++) {
|
for (int i = 0; i < newConfig.size(); i++) {
|
||||||
line = newConfig.get(i);
|
line = newConfig.get(i);
|
||||||
// we don't have to check comments or empty lines
|
// we don't have to check comments or empty lines
|
||||||
if (line.length() == 0 || line.startsWith("#")) {
|
if (line.isEmpty() || line.charAt(0) == '#') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +78,7 @@ public final class ConfigFileUpdater {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// end of subcategory
|
// end of subcategory
|
||||||
if (spaces.length() > 0 && currentSpaces.length() < spaces.length()) {
|
if (!spaces.isEmpty() && currentSpaces.length() < spaces.length()) {
|
||||||
// we can assume this since we don't allow subcategories of subcategories
|
// we can assume this since we don't allow subcategories of subcategories
|
||||||
spaces = "";
|
spaces = "";
|
||||||
map = null;
|
map = null;
|
||||||
@@ -134,7 +138,7 @@ public final class ConfigFileUpdater {
|
|||||||
logger.info("Successfully updated the config file! " +
|
logger.info("Successfully updated the config file! " +
|
||||||
"Your old config has been moved to config-old.yml");
|
"Your old config has been moved to config-old.yml");
|
||||||
|
|
||||||
if (notFound.size() > 0) {
|
if (!notFound.isEmpty()) {
|
||||||
StringBuilder messageBuilder = new StringBuilder(
|
StringBuilder messageBuilder = new StringBuilder(
|
||||||
"Please note that the following keys we not found in the old config and " +
|
"Please note that the following keys we not found in the old config and " +
|
||||||
"are now using the default Floodgate config value. Missing/new keys: ");
|
"are now using the default Floodgate config value. Missing/new keys: ");
|
||||||
|
|||||||
@@ -48,16 +48,15 @@ public final class ConfigUpdater {
|
|||||||
public void update(String defaultConfigLocation) {
|
public void update(String defaultConfigLocation) {
|
||||||
Path configLocation = dataFolder.resolve("config.yml");
|
Path configLocation = dataFolder.resolve("config.yml");
|
||||||
|
|
||||||
BufferedReader configReader;
|
Map<String, Object> config;
|
||||||
try {
|
|
||||||
configReader = Files.newBufferedReader(configLocation);
|
try (BufferedReader configReader = Files.newBufferedReader(configLocation)) {
|
||||||
|
config = new Yaml().load(configReader);
|
||||||
} catch (IOException exception) {
|
} catch (IOException exception) {
|
||||||
logger.error("Error while opening the config file", exception);
|
logger.error("Error while opening the config file", exception);
|
||||||
throw new RuntimeException("Failed to update config");
|
throw new RuntimeException("Failed to update config", exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, Object> config = new Yaml().load(configReader);
|
|
||||||
|
|
||||||
// new name -> old name
|
// new name -> old name
|
||||||
Map<String, String> renames = new HashMap<>();
|
Map<String, String> renames = new HashMap<>();
|
||||||
|
|
||||||
@@ -93,7 +92,7 @@ public final class ConfigUpdater {
|
|||||||
fileUpdater.update(configLocation, config, renames, defaultConfigLocation);
|
fileUpdater.update(configLocation, config, renames, defaultConfigLocation);
|
||||||
} catch (IOException exception) {
|
} catch (IOException exception) {
|
||||||
logger.error("Error while updating the config file", exception);
|
logger.error("Error while updating the config file", exception);
|
||||||
throw new RuntimeException("Failed to update config");
|
throw new RuntimeException("Failed to update config", exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ final class DisabledPlayerLink implements PlayerLink {
|
|||||||
public void load() {
|
public void load() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//todo don't return null
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<LinkedPlayer> getLinkedPlayer(UUID bedrockId) {
|
public CompletableFuture<LinkedPlayer> getLinkedPlayer(UUID bedrockId) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ public class GlobalPlayerLinking extends CommonPlayerLink {
|
|||||||
// player linking and unlinking now goes through the global player linking server.
|
// player linking and unlinking now goes through the global player linking server.
|
||||||
// so individual servers can't register nor unlink players.
|
// so individual servers can't register nor unlink players.
|
||||||
|
|
||||||
//todo probably return a failed future instead of returning null?
|
//todo don't return null
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Void> linkPlayer(UUID bedrockId, UUID javaId, String username) {
|
public CompletableFuture<Void> linkPlayer(UUID bedrockId, UUID javaId, String username) {
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ public final class LinkRequestImpl implements LinkRequest {
|
|||||||
requestTime = Instant.now().getEpochSecond();
|
requestTime = Instant.now().getEpochSecond();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isExpired(long linkTimeout) {
|
public boolean isExpired(long linkTimeout) {
|
||||||
long timePassed = Instant.now().getEpochSecond() - requestTime;
|
long timePassed = Instant.now().getEpochSecond() - requestTime;
|
||||||
return timePassed > linkTimeout;
|
return timePassed > linkTimeout;
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import java.net.URLClassLoader;
|
|||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import org.geysermc.floodgate.api.link.PlayerLink;
|
import org.geysermc.floodgate.api.link.PlayerLink;
|
||||||
@@ -61,13 +62,13 @@ public final class PlayerLinkLoader {
|
|||||||
throw new IllegalStateException("Config cannot be null!");
|
throw new IllegalStateException("Config cannot be null!");
|
||||||
}
|
}
|
||||||
|
|
||||||
FloodgateConfig.PlayerLinkConfig linkConfig = config.getPlayerLink();
|
FloodgateConfig.PlayerLinkConfig linkingConfig = config.getPlayerLink();
|
||||||
if (!linkConfig.isEnabled()) {
|
if (!linkingConfig.isEnabled()) {
|
||||||
return new DisabledPlayerLink();
|
return new DisabledPlayerLink();
|
||||||
}
|
}
|
||||||
|
|
||||||
// we use our own internal PlayerLinking when global linking is enabled
|
// we use our own internal PlayerLinking when global linking is enabled
|
||||||
if (linkConfig.isUseGlobalLinking()) {
|
if (linkingConfig.isUseGlobalLinking()) {
|
||||||
return injector.getInstance(GlobalPlayerLinking.class);
|
return injector.getInstance(GlobalPlayerLinking.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,7 +82,7 @@ public final class PlayerLinkLoader {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (files.size() == 0) {
|
if (files.isEmpty()) {
|
||||||
logger.error("Failed to find a database implementation");
|
logger.error("Failed to find a database implementation");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -89,17 +90,20 @@ public final class PlayerLinkLoader {
|
|||||||
Path implementationPath = files.get(0);
|
Path implementationPath = files.get(0);
|
||||||
|
|
||||||
// We only want to load one database implementation
|
// We only want to load one database implementation
|
||||||
String type = linkConfig.getType().toLowerCase();
|
|
||||||
if (files.size() > 1) {
|
if (files.size() > 1) {
|
||||||
implementationPath = null;
|
boolean found = false;
|
||||||
|
|
||||||
|
String type = linkingConfig.getType().toLowerCase(Locale.ROOT);
|
||||||
for (Path path : files) {
|
for (Path path : files) {
|
||||||
if (path.getFileName().toString().toLowerCase().contains(type)) {
|
if (path.getFileName().toString().toLowerCase(Locale.ROOT).contains(type)) {
|
||||||
implementationPath = path;
|
implementationPath = path;
|
||||||
|
found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (implementationPath == null) {
|
|
||||||
|
if (!found) {
|
||||||
logger.error("Failed to find an implementation for type: {}",
|
logger.error("Failed to find an implementation for type: {}",
|
||||||
linkConfig.getType());
|
linkingConfig.getType());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,23 +111,29 @@ public final class PlayerLinkLoader {
|
|||||||
Class<? extends PlayerLink> mainClass;
|
Class<? extends PlayerLink> mainClass;
|
||||||
try {
|
try {
|
||||||
URL pluginUrl = implementationPath.toUri().toURL();
|
URL pluginUrl = implementationPath.toUri().toURL();
|
||||||
URLClassLoader classLoader = new URLClassLoader(
|
|
||||||
new URL[]{pluginUrl},
|
try (URLClassLoader classLoader = new URLClassLoader(
|
||||||
PlayerLinkLoader.class.getClassLoader()
|
new URL[]{pluginUrl}, PlayerLinkLoader.class.getClassLoader())) {
|
||||||
|
|
||||||
|
String mainClassName;
|
||||||
|
|
||||||
|
try (InputStream linkConfigStream =
|
||||||
|
classLoader.getResourceAsStream("config.json")) {
|
||||||
|
|
||||||
|
requireNonNull(linkConfigStream, "Implementation should have a config");
|
||||||
|
|
||||||
|
JsonObject linkConfig = new Gson().fromJson(
|
||||||
|
new InputStreamReader(linkConfigStream), JsonObject.class
|
||||||
);
|
);
|
||||||
|
|
||||||
InputStream linkImplConfigStream = classLoader.getResourceAsStream("config.json");
|
mainClassName = linkConfig.get("mainClass").getAsString();
|
||||||
requireNonNull(linkImplConfigStream, "Database implementation should contain a config");
|
}
|
||||||
|
|
||||||
JsonObject linkImplConfig = new Gson().fromJson(
|
|
||||||
new InputStreamReader(linkImplConfigStream), JsonObject.class
|
|
||||||
);
|
|
||||||
|
|
||||||
String mainClassName = linkImplConfig.get("mainClass").getAsString();
|
|
||||||
mainClass = (Class<? extends PlayerLink>) classLoader.loadClass(mainClassName);
|
mainClass = (Class<? extends PlayerLink>) classLoader.loadClass(mainClassName);
|
||||||
|
}
|
||||||
} catch (ClassCastException exception) {
|
} catch (ClassCastException exception) {
|
||||||
logger.error("The database implementation ({}) doesn't extend the PlayerLink class!",
|
logger.error("The database implementation ({}) doesn't extend the PlayerLink class!",
|
||||||
implementationPath.getFileName().toString());
|
implementationPath.getFileName().toString(), exception);
|
||||||
return null;
|
return null;
|
||||||
} catch (Exception exception) {
|
} catch (Exception exception) {
|
||||||
logger.error("Error while loading database jar", exception);
|
logger.error("Error while loading database jar", exception);
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ import org.geysermc.floodgate.util.LanguageManager;
|
|||||||
public final class JavaUtilFloodgateLogger implements FloodgateLogger {
|
public final class JavaUtilFloodgateLogger implements FloodgateLogger {
|
||||||
private final Logger logger;
|
private final Logger logger;
|
||||||
private final LanguageManager languageManager;
|
private final LanguageManager languageManager;
|
||||||
private Level originLevel = null;
|
private Level originLevel;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void error(String message, Object... args) {
|
public void error(String message, Object... args) {
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ public interface CommandMessage {
|
|||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
for (int i = 0; i < translateParts.length; i++) {
|
for (int i = 0; i < translateParts.length; i++) {
|
||||||
builder.append(manager.getString(translateParts[i], locale, args));
|
builder.append(manager.getString(translateParts[i], locale, args));
|
||||||
if (++i != translateParts.length) {
|
if (translateParts.length != i + 1) {
|
||||||
builder.append(" ");
|
builder.append(" ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ public abstract class PluginMessageHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void sendSkinResponse(UUID player, boolean failed, String response) {
|
public void sendSkinResponse(UUID player, boolean failed, String response) {
|
||||||
return; // Proxy implementations don't send responses
|
// Proxy implementations don't send responses
|
||||||
}
|
}
|
||||||
|
|
||||||
protected byte[] createFormData(Form form) {
|
protected byte[] createFormData(Form form) {
|
||||||
|
|||||||
@@ -154,10 +154,12 @@ public final class FloodgatePlayerImpl implements FloodgatePlayer {
|
|||||||
CompletableFuture.completedFuture(null);
|
CompletableFuture.completedFuture(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public UUID getCorrectUniqueId() {
|
public UUID getCorrectUniqueId() {
|
||||||
return linkedPlayer != null ? linkedPlayer.getJavaUniqueId() : javaUniqueId;
|
return linkedPlayer != null ? linkedPlayer.getJavaUniqueId() : javaUniqueId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getCorrectUsername() {
|
public String getCorrectUsername() {
|
||||||
return linkedPlayer != null ? linkedPlayer.getJavaUsername() : javaUsername;
|
return linkedPlayer != null ? linkedPlayer.getJavaUsername() : javaUsername;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,9 +64,8 @@ public final class HandshakeHandler {
|
|||||||
private final AttributeKey<FloodgatePlayer> playerAttribute;
|
private final AttributeKey<FloodgatePlayer> playerAttribute;
|
||||||
private final FloodgateLogger logger;
|
private final FloodgateLogger logger;
|
||||||
|
|
||||||
public HandshakeResult handle(Channel channel, @NonNull String hostname) {
|
public HandshakeResult handle(Channel channel, @NonNull String originalHostname) {
|
||||||
try {
|
String[] split = originalHostname.split("\0");
|
||||||
String[] split = hostname.split("\0");
|
|
||||||
String data = null;
|
String data = null;
|
||||||
|
|
||||||
StringBuilder hostnameBuilder = new StringBuilder();
|
StringBuilder hostnameBuilder = new StringBuilder();
|
||||||
@@ -78,7 +77,7 @@ public final class HandshakeHandler {
|
|||||||
hostnameBuilder.append(value);
|
hostnameBuilder.append(value);
|
||||||
}
|
}
|
||||||
// hostname now doesn't have Floodgate data anymore if it had
|
// hostname now doesn't have Floodgate data anymore if it had
|
||||||
hostname = hostnameBuilder.toString();
|
String hostname = hostnameBuilder.toString();
|
||||||
|
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
return callHandlerAndReturnResult(
|
return callHandlerAndReturnResult(
|
||||||
@@ -91,6 +90,7 @@ public final class HandshakeHandler {
|
|||||||
Base64Utils.getEncodedLength(AesCipher.IV_LENGTH);
|
Base64Utils.getEncodedLength(AesCipher.IV_LENGTH);
|
||||||
int lastSplitIndex = data.lastIndexOf(0x21);
|
int lastSplitIndex = data.lastIndexOf(0x21);
|
||||||
|
|
||||||
|
try {
|
||||||
byte[] floodgateData;
|
byte[] floodgateData;
|
||||||
byte[] rawSkinData = null;
|
byte[] rawSkinData = null;
|
||||||
|
|
||||||
@@ -181,8 +181,8 @@ public final class HandshakeHandler {
|
|||||||
ResultType resultType,
|
ResultType resultType,
|
||||||
Channel channel,
|
Channel channel,
|
||||||
BedrockData bedrockData,
|
BedrockData bedrockData,
|
||||||
String hostname
|
String hostname) {
|
||||||
) {
|
|
||||||
HandshakeData handshakeData = new HandshakeDataImpl(channel, bedrockData != null,
|
HandshakeData handshakeData = new HandshakeDataImpl(channel, bedrockData != null,
|
||||||
bedrockData, null, null, hostname, null);
|
bedrockData, null, null, hostname, null);
|
||||||
handshakeHandlers.callHandshakeHandlers(handshakeData);
|
handshakeHandlers.callHandshakeHandlers(handshakeData);
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ public interface UserAudience extends Identified, Identity, Audience {
|
|||||||
|
|
||||||
boolean hasPermission(@NonNull final String permission);
|
boolean hasPermission(@NonNull final String permission);
|
||||||
|
|
||||||
|
@Override
|
||||||
void sendMessage(final @NonNull Identity source,
|
void sendMessage(final @NonNull Identity source,
|
||||||
final @NonNull Component message,
|
final @NonNull Component message,
|
||||||
final @NonNull MessageType type);
|
final @NonNull MessageType type);
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import cloud.commandframework.arguments.parser.ArgumentParser;
|
|||||||
import cloud.commandframework.context.CommandContext;
|
import cloud.commandframework.context.CommandContext;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@@ -154,13 +155,18 @@ public final class UserAudienceArgument extends CommandArgument<UserAudience, Us
|
|||||||
final @NonNull CommandContext<UserAudience> commandContext,
|
final @NonNull CommandContext<UserAudience> commandContext,
|
||||||
final @NonNull String input
|
final @NonNull String input
|
||||||
) {
|
) {
|
||||||
CommandUtil commandUtil = commandContext.get("CommandUtil");
|
final CommandUtil commandUtil = commandContext.get("CommandUtil");
|
||||||
|
final String trimmedInput = input.trim();
|
||||||
|
|
||||||
final String lowercaseInput = input.toLowerCase().trim();
|
if (trimmedInput.isEmpty()) {
|
||||||
|
return ImmutableList.copyOf(commandUtil.getOnlineUsernames(limitTo));
|
||||||
|
}
|
||||||
|
|
||||||
|
final String lowercaseInput = input.toLowerCase(Locale.ROOT);
|
||||||
final ImmutableList.Builder<String> builder = ImmutableList.builder();
|
final ImmutableList.Builder<String> builder = ImmutableList.builder();
|
||||||
|
|
||||||
for (final String player : commandUtil.getOnlineUsernames(limitTo)) {
|
for (final String player : commandUtil.getOnlineUsernames(limitTo)) {
|
||||||
if (lowercaseInput.isEmpty() || player.toLowerCase().startsWith(lowercaseInput)) {
|
if (player.toLowerCase(Locale.ROOT).startsWith(lowercaseInput)) {
|
||||||
builder.add(player);
|
builder.add(player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -182,7 +188,7 @@ public final class UserAudienceArgument extends CommandArgument<UserAudience, Us
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized @NonNull Throwable fillInStackTrace() {
|
public @NonNull Throwable fillInStackTrace() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ package org.geysermc.floodgate.skin;
|
|||||||
|
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
@@ -43,7 +44,7 @@ public final class SkinUploader {
|
|||||||
private static final int MAX_TRIES = 3;
|
private static final int MAX_TRIES = 3;
|
||||||
|
|
||||||
private final Executor requestExecutor = Executors.newSingleThreadExecutor();
|
private final Executor requestExecutor = Executors.newSingleThreadExecutor();
|
||||||
private long nextResult = 0;
|
private long nextResult;
|
||||||
|
|
||||||
public CompletableFuture<UploadResult> uploadSkin(@Nonnull RawSkin rawSkin) {
|
public CompletableFuture<UploadResult> uploadSkin(@Nonnull RawSkin rawSkin) {
|
||||||
return CompletableFuture.supplyAsync(() -> uploadSkinInner(rawSkin, 0), requestExecutor);
|
return CompletableFuture.supplyAsync(() -> uploadSkinInner(rawSkin, 0), requestExecutor);
|
||||||
@@ -65,12 +66,11 @@ public final class SkinUploader {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
UploadResult result = parseAndHandleResponse(HttpUtils.post(url, image));
|
UploadResult result = parseAndHandleResponse(HttpUtils.post(url, image));
|
||||||
if (result.httpCode == 429) {
|
if (result.getHttpCode() == 429) {
|
||||||
times += 1;
|
if (times + 1 >= MAX_TRIES) {
|
||||||
if (times >= MAX_TRIES) {
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
uploadSkinInner(rawSkin, times);
|
uploadSkinInner(rawSkin, times + 1);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
} catch (RuntimeException exception) {
|
} catch (RuntimeException exception) {
|
||||||
@@ -79,7 +79,7 @@ public final class SkinUploader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String getUploadUrlParameters(SkinModel model) {
|
private String getUploadUrlParameters(SkinModel model) {
|
||||||
return "?visibility=1&model=" + model.name;
|
return "?visibility=1&model=" + model.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
private UploadResult parseAndHandleResponse(HttpResponse response) {
|
private UploadResult parseAndHandleResponse(HttpResponse response) {
|
||||||
@@ -103,14 +103,15 @@ public final class SkinUploader {
|
|||||||
STEVE, ALEX;
|
STEVE, ALEX;
|
||||||
|
|
||||||
public static final SkinModel[] VALUES = values();
|
public static final SkinModel[] VALUES = values();
|
||||||
private final String name = name().toLowerCase();
|
|
||||||
|
@Getter private final String name = name().toLowerCase(Locale.ROOT);
|
||||||
|
|
||||||
public static SkinModel getByOrdinal(int ordinal) {
|
public static SkinModel getByOrdinal(int ordinal) {
|
||||||
return VALUES.length > ordinal ? VALUES[ordinal] : STEVE;
|
return VALUES.length > ordinal ? VALUES[ordinal] : STEVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SkinModel getByName(String name) {
|
public static SkinModel getByName(String name) {
|
||||||
return name == null || !name.equalsIgnoreCase("alex") ? STEVE : ALEX;
|
return "alex".equalsIgnoreCase(name) ? ALEX : STEVE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @author GeyserMC
|
||||||
|
* @link https://github.com/GeyserMC/Floodgate
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.geysermc.floodgate.util;
|
||||||
|
|
||||||
|
public final class Constants {
|
||||||
|
public static final int LOGIN_SUCCESS_PACKET_ID = 2;
|
||||||
|
}
|
||||||
@@ -28,6 +28,7 @@ package org.geysermc.floodgate.util;
|
|||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Joiner;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.Reader;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
@@ -63,8 +64,8 @@ public final class LanguageManager {
|
|||||||
*/
|
*/
|
||||||
private static String formatLocale(String locale) {
|
private static String formatLocale(String locale) {
|
||||||
try {
|
try {
|
||||||
String[] parts = locale.toLowerCase().split("_");
|
String[] parts = locale.toLowerCase(Locale.ROOT).split("_");
|
||||||
return parts[0] + "_" + parts[1].toUpperCase();
|
return parts[0] + "_" + parts[1].toUpperCase(Locale.ROOT);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return locale;
|
return locale;
|
||||||
}
|
}
|
||||||
@@ -117,31 +118,32 @@ public final class LanguageManager {
|
|||||||
* @return true if the locale has been found
|
* @return true if the locale has been found
|
||||||
*/
|
*/
|
||||||
public boolean loadLocale(String locale) {
|
public boolean loadLocale(String locale) {
|
||||||
locale = formatLocale(locale);
|
String formatLocale = formatLocale(locale);
|
||||||
|
|
||||||
// just return if the locale has been loaded already
|
// just return if the locale has been loaded already
|
||||||
if (localeMappings.containsKey(locale)) {
|
if (localeMappings.containsKey(formatLocale)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
InputStream localeStream = LanguageManager.class.getClassLoader().getResourceAsStream(
|
InputStream localeStream = LanguageManager.class.getClassLoader().getResourceAsStream(
|
||||||
"languages/texts/" + locale + ".properties");
|
"languages/texts/" + formatLocale + ".properties");
|
||||||
|
|
||||||
// load the locale
|
// load the locale
|
||||||
if (localeStream != null) {
|
if (localeStream != null) {
|
||||||
Properties localeProp = new Properties();
|
Properties localeProp = new Properties();
|
||||||
try {
|
|
||||||
localeProp.load(new InputStreamReader(localeStream, StandardCharsets.UTF_8));
|
try (Reader reader = new InputStreamReader(localeStream, StandardCharsets.UTF_8)) {
|
||||||
|
localeProp.load(reader);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new AssertionError("Failed to load Floodgate locale", e);
|
throw new AssertionError("Failed to load Floodgate locale", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert the locale into the mappings
|
// insert the locale into the mappings
|
||||||
localeMappings.put(locale, localeProp);
|
localeMappings.put(formatLocale, localeProp);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.warn("Missing locale file: " + locale);
|
logger.warn("Missing locale file: " + formatLocale);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,9 +42,8 @@ public final class MessageFormatter {
|
|||||||
|
|
||||||
int previousIndex = -1;
|
int previousIndex = -1;
|
||||||
int currentIndex;
|
int currentIndex;
|
||||||
StringBuilder stringBuilder = new StringBuilder(
|
StringBuilder stringBuilder =
|
||||||
message.length() + getArgsContentLength(args)
|
new StringBuilder(message.length() + getArgsContentLength(args));
|
||||||
);
|
|
||||||
|
|
||||||
for (String argument : args) {
|
for (String argument : args) {
|
||||||
currentIndex = message.indexOf(DELIM_STR, previousIndex);
|
currentIndex = message.indexOf(DELIM_STR, previousIndex);
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ public final class ReflectionUtils {
|
|||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
private static String prefix = null;
|
private static String prefix;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
Field modifiersField = null;
|
Field modifiersField = null;
|
||||||
@@ -59,12 +59,12 @@ public final class ReflectionUtils {
|
|||||||
try {
|
try {
|
||||||
Method declaredFields = getMethod(Class.class, "getDeclaredFields0", boolean.class);
|
Method declaredFields = getMethod(Class.class, "getDeclaredFields0", boolean.class);
|
||||||
if (declaredFields == null) {
|
if (declaredFields == null) {
|
||||||
throw new NoSuchMethodException();
|
throw new NoSuchMethodException("Cannot find method getDeclaredFields0");
|
||||||
}
|
}
|
||||||
|
|
||||||
Field[] fields = castedInvoke(Field.class, declaredFields, false);
|
Field[] fields = castedInvoke(Field.class, declaredFields, false);
|
||||||
if (fields == null) {
|
if (fields == null) {
|
||||||
throw new Exception();
|
throw new RuntimeException("The Field class cannot have null fields");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Field field : fields) {
|
for (Field field : fields) {
|
||||||
@@ -79,7 +79,7 @@ public final class ReflectionUtils {
|
|||||||
System.getProperty("java.version"),
|
System.getProperty("java.version"),
|
||||||
System.getProperty("java.vendor"),
|
System.getProperty("java.vendor"),
|
||||||
System.getProperty("java.vendor.url")
|
System.getProperty("java.vendor.url")
|
||||||
));
|
), exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -382,6 +382,9 @@ public final class ReflectionUtils {
|
|||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public static Object invoke(Object instance, Method method, Object... arguments) {
|
public static Object invoke(Object instance, Method method, Object... arguments) {
|
||||||
|
if (method == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
makeAccessible(method);
|
makeAccessible(method);
|
||||||
try {
|
try {
|
||||||
return method.invoke(instance, arguments);
|
return method.invoke(instance, arguments);
|
||||||
@@ -410,11 +413,7 @@ public final class ReflectionUtils {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Nullable
|
@Nullable
|
||||||
public static <T> T castedInvoke(Object instance, Method method, Object... arguments) {
|
public static <T> T castedInvoke(Object instance, Method method, Object... arguments) {
|
||||||
try {
|
|
||||||
return (T) invoke(instance, method, arguments);
|
return (T) invoke(instance, method, arguments);
|
||||||
} catch (NullPointerException exception) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -438,12 +437,7 @@ public final class ReflectionUtils {
|
|||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public static Object invokeStatic(Class<?> clazz, String method) {
|
public static Object invokeStatic(Class<?> clazz, String method) {
|
||||||
try {
|
|
||||||
return invoke(null, getMethod(clazz, method));
|
return invoke(null, getMethod(clazz, method));
|
||||||
} catch (NullPointerException exception) {
|
|
||||||
exception.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import java.util.Map;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.CompletionException;
|
import java.util.concurrent.CompletionException;
|
||||||
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.geysermc.floodgate.api.link.LinkRequest;
|
import org.geysermc.floodgate.api.link.LinkRequest;
|
||||||
import org.geysermc.floodgate.api.link.LinkRequestResult;
|
import org.geysermc.floodgate.api.link.LinkRequestResult;
|
||||||
import org.geysermc.floodgate.link.CommonPlayerLink;
|
import org.geysermc.floodgate.link.CommonPlayerLink;
|
||||||
@@ -59,11 +60,12 @@ public class SqliteDatabase extends CommonPlayerLink {
|
|||||||
try {
|
try {
|
||||||
Class.forName("org.sqlite.JDBC");
|
Class.forName("org.sqlite.JDBC");
|
||||||
connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath.toString());
|
connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath.toString());
|
||||||
Statement statement = connection.createStatement();
|
try (Statement statement = connection.createStatement()) {
|
||||||
statement.setQueryTimeout(30); // set timeout to 30 sec.
|
statement.setQueryTimeout(30); // set timeout to 30 sec.
|
||||||
statement.executeUpdate(
|
statement.executeUpdate(
|
||||||
"create table if not exists LinkedPlayers (bedrockId string, javaUniqueId string, javaUsername string)"
|
"create table if not exists LinkedPlayers (bedrockId string, javaUniqueId string, javaUsername string)"
|
||||||
);
|
);
|
||||||
|
}
|
||||||
} catch (ClassNotFoundException exception) {
|
} catch (ClassNotFoundException exception) {
|
||||||
getLogger().error("The required class to load the SQLite database wasn't found");
|
getLogger().error("The required class to load the SQLite database wasn't found");
|
||||||
} catch (SQLException exception) {
|
} catch (SQLException exception) {
|
||||||
@@ -82,12 +84,12 @@ public class SqliteDatabase extends CommonPlayerLink {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<LinkedPlayer> getLinkedPlayer(UUID bedrockId) {
|
@NonNull
|
||||||
|
public CompletableFuture<LinkedPlayer> getLinkedPlayer(@NonNull UUID bedrockId) {
|
||||||
return CompletableFuture.supplyAsync(() -> {
|
return CompletableFuture.supplyAsync(() -> {
|
||||||
try {
|
try (PreparedStatement query = connection.prepareStatement(
|
||||||
PreparedStatement query = connection.prepareStatement(
|
"select * from LinkedPlayers where bedrockId = ?")) {
|
||||||
"select * from LinkedPlayers where bedrockId = ?"
|
|
||||||
);
|
|
||||||
query.setString(1, bedrockId.toString());
|
query.setString(1, bedrockId.toString());
|
||||||
ResultSet result = query.executeQuery();
|
ResultSet result = query.executeQuery();
|
||||||
if (!result.next()) {
|
if (!result.next()) {
|
||||||
@@ -97,7 +99,7 @@ public class SqliteDatabase extends CommonPlayerLink {
|
|||||||
String javaUsername = result.getString("javaUsername");
|
String javaUsername = result.getString("javaUsername");
|
||||||
UUID javaUniqueId = UUID.fromString(result.getString("javaUniqueId"));
|
UUID javaUniqueId = UUID.fromString(result.getString("javaUniqueId"));
|
||||||
return LinkedPlayer.of(javaUsername, javaUniqueId, bedrockId);
|
return LinkedPlayer.of(javaUsername, javaUniqueId, bedrockId);
|
||||||
} catch (SQLException | NullPointerException exception) {
|
} catch (SQLException exception) {
|
||||||
getLogger().error("Error while getting LinkedPlayer", exception);
|
getLogger().error("Error while getting LinkedPlayer", exception);
|
||||||
throw new CompletionException("Error while getting LinkedPlayer", exception);
|
throw new CompletionException("Error while getting LinkedPlayer", exception);
|
||||||
}
|
}
|
||||||
@@ -105,17 +107,17 @@ public class SqliteDatabase extends CommonPlayerLink {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Boolean> isLinkedPlayer(UUID playerId) {
|
@NonNull
|
||||||
|
public CompletableFuture<Boolean> isLinkedPlayer(@NonNull UUID playerId) {
|
||||||
return CompletableFuture.supplyAsync(() -> {
|
return CompletableFuture.supplyAsync(() -> {
|
||||||
try {
|
try (PreparedStatement query = connection.prepareStatement(
|
||||||
PreparedStatement query = connection.prepareStatement(
|
"select javaUniqueId from LinkedPlayers where bedrockId = ? or javaUniqueId = ?")) {
|
||||||
"select javaUniqueId from LinkedPlayers where bedrockId = ? or javaUniqueId = ?"
|
|
||||||
);
|
|
||||||
query.setString(1, playerId.toString());
|
query.setString(1, playerId.toString());
|
||||||
query.setString(2, playerId.toString());
|
query.setString(2, playerId.toString());
|
||||||
ResultSet result = query.executeQuery();
|
ResultSet result = query.executeQuery();
|
||||||
return result.next();
|
return result.next();
|
||||||
} catch (SQLException | NullPointerException exception) {
|
} catch (SQLException exception) {
|
||||||
getLogger().error("Error while checking if player is a LinkedPlayer", exception);
|
getLogger().error("Error while checking if player is a LinkedPlayer", exception);
|
||||||
throw new CompletionException(
|
throw new CompletionException(
|
||||||
"Error while checking if player is a LinkedPlayer", exception
|
"Error while checking if player is a LinkedPlayer", exception
|
||||||
@@ -125,38 +127,41 @@ public class SqliteDatabase extends CommonPlayerLink {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Void> linkPlayer(UUID bedrockId, UUID javaId, String username) {
|
@NonNull
|
||||||
|
public CompletableFuture<Void> linkPlayer(
|
||||||
|
@NonNull UUID bedrockId,
|
||||||
|
@NonNull UUID javaId,
|
||||||
|
@NonNull String username) {
|
||||||
return CompletableFuture.runAsync(
|
return CompletableFuture.runAsync(
|
||||||
() -> linkPlayer0(bedrockId, javaId, username),
|
() -> linkPlayer0(bedrockId, javaId, username),
|
||||||
getExecutorService());
|
getExecutorService());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void linkPlayer0(UUID bedrockId, UUID javaId, String username) {
|
private void linkPlayer0(UUID bedrockId, UUID javaId, String username) {
|
||||||
try {
|
try (PreparedStatement query =
|
||||||
PreparedStatement query = connection.prepareStatement(
|
connection.prepareStatement("insert into LinkedPlayers values(?, ?, ?)")) {
|
||||||
"insert into LinkedPlayers values(?, ?, ?)"
|
|
||||||
);
|
|
||||||
query.setString(1, bedrockId.toString());
|
query.setString(1, bedrockId.toString());
|
||||||
query.setString(2, javaId.toString());
|
query.setString(2, javaId.toString());
|
||||||
query.setString(3, username);
|
query.setString(3, username);
|
||||||
query.executeUpdate();
|
query.executeUpdate();
|
||||||
} catch (SQLException | NullPointerException exception) {
|
} catch (SQLException exception) {
|
||||||
getLogger().error("Error while linking player", exception);
|
getLogger().error("Error while linking player", exception);
|
||||||
throw new CompletionException("Error while linking player", exception);
|
throw new CompletionException("Error while linking player", exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Void> unlinkPlayer(UUID javaId) {
|
@NonNull
|
||||||
|
public CompletableFuture<Void> unlinkPlayer(@NonNull UUID javaId) {
|
||||||
return CompletableFuture.runAsync(() -> {
|
return CompletableFuture.runAsync(() -> {
|
||||||
try {
|
try (PreparedStatement query = connection.prepareStatement(
|
||||||
PreparedStatement query = connection.prepareStatement(
|
"delete from LinkedPlayers where javaUniqueId = ? or bedrockId = ?")) {
|
||||||
"delete from LinkedPlayers where javaUniqueId = ? or bedrockId = ?"
|
|
||||||
);
|
|
||||||
query.setString(1, javaId.toString());
|
query.setString(1, javaId.toString());
|
||||||
query.setString(2, javaId.toString());
|
query.setString(2, javaId.toString());
|
||||||
query.executeUpdate();
|
query.executeUpdate();
|
||||||
} catch (SQLException | NullPointerException exception) {
|
} catch (SQLException exception) {
|
||||||
getLogger().error("Error while unlinking player", exception);
|
getLogger().error("Error while unlinking player", exception);
|
||||||
throw new CompletionException("Error while unlinking player", exception);
|
throw new CompletionException("Error while unlinking player", exception);
|
||||||
}
|
}
|
||||||
@@ -164,10 +169,11 @@ public class SqliteDatabase extends CommonPlayerLink {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@NonNull
|
||||||
public CompletableFuture<String> createLinkRequest(
|
public CompletableFuture<String> createLinkRequest(
|
||||||
UUID javaId,
|
@NonNull UUID javaId,
|
||||||
String javaUsername,
|
@NonNull String javaUsername,
|
||||||
String bedrockUsername
|
@NonNull String bedrockUsername
|
||||||
) {
|
) {
|
||||||
return CompletableFuture.supplyAsync(() -> {
|
return CompletableFuture.supplyAsync(() -> {
|
||||||
LinkRequest request =
|
LinkRequest request =
|
||||||
@@ -180,11 +186,12 @@ public class SqliteDatabase extends CommonPlayerLink {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@NonNull
|
||||||
public CompletableFuture<LinkRequestResult> verifyLinkRequest(
|
public CompletableFuture<LinkRequestResult> verifyLinkRequest(
|
||||||
UUID bedrockId,
|
@NonNull UUID bedrockId,
|
||||||
String javaUsername,
|
@NonNull String javaUsername,
|
||||||
String bedrockUsername,
|
@NonNull String bedrockUsername,
|
||||||
String code
|
@NonNull String code
|
||||||
) {
|
) {
|
||||||
return CompletableFuture.supplyAsync(() -> {
|
return CompletableFuture.supplyAsync(() -> {
|
||||||
LinkRequest request = activeLinkRequests.get(javaUsername);
|
LinkRequest request = activeLinkRequests.get(javaUsername);
|
||||||
|
|||||||
43
pom.xml
43
pom.xml
@@ -84,4 +84,47 @@
|
|||||||
<repositories>
|
<repositories>
|
||||||
|
|
||||||
</repositories>
|
</repositories>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-pmd-plugin</artifactId>
|
||||||
|
<version>3.14.0</version>
|
||||||
|
<configuration>
|
||||||
|
<rulesets>
|
||||||
|
<ruleset>${session.executionRootDirectory}/ruleset.xml</ruleset>
|
||||||
|
</rulesets>
|
||||||
|
<printFailingErrors>true</printFailingErrors>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>check</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<reporting>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-pmd-plugin</artifactId>
|
||||||
|
<version>3.14.0</version>
|
||||||
|
<configuration>
|
||||||
|
<rulesets>
|
||||||
|
<ruleset>${session.executionRootDirectory}/ruleset.xml</ruleset>
|
||||||
|
</rulesets>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jxr-plugin</artifactId>
|
||||||
|
<version>2.3</version>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</reporting>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
44
ruleset.xml
Normal file
44
ruleset.xml
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<ruleset name="Floodgate Rules"
|
||||||
|
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd">
|
||||||
|
|
||||||
|
<description>
|
||||||
|
Floodgate Code ruleset
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<exclude-pattern>.*/ReflectionUtils.*</exclude-pattern>
|
||||||
|
<exclude-pattern>.*/CommonPlayerLink.*</exclude-pattern><!-- UnusedPrivateMethod -->
|
||||||
|
<exclude-pattern>.*/DefaultConfigHandler.*</exclude-pattern><!-- NullAssignment -->
|
||||||
|
<exclude-pattern>.*/ConfigFileUpdater.*</exclude-pattern><!-- NullAssignment -->
|
||||||
|
<exclude-pattern>.*/FloodgateConfig.*</exclude-pattern><!-- RedundantFieldInitializer -->
|
||||||
|
|
||||||
|
<rule ref="category/java/bestpractices.xml/MissingOverride" />
|
||||||
|
<rule ref="category/java/bestpractices.xml/UseCollectionIsEmpty" />
|
||||||
|
<rule ref="category/java/bestpractices.xml/UseTryWithResources" />
|
||||||
|
|
||||||
|
<rule ref="category/java/errorprone.xml/CloseResource" />
|
||||||
|
<rule ref="category/java/errorprone.xml/UseLocaleWithCaseConversions" />
|
||||||
|
|
||||||
|
<!-- got a bit lazy, just added whole sections and excluded some unnecessary ones -->
|
||||||
|
<rule ref="category/java/bestpractices.xml">
|
||||||
|
<!-- maybe add these ones back later on -->
|
||||||
|
<exclude name="AvoidPrintStackTrace" />
|
||||||
|
<exclude name="GuardLogStatement" />
|
||||||
|
</rule>
|
||||||
|
<rule ref="category/java/errorprone.xml">
|
||||||
|
<exclude name="AvoidDuplicateLiterals" />
|
||||||
|
<exclude name="AvoidLiteralsInIfCondition" /><!-- Some things just don't change :shrug: -->
|
||||||
|
<exclude name="AvoidFieldNameMatchingMethodName" />
|
||||||
|
<exclude name="BeanMembersShouldSerialize" />
|
||||||
|
<exclude name="UseProperClassLoader" />
|
||||||
|
</rule>
|
||||||
|
<rule ref="category/java/performance.xml">
|
||||||
|
<exclude name="AvoidUsingShortType" />
|
||||||
|
<exclude name="AvoidInstantiatingObjectsInLoops" /><!-- this is ok to some extend -->
|
||||||
|
<exclude name="InefficientStringBuffering" />
|
||||||
|
</rule>
|
||||||
|
<rule ref="category/java/security.xml" />
|
||||||
|
|
||||||
|
</ruleset>
|
||||||
@@ -126,7 +126,7 @@ public final class SpigotDataHandler extends SimpleChannelInboundHandler<Object>
|
|||||||
Enum<?>[] protocolStates = (Enum<?>[]) PROTOCOL_STATE.getType().getEnumConstants();
|
Enum<?>[] protocolStates = (Enum<?>[]) PROTOCOL_STATE.getType().getEnumConstants();
|
||||||
Object readyToAcceptState = null;
|
Object readyToAcceptState = null;
|
||||||
for (Enum<?> protocolState : protocolStates) {
|
for (Enum<?> protocolState : protocolStates) {
|
||||||
if (protocolState.name().equals("READY_TO_ACCEPT")) {
|
if ("READY_TO_ACCEPT".equals(protocolState.name())) {
|
||||||
readyToAcceptState = protocolState;
|
readyToAcceptState = protocolState;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ public final class SpigotInjector extends CommonPlatformInjector {
|
|||||||
private Object serverConnection;
|
private Object serverConnection;
|
||||||
private String injectedFieldName;
|
private String injectedFieldName;
|
||||||
|
|
||||||
@Getter private boolean injected = false;
|
@Getter private boolean injected;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter")
|
@SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter")
|
||||||
@@ -148,7 +148,6 @@ public final class SpigotInjector extends CommonPlatformInjector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
injectedFieldName = null;
|
|
||||||
injected = false;
|
injected = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -162,7 +161,7 @@ public final class SpigotInjector extends CommonPlatformInjector {
|
|||||||
|
|
||||||
Object minecraftServerInstance = ReflectionUtils.invokeStatic(minecraftServer, "getServer");
|
Object minecraftServerInstance = ReflectionUtils.invokeStatic(minecraftServer, "getServer");
|
||||||
for (Method method : minecraftServer.getDeclaredMethods()) {
|
for (Method method : minecraftServer.getDeclaredMethods()) {
|
||||||
if (method.getReturnType().getSimpleName().equals("ServerConnection")) {
|
if ("ServerConnection".equals(method.getReturnType().getSimpleName())) {
|
||||||
if (method.getParameterTypes().length == 0) {
|
if (method.getParameterTypes().length == 0) {
|
||||||
serverConnection = method.invoke(minecraftServerInstance);
|
serverConnection = method.invoke(minecraftServerInstance);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,8 +57,7 @@ public final class SpigotSkinApplier implements SkinApplier {
|
|||||||
public SpigotSkinApplier(
|
public SpigotSkinApplier(
|
||||||
SpigotVersionSpecificMethods versionSpecificMethods,
|
SpigotVersionSpecificMethods versionSpecificMethods,
|
||||||
SpigotPlugin plugin,
|
SpigotPlugin plugin,
|
||||||
FloodgateConfigHolder configHolder
|
FloodgateConfigHolder configHolder) {
|
||||||
) {
|
|
||||||
this.versionSpecificMethods = versionSpecificMethods;
|
this.versionSpecificMethods = versionSpecificMethods;
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.configHolder = configHolder;
|
this.configHolder = configHolder;
|
||||||
@@ -89,7 +88,7 @@ public final class SpigotSkinApplier implements SkinApplier {
|
|||||||
// By running as a task, we don't run into async issues
|
// By running as a task, we don't run into async issues
|
||||||
plugin.getServer().getScheduler().runTask(plugin, () -> {
|
plugin.getServer().getScheduler().runTask(plugin, () -> {
|
||||||
for (Player p : Bukkit.getOnlinePlayers()) {
|
for (Player p : Bukkit.getOnlinePlayers()) {
|
||||||
if (p != player && p.canSee(player)) {
|
if (!p.equals(player) && p.canSee(player)) {
|
||||||
versionSpecificMethods.hidePlayer(p, player);
|
versionSpecificMethods.hidePlayer(p, player);
|
||||||
versionSpecificMethods.showPlayer(p, player);
|
versionSpecificMethods.showPlayer(p, player);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ public final class SpigotCommandUtil implements CommandUtil {
|
|||||||
private final FloodgateLogger logger;
|
private final FloodgateLogger logger;
|
||||||
private final LanguageManager manager;
|
private final LanguageManager manager;
|
||||||
|
|
||||||
|
@Override
|
||||||
public @NonNull UserAudience getAudience(final @NonNull Object sourceObj) {
|
public @NonNull UserAudience getAudience(final @NonNull Object sourceObj) {
|
||||||
if (!(sourceObj instanceof CommandSender)) {
|
if (!(sourceObj instanceof CommandSender)) {
|
||||||
throw new IllegalArgumentException("Source has to be a CommandSender!");
|
throw new IllegalArgumentException("Source has to be a CommandSender!");
|
||||||
@@ -116,14 +117,14 @@ public final class SpigotCommandUtil implements CommandUtil {
|
|||||||
break;
|
break;
|
||||||
case ONLY_JAVA:
|
case ONLY_JAVA:
|
||||||
for (Player player : players) {
|
for (Player player : players) {
|
||||||
if (!api.isBedrockPlayer(player.getUniqueId())) {
|
if (!api.isFloodgatePlayer(player.getUniqueId())) {
|
||||||
usernames.add(player.getName());
|
usernames.add(player.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ONLY_BEDROCK:
|
case ONLY_BEDROCK:
|
||||||
for (Player player : players) {
|
for (Player player : players) {
|
||||||
if (api.isBedrockPlayer(player.getUniqueId())) {
|
if (api.isFloodgatePlayer(player.getUniqueId())) {
|
||||||
usernames.add(player.getName());
|
usernames.add(player.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,6 +106,7 @@ public final class VelocityProxyDataHandler extends SimpleChannelInboundHandler<
|
|||||||
break;
|
break;
|
||||||
case EXCEPTION:
|
case EXCEPTION:
|
||||||
ctx.channel().attr(kickMessageAttribute).set(config.getDisconnect().getInvalidKey());
|
ctx.channel().attr(kickMessageAttribute).set(config.getDisconnect().getInvalidKey());
|
||||||
|
return;
|
||||||
case INVALID_DATA_LENGTH:
|
case INVALID_DATA_LENGTH:
|
||||||
ctx.channel().attr(kickMessageAttribute)
|
ctx.channel().attr(kickMessageAttribute)
|
||||||
.set(config.getDisconnect().getInvalidArgumentsLength());
|
.set(config.getDisconnect().getInvalidArgumentsLength());
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ public final class VelocityServerDataHandler extends MessageToMessageEncoder<Obj
|
|||||||
checkArgument(encryptedData != null, "Encrypted data cannot be null");
|
checkArgument(encryptedData != null, "Encrypted data cannot be null");
|
||||||
|
|
||||||
// use the same system that we use on bungee, our data goes before all the other data
|
// use the same system that we use on bungee, our data goes before all the other data
|
||||||
int addressFinished = address.indexOf("\0");
|
int addressFinished = address.indexOf('\0');
|
||||||
String originalAddress = address.substring(0, addressFinished);
|
String originalAddress = address.substring(0, addressFinished);
|
||||||
String remaining = address.substring(addressFinished);
|
String remaining = address.substring(addressFinished);
|
||||||
|
|
||||||
|
|||||||
@@ -44,8 +44,9 @@ public final class VelocityInjector extends CommonPlatformInjector {
|
|||||||
private final ProxyServer server;
|
private final ProxyServer server;
|
||||||
private final FloodgateLogger logger;
|
private final FloodgateLogger logger;
|
||||||
|
|
||||||
@Getter private boolean injected = false;
|
@Getter private boolean injected;
|
||||||
|
|
||||||
|
@Override
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
public boolean inject() {
|
public boolean inject() {
|
||||||
if (isInjected()) {
|
if (isInjected()) {
|
||||||
|
|||||||
@@ -25,7 +25,9 @@
|
|||||||
|
|
||||||
package org.geysermc.floodgate.listener;
|
package org.geysermc.floodgate.listener;
|
||||||
|
|
||||||
|
import com.google.gson.JsonIOException;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonSyntaxException;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.name.Named;
|
import com.google.inject.name.Named;
|
||||||
import com.velocitypowered.api.event.Subscribe;
|
import com.velocitypowered.api.event.Subscribe;
|
||||||
@@ -165,7 +167,7 @@ public class VelocityPluginMessageHandler extends PluginMessageHandler {
|
|||||||
try {
|
try {
|
||||||
Reader reader = new InputStreamReader(new ByteArrayInputStream(responseData));
|
Reader reader = new InputStreamReader(new ByteArrayInputStream(responseData));
|
||||||
response = GSON.fromJson(reader, JsonObject.class);
|
response = GSON.fromJson(reader, JsonObject.class);
|
||||||
} catch (Throwable throwable) {
|
} catch (JsonIOException | JsonSyntaxException throwable) {
|
||||||
logger.error("Failed to read Skin response", throwable);
|
logger.error("Failed to read Skin response", throwable);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,14 +115,14 @@ public final class VelocityCommandUtil implements CommandUtil {
|
|||||||
break;
|
break;
|
||||||
case ONLY_JAVA:
|
case ONLY_JAVA:
|
||||||
for (Player player : players) {
|
for (Player player : players) {
|
||||||
if (!api.isBedrockPlayer(player.getUniqueId())) {
|
if (!api.isFloodgatePlayer(player.getUniqueId())) {
|
||||||
usernames.add(player.getUsername());
|
usernames.add(player.getUsername());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ONLY_BEDROCK:
|
case ONLY_BEDROCK:
|
||||||
for (Player player : players) {
|
for (Player player : players) {
|
||||||
if (api.isBedrockPlayer(player.getUniqueId())) {
|
if (api.isFloodgatePlayer(player.getUniqueId())) {
|
||||||
usernames.add(player.getUsername());
|
usernames.add(player.getUsername());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user