mud++0.35/etc/
mud++0.35/etc/guilds/
mud++0.35/help/propert/
mud++0.35/mudC/
mud++0.35/player/
mud++0.35/src/interface/
mud++0.35/src/os/cygwin32/
mud++0.35/src/os/win32/
mud++0.35/src/os/win32/bcppbuilder/
mud++0.35/src/osaddon/
mud++0.35/src/util/
/*
....[@@@..[@@@..............[@.................. MUD++ is a written from
....[@..[@..[@..[@..[@..[@@@@@....[@......[@.... scratch multi-user swords and
....[@..[@..[@..[@..[@..[@..[@..[@@@@@..[@@@@@.. sorcery game written in C++.
....[@......[@..[@..[@..[@..[@....[@......[@.... This server is an ongoing
....[@......[@..[@@@@@..[@@@@@.................. development project.  All 
................................................ contributions are welcome. 
....Copyright(C).1995.Melvin.Smith.............. Enjoy. 
------------------------------------------------------------------------------
Melvin Smith (aka Fusion)         msmith@hom.net 
MUD++ development mailing list    mudpp@van.ml.org
------------------------------------------------------------------------------
editarea.cc
*/

#include "config.h"
#include "string.h"
#include "llist.h"
#include "index.h"
#include "room.h"
#include "hash.h"
#include "area.h"
#include "bit.h"
#include "edit.h"
#include "pc.h"

#include "global.h"

int saveAreaList()
{
	Area *area;
	OutputFile out( "../area/area.lst" );
	if( !out )
		return -1;

	areas.reset();
	while( ( area = areas.peek() ) )
	{
		areas.next();
		out << area->getFile() << endl;		
	}

	out.close();
	return 0;
}


void AreaEditor::command( const String & arg )
{
	Area *checkArea;
	Room *room;
	LList<PC> pcIterate;
	LList<Area> areaIterate;
	String str;
	String arg1;
	String arg2;

	arg.startArgs();
	arg1 = arg.getArg();
	arg2 = arg.getArgRest(); // remainder

	if( !(bool)arg1 || arg1[0] == '\n' )
	{
		str << "\n\r"
			<< "Name: "		<< area->getName() << "\n\r"
			<< "Index: "	<< area->getKey() << "\n\r"
			<< "File: "		<< area->getFile() << "\n\r"
			<< "Security: "	<< area->getSecurity() << "\n\r"
			<< "Builder: "	<< area->getBuilder() << "\n\r"
			<< "Repop: "	<< area->getRepopMessg() << "\n\r"
			<< "MinMax: "	<< area->getMinLevel() << " "
							<< area->getMaxLevel() << "\n\r"
			<< "Title: "	<< area->getTitle() << "\n\r"
			<< "\n\r";
		pc->out( str );	
		return;
	}
	else if( arg1 == "reload" || arg1 == "reboot" )
	{
		// There will probably be a problem with someone reloading
		// an area after an index change but before a save.
		// Clean it up later.

		// Check for players in the area.
		PC *ch;
		bool save = false;
		pcIterate = pcs;
		pcIterate.reset();
		while( ( ch = pcIterate.peek() ) )
		{
			pcIterate.next();
			if( ch->inRoom()->getArea() == area )
			{
				if( ch == pc )
				{
					save = true;
					continue;
				}
				pc->out( "Can't reload area. There are players in the zone.\n\r" );
				return;
			}
		}

		String wasIn;
		if( save )
		{
			wasIn = pc->inRoom()->getKey();
			pc->inRoom()->rmCharInv( pc ); 
		}

		area->reload();
		if( save )
		{
			if( !( room = area->lookupRoom( wasIn ) ) )
			{
				pc->out( "Yipes! The room you were in was not reloaded!\n\r" );
				if( !( room = getFirstRoom() ) )
				{
					Cout << "Area reload: no rooms loaded. EeeeK!\n";
					mudpp_exit(0);
				}
			}
			room->addCharInv( pc );			
		}

		pc->out( "Area reloaded from disk.\n\r" );

		Area *pArea;
		areaIterate = areas;
		areaIterate.reset();
		while( ( pArea = areaIterate.peek() ) )
		{
			areaIterate.next();
			pArea->hardLink();
		}
		pc->out( "World relinked.\n\r" );
		return;
	}
	else if( arg1.isAbbrev( "save" ) )
	{
		if( !area->getDirtyBit() )
		{
			pc->out( "No modifications since last save.\n\r" );
			return;
		}

		if( !(bool)area->getKey() )
		{
			pc->out( "This area needs an index key first.\n\r" );
			return;
		}

		area->save();
		pc->out( "Area saved.\n\r" );
		area->rmDirtyBit();
		return;
	}
	else if( arg1 == "rooms" )
	{
		Room * pRoom;
		for_each( area->roomIndex, pRoom )
			str.sprintfAdd( "%15s - %s\n\r", pRoom->getKey().chars(),
										pRoom->getName().chars() );
		pc->out( str );
		return;
	}
	else if( arg1 == "npcs" || arg1 == "mobs" )
	{
		NPC * pNPC;
		for_each( area->npcIndex, pNPC )
			str.sprintfAdd( "%15s - %s\n\r", area->npcIndex.getKey().chars(),
										pNPC->getShort().chars() );
		pc->out( str );
		return;
	}
	else if( arg1 == "objs" || arg1 == "objects" )
	{
		Object * pObj;
		for_each( area->objIndex, pObj )
			str.sprintfAdd( "%15s - %s\n\r", area->objIndex.getKey().chars(),
										pObj->getShort().chars() );
		pc->out( str );
		return;
	}
	else if( arg1 == "help" || arg1 == "?" )
	{
		pc->view( "../help/aedit.hlp" );
		pc->page( "" );
		return;
	}

	if( !(bool)arg2 )
	{
		pc->out( "Invalid argument.\n\r" );
		return;
	}

	if( arg1.isAbbrev( "index" ) )
	{
		if( ( checkArea = lookupArea( arg2 ) )
			&& checkArea != area )
		{
			pc->out( "There is already an area with that index.\n\r" );
			return;
		}

		area->setKey( arg2 );
		arg2 += ".are";
		area->setFile( arg2 );
		pc->out( "Area index key set.\n\r" );
		pc->out( "Filename is now : " );
		pc->out( area->getFile() );
		pc->out( "\n\r" );

		// Save new area.lst
		if( saveAreaList() != -1 )
			pc->out( "New 'area.lst' saved.\n\r" );
		else
			pc->out( "There was an error writing 'area.lst'\n\r" );
		area->save();
		return;
	}
	else if( arg1.isAbbrev( "name" ) )
	{
		area->setName( arg2 );
		pc->out( "Area name set.\n\r" );
	}
	else if( arg1.isAbbrev( "repop" ) )
	{
		str.clr();
		str << "\n\r" << arg2 << "\n\r";
		area->setRepopMessg( str );
		pc->out( "Repop string set.\n\r" );
	}
	else if( arg1.isAbbrev( "title" ) )
	{
		area->setTitle( arg2 );
		pc->out( "Area title set.\n\r" );
	}
	else if( arg1.isAbbrev( "minlevel" ) )
	{
		area->setMinLevel( arg2.asInt() );
		pc->out( "Minlevel set.\n\r" );
	}
	else if( arg1.isAbbrev( "maxlevel" ) )
	{
		area->setMaxLevel( arg2.asInt() );
		pc->out( "Maxlevel set.\n\r" );
	}
	else if( arg1.isAbbrev( "builder" ) )
	{
		area->setBuilder( arg2 );
		pc->out( "Builder set.\n\r" );
	}
	else
	{
		pc->out( "Invalid command.\n\r" );
		return;
	}

	area->setDirtyBit();
}