mirror of
https://github.com/PlaceholderAPI/Javascript-Expansion.git
synced 2025-05-23 10:39:04 +00:00
Shaded Nashorn + QuickJS suppourt (Vshnv) (#42)
Co-authored-by: Vaishnav Anil <vaishnavanil7th@gmail.com>
This commit is contained in:
parent
d5a7ed81a0
commit
cef33ba930
3
.gitignore
vendored
3
.gitignore
vendored
@ -11,6 +11,8 @@ local.properties
|
|||||||
.settings/
|
.settings/
|
||||||
.loadpath
|
.loadpath
|
||||||
.recommenders
|
.recommenders
|
||||||
|
.gradle/
|
||||||
|
target/
|
||||||
|
|
||||||
# External tool builders
|
# External tool builders
|
||||||
.externalToolBuilders/
|
.externalToolBuilders/
|
||||||
@ -118,3 +120,4 @@ dist/
|
|||||||
nbdist/
|
nbdist/
|
||||||
.nb-gradle/
|
.nb-gradle/
|
||||||
nbactions.xml
|
nbactions.xml
|
||||||
|
/.gradle/
|
||||||
|
17
build.gradle
Normal file
17
build.gradle
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
plugins {
|
||||||
|
id 'java'
|
||||||
|
id 'maven-publish'
|
||||||
|
}
|
||||||
|
allprojects {
|
||||||
|
group = 'com.extendedclip.papi.expansion.javascript'
|
||||||
|
version = '1.6.1'
|
||||||
|
description = 'PAPI-Expansion-Javascript'
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
|
||||||
|
}
|
17
evaluator-api/build.gradle
Normal file
17
evaluator-api/build.gradle
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
plugins {
|
||||||
|
id 'java'
|
||||||
|
}
|
||||||
|
|
||||||
|
group 'com.extendedclip.papi.expansion.javascript'
|
||||||
|
version '1.6.1'
|
||||||
|
|
||||||
|
sourceCompatibility = 1.8
|
||||||
|
targetCompatibility = 1.8
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
testImplementation group: 'junit', name: 'junit', version: '4.12'
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.evaluator;
|
||||||
|
|
||||||
|
public final class EvaluatorException extends RuntimeException {
|
||||||
|
public EvaluatorException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.evaluator;
|
||||||
|
|
||||||
|
import javax.script.ScriptException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface ScriptEvaluator {
|
||||||
|
Object execute(final Map<String, Object> additionalBindings, final String script) throws EvaluatorException, ScriptException;
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.evaluator;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface ScriptEvaluatorFactory {
|
||||||
|
|
||||||
|
ScriptEvaluator create(final Map<String, Object> bindings);
|
||||||
|
|
||||||
|
default void cleanBinaries() {}
|
||||||
|
}
|
24
evaluator/build.gradle
Normal file
24
evaluator/build.gradle
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
plugins {
|
||||||
|
id 'java'
|
||||||
|
id 'com.github.johnrengelman.shadow' version '7.0.0'
|
||||||
|
}
|
||||||
|
|
||||||
|
group 'com.extendedclip.papi.expansion.javascript'
|
||||||
|
version '1.6.1'
|
||||||
|
|
||||||
|
sourceCompatibility = 1.8
|
||||||
|
targetCompatibility = 1.8
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
maven {
|
||||||
|
url = "https://repo.vshnv.tech/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compileOnly project(':evaluator-api')
|
||||||
|
compileOnly fileTree("libs")
|
||||||
|
implementation 'io.github.slimjar:slimjar:1.2.3'
|
||||||
|
testImplementation group: 'junit', name: 'junit', version: '4.12'
|
||||||
|
}
|
BIN
evaluator/libs/asm-9.2.jar
Normal file
BIN
evaluator/libs/asm-9.2.jar
Normal file
Binary file not shown.
BIN
evaluator/libs/asm-commons-9.2.jar
Normal file
BIN
evaluator/libs/asm-commons-9.2.jar
Normal file
Binary file not shown.
BIN
evaluator/libs/asm-util-9.2.jar
Normal file
BIN
evaluator/libs/asm-util-9.2.jar
Normal file
Binary file not shown.
BIN
evaluator/libs/nashorn-core-15.1.jar
Normal file
BIN
evaluator/libs/nashorn-core-15.1.jar
Normal file
Binary file not shown.
BIN
evaluator/libs/quickjs-1.0.0.jar
Normal file
BIN
evaluator/libs/quickjs-1.0.0.jar
Normal file
Binary file not shown.
@ -0,0 +1,7 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.evaluator;
|
||||||
|
|
||||||
|
public final class LibraryInjectionException extends RuntimeException {
|
||||||
|
public LibraryInjectionException(final Throwable cause) {
|
||||||
|
super(String.format("Java Version: %s", System.getProperty("java.version")),cause);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.evaluator;
|
||||||
|
|
||||||
|
import com.koushikdutta.quack.QuackContext;
|
||||||
|
import org.openjdk.nashorn.api.scripting.NashornScriptEngine;
|
||||||
|
import org.openjdk.nashorn.api.scripting.NashornScriptEngineFactory;
|
||||||
|
|
||||||
|
import javax.script.Bindings;
|
||||||
|
import javax.script.ScriptContext;
|
||||||
|
import javax.script.ScriptEngine;
|
||||||
|
import javax.script.ScriptException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public final class NashornScriptEvaluator implements ScriptEvaluator {
|
||||||
|
private final NashornScriptEngineFactory scriptEngineFactory;
|
||||||
|
private final Map<String, Object> bindings;
|
||||||
|
|
||||||
|
public NashornScriptEvaluator(final NashornScriptEngineFactory scriptEngineFactory, final Map<String, Object> bindings) {
|
||||||
|
this.scriptEngineFactory = scriptEngineFactory;
|
||||||
|
this.bindings = bindings;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object execute(final Map<String, Object> additionalBindings, final String script) throws EvaluatorException, ScriptException {
|
||||||
|
final ScriptEngine engine = scriptEngineFactory.getScriptEngine();
|
||||||
|
final Bindings globalBindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);
|
||||||
|
globalBindings.putAll(bindings);
|
||||||
|
globalBindings.putAll(additionalBindings);
|
||||||
|
engine.setBindings(globalBindings, ScriptContext.GLOBAL_SCOPE);
|
||||||
|
return engine.eval(script);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.evaluator;
|
||||||
|
|
||||||
|
import com.extendedclip.papi.expansion.javascript.evaluator.util.InjectionUtil;
|
||||||
|
import org.openjdk.nashorn.api.scripting.NashornScriptEngineFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public final class NashornScriptEvaluatorFactory implements ScriptEvaluatorFactory {
|
||||||
|
public static final Collection<String> LIBRARIES = Arrays.asList(
|
||||||
|
"nashorn-core-15.1.isolated-jar",
|
||||||
|
"asm-commons-9.2.isolated-jar",
|
||||||
|
"asm-util-9.2.isolated-jar",
|
||||||
|
"asm-9.2.isolated-jar"
|
||||||
|
);
|
||||||
|
private final NashornScriptEngineFactory engineFactory;
|
||||||
|
|
||||||
|
private NashornScriptEvaluatorFactory(final NashornScriptEngineFactory engineFactory) {
|
||||||
|
this.engineFactory = engineFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ScriptEvaluator create(final Map<String, Object> bindings) {
|
||||||
|
return new NashornScriptEvaluator(engineFactory, bindings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ScriptEvaluatorFactory create() throws URISyntaxException, ReflectiveOperationException, NoSuchAlgorithmException, IOException {
|
||||||
|
InjectionUtil.inject(LIBRARIES);
|
||||||
|
return new NashornScriptEvaluatorFactory(new NashornScriptEngineFactory());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.evaluator;
|
||||||
|
|
||||||
|
import com.koushikdutta.quack.*;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public final class QuickJsScriptEvaluator implements ScriptEvaluator {
|
||||||
|
private final Map<String, Object> bindings;
|
||||||
|
|
||||||
|
public QuickJsScriptEvaluator(final Map<String, Object> bindings) {
|
||||||
|
this.bindings = bindings;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object execute(final Map<String, Object> additionalBindings, final String script) throws EvaluatorException {
|
||||||
|
try (final QuackContext context = QuackContext.create(true)) {
|
||||||
|
for (Map.Entry<String, Object> entry : bindings.entrySet()) {
|
||||||
|
bind(context, entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
for (Map.Entry<String, Object> entry : additionalBindings.entrySet()) {
|
||||||
|
bind(context, entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
return context.evaluate(script);
|
||||||
|
} catch (final Exception exception) {
|
||||||
|
throw new EvaluatorException("Failed to evaluate requested script.", exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void bind(final QuackContext ctx, final String key, final Object value) {
|
||||||
|
ctx.getGlobalObject().set(key, coerce(ctx, value));
|
||||||
|
}
|
||||||
|
private Object coerce(final QuackContext ctx, final Object value) {
|
||||||
|
if (value.getClass().isArray()) {
|
||||||
|
final Object[] array = (Object[]) value;
|
||||||
|
final JavaScriptObject jsObj = ctx.evaluateForJavaScriptObject("[]");
|
||||||
|
for (int i = 0; i < array.length; i++) {
|
||||||
|
jsObj.set(i, coerce(ctx, array[i]));
|
||||||
|
}
|
||||||
|
return jsObj;
|
||||||
|
}
|
||||||
|
return ctx.coerceJavaToJavaScript(value);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.evaluator;
|
||||||
|
|
||||||
|
import com.extendedclip.papi.expansion.javascript.evaluator.util.InjectionUtil;
|
||||||
|
import io.github.slimjar.injector.loader.Injectable;
|
||||||
|
import io.github.slimjar.injector.loader.InjectableFactory;
|
||||||
|
|
||||||
|
import javax.script.ScriptException;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.*;
|
||||||
|
import java.nio.channels.Channels;
|
||||||
|
import java.nio.channels.FileChannel;
|
||||||
|
import java.nio.channels.ReadableByteChannel;
|
||||||
|
import java.nio.file.StandardOpenOption;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.jar.JarFile;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
|
||||||
|
public final class QuickJsScriptEvaluatorFactory implements ScriptEvaluatorFactory {
|
||||||
|
private static final String TEST_EVALUATION_SCRIPT = "10 * 10";
|
||||||
|
private static final int TEST_EVALUATION_RESULT = 100;
|
||||||
|
|
||||||
|
public static final Collection<String> LIBRARIES = Collections.singletonList("quickjs-1.0.0.isolated-jar");
|
||||||
|
private static final URL SELF_JAR_URL = QuickJsScriptEvaluatorFactory.class.getProtectionDomain()
|
||||||
|
.getCodeSource().getLocation();
|
||||||
|
|
||||||
|
private QuickJsScriptEvaluatorFactory() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ScriptEvaluator create(final Map<String, Object> bindings) {
|
||||||
|
return new QuickJsScriptEvaluator(bindings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ScriptEvaluatorFactory createWithFallback(final Function<Void, ScriptEvaluatorFactory> evaluatorFactoryProducer) {
|
||||||
|
try {
|
||||||
|
final ScriptEvaluatorFactory evaluatorFactory = create();
|
||||||
|
attemptBasicEvaluation(evaluatorFactory);
|
||||||
|
return evaluatorFactory;
|
||||||
|
} catch (final Exception exception) {
|
||||||
|
return evaluatorFactoryProducer.apply(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void attemptBasicEvaluation(final ScriptEvaluatorFactory evaluatorFactory) throws ScriptException {
|
||||||
|
final Object result = evaluatorFactory.create(Collections.emptyMap()).execute(Collections.emptyMap(), "10 * 10");
|
||||||
|
if (result instanceof Integer && ((Integer) result).intValue() == TEST_EVALUATION_RESULT) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new RuntimeException("Failed basic evaluation test");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ScriptEvaluatorFactory create() throws URISyntaxException, ReflectiveOperationException, NoSuchAlgorithmException, IOException {
|
||||||
|
InjectionUtil.inject(LIBRARIES);
|
||||||
|
return new QuickJsScriptEvaluatorFactory();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,87 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.evaluator.util;
|
||||||
|
|
||||||
|
import com.extendedclip.papi.expansion.javascript.evaluator.LibraryInjectionException;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.evaluator.QuickJsScriptEvaluatorFactory;
|
||||||
|
import io.github.slimjar.injector.loader.Injectable;
|
||||||
|
import io.github.slimjar.injector.loader.InjectableFactory;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.channels.Channels;
|
||||||
|
import java.nio.channels.FileChannel;
|
||||||
|
import java.nio.channels.ReadableByteChannel;
|
||||||
|
import java.nio.file.StandardOpenOption;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.jar.JarFile;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
|
||||||
|
public final class InjectionUtil {
|
||||||
|
private static final URL SELF_JAR_URL = QuickJsScriptEvaluatorFactory.class.getProtectionDomain()
|
||||||
|
.getCodeSource().getLocation();
|
||||||
|
|
||||||
|
private InjectionUtil() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean tryInject(final Collection<String> libraries) {
|
||||||
|
try {
|
||||||
|
inject(libraries);
|
||||||
|
return true;
|
||||||
|
} catch (final Exception exception) {
|
||||||
|
// Fail silently
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void inject(final Collection<String> libraries) throws LibraryInjectionException {
|
||||||
|
try {
|
||||||
|
final Collection<URL> libraryURLs = extractLibraries(libraries);
|
||||||
|
final ClassLoader bukkitClassLoader = InjectionUtil.class.getClassLoader().getParent();
|
||||||
|
final Injectable injectable = InjectableFactory.create(bukkitClassLoader);
|
||||||
|
for (final URL libraryURL : libraryURLs) {
|
||||||
|
injectable.inject(libraryURL);
|
||||||
|
}
|
||||||
|
} catch (final Exception exception) {
|
||||||
|
throw new LibraryInjectionException(exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Collection<URL> extractLibraries(final Collection<String> libraries) throws IOException, URISyntaxException, NoSuchAlgorithmException, ReflectiveOperationException {
|
||||||
|
final Collection<URL> extracted = new ArrayList<>();
|
||||||
|
final File selfFile = new File(SELF_JAR_URL.toURI());
|
||||||
|
final JarFile jarFile = new JarFile(selfFile);
|
||||||
|
for (final String library : libraries) {
|
||||||
|
final File extractedFile = getExtractionFile(library, selfFile);
|
||||||
|
if (extractedFile.exists()) {
|
||||||
|
extracted.add(extractedFile.toURI().toURL());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final ZipEntry entry = jarFile.getEntry(library);
|
||||||
|
if (entry == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
|
extractedFile.getParentFile().mkdirs();
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
|
extractedFile.createNewFile();
|
||||||
|
try (final InputStream stream = jarFile.getInputStream(entry);
|
||||||
|
final ReadableByteChannel inChannel = Channels.newChannel(stream);
|
||||||
|
final FileChannel outChannel = FileChannel.open(extractedFile.toPath(), StandardOpenOption.CREATE, StandardOpenOption.WRITE)) {
|
||||||
|
outChannel.transferFrom(inChannel, 0, entry.getSize());
|
||||||
|
}
|
||||||
|
extracted.add(extractedFile.toURI().toURL());
|
||||||
|
}
|
||||||
|
return extracted;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static File getExtractionFile(final String name, final File selfFile) {
|
||||||
|
return new File(selfFile.getParentFile(), "libraries/" + name.replace("isolated-jar", "jar"));
|
||||||
|
}
|
||||||
|
}
|
57
expansion/build.gradle
Normal file
57
expansion/build.gradle
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
plugins {
|
||||||
|
id 'java'
|
||||||
|
id 'com.github.johnrengelman.shadow' version '7.0.0'
|
||||||
|
id 'com.coditory.manifest' version '0.1.14'
|
||||||
|
}
|
||||||
|
|
||||||
|
group 'com.extendedclip.papi.expansion.javascript'
|
||||||
|
version '1.6.1'
|
||||||
|
archivesBaseName = "Javascript-Expansion"
|
||||||
|
|
||||||
|
sourceCompatibility = 1.8
|
||||||
|
targetCompatibility = 1.8
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
maven {
|
||||||
|
url = "https://repo.vshnv.tech/"
|
||||||
|
}
|
||||||
|
maven {
|
||||||
|
url = 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/'
|
||||||
|
}
|
||||||
|
|
||||||
|
maven {
|
||||||
|
url = 'https://repo.extendedclip.com/content/repositories/placeholderapi/'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation project(':evaluator')
|
||||||
|
implementation project(':evaluator-api')
|
||||||
|
compileOnly 'org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT'
|
||||||
|
compileOnly 'me.clip:placeholderapi:2.10.9'
|
||||||
|
compileOnly 'org.jetbrains:annotations:21.0.1'
|
||||||
|
testImplementation group: 'junit', name: 'junit', version: '4.12'
|
||||||
|
}
|
||||||
|
|
||||||
|
//shadowJar {
|
||||||
|
// dependsOn(project(':evaluator').shadowJar)
|
||||||
|
// doFirst {
|
||||||
|
// copy {
|
||||||
|
// from project(':evaluator').getTasks().getByName("shadowJar").outputs.files.singleFile
|
||||||
|
// into layout.buildDirectory.file("resources/main/")
|
||||||
|
// include('*.jar')
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
shadowJar {
|
||||||
|
doFirst {
|
||||||
|
copy {
|
||||||
|
from project(':evaluator').getProjectDir().toPath().resolve("libs").toFile()
|
||||||
|
into layout.buildDirectory.file("resources/main/")
|
||||||
|
include('*.jar')
|
||||||
|
rename ('(.*).jar', '$1.isolated-jar')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
relocate 'io.github.slimjar', 'com.extendedclip.papi.expansion.javascript.slimjar'
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
package com.extendedclip.papi.expansion.javascript;
|
package com.extendedclip.papi.expansion.javascript;
|
||||||
|
|
||||||
import jdk.nashorn.api.scripting.ScriptObjectMirror;
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.ChatColor;
|
import org.bukkit.ChatColor;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
@ -66,28 +65,6 @@ public class ExpansionUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only support for Nashorn engine!
|
|
||||||
protected static Object jsonToJava(Object jsObj) {
|
|
||||||
if (jsObj instanceof ScriptObjectMirror) {
|
|
||||||
ScriptObjectMirror jsObjectMirror = (ScriptObjectMirror) jsObj;
|
|
||||||
if (jsObjectMirror.isArray()) {
|
|
||||||
List<Object> list = new ArrayList<>();
|
|
||||||
for (Map.Entry<String, Object> entry : jsObjectMirror.entrySet()) {
|
|
||||||
list.add(jsonToJava(entry.getValue()));
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
} else {
|
|
||||||
Map<String, Object> map = new HashMap<>();
|
|
||||||
for (Map.Entry<String, Object> entry : jsObjectMirror.entrySet()) {
|
|
||||||
map.put(entry.getKey(), jsonToJava(entry.getValue()));
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return jsObj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static Object ymlToJavaObj(Object obj) {
|
protected static Object ymlToJavaObj(Object obj) {
|
||||||
if (obj instanceof MemorySection) {
|
if (obj instanceof MemorySection) {
|
||||||
MemorySection ymlMem = (MemorySection) obj;
|
MemorySection ymlMem = (MemorySection) obj;
|
@ -0,0 +1,181 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* Javascript-Expansion
|
||||||
|
* Copyright (C) 2020 Ryan McCarthy
|
||||||
|
*
|
||||||
|
* This program 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.
|
||||||
|
*
|
||||||
|
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.extendedclip.papi.expansion.javascript;
|
||||||
|
|
||||||
|
import com.extendedclip.papi.expansion.javascript.cloud.*;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.commands.router.CommandRegistrar;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.config.*;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.evaluator.*;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.script.ConfigurationScriptLoader;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.script.ScriptLoader;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.script.ScriptRegistry;
|
||||||
|
import me.clip.placeholderapi.expansion.Cacheable;
|
||||||
|
import me.clip.placeholderapi.expansion.Configurable;
|
||||||
|
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
public class JavascriptExpansion extends PlaceholderExpansion implements Cacheable, Configurable {
|
||||||
|
public static final String AUTHOR = "clip";
|
||||||
|
public static final String IDENTIFIER = "javascript";
|
||||||
|
public static final String VERSION = JavascriptExpansion.class.getPackage().getImplementationVersion();
|
||||||
|
|
||||||
|
private static final URL SELF_JAR_URL = JavascriptExpansion.class.getProtectionDomain()
|
||||||
|
.getCodeSource().getLocation();
|
||||||
|
|
||||||
|
private final ScriptRegistry registry = new ScriptRegistry();
|
||||||
|
private final GitScriptManager scriptManager = GitScriptManager.createDefault(getPlaceholderAPI());
|
||||||
|
|
||||||
|
private String argumentSeparator = "";
|
||||||
|
private boolean useQuickJS = false;
|
||||||
|
private ScriptLoader loader;
|
||||||
|
private ScriptEvaluatorFactory scriptEvaluatorFactory;
|
||||||
|
private CommandRegistrar commandRegistrar;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public String getAuthor() {
|
||||||
|
return AUTHOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public String getIdentifier() {
|
||||||
|
return IDENTIFIER;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public String getVersion() {
|
||||||
|
return VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean register() {
|
||||||
|
argumentSeparator = getString("argument_split", ",");
|
||||||
|
if (argumentSeparator.equals("_")) {
|
||||||
|
argumentSeparator = ",";
|
||||||
|
ExpansionUtils.warnLog("Underscore character will not be allowed for splitting. Defaulting to ',' for this", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
useQuickJS = (boolean) get("use_quick_js", false);
|
||||||
|
|
||||||
|
if (useQuickJS) {
|
||||||
|
this.scriptEvaluatorFactory = QuickJsScriptEvaluatorFactory.createWithFallback(i -> {
|
||||||
|
getPlaceholderAPI().getLogger().log(Level.WARNING, "Failed to use QuickJS Engine. Falling back to Nashorn");
|
||||||
|
return createNashornEvaluatorFactory();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.scriptEvaluatorFactory = createNashornEvaluatorFactory();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
final HeaderWriter headerWriter = HeaderWriter.fromJar(SELF_JAR_URL);
|
||||||
|
|
||||||
|
final File dataFolder = getPlaceholderAPI().getDataFolder();
|
||||||
|
final Path scriptDirectoryPath = dataFolder.toPath().resolve("javascripts");
|
||||||
|
try {
|
||||||
|
Files.createDirectories(scriptDirectoryPath);
|
||||||
|
} catch (IOException exception) {
|
||||||
|
ExpansionUtils.errorLog("Failed to create script folder.", exception);
|
||||||
|
}
|
||||||
|
final File configFile = new File(dataFolder, "javascript_placeholders.yml");
|
||||||
|
final ScriptConfiguration scriptConfiguration = new YamlScriptConfiguration(configFile, headerWriter, scriptDirectoryPath);
|
||||||
|
final JavascriptPlaceholderFactory placeholderFactory = new SimpleJavascriptPlaceholderFactory(this, scriptEvaluatorFactory);
|
||||||
|
this.loader = new ConfigurationScriptLoader(registry, scriptConfiguration, placeholderFactory);
|
||||||
|
try {
|
||||||
|
this.commandRegistrar = new CommandRegistrar(scriptManager, placeholderFactory, scriptConfiguration, registry, loader);
|
||||||
|
} catch (ReflectiveOperationException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
final int amountLoaded = loader.reload();
|
||||||
|
ExpansionUtils.infoLog(amountLoaded + " script" + ExpansionUtils.plural(amountLoaded) + " loaded!");
|
||||||
|
} catch (final IOException exception) {
|
||||||
|
ExpansionUtils.errorLog("Failed to load scripts", exception);
|
||||||
|
}
|
||||||
|
if ((boolean) get("github_script_downloads", false)) {
|
||||||
|
scriptManager.getIndexProvider().refreshIndex(scriptIndex -> {
|
||||||
|
long gitIndexed = scriptIndex.getCount();
|
||||||
|
ExpansionUtils.infoLog("Indexed " + gitIndexed + " gitscript" + ExpansionUtils.plural(Math.toIntExact(gitIndexed)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
commandRegistrar.register();
|
||||||
|
return super.register();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
commandRegistrar.unregister();
|
||||||
|
loader.clear();
|
||||||
|
scriptEvaluatorFactory.cleanBinaries();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String onRequest(OfflinePlayer player, @NotNull String identifier) {
|
||||||
|
if (player == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
for (JavascriptPlaceholder script : registry.getAllPlaceholders()) {
|
||||||
|
if (identifier.startsWith(script.getIdentifier() + "_")) {
|
||||||
|
identifier = identifier.replaceFirst(script.getIdentifier() + "_", "");
|
||||||
|
|
||||||
|
return !identifier.contains(argumentSeparator) ? script.evaluate(player, identifier) : script.evaluate(player, identifier.split(argumentSeparator));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (identifier.equalsIgnoreCase(script.getIdentifier())) {
|
||||||
|
return script.evaluate(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> getDefaults() {
|
||||||
|
final Map<String, Object> defaults = new HashMap<>();
|
||||||
|
defaults.put("debug", false);
|
||||||
|
defaults.put("argument_split", ",");
|
||||||
|
defaults.put("github_script_downloads", false);
|
||||||
|
defaults.put("use_quick_js", false);
|
||||||
|
return defaults;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ScriptEvaluatorFactory createNashornEvaluatorFactory() {
|
||||||
|
try {
|
||||||
|
return NashornScriptEvaluatorFactory.create();
|
||||||
|
} catch (URISyntaxException | ReflectiveOperationException | NoSuchAlgorithmException | IOException exception) {
|
||||||
|
throw new RuntimeException("Failed to create fallback evaluator: Nashorn" ,exception); // Unrecoverable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,157 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* Javascript-Expansion
|
||||||
|
* Copyright (C) 2020 Ryan McCarthy
|
||||||
|
*
|
||||||
|
* This program 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.
|
||||||
|
*
|
||||||
|
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.extendedclip.papi.expansion.javascript;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import com.extendedclip.papi.expansion.javascript.evaluator.ScriptEvaluator;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.evaluator.ScriptEvaluatorFactory;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.script.ScriptData;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.script.data.PersistableData;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.script.data.YmlPersistableData;
|
||||||
|
import me.clip.placeholderapi.PlaceholderAPI;
|
||||||
|
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||||
|
import org.apache.commons.lang.Validate;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
|
import org.bukkit.configuration.InvalidConfigurationException;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import javax.script.ScriptException;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public final class JavascriptPlaceholder {
|
||||||
|
private final String identifier;
|
||||||
|
private final String script;
|
||||||
|
private final PersistableData persistableData;
|
||||||
|
private final Pattern pattern = Pattern.compile("//.*|/\\*[\\S\\s]*?\\*/|%([^%]+)%");
|
||||||
|
private final ScriptEvaluatorFactory evaluatorFactory;
|
||||||
|
private final JavascriptExpansion expansion;
|
||||||
|
|
||||||
|
public JavascriptPlaceholder(@NotNull final String identifier, @NotNull final String script, @NotNull final ScriptEvaluatorFactory evaluatorFactory, @NotNull final JavascriptExpansion expansion) {
|
||||||
|
final Path dataFilePath = expansion.getPlaceholderAPI().getDataFolder()
|
||||||
|
.toPath()
|
||||||
|
.resolve("javascripts")
|
||||||
|
.resolve("javascript_data")
|
||||||
|
.resolve(identifier + "_data.yml");
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.persistableData = YmlPersistableData.create(identifier, dataFilePath);
|
||||||
|
} catch (final IOException exception) {
|
||||||
|
ExpansionUtils.errorLog("Unable to create placeholder data file", exception);
|
||||||
|
throw new RuntimeException(exception);
|
||||||
|
}
|
||||||
|
this.identifier = identifier;
|
||||||
|
this.script = script;
|
||||||
|
this.evaluatorFactory = evaluatorFactory;
|
||||||
|
this.expansion = expansion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIdentifier() {
|
||||||
|
return identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String evaluate(final OfflinePlayer player, final String... args) {
|
||||||
|
// A checker to deny all placeholders inside comment codes
|
||||||
|
final Matcher matcher = pattern.matcher(script);
|
||||||
|
final StringBuffer buffer = new StringBuffer();
|
||||||
|
while (matcher.find()) {
|
||||||
|
final String matched = matcher.group(0);
|
||||||
|
if (!matched.startsWith("%") || matched.startsWith("/*") || matched.startsWith("//")) continue;
|
||||||
|
matcher.appendReplacement(buffer, PlaceholderAPI.setPlaceholders(player, matched));
|
||||||
|
}
|
||||||
|
matcher.appendTail(buffer);
|
||||||
|
final String parsedScript = buffer.toString();
|
||||||
|
try {
|
||||||
|
final int length;
|
||||||
|
if (args != null) {
|
||||||
|
length = args.length;
|
||||||
|
} else {
|
||||||
|
length = 0;
|
||||||
|
}
|
||||||
|
final String[] arguments = new String[length];
|
||||||
|
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
if (args[i] == null || args[i].isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
arguments[i] = PlaceholderAPI.setBracketPlaceholders(player, args[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Map<String, Object> defaultBindings = prepareDefaultBindings();
|
||||||
|
|
||||||
|
final ScriptEvaluator evaluator = evaluatorFactory.create(defaultBindings);
|
||||||
|
|
||||||
|
final Map<String, Object> additionalBindings = new HashMap<>();
|
||||||
|
additionalBindings.put("args", arguments);
|
||||||
|
if (player != null && player.isOnline()) {
|
||||||
|
additionalBindings.put("BukkitPlayer", player.getPlayer());
|
||||||
|
additionalBindings.put("Player", player.getPlayer());
|
||||||
|
}
|
||||||
|
additionalBindings.put("OfflinePlayer", player);
|
||||||
|
try {
|
||||||
|
Object result = evaluator.execute(additionalBindings, parsedScript);
|
||||||
|
return result != null ? PlaceholderAPI.setBracketPlaceholders(player, result.toString()) : "";
|
||||||
|
} catch (RuntimeException | ScriptException exception) { // todo:: prepare specific exception and catch that instead of all runtime exceptions
|
||||||
|
ExpansionUtils.errorLog("An error occurred while executing the script '" + identifier , exception);
|
||||||
|
}
|
||||||
|
} catch (ArrayIndexOutOfBoundsException ex) {
|
||||||
|
ExpansionUtils.errorLog("Argument out of bound while executing script '" + identifier + "':\n\t" + ex.getMessage(), null);
|
||||||
|
}
|
||||||
|
return "Script error (check console)";
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Object> prepareDefaultBindings() {
|
||||||
|
final Map<String, Object> bindings = new HashMap<>();
|
||||||
|
bindings.put("Data", persistableData.getScriptData());
|
||||||
|
bindings.put("DataVar", persistableData.getScriptData().getData());
|
||||||
|
bindings.put("BukkitServer", Bukkit.getServer());
|
||||||
|
bindings.put("Expansion", expansion);
|
||||||
|
bindings.put("Placeholder", this);
|
||||||
|
bindings.put("PlaceholderAPI", PlaceholderAPI.class);
|
||||||
|
return bindings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getScript() {
|
||||||
|
return script;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScriptData getData() {
|
||||||
|
return persistableData.getScriptData();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void saveData() {
|
||||||
|
persistableData.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersistableData getPersistableData() {
|
||||||
|
return persistableData;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript;
|
||||||
|
|
||||||
|
public interface JavascriptPlaceholderFactory {
|
||||||
|
JavascriptPlaceholder create(final String identifier, final String script);
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript;
|
||||||
|
|
||||||
|
import com.extendedclip.papi.expansion.javascript.evaluator.ScriptEvaluatorFactory;
|
||||||
|
|
||||||
|
public final class SimpleJavascriptPlaceholderFactory implements JavascriptPlaceholderFactory {
|
||||||
|
private final JavascriptExpansion expansion;
|
||||||
|
private final ScriptEvaluatorFactory evaluatorFactory;
|
||||||
|
|
||||||
|
public SimpleJavascriptPlaceholderFactory(final JavascriptExpansion expansion, final ScriptEvaluatorFactory evaluatorFactory) {
|
||||||
|
this.expansion = expansion;
|
||||||
|
this.evaluatorFactory = evaluatorFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JavascriptPlaceholder create(final String identifier, final String script) {
|
||||||
|
return new JavascriptPlaceholder(identifier, script, evaluatorFactory, expansion);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.cloud;
|
||||||
|
|
||||||
|
public interface ActiveStateSetter {
|
||||||
|
void setActive(boolean state);
|
||||||
|
boolean isActive();
|
||||||
|
}
|
@ -20,15 +20,22 @@
|
|||||||
*/
|
*/
|
||||||
package com.extendedclip.papi.expansion.javascript.cloud;
|
package com.extendedclip.papi.expansion.javascript.cloud;
|
||||||
|
|
||||||
public class GithubScript {
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public final class GitScript {
|
||||||
private final String name;
|
private final String name;
|
||||||
private final String version;
|
private final String version;
|
||||||
private final String author;
|
private final String author;
|
||||||
private final String description;
|
private final String description;
|
||||||
private final String url;
|
private final String url;
|
||||||
|
|
||||||
public GithubScript(String name, String version, String author, String description, String url) {
|
public GitScript(
|
||||||
|
@NotNull final String name,
|
||||||
|
@NotNull final String version,
|
||||||
|
@NotNull final String author,
|
||||||
|
@NotNull final String description,
|
||||||
|
@NotNull final String url
|
||||||
|
) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.version = version;
|
this.version = version;
|
||||||
this.author = author;
|
this.author = author;
|
||||||
@ -36,22 +43,27 @@ public class GithubScript {
|
|||||||
this.url = url;
|
this.url = url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
public String getVersion() {
|
public String getVersion() {
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
public String getAuthor() {
|
public String getAuthor() {
|
||||||
return author;
|
return author;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
public String getUrl() {
|
public String getUrl() {
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.cloud;
|
||||||
|
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
|
public final class GitScriptActiveStateSetter implements ActiveStateSetter {
|
||||||
|
private static final String ACTIVE_STATE_KEY = "expansions.javascript.github_script_downloads";
|
||||||
|
private final JavaPlugin plugin;
|
||||||
|
|
||||||
|
public GitScriptActiveStateSetter(final JavaPlugin plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setActive(boolean state) {
|
||||||
|
plugin.getConfig().set(ACTIVE_STATE_KEY, state);
|
||||||
|
plugin.saveConfig();
|
||||||
|
plugin.reloadConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isActive() {
|
||||||
|
return plugin.getConfig().getBoolean(ACTIVE_STATE_KEY, false);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.cloud;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public final class GitScriptIndex implements ScriptIndex {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final Map<String, GitScript> scriptMap;
|
||||||
|
|
||||||
|
public GitScriptIndex(@NotNull final Map<String, GitScript> scriptMap) {
|
||||||
|
this.scriptMap = scriptMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<GitScript> getAllScripts() {
|
||||||
|
return scriptMap.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public Optional<GitScript> getScript(final String name) {
|
||||||
|
return Optional.ofNullable(scriptMap.get(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getCount() {
|
||||||
|
return scriptMap.size();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.cloud;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public final class GitScriptIndexProvider implements ScriptIndexProvider {
|
||||||
|
private static final Gson GSON = new Gson();
|
||||||
|
private static final String INDEX_URL =
|
||||||
|
"https://raw.githubusercontent.com/PlaceholderAPI/" +
|
||||||
|
"Javascript-Expansion/master/scripts/master_list.json";
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final JavaPlugin plugin;
|
||||||
|
|
||||||
|
private ScriptIndex index = null;
|
||||||
|
|
||||||
|
public GitScriptIndexProvider(@NotNull final JavaPlugin plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized Optional<ScriptIndex> getScriptIndex() {
|
||||||
|
return Optional.ofNullable(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refreshIndex(@Nullable Consumer<ScriptIndex> indexConsumer) {
|
||||||
|
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||||
|
try(final Reader indexReader = new InputStreamReader(new URL(INDEX_URL).openStream())) {
|
||||||
|
final List<GitScript> scripts = GSON.fromJson(indexReader, new TypeToken<ArrayList<GitScript>>() {}.getType());
|
||||||
|
final Map<String, GitScript> map = scripts.stream().collect(
|
||||||
|
Collectors.toMap(GitScript::getName, Function.identity())
|
||||||
|
);
|
||||||
|
final GitScriptIndex localIndex = new GitScriptIndex(map);
|
||||||
|
synchronized (this) {
|
||||||
|
index = localIndex;
|
||||||
|
}
|
||||||
|
if (indexConsumer != null) {
|
||||||
|
indexConsumer.accept(localIndex);
|
||||||
|
}
|
||||||
|
} catch (final IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.cloud;
|
||||||
|
|
||||||
|
import com.extendedclip.papi.expansion.javascript.cloud.download.ChanneledScriptDownloader;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.cloud.download.GitScriptPathSelector;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.cloud.download.PathSelector;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.cloud.download.ScriptDownloader;
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
public final class GitScriptManager {
|
||||||
|
private final ActiveStateSetter activeStateSetter;
|
||||||
|
private final GitScriptIndexProvider indexProvider;
|
||||||
|
private final ScriptDownloader scriptDownloader;
|
||||||
|
private final PathSelector downloadPathSelector;
|
||||||
|
|
||||||
|
public GitScriptManager(ActiveStateSetter activeStateSetter, GitScriptIndexProvider indexProvider, ScriptDownloader scriptDownloader, PathSelector downloadPathSelector) {
|
||||||
|
this.activeStateSetter = activeStateSetter;
|
||||||
|
this.indexProvider = indexProvider;
|
||||||
|
this.scriptDownloader = scriptDownloader;
|
||||||
|
this.downloadPathSelector = downloadPathSelector;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ActiveStateSetter getActiveStateSetter() {
|
||||||
|
return activeStateSetter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GitScriptIndexProvider getIndexProvider() {
|
||||||
|
return indexProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScriptDownloader getScriptDownloader() {
|
||||||
|
return scriptDownloader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PathSelector getDownloadPathSelector() {
|
||||||
|
return downloadPathSelector;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GitScriptManager createDefault(final JavaPlugin plugin) {
|
||||||
|
final PathSelector pathSelector = new GitScriptPathSelector(new File(plugin.getDataFolder(), "javascripts"));
|
||||||
|
final ScriptDownloader downloader = new ChanneledScriptDownloader(pathSelector);
|
||||||
|
final GitScriptIndexProvider indexProvider = new GitScriptIndexProvider(plugin);
|
||||||
|
final ActiveStateSetter activeStateSetter = new GitScriptActiveStateSetter(plugin);
|
||||||
|
return new GitScriptManager(activeStateSetter, indexProvider, downloader, pathSelector);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.cloud;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public interface ScriptIndex {
|
||||||
|
Collection<GitScript> getAllScripts();
|
||||||
|
Optional<GitScript> getScript(final String name);
|
||||||
|
long getCount();
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.cloud;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
public interface ScriptIndexProvider {
|
||||||
|
Optional<ScriptIndex> getScriptIndex();
|
||||||
|
void refreshIndex(final Consumer<ScriptIndex> indexConsumer);
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.cloud.download;
|
||||||
|
|
||||||
|
import com.extendedclip.papi.expansion.javascript.cloud.GitScript;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
import java.nio.channels.*;
|
||||||
|
import java.nio.file.*;
|
||||||
|
|
||||||
|
public final class ChanneledScriptDownloader implements ScriptDownloader {
|
||||||
|
private final PathSelector pathSelector;
|
||||||
|
|
||||||
|
public ChanneledScriptDownloader(final PathSelector pathSelector) {
|
||||||
|
this.pathSelector = pathSelector;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Path download(final GitScript script) throws IOException {
|
||||||
|
final URL url = new URL(script.getUrl());
|
||||||
|
final URLConnection urlConnection = url.openConnection();
|
||||||
|
final long length = urlConnection.getContentLength();
|
||||||
|
|
||||||
|
final Path to = pathSelector.select(script.getName());
|
||||||
|
try (ReadableByteChannel fromChannel = Channels.newChannel(urlConnection.getInputStream())) {
|
||||||
|
try (FileChannel toChannel = FileChannel.open(to, StandardOpenOption.WRITE, StandardOpenOption.CREATE)) {
|
||||||
|
toChannel.transferFrom(fromChannel, 0, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.cloud.download;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
public final class GitScriptPathSelector implements PathSelector {
|
||||||
|
private final String expansionPath;
|
||||||
|
|
||||||
|
public GitScriptPathSelector(final File expansionFolder) {
|
||||||
|
this.expansionPath = expansionFolder.getAbsolutePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Path select(final String name) {
|
||||||
|
return Path.of(expansionPath, name + ".js");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.cloud.download;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
public interface PathSelector {
|
||||||
|
Path select(final String name);
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.cloud.download;
|
||||||
|
|
||||||
|
import com.extendedclip.papi.expansion.javascript.cloud.GitScript;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
public interface ScriptDownloader {
|
||||||
|
Path download(final GitScript script) throws IOException;
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.commands;
|
||||||
|
|
||||||
|
import com.extendedclip.papi.expansion.javascript.ExpansionUtils;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.JavascriptPlaceholder;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.script.ScriptRegistry;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.commands.router.ExpansionCommand;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.util.StringUtil;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public final class DebugCommand extends ExpansionCommand {
|
||||||
|
private static final String ARG_LOAD = "loaddata";
|
||||||
|
private static final String ARG_SAVE = "savedata";
|
||||||
|
private static final String NAME = "debug";
|
||||||
|
|
||||||
|
private final ScriptRegistry registry;
|
||||||
|
|
||||||
|
public DebugCommand(final String parentCommandName, final ScriptRegistry registry) {
|
||||||
|
super(parentCommandName, NAME);
|
||||||
|
this.registry = registry;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(final CommandSender sender, final String[] args) {
|
||||||
|
if (args.length < 2) {
|
||||||
|
ExpansionUtils.sendMsg(sender, "&cIncorrect usage! Type '&f/" + getParentCommandName() + "&c' for more help.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JavascriptPlaceholder jsp = registry.getPlaceholder(getIdentifier(args));
|
||||||
|
if (jsp == null) {
|
||||||
|
ExpansionUtils.sendMsg(sender, "&cInvalid javascript identifier! Please re-check your typo");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args[0].equals(ARG_SAVE)) {
|
||||||
|
jsp.saveData();
|
||||||
|
ExpansionUtils.sendMsg(sender, "&aJavascript data '" + args[1] + "' successfully saved");
|
||||||
|
} else if (args[0].equals(ARG_LOAD)) {
|
||||||
|
jsp.getPersistableData().reload();
|
||||||
|
ExpansionUtils.sendMsg(sender, "&aJavascript data '" + args[1] + "' successfully loaded");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull List<String> tabComplete(final CommandSender sender, final String[] args) {
|
||||||
|
if (args.length == 1) {
|
||||||
|
return StringUtil.copyPartialMatches(args[0], Arrays.asList(ARG_SAVE, ARG_LOAD), new ArrayList<>());
|
||||||
|
}
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NotNull String getCommandFormat() {
|
||||||
|
return "debug [savedata/loaddata] [identifier]";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NotNull String getDescription() {
|
||||||
|
return "Test JavaScript code in chat";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIdentifier(final String[] args) {
|
||||||
|
return Arrays.stream(args).skip(1).collect(Collectors.joining(" "));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.commands;
|
||||||
|
|
||||||
|
import com.extendedclip.papi.expansion.javascript.ExpansionUtils;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.cloud.*;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.cloud.download.PathSelector;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.cloud.download.ScriptDownloader;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.commands.router.CommandRouter;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.commands.router.ExpansionCommand;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.util.StringUtil;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public final class GitCommand extends ExpansionCommand {
|
||||||
|
private static final String ARG_REFRESH = "refresh";
|
||||||
|
private static final String ARG_LIST = "list";
|
||||||
|
private static final String ARG_INFO = "info";
|
||||||
|
private static final String ARG_DOWNLOAD = "download";
|
||||||
|
private static final String ARG_ENABLED = "enabled";
|
||||||
|
|
||||||
|
private final ActiveStateSetter activeStateSetter;
|
||||||
|
private final CommandRouter subCommandRouter;
|
||||||
|
|
||||||
|
public GitCommand(final String parentCommandName, final ActiveStateSetter activeStateSetter, final CommandRouter subCommandRouter) {
|
||||||
|
super(parentCommandName, "git");
|
||||||
|
this.activeStateSetter = activeStateSetter;
|
||||||
|
this.subCommandRouter = subCommandRouter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(final CommandSender sender, final String[] args) {
|
||||||
|
if (args.length < 1) {
|
||||||
|
ExpansionUtils.sendMsg(sender, "&cIncorrect usage! Type '&f/" + getParentCommandName() + "&c' for more help.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!activeStateSetter.isActive() && !"enabled".equalsIgnoreCase(args[0])) {
|
||||||
|
ExpansionUtils.sendMsg(sender, "&cThis feature is disabled in the PlaceholderAPI config.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
subCommandRouter.execute(sender, getParentCommandName() + " git", args);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public List<String> tabComplete(final CommandSender sender, final String[] args) {
|
||||||
|
if (args.length == 1) {
|
||||||
|
return StringUtil.copyPartialMatches(args[0], Arrays.asList(ARG_REFRESH, ARG_LIST, ARG_DOWNLOAD, ARG_ENABLED, ARG_INFO), new ArrayList<>());
|
||||||
|
} else if (args.length > 1) {
|
||||||
|
return subCommandRouter.tabComplete(sender, args[0], args);
|
||||||
|
}
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
protected String getCommandFormat() {
|
||||||
|
final String args = String.join("/", Arrays.asList(ARG_REFRESH, ARG_LIST, ARG_DOWNLOAD, ARG_ENABLED, ARG_INFO));
|
||||||
|
return "git [" + args + "] [params]";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
protected String getDescription() {
|
||||||
|
return "Manage github scripts";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,94 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.commands;
|
||||||
|
|
||||||
|
import com.extendedclip.papi.expansion.javascript.ExpansionUtils;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.cloud.*;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.cloud.download.PathSelector;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.cloud.download.ScriptDownloader;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.commands.router.ExpansionCommand;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.commands.router.ExpansionCommandRouter;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.config.ScriptConfiguration;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
import org.bukkit.util.StringUtil;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public final class GitDownloadCommand extends ExpansionCommand {
|
||||||
|
private final GitScriptManager scriptManager;
|
||||||
|
private final ScriptConfiguration configuration;
|
||||||
|
|
||||||
|
public GitDownloadCommand(final GitScriptManager scriptManager, final ScriptConfiguration configuration) {
|
||||||
|
super(ExpansionCommandRouter.COMMAND_NAME + " git", "download");
|
||||||
|
this.scriptManager = scriptManager;
|
||||||
|
this.configuration = configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(final CommandSender sender, final String[] args) {
|
||||||
|
if (args.length < 1) {
|
||||||
|
ExpansionUtils.sendMsg(sender, "&cIncorrect usage! &f/" + getParentCommandName() + " git info [name]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final ScriptIndexProvider indexProvider = scriptManager.getIndexProvider();
|
||||||
|
final GitScript script = indexProvider.getScriptIndex().flatMap(index -> index.getScript(args[0])).orElse(null);
|
||||||
|
|
||||||
|
if (script == null) {
|
||||||
|
ExpansionUtils.sendMsg(sender, "&cThe script &f" + args[0] + " &cdoes not exist!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final PathSelector selector = scriptManager.getDownloadPathSelector();
|
||||||
|
final Path path = selector.select(script.getName());
|
||||||
|
if (Files.exists(path)) {
|
||||||
|
ExpansionUtils.sendMsg(sender, "&cCould not download " + script.getName() + " because a file with the same name already exist in the javascripts folder.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final ScriptDownloader downloader = scriptManager.getScriptDownloader();
|
||||||
|
CompletableFuture.supplyAsync(() -> {
|
||||||
|
ExpansionUtils.sendMsg(sender, "&aDownload started. &eCheck the scripts folder in a moment...");
|
||||||
|
try {
|
||||||
|
return downloader.download(script);
|
||||||
|
} catch (IOException exception) {
|
||||||
|
ExpansionUtils.errorLog("Failed to download expansion!", exception);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}).thenAccept(downloadedPath -> {
|
||||||
|
if (downloadedPath == null) return;
|
||||||
|
ExpansionUtils.sendMsg(sender, "&aDownload complete! " + script.getName());
|
||||||
|
configuration.setPath(script.getName(), downloadedPath.getFileName().toString());
|
||||||
|
configuration.save();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull List<String> tabComplete(CommandSender sender, String[] args) {
|
||||||
|
if (args.length > 0) {
|
||||||
|
final ScriptIndexProvider indexProvider = scriptManager.getIndexProvider();
|
||||||
|
final List<String> scripts = indexProvider.getScriptIndex()
|
||||||
|
.map(ScriptIndex::getAllScripts)
|
||||||
|
.orElse(Collections.emptyList()).stream()
|
||||||
|
.map(GitScript::getName)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
return StringUtil.copyPartialMatches(args[0], scripts, new ArrayList<>());
|
||||||
|
}
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NotNull String getCommandFormat() {
|
||||||
|
return "download [name]";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NotNull String getDescription() {
|
||||||
|
return "Downloads specified git-script";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,56 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.commands;
|
||||||
|
|
||||||
|
import com.extendedclip.papi.expansion.javascript.ExpansionUtils;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.cloud.*;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.commands.router.ExpansionCommand;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.commands.router.ExpansionCommandRouter;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.util.StringUtil;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public final class GitEnabledCommand extends ExpansionCommand {
|
||||||
|
private static final List<String> boolCompletion = Arrays.asList("true", "false");
|
||||||
|
private final ActiveStateSetter activeStateSetter;
|
||||||
|
|
||||||
|
public GitEnabledCommand(final ActiveStateSetter activeStateSetter) {
|
||||||
|
super(ExpansionCommandRouter.COMMAND_NAME + " git", "enabled");
|
||||||
|
this.activeStateSetter = activeStateSetter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(final CommandSender sender, final String[] args) {
|
||||||
|
if (args.length < 1) {
|
||||||
|
ExpansionUtils.sendMsg(sender, "&cIncorrect usage! &f/jsexpansion git enabled (true/false)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final boolean enabled = Boolean.parseBoolean(args[0]);
|
||||||
|
activeStateSetter.setActive(enabled);
|
||||||
|
|
||||||
|
ExpansionUtils.sendMsg(sender, "&6Git script downloads set to: &e" + enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull List<String> tabComplete(CommandSender sender, String[] args) {
|
||||||
|
if (args.length > 0) {
|
||||||
|
return StringUtil.copyPartialMatches(args[0], boolCompletion, new ArrayList<>());
|
||||||
|
}
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NotNull String getCommandFormat() {
|
||||||
|
return "enabled (true/false)";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NotNull String getDescription() {
|
||||||
|
return "Enables/Disables usage of git-script management";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.commands;
|
||||||
|
|
||||||
|
import com.extendedclip.papi.expansion.javascript.ExpansionUtils;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.cloud.GitScript;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.cloud.GitScriptIndexProvider;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.cloud.ScriptIndex;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.commands.router.ExpansionCommand;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.commands.router.ExpansionCommandRouter;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.util.StringUtil;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public final class GitInfoCommand extends ExpansionCommand {
|
||||||
|
private final GitScriptIndexProvider indexProvider;
|
||||||
|
|
||||||
|
public GitInfoCommand(final GitScriptIndexProvider indexProvider) {
|
||||||
|
super(ExpansionCommandRouter.COMMAND_NAME + " git", "info");
|
||||||
|
this.indexProvider = indexProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(final CommandSender sender, final String[] args) {
|
||||||
|
if (args.length < 1) {
|
||||||
|
ExpansionUtils.sendMsg(sender, "&cIncorrect usage! &f/" + getParentCommandName() + " git info [name]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final GitScript script = indexProvider.getScriptIndex().flatMap(index -> index.getScript(args[0])).orElse(null);
|
||||||
|
|
||||||
|
if (script == null) {
|
||||||
|
ExpansionUtils.sendMsg(sender, "&cThe script &f" + args[1] + " &cdoes not exist!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpansionUtils.sendMsg(sender,
|
||||||
|
"&eName: &f" + script.getName(),
|
||||||
|
"&eVersion: &f" + script.getVersion(),
|
||||||
|
"&eDescription: &f" + script.getDescription(),
|
||||||
|
"&eAuthor: &f" + script.getAuthor(),
|
||||||
|
"&eSource URL: &f" + script.getUrl()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull List<String> tabComplete(CommandSender sender, String[] args) {
|
||||||
|
if (args.length > 0) {
|
||||||
|
final List<String> scripts = indexProvider.getScriptIndex()
|
||||||
|
.map(ScriptIndex::getAllScripts)
|
||||||
|
.orElse(Collections.emptyList()).stream()
|
||||||
|
.map(GitScript::getName)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
return StringUtil.copyPartialMatches(args[0], scripts, new ArrayList<>());
|
||||||
|
}
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NotNull String getCommandFormat() {
|
||||||
|
return "info [name]";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NotNull String getDescription() {
|
||||||
|
return "Fetches info about a git-script";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.commands;
|
||||||
|
|
||||||
|
import com.extendedclip.papi.expansion.javascript.ExpansionUtils;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.cloud.GitScript;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.cloud.GitScriptIndexProvider;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.cloud.ScriptIndex;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.commands.router.ExpansionCommand;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.commands.router.ExpansionCommandRouter;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.util.StringUtil;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public final class GitListCommand extends ExpansionCommand {
|
||||||
|
private final GitScriptIndexProvider indexProvider;
|
||||||
|
|
||||||
|
public GitListCommand(final GitScriptIndexProvider indexProvider) {
|
||||||
|
super(ExpansionCommandRouter.COMMAND_NAME + " git", "list");
|
||||||
|
this.indexProvider = indexProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(final CommandSender sender, final String[] args) {
|
||||||
|
final Collection<GitScript> availableScripts = indexProvider.getScriptIndex().map(ScriptIndex::getAllScripts).orElse(Collections.emptyList());
|
||||||
|
final Set<String> scripts = availableScripts.stream().map(GitScript::getName).collect(Collectors.toSet());
|
||||||
|
|
||||||
|
ExpansionUtils.sendMsg(sender, availableScripts.size() + " &escript" + ExpansionUtils.plural(availableScripts.size()) + " available on Github.", String.join(", ", scripts));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull List<String> tabComplete(CommandSender sender, String[] args) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NotNull String getCommandFormat() {
|
||||||
|
return "list";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NotNull String getDescription() {
|
||||||
|
return "Lists loaded git-scripts";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.commands;
|
||||||
|
|
||||||
|
import com.extendedclip.papi.expansion.javascript.ExpansionUtils;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.cloud.GitScript;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.cloud.GitScriptIndexProvider;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.cloud.ScriptIndex;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.commands.router.ExpansionCommand;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.commands.router.ExpansionCommandRouter;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public final class GitRefreshCommand extends ExpansionCommand {
|
||||||
|
private final GitScriptIndexProvider indexProvider;
|
||||||
|
|
||||||
|
public GitRefreshCommand(final GitScriptIndexProvider indexProvider) {
|
||||||
|
super(ExpansionCommandRouter.COMMAND_NAME + " git", "refresh");
|
||||||
|
this.indexProvider = indexProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(final CommandSender sender, final String[] args) {
|
||||||
|
ExpansionUtils.sendMsg(sender, "&aFetching available scripts... Check back in a sec!");
|
||||||
|
indexProvider.refreshIndex(index -> {
|
||||||
|
ExpansionUtils.sendMsg(sender, "&aFetched " + index.getCount() + " scripts to index!");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull List<String> tabComplete(CommandSender sender, String[] args) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NotNull String getCommandFormat() {
|
||||||
|
return "refresh";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NotNull String getDescription() {
|
||||||
|
return "Re-indexes git-scripts from master list";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.commands;
|
||||||
|
|
||||||
|
import com.extendedclip.papi.expansion.javascript.ExpansionUtils;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.JavascriptPlaceholder;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.script.ScriptRegistry;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.commands.router.ExpansionCommand;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public final class ListCommand extends ExpansionCommand {
|
||||||
|
|
||||||
|
private final ScriptRegistry registry;
|
||||||
|
|
||||||
|
public ListCommand(final String parentCommandName, final ScriptRegistry registry) {
|
||||||
|
super(parentCommandName, "list");
|
||||||
|
this.registry = registry;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(final CommandSender sender, final String[] args) {
|
||||||
|
|
||||||
|
final List<String> loaded = registry.getAllPlaceholders().stream().map(JavascriptPlaceholder::getIdentifier).collect(Collectors.toList());
|
||||||
|
ExpansionUtils.sendMsg(sender,loaded.size() + " &7script" + ExpansionUtils.plural(loaded.size()) + " loaded.",
|
||||||
|
String.join(", ", loaded));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public List<String> tabComplete(final CommandSender sender, final String[] args) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
protected String getCommandFormat() {
|
||||||
|
return "list";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
protected String getDescription() {
|
||||||
|
return "List loaded script identifiers";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,83 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.commands;
|
||||||
|
|
||||||
|
import com.extendedclip.papi.expansion.javascript.ExpansionUtils;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.JavascriptPlaceholder;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.JavascriptPlaceholderFactory;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.commands.router.ExpansionCommand;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.evaluator.ScriptEvaluatorFactory;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.util.StringUtil;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public final class ParseCommand extends ExpansionCommand {
|
||||||
|
private static final String ARG_ME = "me";
|
||||||
|
private static final String ARG_PLAYER = "player";
|
||||||
|
|
||||||
|
private final JavascriptPlaceholderFactory placeholderFactory;
|
||||||
|
|
||||||
|
public ParseCommand(final String parentCommand, final JavascriptPlaceholderFactory placeholderFactory) {
|
||||||
|
super(parentCommand, "parse");
|
||||||
|
this.placeholderFactory = placeholderFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(final CommandSender sender, final String[] args) {
|
||||||
|
if (args.length < 2) {
|
||||||
|
ExpansionUtils.sendMsg(sender, "&cIncorrect usage! &f/" + getParentCommandName() + " parse [me/player] [code]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final OfflinePlayer player;
|
||||||
|
|
||||||
|
if ("me".equalsIgnoreCase(args[0])) {
|
||||||
|
if (!(sender instanceof Player)) {
|
||||||
|
ExpansionUtils.sendMsg(sender, "&cOnly players can run this command!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
player = (OfflinePlayer) sender;
|
||||||
|
} else {
|
||||||
|
player = Bukkit.getOfflinePlayer(args[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
final String script = String.join(" ", Arrays.copyOfRange(args, 1, args.length));
|
||||||
|
final JavascriptPlaceholder placeholder = placeholderFactory.create( "parse-command", String.join(" ", script));
|
||||||
|
|
||||||
|
|
||||||
|
if (!player.hasPlayedBefore() || player.getName() == null) {
|
||||||
|
ExpansionUtils.sendMsg(sender, "&cUnknown player " + args[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sender.sendMessage(placeholder.evaluate(player));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public List<String> tabComplete(final CommandSender sender, final String[] args) {
|
||||||
|
if (args.length == 1) {
|
||||||
|
return StringUtil.copyPartialMatches(args[0], Arrays.asList(ARG_ME, ARG_PLAYER), new ArrayList<>());
|
||||||
|
}
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
protected String getCommandFormat() {
|
||||||
|
return "parse [me/player] [code]";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
protected String getDescription() {
|
||||||
|
return "Test JavaScript code in chat";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.commands;
|
||||||
|
|
||||||
|
import com.extendedclip.papi.expansion.javascript.ExpansionUtils;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.JavascriptExpansion;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.commands.router.ExpansionCommand;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.script.ScriptLoader;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public final class ReloadCommand extends ExpansionCommand {
|
||||||
|
|
||||||
|
private final ScriptLoader loader;
|
||||||
|
|
||||||
|
public ReloadCommand(final String parentCommandName, final ScriptLoader loader) {
|
||||||
|
super(parentCommandName, "reload");
|
||||||
|
this.loader = loader;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(final CommandSender sender, final String[] args) {
|
||||||
|
|
||||||
|
ExpansionUtils.sendMsg(sender, "&aJavascriptExpansion reloading...");
|
||||||
|
try {
|
||||||
|
final int scripts = loader.reload();
|
||||||
|
ExpansionUtils.sendMsg(sender, scripts + " &7script" + ExpansionUtils.plural(scripts) + " loaded");
|
||||||
|
} catch (final IOException exception) {
|
||||||
|
ExpansionUtils.errorLog("&7Failed to reload scripts.", exception);
|
||||||
|
ExpansionUtils.sendMsg(sender, "&7Failed to reload scripts.");
|
||||||
|
exception.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public List<String> tabComplete(final CommandSender sender, final String[] args) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
protected String getCommandFormat() {
|
||||||
|
return "reload";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
protected String getDescription() {
|
||||||
|
return "Reload your javascripts without reloading PlaceholderAPI";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,99 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.commands.router;
|
||||||
|
|
||||||
|
import com.extendedclip.papi.expansion.javascript.JavascriptExpansion;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.JavascriptPlaceholderFactory;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.script.ScriptLoader;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.script.ScriptRegistry;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.cloud.GitScriptManager;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.commands.*;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.config.ScriptConfiguration;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.evaluator.ScriptEvaluatorFactory;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandMap;
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static com.extendedclip.papi.expansion.javascript.commands.router.ExpansionCommandRouter.COMMAND_NAME;
|
||||||
|
|
||||||
|
public final class CommandRegistrar {
|
||||||
|
private static final String WIKI_LINK = "https://github.com/PlaceholderAPI/Javascript-Expansion/wiki";
|
||||||
|
private final CommandRouter router;
|
||||||
|
private final CommandMap commandMap;
|
||||||
|
|
||||||
|
public CommandRegistrar(final GitScriptManager gitScriptManager, final JavascriptPlaceholderFactory placeholderFactory, final ScriptConfiguration configuration, final ScriptRegistry registry, final ScriptLoader loader) throws ReflectiveOperationException {
|
||||||
|
final GitRefreshCommand gitRefreshCommand = new GitRefreshCommand(gitScriptManager.getIndexProvider());
|
||||||
|
final GitListCommand gitListCommand = new GitListCommand(gitScriptManager.getIndexProvider());
|
||||||
|
final GitDownloadCommand gitDownloadCommand = new GitDownloadCommand(gitScriptManager, configuration);
|
||||||
|
final GitInfoCommand gitInfoCommand = new GitInfoCommand(gitScriptManager.getIndexProvider());
|
||||||
|
final GitEnabledCommand gitEnabledCommand = new GitEnabledCommand(gitScriptManager.getActiveStateSetter());
|
||||||
|
|
||||||
|
|
||||||
|
final Map<String, ExpansionCommand> gitCommandMap = ImmutableMap.<String, ExpansionCommand>builder()
|
||||||
|
.put("refresh", gitRefreshCommand)
|
||||||
|
.put("list", gitListCommand)
|
||||||
|
.put("download", gitDownloadCommand)
|
||||||
|
.put("info", gitInfoCommand)
|
||||||
|
.put("enabled", gitEnabledCommand)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
final CommandRouter gitCommandRouter = new ExpansionCommandRouter(JavascriptExpansion.VERSION, JavascriptExpansion.AUTHOR, WIKI_LINK, gitCommandMap);
|
||||||
|
|
||||||
|
final GitCommand gitCommand = new GitCommand(COMMAND_NAME, gitScriptManager.getActiveStateSetter(), gitCommandRouter);
|
||||||
|
final ListCommand listCommand = new ListCommand(COMMAND_NAME, registry);
|
||||||
|
final DebugCommand debugCommand = new DebugCommand(COMMAND_NAME, registry);
|
||||||
|
final ParseCommand parseCommand = new ParseCommand(COMMAND_NAME, placeholderFactory);
|
||||||
|
final ReloadCommand reloadCommand = new ReloadCommand(COMMAND_NAME, loader);
|
||||||
|
final Map<String, ExpansionCommand> commandMap = ImmutableMap.<String, ExpansionCommand>builder()
|
||||||
|
.put("git", gitCommand)
|
||||||
|
.put("list", listCommand)
|
||||||
|
.put("debug", debugCommand)
|
||||||
|
.put("parse", parseCommand)
|
||||||
|
.put("reload", reloadCommand)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
this.router = new ExpansionCommandRouter(JavascriptExpansion.VERSION, JavascriptExpansion.AUTHOR, WIKI_LINK, commandMap);
|
||||||
|
final Field field = Bukkit.getServer().getClass().getDeclaredField("commandMap");
|
||||||
|
field.setAccessible(true);
|
||||||
|
this.commandMap = (CommandMap) field.get(Bukkit.getServer());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void register() {
|
||||||
|
commandMap.register("papi" + router.getName(), router);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unregister() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
Class<? extends CommandMap> cmdMapClass = commandMap.getClass();
|
||||||
|
final Field knownCommandsField;
|
||||||
|
|
||||||
|
//Check if the server's in 1.13+
|
||||||
|
if (cmdMapClass.getSimpleName().equals("CraftCommandMap")) {
|
||||||
|
knownCommandsField = cmdMapClass.getSuperclass().getDeclaredField("knownCommands");
|
||||||
|
} else {
|
||||||
|
knownCommandsField = cmdMapClass.getDeclaredField("knownCommands");
|
||||||
|
}
|
||||||
|
|
||||||
|
knownCommandsField.setAccessible(true);
|
||||||
|
|
||||||
|
//noinspection unchecked
|
||||||
|
final Map<String, Command> knownCommands = (Map<String, Command>) knownCommandsField.get(commandMap);
|
||||||
|
knownCommands.remove(router.getName());
|
||||||
|
for (String alias : router.getAliases()) {
|
||||||
|
if (knownCommands.containsKey(alias) && knownCommands.get(alias).toString().contains(router.getName())) {
|
||||||
|
knownCommands.remove(alias);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
router.unregister(commandMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,102 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.commands.router;
|
||||||
|
|
||||||
|
import com.extendedclip.papi.expansion.javascript.ExpansionUtils;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.util.StringUtil;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public abstract class CommandRouter extends Command {
|
||||||
|
private final Map<String, ExpansionCommand> subCommandMap;
|
||||||
|
|
||||||
|
protected CommandRouter(
|
||||||
|
@NotNull final String name,
|
||||||
|
@NotNull final String description,
|
||||||
|
@NotNull final String usageMessage,
|
||||||
|
@NotNull final List<String> aliases,
|
||||||
|
@Nullable final String permission,
|
||||||
|
@NotNull final Map<String, ExpansionCommand> commandMap
|
||||||
|
) {
|
||||||
|
super(name, description, usageMessage, aliases);
|
||||||
|
setPermission(permission);
|
||||||
|
this.subCommandMap = commandMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract List<String> getHelpHeader();
|
||||||
|
|
||||||
|
public abstract String getSubCommandHelpFormat();
|
||||||
|
|
||||||
|
public abstract String getInvalidCommandMessage();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final boolean execute(@NotNull CommandSender sender, @NotNull String commandLabel, @NotNull String[] args) {
|
||||||
|
final String perm = getPermission();
|
||||||
|
if (perm != null && !sender.hasPermission(perm)) {
|
||||||
|
sender.sendMessage(CommandRouter.translateColors("&cYou don't have permission to do that!"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (args.length == 0) {
|
||||||
|
final String format = getSubCommandHelpFormat();
|
||||||
|
final List<String> header = getHelpHeader();
|
||||||
|
final List<String> subCommandHelp = subCommandMap
|
||||||
|
.values()
|
||||||
|
.stream()
|
||||||
|
.map(cmd ->
|
||||||
|
String.format(
|
||||||
|
format,
|
||||||
|
cmd.getParentCommandName(),
|
||||||
|
cmd.getCommandFormat(),
|
||||||
|
cmd.getDescription()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
header.stream().map(CommandRouter::translateColors).forEach(sender::sendMessage);
|
||||||
|
subCommandHelp.stream().map(CommandRouter::translateColors).forEach(sender::sendMessage);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String subCommand = args[0].toLowerCase();
|
||||||
|
final ExpansionCommand matchedCommand = subCommandMap.get(subCommand);
|
||||||
|
if (matchedCommand == null) {
|
||||||
|
final String invalidMatchMessage = getInvalidCommandMessage();
|
||||||
|
sender.sendMessage(translateColors(String.format(invalidMatchMessage, getName())));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
final String[] subArgs = new String[args.length - 1];
|
||||||
|
System.arraycopy(args, 1, subArgs, 0, args.length - 1);
|
||||||
|
matchedCommand.execute(sender, subArgs);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public final List<String> tabComplete(@NotNull final CommandSender sender, @NotNull final String alias, @NotNull final String[] args) throws IllegalArgumentException {
|
||||||
|
final int length = args.length;
|
||||||
|
if (length == 1) { // User requires tab completion for subcommand names
|
||||||
|
final String partialString = args[length - 1];
|
||||||
|
return StringUtil.copyPartialMatches(
|
||||||
|
partialString, subCommandMap.keySet(),
|
||||||
|
new ArrayList<>()
|
||||||
|
);
|
||||||
|
} else if (length > 1) { // User requires per-command tab completion
|
||||||
|
final String selectedCommandName = args[0];
|
||||||
|
final ExpansionCommand command = subCommandMap.get(selectedCommandName);
|
||||||
|
if (command == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
final String[] subArgs = new String[args.length - 1];
|
||||||
|
System.arraycopy(args, 1, subArgs, 0, args.length - 1);
|
||||||
|
return command.tabComplete(sender, subArgs);
|
||||||
|
}
|
||||||
|
return super.tabComplete(sender, alias, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String translateColors(final String input) {
|
||||||
|
return ChatColor.translateAlternateColorCodes('&', input);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.commands.router;
|
||||||
|
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public abstract class ExpansionCommand {
|
||||||
|
|
||||||
|
private final String parentCommandName;
|
||||||
|
public final String name;
|
||||||
|
|
||||||
|
public ExpansionCommand(@NotNull final String parentCommandName, @NotNull final String name) {
|
||||||
|
this.parentCommandName = parentCommandName;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void execute(final CommandSender sender, final String[] args);
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public abstract List<String> tabComplete(final CommandSender sender, final String[] args);
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
protected abstract String getCommandFormat();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
protected abstract String getDescription();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
protected final String getParentCommandName() {
|
||||||
|
return parentCommandName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
protected final String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.commands.router;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public final class ExpansionCommandRouter extends CommandRouter {
|
||||||
|
public static final String COMMAND_NAME = "jsexpansion";
|
||||||
|
private static final String PERMISSION = "placeholderapi.js.admin";
|
||||||
|
private static final String DESCRIPTION = "JavaScript Expansion Commands";
|
||||||
|
private static final String USAGE = "/jsexpansion <sub-command> <params>";
|
||||||
|
private static final List<String> ALIASES = Arrays.asList("javascriptexpansion", "jsexp");
|
||||||
|
private static final Collection<String> HELP_HEADER = Arrays.asList(
|
||||||
|
"&eJavascript expansion &7v: &f{version}",
|
||||||
|
"&eCreated by: &f{author}",
|
||||||
|
"&eWiki: &f{wiki}",
|
||||||
|
"&r"
|
||||||
|
);
|
||||||
|
private final String expansionVersion;
|
||||||
|
private final String authorName;
|
||||||
|
private final String wikiLink;
|
||||||
|
|
||||||
|
public ExpansionCommandRouter(
|
||||||
|
@NotNull final String expansionVersion,
|
||||||
|
@NotNull final String authorName,
|
||||||
|
@NotNull final String wikiLink,
|
||||||
|
@NotNull final Map<String, ExpansionCommand> commandMap
|
||||||
|
) {
|
||||||
|
super(COMMAND_NAME, DESCRIPTION, USAGE, ALIASES, PERMISSION, commandMap);
|
||||||
|
this.expansionVersion = expansionVersion;
|
||||||
|
this.authorName = authorName;
|
||||||
|
this.wikiLink = wikiLink;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getHelpHeader() {
|
||||||
|
return HELP_HEADER.stream().map(this::replacePlaceholders).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSubCommandHelpFormat() {
|
||||||
|
return "&e/%1$s %2$s &7- &f%3$s";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getInvalidCommandMessage() {
|
||||||
|
return "&cInvalid expansion sub-command! Type&f /%1$s &cfor help";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String replacePlaceholders(final String input) {
|
||||||
|
return input
|
||||||
|
.replace("{version}", expansionVersion)
|
||||||
|
.replace("{author}", authorName)
|
||||||
|
.replace("{wiki}", wikiLink);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.config;
|
||||||
|
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
public interface HeaderWriter {
|
||||||
|
void writeTo(final FileConfiguration configuration);
|
||||||
|
|
||||||
|
static HeaderWriter fromJar(final URL jarUrl) {
|
||||||
|
return new ResourceHeaderWriter(new JarResourceProvider(jarUrl));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.config;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Contract;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.JarURLConnection;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.jar.JarFile;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
|
||||||
|
public final class JarResourceProvider implements Function<String, InputStream> {
|
||||||
|
private final URL resourceJar;
|
||||||
|
|
||||||
|
public JarResourceProvider(final URL resourceJar) {
|
||||||
|
this.resourceJar = resourceJar;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public InputStream apply(@Nullable final String fileName) {
|
||||||
|
try {
|
||||||
|
final JarFile jarFile = new JarFile(new File(resourceJar.toURI()));
|
||||||
|
final ZipEntry zipEntry = jarFile.getEntry(fileName);
|
||||||
|
if (zipEntry == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return jarFile.getInputStream(zipEntry);
|
||||||
|
} catch (final IOException | URISyntaxException exception) {
|
||||||
|
exception.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.config;
|
||||||
|
|
||||||
|
import com.extendedclip.papi.expansion.javascript.ExpansionUtils;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public final class ResourceHeaderWriter implements HeaderWriter {
|
||||||
|
@NotNull
|
||||||
|
private final Function<String, InputStream> inputStreamFunction;
|
||||||
|
|
||||||
|
public ResourceHeaderWriter(@NotNull final Function<String, InputStream> inputStreamFunction) {
|
||||||
|
this.inputStreamFunction = inputStreamFunction;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeTo(@NotNull final FileConfiguration configuration) {
|
||||||
|
try (final InputStream stream = inputStreamFunction.apply("header.txt")) {
|
||||||
|
final String headerString = new BufferedReader(new InputStreamReader(stream)).lines()
|
||||||
|
.collect(Collectors.joining("\n"));
|
||||||
|
configuration.options().header(headerString);
|
||||||
|
} catch (final IOException exception) {
|
||||||
|
ExpansionUtils.errorLog("Failed to read header file", exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.config;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface ScriptConfiguration {
|
||||||
|
@Nullable
|
||||||
|
Path getPath(@NotNull String scriptName);
|
||||||
|
|
||||||
|
void setPath(@NotNull String scriptName, @Nullable final String name);
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
Collection<String> getScripts();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
Map<String, Path> getEntries();
|
||||||
|
|
||||||
|
void reload();
|
||||||
|
|
||||||
|
void save();
|
||||||
|
}
|
@ -0,0 +1,105 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.config;
|
||||||
|
|
||||||
|
import com.extendedclip.papi.expansion.javascript.ExpansionUtils;
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
import org.bukkit.configuration.InvalidConfigurationException;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public final class YamlScriptConfiguration implements ScriptConfiguration {
|
||||||
|
private final FileConfiguration fileConfiguration;
|
||||||
|
private final File configurationFile;
|
||||||
|
private final HeaderWriter headerWriter;
|
||||||
|
private final Path scriptDirectoryPath;
|
||||||
|
|
||||||
|
public YamlScriptConfiguration(final File configurationFile, final HeaderWriter headerWriter, final Path scriptDirectoryPath) {
|
||||||
|
this(
|
||||||
|
YamlConfiguration.loadConfiguration(configurationFile),
|
||||||
|
configurationFile,
|
||||||
|
headerWriter,
|
||||||
|
scriptDirectoryPath
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public YamlScriptConfiguration(final FileConfiguration configuration, final File configurationFile, final HeaderWriter headerWriter, final Path scriptDirectoryPath) {
|
||||||
|
this.fileConfiguration = configuration;
|
||||||
|
this.configurationFile = configurationFile;
|
||||||
|
this.headerWriter = headerWriter;
|
||||||
|
this.scriptDirectoryPath = scriptDirectoryPath;
|
||||||
|
if (!Files.isDirectory(scriptDirectoryPath)) {
|
||||||
|
throw new AssertionError("Expected directory for scripts to be saved/loaded from. Found non-directory path.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public Path getPath(@NotNull final String scriptName) {
|
||||||
|
final ConfigurationSection scriptSection = fileConfiguration.getConfigurationSection(scriptName);
|
||||||
|
if (scriptSection == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String fileName = scriptSection.getString("file");
|
||||||
|
if (fileName == null) {
|
||||||
|
fileName = scriptName + ".js";
|
||||||
|
}
|
||||||
|
return scriptDirectoryPath.resolve(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPath(@NotNull final String scriptName, @Nullable final String name) {
|
||||||
|
final String key = scriptName + ".file";
|
||||||
|
fileConfiguration.set(key, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public Collection<String> getScripts() {
|
||||||
|
return fileConfiguration.getKeys(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public Map<String, Path> getEntries() {
|
||||||
|
//noinspection ConstantConditions
|
||||||
|
return getScripts().stream().collect(Collectors.toMap(Function.identity(), this::getPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reload() {
|
||||||
|
try {
|
||||||
|
if (!configurationFile.exists()) {
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
|
configurationFile.getParentFile().mkdirs();
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
|
configurationFile.createNewFile();
|
||||||
|
}
|
||||||
|
fileConfiguration.load(configurationFile);
|
||||||
|
setPath("example", "example.js");
|
||||||
|
// Ensure presence of header in case user re-wrote the entire file
|
||||||
|
headerWriter.writeTo(fileConfiguration);
|
||||||
|
save();
|
||||||
|
} catch (final IOException | InvalidConfigurationException exception) {
|
||||||
|
ExpansionUtils.errorLog("Failed to reload configuration", exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save() {
|
||||||
|
try {
|
||||||
|
fileConfiguration.save(configurationFile);
|
||||||
|
} catch (final IOException exception) {
|
||||||
|
ExpansionUtils.errorLog("Failed to save configuration", exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.script;
|
||||||
|
|
||||||
|
import com.extendedclip.papi.expansion.javascript.JavascriptPlaceholder;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.JavascriptPlaceholderFactory;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.config.ScriptConfiguration;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.evaluator.ScriptEvaluatorFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
public final class ConfigurationScriptLoader implements ScriptLoader {
|
||||||
|
private final ScriptRegistry registry;
|
||||||
|
private final ScriptConfiguration configuration;
|
||||||
|
private final JavascriptPlaceholderFactory placeholderFactory;
|
||||||
|
|
||||||
|
public ConfigurationScriptLoader(ScriptRegistry registry, ScriptConfiguration configuration, JavascriptPlaceholderFactory placeholderFactory) {
|
||||||
|
this.registry = registry;
|
||||||
|
this.configuration = configuration;
|
||||||
|
this.placeholderFactory = placeholderFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int reload() throws IOException {
|
||||||
|
registry.getAllPlaceholders().forEach(JavascriptPlaceholder::saveData);
|
||||||
|
registry.clearRegistry();
|
||||||
|
configuration.reload();
|
||||||
|
int loaded = 0;
|
||||||
|
for (final String scriptIdentifier: configuration.getScripts()) {
|
||||||
|
final Path path = configuration.getPath(scriptIdentifier);
|
||||||
|
if (path == null) continue;
|
||||||
|
if (!Files.exists(path)) {
|
||||||
|
Files.createDirectories(path.getParent());
|
||||||
|
Files.createFile(path);
|
||||||
|
}
|
||||||
|
final String script = new String(Files.readAllBytes(path), StandardCharsets.UTF_8);
|
||||||
|
final JavascriptPlaceholder placeholder = placeholderFactory.create(scriptIdentifier, script);
|
||||||
|
registry.register(placeholder);
|
||||||
|
loaded++;
|
||||||
|
}
|
||||||
|
return loaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
registry.getAllPlaceholders().forEach(JavascriptPlaceholder::saveData);
|
||||||
|
registry.clearRegistry();
|
||||||
|
}
|
||||||
|
}
|
@ -18,25 +18,22 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
package com.extendedclip.papi.expansion.javascript;
|
package com.extendedclip.papi.expansion.javascript.script;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class ScriptData {
|
public final class ScriptData {
|
||||||
|
|
||||||
private Map<String, Object> map;
|
private final Map<String, Object> map;
|
||||||
|
|
||||||
public ScriptData(Map<String, Object> data) {
|
public ScriptData(final Map<String, Object> data) {
|
||||||
this.map = data;
|
this.map = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScriptData() {
|
|
||||||
this.map = new HashMap<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, Object> getData() {
|
public Map<String, Object> getData() {
|
||||||
return map;
|
return Collections.unmodifiableMap(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
@ -56,11 +53,7 @@ public class ScriptData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void set(String key, Object value) {
|
public void set(String key, Object value) {
|
||||||
map.put(key, ExpansionUtils.jsonToJava(value));
|
map.put(key, value);
|
||||||
}
|
|
||||||
|
|
||||||
public void setIfNull(String key, Object value) {
|
|
||||||
map.putIfAbsent(key, ExpansionUtils.jsonToJava(value));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
@ -0,0 +1,8 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.script;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public interface ScriptLoader {
|
||||||
|
int reload() throws IOException;
|
||||||
|
void clear();
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.script;
|
||||||
|
|
||||||
|
import com.extendedclip.papi.expansion.javascript.JavascriptPlaceholder;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public final class ScriptRegistry {
|
||||||
|
private final Map<String, JavascriptPlaceholder> registeredScripts;
|
||||||
|
|
||||||
|
public ScriptRegistry() {
|
||||||
|
this(new HashMap<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScriptRegistry(final Map<String, JavascriptPlaceholder> registeredScripts) {
|
||||||
|
this.registeredScripts = registeredScripts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean register(final JavascriptPlaceholder placeholder) {
|
||||||
|
final JavascriptPlaceholder previousPlaceholder = registeredScripts.putIfAbsent(placeholder.getIdentifier(), placeholder);
|
||||||
|
return previousPlaceholder == null; // Registered only if there was not prior script with the same name.
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unregister(final JavascriptPlaceholder placeholder) {
|
||||||
|
registeredScripts.remove(placeholder.getIdentifier());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearRegistry() {
|
||||||
|
registeredScripts.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public JavascriptPlaceholder getPlaceholder(final String identifier) {
|
||||||
|
return registeredScripts.get(identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<JavascriptPlaceholder> getAllPlaceholders() {
|
||||||
|
return registeredScripts.values();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,119 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.script.data;
|
||||||
|
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public final class ConfigurationMap implements Map<String, Object> {
|
||||||
|
private final FileConfiguration configuration;
|
||||||
|
|
||||||
|
public ConfigurationMap(final FileConfiguration configuration) {
|
||||||
|
this.configuration = configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return this.configuration.getKeys(false).size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return size() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsKey(final Object key) {
|
||||||
|
return get(key) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsValue(final Object value) {
|
||||||
|
if (value == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return keySet().stream()
|
||||||
|
.anyMatch(key -> value.equals(get(key)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object get(final Object key) {
|
||||||
|
return this.configuration.get(key.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Object put(String key, Object value) {
|
||||||
|
final Object old = this.configuration.get(key);
|
||||||
|
this.configuration.set(key, value);
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object remove(Object key) {
|
||||||
|
return put(key.toString(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void putAll(@NotNull Map<? extends String, ?> m) {
|
||||||
|
for (final Map.Entry<? extends String, ?> entry : m.entrySet()) {
|
||||||
|
put(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
keySet().forEach(this::remove);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Set<String> keySet() {
|
||||||
|
return configuration.getKeys(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Collection<Object> values() {
|
||||||
|
return keySet().stream().map(this::get).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Set<Map.Entry<String, Object>> entrySet() {
|
||||||
|
return keySet().stream().map(key -> new Entry(key, get(key))).collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class Entry implements Map.Entry<String, Object> {
|
||||||
|
private final String key;
|
||||||
|
private Object value;
|
||||||
|
|
||||||
|
public Entry(String key, Object value) {
|
||||||
|
this.key = key;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object setValue(final Object value) {
|
||||||
|
final Object old = this.value;
|
||||||
|
this.value = value;
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.script.data;
|
||||||
|
|
||||||
|
import com.extendedclip.papi.expansion.javascript.script.ScriptData;
|
||||||
|
|
||||||
|
public interface PersistableData {
|
||||||
|
ScriptData getScriptData();
|
||||||
|
void save();
|
||||||
|
void reload();
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
package com.extendedclip.papi.expansion.javascript.script.data;
|
||||||
|
|
||||||
|
import com.extendedclip.papi.expansion.javascript.ExpansionUtils;
|
||||||
|
import com.extendedclip.papi.expansion.javascript.script.ScriptData;
|
||||||
|
import org.bukkit.configuration.InvalidConfigurationException;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
|
public final class YmlPersistableData implements PersistableData {
|
||||||
|
private final String identifier;
|
||||||
|
private final ScriptData scriptData;
|
||||||
|
private final File dataFile;
|
||||||
|
private final YamlConfiguration configuration;
|
||||||
|
|
||||||
|
private YmlPersistableData(final String identifier, final ScriptData scriptData, final File dataFile, final YamlConfiguration configuration) {
|
||||||
|
this.identifier = identifier;
|
||||||
|
this.scriptData = scriptData;
|
||||||
|
this.dataFile = dataFile;
|
||||||
|
this.configuration = configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ScriptData getScriptData() {
|
||||||
|
return scriptData;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save() {
|
||||||
|
try {
|
||||||
|
configuration.save(dataFile);
|
||||||
|
} catch (IOException e) {
|
||||||
|
ExpansionUtils.errorLog(ExpansionUtils.PREFIX + "An error occurred while saving data for " + identifier, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reload() {
|
||||||
|
try {
|
||||||
|
configuration.load(dataFile);
|
||||||
|
} catch (IOException | InvalidConfigurationException e) {
|
||||||
|
ExpansionUtils.errorLog(ExpansionUtils.PREFIX + "An error occurred while saving data for " + identifier, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PersistableData create(final String identifier, final Path dataPath) throws IOException {
|
||||||
|
if (!Files.exists(dataPath)) {
|
||||||
|
Files.createDirectories(dataPath.getParent());
|
||||||
|
Files.createFile(dataPath);
|
||||||
|
}
|
||||||
|
final YamlConfiguration configuration = YamlConfiguration.loadConfiguration(dataPath.toFile());
|
||||||
|
final Map<String, Object> map = new ConfigurationMap(configuration);
|
||||||
|
return new YmlPersistableData(identifier, new ScriptData(map), dataPath.toFile(), configuration);
|
||||||
|
}
|
||||||
|
}
|
23
expansion/src/main/resources/header.txt
Normal file
23
expansion/src/main/resources/header.txt
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
Javascript Expansion: @VERSION@
|
||||||
|
This is the main configuration file for the Javascript Expansion.
|
||||||
|
|
||||||
|
You will define your javascript placeholders in this file.
|
||||||
|
|
||||||
|
Javascript files must be located in the:
|
||||||
|
/plugins/placeholderapi/javascripts/ folder
|
||||||
|
|
||||||
|
A detailed guide on how to create your own javascript placeholders
|
||||||
|
can be found here:
|
||||||
|
https://github.com/PlaceholderAPI-Expansions/Javascript-Expansion/wiki
|
||||||
|
|
||||||
|
Your javascript placeholders will be identified by: %javascript_<identifier>%
|
||||||
|
|
||||||
|
Configuration format:
|
||||||
|
|
||||||
|
<identifier>:
|
||||||
|
file: <name of file>.<file extension>
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
'my_placeholder':
|
||||||
|
file: 'my_placeholder.js'
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
5
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
5
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
185
gradlew
vendored
Normal file
185
gradlew
vendored
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright 2015 the original author or authors.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
##
|
||||||
|
## Gradle start up script for UN*X
|
||||||
|
##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
PRG="$0"
|
||||||
|
# Need this for relative symlinks.
|
||||||
|
while [ -h "$PRG" ] ; do
|
||||||
|
ls=`ls -ld "$PRG"`
|
||||||
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
|
PRG="$link"
|
||||||
|
else
|
||||||
|
PRG=`dirname "$PRG"`"/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
SAVED="`pwd`"
|
||||||
|
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||||
|
APP_HOME="`pwd -P`"
|
||||||
|
cd "$SAVED" >/dev/null
|
||||||
|
|
||||||
|
APP_NAME="Gradle"
|
||||||
|
APP_BASE_NAME=`basename "$0"`
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD="maximum"
|
||||||
|
|
||||||
|
warn () {
|
||||||
|
echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
die () {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN* )
|
||||||
|
cygwin=true
|
||||||
|
;;
|
||||||
|
Darwin* )
|
||||||
|
darwin=true
|
||||||
|
;;
|
||||||
|
MINGW* )
|
||||||
|
msys=true
|
||||||
|
;;
|
||||||
|
NONSTOP* )
|
||||||
|
nonstop=true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM.
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||||
|
else
|
||||||
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD="java"
|
||||||
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||||
|
MAX_FD_LIMIT=`ulimit -H -n`
|
||||||
|
if [ $? -eq 0 ] ; then
|
||||||
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||||
|
MAX_FD="$MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
ulimit -n $MAX_FD
|
||||||
|
if [ $? -ne 0 ] ; then
|
||||||
|
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Darwin, add options to specify how the application appears in the dock
|
||||||
|
if $darwin; then
|
||||||
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
|
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||||
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
|
|
||||||
|
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||||
|
|
||||||
|
# We build the pattern for arguments to be converted via cygpath
|
||||||
|
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||||
|
SEP=""
|
||||||
|
for dir in $ROOTDIRSRAW ; do
|
||||||
|
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||||
|
SEP="|"
|
||||||
|
done
|
||||||
|
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||||
|
# Add a user-defined pattern to the cygpath arguments
|
||||||
|
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||||
|
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||||
|
fi
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
i=0
|
||||||
|
for arg in "$@" ; do
|
||||||
|
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||||
|
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||||
|
|
||||||
|
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||||
|
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||||
|
else
|
||||||
|
eval `echo args$i`="\"$arg\""
|
||||||
|
fi
|
||||||
|
i=`expr $i + 1`
|
||||||
|
done
|
||||||
|
case $i in
|
||||||
|
0) set -- ;;
|
||||||
|
1) set -- "$args0" ;;
|
||||||
|
2) set -- "$args0" "$args1" ;;
|
||||||
|
3) set -- "$args0" "$args1" "$args2" ;;
|
||||||
|
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||||
|
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||||
|
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||||
|
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||||
|
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||||
|
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Escape application args
|
||||||
|
save () {
|
||||||
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
|
echo " "
|
||||||
|
}
|
||||||
|
APP_ARGS=`save "$@"`
|
||||||
|
|
||||||
|
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||||
|
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
104
gradlew.bat
vendored
Normal file
104
gradlew.bat
vendored
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
@rem
|
||||||
|
@rem Copyright 2015 the original author or authors.
|
||||||
|
@rem
|
||||||
|
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@rem you may not use this file except in compliance with the License.
|
||||||
|
@rem You may obtain a copy of the License at
|
||||||
|
@rem
|
||||||
|
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
@rem
|
||||||
|
@rem Unless required by applicable law or agreed to in writing, software
|
||||||
|
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@rem See the License for the specific language governing permissions and
|
||||||
|
@rem limitations under the License.
|
||||||
|
@rem
|
||||||
|
|
||||||
|
@if "%DEBUG%" == "" @echo off
|
||||||
|
@rem ##########################################################################
|
||||||
|
@rem
|
||||||
|
@rem Gradle startup script for Windows
|
||||||
|
@rem
|
||||||
|
@rem ##########################################################################
|
||||||
|
|
||||||
|
@rem Set local scope for the variables with windows NT shell
|
||||||
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
|
set DIRNAME=%~dp0
|
||||||
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
|
set APP_BASE_NAME=%~n0
|
||||||
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||||
|
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
|
@rem Find java.exe
|
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
set JAVA_EXE=java.exe
|
||||||
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
|
if "%ERRORLEVEL%" == "0" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:findJavaFromJavaHome
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
|
if exist "%JAVA_EXE%" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:init
|
||||||
|
@rem Get command-line arguments, handling Windows variants
|
||||||
|
|
||||||
|
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||||
|
|
||||||
|
:win9xME_args
|
||||||
|
@rem Slurp the command line arguments.
|
||||||
|
set CMD_LINE_ARGS=
|
||||||
|
set _SKIP=2
|
||||||
|
|
||||||
|
:win9xME_args_slurp
|
||||||
|
if "x%~1" == "x" goto execute
|
||||||
|
|
||||||
|
set CMD_LINE_ARGS=%*
|
||||||
|
|
||||||
|
:execute
|
||||||
|
@rem Setup the command line
|
||||||
|
|
||||||
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
|
@rem Execute Gradle
|
||||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||||
|
|
||||||
|
:end
|
||||||
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||||
|
|
||||||
|
:fail
|
||||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
|
rem the _cmd.exe /c_ return code!
|
||||||
|
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||||
|
exit /b 1
|
||||||
|
|
||||||
|
:mainEnd
|
||||||
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
|
:omega
|
66
pom.xml
66
pom.xml
@ -1,66 +0,0 @@
|
|||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<groupId>com.extendedclip.papi.expansion.javascript</groupId>
|
|
||||||
<artifactId>javascript-expansion</artifactId>
|
|
||||||
<version>1.6.1</version>
|
|
||||||
<name>PAPI-Expansion-Javascript</name>
|
|
||||||
<description>PlaceholderAPI expansion for javascript placeholders</description>
|
|
||||||
|
|
||||||
<repositories>
|
|
||||||
<repository>
|
|
||||||
<id>spigot-repo</id>
|
|
||||||
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
|
||||||
</repository>
|
|
||||||
<repository>
|
|
||||||
<id>placeholderapi</id>
|
|
||||||
<url>https://repo.extendedclip.com/content/repositories/placeholderapi/</url>
|
|
||||||
</repository>
|
|
||||||
</repositories>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.spigotmc</groupId>
|
|
||||||
<artifactId>spigot-api</artifactId>
|
|
||||||
<version>1.16.5-R0.1-SNAPSHOT</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>me.clip</groupId>
|
|
||||||
<artifactId>placeholderapi</artifactId>
|
|
||||||
<version>2.10.9</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
|
||||||
<version>3.2.0</version>
|
|
||||||
<configuration>
|
|
||||||
<finalName>${name}</finalName>
|
|
||||||
<archive>
|
|
||||||
<manifest>
|
|
||||||
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
|
|
||||||
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
|
|
||||||
</manifest>
|
|
||||||
</archive>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
|
||||||
<version>3.8.1</version>
|
|
||||||
<configuration>
|
|
||||||
<target>1.8</target>
|
|
||||||
<source>1.8</source>
|
|
||||||
<encoding>UTF-8</encoding>
|
|
||||||
<useIncrementalCompilation>false</useIncrementalCompilation>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
|
|
||||||
</project>
|
|
4
settings.gradle
Normal file
4
settings.gradle
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
rootProject.name = 'javascript-expansion'
|
||||||
|
include 'evaluator'
|
||||||
|
include 'evaluator-api'
|
||||||
|
include 'expansion'
|
@ -1,297 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* Javascript-Expansion
|
|
||||||
* Copyright (C) 2020 Ryan McCarthy
|
|
||||||
*
|
|
||||||
* This program 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.
|
|
||||||
*
|
|
||||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package com.extendedclip.papi.expansion.javascript;
|
|
||||||
|
|
||||||
import com.extendedclip.papi.expansion.javascript.cloud.GithubScriptManager;
|
|
||||||
import me.clip.placeholderapi.expansion.Cacheable;
|
|
||||||
import me.clip.placeholderapi.expansion.Configurable;
|
|
||||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.OfflinePlayer;
|
|
||||||
import org.bukkit.command.Command;
|
|
||||||
import org.bukkit.command.CommandMap;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import javax.script.ScriptEngine;
|
|
||||||
import javax.script.ScriptEngineFactory;
|
|
||||||
import javax.script.ScriptEngineManager;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class JavascriptExpansion extends PlaceholderExpansion implements Cacheable, Configurable {
|
|
||||||
|
|
||||||
private ScriptEngine globalEngine = null;
|
|
||||||
|
|
||||||
private JavascriptPlaceholdersConfig config;
|
|
||||||
private final Set<JavascriptPlaceholder> scripts;
|
|
||||||
private final String VERSION;
|
|
||||||
private static JavascriptExpansion instance;
|
|
||||||
private boolean debug;
|
|
||||||
private GithubScriptManager githubManager;
|
|
||||||
private JavascriptExpansionCommands commands;
|
|
||||||
private CommandMap commandMap;
|
|
||||||
private String argument_split;
|
|
||||||
|
|
||||||
public JavascriptExpansion() {
|
|
||||||
instance = this;
|
|
||||||
this.VERSION = getClass().getPackage().getImplementationVersion();
|
|
||||||
this.scripts = new HashSet<>();
|
|
||||||
|
|
||||||
try {
|
|
||||||
final Field field = Bukkit.getServer().getClass().getDeclaredField("commandMap");
|
|
||||||
field.setAccessible(true);
|
|
||||||
commandMap = (CommandMap) field.get(Bukkit.getServer());
|
|
||||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
|
||||||
ExpansionUtils.errorLog("An error occurred while accessing CommandMap.", e, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getAuthor() {
|
|
||||||
return "clip";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getIdentifier() {
|
|
||||||
return "javascript";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getVersion() {
|
|
||||||
return VERSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean register() {
|
|
||||||
String defaultEngine = ExpansionUtils.DEFAULT_ENGINE;
|
|
||||||
|
|
||||||
if (globalEngine == null) {
|
|
||||||
try {
|
|
||||||
globalEngine = new ScriptEngineManager(null).getEngineByName(getString("engine", defaultEngine));
|
|
||||||
} catch (NullPointerException ex) {
|
|
||||||
ExpansionUtils.warnLog("Javascript engine type was invalid! Defaulting to '" + defaultEngine + "'", null);
|
|
||||||
globalEngine = new ScriptEngineManager(null).getEngineByName(defaultEngine);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
argument_split = getString("argument_split", ",");
|
|
||||||
if (argument_split.equals("_")) {
|
|
||||||
argument_split = ",";
|
|
||||||
ExpansionUtils.warnLog("Underscore character will not be allowed for splitting. Defaulting to ',' for this", null);
|
|
||||||
}
|
|
||||||
|
|
||||||
debug = (boolean) get("debug", false);
|
|
||||||
config = new JavascriptPlaceholdersConfig(this);
|
|
||||||
|
|
||||||
int amountLoaded = config.loadPlaceholders();
|
|
||||||
ExpansionUtils.infoLog(amountLoaded + " script" + ExpansionUtils.plural(amountLoaded) + " loaded!");
|
|
||||||
|
|
||||||
|
|
||||||
if (debug) {
|
|
||||||
ExpansionUtils.infoLog("Java version: " + System.getProperty("java.version"));
|
|
||||||
|
|
||||||
final ScriptEngineManager manager = new ScriptEngineManager(null);
|
|
||||||
final List<ScriptEngineFactory> factories = manager.getEngineFactories();
|
|
||||||
ExpansionUtils.infoLog("Displaying all script engine factories.", false);
|
|
||||||
|
|
||||||
for (ScriptEngineFactory factory : factories) {
|
|
||||||
System.out.println(factory.getEngineName());
|
|
||||||
System.out.println(" Version: " + factory.getEngineVersion());
|
|
||||||
System.out.println(" Lang name: " + factory.getLanguageName());
|
|
||||||
System.out.println(" Lang version: " + factory.getLanguageVersion());
|
|
||||||
System.out.println(" Extensions: ." + String.join(", .", factory.getExtensions()));
|
|
||||||
System.out.println(" Mime types: " + String.join(", ", factory.getMimeTypes()));
|
|
||||||
System.out.println(" Names: " + String.join(", ", factory.getNames()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((boolean) get("github_script_downloads", false)) {
|
|
||||||
githubManager = new GithubScriptManager(this);
|
|
||||||
githubManager.fetch();
|
|
||||||
}
|
|
||||||
|
|
||||||
registerCommand();
|
|
||||||
return super.register();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clear() {
|
|
||||||
unregisterCommand();
|
|
||||||
|
|
||||||
scripts.forEach(script -> {
|
|
||||||
script.saveData();
|
|
||||||
script.cleanup();
|
|
||||||
});
|
|
||||||
|
|
||||||
if (githubManager != null) {
|
|
||||||
githubManager.clear();
|
|
||||||
githubManager = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
scripts.clear();
|
|
||||||
globalEngine = null;
|
|
||||||
instance = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String onRequest(OfflinePlayer player, @NotNull String identifier) {
|
|
||||||
if (player == null || scripts.size() == 0) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
for (JavascriptPlaceholder script : scripts) {
|
|
||||||
if (identifier.startsWith(script.getIdentifier() + "_")) {
|
|
||||||
identifier = identifier.replaceFirst(script.getIdentifier() + "_", "");
|
|
||||||
|
|
||||||
return !identifier.contains(argument_split) ? script.evaluate(player, identifier) : script.evaluate(player, identifier.split(argument_split));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (identifier.equalsIgnoreCase(script.getIdentifier())) {
|
|
||||||
return script.evaluate(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean addJSPlaceholder(JavascriptPlaceholder placeholder) {
|
|
||||||
if (placeholder == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scripts.isEmpty()) {
|
|
||||||
scripts.add(placeholder);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getJSPlaceholder(placeholder.getIdentifier()) != null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
scripts.add(placeholder);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// public Set<JavascriptPlaceholder> getJSPlaceholders() {
|
|
||||||
// return scripts;
|
|
||||||
// }
|
|
||||||
|
|
||||||
public List<String> getLoadedIdentifiers() {
|
|
||||||
return scripts.stream()
|
|
||||||
.map(JavascriptPlaceholder::getIdentifier)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
public JavascriptPlaceholder getJSPlaceholder(String identifier) {
|
|
||||||
return scripts.stream()
|
|
||||||
.filter(s -> s.getIdentifier().equalsIgnoreCase(identifier))
|
|
||||||
.findFirst()
|
|
||||||
.orElse(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getAmountLoaded() {
|
|
||||||
return scripts.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ScriptEngine getGlobalEngine() {
|
|
||||||
return globalEngine;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JavascriptPlaceholdersConfig getConfig() {
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, Object> getDefaults() {
|
|
||||||
final Map<String, Object> defaults = new HashMap<>();
|
|
||||||
defaults.put("engine", "javascript");
|
|
||||||
defaults.put("debug", false);
|
|
||||||
defaults.put("argument_split", ",");
|
|
||||||
defaults.put("github_script_downloads", false);
|
|
||||||
|
|
||||||
return defaults;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int reloadScripts() {
|
|
||||||
scripts.forEach(script -> {
|
|
||||||
script.saveData();
|
|
||||||
script.cleanup();
|
|
||||||
});
|
|
||||||
|
|
||||||
scripts.clear();
|
|
||||||
config.reload();
|
|
||||||
return config.loadPlaceholders();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JavascriptExpansion getInstance() {
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public GithubScriptManager getGithubScriptManager() {
|
|
||||||
return githubManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGithubScriptManager(GithubScriptManager manager) {
|
|
||||||
this.githubManager = manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void unregisterCommand() {
|
|
||||||
if (commandMap != null && commands != null) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
Class<? extends CommandMap> cmdMapClass = commandMap.getClass();
|
|
||||||
final Field f;
|
|
||||||
|
|
||||||
//Check if the server's in 1.13+
|
|
||||||
if (cmdMapClass.getSimpleName().equals("CraftCommandMap")) {
|
|
||||||
f = cmdMapClass.getSuperclass().getDeclaredField("knownCommands");
|
|
||||||
} else {
|
|
||||||
f = cmdMapClass.getDeclaredField("knownCommands");
|
|
||||||
}
|
|
||||||
|
|
||||||
f.setAccessible(true);
|
|
||||||
Map<String, Command> knownCmds = (Map<String, Command>) f.get(commandMap);
|
|
||||||
knownCmds.remove(commands.getName());
|
|
||||||
for (String alias : commands.getAliases()) {
|
|
||||||
if (knownCmds.containsKey(alias) && knownCmds.get(alias).toString().contains(commands.getName())) {
|
|
||||||
knownCmds.remove(alias);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
commands.unregister(commandMap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void registerCommand() {
|
|
||||||
if (commandMap == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
commands = new JavascriptExpansionCommands(this);
|
|
||||||
commandMap.register("papi" + commands.getName(), commands);
|
|
||||||
commands.isRegistered();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,168 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* Javascript-Expansion
|
|
||||||
* Copyright (C) 2020 Ryan McCarthy
|
|
||||||
*
|
|
||||||
* This program 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.
|
|
||||||
*
|
|
||||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package com.extendedclip.papi.expansion.javascript;
|
|
||||||
|
|
||||||
import com.extendedclip.papi.expansion.javascript.cloud.GithubScript;
|
|
||||||
import com.extendedclip.papi.expansion.javascript.command.*;
|
|
||||||
import org.bukkit.command.Command;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.util.StringUtil;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class JavascriptExpansionCommands extends Command {
|
|
||||||
|
|
||||||
private final JavascriptExpansion expansion;
|
|
||||||
private final String PERMISSION = "placeholderapi.js.admin";
|
|
||||||
private final String command;
|
|
||||||
private List<ICommand> subCommands;
|
|
||||||
|
|
||||||
public JavascriptExpansionCommands(JavascriptExpansion expansion) {
|
|
||||||
super("jsexpansion");
|
|
||||||
command = getName();
|
|
||||||
this.expansion = expansion;
|
|
||||||
this.setDescription("Javascript expansion commands");
|
|
||||||
this.setUsage("/" + command + " <args>");
|
|
||||||
this.setAliases(new ArrayList<>(Arrays.asList("javascriptexpansion", "jsexp")));
|
|
||||||
this.setPermission(PERMISSION);
|
|
||||||
initCommands();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void initCommands() {
|
|
||||||
if (subCommands != null) {
|
|
||||||
subCommands.clear();
|
|
||||||
}
|
|
||||||
subCommands = new ArrayList<>(Arrays.asList(
|
|
||||||
new GitCommand(expansion),
|
|
||||||
new ListCommand(expansion),
|
|
||||||
new ParseCommand(expansion),
|
|
||||||
new ReloadCommand(expansion),
|
|
||||||
new DebugCommand(expansion))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean execute(CommandSender sender, @NotNull String label, String[] args) {
|
|
||||||
|
|
||||||
if (!sender.hasPermission(PERMISSION)) {
|
|
||||||
ExpansionUtils.sendMsg(sender, "&cYou don't have permission to do that!");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.length == 0) {
|
|
||||||
sendHelp(sender);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ICommand command = null;
|
|
||||||
for (ICommand icmd : subCommands) {
|
|
||||||
if (icmd.getAlias().equalsIgnoreCase(args[0])) {
|
|
||||||
command = icmd;
|
|
||||||
command.command = getName();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (command == null) {
|
|
||||||
ExpansionUtils.sendMsg(sender, "&cInvalid expansion sub-command! Type&f /" + getName() + " &cfor help");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
command.execute(sender, sliceFirstArr(args));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: This thing here has to be organized thoroughly later...
|
|
||||||
@Override
|
|
||||||
public List<String> tabComplete(CommandSender sender, @NotNull String alias, String[] args) throws IllegalArgumentException {
|
|
||||||
if (!sender.hasPermission(PERMISSION)) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
final List<String> commands = new ArrayList<>(Arrays.asList("list", "parse", "reload"));
|
|
||||||
final List<String> completion = new ArrayList<>();
|
|
||||||
|
|
||||||
if (expansion.getGithubScriptManager() != null) {
|
|
||||||
commands.add(0, "git");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.length == 1) {
|
|
||||||
return StringUtil.copyPartialMatches(args[0], commands, completion);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args[0].equalsIgnoreCase("git")) {
|
|
||||||
if (expansion.getGithubScriptManager() == null) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.length == 2) {
|
|
||||||
return StringUtil.copyPartialMatches(args[1], Arrays.asList("download", "enable", "info", "list", "refresh"), completion);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.length == 3 && args[1].equalsIgnoreCase("download")) {
|
|
||||||
if (expansion.getGithubScriptManager().getAvailableScripts() == null) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
return StringUtil.copyPartialMatches(args[2], expansion.getGithubScriptManager().getAvailableScripts().stream().map(GithubScript::getName).collect(Collectors.toList()), completion);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendHelp(CommandSender sender) {
|
|
||||||
ExpansionUtils.sendMsg(sender,
|
|
||||||
"&eJavascript expansion &7v: &f" + expansion.getVersion(),
|
|
||||||
"&eCreated by: &f" + expansion.getAuthor(),
|
|
||||||
"&eWiki: &fhttps://github.com/PlaceholderAPI/Javascript-Expansion/wiki",
|
|
||||||
"&r",
|
|
||||||
"&e/" + command + " reload &7- &fReload your javascripts without reloading PlaceholderAPI.",
|
|
||||||
"&e/" + command + " list &7- &fList loaded script identifiers.",
|
|
||||||
"&e/" + command + " parse [me/player] [code] &7- &fTest JavaScript code in chat.",
|
|
||||||
"&e/" + command + " debug [savedata/loaddata] [identifier] &7- &fTest JavaScript code in chat."
|
|
||||||
);
|
|
||||||
|
|
||||||
if (expansion.getGithubScriptManager() != null) {
|
|
||||||
ExpansionUtils.sendMsg(sender,
|
|
||||||
"&e/" + command + " git refresh &7- &fRefresh available Github scripts",
|
|
||||||
"&e/" + command + " git download [name] &7- &fDownload a script from the js expansion github.",
|
|
||||||
"&e/" + command + " git list &7- &fList available scripts in the js expansion github.",
|
|
||||||
"&e/" + command + " git info [name] &7- &fGet the description and url of a specific script."
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
ExpansionUtils.sendMsg(sender,
|
|
||||||
"&e/" + command + " git &7- &fGithub command &7(please enable in config)"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String[] sliceFirstArr(String[] args) {
|
|
||||||
return Arrays.stream(args).skip(1).toArray(String[]::new);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,212 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* Javascript-Expansion
|
|
||||||
* Copyright (C) 2020 Ryan McCarthy
|
|
||||||
*
|
|
||||||
* This program 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.
|
|
||||||
*
|
|
||||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package com.extendedclip.papi.expansion.javascript;
|
|
||||||
|
|
||||||
import me.clip.placeholderapi.PlaceholderAPI;
|
|
||||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
|
||||||
import org.apache.commons.lang.Validate;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.OfflinePlayer;
|
|
||||||
import org.bukkit.configuration.InvalidConfigurationException;
|
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
|
||||||
|
|
||||||
import javax.script.ScriptEngine;
|
|
||||||
import javax.script.ScriptException;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
public class JavascriptPlaceholder {
|
|
||||||
|
|
||||||
private final ScriptEngine engine;
|
|
||||||
private final String identifier;
|
|
||||||
private final String script;
|
|
||||||
private ScriptData scriptData;
|
|
||||||
private final File dataFile;
|
|
||||||
private YamlConfiguration yaml;
|
|
||||||
private final Pattern pattern;
|
|
||||||
|
|
||||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
|
||||||
public JavascriptPlaceholder(ScriptEngine engine, String identifier, String script) {
|
|
||||||
Validate.notNull(engine, "ScriptEngine can not be null");
|
|
||||||
Validate.notNull(identifier, "Identifier can not be null");
|
|
||||||
Validate.notNull(script, "Script can not be null");
|
|
||||||
|
|
||||||
String dir = PlaceholderAPIPlugin.getInstance().getDataFolder() + "/javascripts/javascript_data";
|
|
||||||
this.engine = engine;
|
|
||||||
this.identifier = identifier;
|
|
||||||
this.script = script;
|
|
||||||
final File directory = new File(dir);
|
|
||||||
|
|
||||||
if (!directory.exists()) {
|
|
||||||
directory.mkdirs();
|
|
||||||
}
|
|
||||||
|
|
||||||
pattern = Pattern.compile("//.*|/\\*[\\S\\s]*?\\*/|%([^%]+)%");
|
|
||||||
scriptData = new ScriptData();
|
|
||||||
dataFile = new File(directory, identifier + "_data.yml");
|
|
||||||
engine.put("Data", scriptData);
|
|
||||||
engine.put("DataVar", scriptData.getData());
|
|
||||||
engine.put("BukkitServer", Bukkit.getServer());
|
|
||||||
engine.put("Expansion", JavascriptExpansion.getInstance());
|
|
||||||
engine.put("Placeholder", this);
|
|
||||||
engine.put("PlaceholderAPI", PlaceholderAPI.class);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getIdentifier() {
|
|
||||||
return identifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String evaluate(OfflinePlayer player, String... args) {
|
|
||||||
|
|
||||||
// A checker to deny all placeholders inside comment codes
|
|
||||||
Matcher matcher = pattern.matcher(script);
|
|
||||||
StringBuffer buffer = new StringBuffer();
|
|
||||||
|
|
||||||
while (matcher.find()) {
|
|
||||||
String matched = matcher.group(0);
|
|
||||||
if (!matched.startsWith("%") || matched.startsWith("/*") || matched.startsWith("//")) continue;
|
|
||||||
|
|
||||||
matcher.appendReplacement(buffer, PlaceholderAPI.setPlaceholders(player, matched));
|
|
||||||
}
|
|
||||||
|
|
||||||
matcher.appendTail(buffer);
|
|
||||||
String exp = buffer.toString();
|
|
||||||
|
|
||||||
try {
|
|
||||||
String[] arguments = null;
|
|
||||||
|
|
||||||
if (args != null && args.length > 0) {
|
|
||||||
arguments = new String[args.length];
|
|
||||||
|
|
||||||
for (int i = 0; i < args.length; i++) {
|
|
||||||
if (args[i] == null || args[i].isEmpty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
arguments[i] = PlaceholderAPI.setBracketPlaceholders(player, args[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arguments == null) {
|
|
||||||
arguments = new String[]{};
|
|
||||||
}
|
|
||||||
|
|
||||||
engine.put("args", arguments);
|
|
||||||
|
|
||||||
if (player != null && player.isOnline()) {
|
|
||||||
engine.put("BukkitPlayer", player.getPlayer());
|
|
||||||
engine.put("Player", player.getPlayer());
|
|
||||||
}
|
|
||||||
|
|
||||||
engine.put("OfflinePlayer", player);
|
|
||||||
Object result = engine.eval(exp);
|
|
||||||
return result != null ? PlaceholderAPI.setBracketPlaceholders(player, result.toString()) : "";
|
|
||||||
|
|
||||||
} catch (ScriptException ex) {
|
|
||||||
ExpansionUtils.errorLog("An error occurred while executing the script '" + identifier + "':\n\t" + ex.getMessage(), null);
|
|
||||||
} catch (ArrayIndexOutOfBoundsException ex) {
|
|
||||||
ExpansionUtils.errorLog("Argument out of bound while executing script '" + identifier + "':\n\t" + ex.getMessage(), null);
|
|
||||||
}
|
|
||||||
return "Script error (check console)";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getScript() {
|
|
||||||
return script;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ScriptData getData() {
|
|
||||||
if (scriptData == null) {
|
|
||||||
scriptData = new ScriptData();
|
|
||||||
}
|
|
||||||
return scriptData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setData(ScriptData data) {
|
|
||||||
this.scriptData = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
|
||||||
public boolean loadData() {
|
|
||||||
yaml = new YamlConfiguration();
|
|
||||||
dataFile.getParentFile().mkdirs();
|
|
||||||
|
|
||||||
if (!dataFile.exists()) {
|
|
||||||
try {
|
|
||||||
dataFile.createNewFile();
|
|
||||||
} catch (IOException e) {
|
|
||||||
ExpansionUtils.errorLog("An error occurred while creating data file for " + getIdentifier(), e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
yaml.load(dataFile);
|
|
||||||
} catch (IOException | InvalidConfigurationException e) {
|
|
||||||
ExpansionUtils.errorLog("An error occurred while loading for " + getIdentifier(), e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Set<String> keys = yaml.getKeys(true);
|
|
||||||
|
|
||||||
if (keys.size() == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scriptData == null)
|
|
||||||
scriptData = new ScriptData();
|
|
||||||
else scriptData.clear();
|
|
||||||
|
|
||||||
keys.forEach(key -> scriptData.set(key, ExpansionUtils.ymlToJavaObj(yaml.get(key))));
|
|
||||||
|
|
||||||
if (!scriptData.isEmpty()) {
|
|
||||||
setData(scriptData);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void saveData() {
|
|
||||||
if (scriptData == null || scriptData.isEmpty() || yaml == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function for merging JSON.
|
|
||||||
// TODO: This will be removed along with Nashorn in a later future
|
|
||||||
scriptData.getData().forEach((key, value) -> yaml.set(key, ExpansionUtils.jsonToJava(value)));
|
|
||||||
|
|
||||||
try {
|
|
||||||
yaml.save(dataFile);
|
|
||||||
} catch (IOException e) {
|
|
||||||
ExpansionUtils.errorLog(ExpansionUtils.PREFIX + "An error occurred while saving data for " + getIdentifier(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void cleanup() {
|
|
||||||
if (this.scriptData != null) {
|
|
||||||
this.scriptData.clear();
|
|
||||||
this.scriptData = null;
|
|
||||||
}
|
|
||||||
this.yaml = null;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,213 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* Javascript-Expansion
|
|
||||||
* Copyright (C) 2020 Ryan McCarthy
|
|
||||||
*
|
|
||||||
* This program 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.
|
|
||||||
*
|
|
||||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package com.extendedclip.papi.expansion.javascript;
|
|
||||||
|
|
||||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
|
||||||
import org.bukkit.configuration.file.FileConfiguration;
|
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
|
||||||
|
|
||||||
import javax.script.ScriptEngine;
|
|
||||||
import javax.script.ScriptEngineManager;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class JavascriptPlaceholdersConfig {
|
|
||||||
|
|
||||||
private final JavascriptExpansion ex;
|
|
||||||
private final PlaceholderAPIPlugin plugin;
|
|
||||||
private FileConfiguration config;
|
|
||||||
private File file;
|
|
||||||
|
|
||||||
public JavascriptPlaceholdersConfig(JavascriptExpansion ex) {
|
|
||||||
this.ex = ex;
|
|
||||||
plugin = ex.getPlaceholderAPI();
|
|
||||||
reload();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reload() {
|
|
||||||
if (file == null) {
|
|
||||||
file = new File(plugin.getDataFolder(), "javascript_placeholders.yml");
|
|
||||||
}
|
|
||||||
|
|
||||||
config = YamlConfiguration.loadConfiguration(file);
|
|
||||||
config.options().header("Javascript Expansion: " + ex.getVersion()
|
|
||||||
+ "\nThis is the main configuration file for the Javascript Expansion."
|
|
||||||
+ "\n"
|
|
||||||
+ "\nYou will define your javascript placeholders in this file."
|
|
||||||
+ "\n"
|
|
||||||
+ "\nJavascript files must be located in the:"
|
|
||||||
+ "\n /plugins/placeholderapi/javascripts/ folder"
|
|
||||||
+ "\n"
|
|
||||||
+ "\nA detailed guide on how to create your own javascript placeholders"
|
|
||||||
+ "\ncan be found here:"
|
|
||||||
+ "\nhttps://github.com/PlaceholderAPI-Expansions/Javascript-Expansion/wiki"
|
|
||||||
+ "\n"
|
|
||||||
+ "\nYour javascript placeholders will be identified by: %javascript_<identifier>%"
|
|
||||||
+ "\n"
|
|
||||||
+ "\nConfiguration format:"
|
|
||||||
+ "\n"
|
|
||||||
+ "\n<identifier>:"
|
|
||||||
+ "\n file: <name of file>.<file extension>"
|
|
||||||
+ "\n engine: (name of script engine)"
|
|
||||||
+ "\n"
|
|
||||||
+ "\n"
|
|
||||||
+ "\nExample:"
|
|
||||||
+ "\n"
|
|
||||||
+ "\n'my_placeholder':"
|
|
||||||
+ "\n file: 'my_placeholder.js'"
|
|
||||||
+ "\n engine: 'nashorn'");
|
|
||||||
|
|
||||||
if (config.getKeys(false).isEmpty()) {
|
|
||||||
config.set("example.file", "example.js");
|
|
||||||
config.set("example.engine", ExpansionUtils.DEFAULT_ENGINE);
|
|
||||||
}
|
|
||||||
|
|
||||||
save();
|
|
||||||
}
|
|
||||||
|
|
||||||
public FileConfiguration load() {
|
|
||||||
if (config == null) reload();
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void save() {
|
|
||||||
if (config == null || file == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
load().save(file);
|
|
||||||
} catch (IOException ex) {
|
|
||||||
ExpansionUtils.warnLog("Could not save to " + file, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
|
||||||
public int loadPlaceholders() {
|
|
||||||
if (config == null || config.getKeys(false).isEmpty()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
final File directory = new File(plugin.getDataFolder(), "javascripts");
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (!directory.exists()) {
|
|
||||||
directory.mkdirs();
|
|
||||||
ExpansionUtils.infoLog("Creating directory: " + directory.getPath());
|
|
||||||
}
|
|
||||||
} catch (SecurityException e) {
|
|
||||||
ExpansionUtils.errorLog("Could not create directory: " + directory.getPath(), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (String identifier : config.getKeys(false)) {
|
|
||||||
final String fileName = config.getString(identifier + ".file");
|
|
||||||
if (!config.contains(identifier + ".file") || fileName == null) {
|
|
||||||
ExpansionUtils.warnLog("Javascript placeholder: " + identifier + " does not have a file specified", null);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final File scriptFile = new File(plugin.getDataFolder() + "/javascripts", fileName);
|
|
||||||
|
|
||||||
if (!scriptFile.exists()) {
|
|
||||||
ExpansionUtils.infoLog(scriptFile.getName() + " does not exist. Creating one for you...");
|
|
||||||
|
|
||||||
try {
|
|
||||||
scriptFile.createNewFile();
|
|
||||||
ExpansionUtils.infoLog(scriptFile.getName() + " created! Add your javascript to this file and use '/jsexpansion reload' to load it!");
|
|
||||||
} catch (IOException e) {
|
|
||||||
ExpansionUtils.errorLog("An error occurred while creating " + scriptFile.getName(), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final String script = getContents(scriptFile);
|
|
||||||
|
|
||||||
if (script == null || script.isEmpty()) {
|
|
||||||
ExpansionUtils.warnLog("File: " + scriptFile.getName() + " for Javascript placeholder: " + identifier + " is empty", null);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean debug = (boolean) ex.get("debug", false);
|
|
||||||
int errScriptEngine = 0;
|
|
||||||
|
|
||||||
ScriptEngine engine;
|
|
||||||
if (!config.contains(identifier + ".engine")) {
|
|
||||||
engine = ex.getGlobalEngine();
|
|
||||||
if (debug) {
|
|
||||||
ExpansionUtils.warnLog("ScriptEngine type for javascript placeholder: " + identifier + " is empty! Defaulting to global", null);
|
|
||||||
} else {
|
|
||||||
errScriptEngine++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
engine = new ScriptEngineManager(null).getEngineByName(config.getString(identifier + ".engine", "nashorn"));
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
if (debug) {
|
|
||||||
ExpansionUtils.warnLog("ScriptEngine type for javascript placeholder: " + identifier + " is invalid! Defaulting to global", null);
|
|
||||||
} else {
|
|
||||||
errScriptEngine++;
|
|
||||||
}
|
|
||||||
engine = ex.getGlobalEngine();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (errScriptEngine > 0) {
|
|
||||||
ExpansionUtils.warnLog("ScriptEngine type for " + errScriptEngine + " javascript placeholder" + ExpansionUtils.plural(errScriptEngine) +
|
|
||||||
" failed! Defaulting all to global. More information by enabling debug mode", null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (engine == null) {
|
|
||||||
ExpansionUtils.warnLog("Failed to set ScriptEngine for javascript placeholder: " + identifier, null);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final JavascriptPlaceholder placeholder = new JavascriptPlaceholder(engine, identifier, script);
|
|
||||||
final boolean added = ex.addJSPlaceholder(placeholder);
|
|
||||||
|
|
||||||
if (added) {
|
|
||||||
if (placeholder.loadData()) {
|
|
||||||
ExpansionUtils.infoLog("Data for placeholder &b" + identifier + "&r has been loaded");
|
|
||||||
}
|
|
||||||
|
|
||||||
ExpansionUtils.infoLog("Placeholder &b%javascript_" + identifier + "%&r has been loaded");
|
|
||||||
} else {
|
|
||||||
ExpansionUtils.warnLog("Javascript placeholder %javascript_" + identifier + "% is duplicated!", null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ex.getAmountLoaded();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getContents(File file) {
|
|
||||||
final StringBuilder sb = new StringBuilder();
|
|
||||||
|
|
||||||
try {
|
|
||||||
List<String> lines = Files.readAllLines(file.toPath());
|
|
||||||
lines.forEach((line) -> sb.append(line).append("\n"));
|
|
||||||
} catch (IOException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,130 +0,0 @@
|
|||||||
/*
|
|
||||||
*
|
|
||||||
* Javascript-Expansion
|
|
||||||
* Copyright (C) 2020 Ryan McCarthy
|
|
||||||
*
|
|
||||||
* This program 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.
|
|
||||||
*
|
|
||||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package com.extendedclip.papi.expansion.javascript.cloud;
|
|
||||||
|
|
||||||
import com.extendedclip.papi.expansion.javascript.ExpansionUtils;
|
|
||||||
import com.extendedclip.papi.expansion.javascript.JavascriptExpansion;
|
|
||||||
import com.extendedclip.papi.expansion.javascript.JavascriptPlaceholdersConfig;
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import jdk.nashorn.api.scripting.ScriptUtils;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class GithubScriptManager {
|
|
||||||
|
|
||||||
private final JavascriptExpansion expansion;
|
|
||||||
private final String JAVASCRIPTS_FOLDER;
|
|
||||||
private List<GithubScript> availableScripts;
|
|
||||||
private final String MASTER_LIST_URL = "https://raw.githubusercontent.com/PlaceholderAPI/Javascript-Expansion/master/scripts/master_list.json";
|
|
||||||
private final Gson GSON = new Gson();
|
|
||||||
|
|
||||||
public GithubScriptManager(JavascriptExpansion expansion) {
|
|
||||||
this.expansion = expansion;
|
|
||||||
JAVASCRIPTS_FOLDER = expansion.getPlaceholderAPI().getDataFolder()
|
|
||||||
+ File.separator
|
|
||||||
+ "javascripts"
|
|
||||||
+ File.separator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear() {
|
|
||||||
availableScripts = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void fetch() {
|
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(expansion.getPlaceholderAPI(), () -> {
|
|
||||||
final String json = getContents(MASTER_LIST_URL);
|
|
||||||
|
|
||||||
if (json.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
availableScripts = GSON.fromJson(json, new TypeToken<ArrayList<GithubScript>>() {}.getType());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void downloadScript(GithubScript script) {
|
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(expansion.getPlaceholderAPI(), () -> {
|
|
||||||
final List<String> contents = read(script.getUrl());
|
|
||||||
|
|
||||||
if (contents.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try (final PrintStream out = new PrintStream(new FileOutputStream(new File(JAVASCRIPTS_FOLDER, script.getName() + ".js")))) {
|
|
||||||
contents.forEach(out::println);
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
ExpansionUtils.errorLog("An error occurred while downloading " + script.getName(), e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Bukkit.getScheduler().runTask(expansion.getPlaceholderAPI(), () -> {
|
|
||||||
JavascriptPlaceholdersConfig config = expansion.getConfig();
|
|
||||||
config.load().set(script.getName() + ".file", script.getName() + ".js");
|
|
||||||
config.load().set(script.getName() + ".engine", "javascript");
|
|
||||||
|
|
||||||
config.save();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getContents(String url) {
|
|
||||||
return String.join("", read(url));
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> read(final String url) {
|
|
||||||
final List<String> lines = new ArrayList<>();
|
|
||||||
|
|
||||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new URL(url).openStream()))) {
|
|
||||||
lines.addAll(reader.lines().filter(Objects::nonNull).collect(Collectors.toList()));
|
|
||||||
} catch (Exception ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
return lines;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<GithubScript> getAvailableScripts() {
|
|
||||||
return availableScripts;
|
|
||||||
}
|
|
||||||
|
|
||||||
public GithubScript getScript(final String name) {
|
|
||||||
if (availableScripts == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return availableScripts.stream()
|
|
||||||
.filter(s -> s.getName().equalsIgnoreCase(name))
|
|
||||||
.findFirst()
|
|
||||||
.orElse(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getJavascriptsFolder() {
|
|
||||||
return JAVASCRIPTS_FOLDER;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,50 +0,0 @@
|
|||||||
package com.extendedclip.papi.expansion.javascript.command;
|
|
||||||
|
|
||||||
import com.extendedclip.papi.expansion.javascript.ExpansionUtils;
|
|
||||||
import com.extendedclip.papi.expansion.javascript.JavascriptExpansion;
|
|
||||||
import com.extendedclip.papi.expansion.javascript.JavascriptPlaceholder;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class DebugCommand extends ICommand {
|
|
||||||
|
|
||||||
private final JavascriptExpansion expansion;
|
|
||||||
|
|
||||||
public DebugCommand(JavascriptExpansion expansion) {
|
|
||||||
this.expansion = expansion;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(CommandSender sender, String[] args) {
|
|
||||||
if (args.length < 2) {
|
|
||||||
ExpansionUtils.sendMsg(sender, "&cIncorrect usage! Type '&f/" + command + "&c' for more help.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
JavascriptPlaceholder jsp = expansion.getJSPlaceholder(getIdentifier(args));
|
|
||||||
if (jsp == null) {
|
|
||||||
ExpansionUtils.sendMsg(sender, "&cInvalid javascript identifier! Please re-check your typo");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args[0].equals("savedata")) {
|
|
||||||
jsp.saveData();
|
|
||||||
ExpansionUtils.sendMsg(sender, "&aJavascript data '" + args[1] + "' successfully saved");
|
|
||||||
} else if (args[0].equals("loaddata")) {
|
|
||||||
jsp.loadData();
|
|
||||||
ExpansionUtils.sendMsg(sender, "&aJavascript data '" + args[1] + "' successfully loaded");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getIdentifier(String[] args) {
|
|
||||||
return Arrays.stream(args).skip(1).collect(Collectors.joining(" "));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull String getAlias() {
|
|
||||||
return "debug";
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,138 +0,0 @@
|
|||||||
package com.extendedclip.papi.expansion.javascript.command;
|
|
||||||
|
|
||||||
import com.extendedclip.papi.expansion.javascript.ExpansionUtils;
|
|
||||||
import com.extendedclip.papi.expansion.javascript.JavascriptExpansion;
|
|
||||||
import com.extendedclip.papi.expansion.javascript.cloud.GithubScript;
|
|
||||||
import com.extendedclip.papi.expansion.javascript.cloud.GithubScriptManager;
|
|
||||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class GitCommand extends ICommand {
|
|
||||||
|
|
||||||
private final JavascriptExpansion expansion;
|
|
||||||
|
|
||||||
public GitCommand(JavascriptExpansion expansion) {
|
|
||||||
this.expansion = expansion;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(CommandSender sender, String[] args) {
|
|
||||||
|
|
||||||
if (expansion.getGithubScriptManager() == null) {
|
|
||||||
ExpansionUtils.sendMsg(sender, "&cThis feature is disabled in the PlaceholderAPI config.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.length < 1) {
|
|
||||||
ExpansionUtils.sendMsg(sender, "&cIncorrect usage! Type '&f/" + command + "&c' for more help.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final GithubScriptManager manager = expansion.getGithubScriptManager();
|
|
||||||
|
|
||||||
switch (args[0].toLowerCase()) {
|
|
||||||
case "refresh": {
|
|
||||||
expansion.getGithubScriptManager().fetch();
|
|
||||||
ExpansionUtils.sendMsg(sender, "&aFetching available scripts... Check back in a sec!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
case "list": {
|
|
||||||
final List<GithubScript> availableScripts = manager.getAvailableScripts();
|
|
||||||
final Set<String> scripts = availableScripts.stream().map(GithubScript::getName).collect(Collectors.toSet());
|
|
||||||
|
|
||||||
ExpansionUtils.sendMsg(sender, availableScripts.size() + " &escript" + ExpansionUtils.plural(availableScripts.size()) + " available on Github.", String.join(", ", scripts));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
case "info": {
|
|
||||||
if (args.length < 2) {
|
|
||||||
ExpansionUtils.sendMsg(sender, "&cIncorrect usage! &f/" + command + " git info [name]");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final GithubScript script = manager.getScript(args[1]);
|
|
||||||
|
|
||||||
if (script == null) {
|
|
||||||
ExpansionUtils.sendMsg(sender, "&cThe script &f" + args[1] + " &cdoes not exist!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ExpansionUtils.sendMsg(sender,
|
|
||||||
"&eName: &f" + script.getName(),
|
|
||||||
"&eVersion: &f" + script.getVersion(),
|
|
||||||
"&eDescription: &f" + script.getDescription(),
|
|
||||||
"&eAuthor: &f" + script.getAuthor(),
|
|
||||||
"&eSource URL: &f" + script.getUrl()
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
case "download": {
|
|
||||||
if (args.length < 2) {
|
|
||||||
ExpansionUtils.sendMsg(sender, "&cIncorrect usage! &f/" + command + " git download [name]");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final GithubScript script = manager.getScript(args[1]);
|
|
||||||
|
|
||||||
if (script == null) {
|
|
||||||
ExpansionUtils.sendMsg(sender, "&cThe script &f" + args[1] + " &cdoes not exist!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (new File(expansion.getGithubScriptManager().getJavascriptsFolder(), script.getName() + ".js").exists()) {
|
|
||||||
ExpansionUtils.sendMsg(sender, "&cCould not download " + script.getName() + " because a file with the same name already exist in the javascripts folder.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
manager.downloadScript(script);
|
|
||||||
ExpansionUtils.sendMsg(sender, "&aDownload started. &eCheck the scripts folder in a moment...");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
case "enabled":
|
|
||||||
if (args.length < 2) {
|
|
||||||
ExpansionUtils.sendMsg(sender, "&cIncorrect usage! &f/jsexpansion git enabled [true/false]");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final boolean enabled = Boolean.parseBoolean(args[1]);
|
|
||||||
final PlaceholderAPIPlugin papi = expansion.getPlaceholderAPI();
|
|
||||||
|
|
||||||
papi.getConfig().set("expansions." + command + ".github_script_downloads", enabled);
|
|
||||||
papi.saveConfig();
|
|
||||||
papi.reloadConfig();
|
|
||||||
|
|
||||||
if (!enabled) {
|
|
||||||
if (expansion.getGithubScriptManager() != null) {
|
|
||||||
expansion.getGithubScriptManager().clear();
|
|
||||||
expansion.setGithubScriptManager(null);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (expansion.getGithubScriptManager() == null) {
|
|
||||||
expansion.setGithubScriptManager(new GithubScriptManager(expansion));
|
|
||||||
}
|
|
||||||
expansion.getGithubScriptManager().fetch();
|
|
||||||
}
|
|
||||||
|
|
||||||
ExpansionUtils.sendMsg(sender, "&6Git script downloads set to: &e" + enabled);
|
|
||||||
return;
|
|
||||||
|
|
||||||
default: {
|
|
||||||
ExpansionUtils.sendMsg(sender, "&cIncorrect usage! Type '&f/" + command + "&c' for more help.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull String getAlias() {
|
|
||||||
return "git";
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
package com.extendedclip.papi.expansion.javascript.command;
|
|
||||||
|
|
||||||
import com.extendedclip.papi.expansion.javascript.ExpansionUtils;
|
|
||||||
import org.bukkit.ChatColor;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public abstract class ICommand {
|
|
||||||
|
|
||||||
public String command;
|
|
||||||
|
|
||||||
public abstract void execute(CommandSender sender, String[] args);
|
|
||||||
|
|
||||||
public abstract @NotNull String getAlias();
|
|
||||||
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
package com.extendedclip.papi.expansion.javascript.command;
|
|
||||||
|
|
||||||
import com.extendedclip.papi.expansion.javascript.ExpansionUtils;
|
|
||||||
import com.extendedclip.papi.expansion.javascript.JavascriptExpansion;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class ListCommand extends ICommand {
|
|
||||||
|
|
||||||
private final JavascriptExpansion expansion;
|
|
||||||
|
|
||||||
public ListCommand(JavascriptExpansion expansion) {
|
|
||||||
this.expansion = expansion;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(CommandSender sender, String[] args) {
|
|
||||||
|
|
||||||
final List<String> loaded = expansion.getLoadedIdentifiers();
|
|
||||||
ExpansionUtils.sendMsg(sender,loaded.size() + " &7script" + ExpansionUtils.plural(loaded.size()) + " loaded.",
|
|
||||||
String.join(", ", loaded));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@NotNull
|
|
||||||
public String getAlias() {
|
|
||||||
return "list";
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,57 +0,0 @@
|
|||||||
package com.extendedclip.papi.expansion.javascript.command;
|
|
||||||
|
|
||||||
import com.extendedclip.papi.expansion.javascript.ExpansionUtils;
|
|
||||||
import com.extendedclip.papi.expansion.javascript.JavascriptExpansion;
|
|
||||||
import com.extendedclip.papi.expansion.javascript.JavascriptPlaceholder;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.OfflinePlayer;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
public class ParseCommand extends ICommand {
|
|
||||||
|
|
||||||
private final JavascriptExpansion expansion;
|
|
||||||
|
|
||||||
public ParseCommand(JavascriptExpansion expansion) {
|
|
||||||
this.expansion = expansion;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(CommandSender sender, String[] args) {
|
|
||||||
if (args.length < 2) {
|
|
||||||
ExpansionUtils.sendMsg(sender, "&cIncorrect usage! &f/" + command + " parse [me/player] [code]");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final String script = String.join(" ", Arrays.copyOfRange(args, 1, args.length));
|
|
||||||
final JavascriptPlaceholder placeholder = new JavascriptPlaceholder(expansion.getGlobalEngine(), "parse-command", String.join(" ", script));
|
|
||||||
|
|
||||||
if ("me".equalsIgnoreCase(args[0])) {
|
|
||||||
if (!(sender instanceof Player)) {
|
|
||||||
ExpansionUtils.sendMsg(sender, "&cOnly players can run this command!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sender.sendMessage(placeholder.evaluate((Player) sender));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final OfflinePlayer player = Bukkit.getOfflinePlayer(args[1]);
|
|
||||||
|
|
||||||
if (!player.hasPlayedBefore() || player.getName() == null) {
|
|
||||||
ExpansionUtils.sendMsg(sender, "&cUnknown player " + args[1]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sender.sendMessage(placeholder.evaluate(player));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@NotNull
|
|
||||||
public String getAlias() {
|
|
||||||
return "parse";
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
package com.extendedclip.papi.expansion.javascript.command;
|
|
||||||
|
|
||||||
import com.extendedclip.papi.expansion.javascript.ExpansionUtils;
|
|
||||||
import com.extendedclip.papi.expansion.javascript.JavascriptExpansion;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
public class ReloadCommand extends ICommand {
|
|
||||||
|
|
||||||
private final JavascriptExpansion expansion;
|
|
||||||
|
|
||||||
public ReloadCommand(JavascriptExpansion expansion) {
|
|
||||||
this.expansion = expansion;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(CommandSender sender, String[] args) {
|
|
||||||
|
|
||||||
ExpansionUtils.sendMsg(sender, "&aJavascriptExpansion reloading...");
|
|
||||||
final int scripts = expansion.reloadScripts();
|
|
||||||
ExpansionUtils.sendMsg(sender, scripts + " &7script" + ExpansionUtils.plural(scripts) + " loaded");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@NotNull
|
|
||||||
public String getAlias() {
|
|
||||||
return "reload";
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user