Permalink
Browse files

Building and linking rooms is now possible, added Mixin support.

  • Loading branch information...
1 parent 646b458 commit c6675c5c70610f85d005b0dc7b94e8026e481a2e @supernovus committed Jul 26, 2011
Showing with 150 additions and 23 deletions.
  1. +1 −0 .gitignore
  2. +4 −0 README
  3. +18 −3 lib/Client.js
  4. +89 −15 lib/Room.js
  5. +18 −0 lib/Room/Bathroom.js
  6. +1 −1 lib/World.js
  7. +19 −4 nodemoo.js
View
@@ -0,0 +1 @@
+*.swp
View
4 README
@@ -14,14 +14,18 @@ It's very incomplete, yet, give me time.
* Private chat (whisper)
* Emote
* Basic navigation ("go north" or "n")
+ * Mixins
TODO:
* Items
* Inventory
* Light
* Stats
+ * Real users (who can log in again, etc.)
* Persistence
+ * Permissions
+ * Other OO patterns?
* Lots of other stuff
= Author =
View
@@ -17,6 +17,8 @@ Client.prototype.gotoRoom = function (roomid) {
this.visited[roomid] = true;
}
}
+ else
+ this.msg("No such room: "+roomid);
}
Client.prototype.logout = function () {
@@ -74,21 +76,34 @@ Client.prototype.parse = function (data) {
var str = data.toString('utf8').replace(/(\n|\r)+$/, '');
if (str.match(/^exit$/)) return this.logout();
+ else if (this.room.parse(this, str)) true; // We found a Room call.
else if (matches = str.match(/^say "(.*?)" to (.*?)$/)) {
this.whisper(matches[2], matches[1]);
}
else if (matches = str.match(/^say (.*?)$/)) {
this.say(matches[1]);
}
- else if (str.match(/^hi$/)) this.say("hello");
else if (matches = str.match(/^emote (.*?)$/)) {
this.emote(matches[1]);
}
- else if (matches = str.match(/^rename ([\w\s'\.]+)/)) {
+ else if (matches = str.match(/^call me ([\w\s'\.]+)/)) {
this.rename(matches[1]);
}
+ else if (matches = str.match(/^make room (\w+) (called)? ([\w\s'\.]+)?/)) {
+ var roomid = matches[1];
+ var roomname = matches[3];
+ var init = {};
+ if (roomname)
+ init.name = roomname;
+ if (this.world.roomExists(roomid))
+ this.msg("Sorry, a room called "+roomid+" already exists.");
+ else {
+ this.world.addRoom(roomid, init);
+ this.gotoRoom(roomid);
+ }
+ }
+ else if (str.match(/^hi$/)) this.say("hello");
else if (str.match(/^bye$/)) this.say("goodbye");
- else if (this.room.parse(this, str)) true; // Do nothing.
else
this.msg("I don't understand \""+str+"\"");
View
@@ -1,28 +1,47 @@
// New-style Rooms.
var nl = "\r\n";
+var opposites = {
+ 'north' : 'south',
+ 'south' : 'north',
+ 'east' : 'west',
+ 'west' : 'east',
+ 'up' : 'down',
+ 'down' : 'up',
+ 'northeast' : 'southwest',
+ 'southwest' : 'northeast',
+ 'northwest' : 'southeast',
+ 'southeast' : 'northwest'
+};
+
+function Room (id, world, init) {
+ // Required items.
+ this.id = id;
+ this.world = world;
-function Room (init) {
// The room's name.
if (init.name)
this.name = init.name;
else
this.name = "Unnamed room";
+
// The room's description.
if (init.desc)
this.description = init.desc;
- else
- this.descrition = "Nothing to see here.";
+
// Any exits from this room.
if (init.exits)
this.exits = init.exits;
- else
- this.exits = {}; // Empty set.
-
- // Contents starts empty, you can populate with the put() method.
- this.contents = [];
-} // Yeah, pretty boring.
+}
+
+Room.prototype.rename = function (newname) {
+ this.name = newname;
+}
+
+Room.prototype.describe = function (newdesc) {
+ this.description = newdesc;
+}
// Commands applicable to Rooms in general.
Room.prototype.parse = function (client, str) {
@@ -55,11 +74,49 @@ Room.prototype.parse = function (client, str) {
else if (matches = str.match(/^(ne|nw|se|sw)$/)) {
var dir = dirs[matches[1]];
this.go(client, dir);
+ return true;
}
- else if (this.parseRoom && this.parseRoom(client,str))
+ else if (matches = str.match(/^link (\w+) to (\w+)$/)) {
+ var dir = matches[1];
+ var to = matches[2];
+ this.connect(dir, to);
return true;
- else
- return false;
+ }
+ else if (matches = str.match(/^unlink (\w+)$/)) {
+ this.disconnect(dir);
+ return true;
+ }
+ else if (matches = str.match(/^call this (.*?)$/)) {
+ this.rename(matches[1]);
+ return true;
+ }
+ else if (matches = str.match(/^describe here as (.*?)$/)) {
+ this.describe(matches[1]);
+ return true;
+ }
+ else if (matches = str.match(/^extend with (\w+)$/)) {
+ this.mixin(matches[1]);
+ return true;
+ }
+ else if (str.match(/^show parsers$/)) {
+ client.msg("Extra parsers in this room:");
+ for (var p in this.parsers) {
+ var parser = this.parsers[p];
+ client.msg(" " + parser);
+ }
+ return true;
+ }
+ else if (this.parsers)
+ { for (var p in this.parsers) {
+ var parser = this.parsers[p];
+ var func = this[parser];
+ if (func && func(client, str))
+ return true;
+ }
+ }
+
+ // If nothing was found, we return false.
+ return false;
}
// Feel free to override the prototype for look().
@@ -107,15 +164,32 @@ Room.prototype.go = function (client, direction) {
client.msg("You can't go that way.");
}
-Room.prototype.connect = function (direction, target) {
+Room.prototype.connect = function (direction, target, nosync) {
+ if (!this.exits)
+ this.exits = {};
this.exits[direction] = target;
+ if (!nosync && direction in opposites) {
+ var troom = this.world.getRoom(target);
+ var odir = opposites[direction];
+ if (troom)
+ troom.connect(odir, this.id, true);
+ }
}
Room.prototype.disconnect = function (direction) {
+ if (!this.exists)
+ return;
delete(this.exits[direction]);
}
-exports.newRoom = function (init) {
- return new Room(init);
+// Add some functions from an extension class.
+// Specify the role name here.
+Room.prototype.mixin = function (rolename) {
+ var role = require('./Room/'+rolename+'.js');
+ this.extend(role);
+}
+
+exports.newRoom = function (id, world, init) {
+ return new Room(id, world, init);
}
View
@@ -0,0 +1,18 @@
+function Bathroom () {} // A Bathroom Role.
+
+Bathroom.prototype.parseBathroom = function (client, str) {
+ var matches;
+ if (str.match(/^shit$/)) {
+ client.emote("sits on the toilet and takes a big smelly shit.");
+ return true;
+ }
+ return false;
+}
+
+Bathroom.prototype.setup = function (room) {
+ if (!room.parsers)
+ room.parsers = [];
+ room.parsers.push('parseBathroom');
+}
+
+module.exports = new Bathroom();
View
@@ -25,7 +25,7 @@ World.prototype.delClient = function (client) {
// Add a room
World.prototype.addRoom = function (roomid, init) {
- var room = this.Room.newRoom(init);
+ var room = this.Room.newRoom(roomid, this, init);
this.rooms[roomid] = room;
}
View
@@ -2,16 +2,31 @@
var net = require('net');
+// Let's add an "extend" method, with an optional "setup" component.
+Object.defineProperty(Object.prototype, "extend", {
+ enumerable: false,
+ value : function (from) {
+ for (var f in from)
+ { if (f == 'setup')
+ from.setup(this);
+ else
+ this[f] = from[f];
+ }
+ }
+});
+
var world = require('./lib/World.js');
var clib = require('./lib/Client.js');
+// The starting room. Rather boring.
+world.addRoom('start', {
+ 'name' : 'The Lobby',
+ 'desc' : "Not much to see here yet. It's a big, mostly empty room.",
+});
+
var server = net.createServer(function (socket) {
var client = clib.newClient(socket, world);
client.msg("Welcome to NodeMoo");
- world.addRoom('start', {
- 'name' : 'The Lobby',
- 'desc' : "Not much to see here yet. It's a big, mostly empty room.",
- });
client.gotoRoom('start');
world.addClient(client);
client.showPrompt();

0 comments on commit c6675c5

Please sign in to comment.