From 5e446551895b3b1ece1e615f8bbe2e60f9960498 Mon Sep 17 00:00:00 2001 From: phinner <62483793+Phinner@users.noreply.github.com> Date: Tue, 27 Feb 2024 15:16:23 +0100 Subject: [PATCH] fix: Some more changes perhaps --- .../cloud/parser/PlayerInfoParser.java | 50 ++++++++ .../command/cloud/parser/PlayerParser.java | 118 ++++++++++++++++++ .../distributor/core/Distributor.java | 7 +- .../DistributorInitializationException.java | 29 +++++ .../distributor/core/DistributorProvider.java | 72 +++++++++++ .../core/player/SimplePlayerLookup.java | 27 ++-- gradle/libs.versions.toml | 2 +- 7 files changed, 292 insertions(+), 13 deletions(-) create mode 100644 distributor-command-cloud/src/main/java/com/xpdustry/distributor/command/cloud/parser/PlayerInfoParser.java create mode 100644 distributor-command-cloud/src/main/java/com/xpdustry/distributor/command/cloud/parser/PlayerParser.java create mode 100644 distributor-common/src/main/java/com/xpdustry/distributor/core/DistributorInitializationException.java create mode 100644 distributor-common/src/main/java/com/xpdustry/distributor/core/DistributorProvider.java diff --git a/distributor-command-cloud/src/main/java/com/xpdustry/distributor/command/cloud/parser/PlayerInfoParser.java b/distributor-command-cloud/src/main/java/com/xpdustry/distributor/command/cloud/parser/PlayerInfoParser.java new file mode 100644 index 00000000..5c857d02 --- /dev/null +++ b/distributor-command-cloud/src/main/java/com/xpdustry/distributor/command/cloud/parser/PlayerInfoParser.java @@ -0,0 +1,50 @@ +/* + * Distributor, a feature-rich framework for Mindustry plugins. + * + * Copyright (C) 2024 Xpdustry + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.xpdustry.distributor.command.cloud.parser; + +import com.xpdustry.distributor.core.DistributorProvider; +import com.xpdustry.distributor.core.player.PlayerLookup; +import java.util.concurrent.CompletableFuture; +import mindustry.net.Administration; +import org.incendo.cloud.context.CommandContext; +import org.incendo.cloud.context.CommandInput; +import org.incendo.cloud.parser.ArgumentParseResult; +import org.incendo.cloud.parser.ArgumentParser; + +public final class PlayerInfoParser implements ArgumentParser.FutureArgumentParser { + + @Override + public CompletableFuture> parseFuture( + final CommandContext ctx, final CommandInput input) { + final var query = input.readString(); + return DistributorProvider.get() + .getService(PlayerLookup.class) + .orElseThrow() + .findOfflinePlayers(query, true) + .thenApply(result -> { + if (result.isEmpty()) { + return ArgumentParseResult.failure(new PlayerParser.PlayerNotFoundException(query, ctx)); + } else if (result.size() > 1) { + return ArgumentParseResult.failure(new PlayerParser.TooManyPlayersFoundException(query, ctx)); + } else { + return ArgumentParseResult.success(result.get(0)); + } + }); + } +} diff --git a/distributor-command-cloud/src/main/java/com/xpdustry/distributor/command/cloud/parser/PlayerParser.java b/distributor-command-cloud/src/main/java/com/xpdustry/distributor/command/cloud/parser/PlayerParser.java new file mode 100644 index 00000000..2600fc73 --- /dev/null +++ b/distributor-command-cloud/src/main/java/com/xpdustry/distributor/command/cloud/parser/PlayerParser.java @@ -0,0 +1,118 @@ +/* + * Distributor, a feature-rich framework for Mindustry plugins. + * + * Copyright (C) 2024 Xpdustry + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.xpdustry.distributor.command.cloud.parser; + +import arc.Core; +import com.xpdustry.distributor.command.cloud.ArcCaptionKeys; +import com.xpdustry.distributor.core.DistributorProvider; +import com.xpdustry.distributor.core.player.PlayerLookup; +import java.util.concurrent.CompletableFuture; +import mindustry.gen.Player; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.incendo.cloud.caption.Caption; +import org.incendo.cloud.caption.CaptionVariable; +import org.incendo.cloud.context.CommandContext; +import org.incendo.cloud.context.CommandInput; +import org.incendo.cloud.exception.parsing.ParserException; +import org.incendo.cloud.parser.ArgumentParseResult; +import org.incendo.cloud.parser.ArgumentParser; + +public final class PlayerParser implements ArgumentParser { + + @Override + public ArgumentParseResult parse(final CommandContext ctx, final CommandInput input) { + final var query = input.readString(); + final var result = DistributorProvider.get() + .getService(PlayerLookup.class) + .orElseThrow() + .findOnlinePlayers(query, true); + if (result.isEmpty()) { + return ArgumentParseResult.failure(new PlayerNotFoundException(query, ctx)); + } else if (result.size() > 1) { + return ArgumentParseResult.failure(new TooManyPlayersFoundException(query, ctx)); + } else { + return ArgumentParseResult.success(result.get(0)); + } + } + + @Override + public @NonNull CompletableFuture<@NonNull ArgumentParseResult> parseFuture( + final CommandContext ctx, final CommandInput input) { + return CompletableFuture.supplyAsync(() -> this.parse(ctx, input), Core.app::post); + } + + /** + * An exception thrown when a parsing error occurs while searching for a player. + */ + public static sealed class PlayerParseException extends ParserException { + + private final String input; + + /** + * Creates a new {@link PlayerParseException}. + * + * @param input the input string + * @param ctx the command context + * @param caption the error caption of this exception + */ + public PlayerParseException(final String input, final CommandContext ctx, final Caption caption) { + super(PlayerParser.class, ctx, caption, CaptionVariable.of("input", input)); + this.input = input; + } + + /** + * Returns the input string. + */ + public final String getInput() { + return this.input; + } + } + + /** + * An exception thrown when too many players are found for the given input. + */ + public static final class TooManyPlayersFoundException extends PlayerParseException { + + /** + * Creates a new {@link TooManyPlayersFoundException}. + * + * @param input the input string + * @param ctx the command context + */ + public TooManyPlayersFoundException(final String input, final CommandContext ctx) { + super(input, ctx, ArcCaptionKeys.ARGUMENT_PARSE_FAILURE_PLAYER_TOO_MANY); + } + } + + /** + * An exception thrown when no player was found for the given input. + */ + public static final class PlayerNotFoundException extends PlayerParseException { + + /** + * Creates a new {@link PlayerNotFoundException}. + * + * @param input the input string + * @param ctx the command context + */ + public PlayerNotFoundException(final String input, final CommandContext ctx) { + super(input, ctx, ArcCaptionKeys.ARGUMENT_PARSE_FAILURE_PLAYER_NOT_FOUND); + } + } +} diff --git a/distributor-common/src/main/java/com/xpdustry/distributor/core/Distributor.java b/distributor-common/src/main/java/com/xpdustry/distributor/core/Distributor.java index 6d8bd2ab..04c13c29 100644 --- a/distributor-common/src/main/java/com/xpdustry/distributor/core/Distributor.java +++ b/distributor-common/src/main/java/com/xpdustry/distributor/core/Distributor.java @@ -18,4 +18,9 @@ */ package com.xpdustry.distributor.core; -public interface Distributor {} +import java.util.Optional; + +public interface Distributor { + + Optional getService(final Class clazz); +} diff --git a/distributor-common/src/main/java/com/xpdustry/distributor/core/DistributorInitializationException.java b/distributor-common/src/main/java/com/xpdustry/distributor/core/DistributorInitializationException.java new file mode 100644 index 00000000..175efe13 --- /dev/null +++ b/distributor-common/src/main/java/com/xpdustry/distributor/core/DistributorInitializationException.java @@ -0,0 +1,29 @@ +/* + * Distributor, a feature-rich framework for Mindustry plugins. + * + * Copyright (C) 2024 Xpdustry + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.xpdustry.distributor.core; + +/** + * This exception is thrown when the distributor fails to initialize. + */ +public final class DistributorInitializationException extends RuntimeException { + + DistributorInitializationException(final String message) { + super(message); + } +} diff --git a/distributor-common/src/main/java/com/xpdustry/distributor/core/DistributorProvider.java b/distributor-common/src/main/java/com/xpdustry/distributor/core/DistributorProvider.java new file mode 100644 index 00000000..6dcc51e8 --- /dev/null +++ b/distributor-common/src/main/java/com/xpdustry/distributor/core/DistributorProvider.java @@ -0,0 +1,72 @@ +/* + * Distributor, a feature-rich framework for Mindustry plugins. + * + * Copyright (C) 2024 Xpdustry + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.xpdustry.distributor.core; + +import org.jspecify.annotations.Nullable; + +/** + * A holder for the global {@link Distributor} instance. + */ +public final class DistributorProvider { + + private static @Nullable Distributor instance = null; + + private DistributorProvider() {} + + /** + * Returns the global {@link Distributor} instance. + * @throws DistributorInitializationException if the API hasn't been initialized yet + */ + public static Distributor get() { + if (DistributorProvider.instance == null) { + throw new DistributorInitializationException("The API hasn't been initialized yet."); + } + return DistributorProvider.instance; + } + + /** + * Sets the global {@link Distributor} instance. + * @throws DistributorInitializationException if the API has already been initialized + */ + public static void set(final Distributor distributor) { + if (DistributorProvider.instance != null) { + throw new DistributorInitializationException("The API has already been initialized."); + } + DistributorProvider.instance = distributor; + } + + /** + * Clears the global {@link Distributor} instance. + * @throws DistributorInitializationException if the API hasn't been initialized yet + */ + public static void clear() { + if (DistributorProvider.instance != null) { + DistributorProvider.instance = null; + } else { + throw new DistributorInitializationException("The API hasn't been initialized yet."); + } + } + + /** + * Returns whether the API has been initialized. + */ + public static boolean isInitialized() { + return DistributorProvider.instance != null; + } +} diff --git a/distributor-common/src/main/java/com/xpdustry/distributor/core/player/SimplePlayerLookup.java b/distributor-common/src/main/java/com/xpdustry/distributor/core/player/SimplePlayerLookup.java index fe1d60fa..e7b711d8 100644 --- a/distributor-common/src/main/java/com/xpdustry/distributor/core/player/SimplePlayerLookup.java +++ b/distributor-common/src/main/java/com/xpdustry/distributor/core/player/SimplePlayerLookup.java @@ -18,6 +18,7 @@ */ package com.xpdustry.distributor.core.player; +import arc.Core; import arc.util.Strings; import com.xpdustry.distributor.core.collection.ArcCollections; import java.text.Normalizer; @@ -85,17 +86,21 @@ public List findOnlinePlayers(final String query, final boolean admin) { @Override public CompletableFuture> findOfflinePlayers( final String query, final boolean admin) { - final Set result = new LinkedHashSet<>(); - for (final var online : findOnlinePlayers(query, admin)) { - result.add(online.getInfo()); - } - if (admin && MUUID.isUuid(query)) { - final var info = Vars.netServer.admins.getInfoOptional(query); - if (info != null) { - result.add(info); - } - } - return CompletableFuture.completedFuture(List.copyOf(result)); + return CompletableFuture.supplyAsync( + () -> { + final Set result = new LinkedHashSet<>(); + for (final var online : findOnlinePlayers(query, admin)) { + result.add(online.getInfo()); + } + if (admin && MUUID.isUuid(query)) { + final var info = Vars.netServer.admins.getInfoOptional(query); + if (info != null) { + result.add(info); + } + } + return List.copyOf(result); + }, + Core.app::post); } // https://stackoverflow.com/a/4122207 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e3b07ea5..8af0cbed 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ mindustry = "v146" slf4j = "2.0.11" # command -cloud = "2.0.0-beta.2" +cloud = "2.0.0-beta.3" # utilities immutables = "2.9.2"