Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🚀 Add loop-counter & Improve loops #4595

Merged
merged 46 commits into from
Jun 26, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
01fbfe0
🚀 Add `fails at` to while loop
AyhamAl-Ali Feb 11, 2022
d3397f3
Add iteration counter expr
AyhamAl-Ali Feb 12, 2022
5534c34
Merge branch 'master' into ench/while-fails-at
AyhamAl-Ali Feb 13, 2022
6ff2f24
🚀 Add loop-counter
AyhamAl-Ali Mar 30, 2022
691e37c
Extra protection
AyhamAl-Ali Mar 30, 2022
1c44447
Merge branch 'master' into ench/while-fails-at
AyhamAl-Ali Mar 30, 2022
72f4164
Should be ready now
AyhamAl-Ali Apr 5, 2022
6f9068c
Merge branch 'master' into ench/while-fails-at
AyhamAl-Ali Apr 5, 2022
d2314fd
Merge branch 'master' into ench/while-fails-at
AyhamAl-Ali Jun 24, 2022
58ccb26
Update src/main/java/ch/njol/skript/expressions/ExprLoopValue.java
AyhamAl-Ali Jul 1, 2022
56c5b68
Merge branch 'master' into ench/while-fails-at
AyhamAl-Ali Jul 1, 2022
674e7c2
RC - Update EffContinue with new LoopSection & Update loop-value
AyhamAl-Ali Jul 1, 2022
66244af
Update description
AyhamAl-Ali Jul 1, 2022
174fb7d
Merge branch 'master' into ench/while-fails-at
AyhamAl-Ali Jul 1, 2022
7ec6b41
Update src/main/java/ch/njol/skript/effects/EffContinue.java
AyhamAl-Ali Jul 1, 2022
4932f49
Merge branch 'master' into ench/while-fails-at
AyhamAl-Ali Jul 1, 2022
75e8f92
Improvements
AyhamAl-Ali Jul 1, 2022
14c8cb6
Merge remote-tracking branch 'AyhamAl-Ali/ench/while-fails-at' into e…
AyhamAl-Ali Jul 1, 2022
d3e3d6d
Annotations
AyhamAl-Ali Jul 1, 2022
cad44b3
Update src/main/java/ch/njol/skript/expressions/ExprLoopIteration.java
AyhamAl-Ali Jul 9, 2022
4161e68
Update src/main/java/ch/njol/skript/expressions/ExprLoopIteration.java
AyhamAl-Ali Jul 15, 2022
d7816d3
Update src/main/java/ch/njol/skript/expressions/ExprLoopIteration.java
AyhamAl-Ali Jul 18, 2022
85f1775
Update error message
AyhamAl-Ali Jul 18, 2022
f5e2a4c
Merge remote-tracking branch 'AyhamAl-Ali/ench/while-fails-at' into e…
AyhamAl-Ali Jul 18, 2022
8cd9c34
Update src/main/java/ch/njol/skript/expressions/ExprLoopIteration.java
AyhamAl-Ali Jul 22, 2022
875cb15
Update src/main/java/ch/njol/skript/lang/LoopSection.java
AyhamAl-Ali Aug 6, 2022
7c1e5b6
Update src/main/java/ch/njol/skript/expressions/ExprLoopValue.java
AyhamAl-Ali Aug 6, 2022
a71f19e
Update src/main/java/ch/njol/skript/sections/SecLoop.java
AyhamAl-Ali Aug 7, 2022
d43da59
Update src/main/java/ch/njol/skript/sections/SecLoop.java
AyhamAl-Ali Aug 7, 2022
a3e111d
Update src/main/java/ch/njol/skript/expressions/ExprLoopIteration.java
AyhamAl-Ali Aug 7, 2022
c98a4f3
Apply suggestions from code review
AyhamAl-Ali Aug 7, 2022
8d4c2e0
Formatting Improvements
AyhamAl-Ali Aug 26, 2022
a32d070
Update src/main/java/ch/njol/skript/effects/EffContinue.java
AyhamAl-Ali Nov 25, 2022
92cde7b
Better variable naming
AyhamAl-Ali Jan 1, 2023
1623b9d
Merge remote-tracking branch 'AyhamAl-Ali/ench/while-fails-at' into e…
AyhamAl-Ali Jan 1, 2023
60e31ba
Examples formatting
AyhamAl-Ali Jan 1, 2023
f7f7329
Requested Changes
AyhamAl-Ali Apr 18, 2023
9bf0f77
Add tests
AyhamAl-Ali Apr 18, 2023
c8c5ed3
Merge remote-tracking branch 'origin/master' into ench/while-fails-at
AyhamAl-Ali Apr 18, 2023
17c4ca5
Apply suggestions from code review
AyhamAl-Ali Apr 19, 2023
ab32194
Reorder methods
AyhamAl-Ali Apr 19, 2023
511d89b
Merge remote-tracking branch 'AyhamAl-Ali/ench/while-fails-at' into e…
AyhamAl-Ali Apr 19, 2023
8d609c2
Update src/test/skript/tests/regressions/4595-loop-iteration.sk
AyhamAl-Ali Apr 20, 2023
08351d2
Merge branch 'master' into ench/while-fails-at
TheLimeGlass Jun 6, 2023
48862ac
Merge branch 'master' into ench/while-fails-at
TheLimeGlass Jun 25, 2023
128bdc8
Merge branch 'master' into ench/while-fails-at
TheLimeGlass Jun 26, 2023
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
131 changes: 131 additions & 0 deletions src/main/java/ch/njol/skript/expressions/ExprLoopIteration.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/**
* This file is part of Skript.
*
* Skript is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Skript is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Skript. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright Peter Güttinger, SkriptLang team and contributors
*/
package ch.njol.skript.expressions;

import ch.njol.skript.Skript;
import ch.njol.skript.doc.Description;
import ch.njol.skript.doc.Examples;
import ch.njol.skript.doc.Name;
import ch.njol.skript.doc.Since;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.ExpressionType;
import ch.njol.skript.lang.Loop;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.skript.lang.TriggerSection;
import ch.njol.skript.lang.util.SimpleExpression;
import ch.njol.skript.sections.SecLoop;
import ch.njol.skript.sections.SecWhile;
import ch.njol.skript.util.Utils;
import ch.njol.util.Kleenean;
import org.bukkit.event.Event;
import org.eclipse.jdt.annotation.Nullable;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Name("Loop Iteration")
@Description("Returns the loop's current iteration count (for both normal and while loop).")
AyhamAl-Ali marked this conversation as resolved.
Show resolved Hide resolved
@Examples({
"while player is online:",
"\tgive player 1 stone",
"\twait 5 ticks",
"\tif loop-counter > 30:",
"\t\tstop loop",
"",
"loop {top-balances::*}:",
"\tif loop-iteration <= 10:",
"\t\tbroadcast \"##%loop-iteration% %loop-index% has $%loop-value%\"",
AyhamAl-Ali marked this conversation as resolved.
Show resolved Hide resolved
})
@Since("INSERT VERSION")
public class ExprLoopIteration extends SimpleExpression<Number> {

static {
Skript.registerExpression(ExprLoopIteration.class, Number.class, ExpressionType.SIMPLE, "[the] loop-<.+>");
}

@SuppressWarnings("NotNullFieldNotInitialized")
Loop loop;
AyhamAl-Ali marked this conversation as resolved.
Show resolved Hide resolved

private Pattern LOOP_PATTERN = Pattern.compile("^(.+)-(\\d+)$");

@Override
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
String s = "" + parseResult.regexes.get(0).group();
int i = -1;
Matcher m = LOOP_PATTERN.matcher(s);
if (m.matches()) {
s = m.group(1);
i = Utils.parseInt("" + m.group(2));
}

if (!("iteration".equals(s) || "counter".equals(s))) {
return false;
}
AyhamAl-Ali marked this conversation as resolved.
Show resolved Hide resolved

int j = 1;
Loop loop = null;

for (TriggerSection l : getParser().getCurrentSections()) {
if (!(l instanceof SecWhile) && !(l instanceof SecLoop))
AyhamAl-Ali marked this conversation as resolved.
Show resolved Hide resolved
continue;

AyhamAl-Ali marked this conversation as resolved.
Show resolved Hide resolved
if (j < i) {
j++;
continue;
}
if (loop != null) {
Skript.error("There are multiple loops that match loop-" + s + ". Use loop-" + s + "-1/2/3/etc. to specify which loop's " + s + " you want.");
return false;
}
loop = (Loop) l;

AyhamAl-Ali marked this conversation as resolved.
Show resolved Hide resolved
if (j == i)
break;
}

if (loop == null) {
Skript.error("There's no loop that matches 'loop-" + s + "-" + i + "'");
return false;
}

this.loop = loop;
return true;
}

@Override
protected Number[] get(Event e) {
return new Number[] { loop.getLoopCounter() };
}

@Override
public Class<? extends Number> getReturnType() {
return Number.class;
}

@Override
public boolean isSingle() {
AyhamAl-Ali marked this conversation as resolved.
Show resolved Hide resolved
return true;
}

@Override
public String toString(@Nullable Event e, boolean debug) {
return "loop counter of " + loop.toString(e, debug);
AyhamAl-Ali marked this conversation as resolved.
Show resolved Hide resolved
}

}
48 changes: 30 additions & 18 deletions src/main/java/ch/njol/skript/expressions/ExprLoopValue.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
import ch.njol.skript.lang.Variable;
import ch.njol.skript.lang.util.ConvertedExpression;
import ch.njol.skript.lang.util.SimpleExpression;
import ch.njol.skript.log.ErrorQuality;
import ch.njol.skript.registrations.Classes;
import ch.njol.skript.registrations.Converters;
import ch.njol.skript.sections.SecLoop;
Expand All @@ -47,22 +46,26 @@

/**
* Used to access a loop's current value.
* <p>
* TODO expression to get the current # of execution (e.g. loop-index/number/count/etc (not number though));
*
* @author Peter Güttinger
AyhamAl-Ali marked this conversation as resolved.
Show resolved Hide resolved
*/
@Name("Loop value")
@Description("The currently looped value.")
@Examples({"# countdown:",
"loop 10 times:",
" message \"%11 - loop-number%\"",
" wait a second",
"# generate a 10x10 floor made of randomly coloured wool below the player:",
"loop blocks from the block below the player to the block 10 east of the block below the player:",
" loop blocks from the loop-block to the block 10 north of the loop-block:",
" set loop-block-2 to any wool"})
@Since("1.0")
@Examples({
"# Countdown",
"loop 10 times:",
"\tmessage \"%11 - loop-number%\"",
"\twait a second",
"",
"# Generate a 10x10 floor made of randomly colored wool below the player",
"loop blocks from the block below the player to the block 10 east of the block below the player:",
"\tloop blocks from the loop-block to the block 10 north of the loop-block:",
"\t\tset loop-block-2 to any wool",
"",
"loop {top-balances::*}:",
"\tloop-iteration <= 10",
"\tsend \"##%loop-iteration% %loop-index% has $%loop-value%\"",
})
@Since("1.0, INSERT VERSION (loop-counter)")
public class ExprLoopValue extends SimpleExpression<Object> {
static {
Skript.registerExpression(ExprLoopValue.class, Object.class, ExpressionType.SIMPLE, "[the] loop-<.+>");
Expand All @@ -78,17 +81,23 @@ public class ExprLoopValue extends SimpleExpression<Object> {
boolean isVariableLoop = false;
// if this loops a variable and isIndex is true, return the index of the variable instead of the value
boolean isIndex = false;


private Pattern LOOP_PATTERN = Pattern.compile("^(.+)-(\\d+)$");
AyhamAl-Ali marked this conversation as resolved.
Show resolved Hide resolved

@Override
public boolean init(Expression<?>[] vars, int matchedPattern, Kleenean isDelayed, ParseResult parser) {
name = parser.expr;
String s = "" + parser.regexes.get(0).group();
int i = -1;
Matcher m = Pattern.compile("^(.+)-(\\d+)$").matcher(s);
Matcher m = LOOP_PATTERN.matcher(s);
if (m.matches()) {
s = "" + m.group(1);
i = Utils.parseInt("" + m.group(2));
}

if ("counter".equals(s) || "iteration".equals(s)) // ExprLoopIteration - in case of classinfo conflicts
AyhamAl-Ali marked this conversation as resolved.
Show resolved Hide resolved
return false;

Class<?> c = Classes.getClassFromUserInput(s);
int j = 1;
SecLoop loop = null;
Expand All @@ -100,7 +109,7 @@ public boolean init(Expression<?>[] vars, int matchedPattern, Kleenean isDelayed
continue;
}
if (loop != null) {
Skript.error("There are multiple loops that match loop-" + s + ". Use loop-" + s + "-1/2/3/etc. to specify which loop's value you want.", ErrorQuality.SEMANTIC_ERROR);
Skript.error("There are multiple loops that match loop-" + s + ". Use loop-" + s + "-1/2/3/etc. to specify which loop's value you want.");
TheLimeGlass marked this conversation as resolved.
Show resolved Hide resolved
return false;
}
loop = l;
Expand All @@ -109,7 +118,7 @@ public boolean init(Expression<?>[] vars, int matchedPattern, Kleenean isDelayed
}
}
if (loop == null) {
Skript.error("There's no loop that matches 'loop-" + s + "'", ErrorQuality.SEMANTIC_ERROR);
Skript.error("There's no loop that matches 'loop-" + s + "'");
return false;
}
if (loop.getLoopedExpression() instanceof Variable) {
Expand All @@ -126,9 +135,9 @@ public boolean isSingle() {
return true;
}

@SuppressWarnings("unchecked")
@Override
@Nullable
@SuppressWarnings("unchecked")
protected <R> ConvertedExpression<Object, ? extends R> getConvertedExpr(Class<R>... to) {
if (isVariableLoop && !isIndex) {
Class<R> superType = (Class<R>) Utils.getSuperType(to);
Expand Down Expand Up @@ -165,6 +174,9 @@ protected Object[] get(Event e) {
one[0] = current.getValue();
return one;
}
// else if (isWhileLoop) {
// }

AyhamAl-Ali marked this conversation as resolved.
Show resolved Hide resolved
Object[] one = (Object[]) Array.newInstance(getReturnType(), 1);
one[0] = loop.getCurrent(e);
return one;
Expand Down
34 changes: 34 additions & 0 deletions src/main/java/ch/njol/skript/lang/Loop.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* This file is part of Skript.
*
* Skript is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Skript is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Skript. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright Peter Güttinger, SkriptLang team and contributors
*/
package ch.njol.skript.lang;

/**
* Represents a loop section.
*
* @see ch.njol.skript.sections.SecWhile
* @see ch.njol.skript.sections.SecLoop
*/
public interface Loop extends Debuggable {
AyhamAl-Ali marked this conversation as resolved.
Show resolved Hide resolved

/**
* @return The current loop counter
*/
long getLoopCounter();

}
11 changes: 10 additions & 1 deletion src/main/java/ch/njol/skript/sections/SecLoop.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import ch.njol.skript.SkriptAPIException;
import ch.njol.skript.config.SectionNode;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.Loop;
import ch.njol.skript.lang.Section;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.skript.lang.TriggerItem;
Expand All @@ -39,7 +40,7 @@
import java.util.Map;
import java.util.WeakHashMap;

public class SecLoop extends Section {
public class SecLoop extends Section implements Loop {

static {
Skript.registerSection(SecLoop.class, "loop %objects%");
Expand All @@ -53,6 +54,7 @@ public class SecLoop extends Section {

@Nullable
private TriggerItem actualNext;
private long loopCounter = 0;

@Override
public boolean init(Expression<?>[] exprs,
Expand Down Expand Up @@ -101,8 +103,10 @@ protected TriggerItem walk(Event e) {
if (iter == null || !iter.hasNext()) {
exit(e);
debug(e, false);
loopCounter = 0;
AyhamAl-Ali marked this conversation as resolved.
Show resolved Hide resolved
return actualNext;
} else {
loopCounter++;
current.put(e, iter.next());
return walk(e, true);
}
Expand Down Expand Up @@ -137,4 +141,9 @@ public void exit(Event event) {
current.remove(event);
currentIter.remove(event);
}

@Override
public long getLoopCounter() {
return loopCounter;
}
}
20 changes: 14 additions & 6 deletions src/main/java/ch/njol/skript/sections/SecWhile.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import ch.njol.skript.config.SectionNode;
import ch.njol.skript.lang.Condition;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.Loop;
import ch.njol.skript.lang.Section;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.skript.lang.TriggerItem;
Expand All @@ -31,10 +32,10 @@

import java.util.List;

public class SecWhile extends Section {
public class SecWhile extends Section implements Loop {

static {
Skript.registerSection(SecWhile.class, "[(do)] while <.+>");
Skript.registerSection(SecWhile.class, "[(:do)] while <.+>");
}

@SuppressWarnings("NotNullFieldNotInitialized")
Expand All @@ -45,8 +46,10 @@ public class SecWhile extends Section {

private boolean doWhile;
private boolean ranDoWhile = false;
private int loopCounter = 0;

@Override
@SuppressWarnings("unchecked")
public boolean init(Expression<?>[] exprs,
int matchedPattern,
Kleenean isDelayed,
Expand All @@ -58,23 +61,24 @@ public boolean init(Expression<?>[] exprs,
condition = Condition.parse(expr, "Can't understand this condition: " + expr);
if (condition == null)
return false;
doWhile = parseResult.mark == 1;
loadOptionalCode(sectionNode);

doWhile = parseResult.hasTag("do");
loadOptionalCode(sectionNode);
super.setNext(this);

return true;
}

@Nullable
@Override
protected TriggerItem walk(Event e) {
AyhamAl-Ali marked this conversation as resolved.
Show resolved Hide resolved
if ((doWhile && !ranDoWhile) || condition.check(e)) {
if (((doWhile && !ranDoWhile) || condition.check(e))) {
AyhamAl-Ali marked this conversation as resolved.
Show resolved Hide resolved
ranDoWhile = true;
loopCounter++;
return walk(e, true);
} else {
reset();
debug(e, false);
loopCounter = 0;
AyhamAl-Ali marked this conversation as resolved.
Show resolved Hide resolved
return actualNext;
}
}
Expand All @@ -99,4 +103,8 @@ public void reset() {
ranDoWhile = false;
}

@Override
public long getLoopCounter() {
return loopCounter;
}
}