mirror of
https://github.com/TuxCoding/FastLogin.git
synced 2025-07-31 03:07:34 +02:00
Merge pull request #532 from Smart123s/fg-bk-ncshare
Share Floodgate name conflict check between Protocol Plugins
This commit is contained in:
@ -276,7 +276,7 @@ public class FastLoginBukkit extends JavaPlugin implements PlatformPlugin<Comman
|
|||||||
* @param name the name of the plugin
|
* @param name the name of the plugin
|
||||||
* @return true if the plugin is installed
|
* @return true if the plugin is installed
|
||||||
*/
|
*/
|
||||||
private boolean isPluginInstalled(String name) {
|
public boolean isPluginInstalled(String name) {
|
||||||
//the plugin may be enabled after FastLogin, so isPluginEnabled()
|
//the plugin may be enabled after FastLogin, so isPluginEnabled()
|
||||||
//won't work here
|
//won't work here
|
||||||
return Bukkit.getServer().getPluginManager().getPlugin(name) != null;
|
return Bukkit.getServer().getPluginManager().getPlugin(name) != null;
|
||||||
|
@ -37,11 +37,8 @@ import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent;
|
|||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.geysermc.floodgate.api.FloodgateApi;
|
|
||||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
|
||||||
|
|
||||||
public class NameCheckTask extends JoinManagement<Player, CommandSender, ProtocolLibLoginSource>
|
public class NameCheckTask extends JoinManagement<Player, CommandSender, ProtocolLibLoginSource>
|
||||||
implements Runnable {
|
implements Runnable {
|
||||||
@ -55,6 +52,7 @@ public class NameCheckTask extends JoinManagement<Player, CommandSender, Protoco
|
|||||||
private final Player player;
|
private final Player player;
|
||||||
private final String username;
|
private final String username;
|
||||||
|
|
||||||
|
|
||||||
public NameCheckTask(FastLoginBukkit plugin, PacketEvent packetEvent, Random random,
|
public NameCheckTask(FastLoginBukkit plugin, PacketEvent packetEvent, Random random,
|
||||||
Player player, String username, PublicKey publicKey) {
|
Player player, String username, PublicKey publicKey) {
|
||||||
super(plugin.getCore(), plugin.getCore().getAuthPluginHook());
|
super(plugin.getCore(), plugin.getCore().getAuthPluginHook());
|
||||||
@ -70,12 +68,6 @@ public class NameCheckTask extends JoinManagement<Player, CommandSender, Protoco
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
// check if the player is connecting through Geyser
|
|
||||||
if (!plugin.getCore().getConfig().get("allowFloodgateNameConflict").toString().equalsIgnoreCase("false")
|
|
||||||
&& getFloodgatePlayer(username) != null) {
|
|
||||||
plugin.getLog().info("Skipping name conflict checking for player {}", username);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
super.onLogin(username, new ProtocolLibLoginSource(packetEvent, player, random, publicKey));
|
super.onLogin(username, new ProtocolLibLoginSource(packetEvent, player, random, publicKey));
|
||||||
} finally {
|
} finally {
|
||||||
ProtocolLibrary.getProtocolManager().getAsynchronousManager().signalPacketTransmission(packetEvent);
|
ProtocolLibrary.getProtocolManager().getAsynchronousManager().signalPacketTransmission(packetEvent);
|
||||||
@ -119,16 +111,4 @@ public class NameCheckTask extends JoinManagement<Player, CommandSender, Protoco
|
|||||||
BukkitLoginSession loginSession = new BukkitLoginSession(username, profile);
|
BukkitLoginSession loginSession = new BukkitLoginSession(username, profile);
|
||||||
plugin.putSession(player.getAddress(), loginSession);
|
plugin.putSession(player.getAddress(), loginSession);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static FloodgatePlayer getFloodgatePlayer(String username) {
|
|
||||||
if (Bukkit.getServer().getPluginManager().isPluginEnabled("floodgate")) {
|
|
||||||
// the Floodgate API requires UUID, which is inaccessible at NameCheckTask.java
|
|
||||||
for (FloodgatePlayer floodgatePlayer : FloodgateApi.getInstance().getPlayers()) {
|
|
||||||
if (floodgatePlayer.getUsername().equals(username)) {
|
|
||||||
return floodgatePlayer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,7 @@ import org.bukkit.command.CommandSender;
|
|||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
|
|
||||||
import protocolsupport.api.events.ConnectionCloseEvent;
|
import protocolsupport.api.events.ConnectionCloseEvent;
|
||||||
import protocolsupport.api.events.PlayerLoginStartEvent;
|
import protocolsupport.api.events.PlayerLoginStartEvent;
|
||||||
import protocolsupport.api.events.PlayerProfileCompleteEvent;
|
import protocolsupport.api.events.PlayerProfileCompleteEvent;
|
||||||
@ -75,7 +76,8 @@ public class ProtocolSupportListener extends JoinManagement<Player, CommandSende
|
|||||||
//remove old data every time on a new login in order to keep the session only for one person
|
//remove old data every time on a new login in order to keep the session only for one person
|
||||||
plugin.removeSession(address);
|
plugin.removeSession(address);
|
||||||
|
|
||||||
super.onLogin(username, new ProtocolLoginSource(loginStartEvent));
|
ProtocolLoginSource source = new ProtocolLoginSource(loginStartEvent);
|
||||||
|
super.onLogin(username, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
|
@ -51,25 +51,10 @@ public class FloodgateAuthTask implements Runnable {
|
|||||||
plugin.getLog().info(
|
plugin.getLog().info(
|
||||||
"Player {} is connecting through Geyser Floodgate.",
|
"Player {} is connecting through Geyser Floodgate.",
|
||||||
player.getName());
|
player.getName());
|
||||||
String allowNameConflict = plugin.getCore().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
|
||||||
boolean isLinked = floodgatePlayer.getLinkedPlayer() != null;
|
boolean isLinked = floodgatePlayer.getLinkedPlayer() != null;
|
||||||
if (allowNameConflict.equals("linked") && !isLinked) {
|
|
||||||
plugin.getLog().info(
|
|
||||||
"Bedrock Player {}'s name conflits an existing Java Premium Player's name",
|
|
||||||
player.getName());
|
|
||||||
|
|
||||||
// kicking must be synchronous
|
|
||||||
// https://www.spigotmc.org/threads/asynchronous-player-kick-problem.168580/
|
|
||||||
Bukkit.getScheduler().runTask(plugin, new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
player.kickPlayer("This name is allready in use by a Premium Java Player");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
AuthPlugin<Player> authPlugin = plugin.getCore().getAuthPluginHook();
|
AuthPlugin<Player> authPlugin = plugin.getCore().getAuthPluginHook();
|
||||||
|
|
||||||
String autoLoginFloodgate = plugin.getCore().getConfig().get("autoLoginFloodgate").toString().toLowerCase();
|
String autoLoginFloodgate = plugin.getCore().getConfig().get("autoLoginFloodgate").toString().toLowerCase();
|
||||||
|
@ -50,6 +50,7 @@ import java.util.List;
|
|||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.concurrent.ThreadFactory;
|
import java.util.concurrent.ThreadFactory;
|
||||||
|
|
||||||
|
import net.md_5.bungee.BungeeServerInfo;
|
||||||
import net.md_5.bungee.api.CommandSender;
|
import net.md_5.bungee.api.CommandSender;
|
||||||
import net.md_5.bungee.api.chat.TextComponent;
|
import net.md_5.bungee.api.chat.TextComponent;
|
||||||
import net.md_5.bungee.api.connection.PendingConnection;
|
import net.md_5.bungee.api.connection.PendingConnection;
|
||||||
@ -187,4 +188,9 @@ public class FastLoginBungee extends Plugin implements PlatformPlugin<CommandSen
|
|||||||
public AsyncScheduler getScheduler() {
|
public AsyncScheduler getScheduler() {
|
||||||
return scheduler;
|
return scheduler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPluginInstalled(String name) {
|
||||||
|
return getProxy().getPluginManager().getPlugin(name) != null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
13
core/pom.xml
13
core/pom.xml
@ -53,6 +53,11 @@
|
|||||||
<id>codemc-repo</id>
|
<id>codemc-repo</id>
|
||||||
<url>https://repo.codemc.io/repository/maven-public/</url>
|
<url>https://repo.codemc.io/repository/maven-public/</url>
|
||||||
</repository>
|
</repository>
|
||||||
|
<!-- Floodgate -->
|
||||||
|
<repository>
|
||||||
|
<id>nukkitx-snapshot</id>
|
||||||
|
<url>https://repo.nukkitx.com/maven-snapshots/</url>
|
||||||
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@ -85,6 +90,14 @@
|
|||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!--Floodgate for Xbox Live Authentication-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.geysermc.floodgate</groupId>
|
||||||
|
<artifactId>api</artifactId>
|
||||||
|
<version>2.0-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>
|
||||||
|
@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import com.github.games647.craftapi.model.Profile;
|
||||||
|
import com.github.games647.craftapi.resolver.RateLimitException;
|
||||||
|
import com.github.games647.fastlogin.core.shared.FastLoginCore;
|
||||||
|
import com.github.games647.fastlogin.core.shared.LoginSource;
|
||||||
|
|
||||||
|
import org.geysermc.floodgate.api.FloodgateApi;
|
||||||
|
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||||
|
|
||||||
|
public class FloodgateHook<P extends C, C, S extends LoginSource> {
|
||||||
|
|
||||||
|
private final FastLoginCore<P, C, ?> core;
|
||||||
|
|
||||||
|
public FloodgateHook(FastLoginCore<P, C, ?> core) {
|
||||||
|
this.core = core;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
public void checkFloodgateNameConflict(String username, LoginSource source, FloodgatePlayer floodgatePlayer) {
|
||||||
|
String allowConflict = core.getConfig().get("allowFloodgateNameConflict").toString().toLowerCase();
|
||||||
|
|
||||||
|
// check if the Bedrock player is linked to a Java account
|
||||||
|
boolean isLinked = ((FloodgatePlayer) floodgatePlayer).getLinkedPlayer() != null;
|
||||||
|
|
||||||
|
if (allowConflict.equals("false")
|
||||||
|
|| allowConflict.equals("linked") && !isLinked) {
|
||||||
|
|
||||||
|
// 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 wether Floodgate Player {}'s name conflicts a premium Java player's name.",
|
||||||
|
username);
|
||||||
|
try {
|
||||||
|
source.kick("Could not check if your name conflicts an existing Java Premium Player's name");
|
||||||
|
} catch (Exception e1) {
|
||||||
|
core.getPlugin().getLog().error("Could not kick Player {}", username);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (premiumUUID.isPresent()) {
|
||||||
|
core.getPlugin().getLog().info("Bedrock Player {}'s name conflicts an existing Java Premium Player's name",
|
||||||
|
username);
|
||||||
|
try {
|
||||||
|
source.kick("Your name conflicts an existing Java Premium Player's name");
|
||||||
|
} catch (Exception e) {
|
||||||
|
core.getPlugin().getLog().error("Could not kick Player {}", username);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
core.getPlugin().getLog().info("Skipping name conflict checking for player {}", username);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The FloodgateApi does not support querying players by name, so this function
|
||||||
|
* iterates over every online FloodgatePlayer and checks if the requested
|
||||||
|
* username can be found
|
||||||
|
*
|
||||||
|
* @param username the name of the player
|
||||||
|
* @return FloodgatePlayer if found, null otherwise
|
||||||
|
*/
|
||||||
|
public FloodgatePlayer getFloodgatePlayer(String username) {
|
||||||
|
if (core.getPlugin().isPluginInstalled("floodgate")) {
|
||||||
|
for (FloodgatePlayer floodgatePlayer : FloodgateApi.getInstance().getPlayers()) {
|
||||||
|
if (floodgatePlayer.getUsername().equals(username)) {
|
||||||
|
return floodgatePlayer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -29,20 +29,25 @@ 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.FloodgateHook;
|
||||||
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;
|
||||||
|
|
||||||
|
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||||
|
|
||||||
import net.md_5.bungee.config.Configuration;
|
import net.md_5.bungee.config.Configuration;
|
||||||
|
|
||||||
public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
|
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 FloodgateHook<P, C, ?> floodgateHook;
|
||||||
|
|
||||||
public JoinManagement(FastLoginCore<P, C, ?> core, AuthPlugin<P> authHook) {
|
public JoinManagement(FastLoginCore<P, C, ?> core, AuthPlugin<P> authHook) {
|
||||||
this.core = core;
|
this.core = core;
|
||||||
this.authHook = authHook;
|
this.authHook = authHook;
|
||||||
|
this.floodgateHook = new FloodgateHook<>(core);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onLogin(String username, S source) {
|
public void onLogin(String username, S source) {
|
||||||
@ -52,6 +57,13 @@ public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//check if the player is connecting through Floodgate
|
||||||
|
FloodgatePlayer floodgatePlayer = floodgateHook.getFloodgatePlayer(username);
|
||||||
|
|
||||||
|
if (floodgatePlayer != null) {
|
||||||
|
floodgateHook.checkFloodgateNameConflict(username, source, floodgatePlayer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
callFastLoginPreLoginEvent(username, source, profile);
|
callFastLoginPreLoginEvent(username, source, profile);
|
||||||
|
|
||||||
Configuration config = core.getConfig();
|
Configuration config = core.getConfig();
|
||||||
|
@ -45,6 +45,8 @@ public interface PlatformPlugin<C> {
|
|||||||
|
|
||||||
AsyncScheduler getScheduler();
|
AsyncScheduler getScheduler();
|
||||||
|
|
||||||
|
boolean isPluginInstalled(String name);
|
||||||
|
|
||||||
default void sendMultiLineMessage(C receiver, String message) {
|
default void sendMultiLineMessage(C receiver, String message) {
|
||||||
for (String line : message.split("%nl%")) {
|
for (String line : message.split("%nl%")) {
|
||||||
sendMessage(receiver, line);
|
sendMessage(receiver, line);
|
||||||
|
Reference in New Issue
Block a user