From 9660be1571104419bedd7a697074238ef22924ea Mon Sep 17 00:00:00 2001 From: ImBit <151650938+ImBit@users.noreply.github.com> Date: Thu, 18 Jun 2026 16:39:27 +0100 Subject: [PATCH 01/15] :art: Serialization, Animation, ChunkCoordinate tweaks. --- .../bits/util/serializer/SerializationManager.java | 9 ++++++++- .../paper/location/wrapper/ChunkCoordinate.java | 13 +++++++++++++ .../bits/mc/animation/impl/BasicAnimation.java | 3 +-- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/api/src/main/java/xyz/bitsquidd/bits/util/serializer/SerializationManager.java b/api/src/main/java/xyz/bitsquidd/bits/util/serializer/SerializationManager.java index 6b4dc87f..3802c162 100644 --- a/api/src/main/java/xyz/bitsquidd/bits/util/serializer/SerializationManager.java +++ b/api/src/main/java/xyz/bitsquidd/bits/util/serializer/SerializationManager.java @@ -8,7 +8,12 @@ package xyz.bitsquidd.bits.util.serializer; -import com.fasterxml.jackson.databind.*; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.KeyDeserializer; +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.json.JsonMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.datatype.guava.GuavaModule; @@ -23,6 +28,7 @@ import java.util.Set; import java.util.stream.Collectors; + public final class SerializationManager { private SerializationManager() {} @@ -35,6 +41,7 @@ private static ObjectMapper createMapper() { .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) .disable(DeserializationFeature.FAIL_ON_MISSING_CREATOR_PROPERTIES) .disable(MapperFeature.AUTO_DETECT_IS_GETTERS) + .defaultPropertyInclusion(JsonInclude.Value.ALL_NON_NULL) .annotationIntrospector(new NullableAwareIntrospector()); getSerializers().forEach(serializer -> registerSerializer(serializer, builder)); diff --git a/minecraft/paper/src/main/java/xyz/bitsquidd/bits/paper/location/wrapper/ChunkCoordinate.java b/minecraft/paper/src/main/java/xyz/bitsquidd/bits/paper/location/wrapper/ChunkCoordinate.java index ab9cde47..b93229cf 100644 --- a/minecraft/paper/src/main/java/xyz/bitsquidd/bits/paper/location/wrapper/ChunkCoordinate.java +++ b/minecraft/paper/src/main/java/xyz/bitsquidd/bits/paper/location/wrapper/ChunkCoordinate.java @@ -7,12 +7,15 @@ package xyz.bitsquidd.bits.paper.location.wrapper; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.LevelChunk; import org.bukkit.Chunk; import org.bukkit.Location; import org.bukkit.World; import java.util.Objects; + /** * Immutable record representing the coordinates of a chunk in a specific world. * @@ -40,6 +43,16 @@ public static ChunkCoordinate fromChunk(Chunk chunk) { ); } + public static ChunkCoordinate fromChunk(ChunkAccess chunkAccess) { + if (!(chunkAccess instanceof LevelChunk levelChunk)) throw new IllegalArgumentException("ChunkAccess must be an instance of LevelChunk"); + + return new ChunkCoordinate( + levelChunk.locX, + levelChunk.locZ, + levelChunk.level.getWorld() + ); + } + public int manhattanDistance(ChunkCoordinate other) { if (!Objects.equals(this.world, other.world)) throw new IllegalArgumentException("Cannot calculate distance between chunks in different worlds"); return Math.abs(this.x - other.x) + Math.abs(this.z - other.z); diff --git a/minecraft/src/main/java/xyz/bitsquidd/bits/mc/animation/impl/BasicAnimation.java b/minecraft/src/main/java/xyz/bitsquidd/bits/mc/animation/impl/BasicAnimation.java index 391198c2..abc7feaf 100644 --- a/minecraft/src/main/java/xyz/bitsquidd/bits/mc/animation/impl/BasicAnimation.java +++ b/minecraft/src/main/java/xyz/bitsquidd/bits/mc/animation/impl/BasicAnimation.java @@ -59,8 +59,7 @@ public AnimationPose evaluate(int ticks) { float localProgress = Math.min((progress - kf.progress()) / intervalLength, 1f); float easedProgress = kf.easing().progress(localProgress); - AnimationPose delta = AnimationPose.lerp(AnimationPose.identity(), kf.pose(), easedProgress); - result = AnimationPose.add(result, delta); + result = AnimationPose.lerp(kf.pose(), next.pose(), easedProgress); } return result; } From 2b595cc4cd49cedea53067053cacd053d36eae82 Mon Sep 17 00:00:00 2001 From: ImBit <151650938+ImBit@users.noreply.github.com> Date: Thu, 18 Jun 2026 16:42:46 +0100 Subject: [PATCH 02/15] :art: Update README.md --- README.md | 126 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 81 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index 4dbcb210..ee8b3d13 100644 --- a/README.md +++ b/README.md @@ -1,57 +1,100 @@ +
💾 A Utility library for Orbitary development.
{@code * BitsArgumentRegistry> registry = manager.getArgumentRegistry(); - * AbstractArgumentParser> parser = registry.getParser(TypeSignature.of(Player.class)); + * AbstractArgumentParser, ?> parser = registry.getParser(TypeSignature.of(Player.class)); * }
- * This record is primarily used when compiling custom {@link AbstractArgumentParser} + * This record is primarily used when compiling custom {@link ArgumentParser} * instances into their base Brigadier representations for tree registration. * * @param argumentType the underlying Brigadier argument type implementation diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/AbstractArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/AbstractArgumentParser.java deleted file mode 100644 index 579ea5c9..00000000 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/AbstractArgumentParser.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * This file is part of a Bit libraries package. - * Licensed under the GNU Lesser General Public License v3.0. - * - * Copyright (c) 2023-2026 ImBit - */ - -package xyz.bitsquidd.bits.mc.command.argument.parser; - -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import com.mojang.brigadier.suggestion.SuggestionProvider; -import org.jetbrains.annotations.Nullable; - -import xyz.bitsquidd.bits.mc.command.argument.InputTypeContainer; -import xyz.bitsquidd.bits.mc.command.exception.ExceptionBuilder; -import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; -import xyz.bitsquidd.bits.wrapper.type.TypeSignature; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Supplier; - -/** - * A parser responsible for converting a list of raw command arguments into a specific object type. - *
- * This class serves as the foundation for all custom argument parsing within the Bits command framework. - * Implementations define how string inputs or other basic types from Brigadier are structurally resolved - * into complex objects, and optionally provide tab-completion suggestions. - *
- * Example parser implementation: - *
{@code - * public class PlayerArgumentParser extends AbstractArgumentParser { - * public PlayerArgumentParser() { - * super(TypeSignature.of(Player.class), "player_name"); - * } - * - * // Override methods to dictate parsing logic and input types. - * } - * }
- * In the case a non-vanilla primitive is passed in, we expect a parser to be present for this.
- * For example:
- * This method evaluates {@link #getSuggestions()} to dynamically supply tab completion results. - * - * @param the command source type - * - * @return the suggestion provider context for Brigadier nodes - * - * @since 0.0.10 - */ - public final SuggestionProvider getSuggestionProvider() { - return (ctx, builder) -> { - Supplier> suggestionSupplier = getSuggestions(); - if (suggestionSupplier == null) return builder.buildFuture(); - - List suggestions = suggestionSupplier.get(); - String remaining = builder.getRemaining().toLowerCase(); - - for (String suggestion : suggestions) { - if (suggestion.toLowerCase().startsWith(remaining)) { - builder.suggest(suggestion); - } - } - - return builder.buildFuture(); - }; - } - - /** - * Returns a dynamically loaded list of suggestions for the argument at a given context state. - * - * @return a supplier providing available string suggestions, or null if none exist - * - * @since 0.0.10 - */ - public @Nullable Supplier> getSuggestions() { - return null; - } - - - /** - * Retrieves the core type signature handled by this parser. - * - * @return the type signature - * - * @since 0.0.10 - */ - public TypeSignature> getTypeSignature() { - return typeSignature; - } - - /** - * Retrieves the argument name meant for display in syntax sequences. - * - * @return the argument label - * - * @since 0.0.10 - */ - public String getArgumentName() { - return argumentName; - } - -} diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/ArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/ArgumentParser.java index 53a0242d..3d755312 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/ArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/ArgumentParser.java @@ -7,17 +7,215 @@ package xyz.bitsquidd.bits.mc.command.argument.parser; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.suggestion.SuggestionProvider; +import org.jetbrains.annotations.Nullable; + +import xyz.bitsquidd.bits.mc.command.BitsCommandManager; +import xyz.bitsquidd.bits.mc.command.argument.InputTypeContainer; +import xyz.bitsquidd.bits.mc.command.argument.parser.impl.GreedyStringArgumentParser; +import xyz.bitsquidd.bits.mc.command.exception.ExceptionBuilder; +import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; +import xyz.bitsquidd.bits.wrapper.GreedyString; +import xyz.bitsquidd.bits.wrapper.type.TypeSignature; + +import java.lang.reflect.Constructor; +import java.lang.reflect.RecordComponent; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; /** - * Annotation for marking classes as argument parsers. + * A parser responsible for converting a list of raw command arguments into a specific object type. + * + * This class serves as the foundation for all custom argument parsing within the Bits command framework. + * Implementations define how string inputs or other basic types from Brigadier are structurally resolved + * into complex objects, and optionally provide tab-completion suggestions. + * + * Example parser implementation: + * {@code + * public class PlayerArgumentParser extends AbstractArgumentParser { + * public PlayerArgumentParser() { + * super(TypeSignature.of(Player.class), "player_name"); + * } + * + * // Override methods to dictate parsing logic and input types. + * } + * } + * + * @param The type this parser converts to. + * @param The type of the input data (e.g., String, Integer, World) this parser expects to receive from Brigadier or parser. * - * @since 0.0.13 + * @since 0.0.10 */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -public @interface ArgumentParser {} +public abstract class ArgumentParser { + private final TypeSignature> typeSignature; // The type signature this parser handles + private final String argumentName; // The name of the argument, used while displaying suggestions + private final Class dataClass; // The class of the input data type + private final Constructor recordConstructor; + + /** + * @param typeSignature the expected type this parser handles + * @param argumentName the label to display in command syntax suggestions + * @param dataClass the class of the input data type + * + * @since 0.0.10 + */ + protected ArgumentParser(TypeSignature> typeSignature, String argumentName, Class dataClass) { + this.typeSignature = typeSignature; + this.argumentName = argumentName; + this.dataClass = dataClass; + this.recordConstructor = dataClass.isRecord() ? resolveCanonicalConstructor(dataClass) : null; + } + + + private static Constructor resolveCanonicalConstructor(Class recordClass) { + Class>[] paramTypes = Arrays.stream(recordClass.getRecordComponents()) + .map(RecordComponent::getType) + .toArray(Class>[]::new); + + try { + return recordClass.getDeclaredConstructor(paramTypes); + } catch (NoSuchMethodException e) { + // Unreachable: every record has a canonical constructor. + throw new IllegalStateException("No canonical constructor found for record " + recordClass.getSimpleName(), e); + } + } + + + /** + * Parses the provided primitive objects into the target complex object type {@code O}. + * + * @param data the raw inputs captured from the command context + * @param ctx the command execution context + * + * @return the successfully parsed object + * + * @throws CommandSyntaxException if the input is malformed or invalid + * @since 0.0.10 + */ + public abstract O parse(D data, BitsCommandContext> ctx) throws CommandSyntaxException; + + /** + * Returns a list of required objects the parser expects in. + * In the case of most custom parsers this will be a String. + * + * In the case a non-vanilla primitive is passed in, we expect a parser to be present for this. + * For example: + * An Integer parser would expect a single int {@code List.of(Integer.class)} + * A Bukkit Location parser may expect three doubles and a World {@code List.of(Double.class, Double.class, Double.class, World.class)} + * + * + * @return A list of expected required objects. + * + * @since 0.0.20 + */ + public final List getInputTypes() { + // Special case for GreedyString: it captures all remaining input as a single string. + if (this instanceof GreedyStringArgumentParser) return List.of(new InputTypeContainer(TypeSignature.of(GreedyString.class), getArgumentName())); + + // Special case for non-record types: treat the entire data class the input. + if (!dataClass.isRecord()) return List.of(new InputTypeContainer(TypeSignature.of(dataClass), argumentName)); + + RecordComponent[] components = dataClass.getRecordComponents(); + List inputTypes = new ArrayList<>(components.length); + + for (RecordComponent component : components) { + inputTypes.add(new InputTypeContainer(TypeSignature.of(component.getType()), component.getName())); + } + + return inputTypes; + } + + + public final D toData(List inputObjects) throws CommandSyntaxException { + List inputTypes = getInputTypes(); + + if (inputObjects.size() != inputTypes.size()) throw ExceptionBuilder.createCommandException("Expected exactly " + inputTypes.size() + " input object" + (inputTypes.size() > 1 ? "s" : "") + ", got " + inputObjects.size() + "."); + Object[] validated = new Object[inputTypes.size()]; + + for (int i = 0; i < inputTypes.size(); i++) { + Class> expectedType = inputTypes.get(i).typeSignature().toRawType(); + Object value = inputObjects.get(i); + + if (!expectedType.isInstance(value)) throw ExceptionBuilder.createCommandException("Expected input object of type " + expectedType.getSimpleName() + ", got " + value.getClass().getSimpleName() + "."); + validated[i] = value; + } + + // Single-value case: D itself is the scalar type (e.g. D = Double) + if (!dataClass.isRecord()) return dataClass.cast(validated[0]); + + try { + return recordConstructor.newInstance(validated); + } catch (ReflectiveOperationException e) { + throw ExceptionBuilder.createCommandException("Failed to construct " + dataClass.getSimpleName() + ": " + e.getMessage()); + } + } + + + /** + * Retrieves a Brigadier compatible suggestion provider for this argument parser. + * + * This method evaluates {@link #getSuggestions} to dynamically supply tab completion results. + * + * @param the command source type + * + * @return the suggestion provider context for Brigadier nodes + * + * @since 0.0.10 + */ + public final SuggestionProvider createSuggestionProvider() { + SuggestionSupplier suggestionSupplier = getSuggestions(); + if (suggestionSupplier == null) return (ctx, builder) -> builder.buildFuture(); // No suggestions available + BitsCommandManager manager = BitsCommandManager.get(); + + return (ctx, builder) -> { + List suggestions = suggestionSupplier.getSuggestions(manager.createContext(ctx)); + String remaining = builder.getRemaining(); + + for (String suggestion : suggestions) { + if (suggestion.equalsIgnoreCase(remaining)) { + builder.suggest(suggestion); + } + } + + return builder.buildFuture(); + }; + } + + /** + * Returns a dynamically loaded list of suggestions for the argument at a given context state. + * + * @return a supplier providing available string suggestions, or null if none exist + * + * @since 0.0.10 + */ + public @Nullable SuggestionSupplier getSuggestions() { + return null; + } + + + /** + * Retrieves the core type signature handled by this parser. + * + * @return the type signature + * + * @since 0.0.10 + */ + public TypeSignature> getTypeSignature() { + return typeSignature; + } + + /** + * Retrieves the argument name meant for display in syntax sequences. + * + * @return the argument label + * + * @since 0.0.10 + */ + public String getArgumentName() { + return argumentName; + } + +} diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/GreedyStringArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/GreedyStringArgumentParser.java index e1aedc2a..7546c63d 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/GreedyStringArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/GreedyStringArgumentParser.java @@ -8,14 +8,11 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl; import xyz.bitsquidd.bits.mc.command.BrigadierTreeGenerator; -import xyz.bitsquidd.bits.mc.command.argument.InputTypeContainer; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.wrapper.GreedyString; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; -import java.util.List; /** * Argument parser for {@link GreedyString} values. @@ -24,20 +21,15 @@ * * @since 0.0.10 */ -@ArgumentParser -public final class GreedyStringArgumentParser extends AbstractArgumentParser { - public GreedyStringArgumentParser() { - super(TypeSignature.of(GreedyString.class), "String..."); - } - @Override - public GreedyString parse(List inputObjects, BitsCommandContext> ctx) { - return GreedyString.of((String)inputObjects.getFirst()); // Note: can't use singletonInputValidation as GreedyString is special... +public final class GreedyStringArgumentParser extends ArgumentParser { + public GreedyStringArgumentParser() { + super(TypeSignature.of(GreedyString.class), "String...", String.class); } @Override - public List getInputTypes() { - return List.of(new InputTypeContainer(TypeSignature.of(GreedyString.class), getArgumentName())); + public GreedyString parse(String data, BitsCommandContext> ctx) { + return GreedyString.of(data); } } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/KeyArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/KeyArgumentParser.java index 3bce5f65..0664f6b0 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/KeyArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/KeyArgumentParser.java @@ -10,7 +10,7 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.kyori.adventure.key.Key; -import xyz.bitsquidd.bits.mc.command.argument.parser.DefaultArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.BasicArgumentParser; import xyz.bitsquidd.bits.mc.command.argument.parser.SuggestionSupplier; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; @@ -25,7 +25,7 @@ * @since 0.0.20 */ -public final class KeyArgumentParser extends DefaultArgumentParser { +public final class KeyArgumentParser extends BasicArgumentParser { public KeyArgumentParser() { super(TypeSignature.of(Key.class), "Key"); } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LinkArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LinkArgumentParser.java index e15fe7f0..0e4bd58d 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LinkArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LinkArgumentParser.java @@ -9,14 +9,12 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; -import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.BasicArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.SuggestionSupplier; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.wrapper.Link; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; -import java.util.List; -import java.util.function.Supplier; import java.util.stream.Stream; @@ -29,20 +27,19 @@ * * @since 0.0.10 */ -@ArgumentParser -public final class LinkArgumentParser extends AbstractArgumentParser { + +public final class LinkArgumentParser extends BasicArgumentParser { public LinkArgumentParser() { super(TypeSignature.of(Link.class), "URL"); } @Override - public Link parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - String inputString = singletonInputValidation(inputObjects, String.class); - return Link.of(inputString); + public Link parse(String data, BitsCommandContext> ctx) throws CommandSyntaxException { + return Link.of(data); } @Override - public Supplier> getSuggestions() { + public SuggestionSupplier getSuggestions() { return () -> Stream.of("https://", "http://", "www.").toList(); } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/UUIDArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/UUIDArgumentParser.java index 677a9e95..327b6786 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/UUIDArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/UUIDArgumentParser.java @@ -9,7 +9,7 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; -import xyz.bitsquidd.bits.mc.command.argument.parser.DefaultArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.BasicArgumentParser; import xyz.bitsquidd.bits.mc.command.argument.parser.SuggestionSupplier; import xyz.bitsquidd.bits.mc.command.exception.ExceptionBuilder; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; @@ -34,7 +34,7 @@ * @since 0.0.10 */ -public final class UUIDArgumentParser extends DefaultArgumentParser { +public final class UUIDArgumentParser extends BasicArgumentParser { private static final List DASH_POSITIONS = List.of(8, 12, 16, 20); private static final char DASH_CHAR = '-'; private static final int HEX_CHAR_COUNT = 32; diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/VoidArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/VoidArgumentParser.java index 2f039616..cb7afb28 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/VoidArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/VoidArgumentParser.java @@ -7,7 +7,7 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl; -import xyz.bitsquidd.bits.mc.command.argument.parser.DefaultArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.BasicArgumentParser; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; @@ -20,7 +20,7 @@ * @since 0.0.10 */ -public final class VoidArgumentParser extends DefaultArgumentParser { +public final class VoidArgumentParser extends BasicArgumentParser { public static final VoidArgumentParser INSTANCE = new VoidArgumentParser(); private VoidArgumentParser() { diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/abs/AbstractEnumArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/abs/EnumArgumentParser.java similarity index 72% rename from minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/abs/AbstractEnumArgumentParser.java rename to minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/abs/EnumArgumentParser.java index 3242f6e7..27014b53 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/abs/AbstractEnumArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/abs/EnumArgumentParser.java @@ -10,15 +10,16 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import org.jetbrains.annotations.Nullable; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.BasicArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.SuggestionSupplier; import xyz.bitsquidd.bits.mc.command.exception.ExceptionBuilder; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; import java.util.List; -import java.util.function.Supplier; import java.util.stream.Stream; + /** * Base abstract parser providing common parsing and suggestion logic for enum types. * @@ -38,7 +39,7 @@ * * @since 0.0.10 */ -public abstract class AbstractEnumArgumentParser> extends AbstractArgumentParser { +public abstract class EnumArgumentParser> extends BasicArgumentParser { private final Class enumClass; /** @@ -47,28 +48,26 @@ public abstract class AbstractEnumArgumentParser> extends Abst * @throws IllegalArgumentException if the provided class is not an enum * @since 0.0.10 */ - public AbstractEnumArgumentParser(Class enumClass) { + public EnumArgumentParser(Class enumClass) { super(TypeSignature.of(Enum.class), enumClass.getName()); this.enumClass = enumClass; if (!enumClass.isEnum()) throw new IllegalArgumentException("Provided class " + enumClass.getName() + " is not an enum!"); } @Override - public T parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - String inputString = singletonInputValidation(inputObjects, String.class); - + public T parse(String data, BitsCommandContext> ctx) throws CommandSyntaxException { T enumValue; try { - enumValue = Enum.valueOf(enumClass, inputString); + enumValue = Enum.valueOf(enumClass, data); } catch (IllegalArgumentException e) { - throw ExceptionBuilder.createCommandException(inputString + " is not a valid " + enumClass.getSimpleName() + "."); + throw ExceptionBuilder.createCommandException(data + " is not a valid " + enumClass.getSimpleName() + "."); } return enumValue; } @Override - public @Nullable Supplier> getSuggestions() { + public @Nullable SuggestionSupplier getSuggestions() { return () -> enumClass.isEnum() ? Stream.of(enumClass.getEnumConstants()).map(Enum::name).toList() : List.of(); } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/generic/GenericEnumParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/generic/GenericEnumParser.java index 0f522bcf..27daae97 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/generic/GenericEnumParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/generic/GenericEnumParser.java @@ -9,21 +9,21 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; -import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; -import xyz.bitsquidd.bits.mc.command.argument.parser.impl.abs.AbstractEnumArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.BasicArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.SuggestionSupplier; +import xyz.bitsquidd.bits.mc.command.argument.parser.impl.abs.EnumArgumentParser; import xyz.bitsquidd.bits.mc.command.exception.ExceptionBuilder; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; +import xyz.bitsquidd.bits.util.wrapper.Enums; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; -import java.util.List; -import java.util.function.Supplier; import java.util.stream.Stream; + /** * A fallback, generically instantiated parser that handles unmapped enum types automatically. * - * Developer Note: Custom enum parsers should override {@link AbstractEnumArgumentParser} + * Developer Note: Custom enum parsers should override {@link EnumArgumentParser} * if you want more fine-grained control over enum arguments and tab completion. * * This implementation serves as a basic parser that is fallen back upon when no specific enum parser is available. @@ -32,9 +32,8 @@ * * @since 0.0.10 */ -@ArgumentParser -public final class GenericEnumParser> extends AbstractArgumentParser { +public final class GenericEnumParser> extends BasicArgumentParser { private final Class enumClass; public GenericEnumParser(Class enumClass) { @@ -43,18 +42,13 @@ public GenericEnumParser(Class enumClass) { } @Override - public E parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - String inputString = singletonInputValidation(inputObjects, String.class); - - for (E constant : enumClass.getEnumConstants()) { - if (constant.name().equalsIgnoreCase(inputString)) return constant; - } - - throw ExceptionBuilder.createCommandException("Enum constant not found: " + inputString + " for enum " + enumClass.getSimpleName() + "."); + public E parse(String data, BitsCommandContext> ctx) throws CommandSyntaxException { + return Enums.getFromIdentifier(enumClass, data) + .orElseThrow(() -> ExceptionBuilder.createCommandException("Enum constant not found: " + data + " for enum " + enumClass.getSimpleName() + ".")); } @Override - public Supplier> getSuggestions() { + public SuggestionSupplier getSuggestions() { return () -> Stream.of(enumClass.getEnumConstants()).map(Enum::name).toList(); } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/BooleanArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/BooleanArgumentParser.java index 444646e2..9b2fb11d 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/BooleanArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/BooleanArgumentParser.java @@ -7,17 +7,17 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl.primitive; -import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.SuggestionSupplier; import java.util.List; -import java.util.function.Supplier; + /** * Argument parser for Boolean values. * * @since 0.0.10 */ -@ArgumentParser + public final class BooleanArgumentParser extends PrimitiveArgumentParser { public BooleanArgumentParser() { @@ -25,7 +25,7 @@ public BooleanArgumentParser() { } @Override - public Supplier> getSuggestions() { + public SuggestionSupplier getSuggestions() { return () -> List.of("true", "false"); } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/DoubleArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/DoubleArgumentParser.java index 987fa30e..44dd84c1 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/DoubleArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/DoubleArgumentParser.java @@ -7,14 +7,13 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl.primitive; -import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; /** * Argument parser for Double values. * * @since 0.0.10 */ -@ArgumentParser + public final class DoubleArgumentParser extends PrimitiveArgumentParser { public DoubleArgumentParser() { super(Double.class, "Double"); diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/FloatArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/FloatArgumentParser.java index b0bc401d..22162ca9 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/FloatArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/FloatArgumentParser.java @@ -7,14 +7,13 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl.primitive; -import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; /** * Argument parser for Float values. * * @since 0.0.10 */ -@ArgumentParser + public final class FloatArgumentParser extends PrimitiveArgumentParser { public FloatArgumentParser() { super(Float.class, "Float"); diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/IntegerArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/IntegerArgumentParser.java index 79be0c9a..c04430a7 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/IntegerArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/IntegerArgumentParser.java @@ -7,14 +7,13 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl.primitive; -import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; /** * Argument parser for Integer values. * * @since 0.0.10 */ -@ArgumentParser + public final class IntegerArgumentParser extends PrimitiveArgumentParser { public IntegerArgumentParser() { diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/LongArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/LongArgumentParser.java index d59ce089..8e4e88df 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/LongArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/LongArgumentParser.java @@ -7,14 +7,13 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl.primitive; -import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; /** * Argument parser for Long values. * * @since 0.0.10 */ -@ArgumentParser + public final class LongArgumentParser extends PrimitiveArgumentParser { public LongArgumentParser() { diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/PrimitiveArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/PrimitiveArgumentParser.java index 12fb813c..ab6d26bc 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/PrimitiveArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/PrimitiveArgumentParser.java @@ -9,12 +9,10 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; -import xyz.bitsquidd.bits.mc.command.argument.InputTypeContainer; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; -import java.util.List; /** * A foundation parser designed specifically for types that correspond to underlying Brigadier primitives. @@ -26,21 +24,15 @@ * * @since 0.0.10 */ -public abstract class PrimitiveArgumentParser extends AbstractArgumentParser { +public abstract class PrimitiveArgumentParser extends ArgumentParser { protected PrimitiveArgumentParser(Class outputClass, String argumentName) { - super(TypeSignature.of(outputClass), argumentName); + super(TypeSignature.of(outputClass), argumentName, outputClass); } @Override - @SuppressWarnings("unchecked") - public final O parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - return (O)singletonInputValidation(inputObjects, getTypeSignature().toRawType()); - } - - @Override - public final List getInputTypes() { - return List.of(new InputTypeContainer(getTypeSignature(), getArgumentName())); + public final O parse(O data, BitsCommandContext> ctx) throws CommandSyntaxException { + return data; } } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/StringArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/StringArgumentParser.java index c8373738..fd241bea 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/StringArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/StringArgumentParser.java @@ -7,14 +7,13 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl.primitive; -import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; /** * Argument parser for String values. * * @since 0.0.10 */ -@ArgumentParser + public final class StringArgumentParser extends PrimitiveArgumentParser { public StringArgumentParser() { super(String.class, "String"); diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/util/CommandParameterInfo.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/util/CommandParameterInfo.java index 145cdc0c..346be50f 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/util/CommandParameterInfo.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/util/CommandParameterInfo.java @@ -12,7 +12,7 @@ import xyz.bitsquidd.bits.mc.command.BitsCommandManager; import xyz.bitsquidd.bits.mc.command.argument.BrigadierArgumentMapping; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; import java.lang.reflect.Parameter; @@ -39,7 +39,7 @@ public class CommandParameterInfo { private final TypeSignature> typeSignature; // TypeSignature of the parameter - private final AbstractArgumentParser> parser; + private final ArgumentParser, ?> parser; private final List heldArguments = new ArrayList<>(); // Direct mapping from the custom args to brigadier ArgumentTypes @@ -81,13 +81,13 @@ public CommandParameterInfo(Parameter parameter) { if (useArgSuggestions) { TypeSignature> inputType = parser.getInputTypes().get(i).typeSignature(); - AbstractArgumentParser> inputParser = BitsCommandManager.get().getArgumentRegistry().getParser(inputType); + ArgumentParser, ?> inputParser = BitsCommandManager.get().getArgumentRegistry().getParser(inputType); // Use the input-specific parser's suggestions - if (hasSuggestions(inputParser)) argumentBuilder.suggests(inputParser.getSuggestionProvider()); + if (hasSuggestions(inputParser)) argumentBuilder.suggests(inputParser.createSuggestionProvider()); } else { // Use the main parser's suggestions - if (hasSuggestions(parser)) argumentBuilder.suggests(parser.getSuggestionProvider()); + if (hasSuggestions(parser)) argumentBuilder.suggests(parser.createSuggestionProvider()); } brigadierArguments.add(argumentBuilder); @@ -95,7 +95,7 @@ public CommandParameterInfo(Parameter parameter) { return brigadierArguments; } - private boolean hasSuggestions(AbstractArgumentParser> parser) { + private boolean hasSuggestions(ArgumentParser, ?> parser) { return parser.getSuggestions() != null; } @@ -106,7 +106,7 @@ private boolean hasSuggestions(AbstractArgumentParser> parser) { * * @since 0.0.10 */ - public AbstractArgumentParser> getParser() { + public ArgumentParser, ?> getParser() { return parser; } diff --git a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/BlockPosArgumentParser.java b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/BlockPosArgumentParser.java index c885f865..02f8107f 100644 --- a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/BlockPosArgumentParser.java +++ b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/BlockPosArgumentParser.java @@ -7,38 +7,28 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl; -import com.mojang.brigadier.exceptions.CommandSyntaxException; - -import xyz.bitsquidd.bits.mc.command.argument.InputTypeContainer; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.paper.location.wrapper.BlockPos; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; -import java.util.List; -public final class BlockPosArgumentParser extends AbstractArgumentParser { +public final class BlockPosArgumentParser extends ArgumentParser { + + public record BlockPosData( + double x, + double y, + double z + ) {} public BlockPosArgumentParser() { - super(TypeSignature.of(BlockPos.class), "BlockPos"); + super(TypeSignature.of(BlockPos.class), "BlockPos", BlockPosData.class); } - @Override - public BlockPos parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - List inputs = inputValidation(inputObjects); - double x = (double)inputs.get(0); - double y = (double)inputs.get(1); - double z = (double)inputs.get(2); - return BlockPos.of(x, y, z); - } @Override - public List getInputTypes() { - return List.of( - new InputTypeContainer(TypeSignature.of(Double.class), "x"), - new InputTypeContainer(TypeSignature.of(Double.class), "y"), - new InputTypeContainer(TypeSignature.of(Double.class), "z") - ); + public BlockPos parse(BlockPosData data, BitsCommandContext> ctx) { + return BlockPos.of(data.x(), data.y(), data.z()); } } diff --git a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LocationArgumentParser.java b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LocationArgumentParser.java index eb438a13..0da13020 100644 --- a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LocationArgumentParser.java +++ b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LocationArgumentParser.java @@ -7,42 +7,31 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl; -import com.mojang.brigadier.exceptions.CommandSyntaxException; import org.bukkit.Location; import org.bukkit.World; -import xyz.bitsquidd.bits.mc.command.argument.InputTypeContainer; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; -import java.util.List; -public final class LocationArgumentParser extends AbstractArgumentParser { +public final class LocationArgumentParser extends ArgumentParser { + + public record LocationData( + double x, + double y, + double z, + World world + ) {} public LocationArgumentParser() { - super(TypeSignature.of(Location.class), "Location"); + super(TypeSignature.of(Location.class), "Location", LocationData.class); } - @Override - public Location parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - List inputs = inputValidation(inputObjects); - double x = (double)inputs.get(0); - double y = (double)inputs.get(1); - double z = (double)inputs.get(2); - World world = (World)inputs.get(3); - - return new Location(world, x, y, z); - } @Override - public List getInputTypes() { - return List.of( - new InputTypeContainer(TypeSignature.of(Double.class), "x"), - new InputTypeContainer(TypeSignature.of(Double.class), "y"), - new InputTypeContainer(TypeSignature.of(Double.class), "z"), - new InputTypeContainer(TypeSignature.of(World.class), "world") - ); + public Location parse(LocationData data, BitsCommandContext> ctx) { + return new Location(data.world(), data.x(), data.y(), data.z()); } } diff --git a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/PlayerCollectionArgumentParser.java b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/PlayerCollectionArgumentParser.java index 0606bd0c..373de809 100644 --- a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/PlayerCollectionArgumentParser.java +++ b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/PlayerCollectionArgumentParser.java @@ -15,8 +15,7 @@ import org.jetbrains.annotations.Nullable; import xyz.bitsquidd.bits.mc.command.PaperBitsCommandContext; -import xyz.bitsquidd.bits.mc.command.argument.InputTypeContainer; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; @@ -25,9 +24,9 @@ import java.util.List; import java.util.Objects; import java.util.function.Function; -import java.util.function.Supplier; -public final class PlayerCollectionArgumentParser extends AbstractArgumentParser> { + +public final class PlayerCollectionArgumentParser extends ArgumentParser, EntitySelector> { // TODO: Just pull from vanilla EntitySelector. Also pull the completion. private enum SelectorType { @@ -58,14 +57,12 @@ public Collection get(BitsCommandContext> ctx) { } public PlayerCollectionArgumentParser() { - super(TypeSignature.of(Collection.class, Player.class), "Players"); + super(TypeSignature.of(Collection.class, Player.class), "Players", EntitySelector.class); } @Override - public Collection parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - EntitySelector entitySelctor = singletonInputValidation(inputObjects, EntitySelector.class); - - return entitySelctor.findPlayers((CommandSourceStack)ctx.getBrigadierContext().getSource()) + public Collection parse(EntitySelector data, BitsCommandContext> ctx) throws CommandSyntaxException { + return data.findPlayers((CommandSourceStack)ctx.getBrigadierContext().getSource()) .stream() .map(playerEntity -> playerEntity.getBukkitEntity().getPlayer()) .map(Objects::requireNonNull) @@ -73,12 +70,7 @@ public Collection parse(List inputObjects, BitsCommandContext> } @Override - public List getInputTypes() { - return List.of(new InputTypeContainer(TypeSignature.of(EntitySelector.class), getArgumentName())); - } - - @Override - public Supplier> getSuggestions() { + public SuggestionSupplier getSuggestions() { List suggestions = new ArrayList<>(); suggestions.add(SelectorType.ALL.selector); suggestions.add(SelectorType.SELF.selector); diff --git a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/PlayerSingleArgumentParser.java b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/PlayerSingleArgumentParser.java index fc16ca69..98562bb2 100644 --- a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/PlayerSingleArgumentParser.java +++ b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/PlayerSingleArgumentParser.java @@ -13,41 +13,32 @@ import org.bukkit.Bukkit; import org.bukkit.entity.Player; -import xyz.bitsquidd.bits.mc.command.argument.InputTypeContainer; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.mc.command.exception.ExceptionBuilder; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; -import java.util.List; import java.util.Objects; -import java.util.function.Supplier; -public final class PlayerSingleArgumentParser extends AbstractArgumentParser { + +public final class PlayerSingleArgumentParser extends ArgumentParser { public PlayerSingleArgumentParser() { - super(TypeSignature.of(Player.class), "Player"); + super(TypeSignature.of(Player.class), "Player", EntitySelector.class); } @Override - public Player parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - EntitySelector entitySelctor = singletonInputValidation(inputObjects, EntitySelector.class); - - return entitySelctor.findPlayers((CommandSourceStack)ctx.getBrigadierContext().getSource()) + public Player parse(EntitySelector data, BitsCommandContext> ctx) throws CommandSyntaxException { + return data.findPlayers((CommandSourceStack)ctx.getBrigadierContext().getSource()) .stream() .map(playerEntity -> playerEntity.getBukkitEntity().getPlayer()) .map(Objects::requireNonNull) .findFirst() - .orElseThrow(() -> ExceptionBuilder.createCommandException("Player not found: " + entitySelctor)); - } - - @Override - public List getInputTypes() { - return List.of(new InputTypeContainer(TypeSignature.of(EntitySelector.class), getArgumentName())); + .orElseThrow(() -> ExceptionBuilder.createCommandException("Player not found: " + data)); } @Override - public Supplier> getSuggestions() { + public SuggestionSupplier getSuggestions() { return () -> Bukkit.getOnlinePlayers().stream().map(Player::getName).toList(); } diff --git a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/WorldArgumentParser.java b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/WorldArgumentParser.java index f0877c9e..ef734053 100644 --- a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/WorldArgumentParser.java +++ b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/WorldArgumentParser.java @@ -8,44 +8,31 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl; import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.kyori.adventure.key.Key; import org.bukkit.Bukkit; -import org.bukkit.NamespacedKey; import org.bukkit.World; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.mc.command.exception.ExceptionBuilder; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; -import java.util.List; -import java.util.function.Supplier; - -public final class WorldArgumentParser extends AbstractArgumentParser { +public final class WorldArgumentParser extends ArgumentParser { public WorldArgumentParser() { - super(TypeSignature.of(World.class), "World"); + super(TypeSignature.of(World.class), "World", Key.class); } @Override - public World parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - String inputString = singletonInputValidation(inputObjects, String.class); - - NamespacedKey key; - try { - key = NamespacedKey.fromString(inputString); - if (key == null) throw new IllegalArgumentException(); - } catch (IllegalArgumentException e) { - throw ExceptionBuilder.createCommandException("Invalid world key: " + inputString + "."); - } - - World world = Bukkit.getWorld(key); - if (world == null) throw ExceptionBuilder.createCommandException("World not found: " + inputString + "."); + public World parse(Key data, BitsCommandContext> ctx) throws CommandSyntaxException { + World world = Bukkit.getWorld(data); + if (world == null) throw ExceptionBuilder.createCommandException("World not found: " + data + "."); return world; } @Override - public Supplier> getSuggestions() { + public SuggestionSupplier getSuggestions() { return () -> Bukkit.getWorlds().stream().map(w -> "\"" + w.key() + "\"").toList(); } diff --git a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/WorldDefinitionArgumentParser.java b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/WorldDefinitionArgumentParser.java index 7506fd30..4bacdb50 100644 --- a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/WorldDefinitionArgumentParser.java +++ b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/WorldDefinitionArgumentParser.java @@ -10,10 +10,8 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.kyori.adventure.key.Key; import org.bukkit.Bukkit; -import org.bukkit.NamespacedKey; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; -import xyz.bitsquidd.bits.mc.command.exception.ExceptionBuilder; +import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.paper.wrapper.WorldDefinition; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; @@ -25,35 +23,25 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.function.Supplier; import java.util.stream.Stream; +import static xyz.bitsquidd.bits.paper.util.Keys.NSK; -public final class WorldDefinitionArgumentParser extends AbstractArgumentParser { + +public final class WorldDefinitionArgumentParser extends ArgumentParser { private static final Path DIMENSIONS_PATH = Bukkit.getWorldContainer().toPath().resolve("world/dimensions"); public WorldDefinitionArgumentParser() { - super(TypeSignature.of(WorldDefinition.class), "WorldDefinition"); + super(TypeSignature.of(WorldDefinition.class), "WorldDefinition", Key.class); } @Override - public WorldDefinition parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - String inputString = singletonInputValidation(inputObjects, String.class); - - NamespacedKey key; - try { - key = NamespacedKey.fromString(inputString); - if (key == null) throw new IllegalArgumentException(); - } catch (IllegalArgumentException e) { - throw ExceptionBuilder.createCommandException("Invalid world key: " + inputString + "."); - } - - WorldDefinition worldDefinition = WorldDefinition.of(key); - return worldDefinition; + public WorldDefinition parse(Key data, BitsCommandContext> ctx) throws CommandSyntaxException { + return WorldDefinition.of(NSK(data)); } @Override - public Supplier> getSuggestions() { + public SuggestionSupplier getSuggestions() { Set worldKeys = new HashSet<>(); try (Stream namespaces = Files.list(DIMENSIONS_PATH)) { namespaces.forEach(namespacePath -> { From 38057f19bc80156e1e19f74beb31fd9df31eb339 Mon Sep 17 00:00:00 2001 From: ImBit <151650938+ImBit@users.noreply.github.com> Date: Fri, 19 Jun 2026 15:04:47 +0100 Subject: [PATCH 14/15] :bug: Small command refactor fixes. --- .../mc/command/argument/parser/ArgumentParser.java | 5 +++-- .../argument/parser/SuggestionSupplier.java | 5 +++++ .../argument/parser/impl/LinkArgumentParser.java | 4 ++-- .../parser/impl/abs/EnumArgumentParser.java | 14 +++++++------- .../parser/impl/generic/GenericEnumParser.java | 2 +- .../impl/primitive/BooleanArgumentParser.java | 2 +- .../impl/PlayerCollectionArgumentParser.java | 3 ++- .../parser/impl/PlayerSingleArgumentParser.java | 3 ++- .../argument/parser/impl/WorldArgumentParser.java | 3 ++- .../parser/impl/WorldDefinitionArgumentParser.java | 6 +++--- 10 files changed, 28 insertions(+), 19 deletions(-) diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/ArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/ArgumentParser.java index 3d755312..ae56bab9 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/ArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/ArgumentParser.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Objects; /** @@ -53,7 +54,7 @@ public abstract class ArgumentParser { private final TypeSignature> typeSignature; // The type signature this parser handles private final String argumentName; // The name of the argument, used while displaying suggestions private final Class dataClass; // The class of the input data type - private final Constructor recordConstructor; + private final @Nullable Constructor recordConstructor; /** * @param typeSignature the expected type this parser handles @@ -147,7 +148,7 @@ public final D toData(List inputObjects) throws CommandSyntaxException { if (!dataClass.isRecord()) return dataClass.cast(validated[0]); try { - return recordConstructor.newInstance(validated); + return Objects.requireNonNull(this.recordConstructor).newInstance(validated); } catch (ReflectiveOperationException e) { throw ExceptionBuilder.createCommandException("Failed to construct " + dataClass.getSimpleName() + ": " + e.getMessage()); } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/SuggestionSupplier.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/SuggestionSupplier.java index bc128270..411eeb82 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/SuggestionSupplier.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/SuggestionSupplier.java @@ -17,4 +17,9 @@ public interface SuggestionSupplier { List getSuggestions(BitsCommandContext ctx); + + static SuggestionSupplier empty() { + return ctx -> List.of(); + } + } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LinkArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LinkArgumentParser.java index 0e4bd58d..60671b53 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LinkArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LinkArgumentParser.java @@ -15,7 +15,7 @@ import xyz.bitsquidd.bits.wrapper.Link; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; -import java.util.stream.Stream; +import java.util.List; //TODO add better validation for this, enum for a type? WWW. HTTPS:// etc.? @@ -40,7 +40,7 @@ public Link parse(String data, BitsCommandContext> ctx) throws CommandSyntaxEx @Override public SuggestionSupplier getSuggestions() { - return () -> Stream.of("https://", "http://", "www.").toList(); + return ctx -> List.of("https://", "http://", "www."); } } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/abs/EnumArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/abs/EnumArgumentParser.java index 27014b53..560cee41 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/abs/EnumArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/abs/EnumArgumentParser.java @@ -35,12 +35,12 @@ * } * } * - * @param the specific enum type + * @param
+ * This class serves as the foundation for all custom argument parsing within the Bits command framework. + * Implementations define how string inputs or other basic types from Brigadier are structurally resolved + * into complex objects, and optionally provide tab-completion suggestions. + *
+ * Example parser implementation: + *
{@code + * public class PlayerArgumentParser extends AbstractArgumentParser { + * public PlayerArgumentParser() { + * super(TypeSignature.of(Player.class), "player_name"); + * } + * + * // Override methods to dictate parsing logic and input types. + * } + * }
+ * In the case a non-vanilla primitive is passed in, we expect a parser to be present for this.
+ * For example:
+ * This method evaluates {@link #getSuggestions} to dynamically supply tab completion results. + * + * @param the command source type + * + * @return the suggestion provider context for Brigadier nodes + * + * @since 0.0.10 + */ + public final SuggestionProvider createSuggestionProvider() { + SuggestionSupplier suggestionSupplier = getSuggestions(); + if (suggestionSupplier == null) return (ctx, builder) -> builder.buildFuture(); // No suggestions available + BitsCommandManager manager = BitsCommandManager.get(); + + return (ctx, builder) -> { + List suggestions = suggestionSupplier.getSuggestions(manager.createContext(ctx)); + String remaining = builder.getRemaining(); + + for (String suggestion : suggestions) { + if (suggestion.equalsIgnoreCase(remaining)) { + builder.suggest(suggestion); + } + } + + return builder.buildFuture(); + }; + } + + /** + * Returns a dynamically loaded list of suggestions for the argument at a given context state. + * + * @return a supplier providing available string suggestions, or null if none exist + * + * @since 0.0.10 + */ + public @Nullable SuggestionSupplier getSuggestions() { + return null; + } + + + /** + * Retrieves the core type signature handled by this parser. + * + * @return the type signature + * + * @since 0.0.10 + */ + public TypeSignature> getTypeSignature() { + return typeSignature; + } + + /** + * Retrieves the argument name meant for display in syntax sequences. + * + * @return the argument label + * + * @since 0.0.10 + */ + public String getArgumentName() { + return argumentName; + } + +} diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/GreedyStringArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/GreedyStringArgumentParser.java index e1aedc2a..7546c63d 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/GreedyStringArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/GreedyStringArgumentParser.java @@ -8,14 +8,11 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl; import xyz.bitsquidd.bits.mc.command.BrigadierTreeGenerator; -import xyz.bitsquidd.bits.mc.command.argument.InputTypeContainer; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.wrapper.GreedyString; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; -import java.util.List; /** * Argument parser for {@link GreedyString} values. @@ -24,20 +21,15 @@ * * @since 0.0.10 */ -@ArgumentParser -public final class GreedyStringArgumentParser extends AbstractArgumentParser { - public GreedyStringArgumentParser() { - super(TypeSignature.of(GreedyString.class), "String..."); - } - @Override - public GreedyString parse(List inputObjects, BitsCommandContext> ctx) { - return GreedyString.of((String)inputObjects.getFirst()); // Note: can't use singletonInputValidation as GreedyString is special... +public final class GreedyStringArgumentParser extends ArgumentParser { + public GreedyStringArgumentParser() { + super(TypeSignature.of(GreedyString.class), "String...", String.class); } @Override - public List getInputTypes() { - return List.of(new InputTypeContainer(TypeSignature.of(GreedyString.class), getArgumentName())); + public GreedyString parse(String data, BitsCommandContext> ctx) { + return GreedyString.of(data); } } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/KeyArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/KeyArgumentParser.java index 3bce5f65..0664f6b0 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/KeyArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/KeyArgumentParser.java @@ -10,7 +10,7 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.kyori.adventure.key.Key; -import xyz.bitsquidd.bits.mc.command.argument.parser.DefaultArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.BasicArgumentParser; import xyz.bitsquidd.bits.mc.command.argument.parser.SuggestionSupplier; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; @@ -25,7 +25,7 @@ * @since 0.0.20 */ -public final class KeyArgumentParser extends DefaultArgumentParser { +public final class KeyArgumentParser extends BasicArgumentParser { public KeyArgumentParser() { super(TypeSignature.of(Key.class), "Key"); } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LinkArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LinkArgumentParser.java index e15fe7f0..0e4bd58d 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LinkArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LinkArgumentParser.java @@ -9,14 +9,12 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; -import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.BasicArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.SuggestionSupplier; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.wrapper.Link; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; -import java.util.List; -import java.util.function.Supplier; import java.util.stream.Stream; @@ -29,20 +27,19 @@ * * @since 0.0.10 */ -@ArgumentParser -public final class LinkArgumentParser extends AbstractArgumentParser { + +public final class LinkArgumentParser extends BasicArgumentParser { public LinkArgumentParser() { super(TypeSignature.of(Link.class), "URL"); } @Override - public Link parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - String inputString = singletonInputValidation(inputObjects, String.class); - return Link.of(inputString); + public Link parse(String data, BitsCommandContext> ctx) throws CommandSyntaxException { + return Link.of(data); } @Override - public Supplier> getSuggestions() { + public SuggestionSupplier getSuggestions() { return () -> Stream.of("https://", "http://", "www.").toList(); } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/UUIDArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/UUIDArgumentParser.java index 677a9e95..327b6786 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/UUIDArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/UUIDArgumentParser.java @@ -9,7 +9,7 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; -import xyz.bitsquidd.bits.mc.command.argument.parser.DefaultArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.BasicArgumentParser; import xyz.bitsquidd.bits.mc.command.argument.parser.SuggestionSupplier; import xyz.bitsquidd.bits.mc.command.exception.ExceptionBuilder; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; @@ -34,7 +34,7 @@ * @since 0.0.10 */ -public final class UUIDArgumentParser extends DefaultArgumentParser { +public final class UUIDArgumentParser extends BasicArgumentParser { private static final List DASH_POSITIONS = List.of(8, 12, 16, 20); private static final char DASH_CHAR = '-'; private static final int HEX_CHAR_COUNT = 32; diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/VoidArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/VoidArgumentParser.java index 2f039616..cb7afb28 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/VoidArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/VoidArgumentParser.java @@ -7,7 +7,7 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl; -import xyz.bitsquidd.bits.mc.command.argument.parser.DefaultArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.BasicArgumentParser; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; @@ -20,7 +20,7 @@ * @since 0.0.10 */ -public final class VoidArgumentParser extends DefaultArgumentParser { +public final class VoidArgumentParser extends BasicArgumentParser { public static final VoidArgumentParser INSTANCE = new VoidArgumentParser(); private VoidArgumentParser() { diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/abs/AbstractEnumArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/abs/EnumArgumentParser.java similarity index 72% rename from minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/abs/AbstractEnumArgumentParser.java rename to minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/abs/EnumArgumentParser.java index 3242f6e7..27014b53 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/abs/AbstractEnumArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/abs/EnumArgumentParser.java @@ -10,15 +10,16 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import org.jetbrains.annotations.Nullable; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.BasicArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.SuggestionSupplier; import xyz.bitsquidd.bits.mc.command.exception.ExceptionBuilder; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; import java.util.List; -import java.util.function.Supplier; import java.util.stream.Stream; + /** * Base abstract parser providing common parsing and suggestion logic for enum types. * @@ -38,7 +39,7 @@ * * @since 0.0.10 */ -public abstract class AbstractEnumArgumentParser> extends AbstractArgumentParser { +public abstract class EnumArgumentParser> extends BasicArgumentParser { private final Class enumClass; /** @@ -47,28 +48,26 @@ public abstract class AbstractEnumArgumentParser> extends Abst * @throws IllegalArgumentException if the provided class is not an enum * @since 0.0.10 */ - public AbstractEnumArgumentParser(Class enumClass) { + public EnumArgumentParser(Class enumClass) { super(TypeSignature.of(Enum.class), enumClass.getName()); this.enumClass = enumClass; if (!enumClass.isEnum()) throw new IllegalArgumentException("Provided class " + enumClass.getName() + " is not an enum!"); } @Override - public T parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - String inputString = singletonInputValidation(inputObjects, String.class); - + public T parse(String data, BitsCommandContext> ctx) throws CommandSyntaxException { T enumValue; try { - enumValue = Enum.valueOf(enumClass, inputString); + enumValue = Enum.valueOf(enumClass, data); } catch (IllegalArgumentException e) { - throw ExceptionBuilder.createCommandException(inputString + " is not a valid " + enumClass.getSimpleName() + "."); + throw ExceptionBuilder.createCommandException(data + " is not a valid " + enumClass.getSimpleName() + "."); } return enumValue; } @Override - public @Nullable Supplier> getSuggestions() { + public @Nullable SuggestionSupplier getSuggestions() { return () -> enumClass.isEnum() ? Stream.of(enumClass.getEnumConstants()).map(Enum::name).toList() : List.of(); } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/generic/GenericEnumParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/generic/GenericEnumParser.java index 0f522bcf..27daae97 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/generic/GenericEnumParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/generic/GenericEnumParser.java @@ -9,21 +9,21 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; -import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; -import xyz.bitsquidd.bits.mc.command.argument.parser.impl.abs.AbstractEnumArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.BasicArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.SuggestionSupplier; +import xyz.bitsquidd.bits.mc.command.argument.parser.impl.abs.EnumArgumentParser; import xyz.bitsquidd.bits.mc.command.exception.ExceptionBuilder; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; +import xyz.bitsquidd.bits.util.wrapper.Enums; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; -import java.util.List; -import java.util.function.Supplier; import java.util.stream.Stream; + /** * A fallback, generically instantiated parser that handles unmapped enum types automatically. * - * Developer Note: Custom enum parsers should override {@link AbstractEnumArgumentParser} + * Developer Note: Custom enum parsers should override {@link EnumArgumentParser} * if you want more fine-grained control over enum arguments and tab completion. * * This implementation serves as a basic parser that is fallen back upon when no specific enum parser is available. @@ -32,9 +32,8 @@ * * @since 0.0.10 */ -@ArgumentParser -public final class GenericEnumParser> extends AbstractArgumentParser { +public final class GenericEnumParser> extends BasicArgumentParser { private final Class enumClass; public GenericEnumParser(Class enumClass) { @@ -43,18 +42,13 @@ public GenericEnumParser(Class enumClass) { } @Override - public E parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - String inputString = singletonInputValidation(inputObjects, String.class); - - for (E constant : enumClass.getEnumConstants()) { - if (constant.name().equalsIgnoreCase(inputString)) return constant; - } - - throw ExceptionBuilder.createCommandException("Enum constant not found: " + inputString + " for enum " + enumClass.getSimpleName() + "."); + public E parse(String data, BitsCommandContext> ctx) throws CommandSyntaxException { + return Enums.getFromIdentifier(enumClass, data) + .orElseThrow(() -> ExceptionBuilder.createCommandException("Enum constant not found: " + data + " for enum " + enumClass.getSimpleName() + ".")); } @Override - public Supplier> getSuggestions() { + public SuggestionSupplier getSuggestions() { return () -> Stream.of(enumClass.getEnumConstants()).map(Enum::name).toList(); } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/BooleanArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/BooleanArgumentParser.java index 444646e2..9b2fb11d 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/BooleanArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/BooleanArgumentParser.java @@ -7,17 +7,17 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl.primitive; -import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.SuggestionSupplier; import java.util.List; -import java.util.function.Supplier; + /** * Argument parser for Boolean values. * * @since 0.0.10 */ -@ArgumentParser + public final class BooleanArgumentParser extends PrimitiveArgumentParser { public BooleanArgumentParser() { @@ -25,7 +25,7 @@ public BooleanArgumentParser() { } @Override - public Supplier> getSuggestions() { + public SuggestionSupplier getSuggestions() { return () -> List.of("true", "false"); } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/DoubleArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/DoubleArgumentParser.java index 987fa30e..44dd84c1 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/DoubleArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/DoubleArgumentParser.java @@ -7,14 +7,13 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl.primitive; -import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; /** * Argument parser for Double values. * * @since 0.0.10 */ -@ArgumentParser + public final class DoubleArgumentParser extends PrimitiveArgumentParser { public DoubleArgumentParser() { super(Double.class, "Double"); diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/FloatArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/FloatArgumentParser.java index b0bc401d..22162ca9 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/FloatArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/FloatArgumentParser.java @@ -7,14 +7,13 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl.primitive; -import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; /** * Argument parser for Float values. * * @since 0.0.10 */ -@ArgumentParser + public final class FloatArgumentParser extends PrimitiveArgumentParser { public FloatArgumentParser() { super(Float.class, "Float"); diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/IntegerArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/IntegerArgumentParser.java index 79be0c9a..c04430a7 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/IntegerArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/IntegerArgumentParser.java @@ -7,14 +7,13 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl.primitive; -import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; /** * Argument parser for Integer values. * * @since 0.0.10 */ -@ArgumentParser + public final class IntegerArgumentParser extends PrimitiveArgumentParser { public IntegerArgumentParser() { diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/LongArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/LongArgumentParser.java index d59ce089..8e4e88df 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/LongArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/LongArgumentParser.java @@ -7,14 +7,13 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl.primitive; -import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; /** * Argument parser for Long values. * * @since 0.0.10 */ -@ArgumentParser + public final class LongArgumentParser extends PrimitiveArgumentParser { public LongArgumentParser() { diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/PrimitiveArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/PrimitiveArgumentParser.java index 12fb813c..ab6d26bc 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/PrimitiveArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/PrimitiveArgumentParser.java @@ -9,12 +9,10 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; -import xyz.bitsquidd.bits.mc.command.argument.InputTypeContainer; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; -import java.util.List; /** * A foundation parser designed specifically for types that correspond to underlying Brigadier primitives. @@ -26,21 +24,15 @@ * * @since 0.0.10 */ -public abstract class PrimitiveArgumentParser extends AbstractArgumentParser { +public abstract class PrimitiveArgumentParser extends ArgumentParser { protected PrimitiveArgumentParser(Class outputClass, String argumentName) { - super(TypeSignature.of(outputClass), argumentName); + super(TypeSignature.of(outputClass), argumentName, outputClass); } @Override - @SuppressWarnings("unchecked") - public final O parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - return (O)singletonInputValidation(inputObjects, getTypeSignature().toRawType()); - } - - @Override - public final List getInputTypes() { - return List.of(new InputTypeContainer(getTypeSignature(), getArgumentName())); + public final O parse(O data, BitsCommandContext> ctx) throws CommandSyntaxException { + return data; } } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/StringArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/StringArgumentParser.java index c8373738..fd241bea 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/StringArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/StringArgumentParser.java @@ -7,14 +7,13 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl.primitive; -import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; /** * Argument parser for String values. * * @since 0.0.10 */ -@ArgumentParser + public final class StringArgumentParser extends PrimitiveArgumentParser { public StringArgumentParser() { super(String.class, "String"); diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/util/CommandParameterInfo.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/util/CommandParameterInfo.java index 145cdc0c..346be50f 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/util/CommandParameterInfo.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/util/CommandParameterInfo.java @@ -12,7 +12,7 @@ import xyz.bitsquidd.bits.mc.command.BitsCommandManager; import xyz.bitsquidd.bits.mc.command.argument.BrigadierArgumentMapping; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; import java.lang.reflect.Parameter; @@ -39,7 +39,7 @@ public class CommandParameterInfo { private final TypeSignature> typeSignature; // TypeSignature of the parameter - private final AbstractArgumentParser> parser; + private final ArgumentParser, ?> parser; private final List heldArguments = new ArrayList<>(); // Direct mapping from the custom args to brigadier ArgumentTypes @@ -81,13 +81,13 @@ public CommandParameterInfo(Parameter parameter) { if (useArgSuggestions) { TypeSignature> inputType = parser.getInputTypes().get(i).typeSignature(); - AbstractArgumentParser> inputParser = BitsCommandManager.get().getArgumentRegistry().getParser(inputType); + ArgumentParser, ?> inputParser = BitsCommandManager.get().getArgumentRegistry().getParser(inputType); // Use the input-specific parser's suggestions - if (hasSuggestions(inputParser)) argumentBuilder.suggests(inputParser.getSuggestionProvider()); + if (hasSuggestions(inputParser)) argumentBuilder.suggests(inputParser.createSuggestionProvider()); } else { // Use the main parser's suggestions - if (hasSuggestions(parser)) argumentBuilder.suggests(parser.getSuggestionProvider()); + if (hasSuggestions(parser)) argumentBuilder.suggests(parser.createSuggestionProvider()); } brigadierArguments.add(argumentBuilder); @@ -95,7 +95,7 @@ public CommandParameterInfo(Parameter parameter) { return brigadierArguments; } - private boolean hasSuggestions(AbstractArgumentParser> parser) { + private boolean hasSuggestions(ArgumentParser, ?> parser) { return parser.getSuggestions() != null; } @@ -106,7 +106,7 @@ private boolean hasSuggestions(AbstractArgumentParser> parser) { * * @since 0.0.10 */ - public AbstractArgumentParser> getParser() { + public ArgumentParser, ?> getParser() { return parser; } diff --git a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/BlockPosArgumentParser.java b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/BlockPosArgumentParser.java index c885f865..02f8107f 100644 --- a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/BlockPosArgumentParser.java +++ b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/BlockPosArgumentParser.java @@ -7,38 +7,28 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl; -import com.mojang.brigadier.exceptions.CommandSyntaxException; - -import xyz.bitsquidd.bits.mc.command.argument.InputTypeContainer; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.paper.location.wrapper.BlockPos; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; -import java.util.List; -public final class BlockPosArgumentParser extends AbstractArgumentParser { +public final class BlockPosArgumentParser extends ArgumentParser { + + public record BlockPosData( + double x, + double y, + double z + ) {} public BlockPosArgumentParser() { - super(TypeSignature.of(BlockPos.class), "BlockPos"); + super(TypeSignature.of(BlockPos.class), "BlockPos", BlockPosData.class); } - @Override - public BlockPos parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - List inputs = inputValidation(inputObjects); - double x = (double)inputs.get(0); - double y = (double)inputs.get(1); - double z = (double)inputs.get(2); - return BlockPos.of(x, y, z); - } @Override - public List getInputTypes() { - return List.of( - new InputTypeContainer(TypeSignature.of(Double.class), "x"), - new InputTypeContainer(TypeSignature.of(Double.class), "y"), - new InputTypeContainer(TypeSignature.of(Double.class), "z") - ); + public BlockPos parse(BlockPosData data, BitsCommandContext> ctx) { + return BlockPos.of(data.x(), data.y(), data.z()); } } diff --git a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LocationArgumentParser.java b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LocationArgumentParser.java index eb438a13..0da13020 100644 --- a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LocationArgumentParser.java +++ b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LocationArgumentParser.java @@ -7,42 +7,31 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl; -import com.mojang.brigadier.exceptions.CommandSyntaxException; import org.bukkit.Location; import org.bukkit.World; -import xyz.bitsquidd.bits.mc.command.argument.InputTypeContainer; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; -import java.util.List; -public final class LocationArgumentParser extends AbstractArgumentParser { +public final class LocationArgumentParser extends ArgumentParser { + + public record LocationData( + double x, + double y, + double z, + World world + ) {} public LocationArgumentParser() { - super(TypeSignature.of(Location.class), "Location"); + super(TypeSignature.of(Location.class), "Location", LocationData.class); } - @Override - public Location parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - List inputs = inputValidation(inputObjects); - double x = (double)inputs.get(0); - double y = (double)inputs.get(1); - double z = (double)inputs.get(2); - World world = (World)inputs.get(3); - - return new Location(world, x, y, z); - } @Override - public List getInputTypes() { - return List.of( - new InputTypeContainer(TypeSignature.of(Double.class), "x"), - new InputTypeContainer(TypeSignature.of(Double.class), "y"), - new InputTypeContainer(TypeSignature.of(Double.class), "z"), - new InputTypeContainer(TypeSignature.of(World.class), "world") - ); + public Location parse(LocationData data, BitsCommandContext> ctx) { + return new Location(data.world(), data.x(), data.y(), data.z()); } } diff --git a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/PlayerCollectionArgumentParser.java b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/PlayerCollectionArgumentParser.java index 0606bd0c..373de809 100644 --- a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/PlayerCollectionArgumentParser.java +++ b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/PlayerCollectionArgumentParser.java @@ -15,8 +15,7 @@ import org.jetbrains.annotations.Nullable; import xyz.bitsquidd.bits.mc.command.PaperBitsCommandContext; -import xyz.bitsquidd.bits.mc.command.argument.InputTypeContainer; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; @@ -25,9 +24,9 @@ import java.util.List; import java.util.Objects; import java.util.function.Function; -import java.util.function.Supplier; -public final class PlayerCollectionArgumentParser extends AbstractArgumentParser> { + +public final class PlayerCollectionArgumentParser extends ArgumentParser, EntitySelector> { // TODO: Just pull from vanilla EntitySelector. Also pull the completion. private enum SelectorType { @@ -58,14 +57,12 @@ public Collection get(BitsCommandContext> ctx) { } public PlayerCollectionArgumentParser() { - super(TypeSignature.of(Collection.class, Player.class), "Players"); + super(TypeSignature.of(Collection.class, Player.class), "Players", EntitySelector.class); } @Override - public Collection parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - EntitySelector entitySelctor = singletonInputValidation(inputObjects, EntitySelector.class); - - return entitySelctor.findPlayers((CommandSourceStack)ctx.getBrigadierContext().getSource()) + public Collection parse(EntitySelector data, BitsCommandContext> ctx) throws CommandSyntaxException { + return data.findPlayers((CommandSourceStack)ctx.getBrigadierContext().getSource()) .stream() .map(playerEntity -> playerEntity.getBukkitEntity().getPlayer()) .map(Objects::requireNonNull) @@ -73,12 +70,7 @@ public Collection parse(List inputObjects, BitsCommandContext> } @Override - public List getInputTypes() { - return List.of(new InputTypeContainer(TypeSignature.of(EntitySelector.class), getArgumentName())); - } - - @Override - public Supplier> getSuggestions() { + public SuggestionSupplier getSuggestions() { List suggestions = new ArrayList<>(); suggestions.add(SelectorType.ALL.selector); suggestions.add(SelectorType.SELF.selector); diff --git a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/PlayerSingleArgumentParser.java b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/PlayerSingleArgumentParser.java index fc16ca69..98562bb2 100644 --- a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/PlayerSingleArgumentParser.java +++ b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/PlayerSingleArgumentParser.java @@ -13,41 +13,32 @@ import org.bukkit.Bukkit; import org.bukkit.entity.Player; -import xyz.bitsquidd.bits.mc.command.argument.InputTypeContainer; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.mc.command.exception.ExceptionBuilder; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; -import java.util.List; import java.util.Objects; -import java.util.function.Supplier; -public final class PlayerSingleArgumentParser extends AbstractArgumentParser { + +public final class PlayerSingleArgumentParser extends ArgumentParser { public PlayerSingleArgumentParser() { - super(TypeSignature.of(Player.class), "Player"); + super(TypeSignature.of(Player.class), "Player", EntitySelector.class); } @Override - public Player parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - EntitySelector entitySelctor = singletonInputValidation(inputObjects, EntitySelector.class); - - return entitySelctor.findPlayers((CommandSourceStack)ctx.getBrigadierContext().getSource()) + public Player parse(EntitySelector data, BitsCommandContext> ctx) throws CommandSyntaxException { + return data.findPlayers((CommandSourceStack)ctx.getBrigadierContext().getSource()) .stream() .map(playerEntity -> playerEntity.getBukkitEntity().getPlayer()) .map(Objects::requireNonNull) .findFirst() - .orElseThrow(() -> ExceptionBuilder.createCommandException("Player not found: " + entitySelctor)); - } - - @Override - public List getInputTypes() { - return List.of(new InputTypeContainer(TypeSignature.of(EntitySelector.class), getArgumentName())); + .orElseThrow(() -> ExceptionBuilder.createCommandException("Player not found: " + data)); } @Override - public Supplier> getSuggestions() { + public SuggestionSupplier getSuggestions() { return () -> Bukkit.getOnlinePlayers().stream().map(Player::getName).toList(); } diff --git a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/WorldArgumentParser.java b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/WorldArgumentParser.java index f0877c9e..ef734053 100644 --- a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/WorldArgumentParser.java +++ b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/WorldArgumentParser.java @@ -8,44 +8,31 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl; import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.kyori.adventure.key.Key; import org.bukkit.Bukkit; -import org.bukkit.NamespacedKey; import org.bukkit.World; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.mc.command.exception.ExceptionBuilder; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; -import java.util.List; -import java.util.function.Supplier; - -public final class WorldArgumentParser extends AbstractArgumentParser { +public final class WorldArgumentParser extends ArgumentParser { public WorldArgumentParser() { - super(TypeSignature.of(World.class), "World"); + super(TypeSignature.of(World.class), "World", Key.class); } @Override - public World parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - String inputString = singletonInputValidation(inputObjects, String.class); - - NamespacedKey key; - try { - key = NamespacedKey.fromString(inputString); - if (key == null) throw new IllegalArgumentException(); - } catch (IllegalArgumentException e) { - throw ExceptionBuilder.createCommandException("Invalid world key: " + inputString + "."); - } - - World world = Bukkit.getWorld(key); - if (world == null) throw ExceptionBuilder.createCommandException("World not found: " + inputString + "."); + public World parse(Key data, BitsCommandContext> ctx) throws CommandSyntaxException { + World world = Bukkit.getWorld(data); + if (world == null) throw ExceptionBuilder.createCommandException("World not found: " + data + "."); return world; } @Override - public Supplier> getSuggestions() { + public SuggestionSupplier getSuggestions() { return () -> Bukkit.getWorlds().stream().map(w -> "\"" + w.key() + "\"").toList(); } diff --git a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/WorldDefinitionArgumentParser.java b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/WorldDefinitionArgumentParser.java index 7506fd30..4bacdb50 100644 --- a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/WorldDefinitionArgumentParser.java +++ b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/WorldDefinitionArgumentParser.java @@ -10,10 +10,8 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.kyori.adventure.key.Key; import org.bukkit.Bukkit; -import org.bukkit.NamespacedKey; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; -import xyz.bitsquidd.bits.mc.command.exception.ExceptionBuilder; +import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.paper.wrapper.WorldDefinition; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; @@ -25,35 +23,25 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.function.Supplier; import java.util.stream.Stream; +import static xyz.bitsquidd.bits.paper.util.Keys.NSK; -public final class WorldDefinitionArgumentParser extends AbstractArgumentParser { + +public final class WorldDefinitionArgumentParser extends ArgumentParser { private static final Path DIMENSIONS_PATH = Bukkit.getWorldContainer().toPath().resolve("world/dimensions"); public WorldDefinitionArgumentParser() { - super(TypeSignature.of(WorldDefinition.class), "WorldDefinition"); + super(TypeSignature.of(WorldDefinition.class), "WorldDefinition", Key.class); } @Override - public WorldDefinition parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - String inputString = singletonInputValidation(inputObjects, String.class); - - NamespacedKey key; - try { - key = NamespacedKey.fromString(inputString); - if (key == null) throw new IllegalArgumentException(); - } catch (IllegalArgumentException e) { - throw ExceptionBuilder.createCommandException("Invalid world key: " + inputString + "."); - } - - WorldDefinition worldDefinition = WorldDefinition.of(key); - return worldDefinition; + public WorldDefinition parse(Key data, BitsCommandContext> ctx) throws CommandSyntaxException { + return WorldDefinition.of(NSK(data)); } @Override - public Supplier> getSuggestions() { + public SuggestionSupplier getSuggestions() { Set worldKeys = new HashSet<>(); try (Stream namespaces = Files.list(DIMENSIONS_PATH)) { namespaces.forEach(namespacePath -> { From 38057f19bc80156e1e19f74beb31fd9df31eb339 Mon Sep 17 00:00:00 2001 From: ImBit <151650938+ImBit@users.noreply.github.com> Date: Fri, 19 Jun 2026 15:04:47 +0100 Subject: [PATCH 14/15] :bug: Small command refactor fixes. --- .../mc/command/argument/parser/ArgumentParser.java | 5 +++-- .../argument/parser/SuggestionSupplier.java | 5 +++++ .../argument/parser/impl/LinkArgumentParser.java | 4 ++-- .../parser/impl/abs/EnumArgumentParser.java | 14 +++++++------- .../parser/impl/generic/GenericEnumParser.java | 2 +- .../impl/primitive/BooleanArgumentParser.java | 2 +- .../impl/PlayerCollectionArgumentParser.java | 3 ++- .../parser/impl/PlayerSingleArgumentParser.java | 3 ++- .../argument/parser/impl/WorldArgumentParser.java | 3 ++- .../parser/impl/WorldDefinitionArgumentParser.java | 6 +++--- 10 files changed, 28 insertions(+), 19 deletions(-) diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/ArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/ArgumentParser.java index 3d755312..ae56bab9 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/ArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/ArgumentParser.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Objects; /** @@ -53,7 +54,7 @@ public abstract class ArgumentParser { private final TypeSignature> typeSignature; // The type signature this parser handles private final String argumentName; // The name of the argument, used while displaying suggestions private final Class dataClass; // The class of the input data type - private final Constructor recordConstructor; + private final @Nullable Constructor recordConstructor; /** * @param typeSignature the expected type this parser handles @@ -147,7 +148,7 @@ public final D toData(List inputObjects) throws CommandSyntaxException { if (!dataClass.isRecord()) return dataClass.cast(validated[0]); try { - return recordConstructor.newInstance(validated); + return Objects.requireNonNull(this.recordConstructor).newInstance(validated); } catch (ReflectiveOperationException e) { throw ExceptionBuilder.createCommandException("Failed to construct " + dataClass.getSimpleName() + ": " + e.getMessage()); } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/SuggestionSupplier.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/SuggestionSupplier.java index bc128270..411eeb82 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/SuggestionSupplier.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/SuggestionSupplier.java @@ -17,4 +17,9 @@ public interface SuggestionSupplier { List getSuggestions(BitsCommandContext ctx); + + static SuggestionSupplier empty() { + return ctx -> List.of(); + } + } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LinkArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LinkArgumentParser.java index 0e4bd58d..60671b53 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LinkArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LinkArgumentParser.java @@ -15,7 +15,7 @@ import xyz.bitsquidd.bits.wrapper.Link; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; -import java.util.stream.Stream; +import java.util.List; //TODO add better validation for this, enum for a type? WWW. HTTPS:// etc.? @@ -40,7 +40,7 @@ public Link parse(String data, BitsCommandContext> ctx) throws CommandSyntaxEx @Override public SuggestionSupplier getSuggestions() { - return () -> Stream.of("https://", "http://", "www.").toList(); + return ctx -> List.of("https://", "http://", "www."); } } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/abs/EnumArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/abs/EnumArgumentParser.java index 27014b53..560cee41 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/abs/EnumArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/abs/EnumArgumentParser.java @@ -35,12 +35,12 @@ * } * } * - * @param the specific enum type + * @param
@@ -38,7 +39,7 @@ * * @since 0.0.10 */ -public abstract class AbstractEnumArgumentParser> extends AbstractArgumentParser { +public abstract class EnumArgumentParser> extends BasicArgumentParser { private final Class enumClass; /** @@ -47,28 +48,26 @@ public abstract class AbstractEnumArgumentParser> extends Abst * @throws IllegalArgumentException if the provided class is not an enum * @since 0.0.10 */ - public AbstractEnumArgumentParser(Class enumClass) { + public EnumArgumentParser(Class enumClass) { super(TypeSignature.of(Enum.class), enumClass.getName()); this.enumClass = enumClass; if (!enumClass.isEnum()) throw new IllegalArgumentException("Provided class " + enumClass.getName() + " is not an enum!"); } @Override - public T parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - String inputString = singletonInputValidation(inputObjects, String.class); - + public T parse(String data, BitsCommandContext> ctx) throws CommandSyntaxException { T enumValue; try { - enumValue = Enum.valueOf(enumClass, inputString); + enumValue = Enum.valueOf(enumClass, data); } catch (IllegalArgumentException e) { - throw ExceptionBuilder.createCommandException(inputString + " is not a valid " + enumClass.getSimpleName() + "."); + throw ExceptionBuilder.createCommandException(data + " is not a valid " + enumClass.getSimpleName() + "."); } return enumValue; } @Override - public @Nullable Supplier> getSuggestions() { + public @Nullable SuggestionSupplier getSuggestions() { return () -> enumClass.isEnum() ? Stream.of(enumClass.getEnumConstants()).map(Enum::name).toList() : List.of(); } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/generic/GenericEnumParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/generic/GenericEnumParser.java index 0f522bcf..27daae97 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/generic/GenericEnumParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/generic/GenericEnumParser.java @@ -9,21 +9,21 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; -import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; -import xyz.bitsquidd.bits.mc.command.argument.parser.impl.abs.AbstractEnumArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.BasicArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.SuggestionSupplier; +import xyz.bitsquidd.bits.mc.command.argument.parser.impl.abs.EnumArgumentParser; import xyz.bitsquidd.bits.mc.command.exception.ExceptionBuilder; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; +import xyz.bitsquidd.bits.util.wrapper.Enums; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; -import java.util.List; -import java.util.function.Supplier; import java.util.stream.Stream; + /** * A fallback, generically instantiated parser that handles unmapped enum types automatically. * - * Developer Note: Custom enum parsers should override {@link AbstractEnumArgumentParser} + * Developer Note: Custom enum parsers should override {@link EnumArgumentParser} * if you want more fine-grained control over enum arguments and tab completion. * * This implementation serves as a basic parser that is fallen back upon when no specific enum parser is available. @@ -32,9 +32,8 @@ * * @since 0.0.10 */ -@ArgumentParser -public final class GenericEnumParser> extends AbstractArgumentParser { +public final class GenericEnumParser> extends BasicArgumentParser { private final Class enumClass; public GenericEnumParser(Class enumClass) { @@ -43,18 +42,13 @@ public GenericEnumParser(Class enumClass) { } @Override - public E parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - String inputString = singletonInputValidation(inputObjects, String.class); - - for (E constant : enumClass.getEnumConstants()) { - if (constant.name().equalsIgnoreCase(inputString)) return constant; - } - - throw ExceptionBuilder.createCommandException("Enum constant not found: " + inputString + " for enum " + enumClass.getSimpleName() + "."); + public E parse(String data, BitsCommandContext> ctx) throws CommandSyntaxException { + return Enums.getFromIdentifier(enumClass, data) + .orElseThrow(() -> ExceptionBuilder.createCommandException("Enum constant not found: " + data + " for enum " + enumClass.getSimpleName() + ".")); } @Override - public Supplier> getSuggestions() { + public SuggestionSupplier getSuggestions() { return () -> Stream.of(enumClass.getEnumConstants()).map(Enum::name).toList(); } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/BooleanArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/BooleanArgumentParser.java index 444646e2..9b2fb11d 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/BooleanArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/BooleanArgumentParser.java @@ -7,17 +7,17 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl.primitive; -import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.SuggestionSupplier; import java.util.List; -import java.util.function.Supplier; + /** * Argument parser for Boolean values. * * @since 0.0.10 */ -@ArgumentParser + public final class BooleanArgumentParser extends PrimitiveArgumentParser { public BooleanArgumentParser() { @@ -25,7 +25,7 @@ public BooleanArgumentParser() { } @Override - public Supplier> getSuggestions() { + public SuggestionSupplier getSuggestions() { return () -> List.of("true", "false"); } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/DoubleArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/DoubleArgumentParser.java index 987fa30e..44dd84c1 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/DoubleArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/DoubleArgumentParser.java @@ -7,14 +7,13 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl.primitive; -import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; /** * Argument parser for Double values. * * @since 0.0.10 */ -@ArgumentParser + public final class DoubleArgumentParser extends PrimitiveArgumentParser { public DoubleArgumentParser() { super(Double.class, "Double"); diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/FloatArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/FloatArgumentParser.java index b0bc401d..22162ca9 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/FloatArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/FloatArgumentParser.java @@ -7,14 +7,13 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl.primitive; -import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; /** * Argument parser for Float values. * * @since 0.0.10 */ -@ArgumentParser + public final class FloatArgumentParser extends PrimitiveArgumentParser { public FloatArgumentParser() { super(Float.class, "Float"); diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/IntegerArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/IntegerArgumentParser.java index 79be0c9a..c04430a7 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/IntegerArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/IntegerArgumentParser.java @@ -7,14 +7,13 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl.primitive; -import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; /** * Argument parser for Integer values. * * @since 0.0.10 */ -@ArgumentParser + public final class IntegerArgumentParser extends PrimitiveArgumentParser { public IntegerArgumentParser() { diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/LongArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/LongArgumentParser.java index d59ce089..8e4e88df 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/LongArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/LongArgumentParser.java @@ -7,14 +7,13 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl.primitive; -import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; /** * Argument parser for Long values. * * @since 0.0.10 */ -@ArgumentParser + public final class LongArgumentParser extends PrimitiveArgumentParser { public LongArgumentParser() { diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/PrimitiveArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/PrimitiveArgumentParser.java index 12fb813c..ab6d26bc 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/PrimitiveArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/PrimitiveArgumentParser.java @@ -9,12 +9,10 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; -import xyz.bitsquidd.bits.mc.command.argument.InputTypeContainer; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; -import java.util.List; /** * A foundation parser designed specifically for types that correspond to underlying Brigadier primitives. @@ -26,21 +24,15 @@ * * @since 0.0.10 */ -public abstract class PrimitiveArgumentParser extends AbstractArgumentParser { +public abstract class PrimitiveArgumentParser extends ArgumentParser { protected PrimitiveArgumentParser(Class outputClass, String argumentName) { - super(TypeSignature.of(outputClass), argumentName); + super(TypeSignature.of(outputClass), argumentName, outputClass); } @Override - @SuppressWarnings("unchecked") - public final O parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - return (O)singletonInputValidation(inputObjects, getTypeSignature().toRawType()); - } - - @Override - public final List getInputTypes() { - return List.of(new InputTypeContainer(getTypeSignature(), getArgumentName())); + public final O parse(O data, BitsCommandContext> ctx) throws CommandSyntaxException { + return data; } } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/StringArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/StringArgumentParser.java index c8373738..fd241bea 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/StringArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/StringArgumentParser.java @@ -7,14 +7,13 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl.primitive; -import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; /** * Argument parser for String values. * * @since 0.0.10 */ -@ArgumentParser + public final class StringArgumentParser extends PrimitiveArgumentParser { public StringArgumentParser() { super(String.class, "String"); diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/util/CommandParameterInfo.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/util/CommandParameterInfo.java index 145cdc0c..346be50f 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/util/CommandParameterInfo.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/util/CommandParameterInfo.java @@ -12,7 +12,7 @@ import xyz.bitsquidd.bits.mc.command.BitsCommandManager; import xyz.bitsquidd.bits.mc.command.argument.BrigadierArgumentMapping; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; import java.lang.reflect.Parameter; @@ -39,7 +39,7 @@ public class CommandParameterInfo { private final TypeSignature> typeSignature; // TypeSignature of the parameter - private final AbstractArgumentParser> parser; + private final ArgumentParser, ?> parser; private final List heldArguments = new ArrayList<>(); // Direct mapping from the custom args to brigadier ArgumentTypes @@ -81,13 +81,13 @@ public CommandParameterInfo(Parameter parameter) { if (useArgSuggestions) { TypeSignature> inputType = parser.getInputTypes().get(i).typeSignature(); - AbstractArgumentParser> inputParser = BitsCommandManager.get().getArgumentRegistry().getParser(inputType); + ArgumentParser, ?> inputParser = BitsCommandManager.get().getArgumentRegistry().getParser(inputType); // Use the input-specific parser's suggestions - if (hasSuggestions(inputParser)) argumentBuilder.suggests(inputParser.getSuggestionProvider()); + if (hasSuggestions(inputParser)) argumentBuilder.suggests(inputParser.createSuggestionProvider()); } else { // Use the main parser's suggestions - if (hasSuggestions(parser)) argumentBuilder.suggests(parser.getSuggestionProvider()); + if (hasSuggestions(parser)) argumentBuilder.suggests(parser.createSuggestionProvider()); } brigadierArguments.add(argumentBuilder); @@ -95,7 +95,7 @@ public CommandParameterInfo(Parameter parameter) { return brigadierArguments; } - private boolean hasSuggestions(AbstractArgumentParser> parser) { + private boolean hasSuggestions(ArgumentParser, ?> parser) { return parser.getSuggestions() != null; } @@ -106,7 +106,7 @@ private boolean hasSuggestions(AbstractArgumentParser> parser) { * * @since 0.0.10 */ - public AbstractArgumentParser> getParser() { + public ArgumentParser, ?> getParser() { return parser; } diff --git a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/BlockPosArgumentParser.java b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/BlockPosArgumentParser.java index c885f865..02f8107f 100644 --- a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/BlockPosArgumentParser.java +++ b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/BlockPosArgumentParser.java @@ -7,38 +7,28 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl; -import com.mojang.brigadier.exceptions.CommandSyntaxException; - -import xyz.bitsquidd.bits.mc.command.argument.InputTypeContainer; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.paper.location.wrapper.BlockPos; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; -import java.util.List; -public final class BlockPosArgumentParser extends AbstractArgumentParser { +public final class BlockPosArgumentParser extends ArgumentParser { + + public record BlockPosData( + double x, + double y, + double z + ) {} public BlockPosArgumentParser() { - super(TypeSignature.of(BlockPos.class), "BlockPos"); + super(TypeSignature.of(BlockPos.class), "BlockPos", BlockPosData.class); } - @Override - public BlockPos parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - List inputs = inputValidation(inputObjects); - double x = (double)inputs.get(0); - double y = (double)inputs.get(1); - double z = (double)inputs.get(2); - return BlockPos.of(x, y, z); - } @Override - public List getInputTypes() { - return List.of( - new InputTypeContainer(TypeSignature.of(Double.class), "x"), - new InputTypeContainer(TypeSignature.of(Double.class), "y"), - new InputTypeContainer(TypeSignature.of(Double.class), "z") - ); + public BlockPos parse(BlockPosData data, BitsCommandContext> ctx) { + return BlockPos.of(data.x(), data.y(), data.z()); } } diff --git a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LocationArgumentParser.java b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LocationArgumentParser.java index eb438a13..0da13020 100644 --- a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LocationArgumentParser.java +++ b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LocationArgumentParser.java @@ -7,42 +7,31 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl; -import com.mojang.brigadier.exceptions.CommandSyntaxException; import org.bukkit.Location; import org.bukkit.World; -import xyz.bitsquidd.bits.mc.command.argument.InputTypeContainer; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; -import java.util.List; -public final class LocationArgumentParser extends AbstractArgumentParser { +public final class LocationArgumentParser extends ArgumentParser { + + public record LocationData( + double x, + double y, + double z, + World world + ) {} public LocationArgumentParser() { - super(TypeSignature.of(Location.class), "Location"); + super(TypeSignature.of(Location.class), "Location", LocationData.class); } - @Override - public Location parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - List inputs = inputValidation(inputObjects); - double x = (double)inputs.get(0); - double y = (double)inputs.get(1); - double z = (double)inputs.get(2); - World world = (World)inputs.get(3); - - return new Location(world, x, y, z); - } @Override - public List getInputTypes() { - return List.of( - new InputTypeContainer(TypeSignature.of(Double.class), "x"), - new InputTypeContainer(TypeSignature.of(Double.class), "y"), - new InputTypeContainer(TypeSignature.of(Double.class), "z"), - new InputTypeContainer(TypeSignature.of(World.class), "world") - ); + public Location parse(LocationData data, BitsCommandContext> ctx) { + return new Location(data.world(), data.x(), data.y(), data.z()); } } diff --git a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/PlayerCollectionArgumentParser.java b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/PlayerCollectionArgumentParser.java index 0606bd0c..373de809 100644 --- a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/PlayerCollectionArgumentParser.java +++ b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/PlayerCollectionArgumentParser.java @@ -15,8 +15,7 @@ import org.jetbrains.annotations.Nullable; import xyz.bitsquidd.bits.mc.command.PaperBitsCommandContext; -import xyz.bitsquidd.bits.mc.command.argument.InputTypeContainer; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; @@ -25,9 +24,9 @@ import java.util.List; import java.util.Objects; import java.util.function.Function; -import java.util.function.Supplier; -public final class PlayerCollectionArgumentParser extends AbstractArgumentParser> { + +public final class PlayerCollectionArgumentParser extends ArgumentParser, EntitySelector> { // TODO: Just pull from vanilla EntitySelector. Also pull the completion. private enum SelectorType { @@ -58,14 +57,12 @@ public Collection get(BitsCommandContext> ctx) { } public PlayerCollectionArgumentParser() { - super(TypeSignature.of(Collection.class, Player.class), "Players"); + super(TypeSignature.of(Collection.class, Player.class), "Players", EntitySelector.class); } @Override - public Collection parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - EntitySelector entitySelctor = singletonInputValidation(inputObjects, EntitySelector.class); - - return entitySelctor.findPlayers((CommandSourceStack)ctx.getBrigadierContext().getSource()) + public Collection parse(EntitySelector data, BitsCommandContext> ctx) throws CommandSyntaxException { + return data.findPlayers((CommandSourceStack)ctx.getBrigadierContext().getSource()) .stream() .map(playerEntity -> playerEntity.getBukkitEntity().getPlayer()) .map(Objects::requireNonNull) @@ -73,12 +70,7 @@ public Collection parse(List inputObjects, BitsCommandContext> } @Override - public List getInputTypes() { - return List.of(new InputTypeContainer(TypeSignature.of(EntitySelector.class), getArgumentName())); - } - - @Override - public Supplier> getSuggestions() { + public SuggestionSupplier getSuggestions() { List suggestions = new ArrayList<>(); suggestions.add(SelectorType.ALL.selector); suggestions.add(SelectorType.SELF.selector); diff --git a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/PlayerSingleArgumentParser.java b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/PlayerSingleArgumentParser.java index fc16ca69..98562bb2 100644 --- a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/PlayerSingleArgumentParser.java +++ b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/PlayerSingleArgumentParser.java @@ -13,41 +13,32 @@ import org.bukkit.Bukkit; import org.bukkit.entity.Player; -import xyz.bitsquidd.bits.mc.command.argument.InputTypeContainer; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.mc.command.exception.ExceptionBuilder; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; -import java.util.List; import java.util.Objects; -import java.util.function.Supplier; -public final class PlayerSingleArgumentParser extends AbstractArgumentParser { + +public final class PlayerSingleArgumentParser extends ArgumentParser { public PlayerSingleArgumentParser() { - super(TypeSignature.of(Player.class), "Player"); + super(TypeSignature.of(Player.class), "Player", EntitySelector.class); } @Override - public Player parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - EntitySelector entitySelctor = singletonInputValidation(inputObjects, EntitySelector.class); - - return entitySelctor.findPlayers((CommandSourceStack)ctx.getBrigadierContext().getSource()) + public Player parse(EntitySelector data, BitsCommandContext> ctx) throws CommandSyntaxException { + return data.findPlayers((CommandSourceStack)ctx.getBrigadierContext().getSource()) .stream() .map(playerEntity -> playerEntity.getBukkitEntity().getPlayer()) .map(Objects::requireNonNull) .findFirst() - .orElseThrow(() -> ExceptionBuilder.createCommandException("Player not found: " + entitySelctor)); - } - - @Override - public List getInputTypes() { - return List.of(new InputTypeContainer(TypeSignature.of(EntitySelector.class), getArgumentName())); + .orElseThrow(() -> ExceptionBuilder.createCommandException("Player not found: " + data)); } @Override - public Supplier> getSuggestions() { + public SuggestionSupplier getSuggestions() { return () -> Bukkit.getOnlinePlayers().stream().map(Player::getName).toList(); } diff --git a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/WorldArgumentParser.java b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/WorldArgumentParser.java index f0877c9e..ef734053 100644 --- a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/WorldArgumentParser.java +++ b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/WorldArgumentParser.java @@ -8,44 +8,31 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl; import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.kyori.adventure.key.Key; import org.bukkit.Bukkit; -import org.bukkit.NamespacedKey; import org.bukkit.World; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.mc.command.exception.ExceptionBuilder; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; -import java.util.List; -import java.util.function.Supplier; - -public final class WorldArgumentParser extends AbstractArgumentParser { +public final class WorldArgumentParser extends ArgumentParser { public WorldArgumentParser() { - super(TypeSignature.of(World.class), "World"); + super(TypeSignature.of(World.class), "World", Key.class); } @Override - public World parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - String inputString = singletonInputValidation(inputObjects, String.class); - - NamespacedKey key; - try { - key = NamespacedKey.fromString(inputString); - if (key == null) throw new IllegalArgumentException(); - } catch (IllegalArgumentException e) { - throw ExceptionBuilder.createCommandException("Invalid world key: " + inputString + "."); - } - - World world = Bukkit.getWorld(key); - if (world == null) throw ExceptionBuilder.createCommandException("World not found: " + inputString + "."); + public World parse(Key data, BitsCommandContext> ctx) throws CommandSyntaxException { + World world = Bukkit.getWorld(data); + if (world == null) throw ExceptionBuilder.createCommandException("World not found: " + data + "."); return world; } @Override - public Supplier> getSuggestions() { + public SuggestionSupplier getSuggestions() { return () -> Bukkit.getWorlds().stream().map(w -> "\"" + w.key() + "\"").toList(); } diff --git a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/WorldDefinitionArgumentParser.java b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/WorldDefinitionArgumentParser.java index 7506fd30..4bacdb50 100644 --- a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/WorldDefinitionArgumentParser.java +++ b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/WorldDefinitionArgumentParser.java @@ -10,10 +10,8 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.kyori.adventure.key.Key; import org.bukkit.Bukkit; -import org.bukkit.NamespacedKey; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; -import xyz.bitsquidd.bits.mc.command.exception.ExceptionBuilder; +import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.paper.wrapper.WorldDefinition; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; @@ -25,35 +23,25 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.function.Supplier; import java.util.stream.Stream; +import static xyz.bitsquidd.bits.paper.util.Keys.NSK; -public final class WorldDefinitionArgumentParser extends AbstractArgumentParser { + +public final class WorldDefinitionArgumentParser extends ArgumentParser { private static final Path DIMENSIONS_PATH = Bukkit.getWorldContainer().toPath().resolve("world/dimensions"); public WorldDefinitionArgumentParser() { - super(TypeSignature.of(WorldDefinition.class), "WorldDefinition"); + super(TypeSignature.of(WorldDefinition.class), "WorldDefinition", Key.class); } @Override - public WorldDefinition parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - String inputString = singletonInputValidation(inputObjects, String.class); - - NamespacedKey key; - try { - key = NamespacedKey.fromString(inputString); - if (key == null) throw new IllegalArgumentException(); - } catch (IllegalArgumentException e) { - throw ExceptionBuilder.createCommandException("Invalid world key: " + inputString + "."); - } - - WorldDefinition worldDefinition = WorldDefinition.of(key); - return worldDefinition; + public WorldDefinition parse(Key data, BitsCommandContext> ctx) throws CommandSyntaxException { + return WorldDefinition.of(NSK(data)); } @Override - public Supplier> getSuggestions() { + public SuggestionSupplier getSuggestions() { Set worldKeys = new HashSet<>(); try (Stream namespaces = Files.list(DIMENSIONS_PATH)) { namespaces.forEach(namespacePath -> { From 38057f19bc80156e1e19f74beb31fd9df31eb339 Mon Sep 17 00:00:00 2001 From: ImBit <151650938+ImBit@users.noreply.github.com> Date: Fri, 19 Jun 2026 15:04:47 +0100 Subject: [PATCH 14/15] :bug: Small command refactor fixes. --- .../mc/command/argument/parser/ArgumentParser.java | 5 +++-- .../argument/parser/SuggestionSupplier.java | 5 +++++ .../argument/parser/impl/LinkArgumentParser.java | 4 ++-- .../parser/impl/abs/EnumArgumentParser.java | 14 +++++++------- .../parser/impl/generic/GenericEnumParser.java | 2 +- .../impl/primitive/BooleanArgumentParser.java | 2 +- .../impl/PlayerCollectionArgumentParser.java | 3 ++- .../parser/impl/PlayerSingleArgumentParser.java | 3 ++- .../argument/parser/impl/WorldArgumentParser.java | 3 ++- .../parser/impl/WorldDefinitionArgumentParser.java | 6 +++--- 10 files changed, 28 insertions(+), 19 deletions(-) diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/ArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/ArgumentParser.java index 3d755312..ae56bab9 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/ArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/ArgumentParser.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Objects; /** @@ -53,7 +54,7 @@ public abstract class ArgumentParser { private final TypeSignature> typeSignature; // The type signature this parser handles private final String argumentName; // The name of the argument, used while displaying suggestions private final Class dataClass; // The class of the input data type - private final Constructor recordConstructor; + private final @Nullable Constructor recordConstructor; /** * @param typeSignature the expected type this parser handles @@ -147,7 +148,7 @@ public final D toData(List inputObjects) throws CommandSyntaxException { if (!dataClass.isRecord()) return dataClass.cast(validated[0]); try { - return recordConstructor.newInstance(validated); + return Objects.requireNonNull(this.recordConstructor).newInstance(validated); } catch (ReflectiveOperationException e) { throw ExceptionBuilder.createCommandException("Failed to construct " + dataClass.getSimpleName() + ": " + e.getMessage()); } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/SuggestionSupplier.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/SuggestionSupplier.java index bc128270..411eeb82 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/SuggestionSupplier.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/SuggestionSupplier.java @@ -17,4 +17,9 @@ public interface SuggestionSupplier { List getSuggestions(BitsCommandContext ctx); + + static SuggestionSupplier empty() { + return ctx -> List.of(); + } + } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LinkArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LinkArgumentParser.java index 0e4bd58d..60671b53 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LinkArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LinkArgumentParser.java @@ -15,7 +15,7 @@ import xyz.bitsquidd.bits.wrapper.Link; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; -import java.util.stream.Stream; +import java.util.List; //TODO add better validation for this, enum for a type? WWW. HTTPS:// etc.? @@ -40,7 +40,7 @@ public Link parse(String data, BitsCommandContext> ctx) throws CommandSyntaxEx @Override public SuggestionSupplier getSuggestions() { - return () -> Stream.of("https://", "http://", "www.").toList(); + return ctx -> List.of("https://", "http://", "www."); } } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/abs/EnumArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/abs/EnumArgumentParser.java index 27014b53..560cee41 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/abs/EnumArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/abs/EnumArgumentParser.java @@ -35,12 +35,12 @@ * } * } * - * @param the specific enum type + * @param
- * Developer Note: Custom enum parsers should override {@link AbstractEnumArgumentParser} + * Developer Note: Custom enum parsers should override {@link EnumArgumentParser} * if you want more fine-grained control over enum arguments and tab completion. *
* This implementation serves as a basic parser that is fallen back upon when no specific enum parser is available. @@ -32,9 +32,8 @@ * * @since 0.0.10 */ -@ArgumentParser -public final class GenericEnumParser> extends AbstractArgumentParser { +public final class GenericEnumParser> extends BasicArgumentParser { private final Class enumClass; public GenericEnumParser(Class enumClass) { @@ -43,18 +42,13 @@ public GenericEnumParser(Class enumClass) { } @Override - public E parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - String inputString = singletonInputValidation(inputObjects, String.class); - - for (E constant : enumClass.getEnumConstants()) { - if (constant.name().equalsIgnoreCase(inputString)) return constant; - } - - throw ExceptionBuilder.createCommandException("Enum constant not found: " + inputString + " for enum " + enumClass.getSimpleName() + "."); + public E parse(String data, BitsCommandContext> ctx) throws CommandSyntaxException { + return Enums.getFromIdentifier(enumClass, data) + .orElseThrow(() -> ExceptionBuilder.createCommandException("Enum constant not found: " + data + " for enum " + enumClass.getSimpleName() + ".")); } @Override - public Supplier> getSuggestions() { + public SuggestionSupplier getSuggestions() { return () -> Stream.of(enumClass.getEnumConstants()).map(Enum::name).toList(); } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/BooleanArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/BooleanArgumentParser.java index 444646e2..9b2fb11d 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/BooleanArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/BooleanArgumentParser.java @@ -7,17 +7,17 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl.primitive; -import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.SuggestionSupplier; import java.util.List; -import java.util.function.Supplier; + /** * Argument parser for Boolean values. * * @since 0.0.10 */ -@ArgumentParser + public final class BooleanArgumentParser extends PrimitiveArgumentParser { public BooleanArgumentParser() { @@ -25,7 +25,7 @@ public BooleanArgumentParser() { } @Override - public Supplier> getSuggestions() { + public SuggestionSupplier getSuggestions() { return () -> List.of("true", "false"); } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/DoubleArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/DoubleArgumentParser.java index 987fa30e..44dd84c1 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/DoubleArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/DoubleArgumentParser.java @@ -7,14 +7,13 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl.primitive; -import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; /** * Argument parser for Double values. * * @since 0.0.10 */ -@ArgumentParser + public final class DoubleArgumentParser extends PrimitiveArgumentParser { public DoubleArgumentParser() { super(Double.class, "Double"); diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/FloatArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/FloatArgumentParser.java index b0bc401d..22162ca9 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/FloatArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/FloatArgumentParser.java @@ -7,14 +7,13 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl.primitive; -import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; /** * Argument parser for Float values. * * @since 0.0.10 */ -@ArgumentParser + public final class FloatArgumentParser extends PrimitiveArgumentParser { public FloatArgumentParser() { super(Float.class, "Float"); diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/IntegerArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/IntegerArgumentParser.java index 79be0c9a..c04430a7 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/IntegerArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/IntegerArgumentParser.java @@ -7,14 +7,13 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl.primitive; -import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; /** * Argument parser for Integer values. * * @since 0.0.10 */ -@ArgumentParser + public final class IntegerArgumentParser extends PrimitiveArgumentParser { public IntegerArgumentParser() { diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/LongArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/LongArgumentParser.java index d59ce089..8e4e88df 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/LongArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/LongArgumentParser.java @@ -7,14 +7,13 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl.primitive; -import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; /** * Argument parser for Long values. * * @since 0.0.10 */ -@ArgumentParser + public final class LongArgumentParser extends PrimitiveArgumentParser { public LongArgumentParser() { diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/PrimitiveArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/PrimitiveArgumentParser.java index 12fb813c..ab6d26bc 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/PrimitiveArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/PrimitiveArgumentParser.java @@ -9,12 +9,10 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; -import xyz.bitsquidd.bits.mc.command.argument.InputTypeContainer; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; -import java.util.List; /** * A foundation parser designed specifically for types that correspond to underlying Brigadier primitives. @@ -26,21 +24,15 @@ * * @since 0.0.10 */ -public abstract class PrimitiveArgumentParser extends AbstractArgumentParser { +public abstract class PrimitiveArgumentParser extends ArgumentParser { protected PrimitiveArgumentParser(Class outputClass, String argumentName) { - super(TypeSignature.of(outputClass), argumentName); + super(TypeSignature.of(outputClass), argumentName, outputClass); } @Override - @SuppressWarnings("unchecked") - public final O parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - return (O)singletonInputValidation(inputObjects, getTypeSignature().toRawType()); - } - - @Override - public final List getInputTypes() { - return List.of(new InputTypeContainer(getTypeSignature(), getArgumentName())); + public final O parse(O data, BitsCommandContext> ctx) throws CommandSyntaxException { + return data; } } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/StringArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/StringArgumentParser.java index c8373738..fd241bea 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/StringArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/primitive/StringArgumentParser.java @@ -7,14 +7,13 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl.primitive; -import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; /** * Argument parser for String values. * * @since 0.0.10 */ -@ArgumentParser + public final class StringArgumentParser extends PrimitiveArgumentParser { public StringArgumentParser() { super(String.class, "String"); diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/util/CommandParameterInfo.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/util/CommandParameterInfo.java index 145cdc0c..346be50f 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/util/CommandParameterInfo.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/util/CommandParameterInfo.java @@ -12,7 +12,7 @@ import xyz.bitsquidd.bits.mc.command.BitsCommandManager; import xyz.bitsquidd.bits.mc.command.argument.BrigadierArgumentMapping; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; import java.lang.reflect.Parameter; @@ -39,7 +39,7 @@ public class CommandParameterInfo { private final TypeSignature> typeSignature; // TypeSignature of the parameter - private final AbstractArgumentParser> parser; + private final ArgumentParser, ?> parser; private final List heldArguments = new ArrayList<>(); // Direct mapping from the custom args to brigadier ArgumentTypes @@ -81,13 +81,13 @@ public CommandParameterInfo(Parameter parameter) { if (useArgSuggestions) { TypeSignature> inputType = parser.getInputTypes().get(i).typeSignature(); - AbstractArgumentParser> inputParser = BitsCommandManager.get().getArgumentRegistry().getParser(inputType); + ArgumentParser, ?> inputParser = BitsCommandManager.get().getArgumentRegistry().getParser(inputType); // Use the input-specific parser's suggestions - if (hasSuggestions(inputParser)) argumentBuilder.suggests(inputParser.getSuggestionProvider()); + if (hasSuggestions(inputParser)) argumentBuilder.suggests(inputParser.createSuggestionProvider()); } else { // Use the main parser's suggestions - if (hasSuggestions(parser)) argumentBuilder.suggests(parser.getSuggestionProvider()); + if (hasSuggestions(parser)) argumentBuilder.suggests(parser.createSuggestionProvider()); } brigadierArguments.add(argumentBuilder); @@ -95,7 +95,7 @@ public CommandParameterInfo(Parameter parameter) { return brigadierArguments; } - private boolean hasSuggestions(AbstractArgumentParser> parser) { + private boolean hasSuggestions(ArgumentParser, ?> parser) { return parser.getSuggestions() != null; } @@ -106,7 +106,7 @@ private boolean hasSuggestions(AbstractArgumentParser> parser) { * * @since 0.0.10 */ - public AbstractArgumentParser> getParser() { + public ArgumentParser, ?> getParser() { return parser; } diff --git a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/BlockPosArgumentParser.java b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/BlockPosArgumentParser.java index c885f865..02f8107f 100644 --- a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/BlockPosArgumentParser.java +++ b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/BlockPosArgumentParser.java @@ -7,38 +7,28 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl; -import com.mojang.brigadier.exceptions.CommandSyntaxException; - -import xyz.bitsquidd.bits.mc.command.argument.InputTypeContainer; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.paper.location.wrapper.BlockPos; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; -import java.util.List; -public final class BlockPosArgumentParser extends AbstractArgumentParser { +public final class BlockPosArgumentParser extends ArgumentParser { + + public record BlockPosData( + double x, + double y, + double z + ) {} public BlockPosArgumentParser() { - super(TypeSignature.of(BlockPos.class), "BlockPos"); + super(TypeSignature.of(BlockPos.class), "BlockPos", BlockPosData.class); } - @Override - public BlockPos parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - List inputs = inputValidation(inputObjects); - double x = (double)inputs.get(0); - double y = (double)inputs.get(1); - double z = (double)inputs.get(2); - return BlockPos.of(x, y, z); - } @Override - public List getInputTypes() { - return List.of( - new InputTypeContainer(TypeSignature.of(Double.class), "x"), - new InputTypeContainer(TypeSignature.of(Double.class), "y"), - new InputTypeContainer(TypeSignature.of(Double.class), "z") - ); + public BlockPos parse(BlockPosData data, BitsCommandContext> ctx) { + return BlockPos.of(data.x(), data.y(), data.z()); } } diff --git a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LocationArgumentParser.java b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LocationArgumentParser.java index eb438a13..0da13020 100644 --- a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LocationArgumentParser.java +++ b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LocationArgumentParser.java @@ -7,42 +7,31 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl; -import com.mojang.brigadier.exceptions.CommandSyntaxException; import org.bukkit.Location; import org.bukkit.World; -import xyz.bitsquidd.bits.mc.command.argument.InputTypeContainer; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; -import java.util.List; -public final class LocationArgumentParser extends AbstractArgumentParser { +public final class LocationArgumentParser extends ArgumentParser { + + public record LocationData( + double x, + double y, + double z, + World world + ) {} public LocationArgumentParser() { - super(TypeSignature.of(Location.class), "Location"); + super(TypeSignature.of(Location.class), "Location", LocationData.class); } - @Override - public Location parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - List inputs = inputValidation(inputObjects); - double x = (double)inputs.get(0); - double y = (double)inputs.get(1); - double z = (double)inputs.get(2); - World world = (World)inputs.get(3); - - return new Location(world, x, y, z); - } @Override - public List getInputTypes() { - return List.of( - new InputTypeContainer(TypeSignature.of(Double.class), "x"), - new InputTypeContainer(TypeSignature.of(Double.class), "y"), - new InputTypeContainer(TypeSignature.of(Double.class), "z"), - new InputTypeContainer(TypeSignature.of(World.class), "world") - ); + public Location parse(LocationData data, BitsCommandContext> ctx) { + return new Location(data.world(), data.x(), data.y(), data.z()); } } diff --git a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/PlayerCollectionArgumentParser.java b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/PlayerCollectionArgumentParser.java index 0606bd0c..373de809 100644 --- a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/PlayerCollectionArgumentParser.java +++ b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/PlayerCollectionArgumentParser.java @@ -15,8 +15,7 @@ import org.jetbrains.annotations.Nullable; import xyz.bitsquidd.bits.mc.command.PaperBitsCommandContext; -import xyz.bitsquidd.bits.mc.command.argument.InputTypeContainer; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; @@ -25,9 +24,9 @@ import java.util.List; import java.util.Objects; import java.util.function.Function; -import java.util.function.Supplier; -public final class PlayerCollectionArgumentParser extends AbstractArgumentParser> { + +public final class PlayerCollectionArgumentParser extends ArgumentParser, EntitySelector> { // TODO: Just pull from vanilla EntitySelector. Also pull the completion. private enum SelectorType { @@ -58,14 +57,12 @@ public Collection get(BitsCommandContext> ctx) { } public PlayerCollectionArgumentParser() { - super(TypeSignature.of(Collection.class, Player.class), "Players"); + super(TypeSignature.of(Collection.class, Player.class), "Players", EntitySelector.class); } @Override - public Collection parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - EntitySelector entitySelctor = singletonInputValidation(inputObjects, EntitySelector.class); - - return entitySelctor.findPlayers((CommandSourceStack)ctx.getBrigadierContext().getSource()) + public Collection parse(EntitySelector data, BitsCommandContext> ctx) throws CommandSyntaxException { + return data.findPlayers((CommandSourceStack)ctx.getBrigadierContext().getSource()) .stream() .map(playerEntity -> playerEntity.getBukkitEntity().getPlayer()) .map(Objects::requireNonNull) @@ -73,12 +70,7 @@ public Collection parse(List inputObjects, BitsCommandContext> } @Override - public List getInputTypes() { - return List.of(new InputTypeContainer(TypeSignature.of(EntitySelector.class), getArgumentName())); - } - - @Override - public Supplier> getSuggestions() { + public SuggestionSupplier getSuggestions() { List suggestions = new ArrayList<>(); suggestions.add(SelectorType.ALL.selector); suggestions.add(SelectorType.SELF.selector); diff --git a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/PlayerSingleArgumentParser.java b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/PlayerSingleArgumentParser.java index fc16ca69..98562bb2 100644 --- a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/PlayerSingleArgumentParser.java +++ b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/PlayerSingleArgumentParser.java @@ -13,41 +13,32 @@ import org.bukkit.Bukkit; import org.bukkit.entity.Player; -import xyz.bitsquidd.bits.mc.command.argument.InputTypeContainer; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.mc.command.exception.ExceptionBuilder; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; -import java.util.List; import java.util.Objects; -import java.util.function.Supplier; -public final class PlayerSingleArgumentParser extends AbstractArgumentParser { + +public final class PlayerSingleArgumentParser extends ArgumentParser { public PlayerSingleArgumentParser() { - super(TypeSignature.of(Player.class), "Player"); + super(TypeSignature.of(Player.class), "Player", EntitySelector.class); } @Override - public Player parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - EntitySelector entitySelctor = singletonInputValidation(inputObjects, EntitySelector.class); - - return entitySelctor.findPlayers((CommandSourceStack)ctx.getBrigadierContext().getSource()) + public Player parse(EntitySelector data, BitsCommandContext> ctx) throws CommandSyntaxException { + return data.findPlayers((CommandSourceStack)ctx.getBrigadierContext().getSource()) .stream() .map(playerEntity -> playerEntity.getBukkitEntity().getPlayer()) .map(Objects::requireNonNull) .findFirst() - .orElseThrow(() -> ExceptionBuilder.createCommandException("Player not found: " + entitySelctor)); - } - - @Override - public List getInputTypes() { - return List.of(new InputTypeContainer(TypeSignature.of(EntitySelector.class), getArgumentName())); + .orElseThrow(() -> ExceptionBuilder.createCommandException("Player not found: " + data)); } @Override - public Supplier> getSuggestions() { + public SuggestionSupplier getSuggestions() { return () -> Bukkit.getOnlinePlayers().stream().map(Player::getName).toList(); } diff --git a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/WorldArgumentParser.java b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/WorldArgumentParser.java index f0877c9e..ef734053 100644 --- a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/WorldArgumentParser.java +++ b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/WorldArgumentParser.java @@ -8,44 +8,31 @@ package xyz.bitsquidd.bits.mc.command.argument.parser.impl; import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.kyori.adventure.key.Key; import org.bukkit.Bukkit; -import org.bukkit.NamespacedKey; import org.bukkit.World; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; +import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.mc.command.exception.ExceptionBuilder; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; -import java.util.List; -import java.util.function.Supplier; - -public final class WorldArgumentParser extends AbstractArgumentParser { +public final class WorldArgumentParser extends ArgumentParser { public WorldArgumentParser() { - super(TypeSignature.of(World.class), "World"); + super(TypeSignature.of(World.class), "World", Key.class); } @Override - public World parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - String inputString = singletonInputValidation(inputObjects, String.class); - - NamespacedKey key; - try { - key = NamespacedKey.fromString(inputString); - if (key == null) throw new IllegalArgumentException(); - } catch (IllegalArgumentException e) { - throw ExceptionBuilder.createCommandException("Invalid world key: " + inputString + "."); - } - - World world = Bukkit.getWorld(key); - if (world == null) throw ExceptionBuilder.createCommandException("World not found: " + inputString + "."); + public World parse(Key data, BitsCommandContext> ctx) throws CommandSyntaxException { + World world = Bukkit.getWorld(data); + if (world == null) throw ExceptionBuilder.createCommandException("World not found: " + data + "."); return world; } @Override - public Supplier> getSuggestions() { + public SuggestionSupplier getSuggestions() { return () -> Bukkit.getWorlds().stream().map(w -> "\"" + w.key() + "\"").toList(); } diff --git a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/WorldDefinitionArgumentParser.java b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/WorldDefinitionArgumentParser.java index 7506fd30..4bacdb50 100644 --- a/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/WorldDefinitionArgumentParser.java +++ b/minecraft/paper/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/WorldDefinitionArgumentParser.java @@ -10,10 +10,8 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.kyori.adventure.key.Key; import org.bukkit.Bukkit; -import org.bukkit.NamespacedKey; -import xyz.bitsquidd.bits.mc.command.argument.parser.AbstractArgumentParser; -import xyz.bitsquidd.bits.mc.command.exception.ExceptionBuilder; +import xyz.bitsquidd.bits.mc.command.argument.parser.ArgumentParser; import xyz.bitsquidd.bits.mc.command.util.BitsCommandContext; import xyz.bitsquidd.bits.paper.wrapper.WorldDefinition; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; @@ -25,35 +23,25 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.function.Supplier; import java.util.stream.Stream; +import static xyz.bitsquidd.bits.paper.util.Keys.NSK; -public final class WorldDefinitionArgumentParser extends AbstractArgumentParser { + +public final class WorldDefinitionArgumentParser extends ArgumentParser { private static final Path DIMENSIONS_PATH = Bukkit.getWorldContainer().toPath().resolve("world/dimensions"); public WorldDefinitionArgumentParser() { - super(TypeSignature.of(WorldDefinition.class), "WorldDefinition"); + super(TypeSignature.of(WorldDefinition.class), "WorldDefinition", Key.class); } @Override - public WorldDefinition parse(List inputObjects, BitsCommandContext> ctx) throws CommandSyntaxException { - String inputString = singletonInputValidation(inputObjects, String.class); - - NamespacedKey key; - try { - key = NamespacedKey.fromString(inputString); - if (key == null) throw new IllegalArgumentException(); - } catch (IllegalArgumentException e) { - throw ExceptionBuilder.createCommandException("Invalid world key: " + inputString + "."); - } - - WorldDefinition worldDefinition = WorldDefinition.of(key); - return worldDefinition; + public WorldDefinition parse(Key data, BitsCommandContext> ctx) throws CommandSyntaxException { + return WorldDefinition.of(NSK(data)); } @Override - public Supplier> getSuggestions() { + public SuggestionSupplier getSuggestions() { Set worldKeys = new HashSet<>(); try (Stream namespaces = Files.list(DIMENSIONS_PATH)) { namespaces.forEach(namespacePath -> { From 38057f19bc80156e1e19f74beb31fd9df31eb339 Mon Sep 17 00:00:00 2001 From: ImBit <151650938+ImBit@users.noreply.github.com> Date: Fri, 19 Jun 2026 15:04:47 +0100 Subject: [PATCH 14/15] :bug: Small command refactor fixes. --- .../mc/command/argument/parser/ArgumentParser.java | 5 +++-- .../argument/parser/SuggestionSupplier.java | 5 +++++ .../argument/parser/impl/LinkArgumentParser.java | 4 ++-- .../parser/impl/abs/EnumArgumentParser.java | 14 +++++++------- .../parser/impl/generic/GenericEnumParser.java | 2 +- .../impl/primitive/BooleanArgumentParser.java | 2 +- .../impl/PlayerCollectionArgumentParser.java | 3 ++- .../parser/impl/PlayerSingleArgumentParser.java | 3 ++- .../argument/parser/impl/WorldArgumentParser.java | 3 ++- .../parser/impl/WorldDefinitionArgumentParser.java | 6 +++--- 10 files changed, 28 insertions(+), 19 deletions(-) diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/ArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/ArgumentParser.java index 3d755312..ae56bab9 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/ArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/ArgumentParser.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Objects; /** @@ -53,7 +54,7 @@ public abstract class ArgumentParser { private final TypeSignature> typeSignature; // The type signature this parser handles private final String argumentName; // The name of the argument, used while displaying suggestions private final Class dataClass; // The class of the input data type - private final Constructor recordConstructor; + private final @Nullable Constructor recordConstructor; /** * @param typeSignature the expected type this parser handles @@ -147,7 +148,7 @@ public final D toData(List inputObjects) throws CommandSyntaxException { if (!dataClass.isRecord()) return dataClass.cast(validated[0]); try { - return recordConstructor.newInstance(validated); + return Objects.requireNonNull(this.recordConstructor).newInstance(validated); } catch (ReflectiveOperationException e) { throw ExceptionBuilder.createCommandException("Failed to construct " + dataClass.getSimpleName() + ": " + e.getMessage()); } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/SuggestionSupplier.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/SuggestionSupplier.java index bc128270..411eeb82 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/SuggestionSupplier.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/SuggestionSupplier.java @@ -17,4 +17,9 @@ public interface SuggestionSupplier { List getSuggestions(BitsCommandContext ctx); + + static SuggestionSupplier empty() { + return ctx -> List.of(); + } + } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LinkArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LinkArgumentParser.java index 0e4bd58d..60671b53 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LinkArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/LinkArgumentParser.java @@ -15,7 +15,7 @@ import xyz.bitsquidd.bits.wrapper.Link; import xyz.bitsquidd.bits.wrapper.type.TypeSignature; -import java.util.stream.Stream; +import java.util.List; //TODO add better validation for this, enum for a type? WWW. HTTPS:// etc.? @@ -40,7 +40,7 @@ public Link parse(String data, BitsCommandContext> ctx) throws CommandSyntaxEx @Override public SuggestionSupplier getSuggestions() { - return () -> Stream.of("https://", "http://", "www.").toList(); + return ctx -> List.of("https://", "http://", "www."); } } diff --git a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/abs/EnumArgumentParser.java b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/abs/EnumArgumentParser.java index 27014b53..560cee41 100644 --- a/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/abs/EnumArgumentParser.java +++ b/minecraft/module/command/src/main/java/xyz/bitsquidd/bits/mc/command/argument/parser/impl/abs/EnumArgumentParser.java @@ -35,12 +35,12 @@ * } * } * - * @param the specific enum type + * @param