/**************************************************** * Original Copyover patch by Erwin Andreasen. * * This provides some changes, and easy installation* * instructions, and works for 1.4, and 1.4a. * * --Callidyrr * ****************************************************/ /* db.c */ change void boot_db( void ) to this void boot_db( bool fCopyOver ) search for load_morphs( ); MOBtrigger = TRUE; add this underneat it if (fCopyOver) { log_string("Running copyover_recover."); copyover_recover(); } /* mud.h */ search for #define TOGGLE_BIT(var, bit) ((var) ^= (bit)) add this underneath it #define CH(d) ((d)->original ? (d)->original : (d)->character) search for #define PLANE_FILE SYSTEM_DIR "planes.dat" /* For planes */ add this underneath it #define COPYOVER_FILE SYSTEM_DIR "copyover.dat" /* for warm reboots */ #define EXE_FILE "../src/smaug" /* executable path */ search for void act args( ( sh_int AType, const char *format, CHAR_DATA *ch, const void *arg1, const void *arg2, int type ) ); add this underneath it void copyover_recover args( (void) ); search for void boot_db args( ( void ) ); change to void boot_db args( ( bool fCopyOver ) ); search for void ch_printf_color args( ( CHAR_DATA *ch, char *fmt, ... ) ); add this underneath it void log_printf args( (char *fmt, ...) ); search for CON_READ_IMOTD add this after it (remember to put a comma after CON_READ_IMOTD (or the last constate..whichever it may be)) CON_COPYOVER_RECOVER search for DECLARE_DO_FUN( do_compare ); underneath it, add this DECLARE_DO_FUN( do_copyover ); /* comm.c */ search for char hostn[128]; add this underneath it bool fCopyOver = !TRUE; search for if ( !is_number( argv[1] ) ) { fprintf( stderr, "Usage: %s [port #]\n", argv[0] ); exit( 1 ); } else if ( ( port = atoi( argv[1] ) ) <= 1024 ) { fprintf( stderr, "Port number must be above 1024.\n" ); exit( 1 ); } add this underneath it if (argv[2] && argv[2][0]) { fCopyOver = TRUE; control = atoi(argv[3]); control2 = atoi(argv[4]); } else fCopyOver = FALSE; search for #endif /* WIN32 */ log_string("Booting Database"); boot_db( ); change this ( boot_db( ); ) to this: boot_db(fCopyOver); right after that, you'll see this control = init_socket( port ); control2 = init_socket( port+1 ); conclient= init_socket( port+10); conjava = init_socket( port+20); delete all of that and add this if (!fCopyOver) /* We have already the port if copyover'ed */ { control = init_socket (port); } search for this function void bailout(void) { echo_to_all( AT_IMMORT, "MUD shutting down by system operator NOW!!", ECHOTAR_ALL ); shutdown_mud( "MUD shutdown by system operator" ); log_string ("MUD shutdown by system operator"); Sleep (5000); /* give "echo_to_all" time to display */ mud_down = TRUE; /* This will cause game_loop to exit */ service_shut_down = TRUE; /* This will cause characters to be saved */ fflush(stderr); return; } #endif add this function underneath it void do_copyover (CHAR_DATA *ch, char * argument) { FILE *fp; DESCRIPTOR_DATA *d, *d_next; char buf [100], buf2[100], buf3[100], buf4[100], buf5[100]; fp = fopen (COPYOVER_FILE, "w"); if (!fp) { send_to_char ("Copyover file not writeable, aborted.\n\r",ch); log_printf ("Could not write to copyover file: %s", COPYOVER_FILE); perror ("do_copyover:fopen"); return; } /* Consider changing all saved areas here, if you use OLC */ /* do_asave (NULL, ""); - autosave changed areas */ /* Shutdown IMC network or port will already be bound! */ imc_shutdown_network(); sprintf (buf, "\n\r *** COPYOVER initated by %s - please remain seated!\n\r", ch->name); /* For each playing descriptor, save its state */ for (d = first_descriptor; d ; d = d_next) { CHAR_DATA * och = CH(d); d_next = d->next; /* We delete from the list , so need to save this */ if (!d->character || d->connected != CON_PLAYING ) /* drop those logging on */ { write_to_descriptor (d->descriptor, "\n\rSorry, we are rebooting." " Come back in a few minutes.\n\r", 0); close_socket (d, FALSE); /* throw'em out */ } else { fprintf (fp, "%d %s %s\n", d->descriptor, och->name, d->host); if (och->level == 1) { write_to_descriptor (d->descriptor, "Since you are level one," "and level one characters do not save, you gain a free level!\n\r", 0); advance_level (och); och->level++; /* Advance_level doesn't do that */ } save_char_obj (och); write_to_descriptor (d->descriptor, buf, 0); } } fprintf (fp, "-1\n"); fclose (fp); /* Close reserve and other always-open files and release other resources */ fclose (fpReserve); fclose (fpLOG); /* exec - descriptors are inherited */ sprintf (buf, "%d", port); sprintf (buf2, "%d", control); execl (EXE_FILE, "smaug", buf, "copyover", buf2, buf3, buf4, buf5, (char *) NULL); /* Failed - sucessful exec will not return */ perror ("do_copyover: execl"); send_to_char ("Reboot FAILED!\n\r",ch); /* Here you might want to reopen fpReserve */ /* Since I'm a neophyte type guy, I'll assume this is a good idea and cut and past from main() */ if ( ( fpReserve = fopen( NULL_FILE, "r" ) ) == NULL ) { perror( NULL_FILE ); exit( 1 ); } if ( ( fpLOG = fopen( NULL_FILE, "r" ) ) == NULL ) { perror( NULL_FILE ); exit( 1 ); } } /* Recover from a copyover - load players */ void copyover_recover () { DESCRIPTOR_DATA *d; FILE *fp; char name [100]; char host[MAX_STRING_LENGTH]; int desc; bool fOld; log_string ("Warmboot recovery initiated"); fp = fopen (COPYOVER_FILE, "r"); if (!fp) /* there are some descriptors open which will hang forever then ? */ { perror ("copyover_recover:fopen"); log_string("Warmboot file not found. Exitting.\n\r"); exit (1); } unlink (COPYOVER_FILE); /* In case something crashes - doesn't prevent reading */ for (;;) { fscanf (fp, "%d %s %s\n", &desc, name, host); if (desc == -1) break; /* Write something, and check if it goes error-free */ if (!write_to_descriptor (desc, "\n\rRestoring from copyover...\n\r", 0)) { close (desc); /* nope */ continue; } CREATE(d, DESCRIPTOR_DATA, 1); init_descriptor (d, desc); /* set up various stuff */ d->host = STRALLOC( host ); LINK( d, first_descriptor, last_descriptor, next, prev ); d->connected = CON_COPYOVER_RECOVER; /* negative so close_socket will cut them off */ /* Now, find the pfile */ fOld = load_char_obj (d, name, FALSE); if (!fOld) /* Player file not found?! */ { write_to_descriptor (desc, "\n\rSomehow, your character was lost in the warmboot. Please contact an Immortal.\n\r", 0 ); close_socket (d, FALSE); } else /* ok! */ { write_to_descriptor (desc, "\n\rWarmboot recovery complete.\n\r",0); /* This isn't necassary, but _why_ do we want to dump someone in limbo? */ if (!d->character->in_room) d->character->in_room = get_room_index (ROOM_VNUM_TEMPLE); /* Insert in the char_list */ LINK( d->character, first_char, last_char, next, prev ); /* * So that it doesn't reset as default of 0 when 20 players are on * -- Callidyrr */ num_descriptors++; sysdata.maxplayers++; char_to_room (d->character, d->character->in_room); do_look (d->character, "auto noprog"); act (AT_ACTION, "$n materializes!", d->character, NULL, NULL, TO_ROOM); d->connected = CON_PLAYING; } } } search for this void new_descriptor( int new_desc ) above that function, add this one. void init_descriptor( DESCRIPTOR_DATA *dnew, int desc) { dnew->next = NULL; dnew->descriptor = desc; dnew->connected = CON_GET_NAME; dnew->outsize = 2000; dnew->idle = 0; dnew->lines = 0; dnew->scrlen = 24; dnew->user = STRALLOC("unknown"); dnew->newstate = 0; dnew->prevcolor = 0x07; CREATE( dnew->outbuf, char, dnew->outsize ); } THEN just delete the whole void new_descriptor code..and put this one in (I didn't feel like goin to the whole void new_descriptor function and see all of the little changes..because..it's quite big..) After deleting it, put this in it's place void new_descriptor( int new_desc ) { char buf[MAX_STRING_LENGTH]; DESCRIPTOR_DATA *dnew; struct sockaddr_in sock; struct hostent *from; int desc; int size; /* char bugbuf[MAX_STRING_LENGTH];*/ #ifdef WIN32 unsigned long arg = 1; #endif size = sizeof(sock); if ( check_bad_desc( new_desc ) ) { set_alarm( 0 ); return; } set_alarm( 20 ); alarm_section = "new_descriptor::accept"; if ( ( desc = accept( new_desc, (struct sockaddr *) &sock, &size) ) < 0 ) { set_alarm( 0 ); return; } if ( check_bad_desc( new_desc ) ) { set_alarm( 0 ); return; } #if !defined(FNDELAY) #define FNDELAY O_NDELAY #endif set_alarm( 20 ); alarm_section = "new_descriptor: after accept"; #ifdef WIN32 if ( ioctlsocket(desc, FIONBIO, &arg) == -1 ) #else if ( fcntl( desc, F_SETFL, FNDELAY ) == -1 ) #endif { perror( "New_descriptor: fcntl: FNDELAY" ); set_alarm( 0 ); return; } if ( check_bad_desc( new_desc ) ) return; CREATE( dnew, DESCRIPTOR_DATA, 1 ); init_descriptor(dnew, desc ); dnew->port = ntohs(sock.sin_port); strcpy( buf, inet_ntoa( sock.sin_addr ) ); sprintf( log_buf, "Sock.sinaddr: %s, port %hd.", buf, dnew->port ); log_string_plus( log_buf, LOG_COMM, sysdata.log_level ); dnew->host = STRALLOC( buf ); from = gethostbyaddr( (char *) &sock.sin_addr, sizeof(sock.sin_addr), AF_INET ); CREATE( dnew->outbuf, char, dnew->outsize ); strcpy( buf, inet_ntoa( sock.sin_addr ) ); sprintf( log_buf, "Sock.sinaddr: %s, port %hd.", buf, dnew->port ); log_string_plus( log_buf, LOG_COMM, sysdata.log_level ); if ( sysdata.NO_NAME_RESOLVING ) dnew->host = STRALLOC( buf ); else { from = gethostbyaddr( (char *) &sock.sin_addr, sizeof(sock.sin_addr), AF_INET ); dnew->host = STRALLOC( (char *)( from ? from->h_name : buf) ); } if ( check_total_bans( dnew ) ) { write_to_descriptor (desc, "Your site has been banned from this Mud.\n\r", 0); free_desc (dnew); set_alarm (0); return; } /* * Init descriptor data. */ if ( !last_descriptor && first_descriptor ) { DESCRIPTOR_DATA *d; bug( "New_descriptor: last_desc is NULL, but first_desc is not! ...fixing" ); for ( d = first_descriptor; d; d = d->next ) if ( !d->next ) last_descriptor = d; } LINK( dnew, first_descriptor, last_descriptor, next, prev ); /* * Send the greeting. */ { extern char * help_greeting; if ( help_greeting[0] == '.' ) write_to_buffer( dnew, help_greeting+1, 0 ); else write_to_buffer( dnew, help_greeting , 0 ); } alarm_section = "new_descriptor: set_auth"; set_auth(dnew); alarm_section = "new_descriptor: after set_auth"; if ( ++num_descriptors > sysdata.maxplayers ) sysdata.maxplayers = num_descriptors; if ( sysdata.maxplayers > sysdata.alltimemax ) { if ( sysdata.time_of_max ) DISPOSE(sysdata.time_of_max); sprintf(buf, "%24.24s", ctime(¤t_time)); sysdata.time_of_max = str_dup(buf); sysdata.alltimemax = sysdata.maxplayers; sprintf( log_buf, "Broke all-time maximum player record: %d", sysdata.alltimemax ); log_string_plus( log_buf, LOG_COMM, sysdata.log_level ); to_channel( log_buf, CHANNEL_MONITOR, "Monitor", LEVEL_IMMORTAL ); save_sysdata( sysdata ); } set_alarm(0); return; } search for this chunk of code char *myobj( OBJ_DATA *obj ) { if ( !str_prefix("a ", obj->short_descr) ) return obj->short_descr + 2; if ( !str_prefix("an ", obj->short_descr) ) return obj->short_descr + 3; if ( !str_prefix("the ", obj->short_descr) ) return obj->short_descr + 4; if ( !str_prefix("some ", obj->short_descr) ) return obj->short_descr + 5; return obj->short_descr; } right after it, add this void log_printf(char *fmt, ...) { char buf[MAX_STRING_LENGTH*2]; va_list args; va_start(args, fmt); vsprintf(buf, fmt, args); va_end(args); log_string(buf); } /* tables.c */ in case 'c': add this if ( !str_cmp( name, "do_copyover" )) return do_copyover; go down.. a little bit..if you're new to coding..search for.. if ( skill == do_compare ) return "do_compare"; underneath it, add this if ( skill == do_copyover ) return "do_copyover"; /************************************************************************** * End of Code Additions * **************************************************************************/ Ok, now..after all that work is done (finally huh?) do a clean make If you already have a mud running, shut it down, and restart it. once the mud is up, type this: cedit copyover create then you can set it to whatever level you wish by typing this cedit copyover level ## after that, enter this: cedit save cmdtable If you don't have your mud running, start it up, then type this inside the mud: cedit copyover create, and you can also set it to whatever level you with by entering cedit copyover level ##, and then..cedit save cmdtable to save it. THAT'S IT! YOU'RE ALL DONE. Now, just type copyover..and voila --Callidyrr