Skip to content

Commit

Permalink
Added distance and type options
Browse files Browse the repository at this point in the history
  • Loading branch information
Pedro270707 committed Sep 24, 2023
1 parent 24ed700 commit 697050e
Show file tree
Hide file tree
Showing 6 changed files with 357 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ public static boolean isIgnorableKey(int key) {
return IGNORABLE_KEYS.contains(key);
}

public static CompletableFuture<Suggestions> suggest(String string, SuggestionsBuilder suggestionsBuilder) {
String stringRemaining = suggestionsBuilder.getRemaining().toLowerCase(Locale.ROOT);
if (matchesSubStr(stringRemaining, string.toLowerCase(Locale.ROOT))) suggestionsBuilder.suggest(string);
return suggestionsBuilder.buildFuture();
}

public static CompletableFuture<Suggestions> suggest(Iterable<String> iterable, SuggestionsBuilder suggestionsBuilder) {
String string = suggestionsBuilder.getRemaining().toLowerCase(Locale.ROOT);
for (String string2 : iterable) {
Expand All @@ -96,7 +102,7 @@ public static boolean matchesSubStr(String string, String string2) {
public static Optional<String> getStringToSuggest(String checkedString, String input) {
if (checkedString.startsWith(input)) {
return Optional.of(checkedString);
} else if (checkedString.substring(checkedString.indexOf('.') + 1).startsWith(input)) {
} else if (checkedString.contains(".") && checkedString.substring(checkedString.indexOf('.') + 1).startsWith(input)) {
return Optional.of(checkedString.substring(checkedString.indexOf('.') + 1));
}
return Optional.empty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,66 +17,69 @@ public class EntitySelector {
private final boolean includesEntities;
private final BiConsumer<Entity, List<? extends Entity>> order;
private final @Nullable Class<? extends Entity> limitToType;
private final boolean typeInverse;
private final boolean currentEntity;
private final Predicate<Entity> predicate;
private final @Nullable String entityId;
private final @Nullable String playerName;
private final MinMaxBounds.Doubles distance;

public EntitySelector(int maxResults, boolean includesEntities, BiConsumer<Entity, List<? extends Entity>> order, @Nullable Class<? extends Entity> limitToType, boolean currentEntity, Predicate<Entity> predicate, @Nullable String entityId, @Nullable String playerName) {
public EntitySelector(int maxResults, boolean includesEntities, BiConsumer<Entity, List<? extends Entity>> order, @Nullable Class<? extends Entity> limitToType, boolean typeInverse, boolean currentEntity, Predicate<Entity> predicate, @Nullable String entityId, @Nullable String playerName, MinMaxBounds.Doubles distance) {
this.maxResults = maxResults;
this.includesEntities = includesEntities;
this.order = order;
this.limitToType = limitToType;
this.typeInverse = typeInverse;
this.currentEntity = currentEntity;
this.predicate = predicate;
this.entityId = entityId;
this.playerName = playerName;
this.distance = distance;
}

public List<? extends Entity> get(CommanderCommandSource commandSource) throws CommandSyntaxException {
public List<? extends Entity> get(CommanderCommandSource source) throws CommandSyntaxException {
// Entity ID/player
if (this.entityId != null) {
List<Entity> entities = new ArrayList<>();
for (Entity entity : commandSource.getWorld().loadedEntityList) {
for (Entity entity : source.getWorld().loadedEntityList) {
if ((Commander.ENTITY_PREFIX + entity.hashCode()).equals(this.entityId)) {
entities.add(entity);
}
}
return entities.subList(0, Math.min(entities.size(), this.maxResults));
} else if (this.playerName != null) {
List<EntityPlayer> players = new ArrayList<>();
for (EntityPlayer player : commandSource.getWorld().players) {
for (EntityPlayer player : source.getWorld().players) {
if (player.username.equals(this.playerName) || player.nickname.equals(this.playerName)) {
players.add(player);
}
}
return players.subList(0, Math.min(players.size(), this.maxResults));
}

// Player only?
// Player only
List<? extends Entity> entities;
if (this.includesEntities) {
entities = commandSource.getWorld().loadedEntityList;
entities = source.getWorld().loadedEntityList;
} else {
entities = commandSource.getWorld().players;
entities = source.getWorld().players;
}

// Limit to entity type
if (limitToType != null) {
List<? extends Entity> temp = new ArrayList<>(entities);
for (Entity entity : entities) {
if (!limitToType.isInstance(entity)) {
temp.remove(entity);
}
List<? extends Entity> temp = new ArrayList<>(entities);
for (Entity entity : entities) {
if ((limitToType != null && limitToType.isInstance(entity) == this.typeInverse)
|| !predicate.test(entity)
|| !this.distanceContains(source, entity)) {
temp.remove(entity);
}
entities = temp;
}
entities = temp;

// Sorting order
this.order.accept(commandSource.getSender(), entities);
this.order.accept(source.getSender(), entities);

List<Entity> listAfterPredicate = new ArrayList<>();
// Predicate
List<Entity> listAfterPredicate = new ArrayList<>();
for (Entity entity : entities) {
if (!predicate.test(entity)) continue;
listAfterPredicate.add(entity);
Expand All @@ -88,6 +91,11 @@ public List<? extends Entity> get(CommanderCommandSource commandSource) throws C
return listAfterPredicate;
}

private boolean distanceContains(CommanderCommandSource source, Entity entity) {
if (this.distance.isAny()) return true;
return source.getSender() != null && this.distance.contains(source.getSender().distanceTo(entity));
}

public int getMaxResults() {
return this.maxResults;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
package net.pedroricardo.commander.content.helpers;

import com.mojang.brigadier.Message;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import net.minecraft.core.entity.Entity;
import net.minecraft.core.entity.EntityDispatcher;
import net.minecraft.core.entity.player.EntityPlayer;
import net.minecraft.core.lang.I18n;
import net.minecraft.core.lang.text.Text;
import net.minecraft.core.lang.text.TextTranslatable;
import net.minecraft.core.player.gamemode.Gamemode;
import net.pedroricardo.commander.Commander;
import net.pedroricardo.commander.CommanderHelper;

import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Predicate;

public class EntitySelectorOptions {
private static final DynamicCommandExceptionType INAPPLICABLE_OPTION = new DynamicCommandExceptionType(value -> (() -> I18n.getInstance().translateKeyAndFormat("argument_types.commander.entity.selector.options.inapplicable", value)));
private static final DynamicCommandExceptionType UNKNOWN_OPTION = new DynamicCommandExceptionType(value -> (() -> I18n.getInstance().translateKeyAndFormat("argument_types.commander.entity.selector.options.unknown", value)));
private static final DynamicCommandExceptionType UNKNOWN_GAME_MODE = new DynamicCommandExceptionType(value -> (() -> I18n.getInstance().translateKeyAndFormat("argument_types.commander.entity.selector.options.gamemode.invalid", value)));
private static final DynamicCommandExceptionType UNKNOWN_SORT = new DynamicCommandExceptionType(value -> (() -> I18n.getInstance().translateKeyAndFormat("argument_types.commander.entity.selector.options.sort.invalid", value)));
private static final DynamicCommandExceptionType UNKNOWN_ENTITY_TYPE = new DynamicCommandExceptionType(value -> (() -> I18n.getInstance().translateKeyAndFormat("argument_types.commander.entity.selector.options.type.invalid", value)));
private static final SimpleCommandExceptionType NEGATIVE_DISTANCE = new SimpleCommandExceptionType(() -> I18n.getInstance().translateKey("argument_types.commander.entity.selector.options.distance.invalid"));
private static final SimpleCommandExceptionType LIMIT_TOO_SMALL = new SimpleCommandExceptionType(() -> I18n.getInstance().translateKey("argument_types.commander.entity.selector.options.limit.invalid"));

private final StringReader reader;
private final String key;
Expand All @@ -36,6 +43,87 @@ public static void register(String key, Modifier modifier, Predicate<EntitySelec
}

static {
register("distance", (parser) -> {
int cursor = parser.getReader().getCursor();
MinMaxBounds.Doubles bounds = MinMaxBounds.Doubles.fromReader(parser.getReader());
if ((bounds.getMin() != null && bounds.getMin() < 0) || (bounds.getMax() != null && bounds.getMax() < 0)) {
parser.getReader().setCursor(cursor);
throw NEGATIVE_DISTANCE.createWithContext(parser.getReader());
}
parser.setDistance(bounds);
}, parser -> parser.getDistance().isAny(), new TextTranslatable("argument_types.commander.entity.selector.options.distance.description"));
register("type", (parser) -> {
int cursor = parser.getReader().getCursor();
boolean invert = parser.shouldInvertValue();

parser.setSuggestions((builder, consumer) -> {
String string = builder.getRemaining().toLowerCase(Locale.ROOT);
if (!string.isEmpty()) {
if (string.charAt(0) == '!') {
string = string.substring(1);
}
}
CommanderHelper.suggest("!Player", builder);
CommanderHelper.suggest("Player", builder);
for (String key : EntityDispatcher.stringToClassMapping.keySet()) {
if (!key.toLowerCase(Locale.ROOT).startsWith(string)) continue;
CommanderHelper.suggest("!" + key, builder);
if (invert) continue;
CommanderHelper.suggest(key, builder);
}
return builder.buildFuture();
});

if (invert) {
parser.setTypeInverse(true);
}
String type = parser.getReader().readUnquotedString();
if (type.equals("Player")) {
parser.setLimitToType(EntityPlayer.class);
} else {
if (EntityDispatcher.stringToClassMapping.containsKey(type)) {
parser.setLimitToType(EntityDispatcher.stringToClassMapping.get(type));
} else {
parser.getReader().setCursor(cursor);
throw UNKNOWN_ENTITY_TYPE.createWithContext(parser.getReader(), type);
}
}
}, parser -> !parser.hasType(), new TextTranslatable("argument_types.commander.entity.selector.options.type.description"));
register("limit", (parser) -> {
int cursor = parser.getReader().getCursor();
int limit = parser.getReader().readInt();
if (limit < 1) {
parser.getReader().setCursor(cursor);
throw LIMIT_TOO_SMALL.createWithContext(parser.getReader());
}
parser.setMaxResults(limit);
parser.setHasLimit(true);
}, parser -> !parser.hasLimit(), new TextTranslatable("argument_types.commander.entity.selector.options.limit.description"));
register("sort", (parser) -> {
int i = parser.getReader().getCursor();
String string = parser.getReader().readUnquotedString();
parser.setSuggestions((suggestionsBuilder, consumer) -> CommanderHelper.suggest(Arrays.asList("nearest", "furthest", "random", "arbitrary"), suggestionsBuilder));
BiConsumer<Entity, List<? extends Entity>> sort;
switch (string) {
case "nearest":
sort = EntitySelectorParser.ORDER_NEAREST;
break;
case "furthest":
sort = EntitySelectorParser.ORDER_FURTHEST;
break;
case "random":
sort = EntitySelectorParser.ORDER_RANDOM;
break;
case "arbitrary":
sort = EntitySelectorParser.ORDER_ARBITRARY;
break;
default:
parser.getReader().setCursor(i);
throw UNKNOWN_SORT.createWithContext(parser.getReader(), string);
}
parser.setOrder(sort);
parser.setSorted(true);
}, parser -> !parser.isSorted(), new TextTranslatable("argument_types.commander.entity.selector.options.sort.description"));
register("gamemode", (parser) -> {
parser.setSuggestions((builder, consumer) -> {
String string = builder.getRemaining().toLowerCase(Locale.ROOT);
Expand Down Expand Up @@ -75,6 +163,7 @@ public static void register(String key, Modifier modifier, Predicate<EntitySelec
throw UNKNOWN_GAME_MODE.createWithContext(parser.getReader(), value);
}

parser.setIncludesEntities(false);
parser.addPredicate((entity) -> {
if (!(entity instanceof EntityPlayer)) return false;
return CommanderHelper.matchesKeyString(((EntityPlayer) entity).gamemode.languageKey, value) != invert;
Expand Down
Loading

0 comments on commit 697050e

Please sign in to comment.