1
0
mirror of https://github.com/GeyserMC/Floodgate.git synced 2025-12-19 14:59:20 +00:00

Changed how post-enable messages work internally + minor other changes

This commit is contained in:
Tim203
2022-07-11 11:13:37 +02:00
parent 904c584a2a
commit 41de3673a7
10 changed files with 221 additions and 171 deletions

97
.gitignore vendored
View File

@@ -1,5 +1,5 @@
# Created by https://www.gitignore.io/api/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,java,maven,eclipse,netbeans,jetbrains+all # Edit at https://www.gitignore.io/?templates=git,gradle,maven,eclipse,netbeans,jetbrains+all
### Eclipse ### ### Eclipse ###
.metadata .metadata
@@ -52,22 +52,19 @@ local.properties
# Annotation Processing # Annotation Processing
.apt_generated/ .apt_generated/
.apt_generated_test/
# Scala IDE specific (Scala & Java development for Eclipse) # Scala IDE specific (Scala & Java development for Eclipse)
.cache-main .cache-main
.scala_dependencies .scala_dependencies
.worksheet .worksheet
# 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 ### ### Eclipse Patch ###
# Eclipse Core # Spring Boot Tooling
.project
# JDT-specific (Eclipse Java Development Tools)
.classpath
# Annotation Processing
.apt_generated
.sts4-cache/ .sts4-cache/
### Git ### ### Git ###
@@ -109,9 +106,10 @@ local.properties
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid* hs_err_pid*
replay_pid*
### JetBrains+all ### ### 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 # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff # User-specific stuff
@@ -121,6 +119,9 @@ hs_err_pid*
.idea/**/dictionaries .idea/**/dictionaries
.idea/**/shelf .idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files # Generated files
.idea/**/contentModel.xml .idea/**/contentModel.xml
@@ -141,11 +142,14 @@ hs_err_pid*
# When using Gradle or Maven with auto-import, you should exclude module files, # 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 # since they will be recreated, and may cause churn. Uncomment if using
# auto-import. # auto-import.
# .idea/modules.xml .idea/artifacts
# .idea/*.iml .idea/compiler.xml
# .idea/modules .idea/jarRepositories.xml
# *.iml .idea/modules.xml
# *.ipr .idea/*.iml
.idea/modules
*.iml
*.ipr
# CMake # CMake
cmake-build-*/ cmake-build-*/
@@ -168,6 +172,9 @@ atlassian-ide-plugin.xml
# Cursive Clojure plugin # Cursive Clojure plugin
.idea/replstate.xml .idea/replstate.xml
# SonarLint plugin
.idea/sonarlint/
# Crashlytics plugin (for Android Studio and IntelliJ) # Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml com_crashlytics_export_strings.xml
crashlytics.properties crashlytics.properties
@@ -181,32 +188,13 @@ fabric.properties
.idea/caches/build_file_checksums.ser .idea/caches/build_file_checksums.ser
### JetBrains+all Patch ### ### JetBrains+all Patch ###
# Ignores the whole .idea folder and all .iml files # Ignore everything but code style settings and run configurations
# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 # that are supposed to be shared within teams.
.idea/ .idea/*
# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 !.idea/codeStyles
!.idea/runConfigurations
*.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
### NetBeans ### ### NetBeans ###
**/nbproject/private/ **/nbproject/private/
@@ -218,8 +206,29 @@ dist/
nbdist/ nbdist/
.nb-gradle/ .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/ /core/src/main/resources/languages/

View File

@@ -34,10 +34,6 @@ public enum LinkRequestResult {
* An unknown error encountered while creating / verifying the link request. * An unknown error encountered while creating / verifying the link request.
*/ */
UNKNOWN_ERROR, 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. * The specified bedrock username is already linked to a Java account.
*/ */

View File

@@ -35,23 +35,21 @@ import org.geysermc.floodgate.api.InstanceHolder;
import org.geysermc.floodgate.api.handshake.HandshakeHandlers; import org.geysermc.floodgate.api.handshake.HandshakeHandlers;
import org.geysermc.floodgate.api.inject.PlatformInjector; import org.geysermc.floodgate.api.inject.PlatformInjector;
import org.geysermc.floodgate.api.link.PlayerLink; 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.api.packet.PacketHandlers;
import org.geysermc.floodgate.config.FloodgateConfig; import org.geysermc.floodgate.config.FloodgateConfig;
import org.geysermc.floodgate.event.PostEnableEvent;
import org.geysermc.floodgate.event.ShutdownEvent; import org.geysermc.floodgate.event.ShutdownEvent;
import org.geysermc.floodgate.link.PlayerLinkLoader; import org.geysermc.floodgate.link.PlayerLinkLoader;
import org.geysermc.floodgate.module.PostInitializeModule; import org.geysermc.floodgate.module.PostInitializeModule;
import org.geysermc.floodgate.news.NewsChecker; import org.geysermc.floodgate.news.NewsChecker;
import org.geysermc.floodgate.util.Metrics; import org.geysermc.floodgate.util.Metrics;
import org.geysermc.floodgate.util.PrefixCheckTask; import org.geysermc.floodgate.util.PostEnableMessages;
public class FloodgatePlatform { public class FloodgatePlatform {
private static final UUID KEY = UUID.randomUUID(); private static final UUID KEY = UUID.randomUUID();
@Inject private FloodgateApi api; @Inject private FloodgateApi api;
@Inject private PlatformInjector injector; @Inject private PlatformInjector injector;
@Inject private FloodgateLogger logger;
@Inject private FloodgateConfig config; @Inject private FloodgateConfig config;
@Inject private Injector guice; @Inject private Injector guice;
@@ -77,9 +75,11 @@ public class FloodgatePlatform {
this.guice = guice.createChildInjector(new PostInitializeModule(postInitializeModules)); 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(Metrics.class);
guice.getInstance(PubSubSupport.class).publish(new PostEnableEvent());
} }
public void disable() { public void disable() {

View File

@@ -41,7 +41,7 @@ import org.geysermc.floodgate.crypto.KeyProducer;
@Getter @Getter
@RequiredArgsConstructor @RequiredArgsConstructor
public final class ConfigLoader { public final class ConfigLoader {
private final Path dataFolder; private final Path dataDirectory;
private final Class<? extends FloodgateConfig> configClass; private final Class<? extends FloodgateConfig> configClass;
private final KeyProducer keyProducer; private final KeyProducer keyProducer;
@@ -62,7 +62,7 @@ public final class ConfigLoader {
ConfigUtilities utilities = ConfigUtilities utilities =
ConfigUtilities.builder() ConfigUtilities.builder()
.fileCodec(PathFileCodec.of(dataFolder)) .fileCodec(PathFileCodec.of(dataDirectory))
.configFile("config.yml") .configFile("config.yml")
.templateReader(ResourceTemplateReader.of(getClass())) .templateReader(ResourceTemplateReader.of(getClass()))
.template(templateFile) .template(templateFile)

View File

@@ -52,7 +52,9 @@ public class FloodgateConfig implements GenericPostInitializeCallback<ConfigLoad
private boolean debug; private boolean debug;
private int configVersion; private int configVersion;
private Key key; private Key key;
private String rawUsernamePrefix;
public boolean isProxy() { public boolean isProxy() {
return this instanceof ProxyFloodgateConfig; return this instanceof ProxyFloodgateConfig;
@@ -60,7 +62,7 @@ public class FloodgateConfig implements GenericPostInitializeCallback<ConfigLoad
@Override @Override
public CallbackResult postInitialize(ConfigLoader loader) { public CallbackResult postInitialize(ConfigLoader loader) {
Path keyPath = loader.getDataFolder().resolve(getKeyFileName()); Path keyPath = loader.getDataDirectory().resolve(getKeyFileName());
// don't assume that the key always exists with the existence of a config // don't assume that the key always exists with the existence of a config
if (!Files.exists(keyPath)) { if (!Files.exists(keyPath)) {
@@ -74,6 +76,14 @@ public class FloodgateConfig implements GenericPostInitializeCallback<ConfigLoad
} catch (IOException exception) { } catch (IOException exception) {
return CallbackResult.failed(exception.getMessage()); return CallbackResult.failed(exception.getMessage());
} }
rawUsernamePrefix = usernamePrefix;
// Java usernames can't be longer than 16 chars
if (usernamePrefix.length() >= 16) {
usernamePrefix = ".";
}
return CallbackResult.ok(); return CallbackResult.ok();
} }

View File

@@ -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 {
}

View File

@@ -28,11 +28,7 @@ package org.geysermc.floodgate.util;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Singleton; import com.google.inject.Singleton;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL; import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale; import java.util.Locale;
@@ -117,21 +113,11 @@ public final class LanguageManager {
return true; return true;
} }
InputStream localeStream = LanguageManager.class.getClassLoader().getResourceAsStream( Properties properties =
"languages/texts/" + formatLocale + ".properties"); Utils.readProperties("languages/texts/" + formatLocale + ".properties");
// load the locale if (properties != null) {
if (localeStream != null) { localeMappings.put(formatLocale, properties);
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);
return true; return true;
} }

View File

@@ -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<String> 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();
}
}

View File

@@ -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();
}
}

View File

@@ -28,18 +28,10 @@ package org.geysermc.floodgate.util;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelPipeline; import io.netty.channel.ChannelPipeline;
import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringWriter; 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.Locale;
import java.util.Properties; import java.util.Properties;
import java.util.UUID; import java.util.UUID;
@@ -47,7 +39,7 @@ import java.util.concurrent.CompletableFuture;
import java.util.regex.Pattern; import java.util.regex.Pattern;
public class Utils { 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); private static final Pattern DATABASE_NAME = Pattern.compile(Constants.DATABASE_NAME_FORMAT);
/** /**
@@ -66,33 +58,21 @@ public class Utils {
} }
} }
public static List<String> readAllLines(String resourcePath) throws IOException { /**
InputStream stream = Utils.class.getClassLoader().getResourceAsStream(resourcePath); * Reads a properties resource file
try (BufferedReader reader = newBufferedReader(stream, StandardCharsets.UTF_8)) { * @param resourceFile the resource file to read
List<String> result = new ArrayList<>(); * @return the properties file if the resource exists, otherwise null
for (; ; ) { * @throws AssertionError if something went wrong while readin the resource file
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);
}
public static Properties readProperties(String resourceFile) { public static Properties readProperties(String resourceFile) {
Properties properties = new Properties(); Properties properties = new Properties();
try (InputStream is = Utils.class.getClassLoader().getResourceAsStream(resourceFile)) { try (InputStream is = Utils.class.getClassLoader().getResourceAsStream(resourceFile)) {
if (is == null) {
return null;
}
properties.load(is); properties.load(is);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); throw new AssertionError("Failed to read properties file", e);
} }
return properties; return properties;
} }