diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 0619f6fcd..000000000 --- a/build.gradle +++ /dev/null @@ -1,33 +0,0 @@ -plugins { - id "java" - id "application" -} - -mainClassName = "io.github.syst3ms.skriptparser.Parser" - -sourceCompatibility = 1.11 - -repositories { - mavenCentral() -} - -test { - useJUnitPlatform() -} - -dependencies { - implementation "org.jetbrains:annotations:15.0" - implementation group: "com.google.code.findbugs", name: "jsr305", version: "3.0.2" - testRuntimeOnly "org.junit.vintage:junit-vintage-engine:5.4.1" - testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.4.1" - testImplementation "junit:junit:4.12" - testImplementation "org.junit.jupiter:junit-jupiter-api:5.4.1" -} - -jar { - manifest { - attributes("Main-Class": mainClassName, - "Implementation-Title": "skript-parser", - "Implementation-Version": "alpha") - } -} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 000000000..bd7af4f51 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,64 @@ +plugins { + id("java") + id("maven-publish") +} +group = "com.github.SkriptDev" +version = "1.0.1" + +repositories { + mavenCentral() +} + +dependencies { + implementation("org.jetbrains:annotations:15.0") + implementation("com.google.code.findbugs:jsr305:3.0.2") + testRuntimeOnly("org.junit.vintage:junit-vintage-engine:5.4.1") + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.4.1") + implementation ("com.google.code.gson:gson:2.13.2") + testImplementation("junit:junit:4.12") + testImplementation("org.junit.jupiter:junit-jupiter-api:5.4.1") +} + +tasks { + compileJava { + options.release = 25 + options.compilerArgs.add("-Xlint:unchecked") + options.compilerArgs.add("-Xlint:deprecation") + } + register("sourcesJar", Jar::class) { + archiveClassifier.set("sources") + from(sourceSets.main.get().allSource) + } + javadoc { + title = "Skript-Parser API - " + project.version + options.overview = "src/main/javadoc/overview.html" + options.encoding = Charsets.UTF_8.name() + exclude( + "com/github/skriptdev/skript/plugin/elements", + "com/github/skriptdev/skript/plugin/command" + ) + (options as StandardJavadocDocletOptions).links( + "https://javadoc.io/doc/org.jetbrains/annotations/latest/", + "https://skriptdev.github.io/docs/skript-parser/latest/" + ) + (options as StandardJavadocDocletOptions).tags = listOf( + "attr", // Example: replace "attr" with your unknown tag name + "todo:X" // Example of explicitly excluding the @todo tag + ) + (options as StandardJavadocDocletOptions).addBooleanOption("Xdoclint:none", true) + } + java { + withSourcesJar() + } + publishing { + publications { + create("maven") { + from(components["java"]) + group = "com.github.SkriptDev" + version = project.version as String + artifactId = "skript-parser" + } + } + } +} + diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ac72c34e8..bad7c2462 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/jitpack.yml b/jitpack.yml new file mode 100644 index 000000000..e5b4a7680 --- /dev/null +++ b/jitpack.yml @@ -0,0 +1,5 @@ +before_install: + - source "$HOME/.sdkman/bin/sdkman-init.sh" + - sdk update + - sdk install java 25-open + - sdk use java 25-open diff --git a/src/main/java/io/github/syst3ms/skriptparser/Parser.java b/src/main/java/io/github/syst3ms/skriptparser/Parser.java index b3b3d9c05..7604df229 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/Parser.java +++ b/src/main/java/io/github/syst3ms/skriptparser/Parser.java @@ -77,7 +77,7 @@ public static void init(String[] mainPackages, String[] subPackages, String[] pr mainPackages[mainPackages.length - 1] = "io.github.syst3ms.skriptparser"; List sub = new ArrayList<>(); sub.addAll(Arrays.asList(subPackages)); - sub.addAll(Arrays.asList("expressions", "effects", "event", "lang", "sections", "tags")); + sub.addAll(Arrays.asList("expressions", "effects", "event", "lang", "sections", "structures", "tags")); subPackages = sub.toArray(new String[0]); try { for (String mainPackage : mainPackages) { diff --git a/src/main/java/io/github/syst3ms/skriptparser/Skript.java b/src/main/java/io/github/syst3ms/skriptparser/Skript.java index b6c8ce1c1..f0ed8a2fa 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/Skript.java +++ b/src/main/java/io/github/syst3ms/skriptparser/Skript.java @@ -1,23 +1,14 @@ package io.github.syst3ms.skriptparser; -import io.github.syst3ms.skriptparser.event.AtTimeContext; -import io.github.syst3ms.skriptparser.event.EvtAtTime; -import io.github.syst3ms.skriptparser.event.EvtPeriodical; -import io.github.syst3ms.skriptparser.event.EvtScriptLoad; -import io.github.syst3ms.skriptparser.event.EvtWhen; -import io.github.syst3ms.skriptparser.event.PeriodicalContext; -import io.github.syst3ms.skriptparser.event.ScriptLoadContext; -import io.github.syst3ms.skriptparser.event.WhenContext; -import io.github.syst3ms.skriptparser.lang.SkriptEvent; -import io.github.syst3ms.skriptparser.lang.Statement; import io.github.syst3ms.skriptparser.lang.Trigger; +import io.github.syst3ms.skriptparser.lang.TriggerMap; +import io.github.syst3ms.skriptparser.lang.event.StartOnLoadEvent; import io.github.syst3ms.skriptparser.registration.SkriptAddon; -import io.github.syst3ms.skriptparser.util.DurationUtils; -import io.github.syst3ms.skriptparser.util.ThreadUtils; -import io.github.syst3ms.skriptparser.util.Time; +import io.github.syst3ms.skriptparser.registration.SkriptRegistration; +import io.github.syst3ms.skriptparser.structures.functions.StructFunction; +import org.jetbrains.annotations.Nullable; -import java.time.Duration; -import java.util.ArrayList; +import java.util.Comparator; import java.util.List; /** @@ -27,54 +18,31 @@ public class Skript extends SkriptAddon { private final String[] mainArgs; - private final List mainTriggers = new ArrayList<>(); - private final List periodicalTriggers = new ArrayList<>(); - private final List whenTriggers = new ArrayList<>(); - private final List atTimeTriggers = new ArrayList<>(); - public Skript(String[] mainArgs) { + super("Skript-Parser"); this.mainArgs = mainArgs; } @Override - public void handleTrigger(Trigger trigger) { - SkriptEvent event = trigger.getEvent(); - - if (!canHandleEvent(event)) - return; - - if (event instanceof EvtScriptLoad) { - mainTriggers.add(trigger); - } else if (event instanceof EvtPeriodical) { - periodicalTriggers.add(trigger); - } else if (event instanceof EvtWhen) { - whenTriggers.add(trigger); - } else if (event instanceof EvtAtTime) { - atTimeTriggers.add(trigger); + public void finishedLoading(@Nullable String scriptName) { + List triggers; + if (scriptName == null) { + triggers = TriggerMap.getAllTriggers(); + } else { + triggers = TriggerMap.getTriggersByScript(scriptName).values().stream().flatMap(List::stream).toList(); } + triggers.stream().sorted(Comparator.comparing(trigger -> trigger.getEvent().getLoadingPriority())).forEach(trigger -> { + if (trigger.getEvent() instanceof StartOnLoadEvent event) { + event.onInitialLoad(trigger); + } else if (trigger.getEvent() instanceof StructFunction func) { + func.register(trigger); + } + }); } @Override - public void finishedLoading() { - for (Trigger trigger : mainTriggers) { - Statement.runAll(trigger, new ScriptLoadContext(mainArgs)); - } - for (Trigger trigger : periodicalTriggers) { - var ctx = new PeriodicalContext(); - var dur = ((EvtPeriodical) trigger.getEvent()).getDuration().getSingle().orElseThrow(AssertionError::new); - ThreadUtils.runPeriodically(() -> Statement.runAll(trigger, ctx), dur); - } - for (Trigger trigger : whenTriggers) { - var ctx = new WhenContext(); - ThreadUtils.runPeriodically(() -> Statement.runAll(trigger, ctx), Duration.ofMillis(DurationUtils.TICK)); - } - for (Trigger trigger : atTimeTriggers) { - var ctx = new AtTimeContext(); - var time = ((EvtAtTime) trigger.getEvent()).getTime().getSingle().orElseThrow(AssertionError::new); - var initialDelay = (Time.now().getTime().isAfter(time.getTime()) - ? Time.now().difference(Time.LATEST).plus(time.difference(Time.MIDNIGHT)) - : Time.now().difference(time)); - ThreadUtils.runPeriodically(() -> Statement.runAll(trigger, ctx), initialDelay, Duration.ofDays(1)); - } + public SkriptRegistration getSkriptRegistration() { + return Parser.getMainRegistration(); } + } diff --git a/src/main/java/io/github/syst3ms/skriptparser/config/Config.java b/src/main/java/io/github/syst3ms/skriptparser/config/Config.java new file mode 100644 index 000000000..3360d0461 --- /dev/null +++ b/src/main/java/io/github/syst3ms/skriptparser/config/Config.java @@ -0,0 +1,191 @@ +package io.github.syst3ms.skriptparser.config; + +import io.github.syst3ms.skriptparser.file.FileElement; +import io.github.syst3ms.skriptparser.file.FileParser; +import io.github.syst3ms.skriptparser.file.FileSection; +import io.github.syst3ms.skriptparser.lang.entries.OptionLoader; +import io.github.syst3ms.skriptparser.log.SkriptLogger; +import io.github.syst3ms.skriptparser.types.Type; +import io.github.syst3ms.skriptparser.types.TypeManager; +import io.github.syst3ms.skriptparser.util.FileUtils; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.function.Function; + +public class Config { + + @SuppressWarnings("FieldCanBeLocal") + private final SkriptLogger logger; + private final List fileElements; + + public Config(Path path, String resourceToCopy, SkriptLogger logger) { + this.logger = logger; + File file = path.toFile(); + if (!file.exists()) { + file.getParentFile().mkdirs(); + try { + InputStream resourceAsStream = Config.class.getResourceAsStream(resourceToCopy); + if (resourceAsStream == null) { + throw new IllegalArgumentException("Resource not found: " + resourceToCopy); + } + Files.copy(resourceAsStream, file.toPath(), StandardCopyOption.REPLACE_EXISTING); + } catch (IOException e) { + throw new RuntimeException("Failed to copy resource to config file", e); + } + } + + List strings; + try { + strings = FileUtils.readAllLines(path); + } catch (IOException e) { + throw new RuntimeException(e); + } + + this.fileElements = FileParser.parseFileLines(path.toString(), strings, 0, 1, logger); + logger.debug("Loaded config file at " + path + " with " + fileElements.size() + " lines"); + } + + public @Nullable ConfigSection getConfigSection(String name) { + for (FileElement fileElement : this.fileElements) { + if (fileElement instanceof FileSection sec && sec.getLineContent().split(OptionLoader.OPTION_SPLIT_PATTERN)[0].equals(name)) { + return new ConfigSection(name, sec); + } + } + return null; + } + + public @Nullable String getString(String key) { + return getConfigValue(key, String.class); + } + + public int getInt(String key) { + Integer configValue = getConfigValue(key, Integer.class); + return configValue != null ? configValue : -1; + } + + public boolean getBoolean(String key) { + Boolean configValue = getConfigValue(key, Boolean.class); + return configValue != null ? configValue : false; + } + + @SuppressWarnings("unchecked") + public @Nullable T getConfigValue(String key, Class classType) { + for (FileElement fileElement : this.fileElements) { + if (fileElement instanceof FileSection sec) { + String s = sec.getLineContent().split(OptionLoader.OPTION_SPLIT_PATTERN)[0]; + ConfigSection configSection = new ConfigSection(s,sec); + T value = configSection.getConfigValue(key, classType); + if (value != null) + return value; + } else { + String[] split = fileElement.getLineContent().split(OptionLoader.OPTION_SPLIT_PATTERN); + if (split.length < 2) { + return null; + } + + String content = split[1]; + if (classType.equals(String.class)) + return (T) content; + + Optional> type = TypeManager.getByClassExact(classType); + if (type.isEmpty()) { + return null; + } + + Optional> parser = type.get().getLiteralParser(); + return parser.map(stringFunction -> stringFunction.apply(content)).orElse(null); + + } + } + return null; + } + + public SkriptLogger getLogger() { + return this.logger; + } + + public static class ConfigSection { + private final String name; + private final FileSection fileSection; + + public ConfigSection(String name, FileSection fileSection) { + this.name = name; + this.fileSection = fileSection; + } + + public @NotNull String getName() { + return this.name; + } + + public @Nullable ConfigSection getSection(String name) { + for (FileElement element : this.fileSection.getElements()) { + if (element instanceof FileSection sec && sec.getLineContent().split(OptionLoader.OPTION_SPLIT_PATTERN)[0].equals(name)) { + return new ConfigSection(name, sec); + } + } + return null; + } + + public @NotNull List getSections() { + List sections = new ArrayList<>(); + for (FileElement element : this.fileSection.getElements()) { + if (element instanceof FileSection sec) { + String s = sec.getLineContent().split(OptionLoader.OPTION_SPLIT_PATTERN)[0]; + sections.add(new ConfigSection(s, sec)); + } + } + + return sections; + } + + public @Nullable String getString(String key) { + return getConfigValue(key, String.class); + } + + public int getInt(String key) { + Integer configValue = getConfigValue(key, Integer.class); + return configValue != null ? configValue : -1; + } + + public boolean getBoolean(String key) { + Boolean configValue = getConfigValue(key, Boolean.class); + return configValue != null ? configValue : false; + } + + + @SuppressWarnings("unchecked") + public @Nullable T getConfigValue(String key, Class classType) { + Optional value = this.fileSection.get(key); + if (value.isEmpty()) { + return null; + } + String[] split = value.get().getLineContent().split(OptionLoader.OPTION_SPLIT_PATTERN); + if (split.length < 2) { + return null; + } + + String content = split[1]; + if (classType.equals(String.class)) + return (T) content; + + Optional> type = TypeManager.getByClassExact(classType); + if (type.isEmpty()) { + return null; + } + + Optional> parser = type.get().getLiteralParser(); + return parser.map(stringFunction -> stringFunction.apply(content)).orElse(null); + } + } + +} diff --git a/src/main/java/io/github/syst3ms/skriptparser/docs/Documentation.java b/src/main/java/io/github/syst3ms/skriptparser/docs/Documentation.java new file mode 100644 index 000000000..d703da210 --- /dev/null +++ b/src/main/java/io/github/syst3ms/skriptparser/docs/Documentation.java @@ -0,0 +1,75 @@ +package io.github.syst3ms.skriptparser.docs; + +/** + * Represents the documentation for a syntax element + */ +public class Documentation { + + private boolean noDoc = false; + private boolean experimental = false; + private String name; + private String[] description = new String[0]; + private String usage; + private String[] examples = new String[0]; + private String since; + + public Documentation() { + } + + public String getName() { + return this.name; + } + + public String[] getDescription() { + return this.description; + } + + public String getUsage() { + return this.usage; + } + + public String[] getExamples() { + return this.examples; + } + + public String getSince() { + return this.since; + } + + public void setName(String name) { + this.name = name; + } + + public void noDoc() { + this.noDoc = true; + } + + public boolean isNoDoc() { + return this.noDoc; + } + + public void experimental() { + this.experimental = true; + } + + public boolean isExperimental() { + return this.experimental; + } + + public void setDescription(String[] description) { + this.description = description; + } + + public void setUsage(String usage) { + this.usage = usage; + } + + public void setExamples(String[] examples) { + this.examples = examples; + } + + public void setSince(String since) { + this.since = since; + } + +} diff --git a/src/main/java/io/github/syst3ms/skriptparser/effects/EffAsk.java b/src/main/java/io/github/syst3ms/skriptparser/effects/EffAsk.java index 7a68cdae9..2e1090122 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/effects/EffAsk.java +++ b/src/main/java/io/github/syst3ms/skriptparser/effects/EffAsk.java @@ -23,10 +23,11 @@ public class EffAsk extends Effect { static { - Parser.getMainRegistration().addEffect( - EffAsk.class, - "(ask [for] [input]|input) %string%" - ); + // We don't need this +// Parser.getMainRegistration().addEffect( +// EffAsk.class, +// "(ask [for] [input]|input) %string%" +// ); } private Expression message; diff --git a/src/main/java/io/github/syst3ms/skriptparser/effects/EffChange.java b/src/main/java/io/github/syst3ms/skriptparser/effects/EffChange.java index b58353db8..7a366d96f 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/effects/EffChange.java +++ b/src/main/java/io/github/syst3ms/skriptparser/effects/EffChange.java @@ -118,7 +118,7 @@ public void execute(TriggerContext ctx) { changed.change(ctx, mode, new Object[0]); } else { var values = changeWith.getValues(ctx); - if (values.length == 0) + if (values == null || values.length == 0) return; changed.change(ctx, mode, values); } diff --git a/src/main/java/io/github/syst3ms/skriptparser/effects/EffContinue.java b/src/main/java/io/github/syst3ms/skriptparser/effects/EffContinue.java index bec6ef3f0..b206896bd 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/effects/EffContinue.java +++ b/src/main/java/io/github/syst3ms/skriptparser/effects/EffContinue.java @@ -11,7 +11,6 @@ import io.github.syst3ms.skriptparser.log.ErrorType; import io.github.syst3ms.skriptparser.parsing.ParseContext; -import java.math.BigInteger; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @@ -19,10 +18,10 @@ /** * Skips the current looped value and continues to the next one in the list, if it exists. * + * @author Mwexim * @name Continue * @pattern continue [%*integer% loop[s]] * @since ALPHA - * @author Mwexim */ public class EffContinue extends Effect { static { @@ -33,19 +32,19 @@ public class EffContinue extends Effect { ); } - private Expression position; + private Expression position; private List sections; @SuppressWarnings("unchecked") @Override public boolean init(Expression[] expressions, int matchedPattern, ParseContext parseContext) { if (expressions.length == 1) - position = (Expression) expressions[0]; + position = (Expression) expressions[0]; sections = parseContext.getParserState().getCurrentSections().stream() - .filter(sec -> sec instanceof Continuable) - .map(sec -> (Continuable) sec) - .collect(Collectors.toList()); + .filter(sec -> sec instanceof Continuable) + .map(sec -> (Continuable) sec) + .collect(Collectors.toList()); if (sections.size() == 0) { parseContext.getLogger().error("You cannot use the 'continue'-effect here", ErrorType.SEMANTIC_ERROR); return false; @@ -59,12 +58,12 @@ public void execute(TriggerContext ctx) { } @Override - public Optional walk(TriggerContext ctx) { + public Optional walk(TriggerContext ctx) { // Indices start at 1 int pos = position != null ? position.getSingle(ctx) - .filter(val -> val.compareTo(BigInteger.ZERO) > 0 && val.compareTo(BigInteger.valueOf(sections.size())) <= 0) - .map(val -> val.intValue() - 1) - .orElse(-1) : 0; + .filter(val -> val.compareTo(0) > 0 && val.compareTo(Integer.valueOf(sections.size())) <= 0) + .map(val -> val.intValue() - 1) + .orElse(-1) : 0; if (pos == -1) return Optional.empty(); @@ -76,11 +75,11 @@ public Optional walk(TriggerContext ctx) { if (sections.get(pos) instanceof ArgumentSection) { ((ArgumentSection) sections.get(0)).step(this); } - return sections.get(pos).getContinued(ctx); + return sections.get(pos).getContinued(ctx); } @Override public String toString(TriggerContext ctx, boolean debug) { return "continue"; } -} \ No newline at end of file +} diff --git a/src/main/java/io/github/syst3ms/skriptparser/effects/EffEscape.java b/src/main/java/io/github/syst3ms/skriptparser/effects/EffEscape.java index e258ef8aa..853744e5a 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/effects/EffEscape.java +++ b/src/main/java/io/github/syst3ms/skriptparser/effects/EffEscape.java @@ -9,7 +9,6 @@ import io.github.syst3ms.skriptparser.lang.control.SelfReferencing; import io.github.syst3ms.skriptparser.parsing.ParseContext; -import java.math.BigInteger; import java.util.Optional; /** @@ -17,10 +16,10 @@ * Note that lines that have more indentation than this one are not considered in the amount. * Nevertheless, lines that have less indentation will be considered. * + * @author Mwexim * @name Escape * @pattern escape %integer% [(level[s]|line[s])] * @since ALPHA - * @author Mwexim */ public class EffEscape extends Effect { static { @@ -30,12 +29,12 @@ public class EffEscape extends Effect { ); } - private Expression amount; + private Expression amount; @SuppressWarnings("unchecked") @Override public boolean init(Expression[] expressions, int matchedPattern, ParseContext parseContext) { - amount = (Expression) expressions[0]; + amount = (Expression) expressions[0]; return true; } @@ -58,20 +57,21 @@ public Optional walk(TriggerContext ctx) { ((Finishing) current.get()).finish(); } current = current.flatMap(val -> val instanceof SelfReferencing - ? ((SelfReferencing) val).getActualNext() - : val.getNext()); + ? ((SelfReferencing) val).getActualNext() + : val.getNext()); // Because otherwise SelfReferencing sections will first reference to themselves if (current.filter(val -> val instanceof Finishing).isEmpty()) am--; } return current.flatMap(val -> val instanceof SelfReferencing - ? ((SelfReferencing) val).getActualNext() - : val.getNext()); + ? ((SelfReferencing) val).getActualNext() + : val.getNext()); } @Override public String toString(TriggerContext ctx, boolean debug) { return "escape " + amount.toString(ctx, debug) + " lines"; } + } diff --git a/src/main/java/io/github/syst3ms/skriptparser/effects/EffExit.java b/src/main/java/io/github/syst3ms/skriptparser/effects/EffExit.java index b486b888a..999529ab8 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/effects/EffExit.java +++ b/src/main/java/io/github/syst3ms/skriptparser/effects/EffExit.java @@ -14,7 +14,6 @@ import io.github.syst3ms.skriptparser.sections.SecLoop; import io.github.syst3ms.skriptparser.sections.SecWhile; -import java.math.BigInteger; import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -25,22 +24,22 @@ * than the total amount of nested sections, the trigger will stop. * Note that stopping loops also stops while-loops. * + * @author Mwexim * @name Exit - * @pattern (exit|stop) [[the] trigger] - * @pattern (exit|stop) [a|the [current]|this] (section|loop|condition[al]) - * @pattern (exit|stop) %*integer% (section|loop|condition[al])[s] - * @pattern (exit|stop) (every|all [[of] the]) (section|loop|condition[al])s + * @pattern (exit | stop) [[the] trigger] + * @pattern (exit | stop) [a|the [current]|this] (section|loop|condition[al]) + * @pattern (exit | stop) %*integer% (section|loop|condition[al])[s] + * @pattern (exit | stop) (every|all [[of] the]) (section|loop|condition[al])s * @since ALPHA - * @author Mwexim */ public class EffExit extends Effect { static { Parser.getMainRegistration().addEffect( - EffExit.class, - "(exit|stop) [[the] trigger]", - "(exit|stop) [a|the [current]|this] (0:section|1:loop|2:condition[al])", - "(exit|stop) %*integer% (0:section|1:loop|2:condition[al])[s]", - "(exit|stop) (every|all [[of] the]) (0:section|1:loop|2:condition[al])[s]" + EffExit.class, + "(exit|stop) [[the] trigger]", + "(exit|stop) [a|the [current]|this] (0:section|1:loop|2:condition[al])", + "(exit|stop) %*integer% (0:section|1:loop|2:condition[al])[s]", + "(exit|stop) (every|all [[of] the]) (0:section|1:loop|2:condition[al])[s]" ); } @@ -49,7 +48,7 @@ public class EffExit extends Effect { private final List currentSections = new ArrayList<>(); private int pattern; private int mark; - private Literal amount; + private Literal amount; @SuppressWarnings("unchecked") @Override @@ -58,7 +57,7 @@ public boolean init(Expression[] expressions, int matchedPattern, ParseContex pattern = matchedPattern; mark = parseContext.getNumericMark(); if (pattern == 2) - amount = (Literal) expressions[0]; + amount = (Literal) expressions[0]; return true; } @@ -78,7 +77,7 @@ public Optional walk(TriggerContext ctx) { return escapeSections(1, this); case 2: return amount.getSingle() - .flatMap(sec -> escapeSections(sec.intValue(), this)); + .flatMap(sec -> escapeSections(sec.intValue(), this)); case 3: // The current trigger is also a part of the current sections! return escapeSections(currentSections.size() - 1, this); @@ -116,8 +115,8 @@ private Optional escapeSections(int amount, Statement start) { stm = statement.get(); // 0 = all, 1 = only loops, 2 = only conditionals if (mark == 0 - || mark == 1 && (stm instanceof SecLoop || stm instanceof SecWhile) - || mark == 2 && stm instanceof SecConditional) { + || mark == 1 && (stm instanceof SecLoop || stm instanceof SecWhile) + || mark == 2 && stm instanceof SecConditional) { if (stm instanceof Finishing) ((Finishing) stm).finish(); amount--; @@ -128,7 +127,8 @@ private Optional escapeSections(int amount, Statement start) { } return stm instanceof SelfReferencing - ? ((SelfReferencing) stm).getActualNext() - : (Optional) stm.getNext(); + ? ((SelfReferencing) stm).getActualNext() + : (Optional) stm.getNext(); } + } diff --git a/src/main/java/io/github/syst3ms/skriptparser/effects/EffPrint.java b/src/main/java/io/github/syst3ms/skriptparser/effects/EffPrint.java index 43f20816f..ec060fe71 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/effects/EffPrint.java +++ b/src/main/java/io/github/syst3ms/skriptparser/effects/EffPrint.java @@ -17,10 +17,11 @@ */ public class EffPrint extends Effect { static { - Parser.getMainRegistration().addEffect( - EffPrint.class, - "print %strings% [to [the] console]" - ); + // We don't really need this +// Parser.getMainRegistration().addEffect( +// EffPrint.class, +// "print %strings% [to [the] console]" +// ); } private Expression expression; diff --git a/src/main/java/io/github/syst3ms/skriptparser/effects/EffReturn.java b/src/main/java/io/github/syst3ms/skriptparser/effects/EffReturn.java index 624f27a1d..cd8632415 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/effects/EffReturn.java +++ b/src/main/java/io/github/syst3ms/skriptparser/effects/EffReturn.java @@ -9,6 +9,8 @@ import io.github.syst3ms.skriptparser.log.ErrorType; import io.github.syst3ms.skriptparser.parsing.ParseContext; import io.github.syst3ms.skriptparser.parsing.SkriptParserException; +import io.github.syst3ms.skriptparser.structures.functions.Function; +import io.github.syst3ms.skriptparser.structures.functions.FunctionContext; import io.github.syst3ms.skriptparser.types.TypeManager; import io.github.syst3ms.skriptparser.types.conversions.Converters; import io.github.syst3ms.skriptparser.util.StringUtils; @@ -31,6 +33,7 @@ public class EffReturn extends Effect { "return %objects%" ); } + private boolean isInFunction; private ReturnSection section; private Expression returned; @@ -39,6 +42,14 @@ public class EffReturn extends Effect { public boolean init(Expression[] expressions, int matchedPattern, ParseContext parseContext) { returned = expressions[0]; var logger = parseContext.getLogger(); + Optional> optionalContext = parseContext.getParserState().getCurrentContexts().stream().findFirst(); + if (optionalContext.isPresent()) { + Class currentContext = optionalContext.get(); + if (currentContext.equals(FunctionContext.class)) { + isInFunction = true; + return true; + } + } var sec = Expression.getLinkedSection(parseContext.getParserState(), ReturnSection.class); if (sec.isEmpty()) { logger.error("Couldn't find a section matching this return statement", ErrorType.SEMANTIC_ERROR); @@ -67,18 +78,29 @@ public boolean init(Expression[] expressions, int matchedPattern, ParseContex if (!section.getReturnType().isAssignableFrom(returned.getReturnType())) { // The value is convertible but not in the trivial way returned = returned.convertExpression(section.getReturnType()) - .orElseThrow(() -> new SkriptParserException("Return value should be convertible at this stage")); + .orElseThrow(() -> new SkriptParserException("Return value should be convertible at this stage")); } return true; } @Override protected void execute(TriggerContext ctx) { + /*if (isInFunction) { + FunctionContext functionContext = (FunctionContext) ctx; + Function function = functionContext.getOwningFunction(); + function.setReturnValue(returned.getValues(ctx)); + } else throw new UnsupportedOperationException();*/ throw new UnsupportedOperationException(); } @Override public Optional walk(TriggerContext ctx) { + if (isInFunction) { + FunctionContext functionContext = (FunctionContext) ctx; + Function function = functionContext.getOwningFunction(); + function.setReturnValue(returned.getValues(ctx)); + return Optional.empty(); // stop the trigger + } section.setReturned(returned.getValues(ctx)); section.step(this); return Optional.of(section); diff --git a/src/main/java/io/github/syst3ms/skriptparser/effects/EffShutdown.java b/src/main/java/io/github/syst3ms/skriptparser/effects/EffShutdown.java index 5fcb8411c..78edafdbe 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/effects/EffShutdown.java +++ b/src/main/java/io/github/syst3ms/skriptparser/effects/EffShutdown.java @@ -18,10 +18,11 @@ */ public class EffShutdown extends Effect { static { - Parser.getMainRegistration().addEffect( - EffShutdown.class, - "shut[ ]down [[the] [current] session]" - ); + // We shouldn't be using this on a Hytale Server +// Parser.getMainRegistration().addEffect( +// EffShutdown.class, +// "shut[ ]down [[the] [current] session]" +// ); } @Override diff --git a/src/main/java/io/github/syst3ms/skriptparser/effects/EffWait.java b/src/main/java/io/github/syst3ms/skriptparser/effects/EffWait.java index bd78a7936..04e3f0aac 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/effects/EffWait.java +++ b/src/main/java/io/github/syst3ms/skriptparser/effects/EffWait.java @@ -31,11 +31,12 @@ */ public class EffWait extends Effect { static { - Parser.getMainRegistration().addEffect( - EffWait.class, - "(wait|halt) [for] %duration%", - "(wait|halt) (0:until|1:while) %=boolean% [for %*duration%]" - ); + // Handle this in HySkript (different scheduler) +// Parser.getMainRegistration().addEffect( +// EffWait.class, +// "(wait|halt) [for] %duration%", +// "(wait|halt) (0:until|1:while) %=boolean% [for %*duration%]" +// ); } private Expression duration; diff --git a/src/main/java/io/github/syst3ms/skriptparser/event/EvtAtTime.java b/src/main/java/io/github/syst3ms/skriptparser/event/EvtAtTime.java index 6b1d94d72..de552586a 100644 --- a/src/main/java/io/github/syst3ms/skriptparser/event/EvtAtTime.java +++ b/src/main/java/io/github/syst3ms/skriptparser/event/EvtAtTime.java @@ -3,11 +3,17 @@ import io.github.syst3ms.skriptparser.Parser; import io.github.syst3ms.skriptparser.lang.Expression; import io.github.syst3ms.skriptparser.lang.Literal; -import io.github.syst3ms.skriptparser.lang.SkriptEvent; +import io.github.syst3ms.skriptparser.lang.Statement; +import io.github.syst3ms.skriptparser.lang.Trigger; +import io.github.syst3ms.skriptparser.lang.event.SkriptEvent; import io.github.syst3ms.skriptparser.lang.TriggerContext; +import io.github.syst3ms.skriptparser.lang.event.StartOnLoadEvent; import io.github.syst3ms.skriptparser.parsing.ParseContext; +import io.github.syst3ms.skriptparser.util.ThreadUtils; import io.github.syst3ms.skriptparser.util.Time; +import java.time.Duration; + /** * This event will trigger each day at a given time. * Note that this may have some delay. The event certainly isn't accurate to the millisecond. @@ -18,7 +24,7 @@ * @since ALPHA * @author Mwexim */ -public class EvtAtTime extends SkriptEvent { +public class EvtAtTime extends SkriptEvent implements StartOnLoadEvent { static { Parser.getMainRegistration() .newEvent(EvtAtTime.class, "*at %*time%") @@ -48,4 +54,15 @@ public String toString(TriggerContext ctx, boolean debug) { public Literal