feat: add MavenDependLoader
Signed-off-by: MiaoWoo <admin@yumc.pw>
This commit is contained in:
parent
e2f9bbf587
commit
56152657c8
12
pom.xml
12
pom.xml
@ -2,7 +2,7 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>pw.yumc</groupId>
|
<groupId>pw.yumc</groupId>
|
||||||
<artifactId>MiaoScript</artifactId>
|
<artifactId>MiaoScript</artifactId>
|
||||||
<version>0.20.0</version>
|
<version>0.21.1</version>
|
||||||
<developers>
|
<developers>
|
||||||
<developer>
|
<developer>
|
||||||
<id>502647092</id>
|
<id>502647092</id>
|
||||||
@ -16,9 +16,6 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<resource>
|
<resource>
|
||||||
<directory>src/main/resources</directory>
|
<directory>src/main/resources</directory>
|
||||||
<excludes>
|
|
||||||
<exclude>dev-plugins/**</exclude>
|
|
||||||
</excludes>
|
|
||||||
<filtering>true</filtering>
|
<filtering>true</filtering>
|
||||||
</resource>
|
</resource>
|
||||||
</resources>
|
</resources>
|
||||||
@ -230,7 +227,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-websocket</artifactId>
|
<artifactId>spring-websocket</artifactId>
|
||||||
<version>5.3.13</version>
|
<version>5.3.18</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -239,5 +236,10 @@
|
|||||||
<version>9.0.35</version>
|
<version>9.0.35</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.zaxxer</groupId>
|
||||||
|
<artifactId>HikariCP</artifactId>
|
||||||
|
<version>4.0.3</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
@ -2,6 +2,7 @@ package pw.yumc.MiaoScript;
|
|||||||
|
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
import pw.yumc.MiaoScript.api.ScriptEngine;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 喵式脚本
|
* 喵式脚本
|
||||||
|
@ -2,6 +2,7 @@ package pw.yumc.MiaoScript;
|
|||||||
|
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import net.md_5.bungee.api.plugin.Plugin;
|
import net.md_5.bungee.api.plugin.Plugin;
|
||||||
|
import pw.yumc.MiaoScript.api.ScriptEngine;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created with IntelliJ IDEA
|
* Created with IntelliJ IDEA
|
||||||
|
@ -2,6 +2,7 @@ package pw.yumc.MiaoScript;
|
|||||||
|
|
||||||
import cn.nukkit.plugin.PluginBase;
|
import cn.nukkit.plugin.PluginBase;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
|
import pw.yumc.MiaoScript.api.ScriptEngine;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author MiaoWoo
|
* @author MiaoWoo
|
||||||
|
@ -11,6 +11,7 @@ import org.spongepowered.api.event.game.state.GameStartingServerEvent;
|
|||||||
import org.spongepowered.api.event.game.state.GameStoppingServerEvent;
|
import org.spongepowered.api.event.game.state.GameStoppingServerEvent;
|
||||||
import org.spongepowered.api.plugin.Plugin;
|
import org.spongepowered.api.plugin.Plugin;
|
||||||
import pw.yumc.MiaoScript.api.MiaoScriptAPI;
|
import pw.yumc.MiaoScript.api.MiaoScriptAPI;
|
||||||
|
import pw.yumc.MiaoScript.api.ScriptEngine;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import org.springframework.context.ApplicationContext;
|
|||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
|
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
|
||||||
|
import pw.yumc.MiaoScript.api.ScriptEngine;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
package pw.yumc.MiaoScript;
|
package pw.yumc.MiaoScript.api;
|
||||||
|
|
||||||
import pw.yumc.MiaoScript.api.MiaoScriptAPI;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -16,7 +14,7 @@ import java.nio.file.Paths;
|
|||||||
* Created on 2017/10/9 12:40.
|
* Created on 2017/10/9 12:40.
|
||||||
*/
|
*/
|
||||||
public class Base {
|
public class Base {
|
||||||
private Object instance;
|
private final Object instance;
|
||||||
|
|
||||||
Base(Object instance) {
|
Base(Object instance) {
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
@ -42,6 +40,10 @@ public class Base {
|
|||||||
return JavaScriptTask.class;
|
return JavaScriptTask.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public File[] loadMavenDepend(String groupId, String artifactId, String version) {
|
||||||
|
return MiaoScriptAPI.loadMavenDepend(groupId, artifactId, version);
|
||||||
|
}
|
||||||
|
|
||||||
public String read(String path) throws IOException {
|
public String read(String path) throws IOException {
|
||||||
return read(Paths.get(path));
|
return read(Paths.get(path));
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package pw.yumc.MiaoScript;
|
package pw.yumc.MiaoScript.api;
|
||||||
|
|
||||||
import java.util.concurrent.Delayed;
|
import java.util.concurrent.Delayed;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
@ -1,17 +1,48 @@
|
|||||||
package pw.yumc.MiaoScript.api;
|
package pw.yumc.MiaoScript.api;
|
||||||
|
|
||||||
import pw.yumc.MiaoScript.MiaoScriptEngine;
|
import pw.yumc.MiaoScript.api.loader.MavenDependLoader;
|
||||||
import pw.yumc.MiaoScript.ScriptEngine;
|
import pw.yumc.MiaoScript.api.plugin.PluginManager;
|
||||||
|
import pw.yumc.MiaoScript.engine.MiaoScriptEngine;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
public class MiaoScriptAPI {
|
public class MiaoScriptAPI {
|
||||||
public static final String VERSION = "0.20.0";
|
public static final String VERSION = "0.21.1";
|
||||||
|
private static String root;
|
||||||
|
private static String libPath;
|
||||||
private static ScriptEngine scriptEngine;
|
private static ScriptEngine scriptEngine;
|
||||||
|
private static PluginManager pluginManager;
|
||||||
|
|
||||||
public static void setEngine(ScriptEngine scriptEngine) {
|
public static String getRoot() {
|
||||||
MiaoScriptAPI.scriptEngine = scriptEngine;
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setRoot(String root) {
|
||||||
|
MiaoScriptAPI.root = root;
|
||||||
|
MiaoScriptAPI.libPath = Paths.get(root, "libs").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MiaoScriptEngine getEngine() {
|
public static MiaoScriptEngine getEngine() {
|
||||||
return MiaoScriptAPI.scriptEngine.getEngine();
|
return MiaoScriptAPI.scriptEngine.getEngine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setEngine(ScriptEngine scriptEngine) {
|
||||||
|
MiaoScriptAPI.scriptEngine = scriptEngine;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PluginManager getPluginManager() {
|
||||||
|
return pluginManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setPluginManager(Object pluginManager) {
|
||||||
|
MiaoScriptAPI.pluginManager = getEngine().getInterface(pluginManager, PluginManager.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static File[] loadMavenDepend(String groupId, String artifactId, String version) {
|
||||||
|
if (root == null || scriptEngine == null) {
|
||||||
|
throw new IllegalStateException("root can't be null before loadMavenDepend.");
|
||||||
|
}
|
||||||
|
return MavenDependLoader.load(MiaoScriptAPI.libPath, groupId, artifactId, version);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package pw.yumc.MiaoScript;
|
package pw.yumc.MiaoScript.api;
|
||||||
|
|
||||||
import javax.script.Bindings;
|
import javax.script.Bindings;
|
||||||
import javax.script.ScriptEngine;
|
import javax.script.ScriptEngine;
|
@ -1,7 +1,7 @@
|
|||||||
package pw.yumc.MiaoScript;
|
package pw.yumc.MiaoScript.api;
|
||||||
|
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import pw.yumc.MiaoScript.api.MiaoScriptAPI;
|
import pw.yumc.MiaoScript.engine.MiaoScriptEngine;
|
||||||
|
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
@ -25,6 +25,7 @@ public class ScriptEngine {
|
|||||||
this.root = root;
|
this.root = root;
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.base = new Base(instance);
|
this.base = new Base(instance);
|
||||||
|
MiaoScriptAPI.setRoot(root);
|
||||||
MiaoScriptAPI.setEngine(this);
|
MiaoScriptAPI.setEngine(this);
|
||||||
}
|
}
|
||||||
|
|
@ -7,12 +7,12 @@ import org.bukkit.event.HandlerList;
|
|||||||
import javax.script.Bindings;
|
import javax.script.Bindings;
|
||||||
|
|
||||||
public class ScriptEvent extends Event implements Cancellable {
|
public class ScriptEvent extends Event implements Cancellable {
|
||||||
private final String plugin;
|
private final Bindings plugin;
|
||||||
private final String event;
|
private final String event;
|
||||||
private final Bindings data;
|
private final Bindings data;
|
||||||
private boolean cancelled = false;
|
private boolean cancelled = false;
|
||||||
|
|
||||||
public ScriptEvent(String plugin, String event, Bindings data) {
|
public ScriptEvent(Bindings plugin, String event, Bindings data) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.event = event;
|
this.event = event;
|
||||||
this.data = data;
|
this.data = data;
|
||||||
@ -23,7 +23,7 @@ public class ScriptEvent extends Event implements Cancellable {
|
|||||||
*
|
*
|
||||||
* @return PluginName
|
* @return PluginName
|
||||||
*/
|
*/
|
||||||
public String getPlugin() {
|
public Bindings getPlugin() {
|
||||||
return plugin;
|
return plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
48
src/main/java/pw/yumc/MiaoScript/api/loader/JarLoader.java
Normal file
48
src/main/java/pw/yumc/MiaoScript/api/loader/JarLoader.java
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package pw.yumc.MiaoScript.api.loader;
|
||||||
|
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.lang.invoke.MethodHandle;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
public class JarLoader {
|
||||||
|
private static Object ucp;
|
||||||
|
private static MethodHandle addURLMethodHandle;
|
||||||
|
|
||||||
|
static {
|
||||||
|
initReflect();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
public static File load(File file) {
|
||||||
|
addURLMethodHandle.invoke(ucp, file.toURI().toURL());
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void initReflect() {
|
||||||
|
try {
|
||||||
|
ClassLoader loader = Thread.currentThread().getContextClassLoader();
|
||||||
|
Field theUnsafe = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
|
||||||
|
theUnsafe.setAccessible(true);
|
||||||
|
sun.misc.Unsafe unsafe = (sun.misc.Unsafe) theUnsafe.get(null);
|
||||||
|
Field field = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
|
||||||
|
MethodHandles.Lookup lookup = (MethodHandles.Lookup) unsafe.getObject(unsafe.staticFieldBase(field), unsafe.staticFieldOffset(field));
|
||||||
|
Field ucpField;
|
||||||
|
try {
|
||||||
|
ucpField = loader.getClass().getDeclaredField("ucp");
|
||||||
|
} catch (NoSuchFieldException e) {
|
||||||
|
ucpField = loader.getClass().getSuperclass().getDeclaredField("ucp");
|
||||||
|
}
|
||||||
|
long offset = unsafe.objectFieldOffset(ucpField);
|
||||||
|
ucp = unsafe.getObject(loader, offset);
|
||||||
|
Method method = ucp.getClass().getDeclaredMethod("addURL", URL.class);
|
||||||
|
addURLMethodHandle = lookup.unreflect(method);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,80 @@
|
|||||||
|
package pw.yumc.MiaoScript.api.loader;
|
||||||
|
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
import java.nio.MappedByteBuffer;
|
||||||
|
import java.nio.channels.FileChannel;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.nio.file.StandardCopyOption;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
|
||||||
|
public class MavenDependLoader {
|
||||||
|
private static final String MavenRepo = "https://maven.aliyun.com/repository/public";
|
||||||
|
|
||||||
|
public static File[] load(String libPath, String groupId, String artifactId, String version) {
|
||||||
|
return new File[]{
|
||||||
|
downloadAndCheckSha1(libPath, groupId, artifactId, version, "pom"),
|
||||||
|
JarLoader.load(downloadAndCheckSha1(libPath, groupId, artifactId, version, "jar"))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
public static File downloadAndCheckSha1(String libPath, String groupId, String artifactId, String version, String ext) {
|
||||||
|
File sha1 = getMavenFile(libPath, groupId, artifactId, version, ext + ".sha1");
|
||||||
|
if (!sha1.exists()) {
|
||||||
|
downloadFile(sha1, groupId, artifactId, version, ext + ".sha1");
|
||||||
|
}
|
||||||
|
File file = getMavenFile(libPath, groupId, artifactId, version, ext);
|
||||||
|
if (!file.exists()) {
|
||||||
|
downloadFile(file, groupId, artifactId, version, ext);
|
||||||
|
}
|
||||||
|
if (!new String(Files.readAllBytes(sha1.toPath())).equals(getSha1(file))) {
|
||||||
|
file.delete();
|
||||||
|
throw new IllegalStateException("file " + file.getName() + " sha1 not match.");
|
||||||
|
}
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static File getMavenFile(String libPath, String groupId, String artifactId, String version, String ext) {
|
||||||
|
return Paths.get(libPath, groupId.replace(".", File.separator), artifactId, version, String.format("%s-%s.%s", artifactId, version, ext)).toFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
public static void downloadFile(File target, String groupId, String artifactId, String version, String ext) {
|
||||||
|
target.getParentFile().mkdirs();
|
||||||
|
URLConnection connection = new URL(MavenRepo +
|
||||||
|
String.format("/%1$s/%2$s/%3$s/%2$s-%3$s.%4$s",
|
||||||
|
groupId.replace(".", "/"),
|
||||||
|
artifactId,
|
||||||
|
version,
|
||||||
|
ext)
|
||||||
|
).openConnection();
|
||||||
|
connection.setConnectTimeout(5000);
|
||||||
|
connection.setReadTimeout(30000);
|
||||||
|
connection.setUseCaches(true);
|
||||||
|
Files.copy(connection.getInputStream(), target.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
private static String getSha1(File file) {
|
||||||
|
MessageDigest digest = MessageDigest.getInstance("SHA-1");
|
||||||
|
FileInputStream in = new FileInputStream(file);
|
||||||
|
FileChannel ch = in.getChannel();
|
||||||
|
MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0, file.length());
|
||||||
|
digest.update(byteBuffer);
|
||||||
|
return getHash(digest.digest());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getHash(byte[] bytes) {
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
for (byte b : bytes) {
|
||||||
|
result.append(String.format("%02x", b));
|
||||||
|
}
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package pw.yumc.MiaoScript.api.plugin;
|
||||||
|
|
||||||
|
import javax.script.Bindings;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface PluginManager {
|
||||||
|
Map<String, Bindings> getPlugins();
|
||||||
|
|
||||||
|
Bindings getPlugin(String name);
|
||||||
|
}
|
@ -1,19 +1,15 @@
|
|||||||
package pw.yumc.MiaoScript;
|
package pw.yumc.MiaoScript.engine;
|
||||||
|
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
|
import pw.yumc.MiaoScript.api.loader.JarLoader;
|
||||||
|
import pw.yumc.MiaoScript.api.loader.MavenDependLoader;
|
||||||
|
|
||||||
import javax.script.ScriptEngine;
|
import javax.script.ScriptEngine;
|
||||||
import javax.script.*;
|
import javax.script.*;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.lang.invoke.MethodHandle;
|
|
||||||
import java.lang.invoke.MethodHandles;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.net.URL;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.StandardCopyOption;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -23,12 +19,9 @@ import java.util.HashMap;
|
|||||||
* @since 2016年8月29日 上午7:51:43
|
* @since 2016年8月29日 上午7:51:43
|
||||||
*/
|
*/
|
||||||
public class MiaoScriptEngine implements ScriptEngine, Invocable {
|
public class MiaoScriptEngine implements ScriptEngine, Invocable {
|
||||||
private static String MavenRepo = "https://maven.aliyun.com/repository/public";
|
|
||||||
private static MiaoScriptEngine DEFAULT;
|
private static MiaoScriptEngine DEFAULT;
|
||||||
private static final ScriptEngineManager manager;
|
private static final ScriptEngineManager manager;
|
||||||
|
|
||||||
private Object ucp;
|
|
||||||
private MethodHandle addURLMethodHandle;
|
|
||||||
private ScriptEngine engine;
|
private ScriptEngine engine;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@ -88,71 +81,26 @@ public class MiaoScriptEngine implements ScriptEngine, Invocable {
|
|||||||
for (String dir : dirs) {
|
for (String dir : dirs) {
|
||||||
File nashorn = new File(dir, "nashorn.jar");
|
File nashorn = new File(dir, "nashorn.jar");
|
||||||
if (nashorn.exists()) {
|
if (nashorn.exists()) {
|
||||||
this.loadJar(nashorn);
|
JarLoader.load(nashorn);
|
||||||
this.createEngineByName(engineType);
|
this.createEngineByName(engineType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initReflect() {
|
|
||||||
try {
|
|
||||||
ClassLoader loader = Thread.currentThread().getContextClassLoader();
|
|
||||||
Field theUnsafe = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
|
|
||||||
theUnsafe.setAccessible(true);
|
|
||||||
sun.misc.Unsafe unsafe = (sun.misc.Unsafe) theUnsafe.get(null);
|
|
||||||
Field field = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
|
|
||||||
MethodHandles.Lookup lookup = (MethodHandles.Lookup) unsafe.getObject(unsafe.staticFieldBase(field), unsafe.staticFieldOffset(field));
|
|
||||||
Field ucpField;
|
|
||||||
try {
|
|
||||||
ucpField = loader.getClass().getDeclaredField("ucp");
|
|
||||||
} catch (NoSuchFieldException e) {
|
|
||||||
ucpField = loader.getClass().getSuperclass().getDeclaredField("ucp");
|
|
||||||
}
|
|
||||||
long offset = unsafe.objectFieldOffset(ucpField);
|
|
||||||
ucp = unsafe.getObject(loader, offset);
|
|
||||||
Method method = ucp.getClass().getDeclaredMethod("addURL", URL.class);
|
|
||||||
addURLMethodHandle = lookup.unreflect(method);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
private void loadNetworkNashorn(String engineRoot) {
|
private void loadNetworkNashorn(String engineRoot) {
|
||||||
initReflect();
|
File libRootFile = new File(engineRoot, "libs");
|
||||||
File libRootFile = new File(engineRoot, "lib");
|
|
||||||
libRootFile.mkdirs();
|
libRootFile.mkdirs();
|
||||||
String libRoot = libRootFile.getCanonicalPath();
|
String libRoot = libRootFile.getCanonicalPath();
|
||||||
downloadJar(libRoot, "org.openjdk.nashorn", "nashorn-core", "15.3");
|
MavenDependLoader.load(libRoot, "org.openjdk.nashorn", "nashorn-core", "15.3");
|
||||||
downloadJar(libRoot, "org.ow2.asm", "asm", "9.2");
|
MavenDependLoader.load(libRoot, "org.ow2.asm", "asm", "9.2");
|
||||||
downloadJar(libRoot, "org.ow2.asm", "asm-commons", "9.2");
|
MavenDependLoader.load(libRoot, "org.ow2.asm", "asm-commons", "9.2");
|
||||||
downloadJar(libRoot, "org.ow2.asm", "asm-tree", "9.2");
|
MavenDependLoader.load(libRoot, "org.ow2.asm", "asm-tree", "9.2");
|
||||||
downloadJar(libRoot, "org.ow2.asm", "asm-util", "9.2");
|
MavenDependLoader.load(libRoot, "org.ow2.asm", "asm-util", "9.2");
|
||||||
Class<?> NashornScriptEngineFactory = Class.forName("org.openjdk.nashorn.api.scripting.NashornScriptEngineFactory");
|
Class<?> NashornScriptEngineFactory = Class.forName("org.openjdk.nashorn.api.scripting.NashornScriptEngineFactory");
|
||||||
Method getScriptEngine = NashornScriptEngineFactory.getMethod("getScriptEngine", ClassLoader.class);
|
Method getScriptEngine = NashornScriptEngineFactory.getMethod("getScriptEngine");
|
||||||
Object factory = NashornScriptEngineFactory.newInstance();
|
Object factory = NashornScriptEngineFactory.newInstance();
|
||||||
engine = (ScriptEngine) getScriptEngine.invoke(factory, ClassLoader.getSystemClassLoader());
|
engine = (ScriptEngine) getScriptEngine.invoke(factory);
|
||||||
}
|
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
private void loadJar(File file) {
|
|
||||||
addURLMethodHandle.invoke(ucp, file.toURI().toURL());
|
|
||||||
}
|
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
private void downloadJar(String engineRoot, String groupId, String artifactId, String version) {
|
|
||||||
File lib = new File(engineRoot, String.format("%s-%s.jar", artifactId, version));
|
|
||||||
if (!lib.exists()) {
|
|
||||||
Files.copy(new URL(MavenRepo +
|
|
||||||
String.format("/%1$s/%2$s/%3$s/%2$s-%3$s.jar",
|
|
||||||
groupId.replace(".", "/"),
|
|
||||||
artifactId,
|
|
||||||
version)
|
|
||||||
).openStream(),
|
|
||||||
lib.toPath(),
|
|
||||||
StandardCopyOption.REPLACE_EXISTING);
|
|
||||||
}
|
|
||||||
this.loadJar(lib);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createEngineByName(String engineType) {
|
private void createEngineByName(String engineType) {
|
@ -16,7 +16,7 @@ var global = this;
|
|||||||
global.logger = logger
|
global.logger = logger
|
||||||
// Development Env Detect
|
// Development Env Detect
|
||||||
global.root = root || "src/main/resources"
|
global.root = root || "src/main/resources"
|
||||||
checkDebug()
|
readEnvironment()
|
||||||
if (!global.debug) {
|
if (!global.debug) {
|
||||||
checkUpgrade()
|
checkUpgrade()
|
||||||
}
|
}
|
||||||
@ -50,24 +50,24 @@ var global = this;
|
|||||||
global.engineDisableImpl && global.engineDisableImpl()
|
global.engineDisableImpl && global.engineDisableImpl()
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkDebug() {
|
function readEnvironment() {
|
||||||
if (__FILE__.indexOf('!') === -1) {
|
if (__FILE__.indexOf('!') === -1) {
|
||||||
logger.info('Loading custom BIOS file ' + __FILE__)
|
logger.info('loading custom BIOS file ' + __FILE__)
|
||||||
global.debug = true
|
global.debug = true
|
||||||
}
|
}
|
||||||
if (Files.exists(Paths.get(root, "debug"))) {
|
if (Files.exists(Paths.get(root, "debug"))) {
|
||||||
logger.info('Running in debug mode...')
|
logger.info('running in debug mode...')
|
||||||
global.debug = true
|
global.debug = true
|
||||||
}
|
}
|
||||||
if (Files.exists(Paths.get(root, "level"))) {
|
if (Files.exists(Paths.get(root, "level"))) {
|
||||||
global.level = base.read(Paths.get(root, "level"))
|
global.level = base.read(Paths.get(root, "level"))
|
||||||
logger.info('Set system level to [' + global.level + ']...')
|
logger.info('set system level to [' + global.level + ']...')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkUpgrade() {
|
function checkUpgrade() {
|
||||||
if (Files.exists(Paths.get(root, "upgrade"))) {
|
if (Files.exists(Paths.get(root, "upgrade"))) {
|
||||||
logger.info('Found upgrade file starting upgrade...')
|
logger.info('found upgrade file starting upgrade...')
|
||||||
base.move(Paths.get(root, "node_modules"), Paths.get(root, "old_node_modules"))
|
base.move(Paths.get(root, "node_modules"), Paths.get(root, "old_node_modules"))
|
||||||
base.delete(Paths.get(root, "upgrade"))
|
base.delete(Paths.get(root, "upgrade"))
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,30 @@
|
|||||||
// @ts-check
|
// @ts-check
|
||||||
(
|
(
|
||||||
/**
|
/**
|
||||||
* @param {{ info: (arg0: string) => void; }} logger
|
* @param {{
|
||||||
|
* info: (arg0: string) => void;
|
||||||
|
* warn: (arg0: string) => void;
|
||||||
|
* debug: (arg0: string) => void;
|
||||||
|
* error: (arg0: string) => void;
|
||||||
|
* warning: (arg0: string) => void;
|
||||||
|
* }} logger
|
||||||
*/
|
*/
|
||||||
function (logger) {
|
function (logger) {
|
||||||
function log() {
|
function log() {
|
||||||
logger.info(Array.prototype.join.call(arguments, ' '))
|
logger.info(Array.prototype.join.call(arguments, ' '))
|
||||||
}
|
}
|
||||||
|
function warn() {
|
||||||
|
logger.warn(Array.prototype.join.call(arguments, ' '))
|
||||||
|
}
|
||||||
|
function debug() {
|
||||||
|
logger.debug(Array.prototype.join.call(arguments, ' '))
|
||||||
|
}
|
||||||
|
function error() {
|
||||||
|
logger.error(Array.prototype.join.call(arguments, ' '))
|
||||||
|
}
|
||||||
|
function warning() {
|
||||||
|
logger.warning(Array.prototype.join.call(arguments, ' '))
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* @param {string} prefix
|
* @param {string} prefix
|
||||||
*/
|
*/
|
||||||
@ -16,13 +34,23 @@
|
|||||||
log('[' + prefix + ']', Array.prototype.join.call(arguments, ' '))
|
log('[' + prefix + ']', Array.prototype.join.call(arguments, ' '))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {
|
var logProxy = {
|
||||||
log: log,
|
log: log,
|
||||||
info: log,
|
info: log,
|
||||||
ex: log,
|
ex: log,
|
||||||
trace: global.level === "trace" ? _proxy('TRACE') : global.noop,
|
trace: global.level === "trace" ? _proxy('TRACE') : global.noop,
|
||||||
debug: global.debug ? _proxy('DEBUG') : global.noop,
|
debug: global.debug ? logger.debug ? debug : _proxy('DEBUG') : global.noop,
|
||||||
warn: _proxy('WARN'),
|
warn: _proxy('WARN'),
|
||||||
error: _proxy('ERROR')
|
error: _proxy('ERROR')
|
||||||
}
|
}
|
||||||
|
if (logger.warn) {
|
||||||
|
logProxy.warn = warn
|
||||||
|
}
|
||||||
|
if (logger.warning) {
|
||||||
|
logProxy.warn = warning
|
||||||
|
}
|
||||||
|
if (logger.error) {
|
||||||
|
logProxy.error = error
|
||||||
|
}
|
||||||
|
return logProxy
|
||||||
})
|
})
|
||||||
|
@ -217,7 +217,7 @@
|
|||||||
var filename = file.name
|
var filename = file.name
|
||||||
var lastDotIndexOf = filename.lastIndexOf('.')
|
var lastDotIndexOf = filename.lastIndexOf('.')
|
||||||
if (lastDotIndexOf == -1) {
|
if (lastDotIndexOf == -1) {
|
||||||
throw Error('require module must include file ext.')
|
throw Error('require ' + file + ' error: module must include file ext.')
|
||||||
}
|
}
|
||||||
var name = filename.substring(0, lastDotIndexOf)
|
var name = filename.substring(0, lastDotIndexOf)
|
||||||
var ext = filename.substring(lastDotIndexOf + 1)
|
var ext = filename.substring(lastDotIndexOf + 1)
|
||||||
@ -268,8 +268,9 @@
|
|||||||
}
|
}
|
||||||
// 2019-09-19 使用 扩展函数直接 load 无需保存/删除文件
|
// 2019-09-19 使用 扩展函数直接 load 无需保存/删除文件
|
||||||
// 2020-02-16 结尾新增换行 防止有注释导致加载失败
|
// 2020-02-16 结尾新增换行 防止有注释导致加载失败
|
||||||
|
var wrapperScript = '(function (module, exports, require, __dirname, __filename) {' + script + '\n});'
|
||||||
var compiledWrapper = engineLoad({
|
var compiledWrapper = engineLoad({
|
||||||
script: '(function (module, exports, require, __dirname, __filename) {' + script + '\n});',
|
script: wrapperScript,
|
||||||
name: optional.id
|
name: optional.id
|
||||||
})
|
})
|
||||||
compiledWrapper.apply(module.exports, [
|
compiledWrapper.apply(module.exports, [
|
||||||
@ -306,19 +307,24 @@
|
|||||||
var module_name = name.startsWith('@') ? name_arr[0] + '/' + name_arr[1] : name_arr[0]
|
var module_name = name.startsWith('@') ? name_arr[0] + '/' + name_arr[1] : name_arr[0]
|
||||||
var target = MS_NODE_PATH + separatorChar + module_name
|
var target = MS_NODE_PATH + separatorChar + module_name
|
||||||
var _package = new File(target, 'package.json')
|
var _package = new File(target, 'package.json')
|
||||||
if (_package.exists()) {
|
if (_package.exists()) { return name }
|
||||||
return
|
|
||||||
}
|
|
||||||
// at windows need replace file name java.lang.IllegalArgumentException: Invalid prefix or suffix
|
// at windows need replace file name java.lang.IllegalArgumentException: Invalid prefix or suffix
|
||||||
var info = fetchPackageInfo(module_name)
|
var info = fetchPackageInfo(module_name)
|
||||||
var url = info.versions[ModulesVersionLock[module_name] || info['dist-tags']['latest']].dist.tarball
|
var latest_version = info['dist-tags']['latest']
|
||||||
console.log('fetch node_module ' + module_name + ' from ' + url + ' waiting...')
|
var version = ModulesVersionLock[module_name] || latest_version
|
||||||
|
var _version = info.versions[version] || info.versions[latest_version]
|
||||||
|
var url = _version.dist.tarball
|
||||||
|
console.log('fetch node_module ' + module_name + ' version ' + version + ' waiting...')
|
||||||
return executor.submit(new Callable(function () {
|
return executor.submit(new Callable(function () {
|
||||||
var tis = new TarInputStream(new BufferedInputStream(new GZIPInputStream(new URL(url).openStream())))
|
var tis = new TarInputStream(new BufferedInputStream(new GZIPInputStream(new URL(url).openStream())))
|
||||||
var entry
|
var entry
|
||||||
while ((entry = tis.getNextEntry()) != null) {
|
while ((entry = tis.getNextEntry()) != null) {
|
||||||
var targetPath = Paths.get(target + separatorChar + entry.getName().substring(8))
|
var targetPath = Paths.get(target + separatorChar + entry.getName().substring(8))
|
||||||
targetPath.toFile().getParentFile().mkdirs()
|
var parentFile = targetPath.toFile().getParentFile()
|
||||||
|
if (!parentFile.isDirectory()) {
|
||||||
|
parentFile.delete()
|
||||||
|
parentFile.mkdirs()
|
||||||
|
}
|
||||||
Files.copy(tis, targetPath, StandardCopyOption.REPLACE_EXISTING)
|
Files.copy(tis, targetPath, StandardCopyOption.REPLACE_EXISTING)
|
||||||
}
|
}
|
||||||
return name
|
return name
|
||||||
@ -418,13 +424,8 @@
|
|||||||
if (optional.local || optional.recursive || notFoundModules[name]) {
|
if (optional.local || optional.recursive || notFoundModules[name]) {
|
||||||
throw new Error("Can't found module " + name + '(' + JSON.stringify(optional) + ') at local ' + path + ' or network!')
|
throw new Error("Can't found module " + name + '(' + JSON.stringify(optional) + ') at local ' + path + ' or network!')
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
optional.recursive = true
|
optional.recursive = true
|
||||||
return _require(download(name), path, optional)
|
return _require(download(name), path, optional)
|
||||||
} catch (ex) {
|
|
||||||
notFoundModules[name] = true
|
|
||||||
throw new Error("Can't found module " + name + ' in directory ' + path + ' ERROR: ' + ex)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
setCacheModule(file, optional)
|
setCacheModule(file, optional)
|
||||||
return _requireFile(file, optional)
|
return _requireFile(file, optional)
|
||||||
@ -592,7 +593,8 @@
|
|||||||
|
|
||||||
function initVersionLock() {
|
function initVersionLock() {
|
||||||
try {
|
try {
|
||||||
ModulesVersionLock = JSON.parse(fetchContent('https://ms.yumc.pw/api/plugin/download/name/version_lock', 5))
|
var version_lock_url = 'https://ms.yumc.pw/api/plugin/download/name/version_lock' + (global.debug ? '-debug' : '')
|
||||||
|
ModulesVersionLock = JSON.parse(fetchContent(version_lock_url, 5))
|
||||||
try {
|
try {
|
||||||
ModulesVersionLock = __assign(ModulesVersionLock, JSON.parse(base.read(localVersionLockFile)))
|
ModulesVersionLock = __assign(ModulesVersionLock, JSON.parse(base.read(localVersionLockFile)))
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -1,69 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
/**
|
|
||||||
* Hello Wrold 测试插件
|
|
||||||
*/
|
|
||||||
/*global Java, base, module, exports, require*/
|
|
||||||
|
|
||||||
var event = require('api/event');
|
|
||||||
var wrapper = require('api/wrapper');
|
|
||||||
var command = require('api/command');
|
|
||||||
var server = require('api/server');
|
|
||||||
var fs = require('fs');
|
|
||||||
|
|
||||||
var description = {
|
|
||||||
name: 'HelloWorld',
|
|
||||||
version: '1.0',
|
|
||||||
author: 'MiaoWoo',
|
|
||||||
commands: {
|
|
||||||
'hello': {
|
|
||||||
description: 'HelloWorld主命令'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function load() {
|
|
||||||
console.log('载入 Hello Wrold 测试插件!');
|
|
||||||
}
|
|
||||||
|
|
||||||
function enable() {
|
|
||||||
// noinspection JSUnusedLocalSymbols
|
|
||||||
command.on(this, 'hello', {
|
|
||||||
cmd: function(sender, command, args) {
|
|
||||||
engineLoad(fs.file(root, 'test.js'));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
console.log('启用 Hello World 测试插件!');
|
|
||||||
switch (DetectServerType) {
|
|
||||||
case ServerType.Bukkit:
|
|
||||||
event.on(this, 'PlayerLoginEvent', function join(event) {
|
|
||||||
send(event, wrapper.player(event.player));
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case ServerType.Sponge:
|
|
||||||
event.on(this, 'ClientConnectionEvent.Join', function join(event) {
|
|
||||||
send(event, wrapper.player(event.targetEntity));
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function send(event, player) {
|
|
||||||
// noinspection JSUnresolvedVariable
|
|
||||||
console.debug('玩家', player.getName(), "触发事件", event.class.simpleName);
|
|
||||||
setTimeout(function() {
|
|
||||||
// noinspection JSUnresolvedVariable
|
|
||||||
player.sendMessage("§a欢迎来到 §bMiaoScript §a的世界! 当前在线: " + server.players().length)
|
|
||||||
}, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
function disable() {
|
|
||||||
console.log('卸载 Hello World 测试插件!');
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
description: description,
|
|
||||||
load: load,
|
|
||||||
enable: enable,
|
|
||||||
disable: disable
|
|
||||||
};
|
|
@ -1,88 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
/*global Java, base, module, exports, require*/
|
|
||||||
var event = require('api/event');
|
|
||||||
var task = require('api/task');
|
|
||||||
var http = require('http');
|
|
||||||
var fs = require('fs');
|
|
||||||
|
|
||||||
var Keys;
|
|
||||||
|
|
||||||
var description = {
|
|
||||||
name: 'ItemTag',
|
|
||||||
version: '1.0',
|
|
||||||
author: 'MiaoWoo'
|
|
||||||
};
|
|
||||||
|
|
||||||
var itemConfig;
|
|
||||||
|
|
||||||
function load() {
|
|
||||||
var itemFile = self.file('item.yml');
|
|
||||||
task.async(function() {
|
|
||||||
if (!itemFile.exists()) {
|
|
||||||
fs.save(itemFile, http.get('https://data.yumc.pw/config/Item_zh_CN.yml'))
|
|
||||||
}
|
|
||||||
itemConfig = self.getConfig('item.yml')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function enable() {
|
|
||||||
switch (DetectServerType) {
|
|
||||||
case ServerType.Bukkit:
|
|
||||||
var i = require('api/item').create('STONE')
|
|
||||||
if (!i.setCustomName) { return }
|
|
||||||
event.on(self, 'ItemMergeEvent', function(event) {
|
|
||||||
bukkit(event.target, event.entity.itemStack.amount + event.target.itemStack.amount);
|
|
||||||
});
|
|
||||||
event.on(self, 'ItemSpawnEvent', function(event) {
|
|
||||||
if (event.entity.itemStack) {
|
|
||||||
bukkit(event.entity, event.entity.itemStack.amount);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case ServerType.Sponge:
|
|
||||||
Keys = Java.type('org.spongepowered.api.data.key.Keys');
|
|
||||||
event.on(self, 'ItemMergeItemEvent', function(event) {
|
|
||||||
// Sponge 暂未实现当前事件
|
|
||||||
});
|
|
||||||
event.on(self, 'SpawnEntityEvent', function(event) {
|
|
||||||
event.entities.forEach(function(entity) {
|
|
||||||
if (entity.type.name === "item") sponge(entity);
|
|
||||||
})
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function bukkit(item, amount) {
|
|
||||||
item.setCustomName('§b' + getItemName(item.itemStack.type) + getItemCount(amount));
|
|
||||||
item.setCustomNameVisible(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
function sponge(entity) {
|
|
||||||
var itemOptional = entity.get(Keys['REPRESENTED_ITEM']);
|
|
||||||
if (itemOptional.isPresent()) {
|
|
||||||
var item = itemOptional.get();
|
|
||||||
var itemName = '§b' + getItemName(item.type.name.split(':')[1]) + getItemCount(item.count);
|
|
||||||
entity.offer(Keys['DISPLAY_NAME'], org.spongepowered.api.text.Text.of(itemName));
|
|
||||||
entity.offer(Keys['CUSTOM_NAME_VISIBLE'], true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getItemName(name) {
|
|
||||||
return itemConfig[(name + '').toUpperCase()] || name;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getItemCount(amount) {
|
|
||||||
return amount === 1 ? "" : "*" + amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
function disable() {
|
|
||||||
console.log('卸载', description.name, '插件!');
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
description: description,
|
|
||||||
load: load,
|
|
||||||
enable: enable,
|
|
||||||
disable: disable
|
|
||||||
};
|
|
@ -1,70 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
/**
|
|
||||||
* MiaoAuth简易登录系统
|
|
||||||
*/
|
|
||||||
/*global Java, base, module, exports, require*/
|
|
||||||
|
|
||||||
var event = require('api/event');
|
|
||||||
var wrapper = require('api/wrapper');
|
|
||||||
var command = require('api/command');
|
|
||||||
|
|
||||||
var description = {
|
|
||||||
name: 'MiaoAuth',
|
|
||||||
version: '1.0',
|
|
||||||
author: 'MiaoWoo',
|
|
||||||
commands: {
|
|
||||||
'l': {
|
|
||||||
description: 'MiaoAuth登录命令'
|
|
||||||
},
|
|
||||||
'r': {
|
|
||||||
description: 'MiaoAuth注册命令'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function load() {
|
|
||||||
console.log('载入 MiaoAuth 插件!');
|
|
||||||
}
|
|
||||||
|
|
||||||
function enable() {
|
|
||||||
command.on(this, 'l', {
|
|
||||||
cmd: function(sender, command, args) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
command.on(this, 'r', {
|
|
||||||
cmd: function(sender, command, args) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
console.log('启用 MiaoAuth 测试插件!');
|
|
||||||
switch (DetectServerType) {
|
|
||||||
case ServerType.Bukkit:
|
|
||||||
event.on(this, 'playerloginevent', function join(event) {
|
|
||||||
send(wrapper.player(event.player));
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case ServerType.Sponge:
|
|
||||||
event.on(this, 'clientconnectionevent.join', function join(event) {
|
|
||||||
send(wrapper.player(event.targetEntity));
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function send(player) {
|
|
||||||
setTimeout(function sendMessage() {
|
|
||||||
player.sendMessage('§a输入 /l <密码> 以登录!');
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
function disable() {
|
|
||||||
console.log('卸载 MiaoAuth 测试插件!');
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
description: description,
|
|
||||||
load: load,
|
|
||||||
enable: enable,
|
|
||||||
disable: disable
|
|
||||||
};
|
|
@ -1,261 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
/**
|
|
||||||
* MiaoChat 喵式聊天插件
|
|
||||||
*/
|
|
||||||
/*global Java, base, module, exports, require*/
|
|
||||||
|
|
||||||
var event = require('api/event');
|
|
||||||
var command = require('api/command');
|
|
||||||
|
|
||||||
var tellraw = require('tellraw');
|
|
||||||
var papi = require('papi');
|
|
||||||
var utils = require('utils');
|
|
||||||
|
|
||||||
var Player;
|
|
||||||
|
|
||||||
var description = {
|
|
||||||
name: 'MiaoChat',
|
|
||||||
version: '1.0',
|
|
||||||
author: 'MiaoWoo',
|
|
||||||
commands: {
|
|
||||||
'mchat': {
|
|
||||||
description: 'MiaoChat登录命令'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
permissions: {
|
|
||||||
'MiaoChat.default': {
|
|
||||||
default: true,
|
|
||||||
description: '默认权限 赋予玩家'
|
|
||||||
},
|
|
||||||
'MiaoChat.admin': {
|
|
||||||
default: false,
|
|
||||||
description: '管理权限'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
config: {
|
|
||||||
Version: "1.8.5",
|
|
||||||
BungeeCord: true,
|
|
||||||
Server: "生存服",
|
|
||||||
ChatFormats: {
|
|
||||||
"default": {
|
|
||||||
"index": 50,
|
|
||||||
"permission": "MiaoChat.default",
|
|
||||||
"range": 0,
|
|
||||||
"format": "[world][player]&7: ",
|
|
||||||
"item": true,
|
|
||||||
"itemformat": "&6[&b%s&6]&r"
|
|
||||||
},
|
|
||||||
"admin": {
|
|
||||||
"index": 49,
|
|
||||||
"permission": "MiaoChat.admin",
|
|
||||||
"format": "[admin][world][player][help]&7: ",
|
|
||||||
"range": 0,
|
|
||||||
"item": true,
|
|
||||||
"itemformat": "&6[&b%s&6]&r"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
StyleFormats: {
|
|
||||||
"world": {
|
|
||||||
"text": "&6[&a%player_world%&6]",
|
|
||||||
"hover": [
|
|
||||||
"&6当前所在位置:",
|
|
||||||
"&6世界: &d%player_world%",
|
|
||||||
"&6坐标: &aX:%player_x% Y: %player_y% Z: %player_z%",
|
|
||||||
"",
|
|
||||||
"&c点击即可TP我!"
|
|
||||||
],
|
|
||||||
"click": {
|
|
||||||
"type": "COMMAND",
|
|
||||||
"command": "/tpa %player_name%"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"player": {
|
|
||||||
"text": "&b%player_name%",
|
|
||||||
"hover": [
|
|
||||||
"&6玩家名称: &b%player_name%",
|
|
||||||
"&6玩家等级: &a%player_level%",
|
|
||||||
"&6玩家血量: &c%player_health%",
|
|
||||||
"&6玩家饥饿: &d%player_food_level%",
|
|
||||||
"&6游戏模式: &4%player_gamemode%",
|
|
||||||
"",
|
|
||||||
"&c点击与我聊天"
|
|
||||||
],
|
|
||||||
"click": {
|
|
||||||
"type": "SUGGEST",
|
|
||||||
"command": "/tell %player_name%"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"admin": {
|
|
||||||
"text": "&6[&c管理员&6]"
|
|
||||||
},
|
|
||||||
"help": {
|
|
||||||
"text": "&4[求助]",
|
|
||||||
"hover": [
|
|
||||||
"点击求助OP"
|
|
||||||
],
|
|
||||||
"click": {
|
|
||||||
"type": "COMMAND",
|
|
||||||
"command": "管理员@%player_name% 我需要你的帮助!"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var chat_formats;
|
|
||||||
var style_formats;
|
|
||||||
|
|
||||||
function load() {
|
|
||||||
chat_formats = Object.values(self.config.ChatFormats);
|
|
||||||
chat_formats.sort(utils.compare('index'));
|
|
||||||
initFormat(chat_formats);
|
|
||||||
style_formats = self.config.StyleFormats;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 用于匹配 '[xx]' 聊天格式
|
|
||||||
var FORMAT_PATTERN = /[\[]([^\[\]]+)[\]]/ig;
|
|
||||||
|
|
||||||
function initFormat(chat_formats) {
|
|
||||||
chat_formats.forEach(function(chat_format) {
|
|
||||||
var chat_format_str = chat_format.format;
|
|
||||||
var temp = [];
|
|
||||||
var r;
|
|
||||||
while (r = FORMAT_PATTERN.exec(chat_format_str)) {
|
|
||||||
temp.push(r[1]);
|
|
||||||
}
|
|
||||||
var format_list = [];
|
|
||||||
temp.forEach(function splitStyle(t) {
|
|
||||||
var arr = chat_format_str.split('[' + t + ']', 2);
|
|
||||||
if (arr[0]) {
|
|
||||||
format_list.push(arr[0]);
|
|
||||||
}
|
|
||||||
format_list.push(t);
|
|
||||||
chat_format_str = arr[1];
|
|
||||||
});
|
|
||||||
if (chat_format_str) {
|
|
||||||
format_list.push(chat_format_str);
|
|
||||||
}
|
|
||||||
chat_format.format_list = format_list;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function enable() {
|
|
||||||
registerCommand();
|
|
||||||
registerEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
function registerCommand() {
|
|
||||||
command.on(self, 'mchat', {
|
|
||||||
cmd: mainCommand
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// noinspection JSUnusedLocalSymbols
|
|
||||||
function mainCommand(sender, command, args) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function registerEvent() {
|
|
||||||
switch (DetectServerType) {
|
|
||||||
case ServerType.Bukkit:
|
|
||||||
event.on(self, 'AsyncPlayerChatEvent', handlerBukkitChat);
|
|
||||||
break;
|
|
||||||
case ServerType.Sponge:
|
|
||||||
Player = org.spongepowered.api.entity.living.player.Player;
|
|
||||||
event.on(self, 'MessageChannelEvent.Chat', handlerSpongeChat);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function handlerBukkitChat(event) {
|
|
||||||
sendChat(event.player, event.message, function() {
|
|
||||||
event.setCancelled(true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function handlerSpongeChat(event) {
|
|
||||||
var player = event.getCause().first(Player.class).orElse(null);
|
|
||||||
if (player == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var plain = event.getRawMessage().toPlain();
|
|
||||||
if (plain.startsWith(tellraw.duplicateChar)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sendChat(player, plain, function() {
|
|
||||||
event.setMessageCancelled(true)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function sendChat(player, plain, callback) {
|
|
||||||
var chat_format = getChatFormat(player);
|
|
||||||
if (!chat_format) {
|
|
||||||
console.debug('未获得用户', player.name, '的 ChatRule 跳过执行...');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
callback();
|
|
||||||
var tr = tellraw.create();
|
|
||||||
chat_format.format_list.forEach(function setStyle(format) {
|
|
||||||
var style = style_formats[format];
|
|
||||||
if (style) {
|
|
||||||
tr.then(replace(player, style.text));
|
|
||||||
if (style.hover) {
|
|
||||||
tr.tip(replace(player, style.hover));
|
|
||||||
}
|
|
||||||
if (style.click && style.click.type && style.click.command) {
|
|
||||||
var command = replace(player, style.click.command);
|
|
||||||
switch (style.click.type) {
|
|
||||||
case "COMMAND":
|
|
||||||
tr.command(command);
|
|
||||||
break;
|
|
||||||
case "OPENURL":
|
|
||||||
tr.link(command);
|
|
||||||
break;
|
|
||||||
case "SUGGEST":
|
|
||||||
tr.suggest(command);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tr.then(replace(player, format));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
tr.then(replace(player, plain)).sendAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
function getChatFormat(player) {
|
|
||||||
for (var i in chat_formats) {
|
|
||||||
var format = chat_formats[i];
|
|
||||||
if (player.hasPermission(format.permission)) {
|
|
||||||
return format;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function replace(player, target) {
|
|
||||||
if (toString.call(target) === "[object Array]") {
|
|
||||||
for (var i in target) {
|
|
||||||
target[i] = replaceStr(player, target[i]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
target = replaceStr(player, target);
|
|
||||||
}
|
|
||||||
return target;
|
|
||||||
}
|
|
||||||
|
|
||||||
function replaceStr(player, target) {
|
|
||||||
return papi.$(player, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
function disable() {
|
|
||||||
console.log('卸载', description.name, '插件!');
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
description: description,
|
|
||||||
load: load,
|
|
||||||
enable: enable,
|
|
||||||
disable: disable
|
|
||||||
};
|
|
@ -1,231 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
/**
|
|
||||||
* Hello Wrold 测试插件
|
|
||||||
*/
|
|
||||||
/*global Java, base, module, exports, require*/
|
|
||||||
|
|
||||||
var event = require('api/event');
|
|
||||||
var command = require('api/command');
|
|
||||||
var bukkit = require('api/server');
|
|
||||||
var item = require('api/item');
|
|
||||||
|
|
||||||
var Arrays = Java.type('java.util.Arrays');
|
|
||||||
var ItemStackArray = Java.type('org.bukkit.inventory.ItemStack[]');
|
|
||||||
|
|
||||||
var PANE = 'STAINED_GLASS_PANE'
|
|
||||||
|
|
||||||
var description = {
|
|
||||||
name: 'Lottery',
|
|
||||||
version: '1.0',
|
|
||||||
author: 'MiaoWoo',
|
|
||||||
commands: {
|
|
||||||
'lottery': {
|
|
||||||
description: 'Lottery主命令'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
config: {
|
|
||||||
title: '§m§s§a幸运抽奖',
|
|
||||||
control: {
|
|
||||||
panel: PANE + ':13',
|
|
||||||
ok: PANE + ':14',
|
|
||||||
no: PANE + ':15',
|
|
||||||
},
|
|
||||||
list: [
|
|
||||||
{
|
|
||||||
box: {
|
|
||||||
id: PANE,
|
|
||||||
damage: 1,
|
|
||||||
name: '§a箱子',
|
|
||||||
lore: [
|
|
||||||
'这是箱子的Lore'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
key: {
|
|
||||||
id: PANE,
|
|
||||||
damage: 2,
|
|
||||||
name: '§b钥匙',
|
|
||||||
lore: [
|
|
||||||
'这是钥匙的Lore'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
result: [
|
|
||||||
{
|
|
||||||
percent: 10,
|
|
||||||
command: 'money give %player% 100',
|
|
||||||
item: {
|
|
||||||
id: PANE,
|
|
||||||
damage: 3,
|
|
||||||
name: '§c奖品1',
|
|
||||||
lore: [
|
|
||||||
'这是奖品1的Lore'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
percent: 20,
|
|
||||||
command: 'money give %player% 200',
|
|
||||||
item: {
|
|
||||||
id: PANE,
|
|
||||||
damage: 4,
|
|
||||||
name: '§c奖品2',
|
|
||||||
lore: [
|
|
||||||
'这是奖品2的Lore'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var panel;
|
|
||||||
var config;
|
|
||||||
var items;
|
|
||||||
|
|
||||||
function load() {
|
|
||||||
config = this.config;
|
|
||||||
panel = newItemFromString(config.control.panel || PANE + ':13')
|
|
||||||
items = new ItemStackArray(54);
|
|
||||||
item.setName(panel, '');
|
|
||||||
var ok = newItemFromString(config.control.ok || PANE + ':14')
|
|
||||||
item.setName(ok, '§a确定抽奖');
|
|
||||||
var no = newItemFromString(config.control.no || PANE + ':15')
|
|
||||||
item.setName(no, '§c取消抽奖');
|
|
||||||
Arrays.fill(items, 0, 10, panel);
|
|
||||||
Arrays.fill(items, 11, 16, panel);
|
|
||||||
Arrays.fill(items, 17, 29, panel);
|
|
||||||
items[29] = no;
|
|
||||||
Arrays.fill(items, 30, 33, panel);
|
|
||||||
items[33] = ok;
|
|
||||||
Arrays.fill(items, 34, 40, panel);
|
|
||||||
Arrays.fill(items, 41, 54, panel);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isTargetItem(item, config) {
|
|
||||||
return item.typeId === config.id &&
|
|
||||||
item.itemMeta &&
|
|
||||||
item.itemMeta.displayName === config.name &&
|
|
||||||
item.itemMeta.lore && Java.from(item.itemMeta.lore).toJson() === config.lore.toJson()
|
|
||||||
}
|
|
||||||
|
|
||||||
function newItem(name, sub) {
|
|
||||||
return item.create(name, 1, sub || 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
function newItemFromString(str) {
|
|
||||||
var arr = str.split(':');
|
|
||||||
if (arr.length === 2) {
|
|
||||||
return newItem(arr[0], arr[1]);
|
|
||||||
} else {
|
|
||||||
return newItem(arr[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function newItemFromConfig(config) {
|
|
||||||
var i = newItem(config.id, config.damage);
|
|
||||||
if (config.name) item.setName(i, config.name);
|
|
||||||
if (config.lore) item.setLore(i, config.lore);
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
function enable() {
|
|
||||||
// noinspection JSUnusedLocalSymbols
|
|
||||||
command.on(this, 'l', {
|
|
||||||
cmd: function(sender, command, args) {
|
|
||||||
sender.inventory.addItem(newItemFromConfig(config.list[0].box))
|
|
||||||
sender.inventory.addItem(newItemFromConfig(config.list[0].key))
|
|
||||||
if (!sender.openInventory) {
|
|
||||||
console.sender(sender, "§4当前用户无法使用该命令!");
|
|
||||||
}
|
|
||||||
var inv = MServer.createInventory(null, 54, config.title);
|
|
||||||
inv.setContents(items);
|
|
||||||
sender.openInventory(inv);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
event.on(this, 'InventoryClick', function click(event) {
|
|
||||||
var inv = event.inventory;
|
|
||||||
if (inv && inv.title !== config.title) return;
|
|
||||||
var player = event.whoClicked;
|
|
||||||
var slot = event.rawSlot;
|
|
||||||
if (slot > 53 || slot < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
event.cancelled = true;
|
|
||||||
switch (slot) {
|
|
||||||
case 10:
|
|
||||||
case 16:
|
|
||||||
case 40:
|
|
||||||
event.cancelled = false;
|
|
||||||
break;
|
|
||||||
case 29:
|
|
||||||
// TODO 关闭界面
|
|
||||||
player.closeInventory();
|
|
||||||
break;
|
|
||||||
case 33:
|
|
||||||
var temp = inv.getItem(40);
|
|
||||||
if (temp && temp.typeId !== 0) {
|
|
||||||
console.sender(player, '§c请先取走奖品!');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var litem;
|
|
||||||
var box = inv.getItem(10);
|
|
||||||
if (!box) {
|
|
||||||
console.sender(player, '§c请先放入抽奖物品和钥匙!');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var key = inv.getItem(16);
|
|
||||||
if (box && box.typeId !== 0 && key && key.typeId !== 0) {
|
|
||||||
for (var i = 0; i < config.list.length; i++) {
|
|
||||||
var r = config.list[i];
|
|
||||||
if (isTargetItem(box, r.box)) {
|
|
||||||
litem = r;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// TODO 抽奖
|
|
||||||
if (!litem) {
|
|
||||||
console.sender(player, '§c请先放入抽奖物品和钥匙!');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!isTargetItem(key, litem.key)) {
|
|
||||||
console.sender(player, '§c抽奖物品和钥匙不匹配!');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var resultList = [];
|
|
||||||
litem.result.forEach(function(t) {
|
|
||||||
for (var i = 0; i < t.percent; i++) {
|
|
||||||
resultList.push(t);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
var ri = random(resultList.length);
|
|
||||||
var result = resultList[ri];
|
|
||||||
box.amount = box.amount - 1;
|
|
||||||
key.amount = key.amount - 1;
|
|
||||||
inv.setItem(10, box);
|
|
||||||
inv.setItem(16, key);
|
|
||||||
inv.setItem(40, newItemFromConfig(result.item));
|
|
||||||
bukkit.console(result.command.replace('%player%', player.name));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
event.cancelled = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function random(max, min) {
|
|
||||||
min = min === undefined ? 0 : min;
|
|
||||||
return Math.floor(Math.random() * (max - min) + min);
|
|
||||||
};
|
|
||||||
|
|
||||||
function disable() {
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
description: description,
|
|
||||||
load: load,
|
|
||||||
enable: enable,
|
|
||||||
disable: disable
|
|
||||||
};
|
|
@ -1,188 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
/**
|
|
||||||
* MiaoTag
|
|
||||||
* 可兼容任何记分板
|
|
||||||
*/
|
|
||||||
/*global Java, base, module, exports, require*/
|
|
||||||
var event = require('api/event');
|
|
||||||
var bukkit = require('api/server');
|
|
||||||
var command = require('api/command');
|
|
||||||
|
|
||||||
var fakeTag;
|
|
||||||
|
|
||||||
var description = {
|
|
||||||
name: 'MiaoTag',
|
|
||||||
version: '1.1',
|
|
||||||
author: 'MiaoWoo',
|
|
||||||
config: {
|
|
||||||
format: '§4§l❤'
|
|
||||||
},
|
|
||||||
commands: {
|
|
||||||
'mtag': {
|
|
||||||
description: 'MiaoTag主命令',
|
|
||||||
usage: '',
|
|
||||||
permission: 'MiaoTag.admin'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
permissions: {
|
|
||||||
'MiaoTag.default': {
|
|
||||||
default: true,
|
|
||||||
description: '默认权限 赋予玩家'
|
|
||||||
},
|
|
||||||
'MiaoTag.admin': {
|
|
||||||
default: false,
|
|
||||||
description: '管理权限'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var config;
|
|
||||||
|
|
||||||
function load() {
|
|
||||||
config = self.getConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
function enable() {
|
|
||||||
registryCommand()
|
|
||||||
fakeTag = new FakeTag(config.format);
|
|
||||||
registryEvent()
|
|
||||||
}
|
|
||||||
|
|
||||||
function registryCommand() {
|
|
||||||
command.on(self, 'mtag', {
|
|
||||||
cmd: function cmd(sender, command, args) {
|
|
||||||
var subCommand = args[0];
|
|
||||||
switch (subCommand) {
|
|
||||||
case 'reload':
|
|
||||||
self.reloadConfig();
|
|
||||||
fakeTag = new FakeTag(config.format);
|
|
||||||
console.sender(sender, "§a配置文件重载完成!");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tab: function tab(sender, command, args) {
|
|
||||||
return ['reload'];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function registryEvent() {
|
|
||||||
bukkit.players(function(p) { fakeTag.set(p) });
|
|
||||||
event.on(self, 'PlayerJoin', function(event) { fakeTag.set(event.player) });
|
|
||||||
event.on(self, 'EntityRegainHealth', entityUpdate, false);
|
|
||||||
event.on(self, 'EntityDamage', entityUpdate, false);
|
|
||||||
event.on(self, 'EntityRegainHealth', entityUpdate, false);
|
|
||||||
event.on(self, 'PlayerRespawn', entityUpdate, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
function entityUpdate(event) {
|
|
||||||
var player = event.entity || event.player;
|
|
||||||
if (player instanceof org.bukkit.entity.Player) {
|
|
||||||
setTimeout(function() {
|
|
||||||
fakeTag.update(player);
|
|
||||||
}, 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function disable() {
|
|
||||||
if (fakeTag) { fakeTag.disable() };
|
|
||||||
}
|
|
||||||
|
|
||||||
function FakeTag(name) {
|
|
||||||
var ver1_13 = false;
|
|
||||||
// NMS CLASS
|
|
||||||
try {
|
|
||||||
var ScoreboardBaseCriteria = bukkit.nmsCls('ScoreboardBaseCriteria');
|
|
||||||
} catch (ex) {
|
|
||||||
try {
|
|
||||||
var IScoreboardCriteria = bukkit.nmsCls('IScoreboardCriteria');
|
|
||||||
var ScoreboardServer = bukkit.nmsCls("ScoreboardServer");
|
|
||||||
var ChatComponentText = bukkit.nmsCls('ChatComponentText');
|
|
||||||
ver1_13 = true;
|
|
||||||
} catch (ex) {
|
|
||||||
console.log(ex);
|
|
||||||
throw ex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var PacketPlayOutScoreboardScore = bukkit.nmsCls('PacketPlayOutScoreboardScore');
|
|
||||||
var PacketPlayOutScoreboardObjective = bukkit.nmsCls('PacketPlayOutScoreboardObjective');
|
|
||||||
var PacketPlayOutScoreboardDisplayObjective = bukkit.nmsCls('PacketPlayOutScoreboardDisplayObjective');
|
|
||||||
|
|
||||||
var scoreboardManager = bukkit.$.scoreboardManager;
|
|
||||||
var mainScoreboard = scoreboardManager.mainScoreboard.handle;
|
|
||||||
|
|
||||||
// 注销对象
|
|
||||||
var objective = mainScoreboard.getObjective(name);
|
|
||||||
if (objective) {
|
|
||||||
mainScoreboard.unregisterObjective(objective);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (!ver1_13) {
|
|
||||||
// 注册tag对象
|
|
||||||
objective = mainScoreboard.registerObjective(name, new ScoreboardBaseCriteria(name));
|
|
||||||
} else {
|
|
||||||
// 注册tag对象
|
|
||||||
objective = mainScoreboard.registerObjective(name,
|
|
||||||
IScoreboardCriteria.HEALTH,
|
|
||||||
new ChatComponentText(name),
|
|
||||||
IScoreboardCriteria.EnumScoreboardHealthDisplay.HEARTS);
|
|
||||||
}
|
|
||||||
} catch (ex) {
|
|
||||||
throw ex
|
|
||||||
// ignore 忽略创建错误 eg: java.lang.IllegalArgumentException: An objective with the name 'xxxxx' already exists!
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!objective) {
|
|
||||||
throw Error("Error Can't Found MainScoreboard Objective " + name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 缓存虚拟的tag包
|
|
||||||
var cache = {
|
|
||||||
objective: new PacketPlayOutScoreboardObjective(objective, 0),
|
|
||||||
display: new PacketPlayOutScoreboardDisplayObjective(2, objective)
|
|
||||||
};
|
|
||||||
|
|
||||||
function sendPacket(player, p) {
|
|
||||||
player.handle.playerConnection.sendPacket(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.set = function(player) {
|
|
||||||
sendPacket(player, cache.objective);
|
|
||||||
sendPacket(player, cache.display);
|
|
||||||
this.update(player);
|
|
||||||
};
|
|
||||||
|
|
||||||
function createScore(player) {
|
|
||||||
if (!ver1_13) {
|
|
||||||
var score = mainScoreboard.getPlayerScoreForObjective(player.name, objective);
|
|
||||||
score.setScore(player.health);
|
|
||||||
return new PacketPlayOutScoreboardScore(score);
|
|
||||||
} else {
|
|
||||||
return new PacketPlayOutScoreboardScore(ScoreboardServer.Action.CHANGE, name, player.name, player.health)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.update = function update(player) {
|
|
||||||
var scorePack = createScore(player);
|
|
||||||
//把其他玩家缓存的包发给这个玩家
|
|
||||||
bukkit.players(function(t) {
|
|
||||||
sendPacket(t, scorePack);
|
|
||||||
if (t.name !== player.name) {
|
|
||||||
sendPacket(player, createScore(t));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
this.disable = function() {
|
|
||||||
// 注销tag对象
|
|
||||||
mainScoreboard.unregisterObjective(objective);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
description: description,
|
|
||||||
load: load,
|
|
||||||
enable: enable,
|
|
||||||
disable: disable
|
|
||||||
};
|
|
@ -1,48 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
/**
|
|
||||||
* WorldEdit 插件
|
|
||||||
*/
|
|
||||||
/*global Java, base, module, exports, require*/
|
|
||||||
var item = require('/api/item');
|
|
||||||
var command = require('api/command');
|
|
||||||
var Material = Java.type("org.bukkit.Material");
|
|
||||||
|
|
||||||
var description = {
|
|
||||||
name: 'WorldEdit',
|
|
||||||
version: '1.0',
|
|
||||||
author: 'MiaoWoo',
|
|
||||||
commands: {
|
|
||||||
'/up': {
|
|
||||||
description: 'Up Player And Set Block'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function load() {
|
|
||||||
}
|
|
||||||
|
|
||||||
function enable() {
|
|
||||||
command.on(this, '/up', {
|
|
||||||
cmd: function(sender, command, args) {
|
|
||||||
if (!sender.openInventory) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var player = sender;
|
|
||||||
var location = player.location;
|
|
||||||
var type = item.type(args[0], 'STONE');
|
|
||||||
player.velocity = player.velocity.setY(0.5);
|
|
||||||
setTimeout(function() {
|
|
||||||
location.block.type = type
|
|
||||||
}, 6);
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
tab: function(sender, command, args) {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
description: description,
|
|
||||||
enable: enable
|
|
||||||
};
|
|
@ -1,32 +0,0 @@
|
|||||||
## MiaoChat for MiaoScript
|
|
||||||
|
|
||||||
![](https://dn-coding-net-production-pp.qbox.me/f459067b-7829-45ec-9713-bb559d1e0118.png)
|
|
||||||
|
|
||||||
> 注意: MiaoScript 在Windows环境下 暂不支持 reload 所以 Windows 环境请重启服务器
|
|
||||||
> 注意: MiaoScript 将不会计划兼容 非 `Sponge` 的MOD端
|
|
||||||
|
|
||||||
- 基于 `MiaoScript` 开发 同时兼容 `Sponge` 和 `Bukkit`
|
|
||||||
- 支持PAPI
|
|
||||||
- `Bukkit` 为 `me.clip.placeholderapi.PlaceholderAPI`
|
|
||||||
- `Sponge` 为 `me.rojo8399.placeholderapi.PlaceholderService`
|
|
||||||
- 支持悬浮提示
|
|
||||||
- 支持点击执行命令
|
|
||||||
- 支持点击命令补全
|
|
||||||
|
|
||||||
### Feature(开发规划)
|
|
||||||
- 悬浮物品提示
|
|
||||||
- 兼容 `BungeeCord` 支持跨服聊天
|
|
||||||
- 兼容其他聊天插件 保护插件
|
|
||||||
|
|
||||||
### 安装教程
|
|
||||||
- 下载 MiaoChat 本体并安装
|
|
||||||
- [下载地址-论坛](http://www.mcbbs.net/thread-774401-1-1.html)
|
|
||||||
- [下载地址-备用](https://git.yumc.pw/502647092/MiaoScript/releases)
|
|
||||||
- 安装到服务端对应的目录
|
|
||||||
- Bukkit => plugins
|
|
||||||
- Sponge => mods
|
|
||||||
- 重启服务器
|
|
||||||
- 下载 安装 `MiaoScriptPackageManager`
|
|
||||||
- [安装教程](http://www.mcbbs.net/thread-774797-1-1.html)
|
|
||||||
- 使用 `MiaoScriptPackageManager` 安装插件
|
|
||||||
- 执行 `mpm install MiaoChat` 即可安装成功
|
|
@ -1,220 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
/**
|
|
||||||
* MiaoBoard 喵式聊天插件
|
|
||||||
*/
|
|
||||||
/*global Java, base, module, exports, require*/
|
|
||||||
var task = require('api/task');
|
|
||||||
var event = require('api/event');
|
|
||||||
var server = require('api/server');
|
|
||||||
var command = require('api/command');
|
|
||||||
|
|
||||||
var papi = require('papi');
|
|
||||||
|
|
||||||
var Player;
|
|
||||||
|
|
||||||
var boards = [];
|
|
||||||
|
|
||||||
var description = {
|
|
||||||
name: 'MiaoBoard',
|
|
||||||
version: '1.0',
|
|
||||||
author: 'MiaoWoo',
|
|
||||||
commands: {
|
|
||||||
'mboard': {
|
|
||||||
description: '喵式记分板主命令'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
permissions: {
|
|
||||||
'mb.default': {
|
|
||||||
default: true,
|
|
||||||
description: '默认权限 赋予玩家'
|
|
||||||
},
|
|
||||||
'mb.admin': {
|
|
||||||
default: false,
|
|
||||||
description: '管理权限'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
config: {
|
|
||||||
"Version": 2,
|
|
||||||
"UpdateTime": 10,
|
|
||||||
"DisableWorld": [
|
|
||||||
"WorldName"
|
|
||||||
],
|
|
||||||
"Boards": {
|
|
||||||
"default": {
|
|
||||||
"index": 50,
|
|
||||||
"time": {
|
|
||||||
"start": "2016-01-01 00:00:00",
|
|
||||||
"end": "2020-01-01 00:00:00"
|
|
||||||
},
|
|
||||||
"title": "玩家信息",
|
|
||||||
"permission": "mb.default",
|
|
||||||
"lines": [
|
|
||||||
"&6名 称: &a%player_displayname%",
|
|
||||||
"&6世 界: &b%player_world%",
|
|
||||||
"&6位 置: &3%player_x%,%player_y%,%player_z%",
|
|
||||||
"&6等 级: &e%player_level%",
|
|
||||||
"&6血 量: &c%player_health%",
|
|
||||||
"&6模 式: &4%player_gamemode%"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"admin": {
|
|
||||||
"index": 49,
|
|
||||||
"title": "服务器信息",
|
|
||||||
"permission": "mb.reload",
|
|
||||||
"lines": [
|
|
||||||
"&6名 称: &aMiaoBoard",
|
|
||||||
"&6版 本: &b1.0.0",
|
|
||||||
"&6作 者: &cMiaoWoo",
|
|
||||||
"&6人 数: &c%server_online%/%server_max%",
|
|
||||||
"&6内 存: &a%server_ram_used%/%server_ram_total%/%server_ram_max%"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var update_task;
|
|
||||||
var board_formats;
|
|
||||||
|
|
||||||
function load() {
|
|
||||||
board_formats = self.config.Boards;
|
|
||||||
}
|
|
||||||
|
|
||||||
function enable() {
|
|
||||||
registerCommand();
|
|
||||||
registerEvent();
|
|
||||||
registerTask();
|
|
||||||
updatePlayers()
|
|
||||||
}
|
|
||||||
|
|
||||||
function registerCommand() {
|
|
||||||
command.on(self, 'mboard', {
|
|
||||||
cmd: mainCommand
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function mainCommand(sender, command, args) {
|
|
||||||
if (!args[0]) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch (args[0]) {
|
|
||||||
case "reload":
|
|
||||||
self.reloadConfig();
|
|
||||||
load();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function registerEvent() {
|
|
||||||
switch (DetectServerType) {
|
|
||||||
case ServerType.Bukkit:
|
|
||||||
//event.on(self, 'PlayerLoginEvent', handlerPlayerJoin);
|
|
||||||
break;
|
|
||||||
case ServerType.Sponge:
|
|
||||||
Player = org.spongepowered.api.entity.living.player.Player;
|
|
||||||
event.on(self, 'ClientConnectionEvent.Join', handlerPlayerJoin);
|
|
||||||
event.on(self, 'ClientConnectionEvent.Disconnect', handlerPlayerQuit);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function updatePlayers() {
|
|
||||||
switch (DetectServerType) {
|
|
||||||
case ServerType.Bukkit:
|
|
||||||
//event.on(self, 'PlayerLoginEvent', handlerPlayerJoin);
|
|
||||||
break;
|
|
||||||
case ServerType.Sponge:
|
|
||||||
server.players(function(player) {
|
|
||||||
boards[player.name] = new MiaoBoard(player);
|
|
||||||
})
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function handlerPlayerJoin(event) {
|
|
||||||
var player = event.player || event.targetEntity;
|
|
||||||
boards[player.name] = new MiaoBoard(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handlerPlayerQuit(event) {
|
|
||||||
var player = event.player || event.targetEntity;
|
|
||||||
delete boards[player.name];
|
|
||||||
}
|
|
||||||
|
|
||||||
function registerTask() {
|
|
||||||
update_task = task.timerAsync(updateBoard, self.config.UpdateTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateBoard() {
|
|
||||||
for (var i in boards) {
|
|
||||||
var player = server.player(i);
|
|
||||||
if (player.isOnline()) {
|
|
||||||
var format = getBoardFormat(player);
|
|
||||||
if (format) {
|
|
||||||
boards[i].update(papi.$(player, format.title), papi.$(player, format.lines));
|
|
||||||
} else {
|
|
||||||
boards[i].clear();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
delete boards[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getBoardFormat(player) {
|
|
||||||
for (var i in board_formats) {
|
|
||||||
var format = board_formats[i];
|
|
||||||
if (player.hasPermission(format.permission)) {
|
|
||||||
return format;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function disable() {
|
|
||||||
if (update_task) { update_task.cancel(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
function MiaoBoard(player) {
|
|
||||||
var Scoreboard = Java.type('org.spongepowered.api.scoreboard.Scoreboard');
|
|
||||||
var Objective = Java.type('org.spongepowered.api.scoreboard.objective.Objective');
|
|
||||||
var Criteria = Java.type('org.spongepowered.api.scoreboard.critieria.Criteria');
|
|
||||||
var Text = Java.type('org.spongepowered.api.text.Text');
|
|
||||||
var DisplaySlots = Java.type('org.spongepowered.api.scoreboard.displayslot.DisplaySlots');
|
|
||||||
|
|
||||||
var uuid = player.uniqueId;
|
|
||||||
var scoreboard = Scoreboard.builder().build();
|
|
||||||
var sidebar = Objective.builder().criterion(Criteria.DUMMY).displayName(Text.EMPTY).name("Sidebar").build();
|
|
||||||
|
|
||||||
var origin = [];
|
|
||||||
|
|
||||||
scoreboard.addObjective(sidebar);
|
|
||||||
player.setScoreboard(scoreboard);
|
|
||||||
|
|
||||||
this.update = function(title, lines) {
|
|
||||||
this.updateBuffer(title, lines);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.updateBuffer = function(title, lines) {
|
|
||||||
sidebar.scores.values().forEach(function removeScore(score) {
|
|
||||||
sidebar.removeScore(score);
|
|
||||||
})
|
|
||||||
var i = 0;
|
|
||||||
sidebar.setDisplayName(Text.of(title));
|
|
||||||
lines.forEach(function addScore(line) {
|
|
||||||
sidebar.getOrCreateScore(Text.of(line)).setScore(lines.length - i++);
|
|
||||||
})
|
|
||||||
scoreboard.updateDisplaySlot(sidebar, DisplaySlots.SIDEBAR);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.clear = function() {
|
|
||||||
player.setScoreboard(Scoreboard.builder().build());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
description: description,
|
|
||||||
load: load,
|
|
||||||
enable: enable,
|
|
||||||
disable: disable
|
|
||||||
};
|
|
Loading…
Reference in New Issue
Block a user