diff --git a/.gitignore b/.gitignore index 58ae9e78..27c8ac2c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ -# Created by https://www.gitignore.io/api/git,java,maven,eclipse,netbeans,jetbrains+all -# Edit at https://www.gitignore.io/?templates=git,java,maven,eclipse,netbeans,jetbrains+all +# Created by https://www.gitignore.io/api/git,java,gradle,eclipse,netbeans,jetbrains+all +# Edit at https://www.gitignore.io/?templates=git,gradle,maven,eclipse,netbeans,jetbrains+all ### Eclipse ### .metadata @@ -52,22 +52,19 @@ local.properties # Annotation Processing .apt_generated/ +.apt_generated_test/ # Scala IDE specific (Scala & Java development for Eclipse) .cache-main .scala_dependencies .worksheet -### Eclipse Patch ### -# Eclipse Core -.project - -# JDT-specific (Eclipse Java Development Tools) -.classpath - -# Annotation Processing -.apt_generated +# Uncomment this line if you wish to ignore the project description file. +# Typically, this file would be tracked if it contains build/dependency configurations: +#.project +### Eclipse Patch ### +# Spring Boot Tooling .sts4-cache/ ### Git ### @@ -109,9 +106,10 @@ local.properties # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* +replay_pid* ### JetBrains+all ### -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 # User-specific stuff @@ -121,6 +119,9 @@ hs_err_pid* .idea/**/dictionaries .idea/**/shelf +# AWS User-specific +.idea/**/aws.xml + # Generated files .idea/**/contentModel.xml @@ -141,11 +142,14 @@ hs_err_pid* # When using Gradle or Maven with auto-import, you should exclude module files, # since they will be recreated, and may cause churn. Uncomment if using # auto-import. -# .idea/modules.xml -# .idea/*.iml -# .idea/modules -# *.iml -# *.ipr +.idea/artifacts +.idea/compiler.xml +.idea/jarRepositories.xml +.idea/modules.xml +.idea/*.iml +.idea/modules +*.iml +*.ipr # CMake cmake-build-*/ @@ -168,6 +172,9 @@ atlassian-ide-plugin.xml # Cursive Clojure plugin .idea/replstate.xml +# SonarLint plugin +.idea/sonarlint/ + # Crashlytics plugin (for Android Studio and IntelliJ) com_crashlytics_export_strings.xml crashlytics.properties @@ -181,32 +188,13 @@ fabric.properties .idea/caches/build_file_checksums.ser ### JetBrains+all Patch ### -# Ignores the whole .idea folder and all .iml files -# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 +# Ignore everything but code style settings and run configurations +# that are supposed to be shared within teams. -.idea/ +.idea/* -# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 - -*.iml -modules.xml -.idea/misc.xml -*.ipr - -# Sonarlint plugin -.idea/sonarlint - -### Maven ### -target/ -pom.xml.tag -pom.xml.releaseBackup -pom.xml.versionsBackup -pom.xml.next -release.properties -dependency-reduced-pom.xml -buildNumber.properties -.mvn/timing.properties -.mvn/wrapper/maven-wrapper.jar +!.idea/codeStyles +!.idea/runConfigurations ### NetBeans ### **/nbproject/private/ @@ -218,8 +206,29 @@ dist/ nbdist/ .nb-gradle/ -# End of https://www.gitignore.io/api/git,java,maven,eclipse,netbeans,jetbrains+all -gradle/ -**/.gradle/ +### Gradle ### +.gradle +**/build/ +!src/**/build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Avoid ignore Gradle wrappper properties +!gradle-wrapper.properties + +# Cache of project +.gradletasknamecache + +# Eclipse Gradle plugin generated files +# Eclipse Core +.project +# JDT-specific (Eclipse Java Development Tools) +.classpath + +# End of https://www.gitignore.io/api/git,java,gradle,eclipse,netbeans,jetbrains+all /core/src/main/resources/languages/ diff --git a/api/src/main/java/org/geysermc/floodgate/api/link/LinkRequestResult.java b/api/src/main/java/org/geysermc/floodgate/api/link/LinkRequestResult.java index ea7c795c..3d8fad03 100644 --- a/api/src/main/java/org/geysermc/floodgate/api/link/LinkRequestResult.java +++ b/api/src/main/java/org/geysermc/floodgate/api/link/LinkRequestResult.java @@ -34,10 +34,6 @@ public enum LinkRequestResult { * An unknown error encountered while creating / verifying the link request. */ UNKNOWN_ERROR, - /** - * @deprecated this result isn't used. Instead the link code is returned - */ - REQUEST_CREATED, /** * The specified bedrock username is already linked to a Java account. */ diff --git a/core/src/main/java/org/geysermc/floodgate/FloodgatePlatform.java b/core/src/main/java/org/geysermc/floodgate/FloodgatePlatform.java index dfb81699..038bfe50 100644 --- a/core/src/main/java/org/geysermc/floodgate/FloodgatePlatform.java +++ b/core/src/main/java/org/geysermc/floodgate/FloodgatePlatform.java @@ -35,23 +35,21 @@ import org.geysermc.floodgate.api.handshake.HandshakeHandlers; import org.geysermc.floodgate.api.inject.PlatformInjector; import org.geysermc.floodgate.api.link.PlayerLink; -import org.geysermc.floodgate.api.logger.FloodgateLogger; import org.geysermc.floodgate.api.packet.PacketHandlers; import org.geysermc.floodgate.config.FloodgateConfig; +import org.geysermc.floodgate.event.PostEnableEvent; import org.geysermc.floodgate.event.ShutdownEvent; import org.geysermc.floodgate.link.PlayerLinkLoader; import org.geysermc.floodgate.module.PostInitializeModule; import org.geysermc.floodgate.news.NewsChecker; import org.geysermc.floodgate.util.Metrics; -import org.geysermc.floodgate.util.PrefixCheckTask; +import org.geysermc.floodgate.util.PostEnableMessages; public class FloodgatePlatform { private static final UUID KEY = UUID.randomUUID(); @Inject private FloodgateApi api; @Inject private PlatformInjector injector; - @Inject private FloodgateLogger logger; - @Inject private FloodgateConfig config; @Inject private Injector guice; @@ -77,9 +75,11 @@ public void enable(Module... postInitializeModules) throws RuntimeException { this.guice = guice.createChildInjector(new PostInitializeModule(postInitializeModules)); - PrefixCheckTask.checkAndExecuteDelayed(config, logger); - + //todo add some kind of auto-load, as this looks kinda weird + guice.getInstance(PostEnableMessages.class); guice.getInstance(Metrics.class); + + guice.getInstance(PubSubSupport.class).publish(new PostEnableEvent()); } public void disable() { diff --git a/core/src/main/java/org/geysermc/floodgate/config/ConfigLoader.java b/core/src/main/java/org/geysermc/floodgate/config/ConfigLoader.java index 51272b89..e4311058 100644 --- a/core/src/main/java/org/geysermc/floodgate/config/ConfigLoader.java +++ b/core/src/main/java/org/geysermc/floodgate/config/ConfigLoader.java @@ -41,7 +41,7 @@ @Getter @RequiredArgsConstructor public final class ConfigLoader { - private final Path dataFolder; + private final Path dataDirectory; private final Class configClass; private final KeyProducer keyProducer; @@ -62,7 +62,7 @@ public T load() { ConfigUtilities utilities = ConfigUtilities.builder() - .fileCodec(PathFileCodec.of(dataFolder)) + .fileCodec(PathFileCodec.of(dataDirectory)) .configFile("config.yml") .templateReader(ResourceTemplateReader.of(getClass())) .template(templateFile) diff --git a/core/src/main/java/org/geysermc/floodgate/config/FloodgateConfig.java b/core/src/main/java/org/geysermc/floodgate/config/FloodgateConfig.java index b7b6b866..4a87b0d4 100644 --- a/core/src/main/java/org/geysermc/floodgate/config/FloodgateConfig.java +++ b/core/src/main/java/org/geysermc/floodgate/config/FloodgateConfig.java @@ -52,7 +52,9 @@ public class FloodgateConfig implements GenericPostInitializeCallback= 16) { + usernamePrefix = "."; + } + return CallbackResult.ok(); } diff --git a/core/src/main/java/org/geysermc/floodgate/event/PostEnableEvent.java b/core/src/main/java/org/geysermc/floodgate/event/PostEnableEvent.java new file mode 100644 index 00000000..0ae55e26 --- /dev/null +++ b/core/src/main/java/org/geysermc/floodgate/event/PostEnableEvent.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2019-2022 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.event; + +public class PostEnableEvent { +} diff --git a/core/src/main/java/org/geysermc/floodgate/util/LanguageManager.java b/core/src/main/java/org/geysermc/floodgate/util/LanguageManager.java index d0228921..a3d659bf 100644 --- a/core/src/main/java/org/geysermc/floodgate/util/LanguageManager.java +++ b/core/src/main/java/org/geysermc/floodgate/util/LanguageManager.java @@ -28,11 +28,7 @@ import com.google.common.base.Joiner; import com.google.inject.Inject; import com.google.inject.Singleton; -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; import java.util.HashMap; import java.util.Locale; @@ -117,21 +113,11 @@ public boolean loadLocale(String locale) { return true; } - InputStream localeStream = LanguageManager.class.getClassLoader().getResourceAsStream( - "languages/texts/" + formatLocale + ".properties"); + Properties properties = + Utils.readProperties("languages/texts/" + formatLocale + ".properties"); - // load the locale - if (localeStream != null) { - Properties localeProp = new Properties(); - - 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(formatLocale, localeProp); + if (properties != null) { + localeMappings.put(formatLocale, properties); return true; } diff --git a/core/src/main/java/org/geysermc/floodgate/util/PostEnableMessages.java b/core/src/main/java/org/geysermc/floodgate/util/PostEnableMessages.java new file mode 100644 index 00000000..b324f4bd --- /dev/null +++ b/core/src/main/java/org/geysermc/floodgate/util/PostEnableMessages.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2019-2022 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; + +import com.google.inject.Inject; +import java.util.ArrayList; +import java.util.List; +import net.engio.mbassy.listener.Handler; +import net.engio.mbassy.listener.Listener; +import org.geysermc.floodgate.api.logger.FloodgateLogger; +import org.geysermc.floodgate.config.FloodgateConfig; +import org.geysermc.floodgate.event.PostEnableEvent; + +@Listener +public final class PostEnableMessages { + private final List messages = new ArrayList<>(); + + @Inject private FloodgateConfig config; + @Inject private FloodgateLogger logger; + + public void add(String[] message, Object... args) { + StringBuilder builder = new StringBuilder(); + + builder.append("\n**********************************\n"); + for (String part : message) { + builder.append("* ").append(part).append('\n'); + } + builder.append("**********************************"); + + messages.add(MessageFormatter.format(builder.toString(), args)); + } + + @Inject + private void init() { + registerPrefixMessages(); + } + + private void registerPrefixMessages() { + String prefix = config.getRawUsernamePrefix(); + + if (prefix.isEmpty()) { + add(new String[]{ + "You specified an empty prefix in your Floodgate config for Bedrock players!", + "Should a Java player join and a Bedrock player join with the same username, unwanted results and conflicts will happen!", + "We strongly recommend using . as the prefix, but other alternatives that will not conflict include: +, - and *" + }); + } else if (!Utils.isUniquePrefix(prefix)) { + add(new String[]{ + "The prefix you entered in your Floodgate config ({}) could lead to username conflicts!", + "Should a Java player join with the username {}Notch, and a Bedrock player join as Notch (who will be given the name {}Notch), unwanted results will happen!", + "We strongly recommend using . as the prefix, but other alternatives that will not conflict include: +, - and *" + }, prefix, prefix, prefix, prefix); + } + + if (prefix.length() >= 16) { + add(new String[]{ + "The prefix you entered in your Floodgate config ({}) is longer than a Java username can be!", + "Because of this, we reset the prefix to the default Floodgate prefix (.)" + }, prefix); + } else if (prefix.length() > 2) { + // we only have to warn them if we haven't replaced the prefix + add(new String[]{ + "The prefix you entered in your Floodgate config ({}) is long! ({} characters)", + "A prefix is there to prevent username conflicts. However, a long prefix makes the chance of username conflicts higher.", + "We strongly recommend using . as the prefix, but other alternatives that will not conflict include: +, - and *" + }, prefix, prefix.length()); + } + } + + @Handler + public void onPostEnable(PostEnableEvent ignored) { + new Thread(() -> { + // normally proxies don't have a lot of plugins, so proxies don't need to sleep as long + try { + Thread.sleep(config.isProxy() ? 2000 : 5000); + } catch (InterruptedException ignored1) { + } + + messages.forEach(logger::warn); + }).start(); + } +} diff --git a/core/src/main/java/org/geysermc/floodgate/util/PrefixCheckTask.java b/core/src/main/java/org/geysermc/floodgate/util/PrefixCheckTask.java deleted file mode 100644 index 4631171f..00000000 --- a/core/src/main/java/org/geysermc/floodgate/util/PrefixCheckTask.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2019-2022 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; - -import org.geysermc.floodgate.api.logger.FloodgateLogger; -import org.geysermc.floodgate.config.FloodgateConfig; - -public final class PrefixCheckTask { - public static void checkAndExecuteDelayed(FloodgateConfig config, FloodgateLogger logger) { - if (Utils.isUniquePrefix(config.getUsernamePrefix())) { - return; - } - - new Thread(() -> { - // normally proxies don't have a lot of plugins, so proxies don't need to sleep as long - try { - Thread.sleep(config.isProxy() ? 1000 : 2000); - } catch (InterruptedException ignored) { - } - - if (config.getUsernamePrefix().isEmpty()) { - logger.warn("\n" + - "**********************************\n" + - "* You specified an empty prefix in your Floodgate config for Bedrock players!\n" + - "* Should a Java player join and a Bedrock player join with the same username, unwanted results and conflicts will happen!\n" + - "* We strongly recommend using . as the prefix, but other alternatives that will not conflict include: +, - and *\n" + - "**********************************"); - return; - } - - logger.warn( - "\n" + - "**********************************\n" + - "* The prefix you entered in your Floodgate config ({}) could lead to username conflicts!\n" + - "* Should a Java player join with the username {}Notch, and a Bedrock player join as Notch (who will be given the name {}Notch), unwanted results will happen!\n" + - "* We strongly recommend using . as the prefix, but other alternatives that will not conflict include: +, - and *\n" + - "**********************************", - config.getUsernamePrefix(), config.getUsernamePrefix(), - config.getUsernamePrefix(), config.getUsernamePrefix()); - }).start(); - } -} diff --git a/core/src/main/java/org/geysermc/floodgate/util/Utils.java b/core/src/main/java/org/geysermc/floodgate/util/Utils.java index d6efda3a..9d2d93c7 100644 --- a/core/src/main/java/org/geysermc/floodgate/util/Utils.java +++ b/core/src/main/java/org/geysermc/floodgate/util/Utils.java @@ -28,18 +28,10 @@ import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPipeline; -import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; import java.io.PrintWriter; -import java.io.Reader; import java.io.StringWriter; -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; import java.util.Locale; import java.util.Properties; import java.util.UUID; @@ -47,7 +39,7 @@ import java.util.regex.Pattern; public class Utils { - private static final Pattern NON_UNIQUE_PREFIX = Pattern.compile("^[a-zA-Z0-9_]{0,16}$"); + private static final Pattern NON_UNIQUE_PREFIX = Pattern.compile("^\\w{0,16}$"); private static final Pattern DATABASE_NAME = Pattern.compile(Constants.DATABASE_NAME_FORMAT); /** @@ -66,33 +58,21 @@ public static void removeHandler(ChannelPipeline pipeline, String handler) { } } - public static List readAllLines(String resourcePath) throws IOException { - InputStream stream = Utils.class.getClassLoader().getResourceAsStream(resourcePath); - try (BufferedReader reader = newBufferedReader(stream, StandardCharsets.UTF_8)) { - List result = new ArrayList<>(); - for (; ; ) { - String line = reader.readLine(); - if (line == null) { - break; - } - result.add(line); - } - return result; - } - } - - public static BufferedReader newBufferedReader(InputStream inputStream, Charset charset) { - CharsetDecoder decoder = charset.newDecoder(); - Reader reader = new InputStreamReader(inputStream, decoder); - return new BufferedReader(reader); - } - + /** + * Reads a properties resource file + * @param resourceFile the resource file to read + * @return the properties file if the resource exists, otherwise null + * @throws AssertionError if something went wrong while readin the resource file + */ public static Properties readProperties(String resourceFile) { Properties properties = new Properties(); try (InputStream is = Utils.class.getClassLoader().getResourceAsStream(resourceFile)) { + if (is == null) { + return null; + } properties.load(is); } catch (IOException e) { - e.printStackTrace(); + throw new AssertionError("Failed to read properties file", e); } return properties; }