Comparing version 0.0.6 to 0.1.0
303
lib/index.js
/** | ||
* @overview AdvTxt is a text adventure engine, written in Javascript on Node.js | ||
* and using MongoDB as its backing store. | ||
* @overview AdvTxt is a text adventure engine, written in Javascript on Node.js. | ||
* | ||
* @author Nathan Wittstock <code@fardogllc.com> | ||
* @license MIT License - See file 'LICENSE' in this project. | ||
* @version 0.0.6 | ||
* @version 0.1.0 | ||
* @extends EventEmitter | ||
@@ -12,10 +11,10 @@ */ | ||
var natural = require('natural'); | ||
var i18n = new (require('i18n-2'))({ locales: ['en']}); | ||
var _ = require('underscore'); | ||
var Hoek = require('hoek'); | ||
var tokenizer = new natural.WordTokenizer(); | ||
var Parser = require('./parser'); | ||
var events = require('events'); | ||
var util = require('util'); | ||
var async = require('async'); | ||
var debug = require('debug')('advtxt'); | ||
@@ -78,8 +77,7 @@ var advtxt = {}; | ||
* | ||
* @since 0.0.1 | ||
* @param {command} command - The command object. | ||
* @since 0.1.0 | ||
* @param {string} direction - A string representation of the direction we're | ||
* moving in. | ||
*/ | ||
advtxt.Server.prototype.movePlayer = function(command, direction) { | ||
advtxt.Server.prototype.calculateMove = function(direction) { | ||
var self = this; | ||
@@ -101,7 +99,3 @@ | ||
// now we apply those moves to the player object | ||
command.player.x += move[0]; | ||
command.player.y += move[1]; | ||
// now we need to update the player in the database | ||
self.updatePlayerPosition(command, self.getCurrentLocation.bind(self)); | ||
return move; | ||
} | ||
@@ -116,4 +110,5 @@ | ||
* @param {boolean} clearItems - Should we clear their items or not? | ||
* @param {advTxtCallback} next - Function to call next | ||
*/ | ||
advtxt.Server.prototype.resetPlayer = function(command, clearItems) { | ||
advtxt.Server.prototype.resetPlayer = function(command, clearItems, next) { | ||
var self = this; | ||
@@ -126,2 +121,3 @@ | ||
command.player.status = "alive"; | ||
command.move = true; | ||
@@ -131,2 +127,3 @@ // output a different message if we're just moving, or if fully resetting | ||
command.player.items = {}; // clear the player's items array | ||
command.items = true; | ||
self.reply(command, i18n.__("Giving you a blank slate…")); | ||
@@ -138,17 +135,23 @@ } | ||
debug('Now resetting player.'); | ||
// first we need to reset their position | ||
self.updatePlayerPosition(command, function(command) { | ||
self.updatePlayerPosition(command, function(err, command) { | ||
var self = this; | ||
debug('Position reset.'); | ||
// the position has been reset. Clear their items if requested. | ||
if (clearItems) { | ||
self.updatePlayerItems(command, self.getCurrentLocation.bind(self)); | ||
} | ||
// otherwise, call the current location function to let the player know | ||
// where they are | ||
else { | ||
self.getCurrentLocation(command, true); | ||
} | ||
self.updatePlayerItems(command, function(err, command) { | ||
debug('Items cleared.'); | ||
next(null, command); | ||
}); | ||
}.bind(self)); | ||
} | ||
/** | ||
* Standard callback for AdvTxt | ||
* | ||
* @since 0.1.0 | ||
* @callback advTxtCallback | ||
* @param {Error} err - Error object if there was one, else null. | ||
* @param {command} command - The command object. | ||
*/ | ||
@@ -160,3 +163,3 @@ /** | ||
* @param {command} command - The representation of a command. | ||
* @param {updatePlayerCallback} next - The callback to be executed after the update. | ||
* @param {advTxtCallback} next | ||
*/ | ||
@@ -166,14 +169,18 @@ advtxt.Server.prototype.updatePlayerPosition = function(command, next) { | ||
var selector = {_id: command.player._id}; | ||
var data = {x: command.player.x, y: command.player.y}; | ||
self.db.update('player', selector, data, function(err, success){ | ||
// if we were successful, lets update their location and send a response | ||
if (success) { | ||
if(typeof next !== 'undefined' && next) next(command, true); | ||
} | ||
else { | ||
if(typeof next !== 'undefined' && next) next(false); | ||
} | ||
}.bind(self)); | ||
debug("Updating Position"); | ||
var selector = {_id: command.player._id}; | ||
var data = {x: command.player.x, y: command.player.y}; | ||
self.db.update('player', selector, data, function(err, success){ | ||
if (err) next(err, command); | ||
// if we were successful, lets update their location and send a response | ||
if (!success) { | ||
console.error("Couldn't update player position."); | ||
console.error(command.player); | ||
} | ||
debug("Successfully updated position."); | ||
next(null, command); | ||
}.bind(self)); | ||
} | ||
@@ -186,4 +193,3 @@ | ||
* @param {command} command - The command object | ||
* @param {updatePlayerCallback} next - The optional callback to be executed | ||
* after the update. | ||
* @param {advTxtCallback} next | ||
*/ | ||
@@ -196,21 +202,14 @@ advtxt.Server.prototype.updatePlayerItems = function(command, next) { | ||
self.db.update('player', selector, data, function(err, success) { | ||
// the player is saved, do nothing unless there's an error | ||
if (!success) { | ||
console.error("Couldn't save player: " + command.player.username); | ||
console.error(command.player); | ||
} | ||
if (typeof next !== 'undefined' && next) next(command, true); | ||
}.bind(self)); | ||
} | ||
self.db.update('player', selector, data, function(err, success) { | ||
if (err) next(err, command); | ||
/** | ||
* This callback runs after the player is updated. | ||
* | ||
* @since 0.0.1 | ||
* @callback updatePlayerCallback | ||
* @param {command} The command object | ||
* @param {boolean} whether to send output | ||
*/ | ||
// the player is saved, do nothing unless there's an error | ||
if (!success) { | ||
console.error("Couldn't save player: " + command.player.username); | ||
console.error(command.player); | ||
} | ||
next(null, command); | ||
}.bind(self)); | ||
} | ||
@@ -222,4 +221,3 @@ /** | ||
* @param {command} command - The command object | ||
* @param {updatePlayerCallback} next - The optional callback to be | ||
* executed after the update. | ||
* @param {advTxtCallback} next | ||
*/ | ||
@@ -233,2 +231,4 @@ advtxt.Server.prototype.updatePlayerStatus = function(command, next) { | ||
self.db.update('player', selector, data, function(err, success) { | ||
if (err) next(err, command); | ||
if (!success) { | ||
@@ -238,3 +238,4 @@ console.error("Couldn't save player: " + command.player.username); | ||
} | ||
if (typeof next !== 'undefined' && next) next(command, true); | ||
if (typeof next === 'function' && next) next(null, command); | ||
}.bind(self)); | ||
@@ -249,4 +250,5 @@ } | ||
* @param {command} command - The command object | ||
* @param {advTxtCallback} next | ||
*/ | ||
advtxt.Server.prototype.doCommand = function(command) { | ||
advtxt.Server.prototype.doCommand = function(command, next) { | ||
var self = this; | ||
@@ -259,3 +261,3 @@ | ||
else { | ||
self.reply(command, __.i18n("I don't know what you mean.")); | ||
next(new Error(__.i18n("I don't know what you mean.")), command); | ||
} | ||
@@ -270,13 +272,20 @@ | ||
// if we've already performed the command | ||
if (command.performed) { | ||
next(null, command); | ||
} | ||
// set the command as performed | ||
command.performed = true; | ||
// we need to check for reset commands first, so we don't ignore them from a | ||
// dead player | ||
if (verb === commands.RESET && object === '') { | ||
self.resetPlayer(command, false); | ||
self.resetPlayer(command, false, next); | ||
return; | ||
} | ||
else if (verb === commands.RESET && object === i18n.__('all')) { | ||
self.resetPlayer(command, true); | ||
self.resetPlayer(command, true, next); | ||
return; | ||
} | ||
else if (player.status === 'dead' || player.status === 'win') { | ||
self.finalize(command); | ||
} | ||
else if (verb === commands.GET) { | ||
@@ -290,4 +299,4 @@ // would try to get an item | ||
self.reply(command, room.items[object].get(player)); | ||
// update the player | ||
self.updatePlayerItems(command, self.finalize.bind(self)); | ||
// set the player's items as changed | ||
command.items = true; | ||
} | ||
@@ -297,3 +306,2 @@ // that item wasn't available | ||
self.reply(command, available); | ||
self.finalize(command); | ||
} | ||
@@ -304,3 +312,2 @@ } | ||
self.reply(command, i18n.__('You can\'t find a "%s" in this room!', object)); | ||
self.finalize(command); | ||
} | ||
@@ -315,4 +322,13 @@ } | ||
self.reply(command, room.exits[object].go(player)); | ||
// move the player | ||
self.movePlayer(command, object); | ||
// set the player to be moved | ||
var move = self.calculateMove(object); | ||
command.player.x += move[0]; | ||
command.player.y += move[1]; | ||
command.move = true; | ||
// set the room to be announced | ||
command.announceRoom = true; | ||
} | ||
@@ -322,3 +338,2 @@ // that direction wasn't available; give the reason | ||
self.reply(command, available); | ||
self.finalize(command); | ||
} | ||
@@ -330,3 +345,2 @@ } | ||
self.reply(command, i18n.__('You can\'t go "%s", it just doesn\'t work.', object)); | ||
self.finalize(command); | ||
} | ||
@@ -337,3 +351,2 @@ } | ||
self.reply(command, room.commands[verb](player)); | ||
self.finalize(command); | ||
} | ||
@@ -353,8 +366,8 @@ // if they asked for the exits, list them | ||
self.reply(command, exitNames); | ||
self.finalize(command); | ||
} | ||
else { | ||
self.reply(command, i18n.__('Sorry, I don\'t know how to "%s" in this room.', verb)); | ||
self.finalize(command); | ||
} | ||
next(null, command); | ||
} | ||
@@ -368,6 +381,5 @@ | ||
* @param {command} command - The command object. | ||
* @param {boolean} enterRoom - If the player has just entered the room, we need | ||
* to play them an entrance message. | ||
* @param {advTxtCallback} next | ||
*/ | ||
advtxt.Server.prototype.getCurrentLocation = function(command, enterRoom) { | ||
advtxt.Server.prototype.getCurrentLocation = function(command, next) { | ||
var self = this; | ||
@@ -381,3 +393,3 @@ | ||
self.db.findOne('room', {x: command.player.x, y: command.player.y, map: command.player.map}, function (err, room) { | ||
if (err) throw err; | ||
if (err) next(err, command); | ||
@@ -400,10 +412,8 @@ if (room) { | ||
// just exit afterward. | ||
if (enterRoom) { | ||
if (command.announceRoom) { | ||
command.announceRoom = false; | ||
self.reply(command, player.room.description); | ||
self.finalize(command); | ||
} | ||
// otherwise, process the command that was given | ||
else { | ||
self.doCommand(command); | ||
} | ||
next(null, command); | ||
} | ||
@@ -414,17 +424,17 @@ }); | ||
/** | ||
* Get the user that is addressed in the command, and inserts that information | ||
* into the command. | ||
* Gets the player that is addressed in the command. | ||
* | ||
* @since 0.0.1 | ||
* @since 0.1.0 | ||
* @param {command} command - The command object. | ||
* @param {advTxtCallback} next | ||
*/ | ||
advtxt.Server.prototype.processCommand = function(command) { | ||
var self = this; | ||
advtxt.Server.prototype.getPlayer = function(command, next) { | ||
var self = this; | ||
self.db.findOne('player', {username: command.player, map: "default"}, function(err, player) { | ||
if (err) throw err; | ||
self.db.findOne('player', {username: command.player, map: "default"}, function(err, player) { | ||
if (err) next(err, command); | ||
if (player) { | ||
command.player = player; | ||
self.getCurrentLocation(command); | ||
next(null, command); | ||
} | ||
@@ -444,6 +454,63 @@ else { | ||
command.player = player; | ||
self.getCurrentLocation(command, true); | ||
command.announceRoom = true; | ||
next(null, command); | ||
}); | ||
} | ||
}); | ||
}; | ||
/** | ||
* Takes a raw command and runs it through the AdvTxt engine. | ||
* | ||
* @since 0.0.1 | ||
* @param {command} command - The command object. | ||
*/ | ||
advtxt.Server.prototype.processCommand = function(command) { | ||
var self = this; | ||
// we haven't performed the command yet | ||
command.performed = false; | ||
async.waterfall([ | ||
function(next) { | ||
// get the current player, we also need to pass the command object | ||
self.getPlayer(command, next); | ||
}, | ||
// get the player's location | ||
self.getCurrentLocation.bind(self), | ||
// perform their command | ||
self.doCommand.bind(self), | ||
// update their items if necessary | ||
function(command, next) { | ||
if (command.items) { | ||
command.items = false; | ||
self.updatePlayerItems(command, next); | ||
} | ||
else { | ||
next(null, command); | ||
} | ||
}, | ||
// update their position if necessary | ||
function(command, next) { | ||
if (command.move) { | ||
command.move = false; | ||
self.updatePlayerPosition(command, next); | ||
} | ||
else { | ||
next(null, command); | ||
} | ||
}, | ||
// get their location again, if we need to announce it | ||
function(command, next) { | ||
if (command.announceRoom) { | ||
self.getCurrentLocation(command, next); | ||
} | ||
else { | ||
next(null, command); | ||
} | ||
} | ||
], self.finalize.bind(self)); | ||
} | ||
@@ -454,28 +521,38 @@ | ||
* | ||
* @param {Error} err - An error message, or null | ||
* @param {command} command - The command object. | ||
*/ | ||
advtxt.Server.prototype.finalize = function(command) { | ||
advtxt.Server.prototype.finalize = function(err, command) { | ||
var self = this; | ||
// this was the first time we saw the status as different, we need to send | ||
// the first time message and save the player. | ||
if (command.status !== command.player.status) { | ||
if (command.player.status === 'dead') { | ||
self.reply(command, i18n.__('You\'ve died! Send the command `reset all` to try again!')); | ||
} | ||
else if (command.player.status === 'win') { | ||
self.reply(command, i18n.__('You\'ve won the game! How impressive! Send the command `reset all` to play again!')); | ||
} | ||
self.updatePlayerStatus(command); | ||
} | ||
else if (command.player.status === 'dead') { | ||
self.reply(command, i18n.__('You\'re still dead! Send the command `reset all` to try again!')); | ||
} | ||
else if (command.player.status === 'win') { | ||
self.reply(command, i18n.__('Yes, your win was glorious, but send the command `reset all` to play again!')); | ||
} | ||
debug("Command Finalized"); | ||
// now send the replies out to the reply function | ||
if (err) { | ||
console.error("An error occurred. What follows is the error, and the command"); | ||
console.error(err); | ||
console.error(JSON.stringify(command)); | ||
} | ||
else { | ||
// this was the first time we saw the status as different, we need to send | ||
// the first time message and save the player. | ||
if (command.status !== command.player.status) { | ||
if (command.player.status === 'dead') { | ||
self.reply(command, i18n.__('You\'ve died! Send the command `reset all` to try again!')); | ||
} | ||
else if (command.player.status === 'win') { | ||
self.reply(command, i18n.__('You\'ve won the game! How impressive! Send the command `reset all` to play again!')); | ||
} | ||
self.updatePlayerStatus(command); | ||
} | ||
else if (command.player.status === 'dead') { | ||
self.reply(command, i18n.__('You\'re still dead! Send the command `reset all` to try again!')); | ||
} | ||
else if (command.player.status === 'win') { | ||
self.reply(command, i18n.__('Yes, your win was glorious, but send the command `reset all` to play again!')); | ||
} | ||
} | ||
// tell the original caller that we're done | ||
command.done(command); | ||
} | ||
{ | ||
"name": "advtxt", | ||
"version": "0.0.6", | ||
"version": "0.1.0", | ||
"private": false, | ||
"main": "index", | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/fardog/advtxt" | ||
}, | ||
"licenses": [ | ||
{ | ||
"type": "MIT", | ||
"url": "http://github.com/fardog/advtxt/raw/master/LICENSE" | ||
} | ||
], | ||
"main": "index", | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/fardog/advtxt" | ||
}, | ||
"licenses": [ | ||
{ | ||
"type": "MIT", | ||
"url": "http://github.com/fardog/advtxt/raw/master/LICENSE" | ||
} | ||
], | ||
"author": "Nathan Wittstock <code@fardogllc.com>", | ||
"description": "An engine for text-based adventure games.", | ||
"keywords": [ | ||
"game", | ||
"adventure" | ||
], | ||
"engines": { | ||
"node": ">=0.10.22" | ||
}, | ||
"scripts": {}, | ||
"keywords": [ | ||
"game", | ||
"adventure" | ||
], | ||
"engines": { | ||
"node": ">=0.10.22" | ||
}, | ||
"scripts": {}, | ||
"dependencies": { | ||
"underscore": "^1.6.0", | ||
"natural": "^0.1.26", | ||
"i18n-2": "^0.4.6" | ||
"i18n-2": "^0.4.6", | ||
"async": "^0.6.1", | ||
"debug": "^0.8.0" | ||
} | ||
} |
@@ -61,2 +61,4 @@ AdvTxt | ||
- **v0.1.0** | ||
- Moves application flow over to async library, more readable/testable. | ||
- **v0.0.6** | ||
@@ -63,0 +65,0 @@ - AdvTxt now extends EventEmitter and emits 'reply' messages. |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
22951
597
99
5
+ Addedasync@^0.6.1
+ Addeddebug@^0.8.0
+ Addedasync@0.6.2(transitive)
+ Addeddebug@0.8.1(transitive)