custom args WIP
This commit is contained in:
1 parent
a0fc6b3af1
commit
1d81768c54
4 files changed
+178
-37
No files matched your search
@@ -449,7 +449,7 @@ public class ScriptCommand
|
|||||||
}
|
}
|
||||||
//if (!(args.trim().isEmpty()))
|
//if (!(args.trim().isEmpty()))
|
||||||
// arguments.addAll(Arrays.asList(args.trim().split("\\s+")));
|
// arguments.addAll(Arrays.asList(args.trim().split("\\s+")));
|
||||||
return handleCall(source, host, () -> host.call(source, call, positions, args));
|
return handleCall(source, host, () -> host.callLegacy(source, call, positions, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ public class CarpetScriptHost extends ScriptHost
|
|||||||
private int saveTimeout;
|
private int saveTimeout;
|
||||||
public boolean persistenceRequired;
|
public boolean persistenceRequired;
|
||||||
|
|
||||||
|
public Map<Value, Value> appConfig = Collections.emptyMap();
|
||||||
|
|
||||||
private CarpetScriptHost(CarpetScriptServer server, Module code, boolean perUser, ScriptHost parent)
|
private CarpetScriptHost(CarpetScriptServer server, Module code, boolean perUser, ScriptHost parent)
|
||||||
{
|
{
|
||||||
super(code, perUser, parent);
|
super(code, perUser, parent);
|
||||||
@@ -128,6 +130,7 @@ public class CarpetScriptHost extends ScriptHost
|
|||||||
Map<Value, Value> config = ((MapValue) ret).getMap();
|
Map<Value, Value> config = ((MapValue) ret).getMap();
|
||||||
setPerPlayer(config.getOrDefault(new StringValue("scope"), new StringValue("player")).getString().equalsIgnoreCase("player"));
|
setPerPlayer(config.getOrDefault(new StringValue("scope"), new StringValue("player")).getString().equalsIgnoreCase("player"));
|
||||||
persistenceRequired = config.getOrDefault(new StringValue("stay_loaded"), Value.FALSE).getBoolean();
|
persistenceRequired = config.getOrDefault(new StringValue("stay_loaded"), Value.FALSE).getBoolean();
|
||||||
|
this.appConfig = config;
|
||||||
}
|
}
|
||||||
catch (NullPointerException | InvalidCallbackException ignored)
|
catch (NullPointerException | InvalidCallbackException ignored)
|
||||||
{
|
{
|
||||||
@@ -185,11 +188,11 @@ public class CarpetScriptHost extends ScriptHost
|
|||||||
return host;
|
return host;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Value handleCommand(ServerCommandSource source, String call, List<Integer> coords, String arg)
|
public Value handleCommandLegacy(ServerCommandSource source, String call, List<Integer> coords, String arg)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return call(source, call, coords, arg);
|
return callLegacy(source, call, coords, arg);
|
||||||
}
|
}
|
||||||
catch (CarpetExpressionException exc)
|
catch (CarpetExpressionException exc)
|
||||||
{
|
{
|
||||||
@@ -203,7 +206,25 @@ public class CarpetScriptHost extends ScriptHost
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Value call(ServerCommandSource source, String call, List<Integer> coords, String arg)
|
public Value handleCommand(ServerCommandSource source, String call, List<Value> args)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return call(source, call, args);
|
||||||
|
}
|
||||||
|
catch (CarpetExpressionException exc)
|
||||||
|
{
|
||||||
|
handleErrorWithStack("Error while running custom command", exc);
|
||||||
|
return Value.NULL;
|
||||||
|
}
|
||||||
|
catch (ArithmeticException ae)
|
||||||
|
{
|
||||||
|
handleErrorWithStack("Math doesn't compute", ae);
|
||||||
|
return Value.NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Value callLegacy(ServerCommandSource source, String call, List<Integer> coords, String arg)
|
||||||
{
|
{
|
||||||
if (CarpetServer.scriptServer.stopAll)
|
if (CarpetServer.scriptServer.stopAll)
|
||||||
throw new CarpetExpressionException("SCARPET PAUSED", null);
|
throw new CarpetExpressionException("SCARPET PAUSED", null);
|
||||||
@@ -305,6 +326,42 @@ public class CarpetScriptHost extends ScriptHost
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Value call(ServerCommandSource source, String call, List<Value> suppliedArgs)
|
||||||
|
{
|
||||||
|
if (CarpetServer.scriptServer.stopAll)
|
||||||
|
throw new CarpetExpressionException("SCARPET PAUSED", null);
|
||||||
|
FunctionValue function = getFunction(call);
|
||||||
|
if (function == null)
|
||||||
|
throw new CarpetExpressionException("UNDEFINED", null);
|
||||||
|
|
||||||
|
List<LazyValue> argv = FunctionValue.lazify(suppliedArgs);
|
||||||
|
|
||||||
|
List<String> args = function.getArguments();
|
||||||
|
if (argv.size() != args.size())
|
||||||
|
{
|
||||||
|
String error = "Fail: stored function "+call+" takes "+args.size()+" arguments, not "+argv.size()+ ":\n";
|
||||||
|
for (int i = 0; i < max(argv.size(), args.size()); i++)
|
||||||
|
{
|
||||||
|
error += (i<args.size()?args.get(i):"??")+" => "+(i<argv.size()?argv.get(i).evalValue(null).getString():"??")+"\n";
|
||||||
|
}
|
||||||
|
throw new CarpetExpressionException(error, null);
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// TODO: this is just for now - invoke would be able to invoke other hosts scripts
|
||||||
|
Context context = new CarpetContext(this, source, BlockPos.ORIGIN);
|
||||||
|
return function.getExpression().evalValue(
|
||||||
|
() -> function.lazyEval(context, Context.VOID, function.getExpression(), function.getToken(), argv),
|
||||||
|
context,
|
||||||
|
Context.VOID
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch (ExpressionException e)
|
||||||
|
{
|
||||||
|
throw new CarpetExpressionException(e.getMessage(), e.stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Value callUDF(BlockPos pos, ServerCommandSource source, FunctionValue fun, List<Value> argv) throws InvalidCallbackException
|
public Value callUDF(BlockPos pos, ServerCommandSource source, FunctionValue fun, List<Value> argv) throws InvalidCallbackException
|
||||||
{
|
{
|
||||||
if (CarpetServer.scriptServer.stopAll)
|
if (CarpetServer.scriptServer.stopAll)
|
||||||
|
|||||||
@@ -5,15 +5,17 @@ import carpet.CarpetSettings;
|
|||||||
import carpet.CarpetServer;
|
import carpet.CarpetServer;
|
||||||
import carpet.script.bundled.FileModule;
|
import carpet.script.bundled.FileModule;
|
||||||
import carpet.script.bundled.Module;
|
import carpet.script.bundled.Module;
|
||||||
|
import carpet.script.command.CommandArgument;
|
||||||
import carpet.script.exception.InvalidCallbackException;
|
import carpet.script.exception.InvalidCallbackException;
|
||||||
import carpet.script.value.FunctionValue;
|
import carpet.script.value.FunctionValue;
|
||||||
import carpet.script.value.MapValue;
|
|
||||||
import carpet.script.value.StringValue;
|
import carpet.script.value.StringValue;
|
||||||
import carpet.script.value.ThreadValue;
|
|
||||||
import carpet.script.value.Value;
|
import carpet.script.value.Value;
|
||||||
import carpet.utils.Messenger;
|
import carpet.utils.Messenger;
|
||||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
|
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
||||||
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
import com.mojang.brigadier.tree.CommandNode;
|
import com.mojang.brigadier.tree.CommandNode;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.command.ServerCommandSource;
|
import net.minecraft.server.command.ServerCommandSource;
|
||||||
@@ -199,7 +201,7 @@ public class CarpetScriptServer
|
|||||||
|
|
||||||
private void addCommand(ServerCommandSource source, String hostName, boolean isReload)
|
private void addCommand(ServerCommandSource source, String hostName, boolean isReload)
|
||||||
{
|
{
|
||||||
ScriptHost host = modules.get(hostName);
|
CarpetScriptHost host = modules.get(hostName);
|
||||||
String loaded = isReload?"reloaded":"loaded";
|
String loaded = isReload?"reloaded":"loaded";
|
||||||
if (host == null)
|
if (host == null)
|
||||||
{
|
{
|
||||||
@@ -222,35 +224,84 @@ public class CarpetScriptServer
|
|||||||
executes( (c) ->
|
executes( (c) ->
|
||||||
{
|
{
|
||||||
Value response = modules.get(hostName).retrieveForExecution(c.getSource()).
|
Value response = modules.get(hostName).retrieveForExecution(c.getSource()).
|
||||||
handleCommand(c.getSource(),"__command", null, "");
|
handleCommandLegacy(c.getSource(),"__command", null, "");
|
||||||
if (!response.isNull()) Messenger.m(c.getSource(), "gi "+response.getString());
|
if (!response.isNull()) Messenger.m(c.getSource(), "gi "+response.getString());
|
||||||
return (int)response.readInteger();
|
return (int)response.readInteger();
|
||||||
});
|
});
|
||||||
|
|
||||||
for (String function : host.globaFunctionNames(host.main, s -> !s.startsWith("_")).sorted().collect(Collectors.toList()))
|
for (String function : host.globaFunctionNames(host.main, s -> !s.startsWith("_")).sorted().collect(Collectors.toList()))
|
||||||
{
|
{
|
||||||
command = command.
|
if (host.appConfig.containsKey(StringValue.of("test_command_type_support"))) // temporary stuff for testing
|
||||||
then(literal(function).
|
{
|
||||||
requires((player) -> modules.containsKey(hostName) && modules.get(hostName).getFunction(function) != null).
|
command = getFancyCommand(command, host, function);
|
||||||
executes( (c) -> {
|
}
|
||||||
Value response = modules.get(hostName).retrieveForExecution(c.getSource()).
|
else
|
||||||
handleCommand(c.getSource(), function,null,"");
|
{
|
||||||
if (!response.isNull()) Messenger.m(c.getSource(),"gi "+response.getString());
|
command = command.
|
||||||
return (int)response.readInteger();
|
then(literal(function).
|
||||||
}).
|
requires((player) -> modules.containsKey(hostName) && modules.get(hostName).getFunction(function) != null).
|
||||||
then(argument("args...", StringArgumentType.greedyString()).
|
executes((c) -> {
|
||||||
executes( (c) -> {
|
Value response = modules.get(hostName).retrieveForExecution(c.getSource()).
|
||||||
Value response = modules.get(hostName).retrieveForExecution(c.getSource()).
|
handleCommandLegacy(c.getSource(), function, null, "");
|
||||||
handleCommand(c.getSource(), function,null, StringArgumentType.getString(c, "args..."));
|
if (!response.isNull()) Messenger.m(c.getSource(), "gi " + response.getString());
|
||||||
if (!response.isNull()) Messenger.m(c.getSource(), "gi "+response.getString());
|
return (int) response.readInteger();
|
||||||
return (int)response.readInteger();
|
}).
|
||||||
})));
|
then(argument("args...", StringArgumentType.greedyString()).
|
||||||
|
executes( (c) -> {
|
||||||
|
Value response = modules.get(hostName).retrieveForExecution(c.getSource()).
|
||||||
|
handleCommandLegacy(c.getSource(), function,null, StringArgumentType.getString(c, "args..."));
|
||||||
|
if (!response.isNull()) Messenger.m(c.getSource(), "gi "+response.getString());
|
||||||
|
return (int)response.readInteger();
|
||||||
|
})));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Messenger.m(source, "gi "+hostName+" app "+loaded+" with /"+hostName+" command");
|
Messenger.m(source, "gi "+hostName+" app "+loaded+" with /"+hostName+" command");
|
||||||
server.getCommandManager().getDispatcher().register(command);
|
server.getCommandManager().getDispatcher().register(command);
|
||||||
CarpetServer.settingsManager.notifyPlayersCommandsChanged();
|
CarpetServer.settingsManager.notifyPlayersCommandsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int execute(CommandContext<ServerCommandSource> ctx, String hostName, String funName) throws CommandSyntaxException
|
||||||
|
{
|
||||||
|
CarpetScriptHost cHost = modules.get(hostName).retrieveForExecution(ctx.getSource());
|
||||||
|
List<String> argNames = cHost.getFunction(funName).getArguments();
|
||||||
|
List<Value> args = new ArrayList<>(argNames.size());
|
||||||
|
for (String s : argNames)
|
||||||
|
{
|
||||||
|
args.add(CommandArgument.getValue(ctx, s));
|
||||||
|
}
|
||||||
|
Value response = cHost.handleCommand(ctx.getSource(), funName, args);
|
||||||
|
if (!response.isNull()) Messenger.m(ctx.getSource(), "gi " + response.getString());
|
||||||
|
return (int) response.readInteger();
|
||||||
|
}
|
||||||
|
|
||||||
|
private LiteralArgumentBuilder<ServerCommandSource> getFancyCommand(LiteralArgumentBuilder<ServerCommandSource> command, ScriptHost host, String funName )
|
||||||
|
{
|
||||||
|
List<String> argNames = host.getFunction(funName).getArguments();
|
||||||
|
String hostName = host.getName();
|
||||||
|
if (argNames.size() == 0)
|
||||||
|
{
|
||||||
|
return command.then(literal(funName).
|
||||||
|
requires((player) -> modules.containsKey(hostName) && modules.get(hostName).getFunction(funName) != null).
|
||||||
|
executes((c) -> execute(c, hostName, funName)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
List<String> reversedArgs = new ArrayList<>(argNames);
|
||||||
|
Collections.reverse(reversedArgs);
|
||||||
|
RequiredArgumentBuilder<ServerCommandSource, ?> argChain = CommandArgument.argumentNode(reversedArgs.get(0)).executes(c -> execute(c, hostName, funName));
|
||||||
|
for (int i = 1; i < reversedArgs.size(); i++)
|
||||||
|
{
|
||||||
|
argChain = CommandArgument.argumentNode(reversedArgs.get(i)).then(argChain);
|
||||||
|
}
|
||||||
|
return command.then(literal(funName).
|
||||||
|
requires((player) -> modules.containsKey(hostName) && modules.get(hostName).getFunction(funName) != null).
|
||||||
|
then(argChain)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public boolean removeScriptHost(ServerCommandSource source, String name, boolean notifySource)
|
public boolean removeScriptHost(ServerCommandSource source, String name, boolean notifySource)
|
||||||
{
|
{
|
||||||
name = name.toLowerCase(Locale.ROOT);
|
name = name.toLowerCase(Locale.ROOT);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import com.google.common.collect.Lists;
|
|||||||
import com.mojang.brigadier.arguments.ArgumentType;
|
import com.mojang.brigadier.arguments.ArgumentType;
|
||||||
import com.mojang.brigadier.arguments.DoubleArgumentType;
|
import com.mojang.brigadier.arguments.DoubleArgumentType;
|
||||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||||
|
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
||||||
import com.mojang.brigadier.context.CommandContext;
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
||||||
@@ -30,6 +31,9 @@ import java.util.concurrent.CompletableFuture;
|
|||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static net.minecraft.server.command.CommandManager.argument;
|
||||||
|
|
||||||
|
|
||||||
public abstract class CommandArgument
|
public abstract class CommandArgument
|
||||||
{
|
{
|
||||||
private static final List<? extends CommandArgument> baseTypes = Lists.newArrayList(
|
private static final List<? extends CommandArgument> baseTypes = Lists.newArrayList(
|
||||||
@@ -38,20 +42,47 @@ public abstract class CommandArgument
|
|||||||
|
|
||||||
public static final Map<String, CommandArgument> builtIns = baseTypes.stream().collect(Collectors.toMap(CommandArgument::getTypeSuffix, a -> a));
|
public static final Map<String, CommandArgument> builtIns = baseTypes.stream().collect(Collectors.toMap(CommandArgument::getTypeSuffix, a -> a));
|
||||||
|
|
||||||
|
private static CommandArgument getTypeForArgument(String argument)
|
||||||
|
{
|
||||||
|
String[] components = argument.split("_");
|
||||||
|
String suffix = components[components.length-1].toLowerCase(Locale.ROOT);
|
||||||
|
return builtIns.getOrDefault(suffix, builtIns.get("string"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RequiredArgumentBuilder<ServerCommandSource, ?> argumentNode(String param)
|
||||||
|
{
|
||||||
|
CommandArgument arg = getTypeForArgument(param);
|
||||||
|
return arg.needsMatching? argument(param, arg.getArgumentType()).suggests(arg::suggest) : argument(param, arg.getArgumentType());
|
||||||
|
}
|
||||||
|
|
||||||
private String suffix;
|
private String suffix;
|
||||||
private final Collection<String> examples;
|
private final Collection<String> examples;
|
||||||
|
protected boolean needsMatching = false;
|
||||||
|
|
||||||
protected CommandArgument(
|
protected CommandArgument(
|
||||||
String suffix,
|
String suffix,
|
||||||
Collection<String> examples)
|
Collection<String> examples,
|
||||||
|
boolean needsMatching)
|
||||||
{
|
{
|
||||||
this.suffix = suffix;
|
this.suffix = suffix;
|
||||||
this.examples = examples;
|
this.examples = examples;
|
||||||
|
this.needsMatching = needsMatching;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract ArgumentType<?> getArgument();
|
public static ArgumentType<?> getArgument(String param)
|
||||||
|
{
|
||||||
|
return getTypeForArgument(param).getArgumentType();
|
||||||
|
}
|
||||||
|
|
||||||
public abstract Value getValueFromContext(CommandContext<ServerCommandSource> context, String param) throws CommandSyntaxException;
|
protected abstract ArgumentType<?> getArgumentType();
|
||||||
|
|
||||||
|
|
||||||
|
public static Value getValue(CommandContext<ServerCommandSource> context, String param) throws CommandSyntaxException
|
||||||
|
{
|
||||||
|
return getTypeForArgument(param).getValueFromContext(context, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract Value getValueFromContext(CommandContext<ServerCommandSource> context, String param) throws CommandSyntaxException;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -81,8 +112,7 @@ public abstract class CommandArgument
|
|||||||
|
|
||||||
protected abstract void configure(Map<String, Value> config);
|
protected abstract void configure(Map<String, Value> config);
|
||||||
|
|
||||||
|
public CompletableFuture<Suggestions> suggest(
|
||||||
protected CompletableFuture<Suggestions> suggest(
|
|
||||||
CommandContext<ServerCommandSource> context,
|
CommandContext<ServerCommandSource> context,
|
||||||
SuggestionsBuilder suggestionsBuilder
|
SuggestionsBuilder suggestionsBuilder
|
||||||
)
|
)
|
||||||
@@ -99,7 +129,10 @@ public abstract class CommandArgument
|
|||||||
|
|
||||||
protected Collection<String> getOptions()
|
protected Collection<String> getOptions()
|
||||||
{
|
{
|
||||||
return Collections.emptyList();
|
//return Lists.newArrayList("");
|
||||||
|
// better than nothing I guess
|
||||||
|
// nothing is such a bad default.
|
||||||
|
return Collections.singletonList("... "+getTypeSuffix());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean optionMatchesPrefix(String prefix, String option)
|
protected boolean optionMatchesPrefix(String prefix, String option)
|
||||||
@@ -120,11 +153,11 @@ public abstract class CommandArgument
|
|||||||
boolean caseSensitive = false;
|
boolean caseSensitive = false;
|
||||||
private WordArgument()
|
private WordArgument()
|
||||||
{
|
{
|
||||||
super("string", StringArgumentType.StringType.SINGLE_WORD.getExamples());
|
super("string", StringArgumentType.StringType.SINGLE_WORD.getExamples(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ArgumentType<?> getArgument()
|
public ArgumentType<?> getArgumentType()
|
||||||
{
|
{
|
||||||
return StringArgumentType.word();
|
return StringArgumentType.word();
|
||||||
}
|
}
|
||||||
@@ -156,7 +189,7 @@ public abstract class CommandArgument
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Collection<String> getOptions() { return validOptions; }
|
protected Collection<String> getOptions() { return validOptions.isEmpty()?super.getOptions():validOptions; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Supplier<CommandArgument> builder() { return WordArgument::new; }
|
protected Supplier<CommandArgument> builder() { return WordArgument::new; }
|
||||||
@@ -168,11 +201,11 @@ public abstract class CommandArgument
|
|||||||
|
|
||||||
private PosArgument()
|
private PosArgument()
|
||||||
{
|
{
|
||||||
super("pos", BlockPosArgumentType.blockPos().getExamples());
|
super("pos", BlockPosArgumentType.blockPos().getExamples(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ArgumentType<?> getArgument()
|
public ArgumentType<?> getArgumentType()
|
||||||
{
|
{
|
||||||
return BlockPosArgumentType.blockPos();
|
return BlockPosArgumentType.blockPos();
|
||||||
}
|
}
|
||||||
@@ -205,11 +238,11 @@ public abstract class CommandArgument
|
|||||||
private Double max = null;
|
private Double max = null;
|
||||||
private FloatArgument()
|
private FloatArgument()
|
||||||
{
|
{
|
||||||
super("float", DoubleArgumentType.doubleArg().getExamples());
|
super("float", DoubleArgumentType.doubleArg().getExamples(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ArgumentType<?> getArgument()
|
public ArgumentType<?> getArgumentType()
|
||||||
{
|
{
|
||||||
if (min != null)
|
if (min != null)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in new issue
Block a user