From bc86277d31c804efc20d16d304cc61e72ce5647c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Thu, 1 Feb 2024 12:34:54 +0100 Subject: [PATCH] feat: add a very simple gamemode command --- .../command/commands/GameModeCommand.java | 64 ++++++++ .../command/parser/GameModeParser.java | 141 ++++++++++++++++++ .../command/parser/package-info.java | 4 + .../kitchensink/entity/PlayerRepository.java | 1 + .../kitchensink/entity/player/GameMode.java | 113 ++++++++++++++ .../{ => player}/KitchenSinkPlayer.java | 18 ++- .../entity/player/package-info.java | 4 + .../kitchensink/guice/CommandModule.java | 2 + .../kitchensink/paper/PaperKitchenSink.java | 2 +- .../kitchensink/paper/entity/PaperPlayer.java | 26 +++- .../kitchensink/paper/guice/PaperModule.java | 18 +++ .../guice/qualifier/MainThreadExecutor.java | 12 +- .../paper/guice/qualifier/package-info.java | 4 + 13 files changed, 402 insertions(+), 7 deletions(-) create mode 100644 kitchensink-common/src/main/java/org/incendo/kitchensink/command/commands/GameModeCommand.java create mode 100644 kitchensink-common/src/main/java/org/incendo/kitchensink/command/parser/GameModeParser.java create mode 100644 kitchensink-common/src/main/java/org/incendo/kitchensink/command/parser/package-info.java create mode 100644 kitchensink-common/src/main/java/org/incendo/kitchensink/entity/player/GameMode.java rename kitchensink-common/src/main/java/org/incendo/kitchensink/entity/{ => player}/KitchenSinkPlayer.java (69%) create mode 100644 kitchensink-common/src/main/java/org/incendo/kitchensink/entity/player/package-info.java rename kitchensink-common/src/main/java/org/incendo/kitchensink/KitchenSink.java => kitchensink-paper/src/main/java/org/incendo/kitchensink/paper/guice/qualifier/MainThreadExecutor.java (75%) create mode 100644 kitchensink-paper/src/main/java/org/incendo/kitchensink/paper/guice/qualifier/package-info.java diff --git a/kitchensink-common/src/main/java/org/incendo/kitchensink/command/commands/GameModeCommand.java b/kitchensink-common/src/main/java/org/incendo/kitchensink/command/commands/GameModeCommand.java new file mode 100644 index 0000000..97908e6 --- /dev/null +++ b/kitchensink-common/src/main/java/org/incendo/kitchensink/command/commands/GameModeCommand.java @@ -0,0 +1,64 @@ +// +// MIT License +// +// Copyright (c) 2024 Incendo +// +// 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 org.incendo.kitchensink.command.commands; + +import jakarta.inject.Singleton; +import net.kyori.adventure.text.format.NamedTextColor; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.incendo.cloud.Command; +import org.incendo.cloud.bean.CommandProperties; +import org.incendo.kitchensink.command.KitchenSinkCommandBean; +import org.incendo.kitchensink.command.KitchenSinkCommandSender; +import org.incendo.kitchensink.entity.player.GameMode; +import org.incendo.kitchensink.entity.player.KitchenSinkPlayer; + +import static net.kyori.adventure.text.Component.text; +import static org.incendo.kitchensink.command.parser.GameModeParser.gameModeParser; + +@Singleton +public final class GameModeCommand extends KitchenSinkCommandBean { + + @Override + protected @NonNull CommandProperties properties() { + return CommandProperties.of("gamemode", "gm"); + } + + @Override + protected Command.@NonNull Builder configureKitchenSinkCommand( + final Command.@NonNull Builder builder + ) { + // TODO(City): Make the command take in an optional player argument that defaults + // to the executing player (if the sender is a player). + return builder.required("gameMode", gameModeParser()) + .senderType(KitchenSinkPlayer.class) + .handler((FutureCommandExecutionHandler) context -> { + final GameMode gameMode = context.get("gameMode"); + return context.sender().gameMode(gameMode).whenComplete(($, error) -> { + context.sender() + .sendMessage(text("Your game mode has been set to ", NamedTextColor.GRAY) + .append(text(gameMode.key(), NamedTextColor.GOLD))); + }); + }); + } +} diff --git a/kitchensink-common/src/main/java/org/incendo/kitchensink/command/parser/GameModeParser.java b/kitchensink-common/src/main/java/org/incendo/kitchensink/command/parser/GameModeParser.java new file mode 100644 index 0000000..fe2f69a --- /dev/null +++ b/kitchensink-common/src/main/java/org/incendo/kitchensink/command/parser/GameModeParser.java @@ -0,0 +1,141 @@ +// +// MIT License +// +// Copyright (c) 2024 Incendo +// +// 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 org.incendo.kitchensink.command.parser; + +import java.util.Objects; +import java.util.stream.Collectors; +import org.apiguardian.api.API; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.incendo.cloud.caption.CaptionVariable; +import org.incendo.cloud.caption.StandardCaptionKeys; +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; +import org.incendo.cloud.parser.ParserDescriptor; +import org.incendo.cloud.suggestion.BlockingSuggestionProvider; +import org.incendo.cloud.suggestion.Suggestion; +import org.incendo.cloud.type.range.Range; +import org.incendo.kitchensink.command.KitchenSinkCommandSender; +import org.incendo.kitchensink.entity.player.GameMode; + +public final class GameModeParser implements ArgumentParser, + BlockingSuggestionProvider { + + /** + * Creates a new game mode parser. + * + * @return the parser + */ + public static ParserDescriptor gameModeParser() { + return ParserDescriptor.of(new GameModeParser(), GameMode.class); + } + + @Override + public @NonNull ArgumentParseResult<@NonNull GameMode> parse( + final @NonNull CommandContext<@NonNull KitchenSinkCommandSender> commandContext, + final @NonNull CommandInput commandInput + ) { + if (commandInput.isValidInteger(Range.intRange(0, 3))) { + return ArgumentParseResult.success(GameMode.fromId(commandInput.readInteger())); + } + + final String input = commandInput.readString(); + try { + return ArgumentParseResult.success(GameMode.fromKey(input)); + } catch (final IllegalArgumentException ignored) { + return ArgumentParseResult.failure(new GameModeParseException(input, commandContext)); + } + } + + @Override + public @NonNull Iterable<@NonNull Suggestion> suggestions( + final @NonNull CommandContext context, + final @NonNull CommandInput input + ) { + return GameMode.gameModes() + .stream() + .map(GameMode::key) + .map(Suggestion::simple) + .toList(); + } + + + @API(status = API.Status.STABLE) + public static final class GameModeParseException extends ParserException { + + private final String input; + + /** + * Construct a new game mode parse exception. + * + * @param input input + * @param context command context + */ + public GameModeParseException( + final @NonNull String input, + final @NonNull CommandContext context + ) { + super( + GameModeParser.class, + context, + StandardCaptionKeys.ARGUMENT_PARSE_FAILURE_ENUM, + CaptionVariable.of("input", input), + CaptionVariable.of("acceptableValues", GameMode.gameModes() + .stream() + .map(GameMode::key) + .collect(Collectors.joining(", ")) + ) + ); + this.input = input; + } + + /** + * Returns the input provided by the sender. + * + * @return input + */ + public @NonNull String input() { + return this.input; + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || this.getClass() != o.getClass()) { + return false; + } + final GameModeParseException that = (GameModeParseException) o; + return this.input.equals(that.input); + } + + @Override + public int hashCode() { + return Objects.hash(this.input); + } + } +} diff --git a/kitchensink-common/src/main/java/org/incendo/kitchensink/command/parser/package-info.java b/kitchensink-common/src/main/java/org/incendo/kitchensink/command/parser/package-info.java new file mode 100644 index 0000000..7a2bd99 --- /dev/null +++ b/kitchensink-common/src/main/java/org/incendo/kitchensink/command/parser/package-info.java @@ -0,0 +1,4 @@ +/** + * Custom parsers. + */ +package org.incendo.kitchensink.command.parser; diff --git a/kitchensink-common/src/main/java/org/incendo/kitchensink/entity/PlayerRepository.java b/kitchensink-common/src/main/java/org/incendo/kitchensink/entity/PlayerRepository.java index ce6ed54..95311d8 100644 --- a/kitchensink-common/src/main/java/org/incendo/kitchensink/entity/PlayerRepository.java +++ b/kitchensink-common/src/main/java/org/incendo/kitchensink/entity/PlayerRepository.java @@ -26,6 +26,7 @@ import java.util.Optional; import java.util.UUID; import org.checkerframework.checker.nullness.qual.NonNull; +import org.incendo.kitchensink.entity.player.KitchenSinkPlayer; /** * Repository that contains {@link KitchenSinkPlayer players}. diff --git a/kitchensink-common/src/main/java/org/incendo/kitchensink/entity/player/GameMode.java b/kitchensink-common/src/main/java/org/incendo/kitchensink/entity/player/GameMode.java new file mode 100644 index 0000000..479c4c7 --- /dev/null +++ b/kitchensink-common/src/main/java/org/incendo/kitchensink/entity/player/GameMode.java @@ -0,0 +1,113 @@ +// +// MIT License +// +// Copyright (c) 2024 Incendo +// +// 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 org.incendo.kitchensink.entity.player; + +import java.util.Collection; +import java.util.List; +import java.util.Locale; +import java.util.Objects; +import org.checkerframework.checker.nullness.qual.NonNull; + +public final class GameMode { + + public static final GameMode SURVIVAL = new GameMode("survival", 0); + public static final GameMode CREATIVE = new GameMode("creative", 1); + public static final GameMode ADVENTURE = new GameMode("adventure", 2); + public static final GameMode SPECTATOR = new GameMode("spectator", 3); + + // Has to come after because of the forward referencing that would otherwise occur. + private static final List<@NonNull GameMode> GAME_MODES = List.of(SURVIVAL, CREATIVE, ADVENTURE, SPECTATOR); + + /** + * Returns the game mode that corresponds to the given {@code key}. + * + * @param key game mode key + * @return the game mode + * @throws IllegalArgumentException if the game mode does not exist + */ + public static @NonNull GameMode fromKey(final @NonNull String key) { + return switch (key.toLowerCase(Locale.ENGLISH)) { + case "survival" -> GameMode.SURVIVAL; + case "creative" -> GameMode.CREATIVE; + case "adventure" -> GameMode.ADVENTURE; + case "spectator" -> GameMode.SPECTATOR; + default -> throw new IllegalArgumentException("Unknown game mode: " + key); + }; + } + + /** + * Returns the game mode that corresponds to the given {@code id}. + * + * @param id game mode id + * @return the game mode + * @throws IllegalArgumentException if the game mode does not exist + */ + public static @NonNull GameMode fromId(final int id) { + return switch (id) { + case 0 -> GameMode.SURVIVAL; + case 1 -> GameMode.CREATIVE; + case 2 -> GameMode.ADVENTURE; + case 3 -> GameMode.SPECTATOR; + default -> throw new IllegalArgumentException("Unknown game mode: " + id); + }; + } + + /** + * Returns the available game modes. + * + * @return the game modes + */ + public static @NonNull Collection<@NonNull GameMode> gameModes() { + return List.copyOf(GAME_MODES); + } + + private final String key; + private final int id; + + private GameMode( + final @NonNull String key, + final int id + ) { + this.key = Objects.requireNonNull(key, "key"); + this.id = id; + } + + /** + * Returns the game mode key. + * + * @return the key + */ + public @NonNull String key() { + return this.key; + } + + /** + * Returns the numerical id that represents this game mode. + * + * @return the id + */ + public int id() { + return this.id; + } +} diff --git a/kitchensink-common/src/main/java/org/incendo/kitchensink/entity/KitchenSinkPlayer.java b/kitchensink-common/src/main/java/org/incendo/kitchensink/entity/player/KitchenSinkPlayer.java similarity index 69% rename from kitchensink-common/src/main/java/org/incendo/kitchensink/entity/KitchenSinkPlayer.java rename to kitchensink-common/src/main/java/org/incendo/kitchensink/entity/player/KitchenSinkPlayer.java index 75598b8..c5bc41a 100644 --- a/kitchensink-common/src/main/java/org/incendo/kitchensink/entity/KitchenSinkPlayer.java +++ b/kitchensink-common/src/main/java/org/incendo/kitchensink/entity/player/KitchenSinkPlayer.java @@ -21,14 +21,30 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. // -package org.incendo.kitchensink.entity; +package org.incendo.kitchensink.entity.player; +import java.util.concurrent.CompletableFuture; +import org.checkerframework.checker.nullness.qual.NonNull; import org.incendo.kitchensink.command.KitchenSinkCommandSender; +import org.incendo.kitchensink.entity.KitchenSinkEntity; /** * A player. */ public interface KitchenSinkPlayer extends KitchenSinkEntity, KitchenSinkCommandSender { + /** + * Returns the current game mode. + * + * @return the game mode + */ + @NonNull GameMode gameMode(); + /** + * Sets the player game mode. + * + * @param gameMode new game mode + * @return future that completes when the game mode has been updated + */ + @NonNull CompletableFuture gameMode(@NonNull GameMode gameMode); } diff --git a/kitchensink-common/src/main/java/org/incendo/kitchensink/entity/player/package-info.java b/kitchensink-common/src/main/java/org/incendo/kitchensink/entity/player/package-info.java new file mode 100644 index 0000000..2b9407f --- /dev/null +++ b/kitchensink-common/src/main/java/org/incendo/kitchensink/entity/player/package-info.java @@ -0,0 +1,4 @@ +/** + * Classes related to players. + */ +package org.incendo.kitchensink.entity.player; diff --git a/kitchensink-common/src/main/java/org/incendo/kitchensink/guice/CommandModule.java b/kitchensink-common/src/main/java/org/incendo/kitchensink/guice/CommandModule.java index 6a2e0d0..319c0e3 100644 --- a/kitchensink-common/src/main/java/org/incendo/kitchensink/guice/CommandModule.java +++ b/kitchensink-common/src/main/java/org/incendo/kitchensink/guice/CommandModule.java @@ -26,6 +26,7 @@ import com.google.inject.AbstractModule; import com.google.inject.multibindings.Multibinder; import org.incendo.kitchensink.command.KitchenSinkCommandBean; +import org.incendo.kitchensink.command.commands.GameModeCommand; import org.incendo.kitchensink.command.commands.PingCommand; /** @@ -40,5 +41,6 @@ protected void configure() { KitchenSinkCommandBean.class ); commandBinder.addBinding().to(PingCommand.class); + commandBinder.addBinding().to(GameModeCommand.class); } } diff --git a/kitchensink-paper/src/main/java/org/incendo/kitchensink/paper/PaperKitchenSink.java b/kitchensink-paper/src/main/java/org/incendo/kitchensink/paper/PaperKitchenSink.java index ce2f150..353f7b0 100644 --- a/kitchensink-paper/src/main/java/org/incendo/kitchensink/paper/PaperKitchenSink.java +++ b/kitchensink-paper/src/main/java/org/incendo/kitchensink/paper/PaperKitchenSink.java @@ -41,7 +41,7 @@ public final class PaperKitchenSink extends JavaPlugin { @Override public void onLoad() { - this.injector = Guice.createInjector(new PaperModule(), new CloudModule(this), new CommandModule()); + this.injector = Guice.createInjector(new PaperModule(this), new CloudModule(this), new CommandModule()); } @Override diff --git a/kitchensink-paper/src/main/java/org/incendo/kitchensink/paper/entity/PaperPlayer.java b/kitchensink-paper/src/main/java/org/incendo/kitchensink/paper/entity/PaperPlayer.java index 2ac3cbf..33ef9ff 100644 --- a/kitchensink-paper/src/main/java/org/incendo/kitchensink/paper/entity/PaperPlayer.java +++ b/kitchensink-paper/src/main/java/org/incendo/kitchensink/paper/entity/PaperPlayer.java @@ -24,16 +24,21 @@ package org.incendo.kitchensink.paper.entity; import com.google.auto.factory.AutoFactory; +import com.google.auto.factory.Provided; import java.util.List; import java.util.Locale; import java.util.Objects; import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; import net.kyori.adventure.audience.Audience; import net.kyori.adventure.audience.ForwardingAudience; import net.kyori.adventure.text.Component; import org.bukkit.entity.Player; import org.checkerframework.checker.nullness.qual.NonNull; -import org.incendo.kitchensink.entity.KitchenSinkPlayer; +import org.incendo.kitchensink.entity.player.GameMode; +import org.incendo.kitchensink.entity.player.KitchenSinkPlayer; +import org.incendo.kitchensink.paper.guice.qualifier.MainThreadExecutor; import org.jetbrains.annotations.NotNull; /** @@ -43,14 +48,17 @@ public final class PaperPlayer implements KitchenSinkPlayer, ForwardingAudience { private final Player player; + private final Executor mainThreadExecutor; /** * Creates a new player instance. * - * @param player backing Paper player + * @param player backing Paper player + * @param mainThreadExecutor main thread executor */ - public PaperPlayer(final @NonNull Player player) { + public PaperPlayer(final @NonNull Player player, @Provided @MainThreadExecutor final @NonNull Executor mainThreadExecutor) { this.player = Objects.requireNonNull(player, "player"); + this.mainThreadExecutor = Objects.requireNonNull(mainThreadExecutor, "mainThreadExecutor"); } @Override @@ -78,6 +86,18 @@ public PaperPlayer(final @NonNull Player player) { return this.player.locale(); } + @Override + public @NonNull GameMode gameMode() { + return GameMode.fromId(this.player.getGameMode().getValue()); + } + + @Override + public @NonNull CompletableFuture gameMode(final @NonNull GameMode gameMode) { + return CompletableFuture.runAsync(() -> { + this.player.setGameMode(org.bukkit.GameMode.getByValue(gameMode.id())); + }, this.mainThreadExecutor); + } + /** * Returns the Paper player that backs this instance. * diff --git a/kitchensink-paper/src/main/java/org/incendo/kitchensink/paper/guice/PaperModule.java b/kitchensink-paper/src/main/java/org/incendo/kitchensink/paper/guice/PaperModule.java index eecf9ab..9ab89f0 100644 --- a/kitchensink-paper/src/main/java/org/incendo/kitchensink/paper/guice/PaperModule.java +++ b/kitchensink-paper/src/main/java/org/incendo/kitchensink/paper/guice/PaperModule.java @@ -25,18 +25,36 @@ import com.google.inject.AbstractModule; import com.google.inject.TypeLiteral; +import java.util.Objects; +import java.util.concurrent.Executor; import org.bukkit.entity.Player; +import org.checkerframework.checker.nullness.qual.NonNull; import org.incendo.kitchensink.entity.PlayerRepository; +import org.incendo.kitchensink.paper.PaperKitchenSink; import org.incendo.kitchensink.paper.entity.PaperPlayer; import org.incendo.kitchensink.paper.entity.PaperPlayerRepository; +import org.incendo.kitchensink.paper.guice.qualifier.MainThreadExecutor; /** * Module for Paper-specific bindings. */ public final class PaperModule extends AbstractModule { + private final PaperKitchenSink paperKitchenSink; + + /** + * Creates a new paper module instance. + * + * @param paperKitchenSink plugin that is creating the instance + */ + public PaperModule(final @NonNull PaperKitchenSink paperKitchenSink) { + this.paperKitchenSink = Objects.requireNonNull(paperKitchenSink, "paperKitchenSink"); + } + @Override protected void configure() { this.bind(new TypeLiteral>() {}).to(PaperPlayerRepository.class); + this.bind(Executor.class).annotatedWith(MainThreadExecutor.class).toProvider(() -> this.paperKitchenSink.getServer() + .getScheduler().getMainThreadExecutor(this.paperKitchenSink)); } } diff --git a/kitchensink-common/src/main/java/org/incendo/kitchensink/KitchenSink.java b/kitchensink-paper/src/main/java/org/incendo/kitchensink/paper/guice/qualifier/MainThreadExecutor.java similarity index 75% rename from kitchensink-common/src/main/java/org/incendo/kitchensink/KitchenSink.java rename to kitchensink-paper/src/main/java/org/incendo/kitchensink/paper/guice/qualifier/MainThreadExecutor.java index 8ebca6c..a24c875 100644 --- a/kitchensink-common/src/main/java/org/incendo/kitchensink/KitchenSink.java +++ b/kitchensink-paper/src/main/java/org/incendo/kitchensink/paper/guice/qualifier/MainThreadExecutor.java @@ -21,8 +21,16 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. // -package org.incendo.kitchensink; +package org.incendo.kitchensink.paper.guice.qualifier; -public abstract class KitchenSink { +import jakarta.inject.Qualifier; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +@Qualifier +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.PARAMETER) +public @interface MainThreadExecutor { } diff --git a/kitchensink-paper/src/main/java/org/incendo/kitchensink/paper/guice/qualifier/package-info.java b/kitchensink-paper/src/main/java/org/incendo/kitchensink/paper/guice/qualifier/package-info.java new file mode 100644 index 0000000..38fae25 --- /dev/null +++ b/kitchensink-paper/src/main/java/org/incendo/kitchensink/paper/guice/qualifier/package-info.java @@ -0,0 +1,4 @@ +/** + * Injection qualifiers. + */ +package org.incendo.kitchensink.paper.guice.qualifier;