Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -74,19 +74,18 @@ public void change(Event event, Object @Nullable [] delta, ChangeMode mode) {
if (!(event instanceof AreaEffectCloudApplyEvent areaEvent))
return;

LivingEntity[] entities = (LivingEntity[]) delta;
switch (mode) {
case REMOVE:
for (LivingEntity entity : entities) {
areaEvent.getAffectedEntities().remove(entity);
for (Object entity : delta) {
areaEvent.getAffectedEntities().remove((LivingEntity) entity);
}
break;
case SET:
areaEvent.getAffectedEntities().clear();
// FALLTHROUGH
case ADD:
for (LivingEntity entity : entities) {
areaEvent.getAffectedEntities().add(entity);
for (Object entity : delta) {
areaEvent.getAffectedEntities().add((LivingEntity) entity);
}
break;
case RESET, DELETE:
Expand Down
99 changes: 48 additions & 51 deletions src/main/java/ch/njol/skript/expressions/ExprElement.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.skript.lang.simplification.SimplifiedLiteral;
import ch.njol.skript.lang.util.SimpleExpression;
import ch.njol.skript.registrations.Feature;
import ch.njol.skript.util.LiteralUtils;
import ch.njol.skript.util.Patterns;
import ch.njol.util.Kleenean;
Expand Down Expand Up @@ -48,17 +47,11 @@
public class ExprElement<T> extends SimpleExpression<T> implements KeyProviderExpression<T> {

private static final Patterns<ElementType[]> PATTERNS = new Patterns<>(new Object[][]{
{"[the] (first|1:last) element [out] of %objects%", new ElementType[] {ElementType.FIRST_ELEMENT, ElementType.LAST_ELEMENT}},
{"[the] (first|1:last) %integer% elements [out] of %objects%", new ElementType[] {ElementType.FIRST_X_ELEMENTS, ElementType.LAST_X_ELEMENTS}},
{"[a] random element [out] of %objects%", new ElementType[] {ElementType.RANDOM}},
{"[the] %integer%(st|nd|rd|th) [1:[to] last] element [out] of %objects%", new ElementType[] {ElementType.ORDINAL, ElementType.TAIL_END_ORDINAL}},
{"[the] elements (from|between) %integer% (to|and) %integer% [out] of %objects%", new ElementType[] {ElementType.RANGE}},

{"[the] (first|next|1:last) element (of|in) %queue%", new ElementType[] {ElementType.FIRST_ELEMENT, ElementType.LAST_ELEMENT}},
{"[the] (first|1:last) %integer% elements (of|in) %queue%", new ElementType[] {ElementType.FIRST_X_ELEMENTS, ElementType.LAST_X_ELEMENTS}},
{"[a] random element (of|in) %queue%", new ElementType[] {ElementType.RANDOM}},
{"[the] %integer%(st|nd|rd|th) [1:[to] last] element (of|in) %queue%", new ElementType[] {ElementType.ORDINAL, ElementType.TAIL_END_ORDINAL}},
{"[the] elements (from|between) %integer% (to|and) %integer% (of|in) %queue%", new ElementType[] {ElementType.RANGE}},
{"[the] (first|1:last) element [out] (of|in) %objects%", new ElementType[]{ElementType.FIRST_ELEMENT, ElementType.LAST_ELEMENT}},
{"[the] (first|1:last) %integer% elements [out] (of|in) %objects%", new ElementType[]{ElementType.FIRST_X_ELEMENTS, ElementType.LAST_X_ELEMENTS}},
{"[a] random element [out] (of|in) %objects%", new ElementType[]{ElementType.RANDOM}},
{"[the] %integer%(st|nd|rd|th) [1:[to] last] element [out] (of|in) %objects%", new ElementType[]{ElementType.ORDINAL, ElementType.TAIL_END_ORDINAL}},
{"[the] elements (from|between) %integer% (to|and) %integer% [out] (of|in) %objects%", new ElementType[]{ElementType.RANGE}},
});

static {
Expand Down Expand Up @@ -132,23 +125,16 @@ public <T> Iterator<T> apply(Iterator<T> iterator, int startIndex, int endIndex)
private final Map<Event, List<String>> cache = new WeakHashMap<>();

private Expression<? extends T> expr;
private @Nullable Expression<Integer> startIndex, endIndex;
private @Nullable Expression<Integer> startIndex, endIndex;
private ElementType type;
private boolean queue;
private boolean keyed;

@Override
@SuppressWarnings("unchecked")
public boolean init(Expression<?>[] expressions, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
ElementType[] types = PATTERNS.getInfo(matchedPattern);
this.queue = matchedPattern > 4;
if (queue && !this.getParser().hasExperiment(Feature.QUEUES))
return false;
if (queue) {
this.expr = (Expression<T>) expressions[expressions.length - 1];
} else {
this.expr = LiteralUtils.defendExpression(expressions[expressions.length - 1]);
}
this.expr = LiteralUtils.defendExpression(expressions[expressions.length - 1]);

switch (type = types[parseResult.mark]) {
case RANGE:
endIndex = (Expression<Integer>) expressions[1];
Expand All @@ -160,21 +146,31 @@ public boolean init(Expression<?>[] expressions, int matchedPattern, Kleenean is
break;
}
this.keyed = KeyProviderExpression.canReturnKeys(this.expr);
return queue || LiteralUtils.canInitSafely(expr);
return LiteralUtils.canInitSafely(expr);
}

@Override
protected T @Nullable [] get(Event event) {
if (queue)
return this.getFromQueue(event);
if (keyed) {
KeyedValue.UnzippedKeyValues<T> unzipped = KeyedValue.unzip(keyedIterator(event));
cache.put(event, unzipped.keys());
//noinspection unchecked
T[] empty = (T[]) Array.newInstance(getReturnType(), 0);
return unzipped.values().toArray(empty);
}
Iterator<? extends T> iterator = iterator(event);

Comment thread
Efnilite marked this conversation as resolved.
Iterator<? extends T> iterator;
if (expr.isSingle()) {
T single = expr.getSingle(event);
if (single instanceof SkriptQueue queue) {
return this.getFromQueue(event, queue);
} else {
iterator = transformIterator(event, Iterators.singletonIterator(single));
}
} else {
iterator = transformIterator(event, expr.iterator(event));
}

assert iterator != null;
//noinspection unchecked
return Iterators.toArray(iterator, (Class<T>) getReturnType());
Expand All @@ -191,8 +187,13 @@ public boolean init(Expression<?>[] expressions, int matchedPattern, Kleenean is

@Override
public @Nullable Iterator<? extends T> iterator(Event event) {
if (queue)
return Optional.ofNullable(getFromQueue(event)).map(Iterators::forArray).orElse(null);
if (expr.isSingle()) {
T single = expr.getSingle(event);
if (single instanceof SkriptQueue queue) {
return Optional.ofNullable(getFromQueue(event, queue)).map(Iterators::forArray).orElse(null);
}
return Iterators.singletonIterator(single);
Comment thread
Efnilite marked this conversation as resolved.
}
Iterator<? extends T> iterator = expr.iterator(event);
return transformIterator(event, iterator);
}
Expand Down Expand Up @@ -224,8 +225,7 @@ private <A> Iterator<A> transformIterator(Event event, @Nullable Iterator<A> ite
}

@SuppressWarnings("unchecked")
private T @Nullable [] getFromQueue(Event event) {
SkriptQueue queue = (SkriptQueue) expr.getSingle(event);
private T @Nullable [] getFromQueue(Event event, SkriptQueue queue) {
if (queue == null)
return null;
Integer startIndex = 0, endIndex = 0;
Expand All @@ -242,11 +242,13 @@ private <A> Iterator<A> transformIterator(Event event, @Nullable Iterator<A> ite
return switch (type) {
case FIRST_ELEMENT -> CollectionUtils.array((T) queue.pollFirst());
case LAST_ELEMENT -> CollectionUtils.array((T) queue.pollLast());
case RANDOM -> CollectionUtils.array((T) queue.removeSafely(ThreadLocalRandom.current().nextInt(0, queue.size())));
case RANDOM ->
CollectionUtils.array((T) queue.removeSafely(ThreadLocalRandom.current().nextInt(0, queue.size())));
case ORDINAL -> CollectionUtils.array((T) queue.removeSafely(startIndex - 1));
case TAIL_END_ORDINAL -> CollectionUtils.array((T) queue.removeSafely(queue.size() - startIndex));
case FIRST_X_ELEMENTS -> CollectionUtils.array((T[]) queue.removeRangeSafely(0, startIndex));
case LAST_X_ELEMENTS -> CollectionUtils.array((T[]) queue.removeRangeSafely(queue.size() - startIndex, queue.size()));
case LAST_X_ELEMENTS ->
CollectionUtils.array((T[]) queue.removeRangeSafely(queue.size() - startIndex, queue.size()));
case RANGE -> {
boolean reverse = startIndex > endIndex;
T[] elements = CollectionUtils.array((T[]) queue.removeRangeSafely(Math.min(startIndex, endIndex) - 1, Math.max(startIndex, endIndex)));
Expand Down Expand Up @@ -284,7 +286,6 @@ public <R> Expression<? extends R> getConvertedExpression(Class<R>... to) {
exprElement.startIndex = startIndex;
exprElement.endIndex = endIndex;
exprElement.type = type;
exprElement.queue = queue;
return exprElement;
}

Expand All @@ -295,37 +296,33 @@ public boolean isSingle() {

@Override
public Class<? extends T> getReturnType() {
if (queue)
return (Class<? extends T>) Object.class;
return expr.getReturnType();
Class<? extends T> returnType = expr.getReturnType();
//noinspection unchecked
return returnType == SkriptQueue.class ? (Class<? extends T>) Object.class : returnType;
}

@Override
public Class<? extends T>[] possibleReturnTypes() {
if (!queue) {
return expr.possibleReturnTypes();
}
return super.possibleReturnTypes();
Class<? extends T> returnType = expr.getReturnType();
//noinspection unchecked
return returnType == SkriptQueue.class ? new Class[]{Object.class} : expr.possibleReturnTypes();
}

@Override
public boolean canReturn(Class<?> returnType) {
if (!queue) {
return expr.canReturn(returnType);
}
return super.canReturn(returnType);
return returnType == SkriptQueue.class || expr.canReturn(returnType);
}
@Override

@Override
public Expression<? extends T> simplify() {
if (!queue && expr instanceof Literal<?>
&& type != ElementType.RANDOM
&& (startIndex == null || startIndex instanceof Literal<Integer>)
&& (endIndex == null || endIndex instanceof Literal<Integer>)) {
if (expr instanceof Literal<?>
&& type != ElementType.RANDOM
&& (startIndex == null || startIndex instanceof Literal<Integer>)
&& (endIndex == null || endIndex instanceof Literal<Integer>)) {
return SimplifiedLiteral.fromExpression(this);
}
return this;
}
}

@Override
public String toString(@Nullable Event event, boolean debug) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using queues

test "8548 first queue element":
set {queue} to a new queue
add "hello" and "there" to {queue}
assert the first element of {queue} is "hello"
assert the first element of {queue} is "there"