#include <stdio.h> #include <stdlib.h> /* #include <unistd.h> */ #include <sys/types.h> #include <signal.h> #include <string.h> #include <ctype.h> #include <sys/time.h> #include <time.h> #include "global.h" #include "bug.h" #include "utils.h" #include "comm.h" #include "db.h" #include "interpreter.h" #include "multiclass.h" #include "modify.h" #include "handler.h" #include "act_info.h" #define _BOARD_C #include "board.h" struct char_data *board_kludge_char = NULL; struct Board *board_list = NULL; void InitBoards() { if (DEBUG > 2) log_info("called %s with no arguments", __PRETTY_FUNCTION__); /* * this is called at the very beginning, like shopkeepers */ board_list = NULL; } void InitABoard(struct obj_data *obj) { struct Board *new_board = NULL; struct Board *tmp = NULL; if (DEBUG > 2) log_info("called %s with %s", __PRETTY_FUNCTION__, SAFE_ONAME(obj)); if (board_list) { /* ** try to match a board with an existing board in the game */ for (tmp = board_list; tmp; tmp = tmp->next) { if (tmp->Vnum == obj->item_number) { board_load_board(tmp); return; } } } CREATE(new_board, struct Board, 1); new_board->Vnum = obj_index[obj->item_number].virtual; board_load_board(new_board); tmp = board_list; new_board->next = tmp; board_list = new_board; } struct Board *FindBoardInRoom(int room) { struct obj_data *o = NULL; struct Board *nb = NULL; if (DEBUG > 2) log_info("called %s with %d", __PRETTY_FUNCTION__, room); if (!real_roomp(room)) return (NULL); for (o = real_roomp(room)->contents; o; o = o->next_content) { if (obj_index[o->item_number].func == (ifuncp)board) { for (nb = board_list; nb; nb = nb->next) { if (nb->Vnum == obj_index[o->item_number].virtual) return (nb); } return (NULL); } } return (NULL); } /* * This is a special procedure, the cmd/arg arguments must be in this order! */ int board(struct char_data *ch, int cmd, char *arg) { struct Board *nb = NULL; if (DEBUG > 2) log_info("called %s with %s, %s, %d", __PRETTY_FUNCTION__, SAFE_NAME(ch), VNULL(arg), cmd); nb = FindBoardInRoom(ch->in_room); if (!nb) return (FALSE); if (!ch->desc) return (FALSE); switch (cmd) { case CMD_north: case CMD_east: case CMD_south: case CMD_west: case CMD_up: case CMD_down: case CMD_who: case CMD_tell: case CMD_exits: case CMD_goto: case CMD_pager: case CMD_shutdown: return FALSE; break; case CMD_look: /* look */ if (!board_show_board(ch, arg, nb)) /* no args, or failed */ do_look(ch, "", 0); return TRUE; break; case CMD_write: /* write */ board_write_msg(ch, arg, nb); return TRUE; break; case CMD_read: /* read */ board_display_msg(ch, arg, nb); return TRUE; break; case CMD_remove: /* remove */ board_remove_msg(ch, arg, nb); return TRUE; break; default: return TRUE; } } void board_write_msg(struct char_data *ch, char *arg, struct Board *b) { char new_arg[60] = "\0\0\0"; char time_str[60] = "\0\0\0"; struct tm *tm_info = NULL; time_t tc; if (DEBUG > 2) log_info("called %s with %s, %s, %08zx", __PRETTY_FUNCTION__, SAFE_NAME(ch), VNULL(arg), (size_t)b); if (b->msg_num > MAX_MSGS - 1) { cprintf(ch, "The board is full already.\r\n"); return; } if (board_kludge_char) { cprintf(ch, "Sorry, but someone has stolen the pen.. wait a few minutes.\r\n"); return; } for (; isspace(*arg); arg++); if (!*arg) { cprintf(ch, "We must have a headline!\r\n"); return; } board_kludge_char = ch; tc = time(0); tm_info = (struct tm *)localtime(&tc); /* * +4 is for a space and '()' around the character name. */ CREATE(b->head[b->msg_num], char, 70 + strlen(GET_NAME(ch)) + 4); strncpy(new_arg, arg, 40); sprintf(time_str, "%s", asctime(tm_info)); time_str[strlen(time_str) - 1] = '\0'; sprintf(b->head[b->msg_num], "%s (%s) %s", new_arg, GET_NAME(ch), time_str); b->msgs[b->msg_num] = NULL; cprintf(ch, "Write your message. Terminate with an @.\r\n\r\n"); act("$n starts to write a message.", TRUE, ch, 0, 0, TO_ROOM); ch->desc->str = &b->msgs[b->msg_num]; ch->desc->max_str = MAX_MESSAGE_LENGTH; b->msg_num++; } int board_remove_msg(struct char_data *ch, char *arg, struct Board *b) { int ind = 0; int msg = 0; char msg_number[MAX_INPUT_LENGTH] = "\0\0\0"; if (DEBUG > 2) log_info("called %s with %s, %s, %08zx", __PRETTY_FUNCTION__, SAFE_NAME(ch), VNULL(arg), (size_t)b); one_argument(arg, msg_number); if (!*msg_number || !isdigit(*msg_number)) return (0); if (!(msg = atoi(msg_number))) return (0); if (!b->msg_num) { cprintf(ch, "The board is empty!\r\n"); return (1); } if (msg < 1 || msg > b->msg_num) { cprintf(ch, "That message exists only in your imagination..\r\n"); return (1); } if (GetMaxLevel(ch) < 19) { cprintf(ch, "Due to misuse of the REMOVE command, only 19th level\r\n"); cprintf(ch, "and above can remove messages.\r\n"); return 1; } ind = msg; ind--; DESTROY(b->head[ind]); DESTROY(b->msgs[ind]); for (; ind < b->msg_num - 1; ind++) { b->head[ind] = b->head[ind + 1]; b->msgs[ind] = b->msgs[ind + 1]; } b->msg_num--; board_save_board(b); cprintf(ch, "Message %d removed.\r\n", msg); return (1); } void board_reset_board(struct Board *b) { int ind = 0; if (DEBUG > 2) log_info("called %s with %08zx", __PRETTY_FUNCTION__, (size_t)b); for (ind = 0; ind < MAX_MSGS; ind++) { DESTROY(b->head[ind]); DESTROY(b->msgs[ind]); b->head[ind] = b->msgs[ind] = NULL; } b->msg_num = 0; return; } int board_display_msg(struct char_data *ch, char *arg, struct Board *b) { char msg_number[MAX_INPUT_LENGTH] = "\0\0\0"; int msg = 0; if (DEBUG > 2) log_info("called %s with %s, %s, %08zx", __PRETTY_FUNCTION__, SAFE_NAME(ch), VNULL(arg), (size_t)b); one_argument(arg, msg_number); if (!*msg_number || !isdigit(*msg_number)) return (0); if (!(msg = atoi(msg_number))) return (0); if (!b->msg_num) { cprintf(ch, "The board is empty!\r\n"); return (1); } if (msg < 1 || msg > b->msg_num) { cprintf(ch, "That message exists only in your imagination..\r\n"); return (1); } page_printf(ch, "Message %d : %s\r\n\r\n%s", msg, b->head[msg - 1], b->msgs[msg - 1]); return (1); } int board_show_board(struct char_data *ch, char *arg, struct Board *b) { int i = 0; char tmp[MAX_INPUT_LENGTH] = "\0\0\0"; if (DEBUG > 2) log_info("called %s with %s, %s, %08zx", __PRETTY_FUNCTION__, SAFE_NAME(ch), VNULL(arg), (size_t)b); one_argument(arg, tmp); if (!*tmp || !isname(tmp, "board bulletin")) return (0); if (board_kludge_char) { cprintf(ch, "Sorry, but someone is writing a message\r\n"); return (0); } page_printf(ch, "This is a bulletin board. Usage: READ/REMOVE <messg #>, WRITE <header>\r\n"); if (!b->msg_num) { page_printf(ch, "The board is empty.\r\n"); } else if (b->msg_num == 1) { page_printf(ch, "There is 1 message on the board.\r\n"); } else { page_printf(ch, "There are %d messages on the board.\r\n", b->msg_num); } for (i = 0; i < b->msg_num; i++) page_printf(ch, "%-2d : %s\r\n", i + 1, b->head[i]); return (1); } void board_save_board(struct Board *bp) { FILE *fp = NULL; int board_id = 0; int message_id = 0; char board_filename[MAX_STRING_LENGTH] = "\0\0\0\0\0\0\0"; int i = 0; if (DEBUG > 2) log_info("called %s with %08zx", __PRETTY_FUNCTION__, (size_t)bp); if (!bp) return; if (!bp->msg_num) { log_info("No messages to save.\r\n"); return; } board_id = bp->Vnum; sprintf(board_filename, "%s/%d.data", BOARD_DIR, board_id); if(!(fp = fopen(board_filename, "w"))) { log_error("Cannot open %s for writing!", board_filename); return; } fprintf(fp, "%d\n", bp->msg_num); for (i = 0; i < bp->msg_num; i++) { char message_date[25] = "\0\0\0\0\0\0\0"; char message_header[MAX_STRING_LENGTH] = "\0\0\0\0\0\0\0"; char message_sender[MAX_STRING_LENGTH] = "\0\0\0\0\0\0\0"; char message_text[MAX_STRING_LENGTH] = "\0\0\0\0\0\0\0"; char *mp = NULL; message_id = i; /* Adventurers WANTED! (Quixadhal) Sun Jul 25 00:35:39 2004 */ strcpy(message_date, bp->head[i] + strlen(bp->head[i]) - 24); strcpy(message_header, bp->head[i]); message_header[strlen(message_header) - 26] = '\0'; mp = strrchr(message_header, '('); if (mp) { strcpy(message_sender, mp + 1); *(mp - 1) = '\0'; } else { *message_sender = '\0'; } if (!bp->msgs[i]) { CREATE(bp->msgs[i], char, 50); /* Quixadhal: Why 50? */ strcpy(bp->msgs[i], "Generic Message"); } strcpy(message_text, bp->msgs[i]); fprintf(fp, "%d\n%s~\n%s~\n%s~\n%s~\n", message_id, message_date, message_sender, message_header, message_text); } fclose(fp); } void board_load_board(struct Board *bp) { FILE *fp = NULL; int board_id = 0; int message_id = 0; char board_filename[MAX_STRING_LENGTH] = "\0\0\0\0\0\0\0"; int message_count = 0; int i = 0; if (DEBUG > 2) log_info("called %s with %08zx", __PRETTY_FUNCTION__, (size_t)bp); if (!bp) return; board_id = bp->Vnum; sprintf(board_filename, "%s/%d.data", BOARD_DIR, board_id); if(!(fp = fopen(board_filename, "r"))) { log_error("Cannot open %s for reading!", board_filename); return; } message_count = fread_number(fp); bp->msg_num = MIN(MAX_MSGS, message_count); if(message_count >= MAX_MSGS) log_error("BOARD %d IS FULL!", board_id); for (i = 0; i < bp->msg_num; i++) { char *message_date = NULL; char *message_header = NULL; char *message_sender = NULL; char *message_text = NULL; char full_header[MAX_STRING_LENGTH] = "\0\0\0\0\0\0\0"; message_id = fread_number(fp); message_date = strdup(new_fread_string(fp)); message_sender = strdup(new_fread_string(fp)); message_header = strdup(new_fread_string(fp)); message_text = strdup(new_fread_string(fp)); /* Adventurers WANTED! (Quixadhal) Sun Jul 25 00:35:39 2004 */ strcpy(full_header, message_header); strcat(full_header, " ("); strcat(full_header, message_sender); strcat(full_header, ") "); strcat(full_header, message_date); free(message_date); free(message_header); free(message_sender); CREATE(bp->head[message_id], char, strlen(full_header) + 1); strcpy(bp->head[message_id], full_header); bp->msgs[message_id] = message_text; } fclose(fp); }