# HG changeset patch # User Matthew Wild # Date 1269711788 0 # Node ID cc66ad6b0d752da14c51e4d7b27ef510d63df53b Initial commit (importing from old SVN repo which got lost) diff -r 000000000000 -r cc66ad6b0d75 AUTHORS diff -r 000000000000 -r cc66ad6b0d75 COPYING diff -r 000000000000 -r cc66ad6b0d75 ChangeLog --- /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 + +------------------------------------------------------------------------ diff -r 000000000000 -r cc66ad6b0d75 INSTALL diff -r 000000000000 -r cc66ad6b0d75 MUD 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 @@ + /home/matthew/dev/xmud/bot.lua + /home/matthew/dev/xmud/obj_cat.lua + /home/matthew/dev/xmud/occupant.lua + /home/matthew/dev/xmud/obj_room.lua + /home/matthew/dev/xmud/obj_fireplace.lua diff -r 000000000000 -r cc66ad6b0d75 README --- /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 diff -r 000000000000 -r cc66ad6b0d75 TODO --- /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 ' 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 is + 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... diff -r 000000000000 -r cc66ad6b0d75 bot.lua --- /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; diff -r 000000000000 -r cc66ad6b0d75 classes.lua --- /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 diff -r 000000000000 -r cc66ad6b0d75 commands.lua --- /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 diff -r 000000000000 -r cc66ad6b0d75 common.lua --- /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 diff -r 000000000000 -r cc66ad6b0d75 containertables.inc.lua --- /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 diff -r 000000000000 -r cc66ad6b0d75 def_object.lua --- /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 diff -r 000000000000 -r cc66ad6b0d75 def_occupant.lua --- /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, " ", ""); + 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 diff -r 000000000000 -r cc66ad6b0d75 def_room.lua --- /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 diff -r 000000000000 -r cc66ad6b0d75 editing.lua --- /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 diff -r 000000000000 -r cc66ad6b0d75 luacomponent Binary file luacomponent has changed diff -r 000000000000 -r cc66ad6b0d75 luacomponent.cpp --- /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 +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" { +#include +#include +#include +} + +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; +} diff -r 000000000000 -r cc66ad6b0d75 mt_object.lua --- /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 diff -r 000000000000 -r cc66ad6b0d75 muc.lua --- /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; diff -r 000000000000 -r cc66ad6b0d75 objects/obj_banner.lua --- /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 diff -r 000000000000 -r cc66ad6b0d75 objects/obj_bar.lua --- /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 diff -r 000000000000 -r cc66ad6b0d75 objects/obj_box.lua --- /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 diff -r 000000000000 -r cc66ad6b0d75 objects/obj_cat.lua --- /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 +} diff -r 000000000000 -r cc66ad6b0d75 objects/obj_container.lua --- /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 diff -r 000000000000 -r cc66ad6b0d75 objects/obj_cupboard.lua --- /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 diff -r 000000000000 -r cc66ad6b0d75 objects/obj_d2door.lua diff -r 000000000000 -r cc66ad6b0d75 objects/obj_door.lua --- /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 diff -r 000000000000 -r cc66ad6b0d75 objects/obj_drinking_tables.lua --- /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 diff -r 000000000000 -r cc66ad6b0d75 objects/obj_drinks.lua --- /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 diff -r 000000000000 -r cc66ad6b0d75 objects/obj_fireplace.lua --- /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 diff -r 000000000000 -r cc66ad6b0d75 objects/obj_kitten.lua --- /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 diff -r 000000000000 -r cc66ad6b0d75 objects/obj_oven.lua --- /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 diff -r 000000000000 -r cc66ad6b0d75 objects/obj_small_chair.lua --- /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 diff -r 000000000000 -r cc66ad6b0d75 objects/obj_toaster.lua --- /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 diff -r 000000000000 -r cc66ad6b0d75 objects/obj_window.lua --- /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 diff -r 000000000000 -r cc66ad6b0d75 readme --- /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 diff -r 000000000000 -r cc66ad6b0d75 rooms.lua --- /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 diff -r 000000000000 -r cc66ad6b0d75 rooms/d2.lua --- /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 diff -r 000000000000 -r cc66ad6b0d75 rooms/kitchen.lua --- /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 diff -r 000000000000 -r cc66ad6b0d75 rooms/lounge.lua --- /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 diff -r 000000000000 -r cc66ad6b0d75 soo.lua --- /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 diff -r 000000000000 -r cc66ad6b0d75 svn-commit.tmp --- /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