Skip to content

Commit 6571d42

Browse files
committed
lookup links from bedrock players in the DB as opposed to letting floodgate handle that
1 parent 90ecbd2 commit 6571d42

File tree

5 files changed

+128
-60
lines changed

5 files changed

+128
-60
lines changed

src/main/java/org/geysermc/globallinkserver/GlobalLinkServer.java

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
import com.destroystokyo.paper.event.server.PaperServerListPingEvent;
1414
import com.mojang.brigadier.arguments.IntegerArgumentType;
1515
import io.papermc.paper.command.brigadier.Commands;
16-
import io.papermc.paper.command.brigadier.argument.ArgumentTypes;
1716
import io.papermc.paper.event.player.AsyncChatEvent;
1817
import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager;
1918
import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents;
@@ -48,9 +47,9 @@ public class GlobalLinkServer extends JavaPlugin implements Listener {
4847
public static List<String> permittedCommands;
4948
public static Plugin plugin;
5049

51-
public final static Component LINK_INSTRUCTIONS = Component.text("Run the ").color(NamedTextColor.AQUA)
50+
public final static Component LINK_INSTRUCTIONS = Component.text("You are not linked. To link, run the ").color(NamedTextColor.AQUA)
5251
.append(Component.text("`/link`", NamedTextColor.GREEN))
53-
.append(Component.text(" command to link your accounts.", NamedTextColor.AQUA));
52+
.append(Component.text(" command.", NamedTextColor.AQUA));
5453

5554
public final static Component UNLINK_INSTRUCTIONS = Component.text("You are currently linked. To unlink, use ").color(NamedTextColor.AQUA)
5655
.append(Component.text("`/unlink`", NamedTextColor.RED))
@@ -70,10 +69,12 @@ public void onEnable() {
7069
Bukkit.getScheduler().scheduleSyncRepeatingTask(this, linkManager::cleanupTempLinks, 0, 1);
7170
Bukkit.getScheduler().scheduleSyncRepeatingTask(this, () -> {
7271
Bukkit.getOnlinePlayers().forEach(player -> {
73-
if (Utils.isLinked(player)) {
74-
player.sendActionBar(UNLINK_INSTRUCTIONS);
75-
} else {
76-
player.sendActionBar(LINK_INSTRUCTIONS);
72+
if (Utils.shouldShowSuggestion(player)) {
73+
if (Utils.isLinked(player)) {
74+
player.sendActionBar(UNLINK_INSTRUCTIONS);
75+
} else {
76+
player.sendActionBar(LINK_INSTRUCTIONS);
77+
}
7778
}
7879
});
7980
}, 10, 15);
@@ -86,7 +87,7 @@ public void onEnable() {
8687
Commands.literal("link")
8788
.requires(ctx -> ctx.getSender() instanceof Player)
8889
.executes(commandUtils::startLink)
89-
.then(Commands.argument("code", IntegerArgumentType.integer())
90+
.then(Commands.argument("code", IntegerArgumentType.integer(1, 9999))
9091
.executes(commandUtils::linkWithCode)
9192
)
9293
.build(),
@@ -184,11 +185,19 @@ public void preCommand(PlayerCommandPreprocessEvent event) {
184185

185186
if (command.equalsIgnoreCase("help")) {
186187
event.setCancelled(true);
188+
189+
if (!Utils.shouldShowSuggestion(player)) {
190+
player.sendMessage(Component.text("Your linking information is currently unavailable. Please wait!")
191+
.color(NamedTextColor.RED));
192+
return;
193+
}
194+
187195
if (Utils.isLinked(player)) {
188196
player.sendMessage(UNLINK_INSTRUCTIONS);
189197
} else {
190198
player.sendMessage(LINK_INSTRUCTIONS);
191199
}
200+
return;
192201
}
193202

194203
if (!permittedCommands.contains(command)) {

src/main/java/org/geysermc/globallinkserver/link/Link.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ public class Link {
1818
public Link() {
1919
}
2020

21-
public Link(Player javaPlayer) {
22-
this.javaId = javaPlayer.getUniqueId();
23-
this.javaUsername = javaPlayer.getName();
21+
public static Link createFromJavaPlayer(Player javaPlayer) {
22+
return new Link()
23+
.javaId(javaPlayer.getUniqueId())
24+
.javaUsername(javaPlayer.getName());
2425
}
2526

2627
public UUID bedrockId() {
@@ -58,4 +59,8 @@ public Link bedrockUsername(String bedrockUsername) {
5859
this.bedrockUsername = bedrockUsername;
5960
return this;
6061
}
62+
63+
public UUID getOpposed(Player player) {
64+
return player.getUniqueId().equals(bedrockId) ? javaId : bedrockId;
65+
}
6166
}

src/main/java/org/geysermc/globallinkserver/link/LinkManager.java

Lines changed: 59 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ public CompletableFuture<Boolean> unlinkAccount(Player player) {
123123
try (Connection connection = dataSource.getConnection()) {
124124

125125
PreparedStatement query;
126-
if (Utils.isBedrockPlayerId(player)) { // Should never happen
126+
if (Utils.isBedrockPlayerId(player)) {
127127
query = connection.prepareStatement("DELETE FROM `links` WHERE `bedrock_id` = ?;");
128128
query.setLong(1, player.getUniqueId().getLeastSignificantBits());
129129
} else {
@@ -141,34 +141,68 @@ public CompletableFuture<Boolean> unlinkAccount(Player player) {
141141
}
142142

143143
public CompletableFuture<Optional<Link>> attemptFindJavaLink(Player player) {
144-
return CompletableFuture.supplyAsync(
145-
() -> {
146-
try (Connection connection = dataSource.getConnection()) {
147-
try (PreparedStatement query = connection.prepareStatement(
148-
"SELECT `bedrock_id` FROM `links` WHERE `java_id` = ?")) {
149-
query.setString(1, player.getUniqueId().toString());
144+
return attemptFindLink(
145+
"SELECT `bedrock_id` FROM `links` WHERE `java_id` = ?",
146+
stmt -> stmt.setString(1, player.getUniqueId().toString()),
147+
resultSet -> {
148+
long bedrockId = resultSet.getLong("bedrock_id");
149+
String bedrockTag = FloodgateApi.getInstance().getGamertagFor(bedrockId).join();
150+
return Optional.of(Link.createFromJavaPlayer(player)
151+
.bedrockId(new UUID(0, bedrockId))
152+
.bedrockUsername(bedrockTag));
153+
}
154+
);
155+
}
150156

151-
try (ResultSet resultSet = query.executeQuery()) {
152-
if (resultSet.next()) {
153-
long bedrockId = resultSet.getLong("bedrock_id");
154-
String bedrockTag = FloodgateApi.getInstance().getGamertagFor(bedrockId).join();
155-
return Optional.of(
156-
new Link(player)
157-
.bedrockId(new UUID(0, bedrockId))
158-
.bedrockUsername(bedrockTag)
159-
);
160-
} else {
161-
return Optional.empty(); // No match found
162-
}
163-
}
164-
}
165-
} catch (SQLException exception) {
166-
throw new CompletionException("Error while finding Java link", exception);
157+
public CompletableFuture<Optional<Link>> attemptFindBedrockLink(Player player, String bedrockTag) {
158+
return attemptFindLink(
159+
"SELECT `java_id`, `java_name` FROM `links` WHERE `bedrock_id` = ?",
160+
stmt -> stmt.setLong(1, player.getUniqueId().getLeastSignificantBits()),
161+
resultSet -> {
162+
UUID javaId = UUID.fromString(resultSet.getString("java_id"));
163+
String javaName = resultSet.getString("java_name");
164+
return Optional.of(new Link()
165+
.bedrockId(player.getUniqueId())
166+
.bedrockUsername(bedrockTag)
167+
.javaId(javaId)
168+
.javaUsername(javaName));
169+
}
170+
);
171+
}
172+
173+
private CompletableFuture<Optional<Link>> attemptFindLink(
174+
String query,
175+
ThrowingConsumer<PreparedStatement> parameterSetter,
176+
ThrowingFunction<ResultSet, Optional<Link>> resultProcessor
177+
) {
178+
return CompletableFuture.supplyAsync(() -> {
179+
try (Connection connection = dataSource.getConnection();
180+
PreparedStatement queryStmt = connection.prepareStatement(query)) {
181+
parameterSetter.accept(queryStmt);
182+
183+
try (ResultSet resultSet = queryStmt.executeQuery()) {
184+
if (resultSet.next()) {
185+
return resultProcessor.apply(resultSet);
186+
} else {
187+
return Optional.empty();
167188
}
168-
},
169-
executorService);
189+
}
190+
191+
} catch (SQLException exception) {
192+
throw new CompletionException("Error while finding link! ", exception);
193+
}
194+
}, executorService);
170195
}
171196

197+
@FunctionalInterface
198+
interface ThrowingConsumer<T> {
199+
void accept(T t) throws SQLException;
200+
}
201+
202+
@FunctionalInterface
203+
interface ThrowingFunction<T, R> {
204+
R apply(T t) throws SQLException;
205+
}
172206

173207
public void cleanupTempLinks() {
174208
IntSet removedLinks = new IntArraySet();

src/main/java/org/geysermc/globallinkserver/util/CommandUtils.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.bukkit.Bukkit;
1414
import org.bukkit.entity.Player;
1515
import org.geysermc.globallinkserver.GlobalLinkServer;
16+
import org.geysermc.globallinkserver.link.Link;
1617
import org.geysermc.globallinkserver.link.LinkManager;
1718
import org.geysermc.globallinkserver.link.TempLink;
1819

@@ -111,15 +112,15 @@ public int linkWithCode(CommandContext<CommandSourceStack> ctx) {
111112
public int unlink(CommandContext<CommandSourceStack> ctx) {
112113
Player player = getPlayer(ctx);
113114

114-
if (!Utils.isLinked(player)) {
115+
Link currentLink = Utils.getLink(player);
116+
if (currentLink == null) {
115117
player.sendMessage(Component.text("You are not currently linked!").color(NamedTextColor.RED));
116118
return 0;
117119
}
118120

119121
linkManager.unlinkAccount(player).whenComplete((result, error) -> {
120122
if (error != null) {
121123
error.printStackTrace();
122-
System.out.println(result);
123124
player.sendMessage(Component.text("An unknown error occurred while unlinking your account. Try it again later!")
124125
.color(NamedTextColor.RED));
125126
return;
@@ -128,7 +129,14 @@ public int unlink(CommandContext<CommandSourceStack> ctx) {
128129
Bukkit.getScheduler().callSyncMethod(GlobalLinkServer.plugin, () -> {
129130
if (result) {
130131
player.kick(Component.text("You are successfully unlinked.").color(NamedTextColor.GREEN));
132+
133+
// Lookup whether the player's link is online, kick em too
134+
Player otherLink = Bukkit.getServer().getPlayer(currentLink.getOpposed(player));
135+
if (otherLink != null) {
136+
otherLink.kick(Component.text("You are successfully unlinked.").color(NamedTextColor.GREEN));
137+
}
131138
} else {
139+
// Technically impossible
132140
player.kick(Component.text("You are not linked to any account!").color(NamedTextColor.RED));
133141
}
134142

src/main/java/org/geysermc/globallinkserver/util/Utils.java

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,34 +8,42 @@
88
import com.mojang.brigadier.context.CommandContext;
99
import io.papermc.paper.command.brigadier.CommandSourceStack;
1010
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
11+
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
1112
import net.kyori.adventure.text.Component;
1213
import net.kyori.adventure.text.format.NamedTextColor;
1314
import org.bukkit.attribute.Attribute;
1415
import org.bukkit.entity.Player;
1516
import org.bukkit.event.player.PlayerTeleportEvent;
16-
import org.checkerframework.checker.nullness.qual.Nullable;
1717
import org.geysermc.floodgate.api.FloodgateApi;
1818
import org.geysermc.floodgate.api.player.FloodgatePlayer;
1919
import org.geysermc.globallinkserver.GlobalLinkServer;
2020
import org.geysermc.globallinkserver.link.Link;
2121

2222
import java.util.Map;
23+
import java.util.Optional;
24+
import java.util.Set;
2325
import java.util.UUID;
26+
import java.util.concurrent.CompletableFuture;
2427

2528
@SuppressWarnings("UnstableApiUsage")
2629
public class Utils {
2730

2831
private static final Map<UUID, Link> linkedPlayers = new Object2ObjectOpenHashMap<>();
32+
private static final Set<UUID> lookupInProcess = new ObjectOpenHashSet<>();
33+
34+
public static boolean shouldShowSuggestion(Player player) {
35+
return !lookupInProcess.contains(player.getUniqueId());
36+
}
2937

3038
public static boolean isBedrockPlayerId(Player player) {
31-
return FloodgateApi.getInstance().isFloodgateId(player.getUniqueId());
39+
return player.getUniqueId().version() == 0;
3240
}
3341

3442
public static boolean isLinked(Player player) {
3543
return linkedPlayers.containsKey(player.getUniqueId());
3644
}
3745

38-
public static @Nullable Link getLink(Player player) {
46+
public static Link getLink(Player player) {
3947
return linkedPlayers.get(player.getUniqueId());
4048
}
4149

@@ -44,32 +52,36 @@ public static Player getPlayer(CommandContext<CommandSourceStack> ctx) {
4452
}
4553

4654
public static void processJoin(Player player) {
55+
lookupInProcess.add(player.getUniqueId());
56+
4757
FloodgatePlayer floodgatePlayer = FloodgateApi.getInstance().getPlayer(player.getUniqueId());
48-
if (floodgatePlayer == null) {
49-
// Not dealing with a Bedrock player - now check if this Java player has a link
50-
GlobalLinkServer.linkManager.attemptFindJavaLink(player).whenComplete((link, throwable) -> {
51-
if (throwable != null) {
52-
player.sendMessage(Component.text("Failed to find Java link.").color(NamedTextColor.RED));
53-
throwable.printStackTrace();
54-
return;
55-
}
56-
57-
link.ifPresent(value -> linkedPlayers.put(player.getUniqueId(), value));
58-
});
58+
CompletableFuture<Optional<Link>> linkFuture;
59+
60+
if (floodgatePlayer != null) {
61+
// Dealing with a Bedrock player
62+
linkFuture = GlobalLinkServer.linkManager.attemptFindBedrockLink(player, floodgatePlayer.getUsername());
5963
} else {
60-
// easy
61-
if (floodgatePlayer.isLinked()) {
62-
linkedPlayers.put(player.getUniqueId(), new Link()
63-
.javaUsername(player.getName())
64-
.javaId(player.getUniqueId())
65-
.bedrockUsername(floodgatePlayer.getUsername())
66-
.bedrockId(floodgatePlayer.getJavaUniqueId()));
67-
}
64+
linkFuture = GlobalLinkServer.linkManager.attemptFindJavaLink(player);
65+
}
66+
67+
// Handle the result of the lookup
68+
linkFuture.whenComplete((link, throwable) -> handleLinkLookupResult(player, link, throwable));
69+
}
70+
71+
private static void handleLinkLookupResult(Player player, Optional<Link> link, Throwable throwable) {
72+
lookupInProcess.remove(player.getUniqueId());
73+
if (throwable != null) {
74+
player.sendMessage(Component.text("Failed to find current link!").color(NamedTextColor.RED));
75+
throwable.printStackTrace();
76+
return;
6877
}
78+
79+
link.ifPresent(value -> linkedPlayers.put(player.getUniqueId(), value));
6980
}
7081

7182
public static void processLeave(Player player) {
7283
linkedPlayers.remove(player.getUniqueId());
84+
lookupInProcess.remove(player.getUniqueId());
7385
}
7486

7587
public static void sendCurrentLinkInfo(Player player) {

0 commit comments

Comments
 (0)