/****************************************************
* 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