// game logging to std error.. now with sprintf support void mudlog(const char *str, ...) { MSOCKET *sock; char logstr[MAX_BUFFER*2]; char buf[MAX_BUFFER]; char imm[MAX_BUFFER]; va_list ap; static long numlogs=0; if(++numlogs > MUDLOG_LIMIT) return; va_start(ap, str); (void)vsnprintf(buf, MAX_BUFFER, str, ap); sprintf(imm,"&+M[LOG] &+W"); strcat(imm,buf); for(sock = socket_list; sock; sock = sock->next) { if(sock->pc && (!IsPlaying(sock->pc) || !flag_isset(sock->pc->flags, CFLAG_NOTIFY))) continue; sendcrit(sock->pc, imm); } strftime(logstr, MAX_BUFFER, "%m/%d/%Y %H:%M:%S :: ", localtime(¤t_time) ); strcat(logstr,buf); // fprintf(stderr, "%s\n", wraptext(23,logstr,100)); fprintf(stderr, "%s\n", logstr); va_end(ap); }
void use_channel(CREATURE *crit, char *name, char *text, long level, long flag, char *color) { MSOCKET *sock; char buf[MAX_BUFFER]; sprintf(buf,"%s(%s) [&N&+W%s&N%s]: %s&N",color,name,crit->name,color,text); for(sock = socket_list; sock; sock = sock->next) { if(!IsPlaying(sock->pc) || sock->pc->level < level || flag_isset(sock->pc->flags, flag)) continue; sendcrit(sock->pc,buf); } }
// game boot up stuff void init_mud(long hotreboot) { char buf[MAX_BUFFER]; MSOCKET *socket; extern CREATURE *hash_creature[HASH_KEY]; extern OBJECT *hash_object[HASH_KEY]; extern ROOM *hash_room[HASH_KEY]; extern char **connect_attempts; extern void backup_update(); #ifndef WIN32 struct itimerval itime; struct timeval time; #endif extern char * const months[]; extern char * const days[]; long x; for(x = 0; months[x]; x++) ; mudtime.months = x; for(x = 0; days[x]; x++) ; mudtime.days = x; // init hash tables memset(hash_creature, 0,sizeof(hash_creature)); memset(hash_object, 0,sizeof(hash_object)); memset(hash_room, 0,sizeof(hash_room)); memset(hash_reset, 0,sizeof(hash_reset)); // set up process signals to catch and deal with signal(SIGINT, signal_handler); signal(SIGILL, signal_handler); signal(SIGFPE, signal_handler); signal(SIGSEGV, signal_handler); signal(SIGPIPE, SIG_IGN); // ignore pipes! tx to unix socket faq for help // with this. http://http://www.developerweb.net/forum/ #ifndef WIN32 signal(SIGTRAP, signal_handler); signal(SIGVTALRM, signal_handler); // this code is to check for infinite looping time.tv_sec = 5; time.tv_usec = 0; itime.it_interval = time; itime.it_value = time; if( setitimer(ITIMER_VIRTUAL, &itime, 0) < 0 ) mudlog("Error starting setitimer."); #endif // initialize the random number generator init_rand(); // connect_attempts array, to keep people from spam connecting to slow down the mud connect_attempts = malloc(sizeof(char*)); connect_attempts[0] = 0; mysql = mysql_init(NULL); if (!mysql) { mudlog("Error initializing MySQL: %s", mysql_error(mysql)); abort(); } // connect to MySQL database if (!mysql_real_connect(mysql, DB_HOST, DB_LOGIN, DB_PASSWORD, DB_NAME, 0, NULL, 0)) { mudlog("Error opening mysql database: %s", mysql_error(mysql)); abort(); } if (mysql_select_db(mysql, DB_NAME)) { mudlog("Error opening main database: %s",mysql_error(mysql)); if (mysql) mysql_close(mysql); abort(); } // time of da mud ! fread_time(); // load areas/rooms/objects/creatures load_db(); // check if hotreboot and reconnect everything if(hotreboot) { MSOCKET *socket=0; char buf[MAX_BUFFER]; MYSQL_RES *result; MYSQL_ROW row; mysql_query(mysql, "SELECT * FROM player WHERE online='1'"); result = mysql_store_result(mysql); if (mysql_num_rows(result) < 0) { mudlog("hotreboot: mysql error is: %s",mysql_error(mysql)); exit(1); } while((row = mysql_fetch_row(result))) { strcpy(buf, row[P_NAME]); // check for "host" player.. holds control descriptor if(!strcasecmp("host", row[C_NAME])) { host = atoi(row[P_DESCRIPTOR]); } else { socket = init_socket(); fread_player(socket, buf); str_dup(&socket->host, row[P_HOST]); str_dup(&socket->ip, row[P_IP]); socket->desc = atoi(row[P_DESCRIPTOR]); socket->connected = CON_PLAYING; trans(socket->pc, socket->pc->in_room); sendcrit(socket->pc, "Hotreboot completed."); } } mysql_free_result(result); } // make sure nobody has non-existant connections, in the event of a crash + hotreboot // then go through and update people who are online // this is also a good time to get host address, as players will be expecting lag mysql_query(mysql, "UPDATE player SET online='0', descriptor='0'"); for(socket = socket_list; socket; socket = socket->next) { get_hostname(socket); sprintf(buf,"UPDATE player SET online='1', host=\"%s\" WHERE id='%li'", smash_quotes(socket->host), socket->id); mysql_query(mysql, buf); } // see how many players are in each area, to see if area should be 'alive' for(socket = socket_list; socket; socket = socket->next) { if(IsPlaying(socket->pc)) socket->pc->in_room->area->players++; } // check if we need to backup backup_update(); }
// MESSAGE -- main messaging utility for the mud. Can message everyone in room, and you can // use "triggers", for lack of a better word, so the messages make more sense. An example: // message("$n hit$x $N with $p!",crit,xcrit,obj); --> the $n is the actor, all the lowercase // triggers refer to the actor, and upper case refers to the stage. $p refers to the extra. // This would create three messages-> // ACTOR(You hit Pip with a big pointy stick!) // STAGE(Borlak hits you with a big pointy stick!) // EXTRA(Borlak hits Pip with a big pointy stick!) // // Notice what changed.. The 's' on "hits" is removed for the actor. You may supply // a character string for $p. for example, a door exit (borlak exits west...) // // $n/$N->name of actor/stage, $s/$S->his/her, $m/$M->him/her, $x/$X->s or es // $r/$R->is/are $t/$T->your/their $z/$Z->your/Borlak's // world->1 for all players, 2 for all players get the message _immediately_ (shutdown) void create_message(char *buf, void *actor, void *stage, void *extra, bool world) { char bufactor[MAX_BUFFER*2]; char bufstage[MAX_BUFFER*2]; char bufextra[MAX_BUFFER*2]; char actor_name[MAX_BUFFER]; char stage_name[MAX_BUFFER]; char extra_name[MAX_BUFFER]; char temp[24]; CREATURE *crit = 0; CREATURE *xcrit = 0; CREATURE *ppl = 0; MSOCKET *sock = 0; OBJECT *obj = 0; OBJECT *xobj = 0; ROOM *room = 0; char *abuf; char *sbuf; char *ebuf; char *acopy; char *scopy; char *ecopy; long to_room_only = 0; long possessive = 0; actor_name[0] = '\0'; stage_name[0] = '\0'; extra_name[0] = '\0'; bufactor[0] = '\0'; abuf = bufactor; bufstage[0] = '\0'; sbuf = bufstage; bufextra[0] = '\0'; ebuf = bufextra; acopy = ""; scopy = ""; ecopy = ""; if(actor) { switch(*(unsigned int*)actor) { case TYPE_CREATURE: crit = (CREATURE*)actor; room = crit->in_room; strcpy(actor_name,crit->name); break; case TYPE_OBJECT: obj = (OBJECT*)actor; if(obj->in_room) room = obj->in_room; else if(obj->held_by) room = obj->held_by->in_room; else if(obj->in_obj) { if(obj->in_obj->in_room) room = obj->in_obj->in_room; else if(obj->in_obj->held_by) room = obj->in_obj->held_by->in_room; } if(obj->objtype == OBJ_COIN) sprintf(actor_name,"some %s",coin_table[obj->values[0]].ansi_name); else strcpy(actor_name,obj->name); break; case TYPE_ROOM: room = (ROOM*)actor; strcpy(actor_name,room->name); break; default: mudlog("MESSAGE(%s): bad actor type!",buf); return; } } if(stage) { switch(*(unsigned int*)stage) { case TYPE_CREATURE: xcrit = (CREATURE*)stage; strcpy(stage_name,xcrit->name); break; case TYPE_OBJECT: xobj = (OBJECT*)stage; if(xobj->objtype == OBJ_COIN) sprintf(stage_name,"some %s",coin_table[xobj->values[0]].ansi_name); else strcpy(stage_name,xobj->name); break; case TYPE_ROOM: // decided to make TYPE_ROOM stages go NOT to the crit. // so basically, you have a crit that doesn't get message. to_room_only = 1; // mudlog("MESSAGE(%s): can't have room as stage!",buf); break; default: mudlog("MESSAGE(%s): bad stage type!",buf); return; } } if(extra) { switch(*(unsigned int*)extra) { case TYPE_CREATURE: mudlog("MESSAGE(%s): can't have creature as extra!",buf); break; case TYPE_OBJECT: xobj = (OBJECT*)extra; if(xobj->objtype == OBJ_COIN) sprintf(extra_name,"some %s",coin_table[xobj->values[0]].ansi_name); else strcpy(extra_name,xobj->name); break; case TYPE_ROOM: mudlog("MESSAGE(%s): can't have room as extra!",buf); break; default: strcpy(extra_name,(char*)extra); break; } } for(; *buf != '\0'; buf++) { switch(*buf) { case '$': buf++; switch(*buf) { case '\0': break; case 'e': acopy = "you"; scopy = ecopy = heshe[crit->sex]; break; case 'E': scopy = "you"; if (xcrit) acopy = ecopy = heshe[xcrit->sex]; else acopy = ecopy = "their"; break; case 'm': acopy = "your"; scopy = ecopy = himher[crit->sex]; break; case 'M': scopy = "your"; if (xcrit) acopy = ecopy = himher[xcrit->sex]; else acopy = ecopy = "their"; break; case 'n': acopy = "you"; scopy = ecopy = actor_name; break; case 'N': acopy = ecopy = stage_name; scopy = "you"; break; case 'z': acopy = "your"; scopy = ecopy = actor_name; possessive = 1; break; case 'Z': acopy = ecopy = stage_name; scopy = "your"; possessive = 2; break; case 'g': case 'G': acopy = "go"; scopy = ecopy = "goes"; break; case 'd': case 'D': acopy = "don't"; scopy = ecopy = "doesn't"; break; case 'p': case 'P': acopy = scopy = ecopy = extra_name; break; case 'r': case 'R': ecopy = "is"; scopy = acopy = "are"; break; case 's': acopy = "your"; scopy = ecopy = hisher[crit->sex]; break; case 'S': scopy = "your"; if (xcrit) acopy = ecopy = hisher[xcrit->sex]; else acopy = ecopy = "their"; break; case 'y': acopy = "y"; scopy = ecopy = "ies"; break; case 't': case 'T': acopy = scopy = "your"; ecopy = "their"; break; case 'x': acopy = ""; scopy = ecopy = "s"; break; case 'X': acopy = "s"; scopy = ecopy = ""; break; case 'v': case 'V': ecopy = "has"; scopy = acopy = "have"; break; case 'b': acopy = ""; scopy = ecopy = "es"; break; case 'B': acopy = "es"; scopy = ecopy = ""; break; default: sprintf(temp, "%c%c", *(buf-1), *buf); acopy = scopy = ecopy = temp; break; } while(*acopy != '\0') *abuf++ = *acopy++; while(*scopy != '\0') *sbuf++ = *scopy++; while(*ecopy != '\0') *ebuf++ = *ecopy++; if(possessive == 1) { *sbuf++ = '\''; *sbuf++ = 's'; *ebuf++ = '\''; *ebuf++ = 's'; possessive = 0; } else if(possessive == 2) { *abuf++ = '\''; *abuf++ = 's'; *ebuf++ = '\''; *ebuf++ = 's'; possessive = 0; } break; default: *abuf++ = *buf; *sbuf++ = *buf; *ebuf++ = *buf; break; } } *abuf = '\0'; *sbuf = '\0'; *ebuf = '\0'; ansicap(bufactor); ansicap(bufstage); ansicap(bufextra); if (world) { for (sock = socket_list; sock; sock = sock->next) { ppl = sock->pc; if(!ppl || !IsPlaying(ppl)) continue; if (ppl == crit) { if(world > 1 && IsPlayer(crit)) send_immediately(crit->socket,bufactor); else sendcrit(crit,bufactor); } else { if(world > 1 && IsPlayer(ppl)) send_immediately(ppl->socket,bufstage); else sendcrit(ppl,bufstage); } } return; } for(ppl = room->crits; ppl; ppl = ppl->next_content) { if(!IsPlaying(ppl) || ppl->state >= STATE_SLEEPING) continue; if(ppl == crit) { if(!to_room_only) sendcrit(crit,bufactor); } else if(ppl == xcrit) sendcrit(xcrit,bufstage); else sendcrit(ppl,bufextra); } }
/////////////// // FUNCTIONS // /////////////// void interpret(CREATURE *crit, char *buf) { CREATURE *xcrit=0; OBJECT *obj=0; SOCIAL *social=0; EXIT *exit=0; ROOM *room=0; char command[MAX_BUFFER]; char temp[MAX_BUFFER]; char *pbuf = command; char **arguments; char **editargs; long i = 0, x = 0; long string = 0; bool found = 0; bool command_ok = 0; bool social_ok = 0; strcpy(temp,buf); while( isspace(*buf) ) buf++; // check for one character commands without spaces to // seperate arguments. - i.e. chat yo = .yo | pip if(ispunct(*buf)) *pbuf++ = *buf++; else { while( !isspace(*buf) && *buf != '\0' ) *pbuf++ = *buf++; } *pbuf = '\0'; while( isspace(*buf) ) buf++; // moved exits before other commands - pip. // insert full exit name for abbreviated one. for( i = 0; directions[i].abbr; i++) { if (directions[i].abbr[0] != '\0' && !strcasecmp(command,directions[i].abbr)) { sprintf(command,"%s",directions[i].name); break; } } if(!IsDisabled(crit)) { for(exit = crit->in_room->exits; exit; exit = exit->next ) { if( !strindex(exit->name, command) ) { if((room = hashfind_room(exit->to_vnum)) == 0) { sendcrit(crit,"That exit enters into a domain far too powerful for you to handle."); mudlog("exit(%s) in room(%s:%d) has bad to_vnum(%d)!", exit->name, crit->in_room->name, crit->in_room->vnum, exit->to_vnum); continue; } if (exit->door >= DOOR_CLOSED && !IsImmortal(crit)) { sendcritf(crit,"The %s door is closed.",exit->name); return; } if (crit->rider) { sendcritf(crit,"You can't move on your own until %s dismounts you.",crit->rider->name); return; } // adding mounts! if (crit->mount) message("$n ride$x $p on $N.",crit,crit->mount,exit->name); else message("$n leave$x $p.",crit,0,exit->name); trans(crit,room); if (crit->mount) { trans(crit->mount,crit); message("$n arrive$x riding $N.",crit,crit->mount,crit->in_room); } message("$n $v arrived.",crit,crit->in_room,0); interpret(crit,"look"); return; } } } // check if they in editor and get a successful return (edited something) // otherwise let them use normal commands if(IsEditing(crit)) { if(crit->socket->string) { if(!(string = string_editor(crit,temp))) return; str_dup(&(*crit->socket->variable), crit->socket->string); DeleteObject(crit->socket->string) return; } else temp[0] = '\0'; if(!ValidString(command)) strcat(temp,""); else sprintf(temp,"%s %s",command,buf); editargs = make_arguments(temp); if(editor(crit,editargs)) { free_arguments(editargs); return; } free_arguments(editargs); }