Added config.yml for plugin configuration - issue #102

This commit is contained in:
walterhiggins 2014-01-14 22:54:49 +00:00
parent b2e203dd8c
commit a4999745de
8 changed files with 161 additions and 143 deletions

View file

@ -19,6 +19,9 @@
<available file="${minecraft.dir}" property="minecraft.present"/> <available file="${minecraft.dir}" property="minecraft.present"/>
</target> </target>
<target name="test" depends="package" description="Perform unit tests">
</target>
<target name="server-setup" depends="init" description="Downloads the latest bukkit dev jar" <target name="server-setup" depends="init" description="Downloads the latest bukkit dev jar"
unless="minecraft.present"> unless="minecraft.present">
<mkdir dir="${minecraft.dir}" /> <mkdir dir="${minecraft.dir}" />
@ -119,17 +122,39 @@ Walter Higgins
</concat> </concat>
</target> </target>
<target name="zip_js" depends="init"> <target name="zip_js" depends="zip_lib, zip_modules, zip_plugins">
<delete file="${build}/${js-plugins-dir}.zip"/> </target>
<zip destfile="${build}/${js-plugins-dir}.zip">
<zipfileset dir="./src/main/javascript" /> <target name="zip_lib" depends="init">
<delete file="${build}/lib.zip"/>
<zip destfile="${build}/lib.zip"
basedir="./src/main/javascript"
excludes="modules/**, plugins/**,">
</zip>
</target>
<target name="zip_modules" depends="init">
<delete file="${build}/modules.zip"/>
<zip destfile="${build}/modules.zip"
basedir="./src/main/javascript"
excludes="lib/**, plugins/**,">
</zip>
</target>
<target name="zip_plugins" depends="init">
<delete file="${build}/plugins.zip"/>
<zip destfile="${build}/plugins.zip"
basedir="./src/main/javascript"
excludes="lib/**, modules/**">
</zip> </zip>
</target> </target>
<target name="package" depends="gendocs,zip_js,compile" description="generate the distribution" > <target name="package" depends="gendocs,zip_js,compile" description="generate the distribution" >
<!-- ensure plugin.yml is always copied --> <!-- ensure plugin.yml is always copied -->
<delete file="${build}/plugin.yml" /> <delete file="${build}/plugin.yml" />
<copy file="src/main/resources/plugin.yml" todir="${build}"/> <copy todir="${build}">
<fileset dir="src/main/resources"/>
</copy>
<replace file="${build}/plugin.yml" value="${scriptcraft-version}-${DSTAMP}"> <replace file="${build}/plugin.yml" value="${scriptcraft-version}-${DSTAMP}">
<replacetoken>[[version]]</replacetoken> <replacetoken>[[version]]</replacetoken>
</replace> </replace>

View file

@ -1,20 +1,12 @@
package net.walterhiggins.scriptcraft; package net.walterhiggins.scriptcraft;
import java.io.File; import java.io.InputStreamReader;
import java.io.FileReader;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.script.*; import javax.script.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.Collection;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.command.*; import org.bukkit.command.*;
import org.bukkit.Bukkit;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
public class ScriptCraftPlugin extends JavaPlugin implements Listener public class ScriptCraftPlugin extends JavaPlugin implements Listener
@ -23,114 +15,27 @@ public class ScriptCraftPlugin extends JavaPlugin implements Listener
// need to look at possibly having context/scope per operator // need to look at possibly having context/scope per operator
//protected Map<CommandSender,ScriptCraftEvaluator> playerContexts = new HashMap<CommandSender,ScriptCraftEvaluator>(); //protected Map<CommandSender,ScriptCraftEvaluator> playerContexts = new HashMap<CommandSender,ScriptCraftEvaluator>();
protected ScriptEngine engine = null; protected ScriptEngine engine = null;
private static final String JS_PLUGINS_DIR = "plugins/scriptcraft";
private static final String JS_PLUGINS_ZIP = "scriptcraft.zip";
/**
* Unzips bundled javascript code.
*/
private void unzipJS() throws IOException
{
//
// does the js-plugins directory exist?
//
File jsPlugins = new File(JS_PLUGINS_DIR);
if (!jsPlugins.exists())
{
getLogger().info("Directory " + jsPlugins.getCanonicalPath() + " does not exist.");
getLogger().info("Initializing " + jsPlugins.getCanonicalPath() + " directory with contents from plugin archive.");
try{
jsPlugins.mkdirs();
}catch(Exception e){
throw new RuntimeException("Failed to create directory " + jsPlugins.getCanonicalPath() + ":" + e.getMessage());
}
}
ZipInputStream zis = new ZipInputStream(getResource(JS_PLUGINS_ZIP));
ZipEntry entry;
try {
while ( ( entry = zis.getNextEntry() ) != null)
{
String filename = entry.getName();
File newFile = new File(jsPlugins, filename);
//create all non exists folders
//else you will hit FileNotFoundException for compressed folder
if (entry.isDirectory()){
newFile.mkdirs();
}else{
//
// only write out to file if zip entry is newer than file
//
String reason = null;
long zTime = entry.getTime();
boolean unzip = false;
if (!newFile.exists()){
reason = "NE";
unzip = true;
}
else{
long fTime = newFile.lastModified();
if (zTime > fTime){
reason = "" + new Long((zTime-fTime)/3600000) + "h";
unzip = true;
}
}
if (unzip){
getLogger().info("Unzipping " + newFile.getCanonicalPath() + " (" + reason + ")" );
FileOutputStream fout = new FileOutputStream(newFile);
for (int c = zis.read(); c != -1; c = zis.read()) {
fout.write(c);
}
fout.close();
}
}
zis.closeEntry();
}
zis.close();
}catch (IOException ioe){
getLogger().warning(ioe.getMessage());
ioe.printStackTrace();
}
}
@Override @Override
public void onEnable() public void onEnable()
{ {
FileReader reader = null;
try{ try{
unzipJS();
ScriptEngineManager factory = new ScriptEngineManager(); ScriptEngineManager factory = new ScriptEngineManager();
File bootScript = new File(JS_PLUGINS_DIR + "/lib/scriptcraft.js");
this.engine = factory.getEngineByName("JavaScript"); this.engine = factory.getEngineByName("JavaScript");
reader = new FileReader(bootScript);
this.engine.eval(reader);
Invocable inv = (Invocable)this.engine; Invocable inv = (Invocable)this.engine;
inv.invokeFunction("__onEnable", engine, this, bootScript); this.engine.eval(new InputStreamReader(this.getResource("boot.js")));
inv.invokeFunction("__scboot", this, engine);
}catch(Exception e){ }catch(Exception e){
e.printStackTrace(); e.printStackTrace();
this.getLogger().severe(e.getMessage()); this.getLogger().severe(e.getMessage());
}finally {
if (reader != null){
try {
reader.close();
}catch(IOException ioe){
// fail silently
}
}
} }
} }
public List<String> onTabComplete(CommandSender sender, Command cmd, public List<String> onTabComplete(CommandSender sender, Command cmd,
String alias, String alias,
String[] args) String[] args)
{ {
//
// delegate to javascript
//
List<String> result = new ArrayList<String>(); List<String> result = new ArrayList<String>();
try { try {
Invocable inv = (Invocable)this.engine; Invocable inv = (Invocable)this.engine;

View file

@ -93,8 +93,19 @@ exports.on = function(
priority = bkEvent.EventPriority[priority]; priority = bkEvent.EventPriority[priority];
} }
if (typeof eventType == "string"){ if (typeof eventType == "string"){
/*
Nashorn doesn't support bracket notation for accessing packages.
E.g. java.net will work but java['net'] won't.
https://bugs.openjdk.java.net/browse/JDK-8031715
*/
if (typeof Java != 'undefined'){
// nashorn environment
eventType = Java.type('org.bukkit.event.' + eventType);
} else {
eventType = eval('org.bukkit.event.' + eventType); eventType = eval('org.bukkit.event.' + eventType);
} }
}
var handlerList = eventType.getHandlerList(); var handlerList = eventType.getHandlerList();
var listener = {}; var listener = {};
var eventExecutor = new bkEvtExecutor(){ var eventExecutor = new bkEvtExecutor(){

View file

@ -49,6 +49,8 @@ exports.autoload = function(dir) {
var _listSourceFiles = function(store,dir) var _listSourceFiles = function(store,dir)
{ {
var files = dir.listFiles(); var files = dir.listFiles();
if (!files)
return;
for (var i = 0;i < files.length; i++) { for (var i = 0;i < files.length; i++) {
var file = files[i]; var file = files[i];
if (file.isDirectory()){ if (file.isDirectory()){
@ -73,8 +75,6 @@ exports.autoload = function(dir) {
console.info(len + ' scriptcraft plugins found.'); console.info(len + ' scriptcraft plugins found.');
for (var i = 0;i < len; i++){ for (var i = 0;i < len; i++){
var pluginPath = _canonize(sourceFiles[i]); var pluginPath = _canonize(sourceFiles[i]);
if (config.verbose)
console.info('Loading plugin: ' + pluginPath);
var module = {}; var module = {};
try { try {
module = require(pluginPath); module = require(pluginPath);

View file

@ -54,12 +54,7 @@ module specification, the '.js' suffix is optional.
[cjsmodules]: http://wiki.commonjs.org/wiki/Modules/1.1.1. [cjsmodules]: http://wiki.commonjs.org/wiki/Modules/1.1.1.
***/ ***/
(function (logger, evaluator, verbose, rootDir, modulePaths) { (function (rootDir, modulePaths, hooks) {
if (verbose){
logger.info("Setting up 'require' module system. Root Directory: " + rootDir);
logger.info("Module paths: " + JSON.stringify(modulePaths));
}
var File = java.io.File; var File = java.io.File;
@ -152,9 +147,6 @@ When resolving module names to file paths, ScriptCraft uses the following rules.
if (resolvedFile.exists()) if (resolvedFile.exists())
return resolvedFile; return resolvedFile;
} }
if (verbose){
logger.info("Module " + moduleName + " not found in " + modulePaths[i]);
}
} }
} else { } else {
// it's of the form ./path // it's of the form ./path
@ -192,8 +184,7 @@ When resolving module names to file paths, ScriptCraft uses the following rules.
if (! ( (''+path).match(/^\./) )){ if (! ( (''+path).match(/^\./) )){
errMsg = errMsg + ' and not found in paths ' + JSON.stringify(modulePaths); errMsg = errMsg + ' and not found in paths ' + JSON.stringify(modulePaths);
} }
logger.warning(errMsg); throw errMsg;
throw new Error(errMsg);
} }
var canonizedFilename = _canonize(file); var canonizedFilename = _canonize(file);
@ -201,9 +192,8 @@ When resolving module names to file paths, ScriptCraft uses the following rules.
if (moduleInfo){ if (moduleInfo){
return moduleInfo; return moduleInfo;
} }
if (verbose){ if (hooks)
logger.info("loading module " + canonizedFilename); hooks.loading(canonizedFilename);
}
var reader = new java.io.FileReader(file); var reader = new java.io.FileReader(file);
var br = new java.io.BufferedReader(reader); var br = new java.io.BufferedReader(reader);
var code = ""; var code = "";
@ -225,10 +215,9 @@ When resolving module names to file paths, ScriptCraft uses the following rules.
_loadedModules[canonizedFilename] = moduleInfo; _loadedModules[canonizedFilename] = moduleInfo;
var compiledWrapper = null; var compiledWrapper = null;
try { try {
compiledWrapper = evaluator.eval(code); compiledWrapper = eval(code);
}catch (e){ }catch (e){
logger.severe("Error:" + e + " while evaluating module " + canonizedFilename); throw "Error:" + e + " while evaluating module " + canonizedFilename;
throw e;
} }
var __dirname = "" + file.parentFile.canonicalPath; var __dirname = "" + file.parentFile.canonicalPath;
var parameters = [ var parameters = [
@ -243,12 +232,10 @@ When resolving module names to file paths, ScriptCraft uses the following rules.
.apply(moduleInfo.exports, /* this */ .apply(moduleInfo.exports, /* this */
parameters); parameters);
} catch (e){ } catch (e){
logger.severe('Error:' + e + ' while executing module ' + canonizedFilename); throw 'Error:' + e + ' while executing module ' + canonizedFilename;
throw e;
} }
if (verbose) if (hooks)
logger.info("loaded module " + canonizedFilename); hooks.loaded(canonizedFilename);
moduleInfo.loaded = true; moduleInfo.loaded = true;
return moduleInfo; return moduleInfo;
}; };

View file

@ -428,6 +428,7 @@ function __onEnable (__engine, __plugin, __script)
var libDir = __script.parentFile; // lib (assumes scriptcraft.js is in craftbukkit/plugins/scriptcraft/lib directory var libDir = __script.parentFile; // lib (assumes scriptcraft.js is in craftbukkit/plugins/scriptcraft/lib directory
var jsPluginsRootDir = libDir.parentFile; // scriptcraft var jsPluginsRootDir = libDir.parentFile; // scriptcraft
var jsPluginsRootDirName = _canonize(jsPluginsRootDir); var jsPluginsRootDirName = _canonize(jsPluginsRootDir);
var logger = __plugin.logger;
/* /*
Save a javascript object to a file (saves using JSON notation) Save a javascript object to a file (saves using JSON notation)
@ -482,7 +483,7 @@ function __onEnable (__engine, __plugin, __script)
result = __engine.eval(wrappedCode); result = __engine.eval(wrappedCode);
// issue #103 avoid side-effects of || operator on Mac Rhino // issue #103 avoid side-effects of || operator on Mac Rhino
}catch (e){ }catch (e){
__plugin.logger.severe("Error evaluating " + canonizedFilename + ", " + e ); logger.severe("Error evaluating " + canonizedFilename + ", " + e );
} }
finally { finally {
try { try {
@ -493,7 +494,7 @@ function __onEnable (__engine, __plugin, __script)
} }
}else{ }else{
if (warnOnFileNotFound) if (warnOnFileNotFound)
__plugin.logger.warning(canonizedFilename + " not found"); logger.warning(canonizedFilename + " not found");
} }
return result; return result;
}; };
@ -529,7 +530,6 @@ function __onEnable (__engine, __plugin, __script)
}; };
var _echo = function (msg) { var _echo = function (msg) {
__plugin.logger.info( msg );
if (typeof self == "undefined"){ if (typeof self == "undefined"){
return; return;
} }
@ -543,17 +543,28 @@ function __onEnable (__engine, __plugin, __script)
global.addUnloadHandler = _addUnloadHandler; global.addUnloadHandler = _addUnloadHandler;
var fnRequire = _load(jsPluginsRootDirName + '/lib/require.js',true); var configRequire = _load(jsPluginsRootDirName + '/lib/require.js',true);
/* /*
setup paths to search for modules setup paths to search for modules
*/ */
var modulePaths = [jsPluginsRootDirName + '/lib/', var modulePaths = [jsPluginsRootDirName + '/lib/',
jsPluginsRootDirName + '/modules/']; jsPluginsRootDirName + '/modules/'];
global.require = fnRequire(__plugin.logger,
__engine, if (config.verbose){
config.verbose, logger.info('Setting up CommonJS-style module system. Root Directory: ' + jsPluginsRootDirName);
jsPluginsRootDirName, logger.info('Module paths: ' + JSON.stringify(modulePaths));
modulePaths); }
var requireHooks = {
loading: function(path){
if (config.verbose)
logger.info('loading ' + path);
},
loaded: function(path){
if (config.verbose)
logger.info('loaded ' + path);
}
};
global.require = configRequire(jsPluginsRootDirName, modulePaths,requireHooks );
require('js-patch')(global); require('js-patch')(global);
global.console = require('console'); global.console = require('console');
@ -570,10 +581,10 @@ function __onEnable (__engine, __plugin, __script)
var events = require('events'); var events = require('events');
events.on('server.PluginDisableEvent',function(l,e){ events.on('server.PluginDisableEvent',function(l,e){
// save config // save config
_save(global.config, new File(jsPluginsRootDir, "data/global-config.json" )); _save(global.config, new File(jsPluginsRootDir, 'data/global-config.json' ));
_runUnloadHandlers(); _runUnloadHandlers();
org.bukkit.event.HandlerList["unregisterAll(org.bukkit.plugin.Plugin)"](__plugin); org.bukkit.event.HandlerList['unregisterAll(org.bukkit.plugin.Plugin)'](__plugin);
}); });
// wph 20131226 - make events global as it is used by many plugins/modules // wph 20131226 - make events global as it is used by many plugins/modules
global.events = events; global.events = events;
@ -593,12 +604,11 @@ function __onEnable (__engine, __plugin, __script)
global.self = sender; global.self = sender;
global.__engine = __engine; global.__engine = __engine;
try { try {
//var jsResult = __engine["eval(java.lang.String,javax.script.Bindings)"]( fnBody, bindings );
var jsResult = __engine.eval(fnBody); var jsResult = __engine.eval(fnBody);
if (jsResult) if (jsResult)
sender.sendMessage(jsResult); sender.sendMessage(jsResult);
}catch (e){ }catch (e){
__plugin.logger.severe("Error while trying to evaluate javascript: " + fnBody + ", Error: "+ e); logger.severe("Error while trying to evaluate javascript: " + fnBody + ", Error: "+ e);
throw e; throw e;
}finally{ }finally{
delete global.self; delete global.self;

View file

@ -0,0 +1,76 @@
/*
This file is the first and only file executed directly from the Java Plugin.
*/
var __scboot = null;
(function(){
var File = java.io.File
,FileReader = java.io.FileReader
,FileOutputStream = java.io.FileOutputStream
,ZipInputStream = java.util.zip.ZipInputStream
,jsPlugins = new File('plugins/scriptcraft')
,initScript = 'lib/scriptcraft.js';
var unzip = function(path, logger, plugin) {
var zis = new ZipInputStream(plugin.getResource(path))
, entry , reason = null, unzipFile = false, zTime = 0
, fTime = 0, fout = null, c, newFile;
while ( ( entry = zis.nextEntry ) != null ) {
newFile = new File(jsPlugins, entry.name);
if (entry.isDirectory()){
newFile.mkdirs();
zis.closeEntry();
continue;
}
reason = null;
zTime = entry.time;
unzipFile = false;
if (!newFile.exists()) {
reason = 'NE';
unzipFile = true;
}else{
fTime = newFile.lastModified();
if (zTime > fTime) {
reason = ((zTime - fTime) / 3600000) + "h";
unzipFile = true;
}
}
if (unzipFile) {
logger.info('Unzipping ' + newFile.canonicalPath + ' (' + reason + ')' );
fout = new FileOutputStream(newFile);
for (c = zis.read(); c != -1; c = zis.read()) {
fout.write(c);
}
fout.close();
}
zis.closeEntry();
}
zis.close();
};
__scboot = function ( plugin, engine )
{
var logger = plugin.logger, cfg = plugin.config
,cfgName, initScriptFile = new File(jsPlugins,initScript)
,zips = ['lib','plugins','modules']
,i = 0 ,len = zips.length;
if (!jsPlugins.exists()){
logger.info('Directory ' + jsPlugins.canonicalPath + ' does not exist.');
logger.info('Initializing ' + jsPlugins.canonicalPath + ' directory with contents from plugin archive.');
jsPlugins.mkdirs();
}
for (i = 0; i < len;i++){
cfgName = 'extract-js.' + zips[i];
if (cfg.getBoolean(cfgName)){
unzip( zips[i] + '.zip',logger,plugin);
}
}
plugin.saveDefaultConfig();
engine.eval(new FileReader(initScriptFile));
__onEnable(engine, plugin, initScriptFile);
};
})();

View file

@ -0,0 +1,4 @@
extract-js:
plugins: true
modules: true
lib: true