/************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * In order to use any part of this Merc Diku Mud, you must comply with * * both the original Diku license in 'license.doc' as well the Merc * * license in 'license.txt'. In particular, you may not remove either of * * these copyright notices. * * * * Much time and thought has gone into this software and you are * * benefiting. We hope that you share your changes too. What goes * * around, comes around. * *************************************************************************** * ROM 2.4 is copyright 1993-1998 Russ Taylor * * ROM has been brought to you by the ROM consortium * * Russ Taylor (rtaylor@hypercube.org) * * Gabrielle Taylor (gtaylor@hypercube.org) * * Brian Moore (zump@rom.org) * * By using this code, you have agreed to follow the terms of the * * ROM license, in the file Rom24/doc/rom.license * *************************************************************************** * 1stMud ROM Derivative (c) 2001-2004 by Markanth * * http://www.firstmud.com/ <markanth@firstmud.com> * * By using this code you have agreed to follow the term of * * the 1stMud license in ../doc/1stMud/LICENSE * ***************************************************************************/ #include "merc.h" #include "globals.h" #include "interp.h" #include "recycle.h" #include "data_table.h" /* * Local Functions */ TableSave_Fun(rw_change_data) { rw_table(type, CHANGES_FILE, ChangeData, change); } void delete_change(int iChange) { int i, j; ChangeData *new_table; alloc_mem(new_table, ChangeData, top_change); if (!new_table) { return; } for (i = 0, j = 0; i < top_change; i++) { if (i != iChange) { new_table[j] = change_table[i]; j++; } } free_mem(change_table); change_table = new_table; top_change--; return; } void add_change(const char *argument, const char *name) { ChangeData *new_table; int j, i = top_change; top_change++; alloc_mem(new_table, ChangeData, top_change); if (!new_table) { bug("Memory allocation failed. Brace for impact."); return; } for (j = 0; j < i; j++) new_table[j] = change_table[j]; free_mem(change_table); change_table = new_table; change_table[i].change = str_dup(argument); change_table[i].coder = str_dup(name); change_table[i].time = current_time; rw_change_data(act_write); } void post_changes(CharData * ch, int begin, int end) { char buf[MSL], note[MSL * 2], date[MIL]; int i; if (end >= top_change || begin < 0 || begin > end) return; note[0] = NUL; for (i = begin; i <= end; i++) { sprintf(buf, "{G%3d) {C%-45s{x\n\r", i, change_table[i].change); strcat(note, buf); } strcat(note, NEWLINE); sprintf(date, "Changes (%s)", str_time(-1, -1, "%D")); append_to_note(ch, "Announce", ch->name, "All", date, 60, note); } void archive_changes(CharData * ch, int begin, int end) { FileData *fp; int i; int j = 0; int old = top_change; ChangeData *new_table; bool fAuto = (begin == -1 && end == -1); char file[MIL]; #define ARCHIVE_TIME ((WEEK * 4) * 3) if (!fAuto && (end >= top_change || begin < 0 || begin > end)) { chprintln(ch, "Invalid range."); return; } sprintf(file, "%soldchanges/changes.%s", DATA_DIR, str_time(-1, -1, "%H-%M-%S")); fp = f_open(file, "w"); if (!fp) { bug("NULL fp"); chprintln(ch, "Error opening archive file."); return; } if (!fAuto) f_printf(fp, "%d\n", end - begin); else { begin = 0; end = top_change - 1; for (i = 0; i < top_change; i++) if (current_time - change_table[i].time >= ARCHIVE_TIME) j++; f_printf(fp, "%d\n", j); } for (i = begin; i <= end; i++) { if (!fAuto || current_time - change_table[i].time >= ARCHIVE_TIME) { f_printf(fp, "#CHANGE\n"); save_struct(fp, &change_zero, change_data_table, &change_table[i]); f_printf(fp, "#end\n\n"); } } f_printf(fp, "#!\n"); if (!fAuto) top_change = Max(0, top_change - (end - begin) - 1); else top_change = Max(0, top_change - j); alloc_mem(new_table, ChangeData, top_change); if (!new_table) { chprintln(ch, "Unable to remove changes."); return; } for (i = 0, j = 0; i < old; i++) { if (!fAuto ? (i < begin || i > end) : current_time - change_table[i].time < ARCHIVE_TIME) { new_table[j] = change_table[i]; j++; } } free_mem(change_table); change_table = new_table; if (!fAuto) { add_change(FORMATF ("Changes %d through %d archived.", begin + 1, end + 1), GetName(ch)); chprintlnf(ch, "Changes %d through %d archived to %s.", begin + 1, end + 1, file); } else { add_change(FORMATF("%d changes auto archived.", old - j), GetName(ch)); chprintlnf(ch, "%d changes auto archived to %s.", old - j, file); } f_close(fp); rw_change_data(act_write); } int num_changes(void) { struct tm a, *b; int today; int i; b = localtime(¤t_time); a = *b; today = 0; for (i = 0; i < top_change; i++) { if (change_table[i].time <= 0) continue; b = localtime(&change_table[i].time); if (a.tm_year != b->tm_year) continue; if (a.tm_mon != b->tm_mon) continue; if (a.tm_yday != b->tm_yday) continue; today++; } return today; } Do_Fun(do_changes) { char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; Buffer *buf; struct tm a, *b; int today; int i, c = 0, d = top_change; bool fToDay; argument = one_argument(argument, arg1); argument = one_argument(argument, arg2); if (IsImmortal(ch)) { if (NullStr(arg1)) { cmd_syntax(ch, NULL, n_fun, "save", "view", "delete <change number>", "add <change>", "edit <change number> <string>", "post <start #> [end #]", "archive auto | <start #> <end #>", NULL); return; } if (!str_cmp(arg1, "add")) { if (NullStr(arg2)) { chprintln(ch, "Add what change?"); return; } if (!NullStr(argument)) { strcat(arg2, " "); strcat(arg2, argument); } add_change(arg2, GetName(ch)); chprintln(ch, "Change Created."); chprintln(ch, "Type 'changes' to see the changes."); return; } if (!str_cmp(arg1, "save")) { rw_change_data(act_write); chprintln(ch, "Changes Saved."); return; } if (!str_cmp(arg1, "post")) { int begin = 1; int end = top_change; if (NullStr(arg2) || !is_number(arg2)) { cmd_syntax(ch, NULL, n_fun, "post <start #> [end #]", NULL); return; } begin = atoi(arg2); if (!NullStr(argument) && is_number(argument)) end = atoi(argument); if (begin < 1 || begin > top_change || end > top_change || end < 1) { chprintln(ch, "Are you purposly trying to crash the mud?"); return; } post_changes(ch, begin - 1, end - 1); return; } if (!str_cmp(arg1, "archive")) { int begin = 1; int end = top_change; if (NullStr(arg2) || (str_cmp(arg2, "auto") && (!is_number(arg2) || NullStr(argument) || !is_number(argument)))) { cmd_syntax(ch, NULL, n_fun, "archive <start #> <end #>", NULL); return; } if (!str_cmp(arg2, "auto")) { archive_changes(ch, -1, -1); return; } begin = atoi(arg2); end = atoi(argument); if (begin < 1 || begin > top_change || end > top_change || end < 1) { chprintln(ch, "Are you purposly trying to crash the mud?"); return; } archive_changes(ch, begin - 1, end - 1); return; } if (!str_cmp(arg1, "edit")) { int num; if (NullStr(arg2) || !is_number(arg2)) { chprintln(ch, "You must provide the number of the change you want to edit."); return; } num = atoi(arg2); if (num < 1 || num > top_change) { chprintlnf(ch, "Valid changes are from 1 to %d.", top_change); return; } if (NullStr(argument)) { chprintln(ch, "Want to you want the change to say?"); return; } replace_str(&change_table[num - 1].change, argument); chprintln(ch, "Change edited."); rw_change_data(act_write); return; } if (!str_cmp(arg1, "delete")) { int num; if (NullStr(arg2) || !is_number(arg2)) { chprintlnf(ch, "{wFor %s delete, you must provide a change number.{x", n_fun); cmd_syntax(ch, NULL, n_fun, "delete (change number)", NULL); return; } num = atoi(arg2); if (num < 1 || num > top_change) { chprintlnf(ch, "Valid changes are from 1 to %d.", top_change); return; } delete_change(num - 1); chprintln(ch, "Change deleted."); return; } if (str_cmp(arg1, "view")) { do_changes(n_fun, ch, ""); return; } else { strcpy(arg1, arg2); strcpy(arg2, argument); } } if (top_change < 1) { chprintln(ch, "No changes found."); return; } if (NullStr(arg1)) c = top_change - 16; else if (is_number(arg1)) { c = Max(c, atoi(arg1) - 1); if (!NullStr(arg2) && is_number(arg2)) { d = Min(atoi(arg2), d); } if (d <= c) { chprintln(ch, "First number must be lower than the second."); return; } } else { chprintln(ch, "Invalid argument."); return; } b = localtime(¤t_time); a = *b; fToDay = false; buf = new_buf(); bprintln(buf, "{wNo. Coder Date Change{R"); bprintln(buf, draw_line(ch, NULL, 0)); for (i = c; i < d; i++) { if (change_table[i].time > 0) { b = localtime(&change_table[i].time); if (a.tm_year == b->tm_year && a.tm_mon == b->tm_mon && a.tm_yday == b->tm_yday) { fToDay = true; } } bprintf(buf, "{g[{R%3d{g]{w %-9.9s %s%-8.8s {w", (i + 1), change_table[i].coder, fToDay ? "{C" : "{c", str_time(change_table[i].time, GetTzone(ch), "%D")); bprintln(buf, change_table[i].change); fToDay = false; } bprintlnf(buf, "{R%s", draw_line(ch, NULL, 0)); bprintlnf(buf, "{wThere is a total of {g[ {Y%3d {g] {wchanges in the database.{x", top_change); bprintln(buf, "{wAlso see: '{Cchanges <number> [number]{w' to display specific changes.{x"); bprintlnf(buf, "{R%s", draw_line(ch, NULL, 0)); if ((today = num_changes()) > 0) { bprintlnf(buf, "{wThere is a total of {g[ {Y%2d {g] {wnew changes that have been added today.{x", today); bprint(buf, "{R"); bprintln(buf, draw_line(ch, NULL, 0)); } sendpage(ch, buf_string(buf)); free_buf(buf); return; }