Skip to content

Commit bedea0d

Browse files
AyhamAl-AliNotSoDelayed
authored andcommitted
🚀 Add loop-counter & Improve loops (SkriptLang#4595)
1 parent a38e389 commit bedea0d

File tree

9 files changed

+359
-140
lines changed

9 files changed

+359
-140
lines changed

src/main/java/ch/njol/skript/effects/EffContinue.java

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -25,25 +25,33 @@
2525
import ch.njol.skript.doc.Since;
2626
import ch.njol.skript.lang.Effect;
2727
import ch.njol.skript.lang.Expression;
28+
import ch.njol.skript.lang.LoopSection;
2829
import ch.njol.skript.lang.SkriptParser.ParseResult;
2930
import ch.njol.skript.lang.TriggerItem;
30-
import ch.njol.skript.lang.TriggerSection;
31-
import ch.njol.skript.lang.parser.ParserInstance;
32-
import ch.njol.skript.sections.SecLoop;
33-
import ch.njol.skript.sections.SecWhile;
3431
import ch.njol.util.Kleenean;
3532
import org.bukkit.event.Event;
3633
import org.eclipse.jdt.annotation.Nullable;
3734

3835
import java.util.List;
39-
import java.util.stream.Collectors;
4036

4137
@Name("Continue")
42-
@Description("Skips the value currently being looped, moving on to the next value if it exists.")
43-
@Examples({"loop all players:",
38+
@Description("Immediately moves the (while) loop on to the next iteration.")
39+
@Examples({
40+
"# Broadcast online moderators",
41+
"loop all players:",
4442
"\tif loop-value does not have permission \"moderator\":",
45-
"\t\tcontinue # filter out non moderators",
46-
"\tbroadcast \"%loop-player% is a moderator!\" # Only moderators get broadcast"})
43+
"\t\tcontinue # filter out non moderators",
44+
"\tbroadcast \"%loop-player% is a moderator!\" # Only moderators get broadcast",
45+
" ",
46+
"# Game starting counter",
47+
"set {_counter} to 11",
48+
"while {_counter} > 0:",
49+
"\tremove 1 from {_counter}",
50+
"\twait a second",
51+
"\tif {_counter} != 1, 2, 3, 5 or 10:",
52+
"\t\tcontinue # only print when counter is 1, 2, 3, 5 or 10",
53+
"\tbroadcast \"Game starting in %{_counter}% second(s)\"",
54+
})
4755
@Since("2.2-dev37, 2.7 (while loops)")
4856
public class EffContinue extends Effect {
4957

@@ -52,36 +60,34 @@ public class EffContinue extends Effect {
5260
}
5361

5462
@SuppressWarnings("NotNullFieldNotInitialized")
55-
private TriggerSection section;
63+
private LoopSection loop;
5664

5765
@Override
5866
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
59-
List<TriggerSection> currentSections = ParserInstance.get().getCurrentSections().stream()
60-
.filter(s -> s instanceof SecLoop || s instanceof SecWhile)
61-
.collect(Collectors.toList());
67+
List<LoopSection> currentLoops = getParser().getCurrentSections(LoopSection.class);
6268

63-
if (currentSections.isEmpty()) {
64-
Skript.error("Continue may only be used in while or loops");
69+
if (currentLoops.isEmpty()) {
70+
Skript.error("The 'continue' effect may only be used in while and regular loops");
6571
return false;
6672
}
6773

68-
section = currentSections.get(currentSections.size() - 1);
74+
loop = currentLoops.get(currentLoops.size() - 1);
6975
return true;
7076
}
7177

7278
@Override
73-
protected void execute(Event e) {
79+
protected void execute(Event event) {
7480
throw new UnsupportedOperationException();
7581
}
7682

77-
@Nullable
7883
@Override
79-
protected TriggerItem walk(Event e) {
80-
return section;
84+
@Nullable
85+
protected TriggerItem walk(Event event) {
86+
return loop;
8187
}
8288

8389
@Override
84-
public String toString(@Nullable Event e, boolean debug) {
90+
public String toString(@Nullable Event event, boolean debug) {
8591
return "continue";
8692
}
8793

src/main/java/ch/njol/skript/effects/EffExit.java

Lines changed: 35 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -25,50 +25,51 @@
2525
import ch.njol.skript.doc.Since;
2626
import ch.njol.skript.lang.Effect;
2727
import ch.njol.skript.lang.Expression;
28+
import ch.njol.skript.lang.LoopSection;
2829
import ch.njol.skript.lang.SkriptParser.ParseResult;
2930
import ch.njol.skript.lang.TriggerItem;
3031
import ch.njol.skript.lang.TriggerSection;
3132
import ch.njol.skript.lang.parser.ParserInstance;
3233
import ch.njol.skript.log.ErrorQuality;
3334
import ch.njol.skript.sections.SecConditional;
34-
import ch.njol.skript.sections.SecLoop;
35-
import ch.njol.skript.sections.SecWhile;
3635
import ch.njol.util.Kleenean;
3736
import org.bukkit.event.Event;
3837
import org.eclipse.jdt.annotation.Nullable;
3938

4039
import java.util.List;
4140

42-
/**
43-
* @author Peter Güttinger
44-
*/
4541
@Name("Exit")
4642
@Description("Exits a given amount of loops and conditionals, or the entire trigger.")
47-
@Examples({"if player has any ore:",
48-
" stop",
49-
"message \"%player% has no ores!\"",
50-
"loop blocks above the player:",
51-
" loop-block is not air:",
52-
" exit 2 sections",
53-
" set loop-block to water"})
43+
@Examples({
44+
"if player has any ore:",
45+
"\tstop",
46+
"message \"%player% has no ores!\"",
47+
"loop blocks above the player:",
48+
"\tloop-block is not air:",
49+
"\t\texit 2 sections",
50+
"\tset loop-block to water"
51+
})
5452
@Since("<i>unknown</i> (before 2.1)")
5553
public class EffExit extends Effect { // TODO [code style] warn user about code after a stop effect
54+
5655
static {
5756
Skript.registerEffect(EffExit.class,
5857
"(exit|stop) [trigger]",
59-
"(exit|stop) [(1|a|the|this)] (section|1¦loop|2¦conditional)",
60-
"(exit|stop) <\\d+> (section|1¦loop|2¦conditional)s",
61-
"(exit|stop) all (section|1¦loop|2¦conditional)s");
58+
"(exit|stop) [(1|a|the|this)] (section|1:loop|2:conditional)",
59+
"(exit|stop) <\\d+> (section|1:loop|2:conditional)s",
60+
"(exit|stop) all (section|1:loop|2:conditional)s");
6261
}
6362

6463
private int breakLevels;
6564

66-
private final static int EVERYTHING = 0, LOOPS = 1, CONDITIONALS = 2;
67-
private final static String[] names = {"sections", "loops", "conditionals"};
65+
private static final int EVERYTHING = 0;
66+
private static final int LOOPS = 1;
67+
private static final int CONDITIONALS = 2;
68+
private static final String[] names = {"sections", "loops", "conditionals"};
6869
private int type;
6970

7071
@Override
71-
public boolean init(final Expression<?>[] exprs, final int matchedPattern, final Kleenean isDelayed, final ParseResult parser) {
72+
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parser) {
7273
switch (matchedPattern) {
7374
case 0:
7475
breakLevels = getParser().getCurrentSections().size() + 1;
@@ -102,44 +103,41 @@ private static int numLevels(int type) {
102103
List<TriggerSection> currentSections = ParserInstance.get().getCurrentSections();
103104
if (type == EVERYTHING)
104105
return currentSections.size();
105-
int r = 0;
106-
for (TriggerSection s : currentSections) {
107-
if (type == CONDITIONALS ? s instanceof SecConditional : s instanceof SecLoop || s instanceof SecWhile)
108-
r++;
106+
int level = 0;
107+
for (TriggerSection section : currentSections) {
108+
if (type == CONDITIONALS ? section instanceof SecConditional : section instanceof LoopSection)
109+
level++;
109110
}
110-
return r;
111+
return level;
111112
}
112113

113114
@Override
114115
@Nullable
115-
protected TriggerItem walk(final Event e) {
116-
debug(e, false);
117-
TriggerItem n = this;
116+
protected TriggerItem walk(Event event) {
117+
debug(event, false);
118+
TriggerItem node = this;
118119
for (int i = breakLevels; i > 0;) {
119-
n = n.getParent();
120-
if (n == null) {
120+
node = node.getParent();
121+
if (node == null) {
121122
assert false : this;
122123
return null;
123124
}
124-
if (n instanceof SecLoop) {
125-
((SecLoop) n).exit(e);
126-
} else if (n instanceof SecWhile) {
127-
((SecWhile) n).reset();
128-
}
125+
if (node instanceof LoopSection)
126+
((LoopSection) node).exit(event);
129127

130-
if (type == EVERYTHING || type == CONDITIONALS && n instanceof SecConditional || type == LOOPS && (n instanceof SecLoop || n instanceof SecWhile))
128+
if (type == EVERYTHING || type == CONDITIONALS && node instanceof SecConditional || type == LOOPS && (node instanceof LoopSection))
131129
i--;
132130
}
133-
return n instanceof SecLoop ? ((SecLoop) n).getActualNext() : n instanceof SecWhile ? ((SecWhile) n).getActualNext() : n.getNext();
131+
return node instanceof LoopSection ? ((LoopSection) node).getActualNext() : node.getNext();
134132
}
135133

136134
@Override
137-
protected void execute(final Event e) {
135+
protected void execute(Event event) {
138136
assert false;
139137
}
140138

141139
@Override
142-
public String toString(final @Nullable Event e, final boolean debug) {
140+
public String toString(@Nullable Event event, boolean debug) {
143141
return "stop " + breakLevels + " " + names[type];
144142
}
145143

src/main/java/ch/njol/skript/effects/EffReturn.java

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import ch.njol.skript.doc.Since;
2727
import ch.njol.skript.lang.Effect;
2828
import ch.njol.skript.lang.Expression;
29+
import ch.njol.skript.lang.LoopSection;
2930
import ch.njol.skript.lang.SkriptParser.ParseResult;
3031
import ch.njol.skript.lang.TriggerItem;
3132
import ch.njol.skript.lang.TriggerSection;
@@ -34,19 +35,16 @@
3435
import ch.njol.skript.lang.function.ScriptFunction;
3536
import ch.njol.skript.log.RetainingLogHandler;
3637
import ch.njol.skript.log.SkriptLogger;
37-
import ch.njol.skript.sections.SecLoop;
38-
import ch.njol.skript.sections.SecWhile;
3938
import ch.njol.util.Kleenean;
4039
import org.bukkit.event.Event;
4140
import org.eclipse.jdt.annotation.Nullable;
4241

43-
/**
44-
* @author Peter Güttinger
45-
*/
4642
@Name("Return")
4743
@Description("Makes a function return a value")
48-
@Examples({"function double(i: number) :: number:",
49-
" return 2 * {_i}"})
44+
@Examples({
45+
"function double(i: number) :: number:",
46+
"\treturn 2 * {_i}"
47+
})
5048
@Since("2.2")
5149
public class EffReturn extends Effect {
5250

@@ -75,66 +73,64 @@ public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelaye
7573
}
7674

7775
function = f;
78-
ClassInfo<?> rt = function.getReturnType();
79-
if (rt == null) {
76+
ClassInfo<?> returnType = function.getReturnType();
77+
if (returnType == null) {
8078
Skript.error("This function doesn't return any value. Please use 'stop' or 'exit' if you want to stop the function.");
8179
return false;
8280
}
8381

8482
RetainingLogHandler log = SkriptLogger.startRetainingLog();
85-
Expression<?> v;
83+
Expression<?> convertedExpr;
8684
try {
87-
v = exprs[0].getConvertedExpression(rt.getC());
88-
if (v == null) {
89-
log.printErrors("This function is declared to return " + rt.getName().withIndefiniteArticle() + ", but " + exprs[0].toString(null, false) + " is not of that type.");
85+
convertedExpr = exprs[0].getConvertedExpression(returnType.getC());
86+
if (convertedExpr == null) {
87+
log.printErrors("This function is declared to return " + returnType.getName().withIndefiniteArticle() + ", but " + exprs[0].toString(null, false) + " is not of that type.");
9088
return false;
9189
}
9290
log.printLog();
9391
} finally {
9492
log.stop();
9593
}
9694

97-
if (f.isSingle() && !v.isSingle()) {
98-
Skript.error("This function is defined to only return a single " + rt.toString() + ", but this return statement can return multiple values.");
95+
if (f.isSingle() && !convertedExpr.isSingle()) {
96+
Skript.error("This function is defined to only return a single " + returnType.toString() + ", but this return statement can return multiple values.");
9997
return false;
10098
}
101-
value = v;
99+
value = convertedExpr;
102100

103101
return true;
104102
}
105103

106-
@SuppressWarnings({"unchecked", "rawtypes"})
107104
@Override
108105
@Nullable
109-
protected TriggerItem walk(final Event e) {
110-
debug(e, false);
111-
if (e instanceof FunctionEvent) {
112-
((ScriptFunction) function).setReturnValue(value.getArray(e));
106+
@SuppressWarnings({"unchecked", "rawtypes"})
107+
protected TriggerItem walk(Event event) {
108+
debug(event, false);
109+
if (event instanceof FunctionEvent) {
110+
((ScriptFunction) function).setReturnValue(value.getArray(event));
113111
} else {
114-
assert false : e;
112+
assert false : event;
115113
}
116114

117115
TriggerSection parent = getParent();
118116
while (parent != null) {
119-
if (parent instanceof SecLoop) {
120-
((SecLoop) parent).exit(e);
121-
} else if (parent instanceof SecWhile) {
122-
((SecWhile) parent).reset();
123-
}
117+
if (parent instanceof LoopSection)
118+
((LoopSection) parent).exit(event);
119+
124120
parent = parent.getParent();
125121
}
126122

127123
return null;
128124
}
129125

130126
@Override
131-
protected void execute(Event e) {
127+
protected void execute(Event event) {
132128
assert false;
133129
}
134130

135131
@Override
136-
public String toString(@Nullable Event e, boolean debug) {
137-
return "return " + value.toString(e, debug);
132+
public String toString(@Nullable Event event, boolean debug) {
133+
return "return " + value.toString(event, debug);
138134
}
139135

140136
}

0 commit comments

Comments
 (0)