mojo_client/src/Client/PseuWoW.cpp
False.Genesis 6c4ae79a87 * rewrote the realm/world login code.
-> reconnecting does work now, finally.
* updated conf setting: reconnect=0: dont reconnect; reconnect=X: reconnect after X msecs.
* misc code cleanups, crash fixes, and overall improved stability.
* splitted RealmSocket into a RealmSession and the original RealmSocket code. better read-/useabilty because now its handled as WorldSession and related.
2007-05-11 20:55:38 +00:00

373 lines
9.5 KiB
C++

#include "common.h"
#include "PseuWoW.h"
#include <time.h>
#include <openssl/rand.h>
#include "ByteBuffer.h"
#include "DefScript/DefScript.h"
#include "DefScriptInterface.h"
#include "Auth/BigNumber.h"
#include "DefScript/DefScript.h"
#include "RealmSession.h"
#include "WorldSession.h"
#include "CacheHandler.h"
#include "GUI/PseuGUI.h"
#include "Cli.h"
//###### Start of program code #######
PseuInstanceRunnable::PseuInstanceRunnable()
{
}
void PseuInstanceRunnable::run(void)
{
_i = new PseuInstance(this);
_i->SetConfDir("./conf/");
_i->SetScpDir("./scripts/");
if(_i->Init())
{
_i->Run();
}
else
{
getchar();
}
delete _i;
}
void PseuInstanceRunnable::sleep(uint32 msecs)
{
ZThread::Thread::sleep(msecs);
}
PseuInstance::PseuInstance(PseuInstanceRunnable *run)
{
_runnable=run;
_ver="PseuWoW Alpha Build 13" DEBUG_APPENDIX;
_ver_short="A13" DEBUG_APPENDIX;
_wsession=NULL;
_rsession=NULL;
_scp=NULL;
_conf=NULL;
_cli=NULL;
_stop=false;
_fastquit=false;
_startrealm=true;
_createws=false;
_error=false;
_initialized=false;
}
PseuInstance::~PseuInstance()
{
if(_cli)
{
_cli->stop();
}
if(_rsession)
delete _rsession;
if(_wsession)
delete _wsession;
delete _scp;
delete _conf;
log_close();
}
bool PseuInstance::Init(void) {
log_prepare("logfile.txt",this);
log("");
log("--- Initializing Instance ---");
if(_confdir.empty())
_confdir="./conf/";
if(_scpdir.empty())
_scpdir="./scp/";
srand((unsigned)time(NULL));
RAND_set_rand_method(RAND_SSLeay()); // init openssl randomizer
_scp=new DefScriptPackage();
_scp->SetParentMethod((void*)this);
_conf=new PseuInstanceConf();
_scp->SetPath(_scpdir);
_scp->variables.Set("@version_short",_ver_short);
_scp->variables.Set("@version",_ver);
_scp->variables.Set("@inworld","false");
if(!_scp->BoolRunScript("_startup",NULL))
{
logerror("Error executing '_startup.def'");
SetError();
}
// load all .def files in scripts directory
log("Loading DefScripts from folder '%s'",_scpdir.c_str());
std::deque<std::string> fl = GetFileList(_scpdir);
for(uint32 i = 0; i < fl.size(); i++)
{
std::string fn = fl[i]; // do not lowercase filename because of linux case sensitivity
if(fn.length() <= 4) // must be at least "x.def"
continue;
std::string ext = stringToLower(fn.substr(fn.length()-4,4));
std::string sn;
if(ext==".def")
sn = stringToLower(fn.substr(0,fn.length()-ext.length()));
if(sn.length())
{
if(!_scp->ScriptExists(sn))
{
std::string ffn = _scpdir + fn;
if(_scp->LoadScriptFromFile(ffn,sn))
logdebug("-> Auto-loaded script [ %s ]",ffn.c_str());
else
logerror("-> Can't auto-load script [ %s ]",ffn.c_str());
}
}
}
// TODO: find a better loaction where to place this block!
if(GetConf()->enablegui)
{
uint16 x,y,depth;
uint8 driver;
bool shadows,vsync,win;
driver=(uint8)atoi(GetScripts()->variables.Get("GUI::DRIVER").c_str());
vsync=(bool)atoi(GetScripts()->variables.Get("GUI::VSYNC").c_str());
depth=(uint8)atoi(GetScripts()->variables.Get("GUI::DEPTH").c_str());
x=(uint16)atoi(GetScripts()->variables.Get("GUI::RESX").c_str());
y=(uint16)atoi(GetScripts()->variables.Get("GUI::RESY").c_str());
win=(bool)atoi(GetScripts()->variables.Get("GUI::WINDOWED").c_str());
shadows=(bool)atoi(GetScripts()->variables.Get("GUI::SHADOWS").c_str());
log("GUI settings: driver=%u, depth=%u, res=%ux%u, windowed=%u, shadows=%u",driver,depth,x,y,win,shadows);
if(x>0 && y>0 && (depth==16 || depth==32) && driver>0 && driver<=5)
{
PseuGUIRunnable *rgui = new PseuGUIRunnable();
PseuGUI *gui = rgui->GetGUI();
gui->SetInstance(this);
gui->SetDriver(driver);
gui->SetResolution(x,y,depth);
gui->SetVSync(vsync);
gui->UseShadows(shadows);
ZThread::Thread *t = new ZThread::Thread(rgui);
}
else
logerror("GUI: incorrect settings!");
}
if(GetConf()->enablecli)
{
log("Starting CLI...");
_cli = new CliRunnable(this);
ZThread::Thread t(_cli);
}
if(_error)
{
logcritical("Errors while initializing!");
return false;
}
log("Init complete.\n");
_initialized=true;
return true;
}
void PseuInstance::Run(void)
{
if(!_initialized)
return;
if(GetConf()->realmlist.empty() || GetConf()->realmport==0)
{
logcritical("Realmlist address not set, can't connect.");
SetError();
}
else
{
// for now: create the realmsession only on startup.
// may be extended to a script command later on.
// then try to connect
_rsession = new RealmSession(this);
_rsession->Connect();
_rsession->SendLogonChallenge();
// this is the mainloop
while(!_stop)
{
Update();
if(_error)
_stop=true;
}
}
// fastquit is defined if we clicked [X] (on windows)
if(_fastquit)
{
log("Aborting Instance...");
return;
}
log("Shutting down instance...");
// if there was an error, better dont save, as the data might be damaged
if(!_error)
{
SaveAllCache();
//...
}
if(GetConf()->exitonerror == false && _error)
{
log("Exiting on error is disabled, PseuWoW is now IDLE");
log("-- Press enter to exit --");
char crap[100];
fgets(crap,sizeof(crap),stdin); // workaround, need to press enter 2x for now
}
}
void PseuInstance::Update()
{
// delete sessions if they are no longer needed
if(_rsession && _rsession->MustDie())
{
delete _rsession;
_rsession = NULL;
}
if(_wsession && _wsession->MustDie())
{
delete _wsession;
_wsession = NULL;
}
if(_createws)
{
_createws = false;
if(_wsession)
delete _wsession;
_wsession = new WorldSession(this);
_wsession->Start();
}
// if we have no active sessions, we may reconnect
if((!_rsession) && (!_wsession) && GetConf()->reconnect)
{
logdetail("Waiting %u ms before reconnecting.",GetConf()->reconnect);
for(uint32 t = 0; t < GetConf()->reconnect && !this->Stopped(); t+=100) Sleep(100);
this->Sleep(1000); // wait 1 sec before reconnecting
_rsession = new RealmSession(this);
_rsession->Connect();
_rsession->SendLogonChallenge(); // and login again
}
// update currently existing/active sessions
if(_rsession)
_rsession->Update();
if(_wsession)
try { _wsession->Update(); } catch (...)
{
logerror("Unhandled exception in WorldSession::Update()");
}
GetScripts()->GetEventMgr()->Update();
this->Sleep(GetConf()->networksleeptime);
}
void PseuInstance::SaveAllCache(void)
{
//...
if(GetWSession())
{
GetWSession()->plrNameCache.SaveToFile();
ItemProtoCache_WriteDataToCache(GetWSession());
//...
}
}
void PseuInstance::Sleep(uint32 msecs)
{
GetRunnable()->sleep(msecs);
}
PseuInstanceConf::PseuInstanceConf()
{
enablecli=false;
exitonerror=false;
}
void PseuInstanceConf::ApplyFromVarSet(VarSet &v)
{
debug=atoi(v.Get("DEBUG").c_str());
realmlist=v.Get("REALMLIST");
accname=v.Get("ACCNAME");
accpass=v.Get("ACCPASS");
exitonerror=(bool)atoi(v.Get("EXITONERROR").c_str());
reconnect=atoi(v.Get("RECONNECT").c_str());
realmport=atoi(v.Get("REALMPORT").c_str());
clientversion_string=v.Get("CLIENTVERSION");
clientbuild=atoi(v.Get("CLIENTBUILD").c_str());
clientlang=v.Get("CLIENTLANGUAGE");
realmname=v.Get("REALMNAME");
charname=v.Get("CHARNAME");
networksleeptime=atoi(v.Get("NETWORKSLEEPTIME").c_str());
showopcodes=atoi(v.Get("SHOWOPCODES").c_str());
hidefreqopcodes=(bool)atoi(v.Get("HIDEFREQOPCODES").c_str());
enablecli=(bool)atoi(v.Get("ENABLECLI").c_str());
allowgamecmd=(bool)atoi(v.Get("ALLOWGAMECMD").c_str());
enablechatai=(bool)atoi(v.Get("ENABLECHATAI").c_str());
notifyping=(bool)atoi(v.Get("NOTIFYPING").c_str());
showmyopcodes=(bool)atoi(v.Get("SHOWMYOPCODES").c_str());
disablespellcheck=(bool)atoi(v.Get("DISABLESPELLCHECK").c_str());
enablegui=(bool)atoi(v.Get("ENABLEGUI").c_str());
// clientversion is a bit more complicated to add
{
std::string opt=clientversion_string + ".";
std::string num;
uint8 p=0;
for(uint8 i=0;i<opt.length();i++)
{
if(!isdigit(opt.at(i)))
{
clientversion[p]=(unsigned char)atoi(num.c_str());
num.clear();
p++;
if(p>2)
break;
continue;
}
num+=opt.at(i);
}
}
}
PseuInstanceConf::~PseuInstanceConf()
{
//...
}