-
-
Notifications
You must be signed in to change notification settings - Fork 373
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d073e28
commit 1743000
Showing
7 changed files
with
473 additions
and
70 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
/** | ||
* 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; | ||
|
||
import ch.njol.skript.ScriptLoader; | ||
import ch.njol.skript.SkriptAPIException; | ||
import ch.njol.skript.config.SectionNode; | ||
import ch.njol.skript.lang.parser.ParserInstance; | ||
import org.bukkit.event.Event; | ||
import org.jetbrains.annotations.ApiStatus.NonExtendable; | ||
import org.jetbrains.annotations.Nullable; | ||
|
||
import java.util.Deque; | ||
import java.util.LinkedList; | ||
|
||
public interface ReturnHandler<T> { | ||
|
||
/** | ||
* Loads the code in the given {@link SectionNode} using the same logic as | ||
* {@link Section#loadCode(SectionNode)} and pushes the section onto the | ||
* return handler stack | ||
* <br> | ||
* <b>This method may only be called by a {@link Section}</b> | ||
* @throws SkriptAPIException if this return handler is not a {@link Section} | ||
*/ | ||
@NonExtendable | ||
default void loadReturnableSectionCode(SectionNode node) { | ||
if (!(this instanceof Section)) | ||
throw new SkriptAPIException("loadReturnableSectionCode called on a non-section object"); | ||
ParserInstance parser = ParserInstance.get(); | ||
ReturnHandlerStack stack = parser.getData(ReturnHandlerStack.class); | ||
stack.push(this); | ||
Section section = (Section) this; | ||
try { | ||
section.loadCode(node); | ||
} finally { | ||
stack.pop(); | ||
} | ||
} | ||
|
||
/** | ||
* Loads the code in the given {@link SectionNode} using the same logic as | ||
* {@link Section#loadCode(SectionNode, String, Class[])} and pushes the section onto the | ||
* return handler stack | ||
* <br> | ||
* <b>This method may only be called by a {@link Section}</b> | ||
* @param node the section node | ||
* @param name the name of the event(s) being used | ||
* @param events the event(s) during the section's execution | ||
* @return a returnable trigger containing the loaded section. | ||
* This should be stored and used to run the section one or more times | ||
* @throws SkriptAPIException if this return handler is not a {@link Section} | ||
*/ | ||
@NonExtendable | ||
default ReturnableTrigger<T> loadReturnableSectionCode(SectionNode node, String name, Class<? extends Event>[] events) { | ||
if (!(this instanceof Section)) | ||
throw new SkriptAPIException("loadReturnableSectionCode called on a non-section object"); | ||
ParserInstance parser = ParserInstance.get(); | ||
ParserInstance.Backup parserBackup = parser.backup(); | ||
parser.reset(); | ||
|
||
parser.setCurrentEvent(name, events); | ||
SkriptEvent skriptEvent = new SectionSkriptEvent(name, (Section) this); | ||
parser.setCurrentStructure(skriptEvent); | ||
ReturnHandlerStack stack = parser.getData(ReturnHandlerStack.class); | ||
|
||
try { | ||
return new ReturnableTrigger<>( | ||
this, | ||
parser.getCurrentScript(), | ||
name, | ||
skriptEvent, | ||
trigger -> { | ||
stack.push(trigger); | ||
return ScriptLoader.loadItems(node); | ||
} | ||
); | ||
} finally { | ||
stack.pop(); | ||
parser.restoreBackup(parserBackup); | ||
} | ||
} | ||
|
||
/** | ||
* Loads the code in the given {@link SectionNode} into a {@link ReturnableTrigger}. | ||
* <br> | ||
* This is a general method to load a section node without extra logic | ||
* done to the {@link ParserInstance}. | ||
* The calling code is expected to manage the {@code ParserInstance} accordingly, which may vary depending on | ||
* where the code being loaded is located and what state the {@code ParserInstance} is in. | ||
* @param node the section node to load | ||
* @param name the name of the trigger | ||
* @param event the {@link SkriptEvent} of the trigger | ||
* @return a returnable trigger containing the loaded section node | ||
*/ | ||
@NonExtendable | ||
default ReturnableTrigger<T> loadReturnableTrigger(SectionNode node, String name, SkriptEvent event) { | ||
ParserInstance parser = ParserInstance.get(); | ||
ReturnHandlerStack stack = parser.getData(ReturnHandlerStack.class); | ||
try { | ||
return new ReturnableTrigger<T>( | ||
this, | ||
parser.getCurrentScript(), | ||
name, | ||
event, | ||
trigger -> { | ||
stack.push(trigger); | ||
return ScriptLoader.loadItems(node); | ||
} | ||
); | ||
} finally { | ||
stack.pop(); | ||
} | ||
} | ||
|
||
/** | ||
* @param values the values to return | ||
*/ | ||
void returnValues(T @Nullable [] values); | ||
|
||
/** | ||
* @return whether this return handler may accept multiple return values | ||
*/ | ||
boolean isSingleReturnValue(); | ||
|
||
/** | ||
* The return type of this return handler, or null if it can't | ||
* accept return values in this context (e.g. a function without a return type). | ||
* | ||
* @return the return type | ||
*/ | ||
@Nullable Class<? extends T> returnValueType(); | ||
|
||
class ReturnHandlerStack extends ParserInstance.Data { | ||
|
||
private final Deque<ReturnHandler<?>> stack = new LinkedList<>(); | ||
|
||
public ReturnHandlerStack(ParserInstance parserInstance) { | ||
super(parserInstance); | ||
} | ||
|
||
public Deque<ReturnHandler<?>> getStack() { | ||
return stack; | ||
} | ||
|
||
/** | ||
* Retrieves the current {@link ReturnHandler} | ||
* @return the return data | ||
*/ | ||
public @Nullable ReturnHandler<?> getCurrentHandler() { | ||
return stack.peek(); | ||
} | ||
|
||
/** | ||
* Pushes the current return handler onto the return stack. | ||
* <br> | ||
* <b>Note: After the trigger finished loading, | ||
* {@link ReturnHandlerStack#pop()} <u>MUST</u> be called</b> | ||
* @param handler the return handler | ||
* @see ReturnHandlerStack#pop() | ||
*/ | ||
public void push(ReturnHandler<?> handler) { | ||
stack.push(handler); | ||
} | ||
|
||
/** | ||
* Pops the current handler off the return stack. | ||
* Should be called after the trigger has finished loading. | ||
* @return the popped return data | ||
* @see ReturnHandlerStack#push(ReturnHandler) | ||
*/ | ||
public ReturnHandler<?> pop() { | ||
return stack.pop(); | ||
} | ||
|
||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
/** | ||
* 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; | ||
|
||
import org.eclipse.jdt.annotation.Nullable; | ||
import org.skriptlang.skript.lang.script.Script; | ||
|
||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.function.Function; | ||
|
||
public class ReturnableTrigger<T> extends Trigger implements ReturnHandler<T> { | ||
|
||
private final ReturnHandler<T> handler; | ||
|
||
public ReturnableTrigger(ReturnHandler<T> handler, @Nullable Script script, String name, SkriptEvent event, Function<ReturnHandler<T>, List<TriggerItem>> loadItems) { | ||
super(script, name, event, Collections.emptyList()); | ||
this.handler = handler; | ||
setTriggerItems(loadItems.apply(this)); | ||
} | ||
|
||
@Override | ||
public void returnValues(T @Nullable [] values) { | ||
handler.returnValues(values); | ||
} | ||
|
||
@Override | ||
public boolean isSingleReturnValue() { | ||
return handler.isSingleReturnValue(); | ||
} | ||
|
||
@Override | ||
public @Nullable Class<? extends T> returnValueType() { | ||
return handler.returnValueType(); | ||
} | ||
|
||
} |
Oops, something went wrong.