From 93bd039938e5f36b61bf544ce47c3d6785cb7767 Mon Sep 17 00:00:00 2001 From: themode Date: Thu, 4 Mar 2021 13:54:46 +0100 Subject: [PATCH] Fix EntityFinder performance when searching for a constant name or uuid --- .../arguments/minecraft/ArgumentEntity.java | 8 +-- .../server/utils/entity/EntityFinder.java | 52 ++++++++++++++----- 2 files changed, 42 insertions(+), 18 deletions(-) diff --git a/src/main/java/net/minestom/server/command/builder/arguments/minecraft/ArgumentEntity.java b/src/main/java/net/minestom/server/command/builder/arguments/minecraft/ArgumentEntity.java index 9874a3d17..394adaad2 100644 --- a/src/main/java/net/minestom/server/command/builder/arguments/minecraft/ArgumentEntity.java +++ b/src/main/java/net/minestom/server/command/builder/arguments/minecraft/ArgumentEntity.java @@ -99,8 +99,8 @@ public class ArgumentEntity extends Argument { try { final UUID uuid = UUID.fromString(input); return new EntityFinder() - .setTargetSelector(EntityFinder.TargetSelector.ALL_ENTITIES) - .setUuid(uuid); + .setTargetSelector(EntityFinder.TargetSelector.MINESTOM_UUID) + .setConstantUuid(uuid); } catch (IllegalArgumentException ignored) { } @@ -108,8 +108,8 @@ public class ArgumentEntity extends Argument { final Player player = MinecraftServer.getConnectionManager().getPlayer(input); if (player != null) { return new EntityFinder() - .setTargetSelector(EntityFinder.TargetSelector.ALL_PLAYERS) - .setName(input); + .setTargetSelector(EntityFinder.TargetSelector.MINESTOM_USERNAME) + .setConstantName(input); } } diff --git a/src/main/java/net/minestom/server/utils/entity/EntityFinder.java b/src/main/java/net/minestom/server/utils/entity/EntityFinder.java index e753daa78..e4867478f 100644 --- a/src/main/java/net/minestom/server/utils/entity/EntityFinder.java +++ b/src/main/java/net/minestom/server/utils/entity/EntityFinder.java @@ -12,6 +12,7 @@ import net.minestom.server.instance.Instance; import net.minestom.server.utils.MathUtils; import net.minestom.server.utils.Position; import net.minestom.server.utils.math.IntRange; +import net.minestom.server.utils.validate.Check; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -39,8 +40,11 @@ public class EntityFinder { // By traits private Integer limit; private final ToggleableMap entityTypes = new ToggleableMap<>(); - private String name; - private UUID uuid; + private String constantName; + private UUID constantUuid; + private final ToggleableMap names = new ToggleableMap<>(); + private final ToggleableMap uuids = new ToggleableMap<>(); + // Players specific private final ToggleableMap gameModes = new ToggleableMap<>(); @@ -81,13 +85,23 @@ public class EntityFinder { return this; } - public EntityFinder setName(@NotNull String name) { - this.name = name; + public EntityFinder setConstantName(@NotNull String constantName) { + this.constantName = constantName; return this; } - public EntityFinder setUuid(@NotNull UUID uuid) { - this.uuid = uuid; + public EntityFinder setConstantUuid(@NotNull UUID constantUuid) { + this.constantUuid = constantUuid; + return this; + } + + public EntityFinder setName(@NotNull String name, @NotNull ToggleableType toggleableType) { + this.names.put(name, toggleableType.getValue()); + return this; + } + + public EntityFinder setUuid(@NotNull UUID uuid, @NotNull ToggleableType toggleableType) { + this.uuids.put(uuid, toggleableType.getValue()); return this; } @@ -113,6 +127,16 @@ public class EntityFinder { */ @NotNull public List find(@Nullable Instance instance, @Nullable Entity self) { + if (targetSelector == TargetSelector.MINESTOM_USERNAME) { + Check.notNull(constantName, "The player name should not be null when searching for it"); + final Player player = MinecraftServer.getConnectionManager().getPlayer(constantName); + return player != null ? Collections.singletonList(player) : Collections.emptyList(); + } else if (targetSelector == TargetSelector.MINESTOM_UUID) { + Check.notNull(constantUuid, "The UUID should not be null when searching for it"); + final Entity entity = Entity.getEntity(constantUuid); + return entity != null ? Collections.singletonList(entity) : Collections.emptyList(); + } + List result = findTarget(instance, targetSelector, startPosition, self); // Fast exit if there is nothing to process @@ -182,19 +206,19 @@ public class EntityFinder { } // Name - if (name != null) { + if (!names.isEmpty()) { result = result.stream().filter(entity -> { if (!(entity instanceof Player)) return false; - return ((Player) entity).getUsername().equals(name); + return filterToggleableMap(entity, ((Player) entity).getUsername(), names); }).collect(Collectors.toList()); } // UUID - if (uuid != null) { - result = result.stream() - .filter(entity -> entity.getUuid().equals(uuid)) - .collect(Collectors.toList()); + if (!uuids.isEmpty()) { + result = result.stream().filter(entity -> { + return filterToggleableMap(entity, entity.getUuid(), uuids); + }).collect(Collectors.toList()); } @@ -288,7 +312,7 @@ public class EntityFinder { } public enum TargetSelector { - NEAREST_PLAYER, RANDOM_PLAYER, ALL_PLAYERS, ALL_ENTITIES, SELF + NEAREST_PLAYER, RANDOM_PLAYER, ALL_PLAYERS, ALL_ENTITIES, SELF, MINESTOM_USERNAME, MINESTOM_UUID } public enum EntitySort { @@ -344,7 +368,7 @@ public class EntityFinder { } else if (targetSelector == TargetSelector.SELF) { return Collections.singletonList(self); } - throw new IllegalStateException("Weird thing happened"); + throw new IllegalStateException("Weird thing happened: " + targetSelector); } private static boolean filterToggleableMap(@NotNull Entity entity, @NotNull T value, @NotNull ToggleableMap map) {