/* Instructions, Randomly written in hopes that others might be able to add this code more easily than I did. msw Make sure the DIMD.H is included in your protos.h ' #include "dimd.h" You might need to add a few new variables to the char_data struct or you might do as MOZART and Shadowdale did and move your PC related info to ch->pc struct. Here you can add all the needed info. This might mean you will have to re-build your playerfile... but that is up to your coding. I have included all the code in here that should be all ya need to get it working. You will need to place the function dimd_loop() in your comm.c code. ' ' dimd_loop(); ' for (point = descriptor_list; point; point = point->next) { ' FD_SET(point->descriptor, &input_set); ' FD_SET(point->descriptor, &exc_set); ' FD_SET(point->descriptor, &output_set); 'etc.......... See code for funtion descriptions, remember I am telling you this from what I have gathered so it might not be totally correct. Ask the MOZART guys if you need to know more. */ #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #include <netdb.h> #include <netinet/in.h> #include <sys/time.h> #include <signal.h> #include <stdio.h> #include <errno.h> #include "protos.h" #define USE_COLOR FALSE /* do not use DaleMUD color codes. */ void isname_init(const char *str); bool isname_iter(const char *namelist); void printhost(struct in_addr *addr, char *buf); /* this is included */ /* these are some functions that MOZART uses but Shadowdale does not */ /* we just make it call Shadowdale versions, see functions later.. */ void cact(char *s,byte boo, struct char_data *ch, struct obj_data *obj, struct char_data *ch2, int i, int ii); void msg(char *s, struct char_data *ch) ; void cmsg(char *s, struct char_data *ch, int i); /* */ /* these should be in comm.c or there abouts... */ extern struct descriptor_data *descriptor_list, *next_to_process; extern int maxdesc, avail_descs; /* */ /* DIMD internally used VARS */ int dimd_s; bool dimd_on = TRUE; bool dimd_gossip = TRUE; bool dimd_muse = TRUE; bool dimd_think = TRUE; int dimd_state = DIMD_OPENING; int dimd_port; int dimd_local_mud = UNDEFINED; /* */ /* varaibles used internally */ static char is_buf[MAX_STRING_LENGTH], is_names[MAX_STRING_LENGTH], *is_argv[100], *is_xargv[100]; static int is_argc,is_xargc,is_exact; /* */ /* This is where you make the list of muds that you want to 'talk'/DIMD to */ struct mud_data muds[] = /* /-No Idea */ { /* /Mud| /---/--/---No Idea? */ /* /- Mud Name /-- Aliases /-Address to site |Port| ? ? ? */ {"Shadowdale II","dale2 sd2 outpost","outpost.hsc.unt.edu",4000,2,100,1,DD_AUTOTRY}, {"Shadowdale","dale sd","dale.hsc.unt.edu",7777,2,100,1,DD_AUTOTRY}, {"ShadowCode","code dale sd","dale.hsc.unt.edu",4000,2,100,1,DD_AUTOTRY }, { NULL, NULL, NULL, UNDEFINED } /* this must be here */ }; /* this is how dimd determines if you can see the other or the other can */ /* see you (tell and such) */ /* that being said all I know is that if an immortal has it set on one side */ /* and another tries to tell that one (both equaal levels) it will say */ /* Character not found. */ /* needless to ssay the code needs work to function normally */ bool dimd_can_see(int slev, struct char_data *o) { if (!slev && IS_AFFECTED(o, AFF_INVISIBLE)) return FALSE; if (o->invis_level && (o->invis_level - (LOW_IMMORTAL-1)) > slev) return FALSE; return TRUE; } /* internal code sends data to a mud for various tasks */ void dimd_broadcast(char *buf) { int i; for(i=0; muds[i].address; i++) if (IS_SET(muds[i].flags, DD_VERIFIED)) write_to_descriptor(muds[i].desc, buf); } /* this parses dimd 'packet' commands */ char *one_lc_dimd_argument(char *argument, char *first_arg) { char *scan; do { while(isspace(*argument)) argument++; scan = first_arg; while(*argument && *argument != '^') *scan++ = LOWER(*argument), argument++; *scan = 0; } while (fill_word(first_arg)); if (*argument=='^') argument++; return(argument); } /* this is used in parsing dimd 'packet' commands */ char *one_dimd_argument(char *argument, char *first_arg) { char *scan; while(isspace(*argument)) argument++; scan = first_arg; while(*argument && *argument != '^') *scan++ = *argument++; *scan = 0; if (*argument=='^') argument++; return(argument); } /* does the character have sufficent DIMD Credits to send the DIMD */ /* command. This is how MOZART limits usage of DIMD, might wanna come */ /* up with a better plan :) */ /* Shadowdale gives each user 1 credit per tick. spell_parser.c, affect_update: ' GET_HIT(i) = MIN(hit_gain(i) + GET_HIT(i), hit_limit(i)); ' GET_MANA(i) = MIN(GET_MANA(i) + mana_gain(i), mana_limit(i)); ' GET_MOVE(i) = MIN(GET_MOVE(i) + move_gain(i), move_limit(i)); ' 'if (!IS_LINKDEAD(i) && (i->pc)) ' GET_DIMD(i) +=1; ' 'etc.... */ bool dimd_credit(struct char_data *ch, int credits) { if (IS_SET(ch->specials.act, PLR_NODIMD)) { msg("Your DIMD privileges were taken away from you.", ch); return; }; if (credits > GET_DIMD(ch)) { msg("You do not have enough dimd credits to do that.", ch); return(FALSE); }; GET_DIMD(ch) -= credits; return(TRUE); } /* does the *mudname match any nick name in our list? */ int matchmud(char *mudname) { int i; isname_init(mudname); for(i=0; muds[i].nicknames; i++) if (isname_iter(muds[i].nicknames) || isname_iter(muds[i].address)) return i; return UNDEFINED; } /* HERE */ int getlocalmud(void) { char buf[100]; gethostname(buf, 100); DIMDLOG(buf); return matchmud(buf); } int getmud(struct char_data *ch, char *mudname, bool checkforup) { int i; if (!*mudname) { msg("You must pick a mud!", ch); return UNDEFINED; }; if ((i=matchmud(mudname))==UNDEFINED) { msg("I am not aware of that mud.", ch); return UNDEFINED; }; if (i==dimd_local_mud) { msg("You are ON that mud silly!", ch); return UNDEFINED; }; if (checkforup && !IS_SET(muds[i].flags, DD_VERIFIED)) { msg("We are not connected to that mud at the moment.", ch); return UNDEFINED; }; return i; } void do_dgossip(struct char_data *ch, char *argument, int cmd) { char buf[MAX_INPUT_LENGTH], mudname[MAX_INPUT_LENGTH]; struct descriptor_data *d; int i; if (IS_SET(ch->specials.act, PLR_NOSHOUT)) { msg("Ummm, no one can hear you through that gag!", ch); return; }; if (IS_SET(ch->specials.act, PLR_NOGOSSIP)) { msg("You are not tuned into the gossip channel!", ch); return; }; one_argument(argument, mudname); if ((i=matchmud(mudname))!=UNDEFINED) { argument = one_argument(argument, mudname); if ((i=getmud(ch, mudname, TRUE))==UNDEFINED) return; }; while(isspace(*argument)) argument++; if (!*argument) { msg("Surely you have something to gossip!", ch); return; }; if (!dimd_credit(ch, 2+3*(i==UNDEFINED))) return; if (i!=UNDEFINED) { if (IS_SET(muds[i].flags, DD_NOGOSSIP)) { msg("They are no longer listening to remote gossips.", ch); return; }; sprintf(buf, "^%s^%s^%d^g^%s\n\r", PER(ch), GET_KEYNAME(ch), GetMaxLevel(ch), argument); write_to_descriptor(muds[i].desc, buf); } else { sprintf(buf, "^%s^%s^%d^gg^%s\n\r", PER(ch), GET_KEYNAME(ch), GetMaxLevel(ch), argument); for(i=0; muds[i].address; i++) if (IS_SET(muds[i].flags, DD_VERIFIED) && !IS_SET(muds[i].flags, DD_NOGOSSIP)) write_to_descriptor(muds[i].desc, buf); #if USE_COLOR sprintf(buf, "$kW$n $kmdimension gossips, '%s'", argument); #else sprintf(buf, "$n dimension gossips, '%s'", argument); #endif for(d = descriptor_list; d; d = d->next) if (!d->connected && d->character != ch && !IS_SET(d->character->pc->comm, COMM_NOGOSSIP) && !check_soundproof(d->character)) cact(buf, FALSE, ch, 0, d->character, TO_VICT, CLR_GOSSIP); }; } void do_dlink(struct char_data *ch, char *argument, int cmd) { int mud; if (!dimd_on) { msg("The DIMD server is currently down.", ch); return; }; if (IS_SET(ch->pc->plr, PLR_NODIMD)) { msg("Your DIMD privileges were taken away!", ch); return; }; while(isspace(*argument)) argument++; if ((mud=getmud(ch, argument, FALSE))==UNDEFINED) return; if (IS_SET(muds[mud].flags, DD_CONNECTED)) { msg("We are already connected to that mud!", ch); return; }; if (IS_SET(muds[mud].flags, DD_REFUSE)) { msg("We are refusing connections to that mud at the moment.", ch); return; }; msg("Attempting to connect.", ch); if (call_a_mud(mud)) msg("Connection established.", ch); else msg("Connection failed.", ch); } void do_dunlink(struct char_data *ch, char *argument, int cmd) { char buf[MAX_INPUT_LENGTH]; int mud; if (IS_SET(ch->pc->plr, PLR_NODIMD)) { msg("Your DIMD privileges were taken away!", ch); return; }; while(isspace(*argument)) argument++; if ((mud=getmud(ch, argument, FALSE))==UNDEFINED) return; if (!IS_SET(muds[mud].flags, DD_CONNECTED)) { msg("We aren't even connected to that mud!", ch); return; }; sprintf(buf, "Disconnecting %s[%s].", muds[mud].formalname, muds[mud].host); hangup_on_a_mud(mud); } void do_drestrict(struct char_data *ch, char *argument, int cmd) { char buf[MAX_INPUT_LENGTH]; int i, mud; if (IS_SET(ch->pc->plr, PLR_NODIMD)) { msg("Your DIMD privileges were taken away!", ch); return; }; argument = one_argument(argument, buf); if ((mud=getmud(ch, buf, FALSE))==UNDEFINED) return; while(isspace(*argument)) argument++; if (is_abbrev(argument, "refuse")) { SET_BIT(muds[mud].flags, DD_REFUSE); sprintf(buf, "Now refusing new connections with %s.", muds[mud].formalname); msg(buf, ch); DIMDLOG(buf); return; }; if (is_abbrev(argument, "accept")) { REMOVE_BIT(muds[mud].flags, DD_REFUSE); sprintf(buf, "Now accepting new connections with %s.", muds[mud].formalname); msg(buf, ch); DIMDLOG(buf); return; }; i = atoi(argument); muds[mud].min_level = i; sprintf(buf, "Setting %s's DIMD incoming level to %d.", muds[mud].formalname, i); msg(buf, ch); sprintf(buf, "%s set %s's DIMD incoming level to %d.", PER(ch), muds[mud].formalname, i); DIMDLOG(buf); } void do_dlist(struct char_data *ch, char *argument, int cmd) { char buf[MAX_STRING_LENGTH]; int i; #if USE_COLOR strcpy(buf, " $kWCond $kYMud Name $kMNicknames $kGRestricted\n\r" "$kB------ ------------------------- ---------------------- ----------\n\r"); for(i=0; muds[i].formalname; i++) sprintf(buf+strlen(buf), "$kW%s $kY%-25s $kM%-22s $kG%d\n\r", i==dimd_local_mud ? " HERE " : (IS_SET(muds[i].flags, DD_VERIFIED) ? " UP " : (IS_SET(muds[i].flags, DD_REFUSE) ? "REFUSE" : " DOWN ")), muds[i].formalname, muds[i].nicknames, muds[i].min_level); #else strcpy(buf, " Cond Mud Name Nicknames Restricted\n\r" " ------ ------------------------- ---------------------- ----------\n\r"); for(i=0; muds[i].formalname; i++) sprintf(buf+strlen(buf), "%s %-25s %-22s %d\n\r", i==dimd_local_mud ? " HERE " : (IS_SET(muds[i].flags, DD_VERIFIED) ? " UP " : (IS_SET(muds[i].flags, DD_REFUSE) ? "REFUSE" : " DOWN ")), muds[i].formalname, muds[i].nicknames, muds[i].min_level); #endif msg(buf, ch); } void do_dmanage(struct char_data *ch, char *argument, int cmd) { while(isspace(*argument)) argument++; if (!str_cmp(argument, "on")) { if (dimd_on) { msg("The server was already activated.", ch); return; }; dimd_on = TRUE; msg("Bringing up the DIMD server.", ch); return; }; if (!str_cmp(argument, "off")) { if (!dimd_on) { msg("The server was already deactivated.", ch); return; }; dimd_on = FALSE; msg("Bringing down the DIMD server.", ch); return; }; if (!str_cmp(argument, "gossip")) { if (dimd_gossip) { msg("Dimensional gossips will now be rejected.", ch); dimd_broadcast("^DIMD^DIMD^110^rg\n\r"); } else { msg("Dimensional gossips will now be accepted.", ch); dimd_broadcast("^DIMD^DIMD^110^ag\n\r"); } dimd_gossip = !dimd_gossip; return; }; if (!str_cmp(argument, "muse")) { if (dimd_muse) { msg("Dimensional muses will now be rejected.", ch); dimd_broadcast("^DIMD^DIMD^110^rm\n\r"); } else { msg("Dimensional muses will now be accepted.", ch); dimd_broadcast("^DIMD^DIMD^110^am\n\r"); } dimd_muse = !dimd_muse; return; }; if (!str_cmp(argument, "think")) { if (dimd_think) { msg("Dimensional thinking will now be rejected.", ch); dimd_broadcast("^DIMD^DIMD^110^rt\n\r"); } else { msg("Dimensional thinking will now be accepted.", ch); dimd_broadcast("^DIMD^DIMD^110^at\n\r"); } dimd_think = !dimd_think; return; }; msg("Use either on, off, gossip, muse, or think.", ch); } void do_dmuse(struct char_data *ch, char *argument, int cmd) { char buf[MAX_INPUT_LENGTH], mudname[MAX_INPUT_LENGTH]; struct descriptor_data *d; int i; if (IS_SET(ch->specials.act, PLR_NOSHOUT)) { msg("The gods are sick of listen to you! You've been gagged!", ch); return; }; if (HUMAN(ch) && IS_SET(ch->pc->comm, COMM_NOMUSE)) { msg("You are not tuned into the muse channel!", ch); return; }; one_argument(argument, mudname); if ((i=matchmud(mudname))!=UNDEFINED) { argument = one_argument(argument, mudname); if ((i=getmud(ch, mudname, TRUE))==UNDEFINED) return; }; while(isspace(*argument)) argument++; if (!*argument) { msg("Sure you have something to muse!", ch); return; }; if (!dimd_credit(ch, 1+2*(i==UNDEFINED))) return; if (i!=UNDEFINED) { if (IS_SET(muds[i].flags, DD_NOMUSE)) { msg("They are no longer listening to remote muses.", ch); return; }; sprintf(buf, "^%s^%s^%d^mg^%s\n\r", PER(ch), GET_KEYNAME(ch), GetMaxLevel(ch), argument); write_to_descriptor(muds[i].desc, buf); } else { sprintf(buf, "^%s^%s^%d^mg^%s\n\r", PER(ch), GET_KEYNAME(ch), GetMaxLevel(ch), argument); for(i=0; muds[i].address; i++) if (IS_SET(muds[i].flags, DD_VERIFIED) && !IS_SET(muds[i].flags, DD_NOMUSE)) write_to_descriptor(muds[i].desc, buf); #if USE_COLOR sprintf(buf, "$kW$n $kLdimension muses, '%s'", argument); #else sprintf(buf, "$n dimension muses, '%s'", argument); #endif for(d = descriptor_list; d; d = d->next) if (!d->connected && d->character != ch && GetMaxLevel(d->character) >= LOW_IMMORTAL && !IS_SET(d->character->pc->comm, COMM_NOMUSE)) cact(buf, FALSE, ch, 0, d->character, TO_VICT, CLR_MUSE); }; } void do_dtell(struct char_data *ch, char *argument, int cmd) { char name[MAX_INPUT_LENGTH], mudname[MAX_INPUT_LENGTH], buf[MAX_STRING_LENGTH]; int i; /* for (i=0;i<MAX_MOBOBJ;i++) { sprintf(buf,"%s has pos %d",mob_index[i].name, mob_index[i].pos); slog(buf); }*/ argument = one_argument(argument, name); argument = one_argument(argument, mudname); if ((i=getmud(ch, mudname, TRUE))==UNDEFINED) return; while(isspace(*argument)) argument++; if (!*argument) { msg("Surely you have SOMETHING to say ... ?", ch); return; }; if (!dimd_credit(ch, 1)) return; sprintf(buf, "^%s^%s^%d^t^%s^%s\n\r", PER(ch), GET_KEYNAME(ch), GetMaxLevel(ch), name, argument); write_to_descriptor(muds[i].desc, buf); } void do_dthink(struct char_data *ch, char *argument, int cmd) { char buf[MAX_INPUT_LENGTH], mudname[MAX_INPUT_LENGTH]; struct descriptor_data *d; int i; one_argument(argument, mudname); if ((i=matchmud(mudname))!=UNDEFINED) { argument = one_argument(argument, mudname); if ((i=getmud(ch, mudname, TRUE))==UNDEFINED) return; }; while(isspace(*argument)) argument++; if (!*argument) { msg("Sure you have something to think!", ch); return; }; if (!dimd_credit(ch, 1+1*(i==UNDEFINED))) return; if (i!=UNDEFINED) { if (IS_SET(muds[i].flags, DD_NOTHINK)) { msg("They are no longer listening to remote thinks.", ch); return; }; sprintf(buf, "^%s^%s^%d^*^%s\n\r", PER(ch), GET_KEYNAME(ch), GetMaxLevel(ch), argument); write_to_descriptor(muds[i].desc, buf); } else { sprintf(buf, "^%s^%s^%d^*g^%s\n\r", PER(ch), GET_KEYNAME(ch), GetMaxLevel(ch), argument); for(i=0; muds[i].address; i++) if (IS_SET(muds[i].flags, DD_VERIFIED) && !IS_SET(muds[i].flags, DD_NOTHINK)) write_to_descriptor(muds[i].desc, buf); #if USE_COLOR sprintf(buf, "$kW$n $kLdimension thinks, '%s'", argument); #else sprintf(buf, "$n dimension thinks, '%s'", argument); #endif for(d = descriptor_list; d; d = d->next) if (!d->connected && d->character != ch && GetMaxLevel(d->character) >= DEMIGOD) cact(buf, FALSE, ch, 0, d->character, TO_VICT, CLR_THINK); }; } void do_dwho(struct char_data *ch, char *argument, int cmd) { char buf[MAX_INPUT_LENGTH]; int i; argument = one_argument(argument, buf); if ((i=getmud(ch, buf, TRUE))==UNDEFINED) return; if (!dimd_credit(ch, 2)) return; while(isspace(*argument)) argument++; sprintf(buf, "^%s^%s^%d^w^%s\n\r", PER(ch), GET_KEYNAME(ch), GetMaxLevel(ch), argument); write_to_descriptor(muds[i].desc, buf); } bool call_a_mud(int mud) { int size, connectresult; struct sockaddr_in sockaddr; struct hostent *hp; char buf[200]; if (mud == dimd_local_mud) return FALSE; if (isdigit(*muds[mud].address)) sockaddr.sin_addr.s_addr=inet_addr(muds[mud].address); else { if (!(hp=gethostbyname(muds[mud].address))) { sprintf(buf, "Couldn't decipher %s's address.", muds[mud].formalname); DIMDLOG(buf); return FALSE; }; memcpy((char *) &sockaddr.sin_addr, hp->h_addr, sizeof(sockaddr.sin_addr)); }; sockaddr.sin_port = htons(muds[mud].port+2); if ((muds[mud].desc=socket(AF_INET, SOCK_STREAM, 0))<0) { DIMDLOG("Could not obtain a socket."); return FALSE; }; sockaddr.sin_family = AF_INET; connectresult = connect(muds[mud].desc, (struct sockaddr *) &sockaddr, sizeof(sockaddr)); if (connectresult) { close(muds[mud].desc); sprintf(buf, "Couldn't connect to %s[%s].", muds[mud].formalname, muds[mud].address); switch(errno) { case 61: strcat(buf, " Connection refused."); break; default: sprintf(buf+strlen(buf), " Error(%d).", errno); }; DIMDLOG(buf); return FALSE; }; if ((maxdesc+1) >= avail_descs) { sprintf(buf, "Tried to open a connection to %s but ran out of sockets.", muds[mud].formalname); DIMDLOG(buf); close(muds[mud].desc); return FALSE; } else if (muds[mud].desc > maxdesc) maxdesc = muds[mud].desc; size = sizeof(sockaddr); if (getpeername(muds[mud].desc, (struct sockaddr *) &sockaddr, &size) < 0) { perror("getpeername"); *muds[mud].host = '\0'; } else printhost(&sockaddr.sin_addr, muds[mud].host); muds[mud].output.head = NULL; muds[mud].input.head = NULL; *muds[mud].buf = 0; muds[mud].flags |= DD_CONNECTED|DD_VERIFIED; *muds[mud].pcname = 0; sprintf(buf, "DIMD connection to %s[%s] established.", muds[mud].formalname, muds[mud].address); DIMDLOG(buf); write_to_descriptor(muds[mud].desc, DIMD_PASSWORD "\n\r"); return TRUE; } bool answer_a_mud(void) { int desc, size, mud; struct sockaddr_in sock; char buf[1024], host[100]; if ((desc = new_connection(dimd_s)) < 0) return FALSE; if ((maxdesc+1) >= avail_descs) { write_to_descriptor(desc, "Sorry, the game is full."); close(desc); return FALSE; } else if (desc > maxdesc) maxdesc = desc; size = sizeof(sock); if (getpeername(desc, (struct sockaddr *) &sock, &size) < 0) { perror("getpeername"); *host = '\0'; } else printhost(&sock.sin_addr, host); for(mud=0; muds[mud].address; mud++) if (!str_cmp(host, muds[mud].address)) break; if (!muds[mud].address) { write_to_descriptor(desc, "Sorry, I don't recognize your address."); close(desc); sprintf(buf,"DIMD requestor[%s](%d) was refused -- couldn't recognize.", host,mud); DIMDLOG(buf); return FALSE; }; if (IS_SET(muds[mud].flags, DD_CONNECTED)) { write_to_descriptor(desc, "We are already connected to your mud."); close(desc); sprintf(buf, "%s[%s] tried to open a SECOND DIMD connection.", muds[mud].formalname, muds[mud].address); DIMDLOG(buf); return FALSE; }; if (IS_SET(muds[mud].flags, DD_REFUSE)) { write_to_descriptor(desc, "We are not accepting connections from your mud at the moment."); close(desc); sprintf(buf, "%s[%s] tried to connect but is being refused.", muds[mud].formalname, muds[mud].address); DIMDLOG(buf); return FALSE; }; muds[mud].desc = desc; strcpy(muds[mud].host, host); muds[mud].output.head = NULL; muds[mud].input.head = NULL; *muds[mud].buf = 0; muds[mud].flags |= DD_CONNECTED; *muds[mud].pcname = 0; sprintf(buf, "DIMD connection established with %s[%s].", muds[mud].formalname, host); DIMDLOG(buf); return TRUE; } void hangup_on_a_mud(int mud) { char buf[MAX_INPUT_LENGTH]; if (!IS_SET(muds[mud].flags, DD_CONNECTED)) return; close(muds[mud].desc); while(get_from_q(&muds[mud].input, buf)); while(get_from_q(&muds[mud].output, buf)); if (muds[mud].desc == maxdesc) --maxdesc; REMOVE_BIT(muds[mud].flags, DD_CONNECTED|DD_VERIFIED); sprintf(buf, "DIMD connection with %s[%s] closed.", muds[mud].formalname, muds[mud].address); DIMDLOG(buf); } void close_dimd(void) { int mud; if (dimd_state != DIMD_CLOSED) { dimd_state = DIMD_CLOSED ; DIMDLOG("Closing all DIMD sockets and DIMD server."); for(mud=0; muds[mud].address; mud++) hangup_on_a_mud(mud); close(dimd_s); }; } void dimd_loop(void) { int i, fromlevel, fromgodlevel; fd_set input_set, output_set, exc_set; static char buf[MAX_STRING_LENGTH], extra[MAX_STRING_LENGTH], fromname[MAX_INPUT_LENGTH], fromkeyname[MAX_INPUT_LENGTH], dcommand[MAX_INPUT_LENGTH], toname[MAX_INPUT_LENGTH], *scan; struct char_data *vict; char comm[MAX_INPUT_LENGTH]; struct timeval null_time; struct descriptor_data *d; switch (dimd_state) { /****************************************************************/ case DIMD_OPENING: if ((dimd_local_mud=getlocalmud())==UNDEFINED) { DIMDLOG("Couldn't figure out what this mud's name is! DIMD NOT opened."); dimd_state = DIMD_CLOSED; dimd_on = FALSE; return; }; dimd_port = DIMD_PORT; dimd_s=init_socket(dimd_port); DIMDLOG("DIMD port opened."); for(i=0; muds[i].address; i++) if (IS_SET(muds[i].flags, DD_AUTOTRY)) call_a_mud(i); dimd_state = DIMD_OPEN; break; /****************************************************************/ case DIMD_OPEN: null_time.tv_sec = 0; null_time.tv_usec = 0; FD_ZERO(&input_set); FD_ZERO(&output_set); FD_ZERO(&exc_set); FD_SET(dimd_s, &input_set); for(i=0; muds[i].address; i++) if (IS_SET(muds[i].flags, DD_CONNECTED)) { FD_SET(muds[i].desc, &input_set); FD_SET(muds[i].desc, &exc_set); FD_SET(muds[i].desc, &output_set); }; if (select(maxdesc + 1, &input_set, &output_set, &exc_set, &null_time) < 0) { perror("Tell select poll"); return; }; /* Respond to whatever might be happening */ /* New connection? */ if (FD_ISSET(dimd_s, &input_set)) if (!answer_a_mud()) perror("New connection"); for(i=0; muds[i].address; i++) if (IS_SET(muds[i].flags, DD_CONNECTED)) { if (FD_ISSET(muds[i].desc, &exc_set)) { FD_CLR(muds[i].desc, &input_set); FD_CLR(muds[i].desc, &output_set); hangup_on_a_mud(i); }; }; for(i=0; muds[i].address; i++) if (IS_SET(muds[i].flags, DD_CONNECTED)) { if (FD_ISSET(muds[i].desc, &input_set)) if (process_dimd_input(i) < 0) hangup_on_a_mud(i); }; for(i=0; muds[i].address; i++) if (IS_SET(muds[i].flags, DD_CONNECTED)) { while(get_from_q(&muds[i].input, comm)) { if (!IS_SET(muds[i].flags, DD_VERIFIED)) { if (str_cmp(comm, DIMD_PASSWORD)) { sprintf(buf, "The mud is located at port %d.\n\r", dimd_port-2); write_to_descriptor(muds[i].desc, buf); sprintf(buf, "%s[%s]'s server didn't know our password.", muds[i].formalname, muds[i].host); DIMDLOG(buf); hangup_on_a_mud(i); break; }; SET_BIT(muds[i].flags, DD_VERIFIED); break; }; if (*comm != '^') { if (!(vict=get_char(muds[i].pcname))) { sprintf(buf, "DIMD stream for unknown player %s rejected.", muds[i].pcname); DIMDLOG(buf); DIMDLOG(comm); } else msg(comm, vict); continue; }; scan = comm+1; scan = one_dimd_argument(scan, fromname); scan = one_dimd_argument(scan, fromkeyname); scan = one_dimd_argument(scan, buf); fromlevel = atoi(buf); if (!*fromname || !*fromkeyname || !fromlevel) { write_to_descriptor(muds[i].desc, "Your server isn't working properly."); sprintf(buf, "%s[%s] didn't supply PC names or level.", muds[i].formalname, muds[i].host); DIMDLOG(buf); hangup_on_a_mud(i); break; }; if (fromlevel < muds[i].min_level) sprintf(buf, "You must be at least %d level to use DIMD on %s.", muds[i].min_level, muds[i].formalname); else { fromgodlevel = (fromlevel-muds[i].immort_level) * muds[i].immort_level_mult; scan = one_lc_dimd_argument(scan, dcommand); switch(*dcommand) { case '#': strcpy(muds[i].pcname, fromkeyname); continue; case 'a': switch(*(dcommand+1)) { case 'g': sprintf(buf, "%s is now accepting remote gossips.", muds[i].formalname); REMOVE_BIT(muds[i].flags, DD_NOGOSSIP); break; case 'm': sprintf(buf, "%s is now accepting remote muses.", muds[i].formalname); REMOVE_BIT(muds[i].flags, DD_NOMUSE); break; case 't': sprintf(buf, "%s is now accepting remote thinks.", muds[i].formalname); REMOVE_BIT(muds[i].flags, DD_NOTHINK); break; default: sprintf(buf, "Unknown accept command from %s.", muds[i].formalname); }; DIMDLOG(buf); continue; case 'r': switch(*(dcommand+1)) { case 'g': sprintf(buf, "%s is now refusing remote gossips.", muds[i].formalname); SET_BIT(muds[i].flags, DD_NOGOSSIP); break; case 'm': sprintf(buf, "%s is now refusing remote muses.", muds[i].formalname); SET_BIT(muds[i].flags, DD_NOMUSE); break; case 't': sprintf(buf, "%s is now refusing remote thinks.", muds[i].formalname); SET_BIT(muds[i].flags, DD_NOTHINK); break; default: sprintf(buf, "Unknown refuse command from %s.", muds[i].formalname); }; DIMDLOG(buf); continue; case 'w': sprintf(buf, "Who request from %s at %s served.", fromname, muds[i].formalname); DIMDLOG(buf); /* construct_who_list(buf, 39, NULL, fromgodlevel, scan); */ break; case 't': scan = one_lc_dimd_argument(scan, toname); while(isspace(*scan)) scan++; if (!(vict = get_char(toname)) || !dimd_can_see(fromgodlevel, vict)) strcpy(buf, "No char by that name."); else { #if USE_COLOR sprintf(buf, "$kW%s $kMfrom $kW%s $kMtells you '%s'.", fromname, muds[i].formalname, scan); #else sprintf(buf, "%s from %s tells you '%s'.", fromname, muds[i].formalname, scan); #endif cmsg(buf, vict, CLR_TELL); if (IS_SET(vict->pc->comm, COMM_AFK)) #if USE_COLOR sprintf(buf, "$kMYou tell $kW%s$kM (who is AFK), '%s'", PER(vict), scan); #else sprintf(buf, "You tell %s (who is AFK), '%s'", PER(vict), scan); #endif else #if USE_COLOR sprintf(buf, "$kMYou tell $kW%s$kM, '%s'", PER(vict), scan); #else sprintf(buf, "You tell %s, '%s'", PER(vict), scan); #endif }; break; case 'g': if (!dimd_gossip) { write_to_descriptor(muds[i].desc, "^DIMD^DIMD^110^rg\n\r"); sprintf(buf, "%s is no longer accepting remote gossips.", muds[dimd_local_mud].formalname); break; }; if (*(dcommand+1)=='g') #if USE_COLOR sprintf(buf, "$kW%s $kYfrom $kW%s $kYdimension gossips, '%s'", fromname, muds[i].formalname, scan); #else sprintf(buf, "%s from %s dimension gossips, '%s'", fromname, muds[i].formalname, scan); #endif else #if USE_COLOR sprintf(buf, "$kW%s $kYfrom $kW%s $kYgossips, '%s'", fromname, muds[i].formalname, scan); #else sprintf(buf, "%s from %s gossips, '%s'", fromname, muds[i].formalname, scan); #endif for(d = descriptor_list; d; d = d->next) if (!d->connected && !IS_SET(d->character->pc->comm, COMM_NOGOSSIP) && !check_soundproof(d->character)) cmsg(buf, d->character, CLR_GOSSIP); #if USE_COLOR sprintf(buf, "$kYYou gossip on $kW%s$kY, '%s'", muds[dimd_local_mud].formalname, scan); #else sprintf(buf, "You gossip on %s, '%s'", muds[dimd_local_mud].formalname, scan); #endif break; case 'm': if (!dimd_muse) { write_to_descriptor(muds[i].desc, "^DIMD^DIMD^110^rm\n\r"); sprintf(buf, "%s is no longer accepting remote muses.", muds[dimd_local_mud].formalname); break; }; if (*(dcommand+1)=='g') #if USE_COLOR sprintf(buf, "$kW%s $kLfrom $kW%s $kLdimension muses, '%s'", fromname, muds[i].formalname, scan); #else sprintf(buf, "%s from %s dimension muses, '%s'", fromname, muds[i].formalname, scan); #endif else #if USE_COLOR sprintf(buf, "$kW%s $kLfrom $kW%s $kLmuses, '%s'", fromname, muds[i].formalname, scan); #else sprintf(buf, "%s from %s muses, '%s'", fromname, muds[i].formalname, scan); #endif for(d = descriptor_list; d; d = d->next) if (!d->connected && GetMaxLevel(d->character) >= LOW_IMMORTAL && !IS_SET(d->character->pc->comm, COMM_NOMUSE)) cmsg(buf, d->character, CLR_MUSE); #if USE_COLOR sprintf(buf, "$kLYou muse on $kW%s$kL, '%s'", muds[dimd_local_mud].formalname, scan); #else sprintf(buf, "You muse on %s, '%s'", muds[dimd_local_mud].formalname, scan); #endif break; case '*': if (!dimd_think) { write_to_descriptor(muds[i].desc, "^DIMD^DIMD^110^rt\n\r"); sprintf(buf, "%s is no longer accepting remote thinks.", muds[dimd_local_mud].formalname); break; }; if (*(dcommand+1)=='g') #if USE_COLOR sprintf(buf, "$kW%s $kLfrom $kW%s $kLdimension thinks, '%s'", fromname, muds[i].formalname, scan); #else sprintf(buf, "%s from %s dimension thinks, '%s'", fromname, muds[i].formalname, scan); #endif else #if USE_COLOR sprintf(buf, "$kW%s $kLfrom $kW%s $kLthinks, '%s'", fromname, muds[i].formalname, scan); #else sprintf(buf, "%s from %s thinks, '%s'", fromname, muds[i].formalname, scan); #endif for(d = descriptor_list; d; d = d->next) if (!d->connected && GetMaxLevel(d->character) >= DEMIGOD && !IS_SET(d->character->pc->comm, COMM_NOMUSE)) cmsg(buf, d->character, CLR_THINK); #if USE_COLOR sprintf(buf, "$kLYou think on $kW%s$kL, '%s'", muds[dimd_local_mud].formalname, scan); #else sprintf(buf, "You think on %s, '%s'", muds[dimd_local_mud].formalname, scan); #endif break; default: #if USE_COLOR sprintf(buf, "$kW%s $kRfrom $kW%s $kRissued invalid command '%s'.", fromname, muds[i].formalname, dcommand); #else sprintf(buf, "%s from %s issued invalid command '%s'.", fromname, muds[i].formalname, dcommand); #endif DIMDLOG(buf); #if USE_COLOR strcpy(buf, "$k+BRYour server isn't functioning properly."); #else strcpy(buf, "Your server isn't functioning properly."); #endif }; }; strcat(buf, "\n\r"); sprintf(extra, "^%s^%s^%d^#\n\r%s\n\r", fromname, fromkeyname, 1000, buf); write_to_descriptor(muds[i].desc, extra); }; }; /* Are they gone yet? */ for(i=0; muds[i].address; i++) if (IS_SET(muds[i].flags, DD_CONNECTED)) { if (FD_ISSET(muds[i].desc, &output_set) && muds[i].output.head) if (process_dimd_output(i) < 0) hangup_on_a_mud(i); }; if (!dimd_on) dimd_state = DIMD_CLOSING; break; /****************************************************************/ case DIMD_CLOSING: close_dimd(); dimd_state = DIMD_CLOSED ; break; /****************************************************************/ case DIMD_CLOSED: if (dimd_on) dimd_state = DIMD_OPENING; break; } return; } /**********************************************************************/ int process_dimd_output(int mud) { char i[MAX_STRING_LENGTH + 1]; /* Cycle thru output queue */ while(get_from_q(&muds[mud].output, i)) if (write_to_descriptor(muds[mud].desc, i)) return(-1); } int process_dimd_input(int mud) { int sofar, thisround, begin, squelch, i, k, flag; char tmp[MAX_INPUT_LENGTH+2], buffer[MAX_INPUT_LENGTH + 60]; sofar = 0; flag = 0; begin = strlen(muds[mud].buf); /* Read in some stuff */ do { if ((thisround = read(muds[mud].desc, muds[mud].buf + begin + sofar, MAX_STRING_LENGTH - (begin + sofar) - 1)) > 0) { sofar += thisround; } else { if (thisround < 0) { if (errno != EWOULDBLOCK) { perror("Read1 - ERROR"); return(-1); } else { break; } } else { DIMDLOG("EOF encountered on DIMD socket read."); return(-1); } } } while (!ISNEWL(*(muds[mud].buf + begin + sofar - 1))); *(muds[mud].buf + begin + sofar) = 0; /* if no newline is contained in input, return without proc'ing */ for (i = begin; !ISNEWL(*(muds[mud].buf + i)); i++) if (!*(muds[mud].buf + i)) return(0); /* input contains 1 or more newlines; process the stuff */ for (i = 0, k = 0; *(muds[mud].buf + i);) { if (!ISNEWL(*(muds[mud].buf + i)) && !(flag=(k>=(MAX_INPUT_LENGTH - 2)))) if (*(muds[mud].buf + i) == '\b') { /* backspace */ if (k) { /* more than one char ? */ if (*(tmp + --k) == '$') k--; i++; } else { i++; /* no or just one char.. Skip backsp */ } } else { if (isascii(*(muds[mud].buf + i)) && isprint(*(muds[mud].buf + i))) { /* trans char, double for '$' (printf) */ if ((*(tmp + k) = *(muds[mud].buf + i)) == '$') *(tmp + ++k) = '$'; k++; i++; } else { i++; } } else { *(tmp + k) = 0; write_to_q(tmp, &muds[mud].input); if (flag) { sprintf(buffer, "Line too long. Truncated to:\n\r%s\n\r", tmp); if (write_to_descriptor(muds[mud].desc, buffer) < 0) return(-1); /* skip the rest of the line */ for (; !ISNEWL(*(muds[mud].buf + i)); i++); } /* find end of entry */ for (; ISNEWL(*(muds[mud].buf + i)); i++); /* squelch the entry from the buffer */ for (squelch = 0;; squelch++) if ((*(muds[mud].buf + squelch) = *(muds[mud].buf + i + squelch)) == '\0') break; k = 0; i = 0; } } return(1); } void isname_init(const char *str) { char *s; strcpy(is_buf, str); is_argc = split_string(is_buf, "- \t\n\r,", is_argv); s = is_argv[is_argc - 1]; s += strlen(s); if (*(--s) == '.') { is_exact = 1; *s = 0; } else { is_exact = 0; } } bool isname_iter(const char *namelist) { int i, j; strcpy(is_names, namelist); is_xargc = split_string(is_names, "- \t\n\r,", is_xargv); if (is_exact && is_argc != is_xargc) return FALSE; for (i = 0; i < is_argc; i++) { for (j = 0; j < is_xargc; j++) { if (!str_cmp(is_argv[i], is_xargv[j])) { is_xargv[j] = NULL; break; }; }; if (j >= is_xargc) return FALSE; }; return TRUE; } void cact(char *s,byte boo, struct char_data *ch, struct obj_data *obj, struct char_data *ch2, int i, int ii) { act(s,boo,ch,obj,ch2,i); } void msg(char *s, struct char_data *ch) { send_to_char(s,ch); send_to_char("\n\r",ch); } void cmsg(char *s, struct char_data *ch, int i) { send_to_char(s,ch); send_to_char("\n\r",ch); } void printhost(struct in_addr *addr, char *buf) { int i; struct hostent *from; if ((from = gethostbyaddr((char *)addr,sizeof(addr), AF_INET))) { strcpy(buf,from->h_name); } else { log_string("!from!"); i = addr->s_addr; sprintf(buf, "%d.%d.%d.%d", (i&0xff), (i&0xff00)>>8, (i&0xff0000)>>16, (i&0xff000000)>>24); } log_string(buf); } void construct_who_list(char *buf, int cmd, struct char_data *ch, int godlevel, char *argument) { struct char_data *person; struct descriptor_data *d; char levels[40]="", classes[20]=""; char *classname[]={"Mu","Cl","Wa","Th","Dr","Mo","Ba","So","Pa","Ra","Ps"}; char buffer[MAX_STRING_LENGTH],tbuf[MAX_STRING_LENGTH]; int i,total,classn,count,color_cnt=0; long bit; if (godlevel<0) { godlevel=0; log_string("godlevel < 0 in construct_who list"); } sprintf(buffer," Shadowdale Players\n\r"); strcat(buffer, " ------------\n\r"); count=0; for (d = descriptor_list; d; d = d->next) { if ((person=(d->original?d->original:d->character))) if (godlevel>=person->invis_level && real_roomp(person->in_room)) { count++; color_cnt = (color_cnt++ % 9); /* range 1 to 9 */ if(!IS_IMMORTAL(person)) { for(bit=1,i=total=classn=0;i<PSI_LEVEL_IND+1;i++, bit<<=1) { if(HasClass(person,bit)) { classn++; total+=person->player.level[i]; if(strlen(classes)!=0) strcat(classes,"/"); sprintf(classes+strlen(classes),"%s",classname[i]); } } if (total <=0) total =1; if (classn <= 0) classn =1; total/=classn; if(total<11) strcpy(levels,"Newbie"); else if(total<21) strcpy(levels,"Chump"); else if(total<31) strcpy(levels,"Medium"); else if(total<41) strcpy(levels,"Expert"); else if(total<51) strcpy(levels,"Adept"); sprintf(tbuf, "%s %s",levels, classes); sprintf(levels,"%30s",""); strcpy(levels+8-((strlen(tbuf)-12)/2),tbuf); sprintf(tbuf, "%-28s : %s %s",levels, GET_NAME(person),person->player.title?person->player.title:"(Null)"); } else { switch(GetMaxLevel(person)) { case 51: sprintf(levels,"Newbie Immortal"); break; case 52: sprintf(levels,"Saint"); break; case 53: sprintf(levels,"Creator"); break; case 54: sprintf(levels,"Demi God"); break; case 55: sprintf(levels,"God"); break; case 56: sprintf(levels,"Greater God"); break; case 57: sprintf(levels,"Overseer"); break; case 58: sprintf(levels,"SD Lord"); break; case 59: sprintf(levels,"Lord of Realm"); break; case 60: sprintf(levels,"God of Realm"); break; } sprintf(tbuf, "%s",levels); sprintf(levels,"%30s",""); strcpy(levels+8-(strlen(tbuf)/2),tbuf); sprintf(tbuf, "%-16s : %s %s",levels,GET_NAME(person), person->player.title?person->player.title:"(Null)"); } if(IS_SET(person->specials.affected_by2,AFF2_AFK)) sprintf(tbuf+strlen(tbuf)," [AFK] "); if (IS_LINKDEAD(person)) sprintf(tbuf+strlen(tbuf)," [LINKDEAD] "); sprintf(tbuf+strlen(tbuf),"\n\r"); if (strlen(buffer)+strlen(tbuf) < (MAX_STRING_LENGTH*2)-512) strcat(buffer,tbuf); } } sprintf(tbuf, "\n\rTotal visible players: %d\n\r", count); if (strlen(buffer)+strlen(tbuf) < MAX_STRING_LENGTH*2-512) strcat(buffer,tbuf); strcpy(buf,buffer); }