diff --git a/src/main/java/carpet/script/CarpetScriptHost.java b/src/main/java/carpet/script/CarpetScriptHost.java index d0b3fec9..ff52e50d 100644 --- a/src/main/java/carpet/script/CarpetScriptHost.java +++ b/src/main/java/carpet/script/CarpetScriptHost.java @@ -35,6 +35,7 @@ import org.apache.commons.lang3.tuple.Pair; import java.math.BigInteger; import java.util.ArrayList; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -226,23 +227,58 @@ public class CarpetScriptHost extends ScriptHost return true; } + static class ListComparator> implements Comparator,?>> + { + @Override + public int compare(Pair,?> p1, Pair,?> p2) { + List o1 = p1.getKey(); + List o2 = p2.getKey(); + for (int i = 0; i < Math.min(o1.size(), o2.size()); i++) { + int c = o1.get(i).compareTo(o2.get(i)); + if (c != 0) { + return c; + } + } + return Integer.compare(o1.size(), o2.size()); + } + } + public LiteralArgumentBuilder readCommands() throws CommandSyntaxException { Value commands = appConfig.get(StringValue.of("commands")); + if (commands == null) return null; if (!(commands instanceof MapValue)) throw CommandArgument.error("'commands' element in config should be a map"); List,FunctionArgument>> commandEntries = new ArrayList<>(); + for (Map.Entry commandsData : ((MapValue)commands).getMap().entrySet().stream().sorted(Map.Entry.comparingByKey()).collect(Collectors.toList())) { List elements = CommandToken.parseSpec(commandsData.getKey().getString(), this); FunctionArgument funSpec = FunctionArgument.fromCommandSpec(this, commandsData.getValue()); commandEntries.add(Pair.of(elements, funSpec)); } - // validate - // ... - // - + commandEntries.sort(new ListComparator<>()); + if (!appConfig.getOrDefault(StringValue.of("allow_command_conflicts"), Value.FALSE).getBoolean()) + { + for (int i = 0; i < commandEntries.size()-1; i++) + { + List first = commandEntries.get(i).getKey(); + List other = commandEntries.get(i+1).getKey(); + int checkSize = Math.min(first.size(), other.size()); + for (int t = 0; t < checkSize; t++) + { + CommandToken tik = first.get(t); + CommandToken tok = other.get(t); + if (tik.isArgument && tok.isArgument && !tik.surface.equals(tok.surface)) + throw CommandArgument.error("Conflicting commands: \n"+ + " - [" +first.stream().map(tt -> tt.surface).collect(Collectors.joining(" ")) + "] at "+tik.surface+"\n"+ + " - [" +other.stream().map(tt -> tt.surface).collect(Collectors.joining(" ")) + "] at "+tok.surface+"\n"); + if (!tik.equals(tok)) + break; + } + } + } return this.getNewCommandTree(commandEntries); } diff --git a/src/main/java/carpet/script/CarpetScriptServer.java b/src/main/java/carpet/script/CarpetScriptServer.java index 61458ab1..58351dd9 100644 --- a/src/main/java/carpet/script/CarpetScriptServer.java +++ b/src/main/java/carpet/script/CarpetScriptServer.java @@ -303,7 +303,7 @@ public class CarpetScriptServer for (String function : host.globaFunctionNames(host.main, s -> !s.startsWith("_")).sorted().collect(Collectors.toList())) { - if (host.appConfig.containsKey(StringValue.of("legacy_command_type_support"))) // temporary stuff for testing + if (host.appConfig.getOrDefault(StringValue.of("legacy_command_type_support"), Value.FALSE).getBoolean()) { try { diff --git a/src/main/java/carpet/script/command/CommandToken.java b/src/main/java/carpet/script/command/CommandToken.java index cc3606ae..b76a605b 100644 --- a/src/main/java/carpet/script/command/CommandToken.java +++ b/src/main/java/carpet/script/command/CommandToken.java @@ -10,17 +10,20 @@ import net.minecraft.server.command.ServerCommandSource; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Objects; import static net.minecraft.server.command.CommandManager.literal; -public class CommandToken +public class CommandToken implements Comparable { public String surface; public boolean isArgument; + public CommandArgument type; private CommandToken(String surface, CommandArgument type ) { this.surface = surface; + this.type = type; isArgument = type != null; } @@ -65,4 +68,28 @@ public class CommandToken return literal(surface); } + + @Override + public boolean equals(Object o) + { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + CommandToken that = (CommandToken) o; + return surface.equals(that.surface) && + Objects.equals(type, that.type); + } + + @Override + public int hashCode() + { + return Objects.hash(surface, type); + } + + @Override + public int compareTo(CommandToken o) + { + if (isArgument && !o.isArgument) return 1; + if (!isArgument && o.isArgument) return -1; + return surface.compareTo(o.surface); + } }