/* Do not remove the headers from this file! see /USAGE for more info. */
/*
** File: help_d.c
**
** Created 25-OCT-94 by Deathblade for the new help system.
**
** This daemon keeps track of topic->pathname mappings.
** It will also manage a topic name appearing in multiple
** locations.
*/
#include <mudlib.h>
#include <dirs.h>
inherit M_DAEMON_DATA;
// mapping topic_refs, to record directories and topic names
// which should be used as additional topic references for all files
// within those dirs - eg all files within /help/player/bin as to be
// available via "help player commands"
private nosave mapping topic_refs =
([ "/help/player/bin/" : "player_commands",
"/help/player/command/" : "player_commands",
"/help/player/quests/" : "quests",
"/help/player/" : "topics",
"/help/wizard/bin/" : "wizard_commands",
"/help/admin/command/" : "admin_commands",
]);
/*
** This mapping contains all the topics in the system. It
** maps topic names to an array of pathnames. The level-
** restriction on the topic is then computed by examining
** the lead part of the pathname.
*/
private mapping topics;
/*
** This mapping contains the level-restrictions on the help
** sub-directories. It is read from the _restrict file in
** the /help directory.
**
** It maps subdir names to levels.
*/
private mapping restrict;
private nosave int pending_count;
private nosave object initiator;
private nosave array ignore = ({ DIR_HELP "/autodoc/FIXME/" });
nomask void process_dir(string path);
private int f_restrict(string s)
{
string * r;
if ( s[0] == '#' )
return 0;
if ( member_array(':', s) == -1 )
return 0;
r = explode(s, ":");
restrict[trim_spaces(r[0])] = to_int(r[1]);
}
private void process_file(string path, string file)
{
string pathname;
string *player_dirs = keys(topic_refs);
string rfile = "";
if ( file == "." || file == ".." )
return;
if ( file[0] == '_' )
return;
pathname = path + file;
if ( file_size(pathname) == 0 )
{
write("Warning: '" + pathname + "' contains nothing.\n");
return;
}
if ( file_size(pathname) == -2 )
{
pathname += "/";
/* Ack. Avoid execution cost errors. */
call_out((: process_dir :), 1, pathname);
++pending_count;
}
file = lower_case(file);
if ( topics[file] )
topics[file] += ({ pathname });
else
topics[file] = ({ pathname });
if(member_array(path,player_dirs) > -1)
{
rfile = topic_refs[path];
if(topics[rfile])
topics[rfile] += ({ pathname });
else
topics[rfile] = ({ pathname });
}
}
nomask void process_dir(string path)
{
if ( member_array(path, ignore) == -1 )
map_array(get_dir(path + "*"), (: process_file, path :));
if ( !--pending_count )
{
save_me();
if ( initiator )
{
tell(initiator, "HELP_D has finished the rebuild.\n");
initiator = 0;
}
}
}
nomask void rebuild_data()
{
string * lines;
string * dirs;
if ( pending_count )
{
write("HELP_D is currently rebuilding!\n");
return;
}
write("HELP_D is beginning the rebuild...\n");
initiator = this_user();
topics = ([ ]);
restrict = ([ ]);
lines = explode(read_file(DIR_HELP "/_restrict"), "\n");
map_array(lines, (: f_restrict :));
dirs = filter(get_dir(DIR_HELP "/*"), (: $(restrict)[$1] != 99 :));
pending_count = 0;
map_array(dirs, (: process_file, DIR_HELP "/" :));
}
nomask void create()
{
::create();
if ( topics == 0 )
rebuild_data();
}
/*
** find_topic()
**
** Will return 0 if the topic does not exist (within the current
** player's level). Otherwise, an array of pathnames will be
** returned.
*/
nomask string * find_topic(string name)
{
mixed *result;
int lvl;
if ( !this_body() )
return 0;
result = topics[lower_case(name)];
if ( !result )
return 0;
//### simulate the old levels
lvl = adminp(this_user()) ? 5 : wizardp(this_user()) ? 1 : 0;
return filter_array(result, function(string file, int lvl){
array parts = explode(file, "/");
if (sizeof(parts) < 3) return 1;
return (lvl >= restrict[parts[1]]);
}, lvl);
}
/*
** conflict_report()
**
** Print out a report of the topics that have conflicts.
*/
nomask void conflict_report()
{
mixed * values;
values = values(topics);
values = filter_array(values, (: sizeof($1) > 1 :));
more(sprintf("%O", values));
}
/*
** Return the topic and restrict list. Note that these are
** the originals -- the topic mapping is awfully large to
** copy, so we'll just assume we have nice clients.
*/
mapping query_topics(){ return topics; }
mapping query_restrict(){ return restrict; }