Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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"