fabric: implement location argument types
This commit is contained in:
parent
c95d0c70cd
commit
427842cade
11 changed files with 1285 additions and 77 deletions
|
|
@ -25,9 +25,13 @@
|
|||
package cloud.commandframework.fabric;
|
||||
|
||||
import cloud.commandframework.CommandTree;
|
||||
import cloud.commandframework.arguments.parser.ParserParameters;
|
||||
import cloud.commandframework.execution.AsynchronousCommandExecutionCoordinator;
|
||||
import cloud.commandframework.execution.CommandExecutionCoordinator;
|
||||
import cloud.commandframework.fabric.annotations.specifier.Center;
|
||||
import cloud.commandframework.fabric.argument.FabricArgumentParsers;
|
||||
import cloud.commandframework.fabric.argument.FabricArgumentParsers.FabricParserParameters;
|
||||
import cloud.commandframework.fabric.data.Coordinates;
|
||||
import cloud.commandframework.fabric.data.Message;
|
||||
import cloud.commandframework.fabric.data.MultipleEntitySelector;
|
||||
import cloud.commandframework.fabric.data.MultiplePlayerSelector;
|
||||
|
|
@ -131,6 +135,34 @@ public final class FabricServerCommandManager<C> extends FabricCommandManager<C,
|
|||
private void registerParsers() {
|
||||
this.getParserRegistry().registerParserSupplier(TypeToken.get(Message.class), params -> FabricArgumentParsers.message());
|
||||
|
||||
// Location arguments
|
||||
this.getParserRegistry().registerAnnotationMapper(
|
||||
Center.class,
|
||||
(annotation, type) -> ParserParameters.single(FabricParserParameters.CENTER_INTEGERS, true)
|
||||
);
|
||||
this.getParserRegistry().registerParserSupplier(
|
||||
TypeToken.get(Coordinates.class),
|
||||
params -> FabricArgumentParsers.vec3(params.get(
|
||||
FabricParserParameters.CENTER_INTEGERS,
|
||||
false
|
||||
))
|
||||
);
|
||||
this.getParserRegistry().registerParserSupplier(
|
||||
TypeToken.get(Coordinates.CoordinatesXZ.class),
|
||||
params -> FabricArgumentParsers.vec2(params.get(
|
||||
FabricParserParameters.CENTER_INTEGERS,
|
||||
false
|
||||
))
|
||||
);
|
||||
this.getParserRegistry().registerParserSupplier(
|
||||
TypeToken.get(Coordinates.BlockCoordinates.class),
|
||||
params -> FabricArgumentParsers.blockPos()
|
||||
);
|
||||
this.getParserRegistry().registerParserSupplier(
|
||||
TypeToken.get(Coordinates.ColumnCoordinates.class),
|
||||
params -> FabricArgumentParsers.columnPos()
|
||||
);
|
||||
|
||||
// Entity selectors
|
||||
this.getParserRegistry().registerParserSupplier(
|
||||
TypeToken.get(SinglePlayerSelector.class),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
/**
|
||||
* Annotations for cloud-fabric.
|
||||
*
|
||||
* @since 1.5.0
|
||||
*/
|
||||
package cloud.commandframework.fabric.annotations;
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
//
|
||||
// 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.fabric.annotations.specifier;
|
||||
|
||||
import cloud.commandframework.fabric.argument.server.Vec3Argument;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Annotation used to enable coordinate centering for {@link Vec3Argument}.
|
||||
*
|
||||
* @since 1.5.0
|
||||
*/
|
||||
@Target(ElementType.PARAMETER)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Center {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
/**
|
||||
* Specifier annotations for cloud-fabric.
|
||||
*
|
||||
* @since 1.5.0
|
||||
*/
|
||||
package cloud.commandframework.fabric.annotations.specifier;
|
||||
|
|
@ -26,8 +26,11 @@ package cloud.commandframework.fabric.argument;
|
|||
|
||||
import cloud.commandframework.arguments.parser.ArgumentParseResult;
|
||||
import cloud.commandframework.arguments.parser.ArgumentParser;
|
||||
import cloud.commandframework.arguments.parser.ParserParameter;
|
||||
import cloud.commandframework.brigadier.argument.WrappedBrigadierParser;
|
||||
import cloud.commandframework.context.CommandContext;
|
||||
import cloud.commandframework.fabric.FabricCommandContextKeys;
|
||||
import cloud.commandframework.fabric.data.Coordinates;
|
||||
import cloud.commandframework.fabric.data.Message;
|
||||
import cloud.commandframework.fabric.data.MinecraftTime;
|
||||
import cloud.commandframework.fabric.data.MultipleEntitySelector;
|
||||
|
|
@ -38,19 +41,28 @@ import cloud.commandframework.fabric.internal.EntitySelectorAccess;
|
|||
import cloud.commandframework.fabric.mixin.MessageArgumentTypeMessageFormatAccess;
|
||||
import cloud.commandframework.fabric.mixin.MessageArgumentTypeMessageSelectorAccess;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import io.leangen.geantyref.TypeToken;
|
||||
import net.minecraft.command.CommandSource;
|
||||
import net.minecraft.command.EntitySelector;
|
||||
import net.minecraft.command.argument.BlockPosArgumentType;
|
||||
import net.minecraft.command.argument.ColumnPosArgumentType;
|
||||
import net.minecraft.command.argument.EntityArgumentType;
|
||||
import net.minecraft.command.argument.MessageArgumentType;
|
||||
import net.minecraft.command.argument.PosArgument;
|
||||
import net.minecraft.command.argument.TimeArgumentType;
|
||||
import net.minecraft.command.argument.Vec2ArgumentType;
|
||||
import net.minecraft.command.argument.Vec3ArgumentType;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Parsers for Vanilla command argument types.
|
||||
|
|
@ -74,6 +86,67 @@ public final class FabricArgumentParsers {
|
|||
.map((ctx, val) -> ArgumentParseResult.success(MinecraftTime.of(val)));
|
||||
}
|
||||
|
||||
/**
|
||||
* A parser for block coordinates.
|
||||
*
|
||||
* @param <C> sender type
|
||||
* @return a parser instance
|
||||
*/
|
||||
public static <C> @NonNull ArgumentParser<C, Coordinates.BlockCoordinates> blockPos() {
|
||||
return new WrappedBrigadierParser<C, PosArgument>(BlockPosArgumentType.blockPos())
|
||||
.map(FabricArgumentParsers::mapToCoordinates);
|
||||
}
|
||||
|
||||
/**
|
||||
* A parser for column coordinates.
|
||||
*
|
||||
* @param <C> sender type
|
||||
* @return a parser instance
|
||||
*/
|
||||
public static <C> @NonNull ArgumentParser<C, Coordinates.ColumnCoordinates> columnPos() {
|
||||
return new WrappedBrigadierParser<C, PosArgument>(ColumnPosArgumentType.columnPos())
|
||||
.map(FabricArgumentParsers::mapToCoordinates);
|
||||
}
|
||||
|
||||
/**
|
||||
* A parser for coordinates, relative or absolute, from 2 doubles for x and z,
|
||||
* with y always defaulting to 0.
|
||||
*
|
||||
* @param centerIntegers whether to center integers at x.5
|
||||
* @param <C> sender type
|
||||
* @return a parser instance
|
||||
*/
|
||||
public static <C> @NonNull ArgumentParser<C, Coordinates.CoordinatesXZ> vec2(final boolean centerIntegers) {
|
||||
return new WrappedBrigadierParser<C, PosArgument>(new Vec2ArgumentType(centerIntegers))
|
||||
.map(FabricArgumentParsers::mapToCoordinates);
|
||||
}
|
||||
|
||||
/**
|
||||
* A parser for coordinates, relative or absolute, from 3 doubles.
|
||||
*
|
||||
* @param centerIntegers whether to center integers at x.5
|
||||
* @param <C> sender type
|
||||
* @return a parser instance
|
||||
*/
|
||||
public static <C> @NonNull ArgumentParser<C, Coordinates> vec3(final boolean centerIntegers) {
|
||||
return new WrappedBrigadierParser<C, PosArgument>(Vec3ArgumentType.vec3(centerIntegers))
|
||||
.map(FabricArgumentParsers::mapToCoordinates);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <C, O extends Coordinates> @NonNull ArgumentParseResult<@NonNull O> mapToCoordinates(
|
||||
final @NonNull CommandContext<C> ctx,
|
||||
final @NonNull PosArgument posArgument
|
||||
) {
|
||||
return requireServerCommandSource(
|
||||
ctx,
|
||||
serverCommandSource -> ArgumentParseResult.success((O) new CoordinatesImpl(
|
||||
serverCommandSource,
|
||||
posArgument
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* A parser for {@link SinglePlayerSelector}.
|
||||
*
|
||||
|
|
@ -83,21 +156,16 @@ public final class FabricArgumentParsers {
|
|||
*/
|
||||
public static <C> @NonNull ArgumentParser<C, SinglePlayerSelector> singlePlayerSelector() {
|
||||
return new WrappedBrigadierParser<C, EntitySelector>(EntityArgumentType.player())
|
||||
.map((ctx, entitySelector) -> {
|
||||
final CommandSource either = ctx.get(FabricCommandContextKeys.NATIVE_COMMAND_SOURCE);
|
||||
if (!(either instanceof ServerCommandSource)) {
|
||||
return ArgumentParseResult.failure(serverOnly());
|
||||
}
|
||||
try {
|
||||
return ArgumentParseResult.success(new SinglePlayerSelector(
|
||||
((EntitySelectorAccess) entitySelector).inputString(),
|
||||
entitySelector,
|
||||
entitySelector.getPlayer((ServerCommandSource) either)
|
||||
));
|
||||
} catch (final CommandSyntaxException ex) {
|
||||
return ArgumentParseResult.failure(ex);
|
||||
}
|
||||
});
|
||||
.map((ctx, entitySelector) -> requireServerCommandSource(
|
||||
ctx,
|
||||
serverCommandSource -> handleCommandSyntaxExceptionAsFailure(
|
||||
() -> ArgumentParseResult.success(new SinglePlayerSelector(
|
||||
((EntitySelectorAccess) entitySelector).inputString(),
|
||||
entitySelector,
|
||||
entitySelector.getPlayer(serverCommandSource)
|
||||
))
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -109,21 +177,16 @@ public final class FabricArgumentParsers {
|
|||
*/
|
||||
public static <C> @NonNull ArgumentParser<C, MultiplePlayerSelector> multiplePlayerSelector() {
|
||||
return new WrappedBrigadierParser<C, EntitySelector>(EntityArgumentType.players())
|
||||
.map((ctx, entitySelector) -> {
|
||||
final CommandSource either = ctx.get(FabricCommandContextKeys.NATIVE_COMMAND_SOURCE);
|
||||
if (!(either instanceof ServerCommandSource)) {
|
||||
return ArgumentParseResult.failure(serverOnly());
|
||||
}
|
||||
try {
|
||||
return ArgumentParseResult.success(new MultiplePlayerSelector(
|
||||
((EntitySelectorAccess) entitySelector).inputString(),
|
||||
entitySelector,
|
||||
entitySelector.getPlayers((ServerCommandSource) either)
|
||||
));
|
||||
} catch (final CommandSyntaxException ex) {
|
||||
return ArgumentParseResult.failure(ex);
|
||||
}
|
||||
});
|
||||
.map((ctx, entitySelector) -> requireServerCommandSource(
|
||||
ctx,
|
||||
serverCommandSource -> handleCommandSyntaxExceptionAsFailure(
|
||||
() -> ArgumentParseResult.success(new MultiplePlayerSelector(
|
||||
((EntitySelectorAccess) entitySelector).inputString(),
|
||||
entitySelector,
|
||||
entitySelector.getPlayers(serverCommandSource)
|
||||
))
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -135,21 +198,16 @@ public final class FabricArgumentParsers {
|
|||
*/
|
||||
public static <C> @NonNull ArgumentParser<C, SingleEntitySelector> singleEntitySelector() {
|
||||
return new WrappedBrigadierParser<C, EntitySelector>(EntityArgumentType.entity())
|
||||
.map((ctx, entitySelector) -> {
|
||||
final CommandSource either = ctx.get(FabricCommandContextKeys.NATIVE_COMMAND_SOURCE);
|
||||
if (!(either instanceof ServerCommandSource)) {
|
||||
return ArgumentParseResult.failure(serverOnly());
|
||||
}
|
||||
try {
|
||||
return ArgumentParseResult.success(new SingleEntitySelector(
|
||||
((EntitySelectorAccess) entitySelector).inputString(),
|
||||
entitySelector,
|
||||
entitySelector.getEntity((ServerCommandSource) either)
|
||||
));
|
||||
} catch (final CommandSyntaxException ex) {
|
||||
return ArgumentParseResult.failure(ex);
|
||||
}
|
||||
});
|
||||
.map((ctx, entitySelector) -> requireServerCommandSource(
|
||||
ctx,
|
||||
serverCommandSource -> handleCommandSyntaxExceptionAsFailure(
|
||||
() -> ArgumentParseResult.success(new SingleEntitySelector(
|
||||
((EntitySelectorAccess) entitySelector).inputString(),
|
||||
entitySelector,
|
||||
entitySelector.getEntity(serverCommandSource)
|
||||
))
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -161,21 +219,16 @@ public final class FabricArgumentParsers {
|
|||
*/
|
||||
public static <C> @NonNull ArgumentParser<C, MultipleEntitySelector> multipleEntitySelector() {
|
||||
return new WrappedBrigadierParser<C, EntitySelector>(EntityArgumentType.entities())
|
||||
.map((ctx, entitySelector) -> {
|
||||
final CommandSource either = ctx.get(FabricCommandContextKeys.NATIVE_COMMAND_SOURCE);
|
||||
if (!(either instanceof ServerCommandSource)) {
|
||||
return ArgumentParseResult.failure(serverOnly());
|
||||
}
|
||||
try {
|
||||
return ArgumentParseResult.success(new MultipleEntitySelector(
|
||||
((EntitySelectorAccess) entitySelector).inputString(),
|
||||
entitySelector,
|
||||
Collections.unmodifiableCollection(entitySelector.getEntities((ServerCommandSource) either))
|
||||
));
|
||||
} catch (final CommandSyntaxException ex) {
|
||||
return ArgumentParseResult.failure(ex);
|
||||
}
|
||||
});
|
||||
.map((ctx, entitySelector) -> requireServerCommandSource(
|
||||
ctx,
|
||||
serverCommandSource -> handleCommandSyntaxExceptionAsFailure(
|
||||
() -> ArgumentParseResult.success(new MultipleEntitySelector(
|
||||
((EntitySelectorAccess) entitySelector).inputString(),
|
||||
entitySelector,
|
||||
Collections.unmodifiableCollection(entitySelector.getEntities(serverCommandSource))
|
||||
))
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -187,28 +240,75 @@ public final class FabricArgumentParsers {
|
|||
*/
|
||||
public static <C> @NonNull ArgumentParser<C, Message> message() {
|
||||
return new WrappedBrigadierParser<C, MessageArgumentType.MessageFormat>(MessageArgumentType.message())
|
||||
.map((ctx, format) -> {
|
||||
final CommandSource either = ctx.get(FabricCommandContextKeys.NATIVE_COMMAND_SOURCE);
|
||||
if (!(either instanceof ServerCommandSource)) {
|
||||
return ArgumentParseResult.failure(serverOnly());
|
||||
}
|
||||
try {
|
||||
return ArgumentParseResult.success(MessageImpl.from(
|
||||
(ServerCommandSource) either,
|
||||
format,
|
||||
true
|
||||
));
|
||||
} catch (final CommandSyntaxException ex) {
|
||||
return ArgumentParseResult.failure(ex);
|
||||
}
|
||||
});
|
||||
.map((ctx, format) -> requireServerCommandSource(
|
||||
ctx,
|
||||
serverCommandSource -> handleCommandSyntaxExceptionAsFailure(
|
||||
() -> ArgumentParseResult.success(MessageImpl.from(
|
||||
serverCommandSource,
|
||||
format,
|
||||
true
|
||||
))
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
private interface CommandSyntaxExceptionThrowingParseResultSupplier<O> {
|
||||
|
||||
@NonNull ArgumentParseResult<O> result() throws CommandSyntaxException;
|
||||
|
||||
}
|
||||
|
||||
private static <O> @NonNull ArgumentParseResult<O> handleCommandSyntaxExceptionAsFailure(
|
||||
final @NonNull CommandSyntaxExceptionThrowingParseResultSupplier<O> resultSupplier
|
||||
) {
|
||||
try {
|
||||
return resultSupplier.result();
|
||||
} catch (final CommandSyntaxException ex) {
|
||||
return ArgumentParseResult.failure(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static @NonNull IllegalStateException serverOnly() {
|
||||
return new IllegalStateException("This command argument type is server-only.");
|
||||
}
|
||||
|
||||
private static <C, O> @NonNull ArgumentParseResult<O> requireServerCommandSource(
|
||||
final @NonNull CommandContext<C> context,
|
||||
final @NonNull Function<ServerCommandSource, ArgumentParseResult<O>> resultFunction
|
||||
) {
|
||||
final CommandSource nativeSource = context.get(FabricCommandContextKeys.NATIVE_COMMAND_SOURCE);
|
||||
if (!(nativeSource instanceof ServerCommandSource)) {
|
||||
return ArgumentParseResult.failure(serverOnly());
|
||||
}
|
||||
return resultFunction.apply((ServerCommandSource) nativeSource);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ParserParameter} keys for cloud-fabric.
|
||||
*
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static final class FabricParserParameters {
|
||||
|
||||
/**
|
||||
* Indicates that positions should be centered on the middle of blocks, i.e. x.5.
|
||||
*
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static final ParserParameter<Boolean> CENTER_INTEGERS = create("center_integers", TypeToken.get(Boolean.class));
|
||||
|
||||
private static <T> @NonNull ParserParameter<T> create(
|
||||
final @NonNull String key,
|
||||
final @NonNull TypeToken<T> expectedType
|
||||
) {
|
||||
return new ParserParameter<>(key, expectedType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static final class MessageImpl implements Message {
|
||||
|
||||
private final Collection<Entity> mentionedEntities;
|
||||
private final Text contents;
|
||||
|
||||
|
|
@ -217,7 +317,7 @@ public final class FabricArgumentParsers {
|
|||
final MessageArgumentType.@NonNull MessageFormat message,
|
||||
final boolean useSelectors
|
||||
) throws CommandSyntaxException {
|
||||
final Text contents = message.format(source, useSelectors);
|
||||
final Text contents = message.format(source, useSelectors);
|
||||
final MessageArgumentType.MessageSelector[] selectors =
|
||||
((MessageArgumentTypeMessageFormatAccess) message).accessor$selectors();
|
||||
final Collection<Entity> entities;
|
||||
|
|
@ -226,7 +326,9 @@ public final class FabricArgumentParsers {
|
|||
} else {
|
||||
entities = new HashSet<>();
|
||||
for (final MessageArgumentType.MessageSelector selector : selectors) {
|
||||
entities.addAll(((MessageArgumentTypeMessageSelectorAccess) selector).accessor$selector().getEntities(source));
|
||||
entities.addAll(((MessageArgumentTypeMessageSelectorAccess) selector)
|
||||
.accessor$selector()
|
||||
.getEntities(source));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -250,4 +352,49 @@ public final class FabricArgumentParsers {
|
|||
|
||||
}
|
||||
|
||||
static final class CoordinatesImpl implements Coordinates,
|
||||
Coordinates.CoordinatesXZ,
|
||||
Coordinates.BlockCoordinates,
|
||||
Coordinates.ColumnCoordinates {
|
||||
|
||||
private final ServerCommandSource source;
|
||||
private final PosArgument posArgument;
|
||||
|
||||
private CoordinatesImpl(final @NonNull ServerCommandSource source, final @NonNull PosArgument posArgument) {
|
||||
this.source = source;
|
||||
this.posArgument = posArgument;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Vec3d position() {
|
||||
return this.posArgument.toAbsolutePos(this.source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull BlockPos blockPos() {
|
||||
return new BlockPos(this.position());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isXRelative() {
|
||||
return this.posArgument.isXRelative();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isYRelative() {
|
||||
return this.posArgument.isYRelative();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isZRelative() {
|
||||
return this.posArgument.isZRelative();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull PosArgument getWrappedCoordinates() {
|
||||
return this.posArgument;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,151 @@
|
|||
//
|
||||
// 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.fabric.argument.server;
|
||||
|
||||
import cloud.commandframework.arguments.CommandArgument;
|
||||
import cloud.commandframework.context.CommandContext;
|
||||
import cloud.commandframework.fabric.argument.FabricArgumentParsers;
|
||||
import cloud.commandframework.fabric.data.Coordinates.BlockCoordinates;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
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 resolving block coordinates.
|
||||
*
|
||||
* @param <C> the sender type
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public final class BlockPosArgument<C> extends CommandArgument<C, BlockCoordinates> {
|
||||
|
||||
BlockPosArgument(
|
||||
final boolean required,
|
||||
final @NonNull String name,
|
||||
final @NonNull String defaultValue,
|
||||
final @Nullable BiFunction<CommandContext<C>, String, List<String>> suggestionsProvider
|
||||
) {
|
||||
super(
|
||||
required,
|
||||
name,
|
||||
FabricArgumentParsers.blockPos(),
|
||||
defaultValue,
|
||||
BlockCoordinates.class,
|
||||
suggestionsProvider
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new builder.
|
||||
*
|
||||
* @param name Name of the argument
|
||||
* @param <C> Command sender type
|
||||
* @return Created builder
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static <C> BlockPosArgument.@NonNull Builder<C> newBuilder(final @NonNull String name) {
|
||||
return new BlockPosArgument.Builder<>(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new required command argument.
|
||||
*
|
||||
* @param name Component name
|
||||
* @param <C> Command sender type
|
||||
* @return Created argument
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static <C> @NonNull BlockPosArgument<C> of(final @NonNull String name) {
|
||||
return BlockPosArgument.<C>newBuilder(name).asRequired().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new optional command argument
|
||||
*
|
||||
* @param name Component name
|
||||
* @param <C> Command sender type
|
||||
* @return Created argument
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static <C> @NonNull BlockPosArgument<C> optional(final @NonNull String name) {
|
||||
return BlockPosArgument.<C>newBuilder(name).asOptional().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new optional command argument
|
||||
*
|
||||
* @param name Component name
|
||||
* @param defaultValue default value
|
||||
* @param <C> Command sender type
|
||||
* @return Created argument
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static <C> @NonNull BlockPosArgument<C> optional(final @NonNull String name, final @NonNull BlockPos defaultValue) {
|
||||
return BlockPosArgument.<C>newBuilder(name)
|
||||
.asOptionalWithDefault(serializeBlockPos(defaultValue))
|
||||
.build();
|
||||
}
|
||||
|
||||
private static @NonNull String serializeBlockPos(final @NonNull BlockPos pos) {
|
||||
return String.format(
|
||||
"%s %s %s",
|
||||
pos.getX(),
|
||||
pos.getY(),
|
||||
pos.getZ()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for {@link BlockPosArgument}.
|
||||
*
|
||||
* @param <C> sender type
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static final class Builder<C> extends TypedBuilder<C, BlockCoordinates, Builder<C>> {
|
||||
|
||||
Builder(final @NonNull String name) {
|
||||
super(BlockCoordinates.class, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a block position argument.
|
||||
*
|
||||
* @return Constructed argument
|
||||
* @since 1.5.0
|
||||
*/
|
||||
@Override
|
||||
public @NonNull BlockPosArgument<C> build() {
|
||||
return new BlockPosArgument<>(
|
||||
this.isRequired(),
|
||||
this.getName(),
|
||||
this.getDefaultValue(),
|
||||
this.getSuggestionsProvider()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
//
|
||||
// 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.fabric.argument.server;
|
||||
|
||||
import cloud.commandframework.arguments.CommandArgument;
|
||||
import cloud.commandframework.context.CommandContext;
|
||||
import cloud.commandframework.fabric.argument.FabricArgumentParsers;
|
||||
import cloud.commandframework.fabric.data.Coordinates.ColumnCoordinates;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
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 resolving column (xz) coordinates.
|
||||
*
|
||||
* @param <C> the sender type
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public final class ColumnPosArgument<C> extends CommandArgument<C, ColumnCoordinates> {
|
||||
|
||||
ColumnPosArgument(
|
||||
final boolean required,
|
||||
final @NonNull String name,
|
||||
final @NonNull String defaultValue,
|
||||
final @Nullable BiFunction<CommandContext<C>, String, List<String>> suggestionsProvider
|
||||
) {
|
||||
super(
|
||||
required,
|
||||
name,
|
||||
FabricArgumentParsers.columnPos(),
|
||||
defaultValue,
|
||||
ColumnCoordinates.class,
|
||||
suggestionsProvider
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new builder.
|
||||
*
|
||||
* @param name Name of the argument
|
||||
* @param <C> Command sender type
|
||||
* @return Created builder
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static <C> ColumnPosArgument.@NonNull Builder<C> newBuilder(final @NonNull String name) {
|
||||
return new ColumnPosArgument.Builder<>(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new required command argument.
|
||||
*
|
||||
* @param name Component name
|
||||
* @param <C> Command sender type
|
||||
* @return Created argument
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static <C> @NonNull ColumnPosArgument<C> of(final @NonNull String name) {
|
||||
return ColumnPosArgument.<C>newBuilder(name).asRequired().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new optional command argument
|
||||
*
|
||||
* @param name Component name
|
||||
* @param <C> Command sender type
|
||||
* @return Created argument
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static <C> @NonNull ColumnPosArgument<C> optional(final @NonNull String name) {
|
||||
return ColumnPosArgument.<C>newBuilder(name).asOptional().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new optional command argument
|
||||
*
|
||||
* @param name Component name
|
||||
* @param defaultValue default value, y coordinate will be ignored as it is always 0
|
||||
* @param <C> Command sender type
|
||||
* @return Created argument
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static <C> @NonNull ColumnPosArgument<C> optional(final @NonNull String name, final @NonNull BlockPos defaultValue) {
|
||||
return ColumnPosArgument.<C>newBuilder(name)
|
||||
.asOptionalWithDefault(serializeColumnPos(defaultValue))
|
||||
.build();
|
||||
}
|
||||
|
||||
private static @NonNull String serializeColumnPos(final @NonNull BlockPos pos) {
|
||||
return String.format(
|
||||
"%s %s",
|
||||
pos.getX(),
|
||||
pos.getZ()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for {@link ColumnPosArgument}.
|
||||
*
|
||||
* @param <C> sender type
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static final class Builder<C> extends TypedBuilder<C, ColumnCoordinates, Builder<C>> {
|
||||
|
||||
Builder(final @NonNull String name) {
|
||||
super(ColumnCoordinates.class, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a column position argument.
|
||||
*
|
||||
* @return Constructed argument
|
||||
* @since 1.5.0
|
||||
*/
|
||||
@Override
|
||||
public @NonNull ColumnPosArgument<C> build() {
|
||||
return new ColumnPosArgument<>(
|
||||
this.isRequired(),
|
||||
this.getName(),
|
||||
this.getDefaultValue(),
|
||||
this.getSuggestionsProvider()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,236 @@
|
|||
//
|
||||
// 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.fabric.argument.server;
|
||||
|
||||
import cloud.commandframework.arguments.CommandArgument;
|
||||
import cloud.commandframework.context.CommandContext;
|
||||
import cloud.commandframework.fabric.argument.FabricArgumentParsers;
|
||||
import cloud.commandframework.fabric.data.Coordinates;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
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 resolving x and z coordinates from 2 doubles.
|
||||
*
|
||||
* @param <C> the sender type
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public final class Vec2Argument<C> extends CommandArgument<C, Coordinates.CoordinatesXZ> {
|
||||
|
||||
private final boolean centerIntegers;
|
||||
|
||||
Vec2Argument(
|
||||
final boolean required,
|
||||
final @NonNull String name,
|
||||
final @NonNull String defaultValue,
|
||||
final @Nullable BiFunction<CommandContext<C>, String, List<String>> suggestionsProvider,
|
||||
final boolean centerIntegers
|
||||
) {
|
||||
super(
|
||||
required,
|
||||
name,
|
||||
FabricArgumentParsers.vec2(centerIntegers),
|
||||
defaultValue,
|
||||
Coordinates.CoordinatesXZ.class,
|
||||
suggestionsProvider
|
||||
);
|
||||
this.centerIntegers = centerIntegers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether integers will be centered to x.5. Defaults to false.
|
||||
*
|
||||
* @return whether integers will be centered
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public boolean centerIntegers() {
|
||||
return this.centerIntegers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new builder.
|
||||
*
|
||||
* @param name Name of the argument
|
||||
* @param <C> Command sender type
|
||||
* @return Created builder
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static <C> Vec2Argument.@NonNull Builder<C> newBuilder(final @NonNull String name) {
|
||||
return new Vec2Argument.Builder<>(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new required command argument.
|
||||
*
|
||||
* @param name Component name
|
||||
* @param <C> Command sender type
|
||||
* @return Created argument
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static <C> @NonNull Vec2Argument<C> of(final @NonNull String name) {
|
||||
return Vec2Argument.<C>newBuilder(name).asRequired().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new required command argument.
|
||||
*
|
||||
* @param name Component name
|
||||
* @param centerIntegers whether to center integers to x.5.
|
||||
* @param <C> Command sender type
|
||||
* @return Created argument
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static <C> @NonNull Vec2Argument<C> of(final @NonNull String name, final boolean centerIntegers) {
|
||||
return Vec2Argument.<C>newBuilder(name).centerIntegers(centerIntegers).asRequired().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new optional command argument
|
||||
*
|
||||
* @param name Component name
|
||||
* @param <C> Command sender type
|
||||
* @return Created argument
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static <C> @NonNull Vec2Argument<C> optional(final @NonNull String name) {
|
||||
return Vec2Argument.<C>newBuilder(name).asOptional().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new optional command argument
|
||||
*
|
||||
* @param name Component name
|
||||
* @param centerIntegers whether to center integers to x.5.
|
||||
* @param <C> Command sender type
|
||||
* @return Created argument
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static <C> @NonNull Vec2Argument<C> optional(final @NonNull String name, final boolean centerIntegers) {
|
||||
return Vec2Argument.<C>newBuilder(name).centerIntegers(centerIntegers).asOptional().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new optional command argument
|
||||
*
|
||||
* @param name Component name
|
||||
* @param defaultValue default value, y will be ignored as it is always 0
|
||||
* @param <C> Command sender type
|
||||
* @return Created argument
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static <C> @NonNull Vec2Argument<C> optional(final @NonNull String name, final @NonNull Vec3d defaultValue) {
|
||||
return Vec2Argument.<C>newBuilder(name)
|
||||
.asOptionalWithDefault(serializeXandZ(defaultValue))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new optional command argument
|
||||
*
|
||||
* @param name Component name
|
||||
* @param defaultValue default value, y will be ignored as it is always 0
|
||||
* @param centerIntegers whether to center integers to x.5.
|
||||
* @param <C> Command sender type
|
||||
* @return Created argument
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static <C> @NonNull Vec2Argument<C> optional(
|
||||
final @NonNull String name,
|
||||
final boolean centerIntegers,
|
||||
final @NonNull Vec3d defaultValue
|
||||
) {
|
||||
return Vec2Argument.<C>newBuilder(name)
|
||||
.centerIntegers(centerIntegers)
|
||||
.asOptionalWithDefault(serializeXandZ(defaultValue))
|
||||
.build();
|
||||
}
|
||||
|
||||
private static @NonNull String serializeXandZ(final @NonNull Vec3d vec3d) {
|
||||
return String.format(
|
||||
"%.10f %.10f",
|
||||
vec3d.x,
|
||||
vec3d.z
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for {@link Vec2Argument}.
|
||||
*
|
||||
* @param <C> sender type
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static final class Builder<C> extends TypedBuilder<C, Coordinates.CoordinatesXZ, Builder<C>> {
|
||||
|
||||
private boolean centerIntegers = false;
|
||||
|
||||
Builder(final @NonNull String name) {
|
||||
super(Coordinates.CoordinatesXZ.class, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether integers will be centered to x.5. Will be false by default if unset.
|
||||
*
|
||||
* @param centerIntegers whether integers will be centered
|
||||
* @return this builder
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public @NonNull Builder<C> centerIntegers(final boolean centerIntegers) {
|
||||
this.centerIntegers = centerIntegers;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether integers will be centered to x.5. Defaults to false.
|
||||
*
|
||||
* @return whether integers will be centered
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public boolean centerIntegers() {
|
||||
return this.centerIntegers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a vec2 argument.
|
||||
*
|
||||
* @return Constructed argument
|
||||
* @since 1.5.0
|
||||
*/
|
||||
@Override
|
||||
public @NonNull Vec2Argument<C> build() {
|
||||
return new Vec2Argument<>(
|
||||
this.isRequired(),
|
||||
this.getName(),
|
||||
this.getDefaultValue(),
|
||||
this.getSuggestionsProvider(),
|
||||
this.centerIntegers()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,237 @@
|
|||
//
|
||||
// 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.fabric.argument.server;
|
||||
|
||||
import cloud.commandframework.arguments.CommandArgument;
|
||||
import cloud.commandframework.context.CommandContext;
|
||||
import cloud.commandframework.fabric.argument.FabricArgumentParsers;
|
||||
import cloud.commandframework.fabric.data.Coordinates;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
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 resolving coordinates from 3 doubles.
|
||||
*
|
||||
* @param <C> the sender type
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public final class Vec3Argument<C> extends CommandArgument<C, Coordinates> {
|
||||
|
||||
private final boolean centerIntegers;
|
||||
|
||||
Vec3Argument(
|
||||
final boolean required,
|
||||
final @NonNull String name,
|
||||
final @NonNull String defaultValue,
|
||||
final @Nullable BiFunction<CommandContext<C>, String, List<String>> suggestionsProvider,
|
||||
final boolean centerIntegers
|
||||
) {
|
||||
super(
|
||||
required,
|
||||
name,
|
||||
FabricArgumentParsers.vec3(centerIntegers),
|
||||
defaultValue,
|
||||
Coordinates.class,
|
||||
suggestionsProvider
|
||||
);
|
||||
this.centerIntegers = centerIntegers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether integers will be centered to x.5. Defaults to false.
|
||||
*
|
||||
* @return whether integers will be centered
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public boolean centerIntegers() {
|
||||
return this.centerIntegers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new builder.
|
||||
*
|
||||
* @param name Name of the argument
|
||||
* @param <C> Command sender type
|
||||
* @return Created builder
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static <C> Vec3Argument.@NonNull Builder<C> newBuilder(final @NonNull String name) {
|
||||
return new Vec3Argument.Builder<>(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new required command argument.
|
||||
*
|
||||
* @param name Component name
|
||||
* @param <C> Command sender type
|
||||
* @return Created argument
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static <C> @NonNull Vec3Argument<C> of(final @NonNull String name) {
|
||||
return Vec3Argument.<C>newBuilder(name).asRequired().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new required command argument.
|
||||
*
|
||||
* @param name Component name
|
||||
* @param centerIntegers whether to center integers to x.5.
|
||||
* @param <C> Command sender type
|
||||
* @return Created argument
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static <C> @NonNull Vec3Argument<C> of(final @NonNull String name, final boolean centerIntegers) {
|
||||
return Vec3Argument.<C>newBuilder(name).centerIntegers(centerIntegers).asRequired().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new optional command argument
|
||||
*
|
||||
* @param name Component name
|
||||
* @param <C> Command sender type
|
||||
* @return Created argument
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static <C> @NonNull Vec3Argument<C> optional(final @NonNull String name) {
|
||||
return Vec3Argument.<C>newBuilder(name).asOptional().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new optional command argument
|
||||
*
|
||||
* @param name Component name
|
||||
* @param centerIntegers whether to center integers to x.5.
|
||||
* @param <C> Command sender type
|
||||
* @return Created argument
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static <C> @NonNull Vec3Argument<C> optional(final @NonNull String name, final boolean centerIntegers) {
|
||||
return Vec3Argument.<C>newBuilder(name).centerIntegers(centerIntegers).asOptional().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new optional command argument
|
||||
*
|
||||
* @param name Component name
|
||||
* @param defaultValue default value
|
||||
* @param <C> Command sender type
|
||||
* @return Created argument
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static <C> @NonNull Vec3Argument<C> optional(final @NonNull String name, final @NonNull Vec3d defaultValue) {
|
||||
return Vec3Argument.<C>newBuilder(name)
|
||||
.asOptionalWithDefault(serializeVec3(defaultValue))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new optional command argument
|
||||
*
|
||||
* @param name Component name
|
||||
* @param defaultValue default value
|
||||
* @param centerIntegers whether to center integers to x.5.
|
||||
* @param <C> Command sender type
|
||||
* @return Created argument
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static <C> @NonNull Vec3Argument<C> optional(
|
||||
final @NonNull String name,
|
||||
final boolean centerIntegers,
|
||||
final @NonNull Vec3d defaultValue
|
||||
) {
|
||||
return Vec3Argument.<C>newBuilder(name)
|
||||
.centerIntegers(centerIntegers)
|
||||
.asOptionalWithDefault(serializeVec3(defaultValue))
|
||||
.build();
|
||||
}
|
||||
|
||||
private static @NonNull String serializeVec3(final @NonNull Vec3d vec3d) {
|
||||
return String.format(
|
||||
"%.10f %.10f %.10f",
|
||||
vec3d.x,
|
||||
vec3d.y,
|
||||
vec3d.z
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for {@link Vec3Argument}.
|
||||
*
|
||||
* @param <C> sender type
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public static final class Builder<C> extends TypedBuilder<C, Coordinates, Builder<C>> {
|
||||
|
||||
private boolean centerIntegers = false;
|
||||
|
||||
Builder(final @NonNull String name) {
|
||||
super(Coordinates.class, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether integers will be centered to x.5. Will be false by default if unset.
|
||||
*
|
||||
* @param centerIntegers whether integers will be centered
|
||||
* @return this builder
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public @NonNull Builder<C> centerIntegers(final boolean centerIntegers) {
|
||||
this.centerIntegers = centerIntegers;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether integers will be centered to x.5. Defaults to false.
|
||||
*
|
||||
* @return whether integers will be centered
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public boolean centerIntegers() {
|
||||
return this.centerIntegers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a vec3 argument.
|
||||
*
|
||||
* @return Constructed argument
|
||||
* @since 1.5.0
|
||||
*/
|
||||
@Override
|
||||
public @NonNull Vec3Argument<C> build() {
|
||||
return new Vec3Argument<>(
|
||||
this.isRequired(),
|
||||
this.getName(),
|
||||
this.getDefaultValue(),
|
||||
this.getSuggestionsProvider(),
|
||||
this.centerIntegers()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
//
|
||||
// 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.fabric.data;
|
||||
|
||||
import net.minecraft.command.argument.BlockPosArgumentType;
|
||||
import net.minecraft.command.argument.ColumnPosArgumentType;
|
||||
import net.minecraft.command.argument.PosArgument;
|
||||
import net.minecraft.command.argument.Vec2ArgumentType;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
/**
|
||||
* A {@link PosArgument} wrapper for easier use with cloud commands.
|
||||
*
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public interface Coordinates {
|
||||
|
||||
/**
|
||||
* Resolve a position from the parsed coordinates.
|
||||
*
|
||||
* @return position
|
||||
* @since 1.5.0
|
||||
*/
|
||||
@NonNull Vec3d position();
|
||||
|
||||
/**
|
||||
* Resolve a block position from the parsed coordinates.
|
||||
*
|
||||
* @return block position
|
||||
* @since 1.5.0
|
||||
*/
|
||||
@NonNull BlockPos blockPos();
|
||||
|
||||
/**
|
||||
* Get whether the x coordinate is relative.
|
||||
*
|
||||
* @return whether the x coordinate is relative
|
||||
* @since 1.5.0
|
||||
*/
|
||||
boolean isXRelative();
|
||||
|
||||
/**
|
||||
* Get whether the y coordinate is relative.
|
||||
*
|
||||
* @return whether the y coordinate is relative
|
||||
* @since 1.5.0
|
||||
*/
|
||||
boolean isYRelative();
|
||||
|
||||
/**
|
||||
* Get whether the z coordinate is relative.
|
||||
*
|
||||
* @return whether the z coordinate is relative
|
||||
* @since 1.5.0
|
||||
*/
|
||||
boolean isZRelative();
|
||||
|
||||
/**
|
||||
* Get the coordinates wrapped by this {@link Coordinates}.
|
||||
*
|
||||
* @return the base coordinates
|
||||
* @since 1.5.0
|
||||
*/
|
||||
@NonNull PosArgument getWrappedCoordinates();
|
||||
|
||||
/**
|
||||
* A specialized version of {@link Coordinates} for representing the result of the vanilla {@link Vec2ArgumentType},
|
||||
* which accepts two doubles for the x and z coordinate, always defaulting to 0 for the y coordinate.
|
||||
*
|
||||
* @since 1.5.0
|
||||
*/
|
||||
interface CoordinatesXZ extends Coordinates {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A specialized version of {@link Coordinates} for representing the result of the vanilla {@link BlockPosArgumentType}.
|
||||
*
|
||||
* @since 1.5.0
|
||||
*/
|
||||
interface BlockCoordinates extends Coordinates {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A specialized version of {@link Coordinates} for representing the result of the vanilla {@link ColumnPosArgumentType}.
|
||||
*
|
||||
* @since 1.5.0
|
||||
*/
|
||||
interface ColumnCoordinates extends Coordinates {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -33,9 +33,16 @@ import cloud.commandframework.execution.CommandExecutionCoordinator;
|
|||
import cloud.commandframework.fabric.FabricServerCommandManager;
|
||||
import cloud.commandframework.fabric.argument.ColorArgument;
|
||||
import cloud.commandframework.fabric.argument.ItemDataArgument;
|
||||
import cloud.commandframework.fabric.argument.server.ColumnPosArgument;
|
||||
import cloud.commandframework.fabric.argument.server.MultipleEntitySelectorArgument;
|
||||
import cloud.commandframework.fabric.argument.server.MultiplePlayerSelectorArgument;
|
||||
import cloud.commandframework.fabric.argument.server.Vec3Argument;
|
||||
import cloud.commandframework.fabric.data.Coordinates;
|
||||
import cloud.commandframework.fabric.data.Coordinates.ColumnCoordinates;
|
||||
import cloud.commandframework.fabric.data.MultipleEntitySelector;
|
||||
import cloud.commandframework.fabric.data.MultiplePlayerSelector;
|
||||
import cloud.commandframework.fabric.testmod.mixin.GiveCommandAccess;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.fabricmc.loader.api.ModContainer;
|
||||
|
|
@ -52,6 +59,8 @@ import net.minecraft.text.MutableText;
|
|||
import net.minecraft.text.TextColor;
|
||||
import net.minecraft.util.Formatting;
|
||||
import net.minecraft.util.Util;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
|
|
@ -217,6 +226,33 @@ public final class FabricExample implements ModInitializer {
|
|||
false
|
||||
);
|
||||
}));
|
||||
|
||||
manager.command(base.literal("teleport")
|
||||
.permission("cloud.teleport")
|
||||
.argument(MultipleEntitySelectorArgument.of("targets"))
|
||||
.argument(Vec3Argument.of("location"))
|
||||
.handler(ctx -> {
|
||||
final MultipleEntitySelector selector = ctx.get("targets");
|
||||
final Vec3d location = ctx.<Coordinates>get("location").position();
|
||||
selector.get().forEach(target ->
|
||||
target.requestTeleport(location.getX(), location.getY(), location.getZ()));
|
||||
}));
|
||||
|
||||
manager.command(base.literal("gotochunk")
|
||||
.permission("cloud.gotochunk")
|
||||
.argument(ColumnPosArgument.of("chunk_position"))
|
||||
.handler(ctx -> {
|
||||
final ServerPlayerEntity player;
|
||||
try {
|
||||
player = ctx.getSender().getPlayer();
|
||||
} catch (final CommandSyntaxException e) {
|
||||
ctx.getSender().sendFeedback(new LiteralText("Must be a player to use this command"), false);
|
||||
return;
|
||||
}
|
||||
final Vec3d vec = ctx.<ColumnCoordinates>get("chunk_position").position();
|
||||
final ChunkPos pos = new ChunkPos((int) vec.getX(), (int) vec.getZ());
|
||||
player.requestTeleport(pos.getStartX(), 128, pos.getStartZ());
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue