110 lines
4.2 KiB
Java
110 lines
4.2 KiB
Java
package net.minecraft.commands.arguments;
|
|
|
|
import com.mojang.brigadier.StringReader;
|
|
import com.mojang.brigadier.arguments.ArgumentType;
|
|
import com.mojang.brigadier.context.CommandContext;
|
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
|
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
|
import com.mojang.brigadier.suggestion.Suggestions;
|
|
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
|
import java.util.Arrays;
|
|
import java.util.Collection;
|
|
import java.util.concurrent.CompletableFuture;
|
|
import net.minecraft.commands.CommandSourceStack;
|
|
import net.minecraft.commands.SharedSuggestionProvider;
|
|
import net.minecraft.network.chat.Component;
|
|
import net.minecraft.util.Mth;
|
|
import net.minecraft.world.scores.ScoreAccess;
|
|
|
|
public class OperationArgument implements ArgumentType<OperationArgument.Operation> {
|
|
private static final Collection<String> EXAMPLES = Arrays.asList("=", ">", "<");
|
|
private static final SimpleCommandExceptionType ERROR_INVALID_OPERATION = new SimpleCommandExceptionType(Component.translatable("arguments.operation.invalid"));
|
|
private static final SimpleCommandExceptionType ERROR_DIVIDE_BY_ZERO = new SimpleCommandExceptionType(Component.translatable("arguments.operation.div0"));
|
|
|
|
public static OperationArgument operation() {
|
|
return new OperationArgument();
|
|
}
|
|
|
|
public static OperationArgument.Operation getOperation(CommandContext<CommandSourceStack> context, String name) {
|
|
return context.getArgument(name, OperationArgument.Operation.class);
|
|
}
|
|
|
|
public OperationArgument.Operation parse(StringReader reader) throws CommandSyntaxException {
|
|
if (!reader.canRead()) {
|
|
throw ERROR_INVALID_OPERATION.createWithContext(reader);
|
|
} else {
|
|
int i = reader.getCursor();
|
|
|
|
while (reader.canRead() && reader.peek() != ' ') {
|
|
reader.skip();
|
|
}
|
|
|
|
return getOperation(reader.getString().substring(i, reader.getCursor()));
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> commandContext, SuggestionsBuilder suggestionsBuilder) {
|
|
return SharedSuggestionProvider.suggest(new String[]{"=", "+=", "-=", "*=", "/=", "%=", "<", ">", "><"}, suggestionsBuilder);
|
|
}
|
|
|
|
@Override
|
|
public Collection<String> getExamples() {
|
|
return EXAMPLES;
|
|
}
|
|
|
|
/**
|
|
* Makes an {@link net.minecraft.commands.arguments.OperationArgument.Operation} instance based on the given name. This method handles all operations.
|
|
*/
|
|
private static OperationArgument.Operation getOperation(String name) throws CommandSyntaxException {
|
|
return (OperationArgument.Operation)(name.equals("><") ? (scoreAccess, scoreAccess2) -> {
|
|
int i = scoreAccess.get();
|
|
scoreAccess.set(scoreAccess2.get());
|
|
scoreAccess2.set(i);
|
|
} : getSimpleOperation(name));
|
|
}
|
|
|
|
/**
|
|
* Makes an {@link net.minecraft.commands.arguments.OperationArgument.Operation} instance based on the given name. This method actually returns {@link net.minecraft.commands.arguments.OperationArgument.SimpleOperation}, which is used as a functional interface target with 2 ints. It handles all operations other than swap (><).
|
|
*/
|
|
private static OperationArgument.SimpleOperation getSimpleOperation(String name) throws CommandSyntaxException {
|
|
return switch (name) {
|
|
case "=" -> (i, j) -> j;
|
|
case "+=" -> Integer::sum;
|
|
case "-=" -> (i, j) -> i - j;
|
|
case "*=" -> (i, j) -> i * j;
|
|
case "/=" -> (i, j) -> {
|
|
if (j == 0) {
|
|
throw ERROR_DIVIDE_BY_ZERO.create();
|
|
} else {
|
|
return Mth.floorDiv(i, j);
|
|
}
|
|
};
|
|
case "%=" -> (i, j) -> {
|
|
if (j == 0) {
|
|
throw ERROR_DIVIDE_BY_ZERO.create();
|
|
} else {
|
|
return Mth.positiveModulo(i, j);
|
|
}
|
|
};
|
|
case "<" -> Math::min;
|
|
case ">" -> Math::max;
|
|
default -> throw ERROR_INVALID_OPERATION.create();
|
|
};
|
|
}
|
|
|
|
@FunctionalInterface
|
|
public interface Operation {
|
|
void apply(ScoreAccess scoreAccess, ScoreAccess scoreAccess2) throws CommandSyntaxException;
|
|
}
|
|
|
|
@FunctionalInterface
|
|
interface SimpleOperation extends OperationArgument.Operation {
|
|
int apply(int i, int j) throws CommandSyntaxException;
|
|
|
|
@Override
|
|
default void apply(ScoreAccess scoreAccess, ScoreAccess scoreAccess2) throws CommandSyntaxException {
|
|
scoreAccess.set(this.apply(scoreAccess.get(), scoreAccess2.get()));
|
|
}
|
|
}
|
|
}
|