Fix issue #111, reorg of lib/ and (undoc'd) persistence

This commit is contained in:
walterhiggins 2014-01-12 11:26:26 +00:00
parent c77e78c2e5
commit aefc98f172
18 changed files with 514 additions and 106 deletions

View File

@ -7,13 +7,6 @@
<property name="minecraft.dir" location="${dist}/minecraft" />
<property name="js-plugins-dir" value="scriptcraft"/>
<property name="http.agent" value="'Walter'" />
<target name="testy">
<echo message="${http.agent}"/>
<get src="http://dl.bukkit.org/api/1.0/downloads/projects/CraftBukkit/?_accept=application/xml"
verbose="true"
httpusecaches="false"
dest="${minecraft.dir}/waltbukkit.xml" />
</target>
<target name="init">
<property file="build.local.properties"/>
<tstamp>
@ -144,7 +137,7 @@ Walter Higgins
<!-- Put everything in ${build} into the MyProject-${DSTAMP}.jar file -->
<mkdir dir="${dist}/${DSTAMP}" />
<jar jarfile="${dist}/${DSTAMP}/ScriptCraft.jar" basedir="${build}"/>
<jar jarfile="${dist}/${DSTAMP}/scriptcraft.jar" basedir="${build}"/>
</target>
<target name="clean" description="clean up" >
@ -157,6 +150,6 @@ Walter Higgins
<fileset dir="${minecraft.dir}/plugins/" includes="scriptcraft*.*"/>
</delete>
<mkdir dir="${minecraft.dir}/plugins" />
<copy file="${dist}/${DSTAMP}/ScriptCraft.jar" todir="${minecraft.dir}/plugins"/>
<copy file="${dist}/${DSTAMP}/scriptcraft.jar" todir="${minecraft.dir}/plugins"/>
</target>
</project>

View File

@ -117,6 +117,8 @@ Walter Higgins
* [Example Plugin #7 - Listening for events, Greet players when they join the game.](#example-plugin-7---listening-for-events-greet-players-when-they-join-the-game)
* [Arrows Plugin](#arrows-plugin)
* [Usage:](#usage-6)
* [Spawn Plugin](#spawn-plugin)
* [Usage](#usage-7)
* [alias Plugin](#alias-plugin)
* [Examples](#examples-2)
* [Classroom Plugin](#classroom-plugin)
@ -135,6 +137,10 @@ Walter Higgins
* [Example](#example-1)
* [SnowballFight mini-game](#snowballfight-mini-game)
* [Description](#description-2)
* [Cow Clicker Mini-Game](#cow-clicker-mini-game)
* [How to Play](#how-to-play)
* [Rules](#rules)
* [Gameplay Mechanics](#gameplay-mechanics)
## Modules in Scriptcraft
@ -2340,6 +2346,18 @@ All of the above functions can take an optional player object or name
as a parameter. For example: `/js arrows.explosive('player23')` makes
player23's arrows explosive.
## Spawn Plugin
Allows in-game operators to easily spawn creatures at current location.
### Usage
/jsp spawn cow
/jsp spawn sheep
/jsp spawn wolf
See <http://jd.bukkit.org/beta/apidocs/org/bukkit/entity/EntityType.html> for a list of possible entities (creatures) which can be spawned.
## alias Plugin
The alias module lets players and server admins create their own
@ -2621,3 +2639,44 @@ 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.
## Cow Clicker Mini-Game
### How to Play
At the in-game prompt type `jsp cowclicker` to start or stop
playing. Right-Click on Cows to score points. No points for killing
cows (hint: use the same keyboard keys you'd use for opening doors).
Every time you click a cow your score increases by 1 point. Your score
is displayed in a side-bar along the right edge of of the screen.
![cow clicker](img/cowclicker.png)
### Rules
* You can join and leave the Cow Clicker game at any time by typing
`/jsp cowclicker` at the in-game prompt.
* Once you leave the game, your score is reset to zero.
* You can disconnect from the server and your score will be saved for
the next time you join.
### Gameplay Mechanics
This is meant as a trivially simple use of the [Bukkit Scoreboard
API][bukscore]. There are many things you'll want to consider when constructing
your own mini-game...
* Is the game itself a long-lived game - that is - should players and
scores be persisted (stored) between server restarts?
* What should happen when a player quits the server - should this also be
understood as quitting the mini-game?
* What should happen when a player who was previously playing the
mini-game, joins the server - should they automatically resume the
mini-game?
[bukscore]: http://jd.bukkit.org/beta/apidocs/org/bukkit/scoreboard/package-summary.html

View File

@ -35,11 +35,11 @@ using the more succinct...
it is easier to read. The important thing to remember when using the
Bukkit (or any Java API) from Javascript is that for any Java Bean, a
property called `propertyName` will have a getter called
`getPropertyName()` and a setter called `setPropertyName`. From this
`getPropertyName()` and a setter called `setPropertyName()`. From this
rule you can infer what any Bukkit class properties are. For example,
the [Bukkit Player][bukpl] object has the following methods...
* float getWalSpeed()
* float getWalkSpeed()
* void setWalkSpeed(float speed)
... so from this you can infer that every Player object has a
@ -61,7 +61,7 @@ the world in which a player is located...
If you're new to Java and the [Bukkit API][bukapi] is the first time
you've browsed Java documentation, you may be wondering where the
`location` property came from - the `location` property is "inherited"
by one of the Player classes super-classes. You'll see the
from one of the Player class's super-classes (it's ancestors). You'll see the
`getLocation()` method listed under a section titled **Methods
inherited from interface org.bukkit.entity.Entity** in the
[Player][bukpl] javadoc page.

BIN
docs/img/cowclicker.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

View File

@ -1,3 +1,25 @@
# 2014 01 12
## Important
The ScriptCraft.jar file has been renamed scriptcraft.jar (see bug fix
details below). This means that you will have to remove the existing
`plugins/ScriptCraft.jar` file if present.
Bug Fix: On Mac OS, the plugins/scriptcraft directory is copied to
plugins/ScriptCraftPlugin the 2nd time ScriptCraftPlugin is loaded.
This has been fixed by changing the plugin name from ScriptCraftPlugin
to scriptcraft. The jar file has also been rename from
ScriptCraft.jar to scriptcraft.jar.
New command: `jsp spawn` lets in-game operators spawn any type of
entity. For example `/jsp spawn cow` will spawn a cow at the in-game
operator's current location.
New minigame: Cow Clicker. A simple demonstration of using Bukkit's
Scoreboard API. Players click cows to score points. Scores are
displayed in a side bar on screen. Players join or leave the game by
typing `/jsp cowclicker` at the in-game prompt.
# 2014 01 05
Bug Fix: On Mac OS, alias plugin caused Exceptions due to missing

View File

@ -1,5 +1,12 @@
args = args.slice(1);
// wph 20140105 trim not availabe in String on Mac OS.
if (typeof String.prototype.trim == 'undefined'){
String.prototype.trim = function(){
return this.replace(/^\s+|\s+$/g,'');
};
}
var template = args[0];
var BufferedReader = java.io.BufferedReader;

View File

@ -29,7 +29,7 @@ public class ScriptCraftPlugin extends JavaPlugin implements Listener
/**
* Unzips bundled javascript code.
*/
private void unzipJS()
private void unzipJS() throws IOException
{
//
// does the js-plugins directory exist?
@ -37,9 +37,13 @@ public class ScriptCraftPlugin extends JavaPlugin implements Listener
File jsPlugins = new File(JS_PLUGINS_DIR);
if (!jsPlugins.exists())
{
getLogger().finest("Directory " + JS_PLUGINS_DIR + " does not exist.");
getLogger().finest("Initializing " + JS_PLUGINS_DIR + " directory with contents from plugin archive.");
jsPlugins.mkdir();
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));
@ -48,7 +52,7 @@ public class ScriptCraftPlugin extends JavaPlugin implements Listener
while ( ( entry = zis.getNextEntry() ) != null)
{
String filename = entry.getName();
//File newFile = new File(jsPlugins.getName() + File.separator + filename);
File newFile = new File(jsPlugins, filename);
//create all non exists folders
@ -59,17 +63,23 @@ public class ScriptCraftPlugin extends JavaPlugin implements Listener
//
// 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())
if (!newFile.exists()){
reason = "NE";
unzip = true;
}
else{
long fTime = newFile.lastModified();
if (zTime > fTime)
if (zTime > fTime){
reason = "" + new Long((zTime-fTime)/3600000) + "h";
unzip = true;
}
}
if (unzip){
getLogger().info("Unzipping " + newFile.getCanonicalPath());
getLogger().info("Unzipping " + newFile.getCanonicalPath() + " (" + reason + ")" );
FileOutputStream fout = new FileOutputStream(newFile);
for (int c = zis.read(); c != -1; c = zis.read()) {
fout.write(c);
@ -90,9 +100,9 @@ public class ScriptCraftPlugin extends JavaPlugin implements Listener
@Override
public void onEnable()
{
unzipJS();
FileReader reader = null;
try{
unzipJS();
ScriptEngineManager factory = new ScriptEngineManager();
File bootScript = new File(JS_PLUGINS_DIR + "/lib/scriptcraft.js");
this.engine = factory.getEngineByName("JavaScript");
@ -103,6 +113,7 @@ public class ScriptCraftPlugin extends JavaPlugin implements Listener
}catch(Exception e){
e.printStackTrace();
this.getLogger().severe(e.getMessage());
}finally {
if (reader != null){
try {

View File

@ -0,0 +1,33 @@
module.exports = function($){
// wph 20140105 trim not availabe in String on Mac OS.
if (typeof String.prototype.trim == 'undefined'){
String.prototype.trim = function(){
return this.replace(/^\s+|\s+$/g,'');
};
}
$.setTimeout = function( callback, delayInMillis){
/*
javascript programmers familiar with setTimeout know that it expects
a delay in milliseconds. However, bukkit's scheduler expects a delay in ticks
(where 1 tick = 1/20th second)
*/
var bukkitTask = server.scheduler.runTaskLater(__plugin, callback, delayInMillis/50);
return bukkitTask;
};
$.clearTimeout = function(bukkitTask){
bukkitTask.cancel();
};
$.setInterval = function(callback, intervalInMillis){
var delay = intervalInMillis/ 50;
var bukkitTask = server.scheduler.runTaskTimer(__plugin, callback, delay, delay);
return bukkitTask;
};
$.clearInterval = function(bukkitTask){
bukkitTask.cancel();
};
};

View File

@ -0,0 +1,37 @@
var _dataDir = null;
var _persistentData = {};
module.exports = function( rootDir, $ ){
_dataDir = new java.io.File( rootDir, 'data');
$.persist = function(name, data, write){
var i, dataFromFile;
if (typeof data == 'undefined')
data = {};
if (typeof write == 'undefined')
write = false;
if (!write){
dataFromFile = $.load(_dataDir.canonicalPath + '/' + name + '-store.json');
if (dataFromFile){
for (i in dataFromFile){
data[i] = dataFromFile[i];
}
}
}else{
// flush data to file
$.save(data, _dataDir.canonicalPath + '/' + name + '-store.json');
}
_persistentData[name] = data;
return data;
};
$.addUnloadHandler(function(){
for (var name in _persistentData){
var data = _persistentData[name];
$.save(data, _dataDir.canonicalPath + '/' + name + '-store.json');
}
});
};

View File

@ -3,23 +3,6 @@ var console = require('./console');
var File = java.io.File;
var FileWriter = java.io.FileWriter;
var PrintWriter = java.io.PrintWriter;
/*
Save a javascript object to a file (saves using JSON notation)
*/
var _save = function(object, filename){
var objectToStr = null;
try{
objectToStr = JSON.stringify(object,null,2);
}catch(e){
print("ERROR: " + e.getMessage() + " while saving " + filename);
return;
}
var f = (filename instanceof File) ? filename : new File(filename);
var out = new PrintWriter(new FileWriter(f));
out.println( objectToStr );
out.close();
};
/*
plugin management
*/
@ -34,25 +17,18 @@ var _plugin = function(/* String */ moduleName, /* Object */ moduleObject, isPer
return _plugins[moduleName].module;
var pluginData = {persistent: isPersistent, module: moduleObject};
moduleObject.store = moduleObject.store || {};
if (typeof moduleObject.store == 'undefined')
moduleObject.store = {};
_plugins[moduleName] = pluginData;
if (isPersistent){
if (!moduleObject.store){
moduleObject.store = {};
}
var loadedStore = load(dataDir.canonicalPath + "/" + moduleName + "-store.json");
if (loadedStore){
for (var i in loadedStore){
moduleObject.store[i] = loadedStore[i];
}
}
moduleObject.store = persist(moduleName, moduleObject.store);
}
return moduleObject;
};
exports.plugin = _plugin;
exports.save = _save;
var scriptCraftDir = null;
var pluginDir = null;
@ -65,7 +41,7 @@ exports.autoload = function(dir) {
dataDir = new File(dir, "data");
var _canonize = function(file){
return "" + file.getCanonicalPath().replaceAll("\\\\","/");
return '' + file.canonicalPath.replaceAll("\\\\","/");
};
/*
recursively walk the given directory and return a list of all .js files
@ -78,9 +54,7 @@ exports.autoload = function(dir) {
if (file.isDirectory()){
_listSourceFiles(store,file);
}else{
if ((file.getCanonicalPath().endsWith(".js")
|| file.getCanonicalPath().endsWith(".coffee"))
) {
if ( file.canonicalPath.endsWith('.js') ){
store.push(file);
}
}
@ -97,11 +71,11 @@ exports.autoload = function(dir) {
var len = sourceFiles.length;
if (config.verbose)
console.info(len + " scriptcraft plugins found.");
console.info(len + ' scriptcraft plugins found.');
for (var i = 0;i < len; i++){
var pluginPath = _canonize(sourceFiles[i]);
if (config.verbose)
console.info("Loading plugin: " + pluginPath);
console.info('Loading plugin: ' + pluginPath);
var module = {};
try {
module = require(pluginPath);
@ -119,13 +93,3 @@ exports.autoload = function(dir) {
_reload(pluginDir);
};
addUnloadHandler(function(){
//
// save all plugins which have persistent data
//
for (var moduleName in _plugins){
var pluginData = _plugins[moduleName];
if (pluginData.persistent)
_save(pluginData.module.store, dataDir.canonicalPath + "/" + moduleName + "-store.json");
}
});

View File

@ -187,11 +187,12 @@ When resolving module names to file paths, ScriptCraft uses the following rules.
{
var file = resolveModuleToFile(path, parentFile);
if (!file){
var errMsg = java.lang.String
.format("require() failed to find matching file for module '%s' " +
"while searching directory '%s' and paths %s.",
[path, parentFile.canonicalPath, JSON.stringify(modulePaths)]);
console.warn(errMsg);
var errMsg = '' + java.lang.String.format("require() failed to find matching file for module '%s' " +
"in working directory '%s' ", [path, parentFile.canonicalPath]);
if (! ( (''+path).match(/^\./) )){
errMsg = errMsg + ' and not found in paths ' + JSON.stringify(modulePaths);
}
logger.warning(errMsg);
throw new Error(errMsg);
}
var canonizedFilename = _canonize(file);
@ -242,7 +243,7 @@ When resolving module names to file paths, ScriptCraft uses the following rules.
.apply(moduleInfo.exports, /* this */
parameters);
} catch (e){
console.error("Error:" + e + " while executing module " + canonizedFilename);
logger.severe('Error:' + e + ' while executing module ' + canonizedFilename);
throw e;
}
if (verbose)

View File

@ -422,7 +422,9 @@ function __onEnable (__engine, __plugin, __script)
return ;
var File = java.io.File
,FileReader = java.io.FileReader
,BufferedReader = java.io.BufferedReader;
,BufferedReader = java.io.BufferedReader
,PrintWriter = java.io.PrintWriter
,FileWriter = java.io.FileWriter;
var _canonize = function(file){
return "" + file.getCanonicalPath().replaceAll("\\\\","/");
@ -432,6 +434,23 @@ function __onEnable (__engine, __plugin, __script)
var jsPluginsRootDir = libDir.parentFile; // scriptcraft
var jsPluginsRootDirName = _canonize(jsPluginsRootDir);
/*
Save a javascript object to a file (saves using JSON notation)
*/
var _save = function(object, filename){
var objectToStr = null;
try{
objectToStr = JSON.stringify(object,null,2);
}catch(e){
print("ERROR: " + e.getMessage() + " while saving " + filename);
return;
}
var f = (filename instanceof File) ? filename : new File(filename);
var out = new PrintWriter(new FileWriter(f));
out.println( objectToStr );
out.close();
};
var _loaded = {};
/*
Load the contents of the file and evaluate as javascript
@ -487,7 +506,7 @@ function __onEnable (__engine, __plugin, __script)
/*
now that load is defined, use it to load a global config object
*/
var config = _load(new File(jsPluginsRootDir, "data/global-config.json" ));
var config = _load(new File(jsPluginsRootDir, 'data/global-config.json' ));
if (!config)
config = {verbose: false};
global.config = config;
@ -510,27 +529,6 @@ function __onEnable (__engine, __plugin, __script)
}
};
global.setTimeout = function( callback, delayInMillis){
/*
javascript programmers familiar with setTimeout know that it expects
a delay in milliseconds. However, bukkit's scheduler expects a delay in ticks
(where 1 tick = 1/20th second)
*/
var bukkitTask = server.scheduler.runTaskLater(__plugin, callback, delayInMillis/50);
return bukkitTask;
};
global.clearTimeout = function(bukkitTask){
bukkitTask.cancel();
};
global.setInterval = function(callback, intervalInMillis){
var delay = intervalInMillis/ 50;
var bukkitTask = server.scheduler.runTaskTimer(__plugin, callback, delay, delay);
return bukkitTask;
};
global.clearInterval = function(bukkitTask){
bukkitTask.cancel();
};
global.refresh = function(){
__plugin.pluginLoader.disablePlugin(__plugin);
__plugin.pluginLoader.enablePlugin(__plugin);
@ -547,6 +545,7 @@ function __onEnable (__engine, __plugin, __script)
global.echo = _echo;
global.alert = _echo;
global.load = _load;
global.save = _save;
global.addUnloadHandler = _addUnloadHandler;
@ -556,21 +555,30 @@ function __onEnable (__engine, __plugin, __script)
*/
var modulePaths = [jsPluginsRootDirName + '/lib/',
jsPluginsRootDirName + '/modules/'];
global.require = fnRequire(__plugin.logger, __engine, config.verbose, jsPluginsRootDirName, modulePaths);
global.require = fnRequire(__plugin.logger,
__engine,
config.verbose,
jsPluginsRootDirName,
modulePaths);
require('js-patch')(global);
global.console = require('console');
/*
setup persistence
*/
require('persistence')(jsPluginsRootDir,global);
global.command = require('command').command;
var plugins = require('plugin');
global.__onTabComplete = require('tabcomplete');
global.plugin = plugins.plugin;
global.save = plugins.save;
var events = require('events');
events.on('server.PluginDisableEvent',function(l,e){
// save config
plugins.save(global.config, new File(jsPluginsRootDir, "data/global-config.json" ));
save(global.config, new File(jsPluginsRootDir, "data/global-config.json" ));
_runUnloadHandlers();
org.bukkit.event.HandlerList["unregisterAll(org.bukkit.plugin.Plugin)"](__plugin);
@ -625,10 +633,12 @@ function __onEnable (__engine, __plugin, __script)
for (var i = 0; i < legacyDirs.length; i++){
if (legacyDirs[i].exists() && legacyDirs[i].isDirectory()){
legacyExists = true;
console.warn('Legacy ScriptCraft directory ' + legacyDirs[i].canonicalPath + ' was found. This directory is no longer used.');
console.warn('Legacy ScriptCraft directory %s was found. This directory is no longer used.',
legacyDirs[i].canonicalPath);
}
}
if (legacyExists){
console.info('Please note that the working directory for ' + __plugin + ' is ' + jsPluginsRootDir.canonicalPath);
console.info('Please note that the working directory for %s is %s',
__plugin, jsPluginsRootDir.canonicalPath);
}
}

View File

@ -77,9 +77,3 @@ for (var method in formattingCodes){
return function(){return c+this;};
}(formattingCodes[method]);
}
// wph 20140105 trim not availabe in String on Mac OS.
if (!String.prototype.trim){
String.prototype.trim = function(){
return this.replace(/^\s+|\s+$/g,'');
}
}

View File

@ -47,6 +47,7 @@ var classroom = plugin("classroom", {
allowScripting: function (/* boolean: true or false */ canScript, sender) {
if (typeof sender == 'undefined'){
console.log("Attempt to set classroom scripting without credentials");
console.log("classroom.allowScripting(boolean, sender)");
return;
}
if (!sender.op){

View File

@ -15,8 +15,20 @@ Once the game begins, guess a number by typing the `/` character
followed by a number between 1 and 10.
***/
var sb = function(cmd){
org.bukkit.Bukkit.dispatchCommand(server.consoleSender, 'scoreboard ' + cmd)
};
exports.Game_NumberGuess = {
start: function(sender) {
var guesses = 0;
sb('objectives add NumberGuess dummy Guesses');
sb('players set ' + sender.name + ' NumberGuess ' + guesses);
sb('objectives setdisplay sidebar NumberGuess');
importPackage(org.bukkit.conversations);
var number = Math.ceil(Math.random() * 10);
@ -38,6 +50,7 @@ exports.Game_NumberGuess = {
if (s == number){
setTimeout(function(){
ctx.forWhom.sendRawMessage("You guessed Correct!");
sb('objectives remove NumberGuess');
},100);
return null;
}else{
@ -45,6 +58,9 @@ exports.Game_NumberGuess = {
ctx.setSessionData("hint","too low\n");
if (s > number)
ctx.setSessionData("hint","too high\n");
guesses++;
sb('players set ' + sender.name + ' NumberGuess ' + guesses);
return prompt;
}
},

View File

@ -0,0 +1,225 @@
/*************************************************************************
## Cow Clicker Mini-Game
### How to Play
At the in-game prompt type `jsp cowclicker` to start or stop
playing. Right-Click on Cows to score points. No points for killing
cows (hint: use the same keyboard keys you'd use for opening doors).
Every time you click a cow your score increases by 1 point. Your score
is displayed in a side-bar along the right edge of of the screen.
![cow clicker](img/cowclicker.png)
### Rules
* You can join and leave the Cow Clicker game at any time by typing
`/jsp cowclicker` at the in-game prompt.
* Once you leave the game, your score is reset to zero.
* You can disconnect from the server and your score will be saved for
the next time you join.
### Gameplay Mechanics
This is meant as a trivially simple use of the [Bukkit Scoreboard
API][bukscore]. There are many things you'll want to consider when constructing
your own mini-game...
* Is the game itself a long-lived game - that is - should players and
scores be persisted (stored) between server restarts?
* What should happen when a player quits the server - should this also be
understood as quitting the mini-game?
* What should happen when a player who was previously playing the
mini-game, joins the server - should they automatically resume the
mini-game?
[bukscore]: http://jd.bukkit.org/beta/apidocs/org/bukkit/scoreboard/package-summary.html
***/
var store = {};
var scoreboardConfig = {
cowclicker: {SIDEBAR: 'Cows Clicked'}
};
/*
The scoreboard is a simple wrapper around the Bukkit Scoreboard API.
It's only concerned with display of scores, not maintaining them - that's the game's job.
*/
var scoreboard = (function(options){
var temp = {};
var ccScoreboard;
var DisplaySlot = org.bukkit.scoreboard.DisplaySlot;
return {
start: function(){
var objective, slot;
ccScoreboard = server.scoreboardManager.getNewScoreboard();
for (objective in options){
var ccObj = ccScoreboard.registerNewObjective(objective,'dummy');
for (slot in options[objective]){
ccObj.displaySlot = DisplaySlot[slot];
ccObj.displayName = options[objective][slot];
}
}
},
stop: function(){
var objective, slot;
for (objective in options){
ccScoreboard.getObjective(objective).unregister();
for (slot in options[objective]){
ccScoreboard.clearSlot(DisplaySlot[slot]);
}
}
},
update: function(objective,player,score){
if (player.scoreboard && player.scoreboard != ccScoreboard)
{
temp[player.name] = player.scoreboard;
player.scoreboard = ccScoreboard;
}
ccScoreboard.getObjective(objective).getScore(player).score = score;
},
restore: function(player){
// offlineplayers don't have a scoreboard
if (player.scoreboard)
player.scoreboard = temp[player.name];
}
};
}(scoreboardConfig));
var _onPlayerInteract = function(listener, event){
var player = event.player;
var Bukkit = org.bukkit.Bukkit;
if (!store[player.name])
return;
var clickedEntity = event.rightClicked;
var loc = clickedEntity.location;
var sound = function(snd,vol,pitch){
loc.world.playSound(loc,snd,vol,pitch);
};
if (clickedEntity instanceof org.bukkit.entity.Cow)
{
store[player.name].score++;
scoreboard.update('cowclicker', player, store[player.name].score);
Bukkit.dispatchCommand(player, 'me clicked a cow!');
sound(org.bukkit.Sound.CLICK,1,1);
setTimeout(function(){
sound(org.bukkit.Sound.COW_HURT,10,0.85)
},200);
}
};
var _onPlayerQuit = function(listener, event){
_removePlayer(event.player)
};
var _onPlayerJoin = function(listener, event){
var gamePlayer = store[event.player.name];
if (gamePlayer)
_addPlayer(event.player, gamePlayer.score);
};
var _startGame = function(){
if (config.verbose)
console.log('Staring game: Cow Clicker');
events.on('player.PlayerQuitEvent', _onPlayerQuit);
events.on('player.PlayerJoinEvent', _onPlayerJoin);
events.on('player.PlayerInteractEntityEvent', _onPlayerInteract);
scoreboard.start();
store = persist('cowclicker',store);
for (var p in store){
var player = server.getPlayer(p);
if (player){
/*
only add online players
*/
var score = store[p].score;
_addPlayer(player, score);
}
}
};
var _addPlayer = function(player,score){
if (config.verbose)
console.log('Adding player %s to Cow Clicker game',player);
if (typeof score == 'undefined')
score = 0;
store[player.name] = {score: score};
scoreboard.update('cowclicker', player,store[player.name].score);
player.sendMessage('Go forth and click some cows!');
};
var _removePlayer = function(player,notify){
if (player instanceof org.bukkit.OfflinePlayer && player.player)
player = player.player;
if (!store[player.name])
return;
if (config.verbose)
console.log('Removing player %s from Cow Clicker', player);
var playerScore = store[player.name].score;
scoreboard.restore(player);
delete store[player.name];
if (notify && player){
player.sendMessage('You clicked ' + playerScore + ' cows! ' +
'You must be tired after all that clicking.');
}
};
var _removeAllPlayers = function(notify){
if (typeof notify == 'undefined')
notify = false;
for (var p in store){
var player = server.getOfflinePlayer(p);
if (player)
_removePlayer(player,notify);
delete store[p];
}
}
var _stopGame = function(removePlayers){
if (typeof removePlayers == 'undefined')
removePlayers = true;
if (config.verbose)
console.log('Stopping game: Cow Clicker');
scoreboard.stop();
if (!removePlayers)
return;
_removeAllPlayers(false);
persist('cowclicker',store.pers,'w');
};
/*
start the game automatically when this module is loaded.
*/
_startGame();
/*
players can join and leave the game by typing `jsp cowclicker`
*/
command('cowclicker', function(params, sender){
if (!store[sender.name])
_addPlayer(sender);
else
_removePlayer(sender);
});
/*
stop the game when ScriptCraft is unloaded.
*/
addUnloadHandler(function(){
_stopGame(false);
});

View File

@ -0,0 +1,35 @@
/*************************************************************************
## Spawn Plugin
Allows in-game operators to easily spawn creatures at current location.
### Usage
/jsp spawn cow
/jsp spawn sheep
/jsp spawn wolf
This command supports TAB completion so to see a list of possible
entitities, type `/jsp spawn ' at the in-game command prompt, then
press TAB. Visit
<http://jd.bukkit.org/beta/apidocs/org/bukkit/entity/EntityType.html>
for a list of possible entities (creatures) which can be spawned.
***/
var entities = [];
var Types = org.bukkit.entity.EntityType
for (var t in Types){
if (Types[t] && Types[t].ordinal){
entities.push(t);
}
}
command('spawn', function(parameters, sender){
if (!sender.op){
sender.sendMessage('Only operators can perform this command');
return;
}
var location = sender.location;
var world = location.world;
var type = ('' + parameters[0]).toUpperCase();
world.spawnEntity(location, org.bukkit.entity.EntityType[type]);
},entities);

View File

@ -1,4 +1,4 @@
name: ScriptCraftPlugin
name: scriptcraft
main: net.walterhiggins.scriptcraft.ScriptCraftPlugin
version: [[version]]
commands: