/*
* 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 2011-2014 Peter Güttinger
*
*/
package ch.njol.skript.effects;
import org.bukkit.event.Event;
import org.eclipse.jdt.annotation.Nullable;
import ch.njol.skript.ScriptLoader;
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.Conditional;
import ch.njol.skript.lang.Effect;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.Loop;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.skript.lang.TriggerItem;
import ch.njol.skript.lang.TriggerSection;
import ch.njol.skript.lang.While;
import ch.njol.skript.log.ErrorQuality;
import ch.njol.util.Kleenean;
/**
* @author Peter Güttinger
*/
@Name("Exit")
@Description("Exits a given amount of loops and conditionals, or the entire trigger.")
@Examples({"if player has any ore:",
" stop",
"message \"%player% has no ores!\"",
"loop blocks above the player:",
" loop-block is not air:",
" exit 2 sections",
" set loop-block to water"})
@Since("")
public class EffExit extends Effect { // TODO [code style] warn user about code after a stop effect
static {
Skript.registerEffect(EffExit.class,
"(exit|stop) [trigger]",
"(exit|stop) [(1|a|the|this)] (0¦section|1¦loop|2¦conditional)",
"(exit|stop) <\\d+> (0¦section|1¦loop|2¦conditional)s",
"(exit|stop) all (0¦section|1¦loop|2¦conditional)s");
}
private int breakLevels;
private final static int EVERYTHING = 0, LOOPS = 1, CONDITIONALS = 2;
private final static String[] names = {"sections", "loops", "conditionals"};
private int type;
@Override
public boolean init(final Expression<?>[] exprs, final int matchedPattern, final Kleenean isDelayed, final ParseResult parser) {
switch (matchedPattern) {
case 0:
breakLevels = ScriptLoader.currentSections.size() + 1;
type = EVERYTHING;
break;
case 1:
case 2:
breakLevels = matchedPattern == 1 ? 1 : Integer.parseInt(parser.regexes.get(0).group());
type = parser.mark;
if (breakLevels > numLevels(type)) {
if (numLevels(type) == 0)
Skript.error("can't stop any " + names[type] + " as there are no " + names[type] + " present", ErrorQuality.SEMANTIC_ERROR);
else
Skript.error("can't stop " + breakLevels + " " + names[type] + " as there are only " + numLevels(type) + " " + names[type] + " present", ErrorQuality.SEMANTIC_ERROR);
return false;
}
break;
case 3:
type = parser.mark;
breakLevels = numLevels(type);
if (breakLevels == 0) {
Skript.error("can't stop any " + names[type] + " as there are no " + names[type] + " present", ErrorQuality.SEMANTIC_ERROR);
return false;
}
break;
}
return true;
}
private final static int numLevels(final int type) {
if (type == EVERYTHING)
return ScriptLoader.currentSections.size();
int r = 0;
for (final TriggerSection s : ScriptLoader.currentSections) {
if (type == CONDITIONALS ? s instanceof Conditional : s instanceof Loop || s instanceof While)
r++;
}
return r;
}
@Override
@Nullable
protected TriggerItem walk(final Event e) {
debug(e, false);
TriggerItem n = this;
for (int i = breakLevels; i > 0;) {
n = n.getParent();
if (n == null) {
assert false : this;
return null;
}
if (type == EVERYTHING || type == CONDITIONALS && n instanceof Conditional || type == LOOPS && (n instanceof Loop || n instanceof While))
i--;
}
return n instanceof Loop ? ((Loop) n).getActualNext() : n instanceof While ? ((While) n).getActualNext() : n.getNext();
}
@Override
protected void execute(final Event e) {
assert false;
}
@Override
public String toString(final @Nullable Event e, final boolean debug) {
return "stop " + breakLevels + " " + names[type];
}
}