Skip to content

Structure API #4108

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

Merged
merged 140 commits into from
Oct 3, 2022
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
140 commits
Select commit Hold shift + click to select a range
294d196
Start of structure API
TPGamesNL Jun 6, 2021
07621d0
Update files
TPGamesNL Jun 24, 2021
a44ff95
Update part of changes in first commit (broke binary compat with addons)
TPGamesNL Jun 24, 2021
1a543d9
Merge branch 'master' into feature/structure-api
TPGamesNL Jun 24, 2021
4b382e3
Update files
TPGamesNL Jun 24, 2021
4c69efd
Update files
TPGamesNL Jun 24, 2021
cc99131
Update ScriptLoader.java
TPGamesNL Jun 25, 2021
5ea62ce
Merge branch 'master' into feature/structure-api
TPGamesNL Jun 25, 2021
4b7dd08
Merge branch 'master' into feature/structure-api
TPGamesNL Jul 5, 2021
a116c3f
Merge branch 'master' into feature/structure-api
TPGamesNL Jul 14, 2021
3c4d672
Update files
TPGamesNL Jul 14, 2021
f5e6946
Update files
TPGamesNL Jul 19, 2021
3bbbdcb
Merge branch 'master' into feature/structure-api
TPGamesNL Oct 31, 2021
56dbe20
Second part of master merge
TPGamesNL Oct 31, 2021
30c5d07
Improve options (https://github.com/SkriptLang/Skript/issues/4032)
TPGamesNL Nov 1, 2021
bf1f5ed
Merge remote-tracking branch 'upstream/master' into feature/structure…
TPGamesNL Dec 6, 2021
fae9bf7
Fix event pattern to have optional expression parts include dash
TPGamesNL Dec 6, 2021
8e3265b
committee
TPGamesNL Jan 28, 2022
f1980ec
Merge branch 'master' into feature/structure-api
TPGamesNL Jan 28, 2022
45c8239
merge master
TPGamesNL Jan 28, 2022
1a3aa2b
More stuff
TPGamesNL Feb 25, 2022
9e04ff6
Progress Poggies
TPGamesNL Feb 26, 2022
f0e3676
Prefix TODO's so I can filter them more easily
TPGamesNL Feb 26, 2022
665337a
Move Structure to ch.njol.skript.lang.Structure
TPGamesNL Feb 26, 2022
a5607bc
Add docs TODO
TPGamesNL Feb 26, 2022
92c75c5
Merge branch 'master' into feature/structure-api
TPGamesNL Feb 27, 2022
a4969e1
Distribute structure variable functionality over the right methods
TPGamesNL Feb 27, 2022
16c7c70
Make Structure#preload not abstract
TPGamesNL Feb 27, 2022
3c0c72f
Fix missing regexes and other data in ParseResult
TPGamesNL Feb 27, 2022
b0630bb
Fix NPE
TPGamesNL Feb 27, 2022
2b8f24a
Detail
TPGamesNL Feb 27, 2022
7d493df
Rename Skript#normalStructures to Skript#structures
TPGamesNL Feb 28, 2022
0e3ef13
Make Structure#unload not abstract
TPGamesNL Feb 28, 2022
e39d2f3
Bit of cleanup and method rename
TPGamesNL Feb 28, 2022
3fa224f
Fix bug where wrong SyntaxElementInfo was selected
TPGamesNL Feb 28, 2022
bc99c51
Automatically fix event pattern errors due to change
TPGamesNL Feb 28, 2022
c49e842
Detail
TPGamesNL Feb 28, 2022
69185c4
Detail
TPGamesNL Feb 28, 2022
7f1da6a
Details
TPGamesNL Feb 28, 2022
dd3cb0d
Fix function unregistering
TPGamesNL Feb 28, 2022
f08eb8a
Fix command unregistering
TPGamesNL Mar 3, 2022
6bfb9dc
Fix function stuff and apply log handlers
TPGamesNL Mar 3, 2022
6de37c2
Merge branch 'master' into feature/structure-api
APickledWalrus Apr 18, 2022
9dec4f2
First pass for entry validation system
APickledWalrus Apr 20, 2022
95e1052
It builds again
APickledWalrus May 1, 2022
b35efe5
Fix node validation for entry data
APickledWalrus May 1, 2022
0c818b4
Fallback to default value if needed
APickledWalrus May 1, 2022
5779f82
Try new method for EntryContainer value getting
APickledWalrus May 1, 2022
007be59
Internalize commands
APickledWalrus May 1, 2022
edbd7cf
Merge branch 'master' into feature/structure-api
APickledWalrus May 1, 2022
214fb09
Rework structure loading
APickledWalrus May 1, 2022
da4ece6
StructAliases improvements
APickledWalrus May 1, 2022
421dc63
Internalize more of StructOptions
APickledWalrus May 1, 2022
20818b7
Further ScriptLoader improvements
APickledWalrus May 1, 2022
f70611f
Internalize event registration
APickledWalrus May 1, 2022
cebb27d
Improve Structure method name consistency
APickledWalrus May 12, 2022
6f53119
First pass at using new "Script" object
APickledWalrus May 15, 2022
2a9cb19
Merge branch 'master' into feature/structure-api
APickledWalrus May 15, 2022
d5bccbb
Improve calls to obtain Script name
APickledWalrus May 15, 2022
744cb92
Expand and document EntryContainer value methods
APickledWalrus May 15, 2022
82c6d88
Merge branch 'feature/structure-api' of https://github.com/SkriptLang…
APickledWalrus May 15, 2022
e42d212
Improve events in "Script"
APickledWalrus May 22, 2022
65ce080
Make StructureEntryData#canCreateWith abstract
APickledWalrus May 22, 2022
11404de
Add a whole bunch of javadoc
APickledWalrus May 22, 2022
3d4a604
Remove Script "events"
APickledWalrus May 23, 2022
626ce63
Merge branch 'master' into feature/structure-api
APickledWalrus May 29, 2022
af0045c
Re-implement Script events
APickledWalrus Jun 3, 2022
079ec20
First pass at per-script data
APickledWalrus Jun 3, 2022
9fc1186
Rework script aliases to use per-script data
APickledWalrus Jun 3, 2022
69bac14
Rework script options
APickledWalrus Jun 3, 2022
feeec38
Remove "ScriptData" requirement
APickledWalrus Jun 4, 2022
d7458a4
Not sure how this made it in
APickledWalrus Jun 4, 2022
b00fc35
Add doc annotations for structures
APickledWalrus Jun 4, 2022
c4afcb8
Fix major script reloading issues
APickledWalrus Jun 4, 2022
a8582fa
Minor improvements
APickledWalrus Jun 4, 2022
b906734
Fully internalize events
APickledWalrus Jun 5, 2022
cb76bde
Rework Structure loading (again)
APickledWalrus Jun 5, 2022
b2b3ac7
Add Structure#postUnload and rework script loading
APickledWalrus Jun 6, 2022
ea78403
Update other localization files
APickledWalrus Jun 6, 2022
22ed218
Fix silent errors in loadScripts future
APickledWalrus Jun 7, 2022
5bf8493
Improvements and documentation
APickledWalrus Jun 9, 2022
58d70d2
Integrate #4252
APickledWalrus Jun 12, 2022
294e67f
Fix parallel loading CME
APickledWalrus Jun 12, 2022
4a9d3de
Further ScriptLoader reworking and improvements
APickledWalrus Jun 14, 2022
c2c4d91
Additional ScriptLoader "isolation"
APickledWalrus Jun 15, 2022
6ef4ef9
SkriptCommand cleanup
APickledWalrus Jun 15, 2022
6275768
Enforce usage of Set for ScriptLoader methods
APickledWalrus Jun 15, 2022
9c50819
Fixes
APickledWalrus Jun 15, 2022
8d52154
Improve EffScriptFile and handling of enabling/disabling scripts
APickledWalrus Jun 16, 2022
cd8ca27
Merge branch 'master' into feature/structure-api
APickledWalrus Jun 16, 2022
a2d1540
Use canonical form of files where necessary
APickledWalrus Jun 16, 2022
bd2fea8
Final? touches
APickledWalrus Jun 17, 2022
59b08eb
Fix major section entry data issue
APickledWalrus Jun 20, 2022
b89d420
Fix accidental current event clearing
APickledWalrus Jun 20, 2022
7dc1a4a
Add a whole bunch of API stuff
APickledWalrus Jun 22, 2022
312fa46
Fix license violations
APickledWalrus Jun 22, 2022
48e61e3
Merge branch 'master' into feature/structure-api
APickledWalrus Jun 22, 2022
d49a375
Add missing imports
APickledWalrus Jun 22, 2022
12d0ac8
Rework currentEvents
APickledWalrus Jul 12, 2022
eefef61
Merge branch 'master' into feature/structure-api
APickledWalrus Jul 12, 2022
480323c
Re-add fixes removed from branch update
APickledWalrus Jul 12, 2022
ba58dcd
Merge branch 'feature/structure-api' of https://github.com/SkriptLang…
APickledWalrus Jul 12, 2022
ed3487a
Fix messed up EvtItem patterns
APickledWalrus Jul 12, 2022
bd1aa08
Add boolean returns to Structure load methods
APickledWalrus Jul 15, 2022
4379be8
Merge branch 'master' into feature/structure-api
APickledWalrus Jul 18, 2022
a65e871
Improve script loading/unloading process
APickledWalrus Jul 20, 2022
f8187fd
Entry system improvements
APickledWalrus Jul 21, 2022
a2b9073
Fixes and Improvements
APickledWalrus Jul 21, 2022
1153874
Merge branch 'master' into feature/structure-api
APickledWalrus Jul 21, 2022
d7a18b1
No license violations here, Officer
APickledWalrus Jul 21, 2022
88d6ccc
Further enhancements
APickledWalrus Jul 21, 2022
c27d5c7
Add parameter for using default value if parsing failed
APickledWalrus Jul 21, 2022
e556cfb
Still provide EntryContainer as init parameter
APickledWalrus Jul 22, 2022
074c008
Forbid EntryContainer access until after Structure initialization
APickledWalrus Jul 22, 2022
f550b48
Move new API to new package
APickledWalrus Jul 22, 2022
14e3998
Merge branch 'master' into feature/structure-api
APickledWalrus Jul 24, 2022
84a60ff
ParserInstance cleanup
APickledWalrus Jul 24, 2022
c690b21
Stronger Script Data API
APickledWalrus Jul 24, 2022
fa51eab
ScriptData fixes
APickledWalrus Jul 24, 2022
cdbe00d
Final entry data touches
APickledWalrus Jul 24, 2022
c16d5c5
Add 'no scripts found' warning for reload command
APickledWalrus Jul 24, 2022
5f88f8d
Add ParserInstance activity status
APickledWalrus Jul 25, 2022
bb61542
Improve ScriptLoader back-compat
APickledWalrus Jul 25, 2022
532ffab
Fix possible IndexOutOfBounds in EffSuppressWarnings
APickledWalrus Jul 25, 2022
884e961
Merge branch 'master' into feature/structure-api
TPGamesNL Jul 25, 2022
9a52c71
Review-based code enhancements
APickledWalrus Aug 5, 2022
7b8514c
Merge branch 'master' into feature/structure-api
APickledWalrus Aug 5, 2022
e347b35
Merge branch 'master' into feature/structure-api
APickledWalrus Aug 5, 2022
9fb490f
Merge branch 'master' into feature/structure-api
APickledWalrus Aug 21, 2022
a5b5352
Allow ParserInstance Node to be top-level node
APickledWalrus Aug 28, 2022
0343e84
Logging cleanup
APickledWalrus Aug 28, 2022
34a1b8d
Revert ParserInstance Node changes
APickledWalrus Aug 28, 2022
590900a
Merge branch 'master' into feature/structure-api
APickledWalrus Aug 28, 2022
26f19e5
Entry data implementation constructor cleanup
APickledWalrus Sep 1, 2022
9a5a2e4
Generalize entry data system
APickledWalrus Sep 9, 2022
715ad41
Merge branch 'master' into feature/structure-api
APickledWalrus Sep 26, 2022
94120e7
Update "scripts loaded" translation for French
APickledWalrus Sep 26, 2022
ff07211
Minor javadoc update
APickledWalrus Sep 27, 2022
d2d640a
Merge remote-tracking branch 'upstream/master' into feature/structure…
APickledWalrus Oct 3, 2022
c2b11dd
Merge branch 'master' into feature/structure-api
APickledWalrus Oct 3, 2022
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
244 changes: 62 additions & 182 deletions src/main/java/ch/njol/skript/ScriptLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,14 @@
*/
package ch.njol.skript;

import ch.njol.skript.aliases.Aliases;
import ch.njol.skript.aliases.ScriptAliases;
import ch.njol.skript.bukkitutil.CommandReloader;
import ch.njol.skript.classes.ClassInfo;
import ch.njol.skript.command.CommandEvent;
import ch.njol.skript.command.Commands;
import ch.njol.skript.command.ScriptCommand;
import ch.njol.skript.config.Config;
import ch.njol.skript.config.EntryNode;
import ch.njol.skript.config.Node;
import ch.njol.skript.config.SectionNode;
import ch.njol.skript.config.SimpleNode;
import ch.njol.skript.effects.Delay;
import ch.njol.skript.events.bukkit.PreScriptLoadEvent;
import ch.njol.skript.lang.ParseContext;
import ch.njol.skript.lang.Section;
import ch.njol.skript.lang.SelfRegisteringSkriptEvent;
import ch.njol.skript.lang.SkriptEvent;
Expand All @@ -43,26 +36,22 @@
import ch.njol.skript.lang.TriggerItem;
import ch.njol.skript.lang.TriggerSection;
import ch.njol.skript.lang.VariableString;
import ch.njol.skript.lang.function.Function;
import ch.njol.skript.lang.function.FunctionEvent;
import ch.njol.skript.lang.function.Functions;
import ch.njol.skript.lang.parser.ParserInstance;
import ch.njol.skript.localization.Language;
import ch.njol.skript.localization.Message;
import ch.njol.skript.localization.PluralizingArgsMessage;
import ch.njol.skript.log.CountingLogHandler;
import ch.njol.skript.log.LogEntry;
import ch.njol.skript.log.ParseLogHandler;
import ch.njol.skript.log.RetainingLogHandler;
import ch.njol.skript.log.SkriptLogger;
import ch.njol.skript.registrations.Classes;
import ch.njol.skript.registrations.Converters;
import ch.njol.skript.sections.SecLoop;
import ch.njol.skript.structures.PreloadingStructure;
import ch.njol.skript.structures.Structure;
import ch.njol.skript.util.Date;
import ch.njol.skript.util.ExceptionUtils;
import ch.njol.skript.util.Task;
import ch.njol.skript.variables.TypeHints;
import ch.njol.skript.variables.Variables;
import ch.njol.util.Kleenean;
import ch.njol.util.NonNullPair;
import ch.njol.util.OpenCloseable;
Expand All @@ -88,6 +77,7 @@
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
Expand Down Expand Up @@ -520,7 +510,7 @@ public static CompletableFuture<ScriptInfo> loadScripts(List<Config> configs, Op

boolean wasLocal = Language.setUseLocal(false);

Bukkit.getPluginManager().callEvent(new PreScriptLoadEvent(configs));
callPreScriptLoadEvent(configs);

ScriptInfo scriptInfo = new ScriptInfo();

Expand Down Expand Up @@ -566,7 +556,37 @@ public static CompletableFuture<ScriptInfo> loadScripts(List<Config> configs, Op
return scriptInfo;
});
}


private static final WeakHashMap<SectionNode, PreloadingStructure> preloadedStructures = new WeakHashMap<>();

@SuppressWarnings("ConstantConditions")
private static void callPreScriptLoadEvent(List<Config> configs) {
Bukkit.getPluginManager().callEvent(new PreScriptLoadEvent(configs));

// Preloading structure parsing
for (Config config : configs) {
getParser().setCurrentScript(config);
for (Node node : config.getMainNode()) {
if (!(node instanceof SectionNode))
continue;

SectionNode sectionNode = (SectionNode) node;
String key = sectionNode.getKey();
if (key == null)
continue;

if (!SkriptParser.validateLine(key))
continue;

PreloadingStructure preloadingStructure = PreloadingStructure.parse(key, sectionNode);
if (preloadingStructure != null) {
preloadedStructures.put(sectionNode, preloadingStructure);
}
}
getParser().setCurrentScript(null);
}
}

/**
* Represents data for event which is waiting to be loaded.
*/
Expand All @@ -586,7 +606,7 @@ public ParsedEventData(NonNullPair<SkriptEventInfo<?>, SkriptEvent> info,
this.items = items;
}
}

/**
* Loads one script. Only for internal use, as this doesn't register/update
* event handlers.
Expand All @@ -600,11 +620,11 @@ private static ScriptInfo loadScript(@Nullable Config config) {
}

// When something is parsed, it goes there to be loaded later
List<ScriptCommand> commands = new ArrayList<>();
List<ParsedEventData> events = new ArrayList<>();

// Track what is loaded
ScriptInfo scriptInfo = new ScriptInfo();
getParser().setScriptInfo(scriptInfo);
scriptInfo.files = 1; // Loading one script

try {
Expand All @@ -625,121 +645,23 @@ private static ScriptInfo loadScript(@Nullable Config config) {
String event = node.getKey();
if (event == null)
continue;

if (event.equalsIgnoreCase("aliases")) {
node.convertToEntries(0, "=");

// Initialize and load script aliases
ScriptAliases aliases = Aliases.createScriptAliases();
Aliases.setScriptAliases(aliases);
aliases.parser.load(node);
continue;
} else if (event.equalsIgnoreCase("options")) {
node.convertToEntries(0);
for (Node n : node) {
if (!(n instanceof EntryNode)) {
Skript.error("invalid line in options");
continue;
}
getParser().getCurrentOptions().put(n.getKey(), ((EntryNode) n).getValue());
}
continue;
} else if (event.equalsIgnoreCase("variables")) {
// TODO allow to make these override existing variables
node.convertToEntries(0, "=");
for (Node n : node) {
if (!(n instanceof EntryNode)) {
Skript.error("Invalid line in variables section");
continue;
}
String name = n.getKey().toLowerCase(Locale.ENGLISH);
if (name.startsWith("{") && name.endsWith("}"))
name = "" + name.substring(1, name.length() - 1);
String var = name;
name = StringUtils.replaceAll(name, "%(.+)?%", m -> {
if (m.group(1).contains("{") || m.group(1).contains("}") || m.group(1).contains("%")) {
Skript.error("'" + var + "' is not a valid name for a default variable");
return null;
}
ClassInfo<?> ci = Classes.getClassInfoFromUserInput("" + m.group(1));
if (ci == null) {
Skript.error("Can't understand the type '" + m.group(1) + "'");
return null;
}
return "<" + ci.getCodeName() + ">";
});
if (name == null) {
continue;
} else if (name.contains("%")) {
Skript.error("Invalid use of percent signs in variable name");
continue;
}
if (Variables.getVariable(name, null, false) != null)
continue;
Object o;
ParseLogHandler log = SkriptLogger.startParseLogHandler();
try {
o = Classes.parseSimple(((EntryNode) n).getValue(), Object.class, ParseContext.SCRIPT);
if (o == null) {
log.printError("Can't understand the value '" + ((EntryNode) n).getValue() + "'");
continue;
}
log.printLog();
} finally {
log.stop();
}
ClassInfo<?> ci = Classes.getSuperClassInfo(o.getClass());
if (ci.getSerializer() == null) {
Skript.error("Can't save '" + ((EntryNode) n).getValue() + "' in a variable");
continue;
} else if (ci.getSerializeAs() != null) {
ClassInfo<?> as = Classes.getExactClassInfo(ci.getSerializeAs());
if (as == null) {
assert false : ci;
continue;
}
o = Converters.convert(o, as.getC());
if (o == null) {
Skript.error("Can't save '" + ((EntryNode) n).getValue() + "' in a variable");
continue;
}
}
Variables.setVariable(name, o, null, false);
}
continue;
}


if (!SkriptParser.validateLine(event))
continue;

if (event.toLowerCase().startsWith("command ")) {

getParser().setCurrentEvent("command", CommandEvent.class);

ScriptCommand c = Commands.loadCommand(node, false);
if (c != null) {
commands.add(c);
scriptInfo.commandNames.add(c.getName()); // For tab completion
scriptInfo.commands++;
}

getParser().deleteCurrentEvent();

continue;
} else if (event.toLowerCase().startsWith("function ")) {

getParser().setCurrentEvent("function", FunctionEvent.class);

Function<?> func = Functions.loadFunction(node);
if (func != null) {
scriptInfo.functions++;
}

getParser().deleteCurrentEvent();


Structure structure = preloadedStructures.get(node);
if (structure != null) {
PreloadingStructure preloadingStructure = (PreloadingStructure) structure;
preloadingStructure.init(node);
} else {
structure = Structure.parse(event, node);
}

if (structure != null) {
getParser().getLoadedStructures().add(structure);
continue;
}

if (Skript.logVeryHigh() && !Skript.debug())
Skript.info("loading trigger '" + event + "'");

Expand Down Expand Up @@ -775,7 +697,7 @@ private static ScriptInfo loadScript(@Nullable Config config) {
Skript.info("loaded " + scriptInfo.triggers + " trigger" + (scriptInfo.triggers == 1 ? "" : "s")+ " and " + scriptInfo.commands + " command" + (scriptInfo.commands == 1 ? "" : "s") + " from '" + config.getFileName() + "'");

getParser().setCurrentScript(null);
Aliases.setScriptAliases(null); // These are per-script
getParser().getLoadedStructures().clear();
}
} catch (Exception e) {
//noinspection ThrowableNotThrown
Expand All @@ -793,12 +715,7 @@ private static ScriptInfo loadScript(@Nullable Config config) {
if (file != null)
unloadScript_(file);
}

// Now, enable everything!
for (ScriptCommand command : commands) {
Commands.registerCommand(command);
}


for (ParsedEventData event : events) {
getParser().setCurrentEvent("" + event.info.getFirst().getName().toLowerCase(Locale.ENGLISH), event.info.getFirst().events);
getParser().setCurrentSkriptEvent(event.info.getSecond());
Expand Down Expand Up @@ -931,66 +848,21 @@ public static Config loadStructure(File f) {
@Nullable
public static Config loadStructure(InputStream source, String name) {
try {
Config config = new Config(
return new Config(
source,
name,
Skript.getInstance().getDataFolder().toPath().resolve(Skript.SCRIPTSFOLDER).resolve(name).toFile(),
true,
false,
":"
);
return loadStructure(config);
} catch (IOException e) {
Skript.error("Could not load " + name + ": " + ExceptionUtils.toString(e));
}

return null;
}

/**
* Loads structure of given script, currently only for functions. Must be called before
* actually loading that script.
* @param config Config object for the script.
*/
@Nullable
public static Config loadStructure(Config config) {
try {
for (Node cnode : config.getMainNode()) {
if (!(cnode instanceof SectionNode)) {
// Don't spit error yet, we are only pre-parsing...
continue;
}

SectionNode node = ((SectionNode) cnode);
String event = node.getKey();
if (event == null)
continue;

if (!SkriptParser.validateLine(event))
continue;

if (event.toLowerCase().startsWith("function ")) {

getParser().setCurrentEvent("function", FunctionEvent.class);

Functions.loadSignature(config.getFileName(), node);

getParser().deleteCurrentEvent();
}
}

getParser().setCurrentScript(null);
SkriptLogger.setNode(null);
return config;
} catch (Exception e) {
Skript.exception(e, "Could not load " + config.getFileName());
} finally {
SkriptLogger.setNode(null);
}
return null; // Oops something went wrong
}



/*
* Script unloading methods
*/
Expand Down Expand Up @@ -1405,5 +1277,13 @@ public static boolean isCurrentEvent(Class<? extends Event>... events) {
public static Class<? extends Event>[] getCurrentEvents() {
return getParser().getCurrentEvents();
}

/**
* This method has no functionality, it just returns its input.
*/
@Deprecated
public static Config loadStructure(Config config) {
return config;
}

}
Loading