#include <stdio.h> #include <stdlib.h> #include <string.h> #include "db.h" #include "filelist.h" #include "externs.h" static OBJ **get_eventrefs(OBJ *obj) { OBJ **list = NULL, *o; int ctr = 0; FILE *fp; char filename[4096]; char buf[4096]; if(!obj) { list = (OBJ **)stack_alloc(sizeof(OBJ *), 0, 0); list[0] = NULL; return(list); } sprintf(filename, "eventrefs/%d", obj->dbref); if(!(fp = fopen(filename, "r"))) { list = (OBJ **)stack_alloc(sizeof(OBJ *), 0, 0); list[0] = NULL; return(list); } while(fgets(buf, sizeof(buf), fp)) { if(!(o = find_object(atoi(buf)))) continue; if(!ctr) list = (OBJ **)stack_alloc(sizeof(OBJ), 0, 0); else list = (OBJ **)stack_realloc_tmp(list, sizeof(OBJ *)*(ctr+2)); list[ctr++] = o; } fclose(fp); list[ctr] = NULL; return(list); } static void put_eventrefs(OBJ *obj, OBJ **list) { FILE *fp; char filename[4096]; int i; if(!obj) return; sprintf(filename, "eventrefs/%d", obj->dbref); if(!(fp = fopen(filename, "w"))) { log_error(tprintf("Couldn't open \"%s\" for writing!", filename)); return; } for(i = 0;list[i];i++) putref(fp, list[i]->dbref); fclose(fp); if(!*list) unlink(filename); } static void do_eventref_add(OBJ *player, char *arg) { OBJ *obj, *ref; char *p; if(!power(player, POW_DB)) { notify(player, perm_denied()); return; } if(!(p = strchr(arg, ','))) { notify(player, "Usage: +eventref add=<object>,<reference>"); return; } *p++ = '\0'; if(!(obj = match_object(player, arg, NOTYPE))) { notify(player, no_match(arg)); return; } if(!(ref = match_object(player, p, NOTYPE))) { notify(player, no_match(p)); return; } if(!controls(player, obj, POW_MODIFY)) { notify(player, perm_denied()); return; } add_event_ref(obj, ref); notify(player, tprintf("Added reference %s to %s", unparse_object(player, ref), unparse_object(player, obj))); } static void do_eventref_check(OBJ *player, char *arg) { OBJ *obj, *ref; char *p; int answer; if(!power(player, POW_DB)) { notify(player, perm_denied()); return; } if(!(p = strchr(arg, ','))) { notify(player, "Usage: +eventref check=<object>,<reference>"); return; } *p++ = '\0'; if(!(obj = match_object(player, arg, NOTYPE))) { notify(player, no_match(arg)); return; } if(!(ref = match_object(player, p, NOTYPE))) { notify(player, no_match(p)); return; } if(!controls(player, obj, POW_EXAMINE)) { notify(player, perm_denied()); return; } answer = chk_event_ref(obj, ref); notify(player, tprintf("Is %s event referenced to %s? %s", unparse_object(player, ref), unparse_object(player, obj), (answer)?"Yes":"No")); } static void do_eventref_delete(OBJ *player, char *arg) { OBJ *obj, *ref; char *p; if(!power(player, POW_DB)) { notify(player, perm_denied()); return; } if(!(p = strchr(arg, ','))) { notify(player, "Usage: +eventref delete=<object>,<reference>"); return; } *p++ = '\0'; if(!(obj = match_object(player, arg, NOTYPE))) { notify(player, no_match(arg)); return; } if(!(ref = match_object(player, p, NOTYPE))) { notify(player, no_match(p)); return; } if(!controls(player, obj, POW_MODIFY)) { notify(player, perm_denied()); return; } if(!chk_event_ref(obj, ref)) { notify(player, tprintf("%s isn't an event reference of %s.", unparse_object(player, ref), unparse_object(player, obj))); return; } del_event_ref(obj, ref); notify(player, tprintf("Deleted reference %s from %s.", unparse_object(player, ref), unparse_object(player, obj))); } static int list_event_refs(OBJ *player, FILELIST *flist, int type, char *str) { FILELIST *f, *fprev = NULL, *fnext; int ctr = 0; OBJ *o; for(f = flist;f;f = fnext) { fnext = f->next; o = find_object(atoi(f->name)); if(Typeof(o) == type) { if(!ctr++) notify(player, str); notify(player, tprintf(" %s", unparse_object(player, o))); /* Continuously shrink the list so subsequent calls go faster */ if(fprev) fprev->next = fnext; else flist = fnext; } else fprev = f; } return(ctr); } static void do_eventref_list(OBJ *player, char *arg) { OBJ **list, *obj = NULL; int i, ctr = 0; FILELIST *flist; if(!power(player, POW_DB)) { notify(player, perm_denied()); return; } if(*arg) { if(!(obj = match_object(player, arg, NOTYPE))) { notify(player, no_match(arg)); return; } if(!controls(player, obj, POW_EXAMINE)) { notify(player, perm_denied()); return; } list = get_eventrefs(obj); if(!*list) { notify(player, tprintf("%s has no event references.", unparse_object(player, obj))); return; } notify(player, tprintf("|+W|Event references of %s|+W|:", unparse_object(player, obj))); for(i = 0;list[i];++i) { notify(player, unparse_object(player, list[i])); ctr++; } notify(player, tprintf("|+C|%d |+B|total event reference%s", ctr, check_plural(ctr, "", "s"))); return; } if(!(flist = get_filelist("eventrefs", 0))) { notify(player, "There are no objects with event references."); return; } notify(player, "|+W|Objects with event references:"); ctr += list_event_refs(player, flist, TYPE_PLAYER, "|+B|Players|+W|:"); ctr += list_event_refs(player, flist, TYPE_THING, "|+B|Things|+W|:"); ctr += list_event_refs(player, flist, TYPE_ROOM, "|+B|Rooms|+W|:"); ctr += list_event_refs(player, flist, TYPE_EXIT, "|+B|Exits|+W|:"); notify(player, tprintf("|+B|There %s |+C|%d |+B|object%s with event references.", check_plural(ctr, "is", "are"), ctr, check_plural(ctr, "", "s"))); } void do_eventref(OBJ *player, char *arg1, char *arg2) { SUBCOMMAND *sc, commands[] = { { "add", do_eventref_add, 0 }, { "check", do_eventref_check, 0 }, { "delete", do_eventref_delete, 0 }, { "list", do_eventref_list, 0 }, { NULL } }; if(!(sc = subcommand_match(player, arg1, commands, NULL))) subcommand_print(player, "+eventref", commands); else sc->func(player, arg2); } int chk_event_ref(OBJ *obj, OBJ *ref) { OBJ **list; int i; if(!obj || !ref) return(0); list = get_eventrefs(obj); for(i = 0;list[i];++i) if(list[i] == ref) return(1); return(0); } void add_event_ref(OBJ *obj, OBJ *ref) { OBJ **oldlist, **newlist; int i; if(!obj || !ref) return; oldlist = get_eventrefs(obj); for(i = 0;oldlist[i];i++) if(oldlist[i] == ref) return; newlist = (OBJ **)stack_alloc(sizeof(OBJ *)*(i+2), 0, 0); memcpy(newlist, oldlist, sizeof(OBJ *)*i); newlist[i] = ref; newlist[i+1] = NULL; put_eventrefs(obj, newlist); } static void _del_event_ref(OBJ *obj, OBJ *ref) { OBJ **list; int i, j; if(!obj || !ref) return; list = get_eventrefs(obj); for(i = 0;list[i];i++) if(list[i] == ref) break; if(!list[i]) return; for(j = i+1;list[j];++i, ++j) list[i] = list[j]; list[i] = NULL; put_eventrefs(obj, list); } void del_event_ref(OBJ *obj, OBJ *ref) { FILELIST *flist; if(obj) { if(ref) /* Delete 1 reference */ _del_event_ref(obj, ref); else /* Delete all references */ unlink(tprintf("eventrefs/%d", obj->dbref)); return; } if(ref) /* Delete reference from all objects */ for(flist = get_filelist("eventrefs", 0);flist;flist = flist->next) if(!(flist->flags & FILE_DIRECTORY)) _del_event_ref(find_object(atoi(flist->name)), ref); }