bukkit/paper: Add NamespacedKeyArgument (#376)
This commit is contained in:
parent
a441f42666
commit
c250aa642f
12 changed files with 645 additions and 0 deletions
|
|
@ -26,6 +26,7 @@ package cloud.commandframework.bukkit;
|
||||||
import cloud.commandframework.arguments.parser.ArgumentParser;
|
import cloud.commandframework.arguments.parser.ArgumentParser;
|
||||||
import cloud.commandframework.arguments.standard.UUIDArgument;
|
import cloud.commandframework.arguments.standard.UUIDArgument;
|
||||||
import cloud.commandframework.brigadier.CloudBrigadierManager;
|
import cloud.commandframework.brigadier.CloudBrigadierManager;
|
||||||
|
import cloud.commandframework.bukkit.argument.NamespacedKeyArgument;
|
||||||
import cloud.commandframework.bukkit.internal.CommandBuildContextSupplier;
|
import cloud.commandframework.bukkit.internal.CommandBuildContextSupplier;
|
||||||
import cloud.commandframework.bukkit.internal.MinecraftArgumentTypes;
|
import cloud.commandframework.bukkit.internal.MinecraftArgumentTypes;
|
||||||
import cloud.commandframework.bukkit.parsers.BlockPredicateArgument;
|
import cloud.commandframework.bukkit.parsers.BlockPredicateArgument;
|
||||||
|
|
@ -85,6 +86,9 @@ public final class BukkitBrigadierMapper<C> {
|
||||||
} catch (final IllegalArgumentException ignore) {
|
} catch (final IllegalArgumentException ignore) {
|
||||||
// < 1.16
|
// < 1.16
|
||||||
}
|
}
|
||||||
|
/* Map NamespacedKey */
|
||||||
|
this.mapSimpleNMS(new TypeToken<NamespacedKeyArgument.Parser<C>>() {
|
||||||
|
}, "resource_location", true);
|
||||||
/* Map Enchantment */
|
/* Map Enchantment */
|
||||||
this.mapSimpleNMS(new TypeToken<EnchantmentArgument.EnchantmentParser<C>>() {
|
this.mapSimpleNMS(new TypeToken<EnchantmentArgument.EnchantmentParser<C>>() {
|
||||||
}, "item_enchantment");
|
}, "item_enchantment");
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,27 @@ public final class BukkitCaptionKeys {
|
||||||
*/
|
*/
|
||||||
public static final Caption ARGUMENT_PARSE_FAILURE_LOCATION_MIXED_LOCAL_ABSOLUTE = of(
|
public static final Caption ARGUMENT_PARSE_FAILURE_LOCATION_MIXED_LOCAL_ABSOLUTE = of(
|
||||||
"argument.parse.failure.location.mixed_local_absolute");
|
"argument.parse.failure.location.mixed_local_absolute");
|
||||||
|
/**
|
||||||
|
* Variables: {input}
|
||||||
|
*
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
public static final Caption ARGUMENT_PARSE_FAILURE_NAMESPACED_KEY_NAMESPACE =
|
||||||
|
of("argument.parse.failure.namespacedkey.namespace");
|
||||||
|
/**
|
||||||
|
* Variables: {input}
|
||||||
|
*
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
public static final Caption ARGUMENT_PARSE_FAILURE_NAMESPACED_KEY_KEY =
|
||||||
|
of("argument.parse.failure.namespacedkey.key");
|
||||||
|
/**
|
||||||
|
* Variables: {input}
|
||||||
|
*
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
public static final Caption ARGUMENT_PARSE_FAILURE_NAMESPACED_KEY_NEED_NAMESPACE =
|
||||||
|
of("argument.parse.failure.namespacedkey.need_namespace");
|
||||||
|
|
||||||
private BukkitCaptionKeys() {
|
private BukkitCaptionKeys() {
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,28 @@ public class BukkitCaptionRegistry<C> extends SimpleCaptionRegistry<C> {
|
||||||
*/
|
*/
|
||||||
public static final String ARGUMENT_PARSE_FAILURE_LOCATION_MIXED_LOCAL_ABSOLUTE =
|
public static final String ARGUMENT_PARSE_FAILURE_LOCATION_MIXED_LOCAL_ABSOLUTE =
|
||||||
"Cannot mix local and absolute coordinates. (either all coordinates use '^' or none do)";
|
"Cannot mix local and absolute coordinates. (either all coordinates use '^' or none do)";
|
||||||
|
/**
|
||||||
|
* Default caption for {@link BukkitCaptionKeys#ARGUMENT_PARSE_FAILURE_NAMESPACED_KEY_NAMESPACE}
|
||||||
|
*
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
public static final String ARGUMENT_PARSE_FAILURE_NAMESPACED_KEY_NAMESPACE =
|
||||||
|
"Invalid namespace '{input}'. Must be [a-z0-9._-]";
|
||||||
|
/**
|
||||||
|
* Default caption for {@link BukkitCaptionKeys#ARGUMENT_PARSE_FAILURE_NAMESPACED_KEY_KEY}
|
||||||
|
*
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
public static final String ARGUMENT_PARSE_FAILURE_NAMESPACED_KEY_KEY =
|
||||||
|
"Invalid key '{input}'. Must be [a-z0-9/._-]";
|
||||||
|
/**
|
||||||
|
* Default caption for {@link BukkitCaptionKeys#ARGUMENT_PARSE_FAILURE_NAMESPACED_KEY_KEY}
|
||||||
|
*
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
public static final String ARGUMENT_PARSE_FAILURE_NAMESPACED_KEY_NEED_NAMESPACE =
|
||||||
|
"Invalid input '{input}', requires an explicit namespace.";
|
||||||
|
|
||||||
|
|
||||||
protected BukkitCaptionRegistry() {
|
protected BukkitCaptionRegistry() {
|
||||||
super();
|
super();
|
||||||
|
|
@ -134,6 +156,18 @@ public class BukkitCaptionRegistry<C> extends SimpleCaptionRegistry<C> {
|
||||||
BukkitCaptionKeys.ARGUMENT_PARSE_FAILURE_LOCATION_MIXED_LOCAL_ABSOLUTE,
|
BukkitCaptionKeys.ARGUMENT_PARSE_FAILURE_LOCATION_MIXED_LOCAL_ABSOLUTE,
|
||||||
(caption, sender) -> ARGUMENT_PARSE_FAILURE_LOCATION_MIXED_LOCAL_ABSOLUTE
|
(caption, sender) -> ARGUMENT_PARSE_FAILURE_LOCATION_MIXED_LOCAL_ABSOLUTE
|
||||||
);
|
);
|
||||||
|
this.registerMessageFactory(
|
||||||
|
BukkitCaptionKeys.ARGUMENT_PARSE_FAILURE_NAMESPACED_KEY_NAMESPACE,
|
||||||
|
(caption, sender) -> ARGUMENT_PARSE_FAILURE_NAMESPACED_KEY_NAMESPACE
|
||||||
|
);
|
||||||
|
this.registerMessageFactory(
|
||||||
|
BukkitCaptionKeys.ARGUMENT_PARSE_FAILURE_NAMESPACED_KEY_KEY,
|
||||||
|
(caption, sender) -> ARGUMENT_PARSE_FAILURE_NAMESPACED_KEY_KEY
|
||||||
|
);
|
||||||
|
this.registerMessageFactory(
|
||||||
|
BukkitCaptionKeys.ARGUMENT_PARSE_FAILURE_NAMESPACED_KEY_NEED_NAMESPACE,
|
||||||
|
(caption, sender) -> ARGUMENT_PARSE_FAILURE_NAMESPACED_KEY_NEED_NAMESPACE
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,13 +26,18 @@ package cloud.commandframework.bukkit;
|
||||||
import cloud.commandframework.CloudCapability;
|
import cloud.commandframework.CloudCapability;
|
||||||
import cloud.commandframework.CommandManager;
|
import cloud.commandframework.CommandManager;
|
||||||
import cloud.commandframework.CommandTree;
|
import cloud.commandframework.CommandTree;
|
||||||
|
import cloud.commandframework.arguments.parser.ParserParameters;
|
||||||
import cloud.commandframework.brigadier.BrigadierManagerHolder;
|
import cloud.commandframework.brigadier.BrigadierManagerHolder;
|
||||||
import cloud.commandframework.brigadier.CloudBrigadierManager;
|
import cloud.commandframework.brigadier.CloudBrigadierManager;
|
||||||
|
import cloud.commandframework.bukkit.annotation.specifier.DefaultNamespace;
|
||||||
|
import cloud.commandframework.bukkit.annotation.specifier.RequireExplicitNamespace;
|
||||||
|
import cloud.commandframework.bukkit.argument.NamespacedKeyArgument;
|
||||||
import cloud.commandframework.bukkit.arguments.selector.MultipleEntitySelector;
|
import cloud.commandframework.bukkit.arguments.selector.MultipleEntitySelector;
|
||||||
import cloud.commandframework.bukkit.arguments.selector.MultiplePlayerSelector;
|
import cloud.commandframework.bukkit.arguments.selector.MultiplePlayerSelector;
|
||||||
import cloud.commandframework.bukkit.arguments.selector.SingleEntitySelector;
|
import cloud.commandframework.bukkit.arguments.selector.SingleEntitySelector;
|
||||||
import cloud.commandframework.bukkit.arguments.selector.SinglePlayerSelector;
|
import cloud.commandframework.bukkit.arguments.selector.SinglePlayerSelector;
|
||||||
import cloud.commandframework.bukkit.data.ProtoItemStack;
|
import cloud.commandframework.bukkit.data.ProtoItemStack;
|
||||||
|
import cloud.commandframework.bukkit.internal.CraftBukkitReflection;
|
||||||
import cloud.commandframework.bukkit.parsers.BlockPredicateArgument;
|
import cloud.commandframework.bukkit.parsers.BlockPredicateArgument;
|
||||||
import cloud.commandframework.bukkit.parsers.EnchantmentArgument;
|
import cloud.commandframework.bukkit.parsers.EnchantmentArgument;
|
||||||
import cloud.commandframework.bukkit.parsers.ItemStackArgument;
|
import cloud.commandframework.bukkit.parsers.ItemStackArgument;
|
||||||
|
|
@ -162,6 +167,18 @@ public class BukkitCommandManager<C> extends CommandManager<C> implements Brigad
|
||||||
this.getParserRegistry().registerParserSupplier(TypeToken.get(MultiplePlayerSelector.class), parserParameters ->
|
this.getParserRegistry().registerParserSupplier(TypeToken.get(MultiplePlayerSelector.class), parserParameters ->
|
||||||
new MultiplePlayerSelectorArgument.MultiplePlayerSelectorParser<>());
|
new MultiplePlayerSelectorArgument.MultiplePlayerSelectorParser<>());
|
||||||
|
|
||||||
|
if (CraftBukkitReflection.classExists("org.bukkit.NamespacedKey")) {
|
||||||
|
this.registerParserSupplierFor(NamespacedKeyArgument.class);
|
||||||
|
this.getParserRegistry().registerAnnotationMapper(
|
||||||
|
RequireExplicitNamespace.class,
|
||||||
|
(annotation, type) -> ParserParameters.single(BukkitParserParameters.REQUIRE_EXPLICIT_NAMESPACE, true)
|
||||||
|
);
|
||||||
|
this.getParserRegistry().registerAnnotationMapper(
|
||||||
|
DefaultNamespace.class,
|
||||||
|
(annotation, type) -> ParserParameters.single(BukkitParserParameters.DEFAULT_NAMESPACE, annotation.value())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/* Register MC 1.13+ parsers */
|
/* Register MC 1.13+ parsers */
|
||||||
if (this.hasCapability(CloudBukkitCapabilities.BRIGADIER)) {
|
if (this.hasCapability(CloudBukkitCapabilities.BRIGADIER)) {
|
||||||
this.registerParserSupplierFor(ItemStackPredicateArgument.class);
|
this.registerParserSupplierFor(ItemStackPredicateArgument.class);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
//
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2021 Alexander Söderberg & Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
//
|
||||||
|
package cloud.commandframework.bukkit;
|
||||||
|
|
||||||
|
import cloud.commandframework.arguments.parser.ParserParameter;
|
||||||
|
import io.leangen.geantyref.TypeToken;
|
||||||
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link ParserParameter} keys for cloud-bukkit.
|
||||||
|
*
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
public final class BukkitParserParameters {
|
||||||
|
|
||||||
|
private BukkitParserParameters() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets to require explicit namespaces for {@link cloud.commandframework.bukkit.argument.NamespacedKeyArgument}
|
||||||
|
* (i.e. 'test' will be rejected but 'test:test' will pass).
|
||||||
|
*
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
public static final ParserParameter<Boolean> REQUIRE_EXPLICIT_NAMESPACE =
|
||||||
|
create("require_explicit_namespace", TypeToken.get(Boolean.class));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a custom default namespace for {@link cloud.commandframework.bukkit.argument.NamespacedKeyArgument}.
|
||||||
|
* Without this annotation the default is {@link org.bukkit.NamespacedKey#MINECRAFT}.
|
||||||
|
*
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
public static final ParserParameter<String> DEFAULT_NAMESPACE =
|
||||||
|
create("default_namespace", TypeToken.get(String.class));
|
||||||
|
|
||||||
|
private static <T> @NonNull ParserParameter<T> create(
|
||||||
|
final @NonNull String key,
|
||||||
|
final @NonNull TypeToken<T> expectedType
|
||||||
|
) {
|
||||||
|
return new ParserParameter<>(key, expectedType);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
/**
|
||||||
|
* Annotations for cloud-bukkit.
|
||||||
|
*
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
package cloud.commandframework.bukkit.annotation;
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
//
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2021 Alexander Söderberg & Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
//
|
||||||
|
package cloud.commandframework.bukkit.annotation.specifier;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Annotation used to set a custom namespace for {@link cloud.commandframework.bukkit.argument.NamespacedKeyArgument}.
|
||||||
|
* Without this annotation, the default namespace is {@link org.bukkit.NamespacedKey#MINECRAFT}.
|
||||||
|
*
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
@Target(ElementType.PARAMETER)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface DefaultNamespace {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default namespace string.
|
||||||
|
*
|
||||||
|
* @return default namespace
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
@NonNull String value();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
//
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2021 Alexander Söderberg & Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
//
|
||||||
|
package cloud.commandframework.bukkit.annotation.specifier;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Annotation used to set {@link cloud.commandframework.bukkit.argument.NamespacedKeyArgument} to
|
||||||
|
* require explicit namespaces.
|
||||||
|
*
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
@Target(ElementType.PARAMETER)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface RequireExplicitNamespace {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
/**
|
||||||
|
* Specifier annotations for cloud-bukkit.
|
||||||
|
*
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
package cloud.commandframework.bukkit.annotation.specifier;
|
||||||
|
|
@ -0,0 +1,370 @@
|
||||||
|
//
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2021 Alexander Söderberg & Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
//
|
||||||
|
package cloud.commandframework.bukkit.argument;
|
||||||
|
|
||||||
|
import cloud.commandframework.ArgumentDescription;
|
||||||
|
import cloud.commandframework.arguments.CommandArgument;
|
||||||
|
import cloud.commandframework.arguments.parser.ArgumentParseResult;
|
||||||
|
import cloud.commandframework.arguments.parser.ArgumentParser;
|
||||||
|
import cloud.commandframework.bukkit.BukkitCaptionKeys;
|
||||||
|
import cloud.commandframework.bukkit.BukkitCommandManager;
|
||||||
|
import cloud.commandframework.bukkit.BukkitParserParameters;
|
||||||
|
import cloud.commandframework.captions.Caption;
|
||||||
|
import cloud.commandframework.captions.CaptionVariable;
|
||||||
|
import cloud.commandframework.context.CommandContext;
|
||||||
|
import cloud.commandframework.exceptions.parsing.ParserException;
|
||||||
|
import io.leangen.geantyref.TypeToken;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import org.bukkit.NamespacedKey;
|
||||||
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cloud argument type that parses {@link NamespacedKey}s
|
||||||
|
*
|
||||||
|
* @param <C> sender type
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
public final class NamespacedKeyArgument<C> extends CommandArgument<C, NamespacedKey> {
|
||||||
|
|
||||||
|
private NamespacedKeyArgument(
|
||||||
|
final boolean required,
|
||||||
|
final @NonNull String name,
|
||||||
|
final @NonNull String defaultValue,
|
||||||
|
final @Nullable BiFunction<@NonNull CommandContext<C>, @NonNull String,
|
||||||
|
@NonNull List<@NonNull String>> suggestionsProvider,
|
||||||
|
final @NonNull ArgumentDescription defaultDescription,
|
||||||
|
final boolean requireExplicitNamespace,
|
||||||
|
final String defaultNamespace
|
||||||
|
) {
|
||||||
|
super(
|
||||||
|
required,
|
||||||
|
name,
|
||||||
|
new Parser<>(requireExplicitNamespace, defaultNamespace),
|
||||||
|
defaultValue,
|
||||||
|
NamespacedKey.class,
|
||||||
|
suggestionsProvider,
|
||||||
|
defaultDescription
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@link Builder}.
|
||||||
|
*
|
||||||
|
* @param name argument name
|
||||||
|
* @param <C> sender type
|
||||||
|
* @return builder instance
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
public static <C> @NonNull Builder<C> builder(final @NonNull String name) {
|
||||||
|
return new NamespacedKeyArgument.Builder<>(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new required {@link NamespacedKeyArgument}.
|
||||||
|
*
|
||||||
|
* @param name argument name
|
||||||
|
* @param <C> sender type
|
||||||
|
* @return argument instance
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
public static <C> @NonNull NamespacedKeyArgument<C> of(final @NonNull String name) {
|
||||||
|
return NamespacedKeyArgument.<C>builder(name).asRequired().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new optional {@link NamespacedKeyArgument}.
|
||||||
|
*
|
||||||
|
* @param name argument name
|
||||||
|
* @param <C> sender type
|
||||||
|
* @return argument instance
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
public static <C> @NonNull NamespacedKeyArgument<C> optional(final @NonNull String name) {
|
||||||
|
return NamespacedKeyArgument.<C>builder(name).asOptional().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new optional {@link NamespacedKeyArgument} using the provided default value.
|
||||||
|
*
|
||||||
|
* @param name argument name
|
||||||
|
* @param defulatValue default name
|
||||||
|
* @param <C> sender type
|
||||||
|
* @return argument instance
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
public static <C> @NonNull NamespacedKeyArgument<C> optional(
|
||||||
|
final @NonNull String name,
|
||||||
|
final @NonNull NamespacedKey defulatValue
|
||||||
|
) {
|
||||||
|
return NamespacedKeyArgument.<C>builder(name).asOptionalWithDefault(defulatValue).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder for {@link NamespacedKeyArgument}.
|
||||||
|
*
|
||||||
|
* @param <C> sender type
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
public static final class Builder<C> extends CommandArgument.TypedBuilder<C, NamespacedKey, Builder<C>> {
|
||||||
|
|
||||||
|
private boolean requireExplicitNamespace = false;
|
||||||
|
private String defaultNamespace = NamespacedKey.MINECRAFT;
|
||||||
|
|
||||||
|
private Builder(final @NonNull String name) {
|
||||||
|
super(NamespacedKey.class, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set to require explicit namespaces (i.e. 'test' will be rejected but 'test:test' will pass).
|
||||||
|
*
|
||||||
|
* @return this builder
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
public Builder<C> requireExplicitNamespace() {
|
||||||
|
return this.requireExplicitNamespace(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether to require explicit namespaces (i.e. 'test' will be rejected but 'test:test' will pass).
|
||||||
|
*
|
||||||
|
* @param requireExplicitNamespace whether to require explicit namespaces
|
||||||
|
* @return this builder
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
public Builder<C> requireExplicitNamespace(final boolean requireExplicitNamespace) {
|
||||||
|
this.requireExplicitNamespace = requireExplicitNamespace;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a custom default namespace. By default, it is {@link NamespacedKey#MINECRAFT}.
|
||||||
|
*
|
||||||
|
* @param defaultNamespace default namespace
|
||||||
|
* @return this builder
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
public Builder<C> defaultNamespace(final String defaultNamespace) {
|
||||||
|
this.defaultNamespace = defaultNamespace;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the command argument to be optional, with the specified default value.
|
||||||
|
*
|
||||||
|
* @param defaultValue default value
|
||||||
|
* @return this builder
|
||||||
|
* @see CommandArgument.Builder#asOptionalWithDefault(String)
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
public Builder<C> asOptionalWithDefault(final NamespacedKey defaultValue) {
|
||||||
|
return this.asOptionalWithDefault(defaultValue.getNamespace() + ':' + defaultValue.getKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull NamespacedKeyArgument<C> build() {
|
||||||
|
return new NamespacedKeyArgument<>(
|
||||||
|
this.isRequired(),
|
||||||
|
this.getName(),
|
||||||
|
this.getDefaultValue(),
|
||||||
|
this.getSuggestionsProvider(),
|
||||||
|
this.getDefaultDescription(),
|
||||||
|
this.requireExplicitNamespace,
|
||||||
|
this.defaultNamespace
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parser for {@link NamespacedKey}.
|
||||||
|
*
|
||||||
|
* @param <C> sender type
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
public static final class Parser<C> implements ArgumentParser<C, NamespacedKey> {
|
||||||
|
|
||||||
|
private final boolean requireExplicitNamespace;
|
||||||
|
private final String defaultNamespace;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@link Parser}.
|
||||||
|
*
|
||||||
|
* @param requireExplicitNamespace whether to require an explicit namespace
|
||||||
|
* @param defaultNamespace default namespace
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
public Parser(
|
||||||
|
final boolean requireExplicitNamespace,
|
||||||
|
final String defaultNamespace
|
||||||
|
) {
|
||||||
|
this.requireExplicitNamespace = requireExplicitNamespace;
|
||||||
|
this.defaultNamespace = defaultNamespace;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
@Override
|
||||||
|
public @NonNull ArgumentParseResult<NamespacedKey> parse(
|
||||||
|
final @NonNull CommandContext<C> commandContext,
|
||||||
|
final @NonNull Queue<@NonNull String> inputQueue
|
||||||
|
) {
|
||||||
|
final String input = inputQueue.peek();
|
||||||
|
final String[] split = input.split(":");
|
||||||
|
final int maxSemi = split.length > 1 ? 1 : 0;
|
||||||
|
if (input.length() - input.replace(":", "").length() > maxSemi) {
|
||||||
|
// Wrong number of ':'
|
||||||
|
return ArgumentParseResult.failure(new NamespacedKeyParseException(
|
||||||
|
BukkitCaptionKeys.ARGUMENT_PARSE_FAILURE_NAMESPACED_KEY_KEY, input, commandContext
|
||||||
|
));
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
final NamespacedKey ret;
|
||||||
|
if (split.length == 1) {
|
||||||
|
if (this.requireExplicitNamespace) {
|
||||||
|
// Did not provide explicit namespace when option was enabled
|
||||||
|
return ArgumentParseResult.failure(new NamespacedKeyParseException(
|
||||||
|
BukkitCaptionKeys.ARGUMENT_PARSE_FAILURE_NAMESPACED_KEY_NEED_NAMESPACE, input, commandContext
|
||||||
|
));
|
||||||
|
}
|
||||||
|
ret = new NamespacedKey(this.defaultNamespace, split[0]);
|
||||||
|
} else if (split.length == 2) {
|
||||||
|
ret = new NamespacedKey(split[0], split[1]);
|
||||||
|
} else {
|
||||||
|
// Too many parts, ie not:valid:input
|
||||||
|
return ArgumentParseResult.failure(new NamespacedKeyParseException(
|
||||||
|
BukkitCaptionKeys.ARGUMENT_PARSE_FAILURE_NAMESPACED_KEY_KEY, input, commandContext
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Success!
|
||||||
|
inputQueue.remove();
|
||||||
|
return ArgumentParseResult.success(ret);
|
||||||
|
} catch (final IllegalArgumentException ex) {
|
||||||
|
final Caption caption = ex.getMessage().contains("namespace") // stupid but works
|
||||||
|
? BukkitCaptionKeys.ARGUMENT_PARSE_FAILURE_NAMESPACED_KEY_NAMESPACE
|
||||||
|
// this will also get used if someone puts >256 chars
|
||||||
|
: BukkitCaptionKeys.ARGUMENT_PARSE_FAILURE_NAMESPACED_KEY_KEY;
|
||||||
|
return ArgumentParseResult.failure(new NamespacedKeyParseException(caption, input, commandContext));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull List<@NonNull String> suggestions(
|
||||||
|
final @NonNull CommandContext<C> commandContext,
|
||||||
|
final @NonNull String input
|
||||||
|
) {
|
||||||
|
final List<String> ret = new ArrayList<>();
|
||||||
|
ret.add(this.defaultNamespace + ":");
|
||||||
|
if (!input.contains(":") && !input.isEmpty()) {
|
||||||
|
ret.add(input + ":");
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception used when {@link Parser} fails.
|
||||||
|
*
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
public static final class NamespacedKeyParseException extends ParserException {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -482592639358941441L;
|
||||||
|
private final String input;
|
||||||
|
private final Caption caption;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link NamespacedKeyParseException}.
|
||||||
|
*
|
||||||
|
* @param caption caption
|
||||||
|
* @param input input
|
||||||
|
* @param context command context
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
public NamespacedKeyParseException(
|
||||||
|
final @NonNull Caption caption,
|
||||||
|
final @NonNull String input,
|
||||||
|
final @NonNull CommandContext<?> context
|
||||||
|
) {
|
||||||
|
super(
|
||||||
|
Parser.class,
|
||||||
|
context,
|
||||||
|
caption,
|
||||||
|
CaptionVariable.of("input", input)
|
||||||
|
);
|
||||||
|
this.caption = caption;
|
||||||
|
this.input = input;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the input
|
||||||
|
*
|
||||||
|
* @return Input
|
||||||
|
*/
|
||||||
|
public @NonNull String getInput() {
|
||||||
|
return this.input;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o == null || this.getClass() != o.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final NamespacedKeyParseException that = (NamespacedKeyParseException) o;
|
||||||
|
return this.input.equals(that.input) && this.caption.equals(that.caption);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(this.input, this.caption);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called reflectively by {@link BukkitCommandManager}.
|
||||||
|
*
|
||||||
|
* @param commandManager command manager
|
||||||
|
* @param <C> sender type
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private static <C> void registerParserSupplier(final @NonNull BukkitCommandManager<C> commandManager) {
|
||||||
|
commandManager.getParserRegistry()
|
||||||
|
.registerParserSupplier(TypeToken.get(NamespacedKey.class), params -> new Parser<>(
|
||||||
|
params.has(BukkitParserParameters.REQUIRE_EXPLICIT_NAMESPACE),
|
||||||
|
params.get(BukkitParserParameters.DEFAULT_NAMESPACE, NamespacedKey.MINECRAFT)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
/**
|
||||||
|
* Command argument types for the Bukkit platform.
|
||||||
|
*
|
||||||
|
* @since 1.7.0
|
||||||
|
*/
|
||||||
|
package cloud.commandframework.bukkit.argument;
|
||||||
|
|
@ -44,6 +44,7 @@ import cloud.commandframework.arguments.standard.IntegerArgument;
|
||||||
import cloud.commandframework.arguments.standard.StringArrayArgument;
|
import cloud.commandframework.arguments.standard.StringArrayArgument;
|
||||||
import cloud.commandframework.bukkit.BukkitCommandManager;
|
import cloud.commandframework.bukkit.BukkitCommandManager;
|
||||||
import cloud.commandframework.bukkit.CloudBukkitCapabilities;
|
import cloud.commandframework.bukkit.CloudBukkitCapabilities;
|
||||||
|
import cloud.commandframework.bukkit.argument.NamespacedKeyArgument;
|
||||||
import cloud.commandframework.bukkit.arguments.selector.SingleEntitySelector;
|
import cloud.commandframework.bukkit.arguments.selector.SingleEntitySelector;
|
||||||
import cloud.commandframework.bukkit.data.ProtoItemStack;
|
import cloud.commandframework.bukkit.data.ProtoItemStack;
|
||||||
import cloud.commandframework.bukkit.parsers.EnchantmentArgument;
|
import cloud.commandframework.bukkit.parsers.EnchantmentArgument;
|
||||||
|
|
@ -89,6 +90,7 @@ import org.bukkit.ChatColor;
|
||||||
import org.bukkit.GameMode;
|
import org.bukkit.GameMode;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.NamespacedKey;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.enchantments.Enchantment;
|
import org.bukkit.enchantments.Enchantment;
|
||||||
|
|
@ -393,6 +395,8 @@ public final class ExamplePlugin extends JavaPlugin {
|
||||||
new Mc113(this.manager).registerCommands();
|
new Mc113(this.manager).registerCommands();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.registerNamespacedKeyUsingCommand();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Create a Bukkit-like command
|
// Create a Bukkit-like command
|
||||||
//
|
//
|
||||||
|
|
@ -457,6 +461,28 @@ public final class ExamplePlugin extends JavaPlugin {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void registerNamespacedKeyUsingCommand() {
|
||||||
|
boolean nsk = true;
|
||||||
|
try {
|
||||||
|
Class.forName("org.bukkit.NamespacedKey");
|
||||||
|
} catch (final ClassNotFoundException e) {
|
||||||
|
nsk = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nsk) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.manager.command(this.manager.commandBuilder("example")
|
||||||
|
.literal("namespacedkey")
|
||||||
|
.argument(NamespacedKeyArgument.of("key"))
|
||||||
|
.handler(ctx -> {
|
||||||
|
final NamespacedKey namespacedKey = ctx.get("key");
|
||||||
|
final String key = namespacedKey.getNamespace() + ":" + namespacedKey.getKey();
|
||||||
|
ctx.getSender().sendMessage("The key you typed is '" + key + "'.");
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
@CommandMethod("example|e|ex help [query]")
|
@CommandMethod("example|e|ex help [query]")
|
||||||
@CommandDescription("Help menu")
|
@CommandDescription("Help menu")
|
||||||
public void commandHelp(
|
public void commandHelp(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue