mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-03-06 01:49:41 +00:00
[Client] Implement stable cell resets
This commit is contained in:
parent
741553dc00
commit
89da1f39fb
12 changed files with 191 additions and 2 deletions
|
@ -587,6 +587,16 @@ namespace MWBase
|
|||
End of tes3mp addition
|
||||
*/
|
||||
|
||||
/*
|
||||
Start of tes3mp addition
|
||||
|
||||
Make it possible to unload all active cells from elsewhere
|
||||
*/
|
||||
virtual void unloadActiveCells() = 0;
|
||||
/*
|
||||
End of tes3mp addition
|
||||
*/
|
||||
|
||||
/*
|
||||
Start of tes3mp addition
|
||||
|
||||
|
|
|
@ -107,7 +107,7 @@ void CellController::uninitializeCell(const ESM::Cell& cell)
|
|||
{
|
||||
std::string mapIndex = cell.getDescription();
|
||||
|
||||
// If this key doesn't exist, create it
|
||||
// If this key exists, erase the key-value pair from the map
|
||||
if (cellsInitialized.count(mapIndex) > 0)
|
||||
{
|
||||
mwmp::Cell* mpCell = cellsInitialized.at(mapIndex);
|
||||
|
@ -118,6 +118,22 @@ void CellController::uninitializeCell(const ESM::Cell& cell)
|
|||
}
|
||||
}
|
||||
|
||||
void CellController::uninitializeCells()
|
||||
{
|
||||
if (cellsInitialized.size() > 0)
|
||||
{
|
||||
for (auto it = cellsInitialized.cbegin(); it != cellsInitialized.cend(); it++)
|
||||
{
|
||||
mwmp::Cell* mpCell = it->second;
|
||||
mpCell->uninitializeLocalActors();
|
||||
mpCell->uninitializeDedicatedActors();
|
||||
delete it->second;
|
||||
}
|
||||
|
||||
cellsInitialized.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void CellController::readPositions(ActorList& actorList)
|
||||
{
|
||||
std::string mapIndex = actorList.cell.getDescription();
|
||||
|
|
|
@ -21,6 +21,7 @@ namespace mwmp
|
|||
|
||||
void initializeCell(const ESM::Cell& cell);
|
||||
void uninitializeCell(const ESM::Cell& cell);
|
||||
void uninitializeCells();
|
||||
|
||||
void readPositions(mwmp::ActorList& actorList);
|
||||
void readAnimFlags(mwmp::ActorList& actorList);
|
||||
|
|
|
@ -81,6 +81,24 @@ DedicatedPlayer *PlayerList::getPlayer(const MWWorld::Ptr &ptr)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<RakNet::RakNetGUID> PlayerList::getPlayersInCell(const ESM::Cell& cell)
|
||||
{
|
||||
std::vector<RakNet::RakNetGUID> playersInCell;
|
||||
|
||||
for (auto& playerEntry : playerList)
|
||||
{
|
||||
if (playerEntry.first != RakNet::UNASSIGNED_CRABNET_GUID)
|
||||
{
|
||||
if (Main::get().getCellController()->isSameCell(cell, playerEntry.second->cell))
|
||||
{
|
||||
playersInCell.push_back(playerEntry.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return playersInCell;
|
||||
}
|
||||
|
||||
bool PlayerList::isDedicatedPlayer(const MWWorld::Ptr &ptr)
|
||||
{
|
||||
if (ptr.mRef == nullptr)
|
||||
|
|
|
@ -34,6 +34,7 @@ namespace mwmp
|
|||
|
||||
static DedicatedPlayer *getPlayer(RakNet::RakNetGUID guid);
|
||||
static DedicatedPlayer *getPlayer(const MWWorld::Ptr &ptr);
|
||||
static std::vector<RakNet::RakNetGUID> getPlayersInCell(const ESM::Cell& cell);
|
||||
|
||||
static bool isDedicatedPlayer(const MWWorld::Ptr &ptr);
|
||||
|
||||
|
|
|
@ -12,7 +12,10 @@
|
|||
#include "Worldstate.hpp"
|
||||
#include "Main.hpp"
|
||||
#include "Networking.hpp"
|
||||
#include "PlayerList.hpp"
|
||||
#include "DedicatedPlayer.hpp"
|
||||
#include "RecordHelper.hpp"
|
||||
#include "CellController.hpp"
|
||||
|
||||
using namespace mwmp;
|
||||
using namespace std;
|
||||
|
@ -442,6 +445,64 @@ void Worldstate::setWeather()
|
|||
weather.queuedWeather, weather.transitionFactor, forceWeather);
|
||||
}
|
||||
|
||||
void Worldstate::resetCells(std::vector<ESM::Cell>* cells)
|
||||
{
|
||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||
|
||||
bool haveUnloadedActiveCells = false;
|
||||
ESM::Cell playerCell = *world->getPlayerPtr().getCell()->getCell();
|
||||
ESM::Position playerPos = world->getPlayerPtr().getRefData().getPosition();
|
||||
std::vector<RakNet::RakNetGUID> playersInCell;
|
||||
|
||||
for (auto cell : *cells)
|
||||
{
|
||||
if (!haveUnloadedActiveCells)
|
||||
{
|
||||
if (world->isCellActive(cell))
|
||||
{
|
||||
playersInCell = mwmp::PlayerList::getPlayersInCell(cell);
|
||||
|
||||
// If there are any DedicatedPlayers in this cell, also move them to the temporary holding interior cell
|
||||
if (!playersInCell.empty())
|
||||
{
|
||||
for (RakNet::RakNetGUID otherGuid : playersInCell)
|
||||
{
|
||||
DedicatedPlayer* dedicatedPlayer = mwmp::PlayerList::getPlayer(otherGuid);
|
||||
dedicatedPlayer->cell = *world->getInterior(RecordHelper::getPlaceholderInteriorCellName())->getCell();
|
||||
dedicatedPlayer->setCell();
|
||||
}
|
||||
}
|
||||
|
||||
// Change to temporary holding interior cell
|
||||
world->changeToInteriorCell(RecordHelper::getPlaceholderInteriorCellName(), playerPos, true, true);
|
||||
|
||||
mwmp::Main::get().getCellController()->uninitializeCells();
|
||||
world->unloadActiveCells();
|
||||
|
||||
haveUnloadedActiveCells = true;
|
||||
}
|
||||
}
|
||||
|
||||
world->clearCellStore(cell);
|
||||
|
||||
for (RakNet::RakNetGUID otherGuid : playersInCell)
|
||||
{
|
||||
DedicatedPlayer* dedicatedPlayer = mwmp::PlayerList::getPlayer(otherGuid);
|
||||
dedicatedPlayer->cell = cell;
|
||||
dedicatedPlayer->setCell();
|
||||
}
|
||||
}
|
||||
|
||||
// Move the player from their temporary holding cell to their previous cell
|
||||
if (haveUnloadedActiveCells)
|
||||
{
|
||||
if (playerCell.isExterior())
|
||||
world->changeToExteriorCell(playerPos, true, true);
|
||||
else
|
||||
world->changeToInteriorCell(playerCell.mName, playerPos, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
void Worldstate::sendClientGlobal(std::string varName, int value, mwmp::VARIABLE_TYPE variableType)
|
||||
{
|
||||
clientGlobals.clear();
|
||||
|
|
|
@ -23,6 +23,8 @@ namespace mwmp
|
|||
void setMapExplored();
|
||||
void setWeather();
|
||||
|
||||
void resetCells(std::vector<ESM::Cell>* cells);
|
||||
|
||||
void sendClientGlobal(std::string varName, int value, mwmp::VARIABLE_TYPE variableType);
|
||||
void sendClientGlobal(std::string varName, float value);
|
||||
void sendMapExplored(int cellX, int cellY, const std::vector<char>& imageData);
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace mwmp
|
|||
CellController* cellController = Main::get().getCellController();
|
||||
MWBase::World * world = MWBase::Environment::get().getWorld();
|
||||
|
||||
//world->reloadCells(&worldstate.cellsToReset);
|
||||
mwmp::Main::get().getNetworking()->getWorldstate()->resetCells(&worldstate.cellsToReset);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -340,6 +340,37 @@ namespace MWWorld
|
|||
return MWWorld::Ptr(object.getBase(), cellToMoveTo);
|
||||
}
|
||||
|
||||
/*
|
||||
Start of tes3mp addition
|
||||
|
||||
Make it possible to clear the moves to other cells tracked for objects, allowing for
|
||||
on-the-fly cell resets that don't cause crashes
|
||||
*/
|
||||
void CellStore::clearMovesToCells()
|
||||
{
|
||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||
|
||||
for (auto &reference : mMovedHere)
|
||||
{
|
||||
MWWorld::CellStore *otherCell = reference.second;
|
||||
|
||||
otherCell->mMovedToAnotherCell.erase(reference.first);
|
||||
}
|
||||
|
||||
for (auto &reference : mMovedToAnotherCell)
|
||||
{
|
||||
MWWorld::CellStore *otherCell = reference.second;
|
||||
|
||||
otherCell->mMovedHere.erase(reference.first);
|
||||
}
|
||||
|
||||
mMovedHere.empty();
|
||||
mMovedToAnotherCell.empty();
|
||||
}
|
||||
/*
|
||||
End of tes3mp addition
|
||||
*/
|
||||
|
||||
struct MergeVisitor
|
||||
{
|
||||
MergeVisitor(std::vector<LiveCellRefBase*>& mergeTo, const std::map<LiveCellRefBase*, MWWorld::CellStore*>& movedHere,
|
||||
|
|
|
@ -194,6 +194,17 @@ namespace MWWorld
|
|||
/// @return updated MWWorld::Ptr with the new CellStore pointer set.
|
||||
MWWorld::Ptr moveTo(const MWWorld::Ptr& object, MWWorld::CellStore* cellToMoveTo);
|
||||
|
||||
/*
|
||||
Start of tes3mp addition
|
||||
|
||||
Make it possible to clear the moves to other cells tracked for objects, allowing for
|
||||
on-the-fly cell resets that don't cause crashes
|
||||
*/
|
||||
void clearMovesToCells();
|
||||
/*
|
||||
End of tes3mp addition
|
||||
*/
|
||||
|
||||
void rest(double hours);
|
||||
void recharge(float duration);
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "../mwmp/LocalActor.hpp"
|
||||
#include "../mwmp/DedicatedActor.hpp"
|
||||
#include "../mwmp/ObjectList.hpp"
|
||||
#include "../mwmp/RecordHelper.hpp"
|
||||
#include "../mwmp/CellController.hpp"
|
||||
#include "../mwmp/MechanicsHelper.hpp"
|
||||
/*
|
||||
|
@ -2918,6 +2919,28 @@ namespace MWWorld
|
|||
End of tes3mp addition
|
||||
*/
|
||||
|
||||
/*
|
||||
Start of tes3mp addition
|
||||
|
||||
Make it possible to unload all active cells from elsewhere
|
||||
*/
|
||||
void World::unloadActiveCells()
|
||||
{
|
||||
const Scene::CellStoreCollection& activeCells = mWorldScene->getActiveCells();
|
||||
|
||||
for (auto it = activeCells.begin(); it != activeCells.end(); ++it)
|
||||
{
|
||||
// Ignore a placeholder interior that a player may currently be in
|
||||
if ((*it)->getCell()->isExterior() || !Misc::StringUtils::ciEqual((*it)->getCell()->getDescription(), RecordHelper::getPlaceholderInteriorCellName()))
|
||||
{
|
||||
mWorldScene->unloadCell(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
End of tes3mp addition
|
||||
*/
|
||||
|
||||
/*
|
||||
Start of tes3mp addition
|
||||
|
||||
|
@ -2925,6 +2948,11 @@ namespace MWWorld
|
|||
*/
|
||||
void World::clearCellStore(const ESM::Cell& cell)
|
||||
{
|
||||
mwmp::CellController* cellController = mwmp::Main::get().getCellController();
|
||||
MWWorld::CellStore *cellStore = cellController->getCellStore(cell);
|
||||
|
||||
if (cellStore != nullptr)
|
||||
cellStore->clearMovesToCells();
|
||||
mCells.clear(cell);
|
||||
}
|
||||
/*
|
||||
|
|
|
@ -691,6 +691,16 @@ namespace MWWorld
|
|||
End of tes3mp addition
|
||||
*/
|
||||
|
||||
/*
|
||||
Start of tes3mp addition
|
||||
|
||||
Make it possible to unload all active cells from elsewhere
|
||||
*/
|
||||
void unloadActiveCells() override;
|
||||
/*
|
||||
End of tes3mp addition
|
||||
*/
|
||||
|
||||
/*
|
||||
Start of tes3mp addition
|
||||
|
||||
|
|
Loading…
Reference in a new issue