50 Commits

Author SHA1 Message Date
b33826bbe9 feat: 更新版本号 2018-05-20 03:31:19 +00:00
8e2e2bca82 feat: 新增MiaoBoard插件 2018-05-19 17:14:19 +00:00
5ea78a60e5 feat: 新增MiaoAuth插件 2018-05-19 17:13:50 +00:00
c873031cc2 feat: 修改初始化函数名称 2018-05-19 17:11:48 +00:00
9504ec8b12 fix: file.js修复一个语法错误 2018-05-19 17:10:56 +00:00
abdfbce125 feat: 新增config默认值绑定 匿名函数添加名称 2018-05-19 17:10:29 +00:00
e6af7b1828 feat: PAPI支持直接替换数组 2018-05-19 17:09:14 +00:00
8f5bae006a feat: 调整Task任务模块 2018-05-19 17:08:48 +00:00
f94fa71f36 feat: 新增模板预编译插件功能 2018-05-19 17:08:26 +00:00
fcc1f18336 feat: 清除不必要的代码 2018-05-18 15:12:35 +00:00
823ff1c70b feat: 新增MiaoChat插件描述 2018-05-17 12:40:13 +00:00
2360dd9b0e feat: MiaoScriptPackageManager 新增restart和run方法 2018-05-17 12:39:52 +00:00
f94653249d fix: 修复Sponge命令参数存在空字符串的问题 2018-05-17 12:35:38 +00:00
c095593c41 fix: 修复混淆导致的重载方法丢失 2018-05-17 12:35:08 +00:00
202dc9f00c feat: 新增引擎Shutdown方法 关闭资源 2018-05-17 12:34:35 +00:00
88d71abb2a feat: 格式化代码 添加d.ts文件 去除引擎无关代码 清理单元测试 2018-05-17 18:30:40 +08:00
967e7d1beb fix: 修复TellRaw类库错误 2018-05-16 17:05:47 +00:00
e97de1f8d0 fix: 修复pkg不存在的问题 2018-05-16 16:57:06 +00:00
bc6e07cfc8 fix: 修复下载错误的问题 2018-05-16 16:55:44 +00:00
4dec6bca98 feat: 更新版本号 2018-05-16 16:49:58 +00:00
f8ec9b9f6e feat: 新增Hook提示 2018-05-16 16:30:05 +00:00
1735417887 feat: 调整列表载入顺序 2018-05-16 16:11:23 +00:00
9819a82265 feat: 完善MiaoChat的PAPI的替换 2018-05-16 16:09:26 +00:00
d2ebd8fa7e feat: 完善服务获取类 2018-05-16 16:08:27 +00:00
0492275eb2 feat: 新增PAPI代理类 2018-05-16 16:07:52 +00:00
3fe1feccff feat: 去除调试代码 2018-05-16 16:07:30 +00:00
f7b97f3e84 feat: 迁移配置 完善reload命令 2018-05-15 13:47:03 +00:00
89cab251c7 feat: 分离TellRaw类库 2018-05-15 13:33:52 +00:00
3d3bf20acd feat: 完善MiaoChat的Bukkit版本 2018-05-14 16:42:55 +00:00
423c7cc844 feat: 补全内部引入方法的参数 2018-05-14 16:42:35 +00:00
8df9ad9ec7 feat: 调整Event载入提示 完善Bukkit的聊天发送 2018-05-14 16:42:08 +00:00
39d9c67c75 feat: 调整API引入结构 2018-05-14 16:41:33 +00:00
6f1a103aca feat: 新增MiaoChat插件 2018-05-13 16:18:26 +00:00
f79acd43c5 feat: 更新API相关类 2018-05-13 16:18:14 +00:00
f19e51d8a7 feat: 调整相关API名称 2018-05-13 16:17:48 +00:00
d5aa98b716 feat: 新增Object.values垫片 2018-05-13 16:16:01 +00:00
04a7b99ce5 feat: 新增工具类 2018-05-13 16:14:35 +00:00
a672b85678 feat: 更新MiaoScriptPackageManager 2018-05-13 16:14:14 +00:00
288619ddb7 fix: 修复命令执行相关BUG 2018-05-13 16:13:57 +00:00
3df2625e65 feat: 新增聊天相关API 2018-05-13 16:13:32 +00:00
a041e8e2d2 feat: 优化方法调用 2018-03-18 12:06:52 +00:00
320cc0479e feat: 调整get方法 data 参数自动转query 2018-03-18 12:06:27 +00:00
755d4b005d feat: 优化插件代码结构 2018-03-18 12:04:56 +00:00
e290f17771 fix: 修复玩家人数获取错误 更新插件 2018-01-11 14:47:34 +00:00
be95acd001 feat: 更新http类库 server通过orElse返回undefined 2018-01-11 14:46:47 +00:00
75340fd824 feat: 更新基础类库 2018-01-11 13:47:49 +00:00
51499b3b52 feat: 新增插件管理模块 2018-01-10 12:59:55 +00:00
54b5909875 fix: 修复主线程加载的BUG 2018-01-10 12:59:29 +00:00
fe6d0e7250 feat: 修复fs相关BUG 优化插件加载 优化命令补全 2018-01-10 12:58:58 +00:00
bf6d52d8cc feat: 更新.gitignore文件 2018-01-10 01:57:19 +00:00
58 changed files with 1919 additions and 647 deletions

97
.gitignore vendored
View File

@ -1,44 +1,53 @@
# Eclipse stuff # Eclipse stuff
/.settings /.settings
# netbeans # netbeans
/nbproject /nbproject
# we use maven! # we use maven!
/build.xml /build.xml
# maven # maven
/target /target
/repo /repo
# vim # vim
.*.sw[a-p] .*.sw[a-p]
# various other potential build files # various other potential build files
/build /build
/bin /bin
/dist /dist
/manifest.mf /manifest.mf
/world # Mac filesystem dust
*.DS_Store
# Mac filesystem dust
*.DS_Store # intellij
*.iml
# intellij *.ipr
*.iml *.iws
*.ipr .idea/
*.iws
.idea/ # Project Stuff
/src/main/resources/Soulbound
# Project Stuff
/src/main/resources/Soulbound # Atlassian Stuff
/atlassian-ide-plugin.xml
# Atlassian Stuff
/atlassian-ide-plugin.xml # Eclipse
.project
/src/main/resources/cache/ .classpath
.settings
# ThinkPHP
vendor/ # Visual Studio Code
composer.lock .vscode
# NodeJs PHP LOCK File
*.lock
# PHP Vendor
vendor/
# Minecraft Data
/world

67
pom.xml
View File

@ -3,7 +3,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>1.2.1</version> <version>1.3.1</version>
<developers> <developers>
<developer> <developer>
<id>502647092</id> <id>502647092</id>
@ -18,7 +18,7 @@
<resource> <resource>
<directory>src/main/resources</directory> <directory>src/main/resources</directory>
<excludes> <excludes>
<exclude>plugins/**.js</exclude> <exclude>plugins/**</exclude>
</excludes> </excludes>
<filtering>true</filtering> <filtering>true</filtering>
</resource> </resource>
@ -84,11 +84,68 @@
<properties> <properties>
<env.GIT_COMMIT>DEV</env.GIT_COMMIT> <env.GIT_COMMIT>DEV</env.GIT_COMMIT>
<update.changes> <update.changes>
§618-01-09 §afeat: 优化加载流程 完善事件注册 §62018-5-20 §afeat: 新增MiaoBoard插件;
§618-01-02 §afeat: 新增http网络访问模块 §62018-5-20 §afeat: 新增MiaoAuth插件;
§617-12-28 §afeat: 完善Sponge事件注册 新增player封装类 §62018-5-20 §afeat: 修改初始化函数名称;
§62018-5-20 §cfix: file.js修复一个语法错误;
§62018-5-20 §afeat: 新增config默认值绑定 匿名函数添加名称;
§62018-5-20 §afeat: PAPI支持直接替换数组;
§62018-5-20 §afeat: 调整Task任务模块;
§62018-5-20 §afeat: 新增模板预编译插件功能;
§62018-5-18 §afeat: 清除不必要的代码;
§62018-5-17 §afeat: 新增MiaoChat插件描述;
§62018-5-17 §afeat: MiaoScriptPackageManager 新增restart和run方法;
§62018-5-17 §cfix: 修复Sponge命令参数存在空字符串的问题;
§62018-5-17 §cfix: 修复混淆导致的重载方法丢失;
§62018-5-17 §afeat: 新增引擎Shutdown方法 关闭资源;
§62018-5-17 §afeat: 格式化代码 添加d.ts文件 去除引擎无关代码 清理单元测试;
§62018-5-17 §cfix: 修复TellRaw类库错误;
§62018-5-17 §cfix: 修复pkg不存在的问题;
§62018-5-17 §cfix: 修复下载错误的问题;
§62018-5-17 §afeat: 更新版本号
</update.changes> </update.changes>
<update.changelog> <update.changelog>
§618-05-17 §afeat: 新增Hook提示;
§618-05-17 §afeat: 调整列表载入顺序;
§618-05-17 §afeat: 完善MiaoChat的PAPI的替换;
§618-05-17 §afeat: 完善服务获取类;
§618-05-17 §afeat: 新增PAPI代理类;
§618-05-17 §afeat: 去除调试代码;
§618-05-17 §afeat: 迁移配置 完善reload命令;
§618-05-15 §afeat: 分离TellRaw类库;
§618-05-15 §afeat: 完善MiaoChat的Bukkit版本;
§618-05-15 §afeat: 补全内部引入方法的参数;
§618-05-15 §afeat: 调整Event载入提示 完善Bukkit的聊天发送;
§618-05-15 §afeat: 调整API引入结构;
§618-05-15 §afeat: 新增MiaoChat插件;
§618-05-14 §afeat: 更新API相关类;
§618-05-14 §afeat: 调整相关API名称;
§618-05-14 §afeat: 新增Object.values垫片;
§618-05-14 §afeat: 新增工具类;
§618-05-14 §afeat: 更新MiaoScriptPackageManager;
§618-05-14 §cfix: 修复命令执行相关BUG;
§618-05-14 §afeat: 新增聊天相关API;
§618-05-14 §afeat: 优化方法调用;
§618-03-18 §afeat: 调整get方法 data 参数自动转query;
§618-03-18 §afeat: 优化插件代码结构;
§618-03-18 §cfix: 修复玩家人数获取错误 更新插件;
§618-01-11 §afeat: 更新http类库 server通过orElse返回undefined;
§618-01-11 §afeat: 更新基础类库;
§618-01-11 §afeat: 新增插件管理模块;
§618-01-10 §cfix: 修复主线程加载的BUG;
§618-01-10 §afeat: 修复fs相关BUG 优化插件加载 优化命令补全;
§618-01-10 §afeat: 更新.gitignore文件;
§618-01-10 §afeat: 新增案例插件 更新插件版本;
§618-01-09 §afeat: 优化API 修复http模块错误;
§618-01-09 §afeat: 更新 fs 类库 优化 require;
§618-01-09 §afeat: 安全起见暂时屏蔽load方法和disable方法;
§618-01-09 §cfix: 修复调试信息错误;
§618-01-08 §afeat: require新增基础目录api;
§618-01-08 §3doc: 新增README;
§618-01-08 §cfix: 修复重载命令无效的BUG;
§618-01-09 §afeat: 优化加载流程 完善事件注册;
§618-01-02 §afeat: 新增http网络访问模块;
§617-12-28 §afeat: 完善Sponge事件注册 新增player封装类;
§617-11-30 §afeat: 新增Sponge的兼容; §617-11-30 §afeat: 新增Sponge的兼容;
§617-11-03 §afeat: 新增抽奖插件; §617-11-03 §afeat: 新增抽奖插件;
§617-10-16 §cfix: 修复关闭MiaoScript时task异常; §617-10-16 §cfix: 修复关闭MiaoScript时task异常;

View File

@ -1,19 +1,8 @@
package pw.yumc.MiaoScript; package pw.yumc.MiaoScript;
import java.io.File;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.event.HandlerList;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import lombok.val;
import pw.yumc.YumCore.bukkit.Log;
import pw.yumc.YumCore.commands.CommandSub;
import pw.yumc.YumCore.commands.annotation.Cmd;
import pw.yumc.YumCore.commands.annotation.Help;
import pw.yumc.YumCore.commands.interfaces.Executor;
/** /**
* 喵式脚本 * 喵式脚本
@ -21,62 +10,14 @@ import pw.yumc.YumCore.commands.interfaces.Executor;
* @author 喵♂呜 * @author 喵♂呜
* @since 2016年8月29日 上午7:50:39 * @since 2016年8月29日 上午7:50:39
*/ */
public class MiaoScript extends JavaPlugin implements Executor { public class MiaoScript extends JavaPlugin {
private ScriptEngine engine; private ScriptEngine engine;
@Override @Override
@SneakyThrows @SneakyThrows
public void onEnable() { public void onEnable() {
new CommandSub("ms", this);
engine = new ScriptEngine(getDataFolder().getCanonicalPath(), getLogger()); engine = new ScriptEngine(getDataFolder().getCanonicalPath(), getLogger());
enableEngine();
}
@Cmd
@Help("执行 JS 代码")
@SneakyThrows
public void js(CommandSender sender, String script) {
result(sender, engine.getEngine().eval(script));
}
@Cmd
@Help("执行 JS 代码文件")
@SneakyThrows
public void file(CommandSender sender, String file) {
result(sender, engine.getEngine().eval("load('" + new File(getDataFolder(), file).getCanonicalPath() + "')"));
}
@Cmd
@Help("重启脚本引擎")
public void reload(CommandSender sender) {
engine.disableEngine();
val server = Bukkit.getServer();
try {
server.getScheduler().cancelTasks(this);
server.getServicesManager().unregisterAll(this);
HandlerList.unregisterAll(this);
server.getMessenger().unregisterIncomingPluginChannel(this);
server.getMessenger().unregisterOutgoingPluginChannel(this);
} catch (Exception ex) {
Log.d("Error reload", ex);
}
enableEngine();
Log.sender(sender, "§bMiaoScript §eEngine §a重启完成!");
}
private void result(CommandSender sender, Object result) {
if (result == null) {
Log.sender(sender, "§a运行成功! §c没有返回结果!");
} else {
Log.sender(sender, "§a运行成功! §b数据类型: §r%s §d结果: §r%s", result.getClass().getName(), result);
}
}
private void enableEngine() {
val origin = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(getClassLoader());
engine.enableEngine(); engine.enableEngine();
Thread.currentThread().setContextClassLoader(origin);
} }
@Override @Override

View File

@ -1,23 +1,13 @@
package pw.yumc.MiaoScript; package pw.yumc.MiaoScript;
import java.io.File; import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import javax.script.ScriptException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.spongepowered.api.Sponge;
import org.spongepowered.api.command.CommandResult;
import org.spongepowered.api.command.CommandSource;
import org.spongepowered.api.command.args.GenericArguments;
import org.spongepowered.api.command.spec.CommandSpec;
import org.spongepowered.api.config.ConfigDir; import org.spongepowered.api.config.ConfigDir;
import org.spongepowered.api.event.Listener; import org.spongepowered.api.event.Listener;
import org.spongepowered.api.event.game.state.GameInitializationEvent;
import org.spongepowered.api.event.game.state.GameStartedServerEvent; import org.spongepowered.api.event.game.state.GameStartedServerEvent;
import org.spongepowered.api.event.game.state.GameStoppingServerEvent;
import org.spongepowered.api.plugin.Plugin; import org.spongepowered.api.plugin.Plugin;
import org.spongepowered.api.text.Text;
import com.google.inject.Inject; import com.google.inject.Inject;
import lombok.SneakyThrows; import lombok.SneakyThrows;
@ -38,78 +28,16 @@ public class MiaoScriptSponge {
@ConfigDir(sharedRoot = false) @ConfigDir(sharedRoot = false)
private File pluginConfigDir; private File pluginConfigDir;
@Listener
public void onInit(GameInitializationEvent event) {
}
private CommandSpec main() {
return CommandSpec.builder()
.description(Text.of("喵式脚本主命令"))
.permission("MiaoScript.admin")
.child(js(), "js")
.child(file(), "file")
.child(reload(), "reload")
.build();
}
private CommandSpec js() {
return CommandSpec.builder()
.description(Text.of("执行JS命令"))
.arguments(GenericArguments.onlyOne(GenericArguments.remainingJoinedStrings(Text.of("js"))))
.executor((src, args) -> {
try {
result(src, engine.getEngine().eval(args.<String>getOne("js").orElse("")));
} catch (ScriptException e) {
e.printStackTrace();
}
return CommandResult.success();
})
.build();
}
private CommandSpec file() {
return CommandSpec.builder()
.description(Text.of("执行JS文件"))
.arguments(GenericArguments.onlyOne(GenericArguments.remainingJoinedStrings(Text.of("js"))))
.executor((src, args) -> {
try {
result(src, engine.getEngine().eval(new FileReader(new File(pluginConfigDir, args.<String>getOne("js").orElse("")))));
} catch (ScriptException | IOException e) {
e.printStackTrace();
}
return CommandResult.success();
})
.build();
}
private CommandSpec reload() {
return CommandSpec.builder()
.description(Text.of("重载 JS 引擎"))
.executor((src, args) -> {
engine.disableEngine();
Sponge.getEventManager().unregisterPluginListeners(this);
engine.enableEngine();
src.sendMessage(Text.of("§6[§bMiaoScript§6]§r §bMiaoScript §eEngine §a重启完成!"));
return CommandResult.success();
})
.build();
}
private void result(CommandSource sender, Object result) {
if (result == null) {
sender.sendMessage(Text.of("§a运行成功! §c没有返回结果!"));
} else {
sender.sendMessage(Text.of(String.format("§a运行成功! §b数据类型: §r%s §d结果: §r%s", result.getClass().getName(), result)));
}
}
@Listener @Listener
@SneakyThrows @SneakyThrows
public void onStart(GameStartedServerEvent event) { public void onStart(GameStartedServerEvent event) {
Sponge.getServer().getConsole();
Sponge.getCommandManager().register(this, main(), "ms", "mscript", "MiaoScript");
engine = new ScriptEngine(pluginConfigDir.getCanonicalPath(), logger); engine = new ScriptEngine(pluginConfigDir.getCanonicalPath(), logger);
engine.enableEngine(); engine.enableEngine();
} }
@Listener
@SneakyThrows
public void onStop(GameStoppingServerEvent event) {
engine.disableEngine();
}
} }

View File

@ -8,14 +8,15 @@ import java.nio.file.Paths;
import javax.script.ScriptEngineManager; import javax.script.ScriptEngineManager;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import pw.yumc.YumCore.annotation.NotProguard;
import pw.yumc.YumCore.engine.MiaoScriptEngine; import pw.yumc.YumCore.engine.MiaoScriptEngine;
/** /**
* Created with IntelliJ IDEA * Created with IntelliJ IDEA
* *
* @author 喵♂呜 * @author 喵♂呜
* Created on 2017/10/25 21:01. * Created on 2017/10/25 21:01.
*/ */
@NotProguard
public class ScriptEngine { public class ScriptEngine {
private String root; private String root;
private Object logger; private Object logger;
@ -31,6 +32,7 @@ public class ScriptEngine {
ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngineManager manager = new ScriptEngineManager();
this.engine = new MiaoScriptEngine(manager, "nashorn"); this.engine = new MiaoScriptEngine(manager, "nashorn");
this.engine.put("base", new Base()); this.engine.put("base", new Base());
this.engine.put("ScriptEngineContextHolder", this);
Path bios = Paths.get(root, "bios.js"); Path bios = Paths.get(root, "bios.js");
// 如果存在自定义bios就加载自定义的 // 如果存在自定义bios就加载自定义的
if (Files.exists(bios)) { if (Files.exists(bios)) {

View File

@ -1,51 +0,0 @@
package pw.yumc.MiaoScript;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
/**
* Created with IntelliJ IDEA
*
* @author 喵♂呜
* Created on 2017/9/30 21:32.
*/
public class ScriptEvent extends Event implements Cancellable {
private ScriptObjectMirror mirror;
private boolean cancelled = false;
public ScriptEvent(ScriptObjectMirror mirror) {
this.mirror = mirror;
}
public ScriptObjectMirror getMirror() {
return mirror;
}
public void setMirror(ScriptObjectMirror mirror) {
this.mirror = mirror;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
this.cancelled = cancel;
}
private static HandlerList handlerList = new HandlerList();
public static HandlerList getHandlerList() {
return handlerList;
}
@Override
public HandlerList getHandlers() {
return handlerList;
}
}

View File

@ -0,0 +1,10 @@
/*global Java, base, module, exports, require*/
function ChatHandlerDefault() {
// noinspection JSUnusedGlobalSymbols
this.tellraw = function(sender, raw) {
this.json(sender, JSON.stringify(raw));
}
}
var ChatHandler = Object.assign(new ChatHandlerDefault(), requireInternal('chat'));
exports = module.exports = ChatHandler;

View File

@ -1,2 +1,2 @@
/*global Java, base, module, exports, require*/ /*global Java, base, module, exports, require*/
module.exports = require('./msp.js').command; module.exports = requireInternal('command');

View File

@ -2,16 +2,21 @@
/** /**
* Bukkit 事件相关类 * Bukkit 事件相关类
*/ */
/*global Java, base, module, exports, require, __FILE__*/ /*global Java, base, module, exports, require, __FILE__*/
function EventHandlerDefault() { function EventHandlerDefault() {
var Thread = Java.type("java.lang.Thread"); var Thread = Java.type("java.lang.Thread");
// noinspection JSUnresolvedVariable
this.plugin = require('./server').plugin.self; this.plugin = require('./server').plugin.self;
this.mapEvent = []; this.mapEvent = [];
this.listenerMap = []; this.listenerMap = [];
this.baseEventDir = ''; this.baseEventDir = '';
// noinspection JSUnusedLocalSymbols
var self = this;
/** /**
* 扫描包 org.bukkit.event 下的所有事件 * 扫描包 org.bukkit.event 下的所有事件
* 映射简写名称 org.bukkit.event.player.PlayerLoginEvent => playerloginevent * 映射简写名称 org.bukkit.event.player.PlayerLoginEvent => playerloginevent
@ -38,10 +43,11 @@ function EventHandlerDefault() {
try { try {
var clz = base.getClass(i.substring(0, i.length - 6)); var clz = base.getClass(i.substring(0, i.length - 6));
// 继承于 org.bukkit.event.Event 访问符为Public // 继承于 org.bukkit.event.Event 访问符为Public
if (this.isVaildEvent(clz)) { if (this.isValidEvent(clz)) {
// noinspection JSUnresolvedVariable // noinspection JSUnresolvedVariable
var simpleName = this.class2Name(clz); var simpleName = this.class2Name(clz).toLowerCase();
console.debug("Mapping Event [%s] => %s".format(clz.name, simpleName)); /** @namespace clz.canonicalName */
console.debug("Mapping Event [%s] => %s".format(clz.canonicalName, simpleName));
this.mapEvent[simpleName] = clz; this.mapEvent[simpleName] = clz;
count++; count++;
} }
@ -53,44 +59,45 @@ function EventHandlerDefault() {
} }
} }
return count; return count;
} };
this.class2Name = function class2Name(clazz) { this.class2Name = function class2Name(clazz) {
return clazz.simpleName.toLowerCase(); return clazz.simpleName;
} };
this.name2Class = function name2Class(name, event) { this.name2Class = function name2Class(name, event) {
var eventCls = this.mapEvent[event] || this.mapEvent[event.toLowerCase()] || this.mapEvent[event + 'Event'] || this.mapEvent[event.toLowerCase() + 'event']; var eventCls = this.mapEvent[event.toLowerCase()] || this.mapEvent[event.toLowerCase() + 'event'];
if (!eventCls) { if (!eventCls) {
try { try {
eventCls = base.getClass(eventCls); eventCls = base.getClass(eventCls);
this.mapEvent[event] = eventCls; this.mapEvent[event] = eventCls;
} catch (ex) { } catch (ex) {
console.console("§6插件 §b%s §6注册事件 §c%s §6失败 §4事件未找到!".format(name, event)); console.console("§6插件 §b%s §6注册事件 §c%s §6失败 §4事件未找到!".format(name, event));
console.ex(new Error("插件 %s 注册事件 %s 失败 事件未找到!".format(name, event))) console.ex(new Error("插件 %s 注册事件 %s 失败 事件未找到!".format(name, event)));
return; return;
} }
} }
return eventCls; return eventCls;
} };
// noinspection JSUnusedLocalSymbols
/** /**
* 判断是否为一个有效的事件类 * 判断是否为一个有效的事件类
* @param clz * @param clz
* @returns {*|boolean} * @returns {*|boolean}
*/ */
this.isVaildEvent = function isVaildEvent(clz) { this.isValidEvent = function isValidEvent(clz) {
throw new Error("当前服务器不支持事件系统!"); throw new Error("当前服务器不支持事件系统!");
} };
// noinspection JSUnusedLocalSymbols
this.register = function register(eventCls, exec, priority, ignoreCancel) { this.register = function register(eventCls, exec, priority, ignoreCancel) {
throw new Error("当前服务器不支持事件系统!"); throw new Error("当前服务器不支持事件系统!");
} };
// noinspection JSUnusedLocalSymbols
this.unregister = function unregister(event, listener) { this.unregister = function unregister(event, listener) {
throw new Error("当前服务器不支持事件系统!"); throw new Error("当前服务器不支持事件系统!");
} };
this.execute = function execute(name, exec, eventCls) { this.execute = function execute(name, exec, eventCls) {
return function execute() { return function execute() {
try { try {
@ -100,8 +107,8 @@ function EventHandlerDefault() {
console.ex(ex); console.ex(ex);
} }
}.bind(this); }.bind(this);
} };
/** /**
* 添加事件监听 * 添加事件监听
* @param jsp * @param jsp
@ -114,7 +121,9 @@ function EventHandlerDefault() {
if (!jsp || !jsp.description || !jsp.description.name) throw new TypeError('插件名称为空 请检查传入参数!'); if (!jsp || !jsp.description || !jsp.description.name) throw new TypeError('插件名称为空 请检查传入参数!');
var name = jsp.description.name; var name = jsp.description.name;
var eventCls = this.name2Class(name, event); var eventCls = this.name2Class(name, event);
if (!eventCls) { return; } if (!eventCls) {
return;
}
if (typeof priority === 'boolean') { if (typeof priority === 'boolean') {
ignoreCancel = priority; ignoreCancel = priority;
priority = 'NORMAL'; priority = 'NORMAL';
@ -128,7 +137,7 @@ function EventHandlerDefault() {
if (!listenerMap[name]) listenerMap[name] = []; if (!listenerMap[name]) listenerMap[name] = [];
var offExec = function () { var offExec = function () {
this.unregister(eventCls, listener); this.unregister(eventCls, listener);
console.debug('插件 %s 注销事件 %s'.format(name, eventCls.name.substring(eventCls.name.lastIndexOf(".") + 1))); console.debug('插件 %s 注销事件 %s'.format(name, this.class2Name(eventCls)));
}.bind(this); }.bind(this);
var off = { var off = {
event: eventCls, event: eventCls,
@ -137,19 +146,20 @@ function EventHandlerDefault() {
}; };
listenerMap[name].push(off); listenerMap[name].push(off);
// noinspection JSUnresolvedVariable // noinspection JSUnresolvedVariable
console.debug('插件 %s 注册事件 %s => %s'.format(name, eventCls.name.substring(eventCls.name.lastIndexOf(".") + 1), exec.name === '' ? '匿名方法' : exec.name)); console.debug('插件 %s 注册事件 %s => %s'.format(name, this.class2Name(eventCls), exec.name === '' ? '匿名方法' : exec.name));
return off; return off;
} }
} }
var EventHandler = Object.assign(new EventHandlerDefault(), requireInternal('event')); var EventHandler = Object.assign(new EventHandlerDefault(), requireInternal('event'));
// 映射事件名称 // 映射事件名称
console.info('%s 事件映射完毕 共计 %s 个事件!'.format(DetectServerType, EventHandler.mapEventName().toFixed(0))); console.info('%s 事件映射完毕 共计 %s 个事件!'.format(DetectServerType, EventHandler.mapEventName().toFixed(0)));
module.exports = { module.exports = {
on: EventHandler.listen.bind(EventHandler), on: EventHandler.listen.bind(EventHandler),
disable: function (jsp) { disable: function (jsp) {
var jspl = EventHandler.listenerMap[jsp.description.name]; var eventCache = EventHandler.listenerMap[jsp.description.name];
if (jspl) { if (eventCache) {
jspl.forEach(function (t) t.off.call(EventHandler)); eventCache.forEach(function (t) t.off.call(EventHandler));
delete EventHandler.listenerMap[jsp.description.name]; delete EventHandler.listenerMap[jsp.description.name];
} }
} }

View File

@ -1,2 +1,2 @@
/*global Java, base, module, exports, require*/ /*global Java, base, module, exports, require*/
module.exports = require('./msp.js').item; module.exports = requireInternal('item');

View File

@ -1,13 +0,0 @@
/*global Java, base, module, exports, require*/
function impl(name) {
return require('../internal/' + DetectServerType + '/' + name, {warnNotFound: false});
}
exports = module.exports = {
command: impl('command'),
event: impl('event'),
permission: impl('permission'),
server: impl('server'),
task: impl('task'),
item: impl('item')
};

View File

@ -1,2 +1,2 @@
/*global Java, base, module, exports, require*/ /*global Java, base, module, exports, require*/
module.exports = require('./msp.js').permission; module.exports = requireInternal('permission', {warnNotFound: false});

View File

@ -1,9 +1,9 @@
'use strict'; 'use strict';
/** /**
* MiaoScript脚本插件加载类 * MiaoScript脚本插件加载类
* @namespace plugin.configFile.parentFile, command.enable, permission.enable
*/ */
/*global Java, module, exports, require, __FILE__*/ /*global Java, module, exports, require, __FILE__*/
// var zip = require("core/zip");
var fs = require('core/fs'); var fs = require('core/fs');
var yaml = require('modules/yaml'); var yaml = require('modules/yaml');
var event = require('./event'); var event = require('./event');
@ -23,10 +23,10 @@ function loadPlugins(dir) {
console.info("开始扫描 %s 下的插件 ...".format(plugin)); console.info("开始扫描 %s 下的插件 ...".format(plugin));
createUpdate(plugin); createUpdate(plugin);
var files = []; var files = [];
fs.list(plugin).forEach(function (file) { fs.list(plugin).forEach(function searchPlugin(file) {
files.push(file.toFile()); files.push(file.toFile());
}); });
fs.list(fs.file(plugin, DetectServerType)).forEach(function (file) { fs.list(fs.file(plugin, DetectServerType)).forEach(function searchDetectServerPlugin(file) {
files.push(file.toFile()); files.push(file.toFile());
}); });
loadZipPlugins(files); loadZipPlugins(files);
@ -50,33 +50,41 @@ function createUpdate(path) {
* @param files * @param files
*/ */
function loadZipPlugins(files) { function loadZipPlugins(files) {
// // TODO ZIP类型插件加载 files.filter(function filterZipPlugin(file) {
// files.filter(function (file) { return file.name.endsWith(".zip");
// return file.name.endsWith(".zip"); }).forEach(function loadZipPlugin(file) {
// }).forEach(function (file) { // console.log(file);
// zip.unzip(fs.file(plugins_dir, file)); // console.log(fs.file(file,"!package.json"))
// var dir = new File(plugins_dir, file.name.split(".")[0]); // zip.unzip(fs.file(plugins_dir, file));
// // TODO 添加文件夹类型的插件兼容 // var dir = new File(plugins_dir, file.name.split(".")[0]);
// }); // TODO 添加文件夹类型的插件兼容
});
} }
/** /**
* JS类型插件预加载 * JS类型插件预加载
*/ */
function loadJsPlugins(files) { function loadJsPlugins(files) {
files.filter(function (file) { files.filter(function filterJsPlugin(file) {
return file.name.endsWith(".js") return file.name.endsWith(".js")
}).forEach(function (file) { }).forEach(function loadJsPlugin(file) {
try { loadPlugin(file)
loadPlugin(file);
} catch (ex) {
console.console('§6插件 §b%s §6初始化时发生错误 §4%s'.format(fs.path(file), ex.message));
console.ex(ex);
}
}) })
} }
function loadPlugin(file) { function loadPlugin(file) {
try {
var plugin = readPlugin(file);
initPlugin(plugin);
plugins[plugin.description.name] = plugin;
return plugin
} catch (ex) {
console.console('§6插件 §b%s §6初始化时发生错误 §4%s'.format(file.name, ex.message));
console.ex(ex);
}
}
function readPlugin(file) {
var update = fs.file(fs.file(file.parentFile, 'update'), file.name); var update = fs.file(fs.file(file.parentFile, 'update'), file.name);
if (update.exists()) { if (update.exists()) {
console.info('自动升级插件 %s'.format(file.name)); console.info('自动升级插件 %s'.format(file.name));
@ -87,15 +95,19 @@ function loadPlugin(file) {
hook: function (origin) { hook: function (origin) {
return beforeLoadHook(origin); return beforeLoadHook(origin);
} }
}) });
console.debug("插件编译结果: %s".format(JSON.stringify(plugin))); console.debug("插件编译结果: %s".format(JSON.stringify(plugin)));
plugin.__FILE__ = file;
return plugin;
}
function initPlugin(plugin) {
var desc = plugin.description; var desc = plugin.description;
if (!desc || !desc.name) { if (!desc || !desc.name) {
console.warn("文件 %s 不存在 description 描述信息 无法加载插件!".format(file)); throw new Error("文件 %s 不存在 description 描述信息 无法加载插件!".format(plugin.__FILE__));
} else { } else {
initPlugin(file, plugin); internalInitPlugin(plugin);
afterLoadHook(plugin); afterLoadHook(plugin);
plugins[plugin.description.name] = plugin;
console.info('载入插件 %s 版本 %s By %s'.format(desc.name, desc.version || '未知', desc.author || '未知')); console.info('载入插件 %s 版本 %s By %s'.format(desc.name, desc.version || '未知', desc.author || '未知'));
} }
return plugin; return plugin;
@ -106,9 +118,9 @@ function beforeLoadHook(origin) {
// 处理 event 为了不影响 正常逻辑 event 还是手动require吧 // 处理 event 为了不影响 正常逻辑 event 还是手动require吧
// result = result + 'var event = {}; module.exports.event = event;'; // result = result + 'var event = {}; module.exports.event = event;';
// 注入 console 对象 // 给插件注入单独的 console // 注入 console 对象 // 给插件注入单独的 console
result = result + 'var console = new Console(); module.exports.console = console;'; result += '\nvar console = new Console(); module.exports.console = console;';
// 插件注入 self 对象 // 插件注入 self 对象
result = result + 'var self = {}; module.exports.self = self;'; result += '\nvar self = {}; module.exports.self = self;';
return result; return result;
} }
@ -123,15 +135,13 @@ function afterLoadHook(plugin) {
/** /**
* 初始化插件内容(提供config,__DATA__等参数) * 初始化插件内容(提供config,__DATA__等参数)
*/ */
function initPlugin(file, plugin) { function internalInitPlugin(plugin) {
// 初始化 __FILE__
plugin.__FILE__ = file;
// 初始化 __DATA__ // 初始化 __DATA__
plugin.__DATA__ = plugin.dataFolder = fs.file(file.parentFile, plugin.description.name); plugin.__DATA__ = plugin.dataFolder = fs.file(plugin.__FILE__.parentFile, plugin.description.name);
// 初始化 getDataFolder() // 初始化 getDataFolder()
plugin.getDataFolder = function getDataFolder() { plugin.getDataFolder = function getDataFolder() {
return plugin.__DATA__; return plugin.__DATA__;
} };
// 初始化 getFile() // 初始化 getFile()
plugin.getFile = plugin.file = function getFile(name) { plugin.getFile = plugin.file = function getFile(name) {
return fs.file(plugin.getDataFolder(), name); return fs.file(plugin.getDataFolder(), name);
@ -139,7 +149,9 @@ function initPlugin(file, plugin) {
// 初始化插件配置相关方法 // 初始化插件配置相关方法
initPluginConfig(plugin); initPluginConfig(plugin);
/** @namespace command.enable */
if (command.enable) command.enable(plugin); if (command.enable) command.enable(plugin);
/** @namespace permission.enable */
if (permission.enable) permission.enable(plugin); if (permission.enable) permission.enable(plugin);
} }
@ -149,6 +161,12 @@ function initPlugin(file, plugin) {
function initPluginConfig(plugin) { function initPluginConfig(plugin) {
// 初始化 config // 初始化 config
plugin.configFile = plugin.getFile('config.yml'); plugin.configFile = plugin.getFile('config.yml');
// 判断插件目录是否存在 并且不为文件 否则删除重建
// noinspection JSValidateTypes
if (!plugin.configFile.parentFile.isDirectory()) {
fs.del(plugin.configFile.parentFile);
}
plugin.configFile.parentFile.mkdirs();
/** /**
* 获取配置文件 * 获取配置文件
* @constructor * @constructor
@ -163,9 +181,9 @@ function initPluginConfig(plugin) {
if (!file.isFile) { if (!file.isFile) {
file = plugin.getFile(file); file = plugin.getFile(file);
} }
return yaml.safeLoad(fs.read(file), { json: true }); return yaml.safeLoad(fs.read(file), {json: true});
} }
} };
/** /**
* 重载配置文件 * 重载配置文件
* @constructor * @constructor
@ -173,7 +191,7 @@ function initPluginConfig(plugin) {
*/ */
plugin.reloadConfig = function () { plugin.reloadConfig = function () {
plugin.config = plugin.getConfig(plugin.configFile); plugin.config = plugin.getConfig(plugin.configFile);
} };
/** /**
* 保存配置文件 * 保存配置文件
* @constructor * @constructor
@ -182,16 +200,16 @@ function initPluginConfig(plugin) {
plugin.saveConfig = function () { plugin.saveConfig = function () {
switch (arguments.length) { switch (arguments.length) {
case 0: case 0:
plugin.configFile.parentFile.mkdirs();
fs.save(plugin.configFile, yaml.safeDump(plugin.config)); fs.save(plugin.configFile, yaml.safeDump(plugin.config));
break; break;
case 2: case 2:
fs.save(fs.file(plugin.__DATA__, arguments[0]), yaml.safeDump(arguments[1])); fs.save(fs.file(plugin.__DATA__, arguments[0]), yaml.safeDump(arguments[1]));
break; break;
} }
} };
// noinspection JSValidateTypes
if (plugin.configFile.isFile()) { if (plugin.configFile.isFile()) {
plugin.config = plugin.getConfig('config.yml'); plugin.config = Object.assign(plugin.description.config, plugin.getConfig('config.yml'));
} else if (plugin.description.config) { } else if (plugin.description.config) {
plugin.config = plugin.description.config; plugin.config = plugin.description.config;
plugin.saveConfig(); plugin.saveConfig();
@ -204,13 +222,14 @@ function checkAndGet(args) {
} }
var name = args[0]; var name = args[0];
// 如果是插件 则直接返回 // 如果是插件 则直接返回
if (name.description) { if (name && name.description) {
return [name]; return [name];
} }
if (!exports.plugins[name]) { var plugin = exports.plugins[name];
if (!plugin) {
throw new Error("插件 " + name + " 不存在!"); throw new Error("插件 " + name + " 不存在!");
} }
return [exports.plugins[name]]; return [plugin];
} }
function checkAndRun(args, name, ext) { function checkAndRun(args, name, ext) {
@ -221,7 +240,7 @@ function checkAndRun(args, name, ext) {
try { try {
// 绑定方法的this到插件自身 // 绑定方法的this到插件自身
if (typeof exec === "function") exec.call(jsp); if (typeof exec === "function") exec.call(jsp);
if (ext) ext.call(jsp); if (typeof ext === "function") ext.call(jsp);
} catch (ex) { } catch (ex) {
console.console('§6插件 §b%s §6执行 §d%s §6方法时发生错误 §4%s'.format(jsp.description.name, name, ex.message)); console.console('§6插件 §b%s §6执行 §d%s §6方法时发生错误 §4%s'.format(jsp.description.name, name, ex.message));
console.ex(ex); console.ex(ex);
@ -232,27 +251,27 @@ function checkAndRun(args, name, ext) {
var plugins = []; var plugins = [];
function init(path) { function init(path) {
var plugin = exports.$ var plugin = exports.$;
if (plugin !== null) { if (plugin !== null) {
// 如果plugin不等于null 则代表是正式环境 // 如果plugin不等于null 则代表是正式环境
console.info("初始化 MiaoScript 插件系统: %s".format(plugin)); console.info("初始化 MiaoScript 插件系统: %s".format(plugin));
} }
loadPlugins(path); loadPlugins(path);
}; }
function load() { function load() {
checkAndRun(arguments, 'load'); checkAndRun(arguments, 'load');
}; }
function enable() { function enable() {
checkAndRun(arguments, 'enable'); checkAndRun(arguments, 'enable');
}; }
function disable() { function disable() {
checkAndRun(arguments, 'disable', function eventDisable() { checkAndRun(arguments, 'disable', function eventDisable() {
event.disable(this); event.disable(this);
}); });
}; }
function reload() { function reload() {
checkAndGet(arguments).forEach(function (p) { checkAndGet(arguments).forEach(function (p) {
@ -261,8 +280,9 @@ function reload() {
load(p); load(p);
enable(p); enable(p);
}); });
}; }
// noinspection JSUnresolvedVariable
exports = module.exports = { exports = module.exports = {
$: server.plugin.self, $: server.plugin.self,
plugins: plugins, plugins: plugins,
@ -270,5 +290,6 @@ exports = module.exports = {
load: load, load: load,
enable: enable, enable: enable,
disable: disable, disable: disable,
reload: reload reload: reload,
} loadPlugin: loadPlugin
};

View File

@ -1,2 +1,2 @@
/*global Java, base, module, exports, require*/ /*global Java, base, module, exports, require*/
module.exports = require('./msp.js').server; module.exports = requireInternal('server');

View File

@ -1,2 +1,11 @@
'use strict';
/**
* MiaoScript Task处理类
* @namespace plugin.configFile.parentFile, command.enable, permission.enable
*/
/*global Java, base, module, exports, require*/ /*global Java, base, module, exports, require*/
module.exports = require('./msp.js').task; function TaskHandlerDefault() {
}
var TaskHandler = Object.assign(new TaskHandlerDefault(), requireInternal('task'));
exports = module.exports = TaskHandler;

View File

@ -2,4 +2,4 @@
var player = requireInternal('wrapper/player'); var player = requireInternal('wrapper/player');
module.exports = { module.exports = {
player: player.$ player: player.$
} };

View File

@ -2,6 +2,7 @@
var log; var log;
var boot; var boot;
var disable; var disable;
// noinspection ThisExpressionReferencesGlobalObjectJS
var global = this; var global = this;
/** /**
* 初始化框架引擎 * 初始化框架引擎
@ -35,7 +36,8 @@ var global = this;
var pluginYml; var pluginYml;
function checkClassLoader() { function checkClassLoader() {
var classLoader = java.lang.Thread.currentThread().getContextClassLoader(); // noinspection JSUnresolvedVariable
var classLoader = java.lang.Thread.currentThread().contextClassLoader;
pluginYml = classLoader.getResource("plugin.yml"); pluginYml = classLoader.getResource("plugin.yml");
if (pluginYml === null) { if (pluginYml === null) {
log.info("==================== ERROR ===================="); log.info("==================== ERROR ====================");
@ -47,8 +49,8 @@ var global = this;
} }
function release(root, regex, replace) { function release(root, regex, replace) {
var upath = pluginYml.getFile().substring(pluginYml.getFile().indexOf("/") + 1); var filePath = pluginYml.getFile().substring(pluginYml.getFile().indexOf("/") + 1);
var jarPath = java.net.URLDecoder.decode(upath.substring(0, upath.indexOf('!'))); var jarPath = java.net.URLDecoder.decode(filePath.substring(0, filePath.indexOf('!')));
if (!java.nio.file.Files.exists(java.nio.file.Paths.get(jarPath))) { if (!java.nio.file.Files.exists(java.nio.file.Paths.get(jarPath))) {
jarPath = "/" + jarPath; jarPath = "/" + jarPath;
} }
@ -56,9 +58,11 @@ var global = this;
var r = new RegExp(regex);// "[core|modules]/.*" var r = new RegExp(regex);// "[core|modules]/.*"
jar.stream().forEach(function (entry) { jar.stream().forEach(function (entry) {
try { try {
// noinspection JSValidateTypes
if (!entry.isDirectory()) { if (!entry.isDirectory()) {
if (r.test(entry.name)) { if (r.test(entry.name)) {
var path = java.nio.file.Paths.get(root, entry.name); var path = java.nio.file.Paths.get(root, entry.name);
// noinspection JSUnresolvedVariable
var parentFile = path.toFile().parentFile; var parentFile = path.toFile().parentFile;
if (!parentFile.exists()) { parentFile.mkdirs(); } if (!parentFile.exists()) { parentFile.mkdirs(); }
if (!java.nio.file.Files.exists(path) || replace) { if (!java.nio.file.Files.exists(path) || replace) {

View File

@ -12,6 +12,7 @@
}.bind(this), }.bind(this),
set: function (name) { set: function (name) {
this._name = name ? '[' + name + '] ' : ''; this._name = name ? '[' + name + '] ' : '';
// noinspection JSUnusedGlobalSymbols
this.prefix = name ? '§6[§cMS§6][§b' + name + '§6]§r ' : '§6[§bMiaoScript§6]§r '; this.prefix = name ? '§6[§cMS§6][§b' + name + '§6]§r ' : '§6[§bMiaoScript§6]§r ';
}.bind(this) }.bind(this)
}); });
@ -19,6 +20,7 @@
this.log = this.info = function () { this.log = this.info = function () {
log.info(this.name + Array.prototype.join.call(arguments, ' ')); log.info(this.name + Array.prototype.join.call(arguments, ' '));
}; };
// noinspection JSUnusedGlobalSymbols
this.warn = function () { this.warn = function () {
log.warning(this.name + Array.prototype.join.call(arguments, ' ')); log.warning(this.name + Array.prototype.join.call(arguments, ' '));
}; };
@ -35,7 +37,7 @@
for (var i in obj) { for (var i in obj) {
this.log(i, '=>', obj[i]) this.log(i, '=>', obj[i])
} }
} };
this.ex = function (message, ex) { this.ex = function (message, ex) {
if (!ex) { if (!ex) {
this.console('§4' + message); this.console('§4' + message);
@ -55,6 +57,6 @@
} }
}.bind(this)); }.bind(this));
}; };
} };
global.Console = ConsoleDefault; global.Console = ConsoleDefault;
})(global); })(global);

View File

@ -3,18 +3,21 @@
/*global Java, base, module, exports, require, __FILE__*/ /*global Java, base, module, exports, require, __FILE__*/
var File = Java.type("java.io.File"); var File = Java.type("java.io.File");
var Files = Java.type("java.nio.file.Files"); var Files = Java.type("java.nio.file.Files");
// noinspection JSUnresolvedVariable
var separatorChar = File.separatorChar; var separatorChar = File.separatorChar;
var StandardCopyOption = Java.type("java.nio.file.StandardCopyOption"); var StandardCopyOption = Java.type("java.nio.file.StandardCopyOption");
// noinspection JSUnusedLocalSymbols
var _toString = function (obj) { var _toString = function (obj) {
return Object.prototype.toString.call(obj); return Object.prototype.toString.call(obj);
} };
/** /**
* 用文件分割符合并路径 * 用文件分割符合并路径
*/ */
function concat() { function concat() {
return Array.prototype.join.call(arguments, separatorChar); return Array.prototype.join.call(arguments, separatorChar);
}; }
/** /**
* 获得文件 * 获得文件
* @constructor(file) * @constructor(file)
@ -27,39 +30,43 @@ function file() {
} }
switch (arguments.length) { switch (arguments.length) {
case 1: case 1:
var f = arguments[0] var f = arguments[0];
if (f instanceof File) { if (f instanceof File) {
return f; return f;
} }
if (typeof f === "string") { if (typeof f === "string") {
return new File(f); return new File(f);
} }
if (f instanceof Path) { if (f instanceof java.nio.file.Path) {
return f.toFile(); return f.toFile();
} }
case 2: break;
return new File(exports.file(arguments[0]), arguments[1]); default:
return new File(file(arguments[0]), arguments[1]);
} }
}; }
/** /**
* 创建目录 * 创建目录
* @param file * @param path
*/ */
function mkdirs(file) { function mkdirs(path) {
// noinspection JSUnresolvedVariable // noinspection JSUnresolvedVariable
file.parentFile.mkdirs(); fs.file(path).parentFile.mkdirs();
}; }
/** /**
* 创建文件 * 创建文件
* @param file * @param file
*/ */
function create(file) { function create(file) {
f = file(file); var f = fs.file(path);
if (!f.exists()) { if (!f.exists()) {
mkdirs(f); mkdirs(f);
f.createNewFile(); f.createNewFile();
} }
}; }
/** /**
* 获得文件规范路径 * 获得文件规范路径
* @param file * @param file
@ -67,8 +74,9 @@ function create(file) {
*/ */
function path(file) { function path(file) {
// noinspection JSUnresolvedVariable // noinspection JSUnresolvedVariable
return file.canonicalPath; return fs.file(file).canonicalPath;
}; }
/** /**
* 复制文件 * 复制文件
* @param inputStream 输入流 * @param inputStream 输入流
@ -77,20 +85,22 @@ function path(file) {
*/ */
function copy(inputStream, target, override) { function copy(inputStream, target, override) {
Files.copy(inputStream, target.toPath(), StandardCopyOption[override ? 'REPLACE_EXISTING' : 'ATOMIC_MOVE']); Files.copy(inputStream, target.toPath(), StandardCopyOption[override ? 'REPLACE_EXISTING' : 'ATOMIC_MOVE']);
}; }
/** /**
* 读取文件 * 读取文件
* @param file 文件路径 * @param path 文件路径
*/ */
function read(f) { function read(path) {
var file = exports.file(f); var file = fs.file(path);
if (!file.exists()) { if (!file.exists()) {
console.warn('读取文件', file, '错误 文件不存在!'); console.warn('读取文件', file, '错误 文件不存在!');
return; return;
} }
// noinspection JSPrimitiveTypeWrapperUsage // noinspection JSPrimitiveTypeWrapperUsage
return new java.lang.String(Files.readAllBytes(file.toPath()), "UTF-8"); return new java.lang.String(Files.readAllBytes(file.toPath()), "UTF-8");
}; }
/** /**
* 保存内容文件 * 保存内容文件
* @param path 路径 * @param path 路径
@ -98,24 +108,25 @@ function read(f) {
* @param override 是否覆盖 * @param override 是否覆盖
*/ */
function save(path, content, override) { function save(path, content, override) {
var file = new File(path); var file = fs.file(path);
file.getParentFile().mkdirs(); file.getParentFile().mkdirs();
Files.write(file.toPath(), Files.write(file.toPath(), new java.lang.String(content).getBytes("UTF-8"));
content.getBytes("UTF-8"), }
override ? StandardCopyOption['REPLACE_EXISTING'] : StandardCopyOption['ATOMIC_MOVE']);
};
/** /**
* 列出目录文件 * 列出目录文件
* @param path * @param path
*/ */
function list(path) { function list(path) {
var dir = file(path); var dir = file(path);
// noinspection JSValidateTypes
if (dir.isDirectory()) { if (dir.isDirectory()) {
return Files.list(dir.toPath()); return Files.list(dir.toPath());
} }
console.debug('路径', path, '不是一个目录 返回空数组!'); console.debug('路径', path, '不是一个目录 返回空数组!');
return []; return [];
}; }
/** /**
* 移动文件 * 移动文件
* @param src 原始目录 * @param src 原始目录
@ -123,30 +134,46 @@ function list(path) {
* @param override 是否覆盖 * @param override 是否覆盖
*/ */
function move(src, des, override) { function move(src, des, override) {
Files.move(file(src).toPath(), file(des).toPath(), Files.move(fs.file(src).toPath(), fs.file(des).toPath(),
override ? StandardCopyOption['REPLACE_EXISTING'] : StandardCopyOption['ATOMIC_MOVE']) override ? StandardCopyOption['REPLACE_EXISTING'] : StandardCopyOption['ATOMIC_MOVE'])
}; }
function del(file) { function del(file) {
file = exports.file(file); file = fs.file(file);
if (!file.exists()) { return; } if (!file.exists()) {
return;
}
// noinspection JSValidateTypes
if (file.isDirectory()) { if (file.isDirectory()) {
Files.list(file.toPath()).collect(Collectors.toList()).forEach(function (f) { del(f); }) // noinspection JSUnresolvedVariable
Files.list(file.toPath()).collect(java.util.stream.Collector.toList()).forEach(function (f) {
del(f);
})
} }
Files.delete(file.toPath()); Files.delete(file.toPath());
} }
exports = module.exports = { // noinspection JSUnusedLocalSymbols
canonical: path, function exists(file) {
return fs.file(file).exists()
}
var fs = {};
fs.path = fs.canonical = fs.realpath = path;
fs.write = fs.save = save;
fs.readdir = fs.list = list;
fs.rename = fs.move = move;
fs.delete = fs.del = del;
// noinspection JSUnusedGlobalSymbols
Object.assign(fs, {
concat: concat, concat: concat,
create: create, create: create,
mkdirs: mkdirs, mkdirs: mkdirs,
file: file, file: file,
path: path,
copy: copy, copy: copy,
read: read, read: read
save: save, });
list: list,
move: move, exports = module.exports = fs;
del: del
}

View File

@ -7,8 +7,9 @@
global.root = root; global.root = root;
global.noop = function () { global.noop = function () {
}; };
var startTime = new Date().getTime();
loadCore(); loadCore();
loadExt(); loadPatch();
loadRequire(); loadRequire();
try { try {
loadServerLib(); loadServerLib();
@ -17,6 +18,7 @@
console.console("§4初始化插件基础系统库错误:§c", ex); console.console("§4初始化插件基础系统库错误:§c", ex);
console.ex(ex); console.ex(ex);
} }
console.log('MiaoScript Engine Load Complete... Done (' + (new Date().getTime() - startTime) / 1000 + 's)!');
}; };
/** /**
@ -38,19 +40,19 @@
global.engineLoad = load; global.engineLoad = load;
global.load = function __denyGlobalLoad__() { global.load = function __denyGlobalLoad__() {
throw new Error('系统内部不许允许使用 load 如需执行脚本 请使用 engineLoad !'); throw new Error('系统内部不许允许使用 load 如需执行脚本 请使用 engineLoad !');
} };
// 初始化加载器 // 初始化加载器
global.require = engineLoad(root + '/core/require.js')(root); global.require = engineLoad(root + '/core/require.js')(root);
global.requireInternal = function requireInternal(name) { global.requireInternal = function requireInternal(name) {
return require(root + '/internal/' + DetectServerType + '/' + name + '.js'); return require(root + '/internal/' + DetectServerType + '/' + name + '.js', arguments[1]);
} }
} }
/** /**
* 加载补丁 * 加载补丁
*/ */
function loadExt() { function loadPatch() {
java.nio.file.Files.list(new java.io.File(root, 'core/ext').toPath()).forEach(function (path) { java.nio.file.Files.list(new java.io.File(root, 'core/patch').toPath()).forEach(function (path) {
console.log('加载扩展类库', path); console.log('加载扩展类库', path);
try { try {
load(path.toFile()); load(path.toFile());
@ -100,8 +102,17 @@
* 关闭插件Hook * 关闭插件Hook
*/ */
global.engineDisable = function disable() { global.engineDisable = function disable() {
if (global.manager && global.manager.$) { try {
global.manager.disable(); if (global.manager && global.manager.$) {
global.manager.disable();
}
var server = require('api/server');
if (server.shutdown) {
server.shutdown();
}
} catch (ex) {
console.console("§3MiaoScript Engine §aShutDown §4Error... ERR: ", ex);
console.ex(ex);
} }
} }
})(global); })(global);

View File

@ -0,0 +1,19 @@
/**
* 补丁和方法扩展
*/
(function () {
// noinspection JSUnresolvedVariable
if (!Array.prototype.copyPartialMatches) {
Object.defineProperty(Array.prototype, "copyPartialMatches", {
enumerable: false,
value: function (token, array) {
this.forEach(function (e) {
if (e.toLowerCase().startsWith(token.toLowerCase())) {
array.push(e)
}
});
return array
}
});
}
})();

View File

@ -9,7 +9,7 @@
* @param fmt 格式化字符串 * @param fmt 格式化字符串
* @returns {*} * @returns {*}
*/ */
Date.prototype.format = function (fmt) { //author: meizz Date.prototype.format = function (fmt) {
var o = { var o = {
"M+": this.getMonth() + 1, //月份 "M+": this.getMonth() + 1, //月份
"d+": this.getDate(), //日 "d+": this.getDate(), //日

View File

@ -9,7 +9,7 @@
enumerable: false, enumerable: false,
configurable: true, configurable: true,
writable: true, writable: true,
value: function(target) { value: function (target) {
"use strict"; "use strict";
if (target === undefined || target === null) if (target === undefined || target === null)
throw new TypeError("Cannot convert first argument to object"); throw new TypeError("Cannot convert first argument to object");
@ -28,16 +28,37 @@
} }
}); });
} }
// // JSON快捷方法 if (!Object.values) {
if(!Object.toJson){ Object.defineProperty(Object, "values", {
enumerable: false,
configurable: true,
writable: true,
value: function (target) {
"use strict";
var values = [];
for (var key in target) {
var desc = Object.getOwnPropertyDescriptor(target, key);
if (desc !== undefined && desc.enumerable) values.push(target[key]);
}
return values;
}
});
}
// JSON快捷方法
if (!Object.toJson) {
Object.defineProperty(Object.prototype, "toJson", { Object.defineProperty(Object.prototype, "toJson", {
enumerable: false, enumerable: false,
value: function() { configurable: true,
writable: true,
value: function () {
return JSON.stringify(this); return JSON.stringify(this);
} }
}); });
} }
// Object.prototype.toJson = function () { // Object.prototype.toJson = function () {
// return JSON.stringify(this); // return JSON.stringify(this);
// }; // };

View File

@ -1,7 +1,6 @@
/** /**
* 补丁和方法扩展 * 补丁和方法扩展
*/ */
(function () { (function () {
// Java格式化方法 // Java格式化方法
var str = Java.type('java.lang.String'); var str = Java.type('java.lang.String');

View File

@ -33,12 +33,12 @@
var cacheDir = parent + separatorChar + "runtime"; var cacheDir = parent + separatorChar + "runtime";
var paths = [parent, parent + separatorChar + 'core', parent + separatorChar + 'api', parent + separatorChar + 'modules']; var paths = [parent, parent + separatorChar + 'core', parent + separatorChar + 'api', parent + separatorChar + 'modules'];
try{ try {
base.delete(cacheDir); base.delete(cacheDir);
} catch (ex) { } catch (ex) {
console.ex(ex); console.ex(ex);
} }
/** /**
* 判断是否为一个文件 * 判断是否为一个文件
* @param file * @param file
@ -129,6 +129,7 @@
var _package = new File(dir, 'package.json'); var _package = new File(dir, 'package.json');
if (_package.exists()) { if (_package.exists()) {
var json = JSON.parse(base.read(_package)); var json = JSON.parse(base.read(_package));
/** @namespace json.main */
if (json.main) { if (json.main) {
return resolveAsFile(dir, json.main); return resolveAsFile(dir, json.main);
} }
@ -181,6 +182,7 @@
compileJson(module, file, optional); compileJson(module, file, optional);
} }
if (_canonical(file).endsWith('.msm')) { if (_canonical(file).endsWith('.msm')) {
// noinspection ExceptionCaughtLocallyJS
throw Error("暂不支持解析 MiaoScript 模块"); throw Error("暂不支持解析 MiaoScript 模块");
} }
} catch (ex) { } catch (ex) {
@ -192,6 +194,7 @@
/** /**
* 预编译JS * 预编译JS
* @param module JS模块
* @param file JS文件 * @param file JS文件
* @param optional 附加选项 * @param optional 附加选项
* @returns {Object} * @returns {Object}
@ -202,7 +205,7 @@
if (optional.hook) { if (optional.hook) {
origin = optional.hook(origin); origin = optional.hook(origin);
} }
base.save(cacheFile, "(function __init__(module, exports, require, __dirname, __filename) {" + origin + "});"); base.save(cacheFile, "(function $(module, exports, require, __dirname, __filename) {" + origin + "});");
// 使用 load 可以保留行号和文件名称 // 使用 load 可以保留行号和文件名称
var compiledWrapper = engineLoad(cacheFile); var compiledWrapper = engineLoad(cacheFile);
try { try {
@ -218,6 +221,7 @@
/** /**
* 预编译Json * 预编译Json
* @param module Json模块
* @param file Json 文件 * @param file Json 文件
* @param optional 附加选项 * @param optional 附加选项
* @returns {Object} * @returns {Object}

View File

@ -0,0 +1,58 @@
/*global Java, base, module, exports, require*/
var bukkit = require('api/server');
var nmsChatSerializerClass;
var packetTypeClass;
var nmsChatMessageTypeClass;
var chatMessageTypes;
var String = Java.type('java.lang.String');
function init() {
/** @namespace bukkit.nmsVersion */
nmsChatSerializerClass = bukkit.nmsCls(bukkit.nmsVersion.split("_")[1] > 7 ? "IChatBaseComponent$ChatSerializer" : "ChatSerializer");
packetTypeClass = bukkit.nmsCls("PacketPlayOutChat");
var packetTypeConstructor;
Java.from(packetTypeClass.class.constructors).forEach(function (c) {
if (c.parameterTypes.length === 2) {
packetTypeConstructor = c
}
});
// noinspection JSUnusedAssignment
nmsChatMessageTypeClass = packetTypeConstructor.parameterTypes[1];
if (nmsChatMessageTypeClass.isEnum()) {
chatMessageTypes = nmsChatMessageTypeClass.getEnumConstants();
} else {
/** @namespace nmsChatMessageTypeClass.name */
switch (nmsChatMessageTypeClass.name) {
case "int":
nmsChatMessageTypeClass = java.lang.Integer;
break;
case "byte":
nmsChatMessageTypeClass = java.lang.Byte;
break;
}
}
}
function json(sender, json) {
send(sender, json, 0);
}
function send(sender, json, type) {
var serialized = nmsChatSerializerClass.a(json);
// noinspection all
var typeObj = chatMessageTypes == null ? nmsChatMessageTypeClass.valueOf(String.valueOf(type)) : chatMessageTypes[type];
sendPacket(sender, new packetTypeClass(serialized, typeObj))
}
function sendPacket(player, p) {
player.handle.playerConnection.sendPacket(p);
}
init();
exports = module.exports = {
json: json
};

View File

@ -10,34 +10,37 @@ var plugin = bukkit.plugin.self;
var commandMap = ref.on(bukkit.plugin.manager).get('commandMap').get(); var commandMap = ref.on(bukkit.plugin.manager).get('commandMap').get();
var PluginCommand = Java.type('org.bukkit.command.PluginCommand'); var PluginCommand = Java.type('org.bukkit.command.PluginCommand');
var StringUtil = Java.type('org.bukkit.util.StringUtil');
var ArrayList = Java.type('java.util.ArrayList');
var Arrays = Java.type('java.util.Arrays'); var Arrays = Java.type('java.util.Arrays');
function enable(jsp) { function enable(jsp) {
var commands = jsp.description.commands; var commands = jsp.description.commands;
if (commands) { if (commands) {
var pluginCmds = []; var pluginCommands = [];
for (var name in commands) { for (var name in commands) {
// noinspection JSUnfilteredForInLoop
var command = commands[name]; var command = commands[name];
if (typeof command !== 'object') continue; if (typeof command !== 'object') continue;
// noinspection JSUnfilteredForInLoop
var newCmd = create(jsp, name); var newCmd = create(jsp, name);
if (command.description) newCmd.setDescription(command.description); if (command.description) newCmd.setDescription(command.description);
if (command.usage) newCmd.setUsage(command.usage); if (command.usage) newCmd.setUsage(command.usage);
/** @namespace command.aliases */
if (command.aliases) newCmd.setAliases(Arrays.asList(command.aliases)); if (command.aliases) newCmd.setAliases(Arrays.asList(command.aliases));
if (command.permission) newCmd.setPermission(command.permission); if (command.permission) newCmd.setPermission(command.permission);
if (command['permission-message']) newCmd.setPermissionMessage(command['permission-message']); if (command['permission-message']) newCmd.setPermissionMessage(command['permission-message']);
pluginCmds.push(newCmd); pluginCommands.push(newCmd);
// noinspection JSUnfilteredForInLoop
console.debug('插件 %s 注册命令 %s ...'.format(jsp.description.name, name)); console.debug('插件 %s 注册命令 %s ...'.format(jsp.description.name, name));
} }
commandMap.registerAll(jsp.description.name, Arrays.asList(pluginCmds)); commandMap.registerAll(jsp.description.name, Arrays.asList(pluginCommands));
} }
} }
// noinspection JSUnusedLocalSymbols
function disable(jsp) { function disable(jsp) {
var commands = jsp.description.commands; var commands = jsp.description.commands;
if (commands) { if (commands) {
// noinspection JSUnusedLocalSymbols
for (var name in commands) { for (var name in commands) {
//TODO 删除插件命令 //TODO 删除插件命令
} }
@ -62,12 +65,14 @@ function on(jsp, name, exec) {
console.debug('插件 %s 设置命令 %s(%s) 执行器 ...'.format(jsp.description.name, name, c)); console.debug('插件 %s 设置命令 %s(%s) 执行器 ...'.format(jsp.description.name, name, c));
if (exec.cmd) { if (exec.cmd) {
// 必须指定需要实现的接口类型 否则MOD服会报错 // 必须指定需要实现的接口类型 否则MOD服会报错
// noinspection JSUnusedGlobalSymbols
c.setExecutor(new org.bukkit.command.CommandExecutor({ c.setExecutor(new org.bukkit.command.CommandExecutor({
onCommand: function (sender, cmd, command, args) { onCommand: function (sender, cmd, command, args) {
try { try {
return exec.cmd(sender, command, args); return exec.cmd(sender, command, args);
} catch (ex) { } catch (ex) {
console.console('§6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6命令时发生异常 §4%s'.format(sender.name, jsp.description.name, command, Java.from(args).join(' '), ex)); console.console('§6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6命令时发生异常 §4%s'
.format(sender.name, jsp.description.name, command, Java.from(args).join(' '), ex));
console.ex(ex); console.ex(ex);
} }
} }
@ -75,15 +80,16 @@ function on(jsp, name, exec) {
} }
if (exec.tab) { if (exec.tab) {
// 必须指定需要实现的接口类型 否则MOD服会报错 // 必须指定需要实现的接口类型 否则MOD服会报错
// noinspection JSUnusedGlobalSymbols
c.setTabCompleter(new org.bukkit.command.TabCompleter({ c.setTabCompleter(new org.bukkit.command.TabCompleter({
onTabComplete: function (sender, cmd, command, args) { onTabComplete: function (sender, cmd, command, args) {
try { try {
var completions = new ArrayList();
var token = args[args.length - 1]; var token = args[args.length - 1];
StringUtil.copyPartialMatches(token, Arrays.asList(exec.tab(sender, command, args)), completions); var complete = exec.tab(sender, command, args) || [];
return completions; return Arrays.asList(complete.copyPartialMatches(token, []));
} catch (ex) { } catch (ex) {
console.console('§6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6补全时发生异常 §4%s'.format(sender.name, jsp.description.name, command, Java.from(args).join(' '), ex)); console.console('§6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6补全时发生异常 §4%s'
.format(sender.name, jsp.description.name, command, Java.from(args).join(' '), ex));
console.ex(ex); console.ex(ex);
} }
} }

View File

@ -15,7 +15,7 @@ var EventExecutor = Java.type("org.bukkit.plugin.EventExecutor");
* @param clz * @param clz
* @returns {*|boolean} * @returns {*|boolean}
*/ */
function isVaildEvent(clz) { function isValidEvent(clz) {
// noinspection JSUnresolvedVariable 继承于 org.bukkit.event.Event // noinspection JSUnresolvedVariable 继承于 org.bukkit.event.Event
return Event.class.isAssignableFrom(clz) && return Event.class.isAssignableFrom(clz) &&
// 访问符为Public // 访问符为Public
@ -44,7 +44,7 @@ function unregister(event, listener) {
exports = module.exports = { exports = module.exports = {
baseEventDir: 'org/bukkit/event', baseEventDir: 'org/bukkit/event',
isVaildEvent: isVaildEvent, isValidEvent: isValidEvent,
register: register, register: register,
unregister: unregister unregister: unregister
}; };

View File

@ -16,15 +16,18 @@ function enable(plugin) {
var permissions = plugin.description.permissions; var permissions = plugin.description.permissions;
if (permissions) { if (permissions) {
for (var name in permissions) { for (var name in permissions) {
// noinspection JSUnfilteredForInLoop
var permission = permissions[name]; var permission = permissions[name];
if (typeof permission !== 'object') continue; if (typeof permission !== 'object') continue;
var desc = permission.description; var desc = permission.description;
var def = permission.default || 'OP'; var def = permission.default || 'OP';
try { try {
// noinspection JSUnfilteredForInLoop
manager.addPermission(new Permission(name, desc, PermissionDefault.getByName(def))); manager.addPermission(new Permission(name, desc, PermissionDefault.getByName(def)));
} catch (ex) { } catch (ex) {
// ignore eg: java.lang.IllegalArgumentException: The permission xxxxxx.default is already defined! // ignore eg: java.lang.IllegalArgumentException: The permission xxxxxx.default is already defined!
} }
// noinspection JSUnfilteredForInLoop
console.debug('插件 %s 注册权限 %s Default %s ...'.format(plugin.description.name, name, def)); console.debug('插件 %s 注册权限 %s Default %s ...'.format(plugin.description.name, name, def));
} }
} }
@ -35,10 +38,12 @@ function disable(plugin) {
if (permissions) { if (permissions) {
for (var name in permissions) { for (var name in permissions) {
try { try {
// noinspection JSUnfilteredForInLoop
manager.removePermission(name); manager.removePermission(name);
} catch (ex) { } catch (ex) {
// ignore eg: java.lang.IllegalArgumentException: The permission xxxxxx.default is already defined! // ignore eg: java.lang.IllegalArgumentException: The permission xxxxxx.default is already defined!
} }
// noinspection JSUnfilteredForInLoop
console.debug('插件 %s 注销权限 %s ...'.format(plugin.description.name, name)); console.debug('插件 %s 注销权限 %s ...'.format(plugin.description.name, name));
} }
} }

View File

@ -6,8 +6,7 @@
/*global Java, base, module, exports, require, __FILE__*/ /*global Java, base, module, exports, require, __FILE__*/
var Bukkit = MServer; var Bukkit = MServer;
var Server = Bukkit.server; var Server = MServer.server;
var PluginManager = Server.pluginManager;
exports.$ = Bukkit; exports.$ = Bukkit;
/** /**
* 获取NMS版本 * 获取NMS版本
@ -19,6 +18,12 @@ exports.nmsVersion = Bukkit.server.class.name.split('.')[3];
exports.nmsCls = function (name) { exports.nmsCls = function (name) {
return Java.type(['net.minecraft.server', exports.nmsVersion, name].join('.')); return Java.type(['net.minecraft.server', exports.nmsVersion, name].join('.'));
}; };
/**
* 获取OBC类
*/
exports.obcCls = function (name) {
return Java.type(['org.bukkit.craftbukkit', exports.nmsVersion, name].join('.'));
};
/** /**
* 获取玩家 * 获取玩家
*/ */
@ -38,15 +43,16 @@ exports.player = function () {
exports.players = function () { exports.players = function () {
switch (arguments.length) { switch (arguments.length) {
case 1: case 1:
return Server.onlinePlayers.forEach(arguments[0]); return Bukkit.onlinePlayers.forEach(arguments[0]);
default: default:
return Server.onlinePlayers; return Bukkit.onlinePlayers;
} }
}; };
/** /**
* 插件管理 * 插件管理
* @type {{manager: *, get: exports.plugin.get, load: exports.plugin.load}} * @type {{manager: *, get: exports.plugin.get, load: exports.plugin.load}}
*/ */
var PluginManager = Bukkit.pluginManager;
exports.plugin = { exports.plugin = {
/** /**
* 插件管理工具 * 插件管理工具
@ -74,6 +80,26 @@ exports.plugin = {
}, },
self: PluginManager.getPlugin('MiaoScript') self: PluginManager.getPlugin('MiaoScript')
}; };
/**
* 服务管理
* @type {{manager: *, get: exports.plugin.get, load: exports.plugin.load}}
*/
var ServicesManager = Bukkit.servicesManager;
exports.service = {
/**
* 服务管理工具
*/
manager: ServicesManager,
/**
* 获得服务实例
* @param name 插件名称
* @returns {*}
*/
get: function (name) {
var reg = ServicesManager.getRegistration(base.getClass(name));
return reg && reg.provider || null;
}
};
/** /**
* 公告 * 公告
* @param message 消息 * @param message 消息
@ -99,14 +125,28 @@ exports.console = function (command) {
/** /**
* 玩家以OP权限执行命令 * 玩家以OP权限执行命令
* @param player * @param player
* @param exper * @param command
*/ */
exports.opcommand = function (player, exper) { exports.opcommand = function (player, command) {
var origin = player.isOp(); var origin = player.isOp();
player.setOp(true); player.setOp(true);
try { try {
exports.command(player, exper); exports.command(player, command);
} finally { } finally {
player.setOp(origin); player.setOp(origin);
} }
}; };
/**
* 关闭引擎时执行的操作
*/
function shutdown () {
try {
Bukkit.getScheduler().cancelTasks(plugin.self);
Bukkit.getServicesManager().unregisterAll(plugin.self);
org.bukkit.event.HandlerList.unregisterAll(plugin.self);
Bukkit.getMessenger().unregisterIncomingPluginChannel(plugin.self);
Bukkit.getMessenger().unregisterOutgoingPluginChannel(plugin.self);
} catch (ex) {
console.console();
}
}

View File

@ -10,14 +10,15 @@ var BukkitRunnable = Java.type("org.bukkit.scheduler.BukkitRunnable");
* 创建任务对象 * 创建任务对象
* @param func 任务 * @param func 任务
*/ */
exports.create = function (func) { function create(func) {
if (toString.call(func) !== "[object Function]") { throw TypeError('第一个参数 Task 必须为 function !'); };
return new BukkitRunnable(func); return new BukkitRunnable(func);
}; };
/** /**
* 运行任务 * 运行任务
* @param func 任务 * @param func 任务
*/ */
exports.run = function (func) { function run(func) {
return exports.create(func).runTask(plugin); return exports.create(func).runTask(plugin);
}; };
/** /**
@ -25,7 +26,7 @@ exports.run = function (func) {
* @param func 任务 * @param func 任务
* @param time 延时时间 * @param time 延时时间
*/ */
exports.later = function (func, time) { function later(func, time) {
return exports.create(func).runTaskLater(plugin, time); return exports.create(func).runTaskLater(plugin, time);
}; };
/** /**
@ -33,19 +34,21 @@ exports.later = function (func, time) {
* @constructor (任务,执行间隔). * @constructor (任务,执行间隔).
* @constructor (任务,首次延时,执行间隔) * @constructor (任务,首次延时,执行间隔)
*/ */
exports.timer = function () { function timer() {
switch (arguments.length) { switch (arguments.length) {
case 2: case 2:
return exports.create(arguments[0]).runTaskTimer(plugin, 0, arguments[1]); return exports.create(arguments[0]).runTaskTimer(plugin, 0, arguments[1]);
case 3: case 3:
return exports.create(arguments[0]).runTaskTimer(plugin, arguments[1], arguments[2]); return exports.create(arguments[0]).runTaskTimer(plugin, arguments[1], arguments[2]);
default:
throw TypeError('参数错误 task.timer(func, [delay], interval)');
} }
}; };
/** /**
* 运行异步任务 * 运行异步任务
* @param func function 任务 * @param func function 任务
*/ */
exports.async = function (func) { function _async(func) {
return exports.create(func).runTaskAsynchronously(plugin); return exports.create(func).runTaskAsynchronously(plugin);
}; };
/** /**
@ -53,7 +56,7 @@ exports.async = function (func) {
* @param func 任务 * @param func 任务
* @param time 延时时间 * @param time 延时时间
*/ */
exports.laterAsync = function (func, time) { function laterAsync(func, time) {
return exports.create(func).runTaskLaterAsynchronously(plugin, time); return exports.create(func).runTaskLaterAsynchronously(plugin, time);
}; };
/** /**
@ -61,11 +64,22 @@ exports.laterAsync = function (func, time) {
* @constructor (任务,执行间隔). * @constructor (任务,执行间隔).
* @constructor (任务,首次延时,执行间隔) * @constructor (任务,首次延时,执行间隔)
*/ */
exports.timerAsync = function () { function timerAsync() {
switch (arguments.length) { switch (arguments.length) {
case 2: case 2:
return exports.create(arguments[0]).runTaskTimerAsynchronously(plugin, 0, arguments[1]); return exports.create(arguments[0]).runTaskTimerAsynchronously(plugin, 0, arguments[1]);
case 3: case 3:
return exports.create(arguments[0]).runTaskTimerAsynchronously(plugin, arguments[1], arguments[2]); return exports.create(arguments[0]).runTaskTimerAsynchronously(plugin, arguments[1], arguments[2]);
default:
throw TypeError('参数错误 task.timerAsync(func, [delay], interval)');
} }
}; };
exports = module.exports = {
run: run,
later: later,
timer: timer,
async: _async,
laterAsync: laterAsync,
timerAsync: timerAsync
}

View File

@ -0,0 +1,82 @@
interface Class {
name;
class;
static;
methods;
simpleName;
constructors;
parameterTypes;
}
interface Task {
submit(plugin);
}
interface Registration {
provider;
}
interface PluginManager {
isEnabled();
}
interface bukkit {
nmsVersion: string;
}
interface Server {
server;
service;
consoleSender;
onlinePlayers;
pluginManager;
serviceManager;
servicesManager;
onlinePlayers;
}
interface Player {
handle: NMSPlayer;
getName();
openInventory();
}
interface Inventory {
setItem(index: number, item: Item);
}
interface PlayerEvent {
targetEntity;
}
interface ItemEvent {
entity: Item;
}
interface InventoryClickEvent {
inventory;
whoClicked;
rawSlot;
}
interface NMSPlayer {
playerConnection;
}
interface File {
canonicalPath;
isDirectory();
}
interface Item {
itemStack: ItemStack;
}
interface ItemStack {
typeId;
itemMeta;
amount;
}

View File

@ -0,0 +1,9 @@
/*global Java, base, module, exports, require*/
var TextSerializers = Java.type('org.spongepowered.api.text.serializer.TextSerializers');
function json(sender, json) {
sender.sendMessage(TextSerializers.JSON.deserialize(json));
}
exports = module.exports = {
json: json
};

View File

@ -8,9 +8,6 @@ var Sponge = MServer;
var server = require('./server'); var server = require('./server');
var plugin = server.plugin.self; var plugin = server.plugin.self;
var CommandManager = server.CommandManager;
var CommandSpec = Java.type('org.spongepowered.api.command.spec.CommandSpec');
var CommandCallable = Java.type('org.spongepowered.api.command.CommandCallable'); var CommandCallable = Java.type('org.spongepowered.api.command.CommandCallable');
var CommandResult = Java.type('org.spongepowered.api.command.CommandResult'); var CommandResult = Java.type('org.spongepowered.api.command.CommandResult');
@ -21,21 +18,24 @@ var Optional = Java.type('java.util.Optional');
var ArrayList = Java.type('java.util.ArrayList'); var ArrayList = Java.type('java.util.ArrayList');
var Arrays = Java.type('java.util.Arrays'); var Arrays = Java.type('java.util.Arrays');
var commandMap=[]; var commandMap = [];
var SimpleCommandCallable = function (name) { var SimpleCommandCallable = function (command) {
var that = this; var that = this;
this.name = name; this.name = command.name;
this.cmd = noop; this.cmd = noop;
this.tab = function() { return new ArrayList(); }; this.tab = function () {
return new ArrayList();
};
// noinspection JSUnusedGlobalSymbols,JSUnusedLocalSymbols
this.callable = new CommandCallable({ this.callable = new CommandCallable({
//CommandResult process(CommandSource source, String arguments) throws CommandException; //CommandResult process(CommandSource source, String arguments) throws CommandException;
process: function (src, args) { process: function (src, args) {
return that.cmd(src, name, args.split(" ")) ? CommandResult.success() : CommandResult.empty(); return that.cmd(src, that.name, args.length === 0 ? [] : args.split(" ").filter(function (e) { return e; })) ? CommandResult.success() : CommandResult.empty();
}, },
//List<String> getSuggestions(CommandSource source, String arguments, @Nullable Location<World> targetPosition) throws CommandException; //List<String> getSuggestions(CommandSource source, String arguments, @Nullable Location<World> targetPosition) throws CommandException;
getSuggestions: function (src, args, target) { getSuggestions: function (src, args, target) {
return that.tab(src, name, args.split(" ")); return that.tab(src, that.name, args.length === 0 ? [] : args.split(" ").filter(function (e) { return e; }));
}, },
//boolean testPermission(CommandSource source); //boolean testPermission(CommandSource source);
testPermission: function () { testPermission: function () {
@ -43,7 +43,7 @@ var SimpleCommandCallable = function (name) {
}, },
//Optional<Text> getShortDescription(CommandSource source); //Optional<Text> getShortDescription(CommandSource source);
getShortDescription: function () { getShortDescription: function () {
return Optional.of(Text.of("")); return Optional.of(Text.of(command.description || '暂无描述!'));
}, },
//Optional<Text> getHelp(CommandSource source); //Optional<Text> getHelp(CommandSource source);
getHelp: function () { getHelp: function () {
@ -60,71 +60,69 @@ var SimpleCommandCallable = function (name) {
this.setTabCompleter = function (exec) { this.setTabCompleter = function (exec) {
that.tab = exec; that.tab = exec;
} }
} };
function enable(jsp) { function enable(jsp) {
var pname = jsp.description.name; // noinspection JSUnusedLocalSymbols
var plugin = jsp.description.name;
var commands = jsp.description.commands; var commands = jsp.description.commands;
if (commands) { if (commands) {
var pluginCmds = []; // noinspection JSUnusedLocalSymbols
var pluginCommands = [];
for (var name in commands) { for (var name in commands) {
var command = commands[name]; var command = commands[name];
if (typeof command !== 'object') continue; if (typeof command !== 'object') continue;
create(jsp, name) command.name = name;
create(jsp, command);
console.debug('插件 %s 注册命令 %s ...'.format(jsp.description.name, name)); console.debug('插件 %s 注册命令 %s ...'.format(jsp.description.name, name));
} }
} }
} }
// noinspection JSUnusedLocalSymbols
function get(name) { function get(name) {
} }
function create(jsp, name) { function create(jsp, command) {
var commandKey = jsp.description.name.toLowerCase() + ":" + name; var commandKey = jsp.description.name.toLowerCase() + ":" + command.name;
if(!commandMap[commandKey]){ if (!commandMap[commandKey]) {
commandMap[commandKey] = new SimpleCommandCallable(); commandMap[commandKey] = new SimpleCommandCallable(command);
commandMap[commandKey].name = name; Sponge.getCommandManager().register(plugin, commandMap[commandKey].callable, command.name, commandKey);
Sponge.getCommandManager().register(plugin, commandMap[commandKey].callable, name, commandKey);
} }
return commandMap[commandKey]; return commandMap[commandKey];
} }
function on(jsp, name, exec) { function on(jsp, name, exec) {
var c = create(jsp, name); var c = create(jsp, {name: name});
console.debug('插件 %s 设置命令 %s 执行器 ...'.format(jsp.description.name, name)); console.debug('插件 %s 设置命令 %s 执行器 ...'.format(jsp.description.name, name));
if (exec.cmd) { if (exec.cmd) {
c.setExecutor(function (sender, command, args) { c.setExecutor(function execCmd(sender, command, args) {
try { try {
return exec.cmd(sender, command, args); return exec.cmd(sender, command, args);
} catch (ex) { } catch (ex) {
console.log(args) console.console('§6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6命令时发生异常'
console.console('§6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6命令时发生异常 §4%s'.format(sender.name, jsp.description.name, command, args, ex)); .format(sender.name, jsp.description.name, command, args.join(' ')));
console.ex(ex); console.ex(ex);
} }
}); });
} }
if (exec.tab) { if (exec.tab) {
c.setTabCompleter(function (sender, command, args) { c.setTabCompleter(function execTab(sender, command, args) {
try { try {
var token = args[args.length - 1]; var token = args[args.length - 1];
return Arrays.asList(exec.tab(sender, command, args)); var complete = exec.tab(sender, command, args) || [];
return Arrays.asList(complete.copyPartialMatches(token, []));
} catch (ex) { } catch (ex) {
console.console('§6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6补全时发生异常 §4%s'.format(sender.name, jsp.description.name, command, args, ex)); console.console('§6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6补全时发生异常'
.format(sender.name, jsp.description.name, command, args.join(' ')));
console.ex(ex); console.ex(ex);
} }
}); });
} }
} }
var exist = Sponge.getCommandManager().getOwnedBy(plugin);
exist.forEach(function(commandMapping) {
if (!commandMapping.getAllAliases().contains("ms")) {
Sponge.getCommandManager().removeMapping(commandMapping);
}
});
exports = module.exports = { exports = module.exports = {
enable: enable, enable: enable,
on: on, on: on,
off: noop off: noop
} };

View File

@ -14,6 +14,7 @@
this.console = function () { this.console = function () {
this.sender(MServer.server.console, Array.prototype.join.call(arguments, ' ')); this.sender(MServer.server.console, Array.prototype.join.call(arguments, ' '));
}; };
// noinspection JSUnusedGlobalSymbols
this.warn = function () { this.warn = function () {
log.warn(this.name + Array.prototype.join.call(arguments, ' ')); log.warn(this.name + Array.prototype.join.call(arguments, ' '));
}; };

View File

@ -15,14 +15,14 @@ var priorityMap = {
'HIGH': 'LATE', 'HIGH': 'LATE',
'HIGHEST': 'LAST', 'HIGHEST': 'LAST',
'MONITOR': 'POST' 'MONITOR': 'POST'
} };
/** /**
* 判断是否为一个有效的事件类 * 判断是否为一个有效的事件类
* @param clz * @param clz
* @returns {*|boolean} * @returns {*|boolean}
*/ */
function isVaildEvent(clz) { function isValidEvent(clz) {
// noinspection JSUnresolvedVariable 继承于 org.spongepowered.api.event.Event // noinspection JSUnresolvedVariable 继承于 org.spongepowered.api.event.Event
return Event.class.isAssignableFrom(clz) && return Event.class.isAssignableFrom(clz) &&
// 访问符为Public // 访问符为Public
@ -32,7 +32,7 @@ function isVaildEvent(clz) {
} }
function class2Name(clazz) { function class2Name(clazz) {
return clazz.name.substring(clazz.name.lastIndexOf(".") + 1).replace(/\$/g, '.').toLowerCase(); return clazz.canonicalName.substring(clazz.name.lastIndexOf(".") + 1);
} }
function register(eventCls, exec, priority, ignoreCancel) { function register(eventCls, exec, priority, ignoreCancel) {
@ -46,9 +46,11 @@ function register(eventCls, exec, priority, ignoreCancel) {
function unregister(event, listener) { function unregister(event, listener) {
MServer.getEventManager().unregisterListeners(listener); MServer.getEventManager().unregisterListeners(listener);
} }
// noinspection JSUnusedGlobalSymbols
exports = module.exports = { exports = module.exports = {
baseEventDir: 'org/spongepowered/api/event', baseEventDir: 'org/spongepowered/api/event',
isVaildEvent: isVaildEvent, isValidEvent: isValidEvent,
class2Name: class2Name, class2Name: class2Name,
register: register, register: register,
unregister: unregister unregister: unregister

View File

@ -6,14 +6,13 @@
/*global Java, base, module, exports, require, __FILE__*/ /*global Java, base, module, exports, require, __FILE__*/
var Sponge = MServer; var Sponge = MServer;
var Server = Sponge.server; var Server = MServer.server;
var PluginManager = Sponge.pluginManager;
exports.$ = Sponge;
/** /**
* 插件管理 * 插件管理
* @type {{manager: *, get: exports.plugin.get, load: exports.plugin.load}} * @type {{manager: *, get: exports.plugin.get, load: exports.plugin.load}}
*/ */
exports.plugin = { var PluginManager = Sponge.pluginManager;
var plugin = {
/** /**
* 插件管理工具 * 插件管理工具
*/ */
@ -24,7 +23,7 @@ exports.plugin = {
* @returns {*} * @returns {*}
*/ */
get: function (name) { get: function (name) {
return PluginManager.getPlugin(name); return PluginManager.getPlugin(name).orElse(undefined);
}, },
/** /**
* 载入插件 并且返回结果 * 载入插件 并且返回结果
@ -32,35 +31,73 @@ exports.plugin = {
* @returns {*} * @returns {*}
*/ */
load: function (name) { load: function (name) {
var plugin = this.get(name); return PluginManager.isLoaded(name);
if (ext.notNull(plugin) && !plugin.isEnabled()) {
PluginManager.enablePlugin(plugin);
}
return PluginManager.isPluginEnabled(name);
}, },
self: PluginManager.getPlugin('miaoscript').get() self: PluginManager.getPlugin('miaoscript').orElse(undefined)
};
/**
* 服务管理
* @type {{manager: *, get: exports.plugin.get, load: exports.plugin.load}}
*/
var ServicesManager = Sponge.serviceManager;
var service = {
/*
* 服务管理工具
*/
manager: ServicesManager,
/**
* 获得服务实例
* @param name 插件名称
* @returns {*}
*/
get: function (name) {
return ServicesManager.provide(base.getClass(name)).orElse(null);
}
}; };
/** /**
* 获取玩家 * 获取玩家
*/ */
exports.player = function () { function player() {
switch (arguments.length) { switch (arguments.length) {
case 0: case 0:
return undefined; return undefined;
case 1: case 1:
return Server.getPlayer(arguments[0]).get(); return Server.getPlayer(arguments[0]).orElse(undefined);
default: default:
return Server.getPlayer(arguments[0]).get(); return Server.getPlayer(arguments[0]).orElse(undefined);
} }
}; };
/** /**
* 获取在线玩家 * 获取在线玩家
*/ */
exports.players = function () { function players() {
switch (arguments.length) { switch (arguments.length) {
case 1: case 1:
// 此处的forEach是Collection接口的
return Server.onlinePlayers.forEach(arguments[0]); return Server.onlinePlayers.forEach(arguments[0]);
default: default:
return Server.onlinePlayers; // 此处会转换为JS原生的Array
return Java.from(Server.onlinePlayers.toArray());
} }
}; };
/**
* 关闭引擎时执行的操作
*/
function shutdown() {
Sponge.eventManager.unregisterPluginListeners(plugin.self);
Sponge.scheduler.getScheduledTasks(plugin.self).forEach(function (task) {
task.cancel();
});
Sponge.commandManager.getOwnedBy(plugin.self).forEach(function (commandMapping) {
Sponge.commandManager.removeMapping(commandMapping);
});
}
exports = module.exports = {
$: Sponge,
plugin: plugin,
service: service,
player: player,
players: players,
shutdown: shutdown
}

View File

@ -5,14 +5,15 @@
* Created by 蒋天蓓 on 2017/2/9 0009. * Created by 蒋天蓓 on 2017/2/9 0009.
*/ */
var plugin = require('./server').plugin.self; var plugin = require('./server').plugin.self;
var Comsumer = Java.type('java.util.function.Consumer'); var Consumer = Java.type('java.util.function.Consumer');
var Task = Java.type("org.spongepowered.api.scheduler.Task"); var Task = Java.type("org.spongepowered.api.scheduler.Task");
/** /**
* 创建任务对象 * 创建任务对象
* @param func 任务 * @param func 任务
*/ */
exports.create = function (func) { function create(func) {
return Task.builder().execute(new Comsumer(function () { if (toString.call(func) !== "[object Function]") { throw TypeError('第一个参数 Task 必须为 function !'); };
return Task.builder().execute(new Consumer(function () {
try { try {
func(); func();
} catch (ex) { } catch (ex) {
@ -24,55 +25,68 @@ exports.create = function (func) {
* 运行任务 * 运行任务
* @param func 任务 * @param func 任务
*/ */
exports.run = function (func) { function run(func) {
return exports.create(func).submit(plugin); return create(func).submit(plugin);
}; };
/** /**
* 延时运行任务 * 延时运行任务
* @param func 任务 * @param func 任务
* @param time 延时时间 * @param time 延时时间
*/ */
exports.later = function (func, time) { function later(func, time) {
return exports.create(func).delayTicks(time).submit(plugin); return create(func).delayTicks(time).submit(plugin);
}; };
/** /**
* 运行循环任务 * 运行循环任务
* @constructor (任务,执行间隔). * @constructor (任务,执行间隔).
* @constructor (任务,首次延时,执行间隔) * @constructor (任务,首次延时,执行间隔)
*/ */
exports.timer = function () { function timer() {
switch (arguments.length) { switch (arguments.length) {
case 2: case 2:
return exports.create(arguments[0]).intervalTicks(arguments[1]).submit(plugin); return create(arguments[0]).intervalTicks(arguments[1]).submit(plugin);
case 3: case 3:
return exports.create(arguments[0]).delayTicks(arguments[1]).intervalTicks(arguments[2]).submit(plugin); return create(arguments[0]).delayTicks(arguments[1]).intervalTicks(arguments[2]).submit(plugin);
default:
throw TypeError('参数错误 task.timer(func, [delay], interval)');
} }
}; };
/** /**
* 运行异步任务 * 运行异步任务
* @param func function 任务 * @param func function 任务
*/ */
exports.async = function (func) { function _async(func) {
return exports.create(func).async().submit(plugin); return create(func).async().submit(plugin);
}; };
/** /**
* 延时运行异步任务 * 延时运行异步任务
* @param func 任务 * @param func 任务
* @param time 延时时间 * @param time 延时时间
*/ */
exports.laterAsync = function (func, time) { function laterAsync(func, time) {
return exports.create(func).async().delayTicks(time).submit(plugin); return create(func).async().delayTicks(time).submit(plugin);
}; };
/** /**
* 运行异步循环任务 * 运行异步循环任务
* @constructor (任务,执行间隔). * @constructor (任务,执行间隔).
* @constructor (任务,首次延时,执行间隔) * @constructor (任务,首次延时,执行间隔)
*/ */
exports.timerAsync = function () { function timerAsync() {
switch (arguments.length) { switch (arguments.length) {
case 2: case 2:
return exports.create(arguments[0]).async().intervalTicks(arguments[1]).submit(plugin); return create(arguments[0]).async().intervalTicks(arguments[1]).submit(plugin);
case 3: case 3:
return exports.create(arguments[0]).async().delayTicks(arguments[1]).intervalTicks(arguments[2]).submit(plugin); return create(arguments[0]).async().delayTicks(arguments[1]).intervalTicks(arguments[2]).submit(plugin);
default:
throw TypeError('参数错误 task.timerAsync(func, [delay], interval)');
} }
}; };
exports = module.exports = {
run: run,
later: later,
timer: timer,
async: _async,
laterAsync: laterAsync,
timerAsync: timerAsync
}

View File

@ -22,8 +22,8 @@
} }
} }
// constants // constants
var b64chars // noinspection SpellCheckingInspection
= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; var b64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
var b64tab = function (bin) { var b64tab = function (bin) {
var t = {}; var t = {};
for (var i = 0, l = bin.length; i < l; i++) t[bin.charAt(i)] = i; for (var i = 0, l = bin.length; i < l; i++) t[bin.charAt(i)] = i;
@ -39,7 +39,7 @@
+ fromCharCode(0x80 | (cc & 0x3f))) + fromCharCode(0x80 | (cc & 0x3f)))
: (fromCharCode(0xe0 | ((cc >>> 12) & 0x0f)) : (fromCharCode(0xe0 | ((cc >>> 12) & 0x0f))
+ fromCharCode(0x80 | ((cc >>> 6) & 0x3f)) + fromCharCode(0x80 | ((cc >>> 6) & 0x3f))
+ fromCharCode(0x80 | ( cc & 0x3f))); + fromCharCode(0x80 | (cc & 0x3f)));
} else { } else {
var ccc = 0x10000 var ccc = 0x10000
+ (c.charCodeAt(0) - 0xD800) * 0x400 + (c.charCodeAt(0) - 0xD800) * 0x400
@ -47,7 +47,7 @@
return (fromCharCode(0xf0 | ((ccc >>> 18) & 0x07)) return (fromCharCode(0xf0 | ((ccc >>> 18) & 0x07))
+ fromCharCode(0x80 | ((ccc >>> 12) & 0x3f)) + fromCharCode(0x80 | ((ccc >>> 12) & 0x3f))
+ fromCharCode(0x80 | ((ccc >>> 6) & 0x3f)) + fromCharCode(0x80 | ((ccc >>> 6) & 0x3f))
+ fromCharCode(0x80 | ( ccc & 0x3f))); + fromCharCode(0x80 | (ccc & 0x3f)));
} }
}; };
var re_utob = /[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g; var re_utob = /[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g;
@ -173,6 +173,7 @@
return Base64; return Base64;
}; };
// export Base64 // export Base64
// noinspection JSUnusedGlobalSymbols
global.Base64 = { global.Base64 = {
VERSION: version, VERSION: version,
atob: atob, atob: atob,

View File

@ -9,29 +9,32 @@
var URL = Java.type("java.net.URL"); var URL = Java.type("java.net.URL");
var Files = Java.type("java.nio.file.Files"); var Files = Java.type("java.nio.file.Files");
var Paths = Java.type("java.nio.file.Paths"); var Paths = Java.type("java.nio.file.Paths");
var String = Java.type("java.lang.String"); var Str = Java.type("java.lang.String");
var HttpURLConnection = Java.type("java.net.HttpURLConnection");
var HttpsURLConnection = Java.type("javax.net.ssl.HttpsURLConnection"); var HttpsURLConnection = Java.type("javax.net.ssl.HttpsURLConnection");
var SSLContext = Java.type("javax.net.ssl.SSLContext"); var SSLContext = Java.type("javax.net.ssl.SSLContext");
var HostnameVerifier = Java.type("javax.net.ssl.HostnameVerifier"); var HostnameVerifier = Java.type("javax.net.ssl.HostnameVerifier");
var X509TrustManager = Java.type("javax.net.ssl.X509TrustManager"); var X509TrustManager = Java.type("javax.net.ssl.X509TrustManager");
// noinspection JSUnusedGlobalSymbols,JSUnusedLocalSymbols
var TrustAnyHostnameVerifier = new HostnameVerifier({ var TrustAnyHostnameVerifier = new HostnameVerifier({
verify: function (hostname, session) { verify: function (hostname, session) {
return true; return true;
} }
}) });
var SSLSocketFactory = function initSSLSocketFactory() { var SSLSocketFactory = function initSSLSocketFactory() {
var sslContext = SSLContext.getInstance("TLS"); var sslContext = SSLContext.getInstance("TLS");
// noinspection JSUnusedGlobalSymbols
sslContext.init(null, [new X509TrustManager({ sslContext.init(null, [new X509TrustManager({
getAcceptedIssuers: function () { getAcceptedIssuers: function () {
return null; return null;
}, },
checkClientTrusted: function (chain, authType) {}, checkClientTrusted: function (chain, authType) {
checkServerTrusted: function (chain, authType) {} },
checkServerTrusted: function (chain, authType) {
}
})], new java.security.SecureRandom()); })], new java.security.SecureRandom());
return sslContext.getSocketFactory(); return sslContext.getSocketFactory();
}(); }();
@ -39,8 +42,9 @@ var SSLSocketFactory = function initSSLSocketFactory() {
var config = { var config = {
Charset: 'UTF-8', Charset: 'UTF-8',
ConnectTimeout: 10000, ConnectTimeout: 10000,
ReadTimeout: 10000 ReadTimeout: 10000,
} Debug: false
};
function open(url, method, header) { function open(url, method, header) {
// conn.setRequestProperty // conn.setRequestProperty
@ -54,8 +58,11 @@ function open(url, method, header) {
conn.setDoInput(true); conn.setDoInput(true);
conn.setConnectTimeout(config.ConnectTimeout); conn.setConnectTimeout(config.ConnectTimeout);
conn.setReadTimeout(config.ReadTimeout); conn.setReadTimeout(config.ReadTimeout);
for (var key in header) { if (header) {
conn.setRequestProperty(key, header[key]); for (var key in header) {
// noinspection JSUnfilteredForInLoop
conn.setRequestProperty(key, header[key]);
}
} }
return conn; return conn;
} }
@ -63,27 +70,32 @@ function open(url, method, header) {
function buildUrl(url, params) { function buildUrl(url, params) {
if (params && Object.keys(params).length > 0) { if (params && Object.keys(params).length > 0) {
var queryStart = url.indexOf('?'); var queryStart = url.indexOf('?');
if (queryStart == -1) { if (queryStart === -1) {
url += '?'; url += '?';
} }
for (var key in params) { return url += object2URLSearchParams(params);
url += key;
url += '=';
url += params[key];
url += '&';
}
return url.substr(0, url.length - 1);
} }
return url; return url;
} }
function request(url, method, header, params, body) { function request(config) {
var conn = open(buildUrl(url, params), method, header); var conn = open(buildUrl(config.url, config.query), config.method, config.header);
try { try {
conn.connect(); conn.connect();
if (body) { var data = config.data;
if (data) {
var out = conn.getOutputStream(); var out = conn.getOutputStream();
out.write(new String(body).getBytes(config.Charset)); if (typeof data === "object") {
var type = config.header['Content-Type'];
switch (type) {
case "application/x-www-form-urlencoded":
data = object2URLSearchParams(data);
break;
default:
data = JSON.stringify(data)
}
}
out.write(new Str(data).getBytes(config.Charset));
out.flush(); out.flush();
out.close(); out.close();
} }
@ -93,23 +105,46 @@ function request(url, method, header, params, body) {
} }
} }
function response (conn) { function response(conn) {
var temp = Paths.get(java.lang.System.getProperty("java.io.tmpdir"), java.util.UUID.randomUUID().toString()); var temp = Paths.get(java.lang.System.getProperty("java.io.tmpdir"), java.util.UUID.randomUUID().toString());
Files.copy(conn.getInputStream(), temp); Files.copy(conn.getInputStream(), temp);
var result = new String(Files.readAllBytes(temp), config.Charset); var result = new Str(Files.readAllBytes(temp), config.Charset);
var tempFile = temp.toFile(); var tempFile = temp.toFile();
tempFile.delete() || tempFile.deleteOnExit(); tempFile.delete() || tempFile.deleteOnExit();
return result; return result;
} }
function object2URLSearchParams(params) {
var temp = [];
for (var key in params) {
temp.push('%s=%s'.format(encodeURIComponent(key), encodeURIComponent(params[key])))
}
return temp.join('&')
}
var http = { var http = {
config: config config: config,
request: request
}; };
['GET', 'POST', 'PUT', 'DELETE', 'HEADER'].forEach(function(method){ ['GET', 'DELETE', 'HEAD', 'OPTIONS'].forEach(function (method) {
http[method.toLowerCase()] = function (url, header, params, body) { http[method.toLowerCase()] = function __likeGet__(url, data, config) {
return request(url, method, header, params, body); return this.request(Object.assign(config || {}, {
url: url,
method: method,
query: data
}));
} }
}) });
['POST', 'PUT', 'PATCH'].forEach(function (method) {
http[method.toLowerCase()] = function __likePost__(url, data, config) {
return this.request(Object.assign(config || {}, {
url: url,
method: method,
data: data
}));
}
});
exports = module.exports = http; exports = module.exports = http;

View File

@ -0,0 +1,3 @@
interface requestConfig {
header;
}

View File

@ -0,0 +1,54 @@
'use strict';
/**
* PAPI扩展类
*/
/*global Java, base, module, exports, require, __FILE__*/
var PlaceholderAPI;
var server = require('api/server');
PlaceholderAPI = {
setPlaceholders: function () {
return arguments[1].replace(/&([1-9a-fA-F])/, '§$1');
}
};
// 尝试加载 Bukkit 的 PlaceholderAPI
try {
PlaceholderAPI = ext.getStatic("me.clip.placeholderapi.PlaceholderAPI");
console.log('[PAPI] Found Bukkit PlaceholderAPI Hooking...')
} catch (ex) {
}
// 尝试加载 Sponge 的 PlaceholderAPI
try {
/** @namespace server.service */
var spongePapi = server.service.get('me.rojo8399.placeholderapi.PlaceholderService');
var TextSerializers = Java.type('org.spongepowered.api.text.serializer.TextSerializers');
var s = TextSerializers.formattingCode('§');
if (spongePapi) {
PlaceholderAPI = {
setPlaceholders: function () {
return s.serialize(spongePapi.replacePlaceholders(arguments[1], arguments[0], arguments[0]));
}
};
console.log('[PAPI] Found Sponge PlaceholderAPI Hooking...')
}
} catch (ex) {
}
function replace() {
var player = arguments[0];
var line = [];
if (arguments.length === 1) {
player = null;
line = player;
}
if (toString.call(line) === "[object Array]") {
return PlaceholderAPI.setPlaceholders(player, line.join('\n')).split('\n');
}
return PlaceholderAPI.setPlaceholders(player, line);
}
exports = module.exports = {
$: replace
};

View File

@ -44,6 +44,7 @@ function Reflect(obj) {
return arguments.length === 1 ? this.field(arguments[0]) : this.obj; return arguments.length === 1 ? this.field(arguments[0]) : this.obj;
}; };
// noinspection JSUnusedGlobalSymbols
this.set = function (name, value) { this.set = function (name, value) {
accessible(declaredField(this.class, name)).set(this.obj, value); accessible(declaredField(this.class, name)).set(this.obj, value);
return this; return this;
@ -113,27 +114,15 @@ function declaredField(clazz, name) {
} }
function declaredMethod(clazz, name, clazzs) { function declaredMethod(clazz, name, clazzs) {
var mkey = clazz.name + '.' + name + ':' + (clazzs || []).join(':'); var key = clazz.name + '.' + name + ':' + (clazzs || []).join(':');
if (!methodCache[mkey]) { if (!methodCache[key]) {
try { try {
methodCache[mkey] = clazz.getMethod(name, clazzs); methodCache[key] = clazz.getMethod(name, clazzs);
} catch (ex) { } catch (ex) {
methodCache[mkey] = clazz.getDeclaredMethod(name, clazzs); methodCache[key] = clazz.getDeclaredMethod(name, clazzs);
} }
} }
return methodCache[mkey]; return methodCache[key];
}
function declaredMethod(clazz, name, clazzs) {
var mkey = clazz.name + '.' + name + ':' + (clazzs || []).join(':');
if (!methodCache[mkey]) {
try {
methodCache[mkey] = clazz.getMethod(name, clazzs);
} catch (ex) {
methodCache[mkey] = clazz.getDeclaredMethod(name, clazzs);
}
}
return methodCache[mkey];
} }
function declaredMethods(clazz) { function declaredMethods(clazz) {
@ -143,18 +132,22 @@ function declaredMethods(clazz) {
var classMethodsCache = []; var classMethodsCache = [];
function mapToObject(javaObj) { function mapToObject(javaObj) {
if (!javaObj || !javaObj.class) { throw new TypeError('参数 %s 不是一个Java对象!'.format(javaObj)) } if (!javaObj || !javaObj.class) {
throw new TypeError('参数 %s 不是一个Java对象!'.format(javaObj))
}
var target = {}; var target = {};
getJavaObjectMethods(javaObj).forEach(function proxyMethod(t){ mapMethod(target, javaObj, t) }) getJavaObjectMethods(javaObj).forEach(function proxyMethod(t) {
mapMethod(target, javaObj, t)
});
return target; return target;
} }
function getJavaObjectMethods(javaObj) { function getJavaObjectMethods(javaObj) {
var className = javaObj.class.name var className = javaObj.class.name;
if (!classMethodsCache[className]) { if (!classMethodsCache[className]) {
var names = []; var names = [];
var methods = javaObj.class.methods; var methods = javaObj.class.methods;
for (var i in methods){ for (var i in methods) {
names.push(methods[i].name); names.push(methods[i].name);
} }
classMethodsCache[className] = names; classMethodsCache[className] = names;
@ -162,7 +155,7 @@ function getJavaObjectMethods(javaObj) {
return classMethodsCache[className]; return classMethodsCache[className];
} }
function mapMethod (target, source, name) { function mapMethod(target, source, name) {
target[name] = function __SimpleDynamicMethod__() { target[name] = function __SimpleDynamicMethod__() {
if (arguments.length > 0) { if (arguments.length > 0) {
return source[name](Array.prototype.slice.call(arguments)); return source[name](Array.prototype.slice.call(arguments));
@ -173,13 +166,16 @@ function mapMethod (target, source, name) {
} }
function on(obj) { function on(obj) {
if (!obj || !obj.class) { throw new TypeError('参数 %s 不是一个Java对象!'.format(obj)) } if (!obj || !obj.class) {
throw new TypeError('参数 %s 不是一个Java对象!'.format(obj))
}
return new Reflect(obj); return new Reflect(obj);
} }
// noinspection JSUnusedGlobalSymbols
exports = module.exports = { exports = module.exports = {
on: on, on: on,
accessible: accessible, accessible: accessible,
declaredMethods: declaredMethods, declaredMethods: declaredMethods,
mapToObject: mapToObject mapToObject: mapToObject
} };

View File

@ -0,0 +1,131 @@
/*global Java, base, module, exports, require*/
var chat = require('api/chat');
var server = require('api/server');
var ChatMessagePart = function () {
this.click = function (action, value) {
this.clickEventAction = action;
this.clickEventValue = value;
};
this.hover = function (action, value) {
this.hoverEventAction = action;
this.hoverEventValue = value;
};
this.convert = function () {
var str = {};
if (this.text) {
str.text = this.text;
}
if (this.clickEventAction) {
str.clickEvent = {
"action": this.clickEventAction,
"value": this.clickEventValue
}
}
if (this.hoverEventAction) {
str.hoverEvent = {
"action": this.hoverEventAction,
"value": this.hoverEventValue
}
}
if (this.insertion) {
str.insertion = this.insertion;
}
return str;
}
};
var Tellraw = function () {
var parts = [new ChatMessagePart()];
var self = this;
this.then = function (part) {
if (typeof part === "string") {
var newPart = new ChatMessagePart();
newPart.text = part;
this.then(newPart);
return self;
}
var last = this.latest();
if (!last.text) {
last.text = part.text;
} else {
parts.push(part);
}
this.cache = null;
};
this.text = function (text) {
this.latest().text = text;
return this;
};
this.tip = function (str) {
if (toString.call(str) === "[object Array]") {
str = str.join("\n");
}
this.latest().hover("show_text", str);
return this;
};
this.item = function (str) {
this.latest().hover("show_item", str);
return this;
};
this.cmd = this.command = function (command) {
this.latest().click("run_command", command);
return this;
};
this.suggest = function (url) {
this.latest().click("suggest_command", url);
return this;
};
this.file = function (path) {
this.latest().click("open_file", path);
return this;
};
this.link = function (url) {
this.latest().click("open_url", url);
return this;
};
this.latest = function () {
return parts[parts.length - 1];
};
this.json = function () {
if (!this.cache) {
var temp = [];
parts.forEach(function (t) {
temp.push(t.convert());
});
this.cache = JSON.stringify(temp);
console.debug(this.cache);
}
return this.cache;
};
this.send = function (player) {
chat.json(player, self.json());
};
this.sendAll = function () {
server.players(function sendAllMessage(p) {
self.send(p);
})
}
};
Tellraw.create = function () {
return new Tellraw().then(Tellraw.duplicateChar);
};
Tellraw.duplicateChar = '§卐';
exports = module.exports = Tellraw;

View File

@ -0,0 +1,29 @@
function Template(tpl) {
var match;
var code = ['var r=[];'];
var re = /\{\{\s*([a-zA-Z\.\_0-9()]+)\s*\}\}/m;
function addLine(text) {
code.push('r.push(\'' + text.replace(/\'/g, '\\\'').replace(/\n/g, '\\n').replace(/\r/g, '\\r') + '\');');
};
while (match = re.exec(tpl)) {
if (match.index > 0) {
addLine(tpl.slice(0, match.index));
}
code.push('r.push(this.' + match[1] + ');');
tpl = tpl.substring(match.index + match[0].length);
}
addLine(tpl);
code.push('return r.join(\'\');');
// 创建函数:
var fn = new Function(code.join('\n'));
// 用render()调用函数并绑定this参数
this.render = function (model) {
return fn.apply(model);
};
}
exports = module.exports = {
create: function (tpl) {
return new Template(tpl);
}
}

View File

@ -0,0 +1,35 @@
'use strict';
/**
* 常用工具类
* Created by 蒋天蓓 on 2018/5/12 0009.
*/
/*global Java, base, module, exports, require, __FILE__*/
var Arrays = Java.type('java.util.Arrays');
function toStr(obj) {
if (obj.class) {
return Arrays.toString()
}
}
function compare(prop) {
return function (obj1, obj2) {
var val1 = obj1[prop];
var val2 = obj2[prop];
if (!isNaN(Number(val1)) && !isNaN(Number(val2))) {
val1 = Number(val1);
val2 = Number(val2);
}
if (val1 < val2) {
return -1;
} else if (val1 > val2) {
return 1;
} else {
return 0;
}
}
}
exports = module.exports = {
compare: compare
};

View File

@ -16,9 +16,9 @@ function unzip(zipFile, target) {
return; return;
} }
if (target === undefined) { if (target === undefined) {
var fname = zipFile.name; var fileName = zipFile.name;
// noinspection JSUnresolvedVariable // noinspection JSUnresolvedVariable
target = fs.file(zipFile.parentFile.canonicalPath, fname.substring(0, fname.length() - 4)); target = fs.file(zipFile.parentFile.canonicalPath, fileName.substring(0, fileName.length() - 4));
} }
console.debug("解压文件 %s 到目录 %s".format(zipFile.canonicalPath, target)); console.debug("解压文件 %s 到目录 %s".format(zipFile.canonicalPath, target));
var zipObj = new ZipFile(zipFile); var zipObj = new ZipFile(zipFile);

View File

@ -25,6 +25,7 @@ function load() {
} }
function enable() { function enable() {
// noinspection JSUnusedLocalSymbols
command.on(this, 'hello', { command.on(this, 'hello', {
cmd: function (sender, command, args) { cmd: function (sender, command, args) {
engineLoad(fs.file(root, 'test.js')); engineLoad(fs.file(root, 'test.js'));
@ -34,25 +35,24 @@ function enable() {
console.log('启用 Hello World 测试插件!'); console.log('启用 Hello World 测试插件!');
switch (DetectServerType) { switch (DetectServerType) {
case ServerType.Bukkit: case ServerType.Bukkit:
event.on(this, 'playerloginevent', function join(event) { event.on(this, 'PlayerLoginEvent', function join(event) {
send(event, wrapper.player(event.player)); send(event, wrapper.player(event.player));
}); });
break; break;
case ServerType.Sponge: case ServerType.Sponge:
// clientconnectionevent.join event.on(this, 'ClientConnectionEvent.Join', function join(event) {
event.on(this, 'clientconnectionevent.join', function join(event) {
send(event, wrapper.player(event.targetEntity)); send(event, wrapper.player(event.targetEntity));
}); });
break; break;
} }
} }
function send(event, player){ function send(event, player) {
// noinspection JSUnresolvedVariable // noinspection JSUnresolvedVariable
console.debug('玩家', player.getName(), "触发事件", event.class.simpleName); console.debug('玩家', player.getName(), "触发事件", event.class.simpleName);
setTimeout(function () { setTimeout(function () {
// noinspection JSUnresolvedVariable // noinspection JSUnresolvedVariable
player.sendMessage("§a欢迎来到 §bMiaoScript §a的世界! 当前在线: " + server.players.length) player.sendMessage("§a欢迎来到 §bMiaoScript §a的世界! 当前在线: " + server.players().length)
}, 10); }, 10);
} }

View File

@ -1,14 +1,11 @@
'use strict'; 'use strict';
/*global Java, base, module, exports, require*/ /*global Java, base, module, exports, require*/
var event = require('api/event'); var event = require('api/event');
var wrapper = require('api/wrapper'); var task = require('api/task');
var command = require('api/command');
var server = require('api/server');
var http = require('http'); var http = require('http');
var fs = require('fs'); var fs = require('fs');
var nameMap = []; var Keys;
var description = { var description = {
name: 'ItemTag', name: 'ItemTag',
@ -20,10 +17,12 @@ var itemConfig;
function load() { function load() {
var itemFile = self.file('item.yml'); var itemFile = self.file('item.yml');
if (!itemFile.exists()) { task.async(function () {
base.save(itemFile, http.get('https://data.yumc.pw/config/Item_zh_CN.yml')); if (!itemFile.exists()) {
} fs.save(itemFile, http.get('https://data.yumc.pw/config/Item_zh_CN.yml'))
itemConfig = self.getConfig('item.yml'); }
itemConfig = self.getConfig('item.yml')
})
} }
function enable() { function enable() {
@ -31,44 +30,48 @@ function enable() {
case ServerType.Bukkit: case ServerType.Bukkit:
event.on(self, 'ItemMergeEvent', function (event) { event.on(self, 'ItemMergeEvent', function (event) {
bukkit(event.target, event.entity.itemStack.amount + event.target.itemStack.amount); bukkit(event.target, event.entity.itemStack.amount + event.target.itemStack.amount);
}) });
event.on(self, 'ItemSpawnEvent', function (event) { event.on(self, 'ItemSpawnEvent', function (event) {
if (event.entity.itemStack) { if (event.entity.itemStack) {
bukkit(event.entity, event.entity.itemStack.amount); bukkit(event.entity, event.entity.itemStack.amount);
} }
}) });
break; break;
case ServerType.Sponge: case ServerType.Sponge:
event.on(self, 'itemmergeitemevent', function (event) { Keys = Java.type('org.spongepowered.api.data.key.Keys');
event.on(self, 'ItemMergeItemEvent', function (event) {
// Sponge 暂未实现当前事件 // Sponge 暂未实现当前事件
}) });
event.on(self, 'spawnentityevent', function (event) { event.on(self, 'SpawnEntityEvent', function (event) {
event.entities.forEach(function (entity) { event.entities.forEach(function (entity) {
if (entity.type.name === "item") sponge(entity); if (entity.type.name === "item") sponge(entity);
}) })
}) });
break; 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) { function getItemName(name) {
return itemConfig[(name + '').toUpperCase()] || name; return itemConfig[(name + '').toUpperCase()] || name;
} }
function bukkit(item , amount) { function getItemCount(amount) {
var amounts = amount == 1 ? "" : "*" + amount; return amount === 1 ? "" : "*" + amount;
item.setCustomName('§b' + getItemName(item.itemStack.type) + amounts);
item.setCustomNameVisible(true);
}
function sponge(entity) {
var itemOptional = entity.get(Keys.REPRESENTED_ITEM);
if (itemOptional.isPresent()) {
var item = itemOptional.get();
var amounts = item.count == 1 ? "" : "*" + item.count;
entity.offer(org.spongepowered.api.data.key.Keys.DISPLAY_NAME, org.spongepowered.api.text.Text.of('§b' + getItemName(item.type.name.split(':')[1]) + amounts));
entity.offer(org.spongepowered.api.data.key.Keys.CUSTOM_NAME_VISIBLE, true);
}
} }
module.exports = { module.exports = {

View File

@ -0,0 +1,71 @@
'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 server = require('api/server');
var fs = require('fs');
var description = {
name: 'MiaoAuth',
version: '1.0',
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
};

View File

@ -0,0 +1,198 @@
'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 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 Player;
var boards = [];
var description = {
name: 'MiaoBoard',
version: '1.0',
author: '喵呜',
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饥 饿: &d%player_food_level%",
"&6模 式: &4%player_gamemode%"
]
},
"admin": {
"index": 49,
"title": "服务器信息",
"permission": "mb.reload",
"lines": [
"&6名 称: &aMiaoBoard",
"&6版 本: &b" + this.version,
"&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();
server.players(function (player) {
boards[player.name] = new MiaoBoard(player);
})
}
function registerCommand() {
command.on(self, 'mboard', {
cmd: mainCommand
});
}
function mainCommand(sender, command, args) {
boards[sender.name].update('MiaoBoard', ['第一行', '第二行', '第三行']);
}
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 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(format.title, papi.replace(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() {
update_task.cancel();
}
function MiaoBoard(player) {
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) {
sidebar.scores.values().forEach(function removeScore(score) {
sidebar.removeScore(score)
})
var max = lines.length;
var i = 0;
sidebar.setDisplayName(Text.of(title));
lines.forEach(function addScore(line) {
sidebar.getOrCreateScore(Text.of(line)).setScore(max - i++);
})
scoreboard.updateDisplaySlot(sidebar, DisplaySlots.SIDEBAR);
}
this.clear = function () {
player.setScoreboard(Scoreboard.builder().build());
}
}
module.exports = {
description: description,
load: load,
enable: enable,
disable: disable
};

View File

@ -0,0 +1,261 @@
'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: '喵呜',
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]: ",
"item": true,
"itemformat": "&6[&b%s&6]&r"
},
"admin": {
"index": 49,
"permission": "MiaoChat.admin",
"format": "[admin][world][player][help]: ",
"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
};

View File

@ -0,0 +1,194 @@
'use strict';
/*global Java, base, module, exports, require, __dirname, __filename, ScriptEngineContextHolder*/
var task = require('api/task');
var manager = require('api/plugin');
var command = require('api/command');
var fs = require('fs');
var http = require('http');
var template = require('template');
var pluginCache = [];
var packageCache = [];
var packageNameCache = [];
var description = {
name: 'MiaoScriptPackageManager',
version: '1.0',
author: '喵♂呜',
description: 'MiaoScript包管理工具',
commands: {
'mpm': {
description: 'MiaoScriptPackageManager主命令'
}
},
config: {
center: 'https://ms.yumc.pw/api/package/list',
template: 'http://paste.yumc.pw/pxus6ap6l/g7di8z/raw'
}
};
var help = [
'§6========= §6[§a' + description.name + '§6] 帮助 §aBy §b喵♂呜 §6=========',
'§6/mpm §ainstall §e<插件名称> §6- §3安装插件',
'§6/mpm §alist §6- §3列出仓库插件',
'§6/mpm §aupdate §e<插件名称> §6- §3更新插件(无插件名称则更新源)',
'§6/mpm §aupgrade §e<插件名称> §6- §3及时更新插件(update需要重启生效)',
'§6/mpm §areload §e<插件名称> §6- §3重载插件(无插件名称则重载自身)',
'§6/mpm §arun §e<JS代码> §6- §3运行JS代码',
'§6/mpm §acreate §e<插件名称> [作者] [版本] [主命令] §6- §3通过模板创建名称',
'§6/mpm §crestart §6- §4重启MiaoScript脚本引擎'
];
function load() {
task.async(function () {
pluginCache = Object.keys(manager.plugins);
JSON.parse(http.get(self.config.center)).data.forEach(function cachePackageName(pkg) {
packageCache[pkg.name] = pkg;
})
packageNameCache = Object.keys(packageCache);
})
}
function enable() {
command.on(this, 'mpm', {
cmd: function (sender, command, args) {
if (args.length > 0) {
switch (args[0]) {
case "list":
console.sender(sender, '§6当前 §bMiaoScriptPackageCenter §6中存在下列插件:');
for (var pkgName in packageCache) {
var pkg = packageCache[pkgName];
console.sender(sender, '§6插件名称: §b%s §6版本: §a%s'.format(pkg.name, pkg.version))
}
break;
case "install":
if (args.length > 1) {
download(sender, args[1]);
} else {
console.sender(sender, '§c请输入插件名称!')
}
break;
case "update":
if (args.length > 1) {
update(sender, args[1]);
} else {
load();
console.sender(sender, "§a仓库缓存刷新成功 共存在 §b" + pluginCache.length + " §a个插件!")
}
break;
case "upgrade":
break;
case "delete":
if (args.length > 1) {
del(sender, args[1]);
} else {
console.sender(sender, '§c请输入插件名称!')
}
break;
case "reload":
if (args.length > 1) {
var pname = args[1];
if (pluginCache.indexOf(pname) !== -1) {
manager.reload(pname)
} else {
console.sender(sender, '§c插件 %s 不存在!'.format(pname))
}
} else {
self.reloadConfig();
load();
}
break;
case "restart":
try {
ScriptEngineContextHolder.disableEngine();
ScriptEngineContextHolder.enableEngine();
console.sender(sender, '§3MiaoScript Engine §6Reload §aSuccessful...');
} catch (ex) {
console.sender(sender, "§3MiaoScript Engine §6Reload §cError! ERR: " + ex);
console.ex(ex);
}
break;
case "run":
args.shift(1);
console.sender(sender, eval(args.join(' ')));
break;
case "create":
var name = args[1];
if (!name) {
console.sender(sender, '§4参数错误 /mpm create <插件名称> [作者] [版本] [主命令]');
return;
}
var result = template.create(http.get(self.config.template)).render({
name: name,
author: args[2] || 'MiaoWoo',
version: args[3] || '1.0',
command: args[4] || name.toLowerCase(),
});
fs.save(fs.file(__dirname, name + '.js'), result);
console.sender(sender, '§6插件 §a' + name + ' §6已生成到插件目录...');
break;
case "help":
sendHelp(sender);
break;
}
} else {
sendHelp(sender);
}
},
tab: function (sender, command, args) {
if (args.length === 1) return ['list', 'install', 'update', 'upgrade', 'reload', 'restart', 'run', 'help'];
if (args.length > 1) {
switch (args[0]) {
case "install":
return packageNameCache;
case "update":
case "upgrade":
case "reload":
return pluginCache;
}
}
}
})
}
function sendHelp(sender) {
help.forEach(function (msg) {
console.sender(sender, msg);
})
}
function del(sender, name) {
if (pluginCache.indexOf(name) !== -1) {
console.sender(sender, '§c插件 %s 不存在!'.format(name));
return;
}
manager.disable(name);
fs.delete(plugin.__FILE__);
}
function download(sender, name) {
var plugin = packageCache[name];
if (!plugin) {
console.sender(sender, '§c插件§b', name, '§c不存在');
return;
}
var pfile = fs.file(__dirname, name + '.js');
console.sender(sender, '§6开始下载插件: §b%s'.format(plugin.name));
console.sender(sender, '§6插件下载地址: §b%s'.format(plugin.url));
fs.save(pfile, http.get(plugin.url));
console.sender(sender, '§6插件 §b%s §a下载完毕 开始加载 ...'.format(name));
manager.loadPlugin(pfile);
console.sender(sender, '§6插件 §b%s §a安装成功!'.format(name));
}
function disable() {
}
module.exports = {
description: description,
load: load,
enable: enable,
disable: disable
};

View File

@ -121,12 +121,13 @@ function newItemFromConfig(config) {
} }
function enable() { function enable() {
// noinspection JSUnusedLocalSymbols
command.on(this, 'l', { command.on(this, 'l', {
cmd: function (sender, command, args) { cmd: function (sender, command, args) {
if (!sender.openInventory) { if (!sender.openInventory) {
console.sender(sender, "§4当前用户无法使用该命令!"); console.sender(sender, "§4当前用户无法使用该命令!");
} }
var inv = bukkit.$.createInventory(null, 54, config.title); var inv = MServer.createInventory(null, 54, config.title);
inv.setContents(items); inv.setContents(items);
sender.openInventory(inv); sender.openInventory(inv);
return true; return true;
@ -178,14 +179,14 @@ function enable() {
console.sender(player, '§c抽奖物品和钥匙不匹配!'); console.sender(player, '§c抽奖物品和钥匙不匹配!');
return; return;
} }
var resultlist = []; var resultList = [];
litem.result.forEach(function (t) { litem.result.forEach(function (t) {
for (var i = 0; i < t.percent; i++) { for (var i = 0; i < t.percent; i++) {
resultlist.push(t); resultList.push(t);
} }
}); });
var ri = ext.random(resultlist.length); var ri = ext.random(resultList.length);
var result = resultlist[ri]; var result = resultList[ri];
box.amount = box.amount - 1; box.amount = box.amount - 1;
key.amount = key.amount - 1; key.amount = key.amount - 1;
inv.setItem(10, box); inv.setItem(10, box);

View File

@ -46,8 +46,8 @@ function load() {
function enable() { function enable() {
command.on(self, 'mtag', { command.on(self, 'mtag', {
cmd: function cmd(sender, command, args) { cmd: function cmd(sender, command, args) {
var subcommand = args[0]; var subCommand = args[0];
switch (subcommand) { switch (subCommand) {
case 'reload': case 'reload':
self.reloadConfig(); self.reloadConfig();
fakeTag = new FakeTag(config.format); fakeTag = new FakeTag(config.format);

View File

@ -1,24 +0,0 @@
'use strict';
/**
* PAPI扩展类
*/
/*global Java, base, module, exports, require, __FILE__*/
var PlaceholderAPI;
var bukkit = require('api/server');
if (bukkit.plugin.load("PlaceholderAPI")) {
PlaceholderAPI = ext.getStatic("me.clip.placeholderapi.PlaceholderAPI");
} else {
log.w("PlaceholderAPI 未找到 变量替换功能失效!");
PlaceholderAPI = {
setPlaceholders: function () {
return arguments[1];
}
}
}
exports.$ = function () {
if (arguments.length > 1) {
return PlaceholderAPI.setPlaceholders(arguments[0], arguments[1]);
} else {
return PlaceholderAPI.setPlaceholders(null, arguments[0]);
}
};

View File

@ -0,0 +1,32 @@
## 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` 即可安装成功

View File

@ -1,14 +1,7 @@
package pw.yumc.MiaoScript; package pw.yumc.MiaoScript;
import java.io.FileReader;
import javax.script.ScriptEngineManager;
import org.junit.Test; import org.junit.Test;
import pw.yumc.YumCore.bukkit.Log;
import pw.yumc.YumCore.engine.MiaoScriptEngine;
/** /**
* Created with IntelliJ IDEA * Created with IntelliJ IDEA
* *
@ -16,24 +9,7 @@ import pw.yumc.YumCore.engine.MiaoScriptEngine;
* Created on 2017/9/14 10:08. * Created on 2017/9/14 10:08.
*/ */
public class MiaoScriptTest { public class MiaoScriptTest {
private MiaoScriptEngine engine;
@Test @Test
public void testBoot() { public void testBoot() {
Thread currentThread = Thread.currentThread();
ClassLoader previousClassLoader = currentThread.getContextClassLoader();
currentThread.setContextClassLoader(getClass().getClassLoader());
try {
ScriptEngineManager manager = new ScriptEngineManager();
this.engine = new MiaoScriptEngine(manager);
this.engine.put("base", new Base());
this.engine.eval(new FileReader("src/main/resources/bios.js"));
engine.invokeFunction("boot", null, engine);
} catch (Exception e) {
Log.w("脚本引擎初始化失败! %s:%s", e.getClass().getName(), e.getMessage());
e.printStackTrace();
} finally {
currentThread.setContextClassLoader(previousClassLoader);
}
} }
} }