diff --git a/apps/openmw-mp/GUI.cpp b/apps/openmw-mp/GUI.cpp index 5b1f3fad0..fd682378d 100644 --- a/apps/openmw-mp/GUI.cpp +++ b/apps/openmw-mp/GUI.cpp @@ -211,7 +211,6 @@ void QuickKeys::addQuickKey(const QuickKey &quickKey) setChanged(); } - QuickKey QuickKeys::getQuickKey(int id) const { return QuickKey(player->quickKeyChanges.quickKeys.at(id)); @@ -277,3 +276,103 @@ void QuickKey::setItemId(const std::string &itemId) { quickKey.itemId = itemId; } + +void MapTiles::Init(LuaState &lua) +{ + lua.getState()->new_usertype("MapTiles", + "addMapTile", &MapTiles::addMapTile, + "getMapTile", &MapTiles::getMapTile, + "setMapTile", &MapTiles::setMapTile, + "clear", &MapTiles::clear, + "size", &MapTiles::size + ); +} + +MapTiles::MapTiles(Player *player) : BaseMgr(player) +{ + +} + +void MapTiles::processUpdate() +{ + auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_MAP); + packet->setPlayer(player); + packet->Send(false); + clear(); +} + +void MapTiles::addMapTile(const MapTile &mapTile) +{ + player->mapChanges.mapTiles.push_back(mapTile.mapTile); + setChanged(); +} + +MapTile MapTiles::getMapTile(int id) const +{ + return MapTile(player->mapChanges.mapTiles.at(id)); +} + +void MapTiles::setMapTile(int id, const MapTile &mapTile) +{ + player->mapChanges.mapTiles.at(id) = mapTile.mapTile; + setChanged(); +} + +void MapTiles::clear() +{ + player->mapChanges.mapTiles.clear(); + setChanged(); +} + +size_t MapTiles::size() const +{ + return player->mapChanges.mapTiles.size(); +} + +void MapTile::Init(LuaState &lua) +{ + lua.getState()->new_usertype("MapTile", + "cellX", sol::property(&MapTile::getCellX, &MapTile::setCellX), + "cellY", sol::property(&MapTile::getCellY, &MapTile::setCellY), + "loadImageFile", &MapTile::loadImageFile, + "saveImageFile", &MapTile::saveImageFile + ); +} + +MapTile::MapTile(mwmp::MapTile &mapTile) : mapTile(mapTile) +{ + +} + +int MapTile::getCellX() const +{ + return mapTile.x; +} + +void MapTile::setCellX(int cellX) +{ + mapTile.x = cellX; +} + +int MapTile::getCellY() const +{ + return mapTile.y; +} + +void MapTile::setCellY(int cellY) +{ + mapTile.y = cellY; +} + +void MapTile::loadImageFile(const char* filePath) +{ + std::ifstream inputFile(filePath, std::ios::binary); + mapTile.imageData = std::vector(std::istreambuf_iterator(inputFile), std::istreambuf_iterator()); +} + +void MapTile::saveImageFile(const char* filePath) +{ + std::ofstream outputFile(filePath, std::ios::binary); + std::ostream_iterator outputIterator(outputFile); + std::copy(mapTile.imageData.begin(), mapTile.imageData.end(), outputIterator); +} diff --git a/apps/openmw-mp/GUI.hpp b/apps/openmw-mp/GUI.hpp index 9b1c9809b..a9146fdf3 100644 --- a/apps/openmw-mp/GUI.hpp +++ b/apps/openmw-mp/GUI.hpp @@ -84,3 +84,40 @@ public: private: void processUpdate() final; }; + +class MapTile +{ + friend class MapTiles; +public: + static void Init(LuaState &lua); +public: + explicit MapTile(mwmp::MapTile &mapTile); + + int getCellX() const; + void setCellX(int cellX); + + int getCellY() const; + void setCellY(int cellY); + + void loadImageFile(const char* filePath); + void saveImageFile(const char *filePath); + + mwmp::MapTile mapTile; +}; + +class MapTiles final: public BaseMgr +{ +public: + static void Init(LuaState &lua); +public: + explicit MapTiles(Player *player); + + void addMapTile(const MapTile &mapTile); + MapTile getMapTile(int id) const; + void setMapTile(int id, const MapTile &mapTile); + size_t size() const; + void clear(); + +private: + void processUpdate() final; +}; diff --git a/apps/openmw-mp/Player.cpp b/apps/openmw-mp/Player.cpp index c3b4b51b3..9c17df78b 100644 --- a/apps/openmw-mp/Player.cpp +++ b/apps/openmw-mp/Player.cpp @@ -92,6 +92,7 @@ void Player::Init(LuaState &lua) "getQuests", &Player::getQuests, "getSpells", &Player::getSpells, "getQuickKeys", &Player::getQuickKeys, + "getMapTiles", &Player::getMapTiles, "getWeatherMgr", &Player::getWeatherMgr, "getMark", &Player::getMark, @@ -100,9 +101,9 @@ void Player::Init(LuaState &lua) "getSelectedSpell", &Player::getSelectedSpell, "setSelectedSpell", &Player::setSelectedSpell, - "getCellState", &Player::getCellState, "cellStateSize", &Player::cellStateSize, - "addCellExplored", &Player::addCellExplored, + "getCellState", &Player::getCellState, + "setAuthority", &Player::setAuthority, "storedData", &Player::storedData, @@ -119,7 +120,7 @@ void Player::Init(LuaState &lua) Player::Player(RakNet::RakNetGUID guid) : BasePlayer(guid), NetActor(), changedMap(false), cClass(this), settings(this), books(this), gui(this), dialogue(this), factions(this), - quests(this), spells(this), quickKeys(this), weatherMgr(this) + quests(this), spells(this), quickKeys(this), mapTiles(this), weatherMgr(this) { basePlayer = this; netCreature = this; @@ -292,6 +293,7 @@ void Player::update() quests.update(); spells.update(); quickKeys.update(); + mapTiles.update(); weatherMgr.update(); resetUpdateFlags(); @@ -833,6 +835,11 @@ QuickKeys &Player::getQuickKeys() return quickKeys; } +MapTiles &Player::getMapTiles() +{ + return mapTiles; +} + WeatherMgr &Player::getWeatherMgr() { return weatherMgr; @@ -924,13 +931,6 @@ size_t Player::cellStateSize() const return cellStateChanges.cellStates.size(); } -void Player::addCellExplored(const std::string &cellDescription) -{ - auto cellExplored = Utils::getCellFromDescription(cellDescription); - mapChanges.cellsExplored.push_back(cellExplored); - changedMap = true; -} - CellState Player::getCellState(int i) { return CellState(cellStateChanges.cellStates.at(i)); diff --git a/apps/openmw-mp/Player.hpp b/apps/openmw-mp/Player.hpp index 03a17a3dd..0ecda3af8 100644 --- a/apps/openmw-mp/Player.hpp +++ b/apps/openmw-mp/Player.hpp @@ -186,9 +186,8 @@ public: std::string getSelectedSpell(); void setSelectedSpell(const std::string &newSelectedSpellId); - CellState getCellState(int i); size_t cellStateSize() const; - void addCellExplored(const std::string &cellDescription); + CellState getCellState(int i); CharClass &getCharClass(sol::this_state thisState); GameSettings &getSettings(); @@ -199,6 +198,7 @@ public: Quests &getQuests(); Spells &getSpells(); QuickKeys &getQuickKeys(); + MapTiles &getMapTiles(); WeatherMgr &getWeatherMgr(); void setAuthority(); @@ -221,6 +221,7 @@ private: Quests quests; Spells spells; QuickKeys quickKeys; + MapTiles mapTiles; WeatherMgr weatherMgr; sol::table storedData; sol::table customData; diff --git a/apps/openmw-mp/Script/LuaState.cpp b/apps/openmw-mp/Script/LuaState.cpp index 320d4c69d..8f3d7e116 100644 --- a/apps/openmw-mp/Script/LuaState.cpp +++ b/apps/openmw-mp/Script/LuaState.cpp @@ -178,6 +178,10 @@ LuaState::LuaState() mwmp::Networking::getPtr()->setPluginEnforcementState(state); }); + lua->set_function("doesFileExist", [](const char *filePath) { + return boost::filesystem::exists(filePath); + }); + lua->set_function("getCaseInsensitiveFilename", [](const char *folderPath, const char *filename) { if (!boost::filesystem::exists(folderPath)) return "invalid"; diff --git a/apps/openmw-mp/processors/player/ProcessorPlayerMap.hpp b/apps/openmw-mp/processors/player/ProcessorPlayerMap.hpp index dd989b34e..85103e8f0 100644 --- a/apps/openmw-mp/processors/player/ProcessorPlayerMap.hpp +++ b/apps/openmw-mp/processors/player/ProcessorPlayerMap.hpp @@ -17,9 +17,7 @@ namespace mwmp { DEBUG_PRINTF(strPacketID.c_str()); - // Not currently implemented - // - // To be dealt with later to save explored areas on local maps + Networking::get().getState().getEventCtrl().Call(player.get()); } }; } diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index 37e4d7050..6b731fbc4 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -213,9 +213,10 @@ namespace MWBase /* Start of tes3mp addition - Allow setting a cell as explored from elsewhere in the code + Allow the setting of the image data for a global map tile from elsewhere + in the code */ - virtual void setCellExplored(const MWWorld::CellStore* cell) = 0; + virtual void setGlobalMapImage(int cellX, int cellY, const std::vector& imageData) = 0; /* End of tes3mp addition */ diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index b37d2ce2e..1ad1b37e7 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -323,7 +323,7 @@ namespace MWBase Make it possible to set the physics framerate from elsewhere */ - virtual void World::setPhysicsFramerate(float physFramerate) = 0; + virtual void setPhysicsFramerate(float physFramerate) = 0; /* End of tes3mp addition */ diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index ff389c797..84bd1be19 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -941,6 +941,20 @@ namespace MWGui } } + /* + Start of tes3mp addition + + Allow the setting of the image data for a global map tile from elsewhere + in the code + */ + void MapWindow::setGlobalMapImage(int cellX, int cellY, const std::vector& imageData) + { + mGlobalMapRender->setImage(cellX, cellY, imageData); + } + /* + End of tes3mp addition + */ + void MapWindow::updateCustomMarkers() { LocalMapBase::updateCustomMarkers(); diff --git a/apps/openmw/mwgui/mapwindow.hpp b/apps/openmw/mwgui/mapwindow.hpp index bb5546174..b1360268c 100644 --- a/apps/openmw/mwgui/mapwindow.hpp +++ b/apps/openmw/mwgui/mapwindow.hpp @@ -266,6 +266,17 @@ namespace MWGui void setGlobalMapPlayerPosition (float worldX, float worldY); void setGlobalMapPlayerDir(const float x, const float y); + /* + Start of tes3mp addition + + Allow the setting of the image data for a global map tile from elsewhere + in the code + */ + void setGlobalMapImage(int cellX, int cellY, const std::vector& imageData); + /* + End of tes3mp addition + */ + void ensureGlobalMapLoaded(); virtual void onOpen(); diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 1e7edb0ae..a36634542 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1005,11 +1005,12 @@ namespace MWGui /* Start of tes3mp addition - Allow setting a cell as explored from elsewhere in the code + Allow the setting of the image data for a global map tile from elsewhere + in the code */ - void WindowManager::setCellExplored(const MWWorld::CellStore* cell) + void WindowManager::setGlobalMapImage(int cellX, int cellY, const std::vector& imageData) { - mMap->cellExplored(cell->getCell()->getGridX(), cell->getCell()->getGridY()); + mMap->setGlobalMapImage(cellX, cellY, imageData); } /* End of tes3mp addition diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 60d03a7d5..c153438e5 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -246,9 +246,10 @@ namespace MWGui /* Start of tes3mp addition - Allow setting a cell as explored from elsewhere in the code + Allow the setting of the image data for a global map tile from elsewhere + in the code */ - virtual void setCellExplored(const MWWorld::CellStore* cell); + virtual void setGlobalMapImage(int cellX, int cellY, const std::vector& imageData); /* End of tes3mp addition */ diff --git a/apps/openmw/mwmp/LocalPlayer.cpp b/apps/openmw/mwmp/LocalPlayer.cpp index 70bf66034..4fe517308 100644 --- a/apps/openmw/mwmp/LocalPlayer.cpp +++ b/apps/openmw/mwmp/LocalPlayer.cpp @@ -1119,7 +1119,7 @@ void LocalPlayer::setEquipment() else { // Don't try to equip an item that is already equipped - if (!ptrInventory.getSlot(slot).isEqual(it)) + if (ptrInventory.getSlot(slot) != it) ptrInventory.equip(slot, it, ptrPlayer); } } @@ -1299,12 +1299,17 @@ void LocalPlayer::setBooks() void LocalPlayer::setMapExplored() { - for (const auto &cellExplored : mapChanges.cellsExplored) + MWWorld::Ptr ptrPlayer = getPlayerPtr(); + MWMechanics::NpcStats &ptrNpcStats = ptrPlayer.getClass().getNpcStats(ptrPlayer); + + for (const auto &mapTile : mapChanges.mapTiles) { - MWWorld::CellStore *ptrCellStore = Main::get().getCellController()->getCellStore(cellExplored); + const MWWorld::CellStore *cellStore = MWBase::Environment::get().getWorld()->getExterior(mapTile.x, mapTile.y); - if (ptrCellStore) - MWBase::Environment::get().getWindowManager()->setCellExplored(ptrCellStore); + if (!cellStore->getCell()->mName.empty()) + MWBase::Environment::get().getWindowManager()->addVisitedLocation(cellStore->getCell()->mName, mapTile.x, mapTile.y); + + MWBase::Environment::get().getWindowManager()->setGlobalMapImage(mapTile.x, mapTile.y, mapTile.imageData); } } @@ -1651,6 +1656,23 @@ void LocalPlayer::sendSelectedSpell(const std::string& newSelectedSpellId) getNetworking()->getPlayerPacket(ID_PLAYER_MISCELLANEOUS)->Send(); } +void LocalPlayer::sendMapExplored(int x, int y, const std::vector& imageData) +{ + mapChanges.mapTiles.clear(); + + mwmp::MapTile mapTile; + mapTile.x = x; + mapTile.y = y; + mapTile.imageData = imageData; + + LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Sending ID_PLAYER_MAP with x: %i, y: %i", x, y); + + mapChanges.mapTiles.push_back(mapTile); + + getNetworking()->getPlayerPacket(ID_PLAYER_MAP)->setPlayer(this); + getNetworking()->getPlayerPacket(ID_PLAYER_MAP)->Send(); +} + void LocalPlayer::clearCellStates() { cellStateChanges.cellStates.clear(); diff --git a/apps/openmw/mwmp/LocalPlayer.hpp b/apps/openmw/mwmp/LocalPlayer.hpp index 868f07644..b916da73d 100644 --- a/apps/openmw/mwmp/LocalPlayer.hpp +++ b/apps/openmw/mwmp/LocalPlayer.hpp @@ -64,10 +64,10 @@ namespace mwmp void setFactions(); void setKills(); void setBooks(); - void setMapExplored(); void setShapeshift(); void setMarkLocation(); void setSelectedSpell(); + void setMapExplored(); void sendClass(); void sendInventory(); @@ -90,6 +90,7 @@ namespace mwmp void sendWerewolfState(bool isWerewolf); void sendMarkLocation(const ESM::Cell& newMarkCell, const ESM::Position& newMarkPosition); void sendSelectedSpell(const std::string& newSelectedSpellId); + void sendMapExplored(int x, int y, const std::vector& imageData); void clearCellStates(); void clearCurrentContainer(); diff --git a/apps/openmw/mwrender/globalmap.cpp b/apps/openmw/mwrender/globalmap.cpp index 24f6de6ce..52a878eb0 100644 --- a/apps/openmw/mwrender/globalmap.cpp +++ b/apps/openmw/mwrender/globalmap.cpp @@ -19,6 +19,18 @@ #include +/* + Start of tes3mp addition + + Include additional headers for multiplayer purposes +*/ +#include +#include "../mwmp/Main.hpp" +#include "../mwmp/LocalPlayer.hpp" +/* + End of tes3mp addition +*/ + #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -96,6 +108,17 @@ namespace namespace MWRender { + /* + Start of tes3mp addition + + Use maps to track which global map coordinates belong to which cell coordinates + without having to significantly change other methods + */ + std::map originToCellX; + std::map originToCellY; + /* + End of tes3mp addition + */ class CreateMapWorkItem : public SceneUtil::WorkItem { @@ -382,6 +405,17 @@ namespace MWRender if (cellX > mMaxX || cellX < mMinX || cellY > mMaxY || cellY < mMinY) return; + /* + Start of tes3mp addition + + Track the cell coordinates corresponding to these map image coordinates + */ + originToCellX[originX] = cellX; + originToCellY[originY - mCellSize] = cellY; + /* + End of tes3mp addition + */ + requestOverlayTextureUpdate(originX, mHeight - originY, mCellSize, mCellSize, localMapTexture, false, true); } @@ -598,6 +632,40 @@ namespace MWRender ensureLoaded(); mOverlayImage->copySubImage(imageDest.mX, imageDest.mY, 0, imageDest.mImage); + /* + Start of tes3mp addition + + Send an ID_PLAYER_MAP packet with this map tile to the server + */ + 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)); + + 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; + } + + std::ostringstream ostream; + + 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::string stringData = ostream.str(); + std::vector vectorData = std::vector(stringData.begin(), stringData.end()); + + mwmp::Main::get().getLocalPlayer()->sendMapExplored(originToCellX.at(imageDest.mX), originToCellY.at(imageDest.mY), vectorData); + } + /* + End of tes3mp addition + */ + it = mPendingImageDest.erase(it); } } @@ -607,4 +675,50 @@ namespace MWRender cam->removeChildren(0, cam->getNumChildren()); mRoot->removeChild(cam); } + + /* + Start of tes3mp addition + + Allow the setting of the image data for a global map tile from elsewhere + in the code + */ + void GlobalMap::setImage(int cellX, int cellY, const std::vector& imageData) + { + Files::IMemStream istream(&imageData[0], imageData.size()); + + osgDB::ReaderWriter* reader = osgDB::Registry::instance()->getReaderWriterForExtension("png"); + if (!reader) + { + std::cerr << "Error: Failed to read map tile image data, no png readerwriter found" << std::endl; + return; + } + osgDB::ReaderWriter::ReadResult result = reader->readImage(istream); + + if (!result.success()) + { + std::cerr << "Error: Can't read map tile image: " << result.message() << " code " << result.status() << std::endl; + return; + } + + osg::ref_ptr image = result.getImage(); + + int posX = (cellX - mMinX) * mCellSize; + int posY = (cellY - mMinY + 1) * mCellSize; + + if (cellX > mMaxX || cellX < mMinX || cellY > mMaxY || cellY < mMinY) + return; + + osg::ref_ptr texture(new osg::Texture2D); + texture->setImage(image); + texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); + texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); + texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); + texture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); + texture->setResizeNonPowerOfTwoHint(false); + + requestOverlayTextureUpdate(posX, mHeight - posY, mCellSize, mCellSize, texture, true, false); + } + /* + End of tes3mp addition + */ } diff --git a/apps/openmw/mwrender/globalmap.hpp b/apps/openmw/mwrender/globalmap.hpp index f19f4a91f..494bf1a3d 100644 --- a/apps/openmw/mwrender/globalmap.hpp +++ b/apps/openmw/mwrender/globalmap.hpp @@ -60,6 +60,17 @@ namespace MWRender void removeCamera(osg::Camera* cam); + /* + Start of tes3mp addition + + Allow the setting of the image data for a global map tile from elsewhere + in the code + */ + void setImage(int cellX, int cellY, const std::vector& imageData); + /* + End of tes3mp addition + */ + /** * Mark a camera for cleanup in the next update. For internal use only. */ diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 6b7c373bc..a8deea784 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -422,7 +422,7 @@ namespace MWWorld Make it possible to set the physics framerate from elsewhere */ - void World::setPhysicsFramerate(float physFramerate); + void setPhysicsFramerate(float physFramerate); /* End of tes3mp addition */ diff --git a/components/openmw-mp/Base/BasePlayer.hpp b/components/openmw-mp/Base/BasePlayer.hpp index 2f5ada423..4e407a317 100644 --- a/components/openmw-mp/Base/BasePlayer.hpp +++ b/components/openmw-mp/Base/BasePlayer.hpp @@ -127,6 +127,13 @@ namespace mwmp Type type; }; + struct MapTile + { + int x; + int y; + std::vector imageData; + }; + struct JournalChanges { std::vector journalItems; @@ -154,7 +161,7 @@ namespace mwmp struct MapChanges { - std::vector cellsExplored; + std::vector mapTiles; }; struct SpellbookChanges diff --git a/components/openmw-mp/Packets/Player/PacketPlayerMap.cpp b/components/openmw-mp/Packets/Player/PacketPlayerMap.cpp index d2850e366..a0604895b 100644 --- a/components/openmw-mp/Packets/Player/PacketPlayerMap.cpp +++ b/components/openmw-mp/Packets/Player/PacketPlayerMap.cpp @@ -13,22 +13,40 @@ void PacketPlayerMap::Packet(RakNet::BitStream *bs, bool send) { PlayerPacket::Packet(bs, send); - uint32_t count; + uint32_t changesCount; if (send) - count = static_cast(player->mapChanges.cellsExplored.size()); + changesCount = static_cast(player->mapChanges.mapTiles.size()); - RW(count, send); + RW(changesCount, send); if (!send) { - player->mapChanges.cellsExplored.clear(); - player->mapChanges.cellsExplored.resize(count); + player->mapChanges.mapTiles.clear(); + player->mapChanges.mapTiles.resize(changesCount); } - for (auto &&cellExplored : player->mapChanges.cellsExplored) + for (auto &&mapTile : player->mapChanges.mapTiles) { - RW(cellExplored.mData, send, true); - RW(cellExplored.mName, send, true); + RW(mapTile.x, send); + RW(mapTile.y, send); + + uint32_t imageDataCount; + + if (send) + imageDataCount = static_cast(mapTile.imageData.size()); + + RW(imageDataCount, send); + + if (!send) + { + mapTile.imageData.clear(); + mapTile.imageData.resize(imageDataCount); + } + + for (auto &&imageChar : mapTile.imageData) + { + RW(imageChar, send); + } } }