Initial commit (importing from old SVN repo which got lost) default tip

Sat, 27 Mar 2010 17:43:08 +0000

author
Matthew Wild <mwild1@gmail.com>
date
Sat, 27 Mar 2010 17:43:08 +0000
changeset 0
cc66ad6b0d75

Initial commit (importing from old SVN repo which got lost)

AUTHORS file | annotate | diff | comparison | revisions
COPYING file | annotate | diff | comparison | revisions
ChangeLog file | annotate | diff | comparison | revisions
INSTALL file | annotate | diff | comparison | revisions
MUD files file | annotate | diff | comparison | revisions
README file | annotate | diff | comparison | revisions
TODO file | annotate | diff | comparison | revisions
bot.lua file | annotate | diff | comparison | revisions
classes.lua file | annotate | diff | comparison | revisions
commands.lua file | annotate | diff | comparison | revisions
common.lua file | annotate | diff | comparison | revisions
containertables.inc.lua file | annotate | diff | comparison | revisions
def_object.lua file | annotate | diff | comparison | revisions
def_occupant.lua file | annotate | diff | comparison | revisions
def_room.lua file | annotate | diff | comparison | revisions
editing.lua file | annotate | diff | comparison | revisions
luacomponent file | annotate | diff | comparison | revisions
luacomponent.cpp file | annotate | diff | comparison | revisions
mt_object.lua file | annotate | diff | comparison | revisions
muc.lua file | annotate | diff | comparison | revisions
objects/obj_banner.lua file | annotate | diff | comparison | revisions
objects/obj_bar.lua file | annotate | diff | comparison | revisions
objects/obj_box.lua file | annotate | diff | comparison | revisions
objects/obj_cat.lua file | annotate | diff | comparison | revisions
objects/obj_container.lua file | annotate | diff | comparison | revisions
objects/obj_cupboard.lua file | annotate | diff | comparison | revisions
objects/obj_d2door.lua file | annotate | diff | comparison | revisions
objects/obj_door.lua file | annotate | diff | comparison | revisions
objects/obj_drinking_tables.lua file | annotate | diff | comparison | revisions
objects/obj_drinks.lua file | annotate | diff | comparison | revisions
objects/obj_fireplace.lua file | annotate | diff | comparison | revisions
objects/obj_kitten.lua file | annotate | diff | comparison | revisions
objects/obj_oven.lua file | annotate | diff | comparison | revisions
objects/obj_small_chair.lua file | annotate | diff | comparison | revisions
objects/obj_toaster.lua file | annotate | diff | comparison | revisions
objects/obj_window.lua file | annotate | diff | comparison | revisions
readme file | annotate | diff | comparison | revisions
rooms.lua file | annotate | diff | comparison | revisions
rooms/d2.lua file | annotate | diff | comparison | revisions
rooms/kitchen.lua file | annotate | diff | comparison | revisions
rooms/lounge.lua file | annotate | diff | comparison | revisions
soo.lua file | annotate | diff | comparison | revisions
svn-commit.tmp file | annotate | diff | comparison | revisions
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ChangeLog	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,196 @@
+------------------------------------------------------------------------
+r35 | brokenthorn | 2007-02-09 10:29:41 +0000 (Fri, 09 Feb 2007) | 2 lines
+
+Added files required by the GNU standard :P
+
+------------------------------------------------------------------------
+r34 | brokenthorn | 2007-02-08 19:57:18 +0000 (Thu, 08 Feb 2007) | 4 lines
+
+Added a TODO file which currently only lists a few ideas/suggestions for xmoo
+inspired from Canton Becker's "The Unofficial MOO Programming Tutorial"
+which is rather old but still contains some great ideas that would be nice to extend.
+
+------------------------------------------------------------------------
+r33 | brokenthorn | 2007-02-07 19:32:45 +0000 (Wed, 07 Feb 2007) | 2 lines
+
+A small commit after some troubleshooting to make the server run on my host.
+
+------------------------------------------------------------------------
+r32 | mattj | 2007-02-04 19:20:41 +0000 (Sun, 04 Feb 2007) | 2 lines
+
+Various (that means I can't remember)
+
+------------------------------------------------------------------------
+r31 | mattj | 2007-02-01 18:53:57 +0000 (Thu, 01 Feb 2007) | 3 lines
+
+Just small changes ;)
+also a more serius fix for _enter on rooms (now called as a real :_method() )
+
+------------------------------------------------------------------------
+r30 | mattj | 2007-02-01 12:44:42 +0000 (Thu, 01 Feb 2007) | 2 lines
+
+I finally fixed a bug with presence (I think), it's been hanging around since revision 6 (see svn log) :)
+
+------------------------------------------------------------------------
+r29 | mattj | 2007-01-31 22:24:43 +0000 (Wed, 31 Jan 2007) | 3 lines
+
+Loads of changes, a new room. Lots of fixes.
+*classes.lua is now not needed! Class files are loaded ON DEMAND! (This will apply to rooms also, soon)
+
+------------------------------------------------------------------------
+r28 | mattj | 2007-01-30 11:39:04 +0000 (Tue, 30 Jan 2007) | 4 lines
+
+Bug fixes, and more stability. Better inheritance, and some debugging commands.
+*Added a 'door' class, and some doors between the two rooms.
+*Dynamic class loading/reloading works
+
+------------------------------------------------------------------------
+r27 | mattj | 2007-01-29 21:00:47 +0000 (Mon, 29 Jan 2007) | 8 lines
+
+Loads more changes and fixes.
+*All objects now have 100% lowercase longname, and this is how it should stay.
+*get/put work very well now, added a drop command.
+*You can now do things (ie. look at) items you are holding, as wel as just in the room.
+*Certain objects can be 'static', and they cannot be got/put.
+*Inheritance now only uses metatables (I *think*). This is work ongoing.
+*Dynamic loading of objects begun, but broken and far from working.
+
+------------------------------------------------------------------------
+r26 | mattj | 2007-01-29 16:27:03 +0000 (Mon, 29 Jan 2007) | 4 lines
+
+A working revision, with new containertable class. def_room now uses this, nothing else yet. Hence, while rooms can, normal objects, including people, are unable to hold 2 or more of the same kind of object (at least, same name).
+get/put work well!
+New command 'i' to see what you are carrying.
+
+------------------------------------------------------------------------
+r25 | brokenthorn | 2007-01-28 22:09:39 +0000 (Sun, 28 Jan 2007) | 3 lines
+
+Nothing too important. Just a check out for spelling errors and one new 
+object.
+
+------------------------------------------------------------------------
+r24 | mattj | 2007-01-28 17:55:41 +0000 (Sun, 28 Jan 2007) | 2 lines
+
+LOADS of changes, but thankfully all internal. This does not affect how you code objects. I have coded in skeleton get/put commands, but they do not work properly yet.
+
+------------------------------------------------------------------------
+r23 | brokenthorn | 2007-01-27 21:46:38 +0000 (Sat, 27 Jan 2007) | 3 lines
+
+Modified rooms/d2.lua to test objects/obj_window.
+Added 4 new objects that still need working on.
+
+------------------------------------------------------------------------
+r22 | brokenthorn | 2007-01-23 23:21:01 +0000 (Tue, 23 Jan 2007) | 3 lines
+
+Added a simple 'window' object that doesn't work :|
+
+
+------------------------------------------------------------------------
+r21 | mattj | 2007-01-22 12:58:36 +0000 (Mon, 22 Jan 2007) | 2 lines
+
+Short 'Creating a class' tutorial
+
+------------------------------------------------------------------------
+r20 | mattj | 2007-01-22 02:24:28 +0000 (Mon, 22 Jan 2007) | 2 lines
+
+Added _say to objects, now life is SO EASY! :D Also added some helpful comments
+
+------------------------------------------------------------------------
+r19 | mattj | 2007-01-22 01:50:45 +0000 (Mon, 22 Jan 2007) | 2 lines
+
+Added _say methof to occupant, this will deprecate PSay/FSay. It makes things easier for object coders :)
+
+------------------------------------------------------------------------
+r18 | mattj | 2007-01-22 01:23:09 +0000 (Mon, 22 Jan 2007) | 2 lines
+
+Removed some debugging code
+
+------------------------------------------------------------------------
+r17 | mattj | 2007-01-21 22:37:20 +0000 (Sun, 21 Jan 2007) | 2 lines
+
+Command processing moved to 'occupant' object, people now inherit occupant's methods/properties.
+
+------------------------------------------------------------------------
+r16 | brokenthorn | 2007-01-21 22:25:38 +0000 (Sun, 21 Jan 2007) | 2 lines
+
+Added a README file that will be later edited.
+
+------------------------------------------------------------------------
+r15 | matthew | 2007-01-21 12:00:21 +0000 (Sun, 21 Jan 2007) | 2 lines
+
+Fixed incorrect detection of error messages from the Jabber server
+
+------------------------------------------------------------------------
+r14 | matthew | 2007-01-20 01:37:42 +0000 (Sat, 20 Jan 2007) | 3 lines
+
+IT WORKS! Small improvements to be made, but pretty usable :) Need to program commands like get, put, etc. 
+next. This revision brings a working bot.lua and soo.lua both.
+
+------------------------------------------------------------------------
+r13 | matthew | 2007-01-20 00:57:55 +0000 (Sat, 20 Jan 2007) | 2 lines
+
+Fixed some things, still not in a working state
+
+------------------------------------------------------------------------
+r12 | matthew | 2007-01-19 23:04:50 +0000 (Fri, 19 Jan 2007) | 3 lines
+
+Various fixes, bot.lua now has inheritance also (previously only soo.lua). bot.lua 
+is untested, however.
+
+------------------------------------------------------------------------
+r11 | matthew | 2007-01-19 17:44:38 +0000 (Fri, 19 Jan 2007) | 2 lines
+
+Fixed some naming
+
+------------------------------------------------------------------------
+r10 | matthew | 2007-01-19 17:43:06 +0000 (Fri, 19 Jan 2007) | 2 lines
+
+Working inheritance!! Sample objects included.
+
+------------------------------------------------------------------------
+r9 | matthew | 2007-01-19 17:33:30 +0000 (Fri, 19 Jan 2007) | 3 lines
+
+Working on object inheritance, this revision is certainly not working 
+properly!
+
+------------------------------------------------------------------------
+r8 | matthew | 2007-01-16 13:29:53 +0000 (Tue, 16 Jan 2007) | 2 lines
+
+Fixed a bug in soo mode
+
+------------------------------------------------------------------------
+r7 | matthew | 2007-01-16 00:59:12 +0000 (Tue, 16 Jan 2007) | 2 lines
+
+soo.lua to access xmoo on the CLI
+
+------------------------------------------------------------------------
+r6 | matthew | 2007-01-16 00:14:53 +0000 (Tue, 16 Jan 2007) | 2 lines
+
+Large commit, room-to-room working now, except for a very minor bug
+
+------------------------------------------------------------------------
+r5 | matthew | 2007-01-15 15:48:10 +0000 (Mon, 15 Jan 2007) | 2 lines
+
+Buggy, but mostly done room-to-room
+
+------------------------------------------------------------------------
+r4 | matthew | 2007-01-14 19:46:37 +0000 (Sun, 14 Jan 2007) | 2 lines
+
+Fix for syntax error
+
+------------------------------------------------------------------------
+r3 | matthew | 2007-01-14 19:44:19 +0000 (Sun, 14 Jan 2007) | 2 lines
+
+Continuing multi-room patches
+
+------------------------------------------------------------------------
+r2 | matthew | 2007-01-14 19:29:13 +0000 (Sun, 14 Jan 2007) | 2 lines
+
+Switching to new global 'people' table
+
+------------------------------------------------------------------------
+r1 | matthew | 2007-01-14 19:13:34 +0000 (Sun, 14 Jan 2007) | 2 lines
+
+Added all files
+
+------------------------------------------------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MUD files	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,5 @@
+<pos=2273> /home/matthew/dev/xmud/bot.lua
+<pos=1> /home/matthew/dev/xmud/obj_cat.lua
+<pos=1> /home/matthew/dev/xmud/occupant.lua
+<pos=1> /home/matthew/dev/xmud/obj_room.lua
+<pos=-1> /home/matthew/dev/xmud/obj_fireplace.lua
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,56 @@
+# XMOO Readme file.
+
+#Creating a new class
+In this example, we will create a torch.
+
+Start with the line:
+	classes.obj_torch = { } -- This creates an empty class
+
+What you call the class does not matter, it is not visible to users.
+
+Now we must define some things, such as its name, and what it looks like, its properties.
+
+	classes.obj_torch._properties = {
+								name = "torch",
+								longname = "An electric torch",
+								desc = "A small portable electric torch, to help you see when it is dark"
+							}
+							
+Simple, eh? :)
+
+Now, we want the user to be able to do things with the torch, let's say that 'twisting' it, switches it on and off.
+So we must define the method 'twist':
+
+	function classes.obj_torch:twist(info)
+		
+	end
+
+info is a variable we get, that contains information useful to use, such as who twisted it (info.person), and what room we are in (info.room), etc.
+
+Now we must also keep track of whether the torch is lit or unlit. We will store this as a property. In a method, 'self' always refers to the curent object.
+
+	function classes.obj_torch:twist(info)
+		if self._properties.state == "lit" then self._properties.state == "unlit" -- if it is lit, make it unlit
+		else self._properties.state == "lit" end -- Otherwise, make it lit
+	end
+
+Very good, but we must show everyone in the room what is going on:
+
+	function classes.obj_torch:twist(info)
+		if self._properties.state == "lit" then 
+			self._properties.state == "unlit" -- if it is lit, make it unlit
+			self._properties.desc = "A small portable electric torch, to help you see when it is dark. It is not lit."
+			info.person:_say("/me turns off the torch")
+		else
+			self._properties.state == "lit" -- Otherwise, make it lit
+			self._properties.desc = "A small portable electric torch, to help you see when it is dark. It is lit."
+			info.person:_say("/me lights the torch")
+		end 
+	end
+
+As you can see, the colon ':' is used to call methods, or functions of another object. Remember that people are objects too!
+The default 'look' method uses the 'desc' property, so we have changed it, to show whether the torch is lit or not.
+
+It's done!
+
+More to come, including creating new rooms :)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TODO	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,32 @@
+-- TODO file for
+-- xmoo - The Jabber MOO Component
+
+[[ Suggestions for next releases ]]
+
+o	all objects should have incremented object numbers assigned to them
+	so that even if you have two or more same objects with the same name they
+	can be indentified by their object number. This also helps defining the
+	object's file name and distinguish one similar object from another - an
+	object with the same name might have different properties, etc.
+o	A way to create the MOO world within the MOO.
+	eg.: Commands to create objects, fetch their information, set their
+	information, etc. The commands should work with object numbers and not names.
+	A useful command should exist that would list the object numbers of objects
+	that have similar or the same name.
+	eg.:	'@look #____' to fetch the information for an object.
+		'@move #____ to somewhere' to move a newly created or owned object.
+		'@lsobj <object_name>' to fetch all object numbers that share the same name.
+		'@describe #____ as "Put your description here"'
+			A message that appears when you 'look' at the object.
+		'@detail #____ smell is "Assign a smell to the obj"'
+			@detail <object> <verb> is <description>
+	This feature could be restricted to users that don't have building/creating rights.
+o	More suggestions to come.
+	Most suggestions are ideas take from
+	http://tecfa.unige.ch/pub/documentation/MUD/MOO/Becker-Tutorial.text
+	"The Unofficial MOO Programming Tutorial" by Canton Becker
+	originally about MOOcode.
+
+[[ TODO ]]
+
+o	More to come...
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bot.lua	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,173 @@
+--[[ Lua XMPP MOO Component by Matthew Wild (MattJ)					]]
+
+BotName = "Component";
+BotPass = "";
+
+function onPresence(msg)
+	success, message = pcall(handlePresence, msg);
+	if not success then print("\nERROR: "..message.."\n"); end
+end
+
+function onConnect()
+end
+
+function onMessage(msg)
+	success, message = pcall(handleMessage, msg);
+	if not success then print("\nERROR: "..message.."\n"); end
+end
+
+
+function handlePresence(msg)
+	local room, server, nick, id, person;
+	room,server,nick = msg.to:match("^(.+)@(.+)/(.+)$");
+	if not (room and nick) then print("\nERROR: Invalid room or nick!\n"); return; end -- We need to send an error
+	-- print("Type: "..msg.type.." type of type: "..type(msg.type),"\n");
+	if msg.type == "available" or msg.type == "" and not people[msg.fromFull] then
+		print("\nRecieved Available presence to join a room\n");
+		people[msg.fromFull] = { ["nick"] = nick, ["jid"] = msg.fromFull, ["presence"] = msg.type, room = rooms[room], occjid = msg.to, _parent = occupant, group = {}, _contents = { ["in"] = createcontainertable(); } }
+		MoveToRoom(people[msg.fromFull], room);
+		-- rooms[room].people[nick] = people[msg.fromFull];
+		--for id, person in pairs(rooms[room].people) do
+		--	SendPresence(msg.fromFull, person.presence, "", room.."@"..server.."/"..person.nick);
+		--end
+	elseif msg.type == "unavailable" then
+		RemoveFromRoom(rooms[room], msg.fromFull);
+		people[msg.fromFull] = nil;
+	end
+	print("Returning\n");
+	SendPresence(msg.fromFull, msg.type, "", msg.to);
+end
+
+
+
+function handleMessage(msg)
+	local action, object, room, server, person;
+	person = people[msg.fromFull]
+	if msg.type == MSG_ERROR then print("ERROR MESSAGE from "..msg.fromFull..": ", msg.body); return nil; end
+	if not person then print("No such person as "..msg.fromFull, tostring(people[msg.fromFull]).."\n"); 
+	for k,v in pairs(people) do print(string.format("people[\"%s\"]", k),", "); end return nil; end
+	room, server = msg.to:match("^(.+)@(.+)$");
+	if not (room and server) then print("ERROR! Malformed JID? "..msg.to.."\n"); return nil; end --TODO: Reply with error
+	server = server:lower();
+	if not rooms[room] then return; end -- TODO: Reply with error
+	
+	person:_processCommand(msg.body);
+
+	return nil;
+end
+
+function BroadcastPresence(people, fromnick, ptype, text)
+	local nick, t;
+	if type(people) == "string" then if not rooms[people] then print("No room called '"..people.."'","\n"); return; else print("\nLooking up room: "..people, "\n"); people = rooms[people].people; end end
+	if not people then print("No such room. \n"); return; end
+	for nick, t in pairs(people) do
+		if t and t.jid then 
+			SendPresence(t.jid, ptype or "available", text or "", GetJIDParts(t.occjid).node.."@"..GetJIDParts(t.occjid).server.."/"..fromnick);
+		else print("\nOrphaned occupant: "..nick, "\n");
+		end
+	end
+end
+
+function BroadcastMessage(people_, from, text, mtype, sender_sees)
+	local nick, t
+	for nick, t in pairs(people_) do
+		print("\nMessage sent to: "..t.jid);
+		if t.nick ~= from or sender_sees ~= false then 
+			SendMessage(t.jid, GetJIDParts(t.occjid).node.."@"..GetJIDParts(t.occjid).server.."/"..from, text or "", mtype or "groupchat");
+		end
+	end
+	print("\nDone\n");
+end
+
+function GetOccupantNick(jid)
+	local pjid, p
+	for pjid, p in pairs(people) do
+		if CompareJIDs(pjid, jid) then return p.nick; end
+	end
+	return "Somebody";
+end
+
+function CompareJIDs(j1, j2)
+	if not (j1 and j2) then return false; end
+	print("j2: "..type(j2));
+	j1node, j1server, j1res = j1:match("^(.+)@([%a%.]+)/?(.*)$");
+	j2node, j2server, j2res = j2:match("^(.+)@([%a%.]+)/?(.*)$");
+	if j1node == j2node and j1server:lower() == j2server:lower() and (j1res == j2res or j1res == "" or j2res == "") then return true; end
+	return false;
+end
+
+function MoveToRoom(person, room)
+	if not ( person and room) then return; end
+		
+	if type(room) ~= "table" then
+		if not rooms[room] then rooms[room] = CreateObject(classes.obj_room); rooms[room]:_create{ room = room, server = GetJIDParts(person.occjid).server}; end
+		 room = rooms[room];
+	end
+	
+	if person.room ~= room then
+		if person.room then
+			-- Tell everyone in room that user is leaving
+			--BroadcastPresence(person.room.people, person.occjid, "unavailable");
+			for nick, t in pairs(person.room.people) do
+				-- print(string.format("\nPRESENCE: to: %s, from: %s, type: %s\n", t.jid, ));
+				if nick ~= person.nick then
+					SendPresence(t.jid, "unavailable", "", GetJIDParts(t.occjid).node.."@"..GetJIDParts(t.occjid).server.."/"..person.nick);
+				end
+			end
+			-- Tell user that everyone else in the room has gone (clear room roster in their client)
+			for nick, t in pairs(person.room.people) do
+				if person.nick ~= nick then
+					SendPresence(person.jid, "unavailable", "", GetJIDParts(person.occjid).node.."@"..person.room._properties.server.."/"..t.nick);
+				end
+			end
+			person.room.people[person.nick] = nil; -- Remove from room
+		end
+	end
+	person.room = room;
+	room.people[person.nick] = person;
+	--Tell user about people in the new room
+	for nick, t in pairs(person.room.people) do
+		-- print(string.format("\nPRESENCE: to: %s, from: %s, type: %s\n", t.jid, ));
+		if nick ~= person.nick then
+			SendPresence(person.jid, "available", "", GetJIDParts(person.occjid).node.."@"..GetJIDParts(person.occjid).server.."/"..nick);
+		end
+	end
+	--Tell people in new room that user has joined
+	-- BroadcastPresence(person.room.people, person.nick, "available");
+	for nick, t in pairs(person.room.people) do
+		-- print(string.format("\nPRESENCE: to: %s, from: %s, type: %s\n", t.jid, ));
+		if nick ~= person.nick then
+			SendPresence(t.jid, "available", "", GetJIDParts(t.occjid).node.."@"..GetJIDParts(t.occjid).server.."/"..person.nick);
+		end
+	end
+	SendPresence(person.jid, "available", "", person.occjid);
+	room:_enter{ room = person.room, person = person, nick = person.nick };
+end
+
+function RemoveFromRoom(room, jid)
+	if not ( room and jid) then return; end
+	for id, t in pairs(room.people) do
+		if CompareJIDs(t.jid, from) then room.people[id] = nil; end
+	end
+	-- Tell everyone in room that user is leaving
+	for nick, t in pairs(room.people) do
+			SendPresence(t.jid, "unavailable", "", GetJIDParts(t.occjid).node.."@"..GetJIDParts(t.occjid).server.."/"..people[jid].nick);
+	end
+end
+
+function FSay(room, fromnick, text)
+	BroadcastMessage(room.people, fromnick , text);
+end
+
+function PSay(room, tonick, fromnick, text)
+	--print(string.format("Room JID: %s, To: %s, From: %s\n", room.jid, tonick, fromnick));
+	for k,v in pairs(room.people) do print(string.format("people[\"%s\"]", k),", "); end
+	print("\n");
+	-- room.jid..(((fromnick and fromnick:len() > 0) and "/"..fromnick) or "")
+	SendMessage(room.people[tonick].jid, room.people[tonick].occjid, text or "", (fromnick and fromnick:len() > 0 and "groupchat") or "groupchat");
+end
+
+dofile("common.lua");
+
+rooms = rooms or { };
+people = people or setmetatable({ default = {} }, { __newindex = function (t, k, v) if not rawget(v, "_parent") then rawset(v, "_parent", rawget(t, "default")); end return rawset(t, k, setmetatable(v, { __index = occupant })); end }); -- This is our inheritance code;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/classes.lua	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,9 @@
+--[[
+dofile("objects/obj_container.lua");
+dofile("objects/obj_cat.lua");
+dofile("objects/obj_kitten.lua");
+dofile("objects/obj_fireplace.lua");
+dofile("objects/obj_window.lua");
+dofile("objects/obj_box.lua");
+dofile("objects/obj_small_chair.lua");
+dofile("objects/obj_door.lua"); ]]
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands.lua	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,153 @@
+-- Here we process special commands, for example, those with more than one object specified
+
+commands = {};
+
+function commands:_parse(person, command)
+	if person.group.perm_edit and command:match("^@.*$") then
+		local verb, param = command:match("^@(%a+)%s?(.*)$");
+	end
+	local verb, object = command:match("^(%a+%s%a+)%s(.+)$");
+	if verb and object and #verb > 0 and #object > 0 and person.room:_findobject(object) then
+		return verb, object;
+	end
+	verb, object = command:match("^(%a+)%s?(.*)$");
+	if verb and object and #verb > 0 and #object > 0 then
+		return verb, object;
+	end
+	if verb and ((not object) or (object == "")) then return verb, nil; end
+end
+
+function commands:_handle(person, action, object)
+	-- if not (person and action) then print("Invalid parameters!"); return; end
+	function callobjectmethod(object)
+		local o = person.room._objects:findobject(object) or person._contents["in"]:findobject(object);
+		if o and o[action] then o[action](o, {room = person.room, person = person, nick = person.nick }); return true; end
+		return false;
+	end
+	
+	if commands[action] then commands[action](person, action, object);
+	elseif object and object ~= "" and callobjectmethod(object) then return true;
+	elseif occupant[action] then occupant[action](person, { room = person.room, person = person }); return true;
+	elseif action and type(person.room[action]) == "function" then person.room[action](person.room, { room = person.room, person = person, jid = person.jid, nick = person.nick, param = object }); return true;
+	else return false; -- Unable to understand command
+	end
+end
+
+function commands.get(person, action, param)
+	-- Decide if we are taking it from a container
+	obj1, obj2 = param:match("^([%a%s]+)%sfrom%s([%a%s]+)$");
+	if obj1 and obj2 then -- We are taking from a container
+		local container = person:_findobject(obj2) or person.room:_findobject(obj2);
+		if not container then person:_tell(string.format("I don't see any '%s' here.", obj2 or "")); return; end
+		if not (container._contents and container._contents["in"]) then person:_tell(string.format("The %s is not a container.", obj2 or "")); return; end
+		object = container:_findobject(obj1);
+		if not object then
+			if object == false then person:_tell(string.format("Sorry, the %s is locked.", obj2)); 
+			else person:_tell(string.format("I can't find any %s in there.", obj1)); end
+			return;
+		end
+		if person:_get({ object = object, container = container, name = obj1 }) then
+			person:_say(string.format("/me gets %s from %s", object._properties.longname or object._properties.name or "something", container._properties.longname or container._properties.name or "something"));
+		else
+			person:_tell("You can't get that");
+		end
+		return;
+	end
+	obj1 = param:match("^([%a%s]+)$");
+	if not obj1 then person:_tell("uh?"); return; end
+	-- So we are getting an object just in the room
+	local container = person.room;
+	local object = container:_findobject(obj1);
+	if not object then person:_tell(string.format("I can't find any %s in here.", obj1)); return; end
+	if person:_get({ object = object, container = container, name = obj1}) then
+		person:_say(string.format("/me picks up %s", object._properties.longname or object._properties.name or "something"));
+	else
+		person:_tell("You can't get that");
+	end
+end
+
+function commands.put(person, action, param)
+	obj1, obj2 = param:match("^([%a%s]+)%sin%s([%a%s]+)$");
+	if not (obj1 and obj2) then return end
+	local oldcontainer = person; -- Where the object currently is
+	local object = person:_findobject(obj1);
+	if not object then object = person.room:_findobject(obj1); oldcontainer = person.room; end
+	if not object then person:_tell(string.format("Sorry, I can't find the '%s'.", obj1)); return; end
+	local newcontainer = person.room:_findobject(obj2);
+	if not newcontainer then person:_tell(string.format("I don't see any '%s' here.", obj2 or "")); return; end
+	if not (newcontainer._contents and newcontainer._contents["in"]) then person:_tell(string.format("The %s is not a container.", obj2 or "")); return; end
+	
+	if newcontainer:_get({ object = object, container = oldcontainer }) then
+		person:_say(string.format("/me puts %s in %s", object._properties.longname or object._properties.name or "something", newcontainer._properties.longname or newcontainer._properties.name or "something"));
+	else
+		person:_tell("You can't put that in there");
+	end
+end
+
+function commands.drop(person, action, param)
+	 local o = person:_findobject(param);
+	 if not o then person:_tell("You don't seem to have any "..param); return false; end
+	if person.room:_get({ object = o, container = person }) then
+		person:_say("/me drops "..(o._properties.longname or o._properties.name));
+	end
+end
+
+function commands.give(person, action, param)
+	if not param then person:_tell("Give what to whom?"); return; end
+	local objname, tonick = param:match("([%a%s]-)%s* to (.*)");
+	if not objname or not tonick then person:_tell("Give what to whom?"); return; end
+	local o = person:_findobject(objname);
+	 if not o then person:_tell("You don't seem to have any "..objname); return false; end
+	if not person.room.people[tonick] then person:_tell("Sorry, I can't find "..(tonick or "that person").."in this room..."); return; end
+	if person.room.people[tonick]:_get({object = o, container = person}) then
+		person:_action("gives "..(o._properties.longname or ((o._properties.prepend or "the").." "..o._properties.name)).." to "..param);
+	end
+end
+
+function commands.help(person, action, param)
+	
+end
+
+function commands.loadclass(person, action, param)
+	local subenv = { classes = { } }
+	local classdefinition = loadfile("objects/"..param..".lua");
+	setfenv(classdefinition, subenv);
+	local success, message = pcall(classdefinition);
+	if not success then person:_tell(string.format("Error loading %s: %s", param, message));
+	else
+		for k, v in pairs(classes[param]) do classes[param][k] = nil; end -- Clear current class
+		for k, v in pairs(subenv.classes[param]) do classes[param][k] = v; end -- Fill with data from new definition
+		person:_tell("Loaded");
+	end
+end
+
+function commands.dump(person, action, param)
+	table.print(param, person.room:_findobject(param) or person:_findobject(param) or classes.default or {});
+end
+
+function commands.dumproom(person, action, param)
+	table.print(person.room.name or "room", person.room);
+end
+
+function commands.loadroom(person, action, param)
+	if not rooms[param] then person:_tell("You should go into the room, it has not even been created yet."); end
+	local oldpeople = rooms[param].people;
+	rooms[param]:_create{ room = param, server = GetJIDParts(person.occjid).server}
+	rooms[param].people = oldpeople;
+end
+
+commands["@create"] = function (person, action, param)
+	local chunk = loadstring(param);
+	if not chunk then person:_tell("There was an error in your syntax. Please read the manual"); return; end
+	setfenv(chunk, 1);
+	local success, message = pcall(chunk);
+	if not success then person:_tell(message.."\nThere was an error processing the command"); return; end
+	local t = message;
+	local newobj = classes[t.class]:_create(t);
+	if newobj then
+		person._contents["in"]:add(newobj);
+		person:_action("waves his hands, and conjures something from thin air!");
+	else
+		person:_tell("For some reason, the object was not created");
+	end
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common.lua	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,75 @@
+-- New version, using 100% inheritance through metatables
+function CreateObject(base, name)
+	local b = {};
+	for k, v in pairs(base) do
+		if type(v) == "table" then
+			b[k] = CreateObject(v, false);
+		end
+	end
+	if name ~= false then
+		b._parent = base; setmetatable(b, { __index = _inheritproc });
+		b._properties = b._properties or {};
+		b._properties.name = name or (base._properties and base._properties.name) or "";
+	else
+		setmetatable(b, getmetatable(base) or { __index = base });
+	end
+	return b;
+end
+
+function GetJIDParts(jid)
+	local j1node, j1server, j1res = jid:match("^(.+)@([%a%.]+)/?(.*)$");
+	return { node = j1node, server = j1server, resource = j1res, jid = jid }
+end
+
+function basicSerialize (o)
+  if type(o) == "number" or type(o) == "boolean" then
+    return tostring(o)
+  else -- assume it is a string
+    return string.format("%q", tostring(o))
+  end
+end
+
+function table.print (name, value, saved)
+  saved = saved or {}       -- initial value
+  io.write(name, " = ")
+  if type(value) == "number" or type(value) == "string" or type(value) == "boolean" or type(value)=="function" then
+    io.write(basicSerialize(value), "\n")
+  elseif type(value) == "table" then
+    if saved[value] then    -- value already saved?
+      io.write(saved[value], "\n")  -- use its previous name
+    else
+      saved[value] = name   -- save name for next time
+      io.write("{}\n")     -- create a new table
+      for k,v in pairs(value) do      -- save its fields
+        local fieldname = string.format("%s[%s]", name,
+                                        basicSerialize(k))
+        table.print(fieldname, v, saved)
+      end
+    end
+  else
+    error("cannot save a " .. type(value))
+  end
+end
+
+
+function _inheritproc(t, k)
+	local parent = rawget(t, "_parent");
+	if type(parent) == "table" then
+		return (rawget(parent, k) or _inheritproc(parent, k));
+	else
+		return parent and (rawget(classes[parent], k) or _inheritproc(classes[parent], k));
+	end
+end
+
+classes = classes or setmetatable({ default = {} }, { __newindex = function (t, k, v) if not rawget(v, "_parent") then rawset(v, "_parent", rawget(t, "default")); end return rawset(t, k, setmetatable(v, { __index = _inheritproc })); end, __index = function (t, k) dofile(string.format("objects/%s.lua", k)); return rawget(t, k); end }); -- This is our inheritance code;
+tpl_rooms = {}
+
+dofile("containertables.inc.lua");
+dofile("commands.lua");
+dofile("def_object.lua");
+dofile("def_occupant.lua");
+dofile("def_room.lua");
+
+dofile("rooms.lua");
+dofile("classes.lua");
+dofile("editing.lua");
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/containertables.inc.lua	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,52 @@
+
+--[[ I created this class for an easy way of managing the objects inside a container in the MOO. ]]
+
+containertable = { };
+
+function containertable:add(object)
+	local subt = self[(object and object._properties.name) or ""];
+	if not subt then subt = { };
+		self[(object and object._properties.name) or ""] = subt; 
+		-- Also, all object's aliases need to point to subt
+		if object._tags then
+			for i, tag in ipairs(object._tags) do
+				self[tag] = subt;
+			end
+		end
+	end
+	table.insert(subt, object);
+	return object;
+end
+
+function containertable:remove(object)
+	local subt = self[(object._properties and object._properties.name) or ""];
+	if not subt then return false; end
+	for n, stored_object in pairs(subt) do
+		if object == stored_object then table.remove(subt, n); return object; end
+	end
+	return false;
+end
+
+function containertable:addalias(name, tag)
+	self[tag] = self[name];
+end
+
+function containertable:findobject(name)
+	local subt = self[name or ""];
+	if not subt then subt = self[""]; if not subt then return; end end
+	return subt[1];
+end
+
+function containertable:getallobjects()
+	all = {};
+	for tag, list in pairs(self) do
+		for n, object in ipairs(list) do
+			all[object] = true;
+		end
+	end
+	return all; -- We return a table, where the objects are the keys, and the values are true
+end
+
+function createcontainertable(t)
+	return setmetatable(t or {}, { __index = containertable });
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/def_object.lua	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,56 @@
+
+classes.default._properties = { name = "object", longname = "An object", desc = "You see nothing of interest" }
+
+function classes.default:_create(e)
+	local obj = CreateObject(self, e.name);
+	obj._room = e.room;
+	return obj;
+end
+			
+function classes.default:look (e)
+	FSay(e.room, e.nick, "/me looks at "..(self._properties.prepend or "The ")..self._properties.name or "____");
+	PSay(e.room, e.nick, "", self._properties.desc);
+end
+
+function classes.default:_say(text, room)
+	FSay(room or self._room, (self._properties.prepend or "The ")..self._properties.name, text);
+end
+
+function classes.default:_action(text, room)
+	return self:_say("/me "..text, room);
+end
+
+function classes.default:_findobject(name, where)
+	if not (self._contents and self._contents[where or "in"]) then return nil; end
+	if self._properties.locked then return false; end
+	return self._contents[where or "in"]:findobject(name);
+end
+
+function classes.default:_unlink(object)
+	if not (self._contents and self._contents["in"]) then print("Attempt to _unlink on a non-container."); return nil; end
+	if type(object) == "string" then object = self._contents["in"]:findobject(object); end
+	if not object then return false; end
+	if self._contents["in"]:remove(object) then
+		return true;
+	end
+end
+
+function classes.default:_get(i)
+	if not (self._contents and self._contents["in"]) then print("Attempt for a non-container to _get"); return nil; end
+	if not (i.container:_unlink(i.object)) then return false; end
+	self._contents["in"]:add(i.object);
+	return true;
+end
+
+classes.default["look in"] =
+	function (self, e)
+		local contents = {};
+		local contents2 = {};
+		if not (self._contents and self._contents["in"]) then e.person:_tell("That is not a container."); return; end
+		contents = self._contents["in"]:getallobjects();
+		for o, exists in pairs(contents) do
+			print("o");
+			table.insert(contents2, o._properties.longname or o._properties.name or "Something");
+		end
+		e.person:_tell("You see: "..table.concat(contents2,", "));
+	end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/def_occupant.lua	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,70 @@
+
+occupant =
+{ 
+	_properties = {},
+	_default =	function (self, e)
+				PSay(e.room, e.nick, " ", "<not-implemented/>");
+			end,
+	sit	=	function (self, e)
+				self:_action("sits down");
+			end,
+	reload = 	function (self, e)
+				local success, message = pcall(dofile, "bot.lua");
+				if not success then self:_tell(string.format("Error reloading: %s", message)); end
+			end,
+	refresh = 	function (self, e)
+				classes = nil;
+				dofile("bot.lua");
+			end,
+	who = 	function (self, e)
+				local p = {};
+				for nick, t in pairs(self.room.people) do
+					table.insert(p, nick.." ("..(t.jid or "Unknown JID")..")\n");
+				end
+				self:_tell("People in "..self.room._properties.name..":\n"..table.concat(p, ","));
+			end,
+	allwho =	function (self, e)
+				local p = {};
+				for jid, t in pairs(people) do
+					table.insert(p, t.nick.." ("..jid..") in "..t.room._properties.name.."\n");
+				end
+				PSay(e.room, e.nick, " ", "People in MOO:\n"..table.concat(p, ","));
+			end,
+	_say = 	function (self, text, who)
+				BroadcastMessage(self.room.people, self.nick , text, who);
+			end,
+	_action =	function (self, text, who)
+				return self:_say("/me "..text, who);
+			end,
+	_tell = 	function (self, text)
+				SendMessage(self.jid, self.occjid, text or "", "groupchat");
+			end,
+	i = 		function (self, e)
+				local contents = {};
+				local contents2 = {};
+				contents = self._contents["in"]:getallobjects();
+				for o, exists in pairs(contents) do
+					table.insert(contents2, o._properties.longname or o._properties.name or "Something");
+				end
+				self:_tell("You are carrying: "..table.concat(contents2,", "));
+			end,
+	jump = function (self, e) self:_action("jumps"); end
+};
+
+
+function occupant:_processCommand(line)
+	person = self;
+	
+	if line:match("^%..*$") then BroadcastMessage(person.room.people, person.nick, line:match("^%.%s?(.*)$")); return nil; end
+	if line:match("^,.*$") then person:_action(line:match("^,%s?(.*)$")); return nil; end
+	action, object = commands:_parse(self, line); -- line:match("^(%a+)%s(%a+)$");
+	if commands:_handle(self, action, object) == false then person:_tell(string.format("Sorry, I don't know how you can '%s'",line)); end
+end
+
+occupant._findobject = classes.default._findobject;
+occupant._get = classes.default._get;
+occupant._unlink = classes.default._unlink;
+
+function occupant:_sendto(roomname)
+	MoveToRoom(self, roomname);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/def_room.lua	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,74 @@
+
+classes.obj_room =
+{
+	_properties = {};
+	_create = function (self, e)
+				self.people = {}; self._objects = createcontainertable(); self._properties.name = e.room; self._properties.server = e.server; self.jid = e.room.."@"..e.server;
+				if type(tpl_rooms[e.room]) == "table" then
+					for k, v in pairs(tpl_rooms[e.room]) do
+						self[k] = v;
+					end
+					return self._init and self._init(self, e);
+				end
+			end,
+	_addobject = 	function (self, e)
+					if e.class then self._objects:add(e.class:_create{room = self, name = e.name, ext = e }); end
+				end,
+	_addalias = 	function (self, e)
+					for k, v in ipairs(e) do
+						self._objects:addalias(e[1], v);
+					end
+				end,
+	_enter = 	function (self, e)
+				PSay(e.room, e.nick, " ", "You have entered "..(e.room._properties.longname or e.room._properties.name or "the room"));
+			end,
+	_findobject=function (self, tag)
+				if not tag then return nil; end
+				tag = tag:match("^the (.*)$") or tag;
+				return self._objects:findobject(tag);
+			end,
+	look =	function (self, e)
+				local contents = {};
+				local contents2 = {};
+				contents = self._objects:getallobjects();
+				for o, exists in pairs(contents) do
+					table.insert(contents2, o._properties.longname or o._properties.name or "Something");
+				end
+				
+				e.person:_tell("You see in this room: "..table.concat(contents2,", "));
+			end,
+	obj = function (self, e)
+				local contents = {};
+				local contents2 = {};
+				contents = self._objects:getallobjects();
+				for o, exists in pairs(contents) do
+					table.insert(contents2, (o._properties.longname or o._properties.name or "Something")..(" ("..o._properties.name or "No name")..")");
+				end
+				
+				e.person:_tell("You see in this room: \n"..table.concat(contents2,"\n"));
+			end,
+	teleport = function (self, e)
+				if not e.param or #(e.param) == 0 then PSay(e.room, e.nick, " ", "Teleport to where exactly?"); end
+				MoveToRoom(e.person, e.param);
+			end,
+	where =	function (self, e)
+				PSay(e.room, e.nick, " ", "You are in "..e.room._properties.name);
+			end
+}
+
+function classes.obj_room:_unlink(o)
+	if not self._objects then print("Attempt to _unlink from an empty room."); return nil; end
+	if type(o) == "string" then o = self._objects:findobject(o); end
+	if (not o) or (o._properties and o._properties.static == true) then return false; end
+	if self._objects:remove(o) then
+		return true;
+	end
+end
+
+function classes.obj_room:_get(i)
+	if not self._objects then self._objects = createcontainertable(); end
+	if not i.container:_unlink(i.object) then return false; end
+	print("room _get", self._properties.name or "o");
+	self._objects:add(i.object);
+	return true;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/editing.lua	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,42 @@
+
+classes_editable = setmetatable({}, {__mode = "v", __index = function (t, k) return GetEditableClass(k) or {}; end, __newindex = function (t, k, v) return SaveEditableClass(k, v); end });
+moobox = moobox or {};
+
+--Load it from file
+function GetEditableClass(name)
+	local subenv = { classes = { } }
+	local classdefinition = loadfile("objects/"..param..".lua");
+	setfenv(classdefinition, subenv);
+	local success, message = pcall(classdefinition);
+	if not success then return message or "Unkown error reading class"
+	else return subenv.class; end
+end
+
+--Save it to file
+function SaveEditableClass(name, t)
+	function writetable(filename, t)
+		local f = io.open(filename, "w+");
+		if not f then return nil; end
+		for k, v in pairs(t) do
+			if type(v) == "string" then
+				f:write(string.format("class[\"%s\"] = \"%s\";\n", k, v));
+			end
+		end
+	end
+	
+	local success, message = pcall(writetable, string.format("editor/%s.dat", name), t);
+	if not success then return message; end
+	return nil;
+end
+
+--Compile (and the compiled class goes to classes[name]
+function CompileEditableClass(t)
+	if not t then return "Error compiling... no (or invalid) class specified"; end
+	local compiled = {};
+	for k, v in pairs(t) do
+		local success, compiledverb = pcall(loadstring, v);
+		if not success then return "Error compiling verb '"..k.."': "..(compiledverb or "Unkown error"); end
+		compiled[k] = (compiledverb and setfenv(compiledverb, verbbox)) or nil;
+	end
+	return compiled;
+end
\ No newline at end of file
Binary file luacomponent has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/luacomponent.cpp	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,365 @@
+// g++ -Wall -O2 -pipe -march=i686 "%f" /usr/local/lib/libgloox.so /usr/lib/liblua5.1.so
+#include </usr/local/include/gloox/gloox.h>
+#include </usr/local/include/gloox/client.h>
+#include </usr/local/include/gloox/clientbase.h>
+#include </usr/local/include/gloox/messagehandler.h>
+#include </usr/local/include/gloox/tag.h>
+#include </usr/local/include/gloox/stanza.h>
+#include </usr/local/include/gloox/connectionlistener.h>
+#include </usr/local/include/gloox/presencehandler.h>
+#include </usr/local/include/gloox/component.h>
+
+extern "C" {
+#include <lua.h>
+#include <lualib.h>
+#include <lauxlib.h>
+}
+
+using namespace gloox;
+
+lua_State *L = NULL;
+lua_State *calcL = NULL;
+char BotName[26];
+class Bot* theBot = NULL;
+
+int lcJoinMUC(lua_State* L);
+int lcSleep(lua_State* L);
+int lcMemUsage(lua_State* L);
+int lcSendPresence(lua_State* L);
+int lcSendMessage(lua_State* L);
+
+class Bot : public MessageHandler, ConnectionListener , PresenceHandler, LogHandler
+{
+ public:
+   Bot()
+   {
+   	::theBot = this;
+   	lua_getglobal(L, "BotPass");
+	if(!lua_isstring(L, -1))
+	{
+		printf("Please, in the body of the script, set BotJID, BotPass, and BotName!\n");
+		return;
+	}
+      // JID jid( lua_tostring(L, -3) );
+      j = new Component ( "jabber:component:accept", "localhost", "xmoo", "secret", 5347);
+
+      j->registerConnectionListener( this );
+      j->registerMessageHandler( this );
+      j->registerPresenceHandler( this );
+      j->logInstance().registerLogHandler( LogLevelDebug, LogAreaAll, this );
+      // j->setInitialPriority( 5 );
+      // j->setAutoPresence( true );
+      printf("Connecting...\n");
+      j->connect();
+   }
+
+   virtual void handleMessage( Stanza *stanza, MessageSession *session )
+   {
+		if(stanza->findChildWithAttrib("xmlns","jabber:x:delay"))
+		{
+			printf("History message, ignoring.\n");
+			return;
+		}
+		
+		printf("Message.\n");
+			    /* push functions and arguments */
+		lua_getglobal(L, "onMessage");  /* function to be called */
+		if(!lua_isfunction(L, -1))
+		{
+			printf("Unhandled message... please add an onMessage function to the script\n");
+			return;
+		}
+		lua_newtable(L);
+		lua_pushstring(L, stanza->body().c_str());
+		lua_setfield(L,-2, "body");
+		lua_pushstring(L, stanza->from().full().c_str());
+		lua_setfield(L,-2, "fromFull");
+		lua_pushstring(L, stanza->from().bare().c_str());
+		lua_setfield(L,-2, "fromBare");
+		lua_pushstring(L, stanza->to().full().c_str());
+		lua_setfield(L,-2, "to");
+		lua_pushnumber(L, stanza->subtype());
+		lua_setfield(L,-2, "type");
+	
+		/* do the call (1 argument, 1 result) */
+		if (lua_pcall(L, 1, 1, 0) != 0)
+		{
+			printf("Error running function `onMessage': %s",lua_tostring(L, -1));
+			return;
+		}
+		if(lua_istable(L, -1))
+		{
+			Tag *t = new Tag( "message" );
+			
+			lua_getfield(L, -1, "type");
+			t->addAttribute( "type", luaL_optlstring(L, -1, "chat", NULL) );
+			lua_pop(L,1);
+			lua_getfield(L, -1, "to");
+			t->addAttribute( "to", luaL_optlstring(L, -1, stanza->from().bare().c_str(), NULL )); // 
+			lua_pop(L,1);
+			lua_getfield(L, -1, "from");
+			t->addAttribute( "from", luaL_optlstring(L, -1, j->jid().full().c_str(), NULL ));
+			lua_pop(L,1);
+			lua_getfield(L, -1, "body");
+			t->addChild( new Tag( "body", luaL_optlstring(L, -1, "", NULL) ) );
+			lua_pop(L,1);
+			j->send( t ); // Send it!
+		}
+	
+		
+	}
+   
+	virtual void onConnect()
+	{
+		// do something when the connection is established
+	printf("Connecting...");
+	if(L)
+	{
+		lua_pushinteger(L, StanzaMessageChat);
+		lua_setglobal(L, "MSG_CHAT");
+		lua_pushinteger(L, StanzaMessageGroupchat);
+		lua_setglobal(L, "MSG_GROUPCHAT");
+		lua_pushinteger(L, StanzaMessageNormal);
+		lua_setglobal(L, "MSG_NORMAL");
+		lua_pushinteger(L, StanzaMessageError);
+		lua_setglobal(L, "MSG_ERROR");
+		
+		lua_pushinteger(L, StanzaPresenceError);
+		lua_setglobal(L, "PRE_ERROR");
+		lua_pushinteger(L, StanzaPresenceAvailable);
+		lua_setglobal(L, "PRE_AVAILABLE");
+		lua_pushinteger(L, StanzaPresenceUnavailable);
+		lua_setglobal(L, "PRE_UNAVAILABLE");
+
+		lua_register(L, "JoinMUC", lcJoinMUC);
+		lua_register(L, "Sleep", lcSleep);
+		lua_register(L, "MemUsage", lcMemUsage);
+		lua_register(L, "SendPresence", lcSendPresence);
+		lua_register(L, "SendMessage", lcSendMessage);
+	}
+	else
+		printf("Lua not loaded?!\n");
+	
+	 printf("Connected.\n");
+	 
+	 		lua_getglobal(L, "onConnect");  /* function to be called */
+		if(!lua_isfunction(L, -1))
+		{
+			printf("No onConnect() function found.\n");
+			return;
+		}
+		
+		/*Tag *t = new Tag( "presence" );
+		t->addAttribute( "to", "test@conference.jabber.org/Betty" );
+		t->addChild(new Tag( "status", "Betty!" ) );
+		j->send( t ); */
+	
+		/* do the call (0 arguments, 0 results) */
+		if (lua_pcall(L, 0, 0, 0) != 0)
+			return; // error(L, "error running function `f': %s",lua_tostring(L, -1));
+     
+	}
+	
+	virtual void handlePresence( Stanza * stanza)
+	{
+				printf("Presence.\n");
+			    /* push functions and arguments */
+		lua_getglobal(L, "onPresence");  /* function to be called */
+		if(!lua_isfunction(L, -1))
+			return;
+			
+		lua_newtable(L);
+		lua_pushstring(L, stanza->body().c_str());
+		lua_setfield(L,-2, "body");
+		lua_pushstring(L, stanza->from().full().c_str());
+		lua_setfield(L,-2, "fromFull");
+		lua_pushstring(L, stanza->from().bare().c_str());
+		lua_setfield(L,-2, "fromBare");
+		lua_pushstring(L, stanza->to().full().c_str());
+		lua_setfield(L,-2, "to");
+		lua_pushnumber(L, stanza->subtype());
+		lua_setfield(L,-2, "ntype");
+		lua_pushstring(L, stanza->findAttribute("type").c_str());
+		lua_setfield(L,-2, "type");
+		
+		
+	
+		/* do the call (1 arguments, 0 results) */
+		if (lua_pcall(L, 1, 0, 0) != 0)
+		{
+			printf("Error running function `onPresence': %s",lua_tostring(L, -1));
+			return;
+		}
+		return;
+	}
+
+	virtual bool onTLSConnect( const CertInfo& info )
+	{
+		// decide whether you trust the certificate, examine the CertInfo structure
+		// It's not like a bot is bothered with this :)
+		return true; // if you trust it, otherwise return false
+	}
+	
+	virtual void onDisconnect(gloox::ConnectionError e)
+	{
+		std::string msg;
+		if (e == ConnStreamError)
+		{
+			
+		}
+		switch(e)
+		{
+			case ConnStreamError:
+				msg = j->streamErrorText();
+				break;
+			case ConnIoError:
+				msg = "An I/O error occured";
+				break;
+			default:
+				msg = "Unknown error";
+		}
+		printf("Disconnected: %s\n", msg.c_str());
+	}
+	
+	virtual void handleLog( LogLevel level, LogArea area, const std::string & message)
+	{
+		printf("Log: %s\n", message.c_str());
+	}	
+	
+ public:
+   Component* j;
+};
+
+
+int main( int argc, char* argv[] )
+{
+	L = lua_open();   /* opens Lua */
+	if(L == NULL)
+	{
+		printf("Unable to initialize Lua.\n");
+		exit(1);
+	}
+	else
+	{
+		
+	}
+	luaL_openlibs(L);
+	if(luaL_dofile(L, "bot.lua"))
+	{
+		printf("Unable to load/run the bot file\n\t%s\n", lua_tostring(L, -1));
+		exit(1);
+	}
+	else
+		printf("File loaded successfully.\n");
+	
+	Bot b;
+}
+
+int lcJoinMUC(lua_State* L)
+{
+	printf("Joining MUC...\n");
+	if(!lua_isstring(L,1))
+	{
+		printf("Ooops, not passed a string :(\n");
+		return 0;
+	}
+	Tag *t = new Tag( "presence" );
+	t->addAttribute( "to", lua_tostring(L, 1) );
+	if (lua_isstring(L, 2))
+		t->addAttribute( "type", lua_tostring(L, 2) );
+	
+	// t->addChild("status", "Betty!");
+	t->addChild(new Tag( "status", "" ) );
+	printf(t->xml().c_str() );
+	theBot->j->send( t );
+	// 
+	printf("Conference (%s) joined.\n",lua_tostring(L, 1));
+	return 0;
+}
+
+int lcLeaveMUC(lua_State* L)
+{
+	if(!lua_isstring(L,1))
+	{
+		printf("Ooops, not passed a string :(\n");
+		return 0;
+	}
+	Tag *t = new Tag( "presence" );
+	t->addAttribute( "to", lua_tostring(L, 1) );
+	t->addAttribute( "type", "unavailable" );
+	t->addChild(new Tag( "status", "" ) );
+	theBot->j->send( t );
+	printf("Conference (%s) joined.\n",lua_tostring(L, 1));
+	return 0;
+}
+
+int lcSleep(lua_State* L)
+{
+	sleep((int)lua_tonumber(L, 1));
+	return 0;
+}	
+
+int lcMemUsage(lua_State* L)
+{
+	lua_pushinteger(L, lua_gc(L, LUA_GCCOUNT, 0));
+	return 1;
+}
+
+// function SendPresence(to, type, text[, from]);
+int lcSendPresence(lua_State* L)
+{
+	if(!lua_isstring(L,1))
+	{
+		printf("Ooops, not passed a string :(\n");
+		// lua_error(L, 
+		return 0;
+	}
+	Tag *t = new Tag( "presence" );
+	t->addAttribute( "to", lua_tostring(L, 1) );
+	if (lua_isstring(L, 2))
+		t->addAttribute( "type", lua_tostring(L, 2) );
+	else
+		t->addAttribute( "type", "available" );
+	
+	if (lua_isstring(L, 3))
+		t->addChild(new Tag( "status", lua_tostring(L, 3) ) );	
+	else
+		t->addChild(new Tag( "status", "" ) );
+	
+	if (lua_isstring(L, 4))
+		t->addAttribute( "from", lua_tostring(L, 4) );
+	
+	t->addChild(new Tag("x", "xmlns", "http://jabber.org/protocol/muc#user"));
+			
+	theBot->j->send( t );
+	return 0;
+}
+
+int lcSendMessage(lua_State* L)
+{
+	if(!lua_isstring(L,1))
+	{
+		printf("Ooops, not passed a string :(\n");
+		// lua_error(L, 
+		return 0;
+	}
+	Tag *t = new Tag( "message" );
+	t->addAttribute( "to", lua_tostring(L, 1) );
+	
+	if (lua_isstring(L, 2))
+		t->addAttribute( "from", lua_tostring(L, 2) );
+	
+	if (lua_isstring(L, 3))
+		t->addChild(new Tag( "body", lua_tostring(L, 3) ) );	
+	else
+		t->addChild(new Tag( "body", "" ) );
+	
+	if (lua_isstring(L, 4))
+		t->addAttribute( "type", lua_tostring(L, 4) );
+	else
+		t->addAttribute( "type", "normal" );
+	
+			
+	theBot->j->send( t );
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mt_object.lua	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,6 @@
+
+mt_object = {};
+
+function mt_object.__newindex(t, k, v)
+	setmetatable(v, { __index = _parent; });
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/muc.lua	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,173 @@
+--[[ Lua XMPP MOO Component by Matthew Wild (MattJ)					]]
+
+BotName = "Component";
+BotPass = "";
+
+function onPresence(msg)
+	success, message = pcall(handlePresence, msg);
+	if not success then print("\nERROR: "..message.."\n"); end
+end
+
+function onConnect()
+end
+
+function onMessage(msg)
+	success, message = pcall(handleMessage, msg);
+	if not success then print("\nERROR: "..message.."\n"); end
+end
+
+
+function handlePresence(msg)
+	local room, server, nick, id, person;
+	room,server,nick = msg.to:match("^(.+)@(.+)/(.+)$");
+	if not (room and nick) then print("\nERROR: Invalid room or nick!\n"); return; end -- We need to send an error
+	-- print("Type: "..msg.type.." type of type: "..type(msg.type),"\n");
+	if msg.type == "available" or msg.type == "" and not people[msg.fromFull] then
+		print("\nRecieved Available presence to join a room\n");
+		people[msg.fromFull] = { ["nick"] = nick, ["jid"] = msg.fromFull, ["presence"] = msg.type, room = rooms[room], occjid = msg.to, _parent = occupant, group = {}, _contents = { ["in"] = createcontainertable(); } }
+		MoveToRoom(people[msg.fromFull], room);
+		-- rooms[room].people[nick] = people[msg.fromFull];
+		--for id, person in pairs(rooms[room].people) do
+		--	SendPresence(msg.fromFull, person.presence, "", room.."@"..server.."/"..person.nick);
+		--end
+	elseif msg.type == "unavailable" then
+		RemoveFromRoom(rooms[room], msg.fromFull);
+		people[msg.fromFull] = nil;
+	end
+	print("Returning\n");
+	SendPresence(msg.fromFull, msg.type, "", msg.to);
+end
+
+
+
+function handleMessage(msg)
+	local action, object, room, server, person;
+	person = people[msg.fromFull]
+	if msg.type == MSG_ERROR then print("ERROR MESSAGE from "..msg.fromFull..": ", msg.body); return nil; end
+	if not person then print("No such person as "..msg.fromFull, tostring(people[msg.fromFull]).."\n"); 
+	for k,v in pairs(people) do print(string.format("people[\"%s\"]", k),", "); end return nil; end
+	room, server = msg.to:match("^(.+)@(.+)$");
+	if not (room and server) then print("ERROR! Malformed JID? "..msg.to.."\n"); return nil; end --TODO: Reply with error
+	server = server:lower();
+	if not rooms[room] then return; end -- TODO: Reply with error
+	
+	person:_processCommand(msg.body);
+
+	return nil;
+end
+
+function BroadcastPresence(people, fromnick, ptype, text)
+	local nick, t;
+	if type(people) == "string" then if not rooms[people] then print("No room called '"..people.."'","\n"); return; else print("\nLooking up room: "..people, "\n"); people = rooms[people].people; end end
+	if not people then print("No such room. \n"); return; end
+	for nick, t in pairs(people) do
+		if t and t.jid then 
+			SendPresence(t.jid, ptype or "available", text or "", GetJIDParts(t.occjid).node.."@"..GetJIDParts(t.occjid).server.."/"..fromnick);
+		else print("\nOrphaned occupant: "..nick, "\n");
+		end
+	end
+end
+
+function BroadcastMessage(people_, from, text, mtype, sender_sees)
+	local nick, t
+	for nick, t in pairs(people_) do
+		print("\nMessage sent to: "..t.jid);
+		if t.nick ~= from or sender_sees ~= false then 
+			SendMessage(t.jid, GetJIDParts(t.occjid).node.."@"..GetJIDParts(t.occjid).server.."/"..from, text or "", mtype or "groupchat");
+		end
+	end
+	print("\nDone\n");
+end
+
+function GetOccupantNick(jid)
+	local pjid, p
+	for pjid, p in pairs(people) do
+		if CompareJIDs(pjid, jid) then return p.nick; end
+	end
+	return "Somebody";
+end
+
+function CompareJIDs(j1, j2)
+	if not (j1 and j2) then return false; end
+	print("j2: "..type(j2));
+	j1node, j1server, j1res = j1:match("^(.+)@([%a%.]+)/?(.*)$");
+	j2node, j2server, j2res = j2:match("^(.+)@([%a%.]+)/?(.*)$");
+	if j1node == j2node and j1server:lower() == j2server:lower() and (j1res == j2res or j1res == "" or j2res == "") then return true; end
+	return false;
+end
+
+function MoveToRoom(person, room)
+	if not ( person and room) then return; end
+		
+	if type(room) ~= "table" then
+		if not rooms[room] then rooms[room] = CreateObject(classes.obj_room); rooms[room]:_create{ room = room, server = GetJIDParts(person.occjid).server}; end
+		 room = rooms[room];
+	end
+	
+	if person.room ~= room then
+		if person.room then
+			-- Tell everyone in room that user is leaving
+			--BroadcastPresence(person.room.people, person.occjid, "unavailable");
+			for nick, t in pairs(person.room.people) do
+				-- print(string.format("\nPRESENCE: to: %s, from: %s, type: %s\n", t.jid, ));
+				if nick ~= person.nick then
+					SendPresence(t.jid, "unavailable", "", GetJIDParts(t.occjid).node.."@"..GetJIDParts(t.occjid).server.."/"..person.nick);
+				end
+			end
+			-- Tell user that everyone else in the room has gone (clear room roster in their client)
+			for nick, t in pairs(person.room.people) do
+				if person.nick ~= nick then
+					SendPresence(person.jid, "unavailable", "", GetJIDParts(person.occjid).node.."@"..person.room._properties.server.."/"..t.nick);
+				end
+			end
+			person.room.people[person.nick] = nil; -- Remove from room
+		end
+	end
+	person.room = room;
+	room.people[person.nick] = person;
+	--Tell user about people in the new room
+	for nick, t in pairs(person.room.people) do
+		-- print(string.format("\nPRESENCE: to: %s, from: %s, type: %s\n", t.jid, ));
+		if nick ~= person.nick then
+			SendPresence(person.jid, "available", "", GetJIDParts(person.occjid).node.."@"..GetJIDParts(person.occjid).server.."/"..nick);
+		end
+	end
+	--Tell people in new room that user has joined
+	-- BroadcastPresence(person.room.people, person.nick, "available");
+	for nick, t in pairs(person.room.people) do
+		-- print(string.format("\nPRESENCE: to: %s, from: %s, type: %s\n", t.jid, ));
+		if nick ~= person.nick then
+			SendPresence(t.jid, "available", "", GetJIDParts(t.occjid).node.."@"..GetJIDParts(t.occjid).server.."/"..person.nick);
+		end
+	end
+	SendPresence(person.jid, "available", "", person.occjid);
+	room:_enter{ room = person.room, person = person, nick = person.nick };
+end
+
+function RemoveFromRoom(room, jid)
+	if not ( room and jid) then return; end
+	for id, t in pairs(room.people) do
+		if CompareJIDs(t.jid, from) then room.people[id] = nil; end
+	end
+	-- Tell everyone in room that user is leaving
+	for nick, t in pairs(room.people) do
+			SendPresence(t.jid, "unavailable", "", GetJIDParts(t.occjid).node.."@"..GetJIDParts(t.occjid).server.."/"..people[jid].nick);
+	end
+end
+
+function FSay(room, fromnick, text)
+	BroadcastMessage(room.people, fromnick , text);
+end
+
+function PSay(room, tonick, fromnick, text)
+	--print(string.format("Room JID: %s, To: %s, From: %s\n", room.jid, tonick, fromnick));
+	for k,v in pairs(room.people) do print(string.format("people[\"%s\"]", k),", "); end
+	print("\n");
+	-- room.jid..(((fromnick and fromnick:len() > 0) and "/"..fromnick) or "")
+	SendMessage(room.people[tonick].jid, room.people[tonick].occjid, text or "", (fromnick and fromnick:len() > 0 and "groupchat") or "groupchat");
+end
+
+dofile("common.lua");
+
+rooms = rooms or { };
+people = people or setmetatable({ default = {} }, { __newindex = function (t, k, v) if not rawget(v, "_parent") then rawset(v, "_parent", rawget(t, "default")); end return rawset(t, k, setmetatable(v, { __index = occupant })); end }); -- This is our inheritance code;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/objects/obj_banner.lua	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,17 @@
+
+classes.obj_banner = {
+					_properties = { name = "banner", longname = "a banner with writing", desc = "You see a brightly coloured banner hung across the wall, with writing on it. Maybe you should READ it?" }
+				}
+				
+
+function classes.obj_banner:_create(e)
+	local obj = classes.default._create(self, e);
+	obj._properties.text = e.ext.text;
+	return obj;
+end
+
+function classes.obj_banner:read(e)
+	if not self._properties.text then e.person:_tell("It's blank after all!"); return; end
+	e.person:_action("reads the writing on the banner");
+	e.person:_tell("The banner says '"..self._properties.text.."'");
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/objects/obj_bar.lua	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,16 @@
+--[[
+A bar. No, no free drinks!
+
+by Manole Paul-Sebastian (brokenthorn)
+]]
+
+classes.obj_bar =
+{
+	_properties = { name = "bar", longname = "a large bar", desc = "You get closer to the bar and the bartender asks if you want a drink." };
+	_parent = nil;
+	sit		=	function (self, e)
+					e.person:_say("/me pulls a chair");
+					e.person:_say("/me sits quietly at the bar");
+					-- bartender should ask if he/she wants a drink here...
+				end,
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/objects/obj_box.lua	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,9 @@
+
+classes.obj_box = { 
+				_properties =	{
+								name = "box",
+								longname = "a cardboard box",
+								desc = "You see a plain, ordinary, medium-sized cardboard box"
+							},
+				_parent = "obj_container";
+			};
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/objects/obj_cat.lua	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,22 @@
+
+-- This is an example of one way of coding a class, using the { } constructor, see the fireplace for another method
+
+classes.obj_cat =
+{
+	_properties = { name = "cat", longname = "a mother cat", desc = "You see at a furry object curled up in a corner. It watches comers and goers to this room as they pass." },
+	stroke =	function (self, e)
+				e.person:_say("/me strokes the "..self._properties.name); -- This message is said by the person who stroked the cat
+				self:_say("/me purrs softly"); -- This message is said by 'self' which means the current object, the cat
+			end,
+			
+	kill = 	function (self, e)
+				e.person:_say("/me tries to hurt the cat");
+				self:_say("/me runs away before "..e.person.nick.." can catch it");
+				self:_say("Meeooooww!!!!");
+			end,
+			
+	hug =	function (self, e)
+				e.person:_say("/me hugs the cat");
+				self:_say("/me likes "..e.person.nick);
+			end
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/objects/obj_container.lua	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,14 @@
+
+classes.obj_container = { 
+				_properties =	{
+								name = "container",
+								longname = "a container",
+								desc = "You see an ordinary container"
+							},
+			};
+			
+function classes.obj_container:_create(e)
+	local obj = classes.default._create(self, e);
+	obj._contents = { ["in"] = createcontainertable() };
+	return obj;
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/objects/obj_cupboard.lua	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,9 @@
+
+classes.obj_cupboard = { 
+				_properties =	{
+								name = "cupboard",
+								longname = "a cupboard",
+								desc = "You see a large cupboard"
+							},
+				_parent = "obj_container";
+			};
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/objects/obj_door.lua	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,18 @@
+
+classes.obj_door =
+{
+	_properties = {name = "door", longname = "a door", desc = "You see a doorway, through which you can enter.", static = true }
+}
+
+function classes.obj_door:_create(e)
+	local obj = classes.default._create(self, e);
+	obj._properties.to = e.ext.to;
+	obj._properties.longname = e.ext.longname;
+	return obj;
+end
+
+function classes.obj_door:enter(e)
+	if not self._properties.to then e.person:_tell("You find it physically impossible to pass through the doorway!"); end
+	e.person:_say("/me enters "..self._properties.longname);
+	e.person:_sendto(self._properties.to);
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/objects/obj_drinking_tables.lua	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,14 @@
+--[[
+Tables to sit at in the bar or anywhere else
+
+by Manole Paul-Sebastian (brokenthorn)
+]]
+
+classes.obj_drinking_tables =
+{
+	_properties = { name = "tables", longname = "some drinking tables", desc = "You see some uninteresting, uncloathed drinking tables." };
+	_parent = nil;
+	sit		=	function (self, e)
+					e.person:_say("/me pulls a chair and sits at one of the drinking tables");
+				end,
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/objects/obj_drinks.lua	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,18 @@
+
+--[[
+A general 'drinks' object
+
+by Manole Paul-Sebastian (brokenthorn)
+]]
+
+classes.obj_window =
+{
+	_properties = { name = "drinks", longname = "various drinks", desc = "You see various drinks in various containers." };
+	_parent = nil;	
+
+	drink	=	function (self, e)
+					e.person:_say("/me drinks"); -- too simple message?
+				end,
+
+	-- other functions that could be writen: 'taste','buy','sell','open'
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/objects/obj_fireplace.lua	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,14 @@
+
+-- This is an example of one way of coding a class, using the { } constructor, see the cat for another method
+
+classes.obj_fireplace =
+{
+	_properties = { name = "fire", longname = "an ornate fireplace", desc = "You see a decorative fireplace, in which a warming fire is burning.", static = true };
+	_parent = nil; -- This class inherits methods and properties from no other class (except classes.default). If you don't set _parent, this is the default
+}
+
+function classes.obj_fireplace:touch(e)
+				e.person:_say("/me touches the fire", false); -- Everyone else in the room will see this, user will not
+				e.person:_say("Oouuchhh!!!!"); -- By default, all see the message
+				e.person:_tell("That hurt!"); -- Only the user sees this
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/objects/obj_kitten.lua	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,6 @@
+
+classes.obj_kitten =
+{
+	_properties = {name = "kitten", longname = "a small furry kitten", desc = "You see a tiny sleeping kitten curled up close to its mother" },
+	_parent = "obj_cat";
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/objects/obj_oven.lua	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,21 @@
+
+classes.obj_oven = { 
+				_properties =	{
+								name = "oven",
+								longname = "an oven",
+								desc = "You see a large oven, with various knobs and switches. It looks quite obvious how to TURN ON though :)"
+							},
+				_parent = "obj_container";
+			};
+			
+classes.obj_oven["turn on"] = function (self, e)
+	if self._properties.power == "on" then e.person:_tell("The oven is already on!"); end
+	self._properties.power = "on";
+	e.person:_action("switches on the oven");
+end
+
+classes.obj_oven["turn off"] = function (self, e)
+	if self._properties.power ~= "on" then e.person:_tell("The oven is already off!"); end
+	self._properties.power = "off";
+	e.person:_action("switches off the oven");
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/objects/obj_small_chair.lua	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,15 @@
+--[[
+A small, simple chair, though it wouldn't be too smart to sit on one of these for too long... :)
+
+by Manole Paul-Sebastian (brokenthorn)
+]]
+
+classes.obj_small_chair =
+{
+	_properties = { name = "chair", longname = "a simple round chair", desc = "You look at the little chair. It's not exactly confortable but if there's nothing else you can sit on..." };
+	_parent = objcat_chairs;	-- I think there's need for a general category for each general type of object (eg. you can sit on most chairs, usually) :Paul
+					-- I don't know how to do that and link the specific functions here... :Paul
+	move		=	function (self, e)
+					e.person:_say("/me pulls the small chair near");
+				end,
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/objects/obj_toaster.lua	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,9 @@
+
+classes.obj_toaster = { 
+				_properties =	{
+								name = "toaster",
+								longname = "a toaster",
+								desc = "You see a toaster, which looks currently unusable"
+							},
+				_parent = classes.obj_container;
+			};
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/objects/obj_window.lua	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,32 @@
+
+--[[
+A simple window object.
+I coded this after the example 'fireplace' and 'cat' objects but they won't show up in SOO in room d2 or any other.
+I don't know how to store the window open or not property yet.
+
+by Manole Paul-Sebastian (brokenthorn)
+]]
+
+classes.obj_window =
+{
+	_properties = { name = "window", longname = "a large wooden window", desc = "You look at the large wooden window and you can see almost anything going on outside." };
+	_parent = nil;	
+
+	kill		=	function (self, e)
+					e.person:_say("/me tries to break the window");
+					self:_say("/me is unbreakable. Must be break-proof... Hehee ;)");
+				end,
+
+	close	=	function (self, e)
+					e.person:_say("/me tries to close the "..self._properties.name);
+					self:_say("/me closes with a loud creak!");
+				end,
+}
+
+function	classes.obj_window:open(e)
+				e.person:_say("/me opens the window", false);
+				self:_say("/me opens quietly");
+end
+
+classes.obj_window["break"] = classes.obj_window.kill;
+classes.obj_window.smash = classes.obj_window.kill;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readme	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,56 @@
+# XMOO Readme file.
+
+#Creating a new class
+In this example, we will create a torch.
+
+Start with the line:
+	classes.obj_torch = { } -- This creates an empty object
+
+What you call the class does not matter, it is not visible to users.
+
+Now we must define some things, such as its name, and what it looks like, its properties.
+
+	classes.obj_torch._properties = {
+								name = "torch",
+								longname = "An electric torch",
+								desc = "A small portable electric torch, to help you see when it is dark"
+							}
+							
+Simple, eh? :)
+
+Now, we want the user to be able to do things with the torch, let's say that 'twisting' it, switches it on and off.
+So we must define the method 'twist':
+
+	function classes.obj_torch:twist(info)
+		
+	end
+
+info is a variable we get, that contains information useful to use, such as who twisted it (info.person), and what room we are in (info.room), etc.
+
+Now we must also keep track of whether the torch is lit or unlit. We will store this as a property. In a method, 'self' always refers to the curent object.
+
+	function classes.obj_torch:twist(info)
+		if self._properties.state == "lit" then self._properties.state == "unlit" -- if it is lit, make it unlit
+		else self._properties.state == "lit" end -- Otherwise, make it lit
+	end
+
+Very good, but we must show everyone in the room what is going on:
+
+	function classes.obj_torch:twist(info)
+		if self._properties.state == "lit" then 
+			self._properties.state == "unlit" -- if it is lit, make it unlit
+			self._properties.desc = "A small portable electric torch, to help you see when it is dark. It is not lit."
+			info.person:_say("/me turns off the torch")
+		else
+			self._properties.state == "lit" -- Otherwise, make it lit
+			self._properties.desc = "A small portable electric torch, to help you see when it is dark. It is lit."
+			info.person:_say("/me lights the torch")
+		end 
+	end
+
+As you can see, the colon ':' is used to call methods, or functions of another object. Remember that people are objects too!
+The default 'look' method uses the 'desc' property, so we have changed it, to show whether the torch is lit or not.
+
+It's done!
+
+More to come, including creating new rooms :)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rooms.lua	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,3 @@
+dofile("rooms/lounge.lua");
+dofile("rooms/d2.lua");
+dofile("rooms/kitchen.lua");
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rooms/d2.lua	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,13 @@
+tpl_rooms.d2 = { }; -- _properties = { longname = "a testing room" }
+
+function tpl_rooms.d2:_init(e)
+	self._properties.longname = "a testing room";
+	self:_addobject({room = e.room, class = classes.obj_cat, name = "cat"});
+	self:_addobject({room = e.room, class = classes.obj_kitten, name = "kitten"});
+	self:_addobject({ room = self, class = classes.obj_fireplace, name = "fire"});
+	self:_addalias({"fire", "fireplace"});
+	self:_addobject({ room = self, class = classes.obj_correctvs, name = "correctvs"});
+	self:_addalias({"correctvs", "pencase"});
+	self:_addobject({room = self, class = classes.obj_window, name = "window"});
+	self:_addobject({ class = classes.obj_door, name = "door", longname = "the door to the lounge", to = "lounge" });
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rooms/kitchen.lua	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,9 @@
+tpl_rooms.kitchen = {}; -- Creates an empty room
+
+function tpl_rooms.kitchen:_init(e)
+	self._properties.longname = "the kitchen";
+	self:_addobject({ class = classes.obj_oven, name = "oven"}); -- 0121 6241270
+	self:_addobject({ class = classes.obj_toaster, name = "toaster"});
+	self:_addobject({ class = classes.obj_cupboard, name = "cupboard"});
+	self:_addobject({ class = classes.obj_door, name = "door", longname = "the door to the lounge", to = "lounge" });
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rooms/lounge.lua	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,20 @@
+tpl_rooms.lounge = {};
+
+function tpl_rooms.lounge:_init(e)
+	self._properties.longname = "the lounge";
+	self:_addobject({ class = classes.obj_cat, name = "cat"});
+	self:_addobject({ class = classes.obj_small_chair, name = "small chair"});
+	self:_addobject({ class = classes.obj_kitten, name = "kitten"});
+	self:_addobject({ class = classes.obj_fireplace, name = "fire"});
+	self:_addobject({ class = classes.obj_box, name = "box"});
+	self:_addobject({ class = classes.obj_banner, text = "Happy Birthday MattJ!" });
+	self:_addobject({ class = classes.obj_door, name = "door", longname = "the door to the testing room", to = "d2" });
+	self:_addobject({ class = classes.obj_door, name = "kitchen", longname = "the door to the kitchen", to = "kitchen" });
+	self:_addalias({"correctvs", "pencase"});
+	self:_addalias({"fire", "fireplace"}); -- Deprecated!!!!
+end
+
+function tpl_rooms.lounge:_enter(e)
+	classes.obj_room._enter(self, e);
+	e.person:_tell("An unseen force draws your attention to a banner on the wall...");
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/soo.lua	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,88 @@
+--[[ Lua XMPP MOO Component by Matthew Wild (MattJ)					]]
+
+function onMessage(msg)
+	success, message = pcall(handleMessage, msg);
+	if not success then print("\nERROR: "..message.."\n"); end
+end
+
+function handleMessage(msg)
+	local action, object, room, server, person;
+	person = people[msg.fromFull]
+	room = people["local"].room._properties.name;
+	if not person then print("No such person as "..msg.fromFull, tostring(people[msg.fromFull]).."\n"); end
+	if not rooms[room] then return; end
+
+	person:_processCommand(msg.body);
+	
+	return nil;
+end
+
+function GetOccupantNick(jid)
+	local pjid, p
+	for pjid, p in pairs(people) do
+		if CompareJIDs(pjid, jid) then return p.nick; end
+	end
+	return "user";
+end
+
+function CompareJIDs(j1, j2)
+	return j1 == j2;
+end
+
+function MoveToRoom(person, room)
+	if not ( person and room) then print("Error, can't move person to room, invalid args"); return; end
+	if type(room) ~= "table" then
+		if not rooms[room] then rooms[room] = CreateObject(classes.obj_room, room); rooms[room]:_create{ room = room, server = "" }; end
+		 room = rooms[room];
+	end
+	
+	if person.room ~= room then
+		if person.room then
+			person.room.people[person.nick] = nil; -- Remove from room
+		end
+	end
+	person.room = room;
+	--table.print("rooms", rooms);
+	room.people[person.nick] = person;
+	room:_enter{ room = person.room, person = person, nick = person.nick };
+end
+
+function RemoveFromRoom(room, jid)
+	if not ( room and jid) then return; end
+	for id, t in pairs(room.people) do
+		room.people[id] = nil;
+	end
+end
+
+function BroadcastMessage(people_, from, text, mtype, sender_sees)
+	print("\n|>>"..from..": "..text);
+end
+
+function FSay(room, fromnick, text)
+	if text and fromnick then print("\n|>>"..fromnick..": "..text); end
+end
+
+function SendMessage(to, from, text, type)
+	if to == "local" then print("\n>>"..from..": "..text);
+	else print("\n|>>"..(from or "")..": "..text); end
+end
+
+function PSay(room, tonick, fromnick, text)
+		print("\n>>"..fromnick..": "..text);
+end
+
+dofile("common.lua");
+
+rooms = rooms or { };
+people = people or { ["local"] = setmetatable({ nick = "user", group = {} }, { __index = occupant }); };
+people["local"]._contents = { ["in"] = createcontainertable(); };
+
+
+-- Single user --
+
+if not people["local"].room then MoveToRoom(people["local"],"lounge"); end
+io.write("\n> ");
+for line in io.lines() do
+	onMessage({ fromFull = "local", body = line });
+io.write("\n> ");
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/svn-commit.tmp	Sat Mar 27 17:43:08 2010 +0000
@@ -0,0 +1,5 @@
+Trying to fix problems with some clients joining
+--This line, and those below, will be ignored--
+
+M    luacomponent.cpp
+M    luacomponent

mercurial