#include <lib.h>
#include <config.h>
#include <rooms.h>
#include <daemons.h>
#include <commands.h>
inherit LIB_DAEMON;
mapping Reloadees = ([]);
static int *reload_handles = ({});
static int warm_boot_in_progress = 0;
string savefile = "/secure/save/reload";
static string *exceptions = ({ RELOAD_D, RSOCKET_D });
varargs void validate(){
if((!(int)master()->valid_apply(({ "SECURE", "ASSIST" })))){
string offender = identify(previous_object(-1));
debug("RELOAD_D SECURITY VIOLATION: "+offender+" ",get_stack(),"red");
log_file("security", "\n"+timestamp()+" RELOAD_D breach: "+offender+" "+get_stack());
error("RELOAD_D SECURITY VIOLATION: "+offender+" "+get_stack());
}
}
static void create() {
daemon::create();
if(!file_exists(savefile+__SAVE_EXTENSION__))
unguarded( (: save_object(savefile) :) );
else restore_object(savefile);
set_heart_beat(1);
}
void eventDestructEmptyRooms(object room){
validate();
if(room && objectp(room) && !sizeof(get_livings(room,1))){
object *npcs = get_livings(room,2);
if(sizeof(npcs)) npcs->eventDestruct();
catch( room->eventDestruct() );
}
}
void eventResetEmptyRooms(){
validate();
foreach(object foo in objects((: inherits(LIB_ROOM, $1) :))){
//tc("foo: "+identify(foo));
call_out( (: eventDestructEmptyRooms :), 0, foo );
}
}
int ReloadBaseSystem(){
string *tmp = get_dir("/secure/sefun/");
string *sefun_files = ({});
catch( update(MASTER_D) );
foreach(string file in tmp){
if(!strsrch(file,"sefun.")) continue;
sefun_files += ({ "/secure/sefun/"+file });
}
foreach(string file in sefun_files){
catch(update(file));
}
RELOAD_D->eventReload(load_object(SEFUN), 1);
catch( update(MASTER_D) );
catch( reload(load_object(LIB_CREATOR), 1, 1) );
catch( reload(load_object(LIB_SENTIENT), 1, 1) );
catch( reload(load_object(LIB_ROOM), 1, 1) );
catch( reload(load_object(LIB_ARMOR), 1, 1) );
catch( reload(load_object(LIB_STORAGE), 1, 1) );
catch( reload(load_object(LIB_WORN_STORAGE), 1, 1) );
return 1;
}
varargs mixed ReloadPlayer(mixed who, int deep){
mixed mx;
string name;
object tmp_bod, new_bod;
validate();
if(stringp(who)) who = find_player(who);
if(!who) return 0;
name = who->GetKeyName();
who->save_player(name);
mx = reload(load_object(LIB_CREATOR), deep, 0);
if(mx) mx = reload(load_object(LIB_PLAYER), deep, 0);
if(!mx) error("OHSHI-");
tmp_bod = new(LIB_PLAYER_STUB);
tmp_bod->SetKeyName(name);
who->eventMove(ROOM_POD);
mx = exec(tmp_bod, who);
who->eventMove(ROOM_FURNACE);
who->eventDestruct();
new_bod = (object)master()->player_object(name, tmp_bod);
if( !new_bod ) return 0;
mx = exec(new_bod, tmp_bod);
if(!mx){
return 0;
}
destruct(tmp_bod);
new_bod->Setup();
SNOOP_D->CheckBot(name);
return 1;
}
varargs int eventUpdate(mixed what){
mixed tmpwhat = what;
int err;
if(stringp(what)){
what = find_object(tmpwhat);
}
if(!objectp(what)){
err = catch(what = load_object(tmpwhat));
}
if(err || !objectp(what)){
return 0;
}
if(what->GetVirtual()){
return what->eventDestruct();
}
if(!inherits(LIB_ROOM, what)) return update(base_name(what));
else {
tmpwhat = base_name(what);
what->eventDestruct();
return update(tmpwhat);
}
}
varargs int eventReload(mixed what, int when, int nodelay){
if(!what) return 0;
if(what->GetVirtual()){
object *npcs = get_livings(what,2);
if(sizeof(npcs)) npcs->eventDestruct();
return what->eventDestruct();
}
if(nodelay) return reload(what, 0, 1);
if(!when) when = time();
else when += time();
if(!what) return 0;
if(stringp(what)){
if(last(what,2) == ".c") what = trim(what,2);
what = find_object(what);
if(!what) return 0;
}
if(!objectp(what)) return 0;
if(Reloadees[what]) return 0;
if( (previous_object() != what) &&
!((int)master()->valid_apply(({ "ASSIST" }))) ){
log_file("adm/reload_d",get_stack()+" "+identify(previous_object(-1))+
" attempted to use RELOAD_D: "+timestamp()+"\n");
tell_creators(get_stack()+" "+identify(previous_object(-1))+
" attempted to use RELOAD_D: "+timestamp()+"\n");
error("Illegal attempt to access RELOAD_D: "+get_stack()+" "+identify(previous_object(-1)));
}
what = file_name(what);
Reloadees[what] = when;
}
void heart_beat(){
if(warm_boot_in_progress){
Reloadees = ([]);
foreach(mixed element in reload_handles){
if(!intp(element)){
reload_handles -= ({ element });
continue;
}
if(find_call_out(element) == -1){
reload_handles -= ({ element });
}
}
if(!sizeof(reload_handles)){
shout("Reloading users...");
flush_messages();
this_object()->ReloadUsers();
shout("Warm boot complete.");
warm_boot_in_progress = 0;
eventSave();
}
}
foreach(mixed key, mixed val in Reloadees){
if(time() >= val){
map_delete(Reloadees,key);
key = find_object(key);
reload(key);
}
}
}
mapping GetReloads(){
return copy(Reloadees);
}
mapping ClearReloads(){
if(!((int)master()->valid_apply(({ "ASSIST" }))) ){
log_file("adm/reload_d",get_stack()+" "+identify(previous_object(-1))+
" attempted to clear RELOAD_D: "+timestamp()+"\n");
tell_creators(get_stack()+" "+identify(previous_object(-1))+
" attempted to clear RELOAD_D: "+timestamp()+"\n");
error("Illegal attempt to access RELOAD_D: "+get_stack()+" "+identify(previous_object(-1)));
}
Reloadees = ([]);
save_object(savefile);
return copy(Reloadees);
}
int eventDestruct(){
save_object(savefile);
return daemon::eventDestruct();
}
int ReloadDir(string dir, int passes){
object *lib_obs = objects( (: !strsrch(base_name($1),$(dir)) :) );
int err;
validate();
lib_obs = filter(lib_obs, (: !clonep($1) ||
(clonep($1) && environment($1)) :));
if(!passes) passes = 3;
while(passes){
reset_eval_cost();
foreach(object ob in lib_obs){
reset_eval_cost();
if(ob != this_object() &&
member_array(base_name(ob), exceptions) == -1){
if(ob && inherits(LIB_ROOM,ob) && sizeof(livings(ob,1))){
reload_handles += ({ call_out((: eventReload :), 5,ob, 0, 1) });
}
else reload_handles += ({ call_out((: eventUpdate :), 5, base_name(ob)) });
}
}
passes--;
}
return 1;
}
int ReloadUsers(){
int err, mx, ret = 1;
validate();
mx = reload(load_object(LIB_CREATOR), 1, 1);
if(!mx) error("OHFUC-");
foreach(object player in users()){
reset_eval_cost();
err = catch(RELOAD_D->ReloadPlayer(player));
if(err) ret = 0;
}
return ret;
}
int ReloadMud(){
string *dir2 = ({ "/lib/", "/secure/","/daemon/" });
string *dir1 = ({ "/cmds/", "/verbs/","/estates/", "/obj/", "/open/", "/shadows/", "/spells/", "/std/" });
validate();
shout("Warm boot initiated!");
warm_boot_in_progress = 1;
eventResetEmptyRooms();
shout("Rooms resetting...");
flush_messages();
ReloadBaseSystem();
shout("Initializing base system...");
flush_messages();
foreach(string dir in (dir2 + dir1)){
shout("Initializing: "+dir);
flush_messages();
reset_eval_cost();
ReloadDir(dir, ((member_array(dir, dir1) != -1) ? 1 : 2));
}
shout("Reloading domains. This can take a few minutes...");
flush_messages();
ReloadDir("/domains/", 3);
shout("Reloading realms...");
flush_messages();
ReloadDir("/realms/", 3);
return 1;
}
int WarmBoot(){
validate();
call_out( (: ReloadMud :), 0);
return 1;
}
int GetWarmBootInProgress(){
return warm_boot_in_progress;
}