From 8453f04d6623387d08ae52c09d5def4abf33b853 Mon Sep 17 00:00:00 2001 From: shlainn Date: Tue, 8 Apr 2008 02:18:12 +0000 Subject: [PATCH] * Added a Login GUI. Not beautiful, but at least it works. ** Login GUI only appears when GUI is activated in conf and either Password or Accountname are not set ** Don't resize the Login Window ** Community Website button doesn't work yet, but Quit does * Added a dynamic framerate limiter, though i think it's overkill. See comments in PseuGUI.cpp * Changed std::cout to logdebug in the Image and MeshLoaders --- src/Client/GUI/CImageLoaderBLP.cpp | 15 +++-- src/Client/GUI/CM2MeshFileLoader.cpp | 28 ++++---- src/Client/GUI/PseuGUI.cpp | 13 +++- src/Client/GUI/PseuGUI.h | 6 +- src/Client/GUI/Scene.h | 17 ++++- src/Client/GUI/SceneLogin.cpp | 98 ++++++++++++++++++++++++++++ src/Client/PseuWoW.cpp | 28 +++++++- src/Client/PseuWoW.h | 1 + src/Client/Realm/RealmSession.cpp | 39 +++++++---- src/Client/Realm/RealmSession.h | 6 +- 10 files changed, 206 insertions(+), 45 deletions(-) create mode 100644 src/Client/GUI/SceneLogin.cpp diff --git a/src/Client/GUI/CImageLoaderBLP.cpp b/src/Client/GUI/CImageLoaderBLP.cpp index 668b530..c9daa7f 100644 --- a/src/Client/GUI/CImageLoaderBLP.cpp +++ b/src/Client/GUI/CImageLoaderBLP.cpp @@ -1,5 +1,6 @@ #include #include +#include "common.h" #include "irrlicht/irrlicht.h" #include "SImage.h" #include "CImageLoaderBLP.h" @@ -19,7 +20,7 @@ namespace video //! based on the file extension (e.g. ".tga") bool CImageLoaderBLP::isALoadableFileExtension(const c8* fileName) const { -// std::cout << "Checking for file extension\n"; +// Checking for file extension return strstr(fileName, ".blp")!=0; } @@ -27,29 +28,29 @@ bool CImageLoaderBLP::isALoadableFileExtension(const c8* fileName) const //! returns true if the file maybe is able to be loaded by this class bool CImageLoaderBLP::isALoadableFileFormat(io::IReadFile* file) const { - // std::cout <<"Checking if file is a BLP file\n"; + //Checking if file is a BLP file if (!file) { - DEBUG(std::cout<<"No such file: "<getFileName()<<"\n"); + DEBUG(logdebug("No such file: %s",file->getFileName())); return false; } std::string fileId; // Read the first few bytes of the BLP file if (file->read(&fileId[0], 4) != 4) { - DEBUG(std::cout << "Cannot read BLP file header\n"); + DEBUG(logdebug("Cannot read BLP file header\n")); return false; } if(fileId[0]=='B' && fileId[1]=='L' && fileId[2]=='P' && fileId[3]=='2') { - DEBUG(std::cout << "Header is BLP2, file should be loadable\n"); + DEBUG(logdebug("Header is BLP2, file should be loadable")); return true; } else { - DEBUG(std::cout << "Header doesn't match, this is no BLP file\n"); - DEBUG(std::cout << "Expected:BLP2 Got:"< #include "CM2MeshFileLoader.h" +#include "common.h" #ifdef _DEBUG #define DEBUG(code) code; @@ -49,10 +50,9 @@ file->read(&header,sizeof(ModelHeader)); } else { - DEBUG(logger->log(L"header okay",ELL_INFORMATION)); + DEBUG(logdebug("header okay")); } //Name -> not very important I think, but save it nontheless; -DEBUG(std::cout << "Name offset:" << header.nameOfs << "Name length:" << header.nameLength << "\n"); //M2MeshName.clear(); //M2MeshName.reserve(header.nameLength); file->seek(header.nameOfs); @@ -73,7 +73,7 @@ for(u32 i =0;iread(&tempM2MVert,sizeof(ModelVertex)); M2MVertices.push_back(tempM2MVert); } -DEBUG(std::cout << "Read "<0) @@ -87,8 +87,8 @@ for(u32 i =0;ilog("Using View 0 for all further operations",ELL_INFORMATION)); -DEBUG(std::cout<<"This View has "<0) @@ -101,7 +101,7 @@ for(u32 i =0;iread(&tempM2Index,sizeof(u16)); M2MIndices.push_back(tempM2Index); } -DEBUG(std::cout << "Read "<read(&tempM2Triangle,sizeof(u16)); M2MTriangles.push_back(tempM2Triangle); } -DEBUG(std::cout << "Read "<0) M2MSubmeshes.clear(); @@ -129,7 +128,7 @@ for(u32 i =0;iread(&tempM2TexUnit,sizeof(TextureUnit)); M2MTextureUnit.push_back(tempM2TexUnit); } -DEBUG(std::cout << "Read "<read(&tempM2TexLookup,sizeof(u16)); M2MTextureLookup.push_back(tempM2TexLookup); } -DEBUG(std::cout << "Read "<read(&tempM2TexDef,sizeof(TextureDefinition)); M2MTextureDef.push_back(tempM2TexDef); } -DEBUG(std::cout << "Read "<read(&tempM2RF,sizeof(RenderFlags)); M2MRenderFlags.push_back(tempM2RF); } -DEBUG(std::cout << "Read "<seek(M2MTextureDef[i].texFileOfs); file->read((void*)tempTexFileName.c_str(),M2MTextureDef[i].texFileLen); - DEBUG(std::cout << "texture: '" << tempTexFileName << "'\n"); M2MTextureFiles.push_back(tempTexFileName.c_str()); std::cout<getMaterial().setTexture(0,Device->getVideoDriver()->getTexture(TexName.c_str())); if(igetMaterial().BackfaceCulling=(M2MRenderFlags[i].flags & 0x04)?false:true; if(M2MRenderFlags[i].blending==1) IMB->getMaterial().MaterialType=video::EMT_TRANSPARENT_ALPHA_CHANNEL; diff --git a/src/Client/GUI/PseuGUI.cpp b/src/Client/GUI/PseuGUI.cpp index 2e4de39..4042d17 100644 --- a/src/Client/GUI/PseuGUI.cpp +++ b/src/Client/GUI/PseuGUI.cpp @@ -45,7 +45,7 @@ PseuGUI::PseuGUI() _guienv = NULL; _scene = NULL; _passtime = _lastpasstime = _passtimediff = 0; -} + } PseuGUI::~PseuGUI() { @@ -126,7 +126,7 @@ void PseuGUI::_Init(void) _driver->addExternalImageLoader(BLPloader); scene::CM2MeshFileLoader* m2loader = new scene::CM2MeshFileLoader(_device, "./data/texture"); _smgr->addExternalMeshLoader(m2loader); - + _throttle=0; _initialized = true; } @@ -199,6 +199,13 @@ void PseuGUI::Run(void) _guienv->drawAll(); // irr: draw gui elements _scene->OnDraw(); // custom: draw everything that has to be draw late (post-processing also belongs here) _driver->endScene(); // irr: drawing done + if(_driver->getFPS()>100 && _throttle < 10)//Primitive FPS-Limiter - upper cap hardcoded 100 FPS. + _throttle++; //lowercap 60 (if it drops below, limiting is eased). + if(_driver->getFPS()<60 && _throttle>0) //but honestly, a 10 msec delay is not worth this amount of code. + _throttle--; //If the FPS is down, it will never be because of this + if(_throttle>0) //Thus i opt for dropping the charade and using a fixed conf value of max 10. + _device->sleep(_throttle); //sleeps max 10 msec (=_throttle) here. + } catch(...) { @@ -268,6 +275,7 @@ void PseuGUI::_UpdateSceneState(void) switch (_scenestate) { case SCENESTATE_GUISTART: _scene = new SceneGuiStart(this); break; + case SCENESTATE_LOGINSCREEN: _scene = new SceneLogin(this); break; case SCENESTATE_WORLD: _scene = new SceneWorld(this); break; default: _scene = new Scene(this); // will draw nothing, just yield the gui } @@ -277,6 +285,7 @@ void PseuGUI::_UpdateSceneState(void) } } + // used to get our current WorldPosition WorldPosition PseuGUI::GetWorldPosition(void) { diff --git a/src/Client/GUI/PseuGUI.h b/src/Client/GUI/PseuGUI.h index d3b6e56..bfea5a9 100644 --- a/src/Client/GUI/PseuGUI.h +++ b/src/Client/GUI/PseuGUI.h @@ -31,7 +31,7 @@ enum DriverIDs }; #define MOUSE_SENSIVITY 0.5f -#define ANGLE_STEP (M_PI/180.0f) +#define ANGLE_STEP (M_PI/180.0f) #define DEG_TO_RAD(x) ((x)*ANGLE_STEP) #define RAD_TO_DEG(x) ((x)/ANGLE_STEP) #define RAD_FIX(x) ( (x)>(2*M_PI) ? ((x)-(2*M_PI)) : ( ((x)<0) ? ((x)+(2*M_PI)) : (x) ) ) @@ -64,10 +64,11 @@ private: class PseuGUI { - // too bad friends are not inherited... + // too bad friends are not inherited... friend class Scene; friend class SceneWorld; friend class SceneGuiStart; + friend class SceneLogin; // ... public: @@ -117,6 +118,7 @@ private: irr::ITimer *_timer; uint32 _passtime, _lastpasstime, _passtimediff; irr::core::dimension2d _screendimension; + uint32 _throttle;//used for frameratelimiting }; diff --git a/src/Client/GUI/Scene.h b/src/Client/GUI/Scene.h index 7c136a6..4f3f14f 100644 --- a/src/Client/GUI/Scene.h +++ b/src/Client/GUI/Scene.h @@ -26,7 +26,7 @@ public: virtual void OnUpdate(s32); virtual void OnDraw(void); virtual void OnDrawBegin(void); - virtual void OnDelete(void); + virtual void OnDelete(void); virtual video::SColor GetBackgroundColor(void); protected: @@ -48,7 +48,22 @@ private: IGUIImage *irrlogo, *driverlogo; }; + +class GUIEventReceiver; +class SceneLogin : public Scene +{ +public: + SceneLogin(PseuGUI *gui); + void OnUpdate(s32); + void OnDelete(void); + +private: + gui::IGUIElement* root; + IGUIImage *irrlogo, *driverlogo; + GUIEventReceiver *eventrecv; + PseuGUI* _gui; +}; class ShTlTerrainSceneNode; class MCameraFPS; diff --git a/src/Client/GUI/SceneLogin.cpp b/src/Client/GUI/SceneLogin.cpp new file mode 100644 index 0000000..482ebb3 --- /dev/null +++ b/src/Client/GUI/SceneLogin.cpp @@ -0,0 +1,98 @@ +#include "common.h" +#include "PseuGUI.h" +#include "PseuWoW.h" +#include "Scene.h" +#include "RealmSession.h" + +enum GuiElementID +{ + TEXTBOX_NAME = 0x1, + TEXTBOX_PASSWORD = 0x2, + BUTTON_QUIT = 0x4, + BUTTON_COMMUNITY = 0x8, + BUTTON_LOGON = 0x10, +}; + +class GUIEventReceiver : public IEventReceiver +{ +public: + GUIEventReceiver() + { + buttons=0; + } + virtual bool OnEvent(const SEvent& event) + { + //GUI EVENT + if (event.EventType == EET_GUI_EVENT) + { + s32 id = event.GUIEvent.Caller->getID(); + + switch(event.GUIEvent.EventType) + { + case EGET_BUTTON_CLICKED: + logdebug("user clicked button %u",id); + buttons+=id; + return true; + break; + } + } + + return false; + } + u32 buttons; +}; + + + +//TODO: Reposition elements on resize + +SceneLogin::SceneLogin(PseuGUI *gui) : Scene(gui) +{ + _gui=gui; + eventrecv = new GUIEventReceiver(); + device->setEventReceiver(eventrecv); + root = guienv->getRootGUIElement(); + + dimension2d scrn = driver->getScreenSize(); + + irrlogo = guienv->addImage(driver->getTexture("data/misc/irrlichtlogo.png"), core::position2d(5,5)); +guienv->addStaticText(L"Password:",rect((scrn.Width*0.5f)-90, (scrn.Height*0.3f)-10, (scrn.Width*0.5f)+90, (scrn.Height*0.3f)-10), false, false, 0, 0); +guienv->addStaticText(L"Account:", rect((scrn.Width*0.5f)-90, (scrn.Height*0.3f)+50, (scrn.Width*0.5f)+90, (scrn.Height*0.3f)+70), false, false, 0, 0); +guienv->addEditBox(L"", rect((scrn.Width*0.5f)-90, (scrn.Height*0.3f)+10, (scrn.Width*0.5f)+90, (scrn.Height*0.3f)+30), true, 0, 1); +guienv->addEditBox(L"", rect((scrn.Width*0.5f)-90, (scrn.Height*0.3f)+70, (scrn.Width*0.5f)+90, (scrn.Height*0.3f)+90), true, 0, 2)->setPasswordBox(true); +guienv->addButton(rect(scrn.Width-120, scrn.Height-40, scrn.Width-10, scrn.Height-10), 0, 4, L"Quit"); +guienv->addButton(rect(10, scrn.Height-40, 120, scrn.Height-10), 0, 8, L"Community Site"); +guienv->addButton(rect((scrn.Width*0.5f)-60, (scrn.Height*0.3f)+100, (scrn.Width*0.5f)+60, (scrn.Height*0.3f)+130), 0, 16, L"Logon"); + + +} + +void SceneLogin::OnUpdate(s32 timepassed) +{ + if(eventrecv->buttons & BUTTON_QUIT) + { + _gui->Shutdown(); + _gui->GetInstance()->Stop(); + eventrecv->buttons=0; + } + if(eventrecv->buttons & BUTTON_LOGON) + { + logdebug("Commencing Logon"); + core::stringc tmp; + tmp=root->getElementFromId(TEXTBOX_NAME,true)->getText(); + std::string accname =tmp.c_str(); + tmp=root->getElementFromId(TEXTBOX_PASSWORD,true)->getText(); + std::string accpass=tmp.c_str(); + logdebug("Trying to set Logon Data %u, %u", accname.size(), accpass.size()); + _gui->GetInstance()->GetRSession()->SetLogonData(accname,accpass); + _gui->GetInstance()->GetRSession()->SendLogonChallenge(); + eventrecv->buttons=0; + _gui->GetInstance()->login=true; + } +} + +void SceneLogin::OnDelete(void) +{ + // not necessary to delete the images, because they are deleted by guienv->clear() +} + diff --git a/src/Client/PseuWoW.cpp b/src/Client/PseuWoW.cpp index d28dd1f..caebdde 100644 --- a/src/Client/PseuWoW.cpp +++ b/src/Client/PseuWoW.cpp @@ -157,6 +157,8 @@ bool PseuInstance::Init(void) return false; } + login=false;//No GUI Login attempted yet + log("Init complete."); _initialized=true; return true; @@ -227,7 +229,18 @@ void PseuInstance::Run(void) // then try to connect _rsession = new RealmSession(this); _rsession->Connect(); - _rsession->SendLogonChallenge(); + + if(!GetConf()->enablegui||!(GetConf()->accname.empty()||GetConf()->accpass.empty())) + { + logdebug("GUI not active or Login data pre-entered, skipping Login GUI"); + + _rsession->SetLogonData(); + _rsession->SendLogonChallenge(); + } + else + { + GetGUI()->SetSceneState(SCENESTATE_LOGINSCREEN); + } // this is the mainloop while(!_stop) @@ -294,16 +307,25 @@ void PseuInstance::Update() _wsession->Start(); } - // if we have no active sessions, we may reconnect - if((!_rsession) && (!_wsession) && GetConf()->reconnect) + // if we have no active sessions, we may reconnect, if no GUI is active for login + if((!_rsession) && (!_wsession) && GetConf()->reconnect && !(login||GetConf()->enablegui)) { 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->SetLogonData(); _rsession->SendLogonChallenge(); // and login again } + if((!_rsession) && (!_wsession) && GetConf()->enablegui && login) + { + logdetail("Disconnected, switching GUI back to Loginscreen."); + _rsession = new RealmSession(this); + _rsession->Connect(); + _gui->SetSceneState(SCENESTATE_LOGINSCREEN); + login=false; + } // update currently existing/active sessions if(_rsession) diff --git a/src/Client/PseuWoW.h b/src/Client/PseuWoW.h index ba1f1a8..73e4cbb 100644 --- a/src/Client/PseuWoW.h +++ b/src/Client/PseuWoW.h @@ -104,6 +104,7 @@ public: void ProcessCliQueue(void); void AddCliCommand(std::string); + bool login;//Set when GUI attempts to login private: diff --git a/src/Client/Realm/RealmSession.cpp b/src/Client/Realm/RealmSession.cpp index bdbe2d3..d5a711a 100644 --- a/src/Client/Realm/RealmSession.cpp +++ b/src/Client/Realm/RealmSession.cpp @@ -295,6 +295,19 @@ void RealmSession::_HandleRealmList(ByteBuffer& pkt) GetInstance()->CreateWorldSession(); // will be done at next PseuInstance::Update() } +void RealmSession::SetLogonData(void) +{ + _accname=GetInstance()->GetConf()->accname; + _accpass=GetInstance()->GetConf()->accpass; +} + +void RealmSession::SetLogonData(std::string accname, std::string accpass) +{ + _accname=accname; + _accpass=accpass; + logdebug("Data Set"); +} + void RealmSession::SendLogonChallenge(void) { if(!_socket) @@ -302,14 +315,14 @@ void RealmSession::SendLogonChallenge(void) logerror("Can't send logon challenge, socket doesn't exist"); return; } - if( GetInstance()->GetConf()->accname.empty() || GetInstance()->GetConf()->clientversion_string.empty() + if( _accname.empty() || GetInstance()->GetConf()->clientversion_string.empty() || GetInstance()->GetConf()->clientbuild==0 || GetInstance()->GetConf()->clientlang.empty() ) { logcritical("Missing data, can't send Login challenge to Realm Server! (check your conf files)"); GetInstance()->SetError(); return; } - std::string acc = stringToUpper(GetInstance()->GetConf()->accname); + std::string acc = stringToUpper(_accname); ByteBuffer packet; packet << (uint8)AUTH_LOGON_CHALLENGE; packet << (uint8)6; @@ -327,7 +340,7 @@ void RealmSession::SendLogonChallenge(void) packet.append(acc.c_str(),acc.length()); // append accname, skip \0 SendRealmPacket(packet); - + logdebug("Packet Sent"); } void RealmSession::_HandleLogonChallenge(ByteBuffer& pkt) @@ -346,10 +359,10 @@ void RealmSession::_HandleLogonChallenge(ByteBuffer& pkt) switch (lc.error) { case 4: - logerror("Realm Server did not find account \"%s\"!",GetInstance()->GetConf()->accname.c_str()); + logerror("Realm Server did not find account \"%s\"!",_accname.c_str()); break; case 6: - logerror("Account \"%s\" is already logged in!",GetInstance()->GetConf()->accname.c_str()); + logerror("Account \"%s\" is already logged in!",_accname.c_str()); // TODO: wait a certain amount of time before reconnecting? conf option? break; case 9: @@ -362,8 +375,8 @@ void RealmSession::_HandleLogonChallenge(ByteBuffer& pkt) // now lets start calculating BigNumber N,A,B,a,u,x,v,S,salt,unk1,g,k(3); // init BNs, default k to 3 - std::string user=stringToUpper( GetInstance()->GetConf()->accname ); - std::string _authstr=stringToUpper( user +":"+GetInstance()->GetConf()->accpass ); + std::string user=stringToUpper( _accname ); + std::string _authstr=stringToUpper( user +":"+_accpass ); B.SetBinary(lc.B,32); g.SetBinary(lc.g,lc.g_len); @@ -435,7 +448,7 @@ void RealmSession::_HandleLogonChallenge(ByteBuffer& pkt) Nhash.UpdateBigNumbers(&N,NULL); Nhash.Finalize(); ghash.UpdateBigNumbers(&g,NULL); - ghash.Finalize(); + ghash.Finalize(); for(i=0;i<20;i++)Ng_hash[i] = Nhash.GetDigest()[i]^ghash.GetDigest()[i]; //printchex(Ng_hash,20,true); @@ -467,7 +480,7 @@ void RealmSession::_HandleLogonChallenge(ByteBuffer& pkt) logdebug("--> CRC=%s",toHexDump((uint8*)crc_hash,20,false).c_str()); - // now lets prepare the packet + // now lets prepare the packet ByteBuffer packet; packet << (uint8)AUTH_LOGON_PROOF; packet.append(A.AsByteArray(),A.GetNumBytes()); @@ -519,7 +532,7 @@ void RealmSession::_HandleLogonProof(ByteBuffer& pkt) DieOrReconnect(true); return; - // cover all other cases. continue only if success. + // cover all other cases. continue only if success. default: if(error != REALM_AUTH_SUCCESS) { @@ -529,7 +542,7 @@ void RealmSession::_HandleLogonProof(ByteBuffer& pkt) return; } } - + sAuthLogonProof_S lp; pkt.read((uint8*)&lp, 26); // the compiler didnt like 'sizeof(sAuthLogonProof_S)', said it was 28 @@ -592,7 +605,7 @@ void RealmSession::_HandleTransferData(ByteBuffer& pkt) _transbuf.append(pkt.contents(),pkt.size()); // append everything to the transfer buffer, which may also store incomplete bytes from the packet before pkt.rpos(pkt.size()); // set rpos to the end of the packet to indicate that we used all data - + logdev("transbuf size=%u rpos=%u diff=%u",_transbuf.size(),_transbuf.rpos(),_transbuf.size() - _transbuf.rpos()); while( _transbuf.size() - _transbuf.rpos() >= 3) // 3 = sizeof(uint32)+sizeof(uint8) @@ -619,7 +632,7 @@ void RealmSession::_HandleTransferData(ByteBuffer& pkt) printf("\r[%.2f%% done]",pct); _log_resetcolor(true); } - + } // finalize file diff --git a/src/Client/Realm/RealmSession.h b/src/Client/Realm/RealmSession.h index 27dac60..52f2159 100644 --- a/src/Client/Realm/RealmSession.h +++ b/src/Client/Realm/RealmSession.h @@ -16,7 +16,9 @@ public: void Connect(void); void Update(void); PseuInstance *GetInstance(void); - void ClearSocket(void); + void ClearSocket(void); + void SetLogonData(void); + void SetLogonData(std::string, std::string); void SendLogonChallenge(void); bool MustDie(void); void SetMustDie(void); @@ -33,7 +35,7 @@ private: void SendRealmPacket(ByteBuffer&); void DumpInvalidPacket(ByteBuffer&); void DieOrReconnect(bool err = false); - + std::string _accname,_accpass; SocketHandler _sh; PseuInstance *_instance; ZThread::LockedQueue pktQueue;