Updated alias to support aliases without 'jsp' prefix, added 'console' global variable
This commit is contained in:
parent
d4fe3f9b1b
commit
a7a4bf79a1
4 changed files with 271 additions and 183 deletions
57
src/main/javascript/lib/console.js
Normal file
57
src/main/javascript/lib/console.js
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
/*************************************************************************
|
||||||
|
## console global variable
|
||||||
|
|
||||||
|
ScriptCraft provides a `console` global variable with the followng methods...
|
||||||
|
|
||||||
|
* log()
|
||||||
|
* info()
|
||||||
|
* warn()
|
||||||
|
* error()
|
||||||
|
|
||||||
|
The ScriptCraft console methods work like the Web API implementation.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
console.log('Hello %s', 'world');
|
||||||
|
|
||||||
|
Basic variable substitution is supported (ScriptCraft's implementation
|
||||||
|
of console uses the Bukkit Plugin [Logger][lgr] under the hood and
|
||||||
|
uses [java.lang.String.format()][strfmt] for variable
|
||||||
|
substitution. All output will be sent to the server console (not
|
||||||
|
in-game).
|
||||||
|
|
||||||
|
[lgr]: http://jd.bukkit.org/beta/apidocs/org/bukkit/plugin/PluginLogger.html
|
||||||
|
[strfmt]: http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#format(java.lang.String, java.lang.Object...)
|
||||||
|
|
||||||
|
***/
|
||||||
|
var argsToArray = function(args){
|
||||||
|
var result = [];
|
||||||
|
for (var i =0;i < args.length; i++)
|
||||||
|
result.push(args[i]);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
var log = function(level, restOfArgs){
|
||||||
|
var args = argsToArray(restOfArgs);
|
||||||
|
if (args.length > 1){
|
||||||
|
var msg = java.lang.String.format(args[0],args.slice(1));
|
||||||
|
logger['log(java.util.logging.Level,java.lang.String)'](level,msg);
|
||||||
|
}else{
|
||||||
|
logger['log(java.util.logging.Level,java.lang.String)'](level, args[0]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var Level = java.util.logging.Level;
|
||||||
|
|
||||||
|
exports.log = function(){
|
||||||
|
log(Level.INFO, arguments);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.info = function(){
|
||||||
|
log(Level.INFO, arguments);
|
||||||
|
}
|
||||||
|
exports.warn = function(){
|
||||||
|
log(Level.WARNING, arguments);
|
||||||
|
};
|
||||||
|
exports.error = function(){
|
||||||
|
log(Level.SEVERE, arguments);
|
||||||
|
};
|
43
src/main/javascript/lib/tabcomplete-jsp.js
Normal file
43
src/main/javascript/lib/tabcomplete-jsp.js
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
var _commands = require('plugin').commands;
|
||||||
|
/*
|
||||||
|
Tab completion for the /jsp commmand
|
||||||
|
*/
|
||||||
|
var __onTabCompleteJSP = function() {
|
||||||
|
var result = global.__onTC_result;
|
||||||
|
var args = global.__onTC_args;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
module.exports = __onTabCompleteJSP;
|
||||||
|
|
||||||
|
|
171
src/main/javascript/lib/tabcomplete.js
Normal file
171
src/main/javascript/lib/tabcomplete.js
Normal file
|
@ -0,0 +1,171 @@
|
||||||
|
var tabCompleteJSP = require('tabcomplete-jsp');
|
||||||
|
/*
|
||||||
|
Tab Completion of the /js and /jsp commands
|
||||||
|
*/
|
||||||
|
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 = [];
|
||||||
|
if (_isJavaObject(o))
|
||||||
|
{
|
||||||
|
propertyLoop:
|
||||||
|
for (var i in o)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// don't include standard Object methods
|
||||||
|
//
|
||||||
|
var isObjectMethod = false;
|
||||||
|
for (var j = 0;j < _javaLangObjectMethods.length; j++)
|
||||||
|
if (_javaLangObjectMethods[j] == i)
|
||||||
|
continue propertyLoop;
|
||||||
|
var typeofProperty = null;
|
||||||
|
try {
|
||||||
|
typeofProperty = typeof o[i];
|
||||||
|
}catch( e ){
|
||||||
|
if (e.message == 'java.lang.IllegalStateException: Entity not leashed'){
|
||||||
|
// wph 20131020 fail silently for Entity leashing in craftbukkit
|
||||||
|
}else{
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (typeofProperty == 'function' )
|
||||||
|
result.push(i+'()');
|
||||||
|
else
|
||||||
|
result.push(i);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if (o.constructor == Array)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
for (var i in o){
|
||||||
|
if (i.match(/^[^_]/)){
|
||||||
|
if (typeof o[i] == 'function')
|
||||||
|
result.push(i+'()');
|
||||||
|
else
|
||||||
|
result.push(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.sort();
|
||||||
|
};
|
||||||
|
|
||||||
|
var onTabCompleteJS = function() {
|
||||||
|
if (__onTC_cmd.name == 'jsp')
|
||||||
|
return tabCompleteJSP()
|
||||||
|
var _globalSymbols = _getProperties(global)
|
||||||
|
var result = global.__onTC_result;
|
||||||
|
var args = global.__onTC_args;
|
||||||
|
var lastArg = args.length?args[args.length-1]+'':null;
|
||||||
|
var propsOfLastArg = [];
|
||||||
|
var statement = args.join(' ');
|
||||||
|
|
||||||
|
statement = statement.replace(/^\s+/,'').replace(/\s+$/,'');
|
||||||
|
|
||||||
|
|
||||||
|
if (statement.length == 0)
|
||||||
|
propsOfLastArg = _globalSymbols;
|
||||||
|
else{
|
||||||
|
var statementSyms = statement.split(/[^\$a-zA-Z0-9_\.]/);
|
||||||
|
var lastSymbol = statementSyms[statementSyms.length-1];
|
||||||
|
//print('DEBUG: lastSymbol=[' + lastSymbol + ']');
|
||||||
|
//
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
//print('debug:name['+name+']lastSymbol['+lastSymbol+']symbol['+symbol+']');
|
||||||
|
if (typeof symbol == 'undefined'){
|
||||||
|
//
|
||||||
|
// look up partial matches against last good symbol
|
||||||
|
//
|
||||||
|
var objectProps = _getProperties(lastGoodSymbol);
|
||||||
|
if (name == ''){
|
||||||
|
// if the last symbol looks like this..
|
||||||
|
// ScriptCraft.
|
||||||
|
//
|
||||||
|
|
||||||
|
for (var i =0;i < objectProps.length;i++){
|
||||||
|
var candidate = lastSymbol + objectProps[i];
|
||||||
|
var re = new RegExp(lastSymbol + '$','g');
|
||||||
|
propsOfLastArg.push(lastArg.replace(re,candidate));
|
||||||
|
}
|
||||||
|
|
||||||
|
}else{
|
||||||
|
// it looks like this..
|
||||||
|
// ScriptCraft.co
|
||||||
|
//
|
||||||
|
//print('debug:case Y: ScriptCraft.co');
|
||||||
|
|
||||||
|
var li = statement.lastIndexOf(name);
|
||||||
|
for (var i = 0; i < objectProps.length;i++){
|
||||||
|
if (objectProps[i].indexOf(name) == 0)
|
||||||
|
{
|
||||||
|
var candidate = lastSymbol.substring(0,lastSymbol.lastIndexOf(name));
|
||||||
|
candidate = candidate + objectProps[i];
|
||||||
|
var re = new RegExp(lastSymbol+ '$','g');
|
||||||
|
//print('DEBUG: re=' + re + ',lastSymbol='+lastSymbol+',lastArg=' + lastArg + ',candidate=' + candidate);
|
||||||
|
propsOfLastArg.push(lastArg.replace(re,candidate));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
//print('debug:case Z:ScriptCraft');
|
||||||
|
var objectProps = _getProperties(symbol);
|
||||||
|
for (var i = 0; i < objectProps.length; i++){
|
||||||
|
var re = new RegExp(lastSymbol+ '$','g');
|
||||||
|
propsOfLastArg.push(lastArg.replace(re,lastSymbol + '.' + objectProps[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
//print('debug:case AB:ScriptCr');
|
||||||
|
// loop thru globalSymbols looking for a good match
|
||||||
|
for (var i = 0;i < _globalSymbols.length; i++){
|
||||||
|
if (_globalSymbols[i].indexOf(lastSymbol) == 0){
|
||||||
|
var possibleCompletion = _globalSymbols[i];
|
||||||
|
var re = new RegExp(lastSymbol+ '$','g');
|
||||||
|
propsOfLastArg.push(lastArg.replace(re,possibleCompletion));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var i = 0;i < propsOfLastArg.length; i++)
|
||||||
|
result.add(propsOfLastArg[i]);
|
||||||
|
};
|
||||||
|
module.exports = onTabCompleteJS;
|
|
@ -1,183 +0,0 @@
|
||||||
/*************************************************************************
|
|
||||||
# SnowballFight mini-game
|
|
||||||
|
|
||||||
## Description
|
|
||||||
|
|
||||||
This is a rough and ready prototype of a simple multi-player
|
|
||||||
shoot-em-up. To start a game with all players playing against one another...
|
|
||||||
|
|
||||||
/js new Game_SnowballFight(60).start();
|
|
||||||
|
|
||||||
... this obviously works best if all of the players are in close
|
|
||||||
proximity within the same game world. Alternatively you can have team
|
|
||||||
matches...
|
|
||||||
|
|
||||||
|
|
||||||
/js var redTeam = ['<player1>','<player2>',...etc]
|
|
||||||
/js var blueTeam = ['<player3>','<player4>,...etc]
|
|
||||||
/js var greenTeam = ['<player5>','<player6>,...etc]
|
|
||||||
/js new Game_SnowballFight(60, {red: redTeam,blue: blueTeam,green: greenTeam}).start();
|
|
||||||
|
|
||||||
Or you can just have specific players play against each other...
|
|
||||||
|
|
||||||
/js new Game_SnowballFight(60, ['player1','player2','player3']).start();
|
|
||||||
|
|
||||||
(where 'player1' etc are the names of actual players)
|
|
||||||
|
|
||||||
You specify the teams in the game as an object where each property's
|
|
||||||
name is a team name and each property's value is the list of players
|
|
||||||
on that team. You specify the duration of the game (in seconds) You
|
|
||||||
kick off the game with the start() method. I need to work on a
|
|
||||||
better in-game mechanism for players to choose teams and start the
|
|
||||||
game but this will do for now.
|
|
||||||
|
|
||||||
When the game starts, each player is put in survival mode and given
|
|
||||||
snowballs. The aim of the game is to hit players on opposing teams. If
|
|
||||||
you hit a player on your own team, you lose a point.
|
|
||||||
|
|
||||||
At the end of the game the scores for each team are broadcast and each
|
|
||||||
player returns to their previous mode of play (creative or
|
|
||||||
survival). Create a small arena with a couple of small buildings for
|
|
||||||
cover to make the game more fun.
|
|
||||||
|
|
||||||
***/
|
|
||||||
|
|
||||||
var _startGame = function(gameState){
|
|
||||||
// don't let game start if already in progress (wait for game to finish)
|
|
||||||
if (gameState.inProgress){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
gameState.inProgress = true;
|
|
||||||
// reset timer
|
|
||||||
gameState.duration = gameState.originalDuration;
|
|
||||||
// put all players in survival mode and give them each 200 snowballs
|
|
||||||
// 64 snowballs for every 30 seconds should be more than enough
|
|
||||||
for (var i = 10;i < gameState.duration;i+=10)
|
|
||||||
gameState.ammo.push(gameState.ammo[0]);
|
|
||||||
|
|
||||||
for (var teamName in gameState.teams)
|
|
||||||
{
|
|
||||||
gameState.teamScores[teamName] = 0;
|
|
||||||
var team = gameState.teams[teamName];
|
|
||||||
for (var i = 0;i < team.length;i++) {
|
|
||||||
var player = server.getPlayer(team[i]);
|
|
||||||
gameState.savedModes[player.name] = player.gameMode;
|
|
||||||
player.gameMode = org.bukkit.GameMode.SURVIVAL;
|
|
||||||
player.inventory.addItem(gameState.ammo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
/*
|
|
||||||
end the game
|
|
||||||
*/
|
|
||||||
var _endGame = function(gameState){
|
|
||||||
var scores = [];
|
|
||||||
|
|
||||||
var leaderBoard = [];
|
|
||||||
for (var tn in gameState.teamScores){
|
|
||||||
leaderBoard.push([tn,gameState.teamScores[tn]]);
|
|
||||||
}
|
|
||||||
leaderBoard.sort(function(a,b){ return b[1] - a[1];});
|
|
||||||
|
|
||||||
for (var i = 0;i < leaderBoard.length; i++){
|
|
||||||
scores.push("Team " + leaderBoard[i][0] + " scored " + leaderBoard[i][1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var teamName in gameState.teams) {
|
|
||||||
var team = gameState.teams[teamName];
|
|
||||||
for (var i = 0;i < team.length;i++) {
|
|
||||||
// restore player's previous game mode and take back snowballs
|
|
||||||
var player = server.getPlayer(team[i]);
|
|
||||||
player.gameMode = gameState.savedModes[player.name];
|
|
||||||
player.inventory.removeItem(gameState.ammo);
|
|
||||||
player.sendMessage("GAME OVER.");
|
|
||||||
player.sendMessage(scores);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var handlerList = org.bukkit.event.entity.EntityDamageByEntityEvent.getHandlerList();
|
|
||||||
handlerList.unregister(gameState.listener);
|
|
||||||
gameState.inProgress = false;
|
|
||||||
};
|
|
||||||
/*
|
|
||||||
get the team the player belongs to
|
|
||||||
*/
|
|
||||||
var _getTeam = function(player,pteams) {
|
|
||||||
for (var teamName in pteams) {
|
|
||||||
var team = pteams[teamName];
|
|
||||||
for (var i = 0;i < team.length; i++)
|
|
||||||
if (team[i] == player.name)
|
|
||||||
return teamName;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
/*
|
|
||||||
construct a new game
|
|
||||||
*/
|
|
||||||
var createGame = function(duration, teams) {
|
|
||||||
|
|
||||||
var _snowBalls = new org.bukkit.inventory.ItemStack(org.bukkit.Material.SNOW_BALL, 64);
|
|
||||||
|
|
||||||
var _gameState = {
|
|
||||||
teams: teams,
|
|
||||||
duration: duration,
|
|
||||||
originalDuration: duration,
|
|
||||||
inProgress: false,
|
|
||||||
teamScores: {},
|
|
||||||
listener: null,
|
|
||||||
savedModes: {},
|
|
||||||
ammo: [_snowBalls]
|
|
||||||
};
|
|
||||||
if (typeof duration == "undefined"){
|
|
||||||
duration = 60;
|
|
||||||
}
|
|
||||||
if (typeof teams == "undefined"){
|
|
||||||
/*
|
|
||||||
wph 20130511 use all players
|
|
||||||
*/
|
|
||||||
teams = [];
|
|
||||||
var players = server.onlinePlayers;
|
|
||||||
for (var i = 0;i < players.length; i++){
|
|
||||||
teams.push(players[i].name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// allow for teams param to be either {red:['player1','player2'],blue:['player3']} or
|
|
||||||
// ['player1','player2','player3'] if all players are against each other (no teams)
|
|
||||||
//
|
|
||||||
if (teams instanceof Array){
|
|
||||||
_gameState.teams = {};
|
|
||||||
for (var i = 0;i < teams.length; i++)
|
|
||||||
_gameState.teams[teams[i]] = [teams[i]];
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
this function is called every time a player is damaged by another entity/player
|
|
||||||
*/
|
|
||||||
var _onSnowballHit = function(l,event){
|
|
||||||
var snowball = event.damager;
|
|
||||||
if (!snowball || !(snowball instanceof org.bukkit.entity.Snowball))
|
|
||||||
return;
|
|
||||||
var throwersTeam = _getTeam(snowball.shooter,_gameState.teams);
|
|
||||||
var damageeTeam = _getTeam(event.entity,_gameState.teams);
|
|
||||||
if (!throwersTeam || !damageeTeam)
|
|
||||||
return; // thrower/damagee wasn't in game
|
|
||||||
if (throwersTeam != damageeTeam)
|
|
||||||
_gameState.teamScores[throwersTeam]++;
|
|
||||||
else
|
|
||||||
_gameState.teamScores[throwersTeam]--;
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
start: function() {
|
|
||||||
_startGame(_gameState);
|
|
||||||
_gameState.listener = events.on('entity.EntityDamageByEntityEvent',_onSnowballHit);
|
|
||||||
new java.lang.Thread(function(){
|
|
||||||
while (_gameState.duration--)
|
|
||||||
java.lang.Thread.sleep(1000); // sleep 1,000 millisecs (1 second)
|
|
||||||
_endGame(_gameState);
|
|
||||||
}).start();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
exports.Game_SnowballFight = createGame;
|
|
||||||
|
|
||||||
|
|
Reference in a new issue