2013-02-10 14:42:32 +01:00
|
|
|
/************************************************************************
|
2013-02-10 18:52:37 +01:00
|
|
|
ScriptCraft API Reference
|
|
|
|
=========================
|
|
|
|
|
|
|
|
Walter Higgins
|
|
|
|
|
|
|
|
[walter.higgins@gmail.com][email]
|
|
|
|
|
|
|
|
[email]: mailto:walter.higgins@gmail.com?subject=ScriptCraft_API_Reference
|
|
|
|
|
2013-02-10 20:36:39 +01:00
|
|
|
Module Loading
|
|
|
|
==============
|
|
|
|
At server startup the ScriptCraft Java plugin is loaded and once
|
|
|
|
loaded the Java plugin will in turn begin loading all of the
|
|
|
|
javascript (.js) files it finds in the js-plugins directory (in the
|
|
|
|
current working directory). If this is the first time the ScriptCraft
|
|
|
|
plugin is loaded, then the js-plugins directory will not yet exist, it
|
|
|
|
will be created and all of the bundled javascript files will be
|
|
|
|
unzipped into it from a bundled resource within the Java plugin. The
|
|
|
|
very first javascript file to load will always be
|
|
|
|
js-plugins/core/_scriptcraft.js. Then all other javascript files are
|
|
|
|
loaded.
|
|
|
|
|
|
|
|
Directory structure
|
|
|
|
-------------------
|
|
|
|
The js-plugins directory is loosely organised into subdirectories -
|
|
|
|
one for each module. Each subdirectory in turn can contain one or more
|
|
|
|
javascript files. Within each directory, a javascript file with the
|
|
|
|
same filename as the directory will always be loaded before all other
|
|
|
|
files in the same directory. So for example, drone/drone.js will
|
|
|
|
always load before any other files in the drone/ directory. Similarly
|
|
|
|
utils/utils.js will always load before any other files in the utils/
|
|
|
|
directory.
|
|
|
|
|
|
|
|
Directories
|
|
|
|
-----------
|
|
|
|
As of February 10 2013, the js-plugins directory has the following sub-directories...
|
|
|
|
|
|
|
|
* core - Contains javascript files containing Core functionality crucial to ScriptCraft and modules which use it.
|
|
|
|
* drone - Contains the drone module and drone extensions. Drone was the first scriptcraft module.
|
|
|
|
* ext - Contains external 3rd party javascript libraries (e.g. json2.js - the JSON lib)
|
|
|
|
* mini-games - Contains mini-games
|
|
|
|
* arrows - The arrows module
|
|
|
|
* signs - The signs module
|
|
|
|
* chat - The chat plugin/module
|
|
|
|
* alias - The alias plugin/module
|
|
|
|
|
2013-02-10 14:42:32 +01:00
|
|
|
Core Module
|
|
|
|
===========
|
|
|
|
This module defines commonly used functions by all plugins...
|
2013-01-17 01:05:17 +01:00
|
|
|
|
2013-02-10 18:52:37 +01:00
|
|
|
* load (filename,warnOnFileNotFound) - loads and evaluates a javascript file, returning the evaluated object.
|
2013-01-17 01:05:17 +01:00
|
|
|
|
2013-02-10 14:42:32 +01:00
|
|
|
* save (object, filename) - saves an object to a file.
|
|
|
|
|
|
|
|
* plugin (name, interface, isPersistent) - defines a new plugin. If
|
|
|
|
isPersistent is true then the plugin doesn't have to worry about
|
|
|
|
loading and saving state - that will be done by the framework. Just
|
|
|
|
make sure that anything you want to save (and restore) is in the
|
|
|
|
'store' property - this will be created automatically if not
|
|
|
|
already defined. (its type is object {} )
|
2013-01-23 01:02:57 +01:00
|
|
|
|
2013-02-10 14:42:32 +01:00
|
|
|
* ready (function) - specifies code to be executed only when all the plugins have loaded.
|
2013-01-17 01:05:17 +01:00
|
|
|
|
2013-02-10 14:42:32 +01:00
|
|
|
* command (name, function) - defines a command that can be used by non-operators.
|
|
|
|
|
2013-02-10 20:36:39 +01:00
|
|
|
load() function
|
|
|
|
---------------
|
2013-02-17 18:43:28 +01:00
|
|
|
The load() function is used by ScriptCraft at startup to load all of
|
|
|
|
the javascript modules and data. You normally wouldn't need to call
|
|
|
|
this function directly. If you put a javascript file anywhere in the
|
|
|
|
craftbukkit/js-plugins directory tree it will be loaded automatically
|
|
|
|
when craftbukkit starts up. The exception is files whose name begins
|
|
|
|
with an underscore `_` character. These files will not be
|
|
|
|
automatically loaded at startup as they are assumed to be files
|
|
|
|
managed / loaded by plugins.
|
2013-02-10 20:36:39 +01:00
|
|
|
|
|
|
|
Parameters
|
|
|
|
----------
|
|
|
|
|
|
|
|
* filenames - An array of file names or a single file name.
|
|
|
|
* warnOnFileNotFound (optional - default: false) - warn if the file was not found.
|
|
|
|
|
|
|
|
Return
|
|
|
|
------
|
|
|
|
load() will return the result of the last statement evaluated in the file.
|
|
|
|
|
|
|
|
Example
|
|
|
|
-------
|
|
|
|
|
|
|
|
load(__folder + "myFile.js"); // loads a javascript file and evaluates it.
|
|
|
|
|
|
|
|
var myData = load("myData.json"); // loads a javascript file and evaluates it - eval'd contents are returned.
|
|
|
|
|
|
|
|
myData.json contents...
|
|
|
|
|
|
|
|
__data = {players:{
|
|
|
|
walterh:{
|
|
|
|
h: ["jsp home {1}"],
|
|
|
|
sunny:["time set 0",
|
|
|
|
"weather clear"]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-17 18:43:28 +01:00
|
|
|
save() function
|
|
|
|
---------------
|
|
|
|
The save() function saves an in-memory javascript object to a
|
|
|
|
specified file. Under the hood, save() uses JSON (specifically
|
|
|
|
json2.js) to save the object. Again, there will usually be no need to
|
|
|
|
call this function directly as all javascript plugins' state are saved
|
|
|
|
automatically if they are declared using the `plugin()` function. Any
|
|
|
|
in-memory object saved using the `save()` function can later be
|
|
|
|
restored using the `load()` function.
|
|
|
|
|
|
|
|
Parameters
|
|
|
|
----------
|
|
|
|
|
|
|
|
* objectToSave : The object you want to save.
|
|
|
|
* filename : The name of the file you want to save it to.
|
|
|
|
|
|
|
|
Example
|
|
|
|
-------
|
|
|
|
|
|
|
|
var myObject = { name: 'John Doe',
|
|
|
|
aliases: ['John Ray', 'John Mee'],
|
|
|
|
date_of_birth: '1982/01/31' };
|
|
|
|
save(myObject, 'johndoe.json');
|
|
|
|
|
|
|
|
johndoe.json contents...
|
|
|
|
|
|
|
|
var __data = { "name": "John Doe",
|
|
|
|
"aliases": ["John Ray", "John Mee"],
|
|
|
|
"date_of_birth": "1982/01/31" };
|
|
|
|
|
|
|
|
plugin() function
|
|
|
|
-----------------
|
|
|
|
The `plugin()` function should be used to declare a javascript module
|
|
|
|
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
|
|
|
|
automatically saved at shutdown and loaded at startup by
|
|
|
|
ScriptCraft. This makes it easier to write plugins which need to
|
|
|
|
persist data.
|
|
|
|
|
|
|
|
Parameters
|
|
|
|
----------
|
|
|
|
|
|
|
|
* pluginName (String) : The name of the plugin - this becomes a global variable.
|
|
|
|
* pluginDefinition (Object) : The various functions and members of the plugin object.
|
|
|
|
* isPersistent (boolean - optional) : Specifies whether or not the plugin/object state should be loaded and saved by ScriptCraft.
|
|
|
|
|
|
|
|
Example
|
|
|
|
-------
|
|
|
|
See chat/color.js for an example of a simple plugin - one which lets
|
|
|
|
players choose a default chat color. See also [Anatomy of a
|
|
|
|
ScriptCraft Plugin][anatomy].
|
|
|
|
|
|
|
|
[anatomy]: http://walterhiggins.net/blog/ScriptCraft-1-Month-later
|
|
|
|
|
|
|
|
command() function
|
|
|
|
------------------
|
|
|
|
The `command()` function is used to expose javascript functions for
|
|
|
|
use by non-operators (regular players). Only operators should be
|
|
|
|
allowed use raw javascript using the `/js ` command because it is too
|
|
|
|
powerful for use by regular players and can be easily abused. However,
|
|
|
|
the `/jsp ` command lets you (the operator / server administrator /
|
|
|
|
plugin author) safely expose javascript functions for use by players.
|
|
|
|
|
|
|
|
Parameters
|
|
|
|
----------
|
|
|
|
|
|
|
|
* commandName : The name to give your command - the command will be invoked like this by players `/jsp commandName`
|
|
|
|
* commandFunction: The javascript function which will be invoked when the command is invoked by a player.
|
|
|
|
* options (Array - optional) : An array of command options/parameters
|
|
|
|
which the player can supply (It's useful to supply an array so that
|
|
|
|
Tab-Completion works for the `/jsp ` commands.
|
|
|
|
* intercepts (boolean - optional) : Indicates whether this command
|
|
|
|
can intercept Tab-Completion of the `/jsp ` command - advanced
|
|
|
|
usage - see alias/alias.js for example.
|
|
|
|
|
|
|
|
Example
|
|
|
|
-------
|
|
|
|
See chat/colors.js or alias/alias.js or homes/homes.js for examples of how to use the `command()` function.
|
|
|
|
|
|
|
|
ready() function
|
|
|
|
----------------
|
|
|
|
The `ready()` function provides a way for plugins to do additional
|
|
|
|
setup once all of the other plugins/modules have loaded. For example,
|
|
|
|
event listener registration can only be done after the
|
|
|
|
events/events.js module has loaded. A plugin author could load the
|
|
|
|
file explicilty like this...
|
|
|
|
|
|
|
|
load(__folder + "../events/events.js");
|
|
|
|
|
|
|
|
// event listener registration goes here
|
|
|
|
|
|
|
|
... or better still, just do event regristration using the `ready()`
|
|
|
|
handler knowing that by the time the `ready()` callback is invoked,
|
|
|
|
all of the scriptcraft modules have been loaded...
|
|
|
|
|
|
|
|
ready(function(){
|
|
|
|
// event listener registration goes here
|
|
|
|
// code that depends on other plugins/modules also goes here
|
|
|
|
});
|
|
|
|
|
|
|
|
The execution of the function object passed to the `ready()` function
|
|
|
|
is *deferred* until all of the plugins/modules have loaded. That way
|
|
|
|
you are guaranteed that when the function is invoked, all of the
|
|
|
|
plugins/modules have been loaded and evaluated and are ready to use.
|
|
|
|
|
2013-02-10 14:42:32 +01:00
|
|
|
Core Module - Special Variables
|
|
|
|
===============================
|
|
|
|
There are a couple of special javascript variables available in ScriptCraft...
|
2013-02-10 20:36:39 +01:00
|
|
|
|
|
|
|
* __folder - The current working directory - this variable is only to be used within the main body of a .js file.
|
2013-02-17 18:43:28 +01:00
|
|
|
* __plugin - The ScriptCraft JavaPlugin object.
|
2013-02-10 14:42:32 +01:00
|
|
|
* server - The Minecraft Server object.
|
2013-02-17 18:43:28 +01:00
|
|
|
* self - the current player. (Note - this value should not be used in multi-threaded scripts - it's not thread-safe)
|
2013-02-10 14:42:32 +01:00
|
|
|
|
|
|
|
***/
|
|
|
|
|
2013-01-08 00:59:42 +01:00
|
|
|
var global = this;
|
2013-01-18 00:39:43 +01:00
|
|
|
var verbose = verbose || false;
|
2013-01-25 00:47:36 +01:00
|
|
|
/*
|
2013-01-26 18:49:11 +01:00
|
|
|
wph 20130124 - make self, plugin and server public - these are far more useful now that tab-complete works.
|
2013-01-25 00:47:36 +01:00
|
|
|
*/
|
2013-01-26 14:47:16 +01:00
|
|
|
var server = org.bukkit.Bukkit.server;
|
2013-01-08 00:59:42 +01:00
|
|
|
//
|
|
|
|
// private implementation
|
|
|
|
//
|
|
|
|
(function(){
|
2013-01-13 22:06:46 +01:00
|
|
|
//
|
|
|
|
// don't execute this more than once
|
|
|
|
//
|
|
|
|
if (typeof load == "function")
|
|
|
|
return ;
|
2013-01-17 01:05:17 +01:00
|
|
|
|
|
|
|
var _canonize = function(file){ return file.getCanonicalPath().replaceAll("\\\\","/"); };
|
2013-01-13 22:06:46 +01:00
|
|
|
|
|
|
|
var _originalScript = __script;
|
2013-01-18 00:28:12 +01:00
|
|
|
var parentFileObj = new java.io.File(__script).getParentFile();
|
|
|
|
var jsPluginsRootDir = parentFileObj.getParentFile();
|
|
|
|
var jsPluginsRootDirName = _canonize(jsPluginsRootDir);
|
2013-01-17 01:05:17 +01:00
|
|
|
|
|
|
|
|
2013-01-24 21:12:41 +01:00
|
|
|
var _loaded = {};
|
2013-01-18 00:28:12 +01:00
|
|
|
/*
|
|
|
|
Load the contents of the file and evaluate as javascript
|
|
|
|
*/
|
2013-01-19 18:01:59 +01:00
|
|
|
var _load = function(filename,warnOnFileNotFound)
|
2013-01-18 00:28:12 +01:00
|
|
|
{
|
2013-02-10 18:52:37 +01:00
|
|
|
var filenames = [];
|
|
|
|
if (filename.constructor == Array)
|
|
|
|
filenames = filename;
|
|
|
|
else
|
|
|
|
filenames = [filename];
|
|
|
|
|
2013-01-18 00:28:12 +01:00
|
|
|
var result = null;
|
2013-02-10 18:52:37 +01:00
|
|
|
|
|
|
|
for (var i =0;i < filenames.length; i++) {
|
2013-01-15 20:15:40 +01:00
|
|
|
|
2013-02-10 18:52:37 +01:00
|
|
|
var file = new java.io.File(filenames[0]);
|
|
|
|
var canonizedFilename = _canonize(file);
|
|
|
|
//
|
|
|
|
// wph 20130123 don't load the same file more than once.
|
|
|
|
//
|
|
|
|
if (_loaded[canonizedFilename])
|
|
|
|
continue;
|
2013-01-15 20:15:40 +01:00
|
|
|
|
2013-02-10 18:52:37 +01:00
|
|
|
if (verbose)
|
|
|
|
print("loading " + canonizedFilename);
|
|
|
|
|
|
|
|
if (file.exists()) {
|
|
|
|
var parent = file.getParentFile();
|
|
|
|
var reader = new java.io.FileReader(file);
|
|
|
|
__engine.put("__script",canonizedFilename);
|
|
|
|
__engine.put("__folder",(parent?_canonize(parent):"")+"/");
|
|
|
|
try{
|
|
|
|
result = __engine.eval(reader);
|
|
|
|
_loaded[canonizedFilename] = true;
|
2013-02-18 20:33:21 +01:00
|
|
|
reader.close();
|
2013-02-10 18:52:37 +01:00
|
|
|
}catch (e){
|
|
|
|
__plugin.logger.severe("Error evaluating " + canonizedFilename + ", " + e );
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
if (warnOnFileNotFound)
|
|
|
|
__plugin.logger.warning(canonizedFilename + " not found");
|
2013-01-23 01:50:16 +01:00
|
|
|
}
|
2013-01-13 22:06:46 +01:00
|
|
|
}
|
2013-02-10 18:52:37 +01:00
|
|
|
|
2013-01-18 00:28:12 +01:00
|
|
|
return result;
|
2013-01-13 22:06:46 +01:00
|
|
|
};
|
2013-01-18 00:28:12 +01:00
|
|
|
/*
|
|
|
|
recursively walk the given directory and return a list of all .js files
|
|
|
|
*/
|
2013-01-13 22:06:46 +01:00
|
|
|
var _listJsFiles = function(store,dir)
|
|
|
|
{
|
|
|
|
if (typeof dir == "undefined"){
|
2013-01-15 20:15:40 +01:00
|
|
|
dir = new java.io.File(_originalScript).getParentFile().getParentFile();
|
2013-01-13 22:06:46 +01:00
|
|
|
}
|
|
|
|
var files = dir.listFiles();
|
|
|
|
for (var i = 0;i < files.length; i++){
|
2013-01-18 00:28:12 +01:00
|
|
|
var file = files[i];
|
2013-01-15 20:15:40 +01:00
|
|
|
if (file.isDirectory()){
|
|
|
|
_listJsFiles(store,file);
|
2013-01-13 22:06:46 +01:00
|
|
|
}else{
|
2013-01-15 20:15:40 +01:00
|
|
|
if (file.getCanonicalPath().endsWith(".js") &&
|
|
|
|
!(file.getName().startsWith("_")) &&
|
2013-01-18 00:28:12 +01:00
|
|
|
file.exists())
|
2013-01-13 22:06:46 +01:00
|
|
|
{
|
2013-01-15 20:15:40 +01:00
|
|
|
store.push(file);
|
2013-01-13 22:06:46 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2013-02-10 18:52:37 +01:00
|
|
|
/*
|
|
|
|
sort so that .js files with same name as parent directory appear before
|
|
|
|
other files in the same directory
|
|
|
|
*/
|
|
|
|
var sortByModule = function(a,b){
|
|
|
|
var aparts = (""+a).split(/\//);
|
|
|
|
var bparts = (""+b).split(/\//);
|
|
|
|
var adir = aparts[aparts.length-2];
|
|
|
|
var afile = aparts[aparts.length-1];
|
|
|
|
var bdir = bparts[bparts.length-2];
|
|
|
|
var bfile = bparts[bparts.length-1];
|
|
|
|
|
|
|
|
if(adir<bdir) return -1;
|
|
|
|
if(adir>bdir) return 1;
|
|
|
|
if (afile.indexOf(adir) == 0)
|
|
|
|
return -1;
|
|
|
|
else
|
|
|
|
return 1;
|
|
|
|
};
|
2013-01-18 00:28:12 +01:00
|
|
|
/*
|
|
|
|
Reload all of the .js files in the given directory
|
|
|
|
*/
|
2013-01-13 22:06:46 +01:00
|
|
|
var _reload = function(pluginDir)
|
|
|
|
{
|
2013-01-24 21:12:41 +01:00
|
|
|
_loaded = [];
|
2013-01-13 22:06:46 +01:00
|
|
|
var jsFiles = [];
|
|
|
|
_listJsFiles(jsFiles,pluginDir);
|
2013-02-10 18:52:37 +01:00
|
|
|
|
|
|
|
jsFiles.sort(sortByModule);
|
|
|
|
|
2013-01-13 22:06:46 +01:00
|
|
|
//
|
|
|
|
// 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
|
|
|
|
//
|
2013-01-24 21:12:41 +01:00
|
|
|
var len = jsFiles.length;
|
|
|
|
for (var i = 0;i < len; i++){
|
2013-01-23 01:02:57 +01:00
|
|
|
load(_canonize(jsFiles[i]),true);
|
2013-01-13 22:06:46 +01:00
|
|
|
}
|
|
|
|
};
|
2013-01-17 01:05:17 +01:00
|
|
|
|
2013-01-18 00:28:12 +01:00
|
|
|
/*
|
|
|
|
Save a javascript object to a file (saves using JSON notation)
|
|
|
|
*/
|
|
|
|
var _save = function(object, filename){
|
2013-01-23 01:02:57 +01:00
|
|
|
var objectToStr = null;
|
|
|
|
try{
|
|
|
|
objectToStr = JSON.stringify(object);
|
|
|
|
}catch(e){
|
|
|
|
print("ERROR: " + e.getMessage() + " while saving " + filename);
|
|
|
|
return;
|
|
|
|
}
|
2013-01-18 00:28:12 +01:00
|
|
|
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;
|
2013-01-17 01:05:17 +01:00
|
|
|
|
2013-01-18 00:28:12 +01:00
|
|
|
var pluginData = {persistent: isPersistent, module: moduleObject};
|
|
|
|
moduleObject.store = moduleObject.store || {};
|
|
|
|
_plugins[moduleName] = pluginData;
|
2013-01-17 01:05:17 +01:00
|
|
|
|
2013-01-18 00:28:12 +01:00
|
|
|
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);
|
|
|
|
};
|
2013-01-23 01:02:57 +01:00
|
|
|
var _cmdInterceptors = [];
|
2013-01-18 00:28:12 +01:00
|
|
|
/*
|
|
|
|
command management - allow for non-ops to execute approved javascript code.
|
|
|
|
*/
|
|
|
|
var _commands = {};
|
2013-01-26 18:49:11 +01:00
|
|
|
var _command = function(name,func,options,intercepts)
|
|
|
|
{
|
2013-01-18 00:28:12 +01:00
|
|
|
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];
|
2013-01-23 01:02:57 +01:00
|
|
|
var cmd = _commands[name];
|
2013-01-19 18:01:59 +01:00
|
|
|
if (typeof cmd === "undefined"){
|
2013-01-23 01:02:57 +01:00
|
|
|
// 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)
|
2013-01-25 00:47:36 +01:00
|
|
|
self.sendMessage("Command '" + name + "' is not recognised");
|
2013-01-23 01:02:57 +01:00
|
|
|
}else{
|
|
|
|
func = cmd.callback;
|
|
|
|
var params = [];
|
|
|
|
for (var i =1; i < __cmdArgs.length;i++){
|
|
|
|
params.push("" + __cmdArgs[i]);
|
|
|
|
}
|
2013-01-18 00:28:12 +01:00
|
|
|
return func(params);
|
2013-01-23 01:02:57 +01:00
|
|
|
}
|
2013-01-18 00:28:12 +01:00
|
|
|
}else{
|
2013-01-23 01:02:57 +01:00
|
|
|
if (typeof options == "undefined")
|
|
|
|
options = [];
|
2013-01-19 18:01:59 +01:00
|
|
|
_commands[name] = {callback: func, options: options};
|
2013-01-23 01:02:57 +01:00
|
|
|
if (intercepts)
|
|
|
|
_cmdInterceptors.push(func);
|
2013-01-18 00:28:12 +01:00
|
|
|
return func;
|
|
|
|
}
|
|
|
|
};
|
2013-01-23 01:02:57 +01:00
|
|
|
var _rmCommand = function(name){
|
|
|
|
delete _commands[name];
|
|
|
|
};
|
2013-01-18 00:28:12 +01:00
|
|
|
/*
|
|
|
|
Tab Completion of the /js and /jsp commands
|
|
|
|
*/
|
2013-01-13 22:06:46 +01:00
|
|
|
var _isJavaObject = function(o){
|
|
|
|
var result = false;
|
|
|
|
try {
|
|
|
|
o.hasOwnProperty("testForJava");
|
|
|
|
}catch (e){
|
|
|
|
// java will throw an error when an attempt is made to access the
|
|
|
|
// hasOwnProperty method. (it won't exist for Java objects)
|
|
|
|
result = true;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
};
|
|
|
|
var _javaLangObjectMethods = ["equals","getClass","class","getClass","hashCode","notify","notifyAll","toString","wait","clone","finalize"];
|
|
|
|
var _getProperties = function(o)
|
|
|
|
{
|
|
|
|
var result = [];
|
2013-01-17 01:05:17 +01:00
|
|
|
if (_isJavaObject(o))
|
2013-01-18 00:28:12 +01:00
|
|
|
{
|
2013-01-13 22:06:46 +01:00
|
|
|
propertyLoop:
|
2013-01-17 01:05:17 +01:00
|
|
|
for (var i in o)
|
2013-01-18 00:28:12 +01:00
|
|
|
{
|
2013-01-13 22:06:46 +01:00
|
|
|
//
|
|
|
|
// don't include standard Object methods
|
|
|
|
//
|
|
|
|
var isObjectMethod = false;
|
|
|
|
for (var j = 0;j < _javaLangObjectMethods.length; j++)
|
|
|
|
if (_javaLangObjectMethods[j] == i)
|
|
|
|
continue propertyLoop;
|
2013-01-26 14:47:16 +01:00
|
|
|
if (typeof o[i] == "function" )
|
2013-01-13 22:06:46 +01:00
|
|
|
result.push(i+"()");
|
|
|
|
else
|
|
|
|
result.push(i);
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
for (var i in o){
|
|
|
|
if (i.match(/^[^_]/)){
|
|
|
|
if (typeof o[i] == "function")
|
|
|
|
result.push(i+"()");
|
|
|
|
else
|
|
|
|
result.push(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result.sort();
|
|
|
|
};
|
2013-01-18 00:28:12 +01:00
|
|
|
/*
|
|
|
|
Tab completion for the /jsp commmand
|
|
|
|
*/
|
|
|
|
var __onTabCompleteJSP = function() {
|
|
|
|
var result = global.__onTC_result;
|
2013-01-19 18:01:59 +01:00
|
|
|
var args = global.__onTC_args;
|
2013-01-26 18:49:11 +01:00
|
|
|
var cmdInput = args[0];
|
|
|
|
var cmd = _commands[cmdInput];
|
|
|
|
if (cmd){
|
|
|
|
var opts = cmd.options;
|
|
|
|
var len = opts.length;
|
|
|
|
if (args.length == 1){
|
|
|
|
for (var i = 0;i < len; i++)
|
|
|
|
result.add(opts[i]);
|
|
|
|
}else{
|
|
|
|
// partial e.g. /jsp chat_color dar
|
|
|
|
for (var i = 0;i < len; i++){
|
|
|
|
if (opts[i].indexOf(args[1]) == 0){
|
|
|
|
result.add(opts[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
if (args.length == 0){
|
|
|
|
for (var i in _commands)
|
|
|
|
result.add(i);
|
|
|
|
}else{
|
|
|
|
// partial e.g. /jsp al
|
|
|
|
// should tabcomplete to alias
|
|
|
|
//
|
|
|
|
for (var c in _commands){
|
|
|
|
if (c.indexOf(cmdInput) == 0){
|
|
|
|
result.add(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-01-18 00:28:12 +01:00
|
|
|
return result;
|
|
|
|
};
|
|
|
|
/*
|
|
|
|
Tab completion for the /js command
|
|
|
|
*/
|
2013-01-17 01:05:17 +01:00
|
|
|
var __onTabCompleteJS = function()
|
2013-01-13 22:06:46 +01:00
|
|
|
{
|
2013-01-18 00:28:12 +01:00
|
|
|
if (__onTC_cmd.name == "jsp")
|
|
|
|
return __onTabCompleteJSP()
|
2013-01-17 01:05:17 +01:00
|
|
|
|
2013-01-13 22:06:46 +01:00
|
|
|
var _globalSymbols = _getProperties(global)
|
|
|
|
var result = global.__onTC_result;
|
|
|
|
var args = global.__onTC_args;
|
|
|
|
var propsOfLastArg = [];
|
|
|
|
var statement = args.join(" ");
|
2013-01-18 00:28:12 +01:00
|
|
|
statement = statement.replace(/^\s+/,"").replace(/\s+$/,"");
|
|
|
|
|
2013-01-17 01:05:17 +01:00
|
|
|
if (statement.length == 0)
|
2013-01-18 00:28:12 +01:00
|
|
|
propsOfLastArg = _globalSymbols;
|
2013-01-17 01:05:17 +01:00
|
|
|
else{
|
2013-02-02 14:15:32 +01:00
|
|
|
var statementSyms = statement.split(/[^\$a-zA-Z0-9_\.]/);
|
2013-01-13 22:06:46 +01:00
|
|
|
var lastSymbol = statementSyms[statementSyms.length-1];
|
|
|
|
//
|
|
|
|
// try to complete the object ala java IDEs.
|
|
|
|
//
|
|
|
|
var parts = lastSymbol.split(/\./);
|
|
|
|
var name = parts[0];
|
|
|
|
var symbol = global[name];
|
|
|
|
var lastGoodSymbol = symbol;
|
|
|
|
if (typeof symbol != "undefined")
|
|
|
|
{
|
|
|
|
for (var i = 1; i < parts.length;i++){
|
|
|
|
name = parts[i];
|
|
|
|
symbol = symbol[name];
|
|
|
|
if (typeof symbol == "undefined")
|
|
|
|
break;
|
|
|
|
lastGoodSymbol = symbol;
|
|
|
|
}
|
|
|
|
if (typeof symbol == "undefined"){
|
2013-01-18 00:28:12 +01:00
|
|
|
//
|
2013-01-13 22:06:46 +01:00
|
|
|
// look up partial matches against last good symbol
|
|
|
|
//
|
|
|
|
var objectProps = _getProperties(lastGoodSymbol);
|
|
|
|
if (name == ""){
|
2013-01-18 00:28:12 +01:00
|
|
|
// if the last symbol looks like this..
|
|
|
|
// ScriptCraft.
|
|
|
|
//
|
2013-01-13 22:06:46 +01:00
|
|
|
for (var i =0;i < objectProps.length;i++)
|
2013-01-17 01:05:17 +01:00
|
|
|
propsOfLastArg.push(statement+objectProps[i]);
|
2013-01-18 00:28:12 +01:00
|
|
|
|
|
|
|
}else{
|
|
|
|
// it looks like this..
|
|
|
|
// ScriptCraft.co
|
|
|
|
//
|
|
|
|
var li = statement.lastIndexOf(name);
|
|
|
|
statement = statement.substring(0,li);
|
2013-01-08 00:59:42 +01:00
|
|
|
|
2013-01-17 01:05:17 +01:00
|
|
|
for (var i = 0; i < objectProps.length;i++)
|
|
|
|
if (objectProps[i].indexOf(name) == 0)
|
2013-01-13 22:06:46 +01:00
|
|
|
propsOfLastArg.push(statement + objectProps[i]);
|
2013-01-18 00:28:12 +01:00
|
|
|
|
2013-01-13 22:06:46 +01:00
|
|
|
}
|
|
|
|
}else{
|
|
|
|
var objectProps = _getProperties(symbol);
|
2013-02-02 14:15:32 +01:00
|
|
|
for (var i = 0; i < objectProps.length; i++){
|
|
|
|
propsOfLastArg.push(statement + "." + objectProps[i]);
|
|
|
|
}
|
2013-01-13 22:06:46 +01:00
|
|
|
}
|
|
|
|
}else{
|
|
|
|
// loop thru globalSymbols looking for a good match
|
2013-01-17 01:05:17 +01:00
|
|
|
for (var i = 0;i < _globalSymbols.length; i++)
|
|
|
|
if (_globalSymbols[i].indexOf(lastSymbol) == 0)
|
2013-01-13 22:06:46 +01:00
|
|
|
propsOfLastArg.push(statement.replace(lastSymbol,_globalSymbols[i]));
|
2013-01-18 00:28:12 +01:00
|
|
|
|
2013-01-13 22:06:46 +01:00
|
|
|
}
|
|
|
|
}
|
2013-01-17 01:05:17 +01:00
|
|
|
for (var i = 0;i < propsOfLastArg.length; i++)
|
2013-01-13 22:06:46 +01:00
|
|
|
result.add(propsOfLastArg[i]);
|
|
|
|
};
|
|
|
|
|
2013-01-19 01:43:44 +01:00
|
|
|
|
2013-01-18 00:28:12 +01:00
|
|
|
global.load = _load;
|
|
|
|
global.save = _save;
|
|
|
|
global.plugin = _plugin;
|
|
|
|
global.ready = _ready;
|
|
|
|
global.command = _command;
|
2013-01-17 01:05:17 +01:00
|
|
|
global._onTabComplete = __onTabCompleteJS;
|
2013-01-13 22:06:46 +01:00
|
|
|
//
|
|
|
|
// assumes this was loaded from js-plugins/core/
|
2013-01-18 00:28:12 +01:00
|
|
|
// load all of the plugins.
|
2013-01-13 22:06:46 +01:00
|
|
|
//
|
2013-01-24 21:22:22 +01:00
|
|
|
_reload(jsPluginsRootDir);
|
2013-01-13 22:06:46 +01:00
|
|
|
|
2013-01-18 00:28:12 +01:00
|
|
|
//
|
|
|
|
// 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");
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2013-01-13 22:06:46 +01:00
|
|
|
}());
|
2013-01-08 00:59:42 +01:00
|
|
|
|
|
|
|
|
|
|
|
|