added syntax-highlighting to code samples

This commit is contained in:
walterhiggins 2014-02-04 21:36:00 +00:00
parent fe62f61883
commit f1925efd87
7 changed files with 614 additions and 483 deletions

View file

@ -156,21 +156,23 @@ loads the module circle.js in the same directory.
The contents of foo.js:
var circle = require('./circle.js');
console.log( 'The area of a circle of radius 4 is '
+ circle.area(4));
```javascript
var circle = require('./circle.js');
console.log( 'The area of a circle of radius 4 is '
+ circle.area(4));
```
The contents of circle.js:
var PI = Math.PI;
exports.area = function (r) {
return PI * r * r;
};
exports.circumference = function (r) {
return 2 * PI * r;
};
```javascript
var PI = Math.PI;
exports.area = function (r) {
return PI * r * r;
};
exports.circumference = function (r) {
return 2 * PI * r;
};
```
The module circle.js has exported the functions area() and
circumference(). To add functions and objects to the root of your
@ -210,9 +212,11 @@ module in the `plugins` directory exports becomes a global
variable. For example, if you have a module greeting.js in the plugins
directory....
exports.greet = function(player) {
player.sendMessage('Hello ' + player.name);
};
```javascript
exports.greet = function(player) {
player.sendMessage('Hello ' + player.name);
};
```
... then `greet` becomes a global function and can be used at the
in-game (or server) command prompt like so...
@ -400,10 +404,12 @@ restored using the `scload()` function.
#### Example
var myObject = { name: 'John Doe',
aliases: ['John Ray', 'John Mee'],
date_of_birth: '1982/01/31' };
scsave(myObject, 'johndoe.json');
```javascript
var myObject = { name: 'John Doe',
aliases: ['John Ray', 'John Mee'],
date_of_birth: '1982/01/31' };
scsave(myObject, 'johndoe.json');
```
##### johndoe.json contents...
@ -490,13 +496,15 @@ If Node.js supports setTimeout() then it's probably good for ScriptCraft to supp
#### Example
//
// start a storm in 5 seconds
//
setTimeout( function() {
var world = server.worlds.get(0);
world.setStorm(true);
}, 5000);
```javascript
//
// start a storm in 5 seconds
//
setTimeout( function() {
var world = server.worlds.get(0);
world.setStorm(true);
}, 5000);
```
### clearTimeout() function
@ -566,23 +574,29 @@ For example imagine you have 3 files program.js, inc.js and math.js ...
### math.js
exports.add = function(a,b){
return a + b;
}
```javascript
exports.add = function(a,b){
return a + b;
}
```
### inc.js
var math = require('./math');
exports.increment = function(n){
return math.add(n, 1);
}
```javascript
var math = require('./math');
exports.increment = function(n){
return math.add(n, 1);
}
```
### program.js
var inc = require('./inc').increment;
var a = 7;
a = inc(a);
print(a);
```javascript
var inc = require('./inc').increment;
var a = 7;
a = inc(a);
print(a);
```
You can see from the above sample code that programs can use modules
and modules themeselves can use other modules. Modules have full
@ -857,31 +871,38 @@ present in the CraftBukkit classpath. To use this module, you should
craftbukkit-sc-mqtt.bat and edit it to include the following
command...
java -classpath sc-mqtt.jar;craftbukit.jar org.bukkit.craftbukkit.Main
```sh
java -classpath sc-mqtt.jar;craftbukit.jar org.bukkit.craftbukkit.Main
```
If you're using Mac OS, create a new craftbukkit-sc-mqtt.command
file and edit it (using TextWrangler or another text editor) ...
java -classpath sc-mqtt.jar:craftbukkit.jar org.bukit.craftbukkit.Main
```sh
java -classpath sc-mqtt.jar:craftbukkit.jar org.bukit.craftbukkit.Main
```
4. Execute the craftbukkit-sc-mqtt batch file / command file to start
Craftbukkit. You can now begin using this module to send and receive
messages to/from a Net-enabled Arduino or any other device which uses
the [MQTT protocol][mqtt]
var mqtt = require('sc-mqtt');
// create a new client
var client = mqtt.client( 'tcp://localhost:1883', 'uniqueClientId' );
// connect to the broker
client.connect( { keepAliveInterval: 15 } );
// publish a message to the broker
client.publish( 'minecraft', 'loaded' );
// subscribe to messages on 'arduino' topic
client.subscribe( 'arduino' );
// do something when an incoming message arrives...
client.onMessageArrived( function( topic, message ) {
console.log( 'Message arrived: topic=' + topic + ', message=' + message );
});
```javascript
var mqtt = require('sc-mqtt');
// create a new client
var client = mqtt.client( 'tcp://localhost:1883', 'uniqueClientId' );
// connect to the broker
client.connect( { keepAliveInterval: 15 } );
// publish a message to the broker
client.publish( 'minecraft', 'loaded' );
// subscribe to messages on 'arduino' topic
client.subscribe( 'arduino' );
// do something when an incoming message arrives...
client.onMessageArrived( function( topic, message ) {
console.log( 'Message arrived: topic=' + topic + ', message=' + message );
});
```
The `sc-mqtt` module provides a very simple minimal wrapper around the
[Eclipse Paho MQTT Version 3 Client][pahodocs] java-based MQTT
@ -1042,14 +1063,16 @@ String, then it tries to find the player with that name.
#### Example
var utils = require('utils');
var name = 'walterh';
var player = utils.player(name);
if (player) {
player.sendMessage('Got ' + name);
}else{
console.log('No player named ' + name);
}
```javascript
var utils = require('utils');
var name = 'walterh';
var player = utils.player(name);
if ( player ) {
player.sendMessage('Got ' + name);
} else {
console.log('No player named ' + name);
}
```
[bkpl]: http://jd.bukkit.org/dev/apidocs/org/bukkit/entity/Player.html
[bkloc]: http://jd.bukkit.org/dev/apidocs/org/bukkit/Location.html
@ -1087,11 +1110,13 @@ The utils.locationToString() function returns a
keys in a lookup table.
#### Example
var utils = require('utils');
...
var key = utils.locationToString(player.location);
lookupTable[key] = player.name;
```javascript
var utils = require('utils');
...
var key = utils.locationToString(player.location);
lookupTable[key] = player.name;
```
### utils.locationFromJSON() function
@ -1132,12 +1157,14 @@ is the location of the block the player is looking at (targeting).
The following code will strike lightning at the location the player is looking at...
var utils = require('utils');
var playerName = 'walterh';
var targetPos = utils.getMousePos(playerName);
if (targetPos){
targetPos.world.strikeLightning(targetPos);
}
```javascript
var utils = require('utils');
var playerName = 'walterh';
var targetPos = utils.getMousePos(playerName);
if (targetPos){
targetPos.world.strikeLightning(targetPos);
}
```
### utils.foreach() function
@ -1186,42 +1213,48 @@ and put the code there.
The following example illustrates how to use foreach for immediate processing of an array...
var utils = require('utils');
var players = ['moe', 'larry', 'curly'];
utils.foreach (players, function(item){
server.getPlayer(item).sendMessage('Hi ' + item);
});
```javascript
var utils = require('utils');
var players = ['moe', 'larry', 'curly'];
utils.foreach (players, function(item){
server.getPlayer(item).sendMessage('Hi ' + item);
});
```
... The `utils.foreach()` function can work with Arrays or any Java-style collection. This is important
because many objects in the Bukkit API use Java-style collections...
utils.foreach( server.onlinePlayers, function(player){
player.chat('Hello!');
});
```javascript
utils.foreach( server.onlinePlayers, function(player){
player.chat('Hello!');
});
```
... the above code sends a 'Hello!' to every online player.
The following example is a more complex use case - The need to build an enormous structure
without hogging CPU usage...
// build a structure 200 wide x 200 tall x 200 long
// (That's 8 Million Blocks - enough to tax any machine!)
var utils = require('utils');
```javascript
// build a structure 200 wide x 200 tall x 200 long
// (That's 8 Million Blocks - enough to tax any machine!)
var utils = require('utils');
var a = [];
a.length = 200;
var drone = new Drone();
var processItem = function(item, index, object, array){
// build a box 200 wide by 200 long then move up
drone.box(blocks.wood, 200, 1, 200).up();
};
// by the time the job's done 'self' might be someone else
// assume this code is within a function/closure
var player = self;
var onDone = function(){
player.sendMessage('Job Done!');
};
utils.foreach (a, processItem, null, 10, onDone);
var a = [];
a.length = 200;
var drone = new Drone();
var processItem = function(item, index, object, array){
// build a box 200 wide by 200 long then move up
drone.box(blocks.wood, 200, 1, 200).up();
};
// by the time the job's done 'self' might be someone else
// assume this code is within a function/closure
var player = self;
var onDone = function(){
player.sendMessage('Job Done!');
};
utils.foreach (a, processItem, null, 10, onDone);
```
### utils.nicely() function
@ -1262,15 +1295,17 @@ The utils.at() function will perform a given task at a given time every
To warn players when night is approaching...
var utils = require('utils');
```javascript
var utils = require('utils');
utils.at( '19:00', function() {
utils.at( '19:00', function() {
utils.foreach( server.onlinePlayers, function( player ) {
utils.foreach( server.onlinePlayers, function( player ) {
player.chat( 'The night is dark and full of terrors!' );
});
});
});
```
### utils.find() function
@ -1286,10 +1321,12 @@ a given directory and recursiving trawling all sub-directories.
#### Example
var utils = require('utils');
var jsFiles = utils.find('./', function(dir,name){
return name.match(/\.js$/);
});
```javascript
var utils = require('utils');
var jsFiles = utils.find('./', function(dir,name){
return name.match(/\.js$/);
});
```
## Drone Plugin

View file

@ -474,9 +474,11 @@ object can do, let's use that knowledge to create a Minecraft Mod!
Once you've installed Notepad++, Launch it, create a new file and type the following...
exports.greet = function(player){
player.sendMessage('Hi ' + player.name);
}
```javascript
exports.greet = function( player ) {
player.sendMessage('Hi ' + player.name);
}
```
... then save the file in a new directory
`craftbukkit/plugins/scriptcraft/plugins/{your_name}` (replace
@ -514,12 +516,14 @@ one or more functions, objects or variables. For example...
#### thrower.js
exports.egg = function(player){
player.throwEgg();
}
exports.snowball = function(player){
player.throwSnowball();
}
```javascript
exports.egg = function(player){
player.throwEgg();
}
exports.snowball = function(player){
player.throwSnowball();
}
```
... is a plugin which provides 2 javascript functions called `egg()`
and `snowball()` which can be invoked from the in-game prompt like
@ -536,9 +540,11 @@ differently each time it is called.
Change the `greet()` function so that it looks like this...
exports.greet = function ( greeting , player) {
player.sendMessage( greeting + player.name );
}
```javascript
exports.greet = function ( greeting , player) {
player.sendMessage( greeting + player.name );
}
```
... Save your greet.js file and issue the `/js refresh()` command in
minecraft. Now enter the following command in Minecraft...
@ -696,16 +702,20 @@ At the in-game command prompt type the following then hit Enter...
statements on a single line at the in-game command prompt but the
statements could be written like this...
var players = server.onlinePlayers;
for (var i = 0; i < players.length; i++) {
var player = players[i];
player.sendMessage('Hi!');
}
```javascript
var players = server.onlinePlayers;
var player;
var i;
for ( i = 0; i < players.length; i++ ) {
player = players[i];
player.sendMessage( 'Hi!' );
}
```
... On the first line, a new variable `players` is created from the
server object's onlinePlayers property. `players` is more concise and
easier to type than the long-winded `server.onlinePlayers`. On the
second line, the for loop is declared, a counter variable `i` is set
fourth line, the for loop is declared, a counter variable `i` is set
to 0 (zero - arrays in javascript start at 0 not 1) and each time
around the loop is tested to see if it's less than the number of
players online. At the end of each run around the loop the `i`
@ -729,13 +739,17 @@ function. Open the `hi.js` file you created earlier (using NotePad++ ,
TextWrangler or your editor of choice) and add the following code at
the bottom of the file...
exports.hiAll = function (){
var players = server.onlinePlayers;
for (var i = 0; i < players.length; i++) {
var player = players[i];
player.sendMessage('Hi!');
}
```javascript
exports.hiAll = function () {
var players = server.onlinePlayers,
player,
i;
for ( i = 0; i < players.length; i++) {
player = players[i];
player.sendMessage( 'Hi!' );
}
}
```
... save the file, at the in-game command prompt type `reload` and
then type `/js hiAll()`. This will send the message `Hi!` to all of
@ -749,11 +763,13 @@ use `for` loops and Arrays to get things done.
Another way to repeat things over and over is to use a `while`
loop. The following `while` loop counts to 100...
var i = 1;
while (i <= 100){
console.log( i );
i = i + 1;
}
```javascript
var i = 1;
while (i <= 100){
console.log( i );
i = i + 1;
}
```
A `while` loop will repeat until its condition is `false` - the
condition in the above example is `i <= 100` so while i is less than
@ -775,12 +791,14 @@ Just like `for` loops, `while` loops can be also be used to loop
through arrays. The following loop prints out all of the players on
the server...
var players = server.onlinePlayers;
var i = 0;
while ( i < players.length ) {
console.log( players[i] );
i = i + 1;
}
```javascript
var players = server.onlinePlayers;
var i = 0;
while ( i < players.length ) {
console.log( players[i] );
i = i + 1;
}
```
... whether you chose to use a `for` loop or a `while` loop is largely
a matter of personal taste, `for` loops are more commonly used with
@ -814,31 +832,30 @@ above example uses a named function which already exists ( `console.log` ),
you can also create new functions on-the-fly and pass them to the
utils.foreach() function...
/*
give every player the ability to fly.
*/
var utils = require('utils');
utils.foreach( server.onlinePlayers,
function (player) {
player.setAllowFlight(true);
}
);
```javascript
/*
give every player the ability to fly.
*/
var utils = require('utils');
utils.foreach( server.onlinePlayers, function( player ) {
player.setAllowFlight(true);
} );
```
... Another example, this time each player will hear a Cat's Meow...
/*
Play a Cat's Meow sound for each player.
*/
var utils = require('utils');
utils.foreach( server.onlinePlayers,
function (player) {
player.playSound(player.location,
org.bukkit.Sound.CAT_MEOW,
1,
1);
}
);
```javascript
/*
Play a Cat's Meow sound for each player.
*/
var utils = require('utils');
utils.foreach( server.onlinePlayers, function( player ) {
player.playSound(player.location,
org.bukkit.Sound.CAT_MEOW,
1,
1);
} );
```
### Exercise
Try changing the above function so that different sounds are played
@ -873,23 +890,24 @@ loops come in. Open your favorite text editor and create a new file in
your scriptcraft/plugins/{your-name} directory, name the file `myskyscraper.js`, then
type the following...
var myskyscraper = function(floors) {
if (typeof floors == 'undefined'){
floors = 10;
}
this.chkpt('myskyscraper'); // saves the drone position so it can return there later
for (var i = 0; i < floors; i++)
{
this.box(blocks.iron,20,1,20)
.up()
.box0(blocks.glass_pane,20,3,20)
.up(3);
}
return this.move('myskyscraper'); // return to where we started
};
var Drone = require('../drone/drone.js').Drone;
Drone.extend('myskyscraper',myskyscraper);
```javascript
var myskyscraper = function(floors) {
if (typeof floors == 'undefined'){
floors = 10;
}
this.chkpt('myskyscraper'); // saves the drone position so it can return there later
for (var i = 0; i < floors; i++)
{
this.box(blocks.iron,20,1,20)
.up()
.box0(blocks.glass_pane,20,3,20)
.up(3);
}
return this.move('myskyscraper'); // return to where we started
};
var Drone = require('../drone/drone.js').Drone;
Drone.extend('myskyscraper',myskyscraper);
```
... so this takes a little explaining. First I create a new function
called myskyscraper that will take a single parameter `floors` so that
@ -969,17 +987,15 @@ flying or not? This is where the `if - else` construct comes in handy.
Open your favorite editor and type the following code into a new file
in your scriptcraft/plugins directory...
function flightStatus(player)
{
if ( player.flying )
{
player.sendMessage( 'Hey, You are flying!' );
}
else
{
player.sendMessage( 'You are not flying.' );
}
}
```javascript
function flightStatus( player ) {
if ( player.flying ) {
player.sendMessage( 'Hey, You are flying!' );
} else {
player.sendMessage( 'You are not flying.' );
}
}
```
... now type `/reload` at the in-game prompt then type `/js
flightStatus(self)` and an appropriate message will appear based on
@ -1009,10 +1025,12 @@ of event occurs, it's probably best to illustrate this by example. The
following code sends a message to any player who breaks a block in the
game...
events.on('block.BlockBreakEvent', function (listener, event) {
var breaker = event.player;
breaker.sendMessage('You broke a block');
});
```javascript
events.on('block.BlockBreakEvent', function ( listener, event ) {
var breaker = event.player;
breaker.sendMessage('You broke a block');
} );
```
The `events.on()` function is how you *register* a function which you
want to be called whenever a particular type of event occurs. In the
@ -1063,11 +1081,13 @@ just specify the fully qualified class name instead. E.g. ...
If you want an event handler to only execute once, you can remove the handler like this...
events.on('block.BlockBreakEvent', function(listener, evt) {
var breaker = evt.player;
breaker.sendMessage('You broke a block');
evt.handlers.unregister( listener );
});
```javascript
events.on('block.BlockBreakEvent', function( listener, evt ) {
var breaker = evt.player;
breaker.sendMessage('You broke a block');
evt.handlers.unregister( listener );
} );
```
The `evt.handlers.unregister( listener );` statement will remove this
function from the list of listeners for this event.
@ -1121,47 +1141,55 @@ the name column until I find 'jane' then look *across* to get her
score. In Javascript, an object which stored such a table would look
like this...
var scoreboard = {
walter: 5,
tom: 6,
jane: 8,
bart: 7
};
```javascript
var scoreboard = {
walter: 5,
tom: 6,
jane: 8,
bart: 7
};
```
... and if I wanted to write a function which took a player name as a
parameter and returned their score, I'd do it like this...
function getScore(player){
return scoreboard[ player ];
}
```javascript
function getScore(player){
return scoreboard[ player ];
}
```
... I might call such a function like this...
var janesScore = getScore('jane'); // returns 8
```javascript
var janesScore = getScore('jane'); // returns 8
```
... putting it all together, a hypothetical scoreboard.js mdoule might
look something like this...
var utils = require('utils');
var scores = {};
```javascript
var utils = require('utils');
var scores = {};
exports.initialise = function(names){
scores = {};
utils.foreach(names, function(name){
scores[name] = 0;
});
};
exports.initialise = function(names){
scores = {};
utils.foreach(names, function(name){
scores[name] = 0;
});
};
/* changes score by diff e.g. to add 6 to the player's current score
updateScore('walter',6); // walter's new score = 5 + 6 = 11.
*/
exports.updateScore = function(name, diff){
scores[name] += diff;
};
/* changes score by diff e.g. to add 6 to the player's current score
updateScore('walter',6); // walter's new score = 5 + 6 = 11.
*/
exports.updateScore = function(name, diff){
scores[name] += diff;
};
exports.getScore = function(name){
return scores[name];
};
exports.getScore = function(name){
return scores[name];
};
```
## Counting block break events for each player
@ -1170,20 +1198,21 @@ keep a count of how many blocks each player has broken ...
#### block-break-counter.js
var breaks = {};
// every time a player joins the game reset their block-break-count to 0
events.on('player.PlayerJoinEvent', function(listener, event){
breaks[event.player] = 0;
});
events.on('block.BlockBreakEvent', function(listener, event){
var breaker = event.player;
var breakCount = breaks[breaker.name];
breakCount++; // increment the count.
breaks[breaker.name] = breakCount;
breaker.sendMessage('You broke ' + breakCount + ' blocks');
});
```javascript
var breaks = {};
// every time a player joins the game reset their block-break-count to 0
events.on('player.PlayerJoinEvent', function(listener, event){
breaks[event.player] = 0;
});
events.on('block.BlockBreakEvent', function(listener, event){
var breaker = event.player;
var breakCount = breaks[breaker.name];
breakCount++; // increment the count.
breaks[breaker.name] = breakCount;
breaker.sendMessage('You broke ' + breakCount + ' blocks');
});
```
With a little more work, you could turn this into a game where players
compete against each other to break as many blocks as possible within

View file

@ -439,9 +439,11 @@ object can do, let's use that knowledge to create a Minecraft Mod!
Once you've installed Notepad++, Launch it, create a new file and type the following...
exports.greet = function(player){
player.sendMessage('Hi ' + player.name);
}
```javascript
exports.greet = function( player ) {
player.sendMessage('Hi ' + player.name);
}
```
... then save the file in a new directory
`craftbukkit/plugins/scriptcraft/plugins/{your_name}` (replace
@ -479,12 +481,14 @@ one or more functions, objects or variables. For example...
#### thrower.js
exports.egg = function(player){
player.throwEgg();
}
exports.snowball = function(player){
player.throwSnowball();
}
```javascript
exports.egg = function(player){
player.throwEgg();
}
exports.snowball = function(player){
player.throwSnowball();
}
```
... is a plugin which provides 2 javascript functions called `egg()`
and `snowball()` which can be invoked from the in-game prompt like
@ -501,9 +505,11 @@ differently each time it is called.
Change the `greet()` function so that it looks like this...
exports.greet = function ( greeting , player) {
player.sendMessage( greeting + player.name );
}
```javascript
exports.greet = function ( greeting , player) {
player.sendMessage( greeting + player.name );
}
```
... Save your greet.js file and issue the `/js refresh()` command in
minecraft. Now enter the following command in Minecraft...
@ -661,16 +667,20 @@ At the in-game command prompt type the following then hit Enter...
statements on a single line at the in-game command prompt but the
statements could be written like this...
var players = server.onlinePlayers;
for (var i = 0; i < players.length; i++) {
var player = players[i];
player.sendMessage('Hi!');
}
```javascript
var players = server.onlinePlayers;
var player;
var i;
for ( i = 0; i < players.length; i++ ) {
player = players[i];
player.sendMessage( 'Hi!' );
}
```
... On the first line, a new variable `players` is created from the
server object's onlinePlayers property. `players` is more concise and
easier to type than the long-winded `server.onlinePlayers`. On the
second line, the for loop is declared, a counter variable `i` is set
fourth line, the for loop is declared, a counter variable `i` is set
to 0 (zero - arrays in javascript start at 0 not 1) and each time
around the loop is tested to see if it's less than the number of
players online. At the end of each run around the loop the `i`
@ -694,13 +704,17 @@ function. Open the `hi.js` file you created earlier (using NotePad++ ,
TextWrangler or your editor of choice) and add the following code at
the bottom of the file...
exports.hiAll = function (){
var players = server.onlinePlayers;
for (var i = 0; i < players.length; i++) {
var player = players[i];
player.sendMessage('Hi!');
}
```javascript
exports.hiAll = function () {
var players = server.onlinePlayers,
player,
i;
for ( i = 0; i < players.length; i++) {
player = players[i];
player.sendMessage( 'Hi!' );
}
}
```
... save the file, at the in-game command prompt type `reload` and
then type `/js hiAll()`. This will send the message `Hi!` to all of
@ -714,11 +728,13 @@ use `for` loops and Arrays to get things done.
Another way to repeat things over and over is to use a `while`
loop. The following `while` loop counts to 100...
var i = 1;
while (i <= 100){
console.log( i );
i = i + 1;
}
```javascript
var i = 1;
while (i <= 100){
console.log( i );
i = i + 1;
}
```
A `while` loop will repeat until its condition is `false` - the
condition in the above example is `i <= 100` so while i is less than
@ -740,12 +756,14 @@ Just like `for` loops, `while` loops can be also be used to loop
through arrays. The following loop prints out all of the players on
the server...
var players = server.onlinePlayers;
var i = 0;
while ( i < players.length ) {
console.log( players[i] );
i = i + 1;
}
```javascript
var players = server.onlinePlayers;
var i = 0;
while ( i < players.length ) {
console.log( players[i] );
i = i + 1;
}
```
... whether you chose to use a `for` loop or a `while` loop is largely
a matter of personal taste, `for` loops are more commonly used with
@ -779,31 +797,30 @@ above example uses a named function which already exists ( `console.log` ),
you can also create new functions on-the-fly and pass them to the
utils.foreach() function...
/*
give every player the ability to fly.
*/
var utils = require('utils');
utils.foreach( server.onlinePlayers,
function (player) {
player.setAllowFlight(true);
}
);
```javascript
/*
give every player the ability to fly.
*/
var utils = require('utils');
utils.foreach( server.onlinePlayers, function( player ) {
player.setAllowFlight(true);
} );
```
... Another example, this time each player will hear a Cat's Meow...
/*
Play a Cat's Meow sound for each player.
*/
var utils = require('utils');
utils.foreach( server.onlinePlayers,
function (player) {
player.playSound(player.location,
org.bukkit.Sound.CAT_MEOW,
1,
1);
}
);
```javascript
/*
Play a Cat's Meow sound for each player.
*/
var utils = require('utils');
utils.foreach( server.onlinePlayers, function( player ) {
player.playSound(player.location,
org.bukkit.Sound.CAT_MEOW,
1,
1);
} );
```
### Exercise
Try changing the above function so that different sounds are played
@ -838,23 +855,24 @@ loops come in. Open your favorite text editor and create a new file in
your scriptcraft/plugins/{your-name} directory, name the file `myskyscraper.js`, then
type the following...
var myskyscraper = function(floors) {
if (typeof floors == 'undefined'){
floors = 10;
}
this.chkpt('myskyscraper'); // saves the drone position so it can return there later
for (var i = 0; i < floors; i++)
{
this.box(blocks.iron,20,1,20)
.up()
.box0(blocks.glass_pane,20,3,20)
.up(3);
}
return this.move('myskyscraper'); // return to where we started
};
var Drone = require('../drone/drone.js').Drone;
Drone.extend('myskyscraper',myskyscraper);
```javascript
var myskyscraper = function(floors) {
if (typeof floors == 'undefined'){
floors = 10;
}
this.chkpt('myskyscraper'); // saves the drone position so it can return there later
for (var i = 0; i < floors; i++)
{
this.box(blocks.iron,20,1,20)
.up()
.box0(blocks.glass_pane,20,3,20)
.up(3);
}
return this.move('myskyscraper'); // return to where we started
};
var Drone = require('../drone/drone.js').Drone;
Drone.extend('myskyscraper',myskyscraper);
```
... so this takes a little explaining. First I create a new function
called myskyscraper that will take a single parameter `floors` so that
@ -934,17 +952,15 @@ flying or not? This is where the `if - else` construct comes in handy.
Open your favorite editor and type the following code into a new file
in your scriptcraft/plugins directory...
function flightStatus(player)
{
if ( player.flying )
{
player.sendMessage( 'Hey, You are flying!' );
}
else
{
player.sendMessage( 'You are not flying.' );
}
}
```javascript
function flightStatus( player ) {
if ( player.flying ) {
player.sendMessage( 'Hey, You are flying!' );
} else {
player.sendMessage( 'You are not flying.' );
}
}
```
... now type `/reload` at the in-game prompt then type `/js
flightStatus(self)` and an appropriate message will appear based on
@ -974,10 +990,12 @@ of event occurs, it's probably best to illustrate this by example. The
following code sends a message to any player who breaks a block in the
game...
events.on('block.BlockBreakEvent', function (listener, event) {
var breaker = event.player;
breaker.sendMessage('You broke a block');
});
```javascript
events.on('block.BlockBreakEvent', function ( listener, event ) {
var breaker = event.player;
breaker.sendMessage('You broke a block');
} );
```
The `events.on()` function is how you *register* a function which you
want to be called whenever a particular type of event occurs. In the
@ -1028,11 +1046,13 @@ just specify the fully qualified class name instead. E.g. ...
If you want an event handler to only execute once, you can remove the handler like this...
events.on('block.BlockBreakEvent', function(listener, evt) {
var breaker = evt.player;
breaker.sendMessage('You broke a block');
evt.handlers.unregister( listener );
});
```javascript
events.on('block.BlockBreakEvent', function( listener, evt ) {
var breaker = evt.player;
breaker.sendMessage('You broke a block');
evt.handlers.unregister( listener );
} );
```
The `evt.handlers.unregister( listener );` statement will remove this
function from the list of listeners for this event.
@ -1086,47 +1106,55 @@ the name column until I find 'jane' then look *across* to get her
score. In Javascript, an object which stored such a table would look
like this...
var scoreboard = {
walter: 5,
tom: 6,
jane: 8,
bart: 7
};
```javascript
var scoreboard = {
walter: 5,
tom: 6,
jane: 8,
bart: 7
};
```
... and if I wanted to write a function which took a player name as a
parameter and returned their score, I'd do it like this...
function getScore(player){
return scoreboard[ player ];
}
```javascript
function getScore(player){
return scoreboard[ player ];
}
```
... I might call such a function like this...
var janesScore = getScore('jane'); // returns 8
```javascript
var janesScore = getScore('jane'); // returns 8
```
... putting it all together, a hypothetical scoreboard.js mdoule might
look something like this...
var utils = require('utils');
var scores = {};
```javascript
var utils = require('utils');
var scores = {};
exports.initialise = function(names){
scores = {};
utils.foreach(names, function(name){
scores[name] = 0;
});
};
exports.initialise = function(names){
scores = {};
utils.foreach(names, function(name){
scores[name] = 0;
});
};
/* changes score by diff e.g. to add 6 to the player's current score
updateScore('walter',6); // walter's new score = 5 + 6 = 11.
*/
exports.updateScore = function(name, diff){
scores[name] += diff;
};
/* changes score by diff e.g. to add 6 to the player's current score
updateScore('walter',6); // walter's new score = 5 + 6 = 11.
*/
exports.updateScore = function(name, diff){
scores[name] += diff;
};
exports.getScore = function(name){
return scores[name];
};
exports.getScore = function(name){
return scores[name];
};
```
## Counting block break events for each player
@ -1135,20 +1163,21 @@ keep a count of how many blocks each player has broken ...
#### block-break-counter.js
var breaks = {};
// every time a player joins the game reset their block-break-count to 0
events.on('player.PlayerJoinEvent', function(listener, event){
breaks[event.player] = 0;
});
events.on('block.BlockBreakEvent', function(listener, event){
var breaker = event.player;
var breakCount = breaks[breaker.name];
breakCount++; // increment the count.
breaks[breaker.name] = breakCount;
breaker.sendMessage('You broke ' + breakCount + ' blocks');
});
```javascript
var breaks = {};
// every time a player joins the game reset their block-break-count to 0
events.on('player.PlayerJoinEvent', function(listener, event){
breaks[event.player] = 0;
});
events.on('block.BlockBreakEvent', function(listener, event){
var breaker = event.player;
var breakCount = breaks[breaker.name];
breakCount++; // increment the count.
breaks[breaker.name] = breakCount;
breaker.sendMessage('You broke ' + breakCount + ' blocks');
});
```
With a little more work, you could turn this into a game where players
compete against each other to break as many blocks as possible within

View file

@ -18,23 +18,29 @@ For example imagine you have 3 files program.js, inc.js and math.js ...
### math.js
exports.add = function(a,b){
return a + b;
}
```javascript
exports.add = function(a,b){
return a + b;
}
```
### inc.js
var math = require('./math');
exports.increment = function(n){
return math.add(n, 1);
}
```javascript
var math = require('./math');
exports.increment = function(n){
return math.add(n, 1);
}
```
### program.js
var inc = require('./inc').increment;
var a = 7;
a = inc(a);
print(a);
```javascript
var inc = require('./inc').increment;
var a = 7;
a = inc(a);
print(a);
```
You can see from the above sample code that programs can use modules
and modules themeselves can use other modules. Modules have full

View file

@ -12,21 +12,23 @@ loads the module circle.js in the same directory.
The contents of foo.js:
var circle = require('./circle.js');
console.log( 'The area of a circle of radius 4 is '
+ circle.area(4));
```javascript
var circle = require('./circle.js');
console.log( 'The area of a circle of radius 4 is '
+ circle.area(4));
```
The contents of circle.js:
var PI = Math.PI;
exports.area = function (r) {
return PI * r * r;
};
exports.circumference = function (r) {
return 2 * PI * r;
};
```javascript
var PI = Math.PI;
exports.area = function (r) {
return PI * r * r;
};
exports.circumference = function (r) {
return 2 * PI * r;
};
```
The module circle.js has exported the functions area() and
circumference(). To add functions and objects to the root of your
@ -66,9 +68,11 @@ module in the `plugins` directory exports becomes a global
variable. For example, if you have a module greeting.js in the plugins
directory....
exports.greet = function(player) {
player.sendMessage('Hello ' + player.name);
};
```javascript
exports.greet = function(player) {
player.sendMessage('Hello ' + player.name);
};
```
... then `greet` becomes a global function and can be used at the
in-game (or server) command prompt like so...
@ -256,10 +260,12 @@ restored using the `scload()` function.
#### Example
var myObject = { name: 'John Doe',
aliases: ['John Ray', 'John Mee'],
date_of_birth: '1982/01/31' };
scsave(myObject, 'johndoe.json');
```javascript
var myObject = { name: 'John Doe',
aliases: ['John Ray', 'John Mee'],
date_of_birth: '1982/01/31' };
scsave(myObject, 'johndoe.json');
```
##### johndoe.json contents...
@ -346,13 +352,15 @@ If Node.js supports setTimeout() then it's probably good for ScriptCraft to supp
#### Example
//
// start a storm in 5 seconds
//
setTimeout( function() {
var world = server.worlds.get(0);
world.setStorm(true);
}, 5000);
```javascript
//
// start a storm in 5 seconds
//
setTimeout( function() {
var world = server.worlds.get(0);
world.setStorm(true);
}, 5000);
```
### clearTimeout() function
@ -477,7 +485,6 @@ function __onEnable ( __engine, __plugin, __script )
var canonizedFilename = _canonize( file );
if ( file.exists() ) {
parent = file.getParentFile();
reader = new FileReader( file );
br = new BufferedReader( reader );
code = '';

View file

@ -17,31 +17,38 @@ present in the CraftBukkit classpath. To use this module, you should
craftbukkit-sc-mqtt.bat and edit it to include the following
command...
java -classpath sc-mqtt.jar;craftbukit.jar org.bukkit.craftbukkit.Main
```sh
java -classpath sc-mqtt.jar;craftbukit.jar org.bukkit.craftbukkit.Main
```
If you're using Mac OS, create a new craftbukkit-sc-mqtt.command
file and edit it (using TextWrangler or another text editor) ...
java -classpath sc-mqtt.jar:craftbukkit.jar org.bukit.craftbukkit.Main
```sh
java -classpath sc-mqtt.jar:craftbukkit.jar org.bukit.craftbukkit.Main
```
4. Execute the craftbukkit-sc-mqtt batch file / command file to start
Craftbukkit. You can now begin using this module to send and receive
messages to/from a Net-enabled Arduino or any other device which uses
the [MQTT protocol][mqtt]
var mqtt = require('sc-mqtt');
// create a new client
var client = mqtt.client( 'tcp://localhost:1883', 'uniqueClientId' );
// connect to the broker
client.connect( { keepAliveInterval: 15 } );
// publish a message to the broker
client.publish( 'minecraft', 'loaded' );
// subscribe to messages on 'arduino' topic
client.subscribe( 'arduino' );
// do something when an incoming message arrives...
client.onMessageArrived( function( topic, message ) {
console.log( 'Message arrived: topic=' + topic + ', message=' + message );
});
```javascript
var mqtt = require('sc-mqtt');
// create a new client
var client = mqtt.client( 'tcp://localhost:1883', 'uniqueClientId' );
// connect to the broker
client.connect( { keepAliveInterval: 15 } );
// publish a message to the broker
client.publish( 'minecraft', 'loaded' );
// subscribe to messages on 'arduino' topic
client.subscribe( 'arduino' );
// do something when an incoming message arrives...
client.onMessageArrived( function( topic, message ) {
console.log( 'Message arrived: topic=' + topic + ', message=' + message );
});
```
The `sc-mqtt` module provides a very simple minimal wrapper around the
[Eclipse Paho MQTT Version 3 Client][pahodocs] java-based MQTT

View file

@ -22,14 +22,16 @@ String, then it tries to find the player with that name.
#### Example
var utils = require('utils');
var name = 'walterh';
var player = utils.player(name);
if (player) {
player.sendMessage('Got ' + name);
}else{
console.log('No player named ' + name);
}
```javascript
var utils = require('utils');
var name = 'walterh';
var player = utils.player(name);
if ( player ) {
player.sendMessage('Got ' + name);
} else {
console.log('No player named ' + name);
}
```
[bkpl]: http://jd.bukkit.org/dev/apidocs/org/bukkit/entity/Player.html
[bkloc]: http://jd.bukkit.org/dev/apidocs/org/bukkit/Location.html
@ -95,11 +97,13 @@ The utils.locationToString() function returns a
keys in a lookup table.
#### Example
var utils = require('utils');
...
var key = utils.locationToString(player.location);
lookupTable[key] = player.name;
```javascript
var utils = require('utils');
...
var key = utils.locationToString(player.location);
lookupTable[key] = player.name;
```
***/
exports.locationToString = function( location ) {
@ -179,12 +183,14 @@ is the location of the block the player is looking at (targeting).
The following code will strike lightning at the location the player is looking at...
var utils = require('utils');
var playerName = 'walterh';
var targetPos = utils.getMousePos(playerName);
if (targetPos){
targetPos.world.strikeLightning(targetPos);
}
```javascript
var utils = require('utils');
var playerName = 'walterh';
var targetPos = utils.getMousePos(playerName);
if (targetPos){
targetPos.world.strikeLightning(targetPos);
}
```
***/
exports.getMousePos = function( player ) {
@ -251,42 +257,48 @@ and put the code there.
The following example illustrates how to use foreach for immediate processing of an array...
var utils = require('utils');
var players = ['moe', 'larry', 'curly'];
utils.foreach (players, function(item){
server.getPlayer(item).sendMessage('Hi ' + item);
});
```javascript
var utils = require('utils');
var players = ['moe', 'larry', 'curly'];
utils.foreach (players, function(item){
server.getPlayer(item).sendMessage('Hi ' + item);
});
```
... The `utils.foreach()` function can work with Arrays or any Java-style collection. This is important
because many objects in the Bukkit API use Java-style collections...
utils.foreach( server.onlinePlayers, function(player){
player.chat('Hello!');
});
```javascript
utils.foreach( server.onlinePlayers, function(player){
player.chat('Hello!');
});
```
... the above code sends a 'Hello!' to every online player.
The following example is a more complex use case - The need to build an enormous structure
without hogging CPU usage...
// build a structure 200 wide x 200 tall x 200 long
// (That's 8 Million Blocks - enough to tax any machine!)
var utils = require('utils');
```javascript
// build a structure 200 wide x 200 tall x 200 long
// (That's 8 Million Blocks - enough to tax any machine!)
var utils = require('utils');
var a = [];
a.length = 200;
var drone = new Drone();
var processItem = function(item, index, object, array){
// build a box 200 wide by 200 long then move up
drone.box(blocks.wood, 200, 1, 200).up();
};
// by the time the job's done 'self' might be someone else
// assume this code is within a function/closure
var player = self;
var onDone = function(){
player.sendMessage('Job Done!');
};
utils.foreach (a, processItem, null, 10, onDone);
var a = [];
a.length = 200;
var drone = new Drone();
var processItem = function(item, index, object, array){
// build a box 200 wide by 200 long then move up
drone.box(blocks.wood, 200, 1, 200).up();
};
// by the time the job's done 'self' might be someone else
// assume this code is within a function/closure
var player = self;
var onDone = function(){
player.sendMessage('Job Done!');
};
utils.foreach (a, processItem, null, 10, onDone);
```
***/
var _foreach = function( array, callback, context, delay, onCompletion ) {
@ -366,15 +378,17 @@ The utils.at() function will perform a given task at a given time every
To warn players when night is approaching...