More parser work
This commit is contained in:
parent
91b433c14b
commit
52c0796539
14 changed files with 950 additions and 4 deletions
|
|
@ -42,6 +42,10 @@ public final class FabricCaptionKeys {
|
||||||
"argument.parse.failure.registry_entry.unknown_entry"
|
"argument.parse.failure.registry_entry.unknown_entry"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
public static final Caption ARGUMENT_PARSE_FAILURE_TEAM_UNKNOWN = of(
|
||||||
|
"argument.parse.failure.team.unknown"
|
||||||
|
);
|
||||||
|
|
||||||
private static @NonNull Caption of(final @NonNull String key) {
|
private static @NonNull Caption of(final @NonNull String key) {
|
||||||
final Caption caption = Caption.of(key);
|
final Caption caption = Caption.of(key);
|
||||||
RECOGNIZED_CAPTIONS.add(caption);
|
RECOGNIZED_CAPTIONS.add(caption);
|
||||||
|
|
|
||||||
|
|
@ -30,11 +30,15 @@ public class FabricCaptionRegistry<C> extends SimpleCaptionRegistry<C> {
|
||||||
|
|
||||||
public static final String ARGUMENT_PARSE_FAILURE_REGISTRY_ENTRY_UNKNOWN_ENTRY = "Could not find key {id} in registry '{registry}'";
|
public static final String ARGUMENT_PARSE_FAILURE_REGISTRY_ENTRY_UNKNOWN_ENTRY = "Could not find key {id} in registry '{registry}'";
|
||||||
|
|
||||||
|
public static final String ARGUMENT_PARSE_FAILURE_TEAM_UNKOWN = "Could not find any team named '{input}'!";
|
||||||
|
|
||||||
protected FabricCaptionRegistry() {
|
protected FabricCaptionRegistry() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.registerMessageFactory(FabricCaptionKeys.ARGUMENT_PARSE_FAILURE_REGISTRY_ENTRY_UNKNOWN_ENTRY,
|
this.registerMessageFactory(FabricCaptionKeys.ARGUMENT_PARSE_FAILURE_REGISTRY_ENTRY_UNKNOWN_ENTRY,
|
||||||
(caption, sender) -> ARGUMENT_PARSE_FAILURE_REGISTRY_ENTRY_UNKNOWN_ENTRY);
|
(caption, sender) -> ARGUMENT_PARSE_FAILURE_REGISTRY_ENTRY_UNKNOWN_ENTRY);
|
||||||
|
this.registerMessageFactory(FabricCaptionKeys.ARGUMENT_PARSE_FAILURE_TEAM_UNKNOWN,
|
||||||
|
(caption, sender) -> ARGUMENT_PARSE_FAILURE_TEAM_UNKOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,10 @@ import cloud.commandframework.brigadier.argument.WrappedBrigadierParser;
|
||||||
import cloud.commandframework.context.CommandContext;
|
import cloud.commandframework.context.CommandContext;
|
||||||
import cloud.commandframework.execution.AsynchronousCommandExecutionCoordinator;
|
import cloud.commandframework.execution.AsynchronousCommandExecutionCoordinator;
|
||||||
import cloud.commandframework.execution.CommandExecutionCoordinator;
|
import cloud.commandframework.execution.CommandExecutionCoordinator;
|
||||||
|
import cloud.commandframework.fabric.argument.FabricArgumentParsers;
|
||||||
import cloud.commandframework.fabric.argument.RegistryEntryArgument;
|
import cloud.commandframework.fabric.argument.RegistryEntryArgument;
|
||||||
|
import cloud.commandframework.fabric.argument.TeamArgument;
|
||||||
|
import cloud.commandframework.fabric.data.MinecraftTime;
|
||||||
import cloud.commandframework.meta.CommandMeta;
|
import cloud.commandframework.meta.CommandMeta;
|
||||||
import cloud.commandframework.meta.SimpleCommandMeta;
|
import cloud.commandframework.meta.SimpleCommandMeta;
|
||||||
import com.mojang.brigadier.arguments.ArgumentType;
|
import com.mojang.brigadier.arguments.ArgumentType;
|
||||||
|
|
@ -62,6 +65,7 @@ import net.minecraft.command.argument.ObjectiveCriteriaArgumentType;
|
||||||
import net.minecraft.command.argument.OperationArgumentType;
|
import net.minecraft.command.argument.OperationArgumentType;
|
||||||
import net.minecraft.command.argument.ParticleArgumentType;
|
import net.minecraft.command.argument.ParticleArgumentType;
|
||||||
import net.minecraft.command.argument.SwizzleArgumentType;
|
import net.minecraft.command.argument.SwizzleArgumentType;
|
||||||
|
import net.minecraft.command.argument.TeamArgumentType;
|
||||||
import net.minecraft.command.argument.UuidArgumentType;
|
import net.minecraft.command.argument.UuidArgumentType;
|
||||||
import net.minecraft.command.suggestion.SuggestionProviders;
|
import net.minecraft.command.suggestion.SuggestionProviders;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
|
@ -69,6 +73,7 @@ import net.minecraft.nbt.Tag;
|
||||||
import net.minecraft.particle.ParticleEffect;
|
import net.minecraft.particle.ParticleEffect;
|
||||||
import net.minecraft.predicate.NumberRange;
|
import net.minecraft.predicate.NumberRange;
|
||||||
import net.minecraft.scoreboard.ScoreboardCriterion;
|
import net.minecraft.scoreboard.ScoreboardCriterion;
|
||||||
|
import net.minecraft.scoreboard.Team;
|
||||||
import net.minecraft.server.command.ServerCommandSource;
|
import net.minecraft.server.command.ServerCommandSource;
|
||||||
import net.minecraft.util.Formatting;
|
import net.minecraft.util.Formatting;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
|
@ -160,6 +165,8 @@ public abstract class FabricCommandManager<C, S extends CommandSource> extends C
|
||||||
/* Cloud-native argument types */
|
/* Cloud-native argument types */
|
||||||
brigadier.registerMapping(new TypeToken<UUIDArgument.UUIDParser<C>>() {}, builder -> builder.toConstant(UuidArgumentType.uuid()));
|
brigadier.registerMapping(new TypeToken<UUIDArgument.UUIDParser<C>>() {}, builder -> builder.toConstant(UuidArgumentType.uuid()));
|
||||||
this.registerRegistryEntryMappings();
|
this.registerRegistryEntryMappings();
|
||||||
|
brigadier.registerMapping(new TypeToken<TeamArgument.TeamParser<C>>() {}, builder -> builder.toConstant(TeamArgumentType.team()));
|
||||||
|
this.getParserRegistry().registerParserSupplier(TypeToken.get(Team.class), params -> new TeamArgument.TeamParser<>());
|
||||||
|
|
||||||
/* Wrapped/Constant Brigadier types, native value type */
|
/* Wrapped/Constant Brigadier types, native value type */
|
||||||
this.registerConstantNativeParserSupplier(Formatting.class, ColorArgumentType.color());
|
this.registerConstantNativeParserSupplier(Formatting.class, ColorArgumentType.color());
|
||||||
|
|
@ -194,8 +201,8 @@ public abstract class FabricCommandManager<C, S extends CommandSource> extends C
|
||||||
this.registerConstantNativeParserSupplier(ScoreboardSlotArgumentType.scoreboardSlot());
|
this.registerConstantNativeParserSupplier(ScoreboardSlotArgumentType.scoreboardSlot());
|
||||||
this.registerConstantNativeParserSupplier(Team.class, TeamArgumentType.team());
|
this.registerConstantNativeParserSupplier(Team.class, TeamArgumentType.team());
|
||||||
this.registerConstantNativeParserSupplier(/* slot *, ItemSlotArgumentType.itemSlot());
|
this.registerConstantNativeParserSupplier(/* slot *, ItemSlotArgumentType.itemSlot());
|
||||||
this.registerConstantNativeParserSupplier(CommandFunction.class, FunctionArgumentType.function());
|
this.registerConstantNativeParserSupplier(CommandFunction.class, FunctionArgumentType.function()); */
|
||||||
this.registerConstantNativeParserSupplier(/* time representation in ticks *, TimeArgumentType.time());*/
|
this.getParserRegistry().registerParserSupplier(TypeToken.get(MinecraftTime.class), params -> FabricArgumentParsers.time());
|
||||||
|
|
||||||
/* Wrapped brigadier requiring parameters */
|
/* Wrapped brigadier requiring parameters */
|
||||||
// score holder: single vs multiple
|
// score holder: single vs multiple
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,7 @@ public final class AngleArgument<C> extends CommandArgument<C, AngleArgumentType
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build a new criterion argument
|
* Build a new angle argument
|
||||||
*
|
*
|
||||||
* @return Constructed argument
|
* @return Constructed argument
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,44 @@
|
||||||
|
|
||||||
package cloud.commandframework.fabric.argument;
|
package cloud.commandframework.fabric.argument;
|
||||||
|
|
||||||
public class FabricArgumentParsers {
|
import cloud.commandframework.arguments.parser.ArgumentParseResult;
|
||||||
|
import cloud.commandframework.arguments.parser.ArgumentParser;
|
||||||
|
import cloud.commandframework.brigadier.argument.WrappedBrigadierParser;
|
||||||
|
import cloud.commandframework.fabric.FabricCommandContextKeys;
|
||||||
|
import cloud.commandframework.fabric.data.MinecraftTime;
|
||||||
|
import net.minecraft.command.CommandSource;
|
||||||
|
import net.minecraft.command.argument.FunctionArgumentType;
|
||||||
|
import net.minecraft.command.argument.TimeArgumentType;
|
||||||
|
import net.minecraft.server.function.CommandFunction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parsers for Vanilla command argument types.
|
||||||
|
*
|
||||||
|
* @since 1.4.0
|
||||||
|
*/
|
||||||
|
public final class FabricArgumentParsers {
|
||||||
|
|
||||||
|
private FabricArgumentParsers() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A parser for in-game time, in ticks.
|
||||||
|
*
|
||||||
|
* @param <C> sender type
|
||||||
|
* @return a parser instance
|
||||||
|
*/
|
||||||
|
public static <C> ArgumentParser<C, MinecraftTime> time() {
|
||||||
|
return new WrappedBrigadierParser<C, Integer>(TimeArgumentType.time())
|
||||||
|
.map((ctx, val) -> ArgumentParseResult.success(MinecraftTime.of(val)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <C> ArgumentParser<C, CommandFunction> commandFunction() {
|
||||||
|
// TODO: Should probably write our own parser for this, it's either Identifier or tag.
|
||||||
|
// Server parsers
|
||||||
|
return new WrappedBrigadierParser<C, FunctionArgumentType.FunctionArgument>(FunctionArgumentType.function()).map((ctx, val) -> {
|
||||||
|
final CommandSource source = ctx.get(FabricCommandContextKeys.NATIVE_COMMAND_SOURCE);
|
||||||
|
source.getCompletions()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ import static java.util.Objects.requireNonNull;
|
||||||
*
|
*
|
||||||
* @param <C> the command sender type
|
* @param <C> the command sender type
|
||||||
* @param <V> the registry entry type
|
* @param <V> the registry entry type
|
||||||
|
* @since 1.4.0
|
||||||
*/
|
*/
|
||||||
public class RegistryEntryArgument<C, V> extends CommandArgument<C, V> {
|
public class RegistryEntryArgument<C, V> extends CommandArgument<C, V> {
|
||||||
private static final String NAMESPACE_MINECRAFT = "minecraft";
|
private static final String NAMESPACE_MINECRAFT = "minecraft";
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
package cloud.commandframework.fabric.argument;
|
||||||
|
|
||||||
|
import cloud.commandframework.arguments.parser.ArgumentParseResult;
|
||||||
|
import cloud.commandframework.arguments.parser.ArgumentParser;
|
||||||
|
import cloud.commandframework.context.CommandContext;
|
||||||
|
import cloud.commandframework.fabric.FabricCommandContextKeys;
|
||||||
|
import net.fabricmc.api.EnvType;
|
||||||
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
|
import net.minecraft.command.CommandSource;
|
||||||
|
import net.minecraft.server.command.ServerCommandSource;
|
||||||
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
|
||||||
|
import java.util.Queue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An argument parser that is resolved in different ways on the logical server and logical client.
|
||||||
|
*
|
||||||
|
* @param <C> command sender type
|
||||||
|
* @param <I> intermediate type to resolve
|
||||||
|
* @param <R> resolved type
|
||||||
|
*/
|
||||||
|
abstract class SidedArgumentParser<C, I, R> implements ArgumentParser<C, R> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull ArgumentParseResult<@NonNull R> parse(
|
||||||
|
@NonNull final CommandContext<@NonNull C> commandContext,
|
||||||
|
@NonNull final Queue<@NonNull String> inputQueue
|
||||||
|
) {
|
||||||
|
final CommandSource source = commandContext.get(FabricCommandContextKeys.NATIVE_COMMAND_SOURCE);
|
||||||
|
final ArgumentParseResult<I> intermediate = this.parseIntermediate(commandContext, inputQueue);
|
||||||
|
|
||||||
|
return intermediate.flatMapParsedValue(value -> {
|
||||||
|
if (source instanceof ServerCommandSource) {
|
||||||
|
return this.resolveServer(commandContext, source, value);
|
||||||
|
} else if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) {
|
||||||
|
return this.resolveClient(commandContext, source, value);
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("Cannot have non-server command source when not on client");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract ArgumentParseResult<I> parseIntermediate(
|
||||||
|
@NonNull CommandContext<@NonNull C> commandContext,
|
||||||
|
@NonNull Queue<@NonNull String> inputQueue
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve the final value for this argument when running on the client.
|
||||||
|
*
|
||||||
|
* @param context Command context
|
||||||
|
* @param source The command source
|
||||||
|
* @param value parsed intermediate value
|
||||||
|
* @return a resolved value
|
||||||
|
*/
|
||||||
|
protected abstract ArgumentParseResult<R> resolveClient(CommandContext<C> context, CommandSource source, I value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve the final value for this argument when running on the server.
|
||||||
|
*
|
||||||
|
* @param context Command context
|
||||||
|
* @param source The command source
|
||||||
|
* @param value Parsed intermediate value
|
||||||
|
* @return a resolved value
|
||||||
|
*/
|
||||||
|
protected abstract ArgumentParseResult<R> resolveServer(CommandContext<C> context, CommandSource source, I value);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,200 @@
|
||||||
|
//
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2020 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.fabric.argument;
|
||||||
|
|
||||||
|
import cloud.commandframework.arguments.CommandArgument;
|
||||||
|
import cloud.commandframework.arguments.parser.ArgumentParseResult;
|
||||||
|
import cloud.commandframework.captions.CaptionVariable;
|
||||||
|
import cloud.commandframework.context.CommandContext;
|
||||||
|
import cloud.commandframework.exceptions.parsing.NoInputProvidedException;
|
||||||
|
import cloud.commandframework.exceptions.parsing.ParserException;
|
||||||
|
import cloud.commandframework.fabric.FabricCaptionKeys;
|
||||||
|
import cloud.commandframework.fabric.FabricCommandContextKeys;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.command.CommandSource;
|
||||||
|
import net.minecraft.command.argument.EntityAnchorArgumentType;
|
||||||
|
import net.minecraft.scoreboard.Team;
|
||||||
|
import net.minecraft.server.command.ServerCommandSource;
|
||||||
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An argument parsing an entity anchor.
|
||||||
|
*
|
||||||
|
* @param <C> the sender type
|
||||||
|
* @since 1.4.0
|
||||||
|
*/
|
||||||
|
public final class TeamArgument<C> extends CommandArgument<C, Team> {
|
||||||
|
|
||||||
|
TeamArgument(
|
||||||
|
final boolean required,
|
||||||
|
final @NonNull String name,
|
||||||
|
final @NonNull String defaultValue,
|
||||||
|
final @Nullable BiFunction<CommandContext<C>, String, List<String>> suggestionsProvider
|
||||||
|
) {
|
||||||
|
super(
|
||||||
|
required,
|
||||||
|
name,
|
||||||
|
new TeamParser<>(),
|
||||||
|
defaultValue,
|
||||||
|
Team.class,
|
||||||
|
suggestionsProvider
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new builder.
|
||||||
|
*
|
||||||
|
* @param name Name of the argument
|
||||||
|
* @param <C> Command sender type
|
||||||
|
* @return Created builder
|
||||||
|
*/
|
||||||
|
public static <C> TeamArgument.@NonNull Builder<C> newBuilder(final @NonNull String name) {
|
||||||
|
return new TeamArgument.Builder<>(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new required command argument.
|
||||||
|
*
|
||||||
|
* @param name Component name
|
||||||
|
* @param <C> Command sender type
|
||||||
|
* @return Created argument
|
||||||
|
*/
|
||||||
|
public static <C> @NonNull TeamArgument<C> of(final @NonNull String name) {
|
||||||
|
return TeamArgument.<C>newBuilder(name).asRequired().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new optional command argument
|
||||||
|
*
|
||||||
|
* @param name Component name
|
||||||
|
* @param <C> Command sender type
|
||||||
|
* @return Created argument
|
||||||
|
*/
|
||||||
|
public static <C> @NonNull TeamArgument<C> optional(final @NonNull String name) {
|
||||||
|
return TeamArgument.<C>newBuilder(name).asOptional().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new optional command argument with a default value
|
||||||
|
*
|
||||||
|
* @param name Argument name
|
||||||
|
* @param defaultValue Default value
|
||||||
|
* @param <C> Command sender type
|
||||||
|
* @return Created argument
|
||||||
|
*/
|
||||||
|
public static <C> @NonNull TeamArgument<C> optional(
|
||||||
|
final @NonNull String name,
|
||||||
|
final EntityAnchorArgumentType.@NonNull EntityAnchor defaultValue
|
||||||
|
) {
|
||||||
|
return TeamArgument.<C>newBuilder(name).asOptionalWithDefault(defaultValue.name()).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class TeamParser<C> extends SidedArgumentParser<C, String, Team> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull List<@NonNull String> suggestions(
|
||||||
|
final @NonNull CommandContext<C> commandContext,
|
||||||
|
final @NonNull String input
|
||||||
|
) {
|
||||||
|
return new ArrayList<>(commandContext.get(FabricCommandContextKeys.NATIVE_COMMAND_SOURCE).getTeamNames());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ArgumentParseResult<String> parseIntermediate(
|
||||||
|
@NonNull final CommandContext<@NonNull C> commandContext,
|
||||||
|
@NonNull final Queue<@NonNull String> inputQueue
|
||||||
|
) {
|
||||||
|
final String input = inputQueue.peek();
|
||||||
|
if (input == null) {
|
||||||
|
return ArgumentParseResult.failure(new NoInputProvidedException(TeamParser.class, commandContext));
|
||||||
|
}
|
||||||
|
return ArgumentParseResult.success(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ArgumentParseResult<Team> resolveClient(final CommandContext<C> context,
|
||||||
|
final CommandSource source,
|
||||||
|
final String value) {
|
||||||
|
final Team result = MinecraftClient.getInstance().getNetworkHandler().getWorld().getScoreboard().getTeam(value);
|
||||||
|
if (result == null) {
|
||||||
|
return ArgumentParseResult.failure(new UnknownTeamException(context, value));
|
||||||
|
}
|
||||||
|
return ArgumentParseResult.success(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ArgumentParseResult<Team> resolveServer(final CommandContext<C> context,
|
||||||
|
final CommandSource source,
|
||||||
|
final String value) {
|
||||||
|
final Team result = ((ServerCommandSource) source).getWorld().getScoreboard().getTeam(value);
|
||||||
|
if (result == null) {
|
||||||
|
return ArgumentParseResult.failure(new UnknownTeamException(context, value));
|
||||||
|
}
|
||||||
|
return ArgumentParseResult.success(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class Builder<C> extends TypedBuilder<C, Team, Builder<C>> {
|
||||||
|
|
||||||
|
Builder(final @NonNull String name) {
|
||||||
|
super(Team.class, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a new criterion argument
|
||||||
|
*
|
||||||
|
* @return Constructed argument
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public @NonNull TeamArgument<C> build() {
|
||||||
|
return new TeamArgument<>(this.isRequired(), this.getName(), this.getDefaultValue(), this.getSuggestionsProvider());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class UnknownTeamException extends ParserException {
|
||||||
|
|
||||||
|
UnknownTeamException(
|
||||||
|
final @NonNull CommandContext<?> context,
|
||||||
|
final @NonNull String input
|
||||||
|
) {
|
||||||
|
super(
|
||||||
|
TeamParser.class,
|
||||||
|
context,
|
||||||
|
FabricCaptionKeys.ARGUMENT_PARSE_FAILURE_TEAM_UNKNOWN,
|
||||||
|
CaptionVariable.of("input", input)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,130 @@
|
||||||
|
//
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2020 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.fabric.argument;
|
||||||
|
|
||||||
|
import cloud.commandframework.arguments.CommandArgument;
|
||||||
|
import cloud.commandframework.arguments.parser.ArgumentParseResult;
|
||||||
|
import cloud.commandframework.brigadier.argument.WrappedBrigadierParser;
|
||||||
|
import cloud.commandframework.context.CommandContext;
|
||||||
|
import cloud.commandframework.fabric.data.MinecraftTime;
|
||||||
|
import net.minecraft.command.argument.TimeArgumentType;
|
||||||
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An argument for in-game time
|
||||||
|
*
|
||||||
|
* @param <C> the sender type
|
||||||
|
* @since 1.4.0
|
||||||
|
*/
|
||||||
|
public final class TimeArgument<C> extends CommandArgument<C, MinecraftTime> {
|
||||||
|
|
||||||
|
TimeArgument(
|
||||||
|
final boolean required,
|
||||||
|
final @NonNull String name,
|
||||||
|
final @NonNull String defaultValue,
|
||||||
|
final @Nullable BiFunction<CommandContext<C>, String, List<String>> suggestionsProvider
|
||||||
|
) {
|
||||||
|
super(
|
||||||
|
required,
|
||||||
|
name,
|
||||||
|
FabricArgumentParsers.time(),
|
||||||
|
defaultValue,
|
||||||
|
MinecraftTime.class,
|
||||||
|
suggestionsProvider
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new builder.
|
||||||
|
*
|
||||||
|
* @param name Name of the argument
|
||||||
|
* @param <C> Command sender type
|
||||||
|
* @return Created builder
|
||||||
|
*/
|
||||||
|
public static <C> TimeArgument.@NonNull Builder<C> newBuilder(final @NonNull String name) {
|
||||||
|
return new TimeArgument.Builder<>(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new required command argument.
|
||||||
|
*
|
||||||
|
* @param name Component name
|
||||||
|
* @param <C> Command sender type
|
||||||
|
* @return Created argument
|
||||||
|
*/
|
||||||
|
public static <C> @NonNull TimeArgument<C> of(final @NonNull String name) {
|
||||||
|
return TimeArgument.<C>newBuilder(name).asRequired().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new optional command argument
|
||||||
|
*
|
||||||
|
* @param name Component name
|
||||||
|
* @param <C> Command sender type
|
||||||
|
* @return Created argument
|
||||||
|
*/
|
||||||
|
public static <C> @NonNull TimeArgument<C> optional(final @NonNull String name) {
|
||||||
|
return TimeArgument.<C>newBuilder(name).asOptional().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new optional command argument with a default value
|
||||||
|
*
|
||||||
|
* @param name Argument name
|
||||||
|
* @param defaultTime Default time, in ticks
|
||||||
|
* @param <C> Command sender type
|
||||||
|
* @return Created argument
|
||||||
|
*/
|
||||||
|
public static <C> @NonNull TimeArgument<C> optional(
|
||||||
|
final @NonNull String name,
|
||||||
|
final MinecraftTime defaultTime
|
||||||
|
) {
|
||||||
|
return TimeArgument.<C>newBuilder(name).asOptionalWithDefault(defaultTime.toString()).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static final class Builder<C> extends TypedBuilder<C, MinecraftTime, Builder<C>> {
|
||||||
|
|
||||||
|
Builder(final @NonNull String name) {
|
||||||
|
super(MinecraftTime.class, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a new time argument
|
||||||
|
*
|
||||||
|
* @return Constructed argument
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public @NonNull TimeArgument<C> build() {
|
||||||
|
return new TimeArgument<>(this.isRequired(), this.getName(), this.getDefaultValue(), this.getSuggestionsProvider());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,313 @@
|
||||||
|
//
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2020 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.fabric.argument.server;
|
||||||
|
|
||||||
|
import cloud.commandframework.arguments.CommandArgument;
|
||||||
|
import cloud.commandframework.arguments.parser.ArgumentParseResult;
|
||||||
|
import cloud.commandframework.arguments.parser.ArgumentParser;
|
||||||
|
import cloud.commandframework.captions.CaptionVariable;
|
||||||
|
import cloud.commandframework.context.CommandContext;
|
||||||
|
import cloud.commandframework.exceptions.parsing.NoInputProvidedException;
|
||||||
|
import cloud.commandframework.exceptions.parsing.ParserException;
|
||||||
|
import cloud.commandframework.fabric.FabricCaptionKeys;
|
||||||
|
import cloud.commandframework.fabric.FabricCommandContextKeys;
|
||||||
|
import com.mojang.brigadier.StringReader;
|
||||||
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
|
import io.leangen.geantyref.TypeToken;
|
||||||
|
import net.minecraft.command.CommandSource;
|
||||||
|
import net.minecraft.server.function.CommandFunction;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.registry.Registry;
|
||||||
|
import net.minecraft.util.registry.RegistryKey;
|
||||||
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a value from a registry.
|
||||||
|
*
|
||||||
|
* <p>Both static and dynamic registries are supported.</p>
|
||||||
|
*
|
||||||
|
* @param <C> the command sender type
|
||||||
|
* @since 1.4.0
|
||||||
|
*/
|
||||||
|
public class CommandFunctionArgument<C> extends CommandArgument<C, CommandFunction> {
|
||||||
|
|
||||||
|
CommandFunctionArgument(
|
||||||
|
final boolean required,
|
||||||
|
final @NonNull String name,
|
||||||
|
final @NonNull RegistryKey<? extends Registry<V>> registry,
|
||||||
|
final @NonNull String defaultValue,
|
||||||
|
final @NonNull TypeToken<V> valueType,
|
||||||
|
final @Nullable BiFunction<CommandContext<C>, String, List<String>> suggestionsProvider
|
||||||
|
) {
|
||||||
|
super(required, name, new RegistryEntryParser<>(registry), defaultValue, valueType, suggestionsProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new builder.
|
||||||
|
*
|
||||||
|
* @param name Name of the argument
|
||||||
|
* @param type The type of registry entry
|
||||||
|
* @param registry A key for the registry to get values from
|
||||||
|
* @param <C> Command sender type
|
||||||
|
* @param <V> Registry entry type
|
||||||
|
* @return Created builder
|
||||||
|
*/
|
||||||
|
public static <C, V> CommandFunctionArgument.@NonNull Builder<C, V> newBuilder(
|
||||||
|
final @NonNull String name,
|
||||||
|
final @NonNull Class<V> type,
|
||||||
|
final @NonNull RegistryKey<? extends Registry<V>> registry) {
|
||||||
|
return new CommandFunctionArgument.Builder<>(registry, type, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new builder.
|
||||||
|
*
|
||||||
|
* @param name Name of the argument
|
||||||
|
* @param type The type of registry entry
|
||||||
|
* @param registry A key for the registry to get values from
|
||||||
|
* @param <C> Command sender type
|
||||||
|
* @param <V> Registry entry type
|
||||||
|
* @return Created builder
|
||||||
|
*/
|
||||||
|
public static <C, V> CommandFunctionArgument.@NonNull Builder<C, V> newBuilder(
|
||||||
|
final @NonNull String name,
|
||||||
|
final @NonNull TypeToken<V> type,
|
||||||
|
final @NonNull RegistryKey<? extends Registry<V>> registry) {
|
||||||
|
return new CommandFunctionArgument.Builder<>(registry, type, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new required command argument.
|
||||||
|
*
|
||||||
|
* @param name Argument name
|
||||||
|
* @param type The type of registry entry
|
||||||
|
* @param registry A key for the registry to get values from
|
||||||
|
* @param <C> Command sender type
|
||||||
|
* @param <V> Registry entry type
|
||||||
|
* @return Created argument
|
||||||
|
*/
|
||||||
|
public static <C, V> @NonNull CommandFunctionArgument<C, V> of(
|
||||||
|
final @NonNull String name,
|
||||||
|
final @NonNull Class<V> type,
|
||||||
|
final @NonNull RegistryKey<? extends Registry<V>> registry
|
||||||
|
) {
|
||||||
|
return CommandFunctionArgument.<C, V>newBuilder(name, type, registry).asRequired().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new optional command argument
|
||||||
|
*
|
||||||
|
* @param name Argument name
|
||||||
|
* @param type The type of registry entry
|
||||||
|
* @param registry A key for the registry to get values from
|
||||||
|
* @param <C> Command sender type
|
||||||
|
* @param <V> Registry entry type
|
||||||
|
* @return Created argument
|
||||||
|
*/
|
||||||
|
public static <C, V> @NonNull CommandFunctionArgument<C, V> optional(
|
||||||
|
final @NonNull String name,
|
||||||
|
final @NonNull Class<V> type,
|
||||||
|
final @NonNull RegistryKey<? extends Registry<V>> registry
|
||||||
|
) {
|
||||||
|
return CommandFunctionArgument.<C, V>newBuilder(name, type, registry).asOptional().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new optional command argument with a default value
|
||||||
|
*
|
||||||
|
* @param name Argument name
|
||||||
|
* @param type The type of registry entry
|
||||||
|
* @param registry A key for the registry to get values from
|
||||||
|
* @param defaultValue Default value
|
||||||
|
* @param <C> Command sender type
|
||||||
|
* @param <V> Registry entry type
|
||||||
|
* @return Created argument
|
||||||
|
*/
|
||||||
|
public static <C, V> @NonNull CommandFunctionArgument<C, V> optional(
|
||||||
|
final @NonNull String name,
|
||||||
|
final @NonNull Class<V> type,
|
||||||
|
final @NonNull RegistryKey<? extends Registry<V>> registry,
|
||||||
|
final @NonNull RegistryKey<V> defaultValue
|
||||||
|
) {
|
||||||
|
return CommandFunctionArgument.<C, V>newBuilder(name, type, registry)
|
||||||
|
.asOptionalWithDefault(defaultValue.getValue().toString())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A parser for values stored in a {@link Registry}
|
||||||
|
*
|
||||||
|
* @param <C> Command sender type
|
||||||
|
* @param <V> Registry entry type
|
||||||
|
*/
|
||||||
|
public static final class RegistryEntryParser<C, V> implements ArgumentParser<C, V> {
|
||||||
|
private final RegistryKey<? extends Registry<V>> registryIdent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new parser for registry entries.
|
||||||
|
*
|
||||||
|
* @param registryIdent the registry identifier
|
||||||
|
*/
|
||||||
|
public RegistryEntryParser(final RegistryKey<? extends Registry<V>> registryIdent) {
|
||||||
|
this.registryIdent = requireNonNull(registryIdent, "registryIdent");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull ArgumentParseResult<@NonNull V> parse(
|
||||||
|
@NonNull final CommandContext<@NonNull C> commandContext,
|
||||||
|
@NonNull final Queue<@NonNull String> inputQueue
|
||||||
|
) {
|
||||||
|
final String possibleIdentifier = inputQueue.peek();
|
||||||
|
if (possibleIdentifier == null) {
|
||||||
|
return ArgumentParseResult.failure(new NoInputProvidedException(
|
||||||
|
CommandFunctionArgument.class,
|
||||||
|
commandContext
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
final Identifier key;
|
||||||
|
try {
|
||||||
|
key = Identifier.fromCommandInput(new StringReader(possibleIdentifier));
|
||||||
|
} catch (final CommandSyntaxException ex) {
|
||||||
|
return ArgumentParseResult.failure(ex);
|
||||||
|
}
|
||||||
|
inputQueue.poll();
|
||||||
|
|
||||||
|
final Registry<V> registry = this.getRegistry(commandContext);
|
||||||
|
if (registry == null) {
|
||||||
|
return ArgumentParseResult.failure(new IllegalArgumentException("Unknown registry " + this.registryIdent));
|
||||||
|
}
|
||||||
|
|
||||||
|
final V entry = registry.get(key);
|
||||||
|
if (entry == null) {
|
||||||
|
return ArgumentParseResult.failure(new UnknownEntryException(commandContext, key, this.registryIdent));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ArgumentParseResult.success(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Registry<V> getRegistry(final CommandContext<C> ctx) {
|
||||||
|
final CommandSource reverseMapped = ctx.get(FabricCommandContextKeys.NATIVE_COMMAND_SOURCE);
|
||||||
|
// First try dynamic registries (for things loaded from data-packs)
|
||||||
|
Registry<V> registry = reverseMapped.getRegistryManager().getOptional(this.registryIdent).orElse(null);
|
||||||
|
if (registry == null) {
|
||||||
|
// And then static registries
|
||||||
|
registry = (Registry<V>) Registry.REGISTRIES.get(this.registryIdent.getValue());
|
||||||
|
}
|
||||||
|
return registry;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull List<@NonNull String> suggestions(
|
||||||
|
final @NonNull CommandContext<C> commandContext,
|
||||||
|
final @NonNull String input
|
||||||
|
) {
|
||||||
|
final Set<Identifier> ids = this.getRegistry(commandContext).getIds();
|
||||||
|
final List<String> results = new ArrayList<>(ids.size());
|
||||||
|
for (final Identifier entry : ids) {
|
||||||
|
if (entry.getNamespace().equals(NAMESPACE_MINECRAFT)) {
|
||||||
|
results.add(entry.getPath());
|
||||||
|
}
|
||||||
|
results.add(entry.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isContextFree() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the registry associated with this parser
|
||||||
|
* @return the registry
|
||||||
|
*/
|
||||||
|
public RegistryKey<? extends Registry<?>> getRegistry() {
|
||||||
|
return this.registryIdent;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A builder for registry entry arguments.
|
||||||
|
*
|
||||||
|
* @param <C> The sender type
|
||||||
|
* @param <V> The registry value type
|
||||||
|
*/
|
||||||
|
public static final class Builder<C, V> extends TypedBuilder<C, V, Builder<C, V>> {
|
||||||
|
|
||||||
|
Builder(
|
||||||
|
final @NonNull String name
|
||||||
|
) {
|
||||||
|
super(valueType, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull CommandFunctionArgument<@NonNull C, @NonNull V> build() {
|
||||||
|
return new CommandFunctionArgument<>(
|
||||||
|
this.isRequired(),
|
||||||
|
this.getName(),
|
||||||
|
this.getDefaultValue(),
|
||||||
|
this.getValueType(),
|
||||||
|
this.getSuggestionsProvider()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An exception thrown when an entry in a registry could not be found.
|
||||||
|
*/
|
||||||
|
private static final class UnknownEntryException extends ParserException {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 7694424294461849903L;
|
||||||
|
|
||||||
|
UnknownEntryException(
|
||||||
|
final CommandContext<?> context,
|
||||||
|
final Identifier key,
|
||||||
|
final RegistryKey<? extends Registry<?>> registry
|
||||||
|
) {
|
||||||
|
super(
|
||||||
|
CommandFunctionArgument.class,
|
||||||
|
context,
|
||||||
|
FabricCaptionKeys.ARGUMENT_PARSE_FAILURE_REGISTRY_ENTRY_UNKNOWN_ENTRY,
|
||||||
|
CaptionVariable.of("id", key.toString()),
|
||||||
|
CaptionVariable.of("registry", registry.toString())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
/**
|
||||||
|
* Command arguments that can only be used on the logical server.
|
||||||
|
*
|
||||||
|
* @since 1.4.0
|
||||||
|
*/
|
||||||
|
package cloud.commandframework.fabric.argument.server;
|
||||||
|
|
@ -0,0 +1,123 @@
|
||||||
|
package cloud.commandframework.fabric.data;
|
||||||
|
|
||||||
|
import java.time.temporal.TemporalUnit;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An element of in-game time.
|
||||||
|
*
|
||||||
|
* <p>The basic unit is 1 <em>tick</em>, which aims to be {@code 50ms}</p>
|
||||||
|
*
|
||||||
|
* @since 1.4.0
|
||||||
|
*/
|
||||||
|
public final class MinecraftTime {
|
||||||
|
private static final MinecraftTime ZERO = new MinecraftTime(0);
|
||||||
|
|
||||||
|
private final long ticks;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the time instance for the specified number of ticks.
|
||||||
|
*
|
||||||
|
* @param ticks the number of ticks
|
||||||
|
* @return a time holder
|
||||||
|
*/
|
||||||
|
public static MinecraftTime of(final long ticks) {
|
||||||
|
return ticks == 0 ? ZERO : new MinecraftTime(ticks);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given an amount of time in another unit, create a game time holding the number of ticks expected to pass in that time.
|
||||||
|
*
|
||||||
|
* @param amount the amount of time
|
||||||
|
* @param unit the unit
|
||||||
|
* @return a time holder
|
||||||
|
*/
|
||||||
|
public static MinecraftTime of(final long amount, final TemporalUnit unit) {
|
||||||
|
requireNonNull(unit, "unit");
|
||||||
|
return new MinecraftTime(Math.round(amount / 50d * unit.getDuration().toMillis()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given an amount of time in another unit, create a game time holding the number of ticks expected to pass in that time.
|
||||||
|
*
|
||||||
|
* @param amount the amount of time
|
||||||
|
* @param unit the unit
|
||||||
|
* @return a time holder
|
||||||
|
*/
|
||||||
|
public static MinecraftTime of(final long amount, final TimeUnit unit) {
|
||||||
|
requireNonNull(unit, "unit");
|
||||||
|
return amount == 0 ? ZERO : new MinecraftTime(TimeUnit.MILLISECONDS.convert(amount, unit) / 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
MinecraftTime(final long ticks) {
|
||||||
|
this.ticks = ticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of in-game ticks represented by this time.
|
||||||
|
*
|
||||||
|
* <p>This time will be truncated to the maximum value of an integer.
|
||||||
|
* See {@link #getLongTicks()} for the full contents.</p>
|
||||||
|
*
|
||||||
|
* @return the time in ticks
|
||||||
|
*/
|
||||||
|
public int getTicks() {
|
||||||
|
return (int) this.ticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of in-game ticks represented by this time.
|
||||||
|
*
|
||||||
|
* @return the time in ticks
|
||||||
|
*/
|
||||||
|
public long getLongTicks() {
|
||||||
|
return this.ticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert this to another time unit.
|
||||||
|
*
|
||||||
|
* @param unit the target unit
|
||||||
|
* @return the target duration, as represented by the provided unit
|
||||||
|
*/
|
||||||
|
public long convertTo(final TemporalUnit unit) {
|
||||||
|
return this.ticks * 50 / unit.getDuration().toMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert this to another time unit.
|
||||||
|
*
|
||||||
|
* @param unit the target unit
|
||||||
|
* @return the target duration, as represented by the provided unit
|
||||||
|
*/
|
||||||
|
public long convertTo(final TimeUnit unit) {
|
||||||
|
return unit.convert(this.ticks * 50, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object other) {
|
||||||
|
if (this == other) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (other == null || this.getClass() != other.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.ticks == ((MinecraftTime) other).ticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(this.ticks);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return Long.toString(this.ticks);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
package cloud.commandframework.fabric.data;
|
||||||
|
|
||||||
|
import net.minecraft.command.EntitySelector;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A selector string to query multiple entity-like values
|
||||||
|
*
|
||||||
|
* @param <V> Value type
|
||||||
|
*/
|
||||||
|
public interface Selector<V> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the raw string associated with the selector.
|
||||||
|
*
|
||||||
|
* @return the input
|
||||||
|
*/
|
||||||
|
String getInput();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this value came from a parsed selector, this will provide the details of that selector.
|
||||||
|
*
|
||||||
|
* @return the selector
|
||||||
|
*/
|
||||||
|
@Nullable EntitySelector getSelector();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve the value of this selector.
|
||||||
|
*
|
||||||
|
* <p>A successfully parsed selector must match one or more values</p>
|
||||||
|
*
|
||||||
|
* @return all matched entities
|
||||||
|
*/
|
||||||
|
Collection<V> get();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A specialized selector that can only return one value.
|
||||||
|
*
|
||||||
|
* @param <V> the value type
|
||||||
|
*/
|
||||||
|
interface Single<V> extends Selector<V> {
|
||||||
|
|
||||||
|
V getSingle();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
/**
|
||||||
|
* Data holders for representing Vanilla argument type values.
|
||||||
|
*/
|
||||||
|
package cloud.commandframework.fabric.data;
|
||||||
Loading…
Add table
Add a link
Reference in a new issue