Acme-MUDLike

 view release on metacpan or  search on metacpan

lib/Acme/MUDLike.pm  view on Meta::CPAN

    if(! $item ) {
        $self->tell_object("Failed to load object: ``$@''.");
        return;
    }
    # XXX force an inheritance of object onto it if it doesn't already have one?
    $self->inventory->insert($item);
    $self->tell_object("Ok.");
}

sub _dest {
    my $self = shift;
    my @args = @_;
    if(@args != 1) {
        $self->tell_object(qq{Dest what?});
        return;
    }
    $self->inventory->delete($args[0]) or do { $self->tell_object("You don't have a ``$args[0]''."); return; };
    $self->tell_object("Dest: Ok.");
}


=head1 NAME

Acme::MUDLike - Hang out inside of your application

=head1 SYNOPSIS

    use Acme::MUDLike; 
    my $server = Acme::MUDLike->new;

    # ... your code here

    $server->loop;  # or call the Event or AnyEvent event loop

Connect to the URL provided and cut and paste into the text box:

    /eval package sword; our @ISA = qw/Acme::MUDLike::object/; sub new { my $pack = shift; $pack->SUPER::new(name=>"sword", @_); }
    /clone sword
    /i
    /call sword name
    wee, fun!  oh, hai everyone!
    /eval no strict "refs"; join '', map "$_\n", keys %{"main::"};
    /call Acme::MUDLike::player=HASH(0x8985e10) name

=head1 DESCRIPTION

Multi user chat, general purpose object tracer, eval, and give/drop/take/clone/dest/look.

Adds a social element to software development and develop it from within.
Chat within the application, eval code inside of it (sort of like a simple Read-Eval-Parse Loop).
Call methods in objects from the command line.
Create instances of objects, give them to people, drop them on the floor.

The idea is take the simple command line interface and extend it with more commands,
and to create tools and helper objects that inspect and modify the running program from within.

It fires up a Continuity/HTTP::Daemon based Web server on port 2000 and prints out a login
URL on the command line.
Paste the URL into your browser.
Chat with other users logged into the app.
Messages beginning with a slash, C</>, are interpreted as commands:

=over 2

=item C<< /look >> 

See who else and what else is in the room.

=item C<< /mark >>

  /mark 1

  /mark torch

  /mark foo::bar

  /mark 0x812ea54

Select an object as the logical current object by name, package name, number (as a position in your
inventory list, which is useful for when you've cloned an object that does not define an C<id> or C<name> function),
or by memory address (as in C<< Foo::Bar=HASH(0x812ea54) >>).

=item C<< /call >> 

Call a function in an object; eg, if you're holding a C<toaster>, you can write:

  /call toaster add_bread 1

The special name "current" refers to the current object, as marked with mark.

=item C<< /eval >>

Executes Perl.
C<< $self >> is your own player object.
C<< $self->inventory >> is an C<< Acme::MUDLike::inventory >> object with C<delete>, C<insert>, C<named>,
C<apply>, and C<contents> methods.
C<< $self->environment >> is also an C<< Acme::MUDLike::inventory >> object holding you and other players 
and objects in the room.
The environment and players in it all have C<tell_object> methods that takes a string to add to their
message buffer.
Calling C<tell_object> in the environment sends the message to all players.
Objects define various other methods.

=item C<< /who >>

List of who is logged in.  Currently the same C</look>.

=item C<< /inventory >>

Or C</i> or C</inv>.  Lists the items you are carrying.

=item C<< /clone >>

Creates an instance of an object given a package name.  Eg:

  /clone sword

=item C<< /take >>

Pick up an item from the floor (the room) and place it in your inventory.
Or alternatively C<< /take item from player >> to take something from someone.

lib/Acme/MUDLike.pm  view on Meta::CPAN

		/^(>|\/)/, "jQuery.sibling(a.firstChild)",
		/^(\+)/, "jQuery.nth(a,2,'nextSibling')",
		/^(~)/, function(a){
			var s = jQuery.sibling(a.parentNode.firstChild);
			return s.slice(jQuery.inArray(a,s) + 1);
		}
	],

	multiFilter: function( expr, elems, not ) {
		var old, cur = [];

		while ( expr && expr != old ) {
			old = expr;
			var f = jQuery.filter( expr, elems, not );
			expr = f.t.replace(/^\s*,\s*/, "" );
			cur = not ? elems = f.r : jQuery.merge( cur, f.r );
		}

		return cur;
	},
	find: function( t, context ) {
		// Quickly handle non-string expressions
		if ( typeof t != "string" )
			return [ t ];

		// Make sure that the context is a DOM Element
		if ( context && !context.nodeType )
			context = null;

		// Set the correct context (if none is provided)
		context = context || document;

		// Handle the common XPath // expression
		if ( !t.indexOf("//") ) {
			context = context.documentElement;
			t = t.substr(2,t.length);

		// And the / root expression
		} else if ( !t.indexOf("/") ) {
			context = context.documentElement;
			t = t.substr(1,t.length);
			if ( t.indexOf("/") >= 1 )
				t = t.substr(t.indexOf("/"),t.length);
		}

		// Initialize the search
		var ret = [context], done = [], last = null;

		// Continue while a selector expression exists, and while
		// we're no longer looping upon ourselves
		while ( t && last != t ) {
			var r = [];
			last = t;

			t = jQuery.trim(t).replace( /^\/\//i, "" );

			var foundToken = false;

			// An attempt at speeding up child selectors that
			// point to a specific element tag
			var re = /^[\/>]\s*([a-z0-9*-]+)/i;
			var m = re.exec(t);

			if ( m ) {
				// Perform our own iteration and filter
				jQuery.each( ret, function(){
					for ( var c = this.firstChild; c; c = c.nextSibling )
						if ( c.nodeType == 1 && ( jQuery.nodeName(c, m[1]) || m[1] == "*" ) )
							r.push( c );
				});

				ret = r;
				t = t.replace( re, "" );
				if ( t.indexOf(" ") == 0 ) continue;
				foundToken = true;
			} else {
				// Look for pre-defined expression tokens
				for ( var i = 0; i < jQuery.token.length; i += 2 ) {
					// Attempt to match each, individual, token in
					// the specified order
					var re = jQuery.token[i];
					var m = re.exec(t);

					// If the token match was found
					if ( m ) {
						// Map it against the token's handler
						r = ret = jQuery.map( ret, jQuery.isFunction( jQuery.token[i+1] ) ?
							jQuery.token[i+1] :
							function(a){ return eval(jQuery.token[i+1]); });

						// And remove the token
						t = jQuery.trim( t.replace( re, "" ) );
						foundToken = true;
						break;
					}
				}
			}

			// See if there's still an expression, and that we haven't already
			// matched a token
			if ( t && !foundToken ) {
				// Handle multiple expressions
				if ( !t.indexOf(",") ) {
					// Clean the result set
					if ( ret[0] == context ) ret.shift();

					// Merge the result sets
					jQuery.merge( done, ret );

					// Reset the context
					r = ret = [context];

					// Touch up the selector string
					t = " " + t.substr(1,t.length);

				} else {
					// Optomize for the case nodeName#idName
					var re2 = /^([a-z0-9_-]+)(#)([a-z0-9\\*_-]*)/i;
					var m = re2.exec(t);
					
					// Re-organize the results, so that they're consistent



( run in 3.271 seconds using v1.01-cache-2.11-cpan-e1769b4cff6 )