player/a/
player/b/
player/c/
player/d/
player/e/
player/f/
player/g/
player/i/
player/j/
player/k/
player/m/
player/n/
player/r/
player/s/
player/v/
player/w/
player/x/
player/z/
player_fst/e/
player_fst/f/
player_fst/h/
player_fst/i/
player_fst/j/
player_fst/n/
player_fst/o/
player_fst/p/
player_fst/player/a/
player_fst/player/b/
player_fst/player/c/
player_fst/player/d/
player_fst/player/e/
player_fst/player/f/
player_fst/player/g/
player_fst/player/j/
player_fst/player/k/
player_fst/player/m/
player_fst/player/n/
player_fst/player/r/
player_fst/player/s/
player_fst/player/v/
player_fst/player/w/
player_fst/player/x/
player_fst/player/z/
player_fst/u/
player_fst/v/
player_fst/w/
player_fst/x/
/*~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
 ~  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        ~
 ~  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   ~
 ~                                                                         ~
 ~  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          ~
 ~  Chastain, Michael Quan, and Mitchell Tse.                              ~
 ~                                                                         ~
 ~  Ack 2.2 improvements copyright (C) 1994 by Stephen Dooley              ~
 ~  ACK!MUD is modified Merc2.0/2.1/2.2 code (c)Stephen Zepp 1998 Ver: 4.3 ~
 ~                                                                         ~
 ~  In order to use any part of this  PA  Diku Mud, you must comply with   ~
 ~  both the original Diku license in 'license.doc' as well the Merc       ~
 ~  license in 'license.txt', and the Ack!Mud license in 'ack_license.txt'.~
 ~  In particular, you may not remove any of these copyright notices.      ~
 ~                                                                         ~
 ~           _______      _____                                            ~
 ~          /  __  /\    / ___ \       222222        PA_MUD by Amnon Kruvi ~
 ~         /______/ /   / /___\ \            2       PA_MUD is modified    ~
 ~        / _______/   / _______ \           2       Ack!Mud, v4.3         ~
 ~       /_/          /_/       \_\        2                               ~
 ~                                      2                                  ~
 ~                                     2222222                             ~
 ~                                                                         ~
 ~                                                                         ~
 ~   Years of work have been invested to create DIKU, Merc, Ack and PA.    ~
 ~   Please show your respect by following the licenses, and issuing       ~
 ~   credits where due.                                                    ~
 ~                                                                         ~
 ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-*/

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ack.h"



/* Way this works:
	Mud reads in area files, stores details in data lists.
	Edit rooms, objects, resets.
	type savearea.
	Sets bool saving_area to true.
	Incrementally saves an area, using data lists.
*/
	

#define SAVEQUEUESIZE 50
#define NOT_SAVING 0
#define START_SAVING 1
#define AM_SAVING 2
#define BUILD_OK -1
#define BUILD_CANTSAVE 1
#define BUILD_TOOMANY  2

#define BUILD_SEC_AREA     1 
#define BUILD_SEC_HELP     2
#define BUILD_SEC_ROOMS    3
#define BUILD_SEC_OBJECTS  4
#define BUILD_SEC_END      5
#define AREA_VERSION  20


struct save_queue_type
{
   AREA_DATA * area;
   CHAR_DATA * ch;
   int         loops;
} SaveQ[SAVEQUEUESIZE];

/* Semi-local vars. */
int saving_area=0;

/* local */
int 		offset;
int             ToBeSaved=0;
int             CurrentSaving=-1;
AREA_DATA     * CurSaveArea=NULL;
CHAR_DATA     * CurSaveChar=NULL;
int             CurLoops=1;
int             Section;
BUILD_DATA_LIST * Pointer;
FILE          * SaveFile;
FILE	      * Envy;
int             AreasModified=0;

/* Local functions */
/* void build_save(); proto in merc.h */
void build_save_area(void);
void build_save_help(void);
void build_save_mobs(void);
void build_save_mobprogs(void);
void build_save_objects(void);
void build_save_rooms(void);
void build_save_resets(void);
void build_save_objfuns(void);
void build_save_end(void);
char * mprog_type_to_name(int);
void vuild_save_flush(void);
/*  int convert(int lev); */
/* Convert levels from ack -> envy! */

/* int  convert(int lev)	*/
/*  { 		*/
/*   return( lev - ( lev/5 ) ); 	*/
/* }   */   
   
void do_savearea( CHAR_DATA *ch, char *argument )
{
     AREA_DATA * SaveArea;
     int loops;
/*     char first_arg[MAX_INPUT_LENGTH]; unused? */
     

     if (ch==NULL)
     {
       SaveArea=(AREA_DATA *) argument;   
       loops=10;
     }
     else
     {      
      if (ch->in_room==NULL)
       {
        send_to_char("Do not know what room you are in!!, cannot save.\n",ch);
        return;
       }
       
      SaveArea=(ch->in_room)->area;
      if (SaveArea==NULL)
       {
        send_to_char("Do not know what area you are in!!, cannot save.\n",ch);
        return;
       }
      
      if (*argument != '\0')
       {
        loops=atoi(argument);
        if (loops<1)
 	loops=1;
       }
      else
       loops=1;
     }

     if (ToBeSaved==CurrentSaving)
       {
	 send_to_char("Too many areas in queue, please try later.\n",ch);
	 return; 
       }
       
     SaveQ[ToBeSaved].area=SaveArea;
     SaveQ[ToBeSaved].ch=ch;
     SaveQ[ToBeSaved].loops=loops;
     ToBeSaved=(ToBeSaved + 1) % SAVEQUEUESIZE;

     if (saving_area==NOT_SAVING)
      saving_area=START_SAVING;
     else
      send_to_char("Save is queued, please wait. \n",ch);
     
     build_save();
     return;
}

void build_save()
{
  int a;
  char filename[255];
  char buf[MAX_STRING_LENGTH];
  
  for (a=0;a<CurLoops && saving_area>0;a++)
  { 

   if ( saving_area== START_SAVING)
     {
       CurrentSaving=(CurrentSaving+1) % SAVEQUEUESIZE;
       CurSaveArea=SaveQ[CurrentSaving].area;
       CurSaveChar=SaveQ[CurrentSaving].ch;
       CurLoops=SaveQ[CurrentSaving].loops;
       send_to_char("Starting Save.\n",CurSaveChar);
       
       sprintf(filename,"%s.new",CurSaveArea->filename);
       SaveFile=fopen(filename,"w");
       if (SaveFile==NULL)
	{
	 if (CurrentSaving==ToBeSaved)
	  saving_area=NOT_SAVING;
	 send_to_char("Can not open file for saving.\n",CurSaveChar);
	 return;
	}
	/* Open second file for saving in envy format */
	
       sprintf( buf, "Starting to save %s", CurSaveArea->filename );
       monitor_chan( NULL, buf, MONITOR_AREA_SAVING );
	
	
	Section=1;
	offset=CurSaveArea->offset;
	saving_area=AM_SAVING;
	Pointer=NULL;
      }

    switch (Section)
     {
       case BUILD_SEC_AREA:     build_save_area();     break;
       case BUILD_SEC_HELP:     build_save_help();     break;
       case BUILD_SEC_ROOMS:    build_save_rooms();    break;
       case BUILD_SEC_OBJECTS:  build_save_objects();  break;
       case BUILD_SEC_END:      build_save_end();      break;
     }
   }
   return;
}

	    

void build_save_area()
{
     fprintf(SaveFile,"#AREA\n");
     fprintf(SaveFile,"%s~\n",CurSaveArea->name);
     fprintf( SaveFile,"Q %i\n", AREA_VERSION );
     fprintf(SaveFile,"K %s~\n",CurSaveArea->keyword);
     fprintf(SaveFile,"N %i\n",CurSaveArea->area_num);
     fprintf(SaveFile,"V %i %i\n",CurSaveArea->min_vnum,CurSaveArea->max_vnum);
     fprintf(SaveFile,"X %i\n", CurSaveArea->offset );
     if (CurSaveArea->owner != NULL)
        fprintf(SaveFile,"O %s~\n",CurSaveArea->owner);
     if (CurSaveArea->can_read != NULL)
        fprintf(SaveFile,"R %s~\n",CurSaveArea->can_read);
     if (CurSaveArea->can_write != NULL)
        fprintf(SaveFile,"W %s~\n",CurSaveArea->can_write);
     
/*     fprintf( Envy, "#AREA\n" );                      remove save bug */
/*     fprintf( Envy, "%s~\n", CurSaveArea->name );                     */
      
     Section++;
}

void build_save_help()
{
     HELP_DATA *pHelp;

     if (Pointer==NULL) /* Start */
     {
      if (CurSaveArea->first_area_help_text==NULL)
       {
	Section++;
	return;
       }
      send_to_char("Saving help section.\n",CurSaveChar);
      fprintf(SaveFile,"#HELPS\n");
      Pointer=CurSaveArea->first_area_help_text;
     }

     pHelp=Pointer->data;
     fprintf(SaveFile,"%i %s~\n",pHelp->level,pHelp->keyword);
     if (isspace(pHelp->text[0]))
      fprintf(SaveFile,".%s~\n",pHelp->text);
     else
      fprintf(SaveFile,"%s~\n",pHelp->text);

     Pointer=Pointer->next;
     if (Pointer==NULL) /* End */
      {
       fprintf(SaveFile,"0 $~\n");
       Section++;
      }
     /* No saving helps for envy format */
     
     return;
}

void build_save_objects()
{
     OBJ_INDEX_DATA *pObject;
//     int val0,val1,val2,val3;
     int i;

     if (Pointer==NULL)  /* Start */
      {
       if (CurSaveArea->first_area_object==NULL)
	{
	 Section++;
	 return;
	}
       send_to_char("Saving objects.\n",CurSaveChar);
       fprintf(SaveFile,"#OBJECTS\n");
       Pointer=CurSaveArea->first_area_object;
      }

     pObject=Pointer->data;
     
     fprintf(SaveFile,"#%i\n",pObject->vnum);
     fprintf(SaveFile,"%s~\n",pObject->name);
     fprintf(SaveFile,"%s~\n",pObject->short_descr);
     fprintf(SaveFile,"%s~\n",pObject->description);
     fprintf(SaveFile,"%i %i %i\n",pObject->item_type,pObject->extra_flags,
					pObject->wear_flags);

     for ( i=0;i<MAX_OBJECT_VALUES;i++ )
	fprintf(SaveFile,"%i ", pObject->value[i]);
/*     fprintf(SaveFile,"%i %i %i %i %i %i %i %i %i %i\n",val0,val1,val2,val3,
     pObject->value[4], pObject->value[5],pObject->value[6],pObject->value[7],
     pObject->value[8],pObject->value[9]); */
     fprintf(SaveFile,"%i %i %i %ld\n",pObject->weight,pObject->heat,pObject->building,pObject->cost);
     fprintf(SaveFile,"%s~\n",pObject->image);
     
     
       if ( ( pObject->level > 1 ) && (pObject->level < 130 ) )
       {
         fprintf(SaveFile, "L\n");
         fprintf(SaveFile,"%d\n",pObject->level);
       }
       else
       {
         fprintf(SaveFile, "L\n");
         fprintf(SaveFile,"%d\n", 1);
       }

      /* Now for Envy... taken from my OLC :P */

     Pointer=Pointer->next;
     if (Pointer==NULL) /* End */
      {
       fprintf(SaveFile,"#0\n");
       Section++;
      }
     
     return;
}
     
void build_save_rooms()
{
     ROOM_INDEX_DATA *pRoomIndex;

     if (Pointer==NULL)  /* Start */
      {
       if (CurSaveArea->first_area_room==NULL)
	{
	 Section++;
	 return;
	}
       send_to_char("Saving rooms.\n",CurSaveChar);
       fprintf(SaveFile,"#ROOMS\n");
       Pointer=CurSaveArea->first_area_room;
      }

     pRoomIndex=Pointer->data;
     
     fprintf(SaveFile,"#%i\n",pRoomIndex->vnum);

     /* End of one room */
     fprintf(SaveFile,"S\n");

     Pointer=Pointer->next;
     if (Pointer==NULL) /* End */
      {
       fprintf(SaveFile,"#0\n");
       Section++;
      }
      return;
}
     
void build_save_end()
{
     char filename[255];
     char buf[MAX_STRING_LENGTH];

     sprintf( buf, "Finished saving %s", CurSaveArea->filename );
     monitor_chan( NULL, buf, MONITOR_AREA_SAVING );
     
     fprintf(SaveFile,"#$\n");
     send_to_char("Finished saving.\n",CurSaveChar);
     fclose(SaveFile);
     /* Save backup */
     sprintf(filename,"%s.old",CurSaveArea->filename);
     rename(CurSaveArea->filename,filename);
     /* And rename .new to area filename */
     sprintf(filename,"%s.new",CurSaveArea->filename);
     rename(filename,CurSaveArea->filename);
     
     Section=0;
     if (ToBeSaved==(CurrentSaving+1) % SAVEQUEUESIZE)
       saving_area=NOT_SAVING;
     else
       saving_area=START_SAVING;
}

     
void build_save_flush()
{
    AREA_DATA * pArea;
    
    if (AreasModified == 0)
     return;
    
    for (pArea=first_area; pArea != NULL; pArea=pArea->next)
    {
     if (pArea->modified)
      {
       pArea->modified=0;
       do_savearea(NULL,(char *) pArea);
      }
    }
    
    AreasModified=0;
}

void area_modified(AREA_DATA * pArea)
{
   pArea->modified=1;
   AreasModified=1;
}