diff --git a/source/glest_game/facilities/game_util.cpp b/source/glest_game/facilities/game_util.cpp index cf5fa9fde..19e3d7655 100644 --- a/source/glest_game/facilities/game_util.cpp +++ b/source/glest_game/facilities/game_util.cpp @@ -1,11 +1,11 @@ // ============================================================== // This file is part of Glest (www.glest.org) // -// Copyright (C) 2001-2008 Marti�o Figueroa +// 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 +// 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 // ============================================================== @@ -22,7 +22,7 @@ using namespace Shared::Util; namespace Glest{ namespace Game{ const string mailString= "contact_game@glest.org"; -const string glestVersionString= "v3.2.3"; +const string glestVersionString= "v3.2.4-4-beta1"; string getCrashDumpFileName(){ return "glest"+glestVersionString+".dmp"; @@ -52,11 +52,11 @@ string getAboutString2(int i){ string getTeammateName(int i){ switch(i){ - case 0: return "Marti�o Figueroa"; - case 1: return "Jos� Luis Gonz�lez"; - case 2: return "Tucho Fern�ndez"; - case 3: return "Jos� Zanni"; - case 4: return "F�lix Men�ndez"; + case 0: return "Martiño Figueroa"; + case 1: return "José Luis González"; + case 2: return "Tucho Fernández"; + case 3: return "José Zanni"; + case 4: return "Félix Menéndez"; case 5: return "Marcos Caruncho"; case 6: return "Matthias Braun"; } diff --git a/source/glest_game/game/chat_manager.cpp b/source/glest_game/game/chat_manager.cpp index 4f8299521..5b317652f 100644 --- a/source/glest_game/game/chat_manager.cpp +++ b/source/glest_game/game/chat_manager.cpp @@ -3,9 +3,9 @@ // // 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 +// 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 // ============================================================== @@ -40,7 +40,7 @@ void ChatManager::init(Console* console, int thisTeamIndex){ } void ChatManager::keyDown(char key){ - + Lang &lang= Lang::getInstance(); //toggle team mode @@ -86,18 +86,24 @@ void ChatManager::keyPress(char c){ } } -void ChatManager::updateNetwork(){ +void ChatManager::updateNetwork() +{ GameNetworkInterface *gameNetworkInterface= NetworkManager::getInstance().getGameNetworkInterface(); string text; string sender; - - if(!gameNetworkInterface->getChatText().empty()){ + + if(!gameNetworkInterface->getChatText().empty()) + { int teamIndex= gameNetworkInterface->getChatTeamIndex(); - + + if(Socket::enableDebugText) printf("In [%s::%s] got nmtText [%s] for team = %d\n",__FILE__,__FUNCTION__,gameNetworkInterface->getChatText().c_str(),teamIndex); + if(teamIndex==-1 || teamIndex==thisTeamIndex){ console->addLine(gameNetworkInterface->getChatSender()+": "+gameNetworkInterface->getChatText(), true); + + if(Socket::enableDebugText) printf("In [%s::%s] Added text to console\n",__FILE__,__FUNCTION__); } } } - + }}//end namespace diff --git a/source/glest_game/game/game.cpp b/source/glest_game/game/game.cpp index ba4c6fe5c..d979ff12f 100644 --- a/source/glest_game/game/game.cpp +++ b/source/glest_game/game/game.cpp @@ -3,9 +3,9 @@ // // 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 +// 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 // ============================================================== @@ -64,7 +64,7 @@ Game::~Game(){ logger.setState(Lang::getInstance().get("Deleting")); logger.add("Game", true); - + renderer.endGame(); SoundRenderer::getInstance().stopAllSounds(); @@ -75,7 +75,7 @@ Game::~Game(){ } -// ==================== init and load ==================== +// ==================== init and load ==================== void Game::load(){ Logger &logger= Logger::getInstance(); @@ -83,7 +83,7 @@ void Game::load(){ string tilesetName= gameSettings.getTileset(); string techName= gameSettings.getTech(); string scenarioName= gameSettings.getScenario(); - + logger.setState(Lang::getInstance().get("Loading")); if(scenarioName.empty()){ @@ -114,7 +114,10 @@ void Game::load(){ } } -void Game::init(){ +void Game::init() +{ + if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__); + Lang &lang= Lang::getInstance(); Logger &logger= Logger::getInstance(); CoreData &coreData= CoreData::getInstance(); @@ -122,8 +125,9 @@ void Game::init(){ Map *map= world.getMap(); NetworkManager &networkManager= NetworkManager::getInstance(); + if(Socket::enableDebugText) printf("In [%s::%s] Initializing\n",__FILE__,__FUNCTION__); logger.setState(lang.get("Initializing")); - + //mesage box mainMessageBox.init(lang.get("Yes"), lang.get("No")); mainMessageBox.setEnabled(false); @@ -143,6 +147,8 @@ void Game::init(){ gameCamera.setPos(Vec2f(v.x, v.y)); scriptManager.init(&world, &gameCamera); + if(Socket::enableDebugText) printf("In [%s::%s] creating AI's\n",__FILE__,__FUNCTION__); + //create IAs aiInterfaces.resize(world.getFactionCount()); for(int i=0; igetAmbientSounds(); @@ -188,36 +195,40 @@ void Game::init(){ logger.add("Starting ambient stream", true); soundRenderer.playAmbient(ambientSounds->getRain()); } - + //snow if(tileset->getWeather()==wSnowy && ambientSounds->isEnabledSnow()){ logger.add("Starting ambient stream", true); soundRenderer.playAmbient(ambientSounds->getSnow()); } + if(Socket::enableDebugText) printf("In [%s::%s] Waiting for network\n",__FILE__,__FUNCTION__); logger.add("Waiting for network", true); networkManager.getGameNetworkInterface()->waitUntilReady(&checksum); + if(Socket::enableDebugText) printf("In [%s::%s] Starting music stream\n",__FILE__,__FUNCTION__); logger.add("Starting music stream", true); StrSound *gameMusic= world.getThisFaction()->getType()->getMusic(); soundRenderer.playMusic(gameMusic); logger.add("Launching game"); + + if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__); } -// ==================== update ==================== +// ==================== update ==================== //update void Game::update(){ - + // a) Updates non dependant on speed //misc updateFps++; mouse2d= (mouse2d+1) % Renderer::maxMouse2dAnim; - - //console + + //console console.update(); // b) Updates depandant on speed @@ -231,7 +242,7 @@ void Game::update(){ //AiInterface for(int i=0; igetCpuControl() && scriptManager.getPlayerModifiers(i)->getAiEnabled()){ - aiInterfaces[i]->update(); + aiInterfaces[i]->update(); } } @@ -243,7 +254,7 @@ void Game::update(){ //Gui gui.update(); - + //Particle systems if(weatherParticleSystem != NULL){ weatherParticleSystem->setPos(gameCamera.getPos()); @@ -270,7 +281,7 @@ void Game::updateCamera(){ } -// ==================== render ==================== +// ==================== render ==================== //render void Game::render(){ @@ -280,7 +291,7 @@ void Game::render(){ Renderer::getInstance().swapBuffers(); } -// ==================== tick ==================== +// ==================== tick ==================== void Game::tick(){ lastUpdateFps= updateFps; @@ -294,7 +305,7 @@ void Game::tick(){ } -// ==================== events ==================== +// ==================== events ==================== void Game::mouseDownLeft(int x, int y){ @@ -315,12 +326,12 @@ void Game::mouseDownLeft(int x, int y){ //minimap panel if(!messageBoxClick){ if(metrics.isInMinimap(x, y) && !gui.isSelectingPos()){ - + int xm= x - metrics.getMinimapX(); int ym= y - metrics.getMinimapY(); int xCell= static_cast(xm * (static_cast(map->getW()) / metrics.getMinimapW())); int yCell= static_cast(map->getH() - ym * (static_cast(map->getH()) / metrics.getMinimapH())); - + if(map->isInside(xCell, yCell)){ if(!gui.isSelectingPos()){ gameCamera.setPos(Vec2f(static_cast(xCell), static_cast(yCell))); @@ -333,13 +344,13 @@ void Game::mouseDownLeft(int x, int y){ int xd= x - metrics.getDisplayX(); int yd= y - metrics.getDisplayY(); if(gui.mouseValid(xd, yd)){ - gui.mouseDownLeftDisplay(xd, yd); + gui.mouseDownLeftDisplay(xd, yd); } else{ gui.mouseDownLeftGraphics(x, y); } } - + //graphics panel else{ gui.mouseDownLeftGraphics(x, y); @@ -349,12 +360,15 @@ void Game::mouseDownLeft(int x, int y){ //exit message box, has to be the last thing to do in this function if(mainMessageBox.getEnabled()){ int button= 1; - if(mainMessageBox.mouseClick(x, y, button)){ - if(button==1){ - networkManager.getGameNetworkInterface()->quitGame(); + if(mainMessageBox.mouseClick(x, y, button)) + { + if(button==1) + { + networkManager.getGameNetworkInterface()->quitGame(true); quitGame(); } - else{ + else + { //close message box mainMessageBox.setEnabled(false); } @@ -372,7 +386,7 @@ void Game::mouseUpLeft(int x, int y){ void Game::mouseDoubleClickLeft(int x, int y){ const Metrics &metrics= Metrics::getInstance(); - + //display panel if(metrics.isInDisplay(x, y) && !gui.isSelectingPos()){ int xd= x - metrics.getDisplayX(); @@ -389,28 +403,28 @@ void Game::mouseDoubleClickLeft(int x, int y){ void Game::mouseMove(int x, int y, const MouseState *ms){ const Metrics &metrics= Metrics::getInstance(); - + mouseX= x; mouseY= y; //main window - if(y<10){ + if(y<10){ gameCamera.setMoveZ(-1); } - else if(y> metrics.getVirtualH()-10){ + else if(y> metrics.getVirtualH()-10){ gameCamera.setMoveZ(1); } - else{ + else{ gameCamera.stopMoveZ(); } - if(x<10){ + if(x<10){ gameCamera.setMoveX(-1); } - else if(x> metrics.getVirtualW()-10){ + else if(x> metrics.getVirtualW()-10){ gameCamera.setMoveX(1); } - else{ + else{ gameCamera.stopMoveX(); } @@ -449,7 +463,7 @@ void Game::keyDown(char key){ else if(key=='E'){ for(int i=0; i<100; ++i){ string path= "screens/screen" + intToStr(i) + ".tga"; - + FILE *f= fopen(path.c_str(), "rb"); if(f==NULL){ Renderer::getInstance().saveScreen(path); @@ -592,9 +606,9 @@ void Game::quitGame(){ program->setState(new BattleEnd(program, world.getStats())); } -// ==================== PRIVATE ==================== +// ==================== PRIVATE ==================== -// ==================== render ==================== +// ==================== render ==================== void Game::render3d(){ @@ -630,7 +644,7 @@ void Game::render3d(){ //particles renderer.renderParticleManager(rsGame); - + //mouse 3d renderer.renderMouse3d(); } @@ -642,10 +656,10 @@ void Game::render2d(){ //init renderer.reset2d(); - + //display renderer.renderDisplay(); - + //minimap if(!config.getBool("PhotoMode")){ renderer.renderMinimap(); @@ -687,7 +701,7 @@ void Game::render2d(){ str+= "Triangle count: "+intToStr(renderer.getTriangleCount())+"\n"; str+= "Vertex count: "+intToStr(renderer.getPointCount())+"\n"; str+= "Frame count:"+intToStr(world.getFrameCount())+"\n"; - + //visible quad Quad2i visibleQuad= renderer.getVisibleQuad(); @@ -716,7 +730,7 @@ void Game::render2d(){ //network status if(renderNetworkStatus){ renderer.renderText( - NetworkManager::getInstance().getGameNetworkInterface()->getNetworkStatus(), + NetworkManager::getInstance().getGameNetworkInterface()->getNetworkStatus(), coreData.getMenuFontNormal(), Vec3f(1.0f), 20, 500, false); } @@ -726,15 +740,15 @@ void Game::render2d(){ renderer.renderResourceStatus(); renderer.renderConsole(&console); } - + //2d mouse renderer.renderMouse2d(mouseX, mouseY, mouse2d, gui.isSelectingPos()? 1.f: 0.f); } -// ==================== misc ==================== +// ==================== misc ==================== -void Game::checkWinner(){ +void Game::checkWinner(){ if(!gameOver){ if(gameSettings.getDefaultVictoryConditions()){ checkWinnerStandard(); @@ -753,7 +767,7 @@ void Game::checkWinnerStandard(){ lose= true; for(int i=0; iisAlly(world.getThisFaction())){ - world.getStats()->setVictorious(i); + world.getStats()->setVictorious(i); } } gameOver= true; @@ -775,7 +789,7 @@ void Game::checkWinnerStandard(){ if(win){ for(int i=0; i< world.getFactionCount(); ++i){ if(world.getFaction(i)->isAlly(world.getThisFaction())){ - world.getStats()->setVictorious(i); + world.getStats()->setVictorious(i); } } gameOver= true; @@ -789,7 +803,7 @@ void Game::checkWinnerScripted(){ gameOver= true; for(int i= 0; igetWinner()){ - world.getStats()->setVictorious(i); + world.getStats()->setVictorious(i); } } if(scriptManager.getPlayerModifiers(world.getThisFactionIndex())->getWinner()){ @@ -869,7 +883,7 @@ void Game::showMessageBox(const string &text, const string &header, bool toggle) if(!toggle){ mainMessageBox.setEnabled(false); } - + if(!mainMessageBox.getEnabled()){ mainMessageBox.setText(text); mainMessageBox.setHeader(header); diff --git a/source/glest_game/game/game_constants.h b/source/glest_game/game/game_constants.h index 87e5ca1e7..476af46bb 100644 --- a/source/glest_game/game/game_constants.h +++ b/source/glest_game/game/game_constants.h @@ -1,7 +1,7 @@ // ============================================================== // This file is part of Glest (www.glest.org) // -// Copyright (C) 2001-2008 Marti�o Figueroa +// 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 diff --git a/source/glest_game/game/game_settings.h b/source/glest_game/game/game_settings.h index ef5de4544..9ce69792f 100644 --- a/source/glest_game/game/game_settings.h +++ b/source/glest_game/game/game_settings.h @@ -3,9 +3,9 @@ // // 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 +// 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 // ============================================================== @@ -41,7 +41,50 @@ private: bool defaultResources; bool defaultVictoryConditions; -public: + void CopyAll(const GameSettings &game) + { + description = game.description; + map = game.map; + tileset = game.tileset; + tech = game.tech; + scenario = game.scenario; + scenarioDir = game.scenarioDir; + thisFactionIndex = game.thisFactionIndex; + factionCount = game.factionCount; + defaultUnits = game.defaultUnits; + defaultResources = game.defaultResources; + defaultVictoryConditions = game.defaultVictoryConditions; + + for(int i = 0; i < GameConstants::maxPlayers; i++) + { + factionTypeNames[i] = game.factionTypeNames[i]; //faction names + factionControls[i] = game.factionControls[i]; + teams[i] = game.teams[i]; + startLocationIndex[i] = game.startLocationIndex[i]; + } + + //if(Socket::enableDebugText) printf("In [%s::%s] gameSettings->getTileset() = [%s]\n",__FILE__,__FUNCTION__,getTileset().c_str()); + //if(Socket::enableDebugText) printf("In [%s::%s] gameSettings->getTech() = [%s]\n",__FILE__,__FUNCTION__,getTech().c_str()); + //if(Socket::enableDebugText) printf("In [%s::%s] gameSettings->getMap() = [%s]\n",__FILE__,__FUNCTION__,getMap().c_str()); + + } + +public: + + + GameSettings() { } + + GameSettings(const GameSettings &game) + { + CopyAll(game); + } + + GameSettings & operator=(const GameSettings &game) + { + CopyAll(game); + return *this; + } + //get const string &getDescription() const {return description;} const string &getMap() const {return map;} @@ -53,7 +96,7 @@ public: ControlType getFactionControl(int factionIndex) const {return factionControls[factionIndex];} int getThisFactionIndex() const {return thisFactionIndex;} - int getFactionCount() const {return factionCount;} + int getFactionCount() const {return factionCount;} int getTeam(int factionIndex) const {return teams[factionIndex];} int getStartLocationIndex(int factionIndex) const {return startLocationIndex[factionIndex];} @@ -74,7 +117,7 @@ public: void setFactionControl(int factionIndex, ControlType controller) {this->factionControls[factionIndex]= controller;} void setThisFactionIndex(int thisFactionIndex) {this->thisFactionIndex= thisFactionIndex;} - void setFactionCount(int factionCount) {this->factionCount= factionCount;} + void setFactionCount(int factionCount) {this->factionCount= factionCount;} void setTeam(int factionIndex, int team) {this->teams[factionIndex]= team;} void setStartLocationIndex(int factionIndex, int startLocationIndex) {this->startLocationIndex[factionIndex]= startLocationIndex;} diff --git a/source/glest_game/graphics/renderer.cpp b/source/glest_game/graphics/renderer.cpp index de0059f1d..53be80a36 100644 --- a/source/glest_game/graphics/renderer.cpp +++ b/source/glest_game/graphics/renderer.cpp @@ -3,9 +3,9 @@ // // 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 +// 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 // ============================================================== @@ -46,24 +46,24 @@ public: }; void MeshCallbackTeamColor::execute(const Mesh *mesh){ - + //team color if(mesh->getCustomTexture() && teamTexture!=NULL){ //texture 0 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - - //set color to interpolation + + //set color to interpolation glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); - + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); - + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE1); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA); - + //set alpha to 1 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE); @@ -76,20 +76,20 @@ void MeshCallbackTeamColor::execute(const Mesh *mesh){ glBindTexture(GL_TEXTURE_2D, static_cast(teamTexture)->getHandle()); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); - + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); - + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); - + //set alpha to 1 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PRIMARY_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); - + glActiveTexture(GL_TEXTURE0); } else{ @@ -139,13 +139,13 @@ const Vec4f Renderer::defColor= Vec4f(1.f, 1.f, 1.f, 1.f); const float Renderer::maxLightDist= 50.f; -// ==================== constructor and destructor ==================== +// ==================== constructor and destructor ==================== Renderer::Renderer(){ GraphicsInterface &gi= GraphicsInterface::getInstance(); FactoryRepository &fr= FactoryRepository::getInstance(); Config &config= Config::getInstance(); - + gi.setFactory(fr.getGraphicsFactory(config.getString("FactoryGraphics"))); GraphicsFactory *graphicsFactory= GraphicsInterface::getInstance().getFactory(); @@ -183,7 +183,7 @@ Renderer &Renderer::getInstance(){ } -// ==================== init ==================== +// ==================== init ==================== void Renderer::init(){ @@ -231,22 +231,22 @@ void Renderer::initGame(Game *game){ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); if(shadows==sShadowMapping){ - + //shadow mapping glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FAIL_VALUE_ARB, 1.0f-shadowAlpha); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, - shadowTextureSize, shadowTextureSize, + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, + shadowTextureSize, shadowTextureSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); } else{ - + //projected - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, - shadowTextureSize, shadowTextureSize, + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, + shadowTextureSize, shadowTextureSize, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL); } @@ -272,7 +272,7 @@ void Renderer::initMenu(MainMenu *mm){ void Renderer::reset3d(){ assertGl(); - glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); + glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); glCallList(list3d); pointCount= 0; triangleCount= 0; @@ -281,19 +281,19 @@ void Renderer::reset3d(){ void Renderer::reset2d(){ assertGl(); - glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR); + glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR); glCallList(list2d); assertGl(); } void Renderer::reset3dMenu(){ assertGl(); - glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR); + glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR); glCallList(list3dMenu); assertGl(); } -// ==================== end ==================== +// ==================== end ==================== void Renderer::end(){ @@ -347,7 +347,7 @@ void Renderer::reloadResources(){ } -// ==================== engine interface ==================== +// ==================== engine interface ==================== Model *Renderer::newModel(ResourceScope rs){ return modelManager[rs]->newModel(); @@ -385,8 +385,8 @@ void Renderer::swapBuffers(){ GraphicsInterface::getInstance().getCurrentContext()->swapBuffers(); } -// ==================== lighting ==================== - +// ==================== lighting ==================== + //places all the opengl lights void Renderer::setupLighting(){ @@ -412,7 +412,7 @@ void Renderer::setupLighting(){ glFogfv(GL_FOG_COLOR, Vec4f(fogColor*lightColor, 1.f).ptr()); lightCount++; - + //disable all secondary lights for(int i= 1; igetType()->getLightColor()).ptr()); glLightfv(lightEnum, GL_SPECULAR, Vec4f(unit->getType()->getLightColor()*0.3f).ptr()); glLightf(lightEnum, GL_QUADRATIC_ATTENUATION, 0.05f); - + ++lightCount; - + const GameCamera *gameCamera= game->getGameCamera(); if(Vec3f(pos).dist(gameCamera->getPos())getPos())){ @@ -467,7 +467,7 @@ void Renderer::loadGameCameraMatrix(){ void Renderer::loadCameraMatrix(const Camera *camera){ Vec3f position= camera->getPosition(); Quaternion orientation= camera->getOrientation().conjugate(); - + glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glMultMatrixf(orientation.toMatrix4().ptr()); @@ -484,18 +484,18 @@ void Renderer::computeVisibleQuad(){ // ======================================= void Renderer::renderMouse2d(int x, int y, int anim, float fade){ - float color1, color2; + float color1, color2; float fadeFactor= fade+1.f; - anim= anim*2-maxMouse2dAnim; + anim= anim*2-maxMouse2dAnim; - color2= (abs(anim*fadeFactor)/static_cast(maxMouse2dAnim))/2.f+0.4f; + color2= (abs(anim*fadeFactor)/static_cast(maxMouse2dAnim))/2.f+0.4f; color1= (abs(anim*fadeFactor)/static_cast(maxMouse2dAnim))/2.f+0.8f; glPushAttrib(GL_CURRENT_BIT | GL_COLOR_BUFFER_BIT | GL_LINE_BIT); - glEnable(GL_BLEND); - + glEnable(GL_BLEND); + //inside glColor4f(0.4f*fadeFactor, 0.2f*fadeFactor, 0.2f*fadeFactor, 0.5f*fadeFactor); glBegin(GL_TRIANGLES); @@ -517,15 +517,15 @@ void Renderer::renderMouse2d(int x, int y, int anim, float fade){ glPopAttrib(); } -void Renderer::renderMouse3d(){ - +void Renderer::renderMouse3d(){ + const Gui *gui= game->getGui(); const Mouse3d *mouse3d= gui->getMouse3d(); const Map *map= game->getWorld()->getMap(); GLUquadricObj *cilQuadric; Vec4f color; - + assertGl(); if((mouse3d->isEnabled() || gui->isPlacingBuilding()) && gui->isValidPosObjWorld()){ @@ -539,9 +539,9 @@ void Renderer::renderMouse3d(){ glEnable(GL_COLOR_MATERIAL); glDepthMask(GL_FALSE); - Vec2i pos= gui->getPosObjWorld(); - Vec3f pos3f= Vec3f(pos.x, map->getCell(pos)->getHeight(), pos.y); - + Vec2i pos= gui->getPosObjWorld(); + Vec3f pos3f= Vec3f(pos.x, map->getCell(pos)->getHeight(), pos.y); + if(gui->isPlacingBuilding()){ const UnitType *building= gui->getBuilding(); @@ -553,7 +553,7 @@ void Renderer::renderMouse3d(){ //choose color if(map->isFreeCells(pos, building->getSize(), fLand)){ color= Vec4f(1.f, 1.f, 1.f, 0.5f); - } + } else{ color= Vec4f(1.f, 0.f, 0.f, 0.5f); } @@ -563,7 +563,7 @@ void Renderer::renderMouse3d(){ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color.ptr()); const Model *buildingModel= building->getFirstStOfClass(scStop)->getAnimation(); buildingModel->updateInterpolationData(0.f, false); - modelRenderer->render(buildingModel); + modelRenderer->render(buildingModel); glDisable(GL_COLOR_MATERIAL); modelRenderer->end(); @@ -571,11 +571,11 @@ void Renderer::renderMouse3d(){ else{ //standard mouse glDisable(GL_TEXTURE_2D); - glDisable(GL_CULL_FACE); + glDisable(GL_CULL_FACE); color= Vec4f(1.f, 0.f, 0.f, 1.f-mouse3d->getFade()); glColor4fv(color.ptr()); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color.ptr()); - + glTranslatef(pos3f.x, pos3f.y+2.f, pos3f.z); glRotatef(90.f, 1.f, 0.f, 0.f); glRotatef(static_cast(mouse3d->getRot()), 0.f, 0.f, 1.f); @@ -587,19 +587,19 @@ void Renderer::renderMouse3d(){ glTranslatef(0.f, 0.f, 1.f); gluCylinder(cilQuadric, 0.7f, 0.f, 1.f, 4, 1); gluCylinder(cilQuadric, 0.7f, 0.f, 0.f, 4, 1); - gluDeleteQuadric(cilQuadric); + gluDeleteQuadric(cilQuadric); } glPopAttrib(); glPopMatrix(); } - + } void Renderer::renderBackground(const Texture2D *texture){ - + const Metrics &metrics= Metrics::getInstance(); - + assertGl(); glPushAttrib(GL_ENABLE_BIT); @@ -636,8 +636,8 @@ void Renderer::renderConsole(const Console *console){ glEnable(GL_BLEND); for(int i=0; igetLineCount(); ++i){ - renderTextShadow( - console->getLine(i), + renderTextShadow( + console->getLine(i), CoreData::getInstance().getConsoleFont(), 20, i*20+20); } @@ -659,7 +659,7 @@ void Renderer::renderChatManager(const ChatManager *chatManager){ text+= lang.get("All"); } text+= ": " + chatManager->getText() + "_"; - + textRenderer->begin(CoreData::getInstance().getConsoleFont()); textRenderer->render(text, 300, 150); textRenderer->end(); @@ -667,7 +667,7 @@ void Renderer::renderChatManager(const ChatManager *chatManager){ } void Renderer::renderResourceStatus(){ - + const Metrics &metrics= Metrics::getInstance(); const World *world= game->getWorld(); const Faction *thisFaction= world->getFaction(world->getThisFactionIndex()); @@ -675,16 +675,16 @@ void Renderer::renderResourceStatus(){ assertGl(); glPushAttrib(GL_ENABLE_BIT); - - int j= 0; + + int j= 0; for(int i= 0; igetTechTree()->getResourceTypeCount(); ++i){ const ResourceType *rt= world->getTechTree()->getResourceType(i); const Resource *r= thisFaction->getResource(rt); - + //if any unit produces the resource bool showResource= false; for(int k=0; kgetType()->getUnitTypeCount(); ++k){ - const UnitType *ut= thisFaction->getType()->getUnitType(k); + const UnitType *ut= thisFaction->getType()->getUnitType(k); if(ut->getCost(rt)!=NULL){ showResource= true; break; @@ -693,15 +693,16 @@ void Renderer::renderResourceStatus(){ //draw resource status if(showResource){ - + string str= intToStr(r->getAmount()); - + glEnable(GL_TEXTURE_2D); renderQuad(j*100+200, metrics.getVirtualH()-30, 16, 16, rt->getImage()); - - if(rt->getClass()!=rcStatic){ + + if(rt->getClass() != rcStatic) + { str+= "/" + intToStr(thisFaction->getStoreAmount(rt)); - } + } if(rt->getClass()==rcConsumable){ str+= "("; if(r->getBalance()>0){ @@ -713,22 +714,22 @@ void Renderer::renderResourceStatus(){ glDisable(GL_TEXTURE_2D); renderTextShadow( - str, CoreData::getInstance().getMenuFontSmall(), - j*100+220, metrics.getVirtualH()-30, false); + str, CoreData::getInstance().getMenuFontSmall(), + j*100+220, metrics.getVirtualH()-30, false); ++j; } } - + glPopAttrib(); assertGl(); } void Renderer::renderSelectionQuad(){ - + const Gui *gui= game->getGui(); - const SelectionQuad *sq= gui->getSelectionQuad(); + const SelectionQuad *sq= gui->getSelectionQuad(); Vec2i down= sq->getPosDown(); Vec2i up= sq->getPosUp(); @@ -751,7 +752,7 @@ Vec2i computeCenteredPos(const string &text, const Font2D *font, int x, int y){ const Metrics &metrics= Metrics::getInstance(); const FontMetrics *fontMetrics= font->getMetrics(); - + textPos= Vec2i( x-metrics.toVirtualX(static_cast(fontMetrics->getTextWidth(text)/2.f)), y-metrics.toVirtualY(static_cast(fontMetrics->getHeight()/2.f))); @@ -763,32 +764,32 @@ void Renderer::renderText(const string &text, const Font2D *font, float alpha, i glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT); glEnable(GL_BLEND); glColor4fv(Vec4f(1.f, 1.f, 1.f, alpha).ptr()); - + Vec2i pos= centered? computeCenteredPos(text, font, x, y): Vec2i(x, y); textRenderer->begin(font); textRenderer->render(text, pos.x, pos.y); textRenderer->end(); - + glPopAttrib(); } void Renderer::renderText(const string &text, const Font2D *font, const Vec3f &color, int x, int y, bool centered){ glPushAttrib(GL_CURRENT_BIT); glColor3fv(color.ptr()); - + Vec2i pos= centered? computeCenteredPos(text, font, x, y): Vec2i(x, y); textRenderer->begin(font); textRenderer->render(text, pos.x, pos.y); textRenderer->end(); - + glPopAttrib(); } void Renderer::renderTextShadow(const string &text, const Font2D *font, int x, int y, bool centered){ glPushAttrib(GL_CURRENT_BIT); - + Vec2i pos= centered? computeCenteredPos(text, font, x, y): Vec2i(x, y); textRenderer->begin(font); @@ -797,7 +798,7 @@ void Renderer::renderTextShadow(const string &text, const Font2D *font, int x, i glColor3f(1.0f, 1.0f, 1.0f); textRenderer->render(text, pos.x, pos.y); textRenderer->end(); - + glPopAttrib(); } @@ -827,14 +828,14 @@ void Renderer::renderLabel(const GraphicLabel *label){ } void Renderer::renderButton(const GraphicButton *button){ - + int x= button->getX(); int y= button->getY(); int h= button->getH(); int w= button->getW(); glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT); - + //background CoreData &coreData= CoreData::getInstance(); Texture2D *backTexture= w>3*h/2? coreData.getButtonBigTexture(): coreData.getButtonSmallTexture(); @@ -846,29 +847,29 @@ void Renderer::renderButton(const GraphicButton *button){ //button Vec4f color= Vec4f(1.f, 1.f, 1.f, GraphicComponent::getFade()); - glColor4fv(color.ptr()); + glColor4fv(color.ptr()); glBegin(GL_TRIANGLE_STRIP); glTexCoord2f(0.f, 0.f); glVertex2f(x, y); - + glTexCoord2f(0.f, 1.f); glVertex2f(x, y+h); - + glTexCoord2f(1.f, 0.f); glVertex2f(x+w, y); - + glTexCoord2f(1.f, 1.f); glVertex2f(x+w, y+h); - + glEnd(); glDisable(GL_TEXTURE_2D); - + //lighting float anim= GraphicComponent::getAnim(); - if(anim>0.5f) anim= 1.f-anim; - + if(anim>0.5f) anim= 1.f-anim; + if(button->getLighted()){ const int lightSize= 0; const Vec4f color1= Vec4f(1.f, 1.f, 1.f, 0.1f+anim*0.5f); @@ -884,7 +885,7 @@ void Renderer::renderButton(const GraphicButton *button){ glColor4fv(color1.ptr()); glVertex2f(x+w+lightSize, y-lightSize); - + glColor4fv(color1.ptr()); glVertex2f(x+w+lightSize, y+h+lightSize); @@ -899,11 +900,11 @@ void Renderer::renderButton(const GraphicButton *button){ glEnd(); } - + Vec2i textPos= Vec2i(x+w/2, y+h/2); renderText( - button->getText(), button->getFont(), GraphicButton::getFade(), + button->getText(), button->getFont(), GraphicButton::getFade(), x+w/2, y+h/2, true); glPopAttrib(); @@ -913,7 +914,7 @@ void Renderer::renderListBox(const GraphicListBox *listBox){ renderButton(listBox->getButton1()); renderButton(listBox->getButton2()); - + glPushAttrib(GL_ENABLE_BIT); glEnable(GL_BLEND); @@ -932,15 +933,15 @@ void Renderer::renderMessageBox(const GraphicMessageBox *messageBox){ glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT); glEnable(GL_BLEND); - glColor4f(0.0f, 0.0f, 0.0f, 0.5f) ; + glColor4f(0.0f, 0.0f, 0.0f, 0.5f) ; glBegin(GL_TRIANGLE_STRIP); glVertex2i(messageBox->getX(), messageBox->getY()+9*messageBox->getH()/10); glVertex2i(messageBox->getX(), messageBox->getY()); glVertex2i(messageBox->getX() + messageBox->getW(), messageBox->getY() + 9*messageBox->getH()/10); glVertex2i(messageBox->getX() + messageBox->getW(), messageBox->getY()); glEnd(); - - glColor4f(0.0f, 0.0f, 0.0f, 0.8f) ; + + glColor4f(0.0f, 0.0f, 0.0f, 0.8f) ; glBegin(GL_TRIANGLE_STRIP); glVertex2i(messageBox->getX(), messageBox->getY()+messageBox->getH()); glVertex2i(messageBox->getX(), messageBox->getY()+9*messageBox->getH()/10); @@ -949,24 +950,24 @@ void Renderer::renderMessageBox(const GraphicMessageBox *messageBox){ glEnd(); glBegin(GL_LINE_LOOP); - glColor4f(0.5f, 0.5f, 0.5f, 0.25f) ; + glColor4f(0.5f, 0.5f, 0.5f, 0.25f) ; glVertex2i(messageBox->getX(), messageBox->getY()); - - glColor4f(0.0f, 0.0f, 0.0f, 0.25f) ; + + glColor4f(0.0f, 0.0f, 0.0f, 0.25f) ; glVertex2i(messageBox->getX()+ messageBox->getW(), messageBox->getY()); - - glColor4f(0.5f, 0.5f, 0.5f, 0.25f) ; + + glColor4f(0.5f, 0.5f, 0.5f, 0.25f) ; glVertex2i(messageBox->getX()+ messageBox->getW(), messageBox->getY() + messageBox->getH()); - - glColor4f(0.25f, 0.25f, 0.25f, 0.25f) ; + + glColor4f(0.25f, 0.25f, 0.25f, 0.25f) ; glVertex2i(messageBox->getX(), messageBox->getY() + messageBox->getH()); glEnd(); glBegin(GL_LINE_STRIP); - glColor4f(1.0f, 1.0f, 1.0f, 0.25f) ; + glColor4f(1.0f, 1.0f, 1.0f, 0.25f) ; glVertex2i(messageBox->getX(), messageBox->getY() + 90*messageBox->getH()/100); - - glColor4f(0.5f, 0.5f, 0.5f, 0.25f) ; + + glColor4f(0.5f, 0.5f, 0.5f, 0.25f) ; glVertex2i(messageBox->getX()+ messageBox->getW(), messageBox->getY() + 90*messageBox->getH()/100); glEnd(); @@ -980,17 +981,17 @@ void Renderer::renderMessageBox(const GraphicMessageBox *messageBox){ //text renderText( - messageBox->getText(), messageBox->getFont(), Vec3f(1.0f, 1.0f, 1.0f), - messageBox->getX()+15, messageBox->getY()+7*messageBox->getH()/10, + messageBox->getText(), messageBox->getFont(), Vec3f(1.0f, 1.0f, 1.0f), + messageBox->getX()+15, messageBox->getY()+7*messageBox->getH()/10, false ); renderText( - messageBox->getHeader(), messageBox->getFont(),Vec3f(1.0f, 1.0f, 1.0f), - messageBox->getX()+15, messageBox->getY()+93*messageBox->getH()/100, + messageBox->getHeader(), messageBox->getFont(),Vec3f(1.0f, 1.0f, 1.0f), + messageBox->getX()+15, messageBox->getY()+93*messageBox->getH()/100, false ); } -// ==================== complex rendering ==================== +// ==================== complex rendering ==================== void Renderer::renderSurface(){ @@ -1016,15 +1017,15 @@ void Renderer::renderSurface(){ glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, static_cast(fowTex)->getHandle()); glTexSubImage2D( - GL_TEXTURE_2D, 0, 0, 0, - fowTex->getPixmap()->getW(), fowTex->getPixmap()->getH(), - GL_ALPHA, GL_UNSIGNED_BYTE, fowTex->getPixmap()->getPixels()); + GL_TEXTURE_2D, 0, 0, 0, + fowTex->getPixmap()->getW(), fowTex->getPixmap()->getH(), + GL_ALPHA, GL_UNSIGNED_BYTE, fowTex->getPixmap()->getPixels()); //shadow texture if(shadows==sProjected || shadows==sShadowMapping){ glActiveTexture(shadowTexUnit); glEnable(GL_TEXTURE_2D); - + glBindTexture(GL_TEXTURE_2D, shadowMapHandle); static_cast(modelRenderer)->setDuplicateTexCoords(true); @@ -1037,7 +1038,7 @@ void Renderer::renderSurface(){ PosQuadIterator pqi(map, scaledQuad); while(pqi.next()){ - + const Vec2i &pos= pqi.getPos(); if(mapBounds.isInside(pos)){ @@ -1046,7 +1047,7 @@ void Renderer::renderSurface(){ SurfaceCell *tc10= map->getSurfaceCell(pos.x+1, pos.y); SurfaceCell *tc01= map->getSurfaceCell(pos.x, pos.y+1); SurfaceCell *tc11= map->getSurfaceCell(pos.x+1, pos.y+1); - + triangleCount+= 2; pointCount+= 4; @@ -1098,7 +1099,7 @@ void Renderer::renderSurface(){ void Renderer::renderObjects(){ const World *world= game->getWorld(); - const Map *map= world->getMap(); + const Map *map= world->getMap(); assertGl(); const Texture2D *fowTex= world->getMinimap()->getFowTexture(); @@ -1109,7 +1110,7 @@ void Renderer::renderObjects(){ if(shadows==sShadowMapping){ glActiveTexture(shadowTexUnit); glEnable(GL_TEXTURE_2D); - + glBindTexture(GL_TEXTURE_2D, shadowMapHandle); static_cast(modelRenderer)->setDuplicateTexCoords(true); @@ -1151,7 +1152,7 @@ void Renderer::renderObjects(){ objModel->updateInterpolationData(0.f, true); modelRenderer->render(objModel); - + triangleCount+= objModel->getTriangleCount(); pointCount+= objModel->getVertexCount(); @@ -1169,7 +1170,7 @@ void Renderer::renderObjects(){ } void Renderer::renderWater(){ - + bool closed= false; const World *world= game->getWorld(); const Map *map= world->getMap(); @@ -1183,7 +1184,7 @@ void Renderer::renderWater(){ //water texture nit glDisable(GL_TEXTURE_2D); - + glEnable(GL_BLEND); if(textures3D){ Texture3D *waterTex= world->getTileset()->getWaterTex(); @@ -1214,12 +1215,12 @@ void Renderer::renderWater(){ float waterLevel= world->getMap()->getWaterLevel(); for(int j=scaledRect.p[0].y; jgetSurfaceCell(i, j); SurfaceCell *tc1= map->getSurfaceCell(i, j+1); - + int thisTeamIndex= world->getThisTeamIndex(); if(tc0->getNearSubmerged() && (tc0->isExplored(thisTeamIndex) || tc1->isExplored(thisTeamIndex))){ glNormal3f(0.f, 1.f, 0.f); @@ -1230,24 +1231,24 @@ void Renderer::renderWater(){ //vertex 1 glMaterialfv( - GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, + GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, computeWaterColor(waterLevel, tc1->getHeight()).ptr()); glMultiTexCoord2fv(GL_TEXTURE1, tc1->getFowTexCoord().ptr()); glTexCoord3f(i, 1.f, waterAnim); glVertex3f( - static_cast(i)*Map::mapScale, - waterLevel, + static_cast(i)*Map::mapScale, + waterLevel, static_cast(j+1)*Map::mapScale); - + //vertex 2 glMaterialfv( - GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, + GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, computeWaterColor(waterLevel, tc0->getHeight()).ptr()); glMultiTexCoord2fv(GL_TEXTURE1, tc0->getFowTexCoord().ptr()); - glTexCoord3f(i, 0.f, waterAnim); + glTexCoord3f(i, 0.f, waterAnim); glVertex3f( - static_cast(i)*Map::mapScale, - waterLevel, + static_cast(i)*Map::mapScale, + waterLevel, static_cast(j)*Map::mapScale); } @@ -1258,24 +1259,24 @@ void Renderer::renderWater(){ //vertex 1 glMaterialfv( - GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, + GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, computeWaterColor(waterLevel, tc1->getHeight()).ptr()); glMultiTexCoord2fv(GL_TEXTURE1, tc1->getFowTexCoord().ptr()); glTexCoord3f(i, 1.f, waterAnim); glVertex3f( - static_cast(i)*Map::mapScale, - waterLevel, + static_cast(i)*Map::mapScale, + waterLevel, static_cast(j+1)*Map::mapScale); - + //vertex 2 glMaterialfv( - GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, + GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, computeWaterColor(waterLevel, tc0->getHeight()).ptr()); glMultiTexCoord2fv(GL_TEXTURE1, tc0->getFowTexCoord().ptr()); - glTexCoord3f(i, 0.f, waterAnim); + glTexCoord3f(i, 0.f, waterAnim); glVertex3f( - static_cast(i)*Map::mapScale, - waterLevel, + static_cast(i)*Map::mapScale, + waterLevel, static_cast(j)*Map::mapScale); glEnd(); @@ -1303,11 +1304,11 @@ void Renderer::renderUnits(){ glPushAttrib(GL_ENABLE_BIT | GL_FOG_BIT | GL_LIGHTING_BIT | GL_TEXTURE_BIT); glEnable(GL_COLOR_MATERIAL); - + if(shadows==sShadowMapping){ glActiveTexture(shadowTexUnit); glEnable(GL_TEXTURE_2D); - + glBindTexture(GL_TEXTURE_2D, shadowMapHandle); static_cast(modelRenderer)->setDuplicateTexCoords(true); @@ -1322,14 +1323,14 @@ void Renderer::renderUnits(){ for(int j=0; jgetFaction(i)->getUnitCount(); ++j){ unit= world->getFaction(i)->getUnit(j); if(world->toRenderUnit(unit, visibleQuad)) { - + glMatrixMode(GL_MODELVIEW); glPushMatrix(); //translate Vec3f currVec= unit->getCurrVectorFlat(); glTranslatef(currVec.x, currVec.y, currVec.z); - + //rotate glRotatef(unit->getRotation(), 0.f, 1.f, 0.f); glRotatef(unit->getVerticalRotation(), 1.f, 0.f, 0.f); @@ -1345,10 +1346,10 @@ void Renderer::renderUnits(){ else{ glEnable(GL_COLOR_MATERIAL); } - + //render const Model *model= unit->getCurrentModel(); - model->updateInterpolationData(unit->getAnimProgress(), unit->isAlive()); + model->updateInterpolationData(unit->getAnimProgress(), unit->isAlive()); modelRenderer->render(model); triangleCount+= model->getTriangleCount(); @@ -1358,7 +1359,7 @@ void Renderer::renderUnits(){ } } } - modelRenderer->end(); + modelRenderer->end(); //restore static_cast(modelRenderer)->setDuplicateTexCoords(true); @@ -1372,7 +1373,7 @@ void Renderer::renderSelectionEffects(){ const World *world= game->getWorld(); const Map *map= world->getMap(); - const Selection *selection= game->getGui()->getSelection(); + const Selection *selection= game->getGui()->getSelection(); glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT); glDisable(GL_LIGHTING); @@ -1385,13 +1386,13 @@ void Renderer::renderSelectionEffects(){ //units for(int i=0; igetCount(); ++i){ - + const Unit *unit= selection->getUnit(i); //translate Vec3f currVec= unit->getCurrVectorFlat(); currVec.y+= 0.3f; - + //selection circle if(world->getThisFactionIndex()==unit->getFactionIndex()){ glColor4f(0, unit->getHpRatio(), 0, 0.3f); @@ -1400,23 +1401,23 @@ void Renderer::renderSelectionEffects(){ glColor4f(unit->getHpRatio(), 0, 0, 0.3f); } renderSelectionCircle(currVec, unit->getType()->getSize(), selectionCircleRadius); - + //magic circle if(world->getThisFactionIndex()==unit->getFactionIndex() && unit->getType()->getMaxEp()>0){ - glColor4f(unit->getEpRatio()/2.f, unit->getEpRatio(), unit->getEpRatio(), 0.5f); + glColor4f(unit->getEpRatio()/2.f, unit->getEpRatio(), unit->getEpRatio(), 0.5f); renderSelectionCircle(currVec, unit->getType()->getSize(), magicCircleRadius); } } //target arrow if(selection->getCount()==1){ - const Unit *unit= selection->getUnit(0); - + const Unit *unit= selection->getUnit(0); + //comand arrow - if(focusArrows && unit->anyCommand()){ + if(focusArrows && unit->anyCommand()){ const CommandType *ct= unit->getCurrCommand()->getCommandType(); if(ct->getClicks()!=cOne){ - + //arrow color Vec3f arrowColor; switch(ct->getClass()){ @@ -1438,7 +1439,7 @@ void Renderer::renderSelectionEffects(){ arrowTarget= c->getUnit()->getCurrVectorFlat(); } else{ - Vec2i pos= c->getPos(); + Vec2i pos= c->getPos(); arrowTarget= Vec3f(pos.x, map->getCell(pos)->getHeight(), pos.y); } @@ -1448,11 +1449,11 @@ void Renderer::renderSelectionEffects(){ //meeting point arrow if(unit->getType()->getMeetingPoint()){ - Vec2i pos= unit->getMeetingPos(); + Vec2i pos= unit->getMeetingPos(); Vec3f arrowTarget= Vec3f(pos.x, map->getCell(pos)->getHeight(), pos.y); renderArrow(unit->getCurrVectorFlat(), arrowTarget, Vec3f(0.f, 0.f, 1.f), 0.3f); } - + } //render selection hightlights @@ -1485,7 +1486,7 @@ void Renderer::renderWaterEffects(){ const Map *map= world->getMap(); const CoreData &coreData= CoreData::getInstance(); float height= map->getWaterLevel()+0.001f; - + assertGl(); glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT); @@ -1501,17 +1502,17 @@ void Renderer::renderWaterEffects(){ glBindTexture(GL_TEXTURE_2D, static_cast(coreData.getWaterSplashTexture())->getHandle()); for(int i=0; igetWaterSplashCount(); ++i){ const WaterSplash *ws= we->getWaterSplash(i); - + //render only if enabled if(ws->getEnabled()){ - + //render only if visible Vec2i intPos= Vec2i(static_cast(ws->getPos().x), static_cast(ws->getPos().y)); if(map->getSurfaceCell(Map::toSurfCoords(intPos))->isVisible(world->getThisTeamIndex())){ float scale= ws->getAnim(); - - glColor4f(1.f, 1.f, 1.f, 1.f-ws->getAnim()); + + glColor4f(1.f, 1.f, 1.f, 1.f-ws->getAnim()); glBegin(GL_TRIANGLE_STRIP); glTexCoord2f(0.f, 1.f); glVertex3f(ws->getPos().x-scale, height, ws->getPos().y+scale); @@ -1542,9 +1543,9 @@ void Renderer::renderMinimap(){ int my= metrics.getMinimapY(); int mw= metrics.getMinimapW(); int mh= metrics.getMinimapH(); - + Vec2f zoom= Vec2f( - static_cast(mw)/ pixmap->getW(), + static_cast(mw)/ pixmap->getW(), static_cast(mh)/ pixmap->getH()); assertGl(); @@ -1554,12 +1555,12 @@ void Renderer::renderMinimap(){ //draw map glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); - + glActiveTexture(fowTexUnit); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, static_cast(minimap->getFowTexture())->getHandle()); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR); @@ -1571,7 +1572,7 @@ void Renderer::renderMinimap(){ glActiveTexture(baseTexUnit); glBindTexture(GL_TEXTURE_2D, static_cast(minimap->getTexture())->getHandle()); - + glColor4f(0.5f, 0.5f, 0.5f, 0.1f); glBegin(GL_TRIANGLE_STRIP); glTexCoord2f(0.0f, 1.0f); @@ -1589,12 +1590,12 @@ void Renderer::renderMinimap(){ glEnd(); glDisable(GL_BLEND); - + glActiveTexture(fowTexUnit); glDisable(GL_TEXTURE_2D); glActiveTexture(baseTexUnit); glDisable(GL_TEXTURE_2D); - + //draw units glBegin(GL_QUADS); for(int i=0; igetFactionCount(); ++i){ @@ -1602,13 +1603,13 @@ void Renderer::renderMinimap(){ Unit *unit= world->getFaction(i)->getUnit(j); if(world->toRenderUnit(unit)){ Vec2i pos= unit->getPos()/Map::cellScale; - int size= unit->getType()->getSize(); + int size= unit->getType()->getSize(); Vec3f color= world->getFaction(i)->getTexture()->getPixmap()->getPixel3f(0, 0); glColor3fv(color.ptr()); - glVertex2f(mx + pos.x*zoom.x, my + mh - (pos.y*zoom.y)); - glVertex2f(mx + (pos.x+1)*zoom.x+size, my + mh - (pos.y*zoom.y)); - glVertex2f(mx + (pos.x+1)*zoom.x+size, my + mh - ((pos.y+size)*zoom.y)); - glVertex2f(mx + pos.x*zoom.x, my + mh - ((pos.y+size)*zoom.y)); + glVertex2f(mx + pos.x*zoom.x, my + mh - (pos.y*zoom.y)); + glVertex2f(mx + (pos.x+1)*zoom.x+size, my + mh - (pos.y*zoom.y)); + glVertex2f(mx + (pos.x+1)*zoom.x+size, my + mh - ((pos.y+size)*zoom.y)); + glVertex2f(mx + pos.x*zoom.x, my + mh - ((pos.y+size)*zoom.y)); } } } @@ -1624,19 +1625,19 @@ void Renderer::renderMinimap(){ float ang= degToRad(gameCamera->getHAng()); glEnable(GL_BLEND); - + glBegin(GL_TRIANGLES); glColor4f(1.f, 1.f, 1.f, 1.f); glVertex2i(mx+x, my+mh-y); - + glColor4f(1.f, 1.f, 1.f, 0.0f); glVertex2i( - mx + x + static_cast(20*sin(ang-pi/5)), + mx + x + static_cast(20*sin(ang-pi/5)), my + mh - (y-static_cast(20*cos(ang-pi/5)))); - + glColor4f(1.f, 1.f, 1.f, 0.0f); glVertex2i( - mx + x + static_cast(20*sin(ang+pi/5)), + mx + x + static_cast(20*sin(ang+pi/5)), my + mh - (y-static_cast(20*cos(ang+pi/5)))); glEnd(); @@ -1646,45 +1647,45 @@ void Renderer::renderMinimap(){ } void Renderer::renderDisplay(){ - + CoreData &coreData= CoreData::getInstance(); const Metrics &metrics= Metrics::getInstance(); const Display *display= game->getGui()->getDisplay(); glPushAttrib(GL_ENABLE_BIT); - + //infoString renderTextShadow( - display->getInfoText().c_str(), + display->getInfoText().c_str(), coreData.getDisplayFont(), - metrics.getDisplayX(), + metrics.getDisplayX(), metrics.getDisplayY()+Display::infoStringY); //title renderTextShadow( - display->getTitle().c_str(), + display->getTitle().c_str(), coreData.getDisplayFont(), - metrics.getDisplayX()+40, + metrics.getDisplayX()+40, metrics.getDisplayY() + metrics.getDisplayH() - 20); glColor3f(0.0f, 0.0f, 0.0f); //text renderTextShadow( - display->getText().c_str(), + display->getText().c_str(), coreData.getDisplayFont(), - metrics.getDisplayX() -1, + metrics.getDisplayX() -1, metrics.getDisplayY() + metrics.getDisplayH() - 56); //progress Bar if(display->getProgressBar()!=-1){ renderProgressBar( display->getProgressBar(), - metrics.getDisplayX(), - metrics.getDisplayY() + metrics.getDisplayH()-50, + metrics.getDisplayX(), + metrics.getDisplayY() + metrics.getDisplayH()-50, coreData.getMenuFontSmall()); } - + //up images glEnable(GL_TEXTURE_2D); @@ -1692,8 +1693,8 @@ void Renderer::renderDisplay(){ for(int i=0; igetUpImage(i)!=NULL){ renderQuad( - metrics.getDisplayX()+display->computeUpX(i), - metrics.getDisplayY()+display->computeUpY(i), + metrics.getDisplayX()+display->computeUpX(i), + metrics.getDisplayY()+display->computeUpY(i), Display::imageSize, Display::imageSize, display->getUpImage(i)); } } @@ -1707,7 +1708,7 @@ void Renderer::renderDisplay(){ else{ glColor3f(0.3f, 0.3f, 0.3f); } - + int x= metrics.getDisplayX()+display->computeDownX(i); int y= metrics.getDisplayY()+display->computeDownY(i); int size= Display::imageSize; @@ -1738,11 +1739,11 @@ void Renderer::renderDisplay(){ } void Renderer::renderMenuBackground(const MenuBackground *menuBackground){ - + assertGl(); Vec3f cameraPosition= menuBackground->getCamera()->getPosition(); - + glPushAttrib(GL_LIGHTING_BIT | GL_ENABLE_BIT | GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT); //clear @@ -1770,7 +1771,7 @@ void Renderer::renderMenuBackground(const MenuBackground *menuBackground){ modelRenderer->render(menuBackground->getMainModel()); modelRenderer->end(); glDisable(GL_ALPHA_TEST); - + //characters float dist= menuBackground->getAboutPosition().dist(cameraPosition); float minDist= 3.f; @@ -1780,7 +1781,7 @@ void Renderer::renderMenuBackground(const MenuBackground *menuBackground){ float alpha= clamp((minDist-dist)/minDist, 0.f, 1.f); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Vec4f(1.0f, 1.0f, 1.0f, alpha).ptr()); modelRenderer->begin(true, true, false); - + for(int i=0; i(coreData.getWaterSplashTexture())->getHandle()); for(int i=0; igetRaindropPos(i); float scale= menuBackground->getRaindropState(i); float alpha= maxRaindropAlpha-scale*maxRaindropAlpha; - + glMatrixMode(GL_MODELVIEW); glPushMatrix(); - + glColor4f(1.f, 1.f, 1.f, alpha); glTranslatef(pos.x, waterHeight+0.01f, pos.y); @@ -1865,22 +1866,22 @@ void Renderer::renderMenuBackground(const MenuBackground *menuBackground){ assertGl(); } -// ==================== computing ==================== +// ==================== computing ==================== bool Renderer::computePosition(const Vec2i &screenPos, Vec2i &worldPos){ - + assertGl(); const Map* map= game->getWorld()->getMap(); const Metrics &metrics= Metrics::getInstance(); float depth= 0.0f; - GLdouble modelviewMatrix[16]; + GLdouble modelviewMatrix[16]; GLdouble projectionMatrix[16]; GLint viewport[4]= {0, 0, metrics.getScreenW(), metrics.getScreenH()}; GLdouble worldX; GLdouble worldY; GLdouble worldZ; GLint screenX= (screenPos.x * metrics.getScreenW() / metrics.getVirtualW()); - GLint screenY= (screenPos.y * metrics.getScreenH() / metrics.getVirtualH()); + GLint screenY= (screenPos.y * metrics.getScreenH() / metrics.getVirtualH()); //get the depth in the cursor pixel glReadPixels(screenX, screenY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth); @@ -1895,19 +1896,19 @@ bool Renderer::computePosition(const Vec2i &screenPos, Vec2i &worldPos){ //get the world coordinates gluUnProject( - screenX, screenY, depth, + screenX, screenY, depth, modelviewMatrix, projectionMatrix, viewport, &worldX, &worldY, &worldZ); //conver coords to int worldPos= Vec2i(static_cast(worldX+0.5f), static_cast(worldZ+0.5f)); - + //clamp coords to map size return map->isInside(worldPos); } void Renderer::computeSelected(Selection::UnitContainer &units, const Vec2i &posDown, const Vec2i &posUp){ - + //declarations GLuint selectBuffer[Gui::maxSelBuff]; const Metrics &metrics= Metrics::getInstance(); @@ -1945,7 +1946,7 @@ void Renderer::computeSelected(Selection::UnitContainer &units, const Vec2i &pos int unitIndex= selectBuffer[i*5-1]; const World *world= game->getWorld(); if(factionIndexgetFactionCount() && unitIndexgetFaction(factionIndex)->getUnitCount()){ - Unit *unit= world->getFaction(factionIndex)->getUnit(unitIndex); + Unit *unit= world->getFaction(factionIndex)->getUnit(unitIndex); if(unit->isAlive()){ units.push_back(unit); } @@ -1954,7 +1955,7 @@ void Renderer::computeSelected(Selection::UnitContainer &units, const Vec2i &pos } -// ==================== shadows ==================== +// ==================== shadows ==================== void Renderer::renderShadowsToTexture(){ @@ -1975,7 +1976,7 @@ void Renderer::renderShadowsToTexture(){ float color= 1.0f-shadowAlpha; glColor3f(color, color, color); glClearColor(1.f, 1.f, 1.f, 1.f); - glDisable(GL_DEPTH_TEST); + glDisable(GL_DEPTH_TEST); glClear(GL_COLOR_BUFFER_BIT); } @@ -1983,14 +1984,14 @@ void Renderer::renderShadowsToTexture(){ // //set viewport, we leave one texel always in white to avoid problems glViewport(1, 1, shadowTextureSize-2, shadowTextureSize-2); - + if(nearestLightPos.w==0.f){ //directional light - + //light pos const TimeFlow *tf= game->getWorld()->getTimeFlow(); float ang= tf->isDay()? computeSunAngle(tf->getTime()): computeMoonAngle(tf->getTime()); - ang= radToDeg(ang); + ang= radToDeg(ang); //push and set projection glMatrixMode(GL_PROJECTION); @@ -2007,19 +2008,19 @@ void Renderer::renderShadowsToTexture(){ glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); - + glRotatef(15, 0, 1, 0); - + glRotatef(ang, 1, 0, 0); glRotatef(90, 0, 1, 0); Vec3f pos= game->getGameCamera()->getPos(); - + glTranslatef(static_cast(-pos.x), 0, static_cast(-pos.z)); } else{ //non directional light - + //push projection glMatrixMode(GL_PROJECTION); glPushMatrix(); @@ -2033,7 +2034,7 @@ void Renderer::renderShadowsToTexture(){ glRotatef(-90, -1, 0, 0); glTranslatef(-nearestLightPos.x, -nearestLightPos.y-2, -nearestLightPos.z); } - + if(shadows==sShadowMapping){ glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(1.0f, 0.001f); @@ -2042,7 +2043,7 @@ void Renderer::renderShadowsToTexture(){ //render 3d renderUnitsFast(); renderObjectsFast(); - + //read color buffer glBindTexture(GL_TEXTURE_2D, shadowMapHandle); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, shadowTextureSize, shadowTextureSize); @@ -2085,12 +2086,12 @@ void Renderer::renderShadowsToTexture(){ } -// ==================== gl wrap ==================== +// ==================== gl wrap ==================== string Renderer::getGlInfo(){ string infoStr; Lang &lang= Lang::getInstance(); - + infoStr+= lang.get("OpenGlInfo")+":\n"; infoStr+= " "+lang.get("OpenGlVersion")+": "; infoStr+= string(getGlVersion())+"\n"; @@ -2115,10 +2116,10 @@ string Renderer::getGlInfo(){ string Renderer::getGlMoreInfo(){ string infoStr; Lang &lang= Lang::getInstance(); - + //gl extensions infoStr+= lang.get("OpenGlExtensions")+":\n "; - + string extensions= getGlExtensions(); int charCount= 0; for(int i=0; igetWorld()->getTileset(); Vec3f color; - + const float transition= 2; const float dayStart= TimeFlow::dawn; const float dayEnd= TimeFlow::dusk-transition; @@ -2265,7 +2266,7 @@ Vec3f Renderer::computeLightColor(float time){ const float nightEnd= TimeFlow::dawn-transition; if(time>dayStart && timegetSunLightColor(); + color= tileset->getSunLightColor(); } else if(time>nightStart || timegetMoonLightColor(); @@ -2288,12 +2289,12 @@ Vec4f Renderer::computeWaterColor(float waterLevel, float cellHeight){ return Vec4f(1.f, 1.f, 1.f, clamp((waterLevel-cellHeight)*waterFactor, 0.f, 1.f)); } -// ==================== fast render ==================== +// ==================== fast render ==================== //render units for selection purposes void Renderer::renderUnitsFast(){ const World *world= game->getWorld(); - + assertGl(); glPushAttrib(GL_ENABLE_BIT); @@ -2316,7 +2317,7 @@ void Renderer::renderUnitsFast(){ //translate Vec3f currVec= unit->getCurrVectorFlat(); glTranslatef(currVec.x, currVec.y, currVec.z); - + //rotate glRotatef(unit->getRotation(), 0.f, 1.f, 0.f); @@ -2340,7 +2341,7 @@ void Renderer::renderUnitsFast(){ //render objects for selection purposes void Renderer::renderObjectsFast(){ const World *world= game->getWorld(); - const Map *map= world->getMap(); + const Map *map= world->getMap(); assertGl(); @@ -2350,12 +2351,12 @@ void Renderer::renderObjectsFast(){ glAlphaFunc(GL_GREATER, 0.5f); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - - //set color to the texture alpha + + //set color to the texture alpha glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); - + //set alpha to the texture alpha glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE); @@ -2383,7 +2384,7 @@ void Renderer::renderObjectsFast(){ glRotatef(o->getRotation(), 0.f, 1.f, 0.f); modelRenderer->render(objModel); - + glPopMatrix(); } @@ -2397,7 +2398,7 @@ void Renderer::renderObjectsFast(){ assertGl(); } -// ==================== gl caps ==================== +// ==================== gl caps ==================== void Renderer::checkGlCaps(){ @@ -2420,7 +2421,7 @@ void Renderer::checkGlCaps(){ } void Renderer::checkGlOptionalCaps(){ - + //shadows if(shadows==sProjected || shadows==sShadowMapping){ if(getGlMaxTextureUnits()<3){ @@ -2442,7 +2443,7 @@ void Renderer::checkExtension(const string &extension, const string &msg){ } } -// ==================== init 3d lists ==================== +// ==================== init 3d lists ==================== void Renderer::init3dList(){ @@ -2451,14 +2452,14 @@ void Renderer::init3dList(){ assertGl(); list3d= glGenLists(1); - glNewList(list3d, GL_COMPILE_AND_EXECUTE); + glNewList(list3d, GL_COMPILE_AND_EXECUTE); //need to execute, because if not gluPerspective takes no effect and gluLoadMatrix is wrong //misc glViewport(0, 0, metrics.getScreenW(), metrics.getScreenH()); - glClearColor(fowColor.x, fowColor.y, fowColor.z, fowColor.w); - glFrontFace(GL_CW); - glEnable(GL_CULL_FACE); + glClearColor(fowColor.x, fowColor.y, fowColor.z, fowColor.w); + glFrontFace(GL_CW); + glEnable(GL_CULL_FACE); loadProjectionMatrix(); //texture state @@ -2469,7 +2470,7 @@ void Renderer::init3dList(){ glActiveTexture(fowTexUnit); glDisable(GL_TEXTURE_2D); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - + glActiveTexture(baseTexUnit); glEnable(GL_TEXTURE_2D); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); @@ -2478,7 +2479,7 @@ void Renderer::init3dList(){ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, defSpecularColor.ptr()); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, defAmbientColor.ptr()); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, defDiffuseColor.ptr()); - glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); + glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); glColor4fv(defColor.ptr()); //blend state @@ -2523,7 +2524,7 @@ void Renderer::init3dList(){ //assert assertGl(); - + } void Renderer::init2dList(){ @@ -2539,7 +2540,7 @@ void Renderer::init2dList(){ glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, metrics.getVirtualW(), 0, metrics.getVirtualH(), 0, 1); - + //modelview glMatrixMode(GL_MODELVIEW); glLoadIdentity(); @@ -2551,12 +2552,12 @@ void Renderer::init2dList(){ glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); glDisable(GL_FOG); - glDisable(GL_CULL_FACE); + glDisable(GL_CULL_FACE); glFrontFace(GL_CCW); glActiveTexture(baseTexUnit); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glDisable(GL_TEXTURE_2D); - + //blend func glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -2575,28 +2576,28 @@ void Renderer::init3dListMenu(MainMenu *mm){ const MenuBackground *mb= mm->getMenuBackground(); list3dMenu= glGenLists(1); - glNewList(list3dMenu, GL_COMPILE); - + glNewList(list3dMenu, GL_COMPILE); + //misc glViewport(0, 0, metrics.getScreenW(), metrics.getScreenH()); - glClearColor(0.4f, 0.4f, 0.4f, 1.f); - glFrontFace(GL_CW); - glEnable(GL_CULL_FACE); + glClearColor(0.4f, 0.4f, 0.4f, 1.f); + glFrontFace(GL_CW); + glEnable(GL_CULL_FACE); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(perspFov, metrics.getAspectRatio(), perspNearPlane, 1000); - + //texture state glEnable(GL_TEXTURE_2D); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - + //material state glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, defSpecularColor.ptr()); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, defAmbientColor.ptr()); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, defDiffuseColor.ptr()); glColor4fv(defColor.ptr()); - glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); - + glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); + //blend state glDisable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -2619,13 +2620,13 @@ void Renderer::init3dListMenu(MainMenu *mm){ //stencil test glDisable(GL_STENCIL_TEST); - //fog + //fog if(mb->getFog()){ glEnable(GL_FOG); glFogi(GL_FOG_MODE, GL_EXP2); glFogf(GL_FOG_DENSITY, mb->getFogDensity()); } - + glEndList(); //assert @@ -2633,7 +2634,7 @@ void Renderer::init3dListMenu(MainMenu *mm){ } -// ==================== misc ==================== +// ==================== misc ==================== void Renderer::loadProjectionMatrix(){ GLdouble clipping; @@ -2641,8 +2642,8 @@ void Renderer::loadProjectionMatrix(){ assertGl(); - clipping= photoMode ? perspFarPlane*100 : perspFarPlane; - + clipping= photoMode ? perspFarPlane*100 : perspFarPlane; + glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(perspFov, metrics.getAspectRatio(), perspNearPlane, clipping); @@ -2661,14 +2662,14 @@ void Renderer::enableProjectiveTexturing(){ glEnable(GL_TEXTURE_GEN_Q); } -// ==================== private aux drawing ==================== +// ==================== private aux drawing ==================== void Renderer::renderSelectionCircle(Vec3f v, int size, float radius){ GLUquadricObj *disc; - + glMatrixMode(GL_MODELVIEW); glPushMatrix(); - + glTranslatef(v.x, v.y, v.z); glRotatef(90.f, 1.f, 0.f, 0.f); disc= gluNewQuadric(); @@ -2695,7 +2696,7 @@ void Renderer::renderArrow(const Vec3f &pos1, const Vec3f &pos2, const Vec3f &co dir.normalize(); Vec3f normal= dir.cross(Vec3f(0, 1, 0)); - + Vec3f pos2Left= pos2 + normal*(width-0.05f) - dir*arrowEndSize*width; Vec3f pos2Right= pos2 - normal*(width-0.05f) - dir*arrowEndSize*width; Vec3f pos1Left= pos1 + normal*(width+0.05f); @@ -2708,11 +2709,11 @@ void Renderer::renderArrow(const Vec3f &pos1, const Vec3f &pos2, const Vec3f &co Vec3f a= pos1Left.lerp(t, pos2Left); Vec3f b= pos1Right.lerp(t, pos2Right); Vec4f c= Vec4f(color, t*0.25f*alphaFactor); - + glColor4fv(c.ptr()); glVertex3fv(a.ptr()); glVertex3fv(b.ptr()); - } + } glEnd(); //arrow end @@ -2724,7 +2725,7 @@ void Renderer::renderArrow(const Vec3f &pos1, const Vec3f &pos2, const Vec3f &co } void Renderer::renderProgressBar(int size, int x, int y, Font2D *font){ - + //bar glBegin(GL_QUADS); glColor4fv(progressBarFront2.ptr()); @@ -2734,7 +2735,7 @@ void Renderer::renderProgressBar(int size, int x, int y, Font2D *font){ glVertex2i(x+size, y+10); glVertex2i(x+size, y); glEnd(); - + //transp bar glEnable(GL_BLEND); glBegin(GL_QUADS); @@ -2750,47 +2751,47 @@ void Renderer::renderProgressBar(int size, int x, int y, Font2D *font){ //text glColor3fv(defColor.ptr()); textRenderer->begin(font); - textRenderer->render(intToStr(static_cast(size))+"%", x+maxProgressBar/2, y, true); + textRenderer->render(intToStr(static_cast(size))+"%", x+maxProgressBar/2, y, true); textRenderer->end(); } void Renderer::renderTile(const Vec2i &pos){ - + const Map *map= game->getWorld()->getMap(); Vec2i scaledPos= pos * Map::cellScale; glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef(-0.5f, 0.f, -0.5f); - + glInitNames(); for(int i=0; i(renderPos.x), - map->getCell(renderPos.x, renderPos.y)->getHeight(), + static_cast(renderPos.x), + map->getCell(renderPos.x, renderPos.y)->getHeight(), static_cast(renderPos.y)); glVertex3f( - static_cast(renderPos.x), - map->getCell(renderPos.x, renderPos.y+1)->getHeight(), + static_cast(renderPos.x), + map->getCell(renderPos.x, renderPos.y+1)->getHeight(), static_cast(renderPos.y+1)); glVertex3f( - static_cast(renderPos.x+1), - map->getCell(renderPos.x+1, renderPos.y)->getHeight(), + static_cast(renderPos.x+1), + map->getCell(renderPos.x+1, renderPos.y)->getHeight(), static_cast(renderPos.y)); glVertex3f( - static_cast(renderPos.x+1), - map->getCell(renderPos.x+1, renderPos.y+1)->getHeight(), + static_cast(renderPos.x+1), + map->getCell(renderPos.x+1, renderPos.y+1)->getHeight(), static_cast(renderPos.y+1)); glEnd(); @@ -2847,7 +2848,7 @@ Texture2D::Filter Renderer::strToTextureFilter(const string &s){ else if(s=="Trilinear"){ return Texture2D::fTrilinear; } - + throw runtime_error("Error converting from string to FilterType, found: "+s); } diff --git a/source/glest_game/main/battle_end.cpp b/source/glest_game/main/battle_end.cpp index 4cde18a25..9cc72e49d 100644 --- a/source/glest_game/main/battle_end.cpp +++ b/source/glest_game/main/battle_end.cpp @@ -1,7 +1,7 @@ // ============================================================== // This file is part of Glest (www.glest.org) // -// Copyright (C) 2001-2008 Marti�o Figueroa +// 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 diff --git a/source/glest_game/main/program.cpp b/source/glest_game/main/program.cpp index 2678a6f76..2faa44802 100644 --- a/source/glest_game/main/program.cpp +++ b/source/glest_game/main/program.cpp @@ -3,9 +3,9 @@ // // 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 +// 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 // ============================================================== @@ -41,7 +41,7 @@ namespace Glest{ namespace Game{ const int Program::maxTimes= 10; -// ===================== PUBLIC ======================== +// ===================== PUBLIC ======================== Program::Program(){ programState= NULL; @@ -54,7 +54,7 @@ void Program::initNormal(WindowGl *window){ void Program::initServer(WindowGl *window){ MainMenu* mainMenu= NULL; - + init(window); mainMenu= new MainMenu(this); setState(mainMenu); @@ -63,7 +63,7 @@ void Program::initServer(WindowGl *window){ void Program::initClient(WindowGl *window, const Ip &serverIp){ MainMenu* mainMenu= NULL; - + init(window); mainMenu= new MainMenu(this); setState(mainMenu); @@ -72,14 +72,14 @@ void Program::initClient(WindowGl *window, const Ip &serverIp){ Program::~Program(){ delete programState; - + Renderer::getInstance().end(); - + //restore video mode restoreDisplaySettings(); } -void Program::mouseDownLeft(int x, int y){ +void Program::mouseDownLeft(int x, int y){ const Metrics &metrics= Metrics::getInstance(); programState->mouseDownLeft(metrics.toVirtualX(x), metrics.toVirtualY(y)); } @@ -91,12 +91,12 @@ void Program::mouseUpLeft(int x, int y){ void Program::mouseDownRight(int x, int y){ const Metrics &metrics= Metrics::getInstance(); - programState->mouseDownRight(metrics.toVirtualX(x), metrics.toVirtualY(y)); + programState->mouseDownRight(metrics.toVirtualX(x), metrics.toVirtualY(y)); } void Program::mouseDoubleClickLeft(int x, int y){ const Metrics &metrics= Metrics::getInstance(); - programState->mouseDoubleClickLeft(metrics.toVirtualX(x), metrics.toVirtualY(y)); + programState->mouseDoubleClickLeft(metrics.toVirtualX(x), metrics.toVirtualY(y)); } void Program::mouseMove(int x, int y, const MouseState *ms){ @@ -109,7 +109,7 @@ void Program::keyDown(char key){ programState->keyDown(key); } -void Program::keyUp(char key){ +void Program::keyUp(char key){ programState->keyUp(key); } @@ -134,7 +134,7 @@ void Program::loop(){ SoundRenderer::getInstance().update(); NetworkManager::getInstance().update(); } - + //fps timer while(fpsTimer.isTime()){ programState->tick(); @@ -142,7 +142,7 @@ void Program::loop(){ } void Program::resize(SizeState sizeState){ - + switch(sizeState){ case ssMinimized: //restoreVideoMode(); @@ -155,32 +155,44 @@ void Program::resize(SizeState sizeState){ } } -// ==================== misc ==================== +// ==================== misc ==================== + +void Program::setState(ProgramState *programState) +{ + + if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__); -void Program::setState(ProgramState *programState){ - delete this->programState; - + + if(Socket::enableDebugText) printf("In [%s::%s] A\n",__FILE__,__FUNCTION__); + this->programState= programState; programState->load(); + + if(Socket::enableDebugText) printf("In [%s::%s] B\n",__FILE__,__FUNCTION__); + programState->init(); + if(Socket::enableDebugText) printf("In [%s::%s] C\n",__FILE__,__FUNCTION__); + updateTimer.reset(); updateCameraTimer.reset(); fpsTimer.reset(); + + if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__); } - + void Program::exit(){ window->destroy(); } -// ==================== PRIVATE ==================== +// ==================== PRIVATE ==================== void Program::init(WindowGl *window){ this->window= window; Config &config= Config::getInstance(); - + //set video mode setDisplaySettings(); @@ -190,7 +202,7 @@ void Program::init(WindowGl *window){ window->setPos(0, 0); window->setSize(config.getInt("ScreenWidth"), config.getInt("ScreenHeight")); window->create(); - + //timers fpsTimer.init(1, maxTimes); updateTimer.init(GameConstants::updateFps, maxTimes); @@ -204,13 +216,13 @@ void Program::init(WindowGl *window){ //lang Lang &lang= Lang::getInstance(); lang.loadStrings(config.getString("Lang")); - + //render Renderer &renderer= Renderer::getInstance(); window->initGl(config.getInt("ColorBits"), config.getInt("DepthBits"), config.getInt("StencilBits")); window->makeCurrentGl(); - + //coreData, needs renderer, but must load before renderer init CoreData &coreData= CoreData::getInstance(); coreData.load(); @@ -226,29 +238,29 @@ void Program::init(WindowGl *window){ void Program::setDisplaySettings(){ Config &config= Config::getInstance(); - + if(!config.getBool("Windowed")){ - + int freq= config.getInt("RefreshFrequency"); int colorBits= config.getInt("ColorBits"); int screenWidth= config.getInt("ScreenWidth"); int screenHeight= config.getInt("ScreenHeight"); - + if(!(changeVideoMode(screenWidth, screenHeight, colorBits, freq) || changeVideoMode(screenWidth, screenHeight, colorBits, 0))) { throw runtime_error( - "Error setting video mode: " + + "Error setting video mode: " + intToStr(screenWidth) + "x" + intToStr(screenHeight) + "x" + intToStr(colorBits)); - } + } } } void Program::restoreDisplaySettings(){ Config &config= Config::getInstance(); - + if(!config.getBool("Windowed")){ - restoreVideoMode(); + restoreVideoMode(); } } diff --git a/source/glest_game/menu/menu_state_custom_game.cpp b/source/glest_game/menu/menu_state_custom_game.cpp index 1f126e564..f063f0b7d 100644 --- a/source/glest_game/menu/menu_state_custom_game.cpp +++ b/source/glest_game/menu/menu_state_custom_game.cpp @@ -1,11 +1,11 @@ // ============================================================== // This file is part of Glest (www.glest.org) // -// Copyright (C) 2001-2005 Marti�o Figueroa +// Copyright (C) 2001-2005 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 +// 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 // ============================================================== @@ -25,6 +25,7 @@ #include "game.h" #include "leak_dumper.h" +#include namespace Glest{ namespace Game{ @@ -34,12 +35,15 @@ using namespace Shared::Util; // class MenuStateCustomGame // ===================================================== -MenuStateCustomGame::MenuStateCustomGame(Program *program, MainMenu *mainMenu, bool openNetworkSlots): +MenuStateCustomGame::MenuStateCustomGame(Program *program, MainMenu *mainMenu, bool openNetworkSlots): MenuState(program, mainMenu, "new-game") { Lang &lang= Lang::getInstance(); NetworkManager &networkManager= NetworkManager::getInstance(); + needToSetChangedGameSettings = false; + lastSetChangedGameSettings = time(NULL);; + vector results, teamItems, controlItems; //create @@ -121,12 +125,12 @@ MenuStateCustomGame::MenuStateCustomGame(Program *program, MainMenu *mainMenu, b if(results.size()==0){ throw runtime_error("There is no factions for this tech tree"); } - + for(int i=0; isetState(new MenuStateNewGame(program, mainMenu)); - } - else if(buttonPlayNow.mouseClick(x,y)){ - GameSettings gameSettings; - + } + else if(buttonPlayNow.mouseClick(x,y) && buttonPlayNow.getEnabled()) { + closeUnusedSlots(); soundRenderer.playFx(coreData.getClickSoundC()); + + GameSettings gameSettings; loadGameSettings(&gameSettings); - serverInterface->launchGame(&gameSettings); - program->setState(new Game(program, &gameSettings)); + + // Send the game settings to each client if we have at least one networked client + if( hasNetworkGameSettings() == true && + needToSetChangedGameSettings == true) + { + serverInterface->setGameSettings(&gameSettings,true); + + needToSetChangedGameSettings = false; + lastSetChangedGameSettings = time(NULL); + } + + bool bOkToStart = serverInterface->launchGame(&gameSettings); + if(bOkToStart == true) + { + + program->setState(new Game(program, &gameSettings)); + } } else if(listBoxMap.mouseClick(x, y)){ loadMapInfo(Map::getMapPath(mapFiles[listBoxMap.getSelectedItemIndex()]), &mapInfo); labelMapInfo.setText(mapInfo.desc); updateControlers(); + + if(hasNetworkGameSettings() == true) + { + needToSetChangedGameSettings = true; + lastSetChangedGameSettings = time(NULL);; + } } else if(listBoxTileset.mouseClick(x, y)){ + + if(hasNetworkGameSettings() == true) + { + needToSetChangedGameSettings = true; + lastSetChangedGameSettings = time(NULL);; + } } else if(listBoxTechTree.mouseClick(x, y)){ reloadFactions(); - } - else{ - for(int i=0; igetSlot(i); assert(connectionSlot!=NULL); - - if(connectionSlot->isConnected()){ - labelNetStatus[i].setText(connectionSlot->getName()); + + //if(Socket::enableDebugText) printf("In [%s::%s] A - ctNetwork\n",__FILE__,__FUNCTION__); + + if(connectionSlot->isConnected()) + { + haveAtLeastOneNetworkClientConnected = true; + //if(Socket::enableDebugText) printf("In [%s::%s] B - ctNetwork\n",__FILE__,__FUNCTION__); + + string label = connectionSlot->getName(); + if(connectionSlot->getAllowDownloadDataSynch() == true && + connectionSlot->getAllowGameDataSynchCheck() == true) + { + if(connectionSlot->getNetworkGameDataSynchCheckOk() == false) + { + label = connectionSlot->getName() + " - waiting to synch:"; + if(connectionSlot->getNetworkGameDataSynchCheckOkMap() == false) + { + label = label + " map"; + } + if(connectionSlot->getNetworkGameDataSynchCheckOkTile() == false) + { + label = label + " tile"; + } + if(connectionSlot->getNetworkGameDataSynchCheckOkTech() == false) + { + label = label + " techtree"; + } + if(connectionSlot->getNetworkGameDataSynchCheckOkFogOfWar() == false) + { + label = label + " FogOfWar == false"; + } + + } + else + { + label = connectionSlot->getName() + " - data synch is ok"; + } + } + else + { + label = connectionSlot->getName(); + + if(connectionSlot->getAllowGameDataSynchCheck() == true) + { + label += " - warning synch mismatch for:"; + if(connectionSlot->getNetworkGameDataSynchCheckOkMap() == false) + { + label = label + " map"; + } + if(connectionSlot->getNetworkGameDataSynchCheckOkTile() == false) + { + label = label + " tile"; + } + if(connectionSlot->getNetworkGameDataSynchCheckOkTech() == false) + { + label = label + " techtree"; + } + if(connectionSlot->getNetworkGameDataSynchCheckOkFogOfWar() == false) + { + label = label + " FogOfWar == false"; + } + } + } + + labelNetStatus[i].setText(label); } else { + //if(Socket::enableDebugText) printf("In [%s::%s] C - ctNetwork\n",__FILE__,__FUNCTION__); + labelNetStatus[i].setText(lang.get("NotConnected")); } + + //if(Socket::enableDebugText) printf("In [%s::%s] END - ctNetwork\n",__FILE__,__FUNCTION__); } else{ labelNetStatus[i].setText(""); } } + + // Send the game settings to each client if we have at least one networked client + if( serverInterface->getAllowDownloadDataSynch() == true && + haveAtLeastOneNetworkClientConnected == true && + needToSetChangedGameSettings == true && + difftime(time(NULL),lastSetChangedGameSettings) >= 2) + { + GameSettings gameSettings; + loadGameSettings(&gameSettings); + serverInterface->setGameSettings(&gameSettings); + + needToSetChangedGameSettings = false; + lastSetChangedGameSettings = time(NULL); + } + + //call the chat manager + chatManager.updateNetwork(); + + //console + console.update(); } -void MenuStateCustomGame::loadGameSettings(GameSettings *gameSettings){ +void MenuStateCustomGame::loadGameSettings(GameSettings *gameSettings) +{ + //if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__); int factionCount= 0; @@ -307,11 +466,14 @@ void MenuStateCustomGame::loadGameSettings(GameSettings *gameSettings){ gameSettings->setDefaultUnits(true); gameSettings->setDefaultResources(true); gameSettings->setDefaultVictoryConditions(true); - - for(int i=0; i(listBoxControls[i].getSelectedItemIndex()); - if(ct!=ctClosed){ - if(ct==ctHuman){ + if(ct != ctClosed) + { + if(ct == ctHuman) + { gameSettings->setThisFactionIndex(factionCount); } gameSettings->setFactionControl(factionCount, ct); @@ -322,10 +484,36 @@ void MenuStateCustomGame::loadGameSettings(GameSettings *gameSettings){ } } gameSettings->setFactionCount(factionCount); + + //if(Socket::enableDebugText) printf("In [%s::%s] gameSettings->getTileset() = [%s]\n",__FILE__,__FUNCTION__,gameSettings->getTileset().c_str()); + //if(Socket::enableDebugText) printf("In [%s::%s] gameSettings->getTech() = [%s]\n",__FILE__,__FUNCTION__,gameSettings->getTech().c_str()); + //if(Socket::enableDebugText) printf("In [%s::%s] gameSettings->getMap() = [%s]\n",__FILE__,__FUNCTION__,gameSettings->getMap().c_str()); + + //if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__); } // ============ PRIVATE =========================== +bool MenuStateCustomGame::hasNetworkGameSettings() +{ + bool hasNetworkSlot = false; + + for(int i=0; i(listBoxControls[i].getSelectedItemIndex()); + if(ct != ctClosed) + { + if(ct == ctNetwork) + { + hasNetworkSlot = true; + break; + } + } + } + + return hasNetworkSlot; +} + void MenuStateCustomGame::loadMapInfo(string file, MapInfo *mapInfo){ struct MapFileHeader{ @@ -364,7 +552,7 @@ void MenuStateCustomGame::loadMapInfo(string file, MapInfo *mapInfo){ } void MenuStateCustomGame::reloadFactions(){ - + vector results; findAll("techs/"+techTreeFiles[listBoxTechTree.getSelectedItemIndex()]+"/factions/*.", results); @@ -383,7 +571,7 @@ void MenuStateCustomGame::reloadFactions(){ void MenuStateCustomGame::updateControlers(){ bool humanPlayer= false; - + for(int i= 0; igetSlot(i)==NULL && listBoxControls[i].getSelectedItemIndex()==ctNetwork){ + + for(int i= 0; igetSlot(i) == NULL && listBoxControls[i].getSelectedItemIndex() == ctNetwork) + { serverInterface->addSlot(i); } - if(serverInterface->getSlot(i) != NULL && listBoxControls[i].getSelectedItemIndex()!=ctNetwork){ + if(serverInterface->getSlot(i) != NULL && listBoxControls[i].getSelectedItemIndex() != ctNetwork) + { serverInterface->removeSlot(i); } } } +void MenuStateCustomGame::keyDown(char key) +{ + //send key to the chat manager + chatManager.keyDown(key); +} + +void MenuStateCustomGame::keyPress(char c) +{ + chatManager.keyPress(c); +} + + }}//end namespace diff --git a/source/glest_game/menu/menu_state_custom_game.h b/source/glest_game/menu/menu_state_custom_game.h index e48d72a0c..732509223 100644 --- a/source/glest_game/menu/menu_state_custom_game.h +++ b/source/glest_game/menu/menu_state_custom_game.h @@ -3,9 +3,9 @@ // // Copyright (C) 2001-2005 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 +// 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 // ============================================================== @@ -13,11 +13,12 @@ #define _GLEST_GAME_MENUSTATECUSTOMGAME_H_ #include "main_menu.h" +#include "chat_manager.h" namespace Glest{ namespace Game{ // =============================== -// class MenuStateCustomGame +// class MenuStateCustomGame // =============================== class MenuStateCustomGame: public MenuState{ @@ -45,6 +46,12 @@ private: GraphicLabel labelNetStatus[GameConstants::maxPlayers]; MapInfo mapInfo; + bool needToSetChangedGameSettings; + time_t lastSetChangedGameSettings; + + Console console; + ChatManager chatManager; + public: MenuStateCustomGame(Program *program, MainMenu *mainMenu, bool openNetworkSlots= false); @@ -53,7 +60,12 @@ public: void render(); void update(); + virtual void keyDown(char key); + virtual void keyPress(char c); + private: + + bool hasNetworkGameSettings(); void loadGameSettings(GameSettings *gameSettings); void loadMapInfo(string file, MapInfo *mapInfo); void reloadFactions(); diff --git a/source/glest_game/menu/menu_state_join_game.cpp b/source/glest_game/menu/menu_state_join_game.cpp index 3d480eb76..d750e84bc 100644 --- a/source/glest_game/menu/menu_state_join_game.cpp +++ b/source/glest_game/menu/menu_state_join_game.cpp @@ -3,9 +3,9 @@ // // Copyright (C) 2001-2005 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 +// 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 // ============================================================== @@ -31,7 +31,7 @@ namespace Glest{ namespace Game{ using namespace Shared::Util; // =============================== -// class MenuStateJoinGame +// class MenuStateJoinGame // =============================== const int MenuStateJoinGame::newServerIndex= 0; @@ -87,7 +87,8 @@ MenuStateJoinGame::MenuStateJoinGame(Program *program, MainMenu *mainMenu, bool playerIndex= -1; //server ip - if(connect){ + if(connect) + { labelServerIp.setText(serverIp.getString() + "_"); connectToServer(); } @@ -95,9 +96,13 @@ MenuStateJoinGame::MenuStateJoinGame(Program *program, MainMenu *mainMenu, bool { labelServerIp.setText(config.getString("ServerIp") + "_"); } + + chatManager.init(&console, -1); } -void MenuStateJoinGame::mouseClick(int x, int y, MouseButton mouseButton){ +void MenuStateJoinGame::mouseClick(int x, int y, MouseButton mouseButton) +{ + if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__); CoreData &coreData= CoreData::getInstance(); SoundRenderer &soundRenderer= SoundRenderer::getInstance(); @@ -121,25 +126,42 @@ void MenuStateJoinGame::mouseClick(int x, int y, MouseButton mouseButton){ } //return - if(buttonReturn.mouseClick(x, y)){ + if(buttonReturn.mouseClick(x, y)) + { soundRenderer.playFx(coreData.getClickSoundA()); + + if(clientInterface->getSocket() != NULL) + { + if(clientInterface->isConnected() == true) + { + string sQuitText = clientInterface->getHostName() + " has chosen to leave the game!"; + clientInterface->sendTextMessage(sQuitText,-1); + } + clientInterface->close(); + } + mainMenu->setState(new MenuStateRoot(program, mainMenu)); - } + } //connect - else if(buttonConnect.mouseClick(x, y)){ + else if(buttonConnect.mouseClick(x, y)) + { ClientInterface* clientInterface= networkManager.getClientInterface(); soundRenderer.playFx(coreData.getClickSoundA()); labelInfo.setText(""); - - if(clientInterface->isConnected()){ + + if(clientInterface->isConnected()) + { clientInterface->reset(); } - else{ + else + { connectToServer(); } } + + if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__); } void MenuStateJoinGame::mouseMove(int x, int y, const MouseState *ms){ @@ -166,7 +188,7 @@ void MenuStateJoinGame::render(){ renderer.renderLabel(&labelInfo); renderer.renderButton(&buttonConnect); renderer.renderListBox(&listBoxServerType); - + if(listBoxServerType.getSelectedItemIndex()==newServerIndex){ renderer.renderLabel(&labelServerIp); } @@ -174,52 +196,145 @@ void MenuStateJoinGame::render(){ { renderer.renderListBox(&listBoxServers); } + + renderer.renderChatManager(&chatManager); + renderer.renderConsole(&console); } -void MenuStateJoinGame::update(){ +void MenuStateJoinGame::update() +{ ClientInterface* clientInterface= NetworkManager::getInstance().getClientInterface(); Lang &lang= Lang::getInstance(); //update status label - if(clientInterface->isConnected()){ + if(clientInterface->isConnected()) + { buttonConnect.setText(lang.get("Disconnect")); - if(!clientInterface->getServerName().empty()){ - labelStatus.setText(lang.get("ConnectedToServer") + " " + clientInterface->getServerName()); + + if(clientInterface->getAllowDownloadDataSynch() == false) + { + string label = lang.get("ConnectedToServer"); + + if(!clientInterface->getServerName().empty()) + { + label = label + " " + clientInterface->getServerName(); + } + + if(clientInterface->getAllowGameDataSynchCheck() == true && + clientInterface->getNetworkGameDataSynchCheckOk() == false) + { + label = label + " - warning synch mismatch for:"; + if(clientInterface->getNetworkGameDataSynchCheckOkMap() == false) + { + label = label + " map"; + } + if(clientInterface->getNetworkGameDataSynchCheckOkTile() == false) + { + label = label + " tile"; + } + if(clientInterface->getNetworkGameDataSynchCheckOkTech() == false) + { + label = label + " techtree"; + } + if(clientInterface->getNetworkGameDataSynchCheckOkFogOfWar() == false) + { + label = label + " FogOfWar == false"; + } + } + else if(clientInterface->getAllowGameDataSynchCheck() == true) + { + label += " - data synch is ok"; + } + + labelStatus.setText(label); } - else{ - labelStatus.setText(lang.get("ConnectedToServer")); + else + { + string label = lang.get("ConnectedToServer"); + + if(!clientInterface->getServerName().empty()) + { + label = label + " " + clientInterface->getServerName(); + } + + if(clientInterface->getAllowGameDataSynchCheck() == true && + clientInterface->getNetworkGameDataSynchCheckOk() == false) + { + label = label + " - waiting to synch:"; + if(clientInterface->getNetworkGameDataSynchCheckOkMap() == false) + { + label = label + " map"; + } + if(clientInterface->getNetworkGameDataSynchCheckOkTile() == false) + { + label = label + " tile"; + } + if(clientInterface->getNetworkGameDataSynchCheckOkTech() == false) + { + label = label + " techtree"; + } + if(clientInterface->getNetworkGameDataSynchCheckOkFogOfWar() == false) + { + label = label + " FogOfWar == false"; + } + } + else if(clientInterface->getAllowGameDataSynchCheck() == true) + { + label += " - data synch is ok"; + } + + labelStatus.setText(label); } } - else{ + else + { buttonConnect.setText(lang.get("Connect")); labelStatus.setText(lang.get("NotConnected")); labelInfo.setText(""); } //process network messages - if(clientInterface->isConnected()){ - + if(clientInterface->isConnected()) + { //update lobby clientInterface->updateLobby(); - + + //call the chat manager + chatManager.updateNetwork(); + + //console + console.update(); + //intro - if(clientInterface->getIntroDone()){ - labelInfo.setText(lang.get("WaitingHost")); + if(clientInterface->getIntroDone()) + { + labelInfo.setText(lang.get("WaitingHost")); servers.setString(clientInterface->getServerName(), Ip(labelServerIp.getText()).getString()); } //launch - if(clientInterface->getLaunchGame()){ + if(clientInterface->getLaunchGame()) + { + if(Socket::enableDebugText) printf("In [%s::%s] clientInterface->getLaunchGame() - A\n",__FILE__,__FUNCTION__); + servers.save(serverFileName); - program->setState(new Game(program, clientInterface->getGameSettings())); + + if(Socket::enableDebugText) printf("In [%s::%s] clientInterface->getLaunchGame() - B\n",__FILE__,__FUNCTION__); + + program->setState(new Game(program, clientInterface->getGameSettings())); + + if(Socket::enableDebugText) printf("In [%s::%s] clientInterface->getLaunchGame() - C\n",__FILE__,__FUNCTION__); } } + + if(Socket::enableDebugText && clientInterface->getLaunchGame()) printf("In [%s::%s] clientInterface->getLaunchGame() - D\n",__FILE__,__FUNCTION__); } void MenuStateJoinGame::keyDown(char key){ ClientInterface* clientInterface= NetworkManager::getInstance().getClientInterface(); - - if(!clientInterface->isConnected()){ + + if(!clientInterface->isConnected()) + { if(key==vkBack){ string text= labelServerIp.getText(); @@ -230,12 +345,18 @@ void MenuStateJoinGame::keyDown(char key){ labelServerIp.setText(text); } } + else + { + //send key to the chat manager + chatManager.keyDown(key); + } } void MenuStateJoinGame::keyPress(char c){ ClientInterface* clientInterface= NetworkManager::getInstance().getClientInterface(); - - if(!clientInterface->isConnected()){ + + if(!clientInterface->isConnected()) + { int maxTextSize= 16; if(c>='0' && c<='9'){ @@ -258,20 +379,32 @@ void MenuStateJoinGame::keyPress(char c){ } } } + else + { + chatManager.keyPress(c); + } } -void MenuStateJoinGame::connectToServer(){ +void MenuStateJoinGame::connectToServer() +{ + if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__); + ClientInterface* clientInterface= NetworkManager::getInstance().getClientInterface(); Config& config= Config::getInstance(); Ip serverIp(labelServerIp.getText()); clientInterface->connect(serverIp, GameConstants::serverPort); + + if(Socket::enableDebugText) printf("In [%s::%s] server - [%s]\n",__FILE__,__FUNCTION__,serverIp.getString().c_str()); + labelServerIp.setText(serverIp.getString()+'_'); labelInfo.setText(""); //save server ip config.setString("ServerIp", serverIp.getString()); config.save(); + + if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__); } }}//end namespace diff --git a/source/glest_game/menu/menu_state_join_game.h b/source/glest_game/menu/menu_state_join_game.h index ab296898c..f6ab3b5f9 100644 --- a/source/glest_game/menu/menu_state_join_game.h +++ b/source/glest_game/menu/menu_state_join_game.h @@ -3,9 +3,9 @@ // // Copyright (C) 2001-2005 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 +// 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 // ============================================================== @@ -14,6 +14,7 @@ #include "properties.h" #include "main_menu.h" +#include "chat_manager.h" using Shared::Util::Properties; @@ -22,7 +23,7 @@ namespace Glest{ namespace Game{ class NetworkMessageIntro; // =============================== -// class MenuStateJoinGame +// class MenuStateJoinGame // =============================== class MenuStateJoinGame: public MenuState{ @@ -45,6 +46,9 @@ private: int playerIndex; Properties servers; + Console console; + ChatManager chatManager; + public: MenuStateJoinGame(Program *program, MainMenu *mainMenu, bool connect= false, Ip serverIp= Ip()); @@ -52,8 +56,8 @@ public: void mouseMove(int x, int y, const MouseState *mouseState); void render(); void update(); - void keyDown(char key); - void keyPress(char c); + virtual void keyDown(char key); + virtual void keyPress(char c); private: void connectToServer(); diff --git a/source/glest_game/menu/menu_state_root.cpp b/source/glest_game/menu/menu_state_root.cpp index 6e57d4ad0..41b485b66 100644 --- a/source/glest_game/menu/menu_state_root.cpp +++ b/source/glest_game/menu/menu_state_root.cpp @@ -1,7 +1,7 @@ // ============================================================== // This file is part of Glest (www.glest.org) // -// Copyright (C) 2001-2005 Marti�o Figueroa +// Copyright (C) 2001-2005 Martiño Figueroa // // You can redistribute this code and/or modify it under // the terms of the GNU General Public License as published diff --git a/source/glest_game/menu/menu_state_scenario.cpp b/source/glest_game/menu/menu_state_scenario.cpp index 119c7f12c..41b3cdd1f 100644 --- a/source/glest_game/menu/menu_state_scenario.cpp +++ b/source/glest_game/menu/menu_state_scenario.cpp @@ -1,7 +1,7 @@ // ============================================================== // This file is part of Glest (www.glest.org) // -// Copyright (C) 2001-2005 Marti�o Figueroa +// Copyright (C) 2001-2005 Martiño Figueroa // // You can redistribute this code and/or modify it under // the terms of the GNU General Public License as published diff --git a/source/glest_game/network/client_interface.cpp b/source/glest_game/network/client_interface.cpp index 89d112c1a..fc00982ea 100644 --- a/source/glest_game/network/client_interface.cpp +++ b/source/glest_game/network/client_interface.cpp @@ -3,9 +3,9 @@ // // 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 +// 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 // ============================================================== @@ -21,6 +21,10 @@ #include "lang.h" #include "leak_dumper.h" +#include "map.h" +#include "config.h" +#include "logger.h" + using namespace std; using namespace Shared::Platform; using namespace Shared::Util; @@ -39,25 +43,56 @@ ClientInterface::ClientInterface(){ launchGame= false; introDone= false; playerIndex= -1; + + networkGameDataSynchCheckOkMap = false; + networkGameDataSynchCheckOkTile = false; + networkGameDataSynchCheckOkTech = false; } -ClientInterface::~ClientInterface(){ +ClientInterface::~ClientInterface() +{ + if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__); + + if(clientSocket != NULL && clientSocket->isConnected() == true) + { + string sQuitText = getHostName() + " has chosen to leave the game!"; + sendTextMessage(sQuitText,-1); + } + delete clientSocket; + clientSocket = NULL; + + if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__); } -void ClientInterface::connect(const Ip &ip, int port){ +void ClientInterface::connect(const Ip &ip, int port) +{ + if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__); + delete clientSocket; + + this->ip = ip; + this->port = port; + clientSocket= new ClientSocket(); clientSocket->setBlock(false); clientSocket->connect(ip, port); + + if(Socket::enableDebugText) printf("In [%s::%s] END - socket = %d\n",__FILE__,__FUNCTION__,clientSocket->getSocketId()); } -void ClientInterface::reset(){ - delete clientSocket; - clientSocket= NULL; +void ClientInterface::reset() +{ + if(getSocket() != NULL) + { + string sQuitText = getHostName() + " has chosen to leave the game!"; + sendTextMessage(sQuitText,-1); + close(); + } } -void ClientInterface::update(){ +void ClientInterface::update() +{ NetworkMessageCommandList networkMessageCommandList; //send as many commands as we can @@ -79,152 +114,363 @@ void ClientInterface::update(){ chatTeamIndex= -1; } -void ClientInterface::updateLobby(){ - NetworkMessageType networkMessageType= getNextMessageType(); - - switch(networkMessageType){ - case nmtInvalid: - break; +void ClientInterface::updateLobby() +{ + //clear chat variables + chatText.clear(); + chatSender.clear(); + chatTeamIndex= -1; - case nmtIntro:{ - NetworkMessageIntro networkMessageIntro; + NetworkMessageType networkMessageType = getNextMessageType(true); - if(receiveMessage(&networkMessageIntro)){ - - //check consistency - if(Config::getInstance().getBool("NetworkConsistencyChecks")){ - if(networkMessageIntro.getVersionString()!=getNetworkVersionString()){ - throw runtime_error("Server and client versions do not match (" + networkMessageIntro.getVersionString() + "). You have to use the same binaries."); - } - } + switch(networkMessageType) + { + case nmtInvalid: + break; - //send intro message - NetworkMessageIntro sendNetworkMessageIntro(getNetworkVersionString(), getHostName(), -1); + case nmtIntro: + { + NetworkMessageIntro networkMessageIntro; - playerIndex= networkMessageIntro.getPlayerIndex(); - serverName= networkMessageIntro.getName(); - sendMessage(&sendNetworkMessageIntro); - - assert(playerIndex>=0 && playerIndex=0 && playerIndexsetNetworkGameDataSynchCheckOkTile((tilesetCRC == networkMessageSynchNetworkGameData.getTilesetCRC())); + if(this->getNetworkGameDataSynchCheckOkTile() == false) + { + if(Socket::enableDebugText) printf("In [%s::%s] tilesetCRC mismatch, local = %d, remote = %d\n", + __FILE__,__FUNCTION__,tilesetCRC,networkMessageSynchNetworkGameData.getTilesetCRC()); + } + + + //tech, load before map because of resources + //checksum = Checksum(); + //file = "techs/" + networkMessageSynchNetworkGameData.getTech() + "/" + networkMessageSynchNetworkGameData.getTech() + ".xml"; + //checksum.addFile(file); + // factions + // resources + //int32 techCRC = checksum.getSum(); + //if(Socket::enableDebugText) printf("In [%s::%s] file = [%s] checksum = %d\n",__FILE__,__FUNCTION__,file.c_str(),techCRC); + + //if(techCRC != networkMessageSynchNetworkGameData.getTechCRC()) + //{ + // if(Socket::enableDebugText) printf("In [%s::%s] techCRC mismatch, local = %d, remote = %d\n", + // __FILE__,__FUNCTION__,techCRC,networkMessageSynchNetworkGameData.getTechCRC()); + //} + + int32 techCRC = getFolderTreeContentsCheckSumRecursively("techs/" + + networkMessageSynchNetworkGameData.getTech() + "/*", ".xml", NULL); + + this->setNetworkGameDataSynchCheckOkTech((techCRC == networkMessageSynchNetworkGameData.getTechCRC())); + + if(this->getNetworkGameDataSynchCheckOkTech() == false) + { + if(Socket::enableDebugText) printf("In [%s::%s] techCRC mismatch, local = %d, remote = %d\n", + __FILE__,__FUNCTION__,techCRC,networkMessageSynchNetworkGameData.getTechCRC()); + } + + //map + Checksum checksum; + string file = Map::getMapPath(networkMessageSynchNetworkGameData.getMap()); + checksum.addFile(file); + int32 mapCRC = checksum.getSum(); + //if(Socket::enableDebugText) printf("In [%s::%s] file = [%s] checksum = %d\n",__FILE__,__FUNCTION__,file.c_str(),mapCRC); + + this->setNetworkGameDataSynchCheckOkMap((mapCRC == networkMessageSynchNetworkGameData.getMapCRC())); + + if(this->getNetworkGameDataSynchCheckOkMap() == false) + { + if(Socket::enableDebugText) printf("In [%s::%s] mapCRC mismatch, local = %d, remote = %d\n", + __FILE__,__FUNCTION__,mapCRC,networkMessageSynchNetworkGameData.getMapCRC()); + } + + + this->setNetworkGameDataSynchCheckOkFogOfWar((getFogOfWar() == networkMessageSynchNetworkGameData.getFogOfWar())); + + if(this->getNetworkGameDataSynchCheckOkFogOfWar() == false) + { + if(Socket::enableDebugText) printf("In [%s::%s] getFogOfWar mismatch, local = %d, remote = %d\n", + __FILE__,__FUNCTION__,getFogOfWar(),networkMessageSynchNetworkGameData.getFogOfWar()); + } + + NetworkMessageSynchNetworkGameDataStatus sendNetworkMessageSynchNetworkGameDataStatus(mapCRC,tilesetCRC,techCRC,getFogOfWar()); + sendMessage(&sendNetworkMessageSynchNetworkGameDataStatus); + } + } + break; + + case nmtSynchNetworkGameDataFileCRCCheck: + { + NetworkMessageSynchNetworkGameDataFileCRCCheck networkMessageSynchNetworkGameDataFileCRCCheck; + if(receiveMessage(&networkMessageSynchNetworkGameDataFileCRCCheck)) + { + /* + if(Socket::enableDebugText) printf("In [%s::%s] got nmtSynchNetworkGameDataFileCRCCheck totalfiles = %d, fileindex = %d, crc = %d, file [%s]\n", + __FILE__,__FUNCTION__,networkMessageSynchNetworkGameDataFileCRCCheck.getTotalFileCount(), + networkMessageSynchNetworkGameDataFileCRCCheck.getFileIndex(), + networkMessageSynchNetworkGameDataFileCRCCheck.getFileCRC(), + networkMessageSynchNetworkGameDataFileCRCCheck.getFileName().c_str()); + */ + Checksum checksum; + string file = networkMessageSynchNetworkGameDataFileCRCCheck.getFileName(); + checksum.addFile(file); + int32 fileCRC = checksum.getSum(); + + if(fileCRC != networkMessageSynchNetworkGameDataFileCRCCheck.getFileCRC()) + { + if(Socket::enableDebugText) printf("In [%s::%s] got nmtSynchNetworkGameDataFileCRCCheck localCRC = %d, remoteCRC = %d, file [%s]\n", + __FILE__,__FUNCTION__,fileCRC, + networkMessageSynchNetworkGameDataFileCRCCheck.getFileCRC(), + networkMessageSynchNetworkGameDataFileCRCCheck.getFileName().c_str()); + + // Here we initiate a download of missing or mismatched content + + NetworkMessageSynchNetworkGameDataFileGet sendNetworkMessageSynchNetworkGameDataFileGet(networkMessageSynchNetworkGameDataFileCRCCheck.getFileName()); + sendMessage(&sendNetworkMessageSynchNetworkGameDataFileGet); + + FileTransferInfo fileInfo; + fileInfo.hostType = eClient; + fileInfo.serverIP = this->ip.getString(); + fileInfo.serverPort = this->port; + fileInfo.fileName = networkMessageSynchNetworkGameDataFileCRCCheck.getFileName(); + + FileTransferSocketThread *fileXferThread = new FileTransferSocketThread(fileInfo); + fileXferThread->start(); + } + + if(networkMessageSynchNetworkGameDataFileCRCCheck.getFileIndex() < networkMessageSynchNetworkGameDataFileCRCCheck.getTotalFileCount()) + { + NetworkMessageSynchNetworkGameDataFileCRCCheck sendNetworkMessageSynchNetworkGameDataFileCRCCheck( + networkMessageSynchNetworkGameDataFileCRCCheck.getTotalFileCount(), + networkMessageSynchNetworkGameDataFileCRCCheck.getFileIndex() + 1, + 0, + ""); + sendMessage(&sendNetworkMessageSynchNetworkGameDataFileCRCCheck); + } + } + } + break; + + case nmtText: + { + NetworkMessageText networkMessageText; + if(receiveMessage(&networkMessageText)) + { + if(Socket::enableDebugText) printf("In [%s::%s] got nmtText\n",__FILE__,__FUNCTION__); + + chatText = networkMessageText.getText(); + chatSender = networkMessageText.getSender(); + chatTeamIndex = networkMessageText.getTeamIndex(); + } + } + break; + + case nmtLaunch: + { + NetworkMessageLaunch networkMessageLaunch; + + if(receiveMessage(&networkMessageLaunch)) + { + if(Socket::enableDebugText) printf("In [%s::%s] got NetworkMessageLaunch\n",__FILE__,__FUNCTION__); + + networkMessageLaunch.buildGameSettings(&gameSettings); + + //replace server player by network + for(int i= 0; ireadyWaitTimeout){ + else if(networkMessageType == nmtInvalid) + { + if(chrono.getMillis() > readyWaitTimeout) + { throw runtime_error("Timeout waiting for server"); } + else + { + if(chrono.getMillis() / 1000 > lastMillisCheck) + { + lastMillisCheck = (chrono.getMillis() / 1000); + + char szBuf[1024]=""; + sprintf(szBuf,"Waiting for network: %llu seconds elapsed (maximum wait time: %d seconds)",lastMillisCheck,int(readyWaitTimeout / 1000)); + logger.add(szBuf, true); + } + } } - else{ - throw runtime_error("Unexpected network message: " + intToStr(networkMessageType) ); + else + { + throw runtime_error(string(__FILE__) + "::" + string(__FUNCTION__) + " Unexpected network message: " + intToStr(networkMessageType) ); } // sleep a bit @@ -232,14 +478,18 @@ void ClientInterface::waitUntilReady(Checksum* checksum){ } //check checksum - if(Config::getInstance().getBool("NetworkConsistencyChecks")){ - if(networkMessageReady.getChecksum()!=checksum->getSum()){ + if(Config::getInstance().getBool("NetworkConsistencyChecks")) + { + if(networkMessageReady.getChecksum() != checksum->getSum()) + { throw runtime_error("Checksum error, you don't have the same data as the server"); } } //delay the start a bit, so clients have nore room to get messages sleep(GameConstants::networkExtraLatency); + + if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__); } void ClientInterface::sendTextMessage(const string &text, int teamIndex){ @@ -251,18 +501,20 @@ string ClientInterface::getNetworkStatus() const{ return Lang::getInstance().get("Server") + ": " + serverName; } -void ClientInterface::waitForMessage(){ +void ClientInterface::waitForMessage() +{ Chrono chrono; - chrono.start(); - while(getNextMessageType()==nmtInvalid){ - - if(!isConnected()){ + while(getNextMessageType(true) == nmtInvalid) + { + if(!isConnected()) + { throw runtime_error("Disconnected"); } - if(chrono.getMillis()>messageWaitTimeout){ + if(chrono.getMillis()>messageWaitTimeout) + { throw runtime_error("Timeout waiting for message"); } @@ -270,4 +522,31 @@ void ClientInterface::waitForMessage(){ } } +void ClientInterface::quitGame(bool userManuallyQuit) +{ + if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__); + + if(clientSocket != NULL && userManuallyQuit == true) + { + string sQuitText = getHostName() + " has chosen to leave the game!"; + sendTextMessage(sQuitText,-1); + close(); + } + + if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__); +} + +void ClientInterface::close() +{ + if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__); + + delete clientSocket; + clientSocket= NULL; +} + +bool ClientInterface::getFogOfWar() +{ + return Config::getInstance().getBool("FogOfWar"); +} + }}//end namespace diff --git a/source/glest_game/network/client_interface.h b/source/glest_game/network/client_interface.h index 5c16b752b..ce20b4cd1 100644 --- a/source/glest_game/network/client_interface.h +++ b/source/glest_game/network/client_interface.h @@ -3,9 +3,9 @@ // // 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 +// 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 // ============================================================== @@ -15,7 +15,7 @@ #include #include "network_interface.h" -#include "game_settings.h" +//#include "game_settings.h" #include "socket.h" @@ -36,18 +36,22 @@ private: private: ClientSocket *clientSocket; - GameSettings gameSettings; + //GameSettings gameSettings; string serverName; bool introDone; bool launchGame; int playerIndex; + Ip ip; + int port; + public: ClientInterface(); virtual ~ClientInterface(); virtual Socket* getSocket() {return clientSocket;} virtual const Socket* getSocket() const {return clientSocket;} + virtual void close(); //message processing virtual void update(); @@ -57,7 +61,7 @@ public: // message sending virtual void sendTextMessage(const string &text, int teamIndex); - virtual void quitGame(){} + virtual void quitGame(bool userManuallyQuit); //misc virtual string getNetworkStatus() const; @@ -67,10 +71,11 @@ public: bool getLaunchGame() const {return launchGame;} bool getIntroDone() const {return introDone;} int getPlayerIndex() const {return playerIndex;} - const GameSettings *getGameSettings() {return &gameSettings;} + //const GameSettings *getGameSettings() {return &gameSettings;} void connect(const Ip &ip, int port); void reset(); + virtual bool getFogOfWar(); private: void waitForMessage(); diff --git a/source/glest_game/network/connection_slot.cpp b/source/glest_game/network/connection_slot.cpp index 8d015f79b..26cf060c0 100644 --- a/source/glest_game/network/connection_slot.cpp +++ b/source/glest_game/network/connection_slot.cpp @@ -3,9 +3,9 @@ // // 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 +// 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 // ============================================================== @@ -20,8 +20,12 @@ #include "network_message.h" #include "leak_dumper.h" +#include "platform_util.h" +#include "map.h" + using namespace std; using namespace Shared::Util; +//using namespace Shared::Platform; namespace Glest{ namespace Game{ @@ -29,43 +33,108 @@ namespace Glest{ namespace Game{ // class ClientConnection // ===================================================== -ConnectionSlot::ConnectionSlot(ServerInterface* serverInterface, int playerIndex){ +ConnectionSlot::ConnectionSlot(ServerInterface* serverInterface, int playerIndex) +{ this->serverInterface= serverInterface; this->playerIndex= playerIndex; socket= NULL; ready= false; + + networkGameDataSynchCheckOkMap = false; + networkGameDataSynchCheckOkTile = false; + networkGameDataSynchCheckOkTech = false; + networkGameDataSynchCheckOkFogOfWar = false; + + chatText.clear(); + chatSender.clear(); + chatTeamIndex= -1; } -ConnectionSlot::~ConnectionSlot(){ +ConnectionSlot::~ConnectionSlot() +{ + if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__); + close(); + + if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__); } -void ConnectionSlot::update(){ - if(socket==NULL){ - socket= serverInterface->getServerSocket()->accept(); +void ConnectionSlot::update() +{ + update(true); +} - //send intro message when connected - if(socket!=NULL){ - NetworkMessageIntro networkMessageIntro(getNetworkVersionString(), socket->getHostName(), playerIndex); - sendMessage(&networkMessageIntro); - } +void ConnectionSlot::update(bool checkForNewClients) +{ + if(socket == NULL) + { + if(networkGameDataSynchCheckOkMap) networkGameDataSynchCheckOkMap = false; + if(networkGameDataSynchCheckOkTile) networkGameDataSynchCheckOkTile = false; + if(networkGameDataSynchCheckOkTech) networkGameDataSynchCheckOkTech = false; + if(networkGameDataSynchCheckOkFogOfWar) networkGameDataSynchCheckOkFogOfWar = false; + + // Is the listener socket ready to be read? + //if(serverInterface->getServerSocket()->isReadable() == true) + if(checkForNewClients == true) + { + socket = serverInterface->getServerSocket()->accept(); + + //send intro message when connected + if(socket != NULL) + { + if(Socket::enableDebugText) printf("In [%s::%s] accepted new client connection\n",__FILE__,__FUNCTION__); + + chatText.clear(); + chatSender.clear(); + chatTeamIndex= -1; + + NetworkMessageIntro networkMessageIntro(getNetworkVersionString(), socket->getHostName(), playerIndex); + sendMessage(&networkMessageIntro); + } + } } - else{ - if(socket->isConnected()){ + else + { + if(socket->isConnected()) + { + chatText.clear(); + chatSender.clear(); + chatTeamIndex= -1; + NetworkMessageType networkMessageType= getNextMessageType(); //process incoming commands switch(networkMessageType){ - + case nmtInvalid: - case nmtText: break; + case nmtText: + { + if(Socket::enableDebugText) printf("In [%s::%s] got nmtText\n",__FILE__,__FUNCTION__); + + NetworkMessageText networkMessageText; + if(receiveMessage(&networkMessageText)) + { + chatText = networkMessageText.getText(); + chatSender = networkMessageText.getSender(); + chatTeamIndex = networkMessageText.getTeamIndex(); + + if(Socket::enableDebugText) printf("In [%s::%s] chatText [%s] chatSender [%s] chatTeamIndex = %d\n",__FILE__,__FUNCTION__,chatText.c_str(),chatSender.c_str(),chatTeamIndex); + } + } + break; + //command list - case nmtCommandList:{ + case nmtCommandList: { + + if(Socket::enableDebugText) printf("In [%s::%s] got nmtCommandList\n",__FILE__,__FUNCTION__); + NetworkMessageCommandList networkMessageCommandList; - if(receiveMessage(&networkMessageCommandList)){ - for(int i= 0; irequestCommand(networkMessageCommandList.getCommand(i)); } } @@ -73,10 +142,143 @@ void ConnectionSlot::update(){ break; //process intro messages - case nmtIntro:{ + case nmtIntro: + { + + if(Socket::enableDebugText) printf("In [%s::%s] got nmtIntro\n",__FILE__,__FUNCTION__); + NetworkMessageIntro networkMessageIntro; - if(receiveMessage(&networkMessageIntro)){ + if(receiveMessage(&networkMessageIntro)) + { name= networkMessageIntro.getName(); + + if(Socket::enableDebugText) printf("In [%s::%s] got name [%s]\n",__FILE__,__FUNCTION__,name.c_str()); + + if(getAllowGameDataSynchCheck() == true && serverInterface->getGameSettings() != NULL) + { + if(Socket::enableDebugText) printf("In [%s::%s] sending NetworkMessageSynchNetworkGameData\n",__FILE__,__FUNCTION__); + + NetworkMessageSynchNetworkGameData networkMessageSynchNetworkGameData(serverInterface->getGameSettings()); + sendMessage(&networkMessageSynchNetworkGameData); + } + } + } + break; + + //process datasynch messages + case nmtSynchNetworkGameDataStatus: + { + + if(Socket::enableDebugText) printf("In [%s::%s] got nmtSynchNetworkGameDataStatus\n",__FILE__,__FUNCTION__); + + NetworkMessageSynchNetworkGameDataStatus networkMessageSynchNetworkGameDataStatus; + if(receiveMessage(&networkMessageSynchNetworkGameDataStatus)) + { + receivedNetworkGameStatus = true; + + int32 tilesetCRC = getFolderTreeContentsCheckSumRecursively("tilesets/" + serverInterface->getGameSettings()->getTileset() + "/*", ".xml", NULL); + int32 techCRC = getFolderTreeContentsCheckSumRecursively("techs/" + serverInterface->getGameSettings()->getTech() + "/*", ".xml", NULL); + Checksum checksum; + string file = Map::getMapPath(serverInterface->getGameSettings()->getMap()); + checksum.addFile(file); + int32 mapCRC = checksum.getSum(); + + networkGameDataSynchCheckOkMap = (networkMessageSynchNetworkGameDataStatus.getMapCRC() == mapCRC); + networkGameDataSynchCheckOkTile = (networkMessageSynchNetworkGameDataStatus.getTilesetCRC() == tilesetCRC); + networkGameDataSynchCheckOkTech = (networkMessageSynchNetworkGameDataStatus.getTechCRC() == techCRC); + networkGameDataSynchCheckOkFogOfWar = (networkMessageSynchNetworkGameDataStatus.getFogOfWar() == serverInterface->getFogOfWar() == true); + + // For testing + //techCRC++; + + if( networkGameDataSynchCheckOkMap == true && + networkGameDataSynchCheckOkTile == true && + networkGameDataSynchCheckOkTech == true && + networkGameDataSynchCheckOkFogOfWar == true) + { + if(Socket::enableDebugText) printf("In [%s::%s] client data synch ok\n",__FILE__,__FUNCTION__); + } + else + { + if(Socket::enableDebugText) printf("In [%s::%s] mapCRC = %d, remote = %d\n",__FILE__,__FUNCTION__,mapCRC,networkMessageSynchNetworkGameDataStatus.getMapCRC()); + if(Socket::enableDebugText) printf("In [%s::%s] tilesetCRC = %d, remote = %d\n",__FILE__,__FUNCTION__,tilesetCRC,networkMessageSynchNetworkGameDataStatus.getTilesetCRC()); + if(Socket::enableDebugText) printf("In [%s::%s] techCRC = %d, remote = %d\n",__FILE__,__FUNCTION__,techCRC,networkMessageSynchNetworkGameDataStatus.getTechCRC()); + if(Socket::enableDebugText) printf("In [%s::%s] serverInterface->getFogOfWar() = %d, remote = %d\n",__FILE__,__FUNCTION__,serverInterface->getFogOfWar(),networkMessageSynchNetworkGameDataStatus.getFogOfWar()); + + if(allowDownloadDataSynch == true) + { + // Now get all filenames with their CRC values and send to the client + vctFileList.clear(); + + if(networkGameDataSynchCheckOkTile == false) + { + if(tilesetCRC == 0) + { + vctFileList = getFolderTreeContentsCheckSumListRecursively("tilesets/" + serverInterface->getGameSettings()->getTileset() + "/*", "", &vctFileList); + } + else + { + vctFileList = getFolderTreeContentsCheckSumListRecursively("tilesets/" + serverInterface->getGameSettings()->getTileset() + "/*", ".xml", &vctFileList); + } + } + if(networkGameDataSynchCheckOkTech == false) + { + if(techCRC == 0) + { + vctFileList = getFolderTreeContentsCheckSumListRecursively("techs/" + serverInterface->getGameSettings()->getTech() + "/*", "", &vctFileList); + } + else + { + vctFileList = getFolderTreeContentsCheckSumListRecursively("techs/" + serverInterface->getGameSettings()->getTech() + "/*", ".xml", &vctFileList); + } + } + if(networkGameDataSynchCheckOkMap == false) + { + vctFileList.push_back(std::pair(Map::getMapPath(serverInterface->getGameSettings()->getMap()),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: + { + + if(Socket::enableDebugText) printf("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: + { + + if(Socket::enableDebugText) printf("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 = GameConstants::serverPort; + fileInfo.fileName = networkMessageSynchNetworkGameDataFileGet.getFileName(); + + FileTransferSocketThread *fileXferThread = new FileTransferSocketThread(fileInfo); + fileXferThread->start(); } } break; @@ -85,15 +287,38 @@ void ConnectionSlot::update(){ throw runtime_error("Unexpected message in connection slot: " + intToStr(networkMessageType)); } } - else{ + else + { + if(Socket::enableDebugText) printf("In [%s::%s] calling close...\n",__FILE__,__FUNCTION__); + close(); } } } -void ConnectionSlot::close(){ +void ConnectionSlot::close() +{ + if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__); + delete socket; socket= NULL; + + chatText.clear(); + chatSender.clear(); + chatTeamIndex= -1; + + if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__); +} + +bool ConnectionSlot::getFogOfWar() +{ + return networkGameDataSynchCheckOkFogOfWar; +} + +bool ConnectionSlot::hasValidSocketId() +{ + bool result = (socket != NULL && socket->getSocketId() > 0); + return result; } }}//end namespace diff --git a/source/glest_game/network/connection_slot.h b/source/glest_game/network/connection_slot.h index d2069b550..bc1ee8dc4 100644 --- a/source/glest_game/network/connection_slot.h +++ b/source/glest_game/network/connection_slot.h @@ -3,9 +3,9 @@ // // 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 +// 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 // ============================================================== @@ -37,23 +37,30 @@ private: int playerIndex; string name; bool ready; + vector > vctFileList; + bool receivedNetworkGameStatus; public: ConnectionSlot(ServerInterface* serverInterface, int playerIndex); ~ConnectionSlot(); + void update(bool checkForNewClients); virtual void update(); void setReady() {ready= true;} const string &getName() const {return name;} bool isReady() const {return ready;} -protected: virtual Socket* getSocket() {return socket;} virtual Socket* getSocket() const {return socket;} -private: - void close(); + virtual void close(); + virtual bool getFogOfWar(); + + bool getReceivedNetworkGameStatus() { return receivedNetworkGameStatus; } + void setReceivedNetworkGameStatus(bool value) { receivedNetworkGameStatus = value; } + + bool hasValidSocketId(); }; }}//end namespace diff --git a/source/glest_game/network/network_interface.cpp b/source/glest_game/network/network_interface.cpp index 397dd7c22..b4031d0f1 100644 --- a/source/glest_game/network/network_interface.cpp +++ b/source/glest_game/network/network_interface.cpp @@ -3,9 +3,9 @@ // // 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 +// 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 // ============================================================== @@ -19,6 +19,7 @@ #include "platform_util.h" #include "leak_dumper.h" +#include using namespace Shared::Platform; using namespace Shared::Util; @@ -32,6 +33,9 @@ namespace Glest{ namespace Game{ const int NetworkInterface::readyWaitTimeout= 60000; //1 minute +bool NetworkInterface::allowGameDataSynchCheck = false; +bool NetworkInterface::allowDownloadDataSynch = false; + void NetworkInterface::sendMessage(const NetworkMessage* networkMessage){ Socket* socket= getSocket(); @@ -39,31 +43,52 @@ void NetworkInterface::sendMessage(const NetworkMessage* networkMessage){ networkMessage->send(socket); } -NetworkMessageType NetworkInterface::getNextMessageType(){ +NetworkMessageType NetworkInterface::getNextMessageType(bool checkHasDataFirst) +{ Socket* socket= getSocket(); int8 messageType= nmtInvalid; - //peek message type - if(socket->getDataToRead()>=sizeof(messageType)){ - socket->peek(&messageType, sizeof(messageType)); - } + if(checkHasDataFirst == false || + (checkHasDataFirst == true && + socket != NULL && + socket->hasDataToRead() == true)) + { + //peek message type + int dataSize = socket->getDataToRead(); + if(dataSize >= sizeof(messageType)){ + if(Socket::enableDebugText) printf("In [%s::%s] socket->getDataToRead() dataSize = %d\n",__FILE__,__FUNCTION__,dataSize); - //sanity check new message type - if(messageType<0 || messageType>=nmtCount){ - throw runtime_error("Invalid message type: " + intToStr(messageType)); - } + int iPeek = socket->peek(&messageType, sizeof(messageType)); + + if(Socket::enableDebugText) printf("In [%s::%s] socket->getDataToRead() iPeek = %d, messageType = %d\n",__FILE__,__FUNCTION__,iPeek,messageType); + } + + //sanity check new message type + if(messageType<0 || messageType>=nmtCount){ + throw runtime_error("Invalid message type: " + intToStr(messageType)); + } + } return static_cast(messageType); } bool NetworkInterface::receiveMessage(NetworkMessage* networkMessage){ + + if(Socket::enableDebugText) printf("In [%s::%s]\n",__FILE__,__FUNCTION__); + Socket* socket= getSocket(); return networkMessage->receive(socket); } bool NetworkInterface::isConnected(){ - return getSocket()!=NULL && getSocket()->isConnected(); + //if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__); + + bool result = (getSocket()!=NULL && getSocket()->isConnected()); + + //if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__); + + return result; } // ===================================================== @@ -74,4 +99,181 @@ GameNetworkInterface::GameNetworkInterface(){ quit= false; } +// ===================================================== +// class FileTransferSocketThread +// ===================================================== + +const int32 SEND_FILE = 0x20; +const int32 ACK = 0x47; + +FileTransferSocketThread::FileTransferSocketThread(FileTransferInfo fileInfo) +{ + this->info = fileInfo; + this->info.serverPort += 100; +} + +void FileTransferSocketThread::execute() +{ + if(info.hostType == eServer) + { + ServerSocket serverSocket; + //serverSocket.setBlock(false); + serverSocket.bind(this->info.serverPort); + serverSocket.listen(1); + Socket *clientSocket = serverSocket.accept(); + + char data[513]=""; + memset(data, 0, 256); + + clientSocket->receive(data,256); + if(*data == SEND_FILE) + { + FileInfo file; + + memcpy(&file, data+1, sizeof(file)); + + *data=ACK; + clientSocket->send(data,256); + + Checksum checksum; + checksum.addFile(file.fileName); + file.filecrc = checksum.getSum(); + + ifstream infile(file.fileName.c_str(), ios::in | ios::binary | ios::ate); + if(infile.is_open() == true) + { + file.filesize = infile.tellg(); + infile.seekg (0, ios::beg); + + memset(data, 0, 256); + *data=SEND_FILE; + memcpy(data+1,&file,sizeof(file)); + + clientSocket->send(data,256); + clientSocket->receive(data,256); + if(*data != ACK) + ;//transfer error + + int remain=file.filesize % 512 ; + int packs=(file.filesize-remain)/512; + + while(packs--) + { + infile.read(data,512); + //if(!ReadFile(file,data,512,&read,NULL)) + // ; //read error + //if(written!=pack) + // ; //read error + clientSocket->send(data,512); + clientSocket->receive(data,256); + if(*data!=ACK) + ;//transfer error + } + + infile.read(data,remain); + //if(!ReadFile(file,data,remain,&read,NULL)) + // ; //read error + //if(written!=pack) + // ; //read error + + clientSocket->send(data,remain); + clientSocket->receive(data,256); + if(*data!=ACK) + ;//transfer error + + infile.close(); + } + } + + delete clientSocket; + } + else + { + Ip ip(this->info.serverIP); + ClientSocket clientSocket; + //clientSocket.setBlock(false); + clientSocket.connect(this->info.serverIP, this->info.serverPort); + + if(clientSocket.isConnected() == true) + { + FileInfo file; + file.fileName = this->info.fileName; + //file.filesize = + //file.filecrc = this->info. + + string path = extractDirectoryPathFromFile(file.fileName); + createDirectoryPaths(path); + ofstream outFile(file.fileName.c_str(), ios_base::binary | ios_base::out); + if(outFile.is_open() == true) + { + char data[513]=""; + memset(data, 0, 256); + *data=SEND_FILE; + memcpy(data+1,&file,sizeof(file)); + + clientSocket.send(data,256); + clientSocket.receive(data,256); + if(*data!=ACK) + ;//transfer error + + clientSocket.receive(data,256); + if(*data == SEND_FILE) + { + memcpy(&file, data+1, sizeof(file)); + *data=ACK; + clientSocket.send(data,256); + + int remain = file.filesize % 512 ; + int packs = (file.filesize-remain) / 512; + + while(packs--) + { + clientSocket.receive(data,512); + + outFile.write(data, 512); + if(outFile.bad()) + { + int ii = 0; + } + //if(!WriteFile(file,data,512,&written,NULL)) + // ; //write error + //if(written != pack) + // ; //write error + *data=ACK; + clientSocket.send(data,256); + } + clientSocket.receive(data,remain); + + outFile.write(data, remain); + if(outFile.bad()) + { + int ii = 0; + } + + //if(!WriteFile(file,data,remain,&written,NULL)) + // ; //write error + //if(written!=pack) + // ; //write error + *data=ACK; + clientSocket.send(data,256); + + Checksum checksum; + checksum.addFile(file.fileName); + int32 crc = checksum.getSum(); + if(file.filecrc != crc) + { + int ii = 0; + } + + //if(calc_crc(file)!=info.crc) + // ; //transfeer error + } + + outFile.close(); + } + } + } +} + + }}//end namespace diff --git a/source/glest_game/network/network_interface.h b/source/glest_game/network/network_interface.h index dde0bc5ca..d1675b0b0 100644 --- a/source/glest_game/network/network_interface.h +++ b/source/glest_game/network/network_interface.h @@ -3,9 +3,9 @@ // // 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 +// 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 // ============================================================== @@ -19,40 +19,88 @@ #include "network_message.h" #include "network_types.h" +#include "game_settings.h" + +#include "thread.h" +#include "types.h" + using std::string; using std::vector; using Shared::Util::Checksum; +using namespace Shared::Util; +using namespace Shared::Platform; namespace Glest{ namespace Game{ +//class GameSettings; + // ===================================================== // class NetworkInterface // ===================================================== -class NetworkInterface{ +class NetworkInterface { + +protected: + static bool allowGameDataSynchCheck; + static bool allowDownloadDataSynch; + bool networkGameDataSynchCheckOkMap; + bool networkGameDataSynchCheckOkTile; + bool networkGameDataSynchCheckOkTech; + bool networkGameDataSynchCheckOkFogOfWar; + + string chatText; + string chatSender; + int chatTeamIndex; + public: static const int readyWaitTimeout; + GameSettings gameSettings; public: virtual ~NetworkInterface(){} virtual Socket* getSocket()= 0; virtual const Socket* getSocket() const= 0; + virtual void close()= 0; string getIp() const {return getSocket()->getIp();} string getHostName() const {return getSocket()->getHostName();} void sendMessage(const NetworkMessage* networkMessage); - NetworkMessageType getNextMessageType(); + NetworkMessageType getNextMessageType(bool checkHasDataFirst = false); bool receiveMessage(NetworkMessage* networkMessage); bool isConnected(); + + //virtual void setGameSettings(GameSettings *serverGameSettings) { gameSettings = *serverGameSettings; } + const virtual GameSettings * getGameSettings() { return &gameSettings; } + + virtual void setAllowDownloadDataSynch(bool value) { allowDownloadDataSynch = value; } + virtual bool getAllowDownloadDataSynch() { return allowDownloadDataSynch; } + + virtual void setAllowGameDataSynchCheck(bool value) { allowGameDataSynchCheck = value; } + virtual bool getAllowGameDataSynchCheck() { return allowGameDataSynchCheck; } + + virtual bool getNetworkGameDataSynchCheckOk() { return (networkGameDataSynchCheckOkMap && networkGameDataSynchCheckOkTile && networkGameDataSynchCheckOkTech && networkGameDataSynchCheckOkFogOfWar); } + virtual void setNetworkGameDataSynchCheckOkMap(bool value) { networkGameDataSynchCheckOkMap = value; } + virtual void setNetworkGameDataSynchCheckOkTile(bool value) { networkGameDataSynchCheckOkTile = value; } + virtual void setNetworkGameDataSynchCheckOkTech(bool value) { networkGameDataSynchCheckOkTech = value; } + virtual bool getNetworkGameDataSynchCheckOkMap() { return networkGameDataSynchCheckOkMap; } + virtual bool getNetworkGameDataSynchCheckOkTile() { return networkGameDataSynchCheckOkTile; } + virtual bool getNetworkGameDataSynchCheckOkTech() { return networkGameDataSynchCheckOkTech; } + virtual bool getFogOfWar()=0; + virtual bool getNetworkGameDataSynchCheckOkFogOfWar() { return networkGameDataSynchCheckOkFogOfWar; } + virtual void setNetworkGameDataSynchCheckOkFogOfWar(bool value) { networkGameDataSynchCheckOkFogOfWar = value; } + + const string getChatText() const {return chatText;} + const string getChatSender() const {return chatSender;} + int getChatTeamIndex() const {return chatTeamIndex;} }; // ===================================================== // class GameNetworkInterface -// -// Adds functions common to servers and clients +// +// Adds functions common to servers and clients // but not connection slots // ===================================================== @@ -64,9 +112,6 @@ protected: Commands requestedCommands; //commands requested by the user Commands pendingCommands; //commands ready to be given bool quit; - string chatText; - string chatSender; - int chatTeamIndex; public: GameNetworkInterface(); @@ -79,7 +124,7 @@ public: //message sending virtual void sendTextMessage(const string &text, int teamIndex)= 0; - virtual void quitGame()=0; + virtual void quitGame(bool userManuallyQuit)=0; //misc virtual string getNetworkStatus() const= 0; @@ -90,11 +135,77 @@ public: const NetworkCommand* getPendingCommand(int i) const {return &pendingCommands[i];} void clearPendingCommands() {pendingCommands.clear();} bool getQuit() const {return quit;} - const string getChatText() const {return chatText;} - const string getChatSender() const {return chatSender;} - int getChatTeamIndex() const {return chatTeamIndex;} }; +// ===================================================== +// class FileTransferSocketThread +// ===================================================== + +enum FileTransferHostType +{ + eClient, + eServer +}; + +enum FileTransferOperationType +{ + eSend, + eReceive +}; + +class FileTransferInfo +{ +private: + + void CopyAll(const FileTransferInfo &obj) + { + hostType = obj.hostType; + serverIP = obj.serverIP; + serverPort = obj.serverPort; + opType = obj.opType; + fileName = obj.fileName; + } + +public: + FileTransferInfo() + { + } + FileTransferInfo(const FileTransferInfo &obj) + { + CopyAll(obj); + } + FileTransferInfo &operator=(const FileTransferInfo &obj) + { + CopyAll(obj); + return *this; + } + + FileTransferHostType hostType; + string serverIP; + int32 serverPort; + FileTransferOperationType opType; + string fileName; +}; + +class FileInfo +{ +public: + string fileName; + int64 filesize; + int32 filecrc; +}; + +class FileTransferSocketThread : public Thread +{ +private: + FileTransferInfo info; + +public: + FileTransferSocketThread(FileTransferInfo fileInfo); + virtual void execute(); +}; + + }}//end namespace #endif diff --git a/source/glest_game/network/network_message.cpp b/source/glest_game/network/network_message.cpp index 657e975f3..99243eced 100644 --- a/source/glest_game/network/network_message.cpp +++ b/source/glest_game/network/network_message.cpp @@ -3,9 +3,9 @@ // // 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 +// 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 // ============================================================== @@ -20,6 +20,11 @@ #include "leak_dumper.h" +#include "checksum.h" +#include "map.h" +#include "platform_util.h" +#include "config.h" + using namespace Shared::Platform; using namespace Shared::Util; using namespace std; @@ -30,19 +35,48 @@ namespace Glest{ namespace Game{ // class NetworkMessage // ===================================================== -bool NetworkMessage::receive(Socket* socket, void* data, int dataSize){ - if(socket->getDataToRead()>=dataSize){ - if(socket->receive(data, dataSize)!=dataSize){ - throw runtime_error("Error receiving NetworkMessage"); +bool NetworkMessage::receive(Socket* socket, void* data, int dataSize) +{ + int ipeekdatalen = socket->getDataToRead(); + + if(ipeekdatalen >= dataSize) + { + if(socket->receive(data, dataSize)!=dataSize) + { + if(socket != NULL && socket->getSocketId() > 0) + { + throw runtime_error("Error receiving NetworkMessage"); + } + else + { + if(Socket::enableDebugText) printf("In [%s::%s] socket has been disconnected\n",__FILE__,__FUNCTION__); + } + } + else + { + if(Socket::enableDebugText) printf("In [%s::%s] dataSize = %d\n",__FILE__,__FUNCTION__,dataSize); } return true; } + else + { + if(Socket::enableDebugText) printf("In [%s::%s] socket->getDataToRead() returned %d\n",__FILE__,__FUNCTION__,ipeekdatalen); + } return false; } -void NetworkMessage::send(Socket* socket, const void* data, int dataSize) const{ - if(socket->send(data, dataSize)!=dataSize){ - throw runtime_error("Error sending NetworkMessage"); +void NetworkMessage::send(Socket* socket, const void* data, int dataSize) const +{ + if(socket->send(data, dataSize)!=dataSize) + { + if(socket != NULL && socket->getSocketId() > 0) + { + throw runtime_error("Error sending NetworkMessage"); + } + else + { + if(Socket::enableDebugText) printf("In [%s::%s] socket has been disconnected\n",__FILE__,__FUNCTION__); + } } } @@ -51,12 +85,12 @@ void NetworkMessage::send(Socket* socket, const void* data, int dataSize) const{ // ===================================================== NetworkMessageIntro::NetworkMessageIntro(){ - data.messageType= -1; + data.messageType= -1; data.playerIndex= -1; } NetworkMessageIntro::NetworkMessageIntro(const string &versionString, const string &name, int playerIndex){ - data.messageType=nmtIntro; + data.messageType=nmtIntro; data.versionString= versionString; data.name= name; data.playerIndex= static_cast(playerIndex); @@ -76,11 +110,11 @@ void NetworkMessageIntro::send(Socket* socket) const{ // ===================================================== NetworkMessageReady::NetworkMessageReady(){ - data.messageType= nmtReady; + data.messageType= nmtReady; } NetworkMessageReady::NetworkMessageReady(int32 checksum){ - data.messageType= nmtReady; + data.messageType= nmtReady; data.checksum= checksum; } @@ -98,7 +132,7 @@ void NetworkMessageReady::send(Socket* socket) const{ // ===================================================== NetworkMessageLaunch::NetworkMessageLaunch(){ - data.messageType=-1; + data.messageType=-1; } NetworkMessageLaunch::NetworkMessageLaunch(const GameSettings *gameSettings){ @@ -170,12 +204,23 @@ bool NetworkMessageCommandList::addCommand(const NetworkCommand* networkCommand) } bool NetworkMessageCommandList::receive(Socket* socket){ - return NetworkMessage::receive(socket, &data, sizeof(data)); + //return NetworkMessage::receive(socket, &data, sizeof(data)); + + // read type, commandCount & frame num first. + if (!NetworkMessage::receive(socket, &data, networkPacketMsgTypeSize)) { + return false; + } + // read data.commandCount commands. + if (data.commandCount) { + return NetworkMessage::receive(socket, &data.commands, sizeof(NetworkCommand) * data.commandCount); + } + return true; } void NetworkMessageCommandList::send(Socket* socket) const{ assert(data.messageType==nmtCommandList); - NetworkMessage::send(socket, &data, sizeof(data)); + //NetworkMessage::send(socket, &data, sizeof(data)); + NetworkMessage::send(socket, &data, networkPacketMsgTypeSize + sizeof(NetworkCommand) * data.commandCount); } // ===================================================== @@ -183,7 +228,7 @@ void NetworkMessageCommandList::send(Socket* socket) const{ // ===================================================== NetworkMessageText::NetworkMessageText(const string &text, const string &sender, int teamIndex){ - data.messageType= nmtText; + data.messageType= nmtText; data.text= text; data.sender= sender; data.teamIndex= teamIndex; @@ -203,7 +248,7 @@ void NetworkMessageText::send(Socket* socket) const{ // ===================================================== NetworkMessageQuit::NetworkMessageQuit(){ - data.messageType= nmtQuit; + data.messageType= nmtQuit; } bool NetworkMessageQuit::receive(Socket* socket){ @@ -215,4 +260,133 @@ void NetworkMessageQuit::send(Socket* socket) const{ NetworkMessage::send(socket, &data, sizeof(data)); } +// ===================================================== +// class NetworkMessageSynchNetworkGameData +// ===================================================== + +NetworkMessageSynchNetworkGameData::NetworkMessageSynchNetworkGameData(const GameSettings *gameSettings) +{ + data.messageType= nmtSynchNetworkGameData; + + data.map = gameSettings->getMap(); + data.tileset = gameSettings->getTileset(); + data.tech = gameSettings->getTech(); + + //Checksum checksum; + //tileset + //string file = "tilesets/" + gameSettings->getTileset() + "/" + gameSettings->getTileset() + ".xml"; + //checksum.addFile(file); + // models + // sounds + // textures + //data.tilesetCRC = checksum.getSum(); + //if(Socket::enableDebugText) printf("In [%s::%s] file = [%s] checksum = %d\n",__FILE__,__FUNCTION__,file.c_str(),data.tilesetCRC); + data.tilesetCRC = getFolderTreeContentsCheckSumRecursively("tilesets/" + gameSettings->getTileset() + "/*", "xml", NULL); + + //tech, load before map because of resources + //checksum = Checksum(); + //file = "techs/" + gameSettings->getTech() + "/" + gameSettings->getTech() + ".xml"; + //checksum.addFile(file); + // factions + // resources + //data.techCRC = checksum.getSum(); + //if(Socket::enableDebugText) printf("In [%s::%s] file = [%s] checksum = %d\n",__FILE__,__FUNCTION__,file.c_str(),data.techCRC); + data.techCRC = getFolderTreeContentsCheckSumRecursively("techs/" + gameSettings->getTech() + "/*", "xml", NULL); + + //map + Checksum checksum; + string file = Map::getMapPath(gameSettings->getMap()); + checksum.addFile(file); + data.mapCRC = checksum.getSum(); + //if(Socket::enableDebugText) printf("In [%s::%s] file = [%s] checksum = %d\n",__FILE__,__FUNCTION__,file.c_str(),data.mapCRC); + + data.hasFogOfWar = Config::getInstance().getBool("FogOfWar");; +} + +bool NetworkMessageSynchNetworkGameData::receive(Socket* socket) +{ + return NetworkMessage::receive(socket, &data, sizeof(data)); +} + +void NetworkMessageSynchNetworkGameData::send(Socket* socket) const +{ + assert(data.messageType==nmtSynchNetworkGameData); + NetworkMessage::send(socket, &data, sizeof(data)); +} + + +// ===================================================== +// class NetworkMessageSynchNetworkGameDataStatus +// ===================================================== + +NetworkMessageSynchNetworkGameDataStatus::NetworkMessageSynchNetworkGameDataStatus(int32 mapCRC, int32 tilesetCRC, int32 techCRC, int8 hasFogOfWar) +{ + data.messageType= nmtSynchNetworkGameDataStatus; + + data.tilesetCRC = tilesetCRC; + data.techCRC = techCRC; + data.mapCRC = mapCRC; + + data.hasFogOfWar = hasFogOfWar; +} + +bool NetworkMessageSynchNetworkGameDataStatus::receive(Socket* socket) +{ + return NetworkMessage::receive(socket, &data, sizeof(data)); +} + +void NetworkMessageSynchNetworkGameDataStatus::send(Socket* socket) const +{ + assert(data.messageType==nmtSynchNetworkGameDataStatus); + NetworkMessage::send(socket, &data, sizeof(data)); +} + +// ===================================================== +// class NetworkMessageSynchNetworkGameDataFileCRCCheck +// ===================================================== + +NetworkMessageSynchNetworkGameDataFileCRCCheck::NetworkMessageSynchNetworkGameDataFileCRCCheck(int32 totalFileCount, int32 fileIndex, int32 fileCRC, const string fileName) +{ + data.messageType= nmtSynchNetworkGameDataFileCRCCheck; + + data.totalFileCount = totalFileCount; + data.fileIndex = fileIndex; + data.fileCRC = fileCRC; + data.fileName = fileName; +} + +bool NetworkMessageSynchNetworkGameDataFileCRCCheck::receive(Socket* socket) +{ + return NetworkMessage::receive(socket, &data, sizeof(data)); +} + +void NetworkMessageSynchNetworkGameDataFileCRCCheck::send(Socket* socket) const +{ + assert(data.messageType==nmtSynchNetworkGameDataFileCRCCheck); + NetworkMessage::send(socket, &data, sizeof(data)); +} + +// ===================================================== +// class NetworkMessageSynchNetworkGameDataFileGet +// ===================================================== + +NetworkMessageSynchNetworkGameDataFileGet::NetworkMessageSynchNetworkGameDataFileGet(const string fileName) +{ + data.messageType= nmtSynchNetworkGameDataFileGet; + + data.fileName = fileName; +} + +bool NetworkMessageSynchNetworkGameDataFileGet::receive(Socket* socket) +{ + return NetworkMessage::receive(socket, &data, sizeof(data)); +} + +void NetworkMessageSynchNetworkGameDataFileGet::send(Socket* socket) const +{ + assert(data.messageType==nmtSynchNetworkGameDataFileGet); + NetworkMessage::send(socket, &data, sizeof(data)); +} + + }}//end namespace diff --git a/source/glest_game/network/network_message.h b/source/glest_game/network/network_message.h index 4251b33c0..48dfeed8e 100644 --- a/source/glest_game/network/network_message.h +++ b/source/glest_game/network/network_message.h @@ -3,9 +3,9 @@ // // 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 +// 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 // ============================================================== @@ -33,10 +33,16 @@ enum NetworkMessageType{ nmtCommandList, nmtText, nmtQuit, + nmtSynchNetworkGameData, + nmtSynchNetworkGameDataStatus, + nmtSynchNetworkGameDataFileCRCCheck, + nmtSynchNetworkGameDataFileGet, nmtCount }; +const int32 networkPacketMsgTypeSize = 6; + // ===================================================== // class NetworkMessage // ===================================================== @@ -163,10 +169,11 @@ public: // Message to order a commands to several units // ===================================================== +#pragma pack(push, 1) class NetworkMessageCommandList: public NetworkMessage{ private: static const int maxCommandCount= 16*4; - + private: struct Data{ int8 messageType; @@ -182,7 +189,7 @@ public: NetworkMessageCommandList(int32 frameCount= -1); bool addCommand(const NetworkCommand* networkCommand); - + void clear() {data.commandCount= 0;} int getCommandCount() const {return data.commandCount;} int getFrameCount() const {return data.frameCount;} @@ -191,6 +198,7 @@ public: virtual bool receive(Socket* socket); virtual void send(Socket* socket) const; }; +#pragma pack(pop) // ===================================================== // class NetworkMessageText @@ -247,6 +255,164 @@ public: virtual void send(Socket* socket) const; }; +// ===================================================== +// class NetworkMessageSynchNetworkGameData +// +// Message sent at the beggining of a network game +// ===================================================== + +class NetworkMessageSynchNetworkGameData: public NetworkMessage{ + +private: + +static const int maxStringSize= 256; + +private: + struct Data{ + int8 messageType; + + NetworkString map; + NetworkString tileset; + NetworkString tech; + + int32 mapCRC; + int32 tilesetCRC; + int32 techCRC; + int8 hasFogOfWar; + }; + +private: + Data data; + +public: + NetworkMessageSynchNetworkGameData() {}; + NetworkMessageSynchNetworkGameData(const GameSettings *gameSettings); + + virtual bool receive(Socket* socket); + virtual void send(Socket* socket) const; + + string getMap() const {return data.map.getString();} + string getTileset() const {return data.tileset.getString();} + string getTech() const {return data.tech.getString();} + + int32 getMapCRC() const {return data.mapCRC;} + int32 getTilesetCRC() const {return data.tilesetCRC;} + int32 getTechCRC() const {return data.techCRC;} + + int8 getFogOfWar() const { return data.hasFogOfWar; } +}; + +// ===================================================== +// class NetworkMessageSynchNetworkGameDataStatus +// +// Message sent at the beggining of a network game +// ===================================================== + +class NetworkMessageSynchNetworkGameDataStatus: public NetworkMessage{ + +private: + +static const int maxStringSize= 256; + +private: + struct Data{ + int8 messageType; + + int32 mapCRC; + int32 tilesetCRC; + int32 techCRC; + + int8 hasFogOfWar; + }; + +private: + Data data; + +public: + NetworkMessageSynchNetworkGameDataStatus() {}; + NetworkMessageSynchNetworkGameDataStatus(int32 mapCRC, int32 tilesetCRC, int32 techCRC, int8 hasFogOfWar); + + virtual bool receive(Socket* socket); + virtual void send(Socket* socket) const; + + int32 getMapCRC() const {return data.mapCRC;} + int32 getTilesetCRC() const {return data.tilesetCRC;} + int32 getTechCRC() const {return data.techCRC;} + + int8 getFogOfWar() const { return data.hasFogOfWar; } +}; + +// ===================================================== +// class NetworkMessageSynchNetworkGameDataFileCRCCheck +// +// Message sent at the beggining of a network game +// ===================================================== + +class NetworkMessageSynchNetworkGameDataFileCRCCheck: public NetworkMessage{ + +private: + +static const int maxStringSize= 256; + +private: + struct Data{ + int8 messageType; + + int32 totalFileCount; + int32 fileIndex; + int32 fileCRC; + NetworkString fileName; + }; + +private: + Data data; + +public: + NetworkMessageSynchNetworkGameDataFileCRCCheck() {}; + NetworkMessageSynchNetworkGameDataFileCRCCheck(int32 totalFileCount, int32 fileIndex, int32 fileCRC, const string fileName); + + virtual bool receive(Socket* socket); + virtual void send(Socket* socket) const; + + int32 getTotalFileCount() const {return data.totalFileCount;} + int32 getFileIndex() const {return data.fileIndex;} + int32 getFileCRC() const {return data.fileCRC;} + string getFileName() const {return data.fileName.getString();} +}; + +// ===================================================== +// class NetworkMessageSynchNetworkGameDataFileGet +// +// Message sent at the beggining of a network game +// ===================================================== + +class NetworkMessageSynchNetworkGameDataFileGet: public NetworkMessage{ + +private: + +static const int maxStringSize= 256; + +private: + struct Data{ + int8 messageType; + + NetworkString fileName; + }; + +private: + Data data; + +public: + NetworkMessageSynchNetworkGameDataFileGet() {}; + NetworkMessageSynchNetworkGameDataFileGet(const string fileName); + + virtual bool receive(Socket* socket); + virtual void send(Socket* socket) const; + + string getFileName() const {return data.fileName.getString();} +}; + + }}//end namespace #endif diff --git a/source/glest_game/network/network_types.h b/source/glest_game/network/network_types.h index ca5405a13..753d8f096 100644 --- a/source/glest_game/network/network_types.h +++ b/source/glest_game/network/network_types.h @@ -3,9 +3,9 @@ // // 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 +// 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 // ============================================================== @@ -50,6 +50,7 @@ enum NetworkCommandType{ nctSetMeetingPoint }; +#pragma pack(push, 2) class NetworkCommand{ private: int16 networkCommandType; @@ -71,6 +72,7 @@ public: int getUnitTypeId() const {return unitTypeId;} int getTargetId() const {return targetId;} }; +#pragma pack(pop) }}//end namespace diff --git a/source/glest_game/network/server_interface.cpp b/source/glest_game/network/server_interface.cpp index 6a77ce04e..78509c18c 100644 --- a/source/glest_game/network/server_interface.cpp +++ b/source/glest_game/network/server_interface.cpp @@ -3,9 +3,9 @@ // // 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 +// 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 // ============================================================== @@ -20,6 +20,8 @@ #include "lang.h" #include "leak_dumper.h" +#include "logger.h" +#include using namespace std; using namespace Shared::Platform; @@ -32,6 +34,9 @@ namespace Glest{ namespace Game{ // ===================================================== ServerInterface::ServerInterface(){ + gameHasBeenInitiated = false; + gameSettingsUpdateCount = 0; + for(int i= 0; i=0 && playerIndex socketTriggeredList; //update all slots - for(int i= 0; iupdate(); + for(int i= 0; i < GameConstants::maxPlayers; ++i) + { + ConnectionSlot* connectionSlot= slots[i]; + if(connectionSlot != NULL && connectionSlot->getSocket() != NULL && + slots[i]->getSocket()->getSocketId() > 0) + { + socketTriggeredList[connectionSlot->getSocket()->getSocketId()] = false; } } - //process text messages - chatText.clear(); - chatSender.clear(); - chatTeamIndex= -1; + chatText.clear(); + chatSender.clear(); + chatTeamIndex= -1; - for(int i= 0; i 0) + { + if(gameHasBeenInitiated && Socket::enableDebugText) printf("In [%s::%s] socketTriggeredList.size() = %d\n",__FILE__,__FUNCTION__,socketTriggeredList.size()); - if(connectionSlot!= NULL){ - if(connectionSlot->isConnected()){ - if(connectionSlot->getNextMessageType()==nmtText){ - NetworkMessageText networkMessageText; - if(connectionSlot->receiveMessage(&networkMessageText)){ - broadcastMessage(&networkMessageText, i); - chatText= networkMessageText.getText(); - chatSender= networkMessageText.getSender(); - chatTeamIndex= networkMessageText.getTeamIndex(); - break; - } - } - } - } - } + bool hasData = Socket::hasDataToRead(socketTriggeredList); + + if(hasData && Socket::enableDebugText) printf("In [%s::%s] hasData == true\n",__FILE__,__FUNCTION__); + + if(gameHasBeenInitiated == false || hasData == true) + { + //if(gameHasBeenInitiated && Socket::enableDebugText) printf("In [%s::%s] hasData == true\n",__FILE__,__FUNCTION__); + + //std::vector vctTeamMessages; + + //update all slots + bool checkForNewClients = true; + for(int i= 0; igetSocket() != NULL && socketTriggeredList[connectionSlot->getSocket()->getSocketId()] == true))) + { + if(connectionSlot->isConnected() == false || + (socketTriggeredList[connectionSlot->getSocket()->getSocketId()] == true)) + { + if(gameHasBeenInitiated && Socket::enableDebugText) printf("In [%s::%s] socketTriggeredList[i] = %i\n",__FILE__,__FUNCTION__,(socketTriggeredList[connectionSlot->getSocket()->getSocketId()] ? 1 : 0)); + + if(connectionSlot->isConnected()) + { + if(Socket::enableDebugText) printf("In [%s::%s] calling slots[i]->update() for slot = %d socketId = %d\n", + __FILE__,__FUNCTION__,i,connectionSlot->getSocket()->getSocketId()); + } + else + { + if(gameHasBeenInitiated && Socket::enableDebugText) printf("In [%s::%s] slot = %d getSocket() == NULL\n",__FILE__,__FUNCTION__,i); + } + connectionSlot->update(checkForNewClients); + + // This means no clients are trying to connect at the moment + if(connectionSlot != NULL && connectionSlot->getSocket() == NULL) + { + checkForNewClients = false; + } + + if(connectionSlot != NULL && + //connectionSlot->isConnected() == true && + connectionSlot->getChatText().empty() == false) + { + chatText = connectionSlot->getChatText(); + chatSender = connectionSlot->getChatSender(); + chatTeamIndex = connectionSlot->getChatTeamIndex(); + + //TeamMessageData teamMessageData; + //teamMessageData.chatSender = connectionSlot->getChatSender(); + //teamMessageData.chatText = connectionSlot->getChatText(); + //teamMessageData.chatTeamIndex = connectionSlot->getChatTeamIndex(); + //teamMessageData.sourceTeamIndex = i; + //vctTeamMessages.push_back(teamMessageData); + + if(Socket::enableDebugText) printf("In [%s::%s] #1 about to broadcast nmtText chatText [%s] chatSender [%s] chatTeamIndex = %d for SlotIndex# %d\n",__FILE__,__FUNCTION__,chatText.c_str(),chatSender.c_str(),chatTeamIndex,i); + + NetworkMessageText networkMessageText(chatText,chatSender,chatTeamIndex); + broadcastMessage(&networkMessageText, i); + break; + } + } + } + } + + //process text messages + if(chatText.empty() == true) + { + chatText.clear(); + chatSender.clear(); + chatTeamIndex= -1; + + for(int i= 0; i< GameConstants::maxPlayers; ++i) + { + ConnectionSlot* connectionSlot= slots[i]; + + if(connectionSlot!= NULL && + (gameHasBeenInitiated == false || (connectionSlot->getSocket() != NULL && socketTriggeredList[connectionSlot->getSocket()->getSocketId()] == true))) + { + if(connectionSlot->isConnected() && socketTriggeredList[connectionSlot->getSocket()->getSocketId()] == true) + { + if(connectionSlot->getSocket() != NULL && Socket::enableDebugText) printf("In [%s::%s] calling connectionSlot->getNextMessageType() for slots[i]->getSocket()->getSocketId() = %d\n", + __FILE__,__FUNCTION__,connectionSlot->getSocket()->getSocketId()); + + if(connectionSlot->getNextMessageType() == nmtText) + { + NetworkMessageText networkMessageText; + if(connectionSlot->receiveMessage(&networkMessageText)) + { + if(Socket::enableDebugText) printf("In [%s::%s] #2 about to broadcast nmtText msg for SlotIndex# %d\n",__FILE__,__FUNCTION__,i); + + broadcastMessage(&networkMessageText, i); + chatText= networkMessageText.getText(); + chatSender= networkMessageText.getSender(); + chatTeamIndex= networkMessageText.getTeamIndex(); + break; + } + } + } + } + } + } + } + } } void ServerInterface::updateKeyframe(int frameCount){ NetworkMessageCommandList networkMessageCommandList(frameCount); - + //build command list, remove commands from requested and add to pending while(!requestedCommands.empty()){ if(networkMessageCommandList.addCommand(&requestedCommands.back())){ @@ -128,51 +243,100 @@ void ServerInterface::updateKeyframe(int frameCount){ } void ServerInterface::waitUntilReady(Checksum* checksum){ - + + if(Socket::enableDebugText) printf("In [%s] START\n",__FUNCTION__); + + Logger &logger= Logger::getInstance(); + gameHasBeenInitiated = true; + Chrono chrono; bool allReady= false; chrono.start(); //wait until we get a ready message from all clients - while(!allReady){ - + while(allReady == false) + { + vector waitingForHosts; allReady= true; - for(int i= 0; iisReady()){ - NetworkMessageType networkMessageType= connectionSlot->getNextMessageType(); + if(connectionSlot != NULL && connectionSlot->isConnected() == true) + { + if(connectionSlot->isReady() == false) + { + NetworkMessageType networkMessageType= connectionSlot->getNextMessageType(true); NetworkMessageReady networkMessageReady; - if(networkMessageType==nmtReady && connectionSlot->receiveMessage(&networkMessageReady)){ + if(networkMessageType == nmtReady && + connectionSlot->receiveMessage(&networkMessageReady)) + { + if(Socket::enableDebugText) printf("In [%s] networkMessageType==nmtReady\n",__FUNCTION__); + connectionSlot->setReady(); } - else if(networkMessageType!=nmtInvalid){ + else if(networkMessageType != nmtInvalid) + { throw runtime_error("Unexpected network message: " + intToStr(networkMessageType)); } + waitingForHosts.push_back(connectionSlot->getHostName()); + allReady= false; } } } //check for timeout - if(chrono.getMillis()>readyWaitTimeout){ - throw runtime_error("Timeout waiting for clients"); + if(allReady == false) + { + if(chrono.getMillis() > readyWaitTimeout) + { + throw runtime_error("Timeout waiting for clients"); + } + else + { + if(chrono.getMillis() % 1000 == 0) + { + string waitForHosts = ""; + for(int i = 0; i < waitingForHosts.size(); i++) + { + if(waitForHosts != "") + { + waitForHosts += ", "; + } + waitForHosts += waitingForHosts[i]; + } + + char szBuf[1024]=""; + sprintf(szBuf,"Waiting for network: %d of %d max seconds (waiting for: %s)",int(chrono.getMillis() / 1000),int(readyWaitTimeout / 1000),waitForHosts.c_str()); + logger.add(szBuf, true); + } + } } } - //send ready message after, so clients start delayed - for(int i= 0; igetSum()); - ConnectionSlot* connectionSlot= slots[i]; - if(connectionSlot!=NULL){ + // FOR TESTING ONLY - delay to see the client count up while waiting + //sleep(5000); + + if(Socket::enableDebugText) printf("In [%s] PART B (telling client we are ready!\n",__FUNCTION__); + + //send ready message after, so clients start delayed + for(int i= 0; i < GameConstants::maxPlayers; ++i) + { + NetworkMessageReady networkMessageReady(checksum->getSum()); + + ConnectionSlot* connectionSlot= slots[i]; + if(connectionSlot!=NULL) + { connectionSlot->sendMessage(&networkMessageReady); } } + + if(Socket::enableDebugText) printf("In [%s] END\n",__FUNCTION__); } void ServerInterface::sendTextMessage(const string &text, int teamIndex){ @@ -180,7 +344,15 @@ void ServerInterface::sendTextMessage(const string &text, int teamIndex){ broadcastMessage(&networkMessageText); } -void ServerInterface::quitGame(){ +void ServerInterface::quitGame(bool userManuallyQuit) +{ + if(userManuallyQuit == true) + { + string sQuitText = getHostName() + " has chosen to leave the game!"; + NetworkMessageText networkMessageText(sQuitText,getHostName(),-1); + broadcastMessage(&networkMessageText, -1); + } + NetworkMessageQuit networkMessageQuit; broadcastMessage(&networkMessageQuit); } @@ -191,12 +363,13 @@ string ServerInterface::getNetworkStatus() const{ for(int i= 0; iisConnected()){ - str+= connectionSlot->getName(); + + str+= connectionSlot->getName(); } } else @@ -209,31 +382,96 @@ string ServerInterface::getNetworkStatus() const{ return str; } -void ServerInterface::launchGame(const GameSettings* gameSettings){ - NetworkMessageLaunch networkMessageLaunch(gameSettings); - broadcastMessage(&networkMessageLaunch); +bool ServerInterface::launchGame(const GameSettings* gameSettings){ + + bool bOkToStart = true; + + for(int i= 0; igetAllowDownloadDataSynch() == true && + connectionSlot->isConnected()) + { + if(connectionSlot->getNetworkGameDataSynchCheckOk() == false) + { + bOkToStart = false; + break; + } + } + } + + if(bOkToStart == true) + { + NetworkMessageLaunch networkMessageLaunch(gameSettings); + broadcastMessage(&networkMessageLaunch); + } + + return bOkToStart; } void ServerInterface::broadcastMessage(const NetworkMessage* networkMessage, int excludeSlot){ + + //if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__); + + for(int i= 0; iisConnected()) + { + + if(Socket::enableDebugText) printf("In [%s::%s] before sendMessage\n",__FILE__,__FUNCTION__); + connectionSlot->sendMessage(networkMessage); + } + else if(gameHasBeenInitiated == true) + { + + if(Socket::enableDebugText) printf("In [%s::%s] #1 before removeSlot for slot# %d\n",__FILE__,__FUNCTION__,i); + removeSlot(i); + } + } + else if(i == excludeSlot && gameHasBeenInitiated == true && + connectionSlot != NULL && connectionSlot->isConnected() == false) + { + if(Socket::enableDebugText) printf("In [%s::%s] #2 before removeSlot for slot# %d\n",__FILE__,__FUNCTION__,i); + removeSlot(i); + } + } + + //if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__); +} + +void ServerInterface::broadcastMessageToConnectedClients(const NetworkMessage* networkMessage, int excludeSlot){ + + //if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__); + for(int i= 0; iisConnected()){ + + if(Socket::enableDebugText) printf("In [%s::%s] before sendMessage\n",__FILE__,__FUNCTION__); + connectionSlot->sendMessage(networkMessage); } - else{ - removeSlot(i); - } } } + + //if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__); } -void ServerInterface::updateListen(){ +void ServerInterface::updateListen() +{ int openSlotCount= 0; - - for(int i= 0; iisConnected()){ + + for(int i= 0; iisConnected() == false) + { ++openSlotCount; } } @@ -241,4 +479,92 @@ void ServerInterface::updateListen(){ serverSocket.listen(openSlotCount); } +void ServerInterface::setGameSettings(GameSettings *serverGameSettings, bool waitForClientAck) +{ + if(Socket::enableDebugText) printf("In [%s::%s] START gameSettingsUpdateCount = %d\n",__FILE__,__FUNCTION__,gameSettingsUpdateCount); + + if(getAllowGameDataSynchCheck() == true) + { + if(waitForClientAck == true && gameSettingsUpdateCount > 0) + { + if(Socket::enableDebugText) printf("In [%s::%s] Waiting for client acks #1\n",__FILE__,__FUNCTION__); + + time_t tStart = time(NULL); + bool gotAckFromAllClients = false; + while(gotAckFromAllClients == false && difftime(time(NULL),tStart) <= 5) + { + gotAckFromAllClients = true; + for(int i= 0; iisConnected()) + { + if(connectionSlot->getReceivedNetworkGameStatus() == false) + { + gotAckFromAllClients = false; + } + + connectionSlot->update(); + } + } + } + } + + for(int i= 0; iisConnected()) + { + connectionSlot->setReceivedNetworkGameStatus(false); + } + } + + gameSettings = *serverGameSettings; + + NetworkMessageSynchNetworkGameData networkMessageSynchNetworkGameData(getGameSettings()); + broadcastMessageToConnectedClients(&networkMessageSynchNetworkGameData); + + if(waitForClientAck == true) + { + if(Socket::enableDebugText) printf("In [%s::%s] Waiting for client acks #2\n",__FILE__,__FUNCTION__); + + time_t tStart = time(NULL); + bool gotAckFromAllClients = false; + while(gotAckFromAllClients == false && difftime(time(NULL),tStart) <= 5) + { + gotAckFromAllClients = true; + for(int i= 0; iisConnected()) + { + if(connectionSlot->getReceivedNetworkGameStatus() == false) + { + gotAckFromAllClients = false; + } + + connectionSlot->update(); + } + } + } + } + + gameSettingsUpdateCount++; + } + + if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__); +} + +void ServerInterface::close() +{ + if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__); + + //serverSocket = ServerSocket(); +} + +bool ServerInterface::getFogOfWar() +{ + return Config::getInstance().getBool("FogOfWar"); +} + }}//end namespace diff --git a/source/glest_game/network/server_interface.h b/source/glest_game/network/server_interface.h index 88868f570..91cdaa3f8 100644 --- a/source/glest_game/network/server_interface.h +++ b/source/glest_game/network/server_interface.h @@ -3,9 +3,9 @@ // // 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 +// 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 // ============================================================== @@ -28,10 +28,21 @@ namespace Glest{ namespace Game{ // class ServerInterface // ===================================================== +typedef struct +{ + string chatText; + string chatSender; + int chatTeamIndex; + int sourceTeamIndex; + +} TeamMessageData; + class ServerInterface: public GameNetworkInterface{ private: ConnectionSlot* slots[GameConstants::maxPlayers]; ServerSocket serverSocket; + bool gameHasBeenInitiated; + int gameSettingsUpdateCount; public: ServerInterface(); @@ -39,6 +50,7 @@ public: virtual Socket* getSocket() {return &serverSocket;} virtual const Socket* getSocket() const {return &serverSocket;} + virtual void close(); //message processing virtual void update(); @@ -48,7 +60,7 @@ public: // message sending virtual void sendTextMessage(const string &text, int teamIndex); - virtual void quitGame(); + virtual void quitGame(bool userManuallyQuit); //misc virtual string getNetworkStatus() const; @@ -59,11 +71,14 @@ public: ConnectionSlot* getSlot(int playerIndex); int getConnectedSlotCount(); - void launchGame(const GameSettings* gameSettings); + bool launchGame(const GameSettings* gameSettings); + virtual void setGameSettings(GameSettings *serverGameSettings, bool waitForClientAck = false); + virtual bool getFogOfWar(); private: void broadcastMessage(const NetworkMessage* networkMessage, int excludeSlot= -1); void updateListen(); + void broadcastMessageToConnectedClients(const NetworkMessage* networkMessage, int excludeSlot = -1); }; }}//end namespace diff --git a/source/glest_game/type_instances/faction.cpp b/source/glest_game/type_instances/faction.cpp index 8e2a45025..e5f9ea349 100644 --- a/source/glest_game/type_instances/faction.cpp +++ b/source/glest_game/type_instances/faction.cpp @@ -1,11 +1,11 @@ // ============================================================== // This file is part of Glest (www.glest.org) // -// Copyright (C) 2001-2008 Marti�o Figueroa +// 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 +// 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 // ============================================================== @@ -31,7 +31,7 @@ namespace Glest{ namespace Game{ // ===================================================== void Faction::init( - const FactionType *factionType, ControlType control, TechTree *techTree, + const FactionType *factionType, ControlType control, TechTree *techTree, int factionIndex, int teamIndex, int startLocationIndex, bool thisFaction, bool giveResources) { this->control= control; @@ -83,7 +83,7 @@ int Faction::getStoreAmount(const ResourceType *rt) const{ bool Faction::getCpuControl() const{ return control==ctCpuEasy ||control==ctCpu || control==ctCpuUltra|| control==ctCpuMega; } - + // ==================== upgrade manager ==================== @@ -106,9 +106,9 @@ void Faction::finishUpgrade(const UpgradeType *ut){ //checks if all required units and upgrades are present bool Faction::reqsOk(const RequirableType *rt) const{ - + //required units - for(int i=0; igetUnitReqCount(); ++i){ + for(int i=0; igetUnitReqCount(); ++i){ bool found=false; for(int j=0; jgetUpgradeReqCount(); ++i){ - if(!upgradeManager.isUpgraded(rt->getUpgradeReq(i))){ + if(!upgradeManager.isUpgraded(rt->getUpgradeReq(i))){ return false; } } @@ -134,7 +134,7 @@ bool Faction::reqsOk(const RequirableType *rt) const{ } bool Faction::reqsOk(const CommandType *ct) const{ - + if(ct->getProduced()!=NULL && !reqsOk(ct->getProduced())){ return false; } @@ -145,113 +145,134 @@ bool Faction::reqsOk(const CommandType *ct) const{ return false; } } - - return reqsOk(static_cast(ct)); + + return reqsOk(static_cast(ct)); } // ================== cost application ================== //apply costs except static production (start building/production) bool Faction::applyCosts(const ProducibleType *p){ - + if(!checkCosts(p)){ return false; } - + //for each unit cost spend it //pass 2, decrease resources, except negative static costs (ie: farms) - for(int i=0; igetCostCount(); ++i){ + for(int i=0; igetCostCount(); ++i) + { const ResourceType *rt= p->getCost(i)->getType(); int cost= p->getCost(i)->getAmount(); - if((cost>0 || rt->getClass()!=rcStatic) && rt->getClass()!=rcConsumable){ + if((cost > 0 || (rt->getClass() != rcStatic)) && rt->getClass() != rcConsumable) + { incResourceAmount(rt, -(cost)); } - + } return true; } //apply discount (when a morph ends) -void Faction::applyDiscount(const ProducibleType *p, int discount){ +void Faction::applyDiscount(const ProducibleType *p, int discount) +{ //increase resources - for(int i=0; igetCostCount(); ++i){ + for(int i=0; igetCostCount(); ++i) + { const ResourceType *rt= p->getCost(i)->getType(); int cost= p->getCost(i)->getAmount(); - if((cost>0 || rt->getClass()!=rcStatic) && rt->getClass()!=rcConsumable){ + if((cost > 0 || (rt->getClass() != rcStatic)) && rt->getClass() != rcConsumable) + { incResourceAmount(rt, cost*discount/100); } } } //apply static production (for starting units) -void Faction::applyStaticCosts(const ProducibleType *p){ - +void Faction::applyStaticCosts(const ProducibleType *p) +{ //decrease static resources - for(int i=0; igetCostCount(); ++i){ + for(int i=0; igetCostCount(); ++i) + { const ResourceType *rt= p->getCost(i)->getType(); - if(rt->getClass()==rcStatic){ + if(rt->getClass() == rcStatic) + { int cost= p->getCost(i)->getAmount(); - if(cost>0){ + if(cost > 0) + { incResourceAmount(rt, -cost); } - } + } } } //apply static production (when a mana source is done) -void Faction::applyStaticProduction(const ProducibleType *p){ - +void Faction::applyStaticProduction(const ProducibleType *p) +{ //decrease static resources - for(int i=0; igetCostCount(); ++i){ + for(int i=0; igetCostCount(); ++i) + { const ResourceType *rt= p->getCost(i)->getType(); - if(rt->getClass()==rcStatic){ + if(rt->getClass() == rcStatic) + { int cost= p->getCost(i)->getAmount(); - if(cost<0){ + if(cost < 0) + { incResourceAmount(rt, -cost); } - } + } } } //deapply all costs except static production (usually when a building is cancelled) -void Faction::deApplyCosts(const ProducibleType *p){ - +void Faction::deApplyCosts(const ProducibleType *p) +{ //increase resources - for(int i=0; igetCostCount(); ++i){ + for(int i=0; igetCostCount(); ++i) + { const ResourceType *rt= p->getCost(i)->getType(); int cost= p->getCost(i)->getAmount(); - if((cost>0 || rt->getClass()!=rcStatic) && rt->getClass()!=rcConsumable){ + if((cost > 0 || (rt->getClass() != rcStatic)) && rt->getClass() != rcConsumable) + { incResourceAmount(rt, cost); } - + } } //deapply static costs (usually when a unit dies) -void Faction::deApplyStaticCosts(const ProducibleType *p){ - +void Faction::deApplyStaticCosts(const ProducibleType *p) +{ //decrease resources - for(int i=0; igetCostCount(); ++i){ + for(int i=0; igetCostCount(); ++i) + { const ResourceType *rt= p->getCost(i)->getType(); - if(rt->getClass()==rcStatic){ - int cost= p->getCost(i)->getAmount(); - incResourceAmount(rt, cost); - } + if(rt->getClass() == rcStatic) + { + if(rt->getRecoup_cost() == true) + { + int cost= p->getCost(i)->getAmount(); + incResourceAmount(rt, cost); + } + } } } //deapply static costs, but not negative costs, for when building gets killed -void Faction::deApplyStaticConsumption(const ProducibleType *p){ - +void Faction::deApplyStaticConsumption(const ProducibleType *p) +{ //decrease resources - for(int i=0; igetCostCount(); ++i){ + for(int i=0; igetCostCount(); ++i) + { const ResourceType *rt= p->getCost(i)->getType(); - if(rt->getClass()==rcStatic){ + if(rt->getClass() == rcStatic) + { int cost= p->getCost(i)->getAmount(); - if(cost>0){ + if(cost>0) + { incResourceAmount(rt, cost); } - } + } } } @@ -279,7 +300,7 @@ void Faction::applyCostsOnInterval(){ const Resource *resource= unit->getType()->getCost(k); if(resource->getType()->getClass()==rcConsumable && resource->getAmount()>0){ incResourceAmount(resource->getType(), -resource->getAmount()); - + //decrease unit hp if(getResource(resource->getType())->getAmount()<0){ resetResourceAmount(resource->getType()); @@ -296,7 +317,7 @@ void Faction::applyCostsOnInterval(){ } bool Faction::checkCosts(const ProducibleType *pt){ - + //for each unit cost check if enough resources for(int i=0; igetCostCount(); ++i){ const ResourceType *rt= pt->getCost(i)->getType(); @@ -304,7 +325,7 @@ bool Faction::checkCosts(const ProducibleType *pt){ if(cost>0){ int available= getResource(rt)->getAmount(); if(cost>available){ - return false; + return false; } } } @@ -320,12 +341,16 @@ bool Faction::isAlly(const Faction *faction){ // ================== misc ================== -void Faction::incResourceAmount(const ResourceType *rt, int amount){ - for(int i=0; igetType()==rt){ + if(r->getType()==rt) + { r->setAmount(r->getAmount()+amount); - if(r->getType()->getClass()!=rcStatic && r->getAmount()>getStoreAmount(rt)){ + if(r->getType()->getClass() != rcStatic && r->getAmount()>getStoreAmount(rt)) + { r->setAmount(getStoreAmount(rt)); } return; @@ -368,7 +393,7 @@ void Faction::removeUnit(Unit *unit){ return; } } - assert(false); + assert(false); } void Faction::addStore(const UnitType *unitType){ @@ -396,11 +421,14 @@ void Faction::removeStore(const UnitType *unitType){ limitResourcesToStore(); } -void Faction::limitResourcesToStore(){ - for(int i=0; igetType()->getClass()!=rcStatic && r->getAmount()>s->getAmount()){ + if(r->getType()->getClass() != rcStatic && r->getAmount()>s->getAmount()) + { r->setAmount(s->getAmount()); } } diff --git a/source/glest_game/type_instances/faction.h b/source/glest_game/type_instances/faction.h index 1c2bd883b..6aa245c14 100644 --- a/source/glest_game/type_instances/faction.h +++ b/source/glest_game/type_instances/faction.h @@ -1,7 +1,7 @@ // ============================================================== // This file is part of Glest (www.glest.org) // -// Copyright (C) 2001-2008 Marti�o Figueroa +// 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 diff --git a/source/glest_game/type_instances/unit.cpp b/source/glest_game/type_instances/unit.cpp index d1095cf0a..6a50ce2d5 100644 --- a/source/glest_game/type_instances/unit.cpp +++ b/source/glest_game/type_instances/unit.cpp @@ -1,7 +1,7 @@ // ============================================================== // This file is part of Glest (www.glest.org) // -// Copyright (C) 2001-2008 Marti�o Figueroa +// 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 diff --git a/source/glest_game/type_instances/unit.h b/source/glest_game/type_instances/unit.h index f16e53d3d..030d879ca 100644 --- a/source/glest_game/type_instances/unit.h +++ b/source/glest_game/type_instances/unit.h @@ -1,7 +1,7 @@ // ============================================================== // This file is part of Glest (www.glest.org) // -// Copyright (C) 2001-2008 Marti�o Figueroa +// 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 @@ -254,7 +254,7 @@ public: //command related bool anyCommand() const; Command *getCurrCommand() const; - uint getCommandSize() const; + unsigned int getCommandSize() const; CommandResult giveCommand(Command *command); //give a command CommandResult finishCommand(); //command finished CommandResult cancelCommand(); //cancel canceled diff --git a/source/glest_game/types/resource_type.cpp b/source/glest_game/types/resource_type.cpp index d5e46eb19..f872fcda6 100644 --- a/source/glest_game/types/resource_type.cpp +++ b/source/glest_game/types/resource_type.cpp @@ -3,15 +3,15 @@ // // 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 +// 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 "resource_type.h" -#include "util.h" +#include "util.h" #include "element_type.h" #include "logger.h" #include "renderer.h" @@ -33,9 +33,12 @@ void ResourceType::load(const string &dir, Checksum* checksum){ string path, str; Renderer &renderer= Renderer::getInstance(); - try{ + try + { + recoup_cost = true; + name= lastDir(dir); - + Logger::getInstance().add("Resource type: "+ formatString(name), true); path= dir+"/"+name+".xml"; @@ -55,46 +58,64 @@ void ResourceType::load(const string &dir, Checksum* checksum){ const XmlNode *typeNode= resourceNode->getChild("type"); resourceClass= strToRc(typeNode->getAttribute("value")->getRestrictedValue()); - switch(resourceClass){ - case rcTech:{ - //model - const XmlNode *modelNode= typeNode->getChild("model"); - string path=dir+"/" + modelNode->getAttribute("path")->getRestrictedValue(); - - model= renderer.newModel(rsGame); - model->load(path); - - //default resources - const XmlNode *defaultAmountNode= typeNode->getChild("default-amount"); - defResPerPatch= defaultAmountNode->getAttribute("value")->getIntValue(); - - //resource number - const XmlNode *resourceNumberNode= typeNode->getChild("resource-number"); - resourceNumber= resourceNumberNode->getAttribute("value")->getIntValue(); - - } - break; + switch(resourceClass) + { + case rcTech: + { + //model + const XmlNode *modelNode= typeNode->getChild("model"); + string path=dir+"/" + modelNode->getAttribute("path")->getRestrictedValue(); - case rcTileset:{ - //resource number - const XmlNode *defaultAmountNode= typeNode->getChild("default-amount"); - defResPerPatch= defaultAmountNode->getAttribute("value")->getIntValue(); + model= renderer.newModel(rsGame); + model->load(path); - //resource number - const XmlNode *tilesetObjectNode= typeNode->getChild("tileset-object"); - tilesetObject= tilesetObjectNode->getAttribute("value")->getIntValue(); + //default resources + const XmlNode *defaultAmountNode= typeNode->getChild("default-amount"); + defResPerPatch= defaultAmountNode->getAttribute("value")->getIntValue(); + + //resource number + const XmlNode *resourceNumberNode= typeNode->getChild("resource-number"); + resourceNumber= resourceNumberNode->getAttribute("value")->getIntValue(); } break; - case rcConsumable:{ - //interval - const XmlNode *intervalNode= typeNode->getChild("interval"); - interval= intervalNode->getAttribute("value")->getIntValue(); + case rcTileset: + { + //resource number + const XmlNode *defaultAmountNode= typeNode->getChild("default-amount"); + defResPerPatch= defaultAmountNode->getAttribute("value")->getIntValue(); + + //resource number + const XmlNode *tilesetObjectNode= typeNode->getChild("tileset-object"); + tilesetObject= tilesetObjectNode->getAttribute("value")->getIntValue(); } break; + + case rcConsumable: + { + //interval + const XmlNode *intervalNode= typeNode->getChild("interval"); + interval= intervalNode->getAttribute("value")->getIntValue(); + } + break; + + case rcStatic: + { + //recoup_cost + if(typeNode->hasChild("recoup_cost") == true) + { + const XmlNode *recoup_costNode= typeNode->getChild("recoup_cost"); + if(recoup_costNode != NULL) + { + recoup_cost= recoup_costNode->getAttribute("value")->getBoolValue(); + } + } + } + break; + default: - break; + break; } } catch(const exception &e){ @@ -103,7 +124,7 @@ void ResourceType::load(const string &dir, Checksum* checksum){ } -// ==================== misc ==================== +// ==================== misc ==================== ResourceClass ResourceType::strToRc(const string &s){ if(s=="tech"){ diff --git a/source/glest_game/types/resource_type.h b/source/glest_game/types/resource_type.h index cfd484d50..9d97807e3 100644 --- a/source/glest_game/types/resource_type.h +++ b/source/glest_game/types/resource_type.h @@ -3,9 +3,9 @@ // // 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 +// 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 // ============================================================== @@ -22,7 +22,7 @@ using Shared::Graphics::Model; using Shared::Util::Checksum; enum ResourceClass{ - rcTech, + rcTech, rcTileset, rcStatic, rcConsumable @@ -41,6 +41,8 @@ private: int resourceNumber; //used only if class==rcTech, resource number in the map int interval; //used only if class==rcConsumable int defResPerPatch; //used only if class==rcTileset || class==rcTech + bool recoup_cost; + Model *model; public: @@ -53,6 +55,7 @@ public: int getInterval() const {return interval;} int getDefResPerPatch() const {return defResPerPatch;} const Model *getModel() const {return model;} + bool getRecoup_cost() const { return recoup_cost;} static ResourceClass strToRc(const string &s); }; diff --git a/source/glest_game/types/unit_type.h b/source/glest_game/types/unit_type.h index 316c7ebbd..1e079815c 100644 --- a/source/glest_game/types/unit_type.h +++ b/source/glest_game/types/unit_type.h @@ -3,9 +3,9 @@ // // 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 +// 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 // ============================================================== @@ -31,7 +31,7 @@ class FactionType; // =============================== -// class Level +// class Level // =============================== class Level{ @@ -47,7 +47,7 @@ public: }; // =============================== -// class UnitType +// class UnitType // /// A unit or building type // =============================== @@ -89,9 +89,9 @@ private: bool light; Vec3f lightColor; bool multiSelect; - int sight; + int sight; int size; //size in cells - int height; + int height; //cellmap bool *cellMap; @@ -131,10 +131,10 @@ public: bool getProperty(Property property) const {return properties[property];} int getArmor() const {return armor;} const ArmorType *getArmorType() const {return armorType;} - const SkillType *getSkillType(int i) const {return skillTypes[i];} + const SkillType *getSkillType(int i) const {return skillTypes[i];} const CommandType *getCommandType(int i) const {return commandTypes[i];} const Level *getLevel(int i) const {return &levels[i];} - int getSkillTypeCount() const {return skillTypes.size();} + int getSkillTypeCount() const {return skillTypes.size();} int getCommandTypeCount() const {return commandTypes.size();} int getLevelCount() const {return levels.size();} bool getLight() const {return light;} @@ -143,7 +143,7 @@ public: int getSight() const {return sight;} int getSize() const {return size;} int getHeight() const {return height;} - int getStoredResourceCount() const {return storedResources.size();} + int getStoredResourceCount() const {return storedResources.size();} const Resource *getStoredResource(int i) const {return &storedResources[i];} bool getCellMapCell(int x, int y) const {return cellMap[size*y+x];} bool getMeetingPoint() const {return meetingPoint;} @@ -166,7 +166,7 @@ public: int getTotalSight(const TotalUpgrade *totalUpgrade) const; //has - bool hasCommandType(const CommandType *commandType) const; + bool hasCommandType(const CommandType *commandType) const; bool hasCommandClass(CommandClass commandClass) const; bool hasSkillType(const SkillType *skillType) const; bool hasSkillClass(SkillClass skillClass) const; diff --git a/source/glest_game/world/unit_updater.cpp b/source/glest_game/world/unit_updater.cpp index c60235afa..da82bc814 100644 --- a/source/glest_game/world/unit_updater.cpp +++ b/source/glest_game/world/unit_updater.cpp @@ -1,7 +1,7 @@ // ============================================================== // This file is part of Glest (www.glest.org) // -// Copyright (C) 2001-2008 Marti�o Figueroa +// 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 diff --git a/source/glest_game/world/unit_updater.h b/source/glest_game/world/unit_updater.h index 56252df44..4b674ba17 100644 --- a/source/glest_game/world/unit_updater.h +++ b/source/glest_game/world/unit_updater.h @@ -1,7 +1,7 @@ // ============================================================== // This file is part of Glest (www.glest.org) // -// Copyright (C) 2001-2008 Marti�o Figueroa +// 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 diff --git a/source/shared_lib/include/platform/posix/socket.h b/source/shared_lib/include/platform/posix/socket.h index 9230cc669..9fbdecd00 100644 --- a/source/shared_lib/include/platform/posix/socket.h +++ b/source/shared_lib/include/platform/posix/socket.h @@ -3,9 +3,9 @@ // // Copyright (C) 2005 Matthias Braun // -// 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 +// 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 // ============================================================== @@ -22,6 +22,7 @@ #include #include #include +#include using std::string; @@ -51,20 +52,30 @@ public: class Socket { protected: int sock; - + public: Socket(int sock); Socket(); ~Socket(); + static bool enableDebugText; + + // Int lookup is socket fd while bool result is whether or not that socket was signalled for reading + static bool hasDataToRead(std::map &socketTriggeredList); + static bool hasDataToRead(int socket); + bool hasDataToRead(); + void disconnectSocket(); + + int getSocketId() const { return sock; } + int getDataToRead(); int send(const void *data, int dataSize); int receive(void *data, int dataSize); int peek(void *data, int dataSize); - + void setBlock(bool block); bool isReadable(); - bool isWritable(); + bool isWritable(bool waitOnDelayedResponse); bool isConnected(); string getHostName() const; diff --git a/source/shared_lib/include/platform/sdl/platform_util.h b/source/shared_lib/include/platform/sdl/platform_util.h index 5f10a57dd..197aba335 100644 --- a/source/shared_lib/include/platform/sdl/platform_util.h +++ b/source/shared_lib/include/platform/sdl/platform_util.h @@ -3,9 +3,9 @@ // // Copyright (C) 2005 Matthias Braun // -// 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 +// 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 // ============================================================== #ifndef _SHARED_PLATFORM_PLATFORMUTIL_H_ @@ -18,6 +18,8 @@ #include #include "types.h" +#include "checksum.h" +#include using std::string; using std::vector; @@ -25,6 +27,8 @@ using std::exception; using Shared::Platform::int64; +using Shared::Util::Checksum; + namespace Shared{ namespace Platform{ // ===================================================== @@ -41,7 +45,7 @@ private: public: void init(float fps, int maxTimes= -1); - + bool isTime(); void reset(); }; @@ -85,6 +89,10 @@ public: // ===================================================== void findAll(const string &path, vector &results, bool cutExtension=false); +int32 getFolderTreeContentsCheckSumRecursively(const string &path, const string &filterFileExt, Checksum *recursiveChecksum); +vector > getFolderTreeContentsCheckSumListRecursively(const string &path, const string &filterFileExt, vector > *recursiveMap); +void createDirectoryPaths(string Path); +string extractDirectoryPathFromFile(string filename); bool changeVideoMode(int resH, int resW, int colorBits, int refreshFrequency); void restoreVideoMode(); diff --git a/source/shared_lib/include/platform/win32/gl_wrap.h b/source/shared_lib/include/platform/win32/gl_wrap.h index 157f2dd2d..00eb974de 100644 --- a/source/shared_lib/include/platform/win32/gl_wrap.h +++ b/source/shared_lib/include/platform/win32/gl_wrap.h @@ -14,8 +14,8 @@ #include -#include -#include +#include +#include #include #include diff --git a/source/shared_lib/include/platform/win32/platform_util.h b/source/shared_lib/include/platform/win32/platform_util.h index 189ac10c6..cd8321835 100644 --- a/source/shared_lib/include/platform/win32/platform_util.h +++ b/source/shared_lib/include/platform/win32/platform_util.h @@ -19,12 +19,15 @@ #include #include "types.h" +#include "checksum.h" +#include using std::string; using std::vector; using std::exception; using Shared::Platform::int64; +using Shared::Util::Checksum; namespace Shared{ namespace Platform{ @@ -96,6 +99,10 @@ public: // ===================================================== void findAll(const string &path, vector &results, bool cutExtension=false); +int32 getFolderTreeContentsCheckSumRecursively(const string &path, const string &filterFileExt, Checksum *recursiveChecksum); +vector > getFolderTreeContentsCheckSumListRecursively(const string &path, const string &filterFileExt, vector > *recursiveMap); +void createDirectoryPaths(string Path); +string extractDirectoryPathFromFile(string filename); bool changeVideoMode(int resH, int resW, int colorBits, int refreshFrequency); void restoreVideoMode(); diff --git a/source/shared_lib/include/platform/win32/socket.h b/source/shared_lib/include/platform/win32/socket.h index adde4acbf..9fb7c3322 100644 --- a/source/shared_lib/include/platform/win32/socket.h +++ b/source/shared_lib/include/platform/win32/socket.h @@ -3,9 +3,9 @@ // // 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 +// 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 // ============================================================== @@ -14,6 +14,7 @@ #include #include +#include using std::string; @@ -51,20 +52,30 @@ private: protected: static SocketManager socketManager; SOCKET sock; - + public: Socket(SOCKET sock); Socket(); ~Socket(); + static bool enableDebugText; + + // Int lookup is socket fd while bool result is whether or not that socket was signalled for reading + static bool hasDataToRead(std::map &socketTriggeredList); + static bool hasDataToRead(int socket); + bool hasDataToRead(); + void disconnectSocket(); + + int getSocketId() const { return sock; } + int getDataToRead(); int send(const void *data, int dataSize); int receive(void *data, int dataSize); int peek(void *data, int dataSize); - + void setBlock(bool block); bool isReadable(); - bool isWritable(); + bool isWritable(bool waitOnDelayedResponse); bool isConnected(); string getHostName() const; diff --git a/source/shared_lib/include/util/checksum.h b/source/shared_lib/include/util/checksum.h index a29ce40ae..8caf4dcaa 100644 --- a/source/shared_lib/include/util/checksum.h +++ b/source/shared_lib/include/util/checksum.h @@ -3,9 +3,9 @@ // // 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 +// 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 // ============================================================== @@ -32,7 +32,7 @@ private: int32 r; int32 c1; int32 c2; - + public: Checksum(); diff --git a/source/shared_lib/include/xml/xml_parser.h b/source/shared_lib/include/xml/xml_parser.h index c070c7dbd..46d70f2f2 100644 --- a/source/shared_lib/include/xml/xml_parser.h +++ b/source/shared_lib/include/xml/xml_parser.h @@ -3,9 +3,9 @@ // // 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 +// 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 // ============================================================== @@ -35,11 +35,11 @@ class XmlIo; class XmlTree; class XmlNode; class XmlAttribute; - + // ===================================================== -// class XmlIo -// -/// Wrapper for Xerces C++ +// class XmlIo +// +/// Wrapper for Xerces C++ // ===================================================== class XmlIo{ @@ -72,11 +72,11 @@ private: public: XmlTree(); ~XmlTree(); - + void init(const string &name); void load(const string &path); void save(const string &path); - + XmlNode *getRootNode() const {return rootNode;} }; @@ -89,7 +89,7 @@ private: string name; string text; vector children; - vector attributes; + vector attributes; private: XmlNode(XmlNode&); @@ -109,6 +109,7 @@ public: XmlAttribute *getAttribute(const string &name) const; XmlNode *getChild(int i) const; XmlNode *getChild(const string &childName, int childIndex=0) const; + bool hasChild(const string &childName) const; XmlNode *getParent() const; @@ -143,9 +144,9 @@ public: const string &getValue() const {return value;} bool getBoolValue() const; - int getIntValue() const; + int getIntValue() const; int getIntValue(int min, int max) const; - float getFloatValue() const; + float getFloatValue() const; float getFloatValue(float min, float max) const; const string &getRestrictedValue() const; }; diff --git a/source/shared_lib/sources/platform/posix/socket.cpp b/source/shared_lib/sources/platform/posix/socket.cpp index 40a05b6df..284682423 100644 --- a/source/shared_lib/sources/platform/posix/socket.cpp +++ b/source/shared_lib/sources/platform/posix/socket.cpp @@ -1,9 +1,9 @@ //This file is part of Glest Shared Library (www.glest.org) //Copyright (C) 2005 Matthias Braun -//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 +//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 "socket.h" @@ -28,6 +28,8 @@ using namespace Shared::Util; namespace Shared{ namespace Platform{ +bool Socket::enableDebugText = true; + // ===================================================== // class Ip // ===================================================== @@ -48,7 +50,7 @@ Ip::Ip(unsigned char byte0, unsigned char byte1, unsigned char byte2, unsigned c Ip::Ip(const string& ipString){ - int offset= 0; + int offset= 0; int byteIndex= 0; for(byteIndex= 0; byteIndex<4; ++byteIndex){ @@ -71,51 +73,307 @@ Socket::Socket(int sock){ this->sock= sock; } -Socket::Socket(){ +Socket::Socket() +{ sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - if(sock<0) { + if(sock < 0) + { throwException("Error creating socket"); } } -Socket::~Socket() { - ::close(sock); +Socket::~Socket() +{ + if(Socket::enableDebugText) printf("In [%s::%s] START closing socket = %d...\n",__FILE__,__FUNCTION__,sock); + + disconnectSocket(); + + if(Socket::enableDebugText) printf("In [%s::%s] END closing socket = %d...\n",__FILE__,__FUNCTION__,sock); +} + +void Socket::disconnectSocket() +{ + if(Socket::enableDebugText) printf("In [%s::%s] START closing socket = %d...\n",__FILE__,__FUNCTION__,sock); + + if(sock > 0) + { + if(Socket::enableDebugText) printf("In [%s::%s] calling shutdown and close for socket = %d...\n",__FILE__,__FUNCTION__,sock); + ::shutdown(sock,2); + ::close(sock); + sock = -1; + } + + if(Socket::enableDebugText) printf("In [%s::%s] END closing socket = %d...\n",__FILE__,__FUNCTION__,sock); +} + +// Int lookup is socket fd while bool result is whether or not that socket was signalled for reading +bool Socket::hasDataToRead(std::map &socketTriggeredList) +{ + bool bResult = false; + + if(socketTriggeredList.size() > 0) + { + /* Watch stdin (fd 0) to see when it has input. */ + fd_set rfds; + FD_ZERO(&rfds); + + int imaxsocket = 0; + for(std::map::iterator itermap = socketTriggeredList.begin(); + itermap != socketTriggeredList.end(); itermap++) + { + int socket = itermap->first; + if(socket > 0) + { + FD_SET(socket, &rfds); + imaxsocket = max(socket,imaxsocket); + } + } + + if(imaxsocket > 0) + { + /* Wait up to 0 seconds. */ + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 0; + + int retval = select(imaxsocket + 1, &rfds, NULL, NULL, &tv); + if(retval < 0) + { + char szBuf[1024]=""; + sprintf(szBuf,"In [%s::%s] ERROR SELECTING SOCKET DATA retval = %d errno = %d [%s]",__FILE__,__FUNCTION__,retval,errno,strerror(errno)); + fprintf(stderr, "%s", szBuf); + + } + else if(retval) + { + bResult = true; + + if(Socket::enableDebugText) printf("In [%s::%s] select detected data imaxsocket = %d...\n",__FILE__,__FUNCTION__,imaxsocket); + + for(std::map::iterator itermap = socketTriggeredList.begin(); + itermap != socketTriggeredList.end(); itermap++) + { + int socket = itermap->first; + if (FD_ISSET(socket, &rfds)) + { + if(Socket::enableDebugText) printf("In [%s] FD_ISSET true for socket %d...\n",__FUNCTION__,socket); + + itermap->second = true; + } + else + { + itermap->second = false; + } + } + + if(Socket::enableDebugText) printf("In [%s::%s] socketTriggeredList->size() = %d\n",__FILE__,__FUNCTION__,socketTriggeredList.size()); + } + } + } + + return bResult; +} + +bool Socket::hasDataToRead() +{ + return Socket::hasDataToRead(sock) ; +} + +bool Socket::hasDataToRead(int socket) +{ + bool bResult = false; + + if(socket > 0) + { + fd_set rfds; + struct timeval tv; + + /* Watch stdin (fd 0) to see when it has input. */ + FD_ZERO(&rfds); + FD_SET(socket, &rfds); + + /* Wait up to 0 seconds. */ + tv.tv_sec = 0; + tv.tv_usec = 0; + + int retval = select(socket + 1, &rfds, NULL, NULL, &tv); + if(retval) + { + if (FD_ISSET(socket, &rfds)) + { + bResult = true; + } + } + } + + return bResult; } int Socket::getDataToRead(){ - unsigned long size; + unsigned long size = 0; - /* ioctl isn't posix, but the following seems to work on all modern - * unixes */ - int err= ioctl(sock, FIONREAD, &size); + //fd_set rfds; + //struct timeval tv; + //int retval; - if(err < 0 && errno != EAGAIN){ - throwException("Can not get data to read"); - } + /* Watch stdin (fd 0) to see when it has input. */ + //FD_ZERO(&rfds); + //FD_SET(sock, &rfds); + + /* Wait up to 0 seconds. */ + //tv.tv_sec = 0; + //tv.tv_usec = 0; + + //retval = select(sock + 1, &rfds, NULL, NULL, &tv); + //if(retval) + if(sock > 0) + { + /* ioctl isn't posix, but the following seems to work on all modern + * unixes */ + int err= ioctl(sock, FIONREAD, &size); + + if(err < 0 && errno != EAGAIN) + { + char szBuf[1024]=""; + sprintf(szBuf,"In [%s::%s] ERROR PEEKING SOCKET DATA, err = %d errno = %d [%s]",__FILE__,__FUNCTION__,err,errno,strerror(errno)); + + throwException(szBuf); + } + else if(err == 0) + { + //if(Socket::enableDebugText) printf("In [%s] ioctl returned = %d, size = %ld\n",__FUNCTION__,err,size); + } + } return static_cast(size); } int Socket::send(const void *data, int dataSize) { - ssize_t bytesSent= ::send(sock, reinterpret_cast(data), dataSize, 0); - if(bytesSent<0 && errno != EAGAIN) { - throwException("error while receiving socket data"); + ssize_t bytesSent= 0; + if(sock > 0) + { + bytesSent = ::send(sock, reinterpret_cast(data), dataSize, 0); } + if(bytesSent < 0 && errno != EAGAIN) + { + char szBuf[1024]=""; + sprintf(szBuf,"In [%s::%s] ERROR WRITING SOCKET DATA, err = %d errno = %d [%s]",__FILE__,__FUNCTION__,bytesSent,errno,strerror(errno)); + + throwException(szBuf); + } + else if(bytesSent < 0 && errno == EAGAIN) + { + printf("In [%s::%s] #1 EAGAIN during send, trying again...\n",__FILE__,__FUNCTION__); + + time_t tStartTimer = time(NULL); + while((bytesSent < 0 && errno == EAGAIN) && (difftime(time(NULL),tStartTimer) <= 5)) + { + if(Socket::isWritable(true) == true) + { + bytesSent = ::send(sock, reinterpret_cast(data), dataSize, 0); + + printf("In [%s::%s] #2 EAGAIN during send, trying again returned: %d\n",__FILE__,__FUNCTION__,bytesSent); + } + } + } + if(bytesSent <= 0) + { + int iErr = errno; + disconnectSocket(); + + char szBuf[1024]=""; + sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while sending socket data, bytesSent = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,bytesSent,iErr,strerror(iErr)); + printf("%s",szBuf); + //throwException(szBuf); + } + + if(Socket::enableDebugText) printf("In [%s::%s] sock = %d, bytesSent = %d\n",__FILE__,__FUNCTION__,sock,bytesSent); + return static_cast(bytesSent); } -int Socket::receive(void *data, int dataSize) { - ssize_t bytesReceived= recv(sock, reinterpret_cast(data), dataSize, 0); - if(bytesReceived<0 && errno != EAGAIN) { - throwException("error while receiving socket data"); +int Socket::receive(void *data, int dataSize) +{ + ssize_t bytesReceived = 0; + + if(sock > 0) + { + bytesReceived = recv(sock, reinterpret_cast(data), dataSize, 0); + } + if(bytesReceived < 0 && errno != EAGAIN) + { + char szBuf[1024]=""; + sprintf(szBuf,"[%s::%s] ERROR READING SOCKET DATA error while sending socket data, bytesSent = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,bytesReceived,errno,strerror(errno)); + + throwException(szBuf); + } + else if(bytesReceived < 0 && errno == EAGAIN) + { + printf("In [%s::%s] #1 EAGAIN during receive, trying again...\n",__FILE__,__FUNCTION__); + + time_t tStartTimer = time(NULL); + while((bytesReceived < 0 && errno == EAGAIN) && (difftime(time(NULL),tStartTimer) <= 5)) + { + if(Socket::isReadable() == true) + { + bytesReceived = recv(sock, reinterpret_cast(data), dataSize, 0); + + printf("In [%s::%s] #2 EAGAIN during receive, trying again returned: %d\n",__FILE__,__FUNCTION__,bytesReceived); + } + } + } + + if(bytesReceived <= 0) + { + int iErr = errno; + disconnectSocket(); + + char szBuf[1024]=""; + sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while receiving socket data, bytesReceived = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,bytesReceived,iErr,strerror(iErr)); + printf("%s",szBuf); + //throwException(szBuf); } return static_cast(bytesReceived); } int Socket::peek(void *data, int dataSize){ - ssize_t err= recv(sock, reinterpret_cast(data), dataSize, MSG_PEEK); - if(err<0 && errno != EAGAIN){ - throwException("Can not receive data"); + ssize_t err = 0; + if(sock > 0) + { + err = recv(sock, reinterpret_cast(data), dataSize, MSG_PEEK); + } + if(err < 0 && errno != EAGAIN) + { + char szBuf[1024]=""; + sprintf(szBuf,"[%s::%s] ERROR PEEKING SOCKET DATA error while sending socket data, bytesSent = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,err,errno,strerror(errno)); + + throwException(szBuf); + } + else if(err < 0 && errno == EAGAIN) + { + printf("In [%s::%s] #1 EAGAIN during peek, trying again...\n",__FILE__,__FUNCTION__); + + time_t tStartTimer = time(NULL); + while((err < 0 && errno == EAGAIN) && (difftime(time(NULL),tStartTimer) <= 5)) + { + if(Socket::isReadable() == true) + { + err = recv(sock, reinterpret_cast(data), dataSize, MSG_PEEK); + + printf("In [%s::%s] #2 EAGAIN during peek, trying again returned: %d\n",__FILE__,__FUNCTION__,err); + } + } + } + + if(err <= 0) + { + int iErr = errno; + disconnectSocket(); + + char szBuf[1024]=""; + sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while peeking socket data, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,err,iErr,strerror(iErr)); + printf("%s",szBuf); + //throwException(szBuf); } return static_cast(err); @@ -128,49 +386,114 @@ void Socket::setBlock(bool block){ } } -bool Socket::isReadable(){ +bool Socket::isReadable() +{ + if(sock <= 0) return false; + struct timeval tv; tv.tv_sec= 0; - tv.tv_usec= 10; + tv.tv_usec= 1; fd_set set; FD_ZERO(&set); FD_SET(sock, &set); int i= select(sock+1, &set, NULL, NULL, &tv); - if(i<0){ - throwException("Error selecting socket"); + if(i < 0) + { + //throwException("Error selecting socket"); + char szBuf[1024]=""; + sprintf(szBuf,"[%s::%s] error while selecting socket data, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,i,errno,strerror(errno)); + printf("%s",szBuf); } - return i==1; + //return (i == 1 && FD_ISSET(sock, &set)); + return (i == 1); } -bool Socket::isWritable(){ +bool Socket::isWritable(bool waitOnDelayedResponse) +{ + if(sock <= 0) return false; + struct timeval tv; tv.tv_sec= 0; - tv.tv_usec= 10; + tv.tv_usec= 1; fd_set set; FD_ZERO(&set); FD_SET(sock, &set); - int i= select(sock+1, NULL, &set, NULL, &tv); - if(i<0){ - throwException("Error selecting socket"); - } - return i==1; + bool result = false; + do + { + int i = select(sock+1, NULL, &set, NULL, &tv); + if(i < 0 ) + { + char szBuf[1024]=""; + sprintf(szBuf,"[%s::%s] error while selecting socket data, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,i,errno,strerror(errno)); + printf("%s",szBuf); + waitOnDelayedResponse = false; + + //throwException("Error selecting socket"); + } + else if(i == 0) + { + char szBuf[1024]=""; + sprintf(szBuf,"[%s::%s] TIMEOUT while selecting socket data, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,i,errno,strerror(errno)); + printf("%s",szBuf); + + if(waitOnDelayedResponse == false) + { + result = true; + } + } + else + { + result = true; + } + } while(waitOnDelayedResponse == true && result == false); + + //return (i == 1 && FD_ISSET(sock, &set)); + return result; } -bool Socket::isConnected(){ - +bool Socket::isConnected() +{ //if the socket is not writable then it is not conencted - if(!isWritable()){ + if(isWritable(false) == false) + { return false; } //if the socket is readable it is connected if we can read a byte from it - if(isReadable()){ + if(isReadable()) + { char tmp; - return recv(sock, &tmp, sizeof(tmp), MSG_PEEK) > 0; + int err = peek(&tmp, sizeof(tmp)); + return (err > 0); + /* + int err = recv(sock, &tmp, sizeof(tmp), MSG_PEEK); + + if(err <= 0 && errno != EAGAIN) + { + int iErr = errno; + disconnectSocket(); + + char szBuf[1024]=""; + sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while peeking isconnected socket data, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,err,iErr,strerror(iErr)); + printf("%s",szBuf); + + return false; + } + else if(err <= 0) + { + int iErr = errno; + //disconnectSocket(); + + char szBuf[1024]=""; + sprintf(szBuf,"[%s::%s] #2 DISCONNECTED SOCKET error while peeking isconnected socket data, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,err,iErr,strerror(iErr)); + printf("%s",szBuf); + } + */ } //otherwise the socket is connected @@ -198,9 +521,9 @@ string Socket::getIp() const{ throw runtime_error("Error getting host ip"); } - return - intToStr(address[0]) + "." + - intToStr(address[1]) + "." + + return + intToStr(address[0]) + "." + + intToStr(address[1]) + "." + intToStr(address[2]) + "." + intToStr(address[3]); } @@ -215,7 +538,8 @@ void Socket::throwException(const string &str){ // class ClientSocket // =============================================== -void ClientSocket::connect(const Ip &ip, int port){ +void ClientSocket::connect(const Ip &ip, int port) +{ sockaddr_in addr; memset(&addr, 0, sizeof(addr)); @@ -224,20 +548,23 @@ void ClientSocket::connect(const Ip &ip, int port){ addr.sin_port= htons(port); int err= ::connect(sock, reinterpret_cast(&addr), sizeof(addr)); - if(err < 0) { + if(err < 0) + { char szBuf[1024]=""; - sprintf(szBuf,"#2 Error connecting socket for IP: %s for Port: %d err = %d errno = %d [%s]",ip.getString().c_str(),port,err,errno,strerror(errno)); + sprintf(szBuf,"In [%s::%s] #2 Error connecting socket for IP: %s for Port: %d err = %d errno = %d [%s]\n",__FILE__,__FUNCTION__,ip.getString().c_str(),port,err,errno,strerror(errno)); fprintf(stderr, "%s", szBuf); - if (errno == EINPROGRESS) { - + if (errno == EINPROGRESS) + { fd_set myset; struct timeval tv; int valopt; socklen_t lon; - fprintf(stderr, "EINPROGRESS in connect() - selecting\n"); - do { + fprintf(stderr, "In [%s::%s] EINPROGRESS in connect() - selecting\n",__FILE__,__FUNCTION__); + + do + { tv.tv_sec = 10; tv.tv_usec = 0; @@ -246,41 +573,57 @@ void ClientSocket::connect(const Ip &ip, int port){ err = select(sock+1, NULL, &myset, NULL, &tv); - if (err < 0 && errno != EINTR) { - sprintf(szBuf, "Error connecting %d - %s\n", errno, strerror(errno)); - throwException(szBuf); + if (err < 0 && errno != EINTR) + { + sprintf(szBuf, "In [%s::%s] Error connecting %d - [%s]\n",__FILE__,__FUNCTION__,errno, strerror(errno)); + //throwException(szBuf); + fprintf(stderr, "%s", szBuf); + break; } - else if (err > 0) { + else if (err > 0) + { // Socket selected for write lon = sizeof(int); - if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon) < 0) { - sprintf(szBuf, "Error in getsockopt() %d - %s\n", errno, strerror(errno)); - throwException(szBuf); + if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon) < 0) + { + sprintf(szBuf, "In [%s::%s] Error in getsockopt() %d - [%s]\n",__FILE__,__FUNCTION__,errno, strerror(errno)); + //throwException(szBuf); + fprintf(stderr, "%s", szBuf); + break; } // Check the value returned... - if (valopt) { - sprintf(szBuf, "Error in delayed connection() %d - %s\n", valopt, strerror(valopt)); - throwException(szBuf); + if (valopt) + { + sprintf(szBuf, "In [%s::%s] Error in delayed connection() %d - [%s]\n",__FILE__,__FUNCTION__,valopt, strerror(valopt)); + //throwException(szBuf); + fprintf(stderr, "%s", szBuf); + break; } errno = 0; - fprintf(stderr, "Apparent recovery for connection sock = %d, err = %d, errno = %d\n",sock,err,errno); + fprintf(stderr, "In [%s::%s] Apparent recovery for connection sock = %d, err = %d, errno = %d\n",__FILE__,__FUNCTION__,sock,err,errno); break; } - else { - sprintf(szBuf, "Timeout in select() - Cancelling!\n"); - throwException(szBuf); + else + { + sprintf(szBuf, "In [%s::%s] Timeout in select() - Cancelling!\n",__FILE__,__FUNCTION__); + //throwException(szBuf); + fprintf(stderr, "%s", szBuf); + break; } } while (1); } if(err < 0) { - throwException(szBuf); + fprintf(stderr, "In [%s::%s] Before END sock = %d, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,sock,err,errno,strerror(errno)); + //throwException(szBuf); + } + else + { + fprintf(stderr, "In [%s::%s] Valid recovery for connection sock = %d, err = %d, errno = %d\n",__FILE__,__FUNCTION__,sock,err,errno); } - - fprintf(stderr, "Valid recovery for connection sock = %d, err = %d, errno = %d\n",sock,err,errno); } } @@ -288,7 +631,8 @@ void ClientSocket::connect(const Ip &ip, int port){ // class ServerSocket // =============================================== -void ServerSocket::bind(int port){ +void ServerSocket::bind(int port) +{ //sockaddr structure sockaddr_in addr; addr.sin_family= AF_INET; @@ -297,30 +641,45 @@ void ServerSocket::bind(int port){ int val = 1; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); - + int err= ::bind(sock, reinterpret_cast(&addr), sizeof(addr)); - if(err < 0) { - throwException("Error binding socket"); + if(err < 0) + { + char szBuf[1024]=""; + sprintf(szBuf, "In [%s::%s] Error binding socket sock = %d, err = %d, errno = %d\n",__FILE__,__FUNCTION__,sock,err,errno); + throwException(szBuf); } } -void ServerSocket::listen(int connectionQueueSize){ +void ServerSocket::listen(int connectionQueueSize) +{ int err= ::listen(sock, connectionQueueSize); - if(err < 0) { - throwException("Error listening socket"); + if(err < 0) + { + char szBuf[1024]=""; + sprintf(szBuf, "In [%s::%s] Error listening socket sock = %d, err = %d, errno = %d\n",__FILE__,__FUNCTION__,sock,err,errno); + throwException(szBuf); } } -Socket *ServerSocket::accept(){ +Socket *ServerSocket::accept() +{ int newSock= ::accept(sock, NULL, NULL); - if(newSock < 0) { - if(errno == EAGAIN) - return NULL; + if(newSock < 0) + { + char szBuf[1024]=""; + if(Socket::enableDebugText) printf(szBuf, "In [%s::%s] Error accepting socket connection sock = %d, err = %d, errno = %d\n",__FILE__,__FUNCTION__,sock,newSock,errno); + + if(errno == EAGAIN) + { + return NULL; + } + throwException(szBuf); - throwException("Error accepting socket connection"); } return new Socket(newSock); } + }}//end namespace diff --git a/source/shared_lib/sources/platform/sdl/platform_util.cpp b/source/shared_lib/sources/platform/sdl/platform_util.cpp index 0ce00fc6b..b860bd6f0 100644 --- a/source/shared_lib/sources/platform/sdl/platform_util.cpp +++ b/source/shared_lib/sources/platform/sdl/platform_util.cpp @@ -1,9 +1,9 @@ //This file is part of Glest Shared Library (www.glest.org) //Copyright (C) 2005 Matthias Braun -//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 +//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 "platform_util.h" @@ -24,6 +24,10 @@ #include "window.h" #include "noimpl.h" +#include "checksum.h" +#include "socket.h" +#include + using namespace Shared::Util; using namespace std; @@ -38,7 +42,7 @@ int ScreenHeight; } // ===================================== -// PerformanceTimer +// PerformanceTimer // ===================================== void PerformanceTimer::init(float fps, int maxTimes){ @@ -67,7 +71,7 @@ void PerformanceTimer::reset(){ } // ===================================== -// Chrono +// Chrono // ===================================== Chrono::Chrono() { @@ -111,7 +115,7 @@ int64 Chrono::queryCounter(int multiplier) const { } // ===================================== -// Misc +// Misc // ===================================== //finds all filenames like path and stores them in resultys @@ -128,7 +132,7 @@ void findAll(const string &path, vector &results, bool cutExtension) { } glob_t globbuf; - + int res = glob(mypath.c_str(), 0, 0, &globbuf); if(res < 0) { std::stringstream msg; @@ -160,6 +164,217 @@ void findAll(const string &path, vector &results, bool cutExtension) { } } +int isdir(const char *path) +{ + struct stat stats; + + return stat (path, &stats) == 0 && S_ISDIR (stats.st_mode); +} + +bool EndsWith(const string &str, const string& key) +{ + size_t keylen = key.length(); + size_t strlen = str.length(); + + if(keylen <= strlen) + return string::npos != str.rfind(key.c_str(),strlen - keylen, keylen); + else + return false; +} + +//finds all filenames like path and gets their checksum of all files combined +int32 getFolderTreeContentsCheckSumRecursively(const string &path, const string &filterFileExt, Checksum *recursiveChecksum) { + + Checksum checksum = (recursiveChecksum == NULL ? Checksum() : *recursiveChecksum); + + //if(Socket::enableDebugText) printf("In [%s::%s] scanning [%s]\n",__FILE__,__FUNCTION__,path.c_str()); + + std::string mypath = path; + /** Stupid win32 is searching for all files without extension when *. is + * specified as wildcard + */ + if(mypath.compare(mypath.size() - 2, 2, "*.") == 0) { + mypath = mypath.substr(0, mypath.size() - 2); + mypath += "*"; + } + + glob_t globbuf; + + int res = glob(mypath.c_str(), 0, 0, &globbuf); + if(res < 0) { + std::stringstream msg; + msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno); + throw runtime_error(msg.str()); + } + + for(size_t i = 0; i < globbuf.gl_pathc; ++i) { + const char* p = globbuf.gl_pathv[i]; + /* + const char* begin = p; + for( ; *p != 0; ++p) { + // strip the path component + if(*p == '/') + begin = p+1; + } + */ + + if(isdir(p) == 0) + { + bool addFile = true; + if(filterFileExt != "") + { + addFile = EndsWith(p, filterFileExt); + } + + if(addFile) + { + //if(Socket::enableDebugText) printf("In [%s::%s] adding file [%s]\n",__FILE__,__FUNCTION__,p); + + checksum.addFile(p); + } + } + } + + globfree(&globbuf); + + // Look recursively for sub-folders + res = glob(mypath.c_str(), GLOB_ONLYDIR, 0, &globbuf); + if(res < 0) { + std::stringstream msg; + msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno); + throw runtime_error(msg.str()); + } + + for(size_t i = 0; i < globbuf.gl_pathc; ++i) { + const char* p = globbuf.gl_pathv[i]; + /* + const char* begin = p; + for( ; *p != 0; ++p) { + // strip the path component + if(*p == '/') + begin = p+1; + } + */ + + getFolderTreeContentsCheckSumRecursively(string(p) + "/*", filterFileExt, &checksum); + } + + globfree(&globbuf); + + return checksum.getSum(); +} + +//finds all filenames like path and gets the checksum of each file +vector > getFolderTreeContentsCheckSumListRecursively(const string &path, const string &filterFileExt, vector > *recursiveMap) { + + vector > checksumFiles = (recursiveMap == NULL ? vector >() : *recursiveMap); + + //if(Socket::enableDebugText) printf("In [%s::%s] scanning [%s]\n",__FILE__,__FUNCTION__,path.c_str()); + + std::string mypath = path; + /** Stupid win32 is searching for all files without extension when *. is + * specified as wildcard + */ + if(mypath.compare(mypath.size() - 2, 2, "*.") == 0) { + mypath = mypath.substr(0, mypath.size() - 2); + mypath += "*"; + } + + glob_t globbuf; + + int res = glob(mypath.c_str(), 0, 0, &globbuf); + if(res < 0) { + std::stringstream msg; + msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno); + throw runtime_error(msg.str()); + } + + for(size_t i = 0; i < globbuf.gl_pathc; ++i) { + const char* p = globbuf.gl_pathv[i]; + /* + const char* begin = p; + for( ; *p != 0; ++p) { + // strip the path component + if(*p == '/') + begin = p+1; + } + */ + + if(isdir(p) == 0) + { + bool addFile = true; + if(filterFileExt != "") + { + addFile = EndsWith(p, filterFileExt); + } + + if(addFile) + { + //if(Socket::enableDebugText) printf("In [%s::%s] adding file [%s]\n",__FILE__,__FUNCTION__,p); + + Checksum checksum; + checksum.addFile(p); + + checksumFiles.push_back(std::pair(p,checksum.getSum())); + } + } + } + + globfree(&globbuf); + + // Look recursively for sub-folders + res = glob(mypath.c_str(), GLOB_ONLYDIR, 0, &globbuf); + if(res < 0) { + std::stringstream msg; + msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno); + throw runtime_error(msg.str()); + } + + for(size_t i = 0; i < globbuf.gl_pathc; ++i) { + const char* p = globbuf.gl_pathv[i]; + /* + const char* begin = p; + for( ; *p != 0; ++p) { + // strip the path component + if(*p == '/') + begin = p+1; + } + */ + + checksumFiles = getFolderTreeContentsCheckSumListRecursively(string(p) + "/*", filterFileExt, &checksumFiles); + } + + globfree(&globbuf); + + return checksumFiles; +} + +string extractDirectoryPathFromFile(string filename) +{ + return filename.substr( 0, filename.rfind("/")+1 ); +} + +void createDirectoryPaths(string Path) +{ + char DirName[256]=""; + const char *path = Path.c_str(); + char *dirName = DirName; + while(*path) + { + //if (('\\' == *path) || ('/' == *path)) + if ('/' == *path) + { + //if (':' != *(path-1)) + { + mkdir(DirName, S_IRWXO); + } + } + *dirName++ = *path++; + *dirName = '\0'; + } + mkdir(DirName, S_IRWXO); +} + bool changeVideoMode(int resW, int resH, int colorBits, int ) { Private::shouldBeFullscreen = true; return true; diff --git a/source/shared_lib/sources/platform/win32/platform_util.cpp b/source/shared_lib/sources/platform/win32/platform_util.cpp index 4c6ac7784..b59a8a8b1 100644 --- a/source/shared_lib/sources/platform/win32/platform_util.cpp +++ b/source/shared_lib/sources/platform/win32/platform_util.cpp @@ -1,265 +1,480 @@ -// ============================================================== -// This file is part of Glest Shared Library (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 "platform_util.h" - -#include -#include - -#include - -#include "util.h" -#include "conversion.h" - -#include "leak_dumper.h" - -using namespace Shared::Util; -using namespace std; - -namespace Shared{ namespace Platform{ - -// ===================================================== -// class PerformanceTimer -// ===================================================== - -void PerformanceTimer::init(int fps, int maxTimes){ - int64 freq; - - if(QueryPerformanceFrequency((LARGE_INTEGER*) &freq)==0){ - throw runtime_error("Performance counters not supported"); - } - - times= 0; - this->maxTimes= maxTimes; - - QueryPerformanceCounter((LARGE_INTEGER*) &lastTicks); - - updateTicks= freq/fps; -} - -bool PerformanceTimer::isTime(){ - QueryPerformanceCounter((LARGE_INTEGER*) &thisTicks); - - if((thisTicks-lastTicks)>=updateTicks && timesdumpFileName.c_str(), - GENERIC_WRITE, - FILE_SHARE_WRITE, - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - 0); - - MINIDUMP_EXCEPTION_INFORMATION lExceptionInformation; - - lExceptionInformation.ThreadId= GetCurrentThreadId(); - lExceptionInformation.ExceptionPointers= pointers; - lExceptionInformation.ClientPointers= false; - - MiniDumpWriteDump( - GetCurrentProcess(), - GetCurrentProcessId(), - hFile, - MiniDumpNormal, - &lExceptionInformation, - NULL, - NULL ); - - thisPointer->handle(); - - return EXCEPTION_EXECUTE_HANDLER; -} - -void PlatformExceptionHandler::install(string dumpFileName){ - thisPointer= this; - this->dumpFileName= dumpFileName; - SetUnhandledExceptionFilter(handler); -} - -// ===================================================== -// class Misc -// ===================================================== - -//finds all filenames like path and stores them in resultys -void findAll(const string &path, vector &results, bool cutExtension){ - - int i= 0; - struct _finddata_t fi; - intptr_t handle; - char *cstr; - - results.clear(); - - cstr= new char[path.length()+1]; - strcpy(cstr, path.c_str()); - - if((handle=_findfirst(cstr,&fi))!=-1){ - do{ - if(!(strcmp(".", fi.name)==0 || strcmp("..", fi.name)==0)){ - i++; - results.push_back(fi.name); - } - } - while(_findnext(handle, &fi)==0); - } - else{ - throw runtime_error("Error opening files: "+ path); - } - - if(i==0){ - throw runtime_error("No files found: "+ path); - } - - if(cutExtension){ - for (int i=0; i +#include + +#include + +#include "util.h" +#include "conversion.h" + +#include "leak_dumper.h" +#include +#include +#include + +#define S_ISDIR(mode) ((mode) & _S_IFDIR) + + +using namespace Shared::Util; +using namespace std; + +namespace Shared{ namespace Platform{ + +// ===================================================== +// class PerformanceTimer +// ===================================================== + +void PerformanceTimer::init(int fps, int maxTimes){ + int64 freq; + + if(QueryPerformanceFrequency((LARGE_INTEGER*) &freq)==0){ + throw runtime_error("Performance counters not supported"); + } + + times= 0; + this->maxTimes= maxTimes; + + QueryPerformanceCounter((LARGE_INTEGER*) &lastTicks); + + updateTicks= freq/fps; +} + +bool PerformanceTimer::isTime(){ + QueryPerformanceCounter((LARGE_INTEGER*) &thisTicks); + + if((thisTicks-lastTicks)>=updateTicks && timesdumpFileName.c_str(), + GENERIC_WRITE, + FILE_SHARE_WRITE, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + 0); + + MINIDUMP_EXCEPTION_INFORMATION lExceptionInformation; + + lExceptionInformation.ThreadId= GetCurrentThreadId(); + lExceptionInformation.ExceptionPointers= pointers; + lExceptionInformation.ClientPointers= false; + + MiniDumpWriteDump( + GetCurrentProcess(), + GetCurrentProcessId(), + hFile, + MiniDumpNormal, + &lExceptionInformation, + NULL, + NULL ); + + thisPointer->handle(); + + return EXCEPTION_EXECUTE_HANDLER; +} + +void PlatformExceptionHandler::install(string dumpFileName){ + thisPointer= this; + this->dumpFileName= dumpFileName; + SetUnhandledExceptionFilter(handler); +} + +// ===================================================== +// class Misc +// ===================================================== + +//finds all filenames like path and stores them in resultys +void findAll(const string &path, vector &results, bool cutExtension){ + + int i= 0; + struct _finddata_t fi; + intptr_t handle; + char *cstr; + + results.clear(); + + cstr= new char[path.length()+1]; + strcpy(cstr, path.c_str()); + + if((handle=_findfirst(cstr,&fi))!=-1){ + do{ + if(!(strcmp(".", fi.name)==0 || strcmp("..", fi.name)==0)){ + i++; + results.push_back(fi.name); + } + } + while(_findnext(handle, &fi)==0); + } + else{ + throw runtime_error("Error opening files: "+ path); + } + + if(i==0){ + throw runtime_error("No files found: "+ path); + } + + if(cutExtension){ + for (int i=0; i > getFolderTreeContentsCheckSumListRecursively(const string &path, const string &filterFileExt, vector > *recursiveMap) { + + vector > checksumFiles = (recursiveMap == NULL ? vector >() : *recursiveMap); + +/* MV - PORT THIS to win32 + + //if(Socket::enableDebugText) printf("In [%s::%s] scanning [%s]\n",__FILE__,__FUNCTION__,path.c_str()); + + std::string mypath = path; + // Stupid win32 is searching for all files without extension when *. is specified as wildcard + if(mypath.compare(mypath.size() - 2, 2, "*.") == 0) { + mypath = mypath.substr(0, mypath.size() - 2); + mypath += "*"; + } + + glob_t globbuf; + + int res = glob(mypath.c_str(), 0, 0, &globbuf); + if(res < 0) { + std::stringstream msg; + msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno); + throw runtime_error(msg.str()); + } + + for(size_t i = 0; i < globbuf.gl_pathc; ++i) { + const char* p = globbuf.gl_pathv[i]; + // + //const char* begin = p; + //for( ; *p != 0; ++p) { + // strip the path component + // if(*p == '/') + // begin = p+1; + //} + + + if(isdir(p) == 0) + { + bool addFile = true; + if(filterFileExt != "") + { + addFile = EndsWith(p, filterFileExt); + } + + if(addFile) + { + //if(Socket::enableDebugText) printf("In [%s::%s] adding file [%s]\n",__FILE__,__FUNCTION__,p); + + Checksum checksum; + checksum.addFile(p); + + checksumFiles.push_back(std::pair(p,checksum.getSum())); + } + } + } + + globfree(&globbuf); + + // Look recursively for sub-folders + res = glob(mypath.c_str(), GLOB_ONLYDIR, 0, &globbuf); + if(res < 0) { + std::stringstream msg; + msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno); + throw runtime_error(msg.str()); + } + + for(size_t i = 0; i < globbuf.gl_pathc; ++i) { + const char* p = globbuf.gl_pathv[i]; + // + //const char* begin = p; + //for( ; *p != 0; ++p) { + // strip the path component + // if(*p == '/') + // begin = p+1; + //} + + checksumFiles = getFolderTreeContentsCheckSumListRecursively(string(p) + "/*", filterFileExt, &checksumFiles); + } + + globfree(&globbuf); +*/ + return checksumFiles; +} + +string extractDirectoryPathFromFile(string filename) +{ + return filename.substr( 0, filename.rfind("/")+1 ); +} + +void createDirectoryPaths(string Path) +{ + char DirName[256]=""; + const char *path = Path.c_str(); + char *dirName = DirName; + while(*path) + { + //if (('\\' == *path) || ('/' == *path)) + if ('/' == *path) + { + //if (':' != *(path-1)) + { + _mkdir(DirName); + } + } + *dirName++ = *path++; + *dirName = '\0'; + } + _mkdir(DirName); +} + +bool changeVideoMode(int resW, int resH, int colorBits, int refreshFrequency){ + DEVMODE devMode; + + for (int i=0; EnumDisplaySettings(NULL, i, &devMode) ;i++){ + if (devMode.dmPelsWidth== resW && + devMode.dmPelsHeight== resH && + devMode.dmBitsPerPel== colorBits){ + + devMode.dmDisplayFrequency=refreshFrequency; + + LONG result= ChangeDisplaySettings(&devMode, 0); + if(result == DISP_CHANGE_SUCCESSFUL){ + return true; + } + else{ + return false; + } + } + } + + return false; +} + +void restoreVideoMode(){ + int dispChangeErr= ChangeDisplaySettings(NULL, 0); + assert(dispChangeErr==DISP_CHANGE_SUCCESSFUL); +} + +void message(string message){ + MessageBox(NULL, message.c_str(), "Message", MB_OK); +} + +bool ask(string message){ + return MessageBox(NULL, message.c_str(), "Confirmation", MB_YESNO)==IDYES; +} + +void exceptionMessage(const exception &excp){ + string message, title; + showCursor(true); + + message+= "ERROR(S):\n\n"; + message+= excp.what(); + + title= "Error: Unhandled Exception"; + MessageBox(NULL, message.c_str(), title.c_str(), MB_ICONSTOP | MB_OK | MB_TASKMODAL); +} + +int getScreenW(){ + return GetSystemMetrics(SM_CXSCREEN); +} + +int getScreenH(){ + return GetSystemMetrics(SM_CYSCREEN); +} + +void sleep(int millis){ + Sleep(millis); +} + +void showCursor(bool b){ + ShowCursor(b); +} + +bool isKeyDown(int virtualKey){ + return (GetKeyState(virtualKey) & 0x8000) != 0; +} + +}}//end namespace diff --git a/source/shared_lib/sources/platform/win32/socket.cpp b/source/shared_lib/sources/platform/win32/socket.cpp index a1e255a29..691951d73 100644 --- a/source/shared_lib/sources/platform/win32/socket.cpp +++ b/source/shared_lib/sources/platform/win32/socket.cpp @@ -3,9 +3,9 @@ // // Copyright (C) 2001-2007 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 +// 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 // ============================================================== @@ -16,12 +16,17 @@ #include "conversion.h" #include "leak_dumper.h" +#include + +#define socklen_t int using namespace std; using namespace Shared::Util; namespace Shared{ namespace Platform{ +bool Socket::enableDebugText = false; + // ===================================================== // class Ip // ===================================================== @@ -42,7 +47,7 @@ Ip::Ip(unsigned char byte0, unsigned char byte1, unsigned char byte2, unsigned c Ip::Ip(const string& ipString){ - int offset= 0; + int offset= 0; int byteIndex= 0; for(byteIndex= 0; byteIndex<4; ++byteIndex){ @@ -64,7 +69,7 @@ string Ip::getString() const{ Socket::SocketManager Socket::socketManager; Socket::SocketManager::SocketManager(){ - WSADATA wsaData; + WSADATA wsaData; WORD wVersionRequested = MAKEWORD(2, 0); WSAStartup(wVersionRequested, &wsaData); //dont throw exceptions here, this is a static initializacion @@ -85,59 +90,300 @@ Socket::Socket(){ } } -Socket::~Socket(){ - int err= closesocket(sock); - if(err==INVALID_SOCKET){ - throwException("Error closing socket"); - } +Socket::~Socket() +{ + if(Socket::enableDebugText) printf("In [%s::%s] START closing socket = %d...\n",__FILE__,__FUNCTION__,sock); + + disconnectSocket(); + + if(Socket::enableDebugText) printf("In [%s::%s] END closing socket = %d...\n",__FILE__,__FUNCTION__,sock); +} + +void Socket::disconnectSocket() +{ + if(Socket::enableDebugText) printf("In [%s::%s] START closing socket = %d...\n",__FILE__,__FUNCTION__,sock); + + if(sock > 0) + { + ::shutdown(sock,2); + ::closesocket(sock); + sock = -1; + } + + if(Socket::enableDebugText) printf("In [%s::%s] END closing socket = %d...\n",__FILE__,__FUNCTION__,sock); +} + +// Int lookup is socket fd while bool result is whether or not that socket was signalled for reading +bool Socket::hasDataToRead(std::map &socketTriggeredList) +{ + bool bResult = false; + + if(socketTriggeredList.size() > 0) + { + /* Watch stdin (fd 0) to see when it has input. */ + fd_set rfds; + FD_ZERO(&rfds); + + int imaxsocket = 0; + for(std::map::iterator itermap = socketTriggeredList.begin(); + itermap != socketTriggeredList.end(); itermap++) + { + int socket = itermap->first; + if(socket > 0) + { + FD_SET(socket, &rfds); + imaxsocket = max(socket,imaxsocket); + } + } + + if(imaxsocket > 0) + { + /* Wait up to 0 seconds. */ + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 0; + + int retval = select(imaxsocket + 1, &rfds, NULL, NULL, &tv); + if(retval < 0) + { + char szBuf[1024]=""; + sprintf(szBuf,"In [%s::%s] ERROR SELECTING SOCKET DATA retval = %d WSAGetLastError() = %d",__FILE__,__FUNCTION__,retval,WSAGetLastError()); + fprintf(stderr, "%s", szBuf); + + } + else if(retval) + { + bResult = true; + + if(Socket::enableDebugText) printf("In [%s::%s] select detected data imaxsocket = %d...\n",__FILE__,__FUNCTION__,imaxsocket); + + for(std::map::iterator itermap = socketTriggeredList.begin(); + itermap != socketTriggeredList.end(); itermap++) + { + int socket = itermap->first; + if (FD_ISSET(socket, &rfds)) + { + if(Socket::enableDebugText) printf("In [%s] FD_ISSET true for socket %d...\n",__FUNCTION__,socket); + + itermap->second = true; + } + else + { + itermap->second = false; + } + } + + if(Socket::enableDebugText) printf("In [%s::%s] socketTriggeredList->size() = %d\n",__FILE__,__FUNCTION__,socketTriggeredList.size()); + } + } + } + + return bResult; +} + +bool Socket::hasDataToRead() +{ + return Socket::hasDataToRead(sock) ; +} + +bool Socket::hasDataToRead(int socket) +{ + bool bResult = false; + + if(socket > 0) + { + fd_set rfds; + struct timeval tv; + + /* Watch stdin (fd 0) to see when it has input. */ + FD_ZERO(&rfds); + FD_SET(socket, &rfds); + + /* Wait up to 0 seconds. */ + tv.tv_sec = 0; + tv.tv_usec = 0; + + int retval = select(socket + 1, &rfds, NULL, NULL, &tv); + if(retval) + { + if (FD_ISSET(socket, &rfds)) + { + bResult = true; + } + } + } + + return bResult; } int Socket::getDataToRead(){ - u_long size; - - int err= ioctlsocket(sock, FIONREAD, &size); + unsigned long size = 0; - if(err==SOCKET_ERROR){ - if(WSAGetLastError()!=WSAEWOULDBLOCK){ - throwException("Can not get data to read"); - } - } + //fd_set rfds; + //struct timeval tv; + //int retval; + + /* Watch stdin (fd 0) to see when it has input. */ + //FD_ZERO(&rfds); + //FD_SET(sock, &rfds); + + /* Wait up to 0 seconds. */ + //tv.tv_sec = 0; + //tv.tv_usec = 0; + + //retval = select(sock + 1, &rfds, NULL, NULL, &tv); + //if(retval) + if(sock > 0) + { + /* ioctl isn't posix, but the following seems to work on all modern + * unixes */ + int err= ioctlsocket(sock, FIONREAD, &size); + + if(err < 0 && WSAGetLastError() != WSAEWOULDBLOCK) + { + char szBuf[1024]=""; + sprintf(szBuf,"In [%s::%s] ERROR PEEKING SOCKET DATA, err = %d WSAGetLastError() = %d",__FILE__,__FUNCTION__,err,WSAGetLastError()); + + throwException(szBuf); + } + else if(err == 0) + { + //if(Socket::enableDebugText) printf("In [%s] ioctl returned = %d, size = %ld\n",__FUNCTION__,err,size); + } + } return static_cast(size); } -int Socket::send(const void *data, int dataSize){ - int err= ::send(sock, reinterpret_cast(data), dataSize, 0); - if(err==SOCKET_ERROR){ - if(WSAGetLastError()!=WSAEWOULDBLOCK){ - throwException("Can not send data"); - } +int Socket::send(const void *data, int dataSize) { + int bytesSent= 0; + if(sock > 0) + { + bytesSent = ::send(sock, reinterpret_cast(data), dataSize, 0); } - return err; + if(bytesSent < 0 && WSAGetLastError() != WSAEWOULDBLOCK) + { + char szBuf[1024]=""; + sprintf(szBuf,"In [%s::%s] ERROR WRITING SOCKET DATA, err = %d WSAGetLastError() = %d",__FILE__,__FUNCTION__,bytesSent,WSAGetLastError()); + + throwException(szBuf); + } + else if(bytesSent < 0 && WSAGetLastError() == WSAEWOULDBLOCK) + { + printf("In [%s::%s] #1 WSAEWOULDBLOCK during send, trying again...\n",__FILE__,__FUNCTION__); + + time_t tStartTimer = time(NULL); + while((bytesSent < 0 && WSAGetLastError() == WSAEWOULDBLOCK) && (difftime(time(NULL),tStartTimer) <= 5)) + { + if(Socket::isWritable(true) == true) + { + bytesSent = ::send(sock, reinterpret_cast(data), dataSize, 0); + + printf("In [%s::%s] #2 WSAEWOULDBLOCK during send, trying again returned: %d\n",__FILE__,__FUNCTION__,bytesSent); + } + } + } + if(bytesSent <= 0) + { + int iErr = WSAGetLastError(); + disconnectSocket(); + + char szBuf[1024]=""; + sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while sending socket data, bytesSent = %d, WSAGetLastError() = %d\n",__FILE__,__FUNCTION__,bytesSent,iErr); + printf("%s",szBuf); + //throwException(szBuf); + } + + if(Socket::enableDebugText) printf("In [%s::%s] sock = %d, bytesSent = %d\n",__FILE__,__FUNCTION__,sock,bytesSent); + + return static_cast(bytesSent); } -int Socket::receive(void *data, int dataSize){ - int err= recv(sock, reinterpret_cast(data), dataSize, 0); +int Socket::receive(void *data, int dataSize) +{ + int bytesReceived = 0; - if(err==SOCKET_ERROR){ - if(WSAGetLastError()!=WSAEWOULDBLOCK){ - throwException("Can not receive data"); - } + if(sock > 0) + { + bytesReceived = recv(sock, reinterpret_cast(data), dataSize, 0); + } + if(bytesReceived < 0 && WSAGetLastError() != WSAEWOULDBLOCK) + { + char szBuf[1024]=""; + sprintf(szBuf,"[%s::%s] ERROR READING SOCKET DATA error while sending socket data, bytesSent = %d, WSAGetLastError() = %d\n",__FILE__,__FUNCTION__,bytesReceived,WSAGetLastError()); + + throwException(szBuf); + } + else if(bytesReceived < 0 && WSAGetLastError() == WSAEWOULDBLOCK) + { + printf("In [%s::%s] #1 WSAEWOULDBLOCK during receive, trying again...\n",__FILE__,__FUNCTION__); + + time_t tStartTimer = time(NULL); + while((bytesReceived < 0 && WSAGetLastError() == WSAEWOULDBLOCK) && (difftime(time(NULL),tStartTimer) <= 5)) + { + if(Socket::isReadable() == true) + { + bytesReceived = recv(sock, reinterpret_cast(data), dataSize, 0); + + printf("In [%s::%s] #2 WSAEWOULDBLOCK during receive, trying again returned: %d\n",__FILE__,__FUNCTION__,bytesReceived); + } + } } - return err; + if(bytesReceived <= 0) + { + int iErr = WSAGetLastError(); + disconnectSocket(); + + char szBuf[1024]=""; + sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while receiving socket data, bytesReceived = %d, WSAGetLastError() = %d\n",__FILE__,__FUNCTION__,bytesReceived,iErr); + printf("%s",szBuf); + //throwException(szBuf); + } + return static_cast(bytesReceived); } int Socket::peek(void *data, int dataSize){ - int err= recv(sock, reinterpret_cast(data), dataSize, MSG_PEEK); + int err = 0; + if(sock > 0) + { + err = recv(sock, reinterpret_cast(data), dataSize, MSG_PEEK); + } + if(err < 0 && WSAGetLastError() != WSAEWOULDBLOCK) + { + char szBuf[1024]=""; + sprintf(szBuf,"[%s::%s] ERROR PEEKING SOCKET DATA error while sending socket data, bytesSent = %d, WSAGetLastError() = %d\n",__FILE__,__FUNCTION__,err,WSAGetLastError()); - if(err==SOCKET_ERROR){ - if(WSAGetLastError()!=WSAEWOULDBLOCK){ - throwException("Can not receive data"); - } + throwException(szBuf); + } + else if(err < 0 && WSAGetLastError() == WSAEWOULDBLOCK) + { + printf("In [%s::%s] #1 WSAEWOULDBLOCK during peek, trying again...\n",__FILE__,__FUNCTION__); + + time_t tStartTimer = time(NULL); + while((err < 0 && WSAGetLastError() == WSAEWOULDBLOCK) && (difftime(time(NULL),tStartTimer) <= 5)) + { + if(Socket::isReadable() == true) + { + err = recv(sock, reinterpret_cast(data), dataSize, MSG_PEEK); + + printf("In [%s::%s] #2 WSAEWOULDBLOCK during peek, trying again returned: %d\n",__FILE__,__FUNCTION__,err); + } + } } - return err; + if(err <= 0) + { + int iErr = WSAGetLastError(); + disconnectSocket(); + + char szBuf[1024]=""; + sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while peeking socket data, err = %d, WSAGetLastError() = %d\n",__FILE__,__FUNCTION__,err,iErr); + printf("%s",szBuf); + //throwException(szBuf); + } + + return static_cast(err); } void Socket::setBlock(bool block){ @@ -149,49 +395,101 @@ void Socket::setBlock(bool block){ } } -bool Socket::isReadable(){ +bool Socket::isReadable() +{ + if(sock <= 0) return false; + TIMEVAL tv; tv.tv_sec= 0; - tv.tv_usec= 10; + tv.tv_usec= 1; fd_set set; FD_ZERO(&set); FD_SET(sock, &set); - int i= select(0, &set, NULL, NULL, &tv); - if(i==SOCKET_ERROR){ - throwException("Error selecting socket"); - } - return i==1; + int i= select(sock+1, &set, NULL, NULL, &tv); + if(i==SOCKET_ERROR) + { + char szBuf[1024]=""; + sprintf(szBuf,"[%s::%s] error while selecting socket data, err = %d, errno = %d\n",__FILE__,__FUNCTION__,i,WSAGetLastError()); + printf("%s",szBuf); + } + //return (i == 1 && FD_ISSET(sock, &set)); + return (i == 1); } -bool Socket::isWritable(){ +bool Socket::isWritable(bool waitOnDelayedResponse) +{ + if(sock <= 0) return false; + TIMEVAL tv; tv.tv_sec= 0; - tv.tv_usec= 10; + tv.tv_usec= 1; fd_set set; FD_ZERO(&set); FD_SET(sock, &set); - int i= select(0, NULL, &set, NULL, &tv); - if(i==SOCKET_ERROR){ - throwException("Error selecting socket"); - } - return i==1; + bool result = false; + do + { + int i= select(sock+1, NULL, &set, NULL, &tv); + if(i==SOCKET_ERROR) + { + char szBuf[1024]=""; + sprintf(szBuf,"[%s::%s] error while selecting socket data, err = %d, errno = %d\n",__FILE__,__FUNCTION__,i,WSAGetLastError()); + printf("%s",szBuf); + waitOnDelayedResponse = false; + } + else if(i == 0) + { + char szBuf[1024]=""; + sprintf(szBuf,"[%s::%s] TIMEOUT while selecting socket data, err = %d, errno = %d\n",__FILE__,__FUNCTION__,i,WSAGetLastError()); + printf("%s",szBuf); + + if(waitOnDelayedResponse == false) + { + result = true; + } + } + else + { + result = true; + } + } while(waitOnDelayedResponse == true && result == false); + + return result; } bool Socket::isConnected(){ //if the socket is not writable then it is not conencted - if(!isWritable()){ + if(isWritable(false) == false) + { return false; } //if the socket is readable it is connected if we can read a byte from it - if(isReadable()){ - char tmp; - return recv(sock, &tmp, sizeof(tmp), MSG_PEEK) > 0; + if(isReadable()) + { + char tmp; + int err = peek(&tmp, sizeof(tmp)); + return (err > 0); + /* + int err = recv(sock, &tmp, sizeof(tmp), MSG_PEEK); + + if(err <= 0 && WSAGetLastError() != WSAEWOULDBLOCK) + { + int iErr = WSAGetLastError(); + disconnectSocket(); + + char szBuf[1024]=""; + sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while peeking isconnected socket data, err = %d, WSAGetLastError() = %d\n",__FILE__,__FUNCTION__,err,iErr); + printf("%s",szBuf); + + return false; + } + */ } //otherwise the socket is connected @@ -220,9 +518,9 @@ string Socket::getIp() const{ throwException("Error getting host ip"); } - return - intToStr(address[0]) + "." + - intToStr(address[1]) + "." + + return + intToStr(address[0]) + "." + + intToStr(address[1]) + "." + intToStr(address[2]) + "." + intToStr(address[3]); } @@ -235,20 +533,86 @@ void Socket::throwException(const string &str){ // class ClientSocket // ===================================================== -void ClientSocket::connect(const Ip &ip, int port){ +void ClientSocket::connect(const Ip &ip, int port) +{ sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); addr.sin_family= AF_INET; addr.sin_addr.s_addr= inet_addr(ip.getString().c_str()); addr.sin_port= htons(port); int err= ::connect(sock, reinterpret_cast(&addr), sizeof(addr)); - if(err==SOCKET_ERROR){ - int lastError= WSAGetLastError(); + if(err < 0) + { + char szBuf[1024]=""; + sprintf(szBuf,"#2 Error connecting socket for IP: %s for Port: %d err = %d WSAGetLastError() = %d",ip.getString().c_str(),port,err,WSAGetLastError()); + fprintf(stderr, "%s", szBuf); - if(lastError!=WSAEWOULDBLOCK && lastError!=WSAEALREADY){ - throwException("Can not connect"); - } + if (WSAGetLastError() == WSAEINPROGRESS) { + + fd_set myset; + struct timeval tv; + int valopt; + socklen_t lon; + + fprintf(stderr, "EINPROGRESS in connect() - selecting\n"); + do { + tv.tv_sec = 10; + tv.tv_usec = 0; + + FD_ZERO(&myset); + FD_SET(sock, &myset); + + err = select(sock+1, NULL, &myset, NULL, &tv); + + if (err < 0 && WSAGetLastError() != WSAEWOULDBLOCK) + { + sprintf(szBuf, "Error connecting %d\n", WSAGetLastError()); + //throwException(szBuf); + fprintf(stderr, "%s", szBuf); + break; + } + else if (err > 0) { + // Socket selected for write + lon = sizeof(int); + if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)(&valopt), &lon) < 0) + { + sprintf(szBuf, "Error in getsockopt() %d\n", WSAGetLastError()); + //throwException(szBuf); + fprintf(stderr, "%s", szBuf); + break; + } + // Check the value returned... + if (valopt) + { + sprintf(szBuf, "Error in delayed connection() %d\n", valopt); + //throwException(szBuf); + fprintf(stderr, "%s", szBuf); + break; + } + + fprintf(stderr, "Apparent recovery for connection sock = %d, err = %d, WSAGetLastError() = %d\n",sock,err,WSAGetLastError()); + + break; + } + else + { + sprintf(szBuf, "Timeout in select() - Cancelling!\n"); + //throwException(szBuf); + fprintf(stderr, "%s", szBuf); + break; + } + } while (1); + } + + if(err < 0) + { + fprintf(stderr, "In [%s::%s] Before END sock = %d, err = %d, errno = %d\n",__FILE__,__FUNCTION__,sock,err,WSAGetLastError()); + //throwException(szBuf); + } + + fprintf(stderr, "Valid recovery for connection sock = %d, err = %d, WSAGetLastError() = %d\n",sock,err,WSAGetLastError()); } } @@ -262,7 +626,7 @@ void ServerSocket::bind(int port){ addr.sin_family= AF_INET; addr.sin_addr.s_addr= INADDR_ANY; addr.sin_port= htons(port); - + int err= ::bind(sock, reinterpret_cast(&addr), sizeof(addr)); if(err==SOCKET_ERROR){ throwException("Error binding socket"); diff --git a/source/shared_lib/sources/util/checksum.cpp b/source/shared_lib/sources/util/checksum.cpp index 9e50ff3df..95063a1da 100644 --- a/source/shared_lib/sources/util/checksum.cpp +++ b/source/shared_lib/sources/util/checksum.cpp @@ -3,9 +3,9 @@ // // 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 +// 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 // ============================================================== @@ -27,14 +27,14 @@ namespace Shared{ namespace Util{ Checksum::Checksum(){ sum= 0; - r= 55665; - c1= 52845; + r= 55665; + c1= 52845; c2= 22719; } void Checksum::addByte(int8 value){ int32 cipher= (value ^ (r >> 8)); - + r= (cipher + r) * c1 + c2; sum+= cipher; } @@ -46,7 +46,7 @@ void Checksum::addString(const string &value){ } void Checksum::addFile(const string &path){ - + FILE* file= fopen(path.c_str(), "rb"); if(file!=NULL){ diff --git a/source/shared_lib/sources/xml/xml_parser.cpp b/source/shared_lib/sources/xml/xml_parser.cpp index 109777370..3c29a10a4 100644 --- a/source/shared_lib/sources/xml/xml_parser.cpp +++ b/source/shared_lib/sources/xml/xml_parser.cpp @@ -3,9 +3,9 @@ // // 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 +// 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 // ============================================================== @@ -61,7 +61,7 @@ XmlIo::XmlIo(){ } catch(const XMLException&){ throw runtime_error("Error initializing XML system"); - } + } try{ XMLCh str[strSize]; @@ -84,7 +84,7 @@ XmlIo::~XmlIo(){ } XmlNode *XmlIo::load(const string &path){ - + try{ ErrorHandler errorHandler; #if XERCES_VERSION_MAJOR < 3 @@ -99,7 +99,7 @@ XmlNode *XmlIo::load(const string &path){ config->setParameter(XMLUni::fgDOMValidate, true); #endif DOMDocument *document= parser->parseURI(path.c_str()); - + if(document==NULL){ throw runtime_error("Can not parse URL: " + path); } @@ -110,7 +110,7 @@ XmlNode *XmlIo::load(const string &path){ } catch(const DOMException &e){ throw runtime_error("Exception while loading: " + path + ": " + XMLString::transcode(e.msg)); - } + } } void XmlIo::save(const string &path, const XmlNode *node){ @@ -144,7 +144,7 @@ void XmlIo::save(const string &path, const XmlNode *node){ } catch(const DOMException &e){ throw runtime_error("Exception while saving: " + path + ": " + XMLString::transcode(e.msg)); - } + } } // ===================================================== // class XmlTree @@ -188,7 +188,7 @@ XmlNode::XmlNode(DOMNode *node){ //check children for(int i=0; igetChildNodes()->getLength(); ++i){ - DOMNode *currentNode= node->getChildNodes()->item(i); + DOMNode *currentNode= node->getChildNodes()->item(i); if(currentNode->getNodeType()==DOMNode::ELEMENT_NODE){ XmlNode *xmlNode= new XmlNode(currentNode); children.push_back(xmlNode); @@ -234,7 +234,7 @@ XmlAttribute *XmlNode::getAttribute(int i) const{ } return attributes[i]; } - + XmlAttribute *XmlNode::getAttribute(const string &name) const{ for(int i=0; igetName()==name){ @@ -269,6 +269,20 @@ XmlNode *XmlNode::getChild(const string &childName, int i) const{ throw runtime_error("Node \""+getName()+"\" doesn't have "+intToStr(i+1)+" children named \""+childName+"\"\n\nTree: "+getTreeString()); } +bool XmlNode::hasChild(const string &childName) const +{ + int count= 0; + for(int j = 0; j < children.size(); ++j) + { + if(children[j]->getName()==childName) + { + return true; + } + } + + return false; +} + XmlNode *XmlNode::addChild(const string &name){ XmlNode *node= new XmlNode(name); children.push_back(node); @@ -290,10 +304,10 @@ DOMElement *XmlNode::buildElement(DOMDocument *document) const{ for(int i=0; igetName().c_str(), str, strSize-1); DOMAttr *attr= document->createAttribute(str); - + XMLString::transcode(attributes[i]->getValue().c_str(), str, strSize-1); attr->setValue(str); - + node->setAttributeNode(attr); } @@ -387,7 +401,7 @@ const string &XmlAttribute::getRestrictedValue() const "\"\nFor portability reasons the only allowed characters in this field are: " + allowedCharacters); } } - + return value; }