#include <string>
#include <iostream>
#include <fstream>
#include <time.h>
#include <process.h> #include <cstdio>
#include <signal.h>
#include <list>
#include "stringutil.h"
#include "world.h"
#include "timestamp.h"
#include "log.h"
using namespace std;
bool InitStrHash();
void World::Exist( const string &startMessage, int port, bool copyover )
{
string buf;
if ( copyover == false )
SocketServer::Instance().Start();
else
CopyoverRecovery();
if ( !InitStrHash() )
{
glog( "Failed to initialize string hashing table! Aborting..." );
abort();
}
if ( !LoadRooms() )
{
glog("Failed to load rooms! Aborting..." );
abort();
}
if ( !LoadHelps() )
{
glog("Failed to load help files! Aborting..." );
abort();
}
buf << "\n\t" << startMessage << " on port " << port;
buf << "\n\tTime: " << Timestamp::Instance().GetDateTime();
cout << buf << endl << endl;
_worldExists = true; while( _worldExists )
Monitor();
cout << "Shutdown successfully." << endl;
return;
}
bool World::LoadRooms( )
{
Mysql::LMAP::iterator room_info;
string query = "SELECT room_id FROM room";
unsigned int i = 0;
if ( !Mysql::Instance().Load( query.c_str() ) )
return false;
Mysql::RESULT z = Mysql::Instance()._info;
cout << "\n\nLoading Rooms...";
for ( int x = 0; x < z.size(); x++ )
{
i++;
room_info = z[x].find("room_id");
new Room( (unsigned int)atoi((room_info->second).c_str()));
}
cout << " Done.\n";
cout << i << " rooms loaded.\n\n";
cout << "\nLinking exits...";
for ( RoomMap::const_iterator x = World::Instance()._room_map.begin(); x != World::Instance()._room_map.end(); x++ )
x->second->InterpExitStr(x->second->Get("exit_str"));
cout << " Done.\n\n";
return true;
}
bool World::LoadHelps( )
{
Mysql::LMAP::iterator help_info;
string query = "SELECT name FROM help";
unsigned int i = 0;
if ( !Mysql::Instance().Load( query.c_str() ) )
return false;
Mysql::RESULT z = Mysql::Instance()._info;
cout << "\n\nLoading helps...";
for ( int x = 0; x < z.size(); x++ )
{
i++;
help_info = z[x].find("name");
new Help( help_info->second );
}
cout << " Done.\n";
cout << i << " help files loaded.\n\n";
return true;
}
Help * World::FindHelp( const string &target )
{
HelpMap::const_iterator r = World::Instance()._help_map.find(target);
if (r == World::Instance()._help_map.end())
return NULL;
return r->second;
}
Room * World::FindRoom( const string &target )
{
RoomMap::const_iterator r = World::Instance()._room_map.find(target);
if (r == World::Instance()._room_map.end())
{
return NULL;
}
return r->second;
}
void World::Copyover( )
{
list< Avatar *>::iterator a_it;
Avatar * dead;
ofstream fp("file.cpy");
if ( !fp ) {
cout << "Copyover file could not be opened." << endl;
return;
}
for ( a_it = _avatarList.begin(); a_it != _avatarList.end(); ) {
if ( (*a_it)->GetStatus() != CONNECTED ) {
dead = (*a_it);
a_it = _avatarList.erase( a_it );
delete dead;
continue;
}
(*a_it)->Save();
fp << (*a_it)->GetSocket()->GetDescriptor() << " " <<
(*a_it)->Get( "name" ) << " " <<
(*a_it)->GetSocket()->GetSocketIP() << endl;
a_it++;
}
fp << "-1";
fp.close();
string controlSock;
controlSock << SocketServer::Instance().GetHostSocket();
_execl("./scratch", "3000", "-copyover", controlSock.c_str(), NULL );
}
void World::CopyoverRecovery( )
{
Avatar * avatar;
ifstream fp("file.cpy");
int desc;
std::string name;
std::string host;
std::string lhost;
if ( !fp ) {
cout << "Copyover file could not be opened." << endl;
exit(1);
}
for(;;) {
fp >> desc >> name >> host;
if (desc == -1)
break;
avatar = new Avatar;
avatar->GetSocket()->SetDescriptor( desc );
avatar->GetSocket()->SetSocketIP( string(host) );
avatar->Set( "name", name );
avatar->Load();
avatar->SetStatus( CONNECTED );
SocketServer::Instance()._socketList.push_back( avatar->GetSocket() );
_avatarList.push_back( avatar );
avatar->Send( "Reboot Successful.\n\r" );
avatar->StackHandler( new InputHandler );
}
fp.close();
remove( "file.cpy" ); cout << "Copyover Recovery is now Complete." << endl;
}
Avatar * World::FindAvatar( const string &target )
{
list< Avatar * >::iterator it;
for ( it = _avatarList.begin(); it != _avatarList.end(); ++it ) {
if ( str_cmp( (*it)->Get( "name" ), target ) )
return (*it);
}
return NULL;
}
void World::Broadcast( const string &message, BROADCAST_TYPE type ) {
list< Avatar * >::iterator avatar;
if ( type == ALL )
{
for ( avatar = _avatarList.begin(); avatar != _avatarList.end(); ++avatar )
(*avatar)->Send( message );
}
else if ( type == WCONNECTED )
{
for ( avatar = _avatarList.begin(); avatar != _avatarList.end(); ++avatar )
{
if ( (*avatar)->GetStatus() == CONNECTED )
(*avatar)->Send( message );
}
}
}
void World::Die( )
{
_worldExists = false;
}
void World::Monitor( )
{
bool newConnection = false;
FlushOutput();
if ( ( newConnection = SocketServer::Instance().Monitor() ) == true )
{
Avatar * avatar = new Avatar;
avatar->SetSocket( SocketServer::Instance()._socketList.back() );
_avatarList.push_back( avatar );
avatar->StackHandler( new GetNameHandler );
newConnection = false;
avatar->Send( " ============================================= \n\r" );
avatar->Send( " === {WKaladea MUD{x === \n\r" );
avatar->Send( " ============================================= \n\r\n\r" );
avatar->Send( " {RIn Early Development.{x\n\r" );
avatar->Send( " {W- Odis -{x\n\r\n\r" );
}
UpdateTimers();
UpdateAvatars();
HandleInput();
}
void World::FlushOutput( ) {
list< Avatar * >::iterator avatar;
for ( avatar = _avatarList.begin(); avatar != _avatarList.end(); ++avatar ) {
(*avatar)->FlushOutput();
}
}
void World::UpdateAvatars( )
{
list< Avatar * >::iterator avatar;
for ( avatar = _avatarList.begin(); avatar != _avatarList.end(); ++avatar )
{
if ( (*avatar)->GetSocket()->GotInput() == true )
(*avatar)->SetGotInput( true );
if ( (*avatar)->GetSocket()->IsDisconnected() )
(*avatar)->SetDisconnected( true );
}
KillFlaggedAvatars();
}
void World::KillFlaggedAvatars( )
{
list< Avatar * >::iterator avatar;
Avatar * avatar2;
for ( avatar = _avatarList.begin(); avatar != _avatarList.end(); )
{
avatar2 = (*avatar);
if ( avatar2->IsDisconnected() )
{
avatar = _avatarList.erase( avatar );
delete avatar2;
}
else
++avatar;
}
}
void World::HandleInput( )
{
std::list< Avatar * >::iterator avatar;
if ( _avatarList.empty() != true )
{
for ( avatar = _avatarList.begin(); avatar != _avatarList.end(); ++avatar )
{
if ( (*avatar)->GotInput() == true ) {
(*avatar)->HandleInput( (*avatar)->GetSocket()->GetInput() ); (*avatar)->GetSocket()->FlushInput( ); }
}
}
UpdateAvatars();
}
void World::UpdateTimers ()
{
if ( _timers.empty() )
return;
time_t now = time(NULL);
Timer *timer;
for ( timer = _timers.top(); timer->When() <= now; timer = _timers.top() ) {
_timers.pop();
if ( !timer->_enabled || !timer->Fire() ) {
delete timer;
if ( _timers.empty() )
break;
} else {
_timers.push( timer );
}
}
}
void World::Schedule( Timer *timer ) {
_timers.push( timer );
}
void World::Unschedule( Timer *timer ) {
timer->_enabled = false;
}