/**
* This is the organizations handler.
* Keeps track of organizations, their members and other properties.
* @author Sandoz
*/
#define SAVE_FILE HANDLER_SAVE_DIR "/orgs"
#define TIME ctime(time())
#define CHECK_TIME 86400
#define DATA ( ( class org_data ) orgs[name] )
class org_data {
string info; // general info about the organization
string title; // the official title of the organization
string *req_orgs; // any orgs one has to be a memeber of to join
string *anti_orgs; // any orgs one can't be a member of to join
string *req_quests; // any quests one needs to do before joining
string channel;
}
private mapping orgs, members;
private void check_members( string name );
private void check_all_members();
/** @ignore yes */
private void create() {
if( file_size( SAVE_FILE+".o" ) > 0 )
unguarded( (: restore_object, SAVE_FILE :) );
if( !mapp(orgs) )
orgs = ([ ]);
if( !mapp(members) )
members = ([ ]);
if( sizeof( keys(orgs) ) )
call_out( (: check_all_members :), 300 + random( 300 ) );
} /* create() */
/** @ignore yes */
private void save_data_file() {
unguarded( (: save_object, SAVE_FILE :) );
} /* save_data_file() */
/** @ignore yes */
void dest_me() {
destruct(TO);
} /* dest_me() */
/**
* This method returns all the current orgs.
* @return all current orgs
* @see query_members()
* @see query_member()
*/
string *query_orgs() { return keys(orgs); }
/**
* This method adds a new organization into the orgs mapping.
* @param name the name of the organization to add
* @param title the title of the new organization
* @param info the general description of the organization
* @return 1 if successful, 0 if an org with the name already exists
* @see remove_org()
* @see query_org()
*/
varargs int add_org( string name, string title, string info, string channel ) {
class org_data org;
if( !name || name == "" || orgs[name] || !adminp( previous_object(-1) ) )
return 0;
org = new( class org_data );
org->info = info || "Why bother?";
org->title = title || "The Organization of No Title";
org->channel = channel;
orgs[name] = org;
members[name] = ({ });
save_data_file();
return 1;
} /* add_org() */
/**
* This method removes an organization from the handler.
* @param name the name of the organization to remove.
* @return 1 if successfully removed, 0 if not
* @see add_org()
* @see query_org()
*/
int remove_org( string name ) {
if( undefinedp( orgs[name] ) || !adminp( previous_object(-1) ) )
return 0;
map_delete( orgs, name );
map_delete( members, name );
save_data_file();
return 1;
} /* remove_org() */
/**
* This method queries if the specified organization exists or not.
* @param name the name of the organization to check
* @return 1 if the organization exists, 0 if not
* @see add_org()
* @see remove_org()
*/
int query_org( string name ) { return !undefinedp( orgs[name] ); }
/**
* This method sets a new title for the specified org.
* @param name the name of the org to set a new title for
* @param title the new title to set
* @return 1 if title successfully set, 0 if not
* @see query_title()
*/
int set_title( string name, string title ) {
if( !orgs[name] || !title || title == "" )
return 0;
DATA->title = title;
save_data_file();
return 1;
} /* set_title() */
/**
* This method returns the title of the organization.
* @param name the name of the organization to get the title for
* @return the title of the organization
* @see set_title()
*/
string query_title( string name ) {
if( !orgs[name] )
return 0;
return DATA->title;
} /* query_title() */
/**
* This method sets a new channel for the specified org.
* @param name the name of the org to set a new channel for
* @param channel the new channel to set
* @return 1 if channel successfully set, 0 if not
* @see query_channel()
*/
int set_channel( string name, string channel ) {
if( !orgs[name] || !channel || channel == "" )
return 0;
DATA->channel = channel;
save_data_file();
return 1;
} /* set_title() */
/**
* This method returns the channel used by the organization.
* @param name the name of the organization to get the channel for
* @return the channel used by the organization
* @see set_channel()
*/
string query_channel( string name ) {
if( !orgs[name] )
return 0;
return DATA->channel;
} /* query_channel() */
/**
* This method sets a new info for the specified org.
* @param name the name of the org to set a new info for
* @param info the new info to set
* @return 1 if title successfully set, 0 if not
* @see set_info()
*/
int set_info( string name, string info ) {
if( !orgs[name] || !info || info == "" )
return 0;
DATA->info = info;
save_data_file();
return 1;
} /* set_info() */
/**
* This method returns the general info of the organization.
* @param name the name of the organization to get the info for
* @return the general info of the organization
* @see query_info()
*/
string query_info( string name ) {
if( !orgs[name] )
return 0;
return DATA->info;
} /* query_info() */
/**
* This method adds an org to the specified organization's
* required orgs array.
* @param name the name of the org to add the req for
* @param req a string or an array of strings to add to
* the required orgs list
* @see remove_req_org()
* @see query_req_orgs()
*/
void add_req_org( string name, mixed req ) {
string *reqs;
if( !orgs[name] )
return;
if( !pointerp( reqs = DATA->req_orgs ) )
reqs = ({ });
if( stringp(req) && query_org(req) && member_array( req, reqs ) == -1 )
reqs += ({ req });
else if( pointerp(req) )
foreach( req in req )
if( stringp(req) && query_org(req) &&
member_array( req, reqs ) == -1 )
reqs += ({ req });
DATA->req_orgs = reqs;
save_data_file();
} /* add_req_org() */
/**
* This method removes an org from the specified organization's
* required orgs array.
* @param name the name of the org to remove the req from
* @param req a string or an array of strings to remove
* @see add_req_org()
* @see query_req_orgs()
*/
void remove_req_org( string name, mixed req ) {
string *reqs;
if( !orgs[name] )
return;
if( !pointerp( reqs = DATA->req_orgs ) )
return;
if( stringp(req) )
reqs -= ({ req });
else if( pointerp(req) )
foreach( req in req )
if( stringp(req) )
reqs -= ({ req });
DATA->req_orgs = reqs;
save_data_file();
} /* remove_req_org() */
/**
* This method will return the orgs one has to be a member of
* before they can join the specified org.
* @param name the name of the org to get the required orgs for
* @return the required orgs array
* @see add_req_org()
* @see remove_req_org()
*/
string *query_req_orgs( string name ) { return DATA->req_orgs || ({ }); }
/**
* This method adds a quest to the specified organization's
* required quests array.
* @param name the name of the org to add the req quest for
* @param req a string or an array of strings to add to
* the required quests list
* @see remove_req_quest()
* @see query_req_quests()
*/
void add_req_quest( string name, mixed req ) {
string *reqs;
if( !orgs[name] )
return;
if( !pointerp( reqs = DATA->req_quests ) )
reqs = ({ });
if( stringp(req) && member_array( req, reqs ) == -1 )
reqs += ({ req });
else if( pointerp(req) )
foreach( req in req )
if( stringp(req) && member_array( req, reqs ) == -1 )
reqs += ({ req });
DATA->req_quests = reqs;
save_data_file();
} /* add_req_quest() */
/**
* This method removes a quest from the specified organization's
* required quests array.
* @param name the name of the org to remove the req quest from
* @param req a string or an array of strings to remove
* @see add_req_quest()
* @see query_req_quests()
*/
void remove_req_quest( string name, mixed req ) {
string *reqs;
if( !orgs[name] )
return;
if( !pointerp( reqs = DATA->req_quests ) )
return;
if( stringp(req) )
reqs -= ({ req });
else if( pointerp(req) )
foreach( req in req )
if( stringp(req) )
reqs -= ({ req });
DATA->req_quests = reqs;
save_data_file();
} /* remove_req_quest() */
/**
* This method will return the quests has to do before they can
* join the specified org.
* @param name the name of the org to get the required quest for
* @return the required quests array
* @see add_req_quest()
* @see remove_req_quest()
*/
string *query_req_quests( string name ) { return DATA->req_quests || ({ }) ; }
/**
* This method adds an org that one can't be a member of to the
* specified organization's required anti-orgs array.
* @param name the name of the org to add the req for
* @param anti a string or an array of strings to add to
* the anti-org list
* @see remove_anti_org()
* @see query_anti_orgs()
*/
void add_anti_org( string name, mixed anti ) {
string *antis;
if( !orgs[name] )
return;
if( !pointerp( antis = DATA->anti_orgs ) )
antis = ({ });
if( stringp(anti) && query_org(anti) && member_array( anti, antis ) == -1 )
antis += ({ anti });
else if( pointerp(anti) )
foreach( anti in anti )
if( stringp(anti) && query_org(anti) &&
member_array( anti, antis ) == -1 )
antis += ({ anti });
DATA->anti_orgs = antis;
save_data_file();
} /* add_anti_org() */
/**
* This method removes an anti-org from the specified organization's
* anti-orgs array.
* @param name the name of the org to remove the anti-org from
* @param anti a string or an array of strings to remove
* @see add_anti_org()
* @see query_anti_orgs()
*/
void remove_anti_org( string name, mixed anti ) {
string *antis;
if( !orgs[name] )
return;
if( !pointerp( antis = DATA->anti_orgs ) )
return;
if( stringp(anti) )
antis -= ({ anti });
else if( pointerp(anti) )
foreach( anti in anti )
if( stringp(anti) )
antis -= ({ anti });
DATA->anti_orgs = antis;
save_data_file();
} /* remove_anti_org() */
/**
* This method will return the orgs one cannot be a member of
* if they want to join the specified org.
* @param name the name of the org to get the anti-orgs for
* @return the anti-orgs array
* @see add_anti_org()
* @see remove_anti_org()
*/
string *query_anti_orgs( string name ) { return DATA->anti_orgs || ({ }) ; }
/**
* This method returns all the members of the specified org.
* @param name the name of the org to get the members of
* @return the members array
* @see query_member()
*/
string *query_members( string name ) { return members[name] || ({ }); }
/**
* This method queries whether or not the player is a
* member of the organization or not.
* @param name the name of the org to check
* @param player the name of the player to check
* @return 1 if the player is a member, 0 if not
* @see add_member()
* @see remove_member()
* @see query_can_join()
*/
int query_member( string name, string player ) {
string *tmp;
if( !pointerp( tmp = members[name] ) )
return 0;
return ( member_array( player, tmp ) != -1 );
} /* query_member() */
/**
* This method checks whether or not the player can join an org.
* This checks all the reqs and anti-orgs etc.
* @param name the name of the org to check
* @param player the name of the player to check
* @return 1 if the player could join the org, 0 if not
* @see add_member()
* @see remove_member()
* @see query_member()
*/
int query_can_join( string name, string player ) {
if( !orgs[name] || !PLAYER_H->test_user(player) )
return 0;
if( sizeof( filter( query_req_orgs(name),
(: !query_member( $1, $2 ) :), player ) ) )
return 0;
if( sizeof( filter( query_anti_orgs(name),
(: query_member( $1, $2 ) :), player ) ) )
return 0;
if( sizeof( filter( query_req_quests(name),
(: !LIBRARY_H->query_quest_done( $2, $1 ) :), player ) ) )
return 0;
return 1;
} /* query_can_join() */
/**
* This method adds a member to an org.
* @param name the name of the org to add a member to
* @param player the name of the player to add
* @return 1 if successfully added, 0 if not
* @see remove_member()
* @see query_member()
* @see query_can_join()
*/
int add_member( string name, string player ) {
if( !members[name] || query_member( name, player ) ||
!query_can_join( name, player ) )
return 0;
members[name] += ({ player });
save_data_file();
return 1;
} /* add_member() */
/**
* This method removes a member from an org.
* @param name the name of the org to remove a member from
* @param player the name of the player to remove
* @return 1 if successfully removed, 0 if not
* @see add_member()
* @see query_member()
* @see query_can_join()
*/
int remove_member( string name, string player ) {
if( !members[name] )
return 0;
members[name] -= ({ player });
save_data_file();
return 1;
} /* add_member() */
/**
* This method returns the orgs the specified player is a member of.
* @param player the name of the player
* @return the orgs the player is a member of
* @see query_orgs()
* @see query_member()
*/
string *query_my_orgs( string player ) {
return filter( keys(orgs), (: query_member( $1, $2 ) :), player );
} /* query_my_orgs() */
/** @ignore yes */
private void check_members( string *left ) {
if( sizeof(left) ) {
string name;
name = left[0];
left = left[1..];
foreach( string player in query_members( name ) ) {
if( !player || !PLAYER_H->test_user(player) ) {
members[name] -= ({ player });
log_file("ORGS", "%O removed from %O - %s - %s\n",
player, name, "doesn't exist anymore", TIME );
}
}
if( sizeof(left) ) {
call_out( (: check_members :), 10, left );
return;
}
// Save only when the cycle has ended,
// otherwise we save once every ten seconds per org.
save_data_file();
}
} /* check_members() */
/** @ignore yes */
private void check_all_members() {
string *all;
call_out( (: check_all_members :), CHECK_TIME );
if( sizeof( all = keys(orgs) ) )
check_members( all );
} /* check_all_members() */
/**
* This method deletes the given player by name from all orgs.
* This should be called by the refresh handler when the player
* refreshes or is deleted.
* @param player the player to delete
*/
void refresh_player( string player ) {
int flag;
foreach( string name in keys(members) ) {
if( member_array( player, members[name] ) != -1 ) {
flag = 1;
members[name] -= ({ player });
}
}
if( flag )
save_data_file();
} /* refresh_player() */
/** @ignore yes */
mixed stats() {
mixed org_info;
org_info = ({ });
foreach( string name in keys(orgs) )
org_info += ({ ({ name, DATA->title }) });
return ({ ({ "total orgs" , sizeof( keys( orgs ) ) }) }) + org_info;
} /* stats() */