diff --git a/.gitignore b/.gitignore index a67d3fae..29365516 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,9 @@ nb-configuration.xml *.iws .idea/ +# VSCode +.vscode/ + # Maven target/ pom.xml.versionsBackup diff --git a/bukkit/pom.xml b/bukkit/pom.xml index 97492b7c..81a0351c 100644 --- a/bukkit/pom.xml +++ b/bukkit/pom.xml @@ -125,6 +125,12 @@ false + + + + nukkitx-snapshot + https://repo.nukkitx.com/maven-snapshots/ + @@ -183,6 +189,14 @@ + + + org.geysermc.floodgate + api + 2.0-SNAPSHOT + provided + + fr.xephi diff --git a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/FastLoginBukkit.java b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/FastLoginBukkit.java index 3d30c275..067bd9b6 100644 --- a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/FastLoginBukkit.java +++ b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/FastLoginBukkit.java @@ -47,10 +47,13 @@ import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import org.bukkit.Bukkit; +import org.bukkit.Server.Spigot; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; +import org.geysermc.floodgate.api.FloodgateApi; import org.slf4j.Logger; /** @@ -86,6 +89,13 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin + * Writes to Log if the value is invalid. + *

+ * This should be used for: + *

    + *
  • allowFloodgateNameConflict + *
  • autoLoginFloodgate + *
+ *

+ * + * @param key the key of the entry in config.yml + * @return true if the entry's value is "true", "false", or "linked" + */ + private boolean isValidFloodgateConfigString(String key) { + String value = core.getConfig().get(key).toString().toLowerCase(); + if (!value.equals("true") && !value.equals("linked") && !value.equals("false")) { + logger.error("Invalid value detected for {} in FastLogin/config.yml.", key); + return false; + } + return true; + } + + /** + * Checks if a plugin is installed on the server + * @param name the name of the plugin + * @return true if the plugin is installed + */ + private boolean isPluginInstalled(String name) { + //the plugin may be enabled after FastLogin, so isPluginEnabled() + //won't work here + return Bukkit.getServer().getPluginManager().getPlugin(name) != null; + } + + /** + * Send warning messages to log if incompatible plugins are used + */ + private void dependencyWarnings() { + if (isPluginInstalled("floodgate-bukkit")) { + logger.warn("We have detected that you are runnging Floodgate 1.0 which is not supported by the Bukkit " + + "version of FastLogin."); + logger.warn("If you would like to use FastLogin with Floodgate, you can download developement builds of " + + "Floodgate 2.0 from https://ci.opencollab.dev/job/GeyserMC/job/Floodgate/job/dev%252F2.0/"); + logger.warn("Don't forget to update Geyser to a supported version as well from " + + "https://ci.opencollab.dev/job/GeyserMC/job/Geyser/job/floodgate-2.0/"); + } else if (isPluginInstalled("floodgate") && isPluginInstalled("ProtocolLib")) { + logger.warn("We have detected that you are runnging FastLogin alongside Floodgate and ProtocolLib."); + logger.warn("Currently there is an issue with FastLogin that prevents Floodgate name prefixes from showing up " + + "when it is together used with ProtocolLib."); + logger.warn("If you would like to use Floodgate name prefixes, you can replace ProtocolLib with ProtocolSupport " + + "which does not have this issue."); + logger.warn("For more information visit https://github.com/games647/FastLogin/issues/493"); + } + } } diff --git a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/ConnectionListener.java b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/ConnectionListener.java index bbdcdf6a..fc2acad7 100644 --- a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/ConnectionListener.java +++ b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/ConnectionListener.java @@ -27,6 +27,7 @@ package com.github.games647.fastlogin.bukkit.listener; import com.github.games647.fastlogin.bukkit.BukkitLoginSession; import com.github.games647.fastlogin.bukkit.FastLoginBukkit; +import com.github.games647.fastlogin.bukkit.task.FloodgateAuthTask; import com.github.games647.fastlogin.bukkit.task.ForceLoginTask; import org.bukkit.Bukkit; @@ -37,6 +38,8 @@ import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerLoginEvent; import org.bukkit.event.player.PlayerLoginEvent.Result; +import org.geysermc.floodgate.api.FloodgateApi; +import org.geysermc.floodgate.api.player.FloodgatePlayer; import org.bukkit.event.player.PlayerQuitEvent; /** @@ -70,13 +73,26 @@ public class ConnectionListener implements Listener { // cases: Paper (firing BungeeCord message before PlayerJoinEvent) or not running BungeeCord and already // having the login session from the login process BukkitLoginSession session = plugin.getSession(player.getAddress()); - if (session == null) { - String sessionId = plugin.getSessionId(player.getAddress()); - plugin.getLog().info("No on-going login session for player: {} with ID {}", player, sessionId); - } else { - Runnable forceLoginTask = new ForceLoginTask(plugin.getCore(), player, session); - Bukkit.getScheduler().runTaskAsynchronously(plugin, forceLoginTask); - } + + boolean isFloodgateLogin = false; + if (Bukkit.getServer().getPluginManager().isPluginEnabled("floodgate")) { + FloodgatePlayer floodgatePlayer = FloodgateApi.getInstance().getPlayer(player.getUniqueId()); + if (floodgatePlayer != null) { + isFloodgateLogin = true; + Runnable floodgateAuthTask = new FloodgateAuthTask(plugin, player, floodgatePlayer); + Bukkit.getScheduler().runTaskAsynchronously(plugin, floodgateAuthTask); + } + } + + if (!isFloodgateLogin) { + if (session == null) { + String sessionId = plugin.getSessionId(player.getAddress()); + plugin.getLog().info("No on-going login session for player: {} with ID {}", player, sessionId); + } else { + Runnable forceLoginTask = new ForceLoginTask(plugin.getCore(), player, session); + Bukkit.getScheduler().runTaskAsynchronously(plugin, forceLoginTask); + } + } plugin.getBungeeManager().markJoinEventFired(player); // delay the login process to let auth plugins initialize the player diff --git a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocollib/NameCheckTask.java b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocollib/NameCheckTask.java index 79068973..ee6ba69b 100644 --- a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocollib/NameCheckTask.java +++ b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocollib/NameCheckTask.java @@ -37,8 +37,11 @@ import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent; import java.security.PublicKey; import java.util.Random; +import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import org.geysermc.floodgate.api.FloodgateApi; +import org.geysermc.floodgate.api.player.FloodgatePlayer; public class NameCheckTask extends JoinManagement implements Runnable { @@ -67,6 +70,12 @@ public class NameCheckTask extends JoinManagement authPlugin = plugin.getCore().getAuthPluginHook(); + + String autoLoginFloodgate = plugin.getCore().getConfig().get("autoLoginFloodgate").toString().toLowerCase(); + boolean autoRegisterFloodgate = plugin.getCore().getConfig().getBoolean("autoRegisterFloodgate"); + + boolean isRegistered; + try { + isRegistered = authPlugin.isRegistered(player.getName()); + } catch (Exception e) { + plugin.getLog().error( + "An error has occured while checking if player {} is registered", + player.getName()); + return; + } + + if (!isRegistered && !autoRegisterFloodgate) { + plugin.getLog().info( + "Auto registration is disabled for Floodgate players in config.yml"); + return; + } + + // logging in from bedrock for a second time threw an error with UUID + StoredProfile profile = plugin.getCore().getStorage().loadProfile(player.getName()); + if (profile == null) { + profile = new StoredProfile(player.getUniqueId(), player.getName(), true, player.getAddress().toString()); + } + + BukkitLoginSession session = new BukkitLoginSession(player.getName(), isRegistered, profile); + + // enable auto login based on the value of 'autoLoginFloodgate' in config.yml + session.setVerified(autoLoginFloodgate.equals("true") + || (autoLoginFloodgate.equals("linked") && isLinked)); + + // run login task + Runnable forceLoginTask = new ForceLoginTask(plugin.getCore(), player, session); + Bukkit.getScheduler().runTaskAsynchronously(plugin, forceLoginTask); + } + +} diff --git a/bukkit/src/main/resources/plugin.yml b/bukkit/src/main/resources/plugin.yml index df3b48cb..146565bd 100644 --- a/bukkit/src/main/resources/plugin.yml +++ b/bukkit/src/main/resources/plugin.yml @@ -20,6 +20,7 @@ softdepend: - ProtocolLib # Premium variable - PlaceholderAPI + - floodgate # Auth plugins - AuthMe - LoginSecurity diff --git a/core/src/main/resources/config.yml b/core/src/main/resources/config.yml index 2a0fb48d..ca949d2f 100644 --- a/core/src/main/resources/config.yml +++ b/core/src/main/resources/config.yml @@ -187,6 +187,48 @@ auto-register-unknown: false # The password of your Minecraft and the password to login in with your auth plugin autoLogin: true +# Floodgate configuration +# Connecing through Floodgate requires player's to sign in via their Xbox Live account +# Requires Floodgate 2.0 https://github.com/GeyserMC/Floodgate/tree/dev/2.0 +# These settings only work in Bukkit/Spigot/Paper mode +# !!!!!!!! WARNING: FLOODGATE SUPPORT IS AN EXPERIMENTAL FEATURE !!!!!!!! +# Enabling any of these settings might lead to people gaining unauthorized access to other's accounts! + +# This enables auto login for every player connecting through Floodgate. +# Possible values: false, true, linked +# Linked means that only Bedrock accounts linked to a Java account will be logged in automatically +# !!!!!!!! WARNING: FLOODGATE SUPPORT IS AN EXPERIMENTAL FEATURE !!!!!!!! +# Enabling this might lead to people gaining unauthorized access to other's accounts! +autoLoginFloodgate: false + +# This enables Floodgate players to join the server, even if autoRegister is true and there's an existing +# Java **PREMIUM** account with the same name +# +# Java and Bedrock players will get different UUIDs, so their inventories, location, etc. will be different. +# However, some plugins (such as AuthMe) rely on names instead of UUIDs to identify a player which might cause issues. +# In the case of AuthMe (and other auth plugins), both the Java and the Bedrock player will have the same password. +# +# To prevent conflits from two different players having the same name, it is highly recommended to use a 'username-prefix' +# in floodgate/config.yml +# Note: 'username-prefix' is currently broken when used with FastLogin and ProtocolLib. For more information visit: +# https://github.com/games647/FastLogin/issues/493 +# A solution to this is to replace ProtocolLib with ProtocolSupport +# +# Possible values: +# false: Check for Premium Java name conflicts as described in 'autoRegister' +# 'autoRegister' must be 'true' for this to work +# true: Bypass 'autoRegister's name conflict checking +# linked: Bedrock accounts linked to a Java account will be allowed to join with conflicting names +# !!!!!!!! WARNING: FLOODGATE SUPPORT IS AN EXPERIMENTAL FEATURE !!!!!!!! +# Enabling this might lead to people gaining unauthorized access to other's accounts! +allowFloodgateNameConflict: false + +# This enables auto registering every player connecting through Floodgate. +# autoLoginFloodgate must be 'true' for this to work +# !!!!!!!! WARNING: FLOODGATE SUPPORT IS AN EXPERIMENTAL FEATURE !!!!!!!! +# Enabling this might lead to people gaining unauthorized access to other's accounts! +autoRegisterFloodgate: false + # Database configuration # Recommended is the use of MariaDB (a better version of MySQL)