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(); };