Skip to content

Commit

Permalink
Merge branch 'dev/feature' into feature/registry-classes
Browse files Browse the repository at this point in the history
  • Loading branch information
Moderocky authored May 21, 2024
2 parents b539c0b + ef3d360 commit a612b28
Show file tree
Hide file tree
Showing 13 changed files with 1,179 additions and 179 deletions.
346 changes: 180 additions & 166 deletions src/main/java/ch/njol/skript/Skript.java

Large diffs are not rendered by default.

81 changes: 81 additions & 0 deletions src/main/java/ch/njol/skript/conditions/CondIsUsingFeature.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/**
* 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.conditions;

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.Condition;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.util.Kleenean;
import org.bukkit.event.Event;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.skriptlang.skript.lang.experiment.Experimented;

@SuppressWarnings("NotNullFieldNotInitialized")
@Name("Is Using Experimental Feature")
@Description("Checks whether a script is using an experimental feature by name.")
@Examples({"the script is using \"example feature\"",
"on load:",
"\tif the script is using \"example feature\":",
"\t\tbroadcast \"You're using an experimental feature!\""})
@Since("INSERT VERSION")
public class CondIsUsingFeature extends Condition {

static {
Skript.registerCondition(CondIsUsingFeature.class,
"[the] [current] script is using %strings%",
"[the] [current] script is(n't| not) using %strings%");
}

private Expression<String> names;
private Experimented snapshot;

@SuppressWarnings("null")
@Override
public boolean init(Expression<?>[] expressions, int pattern, Kleenean delayed, ParseResult result) {
//noinspection unchecked
this.names = (Expression<String>) expressions[0];
this.setNegated(pattern == 1);
this.snapshot = this.getParser().experimentSnapshot();
return true;
}

@Override
public boolean check(Event event) {
String[] array = names.getArray(event);
if (array.length == 0)
return true;
boolean isUsing = true;
for (@NotNull String object : array) {
isUsing &= snapshot.hasExperiment(object);
}
return isUsing ^ this.isNegated();
}

@Override
public String toString(@Nullable Event event, boolean debug) {
return "the current script " + (isNegated() ? "isn't" : "is") + " using " + names.toString(event, debug);
}

}
83 changes: 70 additions & 13 deletions src/main/java/ch/njol/skript/lang/parser/ParserInstance.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package ch.njol.skript.lang.parser;

import ch.njol.skript.ScriptLoader;
import ch.njol.skript.Skript;
import ch.njol.skript.SkriptAPIException;
import ch.njol.skript.config.Config;
import ch.njol.skript.config.Node;
Expand All @@ -32,7 +33,11 @@
import ch.njol.util.coll.CollectionUtils;
import org.bukkit.event.Event;
import org.eclipse.jdt.annotation.Nullable;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.skriptlang.skript.lang.experiment.Experiment;
import org.skriptlang.skript.lang.experiment.ExperimentSet;
import org.skriptlang.skript.lang.experiment.Experimented;
import org.skriptlang.skript.lang.script.Script;
import org.skriptlang.skript.lang.script.ScriptEvent;
import org.skriptlang.skript.lang.structure.Structure;
Expand All @@ -44,8 +49,8 @@
import java.util.Map;
import java.util.function.Function;

public final class ParserInstance {
public final class ParserInstance implements Experimented {

private static final ThreadLocal<ParserInstance> PARSER_INSTANCES = ThreadLocal.withInitial(ParserInstance::new);

/**
Expand Down Expand Up @@ -394,11 +399,63 @@ public Node getNode() {
public void setIndentation(String indentation) {
this.indentation = indentation;
}

public String getIndentation() {
return indentation;
}

// Experiments API

@Override
public boolean hasExperiment(String featureName) {
return Skript.experiments().isUsing(this.getCurrentScript(), featureName);
}


@Override
public boolean hasExperiment(Experiment experiment) {
return Skript.experiments().isUsing(this.getCurrentScript(), experiment);
}

/**
* Marks this as using an experimental feature.
* @param experiment The feature to register.
*/
@ApiStatus.Internal
public void addExperiment(Experiment experiment) {
Script script = this.getCurrentScript();
ExperimentSet set = script.getData(ExperimentSet.class, () -> new ExperimentSet());
set.add(experiment);
}

/**
* Marks this as no longer using an experimental feature (e.g. during de-registration or reload).
* @param experiment The feature to unregister.
*/
@ApiStatus.Internal
public void removeExperiment(Experiment experiment) {
Script script = this.getCurrentScript();
@Nullable ExperimentSet set = script.getData(ExperimentSet.class);
if (set == null)
return;
set.remove(experiment);
}

/**
* A snapshot of the experiments this script is currently known to be using.
* This is safe to retain during runtime (e.g. to defer a check) but will
* not see changes, such as if a script subsequently 'uses' another experiment.
*
* @return A snapshot of the current experiment flags in use
*/
public Experimented experimentSnapshot() {
Script script = this.getCurrentScript();
@Nullable ExperimentSet set = script.getData(ExperimentSet.class);
if (set == null)
return new ExperimentSet();
return new ExperimentSet(set);
}

// ParserInstance Data API

/**
Expand All @@ -409,13 +466,13 @@ public String getIndentation() {
* {@code ParserInstance.registerData(MyData.class, MyData::new)}
*/
public static abstract class Data {

private final ParserInstance parserInstance;

public Data(ParserInstance parserInstance) {
this.parserInstance = parserInstance;
}

protected final ParserInstance getParser() {
return parserInstance;
}
Expand All @@ -427,13 +484,13 @@ protected final ParserInstance getParser() {
public void onCurrentScriptChange(@Nullable Config currentScript) { }

public void onCurrentEventsChange(Class<? extends Event> @Nullable [] currentEvents) { }

}

private static final Map<Class<? extends Data>, Function<ParserInstance, ? extends Data>> dataRegister = new HashMap<>();
// Should be Map<Class<? extends Data>, ? extends Data>, but that caused issues (with generics) in #getData(Class)
private final Map<Class<? extends Data>, Data> dataMap = new HashMap<>();

/**
* Registers a data class to all {@link ParserInstance}s.
*
Expand All @@ -444,11 +501,11 @@ public static <T extends Data> void registerData(Class<T> dataClass,
Function<ParserInstance, T> dataFunction) {
dataRegister.put(dataClass, dataFunction);
}

public static boolean isRegistered(Class<? extends Data> dataClass) {
return dataRegister.containsKey(dataClass);
}

/**
* @return the data object for the given class from this {@link ParserInstance},
* or null (after {@code false} has been asserted) if the given data class isn't registered.
Expand All @@ -465,7 +522,7 @@ public <T extends Data> T getData(Class<T> dataClass) {
assert false;
return null;
}

private List<? extends Data> getDataInstances() {
// List<? extends Data> gave errors, so using this instead
List<Data> dataList = new ArrayList<>();
Expand Down Expand Up @@ -536,5 +593,5 @@ public void setCurrentScript(@Nullable Config currentScript) {
if (script != null)
setActive(script);
}

}
79 changes: 79 additions & 0 deletions src/main/java/ch/njol/skript/registrations/Feature.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/**
* 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.registrations;

import ch.njol.skript.SkriptAddon;
import ch.njol.skript.patterns.PatternCompiler;
import ch.njol.skript.patterns.SkriptPattern;
import org.skriptlang.skript.lang.experiment.Experiment;
import org.skriptlang.skript.lang.experiment.ExperimentRegistry;
import org.skriptlang.skript.lang.experiment.LifeCycle;

/**
* Experimental feature toggles as provided by Skript itself.
*/
public enum Feature implements Experiment {
;

private final String codeName;
private final LifeCycle phase;
private final SkriptPattern compiledPattern;

Feature(String codeName, LifeCycle phase, String... patterns) {
this.codeName = codeName;
this.phase = phase;
switch (patterns.length) {
case 0:
this.compiledPattern = PatternCompiler.compile(codeName);
break;
case 1:
this.compiledPattern = PatternCompiler.compile(patterns[0]);
break;
default:
this.compiledPattern = PatternCompiler.compile('(' + String.join("|", patterns) + ')');
break;
}
}

Feature(String codeName, LifeCycle phase) {
this(codeName, phase, codeName);
}

public static void registerAll(SkriptAddon addon, ExperimentRegistry manager) {
for (Feature value : values()) {
manager.register(addon, value);
}
}

@Override
public String codeName() {
return codeName;
}

@Override
public LifeCycle phase() {
return phase;
}

@Override
public SkriptPattern pattern() {
return compiledPattern;
}

}
Loading

0 comments on commit a612b28

Please sign in to comment.