This commit is contained in:
walterhiggins 2013-12-24 00:17:07 +00:00
parent 4d807373da
commit aa93491a6c

View file

@ -49,7 +49,12 @@ As of February 10 2013, the js-plugins directory has the following sub-directori
## Core Module
This module defines commonly used functions by all plugins...
* echo (message) - Displays a message on the screen.
For example: `/js echo('Hello World')` will print Hello World on the in-game chat window.
For programmers familiar with Javascript web programming, an `alert` function is also provided.
`alert` works exactly the same as `echo` e.g. `alert('Hello World')`
* load (filename,warnOnFileNotFound) - loads and evaluates a javascript file, returning the evaluated object.
* save (object, filename) - saves an object to a file.
@ -140,7 +145,7 @@ whose state you want to have managed by ScriptCraft - that is - a
Module whose state will be loaded at start up and saved at shut down.
A plugin is just a regular javascript object whose state is managed by
ScriptCraft. The only member of the plugin which whose persistence is
managed by Scriptcraft is `state` - this special member will be
managed by Scriptcraft is `store` - this special member will be
automatically saved at shutdown and loaded at startup by
ScriptCraft. This makes it easier to write plugins which need to
persist data.
@ -225,7 +230,6 @@ There are a couple of special javascript variables available in ScriptCraft...
* self - the current player. (Note - this value should not be used in multi-threaded scripts - it's not thread-safe)
***/
var verbose = verbose || false;
/*
wph 20130124 - make self, plugin and server public - these are far more useful now that tab-complete works.
*/
@ -239,13 +243,14 @@ var server = org.bukkit.Bukkit.server;
//
if (typeof load == "function")
return ;
var File = java.io.File;
var _canonize = function(file){
return "" + file.getCanonicalPath().replaceAll("\\\\","/");
};
var _originalScript = __script;
var parentFileObj = new java.io.File(__script).getParentFile();
var parentFileObj = new File(__script).getParentFile();
var jsPluginsRootDir = parentFileObj.getParentFile();
var jsPluginsRootDirName = _canonize(jsPluginsRootDir);
@ -257,9 +262,15 @@ var server = org.bukkit.Bukkit.server;
*/
var _load = function(filename,warnOnFileNotFound)
{
var result = null;
var FileReader = java.io.FileReader
,BufferedReader = java.io.BufferedReader
,result = null
,file = filename
,r = undefined;
var file = new java.io.File(filename);
if (!(filename instanceof File))
file = new File(filename);
var canonizedFilename = _canonize(file);
//
// wph 20130123 don't load the same file more than once.
@ -267,27 +278,24 @@ var server = org.bukkit.Bukkit.server;
if (_loaded[canonizedFilename])
return _loaded[canonizedFilename];
if (verbose)
print("loading " + canonizedFilename);
if (file.exists()) {
var parent = file.getParentFile();
var reader = new java.io.FileReader(file);
var br = new java.io.BufferedReader(reader);
var reader = new FileReader(file);
var br = new BufferedReader(reader);
__engine.put("__script",canonizedFilename);
__engine.put("__folder",(parent?_canonize(parent):"")+"/");
var code = "";
try{
if (file.getCanonicalPath().endsWith(".coffee")) {
var r = undefined;
while ((r = br.readLine()) !== null) code += "\"" + r + "\" +\n";
code += "\"\"";
var code = "load(__folder + \"../core/_coffeescript.js\"); var ___code = "+code+"; eval(CoffeeScript.compile(___code, {bare: true}))";
} else {
while ((r = br.readLine()) !== null) code += r + "\n";
while ((r = br.readLine()) !== null)
code += r + "\n";
}
result = __engine.eval(code);
result = __engine.eval("(" + code + ")");
_loaded[canonizedFilename] = result || true;
}catch (e){
__plugin.logger.severe("Error evaluating " + canonizedFilename + ", " + e );
@ -306,168 +314,12 @@ var server = org.bukkit.Bukkit.server;
return result;
};
/*
recursively walk the given directory and return a list of all .js files
now that load is defined, use it to load a global config object
*/
var _listSourceFiles = function(store,dir)
{
if (typeof dir == "undefined"){
dir = new java.io.File(_originalScript).getParentFile().getParentFile();
}
var files = dir.listFiles();
for (var i = 0;i < files.length; i++){
var file = files[i];
if (file.isDirectory()){
_listSourceFiles(store,file);
}else{
if ((file.getCanonicalPath().endsWith(".js") || file.getCanonicalPath().endsWith(".coffee")) &&
!(file.getName().startsWith("_")) &&
file.exists())
{
store.push(file);
}
}
}
};
/*
sort so that .js files with same name as parent directory appear before
other files in the same directory
*/
var sortByModule = function(a,b){
a = _canonize(a);
b = _canonize(b);
var aparts = (""+a).split(/\//);
var bparts = (""+b).split(/\//);
//var adir = aparts[aparts.length-2];
var adir = aparts.slice(0,aparts.length-1).join("/");
var afile = aparts[aparts.length-1];
//var bdir = bparts[bparts.length-2];
var bdir = bparts.slice(0,bparts.length-1).join("/");
var bfile = bparts[bparts.length-1];
if(adir<bdir) return -1;
if(adir>bdir) return 1;
afile = afile.match(/[a-zA-Z0-9\-_]+/)[0];
if (adir.match(new RegExp(afile + "$")))
return -1;
else
return 1;
};
/*
Reload all of the .js files in the given directory
*/
var _reload = function(pluginDir)
{
_loaded = [];
var sourceFiles = [];
_listSourceFiles(sourceFiles,pluginDir);
sourceFiles.sort(sortByModule);
//
// script files whose name begins with _ (underscore)
// will not be loaded automatically at startup.
// These files are assumed to be dependencies/private to plugins
//
// E.g. If you have a plugin called myMiniGame.js in the myMiniGame directory
// and which in addition to myMiniGame.js also includes _myMiniGame_currency.js _myMiniGame_events.js etc.
// then it's assumed that _myMiniGame_currency.js and _myMiniGame_events.js will be loaded
// as dependencies by myMiniGame.js and do not need to be loaded via js reload
//
var len = sourceFiles.length;
for (var i = 0;i < len; i++){
load(_canonize(sourceFiles[i]),true);
}
};
/*
Save a javascript object to a file (saves using JSON notation)
*/
var _save = function(object, filename){
var objectToStr = null;
try{
objectToStr = JSON.stringify(object);
}catch(e){
print("ERROR: " + e.getMessage() + " while saving " + filename);
return;
}
var f = new java.io.File(filename);
var out = new java.io.PrintWriter(new java.io.FileWriter(f));
out.println("__data = " + objectToStr);
out.close();
};
/*
plugin management
*/
var _plugins = {};
var _plugin = function(/* String */ moduleName, /* Object */ moduleObject, isPersistent)
{
//
// don't load plugin more than once
//
if (typeof _plugins[moduleName] != "undefined")
return _plugins[moduleName].module;
var pluginData = {persistent: isPersistent, module: moduleObject};
moduleObject.store = moduleObject.store || {};
_plugins[moduleName] = pluginData;
if (isPersistent)
moduleObject.store = load(jsPluginsRootDirName + "/" + moduleName + "-store.txt") || {};
global[moduleName] = moduleObject;
return moduleObject;
};
/*
allow for deferred execution (once all modules have loaded)
*/
var _deferred = [];
var _ready = function( func ){
_deferred.push(func);
};
var _cmdInterceptors = [];
/*
command management - allow for non-ops to execute approved javascript code.
*/
var _commands = {};
var _command = function(name,func,options,intercepts)
{
if (typeof name == "undefined"){
// it's an invocation from the Java Plugin!
if (__cmdArgs.length === 0)
throw new Error("Usage: jsp command-name command-parameters");
var name = __cmdArgs[0];
var cmd = _commands[name];
if (typeof cmd === "undefined"){
// it's not a global command - pass it on to interceptors
var intercepted = false;
for (var i = 0;i < _cmdInterceptors.length;i++){
if (_cmdInterceptors[i](__cmdArgs))
intercepted = true;
}
if (!intercepted)
self.sendMessage("Command '" + name + "' is not recognised");
}else{
func = cmd.callback;
var params = [];
for (var i =1; i < __cmdArgs.length;i++){
params.push("" + __cmdArgs[i]);
}
return func(params);
}
}else{
if (typeof options == "undefined")
options = [];
_commands[name] = {callback: func, options: options};
if (intercepts)
_cmdInterceptors.push(func);
return func;
}
};
var _rmCommand = function(name){
delete _commands[name];
};
var config = _load(new File(jsPluginsRootDir, "data/global-config.json" ));
if (!config)
config = {verbose: false};
global.config = config;
/*
Tab Completion of the /js and /jsp commands
*/
@ -568,6 +420,7 @@ var server = org.bukkit.Bukkit.server;
}
return result;
};
var _commands;
/*
Tab completion for the /js command
*/
@ -775,41 +628,41 @@ See [issue #69][issue69] for more information.
__plugin.pluginLoader.enablePlugin(__plugin);
};
var _echo = function (msg) {
__plugin.logger.info( msg );
if (typeof self == "undefined"){
return;
}
self.sendMessage(msg);
};
global.echo = _echo;
global.alert = _echo;
global.load = _load;
global.save = _save;
global.plugin = _plugin;
global.ready = _ready;
global.command = _command;
global.logger = __plugin.logger;
global._onTabComplete = __onTabCompleteJS;
global.addUnloadHandler = _addUnloadHandler;
var fnRequire = load(jsPluginsRootDirName + '/core/_require.js',true);
global.require = fnRequire(__plugin, __engine, verbose);
//
// assumes this was loaded from js-plugins/core/
// load all of the plugins.
//
_reload(jsPluginsRootDir);
var fnRequire = load(jsPluginsRootDirName + '/lib/require.js',true);
global.require = fnRequire(__plugin.logger, __engine, config.verbose, jsPluginsRootDirName);
//
// all modules have loaded
//
for (var i =0;i < _deferred.length;i++)
_deferred[i]();
events.on("server.PluginDisableEvent",function(l,e){
//
// save all plugins which have persistent data
//
for (var moduleName in _plugins){
var pluginData = _plugins[moduleName];
if (pluginData.persistent)
save(pluginData.module.store, jsPluginsRootDirName + "/" + moduleName + "-store.txt");
}
_runUnloadHandlers();
var plugins = require('plugin');
_commands = plugins.commands;
global.plugin = plugins.plugin;
global.command = plugins.command;
global.save = plugins.save;
plugins.autoload(jsPluginsRootDir);
var events = require('events');
events.on('server.PluginDisableEvent',function(l,e){
// save config
plugins.save(global.config, new File(jsPluginsRootDir, "data/global-config.json" ));
_runUnloadHandlers();
org.bukkit.event.HandlerList["unregisterAll(org.bukkit.plugin.Plugin)"](__plugin);
});
}());