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 )