/* dbutils.c */ #include "copyright.h" #include "config.h" #include <stdio.h> #include <ctype.h> #include "teeny.h" #include "db.h" #include "case.h" /* * This is the only file in the mud directory that knows about the index. Use * EXTREME caution when modifing the routines in this file. */ extern struct dsc **main_index; extern int total_objects; extern int actual_objects; static void find_object(); int controls(player, obj) int player; int obj; { if (obj == -3) return 1; /* everyone controls HOME */ if (player < 0 || player > total_objects || main_index[player] == NULL) { warning("controls", "called with nonexistant player"); return 0; } if (obj < 0 || obj > total_objects || main_index[obj] == NULL) { warning("controls", "called with nonexistant object"); return 0; } if (GodP(main_index[player]) || WizP(main_index[player])) return 1; if (ExitP(main_index[obj]) && exists_object(DSC_DESTINATION(main_index[obj]))) if (DSC_OWNER(main_index[DSC_DESTINATION(main_index[obj])]) == player) return 1; if (DSC_OWNER(main_index[obj]) == player) return 1; return 0; } static void find_object(player, name, type) int player; char *name; int type; { register int i; register char *str; extern char cmdwork[]; for (i = 0; i < total_objects; i++) { if (main_index[i] == NULL) continue; if (((type != -1) && ((DSC_FLAGS(main_index[i]) & TYPE_MASK) != type)) || (type == -1 && isexit(i))) continue; if (!controls(player, i)) continue; str = DSC_NAME(main_index[i]); if (str == NULL) { log_error("find_object: obj (#%d) has NULL name.\n", i); continue; } if ((name == (char *) 0) || strstr_CI(str, name)) { (void) strcpy(cmdwork, stuff_name(player, i)); (void) strcat(cmdwork, "\r\n"); notify_player(player, cmdwork); } } notify_player(player, "***End of list***\r\n"); } voidfunc do_owned(player, argone, argtwo) int player; char *argone; char *argtwo; { int matchfor, i, type; extern char cmdwork[]; if (!iswiz(player)) { notify_player(player, "Only a Wizard may look at the owners list.\r\n"); return; } if (!argone || !*argone) { notify_player(player, "I need a player name.\r\n"); return; } if ((matchfor = resolve_player(player, argone, 1)) == -1) { notify_player(player, "I can't find that person.\r\n"); return; } type = -1; if (argtwo && *argtwo) { parse_type(argtwo, &type); if (type == -1) { notify_player(player, "@owned <player> [=<type>] where type is {e,p,r,t}\r\n"); return; } } for (i = 0; i < total_objects; i++) { if (main_index[i] == NULL) continue; if (DSC_OWNER(main_index[i]) != matchfor) continue; /* they own this object */ if (type != -1) { if ((DSC_FLAGS(main_index[i]) & TYPE_MASK) != type) continue; } (void) strcpy(cmdwork, stuff_name(player, i)); (void) strcat(cmdwork, "\r\n"); notify_player(player, cmdwork); } notify_player(player, "***End of list***\r\n"); } voidfunc do_entrances(player, arg) int player; char *arg; { register int i; int search_for; extern char cmdwork[]; if (!arg || !*arg) { if (get_int_elt(player, LOC, &search_for) == -1) { notify_bad(player); return; } } else { if ((search_for = resolve_object(player, arg, 0)) == -1 || search_for == -2 || search_for == -3) { notify_player(player, "No such thing.\r\n"); return; } if (ExitP(main_index[search_for])) { notify_player(player, "That won't have anything linked to it.\r\n"); return; } } if (!controls(player, search_for)) { notify_player(player, "Permission denied.\r\n"); return; } for (i = 0; i < total_objects; i++) { if (main_index[i] == NULL || !ExitP(main_index[i])) continue; if (DSC_DESTINATION(main_index[i]) != search_for) continue; (void) strcpy(cmdwork, stuff_name(player, i)); (void) strcat(cmdwork, "\r\n"); notify_player(player, cmdwork); } notify_player(player, "***End of list***\r\n"); } int chownall(oldowner, newowner) register int oldowner; register int newowner; { int i, count = 0; if (!exists_object(oldowner) || !exists_object(newowner)) { warning("chownall", "called with nonexistant object as an argument"); return 0; } for (i = 0; i < total_objects; i++) { if (main_index[i] == NULL) continue; if (DSC_OWNER(main_index[i]) == oldowner) { DSC_OWNER(main_index[i]) = newowner; count++; } } return count; } voidfunc do_find(player, argone, argtwo) int player; char *argone; char *argtwo; { int type; if (!argone || !*argone) argone = (char *) 0; type = -1; if (argtwo && *argtwo) { parse_type(argtwo, &type); if (type == -1) { notify_player(player, "@find <string> [=<type>] where type is {e,p,r,t}\r\n"); return; } } find_object(player, argone, type); } #define COUNT_OBJ(x) \ (((matchfor != -2)&&(DSC_OWNER(main_index[x])==matchfor)) || matchfor == -2) #define STATS_FRMT \ "%d object%s = %d room%s, %d exit%s, %d thing%s, %d player%s (%d garbage).\r\n" voidfunc do_stats(player, arg) int player; char *arg; { extern char cmdwork[]; int matchfor; if (!arg || !*arg) { matchfor = -2; } else { if ((matchfor = resolve_player(player, arg, iswiz(player))) == -1) { notify_player(player, "I can't find that person.\r\n"); return; } if ((matchfor != player) && !iswiz(player)) { notify_player(player, "You can't stat other players!\r\n"); return; } /* matchfor should now contain a valid player number */ } if (!iswiz(player) && matchfor == -2) { sprintf(cmdwork, "The universe contains %d objects.\r\n", actual_objects); notify_player(player, cmdwork); } else { register int i; register int exits = 0; register int rooms = 0; register int players = 0; register int things = 0; register int total = 0; for (i = 0; i < total_objects; i++) { if (main_index[i] == NULL) continue; if (ExitP(main_index[i])) { if (COUNT_OBJ(i)) { total++; exits++; } continue; } if (RoomP(main_index[i])) { if (COUNT_OBJ(i)) { rooms++; total++; } continue; } if (PlayerP(main_index[i])) { if (COUNT_OBJ(i)) { total++; players++; } continue; } if (ThingP(main_index[i])) { if (COUNT_OBJ(i)) { total++; things++; } continue; } } sprintf(cmdwork, STATS_FRMT, total, (total == 1) ? "" : "s", rooms, (rooms == 1) ? "" : "s", exits, (exits == 1) ? "" : "s", things, (things == 1) ? "" : "s", players, (players == 1) ? "" : "s", (matchfor == -2) ? total_objects - actual_objects : 0); notify_player(player, cmdwork); if (iswiz(player) && matchfor == -2) { extern int cache_usage, cache_size, cache_hits, cache_misses; extern int cache_errors, malloc_calls, malloc_total, malloc_free; sprintf(cmdwork, "Cache stats: %d bytes in use of %d max. %d cache hits with %d misses. %d database errors.\r\n", cache_usage, cache_size, cache_hits, cache_misses, cache_errors); notify_player(player, cmdwork); sprintf(cmdwork, "Malloc stats: %d requests for %d total bytes. %d requests freed.\r\n", malloc_calls, malloc_total, malloc_free); notify_player(player, cmdwork); } } } #undef COUNT_OBJ #undef STATS_FRMT /* fix up destinations/homes/dropto's that point at non existant objects */ void zap_destinations(oldobj) int oldobj; { register int i; for (i = 0; i < total_objects; i++) { if ((main_index[i] == NULL) || (DSC_HOME(main_index[i]) != oldobj)) continue; switch (DSC_FLAGS(main_index[i]) & TYPE_MASK) { case TYP_PLAYER: DSC_HOME(main_index[i]) = STARTING_LOC; break; case TYP_THING: DSC_HOME(main_index[i]) = /* link to owners home */ DSC_HOME(main_index[DSC_OWNER(main_index[i])]); break; case TYP_ROOM: DSC_DROPTO(main_index[i]) = -1; /* unlink */ break; case TYP_EXIT: DSC_DESTINATION(main_index[i]) = -1; /* unlink */ break; default: /* fuckit */ fprintf(stderr, "warning: object #%d is unknown type.\n", i); } } } int recycleobj(obj) int obj; { int loc; int list, next; int total = 0; if (!exists_object(obj)) return 0; if (PlayerP(main_index[obj])) return 0; if (get_int_elt(obj, LOC, &loc) == -1) goto recbomb; if (RoomP(main_index[obj])) { list_drop(obj, loc, ROOMS_LIST); if (get_int_elt(obj, ROOMS, &list) == -1) goto recbomb; while (list != -1) { next = DSC_NEXT(main_index[list]); list_add(list, ROOT_PARENT, ROOMS_LIST); if (set_int_elt(list, LOC, ROOT_PARENT) == -1) goto recbomb; list = next; } /* Nuke the exits. Ownership? Who cares. */ if (get_int_elt(obj, EXITS, &list) == -1) goto recbomb; while (list != -1) { next = DSC_NEXT(main_index[list]); destroy_obj(list); total++; list = next; } /* Try to send everything here home. Nuke what's left */ /* I.E. Anything homed here will get nuked. BOOM! */ if (get_int_elt(obj, CONTENTS, &list) == -1) goto recbomb; while (list != -1) { next = DSC_NEXT(main_index[list]); /* If this is a player homed here, set home to zero */ if (PlayerP(main_index[list])) { if (DSC_HOME(main_index[list]) == obj) { DSC_HOME(main_index[list]) = STARTING_LOC; } } if (PlayerP(main_index[list])) { register char *name; name = DSC_NAME(main_index[list]); notify_player(list, "You feel a wrenching sensation...\r\n"); send_home(list, obj); notify_oall(list, name); notify_oall(list, " has arrived.\r\n"); do_look(list, (char *) NULL); } else { send_home(list, obj); } list = next; } if (get_int_elt(obj, CONTENTS, &list) == -1) goto recbomb; while (list != -1) { next = DSC_NEXT(main_index[list]); destroy_obj(list); total++; list = next; } /* nuke the room itself. */ destroy_obj(obj); total++; /* Skip over the DB checking all exits, and unlinking the */ /* ones that come here. */ zap_destinations(obj); } else if (ExitP(main_index[obj])) { list_drop(obj, loc, 0); destroy_obj(obj); total++; } else if (ThingP(main_index[obj])) { list_drop(obj, loc, 1); zap_destinations(obj); if (get_int_elt(obj, CONTENTS, &list) == -1) goto recbomb; while (list != -1) { /* send objects home */ next = DSC_NEXT(main_index[list]); send_home(list, obj); list = next; } if (get_int_elt(obj, EXITS, &list) == -1) goto recbomb; while (list != -1) { /* nuke exits */ next = DSC_NEXT(main_index[list]); destroy_obj(list); total++; list = next; } destroy_obj(obj); total++; } else { warning("recycleobj", "unknown object type"); goto recbomb; } return total; recbomb: return -1; } /* recycle everything owned by obj, *except* obj */ int purgepossessions(obj) int obj; { register int i; int ret, total = 0; if (!exists_object(obj)) { warning("purgepossessions", "called with nonexistant object"); return 0; } for (i = 0; i < total_objects; i++) { if (main_index[i] == NULL) continue; if ((i == obj) || (DSC_OWNER(main_index[i]) != obj)) continue; /* nuke this, what ever it is */ ret = recycleobj(i); if (ret > 0) total += ret; } return total; } /* * Matches a player. This is kind of expensive CPU wise. */ int match_player(name) register char *name; { register int i; register char *player; for (i = 0; i < total_objects; i++) { if (main_index[i] == NULL || !PlayerP(main_index[i])) continue; player = DSC_NAME(main_index[i]); if (!player || !*player) { warning("match_player", "player with null name found"); continue; } if (!strcasecmp(name, player)) return (i); } return (-1); } int check_quota(player) int player; { int total, quota; register int i; if (iswiz(player)) return (0); for (i = 0, total = 0; i < total_objects; i++) { if (main_index[i] == NULL) continue; if (DSC_OWNER(main_index[i]) == player) total++; } if (get_int_elt(player, QUOTA, "a) == -1) { log_error("check_quota: player #%d has a bad quota ref.\r\n", player); return (1); } return (total > quota); } voidfunc do_children(player, arg) int player; char *arg; { int list, obj; extern char cmdwork[]; if (arg == NULL || *arg == 0) { if (get_int_elt(player, LOC, &obj) == -1) { notify_bad(player); return; } } else { if ((obj = resolve_object(player, arg, 0)) == -1 || obj == -2) { notify_player(player, "No such room.\r\n"); return; } } if (!exists_object(obj) || !isroom(obj)) { notify_player(player, "Only rooms have children.\r\n"); return; } if (!controls(player, obj) && !isabode(obj)) { notify_player(player, "Permission denied.\r\n"); return; } if (get_int_elt(obj, ROOMS, &list) == -1) { notify_bad(player); return; } if (list != -1) notify_list(player, list, cmdwork, BUFFSIZ, 1); notify_player(player, "**End of list**\r\n"); } voidfunc do_fixlists(player) int player; { register int i; int loc, flags; extern char cmdwork[]; if (player != PLAYER_GOD) { notify_player(player, "Someone doesn't want you doing that.\r\n"); return; } /* SPAM SPAM SPAM */ notify_player(player, "Spamming...\r\n"); for (i = 0; i < db_top(); i++) { if (!exists_object(i)) continue; if (set_int_elt(i, NEXT, -1) == -1) { sprintf(cmdwork, "Failed to spam object #%d - corrupt index!\r\n", i); notify_player(player, cmdwork); continue; } if (set_int_elt(i, CONTENTS, -1) == -1) { sprintf(cmdwork, "Failed to spam object #%d - corrupt disk!\r\n", i); notify_player(player, cmdwork); continue; } if (set_int_elt(i, EXITS, -1) == -1) { sprintf(cmdwork, "Failed to spam object #%d - corrupt disk!\r\n", i); notify_player(player, cmdwork); continue; } if (isroom(i)) { if (set_int_elt(i, ROOMS, -1) == -1) { sprintf(cmdwork, "Failed to spam object #%d = corrupt disk!\r\n", i); notify_player(player, cmdwork); continue; } } } /* rebuild */ notify_player(player, "Rebuilding...\r\n"); for (i = 0; i < db_top(); i++) { if (!exists_object(i)) continue; if (get_int_elt(i, LOC, &loc) == -1) { sprintf(cmdwork, "Failed to get location of object #%d.\r\n", i); notify_player(player, cmdwork); loc = 0; } if (get_int_elt(i, FLAGS, &flags) == -1) { sprintf(cmdwork, "Failed to get flags of object #%d.\r\n", i); notify_player(player, cmdwork); continue; } switch (flags & TYPE_MASK) { case TYP_ROOM: list_add(i, loc, ROOMS_LIST); break; case TYP_PLAYER: case TYP_THING: list_add(i, loc, CONTENTS_LIST); break; case TYP_EXIT: list_add(i, loc, EXITS_LIST); break; default: sprintf(cmdwork, "Bad type on object #%d.\r\n", i); notify_player(player, cmdwork); } } notify_player(player, "Done.\r\n"); }