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

LivingEntity[] entities = (LivingEntity[]) delta;
if (mode != ChangeMode.RESET && mode != ChangeMode.DELETE && delta == null) {
return;
}
Comment thread
Efnilite marked this conversation as resolved.
Outdated

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
95 changes: 46 additions & 49 deletions src/main/java/ch/njol/skript/expressions/ExprElement.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
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;
import ch.njol.util.StringUtils;
import ch.njol.util.coll.CollectionUtils;
import ch.njol.util.coll.iterator.ArrayIterator;
import ch.njol.util.coll.iterator.EmptyIterator;
import com.google.common.collect.Iterators;
import org.apache.commons.lang.ArrayUtils;
Expand Down Expand Up @@ -48,17 +48,17 @@
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 %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}},
Comment thread
Efnilite marked this conversation as resolved.
Outdated
});

static {
Expand Down Expand Up @@ -132,23 +132,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 +153,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 +194,8 @@ 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() && expr.getSingle(event) instanceof SkriptQueue queue)
return Optional.ofNullable(getFromQueue(event, queue)).map(Iterators::forArray).orElse(null);
Iterator<? extends T> iterator = expr.iterator(event);
Comment thread
Efnilite marked this conversation as resolved.
Outdated
return transformIterator(event, iterator);
}
Expand Down Expand Up @@ -224,8 +227,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 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"