diff --git a/changelog b/changelog index 274e5f9..df1e6f1 100644 --- a/changelog +++ b/changelog @@ -42,6 +42,7 @@ Xlist (mlist, olist, rlist, zlist, slist, tlist, qlist) The medit mob flags menu now only shows valid flags (thanks Kyle) Skillset now warns imms when the player shouldn't have a skill (thanks Rumble) Fly spell added! + Added recent command [Nov 04 2010] - Jamdog Bug-Fix: Converted affect flags in struct affected_type from 32-bit to 128-bit Bug Fix: Players with too much gold now don't lose eq when renting diff --git a/src/act.h b/src/act.h index 33cd5d9..c60a2dc 100644 --- a/src/act.h +++ b/src/act.h @@ -280,6 +280,7 @@ room_rnum find_target_room(struct char_data *ch, char *rawroomstr); void perform_immort_vis(struct char_data *ch); void snoop_check(struct char_data *ch); bool change_player_name(struct char_data *ch, struct char_data *vict, char *new_name); +bool AddRecentPlayer(char *chname, char *chhost, bool newplr, bool cpyplr); /* Functions with subcommands */ /* do_date */ ACMD(do_date); @@ -322,6 +323,7 @@ ACMD(do_load); ACMD(do_peace); ACMD(do_plist); ACMD(do_purge); +ACMD(do_recent); ACMD(do_restore); ACMD(do_return); ACMD(do_saveall); diff --git a/src/act.wizard.c b/src/act.wizard.c index a079c78..76fe261 100644 --- a/src/act.wizard.c +++ b/src/act.wizard.c @@ -48,10 +48,16 @@ static void mob_checkload(struct char_data *ch, mob_vnum mvnum); static void obj_checkload(struct char_data *ch, obj_vnum ovnum); static void trg_checkload(struct char_data *ch, trig_vnum tvnum); static void mod_llog_entry(struct last_entry *llast,int type); +static int get_max_recent(void); +static void clear_recent(struct recent_player *this); +static struct recent_player *create_recent(void); const char *get_spec_func_name(SPECIAL(*func)); bool zedit_get_levels(struct descriptor_data *d, char *buf); +/* Local Globals */ +static struct recent_player *recent_list = NULL; /** Global list of recent players */ + int purge_room(room_rnum room) { int j; @@ -4791,3 +4797,140 @@ ACMD(do_zunlock) send_to_char(ch, "Unable to save zone changes. Check syslog!\r\n"); } } + +/* get highest vnum in recent player list */ +static int get_max_recent(void) +{ + struct recent_player *this; + int iRet=0; + + this = recent_list; + + while (this) + { + if (this->vnum > iRet) iRet = this->vnum; + this = this->next; + } + + return iRet; +} + +/* clear an item in recent player list */ +static void clear_recent(struct recent_player *this) +{ + this->vnum = 0; + this->time = 0; + strcpy(this->name, ""); + strcpy(this->host, ""); + this->next = NULL; +} + +/* create new blank player in recent players list */ +static struct recent_player *create_recent(void) +{ + struct recent_player *newrecent; + + CREATE(newrecent, struct recent_player, 1); + clear_recent(newrecent); + newrecent->next = recent_list; + recent_list = newrecent; + + newrecent->vnum = get_max_recent(); + newrecent->vnum++; + return newrecent; +} + +/* Add player to recent player list */ +bool AddRecentPlayer(char *chname, char *chhost, bool newplr, bool cpyplr) +{ + struct recent_player *this; + time_t ct; + int max_vnum; + + ct = time(0); /* Grab the current time */ + + this = create_recent(); + + if (!this) return FALSE; + + this->time = ct; + this->new_player = newplr; + this->copyover_player = cpyplr; + strcpy(this->host, chhost); + strcpy(this->name, chname); + max_vnum = get_max_recent(); + this->vnum = max_vnum; /* Possibly should be +1 ? */ + + return TRUE; +} + +ACMD(do_recent) +{ + time_t ct; + char *tmstr, arg[MAX_INPUT_LENGTH]; + int hits = 0, limit = 0, count = 0; + struct recent_player *this; + bool loc; + + one_argument(argument, arg); + if (!*arg) { + limit = 0; + } else { + limit = atoi(arg); + } + + if (GET_LEVEL(ch) >= LVL_GRGOD) { /* If High-Level Imm, then show Host IP */ + send_to_char(ch, " ID | DATE/TIME | HOST IP | Player Name\r\n"); + } else { + send_to_char(ch, " ID | DATE/TIME | Player Name\r\n"); + } + + this = recent_list; + while(this) + { + loc = FALSE; + hits++; + ct = this->time; + tmstr = asctime(localtime(&ct)); + *(tmstr + strlen(tmstr) - 1) = '\0'; /* Cut off last char */ + if (this->host && *(this->host)) { + if (!strcmp(this->host, "localhost")) loc = TRUE; + } + + if ((limit == 0) || (count < limit)) + { + if (GET_LEVEL(ch) >= LVL_GRGOD) /* If High-Level Imm, then show Host IP */ + { + if (this->new_player == TRUE) { + send_to_char(ch, "%3d | %-19.19s | %s%-37s%s | %s %s(New Player)%s\r\n", this->vnum, tmstr, loc ? QRED : "", this->host, QNRM, this->name, QYEL, QNRM); + } else if (this->copyover_player == TRUE) { + send_to_char(ch, "%3d | %-19.19s | %s%-37s%s | %s %s(Copyover)%s\r\n", this->vnum, tmstr, loc ? QRED : "", this->host, QNRM, this->name, QCYN, QNRM); + } else { + send_to_char(ch, "%3d | %-19.19s | %s%-37s%s | %s\r\n", this->vnum, tmstr, loc ? QRED : "", this->host, QNRM, this->name); + } + } + else + { + if (this->new_player == TRUE) { + send_to_char(ch, "%3d | %-19.19s | %s %s(New Player)%s\r\n", this->vnum, tmstr, this->name, QYEL, QNRM); + } else if (this->copyover_player == TRUE) { + send_to_char(ch, "%3d | %-19.19s | %s %s(Copyover)%s\r\n", this->vnum, tmstr, this->name, QCYN, QNRM); + } else { + send_to_char(ch, "%3d | %-19.19s | %s\r\n", this->vnum, tmstr, this->name); + } + } + count++; + + this = this->next; + } + else + { + this = NULL; + } + } + + ct = time(0); /* Grab the current time */ + tmstr = asctime(localtime(&ct)); + *(tmstr + strlen(tmstr) - 1) = '\0'; + send_to_char(ch, "Current Server Time: %-19.19s\r\nShowing %d players since last copyover/reboot\r\n", tmstr, hits); +} diff --git a/src/comm.c b/src/comm.c index 50a907c..b23dcca 100644 --- a/src/comm.c +++ b/src/comm.c @@ -462,6 +462,12 @@ void copyover_recover() enter_player_game(d); d->connected = CON_PLAYING; look_at_room(d->character, 0); + + /* Add to the list of 'recent' players (since last reboot) with copyover flag */ + if (AddRecentPlayer(GET_NAME(d->character), d->host, FALSE, TRUE) == FALSE) + { + mudlog(BRF, MAX(LVL_IMMORT, GET_INVIS_LEV(d->character)), TRUE, "Failure to AddRecentPlayer (returned FALSE)."); + } } } fclose (fp); diff --git a/src/interpreter.c b/src/interpreter.c index 825303a..29e42ea 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -250,6 +250,7 @@ cpp_extern const struct command_info cmd_info[] = { { "reload" , "reload" , POS_DEAD , do_reboot , LVL_IMPL, 0 }, { "recite" , "reci" , POS_RESTING , do_use , 0, SCMD_RECITE }, { "receive" , "rece" , POS_STANDING, do_not_here , 1, 0 }, + { "recent" , "recent" , POS_DEAD , do_recent , LVL_IMMORT, 0 }, { "remove" , "rem" , POS_RESTING , do_remove , 0, 0 }, { "rent" , "rent" , POS_STANDING, do_not_here , 1, 0 }, { "report" , "repo" , POS_RESTING , do_report , 0, 0 }, @@ -1409,6 +1410,12 @@ void nanny(struct descriptor_data *d, char *arg) else mudlog(BRF, LVL_IMMORT, TRUE, "%s has connected.", GET_NAME(d->character)); + /* Add to the list of 'recent' players (since last reboot) */ + if (AddRecentPlayer(GET_NAME(d->character), d->host, FALSE, FALSE) == FALSE) + { + mudlog(BRF, MAX(LVL_IMMORT, GET_INVIS_LEV(d->character)), TRUE, "Failure to AddRecentPlayer (returned FALSE)."); + } + if (load_result) { write_to_output(d, "\r\n\r\n\007\007\007" "%s%d LOGIN FAILURE%s SINCE LAST SUCCESSFUL LOGIN.%s\r\n", @@ -1506,6 +1513,12 @@ void nanny(struct descriptor_data *d, char *arg) GET_HOST(d->character)= strdup(d->host); mudlog(NRM, LVL_GOD, TRUE, "%s [%s] new player.", GET_NAME(d->character), d->host); + + /* Add to the list of 'recent' players (since last reboot) */ + if (AddRecentPlayer(GET_NAME(d->character), d->host, TRUE, FALSE) == FALSE) + { + mudlog(BRF, MAX(LVL_IMMORT, GET_INVIS_LEV(d->character)), TRUE, "Failure to AddRecentPlayer (returned FALSE)."); + } break; case CON_RMOTD: /* read CR after printing motd */ diff --git a/src/structs.h b/src/structs.h index f1e986b..bf53587 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1240,6 +1240,18 @@ struct happyhour { int ticks_left; }; +/** structure for list of recent players (see 'recent' command) */ +struct recent_player +{ + int vnum; /* The ID number for this instance */ + char name[MAX_NAME_LENGTH]; /* The char name of the player */ + bool new_player; /* Is this a new player? */ + bool copyover_player; /* Is this a player that was on during the last copyover? */ + time_t time; /* login time */ + char host[HOST_LENGTH+1]; /* Host IP address */ + struct recent_player *next; /* Pointer to the next instance */ +}; + /* Config structs */ /** The game configuration structure used for configurating the game play