Skip to content

Commit 4cf6605

Browse files
author
games647
authored
Merge pull request #532 from Smart123s/fg-bk-ncshare
Share Floodgate name conflict check between Protocol Plugins
2 parents edb4179 + 411148b commit 4cf6605

File tree

9 files changed

+150
-39
lines changed

9 files changed

+150
-39
lines changed

bukkit/src/main/java/com/github/games647/fastlogin/bukkit/FastLoginBukkit.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ private boolean isValidFloodgateConfigString(String key) {
276276
* @param name the name of the plugin
277277
* @return true if the plugin is installed
278278
*/
279-
private boolean isPluginInstalled(String name) {
279+
public boolean isPluginInstalled(String name) {
280280
//the plugin may be enabled after FastLogin, so isPluginEnabled()
281281
//won't work here
282282
return Bukkit.getServer().getPluginManager().getPlugin(name) != null;

bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocollib/NameCheckTask.java

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,8 @@
3737
import java.security.PublicKey;
3838
import java.util.Random;
3939

40-
import org.bukkit.Bukkit;
4140
import org.bukkit.command.CommandSender;
4241
import org.bukkit.entity.Player;
43-
import org.geysermc.floodgate.api.FloodgateApi;
44-
import org.geysermc.floodgate.api.player.FloodgatePlayer;
4542

4643
public class NameCheckTask extends JoinManagement<Player, CommandSender, ProtocolLibLoginSource>
4744
implements Runnable {
@@ -55,6 +52,7 @@ public class NameCheckTask extends JoinManagement<Player, CommandSender, Protoco
5552
private final Player player;
5653
private final String username;
5754

55+
5856
public NameCheckTask(FastLoginBukkit plugin, PacketEvent packetEvent, Random random,
5957
Player player, String username, PublicKey publicKey) {
6058
super(plugin.getCore(), plugin.getCore().getAuthPluginHook());
@@ -70,12 +68,6 @@ public NameCheckTask(FastLoginBukkit plugin, PacketEvent packetEvent, Random ran
7068
@Override
7169
public void run() {
7270
try {
73-
// check if the player is connecting through Geyser
74-
if (!plugin.getCore().getConfig().get("allowFloodgateNameConflict").toString().equalsIgnoreCase("false")
75-
&& getFloodgatePlayer(username) != null) {
76-
plugin.getLog().info("Skipping name conflict checking for player {}", username);
77-
return;
78-
}
7971
super.onLogin(username, new ProtocolLibLoginSource(packetEvent, player, random, publicKey));
8072
} finally {
8173
ProtocolLibrary.getProtocolManager().getAsynchronousManager().signalPacketTransmission(packetEvent);
@@ -119,16 +111,4 @@ public void startCrackedSession(ProtocolLibLoginSource source, StoredProfile pro
119111
BukkitLoginSession loginSession = new BukkitLoginSession(username, profile);
120112
plugin.putSession(player.getAddress(), loginSession);
121113
}
122-
123-
private static FloodgatePlayer getFloodgatePlayer(String username) {
124-
if (Bukkit.getServer().getPluginManager().isPluginEnabled("floodgate")) {
125-
// the Floodgate API requires UUID, which is inaccessible at NameCheckTask.java
126-
for (FloodgatePlayer floodgatePlayer : FloodgateApi.getInstance().getPlayers()) {
127-
if (floodgatePlayer.getUsername().equals(username)) {
128-
return floodgatePlayer;
129-
}
130-
}
131-
}
132-
return null;
133-
}
134114
}

bukkit/src/main/java/com/github/games647/fastlogin/bukkit/listener/protocolsupport/ProtocolSupportListener.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import org.bukkit.entity.Player;
4242
import org.bukkit.event.EventHandler;
4343
import org.bukkit.event.Listener;
44+
4445
import protocolsupport.api.events.ConnectionCloseEvent;
4546
import protocolsupport.api.events.PlayerLoginStartEvent;
4647
import protocolsupport.api.events.PlayerProfileCompleteEvent;
@@ -75,7 +76,8 @@ public void onLoginStart(PlayerLoginStartEvent loginStartEvent) {
7576
//remove old data every time on a new login in order to keep the session only for one person
7677
plugin.removeSession(address);
7778

78-
super.onLogin(username, new ProtocolLoginSource(loginStartEvent));
79+
ProtocolLoginSource source = new ProtocolLoginSource(loginStartEvent);
80+
super.onLogin(username, source);
7981
}
8082

8183
@EventHandler

bukkit/src/main/java/com/github/games647/fastlogin/bukkit/task/FloodgateAuthTask.java

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -51,25 +51,10 @@ public void run() {
5151
plugin.getLog().info(
5252
"Player {} is connecting through Geyser Floodgate.",
5353
player.getName());
54-
String allowNameConflict = plugin.getCore().getConfig().get("allowFloodgateNameConflict").toString().toLowerCase();
54+
5555
// check if the Bedrock player is linked to a Java account
5656
boolean isLinked = floodgatePlayer.getLinkedPlayer() != null;
57-
if (allowNameConflict.equals("linked") && !isLinked) {
58-
plugin.getLog().info(
59-
"Bedrock Player {}'s name conflits an existing Java Premium Player's name",
60-
player.getName());
61-
62-
// kicking must be synchronous
63-
// https://www.spigotmc.org/threads/asynchronous-player-kick-problem.168580/
64-
Bukkit.getScheduler().runTask(plugin, new Runnable() {
65-
public void run() {
66-
player.kickPlayer("This name is allready in use by a Premium Java Player");
67-
}
68-
});
69-
return;
7057

71-
}
72-
7358
AuthPlugin<Player> authPlugin = plugin.getCore().getAuthPluginHook();
7459

7560
String autoLoginFloodgate = plugin.getCore().getConfig().get("autoLoginFloodgate").toString().toLowerCase();

bungee/src/main/java/com/github/games647/fastlogin/bungee/FastLoginBungee.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
import java.util.concurrent.ConcurrentMap;
5151
import java.util.concurrent.ThreadFactory;
5252

53+
import net.md_5.bungee.BungeeServerInfo;
5354
import net.md_5.bungee.api.CommandSender;
5455
import net.md_5.bungee.api.chat.TextComponent;
5556
import net.md_5.bungee.api.connection.PendingConnection;
@@ -187,4 +188,9 @@ public ThreadFactory getThreadFactory() {
187188
public AsyncScheduler getScheduler() {
188189
return scheduler;
189190
}
191+
192+
@Override
193+
public boolean isPluginInstalled(String name) {
194+
return getProxy().getPluginManager().getPlugin(name) != null;
195+
}
190196
}

core/pom.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@
5353
<id>codemc-repo</id>
5454
<url>https://repo.codemc.io/repository/maven-public/</url>
5555
</repository>
56+
<!-- Floodgate -->
57+
<repository>
58+
<id>nukkitx-snapshot</id>
59+
<url>https://repo.nukkitx.com/maven-snapshots/</url>
60+
</repository>
5661
</repositories>
5762

5863
<dependencies>
@@ -85,6 +90,14 @@
8590
</exclusions>
8691
</dependency>
8792

93+
<!--Floodgate for Xbox Live Authentication-->
94+
<dependency>
95+
<groupId>org.geysermc.floodgate</groupId>
96+
<artifactId>api</artifactId>
97+
<version>2.0-SNAPSHOT</version>
98+
<scope>provided</scope>
99+
</dependency>
100+
88101
<!--Common component for contacting the Mojang API-->
89102
<dependency>
90103
<groupId>com.github.games647</groupId>
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
* SPDX-License-Identifier: MIT
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2015-2021 <Your name and contributors>
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in all
16+
* copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24+
* SOFTWARE.
25+
*/
26+
package com.github.games647.fastlogin.core.hooks;
27+
28+
import java.io.IOException;
29+
import java.util.Optional;
30+
31+
import com.github.games647.craftapi.model.Profile;
32+
import com.github.games647.craftapi.resolver.RateLimitException;
33+
import com.github.games647.fastlogin.core.shared.FastLoginCore;
34+
import com.github.games647.fastlogin.core.shared.LoginSource;
35+
36+
import org.geysermc.floodgate.api.FloodgateApi;
37+
import org.geysermc.floodgate.api.player.FloodgatePlayer;
38+
39+
public class FloodgateHook<P extends C, C, S extends LoginSource> {
40+
41+
private final FastLoginCore<P, C, ?> core;
42+
43+
public FloodgateHook(FastLoginCore<P, C, ?> core) {
44+
this.core = core;
45+
}
46+
47+
/**
48+
* Check if the player's name conflicts an existing Java player's name, and
49+
* kick them if it does
50+
*
51+
* @param username the name of the player
52+
* @param source an instance of LoginSource
53+
*/
54+
public void checkFloodgateNameConflict(String username, LoginSource source, FloodgatePlayer floodgatePlayer) {
55+
String allowConflict = core.getConfig().get("allowFloodgateNameConflict").toString().toLowerCase();
56+
57+
// check if the Bedrock player is linked to a Java account
58+
boolean isLinked = ((FloodgatePlayer) floodgatePlayer).getLinkedPlayer() != null;
59+
60+
if (allowConflict.equals("false")
61+
|| allowConflict.equals("linked") && !isLinked) {
62+
63+
// check for conflicting Premium Java name
64+
Optional<Profile> premiumUUID = Optional.empty();
65+
try {
66+
premiumUUID = core.getResolver().findProfile(username);
67+
} catch (IOException | RateLimitException e) {
68+
core.getPlugin().getLog().error(
69+
"Could not check wether Floodgate Player {}'s name conflicts a premium Java player's name.",
70+
username);
71+
try {
72+
source.kick("Could not check if your name conflicts an existing Java Premium Player's name");
73+
} catch (Exception e1) {
74+
core.getPlugin().getLog().error("Could not kick Player {}", username);
75+
}
76+
}
77+
78+
if (premiumUUID.isPresent()) {
79+
core.getPlugin().getLog().info("Bedrock Player {}'s name conflicts an existing Java Premium Player's name",
80+
username);
81+
try {
82+
source.kick("Your name conflicts an existing Java Premium Player's name");
83+
} catch (Exception e) {
84+
core.getPlugin().getLog().error("Could not kick Player {}", username);
85+
}
86+
}
87+
} else {
88+
core.getPlugin().getLog().info("Skipping name conflict checking for player {}", username);
89+
}
90+
}
91+
92+
/**
93+
* The FloodgateApi does not support querying players by name, so this function
94+
* iterates over every online FloodgatePlayer and checks if the requested
95+
* username can be found
96+
*
97+
* @param username the name of the player
98+
* @return FloodgatePlayer if found, null otherwise
99+
*/
100+
public FloodgatePlayer getFloodgatePlayer(String username) {
101+
if (core.getPlugin().isPluginInstalled("floodgate")) {
102+
for (FloodgatePlayer floodgatePlayer : FloodgateApi.getInstance().getPlayers()) {
103+
if (floodgatePlayer.getUsername().equals(username)) {
104+
return floodgatePlayer;
105+
}
106+
}
107+
}
108+
return null;
109+
}
110+
111+
}

core/src/main/java/com/github/games647/fastlogin/core/shared/JoinManagement.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,25 @@
2929
import com.github.games647.craftapi.resolver.RateLimitException;
3030
import com.github.games647.fastlogin.core.StoredProfile;
3131
import com.github.games647.fastlogin.core.hooks.AuthPlugin;
32+
import com.github.games647.fastlogin.core.hooks.FloodgateHook;
3233
import com.github.games647.fastlogin.core.shared.event.FastLoginPreLoginEvent;
3334

3435
import java.util.Optional;
3536

37+
import org.geysermc.floodgate.api.player.FloodgatePlayer;
38+
3639
import net.md_5.bungee.config.Configuration;
3740

3841
public abstract class JoinManagement<P extends C, C, S extends LoginSource> {
3942

4043
protected final FastLoginCore<P, C, ?> core;
4144
protected final AuthPlugin<P> authHook;
45+
private final FloodgateHook<P, C, ?> floodgateHook;
4246

4347
public JoinManagement(FastLoginCore<P, C, ?> core, AuthPlugin<P> authHook) {
4448
this.core = core;
4549
this.authHook = authHook;
50+
this.floodgateHook = new FloodgateHook<>(core);
4651
}
4752

4853
public void onLogin(String username, S source) {
@@ -52,6 +57,13 @@ public void onLogin(String username, S source) {
5257
return;
5358
}
5459

60+
//check if the player is connecting through Floodgate
61+
FloodgatePlayer floodgatePlayer = floodgateHook.getFloodgatePlayer(username);
62+
63+
if (floodgatePlayer != null) {
64+
floodgateHook.checkFloodgateNameConflict(username, source, floodgatePlayer);
65+
return;
66+
}
5567
callFastLoginPreLoginEvent(username, source, profile);
5668

5769
Configuration config = core.getConfig();

core/src/main/java/com/github/games647/fastlogin/core/shared/PlatformPlugin.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ public interface PlatformPlugin<C> {
4545

4646
AsyncScheduler getScheduler();
4747

48+
boolean isPluginInstalled(String name);
49+
4850
default void sendMultiLineMessage(C receiver, String message) {
4951
for (String line : message.split("%nl%")) {
5052
sendMessage(receiver, line);

0 commit comments

Comments
 (0)