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 fc2acad7..10ce38d9 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 @@ -79,7 +79,7 @@ public class ConnectionListener implements Listener { FloodgatePlayer floodgatePlayer = FloodgateApi.getInstance().getPlayer(player.getUniqueId()); if (floodgatePlayer != null) { isFloodgateLogin = true; - Runnable floodgateAuthTask = new FloodgateAuthTask(plugin, player, floodgatePlayer); + Runnable floodgateAuthTask = new FloodgateAuthTask(plugin.getCore(), player, floodgatePlayer); Bukkit.getScheduler().runTaskAsynchronously(plugin, floodgateAuthTask); } } diff --git a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/task/FloodgateAuthTask.java b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/task/FloodgateAuthTask.java index 29002568..2df2305b 100644 --- a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/task/FloodgateAuthTask.java +++ b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/task/FloodgateAuthTask.java @@ -25,94 +25,27 @@ */ package com.github.games647.fastlogin.bukkit.task; -import java.io.IOException; -import java.util.Optional; +import java.net.InetSocketAddress; +import java.util.UUID; import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.geysermc.floodgate.api.player.FloodgatePlayer; -import com.github.games647.craftapi.model.Profile; -import com.github.games647.craftapi.resolver.RateLimitException; import com.github.games647.fastlogin.bukkit.BukkitLoginSession; import com.github.games647.fastlogin.bukkit.FastLoginBukkit; -import com.github.games647.fastlogin.core.StoredProfile; -import com.github.games647.fastlogin.core.hooks.AuthPlugin; +import com.github.games647.fastlogin.core.shared.FastLoginCore; +import com.github.games647.fastlogin.core.shared.FloodgateManagement; -public class FloodgateAuthTask implements Runnable { +public class FloodgateAuthTask extends FloodgateManagement { - private final FastLoginBukkit plugin; - private final Player player; - private final FloodgatePlayer floodgatePlayer; - - public FloodgateAuthTask(FastLoginBukkit plugin, Player player, FloodgatePlayer floodgatePlayer) { - this.plugin = plugin; - this.player = player; - this.floodgatePlayer = floodgatePlayer; + public FloodgateAuthTask(FastLoginCore core, Player player, FloodgatePlayer floodgatePlayer) { + super(core, player, floodgatePlayer); } @Override - public void run() { - plugin.getLog().info( - "Player {} is connecting through Geyser Floodgate.", - player.getName()); - - // check if the Bedrock player is linked to a Java account - boolean isLinked = floodgatePlayer.getLinkedPlayer() != null; - AuthPlugin authPlugin = plugin.getCore().getAuthPluginHook(); - - String autoLoginFloodgate = plugin.getCore().getConfig().get("autoLoginFloodgate").toString().toLowerCase(); - String autoRegisterFloodgate = plugin.getCore().getConfig().get("autoRegisterFloodgate").toString().toLowerCase(); - String allowNameConflict = plugin.getCore().getConfig().get("allowFloodgateNameConflict").toString().toLowerCase(); - - 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; - } - - //decide if checks should be made for conflicting Java player names - if (!isLinked //linked players have the same name as their Java profile - // if allowNameConflict is 'false' or 'linked' and the player had a conflicting - // name, than they would have been kicked in FloodgateHook#checkNameConflict - && allowNameConflict.equals("true") && - ( - autoLoginFloodgate.equals("no-conflict") - || !isRegistered && autoRegisterFloodgate.equals("no-conflict")) - ) { - // check for conflicting Premium Java name - Optional premiumUUID = Optional.empty(); - try { - premiumUUID = plugin.getCore().getResolver().findProfile(player.getName()); - } catch (IOException | RateLimitException e) { - plugin.getLog().error( - "Could not check wether Floodgate Player {}'s name conflits a premium Java player's name.", - player.getName()); - return; - } - - //stop execution if player's name is conflicting - if (premiumUUID.isPresent()) { - return; - } - } - - if (!isRegistered && autoRegisterFloodgate.equals("false")) { - 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()); - } - + protected void startLogin() { BukkitLoginSession session = new BukkitLoginSession(player.getName(), isRegistered, profile); // enable auto login based on the value of 'autoLoginFloodgate' in config.yml @@ -120,8 +53,20 @@ public class FloodgateAuthTask implements Runnable { || (autoLoginFloodgate.equals("linked") && isLinked)); // run login task - Runnable forceLoginTask = new ForceLoginTask(plugin.getCore(), player, session); - Bukkit.getScheduler().runTaskAsynchronously(plugin, forceLoginTask); + Runnable forceLoginTask = new ForceLoginTask(core.getPlugin().getCore(), player, session); + Bukkit.getScheduler().runTaskAsynchronously(core.getPlugin(), forceLoginTask); + } + + protected String getName(Player player) { + return player.getName(); + } + + protected UUID getUUID(Player player) { + return player.getUniqueId(); + } + + protected InetSocketAddress getAddress(Player player) { + return player.getAddress(); } } diff --git a/bungee/src/main/java/com/github/games647/fastlogin/bungee/FastLoginBungee.java b/bungee/src/main/java/com/github/games647/fastlogin/bungee/FastLoginBungee.java index 9f4a598c..65a9cfae 100644 --- a/bungee/src/main/java/com/github/games647/fastlogin/bungee/FastLoginBungee.java +++ b/bungee/src/main/java/com/github/games647/fastlogin/bungee/FastLoginBungee.java @@ -86,14 +86,7 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin + * + * 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. + */ +package com.github.games647.fastlogin.bungee.task; + +import java.net.InetSocketAddress; +import java.util.UUID; + +import org.geysermc.floodgate.api.player.FloodgatePlayer; + +import net.md_5.bungee.api.CommandSender; +import net.md_5.bungee.api.connection.ProxiedPlayer; +import net.md_5.bungee.api.connection.Server; + +import com.github.games647.fastlogin.bungee.BungeeLoginSession; +import com.github.games647.fastlogin.bungee.FastLoginBungee; +import com.github.games647.fastlogin.core.shared.FastLoginCore; +import com.github.games647.fastlogin.core.shared.FloodgateManagement; + +public class FloodgateAuthTask + extends FloodgateManagement { + + private final Server server; + + public FloodgateAuthTask(FastLoginCore core, ProxiedPlayer player, + FloodgatePlayer floodgatePlayer, Server server) { + super(core, player, floodgatePlayer); + this.server = server; + } + + @Override + protected void startLogin() { + BungeeLoginSession session = new BungeeLoginSession(player.getName(), isRegistered, profile); + + // enable auto login based on the value of 'autoLoginFloodgate' in config.yml + boolean forcedOnlineMode = autoLoginFloodgate.equals("true") + || (autoLoginFloodgate.equals("linked") && isLinked); + + // run login task + Runnable forceLoginTask = new ForceLoginTask(core.getPlugin().getCore(), player, server, session, + forcedOnlineMode); + core.getPlugin().getScheduler().runAsync(forceLoginTask); + } + + @Override + protected String getName(ProxiedPlayer player) { + return player.getName(); + } + + @Override + protected UUID getUUID(ProxiedPlayer player) { + return player.getUniqueId(); + } + + @Override + protected InetSocketAddress getAddress(ProxiedPlayer player) { + return player.getAddress(); + } + +} diff --git a/bungee/src/main/java/com/github/games647/fastlogin/bungee/task/ForceLoginTask.java b/bungee/src/main/java/com/github/games647/fastlogin/bungee/task/ForceLoginTask.java index 0a7f862c..092cc0c1 100644 --- a/bungee/src/main/java/com/github/games647/fastlogin/bungee/task/ForceLoginTask.java +++ b/bungee/src/main/java/com/github/games647/fastlogin/bungee/task/ForceLoginTask.java @@ -49,11 +49,21 @@ public class ForceLoginTask private final Server server; + //treat player as if they had a premium account, even when they don't + //used for Floodgate auto login/register + private final boolean forcedOnlineMode; + public ForceLoginTask(FastLoginCore core, - ProxiedPlayer player, Server server, BungeeLoginSession session) { + ProxiedPlayer player, Server server, BungeeLoginSession session, boolean forcedOnlineMode) { super(core, player, session); this.server = server; + this.forcedOnlineMode = forcedOnlineMode; + } + + public ForceLoginTask(FastLoginCore core, ProxiedPlayer player, + Server server, BungeeLoginSession session) { + this(core, player, server, session, false); } @Override @@ -116,6 +126,6 @@ public class ForceLoginTask @Override public boolean isOnlineMode() { - return player.getPendingConnection().isOnlineMode(); + return forcedOnlineMode || player.getPendingConnection().isOnlineMode(); } } diff --git a/core/src/main/java/com/github/games647/fastlogin/core/shared/FloodgateManagement.java b/core/src/main/java/com/github/games647/fastlogin/core/shared/FloodgateManagement.java new file mode 100644 index 00000000..6c87698b --- /dev/null +++ b/core/src/main/java/com/github/games647/fastlogin/core/shared/FloodgateManagement.java @@ -0,0 +1,149 @@ +/* + * SPDX-License-Identifier: MIT + * + * The MIT License (MIT) + * + * Copyright (c) 2015-2021 + * + * 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. + */ +package com.github.games647.fastlogin.core.shared; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.util.Optional; +import java.util.UUID; + +import org.geysermc.floodgate.api.player.FloodgatePlayer; + +import com.github.games647.craftapi.model.Profile; +import com.github.games647.craftapi.resolver.RateLimitException; +import com.github.games647.fastlogin.core.StoredProfile; +import com.github.games647.fastlogin.core.hooks.AuthPlugin; + +public abstract class FloodgateManagement

> + implements Runnable { + + protected final FastLoginCore core; + protected final P player; + private final FloodgatePlayer floodgatePlayer; + private final String username; + + //config.yml values that might be accessed by multiple methods + protected final String autoLoginFloodgate; + protected final String autoRegisterFloodgate; + protected final String allowNameConflict; + + //variables initialized through run() and accesses by subclasss + protected boolean isRegistered; + protected StoredProfile profile; + protected boolean isLinked; + + public FloodgateManagement(FastLoginCore core, P player, FloodgatePlayer floodgatePlayer) { + this.core = core; + this.player = player; + this.floodgatePlayer = floodgatePlayer; + this.username = getName(player); + + //load values from config.yml + autoLoginFloodgate = core.getConfig().get("autoLoginFloodgate").toString().toLowerCase(); + autoRegisterFloodgate = core.getConfig().get("autoRegisterFloodgate").toString().toLowerCase(); + allowNameConflict = core.getConfig().get("allowFloodgateNameConflict").toString().toLowerCase(); + } + + @Override + public void run() { + core.getPlugin().getLog().info( + "Player {} is connecting through Geyser Floodgate.", + username); + + // check if the Bedrock player is linked to a Java account + isLinked = floodgatePlayer.getLinkedPlayer() != null; + AuthPlugin

authPlugin = core.getAuthPluginHook(); + + try { + isRegistered = authPlugin.isRegistered(username); + } catch (Exception e) { + core.getPlugin().getLog().error( + "An error has occured while checking if player {} is registered", + username); + return; + } + + //decide if checks should be made for conflicting Java player names + if (isNameCheckRequired()) { + // check for conflicting Premium Java name + Optional premiumUUID = Optional.empty(); + try { + premiumUUID = core.getResolver().findProfile(username); + } catch (IOException | RateLimitException e) { + core.getPlugin().getLog().error( + "Could not check wether Floodgate Player {}'s name conflits a premium Java player's name.", + username); + return; + } + + //stop execution if player's name is conflicting + if (premiumUUID.isPresent()) { + return; + } + } + + if (!isRegistered && autoRegisterFloodgate.equals("false")) { + return; + } + + //logging in from bedrock for a second time threw an error with UUID + profile = core.getStorage().loadProfile(username); + if (profile == null) { + profile = new StoredProfile(getUUID(player), username, true, getAddress(player).toString()); + } + + //start Bukkit/Bungee specific tasks + startLogin(); + + } + + /** + * Decides wether checks for conflicting Java names should be made + * @return ture if an API call to Mojang is needed + */ + private boolean isNameCheckRequired() { + //linked players have the same name as their Java profile + //OR + //if allowNameConflict is 'false' or 'linked' and the player had a conflicting + //name, than they would have been kicked in FloodgateHook#checkNameConflict + if (isLinked || !allowNameConflict.equals("true")) { + return false; + } + + //autoRegisterFloodgate should only be checked if then player is not yet registered + if (!isRegistered && autoRegisterFloodgate.equals("no-conflict")) { + return true; + } + + return autoLoginFloodgate.equals("no-conflict"); + } + + protected abstract void startLogin(); + protected abstract String getName(P player); + protected abstract UUID getUUID(P player); + protected abstract InetSocketAddress getAddress(P player); + +} diff --git a/core/src/main/resources/config.yml b/core/src/main/resources/config.yml index 366a2072..40baad8c 100644 --- a/core/src/main/resources/config.yml +++ b/core/src/main/resources/config.yml @@ -190,7 +190,6 @@ 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! @@ -202,6 +201,7 @@ autoLogin: true # no-conflict: Bedrock players will only be automatically logged in if the Mojang API reports # that there is no existing Premium Java MC account with their name. # This option can be useful if you are not using 'username-prefix' in floodgate/config.yml +# Requires 'autoLogin' to be 'true' # !!!!!!!! WARNING: FLOODGATE SUPPORT IS AN EXPERIMENTAL FEATURE !!!!!!!! # Enabling this might lead to people gaining unauthorized access to other's accounts! autoLoginFloodgate: false @@ -237,6 +237,7 @@ allowFloodgateNameConflict: false # no-conflict: Bedrock players will only be automatically registered if the Mojang API reports # that there is no existing Premium Java MC account with their name. # This option can be useful if you are not using 'username-prefix' in floodgate/config.yml +# Requires 'autoRegister' to be 'true' # !!!!!!!! WARNING: FLOODGATE SUPPORT IS AN EXPERIMENTAL FEATURE !!!!!!!! # Enabling this might lead to people gaining unauthorized access to other's accounts! autoRegisterFloodgate: false