Merge branch 'Smart123s-feature/geyser/allowOfflineNameConflict'

This commit is contained in:
games647
2021-11-28 13:45:33 +01:00
23 changed files with 346 additions and 102 deletions

View File

@ -35,6 +35,15 @@ jobs:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v2 uses: actions/checkout@v2
# Setup Java
- name: Set up JDK
uses: actions/setup-java@v2.3.0
with:
distribution: 'adopt'
# Use Java 16, because it's minimum required version by Geyser
java-version: 16
cache: 'maven'
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v1 uses: github/codeql-action/init@v1

View File

@ -31,8 +31,8 @@ jobs:
uses: actions/setup-java@v2.3.0 uses: actions/setup-java@v2.3.0
with: with:
distribution: 'adopt' distribution: 'adopt'
# Use Java 11, because it's minimum required version # Use Java 16, because it's minimum required version by Geyser
java-version: 11 java-version: 16
cache: 'maven' cache: 'maven'
# Build and test (included in package) # Build and test (included in package)

View File

@ -209,6 +209,14 @@
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<!-- Bedrock player bridge, used for low level checks -->
<dependency>
<groupId>org.geysermc</groupId>
<artifactId>connector</artifactId>
<version>1.4.3-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!--Login Plugins--> <!--Login Plugins-->
<dependency> <dependency>
<groupId>fr.xephi</groupId> <groupId>fr.xephi</groupId>

View File

@ -35,7 +35,9 @@ import com.github.games647.fastlogin.bukkit.listener.protocolsupport.ProtocolSup
import com.github.games647.fastlogin.bukkit.task.DelayedAuthHook; import com.github.games647.fastlogin.bukkit.task.DelayedAuthHook;
import com.github.games647.fastlogin.core.CommonUtil; import com.github.games647.fastlogin.core.CommonUtil;
import com.github.games647.fastlogin.core.PremiumStatus; import com.github.games647.fastlogin.core.PremiumStatus;
import com.github.games647.fastlogin.core.hooks.FloodgateService; import com.github.games647.fastlogin.core.hooks.bedrock.BedrockService;
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
import com.github.games647.fastlogin.core.hooks.bedrock.GeyserService;
import com.github.games647.fastlogin.core.shared.FastLoginCore; import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.PlatformPlugin; import com.github.games647.fastlogin.core.shared.PlatformPlugin;
@ -53,6 +55,7 @@ import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.floodgate.api.FloodgateApi; import org.geysermc.floodgate.api.FloodgateApi;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -71,6 +74,7 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
private final BukkitScheduler scheduler; private final BukkitScheduler scheduler;
private FastLoginCore<Player, CommandSender, FastLoginBukkit> core; private FastLoginCore<Player, CommandSender, FastLoginBukkit> core;
private FloodgateService floodgateService; private FloodgateService floodgateService;
private GeyserService geyserService;
private PremiumPlaceholder premiumPlaceholder; private PremiumPlaceholder premiumPlaceholder;
@ -146,6 +150,10 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
} }
private boolean initializeFloodgate() { private boolean initializeFloodgate() {
if (getServer().getPluginManager().getPlugin("Geyser-Spigot") != null) {
geyserService = new GeyserService(GeyserConnector.getInstance(), core);
}
if (getServer().getPluginManager().getPlugin("floodgate") != null) { if (getServer().getPluginManager().getPlugin("floodgate") != null) {
floodgateService = new FloodgateService(FloodgateApi.getInstance(), core); floodgateService = new FloodgateService(FloodgateApi.getInstance(), core);
@ -276,11 +284,22 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
return Bukkit.getServer().getPluginManager().getPlugin(name) != null; return Bukkit.getServer().getPluginManager().getPlugin(name) != null;
} }
@Override
public FloodgateService getFloodgateService() { public FloodgateService getFloodgateService() {
return floodgateService; return floodgateService;
} }
public GeyserService getGeyserService() {
return geyserService;
}
@Override
public BedrockService<?> getBedrockService() {
if (floodgateService != null) {
return floodgateService;
}
return geyserService;
}
/** /**
* Send warning messages to log if incompatible plugins are used * Send warning messages to log if incompatible plugins are used
*/ */

View File

@ -29,7 +29,7 @@ import com.github.games647.fastlogin.bukkit.BukkitLoginSession;
import com.github.games647.fastlogin.bukkit.FastLoginBukkit; import com.github.games647.fastlogin.bukkit.FastLoginBukkit;
import com.github.games647.fastlogin.bukkit.task.FloodgateAuthTask; import com.github.games647.fastlogin.bukkit.task.FloodgateAuthTask;
import com.github.games647.fastlogin.bukkit.task.ForceLoginTask; import com.github.games647.fastlogin.bukkit.task.ForceLoginTask;
import com.github.games647.fastlogin.core.hooks.FloodgateService; import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -82,7 +82,7 @@ public class ConnectionListener implements Listener {
BukkitLoginSession session = plugin.getSession(player.getAddress()); BukkitLoginSession session = plugin.getSession(player.getAddress());
FloodgateService floodgateService = plugin.getFloodgateService(); FloodgateService floodgateService = plugin.getFloodgateService();
if (floodgateService != null) { if (floodgateService != null) {
FloodgatePlayer floodgatePlayer = floodgateService.getFloodgatePlayer(player.getUniqueId()); FloodgatePlayer floodgatePlayer = floodgateService.getBedrockPlayer(player.getUniqueId());
if (floodgatePlayer != null) { if (floodgatePlayer != null) {
Runnable floodgateAuthTask = new FloodgateAuthTask(plugin.getCore(), player, floodgatePlayer); Runnable floodgateAuthTask = new FloodgateAuthTask(plugin.getCore(), player, floodgatePlayer);
Bukkit.getScheduler().runTaskAsynchronously(plugin, floodgateAuthTask); Bukkit.getScheduler().runTaskAsynchronously(plugin, floodgateAuthTask);

View File

@ -54,7 +54,7 @@ public class NameCheckTask extends JoinManagement<Player, CommandSender, Protoco
public NameCheckTask(FastLoginBukkit plugin, Random random, Player player, PacketEvent packetEvent, public NameCheckTask(FastLoginBukkit plugin, Random random, Player player, PacketEvent packetEvent,
String username, PublicKey publicKey) { String username, PublicKey publicKey) {
super(plugin.getCore(), plugin.getCore().getAuthPluginHook(), plugin.getFloodgateService()); super(plugin.getCore(), plugin.getCore().getAuthPluginHook(), plugin.getBedrockService());
this.plugin = plugin; this.plugin = plugin;
this.packetEvent = packetEvent; this.packetEvent = packetEvent;

View File

@ -53,7 +53,7 @@ public class ProtocolSupportListener extends JoinManagement<Player, CommandSende
private final RateLimiter rateLimiter; private final RateLimiter rateLimiter;
public ProtocolSupportListener(FastLoginBukkit plugin, RateLimiter rateLimiter) { public ProtocolSupportListener(FastLoginBukkit plugin, RateLimiter rateLimiter) {
super(plugin.getCore(), plugin.getCore().getAuthPluginHook(), plugin.getFloodgateService()); super(plugin.getCore(), plugin.getCore().getAuthPluginHook(), plugin.getBedrockService());
this.plugin = plugin; this.plugin = plugin;
this.rateLimiter = rateLimiter; this.rateLimiter = rateLimiter;

View File

@ -20,6 +20,8 @@ softdepend:
- ProtocolLib - ProtocolLib
# Premium variable # Premium variable
- PlaceholderAPI - PlaceholderAPI
# Bedrock Player Bridge
- Geyser-Spigot
- floodgate - floodgate
# Auth plugins # Auth plugins
- AuthMe - AuthMe

View File

@ -123,15 +123,6 @@
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<!-- Bedrock player bridge -->
<!-- Should be removed one Floodgate 2.0 gets a stable release -->
<dependency>
<groupId>org.geysermc</groupId>
<artifactId>floodgate-bungee</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!-- Bedrock player bridge --> <!-- Bedrock player bridge -->
<!-- Version 2.0 --> <!-- Version 2.0 -->
<dependency> <dependency>
@ -141,6 +132,14 @@
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<!-- Bedrock player bridge, used for low level checks -->
<dependency>
<groupId>org.geysermc</groupId>
<artifactId>connector</artifactId>
<version>1.4.3-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!--Login plugin--> <!--Login plugin-->
<dependency> <dependency>
<groupId>me.vik1395</groupId> <groupId>me.vik1395</groupId>

View File

@ -33,7 +33,9 @@ import com.github.games647.fastlogin.bungee.listener.PluginMessageListener;
import com.github.games647.fastlogin.core.AsyncScheduler; import com.github.games647.fastlogin.core.AsyncScheduler;
import com.github.games647.fastlogin.core.CommonUtil; import com.github.games647.fastlogin.core.CommonUtil;
import com.github.games647.fastlogin.core.hooks.AuthPlugin; import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import com.github.games647.fastlogin.core.hooks.FloodgateService; import com.github.games647.fastlogin.core.hooks.bedrock.BedrockService;
import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
import com.github.games647.fastlogin.core.hooks.bedrock.GeyserService;
import com.github.games647.fastlogin.core.message.ChangePremiumMessage; import com.github.games647.fastlogin.core.message.ChangePremiumMessage;
import com.github.games647.fastlogin.core.message.ChannelMessage; import com.github.games647.fastlogin.core.message.ChannelMessage;
import com.github.games647.fastlogin.core.message.NamespaceKey; import com.github.games647.fastlogin.core.message.NamespaceKey;
@ -60,6 +62,7 @@ import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.api.plugin.PluginManager; import net.md_5.bungee.api.plugin.PluginManager;
import net.md_5.bungee.api.scheduler.GroupedThreadFactory; import net.md_5.bungee.api.scheduler.GroupedThreadFactory;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.floodgate.api.FloodgateApi; import org.geysermc.floodgate.api.FloodgateApi;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -73,6 +76,7 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
private FastLoginCore<ProxiedPlayer, CommandSender, FastLoginBungee> core; private FastLoginCore<ProxiedPlayer, CommandSender, FastLoginBungee> core;
private AsyncScheduler scheduler; private AsyncScheduler scheduler;
private FloodgateService floodgateService; private FloodgateService floodgateService;
private GeyserService geyserService;
private Logger logger; private Logger logger;
@Override @Override
@ -90,6 +94,10 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
floodgateService = new FloodgateService(FloodgateApi.getInstance(), core); floodgateService = new FloodgateService(FloodgateApi.getInstance(), core);
} }
if (isPluginInstalled("Geyser-BungeeCord")) {
geyserService = new GeyserService(GeyserConnector.getInstance(), core);
}
//events //events
PluginManager pluginManager = getProxy().getPluginManager(); PluginManager pluginManager = getProxy().getPluginManager();
@ -193,8 +201,19 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
return getProxy().getPluginManager().getPlugin(name) != null; return getProxy().getPluginManager().getPlugin(name) != null;
} }
@Override
public FloodgateService getFloodgateService() { public FloodgateService getFloodgateService() {
return floodgateService; return floodgateService;
} }
public GeyserService getGeyserService() {
return geyserService;
}
@Override
public BedrockService<?> getBedrockService() {
if (floodgateService != null) {
return floodgateService;
}
return geyserService;
}
} }

View File

@ -33,7 +33,7 @@ import com.github.games647.fastlogin.bungee.task.FloodgateAuthTask;
import com.github.games647.fastlogin.bungee.task.ForceLoginTask; import com.github.games647.fastlogin.bungee.task.ForceLoginTask;
import com.github.games647.fastlogin.core.RateLimiter; import com.github.games647.fastlogin.core.RateLimiter;
import com.github.games647.fastlogin.core.StoredProfile; import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.hooks.FloodgateService; import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
import com.github.games647.fastlogin.core.shared.LoginSession; import com.github.games647.fastlogin.core.shared.LoginSession;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
@ -186,7 +186,7 @@ public class ConnectListener implements Listener {
FloodgateService floodgateService = plugin.getFloodgateService(); FloodgateService floodgateService = plugin.getFloodgateService();
if (floodgateService != null) { if (floodgateService != null) {
FloodgatePlayer floodgatePlayer = floodgateService.getFloodgatePlayer(player.getUniqueId()); FloodgatePlayer floodgatePlayer = floodgateService.getBedrockPlayer(player.getUniqueId());
if (floodgatePlayer != null) { if (floodgatePlayer != null) {
Runnable floodgateAuthTask = new FloodgateAuthTask(plugin.getCore(), player, floodgatePlayer, server); Runnable floodgateAuthTask = new FloodgateAuthTask(plugin.getCore(), player, floodgatePlayer, server);
plugin.getScheduler().runAsync(floodgateAuthTask); plugin.getScheduler().runAsync(floodgateAuthTask);

View File

@ -29,7 +29,7 @@ import com.github.games647.fastlogin.bungee.BungeeLoginSession;
import com.github.games647.fastlogin.bungee.FastLoginBungee; import com.github.games647.fastlogin.bungee.FastLoginBungee;
import com.github.games647.fastlogin.bungee.task.AsyncToggleMessage; import com.github.games647.fastlogin.bungee.task.AsyncToggleMessage;
import com.github.games647.fastlogin.core.StoredProfile; import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.hooks.FloodgateService; import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService;
import com.github.games647.fastlogin.core.message.ChangePremiumMessage; import com.github.games647.fastlogin.core.message.ChangePremiumMessage;
import com.github.games647.fastlogin.core.message.NamespaceKey; import com.github.games647.fastlogin.core.message.NamespaceKey;
import com.github.games647.fastlogin.core.message.SuccessMessage; import com.github.games647.fastlogin.core.message.SuccessMessage;
@ -121,7 +121,7 @@ public class PluginMessageListener implements Listener {
FloodgateService floodgateService = plugin.getFloodgateService(); FloodgateService floodgateService = plugin.getFloodgateService();
if (!shouldPersist && floodgateService != null) { if (!shouldPersist && floodgateService != null) {
// always save floodgate players to lock this username // always save floodgate players to lock this username
shouldPersist = floodgateService.isFloodgatePlayer(forPlayer.getUniqueId()); shouldPersist = floodgateService.isBedrockPlayer(forPlayer.getUniqueId());
} }
if (shouldPersist) { if (shouldPersist) {

View File

@ -49,7 +49,7 @@ public class AsyncPremiumCheck extends JoinManagement<ProxiedPlayer, CommandSend
public AsyncPremiumCheck(FastLoginBungee plugin, PreLoginEvent preLoginEvent, PendingConnection connection, public AsyncPremiumCheck(FastLoginBungee plugin, PreLoginEvent preLoginEvent, PendingConnection connection,
String username) { String username) {
super(plugin.getCore(), plugin.getCore().getAuthPluginHook(), plugin.getFloodgateService()); super(plugin.getCore(), plugin.getCore().getAuthPluginHook(), plugin.getBedrockService());
this.plugin = plugin; this.plugin = plugin;
this.preLoginEvent = preLoginEvent; this.preLoginEvent = preLoginEvent;

View File

@ -13,6 +13,9 @@ softDepends:
- BungeeAuth - BungeeAuth
- BungeeCordAuthenticatorBungee - BungeeCordAuthenticatorBungee
- SodionAuth - SodionAuth
# Bedrock Player Bridge
- Geyser-BungeeCord
- floodgate
description: | description: |
${project.description} ${project.description}

View File

@ -98,6 +98,14 @@
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<!-- Bedrock player bridge -->
<dependency>
<groupId>org.geysermc</groupId>
<artifactId>connector</artifactId>
<version>1.4.3-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!--Common component for contacting the Mojang API--> <!--Common component for contacting the Mojang API-->
<dependency> <dependency>
<groupId>com.github.games647</groupId> <groupId>com.github.games647</groupId>

View File

@ -0,0 +1,130 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* 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.hooks.bedrock;
import java.io.IOException;
import java.util.Optional;
import java.util.UUID;
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.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.LoginSource;
/**
* @param B is an instance of either FloodgatePlayer or GeyserSession
*/
public abstract class BedrockService<B> {
protected final FastLoginCore<?, ?, ?> core;
protected final String allowConflict;
public BedrockService(FastLoginCore<?, ?, ?> core) {
this.core = core;
this.allowConflict = core.getConfig().get("allowFloodgateNameConflict").toString().toLowerCase();
}
/**
* Perfrom every packet level check needed on a Bedrock player.
*
* @param username the name of the player
* @param source an instance of LoginSource
* @return true if Java specific checks can be skipped
*/
public abstract boolean performChecks(String username, LoginSource source);
/**
* Check if the player's name conflicts an existing Java player's name, and kick
* them if it does
*
* @param username the name of the player
* @param source an instance of LoginSource
*/
protected void checkNameConflict(String username, LoginSource source) {
// check for conflicting Premium Java name
Optional<Profile> premiumUUID = Optional.empty();
try {
premiumUUID = core.getResolver().findProfile(username);
} catch (IOException | RateLimitException e) {
core.getPlugin().getLog().error(
"Could not check whether Bedrock Player {}'s name conflicts a premium Java player's name.",
username);
try {
source.kick("Could not check if your name conflicts an existing premium Java account's name.\n"
+ "This is usually a serverside error.");
} catch (Exception ex) {
core.getPlugin().getLog().error("Could not kick Player {}", username, ex);
}
}
if (premiumUUID.isPresent()) {
core.getPlugin().getLog().info("Bedrock Player {}'s name conflicts an existing premium Java account's name",
username);
try {
source.kick("Your name conflicts an existing premium Java account's name");
} catch (Exception ex) {
core.getPlugin().getLog().error("Could not kick Player {}", username, ex);
}
}
}
/**
* The Floodgate / Geyser API does not support querying players by name, so this function
* iterates over every online Bedrock Player and checks if the requested
* username can be found
* <br>
* <i>Falls back to non-prefixed name checks, if ProtocolLib is installed</i>
*
* @param prefixedUsername the name of the player with the prefix appended
* @return Bedrock Player if found, null otherwise
*/
public B getBedrockPlayer(String prefixedUsername) {
return null;
}
public B getBedrockPlayer(UUID uuid) {
return null;
}
public boolean isBedrockPlayer(UUID uuid) {
return getBedrockPlayer(uuid) != null;
}
public boolean isBedrockConnection(String username) {
return getBedrockPlayer(username) != null;
}
/**
* Checks if a profile's name starts with the Floodgate prefix, if it's available
* @param profile profile of the conecting player
* @return true if the username is forbidden
*/
public boolean isUsernameForbidden(StoredProfile profile) {
return false;
}
}

View File

@ -23,30 +23,25 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
package com.github.games647.fastlogin.core.hooks; package com.github.games647.fastlogin.core.hooks.bedrock;
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.StoredProfile;
import com.github.games647.fastlogin.core.shared.FastLoginCore; import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.LoginSource; import com.github.games647.fastlogin.core.shared.LoginSource;
import java.io.IOException;
import java.util.Locale; import java.util.Locale;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import org.geysermc.floodgate.api.FloodgateApi; import org.geysermc.floodgate.api.FloodgateApi;
import org.geysermc.floodgate.api.player.FloodgatePlayer; import org.geysermc.floodgate.api.player.FloodgatePlayer;
public class FloodgateService { public class FloodgateService extends BedrockService<FloodgatePlayer> {
private final FloodgateApi floodgate; private final FloodgateApi floodgate;
private final FastLoginCore<?, ?, ?> core;
public FloodgateService(FloodgateApi floodgate, FastLoginCore<?, ?, ?> core) { public FloodgateService(FloodgateApi floodgate, FastLoginCore<?, ?, ?> core) {
super(core);
this.floodgate = floodgate; this.floodgate = floodgate;
this.core = core;
} }
/** /**
@ -74,56 +69,27 @@ public class FloodgateService {
return true; return true;
} }
@Override
public boolean isUsernameForbidden(StoredProfile profile) { public boolean isUsernameForbidden(StoredProfile profile) {
String playerPrefix = FloodgateApi.getInstance().getPlayerPrefix(); String playerPrefix = floodgate.getPlayerPrefix();
return profile.getName().startsWith(playerPrefix) && !playerPrefix.isEmpty(); return profile.getName().startsWith(playerPrefix) && !playerPrefix.isEmpty();
} }
/** @Override
* Check if the player's name conflicts an existing Java player's name, and public boolean performChecks(String username, LoginSource source) {
* kick them if it does
*
* @param username the name of the player
* @param source an instance of LoginSource
*/
public void checkNameConflict(String username, LoginSource source) {
String allowConflict = core.getConfig().get("allowFloodgateNameConflict").toString().toLowerCase();
// check if the Bedrock player is linked to a Java account // check if the Bedrock player is linked to a Java account
FloodgatePlayer floodgatePlayer = getFloodgatePlayer(username); FloodgatePlayer floodgatePlayer = getBedrockPlayer(username);
boolean isLinked = floodgatePlayer.getLinkedPlayer() != null; boolean isLinked = floodgatePlayer.getLinkedPlayer() != null;
if ("false".equals(allowConflict) if ("false".equals(allowConflict)
|| "linked".equals(allowConflict) && !isLinked) { || "linked".equals(allowConflict) && !isLinked) {
super.checkNameConflict(username, source);
// check for conflicting Premium Java name
Optional<Profile> premiumUUID = Optional.empty();
try {
premiumUUID = core.getResolver().findProfile(username);
} catch (IOException | RateLimitException e) {
core.getPlugin().getLog().error(
"Could not check whether Floodgate Player {}'s name conflicts a premium Java player's name.",
username);
try {
source.kick("Could not check if your name conflicts an existing premium Java account's name.\n"
+ "This is usually a serverside error.");
} catch (Exception ex) {
core.getPlugin().getLog().error("Could not kick Player {}", username, ex);
}
}
if (premiumUUID.isPresent()) {
core.getPlugin().getLog().info("Bedrock Player {}'s name conflicts an existing premium Java account's name",
username);
try {
source.kick("Your name conflicts an existing premium Java account's name");
} catch (Exception ex) {
core.getPlugin().getLog().error("Could not kick Player {}", username, ex);
}
}
} else { } else {
core.getPlugin().getLog().info("Skipping name conflict checking for player {}", username); core.getPlugin().getLog().info("Skipping name conflict checking for player {}", username);
} }
//Floodgate users don't need Java specific checks
return true;
} }
/** /**
@ -136,18 +102,18 @@ public class FloodgateService {
* @param prefixedUsername the name of the player with the prefix appended * @param prefixedUsername the name of the player with the prefix appended
* @return FloodgatePlayer if found, null otherwise * @return FloodgatePlayer if found, null otherwise
*/ */
public FloodgatePlayer getFloodgatePlayer(String prefixedUsername) { public FloodgatePlayer getBedrockPlayer(String prefixedUsername) {
//prefixes are broken with ProtocolLib, so fall back to name checks without prefixes //prefixes are broken with ProtocolLib, so fall back to name checks without prefixes
//this should be removed if #493 gets fixed //this should be removed if #493 gets fixed
if (core.getPlugin().isPluginInstalled("ProtocolLib")) { if (core.getPlugin().isPluginInstalled("ProtocolLib")) {
for (FloodgatePlayer floodgatePlayer : FloodgateApi.getInstance().getPlayers()) { for (FloodgatePlayer floodgatePlayer : floodgate.getPlayers()) {
if (floodgatePlayer.getUsername().equals(prefixedUsername)) { if (floodgatePlayer.getUsername().equals(prefixedUsername)) {
return floodgatePlayer; return floodgatePlayer;
} }
} }
return null; return null;
} }
for (FloodgatePlayer floodgatePlayer : FloodgateApi.getInstance().getPlayers()) { for (FloodgatePlayer floodgatePlayer : floodgate.getPlayers()) {
if (floodgatePlayer.getCorrectUsername().equals(prefixedUsername)) { if (floodgatePlayer.getCorrectUsername().equals(prefixedUsername)) {
return floodgatePlayer; return floodgatePlayer;
} }
@ -156,15 +122,15 @@ public class FloodgateService {
return null; return null;
} }
public FloodgatePlayer getFloodgatePlayer(UUID uuid) { public FloodgatePlayer getBedrockPlayer(UUID uuid) {
return FloodgateApi.getInstance().getPlayer(uuid); return floodgate.getPlayer(uuid);
} }
public boolean isFloodgatePlayer(UUID uuid) { public boolean isBedrockPlayer(UUID uuid) {
return getFloodgatePlayer(uuid) != null; return getBedrockPlayer(uuid) != null;
} }
public boolean isFloodgateConnection(String username) { public boolean isBedrockConnection(String username) {
return getFloodgatePlayer(username) != null; return getBedrockPlayer(username) != null;
} }
} }

View File

@ -0,0 +1,81 @@
/*
* SPDX-License-Identifier: MIT
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2021 <Your name and contributors>
*
* 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.hooks.bedrock;
import java.util.UUID;
import com.github.games647.fastlogin.core.shared.FastLoginCore;
import com.github.games647.fastlogin.core.shared.LoginSource;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.common.AuthType;
import org.geysermc.connector.network.session.GeyserSession;
public class GeyserService extends BedrockService<GeyserSession> {
private final GeyserConnector geyser;
private final FastLoginCore<?, ?, ?> core;
private final AuthType authType;
public GeyserService(GeyserConnector geyser, FastLoginCore<?, ?, ?> core) {
super(core);
this.geyser = geyser;
this.core = core;
this.authType = geyser.getConfig().getRemote().getAuthType();
}
@Override
public boolean performChecks(String username, LoginSource source) {
// AuthType.FLOODGATE will be handled by FloodgateService
if (authType == AuthType.ONLINE) {
// authenticate everyone, as if they were Java players, since they have signed
// in through Mojang
return false;
}
if ("true".equals(allowConflict)) {
core.getPlugin().getLog().info("Skipping name conflict checking for player {}", username);
} else {
super.checkNameConflict(username, source);
}
return true;
}
@Override
public GeyserSession getBedrockPlayer(String username) {
for (GeyserSession gSess : geyser.getSessionManager().getSessions().values()) {
if (gSess.getName().equals(username)) {
return gSess;
}
}
return null;
}
@Override
public GeyserSession getBedrockPlayer(UUID uuid) {
return geyser.getPlayerByUuid(uuid);
}
}

View File

@ -29,7 +29,7 @@ import com.github.games647.craftapi.model.Profile;
import com.github.games647.craftapi.resolver.RateLimitException; import com.github.games647.craftapi.resolver.RateLimitException;
import com.github.games647.fastlogin.core.StoredProfile; import com.github.games647.fastlogin.core.StoredProfile;
import com.github.games647.fastlogin.core.hooks.AuthPlugin; import com.github.games647.fastlogin.core.hooks.AuthPlugin;
import com.github.games647.fastlogin.core.hooks.FloodgateService; import com.github.games647.fastlogin.core.hooks.bedrock.BedrockService;
import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent; import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent;
import java.util.Optional; import java.util.Optional;
@ -40,12 +40,12 @@ public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
protected final FastLoginCore<P, C, ?> core; protected final FastLoginCore<P, C, ?> core;
protected final AuthPlugin<P> authHook; protected final AuthPlugin<P> authHook;
private final FloodgateService floodgateService; private final BedrockService<?> bedrockService;
public JoinManagement(FastLoginCore<P, C, ?> core, AuthPlugin<P> authHook, FloodgateService floodService) { public JoinManagement(FastLoginCore<P, C, ?> core, AuthPlugin<P> authHook, BedrockService<?> bedrockService) {
this.core = core; this.core = core;
this.authHook = authHook; this.authHook = authHook;
this.floodgateService = floodService; this.bedrockService = bedrockService;
} }
public void onLogin(String username, S source) { public void onLogin(String username, S source) {
@ -55,11 +55,10 @@ public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
return; return;
} }
//check if the player is connecting through Floodgate //check if the player is connecting through Bedrock Edition
if (floodgateService != null) { if (bedrockService != null && bedrockService.isBedrockConnection(username)) {
if (floodgateService.isFloodgateConnection(username)) { //perform Bedrock specific checks and skip Java checks, if they are not needed
floodgateService.checkNameConflict(username, source); if (bedrockService.performChecks(username, source)) {
// skip flow for any floodgate player
return; return;
} }
} }
@ -117,7 +116,7 @@ public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
} }
protected boolean isValidUsername(LoginSource source, StoredProfile profile) throws Exception { protected boolean isValidUsername(LoginSource source, StoredProfile profile) throws Exception {
if (floodgateService != null && floodgateService.isUsernameForbidden(profile)) { if (bedrockService != null && bedrockService.isUsernameForbidden(profile)) {
core.getPlugin().getLog().info("Floodgate Prefix detected on cracked player"); core.getPlugin().getLog().info("Floodgate Prefix detected on cracked player");
source.kick("Your username contains illegal characters"); source.kick("Your username contains illegal characters");
return false; return false;

View File

@ -26,7 +26,7 @@
package com.github.games647.fastlogin.core.shared; package com.github.games647.fastlogin.core.shared;
import com.github.games647.fastlogin.core.AsyncScheduler; import com.github.games647.fastlogin.core.AsyncScheduler;
import com.github.games647.fastlogin.core.hooks.FloodgateService; import com.github.games647.fastlogin.core.hooks.bedrock.BedrockService;
import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.nio.file.Path; import java.nio.file.Path;
@ -54,7 +54,7 @@ public interface PlatformPlugin<C> {
} }
} }
FloodgateService getFloodgateService(); BedrockService<?> getBedrockService();
default ThreadFactory getThreadFactory() { default ThreadFactory getThreadFactory() {
return new ThreadFactoryBuilder() return new ThreadFactoryBuilder()

View File

@ -205,8 +205,8 @@ autoLogin: true
# Enabling this might lead to people gaining unauthorized access to other's accounts! # Enabling this might lead to people gaining unauthorized access to other's accounts!
autoLoginFloodgate: false autoLoginFloodgate: false
# This enables Floodgate players to join the server, even if autoRegister is true and there's an existing # This enables Floodgate or Offline Geyser players to join the server, even if they are using the name of an
# Java **PREMIUM** account with the same name # existing Java **PREMIUM** account (so someone has bought Minecraft with that username)
# #
# Java and Bedrock players will get different UUIDs, so their inventories, location, etc. will be different. # 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. # However, some plugins (such as AuthMe) rely on names instead of UUIDs to identify a player which might cause issues.
@ -219,12 +219,13 @@ autoLoginFloodgate: false
# A solution to this is to replace ProtocolLib with ProtocolSupport # A solution to this is to replace ProtocolLib with ProtocolSupport
# #
# Possible values: # Possible values:
# false: Check for Premium Java name conflicts as described in 'autoRegister' # false: Kick Bedrock players, if they are using an existing Premium Java account's name
# Note: Linked players have the same name as their Java profile, so the Bedrock player will always conflict # Note: Linked Floodgate players have the same name as their Java profile, so the Bedrock player will always conflict
# their own Java account's name. Therefore, setting this to false will prevent any linked player from joining. # their own Java account's name. Therefore, setting this to false will prevent any linked player from joining.
# true: Bypass 'autoRegister's name conflict checking # true: Bypass name conflict checking.
# linked: Bedrock accounts linked to a Java account will be allowed to join with conflicting names # linked: Floodgate accounts linked to a Java account will be allowed to join with conflicting names
# !!!!!!!! WARNING: FLOODGATE SUPPORT IS AN EXPERIMENTAL FEATURE !!!!!!!! # For Offline Geyser players, 'linked' works as 'false'
# !!!!!!!! WARNING: FLOODGATE/GEYSER SUPPORT IS AN EXPERIMENTAL FEATURE !!!!!!!!
# Enabling this might lead to people gaining unauthorized access to other's accounts! # Enabling this might lead to people gaining unauthorized access to other's accounts!
allowFloodgateNameConflict: false allowFloodgateNameConflict: false

View File

@ -26,7 +26,7 @@
package com.github.games647.fastlogin.velocity; package com.github.games647.fastlogin.velocity;
import com.github.games647.fastlogin.core.AsyncScheduler; import com.github.games647.fastlogin.core.AsyncScheduler;
import com.github.games647.fastlogin.core.hooks.FloodgateService; import com.github.games647.fastlogin.core.hooks.bedrock.BedrockService;
import com.github.games647.fastlogin.core.message.ChangePremiumMessage; import com.github.games647.fastlogin.core.message.ChangePremiumMessage;
import com.github.games647.fastlogin.core.message.ChannelMessage; import com.github.games647.fastlogin.core.message.ChannelMessage;
import com.github.games647.fastlogin.core.message.SuccessMessage; import com.github.games647.fastlogin.core.message.SuccessMessage;
@ -140,7 +140,7 @@ public class FastLoginVelocity implements PlatformPlugin<CommandSource> {
} }
@Override @Override
public FloodgateService getFloodgateService() { public BedrockService<?> getBedrockService() {
return null; return null;
} }

View File

@ -50,7 +50,7 @@ public class AsyncPremiumCheck extends JoinManagement<Player, CommandSource, Vel
private final InboundConnection connection; private final InboundConnection connection;
public AsyncPremiumCheck(FastLoginVelocity plugin, InboundConnection connection, String username, Continuation continuation, PreLoginEvent preLoginEvent) { public AsyncPremiumCheck(FastLoginVelocity plugin, InboundConnection connection, String username, Continuation continuation, PreLoginEvent preLoginEvent) {
super(plugin.getCore(), plugin.getCore().getAuthPluginHook(), plugin.getFloodgateService()); super(plugin.getCore(), plugin.getCore().getAuthPluginHook(), plugin.getBedrockService());
this.plugin = plugin; this.plugin = plugin;
this.connection = connection; this.connection = connection;
this.username = username; this.username = username;