Skip to content

Commit 7ea6a1b

Browse files
Add ExecutableBy.BLOCKS option
1 parent 773d78c commit 7ea6a1b

4 files changed

Lines changed: 54 additions & 49 deletions

File tree

src/main/java/ch/njol/util/coll/CollectionUtils.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,4 +478,29 @@ public static Double[] wrap(double[] primitive) {
478478
return wrapped;
479479
}
480480

481+
/**
482+
* Stringifies a collection as an "and" or "or" list.
483+
* @param collection The collection to stringify.
484+
* @param and Whether this is an "and" list or an "or" list.
485+
* @return Stringification of {@code collection}.
486+
* For example, {@code "x, y, and z"}.
487+
*/
488+
public static String toString(Collection<?> collection, boolean and) {
489+
StringBuilder builder = new StringBuilder();
490+
int i = 0;
491+
int end = collection.size() - 1;
492+
for (Object object : collection) {
493+
if (i > 0) {
494+
if (i == end) {
495+
builder.append(and ? " and " : " or ");
496+
} else {
497+
builder.append(", ");
498+
}
499+
}
500+
builder.append(object);
501+
i++;
502+
}
503+
return builder.toString();
504+
}
505+
481506
}

src/main/java/org/skriptlang/skript/bukkit/command/custom/CommandParsingData.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.util.Deque;
1010
import java.util.LinkedList;
1111
import java.util.List;
12+
import java.util.Set;
1213
import java.util.function.Function;
1314

1415
/**
@@ -17,11 +18,11 @@
1718
public final class CommandParsingData extends Data {
1819

1920
/**
20-
* @param executableBy Describes what kind of {@link CommandSender} can execute the command.
21+
* @param executableBy Set describing what kinds of {@link CommandSender} can execute the command.
2122
* @param cooldownManager Handles cooldown management for cooldown command entries.
2223
*/
2324
public record ExecutorData(
24-
@Nullable ExecutableBy executableBy,
25+
@Nullable Set<ExecutableBy> executableBy,
2526
@Nullable CooldownManager cooldownManager
2627
) { }
2728

src/main/java/org/skriptlang/skript/bukkit/command/custom/ExecutableBy.java

Lines changed: 4 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.skriptlang.skript.bukkit.command.custom;
22

3+
import org.bukkit.command.BlockCommandSender;
34
import org.bukkit.command.CommandSender;
45
import org.bukkit.command.ConsoleCommandSender;
56
import org.bukkit.command.RemoteConsoleCommandSender;
@@ -23,14 +24,9 @@ public enum ExecutableBy {
2324
CONSOLE(sender -> sender instanceof ConsoleCommandSender || sender instanceof RemoteConsoleCommandSender),
2425

2526
/**
26-
* This command is executable by any {@link CommandSender}.
27+
* This command is only executable by blocks (e.g, command blocks).
2728
*/
28-
ALL(ignored -> true),
29-
30-
/**
31-
* This command is not executable.
32-
*/
33-
NONE(ignored -> false);
29+
BLOCKS(sender -> sender instanceof BlockCommandSender);
3430

3531
private final Predicate<CommandSender> predicate;
3632

@@ -45,37 +41,12 @@ public Predicate<CommandSender> predicate() {
4541
return predicate;
4642
}
4743

48-
/**
49-
* Combines (ORs) this ExecutableBy with another.
50-
* For example, {@link #PLAYERS}.with({@link #CONSOLE}) is {@link #ALL}.
51-
*
52-
* @param other Other to OR with.
53-
* @return The resulting ExecutableBy.
54-
*/
55-
public ExecutableBy with(ExecutableBy other) {
56-
if (this == NONE) {
57-
return other;
58-
} else if (other == NONE) {
59-
return this;
60-
}
61-
return this == other ? this : ALL;
62-
}
63-
64-
/**
65-
* @param other Subset ExecutableBy to consider.
66-
* @return Whether this ExecutableBy is the same as or covers a superset of {@code other}.
67-
*/
68-
public boolean includes(ExecutableBy other) {
69-
return this == ALL || this == other;
70-
}
71-
7244
@Override
7345
public String toString() {
7446
return switch (this) {
7547
case PLAYERS -> "players";
7648
case CONSOLE -> "the console";
77-
case ALL -> "the console and players";
78-
case NONE -> "none";
49+
case BLOCKS -> "blocks";
7950
};
8051
}
8152

src/main/java/org/skriptlang/skript/bukkit/command/elements/structures/util/SubCommandEntryData.java

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import ch.njol.skript.util.StringMode;
1212
import ch.njol.skript.util.Timespan;
1313
import ch.njol.skript.variables.HintManager;
14+
import ch.njol.util.coll.CollectionUtils;
1415
import com.mojang.brigadier.arguments.ArgumentType;
1516
import com.mojang.brigadier.arguments.StringArgumentType;
1617
import com.mojang.brigadier.builder.ArgumentBuilder;
@@ -46,7 +47,9 @@
4647
import java.util.ArrayList;
4748
import java.util.Arrays;
4849
import java.util.Collection;
50+
import java.util.EnumSet;
4951
import java.util.List;
52+
import java.util.Set;
5053
import java.util.function.Predicate;
5154
import java.util.regex.Matcher;
5255
import java.util.regex.Pattern;
@@ -88,20 +91,22 @@ protected List<String> getValue(String value) {
8891
.addEntryData(new VariableStringEntryData("usage", null, true))
8992
.addEntry("prefix", null, true)
9093
.addEntry("permission", null, true)
91-
.addEntryData(new KeyValueEntryData<ExecutableBy>("executable by", null, true) {
92-
private final Pattern pattern = Pattern.compile("\\s*,\\s*|\\s+(and|or)\\s+");
94+
.addEntryData(new KeyValueEntryData<Set<ExecutableBy>>("executable by", null, true) {
95+
private final Pattern pattern = Pattern.compile("\\s*,(?:\\s+(?:and|or)\\s+)?\\s*|\\s+(?:and|or)\\s+");
9396

9497
@Override
95-
protected ExecutableBy getValue(String value) {
96-
ExecutableBy executableBy = ExecutableBy.NONE;
98+
protected Set<ExecutableBy> getValue(String value) {
99+
EnumSet<ExecutableBy> executableBy = EnumSet.noneOf(ExecutableBy.class);
97100
for (String type : pattern.split(value)) {
98101
if (type.equalsIgnoreCase("console") || type.equalsIgnoreCase("the console")) {
99-
executableBy = executableBy.with(ExecutableBy.CONSOLE);
102+
executableBy.add(ExecutableBy.CONSOLE);
100103
} else if (type.equalsIgnoreCase("players") || type.equalsIgnoreCase("player")) {
101-
executableBy = executableBy.with(ExecutableBy.PLAYERS);
104+
executableBy.add(ExecutableBy.PLAYERS);
105+
} else if (type.equalsIgnoreCase("blocks") || type.equalsIgnoreCase("block")) {
106+
executableBy.add(ExecutableBy.BLOCKS);
102107
} else {
103108
Skript.error("Invalid command sender type: " + type);
104-
return ExecutableBy.NONE;
109+
return Set.of();
105110
}
106111
}
107112
return executableBy;
@@ -228,18 +233,21 @@ public SubCommandEntryData(String key, boolean optional, boolean multiple) {
228233
}
229234

230235
// executable by requirement
231-
ExecutableBy executableBy = entryContainer.getOptional("executable by", ExecutableBy.class, false);
236+
Set<ExecutableBy> executableBy = entryContainer.getOptional("executable by", Set.class, false);
232237
if (executableBy != null) {
233-
if (executableBy == ExecutableBy.NONE) { // parsing failed
238+
if (executableBy.isEmpty()) { // parsing failed
234239
return null;
235240
}
236-
ExecutableBy parent = parsingData.getExecutorData(ExecutorData::executableBy);
237-
if (parent != null && !parent.includes(executableBy)) {
238-
Skript.error("It is not possible to restrict execution to " + executableBy +
239-
" as the parent command is only executable by " + parent + ".");
241+
Set<ExecutableBy> parent = parsingData.getExecutorData(ExecutorData::executableBy);
242+
if (parent != null && !parent.containsAll(executableBy)) {
243+
Skript.error("It is not possible to restrict execution to " + CollectionUtils.toString(executableBy, true) +
244+
" as the parent command is only executable by " + CollectionUtils.toString(parent, true) + ".");
240245
return null;
241246
}
242-
requires = requires.and(executableBy.predicate());
247+
requires = requires.and(executableBy.stream()
248+
.map(ExecutableBy::predicate)
249+
.reduce(Predicate::or)
250+
.orElseThrow());
243251
}
244252

245253
// prepare final requirements predicate

0 commit comments

Comments
 (0)