Added a bunch of new command arg types

This commit is contained in:
Felix Cravic 2020-07-10 22:50:05 +02:00
parent 23826a0842
commit e4ad66fcde
15 changed files with 384 additions and 22 deletions

View File

@ -4,9 +4,16 @@ import net.minestom.server.command.builder.Command;
import net.minestom.server.command.builder.CommandDispatcher;
import net.minestom.server.command.builder.CommandSyntax;
import net.minestom.server.command.builder.arguments.*;
import net.minestom.server.command.builder.arguments.minecraft.ArgumentColor;
import net.minestom.server.command.builder.arguments.minecraft.ArgumentTime;
import net.minestom.server.command.builder.arguments.minecraft.registry.ArgumentEnchantment;
import net.minestom.server.command.builder.arguments.minecraft.registry.ArgumentEntityType;
import net.minestom.server.command.builder.arguments.minecraft.registry.ArgumentParticle;
import net.minestom.server.command.builder.arguments.minecraft.registry.ArgumentPotion;
import net.minestom.server.command.builder.arguments.number.ArgumentDouble;
import net.minestom.server.command.builder.arguments.number.ArgumentFloat;
import net.minestom.server.command.builder.arguments.number.ArgumentInteger;
import net.minestom.server.command.builder.arguments.number.ArgumentNumber;
import net.minestom.server.command.builder.condition.CommandCondition;
import net.minestom.server.entity.Player;
import net.minestom.server.event.player.PlayerCommandEvent;
@ -15,6 +22,7 @@ import net.minestom.server.utils.ArrayUtils;
import net.minestom.server.utils.validate.Check;
import java.util.*;
import java.util.function.Consumer;
public class CommandManager {
@ -208,7 +216,7 @@ public class CommandManager {
}
}
final List<String> simpleCommands = new ArrayList<>();
for (CommandProcessor commandProcessor : commandProcessorMap.values()) {
// Do not show command if return false
@ -324,6 +332,13 @@ public class CommandManager {
private List<DeclareCommandsPacket.Node> toNodes(Argument argument, boolean executable) {
List<DeclareCommandsPacket.Node> nodes = new ArrayList<>();
/*DeclareCommandsPacket.Node testNode = simpleArgumentNode(nodes, argument, executable);
testNode.parser = "minecraft:entity_summon";
if (true) {
return nodes;
}*/
if (argument instanceof ArgumentBoolean) {
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable);
@ -335,9 +350,11 @@ public class CommandManager {
ArgumentDouble argumentDouble = (ArgumentDouble) argument;
argumentNode.parser = "brigadier:double";
argumentNode.properties = packetWriter -> {
packetWriter.writeByte((byte) 0b11);
packetWriter.writeDouble(argumentDouble.getMin());
packetWriter.writeDouble(argumentDouble.getMax());
packetWriter.writeByte(getNumberProperties(argumentDouble));
if (argumentDouble.hasMin())
packetWriter.writeDouble(argumentDouble.getMin());
if (argumentDouble.hasMax())
packetWriter.writeDouble(argumentDouble.getMax());
};
} else if (argument instanceof ArgumentFloat) {
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable);
@ -345,9 +362,11 @@ public class CommandManager {
ArgumentFloat argumentFloat = (ArgumentFloat) argument;
argumentNode.parser = "brigadier:float";
argumentNode.properties = packetWriter -> {
packetWriter.writeByte((byte) 0b11);
packetWriter.writeFloat(argumentFloat.getMin());
packetWriter.writeFloat(argumentFloat.getMax());
packetWriter.writeByte(getNumberProperties(argumentFloat));
if (argumentFloat.hasMin())
packetWriter.writeFloat(argumentFloat.getMin());
if (argumentFloat.hasMax())
packetWriter.writeFloat(argumentFloat.getMax());
};
} else if (argument instanceof ArgumentInteger) {
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable);
@ -355,36 +374,39 @@ public class CommandManager {
ArgumentInteger argumentInteger = (ArgumentInteger) argument;
argumentNode.parser = "brigadier:integer";
argumentNode.properties = packetWriter -> {
packetWriter.writeByte((byte) 0b11);
packetWriter.writeInt(argumentInteger.getMin());
packetWriter.writeInt(argumentInteger.getMax());
packetWriter.writeByte(getNumberProperties(argumentInteger));
if (argumentInteger.hasMin())
packetWriter.writeInt(argumentInteger.getMin());
if (argumentInteger.hasMax())
packetWriter.writeInt(argumentInteger.getMax());
};
} else if (argument instanceof ArgumentWord) {
ArgumentWord argumentWord = (ArgumentWord) argument;
// Add the single word properties + parser
final Consumer<DeclareCommandsPacket.Node> wordConsumer = node -> {
node.parser = "brigadier:string";
node.properties = packetWriter -> {
packetWriter.writeVarInt(0); // Single word
};
};
final boolean hasRestriction = argumentWord.hasRestrictions();
if (hasRestriction) {
// Create a node for each restrictions as literal
for (String restrictionWord : argumentWord.getRestrictions()) {
DeclareCommandsPacket.Node argumentNode = new DeclareCommandsPacket.Node();
nodes.add(argumentNode);
argumentNode.flags = getFlag(NodeType.LITERAL, executable, false, false);
argumentNode.name = restrictionWord;
argumentNode.parser = "brigadier:string";
argumentNode.properties = packetWriter -> {
packetWriter.writeVarInt(0); // Single word
};
wordConsumer.accept(argumentNode);
}
} else {
// Can be any word, add only one argument node
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable);
argumentNode.parser = "brigadier:string";
argumentNode.properties = packetWriter -> {
packetWriter.writeVarInt(0); // Single word
};
wordConsumer.accept(argumentNode);
}
} else if (argument instanceof ArgumentString) {
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable);
@ -400,11 +422,38 @@ public class CommandManager {
argumentNode.properties = packetWriter -> {
packetWriter.writeVarInt(2); // Greedy phrase
};
} else if (argument instanceof ArgumentColor) {
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable);
argumentNode.parser = "minecraft:color";
} else if (argument instanceof ArgumentTime) {
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable);
argumentNode.parser = "minecraft:time";
} else if (argument instanceof ArgumentEnchantment) {
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable);
argumentNode.parser = "minecraft:item_enchantment";
} else if (argument instanceof ArgumentParticle) {
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable);
argumentNode.parser = "minecraft:particle";
} else if (argument instanceof ArgumentPotion) {
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable);
argumentNode.parser = "minecraft:mob_effect";
} else if (argument instanceof ArgumentEntityType) {
DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable);
argumentNode.parser = "minecraft:entity_summon";
}
return nodes;
}
private byte getNumberProperties(ArgumentNumber argumentNumber) {
byte result = 0;
if (argumentNumber.hasMin())
result += 1;
if (argumentNumber.hasMax())
result += 2;
return result;
}
private DeclareCommandsPacket.Node simpleArgumentNode(List<DeclareCommandsPacket.Node> nodes,
Argument argument, boolean executable) {
DeclareCommandsPacket.Node argumentNode = new DeclareCommandsPacket.Node();

View File

@ -1,6 +1,12 @@
package net.minestom.server.command.builder;
import net.minestom.server.chat.ChatColor;
import net.minestom.server.command.builder.structure.Structure;
import net.minestom.server.entity.EntityType;
import net.minestom.server.item.Enchantment;
import net.minestom.server.particle.Particle;
import net.minestom.server.potion.PotionType;
import net.minestom.server.utils.time.UpdateOption;
import java.util.HashMap;
import java.util.Map;
@ -45,6 +51,30 @@ public class Arguments {
return (String[]) getObject(id);
}
public ChatColor getColor(String id) {
return (ChatColor) getObject(id);
}
public UpdateOption getTime(String id) {
return (UpdateOption) getObject(id);
}
public Enchantment getEnchantment(String id) {
return (Enchantment) getObject(id);
}
public Particle getParticle(String id) {
return (Particle) getObject(id);
}
public PotionType getPotion(String id) {
return (PotionType) getObject(id);
}
public EntityType getEntityType(String id) {
return (EntityType) getObject(id);
}
public Object getObject(String id) {
return args.getOrDefault(id, null);
}

View File

@ -23,6 +23,10 @@ public abstract class Argument<T> {
this(id, allowSpace, false);
}
public Argument(String id) {
this(id, false, false);
}
/**
* Used to provide the appropriate error concerning the args received
*

View File

@ -1,5 +1,11 @@
package net.minestom.server.command.builder.arguments;
import net.minestom.server.command.builder.arguments.minecraft.ArgumentColor;
import net.minestom.server.command.builder.arguments.minecraft.ArgumentTime;
import net.minestom.server.command.builder.arguments.minecraft.registry.ArgumentEnchantment;
import net.minestom.server.command.builder.arguments.minecraft.registry.ArgumentEntityType;
import net.minestom.server.command.builder.arguments.minecraft.registry.ArgumentParticle;
import net.minestom.server.command.builder.arguments.minecraft.registry.ArgumentPotion;
import net.minestom.server.command.builder.arguments.number.ArgumentDouble;
import net.minestom.server.command.builder.arguments.number.ArgumentFloat;
import net.minestom.server.command.builder.arguments.number.ArgumentInteger;
@ -43,4 +49,30 @@ public class ArgumentType {
return new ArgumentStringArray(id);
}
// Minecraft specific
public static ArgumentColor Color(String id) {
return new ArgumentColor(id);
}
public static ArgumentTime Time(String id) {
return new ArgumentTime(id);
}
public static ArgumentEnchantment Enchantment(String id) {
return new ArgumentEnchantment(id);
}
public static ArgumentParticle Particle(String id) {
return new ArgumentParticle(id);
}
public static ArgumentPotion Potion(String id) {
return new ArgumentPotion(id);
}
public static ArgumentEntityType EntityType(String id) {
return new ArgumentEntityType(id);
}
}

View File

@ -0,0 +1,29 @@
package net.minestom.server.command.builder.arguments.minecraft;
import net.minestom.server.chat.ChatColor;
import net.minestom.server.command.builder.arguments.Argument;
public class ArgumentColor extends Argument<ChatColor> {
public static final int UNDEFINED_COLOR = -2;
public ArgumentColor(String id) {
super(id);
}
@Override
public int getCorrectionResult(String value) {
ChatColor color = ChatColor.fromName(value);
return color == ChatColor.NO_COLOR ? UNDEFINED_COLOR : SUCCESS;
}
@Override
public ChatColor parse(String value) {
return ChatColor.fromName(value);
}
@Override
public int getConditionResult(ChatColor value) {
return SUCCESS;
}
}

View File

@ -0,0 +1,27 @@
package net.minestom.server.command.builder.arguments.minecraft;
import net.minestom.server.command.builder.arguments.Argument;
import net.minestom.server.entity.Entity;
// TODO
public class ArgumentEntity extends Argument<Entity> {
public ArgumentEntity(String id, boolean allowSpace) {
super(id, allowSpace);
}
@Override
public int getCorrectionResult(String value) {
return 0;
}
@Override
public Entity parse(String value) {
return null;
}
@Override
public int getConditionResult(Entity value) {
return 0;
}
}

View File

@ -0,0 +1,26 @@
package net.minestom.server.command.builder.arguments.minecraft;
import net.minestom.server.command.builder.arguments.Argument;
// FIXME: cannot make the minecraft:range identifier working
public class ArgumentRange extends Argument<Float> {
public ArgumentRange(String id, boolean allowSpace, boolean useRemaining) {
super(id, allowSpace, useRemaining);
}
@Override
public int getCorrectionResult(String value) {
return 0;
}
@Override
public Float parse(String value) {
return null;
}
@Override
public int getConditionResult(Float value) {
return 0;
}
}

View File

@ -0,0 +1,57 @@
package net.minestom.server.command.builder.arguments.minecraft;
import net.minestom.server.command.builder.arguments.Argument;
import net.minestom.server.utils.time.TimeUnit;
import net.minestom.server.utils.time.UpdateOption;
import java.util.Arrays;
import java.util.List;
public class ArgumentTime extends Argument<UpdateOption> {
public static final int INVALID_TIME_FORMAT = -2;
public static final int NO_NUMBER = -3;
private static final List<Character> suffixes = Arrays.asList('d', 's', 't');
public ArgumentTime(String id) {
super(id);
}
@Override
public int getCorrectionResult(String value) {
final char lastChar = value.charAt(value.length() - 1);
if (!suffixes.contains(lastChar))
return INVALID_TIME_FORMAT;
value = value.substring(0, value.length() - 1);
try {
// Check if value is a number
Integer.valueOf(value);
return SUCCESS;
} catch (NumberFormatException e) {
return NO_NUMBER;
}
}
@Override
public UpdateOption parse(String value) {
final char lastChar = value.charAt(value.length() - 1);
TimeUnit timeUnit = null;
if (lastChar == 'd') {
timeUnit = TimeUnit.DAY;
} else if (lastChar == 's') {
timeUnit = TimeUnit.SECOND;
} else if (lastChar == 't') {
timeUnit = TimeUnit.TICK;
}
value = value.substring(0, value.length() - 1);
final int time = Integer.valueOf(value);
return new UpdateOption(time, timeUnit);
}
@Override
public int getConditionResult(UpdateOption value) {
return SUCCESS;
}
}

View File

@ -0,0 +1,16 @@
package net.minestom.server.command.builder.arguments.minecraft.registry;
import net.minestom.server.item.Enchantment;
import net.minestom.server.registry.Registries;
public class ArgumentEnchantment extends ArgumentRegistry<Enchantment> {
public ArgumentEnchantment(String id) {
super(id);
}
@Override
public Enchantment getRegistry(String value) {
return Registries.getEnchantment(value);
}
}

View File

@ -0,0 +1,16 @@
package net.minestom.server.command.builder.arguments.minecraft.registry;
import net.minestom.server.entity.EntityType;
import net.minestom.server.registry.Registries;
public class ArgumentEntityType extends ArgumentRegistry<EntityType> {
public ArgumentEntityType(String id) {
super(id);
}
@Override
public EntityType getRegistry(String value) {
return Registries.getEntityType(value);
}
}

View File

@ -0,0 +1,16 @@
package net.minestom.server.command.builder.arguments.minecraft.registry;
import net.minestom.server.particle.Particle;
import net.minestom.server.registry.Registries;
public class ArgumentParticle extends ArgumentRegistry<Particle> {
public ArgumentParticle(String id) {
super(id);
}
@Override
public Particle getRegistry(String value) {
return Registries.getParticle(value);
}
}

View File

@ -0,0 +1,16 @@
package net.minestom.server.command.builder.arguments.minecraft.registry;
import net.minestom.server.potion.PotionType;
import net.minestom.server.registry.Registries;
public class ArgumentPotion extends ArgumentRegistry<PotionType> {
public ArgumentPotion(String id) {
super(id);
}
@Override
public PotionType getRegistry(String value) {
return Registries.getPotionType(value);
}
}

View File

@ -0,0 +1,29 @@
package net.minestom.server.command.builder.arguments.minecraft.registry;
import net.minestom.server.command.builder.arguments.Argument;
public abstract class ArgumentRegistry<T> extends Argument<T> {
public static final int INVALID_NAME = -2;
public ArgumentRegistry(String id) {
super(id);
}
public abstract T getRegistry(String value);
@Override
public int getCorrectionResult(String value) {
return getRegistry(value) == null ? INVALID_NAME : SUCCESS;
}
@Override
public T parse(String value) {
return getRegistry(value);
}
@Override
public int getConditionResult(T value) {
return SUCCESS;
}
}

View File

@ -10,6 +10,7 @@ public abstract class ArgumentNumber<T> extends Argument<T> {
public static final int NOT_NUMBER_ERROR = 1;
public static final int RANGE_ERROR = 2;
protected boolean hasMin, hasMax;
protected T min, max;
public ArgumentNumber(String id) {
@ -18,24 +19,36 @@ public abstract class ArgumentNumber<T> extends Argument<T> {
public ArgumentNumber min(T value) {
this.min = value;
this.hasMin = true;
return this;
}
public ArgumentNumber max(T value) {
this.max = value;
this.hasMax = true;
return this;
}
public ArgumentNumber between(T min, T max) {
this.min = min;
this.max = max;
this.hasMin = true;
this.hasMax = true;
return this;
}
public boolean hasMin() {
return hasMin;
}
public T getMin() {
return min;
}
public boolean hasMax() {
return hasMax;
}
public T getMax() {
return max;
}

View File

@ -4,12 +4,14 @@ import net.minestom.server.MinecraftServer;
public enum TimeUnit {
TICK, HOUR, MINUTE, SECOND, MILLISECOND;
TICK, DAY, HOUR, MINUTE, SECOND, MILLISECOND;
public long toMilliseconds(long value) {
switch (this) {
case TICK:
return MinecraftServer.TICK_MS * value;
case DAY:
return value * 86_400_000;
case HOUR:
return value * 3_600_000;
case MINUTE: