diff --git a/src/main/javascript/lib/scriptcraft.js b/src/main/javascript/lib/scriptcraft.js index b874a44..c270f14 100644 --- a/src/main/javascript/lib/scriptcraft.js +++ b/src/main/javascript/lib/scriptcraft.js @@ -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(adirbdir) 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); }); + }());