diff --git a/apps/openmw-mp/Script/Functions/Worldstate.cpp b/apps/openmw-mp/Script/Functions/Worldstate.cpp index 1186ad4be..d963cbf4c 100644 --- a/apps/openmw-mp/Script/Functions/Worldstate.cpp +++ b/apps/openmw-mp/Script/Functions/Worldstate.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -299,8 +300,29 @@ void WorldstateFunctions::SendCellReset(unsigned short pid, bool sendToOtherPlay writeWorldstate.guid = player->guid; packet->setWorldstate(&writeWorldstate); - + packet->Send(sendToOtherPlayers); + + if (sendToOtherPlayers) + { + packet->Send(false); + } + + CellController * cellController = CellController::get(); + + for (ESM::Cell cell : writeWorldstate.cellsToReset) + { + if (sendToOtherPlayers) + { + TPlayers * players = Players::getPlayers(); + for (TPlayers::iterator iter = players->begin(); iter != players->end(); iter++) + { + cellController->getCell(&cell)->removePlayer((*iter).second, true); + } + } + else + cellController->getCell(&cell)->removePlayer(Players::getPlayer(pid), true); + } } diff --git a/apps/openmw-mp/Script/Functions/Worldstate.hpp b/apps/openmw-mp/Script/Functions/Worldstate.hpp index 23eb31dc5..1fe13bb94 100644 --- a/apps/openmw-mp/Script/Functions/Worldstate.hpp +++ b/apps/openmw-mp/Script/Functions/Worldstate.hpp @@ -57,7 +57,7 @@ \ {"AddCellToReset", WorldstateFunctions::AddCellToReset},\ {"ClearCellsToReset", WorldstateFunctions::ClearCellsToReset},\ - {"SendCellsToReset", WorldstateFunctions::SendCellReset},\ + {"SendCellReset", WorldstateFunctions::SendCellReset},\ \ {"ReadLastWorldstate", WorldstateFunctions::ReadLastWorldstate},\ {"CopyLastWorldstateToStore", WorldstateFunctions::CopyLastWorldstateToStore} diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 43b1d1af6..547ff2220 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -579,7 +579,17 @@ namespace MWBase Make it possible to check whether a cell is active */ - virtual bool isCellActive(MWWorld::CellStore* cell) = 0; + virtual bool isCellActive(ESM::Cell cell) = 0; + /* + End of tes3mp addition + */ + + /* + Start of tes3mp addition + + Make it possible to reload active cells (e.g. for CellReset) + */ + virtual void reloadCells(std::vector * cells) = 0; /* End of tes3mp addition */ diff --git a/apps/openmw/mwmp/CellController.cpp b/apps/openmw/mwmp/CellController.cpp index e2d07b084..64b96904d 100644 --- a/apps/openmw/mwmp/CellController.cpp +++ b/apps/openmw/mwmp/CellController.cpp @@ -35,7 +35,7 @@ void CellController::updateLocal(bool forceUpdate) { mwmp::Cell *mpCell = it->second; - if (!MWBase::Environment::get().getWorld()->isCellActive(mpCell->getCellStore())) + if (!MWBase::Environment::get().getWorld()->isCellActive(*(mpCell->getCellStore()->getCell()))) { mpCell->uninitializeLocalActors(); mpCell->uninitializeDedicatedActors(); @@ -312,11 +312,7 @@ bool CellController::isInitializedCell(const ESM::Cell& cell) bool CellController::isActiveWorldCell(const ESM::Cell& cell) { - MWWorld::CellStore *cellStore = getCellStore(cell); - - if (!cellStore) return false; - - return MWBase::Environment::get().getWorld()->isCellActive(cellStore); + return MWBase::Environment::get().getWorld()->isCellActive(cell); } Cell *CellController::getCell(const ESM::Cell& cell) diff --git a/apps/openmw/mwmp/processors/worldstate/ProcessorCellReset.hpp b/apps/openmw/mwmp/processors/worldstate/ProcessorCellReset.hpp index 1a24cb0e0..941ed6b30 100644 --- a/apps/openmw/mwmp/processors/worldstate/ProcessorCellReset.hpp +++ b/apps/openmw/mwmp/processors/worldstate/ProcessorCellReset.hpp @@ -2,6 +2,7 @@ #define OPENMW_PROCESSORCELLRESET_HPP #include "../WorldstateProcessor.hpp" +#include namespace mwmp { @@ -16,19 +17,20 @@ namespace mwmp virtual void Do(WorldstatePacket &packet, Worldstate &worldstate) { LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Received ID_CELL_RESET"); + CellController* cellController = Main::get().getCellController(); + MWBase::World * world = MWBase::Environment::get().getWorld(); + + world->reloadCells(&worldstate.cellsToReset); + + - for (ESM::Cell cell : worldstate.cellsToReset) + /*for (ESM::Cell cell : worldstate.cellsToReset) { - MWWorld::CellStore * cellStore = cellController->getCellStore(cell); - if (cellStore != nullptr) - { - LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Resetting cell %s!", cell.getDescription().c_str()); - cellStore->clear(); - } - else - LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Attempted to reset an uninitialized cell %s!", cell.getDescription().c_str()); + Main::get().getLocalPlayer()->storeCellState(cell, CellState::LOAD); } + Main::get().getLocalPlayer()->sendCellStates(); + Main::get().getLocalPlayer()->clearCellStates();*/ } }; } diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 5327a0898..76e1f9f85 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -605,6 +605,41 @@ namespace MWWorld End of tes3mp addition */ + /* + Start of tes3mp addition + + Make it possible to get mMovedHere in the CellStore from elsewhere in the code + */ + std::vector CellStore::getMovedHere() + { + std::vector hereVector; + for (CellStore::MovedRefTracker::iterator iter = mMovedHere.begin(); iter != mMovedHere.end(); ++iter) + { + hereVector.push_back(Ptr(iter->first, iter->second)); + } + return hereVector; + } + /* + End of tes3mp addition + */ + + /* + Start of tes3mp addition + + Make it possible to return all NPCs back to this cell from elsewhere in the code + */ + void CellStore::returnFromOtherCells() + { + for (CellStore::MovedRefTracker::iterator iter = mMovedToAnotherCell.begin(); iter != mMovedToAnotherCell.end(); ++iter) + { + LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Returning actor from %d, %d!", iter->second->getCell()->getGridX(), iter->second->getCell()->getGridY()); + iter->second->moveTo(iter->first, this); + } + } + /* + End of tes3mp addition + */ + float CellStore::getWaterLevel() const { if (isExterior()) @@ -1198,7 +1233,6 @@ namespace MWWorld mBooks.mList.clear(); mClothes.mList.clear(); mContainers.mList.clear(); - mCreatures.mList.clear(); mDoors.mList.clear(); mIngreds.mList.clear(); mCreatureLists.mList.clear(); @@ -1206,13 +1240,30 @@ namespace MWWorld mLights.mList.clear(); mLockpicks.mList.clear(); mMiscItems.mList.clear(); - mNpcs.mList.clear(); mProbes.mList.clear(); mRepairs.mList.clear(); mStatics.mList.clear(); mWeapons.mList.clear(); mBodyParts.mList.clear(); + mwmp::CellController * cellController = mwmp::Main::get().getCellController(); + + for (std::list>::iterator ref = mCreatures.mList.begin(); ref != mCreatures.mList.end(); ref++) + { + if (!cellController->isDedicatedActor(MWWorld::Ptr(&*ref, this))) + { + mCreatures.mList.erase(ref); + } + } + + for (std::list>::iterator ref = mNpcs.mList.begin(); ref != mNpcs.mList.end(); ref++) + { + if (!cellController->isDedicatedActor(MWWorld::Ptr(&*ref, this))) + { + mNpcs.mList.erase(ref); + } + } + mMovedHere.clear(); mMovedToAnotherCell.clear(); mMergedRefs.clear(); diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index 3975c698d..6e7d9d585 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -289,6 +289,26 @@ namespace MWWorld End of tes3mp addition */ + /* + Start of tes3mp addition + + Make it possible to get the mContainers in the CellStore from elsewhere in the code + */ + std::vector getMovedHere(); + /* + End of tes3mp addition + */ + + /* + Start of tes3mp addition + + Make it possible to get mMovedHere in the CellStore from elsewhere in the code + */ + void returnFromOtherCells(); + /* + End of tes3mp addition + */ + float getWaterLevel() const; void setWaterLevel (float level); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index c4ad67d53..286689991 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2691,9 +2691,106 @@ namespace MWWorld Make it possible to check whether a cell is active */ - bool World::isCellActive(MWWorld::CellStore* cell) + bool World::isCellActive(ESM::Cell cell) { - return mWorldScene->isCellActive(*cell); + MWWorld::Scene::CellStoreCollection activeCells = (*mWorldScene).getActiveCells(); + mwmp::CellController* cellController = mwmp::Main::get().getCellController(); + for (MWWorld::Scene::CellStoreCollection::iterator iter = activeCells.begin(); iter != activeCells.end(); iter++) + { + ESM::Cell iterCell = *(*iter)->getCell(); + if (cellController->isSameCell(iterCell, cell)) { + return true; + } + } + + return false; + } + /* + End of tes3mp addition + */ + + /* + */ + + /* + Start of tes3mp addition + + Make it possible to reload active cells (e.g. for CellReset) + */ + void World::reloadCells(std::vector * cells) + { + mwmp::CellController* cellController = mwmp::Main::get().getCellController(); + MWWorld::Scene::CellStoreCollection activeCells = (*mWorldScene).getActiveCells(); + + MWWorld::Scene::CellStoreCollection activeToReset; + + for (MWWorld::Scene::CellStoreCollection::iterator iter = activeCells.begin(); iter != activeCells.end(); iter++) + { + ESM::Cell iterCell = *(*iter)->getCell(); + for (ESM::Cell cell : *cells) + { + if (cellController->isSameCell(iterCell, cell)) + { + activeToReset.insert(*iter); + break; + } + } + } + + if (!activeToReset.empty()) + { + typedef std::pair returnPtr; + std::map moveBack; + for (MWWorld::Scene::CellStoreCollection::iterator iter = activeToReset.begin(); iter != activeToReset.end(); iter++) + { + ESM::Cell iterCell = *(*iter)->getCell(); + MWWorld::CellStore * cellStore = cellController->getCellStore(iterCell); + + cellStore->returnFromOtherCells(); + std::vector movedRefs = cellStore->getMovedHere(); + for (Ptr ref : movedRefs) + { + moveBack.insert(returnPtr(ref, cellStore)); + } + } + + for (MWWorld::Scene::CellStoreCollection::iterator iter = activeCells.begin(); iter != activeCells.end(); iter++) + { + ESM::Cell iterCell = *(*iter)->getCell(); + MWWorld::CellStore * cellStore = cellController->getCellStore(iterCell); + + mWorldScene->unloadCell(iter); + cellController->getCell(iterCell)->uninitializeLocalActors(); + cellController->getCell(iterCell)->uninitializeDedicatedActors(); + + if (activeToReset.count(*iter) > 0) + { + cellStore->clear(); + LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Resetting cell %s!", iterCell.getDescription().c_str()); + + } + + + } + + ESM::CellId pCellId = getPlayerPtr().getCell()->getCell()->getCellId(); + + changeToCell(pCellId, getPlayerPtr().getRefData().getPosition(), false, true); + + for (returnPtr ret : moveBack) + { + ret.first.getCell()->moveTo(ret.first, ret.second); + cellController->getCell(*ret.second->getCell())->initializeDedicatedActor(ret.first); + } + } + else + { + for (ESM::Cell cell : *cells) + { + MWWorld::CellStore * cellStore = cellController->getCellStore(cell); + cellStore->clear(); + } + } } /* End of tes3mp addition diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index f98b3473b..0ab306220 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -677,7 +677,17 @@ namespace MWWorld Make it possible to check whether a cell is active */ - bool isCellActive(MWWorld::CellStore* cell) override; + bool isCellActive(ESM::Cell cell) override; + /* + End of tes3mp addition + */ + + /* + Start of tes3mp addition + + Make it possible to reload active cells (e.g. for CellReset) + */ + void reloadCells(std::vector * cells) override; /* End of tes3mp addition */