/* notify.c */ #include "config.h" /* * This file is part of TeenyMUD II. * Copyright(C) 1993, 1994, 1995 by Jason Downs. * All rights reserved. * * TeenyMUD II is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * TeenyMUD II is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program (see the file 'COPYING'); if not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * */ /* AIX requires this to be the first thing in the file. */ #ifdef __GNUC__ #define alloca __builtin_alloca #else /* not __GNUC__ */ #ifdef HAVE_ALLOCA_H #include <alloca.h> #else /* not HAVE_ALLOCA_H */ #ifdef _AIX #pragma alloca #endif /* not _AIX */ #endif /* not HAVE_ALLOCA_H */ #endif /* not __GNUC__ */ #include <stdio.h> #include <sys/types.h> #ifdef HAVE_STRING_H #include <string.h> #else #include <strings.h> #endif /* HAVE_STRING_H */ #ifdef HAVE_STDLIB_H #include <stdlib.h> #endif /* HAVE_STDLIB_H */ #include "conf.h" #include "teeny.h" #include "teenydb.h" #include "externs.h" /* routines for sending strings to players. */ static void nospoof_mesg _ANSI_ARGS_((char *, int, int, int)); void notify_bad(player) int player; { notify_player(player, player, player, "Something truly horrid just happened. Good luck.", 0); } /* Emulate MUSH-style NOSPOOF output. */ static void nospoof_mesg(buf, player, cause, sender) char *buf; int player, cause, sender; { char *sname, *soname; int sowner; if(get_str_elt(sender, NAME, &sname) != -1) { sprintf(buf, "[%s(#%d)", sname, sender); } else { sprintf(buf, "[(#%d", sender); } if(get_int_elt(sender, OWNER, &sowner) != -1) { if(sender != sowner) { if(get_str_elt(sowner, NAME, &soname) != -1) sprintf(&buf[strlen(buf)], "{%s}", soname); } } if(sender != cause) sprintf(&buf[strlen(buf)], "<-(#%d)", cause); strcat(buf, "]"); } /* Ugh. */ void notify_player(player, cause, sender, str, nflags) int player, cause, sender; char *str; int nflags; { char buf[MEDBUFFSIZ]; char *lbuf; int owner, loc, oloc; register int i, j; register char *nstr, *cstr; char *name; if ((str == (char *)NULL) || (str[0] == '\0')) return; if (!can_hear(player)) return; if ((nflags & NOT_QUIET) && (isQUIET(player) || isQUIET(sender))) return; /* we don't want to modify str. */ lbuf = (char *)alloca(strlen(str)+1); if(lbuf == (char *)NULL) panic("notify_player: stack allocation failed.\n"); strcpy(lbuf, str); nstr = lbuf; cstr = lbuf; while (nstr[0]) { for (; nstr[0] && (nstr[0] != '\n') && (nstr[0] != '\r'); nstr++); if ((nstr[0] == '\n') || (nstr[0] == '\r')) { nstr[0] = '\0'; for (nstr++; nstr[0] && ((nstr[0] == '\n') || (nstr[0] == '\r')); nstr++); } if (isALIVE(player)) { if ((nflags & NOT_NOSPOOF) && isNOSPOOF(player)) { nospoof_mesg(buf, player, cause, sender); i = strlen(buf); } else i = 0; for (j = 0; (i < sizeof(buf)-2) && cstr[j]; i++, j++) { buf[i] = cstr[j]; } buf[i] = '\0'; if (nflags & NOT_RAW) tcp_notify_raw(player, buf); else tcp_notify(player, buf); } if (isPUPPET(player)) { switch (Typeof(player)) { case TYP_THING: if ((get_str_elt(player, NAME, &name) == -1) || (get_int_elt(player, OWNER, &owner) == -1) || (get_int_elt(player, LOC, &loc) == -1) || (get_int_elt(owner, LOC, &oloc) == -1)) return; if (((nflags & NOT_NOPUPPET) && (loc == oloc)) || !isALIVE(owner)) break; if ((nflags & NOT_NOSPOOF) && isNOSPOOF(player)) { nospoof_mesg(buf, player, cause, sender); i = strlen(buf); } else i = 0; for (j = 0; (i < sizeof(buf)-3) && name[j]; i++, j++) { buf[i] = name[j]; } buf[i++] = '>'; buf[i++] = ' '; for (j = 0; (i < sizeof(buf)-2) && cstr[j]; i++, j++) { buf[i] = cstr[j]; } buf[i] = '\0'; if (nflags & NOT_RAW) tcp_notify_raw(owner, buf); else tcp_notify(owner, buf); break; } } if (isLISTENER(player)) { if(player != sender) { attr_listen(player, cause, '^', cstr); } else { attr_listen(player, cause, '+', cstr); } } if (isAUDIBLE(player) && !isROOM(player) && !(nflags & NOT_NOAUDIBLE)) notify_audible(player, cause, sender, cstr); cstr = nstr; } } void notify_audible(object, cause, sender, str) int object, cause, sender; char *str; { char buf[MEDBUFFSIZ], *prefix, *filter; int aflags, source; register int i, j; if ((attr_get_parent(object, APREFIX, &prefix, &aflags, &source) == -1) || (attr_get_parent(object, AFILTER, &filter, &aflags, &source) == -1)) return; if ((filter != (char *) NULL) && filter_match(str, filter)) return; if ((prefix == (char *) NULL) && isEXIT(object)) prefix = "From a distance,"; if (prefix && prefix[0]) { strcpy(buf, prefix); strcat(buf, " "); } else buf[0] = '\0'; for (i = strlen(buf), j = 0; (i < MEDBUFFSIZ) && str[j]; i++, j++) buf[i] = str[j]; buf[i] = '\0'; if (isEXIT(object)) { int *dests, loc; if ((get_int_elt(object, LOC, &loc) == -1) || (get_array_elt(object, DESTS, &dests) == -1) || (dests == (int *)NULL) || (loc == dests[1]) || !exists_object(dests[1]) || isACTION(object)) return; notify_contents(dests[1], cause, sender, buf, NOT_NOAUDIBLE); } else notify_contents(object, cause, sender, buf, NOT_NOAUDIBLE); } void notify_except2(player, cause, sender, string, except1, except2, nflags) int player, cause, sender; char *string; int except1, except2, nflags; { int loc, list; if (!string || !string[0]) return; if (get_int_elt(player, LOC, &loc) == -1) { logfile(LOG_ERROR, "notify_except2: bad location reference on object #%d\n", player); return; } if (get_int_elt(loc, CONTENTS, &list) == -1) { logfile(LOG_ERROR, "notify_except2: bad contents reference on object #%d\n", loc); return; } while (list != -1) { if ((list != except1) && (list != except2)) { notify_player(list, cause, sender, string, nflags); } if (get_int_elt(list, NEXT, &list) == -1) { logfile(LOG_ERROR, "notify_except2: bad next reference on object #%d\n", list); return; } } if (!(nflags & NOT_NOAUDIBLE)) { if (get_int_elt(loc, EXITS, &list) == -1) { logfile(LOG_ERROR, "notify_except2: bad exits list on object #%d\n", loc); return; } while (list != -1) { if (isAUDIBLE(list) && (list != except1) && (list != except2)) notify_audible(list, cause, sender, string); if (get_int_elt(list, NEXT, &list) == -1) { logfile(LOG_ERROR, "notify_except2: bad next reference on object #%d\n", list); return; } } } } void notify_contents_except(loc, cause, sender, str, except, nflags) int loc, cause, sender; char *str; int except, nflags; { int list; if (!has_contents(loc) || !str || !str[0]) return; if (get_int_elt(loc, CONTENTS, &list) == -1) { logfile(LOG_ERROR, "notify_contents_except: bad contents list on object #%d\n", list); return; } while (list != -1) { if ((except == -1) || (list != except)) { notify_player(list, cause, sender, str, nflags); } if (get_int_elt(list, NEXT, &list) == -1) { logfile(LOG_ERROR, "notify_contents_except: bad next reference on object #%d\n", list); return; } } if (!(nflags & NOT_NOAUDIBLE)) { if (get_int_elt(loc, EXITS, &list) == -1) { logfile(LOG_ERROR, "notify_contents_except: bad exits on object #%d\n", loc); return; } while (list != -1) { if (isAUDIBLE(list) && (list != except)) notify_audible(list, cause, sender, str); if (get_int_elt(list, NEXT, &list) == -1) { logfile(LOG_ERROR, "notify_contents_except: bad next reference on object #%d\n", list); return; } } } } void notify_contents_loc(loc, cause, sender, str, except, nflags) int loc, cause, sender; char *str; int except, nflags; { int list; if (!has_contents(loc) || !str || !str[0]) return; do { if (get_int_elt(loc, CONTENTS, &list) == -1) { logfile(LOG_ERROR, "notify_contents_loc: bad contents list on object #%d\n", list); return; } while (list != -1) { if ((except == -1) || (list != except)) { notify_player(list, cause, sender, str, nflags); } if (get_int_elt(list, NEXT, &list) == -1) { logfile(LOG_ERROR, "notify_contents_loc: bad next reference on object #%d\n", list); return; } } if (!(nflags & NOT_NOAUDIBLE)) { if (get_int_elt(loc, EXITS, &list) == -1) { logfile(LOG_ERROR, "notify_contents_loc: bad exits list on object #%d\n", loc); return; } while (list != -1) { if (isAUDIBLE(list) && (list != except)) notify_audible(list, cause, sender, str); if (get_int_elt(list, NEXT, &list) == -1) { logfile(LOG_ERROR, "notify_contents_loc: bad next reference on object #%d\n", list); return; } } } } while (!isROOM(loc) && (get_int_elt(loc, LOC, &loc) != -1)); } void notify_exits(player, cause, sender, list) int player, cause, sender, list; { char *name, buffer[BUFFSIZ + 4], *p; int any = 0, bufsiz, dohtml; dohtml = has_html(player); p = buffer; bufsiz = sizeof(buffer) - 4; while (list != -1) { if (!isOBVIOUS(list)) { if (get_int_elt(list, NEXT, &list) == -1) { logfile(LOG_ERROR, "notify_exits: bad next reference on object #%d\n", list); return; } continue; } any++; if (get_str_elt(list, NAME, &name) == -1) { logfile(LOG_ERROR, "notify_exits: bad name reference on object #%d\n", list); return; } while ((name[0] == ' ') || (name[0] == ';')) name++; if (dohtml) name = html_anchor_exit(name); for (; *name && (*name != ';') && ((p - buffer) < bufsiz); *p++ = *name++); if ((p - buffer) > bufsiz) { *p = '\0'; break; } *p++ = ','; *p++ = ' '; if (get_int_elt(list, NEXT, &list) == -1) { logfile(LOG_ERROR, "notify_exits: bad next reference on object #%d\n", list); return; } } if (any) { notify_player(player, cause, sender, "Obvious exits:", 0); if(p[-2] == ',') p[-2] = '\0'; if(dohtml) notify_player(player, cause, sender, buffer, NOT_RAW); else notify_player(player, cause, sender, buffer, 0); } } void notify_list(player, cause, sender, list, flags) int player, cause, sender, list, flags; { int count; int dohtml = has_html(player); if (dohtml) flags |= NOT_RAW; for (count = 0; (list != -1) && (count < mudconf.max_list); count++) { if (!(flags & NOT_DARKOK)) { if (!can_see(player, cause, list)) { /* Skip this name */ if (get_int_elt(list, NEXT, &list) == -1) { logfile(LOG_ERROR, "notify_list: bad next reference on object #%d\n", list); break; } continue; } } if ((flags & NOT_DARKOK) || (list != player)) { if (dohtml) { char *name; if(get_str_elt(list, NAME, &name) == -1) name = "???"; notify_player(player, cause, sender, html_anchor_contents(name, display_name(player, cause, list)), flags); } else { notify_player(player, cause, sender, display_name(player, cause, list), flags); } } if (get_int_elt(list, NEXT, &list) == -1) { logfile(LOG_ERROR, "notify_list: bad next reference on object #%d\n", list); break; } } } /* a combination of notify_exits() and notify_list(). */ void notify_list2(player, cause, sender, list, flags) int player, cause, sender, list, flags; { char *name, buffer[BUFFSIZ + 4], *ptr; int count, bufsiz; int dohtml = has_html(player); if (dohtml) flags |= NOT_RAW; bufsiz = sizeof(buffer) - 4; ptr = buffer; for (count = 0; (list != -1) && (count < mudconf.max_list); count++) { if (!(flags & NOT_DARKOK)) { if (!can_see(player, cause, list)) { /* Skip this name */ if (get_int_elt(list, NEXT, &list) == -1) { logfile(LOG_ERROR, "notify_list2: bad next reference on object #%d\n", list); break; } continue; } } if ((flags & NOT_DARKOK) || (list != player)) { if (dohtml) { char *sname; if(get_str_elt(list, NAME, &sname) == -1) sname = "???"; name = html_anchor_contents(sname, display_name(player, cause, list)); } else name = display_name(player, cause, list); if (((ptr - buffer) + strlen(name)) > bufsiz) { /* Display what we have and continue. */ if (ptr[-2] == ',') ptr[-2] = '\0'; notify_player(player, cause, sender, buffer, flags); ptr = buffer; goto nextlist; } for (; *name && ((ptr - buffer) < bufsiz); *ptr++ = *name++); if ((ptr - buffer) > bufsiz) { /* Opps, we overran it... */ *ptr = '\0'; break; } *ptr++ = ','; *ptr++ = ' '; } nextlist: if (get_int_elt(list, NEXT, &list) == -1) { logfile(LOG_ERROR, "notify_list2: bad next reference on object #%d\n", list); break; } } if (ptr > buffer) { if(ptr[-2] == ',') ptr[-2] = '\0'; notify_player(player, cause, sender, buffer, flags); } }