diff --git a/core/src/main/java/org/geysermc/floodgate/command/UnlinkAccountCommand.java b/core/src/main/java/org/geysermc/floodgate/command/UnlinkAccountCommand.java index 3ba4682b0..35db38805 100644 --- a/core/src/main/java/org/geysermc/floodgate/command/UnlinkAccountCommand.java +++ b/core/src/main/java/org/geysermc/floodgate/command/UnlinkAccountCommand.java @@ -32,6 +32,7 @@ import lombok.NoArgsConstructor; import org.geysermc.floodgate.api.FloodgateApi; import org.geysermc.floodgate.api.link.PlayerLink; +import org.geysermc.floodgate.command.util.Permission; import org.geysermc.floodgate.config.FloodgateConfig; import org.geysermc.floodgate.link.GlobalPlayerLinking; import org.geysermc.floodgate.platform.command.FloodgateCommand; @@ -39,7 +40,6 @@ import org.geysermc.floodgate.player.UserAudience; import org.geysermc.floodgate.player.UserAudience.PlayerAudience; import org.geysermc.floodgate.util.Constants; -import org.geysermc.floodgate.command.util.Permission; import org.incendo.cloud.Command; import org.incendo.cloud.CommandManager; import org.incendo.cloud.context.CommandContext; diff --git a/core/src/main/java/org/geysermc/floodgate/command/WhitelistCommand.java b/core/src/main/java/org/geysermc/floodgate/command/WhitelistCommand.java index 54c5efcb6..cf63ba998 100644 --- a/core/src/main/java/org/geysermc/floodgate/command/WhitelistCommand.java +++ b/core/src/main/java/org/geysermc/floodgate/command/WhitelistCommand.java @@ -40,7 +40,6 @@ import org.geysermc.floodgate.platform.command.CommandUtil; import org.geysermc.floodgate.platform.command.FloodgateCommand; import org.geysermc.floodgate.platform.command.TranslatableMessage; -import org.geysermc.floodgate.platform.util.PlayerType; import org.geysermc.floodgate.player.UserAudience; import org.geysermc.floodgate.player.audience.PlayerAudienceArgument; import org.geysermc.floodgate.player.audience.ProfileAudience; diff --git a/core/src/main/java/org/geysermc/floodgate/link/GlobalPlayerLinking.java b/core/src/main/java/org/geysermc/floodgate/link/GlobalPlayerLinking.java index bc57c61b1..babff2347 100644 --- a/core/src/main/java/org/geysermc/floodgate/link/GlobalPlayerLinking.java +++ b/core/src/main/java/org/geysermc/floodgate/link/GlobalPlayerLinking.java @@ -32,6 +32,7 @@ import com.google.inject.Inject; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; import lombok.Getter; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.floodgate.api.link.LinkRequestResult; @@ -95,28 +96,39 @@ public CompletableFuture getLinkedPlayer(@NonNull UUID bedrockId) @NonNull private CompletableFuture getLinkedPlayer0(@NonNull UUID bedrockId) { + ExecutorService executor = getExecutorService(); + if (executor.isShutdown() || executor.isTerminated()) { + return CompletableFuture.completedFuture(null); + } + return CompletableFuture.supplyAsync( () -> { DefaultHttpResponse response = httpClient.get(GET_BEDROCK_LINK + bedrockId.getLeastSignificantBits()); + JsonObject data = response.getResponse(); + // either the global api is down or it failed to return link - if (!response.isCodeOk()) { - if (response.getResponse() != null) { + if (!response.isCodeOk() || data == null) { + if (data != null && data.has("message")) { getLogger().error( "Failed to request link for {}: {}", bedrockId.getLeastSignificantBits(), - response.getResponse().get("message").getAsString() + data.get("message").getAsString() + ); + } else { + getLogger().error( + "Failed to request link for {}: empty or invalid response (HTTP {})", + bedrockId.getLeastSignificantBits(), + response.getHttpCode() ); } return null; } - JsonObject data = response.getResponse(); - JsonElement javaName = data.get("java_name"); // javaName will be null when the player isn't linked - if (javaName == null) { + if (javaName == null || javaName.isJsonNull()) { return null; } @@ -125,7 +137,7 @@ private CompletableFuture getLinkedPlayer0(@NonNull UUID bedrockId UUID.fromString(data.get("java_id").getAsString()), Utils.getJavaUuid(data.get("bedrock_id").getAsLong())); }, - getExecutorService()); + executor); } @Override @@ -145,23 +157,39 @@ public CompletableFuture isLinkedPlayer(@NonNull UUID bedrockId) { @NonNull private CompletableFuture isLinkedPlayer0(@NonNull UUID bedrockId) { + ExecutorService executor = getExecutorService(); + if (executor.isShutdown() || executor.isTerminated()) { + return CompletableFuture.completedFuture(false); + } + return CompletableFuture.supplyAsync( () -> { DefaultHttpResponse response = httpClient.get(GET_BEDROCK_LINK + bedrockId.getLeastSignificantBits()); - if (!response.isCodeOk()) { - getLogger().error( - "Failed to request link for {}: {}", - bedrockId.getLeastSignificantBits(), - response.getResponse().get("message").getAsString()); + JsonObject data = response.getResponse(); + + if (!response.isCodeOk() || data == null) { + if (data != null && data.has("message")) { + getLogger().error( + "Failed to request link for {}: {}", + bedrockId.getLeastSignificantBits(), + data.get("message").getAsString() + ); + } else { + getLogger().error( + "Failed to request link for {}: empty or invalid response (HTTP {})", + bedrockId.getLeastSignificantBits(), + response.getHttpCode() + ); + } return false; } // no link if data is empty, otherwise the player is linked - return response.getResponse().entrySet().size() != 0; + return data.entrySet().size() != 0; }, - getExecutorService()); + executor); } // player linking and unlinking now goes through the global player linking server. diff --git a/core/src/main/java/org/geysermc/floodgate/util/HttpClient.java b/core/src/main/java/org/geysermc/floodgate/util/HttpClient.java index 960dc1b12..688a6a259 100644 --- a/core/src/main/java/org/geysermc/floodgate/util/HttpClient.java +++ b/core/src/main/java/org/geysermc/floodgate/util/HttpClient.java @@ -26,6 +26,7 @@ package org.geysermc.floodgate.util; import com.google.gson.Gson; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.inject.Inject; import com.google.inject.Singleton; @@ -135,12 +136,20 @@ private DefaultHttpResponse readDefaultResponse(HttpURLConnection connection) { return new DefaultHttpResponse(-1, null); } + int responseCode = -1; try { - int responseCode = connection.getResponseCode(); - JsonObject response = gson.fromJson(streamReader, JsonObject.class); + responseCode = connection.getResponseCode(); + + JsonElement element = gson.fromJson(streamReader, JsonElement.class); + + JsonObject response = null; + if (element != null && element.isJsonObject()) { + response = element.getAsJsonObject(); + } + return new DefaultHttpResponse(responseCode, response); - } catch (Exception exception) { - throw new RuntimeException("Failed to read response", exception); + } catch (Exception ignored) { + return new DefaultHttpResponse(responseCode, null); } finally { try { streamReader.close(); diff --git a/spigot/src/main/java/org/geysermc/floodgate/SpigotPlugin.java b/spigot/src/main/java/org/geysermc/floodgate/SpigotPlugin.java index a12c41a82..16a10dc66 100644 --- a/spigot/src/main/java/org/geysermc/floodgate/SpigotPlugin.java +++ b/spigot/src/main/java/org/geysermc/floodgate/SpigotPlugin.java @@ -27,7 +27,6 @@ import com.google.inject.Guice; import com.google.inject.Injector; -import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; import org.geysermc.floodgate.api.handshake.HandshakeHandlers; import org.geysermc.floodgate.api.logger.FloodgateLogger; diff --git a/spigot/src/main/java/org/geysermc/floodgate/util/SpigotCommandUtil.java b/spigot/src/main/java/org/geysermc/floodgate/util/SpigotCommandUtil.java index d6028abef..4cf0f1ed4 100644 --- a/spigot/src/main/java/org/geysermc/floodgate/util/SpigotCommandUtil.java +++ b/spigot/src/main/java/org/geysermc/floodgate/util/SpigotCommandUtil.java @@ -27,7 +27,6 @@ import java.util.Collection; import java.util.UUID; -import org.bukkit.OfflinePlayer; import org.bukkit.Server; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; diff --git a/spigot/src/main/java/org/geysermc/floodgate/util/SpigotVersionSpecificMethods.java b/spigot/src/main/java/org/geysermc/floodgate/util/SpigotVersionSpecificMethods.java index 65fa1ac16..f2e71c18c 100644 --- a/spigot/src/main/java/org/geysermc/floodgate/util/SpigotVersionSpecificMethods.java +++ b/spigot/src/main/java/org/geysermc/floodgate/util/SpigotVersionSpecificMethods.java @@ -35,6 +35,7 @@ import java.util.Map; import java.util.UUID; import java.util.concurrent.TimeUnit; +import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; import org.geysermc.floodgate.SpigotPlugin; @@ -120,7 +121,7 @@ public String getLocale(Player player) { } public void hideAndShowPlayer(Player on, Player target) { - // In Folia we don't have to schedule this as there is no concept of a single main thread. + // In Folia, we don't have to schedule this as there is no concept of a single main thread. // Instead, we have to schedule the task per player. if (ClassNames.IS_FOLIA) { on.getScheduler().execute(plugin, () -> hideAndShowPlayer0(on, target), null, 0); @@ -168,6 +169,9 @@ public void schedule(Runnable runnable, long delay) { @SuppressWarnings("deprecation") private void hideAndShowPlayer0(Player source, Player target) { + if (!Bukkit.isOwnedByCurrentRegion(source) || !Bukkit.isOwnedByCurrentRegion(target)) { + return; + } if (NEW_VISIBILITY) { source.hidePlayer(plugin, target); source.showPlayer(plugin, target); @@ -182,7 +186,7 @@ public void maybeSchedule(Runnable runnable) { } public void maybeSchedule(Runnable runnable, boolean globalContext) { - // In Folia we don't usually have to schedule this as there is no concept of a single main thread. + // In Folia, we don't usually have to schedule this as there is no concept of a single main thread. // Instead, we have to schedule the task per player. // However, in some cases we may want to access the global region for a global context. if (ClassNames.IS_FOLIA) { diff --git a/spigot/src/main/java/org/geysermc/floodgate/util/WhitelistUtils.java b/spigot/src/main/java/org/geysermc/floodgate/util/WhitelistUtils.java index 9ddedd285..0b32a5d66 100644 --- a/spigot/src/main/java/org/geysermc/floodgate/util/WhitelistUtils.java +++ b/spigot/src/main/java/org/geysermc/floodgate/util/WhitelistUtils.java @@ -29,7 +29,6 @@ import java.util.UUID; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; -import org.bukkit.Server; @SuppressWarnings("ConstantConditions") public final class WhitelistUtils {