From b737184fb0ac7338bd14e831bdb88ba79dd32f86 Mon Sep 17 00:00:00 2001 From: Tim203 Date: Sat, 16 Jan 2021 16:52:04 +0100 Subject: [PATCH] Added PMD Plugin and changed isBedrockPlayer to isFloodgatePlayer --- .../geysermc/floodgate/api/FloodgateApi.java | 6 +- .../floodgate/api/InstanceHolder.java | 25 +++--- .../floodgate/api/link/PlayerLink.java | 32 +++++--- .../floodgate/api/player/PropertyKey.java | 12 --- .../floodgate/handler/BungeeDataHandler.java | 25 +++--- .../BungeePluginMessageHandler.java | 4 +- .../floodgate/util/BungeeCommandUtil.java | 4 +- .../geysermc/floodgate/FloodgatePlatform.java | 18 +++-- .../addonmanager/AddonManagerHandler.java | 4 +- .../floodgate/api/SimpleFloodgateApi.java | 2 +- .../floodgate/command/LinkAccountCommand.java | 6 +- .../floodgate/config/FloodgateConfig.java | 2 +- .../config/loader/ConfigInitializer.java | 16 ++-- .../floodgate/config/loader/ConfigLoader.java | 5 +- .../config/updater/ConfigFileUpdater.java | 14 ++-- .../config/updater/ConfigUpdater.java | 13 ++- .../floodgate/link/DisabledPlayerLink.java | 2 + .../floodgate/link/GlobalPlayerLinking.java | 2 +- .../floodgate/link/LinkRequestImpl.java | 1 + .../floodgate/link/PlayerLinkLoader.java | 52 +++++++----- .../logger/JavaUtilFloodgateLogger.java | 2 +- .../platform/command/CommandMessage.java | 2 +- .../pluginmessage/PluginMessageHandler.java | 2 +- .../floodgate/player/FloodgatePlayerImpl.java | 2 + .../floodgate/player/HandshakeHandler.java | 56 ++++++------- .../floodgate/player/UserAudience.java | 1 + .../player/UserAudienceArgument.java | 14 +++- .../geysermc/floodgate/skin/SkinUploader.java | 17 ++-- .../geysermc/floodgate/util/Constants.java | 30 +++++++ .../floodgate/util/LanguageManager.java | 20 ++--- .../floodgate/util/MessageFormatter.java | 5 +- .../floodgate/util/ReflectionUtils.java | 24 +++--- .../floodgate/database/SqliteDatabase.java | 79 ++++++++++--------- pom.xml | 43 ++++++++++ ruleset.xml | 44 +++++++++++ .../addon/data/SpigotDataHandler.java | 2 +- .../inject/spigot/SpigotInjector.java | 5 +- .../pluginmessage/SpigotSkinApplier.java | 5 +- .../floodgate/util/SpigotCommandUtil.java | 5 +- .../addon/data/VelocityProxyDataHandler.java | 1 + .../addon/data/VelocityServerDataHandler.java | 2 +- .../inject/velocity/VelocityInjector.java | 3 +- .../VelocityPluginMessageHandler.java | 4 +- .../floodgate/util/VelocityCommandUtil.java | 4 +- 44 files changed, 392 insertions(+), 225 deletions(-) create mode 100644 common/src/main/java/org/geysermc/floodgate/util/Constants.java create mode 100644 ruleset.xml diff --git a/api/src/main/java/org/geysermc/floodgate/api/FloodgateApi.java b/api/src/main/java/org/geysermc/floodgate/api/FloodgateApi.java index cf9cc00d..1e105a8b 100644 --- a/api/src/main/java/org/geysermc/floodgate/api/FloodgateApi.java +++ b/api/src/main/java/org/geysermc/floodgate/api/FloodgateApi.java @@ -36,7 +36,7 @@ public interface FloodgateApi { * Returns the Floodgate API instance. */ static FloodgateApi getInstance() { - return InstanceHolder.getInstance(); + return InstanceHolder.getApi(); } /** @@ -45,7 +45,7 @@ public interface FloodgateApi { * @param uuid The uuid of the online player * @return true if the given online player is a Bedrock player */ - boolean isBedrockPlayer(UUID uuid); + boolean isFloodgatePlayer(UUID uuid); /** * 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 * 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 * @return true if the given uuid has the correct format. diff --git a/api/src/main/java/org/geysermc/floodgate/api/InstanceHolder.java b/api/src/main/java/org/geysermc/floodgate/api/InstanceHolder.java index 3d7a7b91..18646a62 100644 --- a/api/src/main/java/org/geysermc/floodgate/api/InstanceHolder.java +++ b/api/src/main/java/org/geysermc/floodgate/api/InstanceHolder.java @@ -32,25 +32,28 @@ import org.geysermc.floodgate.api.inject.PlatformInjector; import org.geysermc.floodgate.api.link.PlayerLink; public final class InstanceHolder { - @Getter private static FloodgateApi instance; + @Getter private static FloodgateApi api; @Getter private static PlayerLink playerLink; @Getter private static PlatformInjector injector; @Getter private static HandshakeHandlers handshakeHandlers; - private static UUID key; + private static UUID storedKey; - public static boolean setInstance( + public static boolean set( FloodgateApi floodgateApi, PlayerLink link, PlatformInjector platformInjector, HandshakeHandlers handshakeHandlers, - UUID key - ) { - if (instance == null) { - InstanceHolder.key = key; - } else if (!InstanceHolder.key.equals(key)) { - return false; + UUID key) { + + if (storedKey != null) { + if (!storedKey.equals(key)) { + return false; + } + } else { + storedKey = key; } - instance = floodgateApi; + + api = floodgateApi; playerLink = link; injector = platformInjector; InstanceHolder.handshakeHandlers = handshakeHandlers; @@ -59,6 +62,6 @@ public final class InstanceHolder { @SuppressWarnings("unchecked") public static T castApi(Class cast) { - return (T) instance; + return (T) api; } } diff --git a/api/src/main/java/org/geysermc/floodgate/api/link/PlayerLink.java b/api/src/main/java/org/geysermc/floodgate/api/link/PlayerLink.java index 9ecbd7f1..95403ee3 100644 --- a/api/src/main/java/org/geysermc/floodgate/api/link/PlayerLink.java +++ b/api/src/main/java/org/geysermc/floodgate/api/link/PlayerLink.java @@ -27,6 +27,7 @@ package org.geysermc.floodgate.api.link; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import org.checkerframework.checker.nullness.qual.NonNull; 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 * if that Bedrock player isn't linked */ - CompletableFuture getLinkedPlayer(UUID bedrockId); + @NonNull + CompletableFuture getLinkedPlayer(@NonNull UUID bedrockId); /** * 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 * @return true if the player is a linked player */ - CompletableFuture isLinkedPlayer(UUID playerId); + @NonNull + CompletableFuture isLinkedPlayer(@NonNull UUID playerId); /** * Links a Java account to a Bedrock account. @@ -67,7 +70,11 @@ public interface PlayerLink { * @param username the username of the Java player * @return a future holding void on success or completed exceptionally when failed */ - CompletableFuture linkPlayer(UUID bedrockId, UUID javaId, String username); + @NonNull + CompletableFuture linkPlayer( + @NonNull UUID bedrockId, + @NonNull UUID javaId, + @NonNull String username); /** * Unlinks a Java account from a Bedrock account. @@ -75,7 +82,8 @@ public interface PlayerLink { * @param javaId the uuid of the Java player * @return a future holding void on success or completed exceptionally when failed */ - CompletableFuture unlinkPlayer(UUID javaId); + @NonNull + CompletableFuture unlinkPlayer(@NonNull UUID javaId); /** * 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 * LinkRequestResult} on failure and the link code (string) on success */ + @NonNull CompletableFuture createLinkRequest( - UUID javaId, - String javaUsername, - String bedrockUsername + @NonNull UUID javaId, + @NonNull String javaUsername, + @NonNull String bedrockUsername ); /** @@ -101,11 +110,12 @@ public interface PlayerLink { * @param code the code created in {@link #createLinkRequest(UUID, String, String)} * @return a future holding the result of the link verification */ + @NonNull CompletableFuture verifyLinkRequest( - UUID bedrockId, - String javaUsername, - String bedrockUsername, - String code + @NonNull UUID bedrockId, + @NonNull String javaUsername, + @NonNull String bedrockUsername, + @NonNull String code ); /** diff --git a/api/src/main/java/org/geysermc/floodgate/api/player/PropertyKey.java b/api/src/main/java/org/geysermc/floodgate/api/player/PropertyKey.java index 23a267d6..ae25b75d 100644 --- a/api/src/main/java/org/geysermc/floodgate/api/player/PropertyKey.java +++ b/api/src/main/java/org/geysermc/floodgate/api/player/PropertyKey.java @@ -51,18 +51,6 @@ public class PropertyKey { 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 if (obj instanceof PropertyKey) { PropertyKey propertyKey = (PropertyKey) obj; diff --git a/bungee/src/main/java/org/geysermc/floodgate/handler/BungeeDataHandler.java b/bungee/src/main/java/org/geysermc/floodgate/handler/BungeeDataHandler.java index 56ac8ee4..f83c47ce 100644 --- a/bungee/src/main/java/org/geysermc/floodgate/handler/BungeeDataHandler.java +++ b/bungee/src/main/java/org/geysermc/floodgate/handler/BungeeDataHandler.java @@ -106,16 +106,19 @@ public final class BungeeDataHandler { return; } - switch (result.getResultType()) { - case EXCEPTION: - event.setCancelReason(config.getDisconnect().getInvalidKey()); - break; - case INVALID_DATA_LENGTH: - event.setCancelReason(TextComponent.fromLegacyText(String.format( - config.getDisconnect().getInvalidArgumentsLength(), - BedrockData.EXPECTED_LENGTH, result.getBedrockData().getDataLength() - ))); - break; + if (result.getResultType() == ResultType.EXCEPTION) { + event.setCancelReason(config.getDisconnect().getInvalidKey()); + event.completeIntent(plugin); + return; + } + + if (result.getResultType() == ResultType.INVALID_DATA_LENGTH) { + event.setCancelReason(TextComponent.fromLegacyText(String.format( + config.getDisconnect().getInvalidArgumentsLength(), + BedrockData.EXPECTED_LENGTH, result.getBedrockData().getDataLength() + ))); + event.completeIntent(plugin); + return; } // only continue when SUCCESS @@ -155,7 +158,7 @@ public final class BungeeDataHandler { public void handleServerConnect(ProxiedPlayer player) { // 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( player.getPendingConnection(), CACHED_HANDSHAKE_PACKET ); diff --git a/bungee/src/main/java/org/geysermc/floodgate/pluginmessage/BungeePluginMessageHandler.java b/bungee/src/main/java/org/geysermc/floodgate/pluginmessage/BungeePluginMessageHandler.java index 58608535..a374811d 100644 --- a/bungee/src/main/java/org/geysermc/floodgate/pluginmessage/BungeePluginMessageHandler.java +++ b/bungee/src/main/java/org/geysermc/floodgate/pluginmessage/BungeePluginMessageHandler.java @@ -25,7 +25,9 @@ package org.geysermc.floodgate.pluginmessage; +import com.google.gson.JsonIOException; import com.google.gson.JsonObject; +import com.google.gson.JsonSyntaxException; import com.google.inject.Inject; import com.google.inject.name.Named; import java.io.ByteArrayInputStream; @@ -165,7 +167,7 @@ public final class BungeePluginMessageHandler extends PluginMessageHandler imple try { Reader reader = new InputStreamReader(new ByteArrayInputStream(responseData)); response = GSON.fromJson(reader, JsonObject.class); - } catch (Throwable throwable) { + } catch (JsonIOException | JsonSyntaxException throwable) { logger.error("Failed to read Skin response", throwable); return; } diff --git a/bungee/src/main/java/org/geysermc/floodgate/util/BungeeCommandUtil.java b/bungee/src/main/java/org/geysermc/floodgate/util/BungeeCommandUtil.java index a0751cf3..0d6643df 100644 --- a/bungee/src/main/java/org/geysermc/floodgate/util/BungeeCommandUtil.java +++ b/bungee/src/main/java/org/geysermc/floodgate/util/BungeeCommandUtil.java @@ -116,14 +116,14 @@ public final class BungeeCommandUtil implements CommandUtil { break; case ONLY_JAVA: for (ProxiedPlayer player : players) { - if (!api.isBedrockPlayer(player.getUniqueId())) { + if (!api.isFloodgatePlayer(player.getUniqueId())) { usernames.add(player.getName()); } } break; case ONLY_BEDROCK: for (ProxiedPlayer player : players) { - if (api.isBedrockPlayer(player.getUniqueId())) { + if (api.isFloodgatePlayer(player.getUniqueId())) { usernames.add(player.getName()); } } diff --git a/common/src/main/java/org/geysermc/floodgate/FloodgatePlatform.java b/common/src/main/java/org/geysermc/floodgate/FloodgatePlatform.java index 728ea870..9c5523a7 100644 --- a/common/src/main/java/org/geysermc/floodgate/FloodgatePlatform.java +++ b/common/src/main/java/org/geysermc/floodgate/FloodgatePlatform.java @@ -29,6 +29,7 @@ import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.Module; import com.google.inject.name.Named; +import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.UUID; @@ -56,8 +57,12 @@ public class FloodgatePlatform { private Injector guice; @Inject - public FloodgatePlatform(FloodgateApi api, PlatformInjector platformInjector, - FloodgateLogger logger, Injector guice) { + public FloodgatePlatform( + FloodgateApi api, + PlatformInjector platformInjector, + FloodgateLogger logger, + Injector guice) { + this.api = api; this.injector = platformInjector; this.logger = logger; @@ -69,15 +74,14 @@ public class FloodgatePlatform { @Named("dataDirectory") Path dataDirectory, ConfigLoader configLoader, FloodgateConfigHolder configHolder, - HandshakeHandlers handshakeHandlers - ) { + HandshakeHandlers handshakeHandlers) { if (!Files.isDirectory(dataDirectory)) { try { Files.createDirectory(dataDirectory); - } catch (Exception exception) { + } catch (IOException 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)); 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) { diff --git a/common/src/main/java/org/geysermc/floodgate/addon/addonmanager/AddonManagerHandler.java b/common/src/main/java/org/geysermc/floodgate/addon/addonmanager/AddonManagerHandler.java index dcfd52ee..4e694665 100644 --- a/common/src/main/java/org/geysermc/floodgate/addon/addonmanager/AddonManagerHandler.java +++ b/common/src/main/java/org/geysermc/floodgate/addon/addonmanager/AddonManagerHandler.java @@ -31,6 +31,7 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; import lombok.RequiredArgsConstructor; import org.geysermc.floodgate.inject.CommonPlatformInjector; +import org.geysermc.floodgate.util.Constants; @RequiredArgsConstructor public final class AddonManagerHandler extends MessageToByteEncoder { @@ -57,8 +58,7 @@ public final class AddonManagerHandler extends MessageToByteEncoder { } int index = msg.readerIndex(); - // LoginSuccess packet = 2 - if (readVarInt(msg) == 2) { + if (readVarInt(msg) == Constants.LOGIN_SUCCESS_PACKET_ID) { loggedIn = true; injector.loginSuccessCall(channel); } diff --git a/common/src/main/java/org/geysermc/floodgate/api/SimpleFloodgateApi.java b/common/src/main/java/org/geysermc/floodgate/api/SimpleFloodgateApi.java index de3c5041..f72042cb 100644 --- a/common/src/main/java/org/geysermc/floodgate/api/SimpleFloodgateApi.java +++ b/common/src/main/java/org/geysermc/floodgate/api/SimpleFloodgateApi.java @@ -43,7 +43,7 @@ public class SimpleFloodgateApi implements FloodgateApi { private final PluginMessageHandler pluginMessageHandler; @Override - public boolean isBedrockPlayer(UUID uuid) { + public boolean isFloodgatePlayer(UUID uuid) { return getPlayer(uuid) != null; } diff --git a/common/src/main/java/org/geysermc/floodgate/command/LinkAccountCommand.java b/common/src/main/java/org/geysermc/floodgate/command/LinkAccountCommand.java index d3c175dc..49b1b64f 100644 --- a/common/src/main/java/org/geysermc/floodgate/command/LinkAccountCommand.java +++ b/common/src/main/java/org/geysermc/floodgate/command/LinkAccountCommand.java @@ -35,6 +35,7 @@ import cloud.commandframework.context.CommandContext; import com.google.inject.Inject; import lombok.Getter; import lombok.NoArgsConstructor; +import net.kyori.adventure.text.Component; import org.geysermc.floodgate.api.FloodgateApi; import org.geysermc.floodgate.api.link.LinkRequestResult; import org.geysermc.floodgate.api.link.PlayerLink; @@ -74,7 +75,7 @@ public final class LinkAccountCommand implements FloodgateCommand { } // when the player is a Bedrock player - if (api.isBedrockPlayer(sender.uuid())) { + if (api.isFloodgatePlayer(sender.uuid())) { if (!context.contains("code")) { sender.sendMessage(Message.BEDROCK_USAGE); return; @@ -107,6 +108,9 @@ public final class LinkAccountCommand implements FloodgateCommand { case LINK_COMPLETED: sender.disconnect(Message.LINK_REQUEST_COMPLETED, targetName); break; + default: + sender.disconnect(Component.text("Invalid account linking result")); + break; } }); return; diff --git a/common/src/main/java/org/geysermc/floodgate/config/FloodgateConfig.java b/common/src/main/java/org/geysermc/floodgate/config/FloodgateConfig.java index 1cdd7ec7..4370bed5 100644 --- a/common/src/main/java/org/geysermc/floodgate/config/FloodgateConfig.java +++ b/common/src/main/java/org/geysermc/floodgate/config/FloodgateConfig.java @@ -47,7 +47,7 @@ public class FloodgateConfig { private boolean debug; private int configVersion; - private Key key = null; + private Key key; public void setKey(Key key) { if (this.key == null) { diff --git a/common/src/main/java/org/geysermc/floodgate/config/loader/ConfigInitializer.java b/common/src/main/java/org/geysermc/floodgate/config/loader/ConfigInitializer.java index 398737b5..a4f470a8 100644 --- a/common/src/main/java/org/geysermc/floodgate/config/loader/ConfigInitializer.java +++ b/common/src/main/java/org/geysermc/floodgate/config/loader/ConfigInitializer.java @@ -43,8 +43,8 @@ public class ConfigInitializer { private static final Yaml YAML; static { - Constructor constructor = new CustomClassLoaderConstructor( - ConfigInitializer.class.getClassLoader()); + Constructor constructor = + new CustomClassLoaderConstructor(ConfigInitializer.class.getClassLoader()); constructor.setPropertyUtils(new PropertyUtils() { @Override @@ -54,8 +54,11 @@ public class ConfigInitializer { return properties; } - private void getPropertiesFromClass(Class type, Class stopAfter, - Map propertyMap) { + private void getPropertiesFromClass( + Class type, + Class stopAfter, + Map propertyMap) { + Class current = type; while (!Object.class.equals(current)) { for (Field field : current.getDeclaredFields()) { @@ -98,8 +101,9 @@ public class ConfigInitializer { YAML = new Yaml(constructor); } - public static T initializeFrom(InputStream dataStream, - Class configClass) { + public static T initializeFrom( + InputStream dataStream, + Class configClass) { return YAML.loadAs(dataStream, configClass); } } diff --git a/common/src/main/java/org/geysermc/floodgate/config/loader/ConfigLoader.java b/common/src/main/java/org/geysermc/floodgate/config/loader/ConfigLoader.java index 216e2b73..287b711b 100644 --- a/common/src/main/java/org/geysermc/floodgate/config/loader/ConfigLoader.java +++ b/common/src/main/java/org/geysermc/floodgate/config/loader/ConfigLoader.java @@ -86,7 +86,8 @@ public final class ConfigLoader { } } catch (Exception 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()); @@ -125,7 +126,7 @@ public final class ConfigLoader { configInstance.setKey(key); } catch (IOException 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; diff --git a/common/src/main/java/org/geysermc/floodgate/config/updater/ConfigFileUpdater.java b/common/src/main/java/org/geysermc/floodgate/config/updater/ConfigFileUpdater.java index cf88cdbf..0fa30299 100644 --- a/common/src/main/java/org/geysermc/floodgate/config/updater/ConfigFileUpdater.java +++ b/common/src/main/java/org/geysermc/floodgate/config/updater/ConfigFileUpdater.java @@ -51,9 +51,13 @@ public final class ConfigFileUpdater { * @param defaultConfigLocation the location of the default Floodgate config * @throws IOException if an I/O error occurs */ - public void update(Path configLocation, Map currentVersion, - Map renames, String defaultConfigLocation) + public void update( + Path configLocation, + Map currentVersion, + Map renames, + String defaultConfigLocation) throws IOException { + List notFound = new ArrayList<>(); List newConfig = defaultConfigHandler.loadDefaultConfig(defaultConfigLocation); @@ -64,7 +68,7 @@ public final class ConfigFileUpdater { for (int i = 0; i < newConfig.size(); i++) { line = newConfig.get(i); // we don't have to check comments or empty lines - if (line.length() == 0 || line.startsWith("#")) { + if (line.isEmpty() || line.charAt(0) == '#') { continue; } @@ -74,7 +78,7 @@ public final class ConfigFileUpdater { } // 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 spaces = ""; map = null; @@ -134,7 +138,7 @@ public final class ConfigFileUpdater { logger.info("Successfully updated the config file! " + "Your old config has been moved to config-old.yml"); - if (notFound.size() > 0) { + if (!notFound.isEmpty()) { StringBuilder messageBuilder = new StringBuilder( "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: "); diff --git a/common/src/main/java/org/geysermc/floodgate/config/updater/ConfigUpdater.java b/common/src/main/java/org/geysermc/floodgate/config/updater/ConfigUpdater.java index 89823751..76523e16 100644 --- a/common/src/main/java/org/geysermc/floodgate/config/updater/ConfigUpdater.java +++ b/common/src/main/java/org/geysermc/floodgate/config/updater/ConfigUpdater.java @@ -48,16 +48,15 @@ public final class ConfigUpdater { public void update(String defaultConfigLocation) { Path configLocation = dataFolder.resolve("config.yml"); - BufferedReader configReader; - try { - configReader = Files.newBufferedReader(configLocation); + Map config; + + try (BufferedReader configReader = Files.newBufferedReader(configLocation)) { + config = new Yaml().load(configReader); } catch (IOException 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 config = new Yaml().load(configReader); - // new name -> old name Map renames = new HashMap<>(); @@ -93,7 +92,7 @@ public final class ConfigUpdater { fileUpdater.update(configLocation, config, renames, defaultConfigLocation); } catch (IOException 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); } } } diff --git a/common/src/main/java/org/geysermc/floodgate/link/DisabledPlayerLink.java b/common/src/main/java/org/geysermc/floodgate/link/DisabledPlayerLink.java index f162ea8b..88c209af 100644 --- a/common/src/main/java/org/geysermc/floodgate/link/DisabledPlayerLink.java +++ b/common/src/main/java/org/geysermc/floodgate/link/DisabledPlayerLink.java @@ -42,6 +42,8 @@ final class DisabledPlayerLink implements PlayerLink { public void load() { } + //todo don't return null + @Override public CompletableFuture getLinkedPlayer(UUID bedrockId) { return null; diff --git a/common/src/main/java/org/geysermc/floodgate/link/GlobalPlayerLinking.java b/common/src/main/java/org/geysermc/floodgate/link/GlobalPlayerLinking.java index 1cb6e5cd..c5c220d5 100644 --- a/common/src/main/java/org/geysermc/floodgate/link/GlobalPlayerLinking.java +++ b/common/src/main/java/org/geysermc/floodgate/link/GlobalPlayerLinking.java @@ -99,7 +99,7 @@ public class GlobalPlayerLinking extends CommonPlayerLink { // player linking and unlinking now goes through the global player linking server. // 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 public CompletableFuture linkPlayer(UUID bedrockId, UUID javaId, String username) { diff --git a/common/src/main/java/org/geysermc/floodgate/link/LinkRequestImpl.java b/common/src/main/java/org/geysermc/floodgate/link/LinkRequestImpl.java index dc9e2c3a..9eff4528 100644 --- a/common/src/main/java/org/geysermc/floodgate/link/LinkRequestImpl.java +++ b/common/src/main/java/org/geysermc/floodgate/link/LinkRequestImpl.java @@ -47,6 +47,7 @@ public final class LinkRequestImpl implements LinkRequest { requestTime = Instant.now().getEpochSecond(); } + @Override public boolean isExpired(long linkTimeout) { long timePassed = Instant.now().getEpochSecond() - requestTime; return timePassed > linkTimeout; diff --git a/common/src/main/java/org/geysermc/floodgate/link/PlayerLinkLoader.java b/common/src/main/java/org/geysermc/floodgate/link/PlayerLinkLoader.java index 81f63a58..e98d0d94 100644 --- a/common/src/main/java/org/geysermc/floodgate/link/PlayerLinkLoader.java +++ b/common/src/main/java/org/geysermc/floodgate/link/PlayerLinkLoader.java @@ -40,6 +40,7 @@ import java.net.URLClassLoader; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; +import java.util.Locale; import java.util.stream.Collectors; import javax.inject.Named; import org.geysermc.floodgate.api.link.PlayerLink; @@ -61,13 +62,13 @@ public final class PlayerLinkLoader { throw new IllegalStateException("Config cannot be null!"); } - FloodgateConfig.PlayerLinkConfig linkConfig = config.getPlayerLink(); - if (!linkConfig.isEnabled()) { + FloodgateConfig.PlayerLinkConfig linkingConfig = config.getPlayerLink(); + if (!linkingConfig.isEnabled()) { return new DisabledPlayerLink(); } // we use our own internal PlayerLinking when global linking is enabled - if (linkConfig.isUseGlobalLinking()) { + if (linkingConfig.isUseGlobalLinking()) { return injector.getInstance(GlobalPlayerLinking.class); } @@ -81,7 +82,7 @@ public final class PlayerLinkLoader { return null; } - if (files.size() == 0) { + if (files.isEmpty()) { logger.error("Failed to find a database implementation"); return null; } @@ -89,17 +90,20 @@ public final class PlayerLinkLoader { Path implementationPath = files.get(0); // We only want to load one database implementation - String type = linkConfig.getType().toLowerCase(); if (files.size() > 1) { - implementationPath = null; + boolean found = false; + + String type = linkingConfig.getType().toLowerCase(Locale.ROOT); for (Path path : files) { - if (path.getFileName().toString().toLowerCase().contains(type)) { + if (path.getFileName().toString().toLowerCase(Locale.ROOT).contains(type)) { implementationPath = path; + found = true; } } - if (implementationPath == null) { + + if (!found) { logger.error("Failed to find an implementation for type: {}", - linkConfig.getType()); + linkingConfig.getType()); return null; } } @@ -107,23 +111,29 @@ public final class PlayerLinkLoader { Class mainClass; try { URL pluginUrl = implementationPath.toUri().toURL(); - URLClassLoader classLoader = new URLClassLoader( - new URL[]{pluginUrl}, - PlayerLinkLoader.class.getClassLoader() - ); - InputStream linkImplConfigStream = classLoader.getResourceAsStream("config.json"); - requireNonNull(linkImplConfigStream, "Database implementation should contain a config"); + try (URLClassLoader classLoader = new URLClassLoader( + new URL[]{pluginUrl}, PlayerLinkLoader.class.getClassLoader())) { - JsonObject linkImplConfig = new Gson().fromJson( - new InputStreamReader(linkImplConfigStream), JsonObject.class - ); + String mainClassName; - String mainClassName = linkImplConfig.get("mainClass").getAsString(); - mainClass = (Class) classLoader.loadClass(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 + ); + + mainClassName = linkConfig.get("mainClass").getAsString(); + } + + mainClass = (Class) classLoader.loadClass(mainClassName); + } } catch (ClassCastException exception) { logger.error("The database implementation ({}) doesn't extend the PlayerLink class!", - implementationPath.getFileName().toString()); + implementationPath.getFileName().toString(), exception); return null; } catch (Exception exception) { logger.error("Error while loading database jar", exception); diff --git a/common/src/main/java/org/geysermc/floodgate/logger/JavaUtilFloodgateLogger.java b/common/src/main/java/org/geysermc/floodgate/logger/JavaUtilFloodgateLogger.java index 993400dc..0277c9df 100644 --- a/common/src/main/java/org/geysermc/floodgate/logger/JavaUtilFloodgateLogger.java +++ b/common/src/main/java/org/geysermc/floodgate/logger/JavaUtilFloodgateLogger.java @@ -37,7 +37,7 @@ import org.geysermc.floodgate.util.LanguageManager; public final class JavaUtilFloodgateLogger implements FloodgateLogger { private final Logger logger; private final LanguageManager languageManager; - private Level originLevel = null; + private Level originLevel; @Override public void error(String message, Object... args) { diff --git a/common/src/main/java/org/geysermc/floodgate/platform/command/CommandMessage.java b/common/src/main/java/org/geysermc/floodgate/platform/command/CommandMessage.java index b0080605..ef6a06c8 100644 --- a/common/src/main/java/org/geysermc/floodgate/platform/command/CommandMessage.java +++ b/common/src/main/java/org/geysermc/floodgate/platform/command/CommandMessage.java @@ -51,7 +51,7 @@ public interface CommandMessage { StringBuilder builder = new StringBuilder(); for (int i = 0; i < translateParts.length; i++) { builder.append(manager.getString(translateParts[i], locale, args)); - if (++i != translateParts.length) { + if (translateParts.length != i + 1) { builder.append(" "); } } diff --git a/common/src/main/java/org/geysermc/floodgate/platform/pluginmessage/PluginMessageHandler.java b/common/src/main/java/org/geysermc/floodgate/platform/pluginmessage/PluginMessageHandler.java index 9aad3834..49901f45 100644 --- a/common/src/main/java/org/geysermc/floodgate/platform/pluginmessage/PluginMessageHandler.java +++ b/common/src/main/java/org/geysermc/floodgate/platform/pluginmessage/PluginMessageHandler.java @@ -53,7 +53,7 @@ public abstract class PluginMessageHandler { } 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) { diff --git a/common/src/main/java/org/geysermc/floodgate/player/FloodgatePlayerImpl.java b/common/src/main/java/org/geysermc/floodgate/player/FloodgatePlayerImpl.java index 2c294434..415c3159 100644 --- a/common/src/main/java/org/geysermc/floodgate/player/FloodgatePlayerImpl.java +++ b/common/src/main/java/org/geysermc/floodgate/player/FloodgatePlayerImpl.java @@ -154,10 +154,12 @@ public final class FloodgatePlayerImpl implements FloodgatePlayer { CompletableFuture.completedFuture(null); } + @Override public UUID getCorrectUniqueId() { return linkedPlayer != null ? linkedPlayer.getJavaUniqueId() : javaUniqueId; } + @Override public String getCorrectUsername() { return linkedPlayer != null ? linkedPlayer.getJavaUsername() : javaUsername; } diff --git a/common/src/main/java/org/geysermc/floodgate/player/HandshakeHandler.java b/common/src/main/java/org/geysermc/floodgate/player/HandshakeHandler.java index 4a10017a..2abc2196 100644 --- a/common/src/main/java/org/geysermc/floodgate/player/HandshakeHandler.java +++ b/common/src/main/java/org/geysermc/floodgate/player/HandshakeHandler.java @@ -64,33 +64,33 @@ public final class HandshakeHandler { private final AttributeKey playerAttribute; private final FloodgateLogger logger; - public HandshakeResult handle(Channel channel, @NonNull String hostname) { + public HandshakeResult handle(Channel channel, @NonNull String originalHostname) { + String[] split = originalHostname.split("\0"); + String data = null; + + StringBuilder hostnameBuilder = new StringBuilder(); + for (String value : split) { + if (data == null && FloodgateCipher.hasHeader(value)) { + data = value; + continue; + } + hostnameBuilder.append(value); + } + // hostname now doesn't have Floodgate data anymore if it had + String hostname = hostnameBuilder.toString(); + + if (data == null) { + return callHandlerAndReturnResult( + ResultType.NOT_FLOODGATE_DATA, + channel, null, hostname); + } + + // header + base64 iv - 0x21 - encrypted data - 0x21 - RawSkin + int expectedHeaderLength = FloodgateCipher.HEADER_LENGTH + + Base64Utils.getEncodedLength(AesCipher.IV_LENGTH); + int lastSplitIndex = data.lastIndexOf(0x21); + try { - String[] split = hostname.split("\0"); - String data = null; - - StringBuilder hostnameBuilder = new StringBuilder(); - for (String value : split) { - if (data == null && FloodgateCipher.hasHeader(value)) { - data = value; - continue; - } - hostnameBuilder.append(value); - } - // hostname now doesn't have Floodgate data anymore if it had - hostname = hostnameBuilder.toString(); - - if (data == null) { - return callHandlerAndReturnResult( - ResultType.NOT_FLOODGATE_DATA, - channel, null, hostname); - } - - // header + base64 iv - 0x21 - encrypted data - 0x21 - RawSkin - int expectedHeaderLength = FloodgateCipher.HEADER_LENGTH + - Base64Utils.getEncodedLength(AesCipher.IV_LENGTH); - int lastSplitIndex = data.lastIndexOf(0x21); - byte[] floodgateData; byte[] rawSkinData = null; @@ -181,8 +181,8 @@ public final class HandshakeHandler { ResultType resultType, Channel channel, BedrockData bedrockData, - String hostname - ) { + String hostname) { + HandshakeData handshakeData = new HandshakeDataImpl(channel, bedrockData != null, bedrockData, null, null, hostname, null); handshakeHandlers.callHandshakeHandlers(handshakeData); diff --git a/common/src/main/java/org/geysermc/floodgate/player/UserAudience.java b/common/src/main/java/org/geysermc/floodgate/player/UserAudience.java index 92c464a0..3ca9c208 100644 --- a/common/src/main/java/org/geysermc/floodgate/player/UserAudience.java +++ b/common/src/main/java/org/geysermc/floodgate/player/UserAudience.java @@ -46,6 +46,7 @@ public interface UserAudience extends Identified, Identity, Audience { boolean hasPermission(@NonNull final String permission); + @Override void sendMessage(final @NonNull Identity source, final @NonNull Component message, final @NonNull MessageType type); diff --git a/common/src/main/java/org/geysermc/floodgate/player/UserAudienceArgument.java b/common/src/main/java/org/geysermc/floodgate/player/UserAudienceArgument.java index 45ecd179..b00b97bb 100644 --- a/common/src/main/java/org/geysermc/floodgate/player/UserAudienceArgument.java +++ b/common/src/main/java/org/geysermc/floodgate/player/UserAudienceArgument.java @@ -31,6 +31,7 @@ import cloud.commandframework.arguments.parser.ArgumentParser; import cloud.commandframework.context.CommandContext; import com.google.common.collect.ImmutableList; import java.util.List; +import java.util.Locale; import java.util.Queue; import java.util.UUID; import lombok.RequiredArgsConstructor; @@ -154,13 +155,18 @@ public final class UserAudienceArgument extends CommandArgument commandContext, 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 builder = ImmutableList.builder(); for (final String player : commandUtil.getOnlineUsernames(limitTo)) { - if (lowercaseInput.isEmpty() || player.toLowerCase().startsWith(lowercaseInput)) { + if (player.toLowerCase(Locale.ROOT).startsWith(lowercaseInput)) { builder.add(player); } } @@ -182,7 +188,7 @@ public final class UserAudienceArgument extends CommandArgument uploadSkin(@Nonnull RawSkin rawSkin) { return CompletableFuture.supplyAsync(() -> uploadSkinInner(rawSkin, 0), requestExecutor); @@ -65,12 +66,11 @@ public final class SkinUploader { try { UploadResult result = parseAndHandleResponse(HttpUtils.post(url, image)); - if (result.httpCode == 429) { - times += 1; - if (times >= MAX_TRIES) { + if (result.getHttpCode() == 429) { + if (times + 1 >= MAX_TRIES) { return result; } - uploadSkinInner(rawSkin, times); + uploadSkinInner(rawSkin, times + 1); } return result; } catch (RuntimeException exception) { @@ -79,7 +79,7 @@ public final class SkinUploader { } private String getUploadUrlParameters(SkinModel model) { - return "?visibility=1&model=" + model.name; + return "?visibility=1&model=" + model.getName(); } private UploadResult parseAndHandleResponse(HttpResponse response) { @@ -103,14 +103,15 @@ public final class SkinUploader { STEVE, ALEX; 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) { return VALUES.length > ordinal ? VALUES[ordinal] : STEVE; } public static SkinModel getByName(String name) { - return name == null || !name.equalsIgnoreCase("alex") ? STEVE : ALEX; + return "alex".equalsIgnoreCase(name) ? ALEX : STEVE; } } diff --git a/common/src/main/java/org/geysermc/floodgate/util/Constants.java b/common/src/main/java/org/geysermc/floodgate/util/Constants.java new file mode 100644 index 00000000..8b9e5a1d --- /dev/null +++ b/common/src/main/java/org/geysermc/floodgate/util/Constants.java @@ -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; +} diff --git a/common/src/main/java/org/geysermc/floodgate/util/LanguageManager.java b/common/src/main/java/org/geysermc/floodgate/util/LanguageManager.java index 5cafb86a..94ca3770 100644 --- a/common/src/main/java/org/geysermc/floodgate/util/LanguageManager.java +++ b/common/src/main/java/org/geysermc/floodgate/util/LanguageManager.java @@ -28,6 +28,7 @@ package org.geysermc.floodgate.util; import com.google.common.base.Joiner; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.Reader; import java.net.URL; import java.nio.charset.StandardCharsets; import java.text.MessageFormat; @@ -63,8 +64,8 @@ public final class LanguageManager { */ private static String formatLocale(String locale) { try { - String[] parts = locale.toLowerCase().split("_"); - return parts[0] + "_" + parts[1].toUpperCase(); + String[] parts = locale.toLowerCase(Locale.ROOT).split("_"); + return parts[0] + "_" + parts[1].toUpperCase(Locale.ROOT); } catch (Exception e) { return locale; } @@ -117,31 +118,32 @@ public final class LanguageManager { * @return true if the locale has been found */ public boolean loadLocale(String locale) { - locale = formatLocale(locale); + String formatLocale = formatLocale(locale); // just return if the locale has been loaded already - if (localeMappings.containsKey(locale)) { + if (localeMappings.containsKey(formatLocale)) { return true; } InputStream localeStream = LanguageManager.class.getClassLoader().getResourceAsStream( - "languages/texts/" + locale + ".properties"); + "languages/texts/" + formatLocale + ".properties"); // load the locale if (localeStream != null) { 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) { throw new AssertionError("Failed to load Floodgate locale", e); } // insert the locale into the mappings - localeMappings.put(locale, localeProp); + localeMappings.put(formatLocale, localeProp); return true; } - logger.warn("Missing locale file: " + locale); + logger.warn("Missing locale file: " + formatLocale); return false; } diff --git a/common/src/main/java/org/geysermc/floodgate/util/MessageFormatter.java b/common/src/main/java/org/geysermc/floodgate/util/MessageFormatter.java index 65be6d4c..9912bc44 100644 --- a/common/src/main/java/org/geysermc/floodgate/util/MessageFormatter.java +++ b/common/src/main/java/org/geysermc/floodgate/util/MessageFormatter.java @@ -42,9 +42,8 @@ public final class MessageFormatter { int previousIndex = -1; int currentIndex; - StringBuilder stringBuilder = new StringBuilder( - message.length() + getArgsContentLength(args) - ); + StringBuilder stringBuilder = + new StringBuilder(message.length() + getArgsContentLength(args)); for (String argument : args) { currentIndex = message.indexOf(DELIM_STR, previousIndex); diff --git a/common/src/main/java/org/geysermc/floodgate/util/ReflectionUtils.java b/common/src/main/java/org/geysermc/floodgate/util/ReflectionUtils.java index d4708f9e..3601fc81 100644 --- a/common/src/main/java/org/geysermc/floodgate/util/ReflectionUtils.java +++ b/common/src/main/java/org/geysermc/floodgate/util/ReflectionUtils.java @@ -48,7 +48,7 @@ public final class ReflectionUtils { */ @Getter @Setter - private static String prefix = null; + private static String prefix; static { Field modifiersField = null; @@ -59,12 +59,12 @@ public final class ReflectionUtils { try { Method declaredFields = getMethod(Class.class, "getDeclaredFields0", boolean.class); if (declaredFields == null) { - throw new NoSuchMethodException(); + throw new NoSuchMethodException("Cannot find method getDeclaredFields0"); } Field[] fields = castedInvoke(Field.class, declaredFields, false); if (fields == null) { - throw new Exception(); + throw new RuntimeException("The Field class cannot have null fields"); } for (Field field : fields) { @@ -79,7 +79,7 @@ public final class ReflectionUtils { System.getProperty("java.version"), System.getProperty("java.vendor"), System.getProperty("java.vendor.url") - )); + ), exception); } } @@ -382,6 +382,9 @@ public final class ReflectionUtils { */ @Nullable public static Object invoke(Object instance, Method method, Object... arguments) { + if (method == null) { + return null; + } makeAccessible(method); try { return method.invoke(instance, arguments); @@ -410,11 +413,7 @@ public final class ReflectionUtils { @SuppressWarnings("unchecked") @Nullable public static T castedInvoke(Object instance, Method method, Object... arguments) { - try { - return (T) invoke(instance, method, arguments); - } catch (NullPointerException exception) { - return null; - } + return (T) invoke(instance, method, arguments); } /** @@ -438,12 +437,7 @@ public final class ReflectionUtils { */ @Nullable public static Object invokeStatic(Class clazz, String method) { - try { - return invoke(null, getMethod(clazz, method)); - } catch (NullPointerException exception) { - exception.printStackTrace(); - return null; - } + return invoke(null, getMethod(clazz, method)); } /** diff --git a/database/sqlite/src/main/java/org/geysermc/floodgate/database/SqliteDatabase.java b/database/sqlite/src/main/java/org/geysermc/floodgate/database/SqliteDatabase.java index 83ff421d..e721b701 100644 --- a/database/sqlite/src/main/java/org/geysermc/floodgate/database/SqliteDatabase.java +++ b/database/sqlite/src/main/java/org/geysermc/floodgate/database/SqliteDatabase.java @@ -39,6 +39,7 @@ import java.util.Map; import java.util.UUID; import java.util.concurrent.CompletableFuture; 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.LinkRequestResult; import org.geysermc.floodgate.link.CommonPlayerLink; @@ -59,11 +60,12 @@ public class SqliteDatabase extends CommonPlayerLink { try { Class.forName("org.sqlite.JDBC"); connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath.toString()); - Statement statement = connection.createStatement(); - statement.setQueryTimeout(30); // set timeout to 30 sec. - statement.executeUpdate( - "create table if not exists LinkedPlayers (bedrockId string, javaUniqueId string, javaUsername string)" - ); + try (Statement statement = connection.createStatement()) { + statement.setQueryTimeout(30); // set timeout to 30 sec. + statement.executeUpdate( + "create table if not exists LinkedPlayers (bedrockId string, javaUniqueId string, javaUsername string)" + ); + } } catch (ClassNotFoundException exception) { getLogger().error("The required class to load the SQLite database wasn't found"); } catch (SQLException exception) { @@ -82,12 +84,12 @@ public class SqliteDatabase extends CommonPlayerLink { } @Override - public CompletableFuture getLinkedPlayer(UUID bedrockId) { + @NonNull + public CompletableFuture getLinkedPlayer(@NonNull UUID bedrockId) { return CompletableFuture.supplyAsync(() -> { - try { - PreparedStatement query = connection.prepareStatement( - "select * from LinkedPlayers where bedrockId = ?" - ); + try (PreparedStatement query = connection.prepareStatement( + "select * from LinkedPlayers where bedrockId = ?")) { + query.setString(1, bedrockId.toString()); ResultSet result = query.executeQuery(); if (!result.next()) { @@ -97,7 +99,7 @@ public class SqliteDatabase extends CommonPlayerLink { String javaUsername = result.getString("javaUsername"); UUID javaUniqueId = UUID.fromString(result.getString("javaUniqueId")); return LinkedPlayer.of(javaUsername, javaUniqueId, bedrockId); - } catch (SQLException | NullPointerException exception) { + } catch (SQLException exception) { getLogger().error("Error while getting LinkedPlayer", exception); throw new CompletionException("Error while getting LinkedPlayer", exception); } @@ -105,17 +107,17 @@ public class SqliteDatabase extends CommonPlayerLink { } @Override - public CompletableFuture isLinkedPlayer(UUID playerId) { + @NonNull + public CompletableFuture isLinkedPlayer(@NonNull UUID playerId) { return CompletableFuture.supplyAsync(() -> { - try { - PreparedStatement query = connection.prepareStatement( - "select javaUniqueId from LinkedPlayers where bedrockId = ? or javaUniqueId = ?" - ); + try (PreparedStatement query = connection.prepareStatement( + "select javaUniqueId from LinkedPlayers where bedrockId = ? or javaUniqueId = ?")) { + query.setString(1, playerId.toString()); query.setString(2, playerId.toString()); ResultSet result = query.executeQuery(); return result.next(); - } catch (SQLException | NullPointerException exception) { + } catch (SQLException exception) { getLogger().error("Error while checking if player is a LinkedPlayer", exception); throw new CompletionException( "Error while checking if player is a LinkedPlayer", exception @@ -125,38 +127,41 @@ public class SqliteDatabase extends CommonPlayerLink { } @Override - public CompletableFuture linkPlayer(UUID bedrockId, UUID javaId, String username) { + @NonNull + public CompletableFuture linkPlayer( + @NonNull UUID bedrockId, + @NonNull UUID javaId, + @NonNull String username) { return CompletableFuture.runAsync( () -> linkPlayer0(bedrockId, javaId, username), getExecutorService()); } private void linkPlayer0(UUID bedrockId, UUID javaId, String username) { - try { - PreparedStatement query = connection.prepareStatement( - "insert into LinkedPlayers values(?, ?, ?)" - ); + try (PreparedStatement query = + connection.prepareStatement("insert into LinkedPlayers values(?, ?, ?)")) { + query.setString(1, bedrockId.toString()); query.setString(2, javaId.toString()); query.setString(3, username); query.executeUpdate(); - } catch (SQLException | NullPointerException exception) { + } catch (SQLException exception) { getLogger().error("Error while linking player", exception); throw new CompletionException("Error while linking player", exception); } } @Override - public CompletableFuture unlinkPlayer(UUID javaId) { + @NonNull + public CompletableFuture unlinkPlayer(@NonNull UUID javaId) { return CompletableFuture.runAsync(() -> { - try { - PreparedStatement query = connection.prepareStatement( - "delete from LinkedPlayers where javaUniqueId = ? or bedrockId = ?" - ); + try (PreparedStatement query = connection.prepareStatement( + "delete from LinkedPlayers where javaUniqueId = ? or bedrockId = ?")) { + query.setString(1, javaId.toString()); query.setString(2, javaId.toString()); query.executeUpdate(); - } catch (SQLException | NullPointerException exception) { + } catch (SQLException exception) { getLogger().error("Error while unlinking player", exception); throw new CompletionException("Error while unlinking player", exception); } @@ -164,10 +169,11 @@ public class SqliteDatabase extends CommonPlayerLink { } @Override + @NonNull public CompletableFuture createLinkRequest( - UUID javaId, - String javaUsername, - String bedrockUsername + @NonNull UUID javaId, + @NonNull String javaUsername, + @NonNull String bedrockUsername ) { return CompletableFuture.supplyAsync(() -> { LinkRequest request = @@ -180,11 +186,12 @@ public class SqliteDatabase extends CommonPlayerLink { } @Override + @NonNull public CompletableFuture verifyLinkRequest( - UUID bedrockId, - String javaUsername, - String bedrockUsername, - String code + @NonNull UUID bedrockId, + @NonNull String javaUsername, + @NonNull String bedrockUsername, + @NonNull String code ) { return CompletableFuture.supplyAsync(() -> { LinkRequest request = activeLinkRequests.get(javaUsername); diff --git a/pom.xml b/pom.xml index 98c0d37e..47a1c960 100644 --- a/pom.xml +++ b/pom.xml @@ -84,4 +84,47 @@ + + + + + org.apache.maven.plugins + maven-pmd-plugin + 3.14.0 + + + ${session.executionRootDirectory}/ruleset.xml + + true + + + + + check + + + + + + + + + + + org.apache.maven.plugins + maven-pmd-plugin + 3.14.0 + + + ${session.executionRootDirectory}/ruleset.xml + + + + + org.apache.maven.plugins + maven-jxr-plugin + 2.3 + + + diff --git a/ruleset.xml b/ruleset.xml new file mode 100644 index 00000000..da854c3a --- /dev/null +++ b/ruleset.xml @@ -0,0 +1,44 @@ + + + + + Floodgate Code ruleset + + + .*/ReflectionUtils.* + .*/CommonPlayerLink.* + .*/DefaultConfigHandler.* + .*/ConfigFileUpdater.* + .*/FloodgateConfig.* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spigot/src/main/java/org/geysermc/floodgate/addon/data/SpigotDataHandler.java b/spigot/src/main/java/org/geysermc/floodgate/addon/data/SpigotDataHandler.java index 00362806..9bccb57f 100644 --- a/spigot/src/main/java/org/geysermc/floodgate/addon/data/SpigotDataHandler.java +++ b/spigot/src/main/java/org/geysermc/floodgate/addon/data/SpigotDataHandler.java @@ -126,7 +126,7 @@ public final class SpigotDataHandler extends SimpleChannelInboundHandler Enum[] protocolStates = (Enum[]) PROTOCOL_STATE.getType().getEnumConstants(); Object readyToAcceptState = null; for (Enum protocolState : protocolStates) { - if (protocolState.name().equals("READY_TO_ACCEPT")) { + if ("READY_TO_ACCEPT".equals(protocolState.name())) { readyToAcceptState = protocolState; } } diff --git a/spigot/src/main/java/org/geysermc/floodgate/inject/spigot/SpigotInjector.java b/spigot/src/main/java/org/geysermc/floodgate/inject/spigot/SpigotInjector.java index 01c42afb..74c70a6b 100644 --- a/spigot/src/main/java/org/geysermc/floodgate/inject/spigot/SpigotInjector.java +++ b/spigot/src/main/java/org/geysermc/floodgate/inject/spigot/SpigotInjector.java @@ -50,7 +50,7 @@ public final class SpigotInjector extends CommonPlatformInjector { private Object serverConnection; private String injectedFieldName; - @Getter private boolean injected = false; + @Getter private boolean injected; @Override @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") @@ -148,7 +148,6 @@ public final class SpigotInjector extends CommonPlatformInjector { } } - injectedFieldName = null; injected = false; return true; } @@ -162,7 +161,7 @@ public final class SpigotInjector extends CommonPlatformInjector { Object minecraftServerInstance = ReflectionUtils.invokeStatic(minecraftServer, "getServer"); for (Method method : minecraftServer.getDeclaredMethods()) { - if (method.getReturnType().getSimpleName().equals("ServerConnection")) { + if ("ServerConnection".equals(method.getReturnType().getSimpleName())) { if (method.getParameterTypes().length == 0) { serverConnection = method.invoke(minecraftServerInstance); } diff --git a/spigot/src/main/java/org/geysermc/floodgate/pluginmessage/SpigotSkinApplier.java b/spigot/src/main/java/org/geysermc/floodgate/pluginmessage/SpigotSkinApplier.java index 31e7b90d..b8e9d3fc 100644 --- a/spigot/src/main/java/org/geysermc/floodgate/pluginmessage/SpigotSkinApplier.java +++ b/spigot/src/main/java/org/geysermc/floodgate/pluginmessage/SpigotSkinApplier.java @@ -57,8 +57,7 @@ public final class SpigotSkinApplier implements SkinApplier { public SpigotSkinApplier( SpigotVersionSpecificMethods versionSpecificMethods, SpigotPlugin plugin, - FloodgateConfigHolder configHolder - ) { + FloodgateConfigHolder configHolder) { this.versionSpecificMethods = versionSpecificMethods; this.plugin = plugin; 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 plugin.getServer().getScheduler().runTask(plugin, () -> { for (Player p : Bukkit.getOnlinePlayers()) { - if (p != player && p.canSee(player)) { + if (!p.equals(player) && p.canSee(player)) { versionSpecificMethods.hidePlayer(p, player); versionSpecificMethods.showPlayer(p, player); } diff --git a/spigot/src/main/java/org/geysermc/floodgate/util/SpigotCommandUtil.java b/spigot/src/main/java/org/geysermc/floodgate/util/SpigotCommandUtil.java index de636e93..14efe34e 100644 --- a/spigot/src/main/java/org/geysermc/floodgate/util/SpigotCommandUtil.java +++ b/spigot/src/main/java/org/geysermc/floodgate/util/SpigotCommandUtil.java @@ -60,6 +60,7 @@ public final class SpigotCommandUtil implements CommandUtil { private final FloodgateLogger logger; private final LanguageManager manager; + @Override public @NonNull UserAudience getAudience(final @NonNull Object sourceObj) { if (!(sourceObj instanceof CommandSender)) { throw new IllegalArgumentException("Source has to be a CommandSender!"); @@ -116,14 +117,14 @@ public final class SpigotCommandUtil implements CommandUtil { break; case ONLY_JAVA: for (Player player : players) { - if (!api.isBedrockPlayer(player.getUniqueId())) { + if (!api.isFloodgatePlayer(player.getUniqueId())) { usernames.add(player.getName()); } } break; case ONLY_BEDROCK: for (Player player : players) { - if (api.isBedrockPlayer(player.getUniqueId())) { + if (api.isFloodgatePlayer(player.getUniqueId())) { usernames.add(player.getName()); } } diff --git a/velocity/src/main/java/org/geysermc/floodgate/addon/data/VelocityProxyDataHandler.java b/velocity/src/main/java/org/geysermc/floodgate/addon/data/VelocityProxyDataHandler.java index 9f6692bc..8dda1d96 100644 --- a/velocity/src/main/java/org/geysermc/floodgate/addon/data/VelocityProxyDataHandler.java +++ b/velocity/src/main/java/org/geysermc/floodgate/addon/data/VelocityProxyDataHandler.java @@ -106,6 +106,7 @@ public final class VelocityProxyDataHandler extends SimpleChannelInboundHandler< break; case EXCEPTION: ctx.channel().attr(kickMessageAttribute).set(config.getDisconnect().getInvalidKey()); + return; case INVALID_DATA_LENGTH: ctx.channel().attr(kickMessageAttribute) .set(config.getDisconnect().getInvalidArgumentsLength()); diff --git a/velocity/src/main/java/org/geysermc/floodgate/addon/data/VelocityServerDataHandler.java b/velocity/src/main/java/org/geysermc/floodgate/addon/data/VelocityServerDataHandler.java index 2223f001..513cc15f 100644 --- a/velocity/src/main/java/org/geysermc/floodgate/addon/data/VelocityServerDataHandler.java +++ b/velocity/src/main/java/org/geysermc/floodgate/addon/data/VelocityServerDataHandler.java @@ -110,7 +110,7 @@ public final class VelocityServerDataHandler extends MessageToMessageEncoder