From 943dcef9fe6dfbc863dac54fbfe6cfc5463ca548 Mon Sep 17 00:00:00 2001 From: Mark Vejvoda Date: Tue, 12 Jun 2012 20:37:00 +0000 Subject: [PATCH] - first pass of VERY ROUGH crude implementation of 'cell markers'. Need to properly find icons, apply alpha to icon on the map and add support for notes when user hovers over the marker. --- source/glest_game/game/game.cpp | 95 +++++++++ source/glest_game/game/game.h | 10 + source/glest_game/graphics/renderer.cpp | 184 +++++++++++++++++- source/glest_game/graphics/renderer.h | 12 +- .../glest_game/network/client_interface.cpp | 56 +++++- source/glest_game/network/client_interface.h | 3 +- source/glest_game/network/connection_slot.cpp | 30 +++ .../glest_game/network/network_interface.cpp | 19 ++ source/glest_game/network/network_interface.h | 40 ++++ source/glest_game/network/network_message.cpp | 35 ++++ source/glest_game/network/network_message.h | 39 ++++ .../glest_game/network/server_interface.cpp | 90 +++++++++ source/glest_game/network/server_interface.h | 6 + 13 files changed, 608 insertions(+), 11 deletions(-) diff --git a/source/glest_game/game/game.cpp b/source/glest_game/game/game.cpp index efe61655..1ca8ccf6 100644 --- a/source/glest_game/game/game.cpp +++ b/source/glest_game/game/game.cpp @@ -114,7 +114,12 @@ Game::Game() : ProgramState(NULL) { pauseGamePopupMenuIndex = -1; saveGamePopupMenuIndex = -1; loadGamePopupMenuIndex = -1; + markCellPopupMenuIndex = -1; keyboardSetupPopupMenuIndex = -1; + + isMarkCellEnabled = false; + markCellTexture = NULL; + masterserverMode = false; currentUIState=NULL; currentAmbientSound=NULL; @@ -161,7 +166,12 @@ void Game::resetMembers() { pauseGamePopupMenuIndex = -1; saveGamePopupMenuIndex = -1; loadGamePopupMenuIndex = -1; + markCellPopupMenuIndex = -1; keyboardSetupPopupMenuIndex = -1; + + isMarkCellEnabled = false; + markCellTexture = NULL; + currentUIState = NULL; //this->gameSettings= NULL; @@ -728,6 +738,10 @@ void Game::load(int loadTypes) { loadHudTexture(&gameSettings); + string data_path = getGameReadWritePath(GameConstants::path_data_CacheLookupKey); + const string markCellTextureFilename = data_path + "data/core/misc_textures/mark_cell.png"; + markCellTexture = Renderer::findFactionLogoTexture(markCellTextureFilename); + string scenarioDir = ""; if(gameSettings.getScenarioDir() != "") { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); @@ -1137,6 +1151,9 @@ void Game::setupPopupMenus(bool checkClientAdminOverrideOnly) { joinTeamPopupMenuIndex = menuItems.size()-1; } + menuItems.push_back(lang.get("MarkCell")); + markCellPopupMenuIndex = menuItems.size()-1; + if(allowAdminMenuItems == true){ menuItems.push_back(lang.get("PauseResumeGame")); pauseGamePopupMenuIndex= menuItems.size() - 1; @@ -1152,6 +1169,7 @@ void Game::setupPopupMenus(bool checkClientAdminOverrideOnly) { menuItems.push_back(lang.get("Keyboardsetup")); keyboardSetupPopupMenuIndex = menuItems.size()-1; menuItems.push_back(lang.get("Cancel")); + popupMenu.setW(100); popupMenu.setH(100); popupMenu.init(lang.get("GameMenuTitle"),menuItems); @@ -1364,6 +1382,8 @@ void Game::update() { if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [chatManager.updateNetwork]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis()); if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start(); + updateNetworkMarkedCells(); + //check for quiting status if(NetworkManager::getInstance().getGameNetworkInterface() != NULL && NetworkManager::getInstance().getGameNetworkInterface()->getQuit() && @@ -1531,6 +1551,33 @@ void Game::update() { } } +void Game::updateNetworkMarkedCells() { + try { + GameNetworkInterface *gameNetworkInterface= NetworkManager::getInstance().getGameNetworkInterface(); + + if(gameNetworkInterface != NULL && + gameNetworkInterface->getMarkedCellList(false).empty() == false) { + Lang &lang= Lang::getInstance(); + + std::vector chatList = gameNetworkInterface->getMarkedCellList(true); + for(int idx = 0; idx < chatList.size(); idx++) { + MarkedCell mc = chatList[idx]; + mc.setFaction((const Faction *)world.getFaction(mc.getFactionIndex())); + + Map *map= world.getMap(); + Vec2i surfaceCellPos = map->toSurfCoords(mc.getTargetPos()); + mapMarkedCellList[surfaceCellPos] = mc; + } + } + } + catch(const std::exception &ex) { + char szBuf[1024]=""; + sprintf(szBuf,"In [%s::%s %d] error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what()); + SystemFlags::OutputDebug(SystemFlags::debugError,szBuf); + throw megaglest_runtime_error(szBuf); + } +} + void Game::ReplaceDisconnectedNetworkPlayersWithAI(bool isNetworkGame, NetworkRole role) { if(role == nrServer && isNetworkGame == true && difftime(time(NULL),lastNetworkPlayerConnectionCheck) >= NETWORK_PLAYER_CONNECTION_CHECK_SECONDS) { @@ -1868,6 +1915,7 @@ void Game::mouseDownLeft(int x, int y) { const Metrics &metrics= Metrics::getInstance(); NetworkManager &networkManager= NetworkManager::getInstance(); bool messageBoxClick= false; + bool originalIsMarkCellEnabled = isMarkCellEnabled; if(popupMenu.mouseClick(x, y)) { std::pair result = popupMenu.mouseClickedMenuItem(x, y); @@ -1964,6 +2012,9 @@ void Game::mouseDownLeft(int x, int y) { else if(result.first == saveGamePopupMenuIndex){ saveGame(); } + else if(result.first == markCellPopupMenuIndex) { + isMarkCellEnabled = true; + } } else if(popupMenuSwitchTeams.mouseClick(x, y)) { //popupMenuSwitchTeams @@ -2047,6 +2098,27 @@ void Game::mouseDownLeft(int x, int y) { { gameCamera.setPos(Vec2f(static_cast(xCell), static_cast(yCell))); } + + if(originalIsMarkCellEnabled == true && isMarkCellEnabled == true) { + Vec2i surfaceCellPos = map->toSurfCoords(Vec2i(xCell,yCell)); + SurfaceCell *sc = map->getSurfaceCell(surfaceCellPos); + Vec3f vertex = sc->getVertex(); + Vec2i targetPos(vertex.x,vertex.z); + + MarkedCell mc(targetPos,world.getThisFaction(),"placeholder for note"); + mapMarkedCellList[surfaceCellPos] = mc; + + GameNetworkInterface *gameNetworkInterface= NetworkManager::getInstance().getGameNetworkInterface(); + gameNetworkInterface->sendMarkCellMessage(mc.getTargetPos(),mc.getFaction()->getIndex(),mc.getNote()); + + //printf("#1 ADDED in marked list pos [%s] markedCells.size() = %lu\n",surfaceCellPos.getString().c_str(),mapMarkedCellList.size()); + + isMarkCellEnabled = false; + + Renderer &renderer= Renderer::getInstance(); + //renderer.updateMarkedCellScreenPosQuadCache(surfaceCellPos); + renderer.forceQuadCacheUpdate(); + } } } //display panel @@ -2063,6 +2135,27 @@ void Game::mouseDownLeft(int x, int y) { //graphics panel else { gui.mouseDownLeftGraphics(x, y, false); + + if(originalIsMarkCellEnabled == true && isMarkCellEnabled == true) { + Vec2i targetPos; + Vec2i screenPos(x,y); + Renderer &renderer= Renderer::getInstance(); + renderer.computePosition(screenPos, targetPos); + Vec2i surfaceCellPos = map->toSurfCoords(targetPos); + + MarkedCell mc(targetPos,world.getThisFaction(),"placeholder for note"); + mapMarkedCellList[surfaceCellPos] = mc; + + GameNetworkInterface *gameNetworkInterface= NetworkManager::getInstance().getGameNetworkInterface(); + gameNetworkInterface->sendMarkCellMessage(mc.getTargetPos(),mc.getFaction()->getIndex(),mc.getNote()); + + //printf("#2 ADDED in marked list pos [%s] markedCells.size() = %lu\n",surfaceCellPos.getString().c_str(),mapMarkedCellList.size()); + + isMarkCellEnabled = false; + + //renderer.updateMarkedCellScreenPosQuadCache(surfaceCellPos); + renderer.forceQuadCacheUpdate(); + } } } @@ -3143,6 +3236,8 @@ void Game::render2d() { renderer.renderMinimap(); } + renderer.renderVisibleMarkedCells(); + //selection renderer.renderSelectionQuad(); diff --git a/source/glest_game/game/game.h b/source/glest_game/game/game.h index ab78356f..58cd21cf 100644 --- a/source/glest_game/game/game.h +++ b/source/glest_game/game/game.h @@ -148,10 +148,14 @@ private: int pauseGamePopupMenuIndex; int saveGamePopupMenuIndex; int loadGamePopupMenuIndex; + int markCellPopupMenuIndex; int keyboardSetupPopupMenuIndex; //GLuint statelist3dMenu; ProgramState *currentUIState; + bool isMarkCellEnabled; + Texture2D *markCellTexture; + std::map mapMarkedCellList; bool masterserverMode; StrSound *currentAmbientSound; @@ -173,6 +177,10 @@ public: Game(Program *program, const GameSettings *gameSettings, bool masterserverMode); ~Game(); + bool isMarkCellMode() const { return isMarkCellEnabled; } + const Texture2D * getMarkCellTexture() const { return markCellTexture; } + std::map getMapMarkedCellList() const { return mapMarkedCellList; } + bool isMasterserverMode() const { return masterserverMode; } //get GameSettings *getGameSettings() {return &gameSettings;} @@ -296,6 +304,8 @@ private: string getDebugStats(std::map &factionDebugInfo); void renderVideoPlayer(); + + void updateNetworkMarkedCells(); }; }}//end namespace diff --git a/source/glest_game/graphics/renderer.cpp b/source/glest_game/graphics/renderer.cpp index 8e794e6c..73ea7a7d 100644 --- a/source/glest_game/graphics/renderer.cpp +++ b/source/glest_game/graphics/renderer.cpp @@ -1582,11 +1582,11 @@ void Renderer::renderMouse2d(int x, int y, int anim, float fade) { } // float blue=0.0f; // float green=0.4f; - if(game!=NULL && game->getGui()!=NULL){ + if(game != NULL && game->getGui() != NULL) { const Gui *gui=game->getGui(); const Display *display=gui->getDisplay(); int downPos= display->getDownSelectedPos(); - if(downPos!=Display::invalidPos){ + if(downPos != Display::invalidPos){ // in state of doing something const Texture2D *texture= display->getDownImage(downPos); renderTextureQuad(x+18,y-50,32,32,texture,0.8f); @@ -1606,6 +1606,11 @@ void Renderer::renderMouse2d(int x, int y, int anim, float fade) { // } // } // } + + if(game->isMarkCellMode() == true) { + const Texture2D *texture= game->getMarkCellTexture(); + renderTextureQuad(x-18,y-50,32,32,texture,0.8f); + } } float color1 = 0.0, color2 = 0.0; @@ -5456,6 +5461,8 @@ void Renderer::renderMinimap(){ } + renderMarkedCellsOnMinimap(); + //draw camera float wRatio= static_cast(metrics.getMinimapW()) / world->getMap()->getW(); float hRatio= static_cast(metrics.getMinimapH()) / world->getMap()->getH(); @@ -5503,6 +5510,102 @@ void Renderer::renderMinimap(){ assertGl(); } +void Renderer::renderMarkedCellsOnMinimap() { + // Draw marked cells + std::map markedCells = game->getMapMarkedCellList(); + if(markedCells.empty() == false) { + const Map *map= game->getWorld()->getMap(); + const World *world= game->getWorld(); + const Minimap *minimap= world->getMinimap(); + + if(minimap == NULL || minimap->getTexture() == NULL) { + return; + } + + const GameCamera *gameCamera= game->getGameCamera(); + const Pixmap2D *pixmap= minimap->getTexture()->getPixmapConst(); + const Metrics &metrics= Metrics::getInstance(); + const WaterEffects *attackEffects= world->getAttackEffects(); + + int mx= metrics.getMinimapX(); + int my= metrics.getMinimapY(); + int mw= metrics.getMinimapW(); + int mh= metrics.getMinimapH(); + + Vec2f zoom= Vec2f( + static_cast(mw)/ pixmap->getW(), + static_cast(mh)/ pixmap->getH()); + + uint32 unitIdx=0; + vector unit_vertices; + unit_vertices.resize(markedCells.size()*4); + vector unit_colors; + unit_colors.resize(markedCells.size()*4); + + for(std::map::iterator iterMap =markedCells.begin(); + iterMap != markedCells.end(); ++iterMap) { + MarkedCell &bm = iterMap->second; + if(bm.getFaction() != NULL && bm.getFaction()->getTeam() == game->getWorld()->getThisFaction()->getTeam()) { + Vec2i pos= bm.getTargetPos() / Map::cellScale; + float size= 0.5f; + //Vec3f color= bm.color; + Vec3f color= bm.getFaction()->getTexture()->getPixmapConst()->getPixel3f(0, 0); + float alpha = 0.65; + + unit_colors[unitIdx] = Vec4f(color.x,color.y,color.z,alpha); + unit_vertices[unitIdx] = Vec2f(mx + pos.x*zoom.x, my + mh - (pos.y*zoom.y)); + unitIdx++; + + unit_colors[unitIdx] = Vec4f(color.x,color.y,color.z,alpha); + unit_vertices[unitIdx] = Vec2f(mx + (pos.x+1)*zoom.x+size, my + mh - (pos.y*zoom.y)); + unitIdx++; + + unit_colors[unitIdx] = Vec4f(color.x,color.y,color.z,alpha); + unit_vertices[unitIdx] = Vec2f(mx + (pos.x+1)*zoom.x+size, my + mh - ((pos.y+size)*zoom.y)); + unitIdx++; + + unit_colors[unitIdx] = Vec4f(color.x,color.y,color.z,alpha); + unit_vertices[unitIdx] = Vec2f(mx + pos.x*zoom.x, my + mh - ((pos.y+size)*zoom.y)); + unitIdx++; + } + } + + if(unitIdx > 0) { + glEnable(GL_BLEND); + + glEnableClientState(GL_COLOR_ARRAY); + glEnableClientState(GL_VERTEX_ARRAY); + glColorPointer(4,GL_FLOAT, 0, &unit_colors[0]); + glVertexPointer(2, GL_FLOAT, 0, &unit_vertices[0]); + glDrawArrays(GL_QUADS, 0, unitIdx); + //glDrawArrays(GL_TRIANGLE_STRIP, 0, unitIdx); + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + + glDisable(GL_BLEND); + } + } +} +void Renderer::renderVisibleMarkedCells() { + // Draw marked cells + std::map markedCells = game->getMapMarkedCellList(); + if(markedCells.empty() == false) { + for(std::map::iterator iterMap =markedCells.begin(); + iterMap != markedCells.end(); ++iterMap) { + MarkedCell &bm = iterMap->second; + if(bm.getFaction() != NULL && bm.getFaction()->getTeam() == game->getWorld()->getThisFaction()->getTeam()) { + const Map *map= game->getWorld()->getMap(); + std::pair bmVisible = posInCellQuadCache( + map->toSurfCoords(bm.getTargetPos())); + if(bmVisible.first == true) { + const Texture2D *texture= game->getMarkCellTexture(); + renderTextureQuad(bmVisible.second.x,bmVisible.second.y+10,32,32,texture,0.8f); + } + } + } + } +} + void Renderer::renderDisplay() { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; @@ -5884,7 +5987,7 @@ void Renderer::renderMenuBackground(Camera *camera, float fade, Model *mainModel // ==================== computing ==================== -bool Renderer::computePosition(const Vec2i &screenPos, Vec2i &worldPos){ +bool Renderer::computePosition(const Vec2i &screenPos, Vec2i &worldPos, bool exactCoords) { assertGl(); const Map* map= game->getWorld()->getMap(); const Metrics &metrics= Metrics::getInstance(); @@ -5916,7 +6019,12 @@ bool Renderer::computePosition(const Vec2i &screenPos, Vec2i &worldPos){ &worldX, &worldY, &worldZ); //conver coords to int - worldPos= Vec2i(static_cast(worldX+0.5f), static_cast(worldZ+0.5f)); + if(exactCoords == true) { + worldPos= Vec2i(static_cast(worldX), static_cast(worldZ)); + } + else { + worldPos= Vec2i(static_cast(worldX+0.5f), static_cast(worldZ+0.5f)); + } //clamp coords to map size return map->isInside(worldPos); @@ -7969,6 +8077,8 @@ VisibleQuadContainerCache & Renderer::getQuadCache( bool updateOnDirtyFrame, //int loops2=0; + std::map markedCells = game->getMapMarkedCellList(); + const Rect2i mapBounds(0, 0, map->getSurfaceW()-1, map->getSurfaceH()-1); Quad2i scaledQuad = visibleQuad / Map::cellScale; PosQuadIterator pqis(map,scaledQuad); @@ -7978,6 +8088,19 @@ VisibleQuadContainerCache & Renderer::getQuadCache( bool updateOnDirtyFrame, //loops2++; if(VisibleQuadContainerCache::enableFrustumCalcs == false) { quadCache.visibleScaledCellList.push_back(pos); + + if(markedCells.empty() == false) { + if(markedCells.find(pos) != markedCells.end()) { + //printf("#1 ******** VISIBLE SCALED CELL FOUND in marked list pos [%s] markedCells.size() = %lu\n",pos.getString().c_str(),markedCells.size()); + //if(markedCells.empty() == false) { + //SurfaceCell *sc = map->getSurfaceCell(pos); + //quadCache.visibleScaledCellToScreenPosList[pos]=computeScreenPosition(sc->getVertex()); + updateMarkedCellScreenPosQuadCache(pos); + } + else { + //printf("#1 VISIBLE SCALED CELL NOT FOUND in marked list pos [%s] markedCells.size() = %lu\n",pos.getString().c_str(),markedCells.size()); + } + } } else { SurfaceCell *sc = map->getSurfaceCell(pos); @@ -7987,6 +8110,18 @@ VisibleQuadContainerCache & Renderer::getQuadCache( bool updateOnDirtyFrame, if(insideQuad == true) { quadCache.visibleScaledCellList.push_back(pos); + + if(markedCells.empty() == false) { + if(markedCells.find(pos) != markedCells.end()) { + //printf("#2 ******** VISIBLE SCALED CELL FOUND in marked list pos [%s] markedCells.size() = %lu\n",pos.getString().c_str(),markedCells.size()); + //if(markedCells.empty() == false) { + //quadCache.visibleScaledCellToScreenPosList[pos]=computeScreenPosition(sc->getVertex()); + updateMarkedCellScreenPosQuadCache(pos); + } + else { + //printf("#2 VISIBLE SCALED CELL NOT FOUND in marked list pos [%s] markedCells.size() = %lu\n",pos.getString().c_str(),markedCells.size()); + } + } } } } @@ -8001,6 +8136,47 @@ VisibleQuadContainerCache & Renderer::getQuadCache( bool updateOnDirtyFrame, return quadCache; } +void Renderer::updateMarkedCellScreenPosQuadCache(Vec2i pos) { + const World *world= game->getWorld(); + const Map *map= world->getMap(); + + SurfaceCell *sc = map->getSurfaceCell(pos); + quadCache.visibleScaledCellToScreenPosList[pos]=computeScreenPosition(sc->getVertex()); +} + +void Renderer::forceQuadCacheUpdate() { + quadCache.cacheFrame = -1; + + Vec2i clearPos(-1,-1); + quadCache.lastVisibleQuad.p[0] = clearPos; + quadCache.lastVisibleQuad.p[1] = clearPos; + quadCache.lastVisibleQuad.p[2] = clearPos; + quadCache.lastVisibleQuad.p[3] = clearPos; +} + +std::pair Renderer::posInCellQuadCache(Vec2i pos) { + std::pair result = make_pair(false,Vec3f()); + if(std::find( + quadCache.visibleScaledCellList.begin(), + quadCache.visibleScaledCellList.end(), + pos) != quadCache.visibleScaledCellList.end()) { + result.first = true; + result.second = quadCache.visibleScaledCellToScreenPosList[pos]; + } + return result; +} + +Vec3f Renderer::getMarkedCellScreenPosQuadCache(Vec2i pos) { + Vec3f result(-1,-1,-1); + if(std::find( + quadCache.visibleScaledCellList.begin(), + quadCache.visibleScaledCellList.end(), + pos) != quadCache.visibleScaledCellList.end()) { + result = quadCache.visibleScaledCellToScreenPosList[pos]; + } + return result; +} + void Renderer::beginRenderToTexture(Texture2D **renderToTexture) { if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) { return; diff --git a/source/glest_game/graphics/renderer.h b/source/glest_game/graphics/renderer.h index 6c7ca683..52f3bdbb 100644 --- a/source/glest_game/graphics/renderer.h +++ b/source/glest_game/graphics/renderer.h @@ -103,6 +103,7 @@ protected: visibleUnitList = obj.visibleUnitList; visibleQuadUnitList = obj.visibleQuadUnitList; visibleScaledCellList = obj.visibleScaledCellList; + visibleScaledCellToScreenPosList = obj.visibleScaledCellToScreenPosList; lastVisibleQuad = obj.lastVisibleQuad; frustumData = obj.frustumData; proj = obj.proj; @@ -140,6 +141,7 @@ public: inline void clearNonVolatileCacheData() { visibleObjectList.clear(); visibleScaledCellList.clear(); + visibleScaledCellToScreenPosList.clear(); visibleObjectList.reserve(500); visibleScaledCellList.reserve(500); @@ -156,6 +158,7 @@ public: std::vector visibleQuadUnitList; std::vector visibleUnitList; std::vector visibleScaledCellList; + std::map visibleScaledCellToScreenPosList; static bool enableFrustumCalcs; vector > frustumData; @@ -519,7 +522,7 @@ public: void renderMenuBackground(Camera *camera, float fade, Model *mainModel, vector characterModels,const Vec3f characterPosition, float anim); //computing - bool computePosition(const Vec2i &screenPos, Vec2i &worldPos); + bool computePosition(const Vec2i &screenPos, Vec2i &worldPos,bool exactCoords=false); void computeSelected(Selection::UnitContainer &units, const Object *&obj, const bool withObjectSelection, const Vec2i &posDown, const Vec2i &posUp); void selectUsingColorPicking(Selection::UnitContainer &units, const Object *&obj,const bool withObjectSelection,const Vec2i &posDown, const Vec2i &posUp); void selectUsingSelectionBuffer(Selection::UnitContainer &units,const Object *&obj, const bool withObjectSelection,const Vec2i &posDown, const Vec2i &posUp); @@ -574,6 +577,13 @@ public: inline int getLastRenderFps() const { return lastRenderFps;} VisibleQuadContainerCache & getQuadCache(bool updateOnDirtyFrame=true,bool forceNew=false); + std::pair posInCellQuadCache(Vec2i pos); + Vec3f getMarkedCellScreenPosQuadCache(Vec2i pos); + void updateMarkedCellScreenPosQuadCache(Vec2i pos); + void forceQuadCacheUpdate(); + void renderVisibleMarkedCells(); + void renderMarkedCellsOnMinimap(); + void removeObjectFromQuadCache(const Object *o); void removeUnitFromQuadCache(const Unit *unit); diff --git a/source/glest_game/network/client_interface.cpp b/source/glest_game/network/client_interface.cpp index edd8d86a..89f1178d 100644 --- a/source/glest_game/network/client_interface.cpp +++ b/source/glest_game/network/client_interface.cpp @@ -471,6 +471,20 @@ void ClientInterface::updateLobby() { } break; + case nmtMarkCell: + { + NetworkMessageMarkCell networkMessageMarkCell; + if(receiveMessage(&networkMessageMarkCell)) { + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtMarkCell\n",__FILE__,__FUNCTION__); + + MarkedCell msg(networkMessageMarkCell.getTarget(), + networkMessageMarkCell.getFactionIndex(), + networkMessageMarkCell.getText().c_str()); + this->addMarkedCell(msg); + } + } + break; + case nmtLaunch: case nmtBroadCastSetup: { @@ -656,12 +670,8 @@ void ClientInterface::updateFrame(int *checkFrame) { case nmtText: { - time_t receiveTimeElapsed = time(NULL); + //time_t receiveTimeElapsed = time(NULL); NetworkMessageText networkMessageText; - // while(receiveMessage(&networkMessageText) == false && - // isConnected() == true && - // difftime(time(NULL),receiveTimeElapsed) <= (messageWaitTimeout / 1000)) { - // } bool gotCmd = receiveMessage(&networkMessageText); if(gotCmd == false) { throw megaglest_runtime_error("error retrieving nmtText returned false!"); @@ -676,6 +686,20 @@ void ClientInterface::updateFrame(int *checkFrame) { } break; + case nmtMarkCell: + { + NetworkMessageMarkCell networkMessageMarkCell; + if(receiveMessage(&networkMessageMarkCell)) { + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtMarkCell\n",__FILE__,__FUNCTION__); + + MarkedCell msg(networkMessageMarkCell.getTarget(), + networkMessageMarkCell.getFactionIndex(), + networkMessageMarkCell.getText().c_str()); + this->addMarkedCell(msg); + } + } + break; + case nmtLaunch: case nmtBroadCastSetup: { @@ -1168,6 +1192,14 @@ void ClientInterface::sendTextMessage(const string &text, int teamIndex, bool ec } } +void ClientInterface::sendMarkCellMessage(Vec2i targetPos, int factionIndex, string note) { + string humanPlayerName = getHumanPlayerName(); + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] humanPlayerName = [%s] playerIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,humanPlayerName.c_str(),playerIndex); + + NetworkMessageMarkCell networkMessageMarkCell(targetPos,factionIndex, note); + sendMessage(&networkMessageMarkCell); +} + void ClientInterface::sendPingMessage(int32 pingFrequency, int64 pingTime) { NetworkMessagePing networkMessagePing(pingFrequency,pingTime); sendMessage(&networkMessagePing); @@ -1355,6 +1387,20 @@ bool ClientInterface::shouldDiscardNetworkMessage(NetworkMessageType networkMess this->addChatInfo(msg); } break; + + case nmtMarkCell: + { + discard = true; + NetworkMessageMarkCell networkMessageMarkCell; + receiveMessage(&networkMessageMarkCell); + + MarkedCell msg(networkMessageMarkCell.getTarget(), + networkMessageMarkCell.getFactionIndex(), + networkMessageMarkCell.getText().c_str()); + this->addMarkedCell(msg); + } + break; + case nmtSynchNetworkGameData: { discard = true; diff --git a/source/glest_game/network/client_interface.h b/source/glest_game/network/client_interface.h index b585c6e4..5cef02ee 100644 --- a/source/glest_game/network/client_interface.h +++ b/source/glest_game/network/client_interface.h @@ -41,7 +41,6 @@ private: private: ClientSocket *clientSocket; - //GameSettings gameSettings; string serverName; bool introDone; bool launchGame; @@ -87,6 +86,8 @@ public: string targetLanguage); virtual void quitGame(bool userManuallyQuit); + virtual void sendMarkCellMessage(Vec2i targetPos, int factionIndex, string note); + //misc virtual string getNetworkStatus() ; diff --git a/source/glest_game/network/connection_slot.cpp b/source/glest_game/network/connection_slot.cpp index fa00080e..ce36c340 100644 --- a/source/glest_game/network/connection_slot.cpp +++ b/source/glest_game/network/connection_slot.cpp @@ -560,6 +560,36 @@ void ConnectionSlot::update(bool checkForNewClients,int lockedSlotIndex) { } break; + case nmtMarkCell: + { + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] got nmtMarkCell gotIntro = %d\n",__FILE__,__FUNCTION__,__LINE__,gotIntro); + + if(gotIntro == true) { + NetworkMessageMarkCell networkMessageMarkCell; + if(receiveMessage(&networkMessageMarkCell)) { + MarkedCell msg(networkMessageMarkCell.getTarget(), + networkMessageMarkCell.getFactionIndex(), + networkMessageMarkCell.getText().c_str()); + + this->addMarkedCell(msg); + //gotTextMsg = true; + } + else { + if(SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled) SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d]\nInvalid message type before intro handshake [%d]\nDisconnecting socket for slot: %d [%s].\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageType,this->playerIndex,this->getIpAddress().c_str()); + this->serverInterface->notifyBadClientConnectAttempt(this->getIpAddress()); + close(); + return; + } + } + else { + if(SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled) SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d]\nInvalid message type before intro handshake [%d]\nDisconnecting socket for slot: %d [%s].\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageType,this->playerIndex,this->getIpAddress().c_str()); + this->serverInterface->notifyBadClientConnectAttempt(this->getIpAddress()); + close(); + return; + } + } + break; + //command list case nmtCommandList: { diff --git a/source/glest_game/network/network_interface.cpp b/source/glest_game/network/network_interface.cpp index 32e6e030..fd735253 100644 --- a/source/glest_game/network/network_interface.cpp +++ b/source/glest_game/network/network_interface.cpp @@ -127,6 +127,25 @@ void NetworkInterface::clearChatInfo() { } } +std::vector NetworkInterface::getMarkedCellList(bool clearList) { + std::vector result; + if(markedCellList.empty() == false) { + result = markedCellList; + + if(clearList == true) { + markedCellList.clear(); + } + } + return result; +} + +void NetworkInterface::clearMarkedCellList() { + if(markedCellList.empty() == false) { + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] markedCellList.size() = %d\n",__FILE__,__FUNCTION__,__LINE__,markedCellList.size()); + markedCellList.clear(); + } +} + std::string NetworkInterface::getIpAddress() { std::string result = ""; diff --git a/source/glest_game/network/network_interface.h b/source/glest_game/network/network_interface.h index d724e1f5..e5e36816 100644 --- a/source/glest_game/network/network_interface.h +++ b/source/glest_game/network/network_interface.h @@ -82,6 +82,39 @@ public: }; +class MarkedCell { +protected: + Vec2i targetPos; + const Faction *faction; + int factionIndex; + string note; + +public: + MarkedCell() { + faction = NULL; + factionIndex = -1; + note = ""; + } + MarkedCell(Vec2i targetPos,const Faction *faction,string note) { + this->targetPos = targetPos; + this->faction = faction; + this->factionIndex = -1; + this->note = note; + } + MarkedCell(Vec2i targetPos,int factionIndex,string note) { + this->targetPos = targetPos; + this->faction = NULL; + this->factionIndex = factionIndex; + this->note = note; + } + + Vec2i getTargetPos() const { return targetPos; } + const Faction * getFaction() const { return faction; } + void setFaction(const Faction *faction) { this->faction = faction; } + int getFactionIndex() const { return factionIndex; } + string getNote() const { return note; } +}; + typedef int (*DisplayMessageFunction)(const char *msg, bool exit); class NetworkInterface { @@ -97,6 +130,7 @@ protected: std::vector chatTextList; NetworkMessagePing lastPingInfo; + std::vector markedCellList; static DisplayMessageFunction pCB_DisplayMessage; void DisplayErrorMessage(string sErr, bool closeSocket=true); @@ -148,6 +182,10 @@ public: void clearChatInfo(); void addChatInfo(const ChatMsgInfo &msg) { chatTextList.push_back(msg); } + std::vector getMarkedCellList(bool clearList); + void clearMarkedCellList(); + void addMarkedCell(const MarkedCell &msg) { markedCellList.push_back(msg); } + virtual bool getConnectHasHandshaked() const= 0; NetworkMessagePing getLastPingInfo() const { return lastPingInfo; } @@ -200,6 +238,8 @@ public: string targetLanguage)= 0; virtual void quitGame(bool userManuallyQuit)=0; + virtual void sendMarkCellMessage(Vec2i targetPos, int factionIndex, string note) = 0; + //misc virtual string getNetworkStatus() = 0; diff --git a/source/glest_game/network/network_message.cpp b/source/glest_game/network/network_message.cpp index 7733a9b8..c002ad23 100644 --- a/source/glest_game/network/network_message.cpp +++ b/source/glest_game/network/network_message.cpp @@ -979,4 +979,39 @@ void NetworkMessageLoadingStatus::send(Socket* socket) const NetworkMessage::send(socket, &data, sizeof(data)); } +// ===================================================== +// class NetworkMessageMarkCell +// ===================================================== + +NetworkMessageMarkCell::NetworkMessageMarkCell(Vec2i target, int factionIndex, const string &text) { + if(text.length() >= maxTextStringSize) { + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] WARNING / ERROR - text [%s] length = %d, max = %d\n",__FILE__,__FUNCTION__,__LINE__,text.c_str(),text.length(),maxTextStringSize); + } + + data.messageType = nmtMarkCell; + data.text = text; + data.targetX = target.x; + data.targetY = target.y; + data.factionIndex = factionIndex; +} + +NetworkMessageMarkCell * NetworkMessageMarkCell::getCopy() const { + NetworkMessageMarkCell *copy = new NetworkMessageMarkCell(); + copy->data = this->data; + return copy; +} + +bool NetworkMessageMarkCell::receive(Socket* socket){ + bool result = NetworkMessage::receive(socket, &data, sizeof(data), true); + data.text.nullTerminate(); + return result; +} + +void NetworkMessageMarkCell::send(Socket* socket) const{ + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] nmtMarkCell\n",__FILE__,__FUNCTION__,__LINE__); + + assert(data.messageType == nmtMarkCell); + 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 859c9f37..29884f1a 100644 --- a/source/glest_game/network/network_message.h +++ b/source/glest_game/network/network_message.h @@ -43,6 +43,7 @@ enum NetworkMessageType { nmtSwitchSetupRequest, nmtPlayerIndexMessage, nmtLoadingStatusMessage, + nmtMarkCell, nmtCount }; @@ -729,6 +730,44 @@ public: #pragma pack(pop) +// ===================================================== +// class NetworkMessageText +// +// Mark a Cell message nmtMarkCell +// ===================================================== + +#pragma pack(push, 1) +class NetworkMessageMarkCell: public NetworkMessage { +private: + static const int maxTextStringSize= 500; + +private: + struct Data{ + int8 messageType; + + int16 targetX; + int16 targetY; + int8 factionIndex; + NetworkString text; + }; + +private: + Data data; + +public: + NetworkMessageMarkCell(){} + NetworkMessageMarkCell(Vec2i target, int factionIndex, const string &text); + + string getText() const { return data.text.getString(); } + Vec2i getTarget() const { return Vec2i(data.targetX,data.targetY); } + int getFactionIndex() const { return data.factionIndex; } + + virtual bool receive(Socket* socket); + virtual void send(Socket* socket) const; + NetworkMessageMarkCell * getCopy() const; +}; +#pragma pack(pop) + }}//end namespace #endif diff --git a/source/glest_game/network/server_interface.cpp b/source/glest_game/network/server_interface.cpp index aca903c2..f753f315 100644 --- a/source/glest_game/network/server_interface.cpp +++ b/source/glest_game/network/server_interface.cpp @@ -1094,6 +1094,45 @@ void ServerInterface::dispatchPendingChatMessages(std::vector &errorMsg } } +void ServerInterface::dispatchPendingMarkCellMessages(std::vector &errorMsgList) { + for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) { + MutexSafeWrapper safeMutexSlot(slotAccessorMutexes[i],CODE_AT_LINE_X(i)); + ConnectionSlot* connectionSlot= slots[i]; + if(connectionSlot != NULL && + connectionSlot->getMarkedCellList(false).empty() == false) { + try { + std::vector chatText = connectionSlot->getMarkedCellList(true); + for(int chatIdx = 0; + exitServer == false && slots[i] != NULL && + chatIdx < chatText.size(); chatIdx++) { + connectionSlot= slots[i]; + if(connectionSlot != NULL) { + MarkedCell msg(chatText[chatIdx]); + this->addMarkedCell(msg); + + NetworkMessageMarkCell networkMessageMarkCell(msg.getTargetPos(),msg.getFactionIndex(),msg.getNote()); + broadcastMessage(&networkMessageMarkCell, connectionSlot->getPlayerIndex(),i); + + //if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] after broadcast nmtText chatText [%s] chatTeamIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,newChatText.c_str(),newChatTeamIndex); + } + } + + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] i = %d\n",__FILE__,__FUNCTION__,__LINE__,i); + // Its possible that the slot is disconnected here + // so check the original pointer again + if(slots[i] != NULL) { + slots[i]->clearMarkedCellList(); + } + } + catch(const exception &ex) { + SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what()); + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] error detected [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what()); + errorMsgList.push_back(ex.what()); + } + } + } +} + void ServerInterface::update() { Chrono chrono; if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start(); @@ -1166,6 +1205,8 @@ void ServerInterface::update() { dispatchPendingChatMessages(errorMsgList); if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__); + dispatchPendingMarkCellMessages(errorMsgList); + if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took %lld msecs\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); } else if(gameHasBeenInitiated == true && @@ -1332,6 +1373,41 @@ bool ServerInterface::shouldDiscardNetworkMessage(NetworkMessageType networkMess } break; + + case nmtMarkCell: + { + discard = true; + NetworkMessageMarkCell networkMessageMarkCell; + connectionSlot->receiveMessage(&networkMessageMarkCell); + + MarkedCell msg(networkMessageMarkCell.getTarget(), + networkMessageMarkCell.getFactionIndex(), + networkMessageMarkCell.getText().c_str()); + + this->addMarkedCell(msg); + +// string newChatText = msg.chatText.c_str(); +// //string newChatSender = msg.chatSender.c_str(); +// int newChatTeamIndex = msg.chatTeamIndex; +// int newChatPlayerIndex = msg.chatPlayerIndex; +// string newChatLanguage = msg.targetLanguage.c_str(); +// +// if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] #1 about to broadcast nmtText chatText [%s] chatTeamIndex = %d, newChatPlayerIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,newChatText.c_str(),newChatTeamIndex,newChatPlayerIndex); +// +// NetworkMessageText networkMessageText(newChatText.c_str(),newChatTeamIndex,newChatPlayerIndex,newChatLanguage); +// broadcastMessage(&networkMessageText, connectionSlot->getPlayerIndex()); + + NetworkMessageMarkCell networkMessageMarkCellBroadcast( + networkMessageMarkCell.getTarget(), + networkMessageMarkCell.getFactionIndex(), + networkMessageMarkCell.getText().c_str()); + broadcastMessage(&networkMessageMarkCellBroadcast, connectionSlot->getPlayerIndex()); + + //if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] after broadcast nmtMarkCell chatText [%s] chatTeamIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,newChatText.c_str(),newChatTeamIndex); + + } + break; + case nmtSynchNetworkGameData: { discard = true; @@ -1673,6 +1749,20 @@ void ServerInterface::sendTextMessage(const string& text, int teamIndex, bool ec if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__); } +void ServerInterface::sendMarkCellMessage(Vec2i targetPos, int factionIndex, string note) { + sendMarkCellMessage(targetPos, factionIndex, note, -1); +} + +void ServerInterface::sendMarkCellMessage(Vec2i targetPos, int factionIndex, string note, int lockedSlotIndex) { + //printf("Line: %d text [%s] echoLocal = %d\n",__LINE__,text.c_str(),echoLocal); + //assert(text.length() > 0); + + //if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] text [%s] teamIndex = %d, echoLocal = %d, lockedSlotIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,text.c_str(),teamIndex,echoLocal,lockedSlotIndex); + NetworkMessageMarkCell networkMessageMarkCell(targetPos,factionIndex, note); + broadcastMessage(&networkMessageMarkCell, -1, lockedSlotIndex); + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__); +} + void ServerInterface::quitGame(bool userManuallyQuit) { if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__); NetworkMessageQuit networkMessageQuit; diff --git a/source/glest_game/network/server_interface.h b/source/glest_game/network/server_interface.h index 83431915..9abc1a77 100644 --- a/source/glest_game/network/server_interface.h +++ b/source/glest_game/network/server_interface.h @@ -113,7 +113,12 @@ public: virtual void waitUntilReady(Checksum *checksum); virtual void sendTextMessage(const string & text, int teamIndex, bool echoLocal, string targetLanguage); void sendTextMessage(const string & text, int teamIndex, bool echoLocal, string targetLanguage, int lockedSlotIndex); + void queueTextMessage(const string & text, int teamIndex, bool echoLocal, string targetLanguage); + + virtual void sendMarkCellMessage(Vec2i targetPos, int factionIndex, string note); + void sendMarkCellMessage(Vec2i targetPos, int factionIndex, string note, int lockedSlotIndex); + virtual void quitGame(bool userManuallyQuit); virtual string getNetworkStatus(); ServerSocket *getServerSocket() @@ -224,6 +229,7 @@ protected: void checkForLaggingClients(std::map &mapSlotSignalledList, std::map &eventList, std::map &socketTriggeredList,std::vector &errorMsgList); void executeNetworkCommandsFromClients(); void dispatchPendingChatMessages(std::vector &errorMsgList); + void dispatchPendingMarkCellMessages(std::vector &errorMsgList); void shutdownMasterserverPublishThread(); };