Acme-MUDLike

 view release on metacpan or  search on metacpan

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

      my $hex;
      ($hex) = $item =~ m{^[a-z][a-z_:]+\((0x[0-9a-z]+)\)}i;
      $hex or ($hex) = $item =~ m{^0x([0-9a-z]+)}i;
      if($hex) {
          $ob = Devel::Pointer::deref(hex($hex));
      }
    };
    return $ob;
}

# actions

sub _call {
    my $self = shift;
    # XXX call a method an in object
    # XXX call sword name 
    my $item = shift;
    my $func = shift;
    my @args = @_; # XXX for each arg, go through the item finding code below, except keep identify if not found
    my $ob = $self->item_by_arg($item) or do {
        $self->tell_object("call: no item by that name/number/package name here");
        return;
    };
    for my $i (0..$#args) {
        my $x = $self->item_by_arg($args[$i]);
        $args[$i] = $x if $x;
    }
    $ob->can($func) or do {
        $self->tell_object("call:  item ``$item'' has no ``$func'' method");
        return;
    };
    $self->tell_object(join '', "Call: ", eval { $ob->can($func)->($ob, @args); } || "Error: ``$@''.");
    1;
}

sub _list {
    my $self = shift;
    my $i = 0;
    $self->tell_object(join '', 
        "Here, you see:\n", 
        map qq{$_\n}, 
        map { $i . ': ' . $_ }
        $self->environment->contents, $self->inventory->contents,
    ); 
}

sub _mark {
    my $self = shift;
    my $item = shift;
    my $ob = $self->item_by_arg($item) or do {
        $self->tell_object("mark: no item by that name/number/package name here");
        return;
    };
    $self->current_item = $ob;
}

sub _eval {
    my $self = shift;
    my $cmd = join ' ', @_;
    no warnings 'redefine';
    # *print = sub { $self->tell_object(@_); };  # this doesn't work reliablely due to possible context changes but worth a shot
    # *say = sub { $self->tell_object("@_\n"); }; # ack... doesn't work at all.
    select $self->request->{request}->{conn};  # would rather it went into their message buffer but comprimising for now
    my $res = eval($cmd) || "Error: ``$@''.";
    $self->tell_object("eval:\n$res");
}

sub _who {
    my $self = shift;
    $self->_look(@_); # for now
}

sub _look {
    my $self = shift;
    my @args = @_;
    # $self->tell_object(join '', "Here, you see:\n", map qq{$_\n}, map $_->name, $floor->contents); 
    $self->tell_object(join '', 
        "Here, you see:\n", 
        map qq{$_\n}, 
        map { $_->can('name') ? $_->name : ref($_) }
        $self->environment->contents
    ); 
}

sub _inv {
    my $self = shift;
    $self->_inventory(@_);
}

sub _i {
    my $self = shift;
    $self->_inventory(@_);
}

sub _inventory {
    my $self = shift;
    my @args = @_;
    $self->tell_object(join '', 
        "You are holding:\n", 
        map qq{$_\n}, 
        map { $_->can('name') ? $_->name : ''.$_ } 
        $self->inventory->contents
    ); 
}

sub _take {
    my $self = shift;
    my @args = @_;
    if(@args == 1) {
        # take thingie
        my $item = $floor->delete($args[0]) or do { $self->tell_object("No ``$args[0]'' here."); return; };
        $self->inventory->insert($item);
        $self->tell_object(qq{Taken.});
    } elsif(@args == 2) {
        $self->tell_object("I don't understand ``$args[0] $args[1]''.");
    } elsif(@args == 3) {
        if($args[1] ne 'from') {
            $self->tell_object("I don't understand ``$args[1] $args[2]''.");
            return;
        }
        my $container = $floor->named($args[2]) or do { $self->tell_object("No ``$args[2]'' here."); return; };

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

=item C<continuity>

Optional.  Pass in an existing L<Continuity> instance.
Must have been created with the parameter  C<< path_session => 1 >>.

=item C<port>

Optional.  Defaults to C<2000>.
This and other parameters, such as those documented in L<Continuity>, are passed through
to C<< Continuity->new() >>.

=item C<password>

Optional.  Password to use.
Everyone gets the same password, and anyone with the password can log in with any name.
Otherwise one is pseudo-randomly generated and printed to C<stdout>.

=cut

=head1 HISTORY

=over 8

=item 0.01

Original version; created by h2xs 1.23 with options

  -A -C -X -b 5.8.0 -c -n Acme::MUDLike

=back

=head1 TODO

(Major items... additional in the source.)

=item Test.  Very, very green right now.

=item Telnet in as well as HTTP.

=item JavaScript vi/L<Acme::SubstituteSubs> integration.

=item Multiple rooms.  Right now, there's just one.

The JavaScript based vi and file browser I've been using with L<Acme::SubstituteSubs> isn't in any of my modules 
yet so development from within isn't really practical using just these modules. 
There's some glue missing.

=head1 SEE ALSO

=item L<Continuity>

=item L<Continuity::Monitor>

=item L<Acme::State>

=item  L<Acme::SubstituteSubs>

L<Acme::State> preserves state across runs and L<Acme::SubstituteSubs>.
These three modules work on their own but are complimentary to each other.
Using L<Acme::SubstituteSubs>, the program can be modified in-place without being restarted,
so you don't have to log back in again after each change batch of changes to the code.
Code changes take effect immediately.
L<Acme::State> persists variable values when the program is finally stopped and restarted.
L<Acme::State> will also optionally serialize code references to disc, so you can
C<eval> subs into existance and let it save them to disc for you and then later
use L<B::Deparse> to retrieve a version of the source.

The C<Todo> comments near the top of the source.

=head1 AUTHOR

Scott Walters, E<lt>scott@slowass.netE<gt>

=head1 COPYRIGHT AND LICENSE

Copyright (C) 2009 by Scott Walters

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.9 or,
at your option, any later version of Perl 5 you may have available.
By using this software, you signify that you like llamas.

Includes code by John Resig:

 jQuery 1.1.2 - New Wave Javascript

 Copyright (c) 2007 John Resig (jquery.com) 
 Dual licensed under the MIT (MIT-LICENSE.txt)
 and GPL (GPL-LICENSE.txt) licenses.

 $Date: 2007-02-28 12:03:00 -0500 (Wed, 28 Feb 2007) $
 $Rev: 1465 $

Includes code by Awwaiid (Brock Wilcox)

=cut

package Acme::MUDLike::data;

sub chat_js {

return <<'EOF';

var poll_count = 0;

function new_request() {
  var req;
  if (window.XMLHttpRequest) {
    req = new XMLHttpRequest();
  } else if (window.ActiveXObject) {
    req = new ActiveXObject("Microsoft.XMLHTTP");
  } 
  return req;
}

function do_request(url, callback) {
  var req = new_request();
  if(req != undefined) {
    req.onreadystatechange = function() {
      if (req.readyState == 4) { // only if req is "loaded"
        if (req.status == 200) { // only if "OK"
          if(callback) callback(req.responseText);
        } else {
          alert("AJAX Error:\r\n" + req.statusText);
        }
      }
    }
    req.open("GET", url, true);
    req.send("");
  }
}

function setup_poll() {
   setTimeout('poll_server()', 1000);
}

function poll_server() {
  var nick = document.getElementById("nick").value;
  var admin = document.getElementById("admin").value;
  document.getElementById('status').innerHTML = 'Polling ('+(poll_count++)+')...';
  do_request('/pushstream/?nick=' + nick + '&admin=' + admin, got_update);
}

function got_update(txt) {
  document.getElementById('status').innerHTML = 'Got update.'
  if(document.getElementById("log").innerHTML != txt)
    document.getElementById("log").innerHTML = txt;
  setup_poll();
}

// This stuff gets executed once the document is loaded
$(function(){
  // Start up the long-pull cycle
  setup_poll();
  // Unobtrusively make submitting a message use send_message()
  $('#f').submit(send_message);
});

// We also send messages using AJAX
function send_message() {
  var nick = $('#nick').val();
  var admin = $('#admin').val();
  var message = $('#message').val();
  $('#log').load('/sendmessage', {
    nick:     nick,
    admin:    admin,
    action:   'ajaxchat',
    message:  message
  }, function() {
    $('#message').val('');
    $('#message').focus();
  });
  return false;
}

EOF

}

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

			// If we actually just moused on to a sub-element, ignore it
			if ( p == this ) return false;
			
			// Execute the right function
			return (e.type == "mouseover" ? f : g).apply(this, [e]);
		}
		
		// Bind the function to the two event listeners
		return this.mouseover(handleHover).mouseout(handleHover);
	},
	ready: function(f) {
		// If the DOM is already ready
		if ( jQuery.isReady )
			// Execute the function immediately
			f.apply( document, [jQuery] );
			
		// Otherwise, remember the function for later
		else {
			// Add the function to the wait list
			jQuery.readyList.push( function() { return f.apply(this, [jQuery]) } );
		}
	
		return this;
	}
});

jQuery.extend({
	/*
	 * All the code that makes DOM Ready work nicely.
	 */
	isReady: false,
	readyList: [],
	
	// Handle when the DOM is ready
	ready: function() {
		// Make sure that the DOM is not already loaded
		if ( !jQuery.isReady ) {
			// Remember that the DOM is ready
			jQuery.isReady = true;
			
			// If there are functions bound, to execute
			if ( jQuery.readyList ) {
				// Execute all of them
				jQuery.each( jQuery.readyList, function(){
					this.apply( document );
				});
				
				// Reset the list of functions
				jQuery.readyList = null;
			}
			// Remove event lisenter to avoid memory leak
			if ( jQuery.browser.mozilla || jQuery.browser.opera )
				document.removeEventListener( "DOMContentLoaded", jQuery.ready, false );
		}
	}
});

new function(){

	jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
		"mousedown,mouseup,mousemove,mouseover,mouseout,change,select," + 
		"submit,keydown,keypress,keyup,error").split(","), function(i,o){
		
		// Handle event binding
		jQuery.fn[o] = function(f){
			return f ? this.bind(o, f) : this.trigger(o);
		};
			
	});
	
	// If Mozilla is used
	if ( jQuery.browser.mozilla || jQuery.browser.opera )
		// Use the handy event callback
		document.addEventListener( "DOMContentLoaded", jQuery.ready, false );
	
	// If IE is used, use the excellent hack by Matthias Miller
	// http://www.outofhanwell.com/blog/index.php?title=the_window_onload_problem_revisited
	else if ( jQuery.browser.msie ) {
	
		// Only works if you document.write() it
		document.write("<scr" + "ipt id=__ie_init defer=true " + 
			"src=//:><\/script>");
	
		// Use the defer script hack
		var script = document.getElementById("__ie_init");
		
		// script does not exist if jQuery is loaded dynamically
		if ( script ) 
			script.onreadystatechange = function() {
				if ( this.readyState != "complete" ) return;
				this.parentNode.removeChild( this );
				jQuery.ready();
			};
	
		// Clear from memory
		script = null;
	
	// If Safari  is used
	} else if ( jQuery.browser.safari )
		// Continually check to see if the document.readyState is valid
		jQuery.safariTimer = setInterval(function(){
			// loaded and complete are both valid states
			if ( document.readyState == "loaded" || 
				document.readyState == "complete" ) {
	
				// If either one are found, remove the timer
				clearInterval( jQuery.safariTimer );
				jQuery.safariTimer = null;
	
				// and execute any waiting functions
				jQuery.ready();
			}
		}, 10); 

	// A fallback to window.onload, that will always work
	jQuery.event.add( window, "load", jQuery.ready );
	
};

// Clean up after IE to avoid memory leaks
if (jQuery.browser.msie)
	jQuery(window).one("unload", function() {
		var global = jQuery.event.global;
		for ( var type in global ) {
			var els = global[type], i = els.length;
			if ( i && type != 'unload' )
				do
					jQuery.event.remove(els[i-1], type);
				while (--i);
		}
	});
jQuery.fn.extend({
	loadIfModified: function( url, params, callback ) {
		this.load( url, params, callback, 1 );
	},
	load: function( url, params, callback, ifModified ) {
		if ( jQuery.isFunction( url ) )
			return this.bind("load", url);

		callback = callback || function(){};

		// Default to a GET request
		var type = "GET";

		// If the second parameter was provided
		if ( params )
			// If it's a function
			if ( jQuery.isFunction( params ) ) {
				// We assume that it's the callback

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

		async: true,
		data: null
	},
	
	// Last-Modified header cache for next request
	lastModified: {},
	ajax: function( s ) {
		// TODO introduce global settings, allowing the client to modify them for all requests, not only timeout
		s = jQuery.extend({}, jQuery.ajaxSettings, s);

		// if data available
		if ( s.data ) {
			// convert data if not already a string
			if (s.processData && typeof s.data != "string")
    			s.data = jQuery.param(s.data);
			// append data to url for get requests
			if( s.type.toLowerCase() == "get" ) {
				// "?" + data or "&" + data (in case there are already params)
				s.url += ((s.url.indexOf("?") > -1) ? "&" : "?") + s.data;
				// IE likes to send both get and post data, prevent this
				s.data = null;
			}
		}

		// Watch for a new set of requests
		if ( s.global && ! jQuery.active++ )
			jQuery.event.trigger( "ajaxStart" );

		var requestDone = false;

		// Create the request object
		var xml = new XMLHttpRequest();

		// Open the socket
		xml.open(s.type, s.url, s.async);

		// Set the correct header, if data is being sent
		if ( s.data )
			xml.setRequestHeader("Content-Type", s.contentType);

		// Set the If-Modified-Since header, if ifModified mode.
		if ( s.ifModified )
			xml.setRequestHeader("If-Modified-Since",
				jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );

		// Set header so the called script knows that it's an XMLHttpRequest
		xml.setRequestHeader("X-Requested-With", "XMLHttpRequest");

		// Make sure the browser sends the right content length
		if ( xml.overrideMimeType )
			xml.setRequestHeader("Connection", "close");
			
		// Allow custom headers/mimetypes
		if( s.beforeSend )
			s.beforeSend(xml);
			
		if ( s.global )
		    jQuery.event.trigger("ajaxSend", [xml, s]);

		// Wait for a response to come back
		var onreadystatechange = function(isTimeout){
			// The transfer is complete and the data is available, or the request timed out
			if ( xml && (xml.readyState == 4 || isTimeout == "timeout") ) {
				requestDone = true;
				
				// clear poll interval
				if (ival) {
					clearInterval(ival);
					ival = null;
				}
				
				var status;
				try {
					status = jQuery.httpSuccess( xml ) && isTimeout != "timeout" ?
						s.ifModified && jQuery.httpNotModified( xml, s.url ) ? "notmodified" : "success" : "error";
					// Make sure that the request was successful or notmodified
					if ( status != "error" ) {
						// Cache Last-Modified header, if ifModified mode.
						var modRes;
						try {
							modRes = xml.getResponseHeader("Last-Modified");
						} catch(e) {} // swallow exception thrown by FF if header is not available
	
						if ( s.ifModified && modRes )
							jQuery.lastModified[s.url] = modRes;
	
						// process the data (runs the xml through httpData regardless of callback)
						var data = jQuery.httpData( xml, s.dataType );
	
						// If a local callback was specified, fire it and pass it the data
						if ( s.success )
							s.success( data, status );
	
						// Fire the global callback
						if( s.global )
							jQuery.event.trigger( "ajaxSuccess", [xml, s] );
					} else
						jQuery.handleError(s, xml, status);
				} catch(e) {
					status = "error";
					jQuery.handleError(s, xml, status, e);
				}

				// The request was completed
				if( s.global )
					jQuery.event.trigger( "ajaxComplete", [xml, s] );

				// Handle the global AJAX counter
				if ( s.global && ! --jQuery.active )
					jQuery.event.trigger( "ajaxStop" );

				// Process result
				if ( s.complete )
					s.complete(xml, status);

				// Stop memory leaks
				if(s.async)
					xml = null;
			}
		};
		
		// don't attach the handler to the request, just poll it instead
		var ival = setInterval(onreadystatechange, 13); 

		// Timeout checker
		if ( s.timeout > 0 )
			setTimeout(function(){
				// Check to see if the request is still happening
				if ( xml ) {
					// Cancel the request
					xml.abort();

					if( !requestDone )
						onreadystatechange( "timeout" );
				}
			}, s.timeout);
			
		// Send the data
		try {
			xml.send(s.data);
		} catch(e) {
			jQuery.handleError(s, xml, null, e);
		}
		
		// firefox 1.5 doesn't fire statechange for sync requests
		if ( !s.async )
			onreadystatechange();
		
		// return XMLHttpRequest to allow aborting the request etc.
		return xml;
	},

	handleError: function( s, xml, status, e ) {
		// If a local callback was specified, fire it
		if ( s.error ) s.error( xml, status, e );

		// Fire the global callback
		if ( s.global )
			jQuery.event.trigger( "ajaxError", [xml, s, e] );
	},

	// Counter for holding the number of active queries
	active: 0,

	// Determines if an XMLHttpRequest was successful or not
	httpSuccess: function( r ) {
		try {
			return !r.status && location.protocol == "file:" ||
				( r.status >= 200 && r.status < 300 ) || r.status == 304 ||
				jQuery.browser.safari && r.status == undefined;
		} catch(e){}
		return false;
	},

	// Determines if an XMLHttpRequest returns NotModified
	httpNotModified: function( xml, url ) {
		try {
			var xmlRes = xml.getResponseHeader("Last-Modified");

			// Firefox always returns 200. check Last-Modified date
			return xml.status == 304 || xmlRes == jQuery.lastModified[url] ||
				jQuery.browser.safari && xml.status == undefined;
		} catch(e){}
		return false;
	},

	/* Get the data out of an XMLHttpRequest.
	 * Return parsed XML if content-type header is "xml" and type is "xml" or omitted,
	 * otherwise return plain text.
	 * (String) data - The type of data that you're expecting back,
	 * (e.g. "xml", "html", "script")
	 */
	httpData: function( r, type ) {
		var ct = r.getResponseHeader("content-type");
		var data = !type && ct && ct.indexOf("xml") >= 0;
		data = type == "xml" || data ? r.responseXML : r.responseText;

		// If the type is "script", eval it in global context
		if ( type == "script" )
			jQuery.globalEval( data );

		// Get the JavaScript object, if JSON is used.
		if ( type == "json" )
			eval( "data = " + data );

		// evaluate scripts within html
		if ( type == "html" )



( run in 3.411 seconds using v1.01-cache-2.11-cpan-0fb53d1c279 )