From 4b6e017241aa62deac0a29d6beed1863e0d32e35 Mon Sep 17 00:00:00 2001 From: Mark Vejvoda Date: Tue, 25 May 2010 18:06:42 +0000 Subject: [PATCH] - Added particle support to g3d viewer --- mk/linux/Jamfile | 14 +- source/g3d_viewer/main.cpp | 245 ++++++++- source/g3d_viewer/main.h | 22 +- source/g3d_viewer/renderer.cpp | 62 +++ source/g3d_viewer/renderer.h | 21 +- source/glest_game/facilities/game_util.cpp | 2 +- .../graphics/unit_particle_type.cpp | 18 +- .../glest_game/graphics/unit_particle_type.h | 4 +- source/glest_game/network/connection_slot.cpp | 519 +++++++++--------- source/glest_game/network/connection_slot.h | 3 + .../glest_game/network/server_interface.cpp | 12 + source/glest_game/type_instances/unit.cpp | 1 + source/glest_game/types/skill_type.cpp | 403 ++++++++++++++ source/glest_game/types/unit_type.cpp | 3 +- 14 files changed, 1043 insertions(+), 286 deletions(-) create mode 100755 source/glest_game/types/skill_type.cpp diff --git a/mk/linux/Jamfile b/mk/linux/Jamfile index 1a74191f4..8cde5367f 100644 --- a/mk/linux/Jamfile +++ b/mk/linux/Jamfile @@ -101,15 +101,19 @@ if $(WX_AVAILABLE) = "yes" { if $(WX_AVAILABLE) = "yes" { SubDir TOP g3d_viewer ; - GLEST_VIEWER_DIRS = . ; - for i in $(GLEST_DIRS) { + GLEST_VIEWER_DIRS = + . + +; + + for i in $(GLEST_VIEWER_DIRS) { GLEST_VIEWER_SOURCES += [ Wildcard $(i) : *.cpp *.h ] ; } - Application glest_g3dviewer : $(GLEST_VIEWER_SOURCES) ; + Application glest_g3dviewer : $(GLEST_VIEWER_SOURCES) ../glest_game/graphics/unit_particle_type.cpp ; LinkWith glest_g3dviewer : glestlib strefloplib ; - ExternalLibs glest_g3dviewer : SDL GL GLU WX CURL ; - IncludeDir glest_g3dviewer : ../shared_lib/include/$(LIB_INCLUDE_DIRS) $(GLEST_VIEWER_DIRS) ; + ExternalLibs glest_g3dviewer : SDL GL GLU XERCES VORBIS VORBISFILE OGG OPENAL LUA JPEG PNG CURL WX ; + IncludeDir glest_g3dviewer : ../shared_lib/include/$(LIB_INCLUDE_DIRS) $(GLEST_VIEWER_DIRS) ../glest_game/graphics ../glest_game/global ../glest_game/sound ../glest_game/game ; } ### Configurator ### diff --git a/source/g3d_viewer/main.cpp b/source/g3d_viewer/main.cpp index 0b0b9e77b..4e5465508 100644 --- a/source/g3d_viewer/main.cpp +++ b/source/g3d_viewer/main.cpp @@ -7,11 +7,15 @@ #include "graphics_interface.h" #include "util.h" #include "conversion.h" +#include "platform_common.h" +#include "xml_parser.h" using namespace Shared::Platform; +using namespace Shared::PlatformCommon; using namespace Shared::Graphics; using namespace Shared::Graphics::Gl; using namespace Shared::Util; +using namespace Shared::Xml; using namespace std; @@ -42,7 +46,9 @@ MainWindow::MainWindow(const string &modelPath) { //getGlPlatformExtensions(); renderer= Renderer::getInstance(); - this->modelPath= modelPath; + if(modelPath != "") { + this->modelPathList.push_back(modelPath); + } model= NULL; playerColor= Renderer::pcRed; @@ -60,6 +66,7 @@ MainWindow::MainWindow(const string &modelPath) //menu menuFile= new wxMenu(); menuFile->Append(miFileLoad, wxT("Load")); + menuFile->Append(miFileLoadParticleXML, wxT("Load Particle XML")); menu->Append(menuFile, wxT("File")); //mode @@ -116,16 +123,7 @@ void MainWindow::init(){ glCanvas->SetCurrent(); renderer->init(); - if(!modelPath.empty()){ - Model *tmpModel= new ModelGl(); - - printf("In [%s::%s] modelPath = [%s]\n",__FILE__,__FUNCTION__,modelPath.c_str()); - - renderer->loadTheModel(tmpModel, modelPath); - model= tmpModel; - - GetStatusBar()->SetStatusText(ToUnicode(getModelInfo().c_str())); - } + loadModel(""); //SetTitle(ToUnicode(winHeader + "; " + modelPath)); } @@ -138,6 +136,14 @@ void MainWindow::onPaint(wxPaintEvent &event){ renderer->renderTheModel(model, anim); + //int updateLoops = 100; + int updateLoops = 1; + for(int i=0; i< updateLoops; ++i) { + renderer->updateParticleManager(); + } + + renderer->renderParticleManager(); + glCanvas->SwapBuffers(); } @@ -170,14 +176,98 @@ void MainWindow::onMenuFileLoad(wxCommandEvent &event){ wxFileDialog fileDialog(this); fileDialog.SetWildcard(wxT("G3D files (*.g3d)|*.g3d")); if(fileDialog.ShowModal()==wxID_OK){ + modelPathList.clear(); + loadModel((const char*)wxFNCONV(fileDialog.GetPath().c_str())); + } +} + +void MainWindow::onMenuFileLoadParticleXML(wxCommandEvent &event){ + string fileName; + wxFileDialog fileDialog(this); + fileDialog.SetWildcard(wxT("XML files (*.xml)|*.xml")); + if(fileDialog.ShowModal()==wxID_OK){ + string path = (const char*)wxFNCONV(fileDialog.GetPath().c_str()); + loadParticle(path); + } +} + +void MainWindow::loadModel(string path) { + if(path != "" && fileExists(path) == true) { + this->modelPathList.push_back(path); + } + + for(int idx =0; idx < this->modelPathList.size(); idx++) { + string modelPath = this->modelPathList[idx]; + + //this->modelPath = path; delete model; Model *tmpModel= new ModelGl(); - renderer->loadTheModel(tmpModel, (const char*)wxFNCONV(fileDialog.GetPath().c_str())); + renderer->loadTheModel(tmpModel, modelPath); model= tmpModel; GetStatusBar()->SetStatusText(ToUnicode(getModelInfo().c_str())); } } +void MainWindow::loadParticle(string path) { + if(path != "" && fileExists(path) == true) { + this->particlePathList.push_back(path); + } + + if(this->particlePathList.size() > 0) { + for(int idx = 0; idx < this->particlePathList.size(); idx++) { + string particlePath = this->particlePathList[idx]; + string dir= extractDirectoryPathFromFile(particlePath); + + size_t pos = dir.find_last_of("/"); + if(pos == dir.length()-1) { + dir.erase(dir.length() -1); + } + + particlePath= extractFileFromDirectoryPath(particlePath); + + std::string unitXML = dir + "/" + extractFileFromDirectoryPath(dir) + ".xml"; + + int size = -1; + int height = -1; + + if(fileExists(unitXML) == true) { + XmlTree xmlTree; + xmlTree.load(unitXML); + const XmlNode *unitNode= xmlTree.getRootNode(); + const XmlNode *parametersNode= unitNode->getChild("parameters"); + //size + size= parametersNode->getChild("size")->getAttribute("value")->getIntValue(); + //height + height= parametersNode->getChild("height")->getAttribute("value")->getIntValue(); + } + + std::cout << "About to load [" << particlePath << "] from [" << dir << "] unit [" << unitXML << "]" << std::endl; + + UnitParticleSystemType *unitParticleSystemType= new UnitParticleSystemType(); + unitParticleSystemType->load(dir, dir + "/" + particlePath, renderer->getNewTexture2D()); + unitParticleSystemTypes.push_back(unitParticleSystemType); + + for(std::vector::const_iterator it= unitParticleSystemTypes.begin(); it != unitParticleSystemTypes.end(); ++it) { + UnitParticleSystem *ups= new UnitParticleSystem(200); + (*it)->setValues(ups); + if(size > 0) { + //getCurrVectorFlat() + Vec3f(0.f, type->getHeight()/2.f, 0.f); + Vec3f vec = Vec3f(0.f, height / 2.f, 0.f); + ups->setPos(vec); + } + //ups->setFactionColor(getFaction()->getTexture()->getPixmap()->getPixel3f(0,0)); + ups->setFactionColor(renderer->getPlayerColorTexture(playerColor)->getPixmap()->getPixel3f(0,0)); + unitParticleSystems.push_back(ups); + renderer->manageParticleSystem(ups); + + ups->setVisible(true); + } + + renderer->initTextureManager(); + } + } +} + void MainWindow::onMenuModeNormals(wxCommandEvent &event){ renderer->toggleNormals(); menuMode->Check(miModeNormals, renderer->getNormals()); @@ -256,10 +346,124 @@ string MainWindow::getModelInfo(){ return str; } +void MainWindow::onKeyDown(wxKeyEvent &e) { +/* + if (currentBrush == btHeight || currentBrush == btGradient) { // 'height' brush + if (e.GetKeyCode() >= '0' && e.GetKeyCode() <= '5') { + height = e.GetKeyCode() - 48; // '0'-'5' == 0-5 + if (e.GetModifiers() == wxMOD_CONTROL) { // Ctrl means negative + height = -height ; + } + int id_offset = heightCount / 2 + height + 1; + if (currentBrush == btHeight) { + wxCommandEvent evt(wxEVT_NULL, miBrushHeight + id_offset); + onMenuBrushHeight(evt); + } else { + wxCommandEvent evt(wxEVT_NULL, miBrushGradient + id_offset); + onMenuBrushGradient(evt); + } + return; + } + } + if (currentBrush == btSurface) { // surface texture + if (e.GetKeyCode() >= '1' && e.GetKeyCode() <= '5') { + surface = e.GetKeyCode() - 48; // '1'-'5' == 1-5 + wxCommandEvent evt(wxEVT_NULL, miBrushSurface + surface); + onMenuBrushSurface(evt); + return; + } + } + if (currentBrush == btObject) { + bool valid = true; + if (e.GetKeyCode() >= '1' && e.GetKeyCode() <= '9') { + object = e.GetKeyCode() - 48; // '1'-'9' == 1-9 + } else if (e.GetKeyCode() == '0') { // '0' == 10 + object = 10; + } else if (e.GetKeyCode() == '-') { // '-' == 0 + object = 0; + } else { + valid = false; + } + if (valid) { + wxCommandEvent evt(wxEVT_NULL, miBrushObject + object + 1); + onMenuBrushObject(evt); + return; + } + } + if (currentBrush == btResource) { + if (e.GetKeyCode() >= '0' && e.GetKeyCode() <= '5') { + resource = e.GetKeyCode() - 48; // '0'-'5' == 0-5 + wxCommandEvent evt(wxEVT_NULL, miBrushResource + resource + 1); + onMenuBrushResource(evt); + return; + } + } + if (currentBrush == btStartLocation) { + if (e.GetKeyCode() >= '1' && e.GetKeyCode() <= '8') { + startLocation = e.GetKeyCode() - 48; // '1'-'8' == 0-7 + wxCommandEvent evt(wxEVT_NULL, miBrushStartLocation + startLocation); + onMenuBrushStartLocation(evt); + return; + } + } + if (e.GetKeyCode() == 'H') { + wxCommandEvent evt(wxEVT_NULL, miBrushHeight + height + heightCount / 2 + 1); + onMenuBrushHeight(evt); + } else if (e.GetKeyCode() == ' ') { + if (resourceUnderMouse != 0) { + wxCommandEvent evt(wxEVT_NULL, miBrushResource + resourceUnderMouse + 1); + onMenuBrushResource(evt); + } else { + wxCommandEvent evt(wxEVT_NULL, miBrushObject + objectUnderMouse + 1); + onMenuBrushObject(evt); + } + } else if (e.GetKeyCode() == 'G') { + wxCommandEvent evt(wxEVT_NULL, miBrushGradient + height + heightCount / 2 + 1); + onMenuBrushGradient(evt); + } else if (e.GetKeyCode() == 'S') { + wxCommandEvent evt(wxEVT_NULL, miBrushSurface + surface); + onMenuBrushSurface(evt); + } else if (e.GetKeyCode() == 'O') { + wxCommandEvent evt(wxEVT_NULL, miBrushObject + object + 1); + onMenuBrushObject(evt); + } else if (e.GetKeyCode() == 'R') { + wxCommandEvent evt(wxEVT_NULL, miBrushResource + resource + 1); + onMenuBrushResource(evt); + } else if (e.GetKeyCode() == 'L') { + wxCommandEvent evt(wxEVT_NULL, miBrushStartLocation + startLocation + 1); + onMenuBrushStartLocation(evt); + } else { + e.Skip(); + } +*/ + + if (e.GetKeyCode() == 'R') { + renderer->end(); + + for(int idx = 0; idx < unitParticleSystems.size(); ++idx) { + //UnitParticleSystem *ups = unitParticleSystems[idx]; + //delete ups; + //ups = NULL; + } + unitParticleSystems.clear(); + + for(int idx = 0; idx < unitParticleSystemTypes.size(); ++idx) { + //UnitParticleSystemType *unitParticleSystemType = unitParticleSystemTypes[idx]; + //delete unitParticleSystemType; + //unitParticleSystemType = NULL; + } + unitParticleSystemTypes.clear(); + + loadModel(""); + loadParticle(""); + } +} + BEGIN_EVENT_TABLE(MainWindow, wxFrame) EVT_TIMER(-1, MainWindow::onTimer) EVT_CLOSE(MainWindow::onClose) EVT_MENU(miFileLoad, MainWindow::onMenuFileLoad) + EVT_MENU(miFileLoadParticleXML, MainWindow::onMenuFileLoadParticleXML) EVT_MENU(miModeWireframe, MainWindow::onMenuModeWireframe) EVT_MENU(miModeNormals, MainWindow::onMenuModeNormals) @@ -278,6 +482,15 @@ END_EVENT_TABLE() // class GlCanvas // ===================================================== +void translateCoords(wxWindow *wnd, int &x, int &y) { +#ifdef WIN32 + int cx, cy; + wnd->GetPosition(&cx, &cy); + x += cx; + y += cy; +#endif +} + GlCanvas::GlCanvas(MainWindow * mainWindow): wxGLCanvas(mainWindow, -1, wxDefaultPosition) { @@ -288,8 +501,16 @@ void GlCanvas::onMouseMove(wxMouseEvent &event){ mainWindow->onMouseMove(event); } +void GlCanvas::onKeyDown(wxKeyEvent &event) { + int x, y; + event.GetPosition(&x, &y); + translateCoords(this, x, y); + mainWindow->onKeyDown(event); +} + BEGIN_EVENT_TABLE(GlCanvas, wxGLCanvas) EVT_MOTION(GlCanvas::onMouseMove) + EVT_KEY_DOWN(GlCanvas::onKeyDown) END_EVENT_TABLE() // =============================================== diff --git a/source/g3d_viewer/main.h b/source/g3d_viewer/main.h index d48754ff8..499bac5b1 100644 --- a/source/g3d_viewer/main.h +++ b/source/g3d_viewer/main.h @@ -8,8 +8,11 @@ #include "renderer.h" #include "util.h" +#include "particle_type.h" +#include "unit_particle_type.h" using std::string; +using namespace Glest::Game; namespace Shared{ namespace G3dViewer{ @@ -29,6 +32,7 @@ public: enum MenuId{ miFileLoad, + miFileLoadParticleXML, miModeWireframe, miModeNormals, miModeGrid, @@ -53,7 +57,11 @@ private: wxMenu *menuCustomColor; Model *model; - string modelPath; + + //string modelPath; + //string ParticlePath; + std::vector modelPathList; + std::vector particlePathList; float speed; float anim; @@ -61,6 +69,12 @@ private: int lastX, lastY; Renderer::PlayerColor playerColor; + std::vector unitParticleSystemTypes; + std::vector unitParticleSystems; + + void loadModel(string path); + void loadParticle(string path); + public: MainWindow(const string &modelPath); ~MainWindow(); @@ -71,6 +85,7 @@ public: void onPaint(wxPaintEvent &event); void onClose(wxCloseEvent &event); void onMenuFileLoad(wxCommandEvent &event); + void onMenuFileLoadParticleXML(wxCommandEvent &event); void onMenuModeNormals(wxCommandEvent &event); void onMenuModeWireframe(wxCommandEvent &event); void onMenuModeGrid(wxCommandEvent &event); @@ -83,6 +98,8 @@ public: void onMouseMove(wxMouseEvent &event); void onTimer(wxTimerEvent &event); + void onKeyDown(wxKeyEvent &e); + string getModelInfo(); }; @@ -98,7 +115,8 @@ public: GlCanvas(MainWindow *mainWindow); void onMouseMove(wxMouseEvent &event); - void onPaint(wxPaintEvent &event); + void onPaint(wxPaintEvent &event); + void onKeyDown(wxKeyEvent &event); private: MainWindow *mainWindow; diff --git a/source/g3d_viewer/renderer.cpp b/source/g3d_viewer/renderer.cpp index 29dd79ea0..e26679b44 100644 --- a/source/g3d_viewer/renderer.cpp +++ b/source/g3d_viewer/renderer.cpp @@ -77,11 +77,17 @@ Renderer::Renderer(){ grid= true; modelRenderer = NULL; textureManager = NULL; + particleRenderer = NULL; + particleManager = NULL; } Renderer::~Renderer(){ delete modelRenderer; delete textureManager; + delete particleRenderer; + + //resources + delete particleManager; } Renderer * Renderer::getInstance(){ @@ -130,6 +136,11 @@ void Renderer::checkExtension(const string &extension, const string &msg){ } } +Texture2D * Renderer::getNewTexture2D() { + Texture2D *newTexture = textureManager->newTexture2D(); + return newTexture; +} + void Renderer::init(){ assertGl(); @@ -141,6 +152,10 @@ void Renderer::init(){ modelRenderer= gf->newModelRenderer(); textureManager= gf->newTextureManager(); + particleRenderer= gf->newParticleRenderer(); + + //resources + particleManager= gf->newParticleManager(); //red tex customTextureRed= textureManager->newTexture2D(); @@ -299,4 +314,51 @@ void Renderer::renderTheModel(Model *model, float f){ } } +void Renderer::manageParticleSystem(ParticleSystem *particleSystem){ + particleManager->manage(particleSystem); +} + +void Renderer::updateParticleManager(){ + particleManager->update(); +} + +void Renderer::renderParticleManager(){ + glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + glDepthFunc(GL_LESS); + particleRenderer->renderManager(particleManager, modelRenderer); + glPopAttrib(); +} + +Texture2D * Renderer::getPlayerColorTexture(PlayerColor playerColor) { + Texture2D *customTexture; + switch(playerColor){ + case pcRed: + customTexture= customTextureRed; + break; + case pcBlue: + customTexture= customTextureBlue; + break; + case pcYellow: + customTexture= customTextureYellow; + break; + case pcGreen: + customTexture= customTextureGreen; + break; + default: + assert(false); + } + + return customTexture; +} + +void Renderer::initTextureManager() { + textureManager->init(); +} + +void Renderer::end() { + //delete resources + //textureManager->end(); + particleManager->end(); +} + }}//end namespace diff --git a/source/g3d_viewer/renderer.h b/source/g3d_viewer/renderer.h index 84b5f56a6..ca71ff523 100644 --- a/source/g3d_viewer/renderer.h +++ b/source/g3d_viewer/renderer.h @@ -11,7 +11,10 @@ #include "model_renderer.h" #include "texture_manager.h" #include "model.h" -#include "texture.h" +#include "texture.h" + +#include "particle_renderer.h" + //#include "model_manager.h" //#include "graphics_factory_gl.h" @@ -19,7 +22,9 @@ using Shared::Graphics::ModelRenderer; using Shared::Graphics::TextureManager; using Shared::Graphics::Model; using Shared::Graphics::Texture2D; - +using Shared::Graphics::ParticleRenderer; +using Shared::Graphics::ParticleManager; +using Shared::Graphics::ParticleSystem; //#include "model_renderer.h" using Shared::Graphics::MeshCallback; @@ -67,6 +72,10 @@ private: ModelRenderer *modelRenderer; TextureManager *textureManager; + ParticleRenderer *particleRenderer; + + ParticleManager *particleManager; + Texture2D *customTextureRed; Texture2D *customTextureBlue; Texture2D *customTextureYellow; @@ -96,6 +105,14 @@ public: void loadTheModel(Model *model, string file); void renderTheModel(Model *model, float f); + + void manageParticleSystem(ParticleSystem *particleSystem); + void updateParticleManager(); + void renderParticleManager(); + Texture2D *getPlayerColorTexture(PlayerColor playerColor); + Texture2D * getNewTexture2D(); + void initTextureManager(); + void end(); }; }}//end namespace diff --git a/source/glest_game/facilities/game_util.cpp b/source/glest_game/facilities/game_util.cpp index 9d11d010e..ce8d97413 100644 --- a/source/glest_game/facilities/game_util.cpp +++ b/source/glest_game/facilities/game_util.cpp @@ -26,7 +26,7 @@ using namespace Shared::Platform; namespace Glest{ namespace Game{ const string mailString= "contact_game@glest.org"; -const string glestVersionString= "v3.3.5-alpha2"; +const string glestVersionString= "v3.3.5-alpha3"; string getCrashDumpFileName(){ return "glest" + glestVersionString + ".dmp"; diff --git a/source/glest_game/graphics/unit_particle_type.cpp b/source/glest_game/graphics/unit_particle_type.cpp index 1b2456e5f..41403a048 100644 --- a/source/glest_game/graphics/unit_particle_type.cpp +++ b/source/glest_game/graphics/unit_particle_type.cpp @@ -14,7 +14,6 @@ #include "util.h" #include "core_data.h" #include "xml_parser.h" -#include "renderer.h" #include "config.h" #include "game_constants.h" @@ -30,17 +29,15 @@ namespace Glest{ namespace Game{ // ===================================================== UnitParticleSystemType::UnitParticleSystemType(){ + texture = NULL; } -void UnitParticleSystemType::load(const XmlNode *particleSystemNode, const string &dir){ - - Renderer &renderer= Renderer::getInstance(); - +void UnitParticleSystemType::load(const XmlNode *particleSystemNode, const string &dir, Texture2D *newTexture){ //texture const XmlNode *textureNode= particleSystemNode->getChild("texture"); bool textureEnabled= textureNode->getAttribute("value")->getBoolValue(); - if(textureEnabled){ - texture= renderer.newTexture2D(rsGame); + if(textureEnabled == true) { + texture = newTexture; if(textureNode->getAttribute("luminance")->getBoolValue()){ texture->setFormat(Texture::fAlpha); texture->getPixmap()->init(1); @@ -52,6 +49,9 @@ void UnitParticleSystemType::load(const XmlNode *particleSystemNode, const strin } else{ texture= NULL; + + delete newTexture; + newTexture = NULL; } //primitive @@ -186,14 +186,14 @@ void UnitParticleSystemType::setValues(UnitParticleSystem *ups){ ups->setBlendMode(ParticleSystem::strToBlendMode(mode)); } -void UnitParticleSystemType::load(const string &dir, const string &path){ +void UnitParticleSystemType::load(const string &dir, const string &path, Texture2D *newTexture){ try{ XmlTree xmlTree; xmlTree.load(path); const XmlNode *particleSystemNode= xmlTree.getRootNode(); - UnitParticleSystemType::load(particleSystemNode, dir); + UnitParticleSystemType::load(particleSystemNode, dir, newTexture); } catch(const exception &e){ throw runtime_error("Error loading ParticleSystem: "+ path + "\n" +e.what()); diff --git a/source/glest_game/graphics/unit_particle_type.h b/source/glest_game/graphics/unit_particle_type.h index c2da33e24..ecb7ea34f 100644 --- a/source/glest_game/graphics/unit_particle_type.h +++ b/source/glest_game/graphics/unit_particle_type.h @@ -64,8 +64,8 @@ protected: public: UnitParticleSystemType(); - void load(const XmlNode *particleSystemNode, const string &dir); - void load(const string &dir, const string &path); + void load(const XmlNode *particleSystemNode, const string &dir, Texture2D *newTexture); + void load(const string &dir, const string &path, Texture2D *newTexture); void setValues(UnitParticleSystem *uts); }; diff --git a/source/glest_game/network/connection_slot.cpp b/source/glest_game/network/connection_slot.cpp index 16f825465..b95cce8e6 100644 --- a/source/glest_game/network/connection_slot.cpp +++ b/source/glest_game/network/connection_slot.cpp @@ -65,290 +65,305 @@ void ConnectionSlot::update() { } void ConnectionSlot::update(bool checkForNewClients) { - if(socket == NULL) { - if(networkGameDataSynchCheckOkMap) networkGameDataSynchCheckOkMap = false; - if(networkGameDataSynchCheckOkTile) networkGameDataSynchCheckOkTile = false; - if(networkGameDataSynchCheckOkTech) networkGameDataSynchCheckOkTech = false; - //if(networkGameDataSynchCheckOkFogOfWar) networkGameDataSynchCheckOkFogOfWar = false; + clearThreadErrorList(); - // Is the listener socket ready to be read? - //if(serverInterface->getServerSocket()->isReadable() == true) - if(checkForNewClients == true) { - //SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] BEFORE accept new client connection, serverInterface->getOpenSlotCount() = %d\n",__FILE__,__FUNCTION__,serverInterface->getOpenSlotCount()); - bool hasOpenSlots = (serverInterface->getOpenSlotCount() > 0); - if(serverInterface->getServerSocket()->hasDataToRead() == true) { - socket = serverInterface->getServerSocket()->accept(); - serverInterface->updateListen(); - } - //send intro message when connected - if(socket != NULL) { - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] accepted new client connection, serverInterface->getOpenSlotCount() = %d\n",__FILE__,__FUNCTION__,serverInterface->getOpenSlotCount()); - connectedTime = time(NULL); + try { + if(socket == NULL) { + if(networkGameDataSynchCheckOkMap) networkGameDataSynchCheckOkMap = false; + if(networkGameDataSynchCheckOkTile) networkGameDataSynchCheckOkTile = false; + if(networkGameDataSynchCheckOkTech) networkGameDataSynchCheckOkTech = false; + // Is the listener socket ready to be read? + //if(serverInterface->getServerSocket()->isReadable() == true) + if(checkForNewClients == true) { + //SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] BEFORE accept new client connection, serverInterface->getOpenSlotCount() = %d\n",__FILE__,__FUNCTION__,serverInterface->getOpenSlotCount()); + bool hasOpenSlots = (serverInterface->getOpenSlotCount() > 0); + if(serverInterface->getServerSocket()->hasDataToRead() == true) { + socket = serverInterface->getServerSocket()->accept(); + serverInterface->updateListen(); + } + //send intro message when connected + if(socket != NULL) { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] accepted new client connection, serverInterface->getOpenSlotCount() = %d\n",__FILE__,__FUNCTION__,serverInterface->getOpenSlotCount()); + connectedTime = time(NULL); + + chatText.clear(); + chatSender.clear(); + chatTeamIndex= -1; + + if(hasOpenSlots == false) { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] no open slots, disconnecting client\n",__FILE__,__FUNCTION__); + + NetworkMessageIntro networkMessageIntro(getNetworkVersionString(), socket->getHostName(), playerIndex, nmgstNoSlots); + sendMessage(&networkMessageIntro); + + close(); + } + else { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] client will be assigned to the next open slot\n",__FILE__,__FUNCTION__); + + NetworkMessageIntro networkMessageIntro(getNetworkVersionString(), socket->getHostName(), playerIndex, nmgstOk); + sendMessage(&networkMessageIntro); + } + } + } + } + else { + if(socket->isConnected()) { chatText.clear(); chatSender.clear(); chatTeamIndex= -1; - if(hasOpenSlots == false) { - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] no open slots, disconnecting client\n",__FILE__,__FUNCTION__); + NetworkMessageType networkMessageType= getNextMessageType(); - NetworkMessageIntro networkMessageIntro(getNetworkVersionString(), socket->getHostName(), playerIndex, nmgstNoSlots); - sendMessage(&networkMessageIntro); + //process incoming commands + switch(networkMessageType) { - close(); - } - else { - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] client will be assigned to the next open slot\n",__FILE__,__FUNCTION__); + case nmtInvalid: + break; - NetworkMessageIntro networkMessageIntro(getNetworkVersionString(), socket->getHostName(), playerIndex, nmgstOk); - sendMessage(&networkMessageIntro); - } - } - } - } - else { - if(socket->isConnected()) { - chatText.clear(); - chatSender.clear(); - chatTeamIndex= -1; + case nmtText: + { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtText\n",__FILE__,__FUNCTION__); - NetworkMessageType networkMessageType= getNextMessageType(); + NetworkMessageText networkMessageText; + if(receiveMessage(&networkMessageText)) { + chatText = networkMessageText.getText(); + chatSender = networkMessageText.getSender(); + chatTeamIndex = networkMessageText.getTeamIndex(); - //process incoming commands - switch(networkMessageType) { - - case nmtInvalid: + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] chatText [%s] chatSender [%s] chatTeamIndex = %d\n",__FILE__,__FUNCTION__,chatText.c_str(),chatSender.c_str(),chatTeamIndex); + } + } break; - case nmtText: - { - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtText\n",__FILE__,__FUNCTION__); + //command list + case nmtCommandList: { - NetworkMessageText networkMessageText; - if(receiveMessage(&networkMessageText)) { - chatText = networkMessageText.getText(); - chatSender = networkMessageText.getSender(); - chatTeamIndex = networkMessageText.getTeamIndex(); + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtCommandList\n",__FILE__,__FUNCTION__); - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] chatText [%s] chatSender [%s] chatTeamIndex = %d\n",__FILE__,__FUNCTION__,chatText.c_str(),chatSender.c_str(),chatTeamIndex); - } - } - break; + //throw runtime_error("test"); - //command list - case nmtCommandList: { - - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtCommandList\n",__FILE__,__FUNCTION__); - - NetworkMessageCommandList networkMessageCommandList; - if(receiveMessage(&networkMessageCommandList)) { - for(int i= 0; irequestCommand(networkMessageCommandList.getCommand(i)); + NetworkMessageCommandList networkMessageCommandList; + if(receiveMessage(&networkMessageCommandList)) { + for(int i= 0; irequestCommand(networkMessageCommandList.getCommand(i)); + } } } - } - break; + break; - //process intro messages - case nmtIntro: - { - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtIntro\n",__FILE__,__FUNCTION__); - - NetworkMessageIntro networkMessageIntro; - if(receiveMessage(&networkMessageIntro)) + //process intro messages + case nmtIntro: { - gotIntro = true; - name= networkMessageIntro.getName(); + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtIntro\n",__FILE__,__FUNCTION__); - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got name [%s]\n",__FILE__,__FUNCTION__,name.c_str()); + NetworkMessageIntro networkMessageIntro; + if(receiveMessage(&networkMessageIntro)) + { + gotIntro = true; + name= networkMessageIntro.getName(); - if(getAllowGameDataSynchCheck() == true && serverInterface->getGameSettings() != NULL) - { - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] sending NetworkMessageSynchNetworkGameData\n",__FILE__,__FUNCTION__); + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got name [%s]\n",__FILE__,__FUNCTION__,name.c_str()); - NetworkMessageSynchNetworkGameData networkMessageSynchNetworkGameData(serverInterface->getGameSettings()); - sendMessage(&networkMessageSynchNetworkGameData); - } - } - } - break; + if(getAllowGameDataSynchCheck() == true && serverInterface->getGameSettings() != NULL) + { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] sending NetworkMessageSynchNetworkGameData\n",__FILE__,__FUNCTION__); - //process datasynch messages - case nmtSynchNetworkGameDataStatus: - { - - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtSynchNetworkGameDataStatus\n",__FILE__,__FUNCTION__); - - NetworkMessageSynchNetworkGameDataStatus networkMessageSynchNetworkGameDataStatus; - if(receiveMessage(&networkMessageSynchNetworkGameDataStatus)) - { - receivedNetworkGameStatus = true; - - Config &config = Config::getInstance(); - string scenarioDir = ""; - if(serverInterface->getGameSettings()->getScenarioDir() != "") { - scenarioDir = serverInterface->getGameSettings()->getScenarioDir(); - if(EndsWith(scenarioDir, ".xml") == true) { - scenarioDir = scenarioDir.erase(scenarioDir.size() - 4, 4); - scenarioDir = scenarioDir.erase(scenarioDir.size() - serverInterface->getGameSettings()->getScenario().size(), serverInterface->getGameSettings()->getScenario().size() + 1); - } - - SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] gameSettings.getScenarioDir() = [%s] gameSettings.getScenario() = [%s] scenarioDir = [%s]\n",__FILE__,__FUNCTION__,__LINE__,serverInterface->getGameSettings()->getScenarioDir().c_str(),serverInterface->getGameSettings()->getScenario().c_str(),scenarioDir.c_str()); - } - - //tileset - int32 tilesetCRC = getFolderTreeContentsCheckSumRecursively(config.getPathListForType(ptTilesets,scenarioDir), string("/") + serverInterface->getGameSettings()->getTileset() + string("/*"), ".xml", NULL); - int32 techCRC = getFolderTreeContentsCheckSumRecursively(config.getPathListForType(ptTechs,scenarioDir), "/" + serverInterface->getGameSettings()->getTech() + "/*", ".xml", NULL); - Checksum checksum; - string file = Map::getMapPath(serverInterface->getGameSettings()->getMap(),scenarioDir); - checksum.addFile(file); - int32 mapCRC = checksum.getSum(); - - networkGameDataSynchCheckOkMap = (networkMessageSynchNetworkGameDataStatus.getMapCRC() == mapCRC); - networkGameDataSynchCheckOkTile = (networkMessageSynchNetworkGameDataStatus.getTilesetCRC() == tilesetCRC); - networkGameDataSynchCheckOkTech = (networkMessageSynchNetworkGameDataStatus.getTechCRC() == techCRC); - - // For testing - //techCRC++; - - if( networkGameDataSynchCheckOkMap == true && - networkGameDataSynchCheckOkTile == true && - networkGameDataSynchCheckOkTech == true) { - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] client data synch ok\n",__FILE__,__FUNCTION__); - } - else { - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] mapCRC = %d, remote = %d\n",__FILE__,__FUNCTION__,mapCRC,networkMessageSynchNetworkGameDataStatus.getMapCRC()); - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] tilesetCRC = %d, remote = %d\n",__FILE__,__FUNCTION__,tilesetCRC,networkMessageSynchNetworkGameDataStatus.getTilesetCRC()); - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] techCRC = %d, remote = %d\n",__FILE__,__FUNCTION__,techCRC,networkMessageSynchNetworkGameDataStatus.getTechCRC()); - - if(allowDownloadDataSynch == true) { - // Now get all filenames with their CRC values and send to the client - vctFileList.clear(); - - Config &config = Config::getInstance(); - string scenarioDir = ""; - if(serverInterface->getGameSettings()->getScenarioDir() != "") { - scenarioDir = serverInterface->getGameSettings()->getScenarioDir(); - if(EndsWith(scenarioDir, ".xml") == true) { - scenarioDir = scenarioDir.erase(scenarioDir.size() - 4, 4); - scenarioDir = scenarioDir.erase(scenarioDir.size() - serverInterface->getGameSettings()->getScenario().size(), serverInterface->getGameSettings()->getScenario().size() + 1); - } - - SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] gameSettings.getScenarioDir() = [%s] gameSettings.getScenario() = [%s] scenarioDir = [%s]\n",__FILE__,__FUNCTION__,__LINE__,serverInterface->getGameSettings()->getScenarioDir().c_str(),serverInterface->getGameSettings()->getScenario().c_str(),scenarioDir.c_str()); - } - - if(networkGameDataSynchCheckOkTile == false) { - if(tilesetCRC == 0) { - //vctFileList = getFolderTreeContentsCheckSumListRecursively(string(GameConstants::folder_path_tilesets) + "/" + serverInterface->getGameSettings()->getTileset() + "/*", "", &vctFileList); - vctFileList = getFolderTreeContentsCheckSumListRecursively(config.getPathListForType(ptTilesets,scenarioDir), string("/") + serverInterface->getGameSettings()->getTileset() + string("/*"), "", &vctFileList); - } - else { - //vctFileList = getFolderTreeContentsCheckSumListRecursively(string(GameConstants::folder_path_tilesets) + "/" + serverInterface->getGameSettings()->getTileset() + "/*", ".xml", &vctFileList); - vctFileList = getFolderTreeContentsCheckSumListRecursively(config.getPathListForType(ptTilesets,scenarioDir), "/" + serverInterface->getGameSettings()->getTileset() + "/*", ".xml", &vctFileList); - } - } - if(networkGameDataSynchCheckOkTech == false) { - if(techCRC == 0) { - //vctFileList = getFolderTreeContentsCheckSumListRecursively(string(GameConstants::folder_path_techs) + "/" + serverInterface->getGameSettings()->getTech() + "/*", "", &vctFileList); - vctFileList = getFolderTreeContentsCheckSumListRecursively(config.getPathListForType(ptTechs,scenarioDir),"/" + serverInterface->getGameSettings()->getTech() + "/*", "", &vctFileList); - } - else { - //vctFileList = getFolderTreeContentsCheckSumListRecursively(string(GameConstants::folder_path_techs) + "/" + serverInterface->getGameSettings()->getTech() + "/*", ".xml", &vctFileList); - vctFileList = getFolderTreeContentsCheckSumListRecursively(config.getPathListForType(ptTechs,scenarioDir),"/" + serverInterface->getGameSettings()->getTech() + "/*", ".xml", &vctFileList); - } - } - if(networkGameDataSynchCheckOkMap == false) { - vctFileList.push_back(std::pair(Map::getMapPath(serverInterface->getGameSettings()->getMap(),scenarioDir),mapCRC)); - } - - //for(int i = 0; i < vctFileList.size(); i++) - //{ - NetworkMessageSynchNetworkGameDataFileCRCCheck networkMessageSynchNetworkGameDataFileCRCCheck(vctFileList.size(), 1, vctFileList[0].second, vctFileList[0].first); - sendMessage(&networkMessageSynchNetworkGameDataFileCRCCheck); - //} - } - } - } - } - break; - - case nmtSynchNetworkGameDataFileCRCCheck: - { - - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtSynchNetworkGameDataFileCRCCheck\n",__FILE__,__FUNCTION__); - - NetworkMessageSynchNetworkGameDataFileCRCCheck networkMessageSynchNetworkGameDataFileCRCCheck; - if(receiveMessage(&networkMessageSynchNetworkGameDataFileCRCCheck)) - { - int fileIndex = networkMessageSynchNetworkGameDataFileCRCCheck.getFileIndex(); - NetworkMessageSynchNetworkGameDataFileCRCCheck networkMessageSynchNetworkGameDataFileCRCCheck(vctFileList.size(), fileIndex, vctFileList[fileIndex-1].second, vctFileList[fileIndex-1].first); - sendMessage(&networkMessageSynchNetworkGameDataFileCRCCheck); - } - } - break; - - case nmtSynchNetworkGameDataFileGet: - { - - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtSynchNetworkGameDataFileGet\n",__FILE__,__FUNCTION__); - - NetworkMessageSynchNetworkGameDataFileGet networkMessageSynchNetworkGameDataFileGet; - if(receiveMessage(&networkMessageSynchNetworkGameDataFileGet)) { - FileTransferInfo fileInfo; - fileInfo.hostType = eServer; - //fileInfo.serverIP = this->ip.getString(); - fileInfo.serverPort = Config::getInstance().getInt("ServerPort",intToStr(GameConstants::serverPort).c_str()); - fileInfo.fileName = networkMessageSynchNetworkGameDataFileGet.getFileName(); - - FileTransferSocketThread *fileXferThread = new FileTransferSocketThread(fileInfo); - fileXferThread->start(); - } - } - break; - - case nmtSwitchSetupRequest: - { - SwitchSetupRequest switchSetupRequest; - if(receiveMessage(&switchSetupRequest)) { - if(serverInterface->getSwitchSetupRequests()[switchSetupRequest.getCurrentFactionIndex()]==NULL) { - serverInterface->getSwitchSetupRequests()[switchSetupRequest.getCurrentFactionIndex()]= new SwitchSetupRequest(); - } - *(serverInterface->getSwitchSetupRequests()[switchSetupRequest.getCurrentFactionIndex()])=switchSetupRequest; - - } - break; - } - case nmtReady: - { - // its simply ignored here. Probably we are starting a game - break; - } - default: - { - if(gotIntro == true) { - //throw runtime_error("Unexpected message in connection slot: " + intToStr(networkMessageType)); - string sErr = "Unexpected message in connection slot: " + intToStr(networkMessageType); - //sendTextMessage(sErr,-1); - DisplayErrorMessage(sErr); - return; + NetworkMessageSynchNetworkGameData networkMessageSynchNetworkGameData(serverInterface->getGameSettings()); + sendMessage(&networkMessageSynchNetworkGameData); + } } - else { - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] got invalid message type before intro, disconnecting socket.\n",__FILE__,__FUNCTION__,__LINE__); - close(); + } + break; + + //process datasynch messages + case nmtSynchNetworkGameDataStatus: + { + + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtSynchNetworkGameDataStatus\n",__FILE__,__FUNCTION__); + + NetworkMessageSynchNetworkGameDataStatus networkMessageSynchNetworkGameDataStatus; + if(receiveMessage(&networkMessageSynchNetworkGameDataStatus)) + { + receivedNetworkGameStatus = true; + + Config &config = Config::getInstance(); + string scenarioDir = ""; + if(serverInterface->getGameSettings()->getScenarioDir() != "") { + scenarioDir = serverInterface->getGameSettings()->getScenarioDir(); + if(EndsWith(scenarioDir, ".xml") == true) { + scenarioDir = scenarioDir.erase(scenarioDir.size() - 4, 4); + scenarioDir = scenarioDir.erase(scenarioDir.size() - serverInterface->getGameSettings()->getScenario().size(), serverInterface->getGameSettings()->getScenario().size() + 1); + } + + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] gameSettings.getScenarioDir() = [%s] gameSettings.getScenario() = [%s] scenarioDir = [%s]\n",__FILE__,__FUNCTION__,__LINE__,serverInterface->getGameSettings()->getScenarioDir().c_str(),serverInterface->getGameSettings()->getScenario().c_str(),scenarioDir.c_str()); + } + + //tileset + int32 tilesetCRC = getFolderTreeContentsCheckSumRecursively(config.getPathListForType(ptTilesets,scenarioDir), string("/") + serverInterface->getGameSettings()->getTileset() + string("/*"), ".xml", NULL); + int32 techCRC = getFolderTreeContentsCheckSumRecursively(config.getPathListForType(ptTechs,scenarioDir), "/" + serverInterface->getGameSettings()->getTech() + "/*", ".xml", NULL); + Checksum checksum; + string file = Map::getMapPath(serverInterface->getGameSettings()->getMap(),scenarioDir); + checksum.addFile(file); + int32 mapCRC = checksum.getSum(); + + networkGameDataSynchCheckOkMap = (networkMessageSynchNetworkGameDataStatus.getMapCRC() == mapCRC); + networkGameDataSynchCheckOkTile = (networkMessageSynchNetworkGameDataStatus.getTilesetCRC() == tilesetCRC); + networkGameDataSynchCheckOkTech = (networkMessageSynchNetworkGameDataStatus.getTechCRC() == techCRC); + + // For testing + //techCRC++; + + if( networkGameDataSynchCheckOkMap == true && + networkGameDataSynchCheckOkTile == true && + networkGameDataSynchCheckOkTech == true) { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] client data synch ok\n",__FILE__,__FUNCTION__); + } + else { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] mapCRC = %d, remote = %d\n",__FILE__,__FUNCTION__,mapCRC,networkMessageSynchNetworkGameDataStatus.getMapCRC()); + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] tilesetCRC = %d, remote = %d\n",__FILE__,__FUNCTION__,tilesetCRC,networkMessageSynchNetworkGameDataStatus.getTilesetCRC()); + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] techCRC = %d, remote = %d\n",__FILE__,__FUNCTION__,techCRC,networkMessageSynchNetworkGameDataStatus.getTechCRC()); + + if(allowDownloadDataSynch == true) { + // Now get all filenames with their CRC values and send to the client + vctFileList.clear(); + + Config &config = Config::getInstance(); + string scenarioDir = ""; + if(serverInterface->getGameSettings()->getScenarioDir() != "") { + scenarioDir = serverInterface->getGameSettings()->getScenarioDir(); + if(EndsWith(scenarioDir, ".xml") == true) { + scenarioDir = scenarioDir.erase(scenarioDir.size() - 4, 4); + scenarioDir = scenarioDir.erase(scenarioDir.size() - serverInterface->getGameSettings()->getScenario().size(), serverInterface->getGameSettings()->getScenario().size() + 1); + } + + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] gameSettings.getScenarioDir() = [%s] gameSettings.getScenario() = [%s] scenarioDir = [%s]\n",__FILE__,__FUNCTION__,__LINE__,serverInterface->getGameSettings()->getScenarioDir().c_str(),serverInterface->getGameSettings()->getScenario().c_str(),scenarioDir.c_str()); + } + + if(networkGameDataSynchCheckOkTile == false) { + if(tilesetCRC == 0) { + //vctFileList = getFolderTreeContentsCheckSumListRecursively(string(GameConstants::folder_path_tilesets) + "/" + serverInterface->getGameSettings()->getTileset() + "/*", "", &vctFileList); + vctFileList = getFolderTreeContentsCheckSumListRecursively(config.getPathListForType(ptTilesets,scenarioDir), string("/") + serverInterface->getGameSettings()->getTileset() + string("/*"), "", &vctFileList); + } + else { + //vctFileList = getFolderTreeContentsCheckSumListRecursively(string(GameConstants::folder_path_tilesets) + "/" + serverInterface->getGameSettings()->getTileset() + "/*", ".xml", &vctFileList); + vctFileList = getFolderTreeContentsCheckSumListRecursively(config.getPathListForType(ptTilesets,scenarioDir), "/" + serverInterface->getGameSettings()->getTileset() + "/*", ".xml", &vctFileList); + } + } + if(networkGameDataSynchCheckOkTech == false) { + if(techCRC == 0) { + //vctFileList = getFolderTreeContentsCheckSumListRecursively(string(GameConstants::folder_path_techs) + "/" + serverInterface->getGameSettings()->getTech() + "/*", "", &vctFileList); + vctFileList = getFolderTreeContentsCheckSumListRecursively(config.getPathListForType(ptTechs,scenarioDir),"/" + serverInterface->getGameSettings()->getTech() + "/*", "", &vctFileList); + } + else { + //vctFileList = getFolderTreeContentsCheckSumListRecursively(string(GameConstants::folder_path_techs) + "/" + serverInterface->getGameSettings()->getTech() + "/*", ".xml", &vctFileList); + vctFileList = getFolderTreeContentsCheckSumListRecursively(config.getPathListForType(ptTechs,scenarioDir),"/" + serverInterface->getGameSettings()->getTech() + "/*", ".xml", &vctFileList); + } + } + if(networkGameDataSynchCheckOkMap == false) { + vctFileList.push_back(std::pair(Map::getMapPath(serverInterface->getGameSettings()->getMap(),scenarioDir),mapCRC)); + } + + //for(int i = 0; i < vctFileList.size(); i++) + //{ + NetworkMessageSynchNetworkGameDataFileCRCCheck networkMessageSynchNetworkGameDataFileCRCCheck(vctFileList.size(), 1, vctFileList[0].second, vctFileList[0].first); + sendMessage(&networkMessageSynchNetworkGameDataFileCRCCheck); + //} + } + } } - } + } + break; + + case nmtSynchNetworkGameDataFileCRCCheck: + { + + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtSynchNetworkGameDataFileCRCCheck\n",__FILE__,__FUNCTION__); + + NetworkMessageSynchNetworkGameDataFileCRCCheck networkMessageSynchNetworkGameDataFileCRCCheck; + if(receiveMessage(&networkMessageSynchNetworkGameDataFileCRCCheck)) + { + int fileIndex = networkMessageSynchNetworkGameDataFileCRCCheck.getFileIndex(); + NetworkMessageSynchNetworkGameDataFileCRCCheck networkMessageSynchNetworkGameDataFileCRCCheck(vctFileList.size(), fileIndex, vctFileList[fileIndex-1].second, vctFileList[fileIndex-1].first); + sendMessage(&networkMessageSynchNetworkGameDataFileCRCCheck); + } + } + break; + + case nmtSynchNetworkGameDataFileGet: + { + + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtSynchNetworkGameDataFileGet\n",__FILE__,__FUNCTION__); + + NetworkMessageSynchNetworkGameDataFileGet networkMessageSynchNetworkGameDataFileGet; + if(receiveMessage(&networkMessageSynchNetworkGameDataFileGet)) { + FileTransferInfo fileInfo; + fileInfo.hostType = eServer; + //fileInfo.serverIP = this->ip.getString(); + fileInfo.serverPort = Config::getInstance().getInt("ServerPort",intToStr(GameConstants::serverPort).c_str()); + fileInfo.fileName = networkMessageSynchNetworkGameDataFileGet.getFileName(); + + FileTransferSocketThread *fileXferThread = new FileTransferSocketThread(fileInfo); + fileXferThread->start(); + } + } + break; + + case nmtSwitchSetupRequest: + { + SwitchSetupRequest switchSetupRequest; + if(receiveMessage(&switchSetupRequest)) { + Mutex *mutex = getServerSynchAccessor(); + if(mutex != NULL) mutex->p(); + + if(serverInterface->getSwitchSetupRequests()[switchSetupRequest.getCurrentFactionIndex()]==NULL) { + serverInterface->getSwitchSetupRequests()[switchSetupRequest.getCurrentFactionIndex()]= new SwitchSetupRequest(); + } + *(serverInterface->getSwitchSetupRequests()[switchSetupRequest.getCurrentFactionIndex()])=switchSetupRequest; + + if(mutex != NULL) mutex->v(); + } + break; + } + case nmtReady: + { + // its simply ignored here. Probably we are starting a game + break; + } + default: + { + if(gotIntro == true) { + //throw runtime_error("Unexpected message in connection slot: " + intToStr(networkMessageType)); + string sErr = "Unexpected message in connection slot: " + intToStr(networkMessageType); + //sendTextMessage(sErr,-1); + //DisplayErrorMessage(sErr); + threadErrorList.push_back(sErr); + return; + } + else { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] got invalid message type before intro, disconnecting socket.\n",__FILE__,__FUNCTION__,__LINE__); + close(); + } + } + } + + if(gotIntro == false && difftime(time(NULL),connectedTime) > GameConstants::maxClientConnectHandshakeSecs) { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] difftime(time(NULL),connectedTime) = %d\n",__FILE__,__FUNCTION__,__LINE__,difftime(time(NULL),connectedTime)); + close(); + } } + else { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] calling close...\n",__FILE__,__FUNCTION__); - if(gotIntro == false && difftime(time(NULL),connectedTime) > GameConstants::maxClientConnectHandshakeSecs) { - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] difftime(time(NULL),connectedTime) = %d\n",__FILE__,__FUNCTION__,__LINE__,difftime(time(NULL),connectedTime)); close(); } } - else { - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] calling close...\n",__FILE__,__FUNCTION__); + } + catch(const exception &ex) { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] error detected [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what()); - close(); - } + threadErrorList.push_back(ex.what()); } } diff --git a/source/glest_game/network/connection_slot.h b/source/glest_game/network/connection_slot.h index 654a42406..cfe9ac2f2 100644 --- a/source/glest_game/network/connection_slot.h +++ b/source/glest_game/network/connection_slot.h @@ -65,10 +65,13 @@ public: bool hasValidSocketId(); virtual bool getConnectHasHandshaked() const { return gotIntro; } + std::vector getThreadErrorList() const { return threadErrorList; } + void clearThreadErrorList() { threadErrorList.clear(); } protected: Mutex * getServerSynchAccessor(); + std::vector threadErrorList; }; }}//end namespace diff --git a/source/glest_game/network/server_interface.cpp b/source/glest_game/network/server_interface.cpp index 49951910e..d14955847 100644 --- a/source/glest_game/network/server_interface.cpp +++ b/source/glest_game/network/server_interface.cpp @@ -414,6 +414,18 @@ void ServerInterface::update() { // Examine all threads for completion of delegation for(int i= 0; i< GameConstants::maxPlayers; ++i) { if(slotThreads[i] != NULL && slotsCompleted.find(i) == slotsCompleted.end()) { + ConnectionSlot* connectionSlot= slots[i]; + if(connectionSlot != NULL) { + std::vector errorList = connectionSlot->getThreadErrorList(); + if(errorList.size() > 0) { + for(int iErrIdx = 0; iErrIdx < errorList.size(); ++iErrIdx) { + string &sErr = errorList[iErrIdx]; + DisplayErrorMessage(sErr); + } + connectionSlot->clearThreadErrorList(); + } + } + if(slotThreads[i]->isSignalCompleted() == false && slotThreads[i]->getQuitStatus() == false && slotThreads[i]->getRunningStatus() == true) { diff --git a/source/glest_game/type_instances/unit.cpp b/source/glest_game/type_instances/unit.cpp index 2eecd9ec0..1594b5133 100644 --- a/source/glest_game/type_instances/unit.cpp +++ b/source/glest_game/type_instances/unit.cpp @@ -23,6 +23,7 @@ #include "skill_type.h" #include "core_data.h" #include "renderer.h" + #include "game.h" #ifndef WIN32 diff --git a/source/glest_game/types/skill_type.cpp b/source/glest_game/types/skill_type.cpp new file mode 100755 index 000000000..6fcdcd2a4 --- /dev/null +++ b/source/glest_game/types/skill_type.cpp @@ -0,0 +1,403 @@ +// ============================================================== +// This file is part of Glest (www.glest.org) +// +// Copyright (C) 2001-2008 Marti�o Figueroa +// +// You can redistribute this code and/or modify it under +// the terms of the GNU General Public License as published +// by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version +// ============================================================== + +#include "skill_type.h" + +#include + +#include "sound.h" +#include "util.h" +#include "lang.h" +#include "renderer.h" +#include "particle_type.h" +#include "unit_particle_type.h" +#include "tech_tree.h" +#include "faction_type.h" +#include "leak_dumper.h" + +using namespace Shared::Util; +using namespace Shared::Graphics; + +namespace Glest{ namespace Game{ + +// ===================================================== +// class SkillType +// ===================================================== + +SkillType::~SkillType(){ + deleteValues(sounds.getSounds().begin(), sounds.getSounds().end()); + //remove unitParticleSystemTypes + while(!unitParticleSystemTypes.empty()){ + delete unitParticleSystemTypes.back(); + unitParticleSystemTypes.pop_back(); + } +} + +void SkillType::load(const XmlNode *sn, const string &dir, const TechTree *tt, const FactionType *ft){ + //name + name= sn->getChild("name")->getAttribute("value")->getRestrictedValue(); + + //ep cost + mpCost= sn->getChild("ep-cost")->getAttribute("value")->getIntValue(); + + //speed + speed= sn->getChild("speed")->getAttribute("value")->getIntValue(); + + //anim speed + animSpeed= sn->getChild("anim-speed")->getAttribute("value")->getIntValue(); + + //model + string path= sn->getChild("animation")->getAttribute("path")->getRestrictedValue(); + animation= Renderer::getInstance().newModel(rsGame); + animation->load(dir + "/" + path); + + //particles + if(sn->hasChild("particles")){ + const XmlNode *particleNode= sn->getChild("particles"); + bool particleEnabled= particleNode->getAttribute("value")->getBoolValue(); + if(particleEnabled){ + for(int i=0; igetChildCount(); ++i){ + const XmlNode *particleFileNode= particleNode->getChild("particle-file", i); + string path= particleFileNode->getAttribute("path")->getRestrictedValue(); + UnitParticleSystemType *unitParticleSystemType= new UnitParticleSystemType(); + + unitParticleSystemType->load(dir, dir + "/" + path, Renderer::getInstance().newTexture2D(rsGame)); + unitParticleSystemTypes.push_back(unitParticleSystemType); + } + } + } + + + + //sound + const XmlNode *soundNode= sn->getChild("sound"); + if(soundNode->getAttribute("enabled")->getBoolValue()){ + + soundStartTime= soundNode->getAttribute("start-time")->getFloatValue(); + + sounds.resize(soundNode->getChildCount()); + for(int i=0; igetChildCount(); ++i){ + const XmlNode *soundFileNode= soundNode->getChild("sound-file", i); + string path= soundFileNode->getAttribute("path")->getRestrictedValue(); + StaticSound *sound= new StaticSound(); + sound->load(dir + "/" + path); + sounds[i]= sound; + } + } +} + +string SkillType::skillClassToStr(SkillClass skillClass){ + switch(skillClass){ + case scStop: return "Stop"; + case scMove: return "Move"; + case scAttack: return "Attack"; + case scHarvest: return "Harvest"; + case scRepair: return "Repair"; + case scBuild: return "Build"; + case scDie: return "Die"; + case scBeBuilt: return "Be Built"; + case scProduce: return "Produce"; + case scUpgrade: return "Upgrade"; + default: + assert(false); + return ""; + }; +} + +string SkillType::fieldToStr(Field field){ + switch(field){ + case fLand: return "Land"; + case fAir: return "Air"; + default: + assert(false); + return ""; + }; +} + + +// ===================================================== +// class StopSkillType +// ===================================================== + +StopSkillType::StopSkillType(){ + skillClass= scStop; +} + +string StopSkillType::toString() const{ + return Lang::getInstance().get("Stop"); +} + +// ===================================================== +// class MoveSkillType +// ===================================================== + +MoveSkillType::MoveSkillType(){ + skillClass= scMove; +} + +string MoveSkillType::toString() const{ + return Lang::getInstance().get("Move"); +} + +int MoveSkillType::getTotalSpeed(const TotalUpgrade *totalUpgrade) const{ + return speed + totalUpgrade->getMoveSpeed(); +} + +// ===================================================== +// class AttackSkillType +// ===================================================== + +//varios +AttackSkillType::AttackSkillType(){ + skillClass= scAttack; + attackType= NULL; + projectile= false; + splash= false; + splashRadius= 0; + projectileParticleSystemType= NULL; + splashParticleSystemType= NULL; + for(int i=0; igetChild("attack-strenght")->getAttribute("value")->getIntValue(); + attackVar= sn->getChild("attack-var")->getAttribute("value")->getIntValue(); + attackRange= sn->getChild("attack-range")->getAttribute("value")->getIntValue(); + string attackTypeName= sn->getChild("attack-type")->getAttribute("value")->getRestrictedValue(); + attackType= tt->getAttackType(attackTypeName); + attackStartTime= sn->getChild("attack-start-time")->getAttribute("value")->getFloatValue(); + + //attack fields + const XmlNode *attackFieldsNode= sn->getChild("attack-fields"); + for(int i=0; igetChildCount(); ++i){ + const XmlNode *fieldNode= attackFieldsNode->getChild("field", i); + string fieldName= fieldNode->getAttribute("value")->getRestrictedValue(); + if(fieldName=="land"){ + attackFields[fLand]= true; + } + else if(fieldName=="air"){ + attackFields[fAir]= true; + } + else{ + throw runtime_error("Not a valid field: "+fieldName+": "+ dir); + } + } + + //projectile + const XmlNode *projectileNode= sn->getChild("projectile"); + projectile= projectileNode->getAttribute("value")->getBoolValue(); + if(projectile){ + + //proj particle + const XmlNode *particleNode= projectileNode->getChild("particle"); + bool particleEnabled= particleNode->getAttribute("value")->getBoolValue(); + if(particleEnabled){ + string path= particleNode->getAttribute("path")->getRestrictedValue(); + projectileParticleSystemType= new ParticleSystemTypeProjectile(); + projectileParticleSystemType->load(dir, dir + "/" + path); + } + + //proj sounds + const XmlNode *soundNode= projectileNode->getChild("sound"); + if(soundNode->getAttribute("enabled")->getBoolValue()){ + + projSounds.resize(soundNode->getChildCount()); + for(int i=0; igetChildCount(); ++i){ + const XmlNode *soundFileNode= soundNode->getChild("sound-file", i); + string path= soundFileNode->getAttribute("path")->getRestrictedValue(); + StaticSound *sound= new StaticSound(); + sound->load(dir + "/" + path); + projSounds[i]= sound; + } + } + } + + //splash + const XmlNode *splashNode= sn->getChild("splash"); + splash= splashNode->getAttribute("value")->getBoolValue(); + if(splash){ + splashRadius= splashNode->getChild("radius")->getAttribute("value")->getIntValue(); + splashDamageAll= splashNode->getChild("damage-all")->getAttribute("value")->getBoolValue(); + + //splash particle + const XmlNode *particleNode= splashNode->getChild("particle"); + bool particleEnabled= particleNode->getAttribute("value")->getBoolValue(); + if(particleEnabled){ + string path= particleNode->getAttribute("path")->getRestrictedValue(); + splashParticleSystemType= new ParticleSystemTypeSplash(); + splashParticleSystemType->load(dir, dir + "/" + path); + } + } +} + +string AttackSkillType::toString() const{ + return Lang::getInstance().get("Attack"); +} + +//get totals +int AttackSkillType::getTotalAttackStrength(const TotalUpgrade *totalUpgrade) const{ + return attackStrength + totalUpgrade->getAttackStrength(); +} + +int AttackSkillType::getTotalAttackRange(const TotalUpgrade *totalUpgrade) const{ + return attackRange + totalUpgrade->getAttackRange(); +} + +// ===================================================== +// class BuildSkillType +// ===================================================== + +BuildSkillType::BuildSkillType(){ + skillClass= scBuild; +} + +string BuildSkillType::toString() const{ + return Lang::getInstance().get("Build"); +} + +// ===================================================== +// class HarvestSkillType +// ===================================================== + +HarvestSkillType::HarvestSkillType(){ + skillClass= scHarvest; +} + +string HarvestSkillType::toString() const{ + return Lang::getInstance().get("Harvest"); +} + +// ===================================================== +// class RepairSkillType +// ===================================================== + +RepairSkillType::RepairSkillType(){ + skillClass= scRepair; +} + +string RepairSkillType::toString() const{ + return Lang::getInstance().get("Repair"); +} + +// ===================================================== +// class ProduceSkillType +// ===================================================== + +ProduceSkillType::ProduceSkillType(){ + skillClass= scProduce; +} + +string ProduceSkillType::toString() const{ + return Lang::getInstance().get("Produce"); +} + +int ProduceSkillType::getTotalSpeed(const TotalUpgrade *totalUpgrade) const{ + return speed + totalUpgrade->getProdSpeed(); +} + +// ===================================================== +// class UpgradeSkillType +// ===================================================== + +UpgradeSkillType::UpgradeSkillType(){ + skillClass= scUpgrade; +} + +string UpgradeSkillType::toString() const{ + return Lang::getInstance().get("Upgrade"); +} + +int UpgradeSkillType::getTotalSpeed(const TotalUpgrade *totalUpgrade) const{ + return speed + totalUpgrade->getProdSpeed(); +} + +// ===================================================== +// class BeBuiltSkillType +// ===================================================== + +BeBuiltSkillType::BeBuiltSkillType(){ + skillClass= scBeBuilt; +} + +string BeBuiltSkillType::toString() const{ + return "Be built"; +} + +// ===================================================== +// class MorphSkillType +// ===================================================== + +MorphSkillType::MorphSkillType(){ + skillClass= scMorph; +} + +string MorphSkillType::toString() const{ + return "Morph"; +} + +int MorphSkillType::getTotalSpeed(const TotalUpgrade *totalUpgrade) const{ + return speed + totalUpgrade->getProdSpeed(); +} + +// ===================================================== +// class DieSkillType +// ===================================================== + +DieSkillType::DieSkillType(){ + skillClass= scDie; +} + +void DieSkillType::load(const XmlNode *sn, const string &dir, const TechTree *tt, const FactionType *ft){ + SkillType::load(sn, dir, tt, ft); + + fade= sn->getChild("fade")->getAttribute("value")->getBoolValue(); +} + +string DieSkillType::toString() const{ + return "Die"; +} + +// ===================================================== +// class SkillTypeFactory +// ===================================================== + +SkillTypeFactory::SkillTypeFactory(){ + registerClass("stop"); + registerClass("move"); + registerClass("attack"); + registerClass("build"); + registerClass("be_built"); + registerClass("harvest"); + registerClass("repair"); + registerClass("produce"); + registerClass("upgrade"); + registerClass("morph"); + registerClass("die"); +} + +SkillTypeFactory &SkillTypeFactory::getInstance(){ + static SkillTypeFactory ctf; + return ctf; +} + +}} //end namespace diff --git a/source/glest_game/types/unit_type.cpp b/source/glest_game/types/unit_type.cpp index a02b412e2..6e52403b7 100644 --- a/source/glest_game/types/unit_type.cpp +++ b/source/glest_game/types/unit_type.cpp @@ -222,7 +222,8 @@ void UnitType::load(int id,const string &dir, const TechTree *techTree, const Fa const XmlNode *particleFileNode= particleNode->getChild("particle-file", i); string path= particleFileNode->getAttribute("path")->getRestrictedValue(); UnitParticleSystemType *unitParticleSystemType= new UnitParticleSystemType(); - unitParticleSystemType->load(dir, dir + "/" + path); + + unitParticleSystemType->load(dir, dir + "/" + path, Renderer::getInstance().newTexture2D(rsGame)); damageParticleSystemTypes.push_back(unitParticleSystemType); } }