--- a/net/minecraft/commands/arguments/selector/EntitySelectorParser.java
+++ b/net/minecraft/commands/arguments/selector/EntitySelectorParser.java
@@ -30,6 +30,7 @@
 import net.minecraft.world.phys.Vec3;
 
 public class EntitySelectorParser {
+
     public static final char SYNTAX_SELECTOR_START = '@';
     private static final char SYNTAX_OPTIONS_START = '[';
     private static final char SYNTAX_OPTIONS_END = ']';
@@ -43,38 +44,38 @@
     private static final char SELECTOR_CURRENT_ENTITY = 's';
     private static final char SELECTOR_ALL_ENTITIES = 'e';
     public static final SimpleCommandExceptionType ERROR_INVALID_NAME_OR_UUID = new SimpleCommandExceptionType(Component.translatable("argument.entity.invalid"));
-    public static final DynamicCommandExceptionType ERROR_UNKNOWN_SELECTOR_TYPE = new DynamicCommandExceptionType((selectorType) -> {
-        return Component.translatable("argument.entity.selector.unknown", selectorType);
+    public static final DynamicCommandExceptionType ERROR_UNKNOWN_SELECTOR_TYPE = new DynamicCommandExceptionType((object) -> {
+        return Component.translatable("argument.entity.selector.unknown", object);
     });
     public static final SimpleCommandExceptionType ERROR_SELECTORS_NOT_ALLOWED = new SimpleCommandExceptionType(Component.translatable("argument.entity.selector.not_allowed"));
     public static final SimpleCommandExceptionType ERROR_MISSING_SELECTOR_TYPE = new SimpleCommandExceptionType(Component.translatable("argument.entity.selector.missing"));
     public static final SimpleCommandExceptionType ERROR_EXPECTED_END_OF_OPTIONS = new SimpleCommandExceptionType(Component.translatable("argument.entity.options.unterminated"));
-    public static final DynamicCommandExceptionType ERROR_EXPECTED_OPTION_VALUE = new DynamicCommandExceptionType((option) -> {
-        return Component.translatable("argument.entity.options.valueless", option);
+    public static final DynamicCommandExceptionType ERROR_EXPECTED_OPTION_VALUE = new DynamicCommandExceptionType((object) -> {
+        return Component.translatable("argument.entity.options.valueless", object);
     });
-    public static final BiConsumer<Vec3, List<? extends Entity>> ORDER_NEAREST = (pos, entities) -> {
-        entities.sort((entity1, entity2) -> {
-            return Doubles.compare(entity1.distanceToSqr(pos), entity2.distanceToSqr(pos));
+    public static final BiConsumer<Vec3, List<? extends Entity>> ORDER_NEAREST = (vec3d, list) -> {
+        list.sort((entity, entity1) -> {
+            return Doubles.compare(entity.distanceToSqr(vec3d), entity1.distanceToSqr(vec3d));
         });
     };
-    public static final BiConsumer<Vec3, List<? extends Entity>> ORDER_FURTHEST = (pos, entities) -> {
-        entities.sort((entity1, entity2) -> {
-            return Doubles.compare(entity2.distanceToSqr(pos), entity1.distanceToSqr(pos));
+    public static final BiConsumer<Vec3, List<? extends Entity>> ORDER_FURTHEST = (vec3d, list) -> {
+        list.sort((entity, entity1) -> {
+            return Doubles.compare(entity1.distanceToSqr(vec3d), entity.distanceToSqr(vec3d));
         });
     };
-    public static final BiConsumer<Vec3, List<? extends Entity>> ORDER_RANDOM = (pos, entities) -> {
-        Collections.shuffle(entities);
+    public static final BiConsumer<Vec3, List<? extends Entity>> ORDER_RANDOM = (vec3d, list) -> {
+        Collections.shuffle(list);
     };
-    public static final BiFunction<SuggestionsBuilder, Consumer<SuggestionsBuilder>, CompletableFuture<Suggestions>> SUGGEST_NOTHING = (builder, consumer) -> {
-        return builder.buildFuture();
+    public static final BiFunction<SuggestionsBuilder, Consumer<SuggestionsBuilder>, CompletableFuture<Suggestions>> SUGGEST_NOTHING = (suggestionsbuilder, consumer) -> {
+        return suggestionsbuilder.buildFuture();
     };
     private final StringReader reader;
     private final boolean allowSelectors;
     private int maxResults;
     private boolean includesEntities;
     private boolean worldLimited;
-    private MinMaxBounds.Doubles distance = MinMaxBounds.Doubles.ANY;
-    private MinMaxBounds.Ints level = MinMaxBounds.Ints.ANY;
+    private MinMaxBounds.Doubles distance;
+    private MinMaxBounds.Ints level;
     @Nullable
     private Double x;
     @Nullable
@@ -87,19 +88,17 @@
     private Double deltaY;
     @Nullable
     private Double deltaZ;
-    private WrappedMinMaxBounds rotX = WrappedMinMaxBounds.ANY;
-    private WrappedMinMaxBounds rotY = WrappedMinMaxBounds.ANY;
-    private Predicate<Entity> predicate = (entity) -> {
-        return true;
-    };
-    private BiConsumer<Vec3, List<? extends Entity>> order = EntitySelector.ORDER_ARBITRARY;
+    private WrappedMinMaxBounds rotX;
+    private WrappedMinMaxBounds rotY;
+    private Predicate<Entity> predicate;
+    private BiConsumer<Vec3, List<? extends Entity>> order;
     private boolean currentEntity;
     @Nullable
     private String playerName;
     private int startPosition;
     @Nullable
     private UUID entityUUID;
-    private BiFunction<SuggestionsBuilder, Consumer<SuggestionsBuilder>, CompletableFuture<Suggestions>> suggestions = SUGGEST_NOTHING;
+    private BiFunction<SuggestionsBuilder, Consumer<SuggestionsBuilder>, CompletableFuture<Suggestions>> suggestions;
     private boolean hasNameEquals;
     private boolean hasNameNotEquals;
     private boolean isLimited;
@@ -114,54 +113,74 @@
     private boolean hasScores;
     private boolean hasAdvancements;
     private boolean usesSelectors;
+    public boolean parsingEntityArgumentSuggestions; // Paper - track when parsing EntityArgument suggestions
 
     public EntitySelectorParser(StringReader reader) {
         this(reader, true);
     }
 
     public EntitySelectorParser(StringReader reader, boolean atAllowed) {
+        // Paper start
+        this(reader, atAllowed, false);
+    }
+    public EntitySelectorParser(StringReader reader, boolean atAllowed, boolean parsingEntityArgumentSuggestions) {
+        this.parsingEntityArgumentSuggestions = parsingEntityArgumentSuggestions;
+        // Paper end
+        this.distance = MinMaxBounds.Doubles.ANY;
+        this.level = MinMaxBounds.Ints.ANY;
+        this.rotX = WrappedMinMaxBounds.ANY;
+        this.rotY = WrappedMinMaxBounds.ANY;
+        this.predicate = (entity) -> {
+            return true;
+        };
+        this.order = EntitySelector.ORDER_ARBITRARY;
+        this.suggestions = EntitySelectorParser.SUGGEST_NOTHING;
         this.reader = reader;
         this.allowSelectors = atAllowed;
     }
 
     public EntitySelector getSelector() {
-        AABB aABB2;
+        AABB axisalignedbb;
+
         if (this.deltaX == null && this.deltaY == null && this.deltaZ == null) {
             if (this.distance.getMax() != null) {
-                double d = this.distance.getMax();
-                aABB2 = new AABB(-d, -d, -d, d + 1.0D, d + 1.0D, d + 1.0D);
+                double d0 = (Double) this.distance.getMax();
+
+                axisalignedbb = new AABB(-d0, -d0, -d0, d0 + 1.0D, d0 + 1.0D, d0 + 1.0D);
             } else {
-                aABB2 = null;
+                axisalignedbb = null;
             }
         } else {
-            aABB2 = this.createAabb(this.deltaX == null ? 0.0D : this.deltaX, this.deltaY == null ? 0.0D : this.deltaY, this.deltaZ == null ? 0.0D : this.deltaZ);
+            axisalignedbb = this.createAabb(this.deltaX == null ? 0.0D : this.deltaX, this.deltaY == null ? 0.0D : this.deltaY, this.deltaZ == null ? 0.0D : this.deltaZ);
         }
 
-        Function<Vec3, Vec3> function;
+        Function<Vec3, Vec3> function; // CraftBukkit - decompile error
+
         if (this.x == null && this.y == null && this.z == null) {
-            function = (pos) -> {
-                return pos;
+            function = (vec3d) -> {
+                return vec3d;
             };
         } else {
-            function = (pos) -> {
-                return new Vec3(this.x == null ? pos.x : this.x, this.y == null ? pos.y : this.y, this.z == null ? pos.z : this.z);
+            function = (vec3d) -> {
+                return new Vec3(this.x == null ? vec3d.x : this.x, this.y == null ? vec3d.y : this.y, this.z == null ? vec3d.z : this.z);
             };
         }
 
-        return new EntitySelector(this.maxResults, this.includesEntities, this.worldLimited, this.predicate, this.distance, function, aABB2, this.order, this.currentEntity, this.playerName, this.entityUUID, this.type, this.usesSelectors);
+        return new EntitySelector(this.maxResults, this.includesEntities, this.worldLimited, this.predicate, this.distance, function, axisalignedbb, this.order, this.currentEntity, this.playerName, this.entityUUID, this.type, this.usesSelectors);
     }
 
     private AABB createAabb(double x, double y, double z) {
-        boolean bl = x < 0.0D;
-        boolean bl2 = y < 0.0D;
-        boolean bl3 = z < 0.0D;
-        double d = bl ? x : 0.0D;
-        double e = bl2 ? y : 0.0D;
-        double f = bl3 ? z : 0.0D;
-        double g = (bl ? 0.0D : x) + 1.0D;
-        double h = (bl2 ? 0.0D : y) + 1.0D;
-        double i = (bl3 ? 0.0D : z) + 1.0D;
-        return new AABB(d, e, f, g, h, i);
+        boolean flag = x < 0.0D;
+        boolean flag1 = y < 0.0D;
+        boolean flag2 = z < 0.0D;
+        double d3 = flag ? x : 0.0D;
+        double d4 = flag1 ? y : 0.0D;
+        double d5 = flag2 ? z : 0.0D;
+        double d6 = (flag ? 0.0D : x) + 1.0D;
+        double d7 = (flag1 ? 0.0D : y) + 1.0D;
+        double d8 = (flag2 ? 0.0D : z) + 1.0D;
+
+        return new AABB(d3, d4, d5, d6, d7, d8);
     }
 
     private void finalizePredicates() {
@@ -175,56 +194,57 @@
 
         if (!this.level.isAny()) {
             this.predicate = this.predicate.and((entity) -> {
-                return !(entity instanceof ServerPlayer) ? false : this.level.matches(((ServerPlayer)entity).experienceLevel);
+                return !(entity instanceof ServerPlayer) ? false : this.level.matches(((ServerPlayer) entity).experienceLevel);
             });
         }
 
     }
 
     private Predicate<Entity> createRotationPredicate(WrappedMinMaxBounds angleRange, ToDoubleFunction<Entity> entityToAngle) {
-        double d = (double)Mth.wrapDegrees(angleRange.getMin() == null ? 0.0F : angleRange.getMin());
-        double e = (double)Mth.wrapDegrees(angleRange.getMax() == null ? 359.0F : angleRange.getMax());
+        double d0 = (double) Mth.wrapDegrees(angleRange.getMin() == null ? 0.0F : angleRange.getMin());
+        double d1 = (double) Mth.wrapDegrees(angleRange.getMax() == null ? 359.0F : angleRange.getMax());
+
         return (entity) -> {
-            double f = Mth.wrapDegrees(entityToAngle.applyAsDouble(entity));
-            if (d > e) {
-                return f >= d || f <= e;
-            } else {
-                return f >= d && f <= e;
-            }
+            double d2 = Mth.wrapDegrees(entityToAngle.applyAsDouble(entity));
+
+            return d0 > d1 ? d2 >= d0 || d2 <= d1 : d2 >= d0 && d2 <= d1;
         };
     }
 
-    protected void parseSelector() throws CommandSyntaxException {
-        this.usesSelectors = true;
+    // CraftBukkit start
+    protected void parseSelector(boolean overridePermissions) throws CommandSyntaxException {
+        this.usesSelectors = !overridePermissions;
+        // CraftBukkit end
         this.suggestions = this::suggestSelector;
         if (!this.reader.canRead()) {
-            throw ERROR_MISSING_SELECTOR_TYPE.createWithContext(this.reader);
+            throw EntitySelectorParser.ERROR_MISSING_SELECTOR_TYPE.createWithContext(this.reader);
         } else {
             int i = this.reader.getCursor();
-            char c = this.reader.read();
-            if (c == 'p') {
+            char c0 = this.reader.read();
+
+            if (c0 == 'p') {
                 this.maxResults = 1;
                 this.includesEntities = false;
-                this.order = ORDER_NEAREST;
+                this.order = EntitySelectorParser.ORDER_NEAREST;
                 this.limitToType(EntityType.PLAYER);
-            } else if (c == 'a') {
+            } else if (c0 == 'a') {
                 this.maxResults = Integer.MAX_VALUE;
                 this.includesEntities = false;
                 this.order = EntitySelector.ORDER_ARBITRARY;
                 this.limitToType(EntityType.PLAYER);
-            } else if (c == 'r') {
+            } else if (c0 == 'r') {
                 this.maxResults = 1;
                 this.includesEntities = false;
-                this.order = ORDER_RANDOM;
+                this.order = EntitySelectorParser.ORDER_RANDOM;
                 this.limitToType(EntityType.PLAYER);
-            } else if (c == 's') {
+            } else if (c0 == 's') {
                 this.maxResults = 1;
                 this.includesEntities = true;
                 this.currentEntity = true;
             } else {
-                if (c != 'e') {
+                if (c0 != 'e') {
                     this.reader.setCursor(i);
-                    throw ERROR_UNKNOWN_SELECTOR_TYPE.createWithContext(this.reader, "@" + String.valueOf(c));
+                    throw EntitySelectorParser.ERROR_UNKNOWN_SELECTOR_TYPE.createWithContext(this.reader, "@" + String.valueOf(c0));
                 }
 
                 this.maxResults = Integer.MAX_VALUE;
@@ -249,19 +269,19 @@
         }
 
         int i = this.reader.getCursor();
-        String string = this.reader.readString();
+        String s = this.reader.readString();
 
         try {
-            this.entityUUID = UUID.fromString(string);
+            this.entityUUID = UUID.fromString(s);
             this.includesEntities = true;
-        } catch (IllegalArgumentException var4) {
-            if (string.isEmpty() || string.length() > 16) {
+        } catch (IllegalArgumentException illegalargumentexception) {
+            if (s.isEmpty() || s.length() > 16) {
                 this.reader.setCursor(i);
-                throw ERROR_INVALID_NAME_OR_UUID.createWithContext(this.reader);
+                throw EntitySelectorParser.ERROR_INVALID_NAME_OR_UUID.createWithContext(this.reader);
             }
 
             this.includesEntities = false;
-            this.playerName = string;
+            this.playerName = s;
         }
 
         this.maxResults = 1;
@@ -271,22 +291,23 @@
         this.suggestions = this::suggestOptionsKey;
         this.reader.skipWhitespace();
 
-        while(true) {
+        while (true) {
             if (this.reader.canRead() && this.reader.peek() != ']') {
                 this.reader.skipWhitespace();
                 int i = this.reader.getCursor();
-                String string = this.reader.readString();
-                EntitySelectorOptions.Modifier modifier = EntitySelectorOptions.get(this, string, i);
+                String s = this.reader.readString();
+                EntitySelectorOptions.Modifier playerselector_a = EntitySelectorOptions.get(this, s, i);
+
                 this.reader.skipWhitespace();
                 if (!this.reader.canRead() || this.reader.peek() != '=') {
                     this.reader.setCursor(i);
-                    throw ERROR_EXPECTED_OPTION_VALUE.createWithContext(this.reader, string);
+                    throw EntitySelectorParser.ERROR_EXPECTED_OPTION_VALUE.createWithContext(this.reader, s);
                 }
 
                 this.reader.skip();
                 this.reader.skipWhitespace();
-                this.suggestions = SUGGEST_NOTHING;
-                modifier.handle(this);
+                this.suggestions = EntitySelectorParser.SUGGEST_NOTHING;
+                playerselector_a.handle(this);
                 this.reader.skipWhitespace();
                 this.suggestions = this::suggestOptionsNextOrClose;
                 if (!this.reader.canRead()) {
@@ -300,17 +321,17 @@
                 }
 
                 if (this.reader.peek() != ']') {
-                    throw ERROR_EXPECTED_END_OF_OPTIONS.createWithContext(this.reader);
+                    throw EntitySelectorParser.ERROR_EXPECTED_END_OF_OPTIONS.createWithContext(this.reader);
                 }
             }
 
             if (this.reader.canRead()) {
                 this.reader.skip();
-                this.suggestions = SUGGEST_NOTHING;
+                this.suggestions = EntitySelectorParser.SUGGEST_NOTHING;
                 return;
             }
 
-            throw ERROR_EXPECTED_END_OF_OPTIONS.createWithContext(this.reader);
+            throw EntitySelectorParser.ERROR_EXPECTED_END_OF_OPTIONS.createWithContext(this.reader);
         }
     }
 
@@ -451,15 +472,21 @@
     }
 
     public EntitySelector parse() throws CommandSyntaxException {
+        // CraftBukkit start
+        return this.parse(false);
+    }
+
+    public EntitySelector parse(boolean overridePermissions) throws CommandSyntaxException {
+        // CraftBukkit end
         this.startPosition = this.reader.getCursor();
         this.suggestions = this::suggestNameOrSelector;
         if (this.reader.canRead() && this.reader.peek() == '@') {
             if (!this.allowSelectors) {
-                throw ERROR_SELECTORS_NOT_ALLOWED.createWithContext(this.reader);
+                throw EntitySelectorParser.ERROR_SELECTORS_NOT_ALLOWED.createWithContext(this.reader);
             }
 
             this.reader.skip();
-            this.parseSelector();
+            this.parseSelector(overridePermissions); // CraftBukkit
         } else {
             this.parseNameOrUUID();
         }
@@ -479,22 +506,24 @@
     private CompletableFuture<Suggestions> suggestNameOrSelector(SuggestionsBuilder builder, Consumer<SuggestionsBuilder> consumer) {
         consumer.accept(builder);
         if (this.allowSelectors) {
-            fillSelectorSuggestions(builder);
+            EntitySelectorParser.fillSelectorSuggestions(builder);
         }
 
         return builder.buildFuture();
     }
 
     private CompletableFuture<Suggestions> suggestName(SuggestionsBuilder builder, Consumer<SuggestionsBuilder> consumer) {
-        SuggestionsBuilder suggestionsBuilder = builder.createOffset(this.startPosition);
-        consumer.accept(suggestionsBuilder);
-        return builder.add(suggestionsBuilder).buildFuture();
+        SuggestionsBuilder suggestionsbuilder1 = builder.createOffset(this.startPosition);
+
+        consumer.accept(suggestionsbuilder1);
+        return builder.add(suggestionsbuilder1).buildFuture();
     }
 
     private CompletableFuture<Suggestions> suggestSelector(SuggestionsBuilder builder, Consumer<SuggestionsBuilder> consumer) {
-        SuggestionsBuilder suggestionsBuilder = builder.createOffset(builder.getStart() - 1);
-        fillSelectorSuggestions(suggestionsBuilder);
-        builder.add(suggestionsBuilder);
+        SuggestionsBuilder suggestionsbuilder1 = builder.createOffset(builder.getStart() - 1);
+
+        EntitySelectorParser.fillSelectorSuggestions(suggestionsbuilder1);
+        builder.add(suggestionsbuilder1);
         return builder.buildFuture();
     }
 
@@ -534,7 +563,7 @@
     }
 
     public CompletableFuture<Suggestions> fillSuggestions(SuggestionsBuilder builder, Consumer<SuggestionsBuilder> consumer) {
-        return this.suggestions.apply(builder.createOffset(this.reader.getCursor()), consumer);
+        return (CompletableFuture) this.suggestions.apply(builder.createOffset(this.reader.getCursor()), consumer);
     }
 
     public boolean hasNameEquals() {
