From 9888316d8eff0c8cdb9959ee32e75708781e55c3 Mon Sep 17 00:00:00 2001 From: David Cernat Date: Thu, 21 Jun 2018 23:26:24 +0300 Subject: [PATCH 1/4] [Documentation] Update credits --- tes3mp-credits.md | 1 + 1 file changed, 1 insertion(+) diff --git a/tes3mp-credits.md b/tes3mp-credits.md index 5660591e1..6811a9bc1 100644 --- a/tes3mp-credits.md +++ b/tes3mp-credits.md @@ -49,6 +49,7 @@ Special thanks (in alphabetical order) Camul David Wery DestinedToDie + Donovan Ando Gluka Goodevil greetasdf From 5bb2ba1e9e42d39c859c833566974be55f18bd8f Mon Sep 17 00:00:00 2001 From: David Cernat Date: Sat, 23 Jun 2018 02:33:34 +0300 Subject: [PATCH 2/4] [General] Limit maximum imageData size in WorldMap packets --- apps/openmw-mp/Script/Functions/Worldstate.cpp | 11 ++++++++++- components/openmw-mp/Base/BaseWorldstate.hpp | 2 ++ .../Packets/Worldstate/PacketWorldMap.cpp | 17 +++++++++++++---- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/apps/openmw-mp/Script/Functions/Worldstate.cpp b/apps/openmw-mp/Script/Functions/Worldstate.cpp index 51bcb75b9..825dff1f2 100644 --- a/apps/openmw-mp/Script/Functions/Worldstate.cpp +++ b/apps/openmw-mp/Script/Functions/Worldstate.cpp @@ -59,7 +59,16 @@ void WorldstateFunctions::LoadMapTileImageFile(int cellX, int cellY, const char* std::ifstream inputFile(filePath, std::ios::binary); mapTile.imageData = std::vector(std::istreambuf_iterator(inputFile), std::istreambuf_iterator()); - writeWorldstate.mapChanges.mapTiles.push_back(mapTile); + if (mapTile.imageData.size() > mwmp::maxImageDataSize) + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Error loading image file for map tile: " + "%s has a size of %i, which is over the maximum allowed of %i!", + filePath, mapTile.imageData.size(), mwmp::maxImageDataSize); + } + else + { + writeWorldstate.mapChanges.mapTiles.push_back(mapTile); + } } void WorldstateFunctions::SetHour(double hour) noexcept diff --git a/components/openmw-mp/Base/BaseWorldstate.hpp b/components/openmw-mp/Base/BaseWorldstate.hpp index b4d56d867..0d2d3adcb 100644 --- a/components/openmw-mp/Base/BaseWorldstate.hpp +++ b/components/openmw-mp/Base/BaseWorldstate.hpp @@ -9,6 +9,8 @@ namespace mwmp { + static const int maxImageDataSize = 1400; + struct MapTile { int x; diff --git a/components/openmw-mp/Packets/Worldstate/PacketWorldMap.cpp b/components/openmw-mp/Packets/Worldstate/PacketWorldMap.cpp index 36b5c4303..43b72bb64 100644 --- a/components/openmw-mp/Packets/Worldstate/PacketWorldMap.cpp +++ b/components/openmw-mp/Packets/Worldstate/PacketWorldMap.cpp @@ -1,4 +1,5 @@ #include +#include #include "PacketWorldMap.hpp" using namespace std; @@ -31,17 +32,25 @@ void PacketWorldMap::Packet(RakNet::BitStream *bs, bool send) RW(mapTile.x, send); RW(mapTile.y, send); - uint32_t imageDataCount; + uint32_t imageDataSize; if (send) - imageDataCount = static_cast(mapTile.imageData.size()); + imageDataSize = static_cast(mapTile.imageData.size()); - RW(imageDataCount, send); + RW(imageDataSize, send); + + if (imageDataSize > mwmp::maxImageDataSize) + { + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Processed invalid ID_WORLD_MAP packet where tile %i, %i had an imageDataSize of %i", + mapTile.x, mapTile.y, imageDataSize); + LOG_APPEND(Log::LOG_ERROR, "- The packet was ignored after that point"); + return; + } if (!send) { mapTile.imageData.clear(); - mapTile.imageData.resize(imageDataCount); + mapTile.imageData.resize(imageDataSize); } for (auto &&imageChar : mapTile.imageData) From d53bd054248e1734bbf3d76e27a6d65fde24c166 Mon Sep 17 00:00:00 2001 From: David Cernat Date: Sat, 23 Jun 2018 14:37:47 +0300 Subject: [PATCH 3/4] [General] Use slightly larger maximum imageData size in WorldMap packets --- components/openmw-mp/Base/BaseWorldstate.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/openmw-mp/Base/BaseWorldstate.hpp b/components/openmw-mp/Base/BaseWorldstate.hpp index 0d2d3adcb..12839fbc2 100644 --- a/components/openmw-mp/Base/BaseWorldstate.hpp +++ b/components/openmw-mp/Base/BaseWorldstate.hpp @@ -9,7 +9,7 @@ namespace mwmp { - static const int maxImageDataSize = 1400; + static const int maxImageDataSize = 1800; struct MapTile { From deda6ec071067e57439d30eacfab675b8fe1e2a6 Mon Sep 17 00:00:00 2001 From: David Cernat Date: Mon, 25 Jun 2018 02:34:11 +0300 Subject: [PATCH 4/4] [Client] Don't send WorldMap packets for already explored map tiles --- apps/openmw/mwmp/Worldstate.cpp | 33 +++++++++++++++++++--- apps/openmw/mwmp/Worldstate.hpp | 9 +++++- apps/openmw/mwrender/globalmap.cpp | 44 ++++++++++++++++++------------ 3 files changed, 64 insertions(+), 22 deletions(-) diff --git a/apps/openmw/mwmp/Worldstate.cpp b/apps/openmw/mwmp/Worldstate.cpp index 6177c9dac..8b08a810b 100644 --- a/apps/openmw/mwmp/Worldstate.cpp +++ b/apps/openmw/mwmp/Worldstate.cpp @@ -31,21 +31,43 @@ Networking *Worldstate::getNetworking() return mwmp::Main::get().getNetworking(); } -void Worldstate::sendMapExplored(int x, int y, const std::vector& imageData) +bool Worldstate::containsExploredMapTile(int cellX, int cellY) +{ + for (const auto &mapTile : exploredMapTiles) + { + if (mapTile.x == cellX && mapTile.y == cellY) + return true; + } + + return false; +} + +void Worldstate::markExploredMapTile(int cellX, int cellY) +{ + mwmp::MapTile exploredTile; + exploredTile.x = cellX; + exploredTile.y = cellY; + exploredMapTiles.push_back(exploredTile); +} + +void Worldstate::sendMapExplored(int cellX, int cellY, const std::vector& imageData) { mapChanges.mapTiles.clear(); mwmp::MapTile mapTile; - mapTile.x = x; - mapTile.y = y; + mapTile.x = cellX; + mapTile.y = cellY; mapTile.imageData = imageData; - LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Sending ID_PLAYER_MAP with x: %i, y: %i", x, y); + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Sending ID_PLAYER_MAP with x: %i, y: %i", cellX, cellY); mapChanges.mapTiles.push_back(mapTile); getNetworking()->getWorldstatePacket(ID_WORLD_MAP)->setWorldstate(this); getNetworking()->getWorldstatePacket(ID_WORLD_MAP)->Send(); + + // Keep this tile marked as explored so we don't send any more packets for it + markExploredMapTile(mapTile.x, mapTile.y); } void Worldstate::setMapExplored() @@ -58,5 +80,8 @@ void Worldstate::setMapExplored() MWBase::Environment::get().getWindowManager()->addVisitedLocation(cellStore->getCell()->mName, mapTile.x, mapTile.y); MWBase::Environment::get().getWindowManager()->setGlobalMapImage(mapTile.x, mapTile.y, mapTile.imageData); + + // Keep this tile marked as explored so we don't send any more packets for it + markExploredMapTile(mapTile.x, mapTile.y); } } diff --git a/apps/openmw/mwmp/Worldstate.hpp b/apps/openmw/mwmp/Worldstate.hpp index df44372c1..e1f7a0d0d 100644 --- a/apps/openmw/mwmp/Worldstate.hpp +++ b/apps/openmw/mwmp/Worldstate.hpp @@ -13,11 +13,18 @@ namespace mwmp Worldstate(); virtual ~Worldstate(); + bool containsExploredMapTile(int cellX, int cellY); + + void markExploredMapTile(int cellX, int cellY); + void setMapExplored(); - void sendMapExplored(int x, int y, const std::vector& imageData); + void sendMapExplored(int cellX, int cellY, const std::vector& imageData); private: + + std::vector exploredMapTiles; + Networking *getNetworking(); }; diff --git a/apps/openmw/mwrender/globalmap.cpp b/apps/openmw/mwrender/globalmap.cpp index 218ef7704..7f088b94e 100644 --- a/apps/openmw/mwrender/globalmap.cpp +++ b/apps/openmw/mwrender/globalmap.cpp @@ -636,32 +636,42 @@ namespace MWRender /* Start of tes3mp addition - Send an ID_PLAYER_MAP packet with this map tile to the server + Send an ID_PLAYER_MAP packet with this map tile to the server, but only if: + 1) We have recorded the exterior cell corresponding to this tile's coordinates + 2) The tile has not previously been marked as explored in this client's mwmp::Worldstate */ if (originToCellX.count(imageDest.mX) > 0 && originToCellY.count(imageDest.mY) > 0) { - LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "New global map tile corresponds to cell %i, %i", originToCellX.at(imageDest.mX), originToCellY.at(imageDest.mY)); + int cellX = originToCellX.at(imageDest.mX); + int cellY = originToCellY.at(imageDest.mY); - osgDB::ReaderWriter* readerwriter = osgDB::Registry::instance()->getReaderWriterForExtension("png"); - if (!readerwriter) + mwmp::Worldstate *worldstate = mwmp::Main::get().getNetworking()->getWorldstate(); + + if (!worldstate->containsExploredMapTile(cellX, cellY)) { - std::cerr << "Error: Can't write temporary map image, no '" << "png" << "' readerwriter found" << std::endl; - return; - } + LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "New global map tile corresponds to cell %i, %i", originToCellX.at(imageDest.mX), originToCellY.at(imageDest.mY)); - std::ostringstream ostream; + osgDB::ReaderWriter* readerwriter = osgDB::Registry::instance()->getReaderWriterForExtension("png"); + if (!readerwriter) + { + std::cerr << "Error: Can't write temporary map image, no '" << "png" << "' readerwriter found" << std::endl; + return; + } - osgDB::ReaderWriter::WriteResult result = readerwriter->writeImage(*imageDest.mImage, ostream); - - if (!result.success()) - { - std::cerr << "Error: Can't write temporary map image: " << result.message() << " code " << result.status() << std::endl; - } + std::ostringstream ostream; - std::string stringData = ostream.str(); - std::vector vectorData = std::vector(stringData.begin(), stringData.end()); + osgDB::ReaderWriter::WriteResult result = readerwriter->writeImage(*imageDest.mImage, ostream); - mwmp::Main::get().getNetworking()->getWorldstate()->sendMapExplored(originToCellX.at(imageDest.mX), originToCellY.at(imageDest.mY), vectorData); + if (!result.success()) + { + std::cerr << "Error: Can't write temporary map image: " << result.message() << " code " << result.status() << std::endl; + } + + std::string stringData = ostream.str(); + std::vector vectorData = std::vector(stringData.begin(), stringData.end()); + + worldstate->sendMapExplored(cellX, cellY, vectorData); + } } /* End of tes3mp addition