daleken/
daleken/data/notes/
daleken/data/player/
daleken/data/system/poses/
daleken/doc/Homepage/images/
daleken/log/
/*___________________________________________________________________________*
   )()(			  DalekenMUD 1.12 (C) 2000			)()(
   `]['		       by Martin Thomson, Lee Brooks,			`]['
    ||		       Ken Herbert and David Jacques			 ||
    || ----------------------------------------------------------------- ||
    || Envy Diku Mud improvements copyright (C) 1994 by Michael Quan,	 ||
    || David Love, Guilherme 'Willie' Arnold, and Mitchell Tse.		 ||
    || Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael	 ||
    || Chastain, Michael Quan, and Mitchell Tse.			 ||
    || Original Diku Mud copyright (C) 1990, 1991			 ||
    || by Sebastian Hammer, Michael Seifert, Hans Henrik St{rfeldt,	 ||
    || Tom Madsen, and Katja Nyboe.					 ||
    || ----------------------------------------------------------------- ||
    || Any use of this software must follow the licenses of the		 ||
    || creators.  Much time and thought has gone into this software and	 ||
    || you are benefitting. We hope that you share your changes too.	 ||
    || What goes around, comes around.					 ||
    || ----------------------------------------------------------------- ||
    ||                             olc_save.c                            ||
    || Saving routines for areas.                                        ||
 *_/<>\_________________________________________________________________/<>\_*/


#include "mud.h"
#include "olc.h"
#include "db.h"

/*
 * Local functions.
 */
void save_area_list	args( ( void ) );

/*****************************************************************************
 Name:		fix_string
 Purpose:	Returns a string without \r and ~.
 ****************************************************************************/
char *fix_string( char *strfix, const char *str )
{
    int i;
    int o;

    if( str == NULL || str[0] == '\0' || strlen( str ) > MAX_STRING_LENGTH )
	return strcpy( strfix, "" );

    for( o = i = 0; str[i + o] != '\0'; i++ )
    {
	while( str[i + o] == '\r' || str[i + o] == '~' )
	    o++;
	strfix[i] = str[i + o];
    }
    strfix[i] = '\0';
    return strfix;
}


/*****************************************************************************
 Name:		save_area_list
 Purpose:	Saves the listing of files to be loaded at startup.
 Called by:	do_asave (olc_save.c).
 ****************************************************************************/
void save_area_list( )
{
    FILE *fp;
    AREA_DATA *pArea;

    if( ( fp = open_file( AREA_DIR AREA_LIST, "w", FALSE ) ) == NULL )
    {
	bug( "Save_area_list: open_file" );
	perror( AREA_DIR AREA_LIST );
    }
    else
    {
	/*
	 * Add any help files that need to be loaded at
	 * startup to this section.
	 * These are the files which don't have a '@AREA' section.
	 * fprintf( fp, "all.hlp\n" );
	 */

	for( pArea = area_first; pArea; pArea = pArea->next )
	{
	    if( IS_SET( pArea->area_flags, AREA_DELETED ) )
		continue;
	    fprintf( fp, "%s\n", pArea->filename );
	}

	fprintf( fp, "$\n" );
	close_file( fp );
    }

    return;
}


/*****************************************************************************
 Name:		save_mobprogs
 Purpose:	Save the mudprogs used for the entire area.
 Called by:	save_area (olc_save.c).
 ****************************************************************************/
void save_area_mudprogs( FILE *fp, AREA_DATA *area )
{
    int i;
    MPROG_GLOBAL *mprg;


    for( i = 0; i < MPROG_GLOBAL_HASH; ++i )
	for( mprg = global_progs[i]; mprg; mprg = mprg->next )
	    if( mprg->area == area )
		write_next_item( fp, "GProg", mprg );
    fprintf( fp, "\n\n" );
    return;
}


/*****************************************************************************
 Name:		save_mobiles
 Purpose:	Save #MOBILES secion of an area file.
 Called by:	save_area( olc_save.c ).
 ****************************************************************************/
void save_mobiles( FILE *fp, AREA_DATA *pArea )
{
    int vnum;
    MOB_INDEX_DATA *pMob;

    for( vnum = pArea->lvnum; vnum <= pArea->uvnum; vnum++ )
    {
	if( ( pMob = get_mob_index( vnum ) )
	    && pMob->area == pArea )
	    write_next_item( fp, "Mobile", pMob );
    }

    fprintf( fp, "\n\n" );

    return;
}


/*****************************************************************************
 Name:		save_objects
 Purpose:	Save #OBJECTS section of an area file.
 Called by:	save_area( olc_save.c ).
 ****************************************************************************/
void save_objects( FILE *fp, AREA_DATA *pArea )
{
    int vnum;
    OBJ_INDEX_DATA *pObj;

    for( vnum = pArea->lvnum; vnum <= pArea->uvnum; vnum++ )
    {
	if( ( pObj = get_obj_index( vnum ) )
	    && pObj->area == pArea )
	    write_next_item( fp, "Object", pObj );
    }

    fprintf( fp, "\n\n" );

    return;
}


/* OLC 1.1b */
/*****************************************************************************
  Name:		save_rooms
  Purpose:	Save #ROOMDATA section of an area file.
  Called by:	save_area( olc_save.c ).
 ****************************************************************************/
void save_rooms( FILE *fp, AREA_DATA *pArea )
{
    ROOM_INDEX_DATA *pRoom;
    int vnum;

    for( vnum = pArea->lvnum; vnum <= pArea->uvnum; vnum++ )
    {
	if( ( pRoom = get_room_index( vnum ) )
	    && pRoom->area == pArea )
	    write_next_item( fp, "Room", pRoom );
    }

    fprintf( fp, "\n\n" );

    return;
}


/*****************************************************************************
 Name:		save_helps
 Purpose:	Save #HELPS section of an area file.
 Written by:	Walker <nkrendel@evans.Denver.Colorado.EDU>
 Called by:	save_area( olc_save.c ).
 ****************************************************************************/
void save_helps( FILE * fp, AREA_DATA * pArea )
{
    HELP_DATA *pHelp;

    for( pHelp = help_first; pHelp; pHelp = pHelp->next )
    {
	if( pHelp->area != pArea )
	    continue;

	write_next_item( fp, "Help", pHelp );
    }

    fprintf( fp, "\n\n" );

    return;
}


/*****************************************************************************
 Name:		save_area
 Purpose:	Save an area, note that this format is new.
 Called by:	do_asave( olc_save.c ).
 ****************************************************************************/
void save_area( AREA_DATA *pArea )
{
    FILE *fp;
    char buf[MAX_INPUT_LENGTH];

    if( IS_SET( pArea->area_flags, AREA_DELETED )
	|| IS_SET( pArea->area_flags, AREA_NOSAVE ) )
	return;

    sprintf( buf, "%s%s", AREA_DIR, pArea->filename );
    if( !( fp = open_file( buf, "w", TRUE ) ) )
    {
	bug( "Open_area: open_file" );
	perror( buf );
    }

    write_next_item( fp, "Area", pArea );
    fprintf( fp, "\n\n" );

    save_helps( fp, pArea );
    save_area_mudprogs( fp, pArea );
    save_mobiles( fp, pArea );
    save_objects( fp, pArea );
    save_rooms( fp, pArea );

    fprintf( fp, "\neof\n\n" );

    close_file( fp );
    return;
}


/* OLC 1.1b */
/*****************************************************************************
  Name:		do_asave
  Purpose:	Entry point for saving area data.
  Called by:	interpreter( interp.c )
  ****************************************************************************/
void do_asave( CHAR_DATA *ch, const char *argument )
{
    char arg1[MAX_INPUT_LENGTH];
    AREA_DATA *pArea;
    int value;
    CHAR_DATA *rch;

    if( !ch )			/* Do an autosave */
    {
	log_string( "ASave: automatic save of areas." );
	send_to_all_char( "&bA gentle breeze comes from the east.&n\n\r" );

	/* Turn of the CPU time alarm for this function. */
	SET_BIT( SysInfo->flags, SYSINFO_NOCPULIMIT );

	save_area_list( );
	for( pArea = area_first; pArea; pArea = pArea->next )
	{
	    if( IS_SET( SysInfo->flags, SYSINFO_SAVEALL )
		|| IS_SET( pArea->area_flags, AREA_CHANGED | AREA_ADDED ) )
		save_area( pArea );
	    REMOVE_BIT( pArea->area_flags, AREA_CHANGED | AREA_ADDED );
	}

	REMOVE_BIT( SysInfo->flags, SYSINFO_NOCPULIMIT );

	send_to_all_char( "&bAfter the breeze all seems calm.&n\n\r" );

	return;
    }

    rch = get_char( ch );

    if( !authorized( rch, "asave" ) )
	return;

    argument = one_argument( argument, arg1 );

    if( arg1[0] == '\0' )
    {
	send_to_char( "Syntax:\n\r"
		      "	 asave <vnum>    - saves a particular area\n\r"
		      "	 asave list      - saves the AREA.LST file\n\r"
		      "	 asave area      - saves the area being edited\n\r"
		      "	 asave changed   - saves all changed zones\n\r"
		      "	 asave world     - saves the world! (db dump)\n\r"
		      "	 asave ^ verbose - saves in verbose mode\n\r"
		      "\n\r", ch );
	return;
    }

    /* Snarf the value ( which need not be numeric ). */
    value = atoi( arg1 );

    /* Save the area of given vnum. */
    /* ---------------------------- */

    if( !( pArea = get_area_data( value ) ) && is_number( arg1 ) )
    {
	send_to_char( "That area does not exist.\n\r", ch );
	return;
    }

    if( is_number( arg1 ) )
    {
	if( !IS_BUILDER( ch, pArea ) )
	{
	    send_to_char( "You are not a builder for this area.\n\r", ch );
	    return;
	}
	if( IS_SET( pArea->area_flags, AREA_DELETED )
	    || IS_SET( pArea->area_flags, AREA_DELETED ) )
	{
	    send_to_char( "Check the area flags for this area first.\n\r", ch );
	    send_to_char( "It may be tagged for deletion of be finished.\n\r", ch );
	    return;
	}

	save_area_list( );
	if( !str_cmp( "verbose", argument ) )
	    SET_BIT( pArea->area_flags, AREA_VERBOSE );
	save_area( pArea );
	REMOVE_BIT( pArea->area_flags, AREA_VERBOSE );
	return;
    }

    /* Save the world, only authorized areas. */
    /* -------------------------------------- */

    if( !str_cmp( "world", arg1 ) )
    {
	log_string( "ASave: %s saving the world.", ch->name );

	/* Turn of the CPU time alarm for this function. */
	SET_BIT( SysInfo->flags, SYSINFO_NOCPULIMIT );

	save_area_list( );
	for( pArea = area_first; pArea; pArea = pArea->next )
	{
	    /* Builder must be assigned this area. */
	    if( !IS_BUILDER( ch, pArea ) )
		continue;

	    if( !str_cmp( "verbose", argument ) )
		SET_BIT( pArea->area_flags, AREA_VERBOSE );
	    save_area( pArea );
	    REMOVE_BIT( pArea->area_flags,
			AREA_CHANGED|AREA_ADDED|AREA_VERBOSE );
	}

	REMOVE_BIT( SysInfo->flags, SYSINFO_NOCPULIMIT );

	send_to_char( "You saved the world.\n\r", ch );
	return;
    }

    /* Save changed areas, only authorized areas. */
    /* ------------------------------------------ */

    if( !str_cmp( "changed", arg1 ) )
    {
	char buf[MAX_INPUT_LENGTH];

	/* Turn of the CPU time alarm for this function. */
	SET_BIT( SysInfo->flags, SYSINFO_NOCPULIMIT );

	save_area_list( );

	send_to_char( "Saved zones:\n\r", ch );
	sprintf( buf, "None.\n\r" );

	for( pArea = area_first; pArea; pArea = pArea->next )
	{
	    /* Builder must be assigned this area. */
	    if( !IS_BUILDER( ch, pArea ) )
		continue;

	    /* Save changed areas. */
	    if( IS_SET( pArea->area_flags, AREA_CHANGED )
		|| IS_SET( pArea->area_flags, AREA_ADDED ) )
	    {
		if( !str_cmp( "verbose", argument ) )
		    SET_BIT( pArea->area_flags, AREA_VERBOSE );
		save_area( pArea );
		REMOVE_BIT( pArea->area_flags, AREA_CHANGED | AREA_ADDED
			    | AREA_VERBOSE );
		sprintf( buf, "%24s&n - '%s'%s%s\n\r",
			 pArea->name, pArea->filename,
			 IS_SET( pArea->area_flags, AREA_DELETED )
			 ? " [deleted]" : "",
			 IS_SET( pArea->area_flags, AREA_NOSAVE )
			 ? " [finished]" : "" );
		send_to_char( buf, ch );
	    }
	}
	if( !str_cmp( buf, "None.\n\r" ) )
	    send_to_char( buf, ch );

	REMOVE_BIT( SysInfo->flags, SYSINFO_NOCPULIMIT );

	return;
    }

    /* Save the AREA.LST file. */
    /* ----------------------- */
    if( !str_cmp( arg1, "list" ) )
    {
	save_area_list( );
	return;
    }

    /* Save area being edited, if authorized. */
    /* -------------------------------------- */
    if( !str_cmp( arg1, "area" ) )
    {
	pArea = get_editing_area( ch );

	if( !IS_BUILDER( ch, pArea ) )
	{
	    send_to_char( "You are not a builder for this area.\n\r", ch );
	    return;
	}
	if( IS_SET( pArea->area_flags, AREA_DELETED )
	    || IS_SET( pArea->area_flags, AREA_NOSAVE ) )
	{
	    send_to_char( "Check the area flags for this area first.\n\r", ch );
	    send_to_char( "It may be tagged for deletion or be finished.\n\r", ch );
	    return;
	}

	save_area_list( );
	if( !str_cmp( "verbose", argument ) )
	    SET_BIT( pArea->area_flags, AREA_VERBOSE );
	save_area( pArea );
	REMOVE_BIT( pArea->area_flags, AREA_CHANGED|AREA_ADDED|AREA_VERBOSE );
	send_to_char( "Area saved.\n\r", ch );
	return;
    }

    /* Show correct syntax. */
    /* -------------------- */
    do_asave( ch, "" );
    return;
}