/**
* This is the Refresh Handler. When a player refreshes or
* gets deleted, this handler is called upon, so that all the
* miscellaneous bookkeeping about that player can be reset.
* This should be used for taking someone out of the playtesters'
* group, resetting their criminal status, etc. Everything,
* in short, which is not a property on the player object or otherwise
* can be handled entirely by the player object without using any other
* objects.
*
* If you have code that stores information about a player outside of
* the player object, then you should call register_delete() on this
* handler. That will then remember the function you give it.
* Then, whenever a player refreshes or deletes, the function you
* specified will get called with a string with the player
* name. Do the right thing.
*
* If your object moves to a different file, then you will
* have to manually unregister the object from the refresh
* handler. This is very important! To unregister, simply
* call register_delete() again, with the same object, but
* give 0 for the function.
*
* Each object can have only one refresh function registered,
* and clones can't have any!
*
* The callback functions should be in the form of -
* void callback_func( string player )
*
* @author Sin
*
* @change 17 Nov 1998, Sin
* Handles deletions now, too.
* @change 04 Aug 2001, Sandoz
* Stripped all the refresh stuff and left only one type of deletion.
* Fixed a few things regarding removing callback functions.
*/
#include <playerinfo.h>
#include <origin.h>
#define SAVE_FILE "/save/refresh"
mapping delete_callbacks;
/** @ignore yes */
protected void save_me() {
unguarded( (: save_object, SAVE_FILE, 0 :) );
} /* save_me() */
/** @ignore yes */
/* This is used to make the player info handler happy */
string query_name() { return "Refresh Handler"; }
/** @ignore yes */
void create() {
seteuid( master()->creator_file( file_name(TO) ) );
unguarded( (: restore_object, SAVE_FILE :) );
if( !delete_callbacks )
delete_callbacks = ([ ]);
} /* create() */
/** @ignore yes */
void dest_me() {
destruct(TO);
} /* dest_me() */
/**
* Use this function to tell the refresh handler about functions that
* you want to have called whenever any player refreshes or gets
* deleted.
*
* Typically, you will call this by hand, with the 'call' command,
* rather than coding a call to this function into your code.
*
* The first parameter is the object that contains the callback
* to be called. This can be either a pointer to the object, or
* the filename to the object.
*
* The second parameter is the name of the function that should be
* called. This callback should take one parameter: a string
* containing the player's name who's data is being deleted.
*
* This function will refuse to register a callback if either:
* the object is a clone, the callback isn't defined in the object, or
* the callback is a function pointer.
* @see unregister_delete()
*/
string register_delete( mixed ob, string func ) {
object real;
if( objectp(ob) ) {
if( !ob = base_name(ob) )
return "Please supply an object.";
}
if( !real = load_object(ob) )
return "Couldn't find the object.";
if( !func || !function_exists( func, real ) )
return "Couldn't find the callback function.";
if( !undefinedp( delete_callbacks[ob] ) && delete_callbacks[ob] == func )
return "Callback function already registered.";
delete_callbacks[ob] = func;
save_me();
return "Delete callback function successfully added.";
} /* register_delete() */
/**
* This method unregisters a deletion call back function.
* @param ob the object to remove
* @param fun the function to remove
* @return 1 upon success, 0 upon failure
*/
int unregister_delete( string ob, string fun ) {
if( adminp( previous_object(-1) ) &&
!undefinedp( delete_callbacks[ob] ) && delete_callbacks[ob] == fun ) {
map_delete( delete_callbacks, ob );
save_me();
return 1;
}
return 0;
} /* unregister_delete() */
/**
* This method goes through and calls all the registered deletion
* callbacks. The parameter passed to the deletion callbacks is
* a string containing the name of the player who is being deleted.
*/
void player_deleted( string player ) {
string ob;
if( origin() != ORIGIN_LOCAL &&
file_name(PO) != BULK_DELETE_H ) {
return;
}
foreach( ob in keys( delete_callbacks ) ) {
object obj;
catch( obj = load_object(ob) );
if( !obj ) {
log_file("BAD_DEL_CALLBACK", "File : %s, Function : %s\n",
ob, delete_callbacks[ob] );
continue;
}
call_out( (: call_other, obj, ({ delete_callbacks[ob], player }) :), 1 );
}
} /* player_deleted() */
/**
* This function gets called by the player object whenever
* a player refreshes. You should never call this function directly.
*/
void player_refreshed( object player ) {
if( !player || base_name(PO) != PLAYER_OBJ )
return;
// Slip an event into their playerinfo.
PLAYERINFO_HANDLER->add_entry( TO, player->query_name(), "refresh",
"They did a full refresh.", 0 );
// Delete their stuff.
player_deleted( player->query_name() );
} /* player_refreshed() */
/**
* This method returns the current list of deletion callback functions.
* @return the current list of deletion callback functions
*/
mapping query_delete_callbacks() { return delete_callbacks; }
/** @ignore yes */
mixed stats() {
return map( sort_array( keys( delete_callbacks ), 1 ),
(: ({ $1, $2[$1] }) :), delete_callbacks );
} /* stats() */