/* * IMC2 - an inter-mud communications protocol * * imc-mercbase.c: integrated interface code for Merc-derived codebases. * Now also includes patches for Circle. * * Copyright (C) 1996,1997 Oliver Jowett <oliver@jowett.manawatu.planet.co.nz> * * This program 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. * * This program 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., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /* Modifications by: * Erwin S. Andreasen <erwin@pip.dknet.dk> (Envy changes) * Erin Moeller <altrag@game.org> (Merc, SMAUG changes) * Stephen Zepp <zenithar@fullnet.net> (Ack! changes) * Trevor Man <tman@iname.com> (Circle changes) * * integration by Oliver Jowett */ #if !defined(CIRCLE) #include <stdlib.h> #include <sys/types.h> #include <sys/time.h> #include <ctype.h> #include <errno.h> #include <stdio.h> #include <unistd.h> #include <string.h> #endif #include "imc.h" /* ick! */ #define IN_IMC #include "imc-mercdefs.h" #include "imc-mercbase.h" /* memory allocation hooks */ void *imc_malloc(int size) { #if defined(SMAUG) || defined(CIRCLE) /* Have to use char because CREATE uses a sizeof, which doesnt like void */ char *mem; CREATE(mem, char, size); return (void *)mem; #elif defined(ACK) return getmem(size); #else return alloc_mem(size); #endif } void imc_free(void *block, int size) { #ifdef SMAUG DISPOSE(block); #elif defined(ACK) dispose(block, size); #elif defined(CIRCLE) free(block); #else free_mem(block, size); #endif } char *imc_strdup(const char *src) { return str_dup(src); } void imc_strfree(char *str) { #ifdef SMAUG DISPOSE(str); #elif defined(CIRCLE) free(str); #else free_string(str); #endif } /* config hooks */ int imc_readconfighook(const char *word, const char *value) { return 0; } void imc_saveconfighook(FILE *fp) { } /* call markfn for every chunk of memory allocated by IMC */ void imc_markmemory(void (*markfn)(void *)) { imc_reminfo *r; imc_mail *mailp; imc_qnode *queuep; imc_mailid *idp; imc_info *infop; imc_connect *cp; imc_event *ep; for (infop=imc_info_list; infop; infop=infop->next) markfn(infop); for (cp=imc_connect_list; cp; cp=cp->next) { markfn(cp->inbuf); markfn(cp->outbuf); markfn(cp); } for (r=imc_reminfo_list; r; r=r->next) markfn(r); for (mailp=imc_ml_head; mailp; mailp=mailp->next) markfn(mailp); for (queuep=imc_mq_head; queuep; queuep=queuep->next) markfn(queuep); for (idp=imc_idlist; idp; idp=idp->next) markfn(idp); for (ep=imc_event_list; ep; ep=ep->next) markfn(ep); for (ep=imc_event_free; ep; ep=ep->next) markfn(ep); } /* call markfn for every string allocated by IMC */ void imc_markstrings(void (*markfn)(char *)) { int i; imc_reminfo *r; imc_mail *mailp; imc_qnode *queuep; imc_mailid *idp; imc_info *infop; imc_ignore_data *ign; markfn(imc_name); markfn(imc_prefix); for (infop=imc_info_list; infop; infop=infop->next) { markfn(infop->name); markfn(infop->host); markfn(infop->serverpw); markfn(infop->clientpw); } for (r=imc_reminfo_list; r; r=r->next) { markfn(r->name); markfn(r->version); markfn(r->route); } for (ign=imc_ignore_list; ign; ign=ign->next) markfn(ign->name); for (i=0; i<IMC_MEMORY; i++) if (imc_memory[i].from) markfn(imc_memory[i].from); for (mailp=imc_ml_head; mailp; mailp=mailp->next) { markfn(mailp->from); markfn(mailp->to); markfn(mailp->date); markfn(mailp->text); markfn(mailp->subject); markfn(mailp->id); } for (queuep=imc_mq_head; queuep; queuep=queuep->next) markfn(queuep->tomud); for (idp=imc_idlist; idp; idp=idp->next) markfn(idp->id); } /* Color configuration (more tables to configure.. sowwy) * * The various #defines here are used within the IMC code to format * things like rtells themselves (not the text of the message, but the * "a@b rtells you 'blah'" structure) * * Each C_? #define maps an IMC color code (the ?) to one of your color codes. * * The various FORMATs define colors for rbeep, etc * * this may seem ugly, but it makes things expandable - and it will probably * go away in the near future anyway * */ #ifdef ACK #define RTELL_FORMAT_1 COL(W) "You rtell " COL(Y) "%s " COL(W) "'" COL(w) "%s" COL(W) "'\n\r" COL(d) #define RTELL_FORMAT_2 COL(Y) "%s " COL(W) "rtells you '" COL(w) "%s" COL(W) "'\n\r" COL(d) #define RBEEP_FORMAT_1 COL(R) "You rbeep " COL(Y) "%s" COL(R) ".\n\r" COL(d) #define RBEEP_FORMAT_2 COL(Y) "\a%s " COL(R) "rbeeps you.\n\r" COL(d) #else /* custom formats */ #define RTELL_FORMAT_1 "You rtell %s '%s" COL(d) "'.\n\r" #define RTELL_FORMAT_2 "%s rtells you '%s" COL(d) "'.\n\r" #define RBEEP_FORMAT_1 "You rbeep %s.\n\r" #define RBEEP_FORMAT_2 "\a%s rbeeps you.\n\r" #endif #ifdef ACK /* Ack! colors */ #define COL(x) C_##x #define C_b "@@B" #define C_g "@@G" #define C_r "@@R" #define C_y "@@b" #define C_m "@@m" #define C_c "@@c" #define C_w "@@g" #define C_D "@@d" #define C_B "@@l" #define C_G "@@r" #define C_R "@@e" #define C_Y "@@y" #define C_M "@@p" #define C_C "@@a" #define C_W "@@W" #define C_x "@@N" #define C_d "@@N" #elif defined(SMAUG) /* SMAUG colors */ #define COL(x) C_##x #define C_b "&b" #define C_g "&g" #define C_r "&r" #define C_y "&O" #define C_m "&p" #define C_c "&c" #define C_w "&w" #define C_D "&z" #define C_B "&B" #define C_G "&G" #define C_R "&R" #define C_Y "&Y" #define C_M "&P" #define C_C "&C" #define C_W "&W" #define C_x "&w" #define C_d "&w" #elif defined(CIRCLE) /* Circle colors - Easy Colour 2.2 */ #define COL(x) C_##x #define C_b "&b" #define C_g "&g" #define C_r "&r" #define C_y "&y" #define C_m "&m" #define C_c "&c" #define C_w "&w" #define C_D "&K" #define C_B "&B" #define C_G "&G" #define C_R "&R" #define C_Y "&Y" #define C_M "&M" #define C_C "&C" #define C_W "&W" #define C_x "&n" #define C_d "&n" #elif defined(IMC_COLOR) /* custom color configuration */ #define COL(x) C_##x #define C_b "{b" #define C_g "{g" #define C_r "{r" #define C_y "{y" #define C_m "{m" #define C_c "{c" #define C_w "{w" #define C_D "{D" #define C_B "{B" #define C_G "{G" #define C_R "{R" #define C_Y "{Y" #define C_M "{M" #define C_C "{C" #define C_W "{W" #define C_x "{x" #define C_d "{d" #else /* no color */ #define COL(x) "" #endif /* maps IMC standard -> mud local color codes * let's be unique, noone uses ~ :> */ /* Most of this table will be generated from the #defines above; * you will just need to add the exceptions. */ struct { char *imc; /* IMC code to convert */ char *mud; /* Equivalent mud code */ } trans_table[]= { /* common color definitions, derived from the #defines above */ { "~!", COL(x) }, /* reset */ { "~d", COL(d) }, /* default */ { "~b", COL(b) }, /* dark blue */ { "~g", COL(g) }, /* dark green */ { "~r", COL(r) }, /* dark red */ { "~y", COL(y) }, /* dark yellow / brown */ { "~m", COL(m) }, /* dark magenta / purple */ { "~c", COL(c) }, /* cyan */ { "~w", COL(w) }, /* white */ { "~D", COL(D) }, /* dark grey / "z" ? */ { "~B", COL(B) }, /* light blue */ { "~G", COL(G) }, /* light green */ { "~R", COL(R) }, /* light red */ { "~Y", COL(Y) }, /* light yellow */ { "~M", COL(M) }, /* light magenta / purple */ { "~C", COL(C) }, /* light cyan */ { "~W", COL(W) }, /* bright white */ #ifdef SMAUG /* built-in SMAUG color */ { "&", "&&" }, { "^", "^^" }, { "~~", "&-" }, /* note ordering here.. */ { "~~", "~" }, /* background colors - no support for these in IMC */ { "", "^b" }, { "", "^g" }, { "", "^r" }, { "", "^O" }, { "", "^p" }, { "", "^c" }, { "", "^w" }, { "", "^z" }, { "", "^B" }, { "", "^G" }, { "", "^R" }, { "", "^Y" }, { "", "^P" }, { "", "^C" }, { "", "^W" }, #elif defined(ACK) /* built-in Ack! color */ { "~~", "~" }, /* escape raw tildes */ { "@@", "@ @" }, /* escape our color character */ { "~!", "@@x" }, /* catch commonly used (but incorrect) codes */ { "~!", "@@f" }, /* ditto */ { "~!", "@@!" }, /* ditto */ { "~!", "@@." }, /* ditto */ { "~!", "@@n" }, /* ditto */ { "~!", "@@i" }, /* ditto */ { "~D", "@@k" }, /* black -> grey */ #elif defined(IMC_COLOR) /* generic color; change as needed */ { "~~", "~" }, /* escape raw tildes */ { "{", "{{" }, /* escape our color character */ #else /* no color support */ { "~~", "~" }, /* escape raw tildes */ #endif }; #define numtrans (sizeof(trans_table)/sizeof(trans_table[0])) /* convert from imc color -> mud color */ const char *color_itom(const char *s) { char *buf=imc_getsbuf(IMC_DATA_LENGTH); const char *current; char *out; int i, l; int count; for (current=s, out=buf, count=0; *current && count<IMC_DATA_LENGTH; ) { if (*current=='~' || *current==IMC_COLORCHAR || *current==IMC_COLORCHAR2) { for (i=0; i<numtrans; i++) { l=strlen(trans_table[i].imc); if (l && !strncmp(current, trans_table[i].imc, l)) break; } if (i!=numtrans) /* match */ { int len; len=strlen(trans_table[i].mud); count+=len; if (count >= IMC_DATA_LENGTH) break; memcpy(out, trans_table[i].mud, len); out+=len; current+=l; continue; } } *out++=*current++; count++; } *out=0; imc_shrinksbuf(buf); return buf; } /* convert from mud color -> imc color */ const char *color_mtoi(const char *s) { char *buf=imc_getsbuf(IMC_DATA_LENGTH); const char *current; char *out; int i, l; int count; for (current=s, out=buf, count=0; *current && count<IMC_DATA_LENGTH; ) { if (*current=='~' || *current==IMC_COLORCHAR || *current==IMC_COLORCHAR2) { for (i=0; i<numtrans; i++) { l=strlen(trans_table[i].mud); if (l && !strncmp(current, trans_table[i].mud, l)) break; } if (i!=numtrans) /* match */ { int len; len=strlen(trans_table[i].imc); count+=len; if (count>=IMC_DATA_LENGTH) break; memcpy(out, trans_table[i].imc, len); out+=len; current+=l; continue; } } *out++=*current++; count++; } *out=0; imc_shrinksbuf(buf); return buf; } /* #ifdefs here are ugly, but will eventually disappear */ static struct { int number; const char *name; const char *chatstr; const char *emotestr; long flag; int minlevel; char *to; } imc_channels[]= { #ifdef ACK /* Ack!-specific formatting - ick */ { 2, "RInfo", "@@W[@@aRINFO@@W] @@a%s@@W:'@@g%s@@W'@@N\n\r", "@@W[@@aRINFO@@W] @@a%s@@W %s@@N\n\r", IMC_RINFO, L_SUP, "*", }, /* ICE status channel */ { 15, "ICE", "@@W[@@aICE@@W] @@a%s@@W %s@@N\n\r", "@@W[@@aICE@@W] @@a%s@@W %s@@N\n\r", IMC_ICE, L_SUP, "*" }, #else /* non-Ack! */ { 2, "RInfo", /* why didn't I think of this? :) */ "%s announces '%s" COL(d) "'\n\r", "[RInfo] %s %s\n\r" COL(d), IMC_RINFO, LEVEL_IMMORTAL, "*", }, { 15, "ICE", "[ICE] %s %s" COL(d) "\n\r", "[ICE] %s %s" COL(d) "\n\r", IMC_ICE, LEVEL_IMMORTAL, "*" } #endif /* #ifdef ACK */ /* * An example of how to set up a channel that is only distributed between * the three muds 'mud1', 'mud2', and 'mud3'. { 76, -- channel number to use, change this! "LocalChannel", -- the channel name "%s localchannels '%s'\n\r", -- format for a normal message "[LocalChannel] %s %s\n\r", -- format for an emote IMC_LOCALCHANNEL, -- flag in imc_deaf, etc LEVEL_IMMORTAL, -- min. level for channel "mud1 mud2 mud3" -- muds to distribute to (include your own) } * (see the interack channel in #ifdef ACK, above, for an example) * */ }; #define numchannels (sizeof(imc_channels)/sizeof(imc_channels[0])) static int getlevel(int l) { if (l<LEVEL_HERO) return 1; else return -1; } #ifdef CIRCLE void bug(char *format, int tmp) { sprintf(buf, format, tmp); log(buf); return; } #endif #if defined(CIRCLE) && defined(NEED_STR_PREFIX) bool str_prefix(const char *astr, const char *bstr) { if (!astr) { log("Strn_cmp: null astr."); return TRUE; } if (!bstr) { log("Strn_cmp: null astr."); return TRUE; } for(; *astr; astr++, bstr++) { if(LOWER(*astr) != LOWER(*bstr)) return TRUE; } return FALSE; } #endif static const imc_char_data *getdata(CHAR_DATA *ch) { static imc_char_data d; if (!ch) /* fake system character */ { d.wizi=0; d.level=-1; d.invis=0; strcpy(d.name, "*"); return &d; } if (IS_RINVIS(ch)) d.invis=1; else d.invis=0; #ifdef ROM d.wizi=(ch->invis_level || ch->incog_level || IS_AFFECTED(ch, AFF_HIDE) || IS_AFFECTED(ch, AFF_SNEAK) || IS_AFFECTED(ch, AFF_INVISIBLE)) ? -1 : 0; #elif defined(SMAUG) d.wizi=(IS_SET(ch->act, PLR_WIZINVIS) || IS_AFFECTED(ch, AFF_HIDE) || IS_AFFECTED(ch, AFF_SNEAK) || IS_AFFECTED(ch, AFF_INVISIBLE)) ? -1 : 0; #elif defined(ACK) d.wizi=(IS_SET(ch->act, PLR_WIZINVIS) || IS_AFFECTED(ch, AFF_HIDE) || IS_AFFECTED(ch, AFF_SNEAK) || IS_AFFECTED(ch, AFF_INVISIBLE)) ? -1 : 0; #elif defined(CIRCLE) d.wizi=GET_INVIS_LEV(ch); #else d.wizi=(IS_SET(ch->act, PLR_WIZINVIS) || IS_AFFECTED(ch, AFF_HIDE) || IS_AFFECTED(ch, AFF_SNEAK) || IS_AFFECTED(ch, AFF_INVISIBLE)) ? -1 : 0; #endif d.level=getlevel(get_trust(ch)); strcpy(d.name, GET_NAME(ch)); return &d; } static int visible(const imc_char_data *viewer, const imc_char_data *viewed) { /* this is now a lot simpler */ return !viewed->invis && (viewer->level < 0 || viewed->wizi >= 0); } static const char *getname(CHAR_DATA *ch, const imc_char_data *vict) { const char *mud, *name; const imc_char_data *chdata; mud=imc_mudof(vict->name); name=imc_nameof(vict->name); chdata=getdata(ch); #ifdef CIRCLE if (!str_cmp((char *)mud, imc_name)) #else if (!str_cmp(mud, imc_name)) #endif #ifdef ACK return visible(chdata,vict) ? imc_nameof(name) : (chdata->wizi ? "A Mystical Being" : "someone"); #else return visible(getdata(ch),vict) ? imc_nameof(name) : "someone"; #endif else { if (visible(getdata(ch),vict)) return vict->name; else { char *buf=imc_getsbuf(IMC_NAME_LENGTH); #ifdef ACK sprintf(buf, "%s@%s", (getdata(ch))->wizi ? "A Mystical Being" : "someone", mud); #else sprintf(buf, "someone@%s", mud); #endif imc_shrinksbuf(buf); return buf; } } } static void send_rchannel(CHAR_DATA *ch, char *argument, int number) { char arg[MAX_STRING_LENGTH]; char *arg2; int chan; CHECKIMC(ch); #ifdef CIRCLE skip_spaces(&argument); #endif for (chan=0; chan<numchannels; chan++) if (imc_channels[chan].number==number) break; if (chan==numchannels) { send_to_char("That channel doesn't seem to exist!\n\r", ch); bug("IMC channel %d doesn't exist?!", number); return; /* oops */ } if (!CAN(ch, imc_channels[chan].flag, imc_channels[chan].minlevel)) { sprintf(arg, "You are not authorised to use %s.\n\r", imc_channels[chan].name); send_to_char(arg, ch); return; } if (!argument[0]) { if (IS_SET(IMC_DEAF_FLAGS(ch), imc_channels[chan].flag)) { sprintf(arg, "%s channel is now ON.\n\r", imc_channels[chan].name); send_to_char(arg, ch); REMOVE_BIT(IMC_DEAF_FLAGS(ch), imc_channels[chan].flag); return; } sprintf(arg, "%s channel is now OFF.\n\r", imc_channels[chan].name); send_to_char(arg, ch); SET_BIT(IMC_DEAF_FLAGS(ch), imc_channels[chan].flag); return; } if (IS_NOCHAN(ch)) { send_to_char("The gods have revoked your channel priviliges.\n\r", ch); return; } if (IS_QUIET(ch)) { send_to_char("You must turn off quiet mode first.\n\r", ch); return; } if (IS_SILENT(ch)) { send_to_char ("You can't seem to break the silence.\n\r",ch); return; } if (IS_RINVIS(ch)) { send_to_char ("You cannot use IMC channels while invisible to IMC.\n\r", ch); return; } REMOVE_BIT(IMC_DEAF_FLAGS(ch), imc_channels[chan].flag); /* NargoRoth's bugfix here */ arg2=one_argument(argument, arg); #ifdef CIRCLE skip_spaces(&arg2); #endif if (!str_cmp(arg, ",") || !str_cmp(arg, "emote")) imc_send_emote(getdata(ch), number, color_mtoi(arg2), imc_channels[chan].to); else imc_send_chat(getdata(ch), number, color_mtoi(argument), imc_channels[chan].to); } DEFINE_DO_FUN(do_rchat) { send_rchannel(ch, argument, 0); } DEFINE_DO_FUN(do_rimm) { send_rchannel(ch, argument, 1); } DEFINE_DO_FUN(do_rinfo) { send_rchannel(ch, argument, 2); } DEFINE_DO_FUN(do_rcode) { send_rchannel(ch, argument, 3); } #ifdef ACK DEFINE_DO_FUN(do_interack) { send_rchannel(ch, argument, 243); } #endif DEFINE_DO_FUN(do_rtell) { char buf[MAX_STRING_LENGTH], buf1[MAX_STRING_LENGTH]; CHECKIMC(ch); argument=one_argument(argument, buf); #ifdef CIRCLE skip_spaces(&argument); #endif if (!buf[0] || !strchr(buf, '@') || !argument[0]) { send_to_char("rtell who@where what?\n\r", ch); return; } if (!CAN(ch, IMC_RTELL, IMC_LEVEL_RTELL)) { send_to_char("You are not authorised to use rtell.\n\r", ch); return; } if (IS_NOTELL(ch)) { send_to_char("You cannot tell!\n\r", ch); return; } if (IS_RINVIS(ch)) { send_to_char ("You cannot rtell while invisible to IMC.\n\r", ch); return; } if (IS_SET(IMC_DEAF_FLAGS(ch), IMC_RTELL)) { send_to_char("Enable incoming rtells first ('rchannel +rtell').\n\r", ch); return; } #ifdef ACK if (IS_SET(ch->pcdata->pflags, PFLAG_AFK)) { send_to_char("Turn off AFK mode first.\n\r", ch); return; } #endif #ifdef ROM if (IS_SET(ch->comm, COMM_AFK)) { send_to_char("Turn off AFK mode first.\n\r", ch); return; } if (IS_SET(ch->comm, COMM_DEAF)) { send_to_char("You must turn off deaf mode first.\n\r", ch); return; } #endif if (IS_QUIET(ch)) { send_to_char("You must turn off quiet mode first.\n\r", ch); return; } CHECKMUDOF(ch, buf); imc_send_tell(getdata(ch), buf, color_mtoi(argument), 0); sprintf(buf1, RTELL_FORMAT_1, buf, argument); send_to_char(buf1, ch); } DEFINE_DO_FUN(do_rreply) { char buf1[MAX_STRING_LENGTH]; CHECKIMC(ch); if (!IMC_RREPLY(ch)) { send_to_char("rreply to who?\n\r", ch); return; } #ifdef CIRCLE skip_spaces(&argument); #endif if (!argument[0]) { send_to_char("rreply what?\n\r", ch); return; } /* just check for deny, since you can rtell someone < IMC_LEVEL_RTELL */ if (IS_SET(IMC_DENY_FLAGS(ch), IMC_RTELL)) { send_to_char("You are not authorised to use rreply.\n\r", ch); return; } if (IS_NOTELL(ch)) { send_to_char("You cannot tell!\n\r", ch); return; } if (IS_RINVIS(ch)) { send_to_char ("You cannot rreply while invisible to IMC.\n\r", ch); return; } if (IS_SET(IMC_DEAF_FLAGS(ch), IMC_RTELL)) { send_to_char("Enable incoming rtells first ('rchannel +rtell').\n\r", ch); return; } #ifdef ACK if (IS_SET(ch->pcdata->pflags, PFLAG_AFK)) { send_to_char("Turn off AFK mode first.\n\r", ch); return; } #endif #ifdef ROM if (IS_SET(ch->comm, COMM_AFK)) { send_to_char("Turn off AFK mode first.\n\r", ch); return; } if (IS_SET(ch->comm, COMM_DEAF)) { send_to_char("You must turn off deaf mode first.\n\r",ch); return; } #endif if (IS_QUIET(ch)) { send_to_char("You must turn off quiet mode first.\n\r", ch); return; } CHECKMUDOF(ch, IMC_RREPLY(ch)); imc_send_tell(getdata(ch), IMC_RREPLY(ch), color_mtoi(argument), 1); sprintf(buf1, RTELL_FORMAT_1, IMC_RREPLY_NAME(ch), argument); send_to_char(buf1, ch); } DEFINE_DO_FUN(do_rwho) { char arg[MAX_STRING_LENGTH]; CHECKIMC(ch); argument=one_argument(argument, arg); #ifdef CIRCLE skip_spaces(&argument); #endif if (!arg[0]) { send_to_char("rwho where?\n\r", ch); return; } CHECKMUD(ch, arg); imc_send_who(getdata(ch), arg, argument[0] ? argument : "who"); } DEFINE_DO_FUN(do_rwhois) { char arg[MAX_STRING_LENGTH]; CHECKIMC(ch); argument=one_argument(argument, arg); #ifdef CIRCLE skip_spaces(&argument); #endif if (!arg[0]) { send_to_char("rwho whom?\n\r", ch); return; } imc_send_whois(getdata(ch), arg); } DEFINE_DO_FUN(do_rfinger) { char arg[MAX_STRING_LENGTH]; char name[MAX_STRING_LENGTH]; CHECKIMC(ch); argument=one_argument(argument, arg); #ifdef CIRCLE skip_spaces(&argument); #endif if (!arg[0] || !strchr(arg, '@')) { send_to_char("rfinger who@where?\n\r", ch); return; } CHECKMUD(ch, imc_mudof(arg)); sprintf(name, "finger %s", imc_nameof(arg)); imc_send_who(getdata(ch), imc_mudof(arg), name); } DEFINE_DO_FUN(do_rquery) { char arg[MAX_STRING_LENGTH]; CHECKIMC(ch); argument=one_argument(argument, arg); #ifdef CIRCLE skip_spaces(&argument); #endif if (!arg[0]) { send_to_char("rquery where?\n\r", ch); return; } CHECKMUD(ch, arg); imc_send_who(getdata(ch), arg, argument[0] ? argument : "help"); } DEFINE_DO_FUN(do_rbeep) { char buf[MAX_STRING_LENGTH]; CHECKIMC(ch); #ifdef CIRCLE skip_spaces(&argument); #endif if (!argument[0] || !strchr(argument, '@')) { send_to_char("rbeep who@where?\n\r", ch); return; } if (!CAN(ch, IMC_RBEEP, IMC_LEVEL_RBEEP)) { send_to_char("You are not authorised to rbeep.\n\r", ch); return; } if (IS_NOTELL(ch)) { send_to_char("You cannot beep!\n\r", ch); return; } if (IS_RINVIS(ch)) { send_to_char ("You cannot rbeep while invisible to IMC.\n\r", ch); return; } if (IS_QUIET(ch)) { send_to_char("You must turn off quiet mode first.\n\r", ch); return; } #ifdef ROM if (IS_SET(ch->comm, COMM_DEAF)) { send_to_char("You must turn off deaf mode first.\n\r", ch); return; } #endif CHECKMUDOF(ch, argument); imc_send_beep(getdata(ch), argument); sprintf(buf, RBEEP_FORMAT_1, argument); send_to_char(buf, ch); WAIT_STATE(ch, PULSE_PER_SECOND * 5); } DEFINE_DO_FUN(do_imclist) { #ifdef CIRCLE skip_spaces(&argument); #endif if (!argument[0]) page_to_char(imc_list(3), ch); else if (!str_prefix(argument, "all")) page_to_char(imc_list(6), ch); else if (!str_prefix(argument, "direct")) { if (get_trust(ch)>=MAX_LEVEL-1) page_to_char(imc_list(2), ch); else if (IS_IMMORTAL(ch)) page_to_char(imc_list(1), ch); else page_to_char(imc_list(0), ch); } else if (!str_prefix(argument, "config")) { if (IS_IMMORTAL(ch)) page_to_char(imc_list(5), ch); else page_to_char(imc_list(4), ch); } else page_to_char("Unknown option.", ch); page_to_char("\n\r", ch); } DEFINE_DO_FUN(do_rsockets) { CHECKIMC(ch); page_to_char(imc_sockets(), ch); } DEFINE_DO_FUN(do_imc) { int r; #ifdef CIRCLE skip_spaces(&argument); #endif r=imc_command(argument); if (r>0) { send_to_char("Ok.\n\r", ch); return; } else if (r==0) { send_to_char("Syntax: imc add <mudname>\n\r" " imc delete <mudname>\n\r" " imc set <mudname> all <host> <port> <clientpw> <serverpw>\n\r" " <rcvstamp> <noforward> <flags>\n\r" " imc set <mudname> host|port|clientpw|serverpw|rcvstamp|\n\r" " noforward|flags <value>\n\r" " imc rename <oldmudname> <newmudname>\n\r" " imc localname <mudname>\n\r" " imc localport <portnum>\n\r" " imc reload\n\r", ch); return; } #ifdef CIRCLE send_to_char((char *)imc_error(), ch); #else send_to_char(imc_error(), ch); #endif send_to_char("\n\r", ch); } DEFINE_DO_FUN(do_rignore) { #ifdef CIRCLE skip_spaces(&argument); #endif #ifdef CIRCLE send_to_char((char *)imc_ignore(argument), ch); #else send_to_char(imc_ignore(argument), ch); #endif send_to_char("\n\r", ch); } DEFINE_DO_FUN(do_rconnect) { CHECKIMC(ch); #ifdef CIRCLE skip_spaces(&argument); #endif if (!argument[0]) { send_to_char("rconnect to where?\n\r", ch); return; } if (imc_connect_to(argument)) { send_to_char("Ok.\n\r", ch); return; } #ifdef CIRCLE send_to_char((char *)imc_error(), ch); #else send_to_char(imc_error(), ch); #endif send_to_char("\n\r", ch); } DEFINE_DO_FUN(do_rdisconnect) { CHECKIMC(ch); #ifdef CIRCLE skip_spaces(&argument); #endif if (!argument[0]) { send_to_char("rdisconnect where?\n\r", ch); return; } if (imc_disconnect(argument)) { send_to_char("Ok.\n\r", ch); return; } #ifdef CIRCLE send_to_char((char *)imc_error(), ch); #else send_to_char(imc_error(), ch); #endif send_to_char("\n\r", ch); } DEFINE_DO_FUN(do_mailqueue) { CHECKIMC(ch); page_to_char(imc_mail_showqueue(), ch); } DEFINE_DO_FUN(do_istats) { CHECKIMC(ch); #ifdef CIRCLE send_to_char((char *)imc_getstats(), ch); #else send_to_char(imc_getstats(), ch); #endif } DEFINE_DO_FUN(do_rchannels) { char buf[MAX_STRING_LENGTH]; char arg[MAX_STRING_LENGTH]; bool toggle; int i; const char *name; long flag; if (IS_NPC(ch)) { send_to_char("NPCs cannot use IMC.\n\r", ch); return; } one_argument(argument, arg); #ifdef CIRCLE skip_spaces(&argument); #endif if (!arg[0]) { /* list channel status */ bool found=FALSE; strcpy(buf, "channel status\n\r" "-------------------\n\r"); for (i=0; i<numchannels; i++) { if (IS_SET(IMC_DENY_FLAGS(ch), imc_channels[i].flag)) { sprintf(buf+strlen(buf), "%-10s : you are denied from this channel.\n\r", imc_channels[i].name); found=TRUE; } else if (CAN(ch, imc_channels[i].flag, imc_channels[i].minlevel)) { sprintf(buf+strlen(buf), "%-10s : %s\n\r", imc_channels[i].name, (IS_SET(IMC_DEAF_FLAGS(ch), imc_channels[i].flag) ? "OFF" : "ON")); found=TRUE; } } if (IS_SET(IMC_DENY_FLAGS(ch), IMC_RTELL)) { strcat(buf, "RTells : you cannot rtell.\n\r"); found=TRUE; } else if (CAN(ch, IMC_RTELL, IMC_LEVEL_RTELL)) { sprintf(buf+strlen(buf), "%-10s : %s\n\r", "RTell", IS_SET(IMC_DEAF_FLAGS(ch), IMC_RTELL) ? "OFF" : "ON"); found=TRUE; } if (IS_SET(IMC_DENY_FLAGS(ch), IMC_RBEEP)) { strcat(buf, "RBeeps : you cannot rbeep.\n\r"); found=TRUE; } else if (CAN(ch, IMC_RBEEP, IMC_LEVEL_RBEEP)) { sprintf(buf+strlen(buf), "%-10s : %s\n\r", "RBeep", IS_SET(IMC_DEAF_FLAGS(ch), IMC_RBEEP) ? "OFF" : "ON"); found=TRUE; } if (IS_SET(IMC_DEAF_FLAGS(ch), IMC_RINVIS)) sprintf(buf+strlen(buf), "You are not visible to others over IMC.\n\r"); if (!found) send_to_char("You have access to no IMC channels.\n\r", ch); else send_to_char(buf, ch); return; } /* turn some things on or off */ while((argument=one_argument(argument, arg)), arg[0]) { if (arg[0]=='-') toggle=FALSE; else if (arg[0]=='+') toggle=TRUE; else { send_to_char("Syntax: rchannels displays current IMC channels\n\r" " rchannels +chan turn on a channel\n\r" " rchannels -chan turn off a channel\n\r" "chan may be an IMC channel name, 'rbeep', 'rtell', 'rinvis', or 'all'.\n\r" "Multiple settings may be given in one command.\n\r", ch); return; } if (!str_cmp(arg+1, "all")) { if (toggle) { send_to_char("ALL available IMC channels are now on.\n\r", ch); IMC_DEAF_FLAGS(ch)=0; } else { send_to_char("ALL available IMC channels are now off.\n\r", ch); IMC_DEAF_FLAGS(ch)=-1L; } continue; } else if (!str_cmp(arg+1, "rtell") && CAN(ch, IMC_RTELL, IMC_LEVEL_RTELL)) { name="RTell"; flag=IMC_RTELL; } else if (!str_cmp(arg+1, "rbeep") && CAN(ch, IMC_RBEEP, IMC_LEVEL_RBEEP)) { name="RBeep"; flag=IMC_RBEEP; } else if (!str_cmp(arg+1, "rinvis")) { name="RInvis"; flag=IMC_RINVIS; toggle=!toggle; } else { for (i=0; i<numchannels; i++) { if (CAN(ch, imc_channels[i].flag, imc_channels[i].minlevel) && #ifdef CIRCLE !str_cmp((char *)imc_channels[i].name, arg+1)) #else !str_cmp(imc_channels[i].name, arg+1)) #endif break; } if (i==numchannels) { sprintf(buf, "You don't have access to an IMC channel called \"%s\".\n\r", arg); send_to_char(buf, ch); continue; } name=imc_channels[i].name; flag=imc_channels[i].flag; } if (toggle && !IS_SET(IMC_DEAF_FLAGS(ch), flag)) { if (flag==IMC_RINVIS) strcpy(buf, "You are already visible on IMC.\n\r"); else sprintf(buf, "%s is already on.\n\r", name); send_to_char(buf, ch); continue; } if (!toggle && IS_SET(IMC_DEAF_FLAGS(ch), flag)) { if (flag==IMC_RINVIS) strcpy(buf, "You are already invisible on IMC.\n\r"); else sprintf(buf, "%s is already off.\n\r", name); send_to_char(buf, ch); continue; } if (toggle) { if (flag==IMC_RINVIS) strcpy(buf, "You are no longer invisible to IMC.\n\r"); else sprintf(buf, "%s is now ON.\n\r", name); REMOVE_BIT(IMC_DEAF_FLAGS(ch), flag); } else { if (flag==IMC_RINVIS) strcpy(buf, "You are now invisible to rwho, rtell and rbeep on IMC.\n\r"); else sprintf(buf, "%s is now OFF.\n\r", name); SET_BIT(IMC_DEAF_FLAGS(ch), flag); } send_to_char(buf, ch); } } DEFINE_DO_FUN(do_rchanset) { char arg[MAX_STRING_LENGTH]; CHAR_DATA *victim; int flag, i; const char *name; int fn; bool found=FALSE; char buf[MAX_STRING_LENGTH]; argument=one_argument(argument, arg); #ifdef CIRCLE skip_spaces(&argument); #endif if (!arg[0]) { send_to_char("Syntax: rchanset <char> - check flag settings\n\r" " rchanset <char> +<channel> - set allow flag\n\r" " rchanset <char> -<channel> - set deny flag\n\r" " rchanset <char> =<channel> - reset allow/deny\n\r", ch); return; } if (!(victim=get_char_world(ch, arg))) { send_to_char("They're not here.\n\r", ch); return; } if (IS_NPC(victim)) { send_to_char("Can't set rchannel status on NPCs.\n\r", ch); return; } if (get_trust(victim) >= get_trust(ch)) { send_to_char("You failed.\n\r", ch); return; } if (!argument[0]) { sprintf(buf, "%s's IMC channel flags:\n\r" "------------------------------\n\r", GET_NAME(victim)); for (i=0; i<numchannels; i++) { if (IS_SET(IMC_ALLOW_FLAGS(victim), imc_channels[i].flag)) { sprintf(buf+strlen(buf), "%-10s : allow flag set.\n\r", imc_channels[i].name); found=TRUE; } if (IS_SET(IMC_DENY_FLAGS(victim), imc_channels[i].flag)) { sprintf(buf+strlen(buf), "%-10s : deny flag set.\n\r", imc_channels[i].name); found=TRUE; } } if (IS_SET(IMC_ALLOW_FLAGS(victim), IMC_RTELL)) { sprintf(buf+strlen(buf), "%-10s : allow flag set.\n\r", "RTell"); found=TRUE; } if (IS_SET(IMC_DENY_FLAGS(victim), IMC_RTELL)) { sprintf(buf+strlen(buf), "%-10s : deny flag set.\n\r", "RTell"); found=TRUE; } if (IS_SET(IMC_ALLOW_FLAGS(victim), IMC_RBEEP)) { sprintf(buf+strlen(buf), "%-10s : allow flag set.\n\r", "RBeep"); found=TRUE; } if (IS_SET(IMC_DENY_FLAGS(victim), IMC_RBEEP)) { sprintf(buf+strlen(buf), "%-10s : deny flag set.\n\r", "RBeep"); found=TRUE; } if (!found) sprintf(buf, "%s has no IMC flags set.\n\r", GET_NAME(victim)); send_to_char(buf, ch); return; } if (argument[0]=='-') fn=0; else if (argument[0]=='+') fn=1; else if (argument[0]=='=') fn=2; else { send_to_char("Channel name must be preceeded by +, -, or =.\n\r", ch); return; } argument++; if (!str_cmp(argument, "rtell")) { flag=IMC_RTELL; name="RTell"; } else if (!str_cmp(argument, "rbeep")) { flag=IMC_RBEEP; name="RBeep"; } else { for (i=0; i<numchannels; i++) #ifdef CIRCLE if (!str_cmp((char *)imc_channels[i].name, argument)) #else if (!str_cmp(imc_channels[i].name, argument)) #endif break; if (i==numchannels) { send_to_char("No such channel.\n\r", ch); return; } flag=imc_channels[i].flag; name=imc_channels[i].name; } switch(fn) { case 0: /* set deny flag */ if (IS_SET(IMC_DENY_FLAGS(victim), flag)) { send_to_char("Deny flag already set.\n\r", ch); return; } SET_BIT(IMC_DENY_FLAGS(victim), flag); REMOVE_BIT(IMC_ALLOW_FLAGS(victim), flag); sprintf(buf, "The gods have revoked your %s priviliges.\n\r", name); send_to_char(buf, victim); send_to_char("Ok.\n\r", ch); #ifdef ROM sprintf(buf, "$N revokes %s's access to %s.", GET_NAME(victim), name); wiznet(buf, ch, NULL, WIZ_PENALTIES, WIZ_SECURE, 0); #endif return; case 1: /* set allow flag */ if (IS_SET(IMC_ALLOW_FLAGS(victim), flag)) { send_to_char("Allow flag already set.\n\r", ch); return; } SET_BIT(IMC_ALLOW_FLAGS(victim), flag); REMOVE_BIT(IMC_DENY_FLAGS(victim), flag); sprintf(buf, "The gods have allowed you access to %s.\n\r", name); send_to_char(buf, victim); send_to_char("Ok.\n\r", ch); #ifdef ROM sprintf(buf, "$N allows %s access to %s.", GET_NAME(victim), name); wiznet(buf, ch, NULL, WIZ_PENALTIES, WIZ_SECURE, 0); #endif return; case 2: /* clears flags */ if (IS_SET(IMC_ALLOW_FLAGS(victim), flag)) { REMOVE_BIT(IMC_ALLOW_FLAGS(victim), flag); sprintf(buf, "The gods have removed your special access to %s.\n\r", name); send_to_char(buf, victim); #ifdef ROM sprintf(buf, "$N removes %s's access to %s.", GET_NAME(victim), name); wiznet(buf, ch, NULL, WIZ_PENALTIES, WIZ_SECURE, 0); #endif found=TRUE; } if (IS_SET(IMC_DENY_FLAGS(victim), flag)) { REMOVE_BIT(IMC_DENY_FLAGS(victim), flag); sprintf(buf, "The gods have restored your %s priviliges.\n\r", name); send_to_char(buf, victim); #ifdef ROM sprintf(buf, "$N restores %s to %s.", name, GET_NAME(victim)); wiznet(buf, ch, NULL, WIZ_PENALTIES, WIZ_SECURE, 0); #endif found=TRUE; } if (!found) send_to_char("They have no flags to clear.\n\r", ch); else send_to_char("Ok.\n\r", ch); return; } } /* renamed from do_rchannel */ static void do_imcchannel(const imc_char_data *from, int number, const char *argument, int emote) { DESCRIPTOR_DATA *d; CHAR_DATA *victim; const char *str; const char *arg; char buf[IMC_DATA_LENGTH]; int chan; for (chan=0; chan<numchannels; chan++) if (imc_channels[chan].number==number) break; if (chan==numchannels) return; str=emote ? imc_channels[chan].emotestr : imc_channels[chan].chatstr; arg=color_itom(argument); for (d=descriptor_list; d; d=d->next) { if (d->connected==CON_PLAYING && (victim=d->original ? d->original : d->character)!=NULL && !IS_QUIET(victim) && !IS_SILENT(victim) && !IS_SET(IMC_DEAF_FLAGS(victim), imc_channels[chan].flag) && CAN(victim, imc_channels[chan].flag, imc_channels[chan].minlevel)) { #if NO_VSNPRINTF sprintf(buf, str, getname(victim, from), arg); #else snprintf(buf, IMC_DATA_LENGTH, str, getname(victim, from), arg); #endif send_to_char(buf, victim); } } } /* Traceroute and ping. * * Be lazy - only remember the last traceroute */ static char lastping[IMC_MNAME_LENGTH]; static char pinger[100]; DEFINE_DO_FUN(do_rping) { char arg[MAX_STRING_LENGTH]; struct timeval tv; CHECKIMC(ch); #ifdef CIRCLE skip_spaces(&argument); #endif one_argument(argument, arg); if (!arg[0]) { send_to_char("Ping which mud?\n\r", ch); return; } CHECKMUD(ch, arg); gettimeofday(&tv, NULL); strcpy(lastping, arg); strcpy(pinger, ch->name); imc_send_ping(arg, tv.tv_sec, tv.tv_usec); } void imc_traceroute(int ping, const char *pathto, const char *pathfrom) { if (!str_cmp(imc_firstinpath(pathfrom), lastping)) { DESCRIPTOR_DATA *d; CHAR_DATA *ch=NULL; char buf[MAX_STRING_LENGTH]; for (d=descriptor_list; d; d=d->next) { if (d->connected == CON_PLAYING && (ch =d->original ? d->original : d->character)!=NULL && !str_cmp(ch->name, pinger)) break; } if (!ch) return; sprintf(buf, "%s: %dms round-trip-time.\n\r" "Return path: %s\n\r" "Send path: %s\n\r", imc_firstinpath(pathfrom), ping, pathfrom, pathto ? pathto : "unknown"); send_to_char(buf, ch); } } void imc_recv_chat(const imc_char_data *from, int channel, const char *argument) { do_imcchannel(from, channel, argument, 0); } void imc_recv_emote(const imc_char_data *from, int channel, const char *argument) { do_imcchannel(from, channel, argument, 1); } /* new imc_whoreply_* support, see imc-interp.c */ /* expanded for minimal mud-specific code. I really don't want to replicate * stock in-game who displays here, since it's one of the most commonly * changed pieces of code. shrug. */ static void process_rwho(const imc_char_data *from, const char *argument) { CHAR_DATA *victim; int count=0; char output[MAX_STRING_LENGTH]; DESCRIPTOR_DATA *d; imc_whoreply_start(from->name); #ifdef ACK imc_whoreply_add(color_mtoi("@@RWho's Playing " mudnamecolor ":\n\r")); #endif for (d = descriptor_list; d; d = d->next) { victim = ( d->original ) ? d->original : d->character; if (d->connected != CON_PLAYING || !visible(from, getdata(victim)) || IS_NPC(victim)) continue; count++; #ifdef ACK sprintf(output, "@@W[@@p%s@@W] @@G%s@@N%s@@N\n\r", ((IS_IMMORTAL(victim) || (victim->adept_level>0)) ? victim->pcdata->who_name : is_remort(victim) ? " @@mREMORT@@N " : " @@cMORTAL@@N "), GET_NAME(victim), GET_TITLE(victim)); #elif defined(CIRCLE) sprintf(output, "%s %s\r\n", GET_NAME(victim), GET_TITLE(victim)); #else sprintf(output, "%s%s\n\r", GET_NAME(victim), GET_TITLE(victim)); #endif imc_whoreply_add(color_mtoi(output)); } sprintf(output, "\n\rRWHO for %s [%d players found]\n\r", imc_name, count); imc_whoreply_add(output); imc_whoreply_end(); } /* edit this if you want to support rfinger */ static void process_rfinger(const imc_char_data *from, const char *argument) { imc_send_whoreply(from->name, "Sorry, no information is available of that type.\n\r", -1); } void imc_recv_who(const imc_char_data *from, const char *type) { char arg[MAX_STRING_LENGTH]; char output[MAX_STRING_LENGTH]; type=imc_getarg(type, arg, MAX_STRING_LENGTH); if (!str_cmp(arg, "who")) { process_rwho(from, type); return; } else if (!str_cmp(arg, "finger")) { process_rfinger(from, type); return; } else if (!str_cmp(arg, "info")) strcpy(output, IMC_MUD_INFO); else if (!str_cmp(arg, "list")) strcpy(output, imc_list(3)); else if (!str_cmp(arg, "config")) strcpy(output, imc_list(4)); else if (!str_cmp(arg, "direct")) strcpy(output, imc_list(0)); else if (!str_cmp(arg, "options") || !str_cmp(arg, "services") || !str_cmp(arg, "help")) strcpy(output, "Available rquery types:\n\r" "help - this list\n\r" "who - who listing\n\r" "info - mud information\n\r" "list - active IMC connections\n\r" "direct - direct IMC connections\n\r" "config - local IMC configuration\n\r" /* uncomment if you support rfinger */ /* "finger xxx - finger player xxx\n\r" */ ); else strcpy(output, "Sorry, no information is available of that type.\n\r"); imc_send_whoreply(from->name, color_mtoi(output), -1); } void imc_recv_whoreply(const char *to, const char *text, int sequence) { DESCRIPTOR_DATA *d; CHAR_DATA *victim; for (d=descriptor_list; d; d=d->next) { if (d->connected==CON_PLAYING && (victim=d->original ? d->original : d->character)!=NULL && is_name((char *)to, GET_NAME(victim))) { page_to_char(color_itom(text), victim); return; } } } void imc_recv_whois(const imc_char_data *from, const char *to) { DESCRIPTOR_DATA *d; CHAR_DATA *victim; char buf[MAX_STRING_LENGTH]; for (d=descriptor_list; d; d = d->next) { if (d->connected==CON_PLAYING && (victim = d->original ? d->original : d->character)!=NULL && !IS_NPC(victim) && visible(from, getdata(victim)) && #ifdef CIRCLE (!str_cmp((char *)to, GET_NAME(victim)) || #else (!str_cmp(to, GET_NAME(victim)) || #endif (strlen(to)>3 && !str_prefix(to, GET_NAME(victim))))) { sprintf(buf, "rwhois %s : %s@%s is online.\n\r", to, GET_NAME(victim), imc_name); imc_send_whoisreply(from->name, buf); } } } void imc_recv_whoisreply(const char *to, const char *text) { DESCRIPTOR_DATA *d; CHAR_DATA *victim; for (d=descriptor_list; d; d=d->next) { if (d->connected==CON_PLAYING && (victim=d->original ? d->original : d->character)!=NULL && !str_cmp((char *)to, GET_NAME(victim))) { #ifdef CIRCLE send_to_char((char *)color_itom(text), victim); #else send_to_char(color_itom(text), victim); #endif return; } } } void imc_recv_tell(const imc_char_data *from, const char *to, const char *argument, int isreply) { DESCRIPTOR_DATA *d; CHAR_DATA *victim, *vch; char buf[IMC_DATA_LENGTH]; if (!strcmp(to, "*")) /* ignore messages to system */ return; victim=NULL; for (d=descriptor_list; d; d=d->next) { if (d->connected==CON_PLAYING && (vch=d->original ? d->original : d->character)!=NULL && !IS_NPC(vch) && /* sanity check */ !IS_RINVIS(vch) && (isreply || visible(from, getdata(vch)))) { if (!str_cmp((char *)to, GET_NAME(vch))) { victim=vch; break; } if (is_name((char *)to, GET_NAME(vch))) victim=vch; } } if (victim) { if (IS_SET(IMC_DEAF_FLAGS(victim), IMC_RTELL) || IS_QUIET(victim) || #ifdef ROM IS_SET(victim->comm, COMM_DEAF) || #endif #ifdef ACK IS_SET(victim->pcdata->pflags, PFLAG_AFK) || #endif IS_SILENT(victim) || IS_SET(IMC_DENY_FLAGS(victim), IMC_RTELL)) { #ifdef CIRCLE if (str_cmp((char *)imc_nameof(from->name), "*")) #else if (str_cmp(imc_nameof(from->name), "*")) #endif { sprintf(buf, "%s is not receiving tells.", to); imc_send_tell(NULL, from->name, buf, 1); } return; } #ifdef ROM if (IS_SET(victim->comm, COMM_AFK) && str_cmp(imc_nameof(from->name), "*")) { sprintf(buf, "%s is AFK, but your tell will go through when they " "return.", to); imc_send_tell(NULL, from->name, buf, 1); } else if (!victim->desc && str_cmp(imc_nameof(from->name), "*")) { sprintf(buf, "%s is switched, but your tell will go through when " "they return.", to); imc_send_tell(NULL, from->name, buf, 1); } #endif #ifdef CIRCLE if (str_cmp((char *)imc_nameof(from->name), "*")) /* not a system message */ #else if (str_cmp(imc_nameof(from->name), "*")) /* not a system message */ #endif { if (IMC_RREPLY(victim)) imc_strfree(IMC_RREPLY(victim)); if (IMC_RREPLY_NAME(victim)) imc_strfree(IMC_RREPLY_NAME(victim)); IMC_RREPLY(victim)=imc_strdup(from->name); IMC_RREPLY_NAME(victim)=imc_strdup(getname(victim, from)); } #if NO_VSNPRINTF sprintf(buf, RTELL_FORMAT_2, getname(victim, from), color_itom(argument)); #else snprintf(buf, IMC_DATA_LENGTH, RTELL_FORMAT_2, getname(victim, from), color_itom(argument)); #endif #ifdef ROM if (IS_SET(victim->comm, COMM_AFK) || !victim->desc) add_buf(victim->pcdata->buffer, buf); else page_to_char(buf, victim); #else page_to_char(buf, victim); #endif } else { sprintf(buf, "%s is not here.", to); imc_send_tell(NULL, from->name, buf, 1); } } void imc_recv_beep(const imc_char_data *from, const char *to) { DESCRIPTOR_DATA *d; CHAR_DATA *victim, *vch; char buf[IMC_DATA_LENGTH]; if (!strcmp(to, "*")) /* ignore messages to system */ return; victim=NULL; for (d=descriptor_list; d; d=d->next) { if (d->connected==CON_PLAYING && (vch=d->original ? d->original : d->character)!=NULL && visible(from, getdata(vch))) { if (!str_cmp((char *)to, GET_NAME(vch))) { victim=vch; break; } if (is_name((char *)to, GET_NAME(vch))) victim=vch; } } if (victim) { if (IS_SET(IMC_DEAF_FLAGS(victim), IMC_RBEEP) || IS_SILENT(victim) || !CAN(victim, IMC_RTELL, IMC_LEVEL_RTELL)) { sprintf(buf, "%s is not receiving beeps.", to); imc_send_tell(NULL, from->name, buf, 1); return; } /* always display the true name here */ sprintf(buf, RBEEP_FORMAT_2, from->name); send_to_char(buf, victim); } else { sprintf(buf, "%s is not here", to); imc_send_tell(NULL, from->name, buf, 1); } } /** IMC MAIL **/ /* shell for sending IMC mail */ void imc_post_mail(CHAR_DATA *from, const char *sender, const char *to_list, const char *subject, const char *date, const char *text) { char arg[MAX_STRING_LENGTH]; const char *temp; CHECKIMC(from); if (!strchr(to_list, '@')) return; for (temp=one_argument((char *)to_list, arg); arg[0]; /* blech */ temp=one_argument((char *)temp, arg)) if (strchr(arg, '@')) CHECKMUD(from, imc_mudof(arg)); imc_send_mail(sender, to_list, subject, date, color_mtoi(text)); } /* Since there are half-a-dozen different ways that people do this, I'm * sticking to the stock code, plus Erwin's board system. */ #ifdef SMAUG /* * Find the IMC mail board. It SHOULD exist.. :) */ BOARD_DATA *imc_find_board(void) { BOARD_DATA *board; for (board = first_board; board; board = board->next) if (board->board_obj == sysdata.imc_mail_vnum) return board; return NULL; } char *imc_mail_arrived (const char *from, const char *to, const char *date, const char *subject, const char *text) { void write_board(BOARD_DATA *board); BOARD_DATA *board; NOTE_DATA *pnote; char buf[MAX_STRING_LENGTH]; /* don't let people write to 'all' over IMC */ /* yeesh, why doesn't anyone maintain 'const'-ness any more? */ if (is_name("all", (char *)to)) return "Notes to 'all' are not accepted."; if ( !(board = imc_find_board()) ) return "Could not find the IMC board."; if ( board->num_posts >= board->max_posts ) return "There is no room on the IMC board to post your note."; CREATE( pnote, NOTE_DATA, 1 ); /* Smash all the tildes, just in case * This is a complete mess, but smaug's string hasher would do bad things * if we smash_tilde'd a STRALLOC'd string.. */ #define SET_STR(new, old) \ do { \ strcpy(buf, old); \ smash_tilde(buf); \ pnote->new = STRALLOC(buf); \ } while(0) SET_STR(sender, from); SET_STR(to_list, to); SET_STR(date, date); SET_STR(subject, color_itom(subject)); SET_STR(text, text); #undef SET_STR pnote->voting = 0; pnote->yesvotes = str_dup(""); pnote->novotes = str_dup(""); pnote->abstentions = str_dup(""); LINK(pnote, board->first_note, board->last_note, next, prev); board->num_posts++; write_board( board ); return NULL; /* Errors? What errors? <G> */ } #endif /* SMAUG */ #if defined(ACK) /* Added support for ackmud boards. * You must configure IMC_BOARD_PUBLIC and IMC_BOARD_IMMORTAL * in imc-mercbase.h to suit your mud! */ #ifndef IMC_BOARD_PUBLIC #error You must #define a value for IMC_BOARD_VNUM in imc-mercbase.h! #endif #ifndef IMC_BOARD_IMMORTAL #error You must #define a value for IMC_BOARD_VNUM in imc-mercbase.h! #endif char *imc_mail_arrived(const char *from, const char *to, const char *date, const char *subject, const char *text) { BOARD_DATA *board; MESSAGE_DATA *msg; char buf[MAX_STRING_LENGTH]; const char *temp=to; int vnum; int toimm=0; char toname[MAX_STRING_LENGTH]; toname[0]=0; while ((temp=imc_getarg(temp, buf, MAX_STRING_LENGTH)), buf[0]) { if (!strchr(buf, '@')) { if (toname[0]) return "Sorry, multiple to: names over IMC are not supported here."; strcpy(toname, buf); } } if (str_cmp("all", toname)) return "Notes to 'all' are not accepted."; if (str_cmp("immortal", toname) || str_cmp("imm", toname) || str_cmp("imms", toname) || str_cmp("immortals", toname)) { vnum=IMC_BOARD_IMMORTAL; toimm=1; } else vnum=IMC_BOARD_PUBLIC; /* First find the board, and if not there, create one. */ for (board=first_board; board != NULL; board=board->next) { if (board->vnum==vnum) break; } if (board==NULL) { /* uh oh.. */ OBJ_INDEX_DATA *pObj; int i; for (i=0; i<MAX_KEY_HASH; i++) for (pObj=obj_index_hash[i]; pObj; pObj=pObj->next) if (pObj->item_type==ITEM_BOARD && pObj->value[3]==vnum) break; if (!pObj) return "Couldn't find a board to post the note on."; board=load_board(pObj); } GET_FREE(msg, message_free); msg->datetime=time(NULL); /* erk.. this is messy. * assume that notes to 'immortal' are public * assume that anything else is private */ if (toimm) sprintf(buf, "%s @@a%s@@N\n\r", subject, date); else sprintf(buf, "to: %s @@a%s@@N\n\r", toname, date); msg->title=str_dup(buf); msg->author=str_dup(from); msg->board=board; msg->message=str_dup(color_itom(text)); LINK(msg, board->first_message, board->last_message, next, prev); return NULL; } #endif /* ACK */ /* #define ERWIN -- to use the code for Erwin's boards */ #if defined(MERC) || defined(ROM) || defined(ENVY) #if !defined(ERWIN) /* post a note; currently all rnotes go to the default note spool */ char *imc_mail_arrived(const char *from, const char *to, const char *date, const char *subject, const char *text) { NOTE_DATA *pnote; #if defined(MERC) || defined(ENVY) NOTE_DATA *prev_note; FILE *fp; #endif /* don't let people write to 'all' over IMC */ /* yeesh, why doesn't anyone maintain 'const'-ness any more? */ if (is_name("all", (char *)to)) return "Notes to 'all' are not accepted."; #ifdef ROM pnote=new_note(); pnote->type=NOTE_NOTE; #else pnote=alloc_perm(sizeof(*pnote)); #endif pnote->sender=str_dup(from); pnote->to_list=str_dup(to); pnote->date=str_dup(date); pnote->subject=str_dup(subject); pnote->text=str_dup(color_itom(text)); pnote->next=NULL; /* a bit of paranoia re. tildes here.. */ smash_tilde(pnote->sender); smash_tilde(pnote->to_list); smash_tilde(pnote->date); smash_tilde(pnote->subject); smash_tilde(pnote->text); #ifdef ROM append_note(pnote); #else if (!note_list) { note_list = pnote; } else { for (prev_note = note_list; prev_note->next; prev_note = prev_note->next) ; prev_note->next = pnote; } fclose (fpReserve); if (!(fp = fopen (NOTE_FILE, "a"))) { perror (NOTE_FILE); fpReserve = fopen (NULL_FILE, "r"); return "Couldn't open the note file"; } else { fprintf (fp, "Sender %s~\n", pnote->sender); fprintf (fp, "Date %s~\n", pnote->date); fprintf (fp, "To %s~\n", pnote->to_list); fprintf (fp, "Subject %s~\n", pnote->subject); fprintf (fp, "Text\n%s~\n\n", pnote->text); fclose (fp); } fpReserve = fopen (NULL_FILE, "r"); #endif return NULL; /* Errors? What errors? <G> */ } #else /* * If you are using my code (ftp://pip.dknet.dk/pub/pip1773/board-2.tgz) * there is another imc_mail_arrived() below - Erwin * * Note that this assumes that your make_note() does a smash_tilde(), the * latest version of the board snippet does, but your may not. Oh well. */ char *imc_mail_arrived (const char *from, const char *to, const char *date, const char *subject, const char *text) { /* don't let people write to 'all' over IMC */ /* yeesh, why doesn't anyone maintain 'const'-ness any more? */ if (is_name("all", (char *)to)) return "Notes to 'all' are not accepted."; make_note ("Personal", from, to, subject, 14, color_itom(text)); return NULL; } #endif /* Erwin's board code */ #endif /* merc/rom/envy */ #ifdef CIRCLE char *imc_mail_arrived(const char *from, const char *to, const char *date, const char *subject, const char *text) { char buf[MAX_STRING_LENGTH]; /* don't let people write to 'all' over IMC */ /* yeesh, why doesn't anyone maintain 'const'-ness any more? */ if (isname("all", (char *) to)) return "Notes to 'all' are not accepted."; sprintf(buf, "-= IMC Header =-\r\n" " From: %s\r\n" " To: %s\r\n" " Date: %s\r\n" "Subject: %s\r\n" "\r\n%s", from, to, date, subject, text); store_mail(get_id_by_name((char *)to), 0, buf); return NULL; /* Errors? What errors? <G> */ } #endif void imc_log(const char *string) { char buf[MAX_STRING_LENGTH]; sprintf(buf, "imc: %s", string); log_string(buf); #ifdef ACK monitor_chan(buf, MONITOR_CONNECT); #endif #ifdef ROM /* ick, wiznet is a bit broken wrt. passing non-objects to act.. * it should really take a void * as its 3rd argument */ wiznet("imc: $t", NULL, (OBJ_DATA *)string, WIZ_IMC, 0, 0); #endif } void imc_debug(const imc_connect *c, int out, const char *string) { #ifdef ROM char buf[MAX_STRING_LENGTH]; char *dir; dir=out ? "<" : ">"; /* chop to 130 chars (should fit on 2 lines) */ sprintf(buf, "%s %s %-.130s", imc_getconnectname(c), dir, string); wiznet("$t", NULL, (OBJ_DATA *)buf, WIZ_IMCDEBUG, 0, 0); #endif }