mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-21 06:09:42 +00:00
Replace World::getExterior with WorldModel::getCell
This commit is contained in:
parent
0fef8f12d0
commit
aef2e9d8de
12 changed files with 105 additions and 130 deletions
|
@ -263,9 +263,6 @@ namespace MWBase
|
|||
= 0;
|
||||
///< @param changeEvent If false, do not trigger cell change flag or detect worldspace changes
|
||||
|
||||
virtual const ESM::Cell* getExterior(const ESM::RefId& cellName) const = 0;
|
||||
///< Return a cell matching the given name or a 0-pointer, if there is no such cell.
|
||||
|
||||
virtual MWWorld::Ptr getFacedObject() = 0;
|
||||
///< Return pointer to the object the player is looking at, if it is within activation range
|
||||
|
||||
|
|
|
@ -38,8 +38,10 @@ namespace MWLua
|
|||
return res.str();
|
||||
};
|
||||
|
||||
cellT["name"] = sol::readonly_property([](const CellT& c) { return c.mStore->getCell()->mName; });
|
||||
cellT["region"] = sol::readonly_property([](const CellT& c) { return c.mStore->getCell()->mRegion; });
|
||||
cellT["name"]
|
||||
= sol::readonly_property([](const CellT& c) { return c.mStore->getCell()->mName.getRefIdString(); });
|
||||
cellT["region"]
|
||||
= sol::readonly_property([](const CellT& c) { return c.mStore->getCell()->mRegion.getRefIdString(); });
|
||||
cellT["gridX"] = sol::readonly_property([](const CellT& c) { return c.mStore->getCell()->getGridX(); });
|
||||
cellT["gridY"] = sol::readonly_property([](const CellT& c) { return c.mStore->getCell()->getGridY(); });
|
||||
cellT["hasWater"] = sol::readonly_property([](const CellT& c) { return c.mStore->getCell()->hasWater(); });
|
||||
|
|
|
@ -78,20 +78,11 @@ namespace MWLua
|
|||
sol::table api(context.mLua->sol(), sol::create);
|
||||
WorldView* worldView = context.mWorldView;
|
||||
addTimeBindings(api, context, true);
|
||||
api["getCellByName"] = [worldView = context.mWorldView](const std::string& name) -> sol::optional<GCell> {
|
||||
MWWorld::CellStore* cell = worldView->findNamedCell(ESM::RefId::stringRefId(name));
|
||||
if (cell)
|
||||
return GCell{ cell };
|
||||
else
|
||||
return sol::nullopt;
|
||||
};
|
||||
api["getExteriorCell"] = [worldView = context.mWorldView](int x, int y) -> sol::optional<GCell> {
|
||||
MWWorld::CellStore* cell = worldView->findExteriorCell(x, y);
|
||||
if (cell)
|
||||
return GCell{ cell };
|
||||
else
|
||||
return sol::nullopt;
|
||||
api["getCellByName"] = [](std::string_view name) {
|
||||
return GCell{ MWBase::Environment::get().getWorldModel()->getCell(ESM::RefId::stringRefId(name)) };
|
||||
};
|
||||
api["getExteriorCell"]
|
||||
= [](int x, int y) { return GCell{ MWBase::Environment::get().getWorldModel()->getExterior(x, y) }; };
|
||||
api["activeActors"] = GObjectList{ worldView->getActorsInScene() };
|
||||
// TODO: add world.placeNewObject(recordId, cell, pos, [rot])
|
||||
return LuaUtil::makeReadOnly(api);
|
||||
|
|
|
@ -61,14 +61,12 @@ namespace MWLua
|
|||
{
|
||||
}
|
||||
|
||||
void apply(WorldView& worldView) const override
|
||||
void apply(WorldView&) const override
|
||||
{
|
||||
MWWorld::CellStore* cell = worldView.findCell(mCell, mPos);
|
||||
if (!cell)
|
||||
throw std::runtime_error(std::string("cell not found: '") + mCell.getRefIdString() + "'");
|
||||
|
||||
MWWorld::WorldModel& wm = *MWBase::Environment::get().getWorldModel();
|
||||
MWWorld::CellStore* cell = wm.getCellByPosition(mPos, mCell);
|
||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||
MWWorld::Ptr obj = MWBase::Environment::get().getWorldModel()->getPtr(mObject);
|
||||
MWWorld::Ptr obj = wm.getPtr(mObject);
|
||||
const MWWorld::Class& cls = obj.getClass();
|
||||
bool isPlayer = obj == world->getPlayerPtr();
|
||||
if (cls.isActor())
|
||||
|
@ -166,7 +164,7 @@ namespace MWLua
|
|||
{
|
||||
objectT["isValid"] = [](const ObjectT& o) { return o.isValid(); };
|
||||
objectT["recordId"] = sol::readonly_property(
|
||||
[](const ObjectT& o) -> ESM::RefId { return o.ptr().getCellRef().getRefId(); });
|
||||
[](const ObjectT& o) -> std::string { return o.ptr().getCellRef().getRefId().getRefIdString(); });
|
||||
objectT["cell"] = sol::readonly_property([](const ObjectT& o) -> sol::optional<Cell<ObjectT>> {
|
||||
const MWWorld::Ptr& ptr = o.ptr();
|
||||
if (ptr.isInCell())
|
||||
|
@ -334,10 +332,10 @@ namespace MWLua
|
|||
return ObjectList<ObjectT>{ list };
|
||||
};
|
||||
|
||||
inventoryT["countOf"] = [](const InventoryT& inventory, const ESM::RefId& recordId) {
|
||||
inventoryT["countOf"] = [](const InventoryT& inventory, const std::string& recordId) {
|
||||
const MWWorld::Ptr& ptr = inventory.mObj.ptr();
|
||||
MWWorld::ContainerStore& store = ptr.getClass().getContainerStore(ptr);
|
||||
return store.count(recordId);
|
||||
return store.count(ESM::RefId::stringRefId(recordId));
|
||||
};
|
||||
|
||||
if constexpr (std::is_same_v<ObjectT, GObject>)
|
||||
|
|
|
@ -32,15 +32,14 @@ namespace MWLua
|
|||
= [](const Object& o) -> osg::Vec3f { return doorPtr(o).getCellRef().getDoorDest().asVec3(); };
|
||||
door["destRotation"]
|
||||
= [](const Object& o) -> osg::Vec3f { return doorPtr(o).getCellRef().getDoorDest().asRotationVec3(); };
|
||||
door["destCell"] = [worldView = context.mWorldView](sol::this_state lua, const Object& o) -> sol::object {
|
||||
door["destCell"] = [](sol::this_state lua, const Object& o) -> sol::object {
|
||||
const MWWorld::CellRef& cellRef = doorPtr(o).getCellRef();
|
||||
if (!cellRef.getTeleport())
|
||||
return sol::nil;
|
||||
MWWorld::CellStore* cell = worldView->findCell(cellRef.getDestCell(), cellRef.getDoorDest().asVec3());
|
||||
if (cell)
|
||||
return o.getCell(lua, cell);
|
||||
else
|
||||
return sol::nil;
|
||||
MWWorld::CellStore* cell = MWBase::Environment::get().getWorldModel()->getCellByPosition(
|
||||
cellRef.getDoorDest().asVec3(), cellRef.getDestCell());
|
||||
assert(cell);
|
||||
return o.getCell(lua, cell);
|
||||
};
|
||||
|
||||
auto vfs = MWBase::Environment::get().getResourceSystem()->getVFS();
|
||||
|
|
|
@ -120,35 +120,4 @@ namespace MWLua
|
|||
group.mSet.erase(getId(ptr));
|
||||
group.mChanged = true;
|
||||
}
|
||||
|
||||
// TODO: If Lua scripts will use several threads at the same time, then `find*Cell` functions should have critical
|
||||
// sections.
|
||||
MWWorld::CellStore* WorldView::findCell(const ESM::RefId& name, osg::Vec3f position)
|
||||
{
|
||||
MWWorld::WorldModel* worldModel = MWBase::Environment::get().getWorldModel();
|
||||
bool exterior = name.empty() || MWBase::Environment::get().getWorld()->getExterior(name);
|
||||
if (exterior)
|
||||
{
|
||||
const osg::Vec2i cellIndex = MWWorld::positionToCellIndex(position.x(), position.y());
|
||||
return worldModel->getExterior(cellIndex.x(), cellIndex.y());
|
||||
}
|
||||
else
|
||||
return worldModel->getInterior(name);
|
||||
}
|
||||
|
||||
MWWorld::CellStore* WorldView::findNamedCell(const ESM::RefId& name)
|
||||
{
|
||||
MWWorld::WorldModel* worldModel = MWBase::Environment::get().getWorldModel();
|
||||
const ESM::Cell* esmCell = MWBase::Environment::get().getWorld()->getExterior(name);
|
||||
if (esmCell)
|
||||
return worldModel->getExterior(esmCell->getGridX(), esmCell->getGridY());
|
||||
else
|
||||
return worldModel->getInterior(name);
|
||||
}
|
||||
|
||||
MWWorld::CellStore* WorldView::findExteriorCell(int x, int y)
|
||||
{
|
||||
return MWBase::Environment::get().getWorldModel()->getExterior(x, y);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -50,14 +50,6 @@ namespace MWLua
|
|||
void objectAddedToScene(const MWWorld::Ptr& ptr);
|
||||
void objectRemovedFromScene(const MWWorld::Ptr& ptr);
|
||||
|
||||
// Returns list of objects that meets the `query` criteria.
|
||||
// If onlyActive = true, then search only among the objects that are currently in the scene.
|
||||
// TODO: ObjectIdList selectObjects(const Queries::Query& query, bool onlyActive);
|
||||
|
||||
MWWorld::CellStore* findCell(const ESM::RefId& name, osg::Vec3f position);
|
||||
MWWorld::CellStore* findNamedCell(const ESM::RefId& name);
|
||||
MWWorld::CellStore* findExteriorCell(int x, int y);
|
||||
|
||||
void load(ESM::ESMReader& esm);
|
||||
void save(ESM::ESMWriter& esm) const;
|
||||
|
||||
|
|
|
@ -399,24 +399,20 @@ namespace MWScript
|
|||
MWWorld::CellStore* store = nullptr;
|
||||
try
|
||||
{
|
||||
store = worldModel->getInterior(cellID);
|
||||
store = worldModel->getCell(cellID);
|
||||
}
|
||||
catch (std::exception&)
|
||||
{
|
||||
// cell not found, move to exterior instead if moving the player (vanilla PositionCell
|
||||
// compatibility)
|
||||
const ESM::Cell* cell = world->getExterior(cellID);
|
||||
if (!cell)
|
||||
{
|
||||
std::string error
|
||||
= "Warning: PositionCell: unknown interior cell (" + cellID.getRefIdString() + ")";
|
||||
if (isPlayer)
|
||||
error += ", moving to exterior instead";
|
||||
runtime.getContext().report(error);
|
||||
Log(Debug::Warning) << error;
|
||||
if (!isPlayer)
|
||||
return;
|
||||
}
|
||||
std::string error
|
||||
= "Warning: PositionCell: unknown interior cell (" + cellID.getRefIdString() + ")";
|
||||
if (isPlayer)
|
||||
error += ", moving to exterior instead";
|
||||
runtime.getContext().report(error);
|
||||
Log(Debug::Warning) << error;
|
||||
if (!isPlayer)
|
||||
return;
|
||||
const osg::Vec2i cellIndex = MWWorld::positionToCellIndex(x, y);
|
||||
store = worldModel->getExterior(cellIndex.x(), cellIndex.y());
|
||||
}
|
||||
|
@ -519,18 +515,12 @@ namespace MWScript
|
|||
MWWorld::CellStore* store = nullptr;
|
||||
try
|
||||
{
|
||||
store = MWBase::Environment::get().getWorldModel()->getInterior(cellID);
|
||||
store = MWBase::Environment::get().getWorldModel()->getCell(cellID);
|
||||
}
|
||||
catch (std::exception&)
|
||||
{
|
||||
const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getExterior(cellID);
|
||||
const osg::Vec2i cellIndex = MWWorld::positionToCellIndex(x, y);
|
||||
store = MWBase::Environment::get().getWorldModel()->getExterior(cellIndex.x(), cellIndex.y());
|
||||
if (!cell)
|
||||
{
|
||||
runtime.getContext().report("unknown cell (" + cellID.getRefIdString() + ")");
|
||||
Log(Debug::Error) << "Error: unknown cell (" << cellID << ")";
|
||||
}
|
||||
runtime.getContext().report("unknown cell (" + cellID.getRefIdString() + ")");
|
||||
Log(Debug::Error) << "Error: unknown cell (" << cellID << ")";
|
||||
}
|
||||
if (store)
|
||||
{
|
||||
|
|
|
@ -564,34 +564,6 @@ namespace MWWorld
|
|||
mRandomSeed = seed;
|
||||
}
|
||||
|
||||
const ESM::Cell* World::getExterior(const ESM::RefId& cellName) const
|
||||
{
|
||||
// first try named cells
|
||||
const ESM::Cell* cell = mStore.get<ESM::Cell>().searchExtByName(cellName);
|
||||
if (cell)
|
||||
return cell;
|
||||
// treat "Wilderness" like an empty string
|
||||
static const ESM::RefId defaultName
|
||||
= ESM::RefId::stringRefId(mStore.get<ESM::GameSetting>().find("sDefaultCellname")->mValue.getString());
|
||||
if (cellName == defaultName)
|
||||
{
|
||||
cell = mStore.get<ESM::Cell>().searchExtByName(ESM::RefId::sEmpty);
|
||||
if (cell)
|
||||
return cell;
|
||||
}
|
||||
|
||||
// didn't work -> now check for regions
|
||||
for (const ESM::Region& region : mStore.get<ESM::Region>())
|
||||
{
|
||||
if (cellName == ESM::RefId::stringRefId(region.mName))
|
||||
{
|
||||
return mStore.get<ESM::Cell>().searchExtByRegion(region.mId);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void World::useDeathCamera()
|
||||
{
|
||||
mRendering->getCamera()->setMode(MWRender::Camera::Mode::ThirdPerson);
|
||||
|
@ -2859,7 +2831,17 @@ namespace MWWorld
|
|||
{
|
||||
pos.rot[0] = pos.rot[1] = pos.rot[2] = 0;
|
||||
const std::string& name = nameId.getRefIdString();
|
||||
const ESM::Cell* ext = getExterior(nameId);
|
||||
|
||||
const ESM::Cell* ext = nullptr;
|
||||
try
|
||||
{
|
||||
ext = mWorldModel.getCell(nameId)->getCell();
|
||||
if (!ext->isExterior())
|
||||
return false;
|
||||
}
|
||||
catch (std::exception&)
|
||||
{
|
||||
}
|
||||
if (!ext)
|
||||
{
|
||||
size_t comma = name.find(',');
|
||||
|
|
|
@ -358,9 +358,6 @@ namespace MWWorld
|
|||
bool changeEvent = true) override;
|
||||
///< @param changeEvent If false, do not trigger cell change flag or detect worldspace changes
|
||||
|
||||
const ESM::Cell* getExterior(const ESM::RefId& cellName) const override;
|
||||
///< Return a cell matching the given name or a 0-pointer, if there is no such cell.
|
||||
|
||||
MWWorld::Ptr getFacedObject() override;
|
||||
///< Return pointer to the object the player is looking at, if it is within activation range
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <components/esm3/cellstate.hpp>
|
||||
#include <components/esm3/esmreader.hpp>
|
||||
#include <components/esm3/esmwriter.hpp>
|
||||
#include <components/esm3/loadregn.hpp>
|
||||
#include <components/loadinglistener/loadinglistener.hpp>
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
|
@ -13,6 +14,7 @@
|
|||
#include "../mwbase/world.hpp"
|
||||
|
||||
#include "cellstore.hpp"
|
||||
#include "cellutils.hpp"
|
||||
#include "esmstore.hpp"
|
||||
|
||||
namespace
|
||||
|
@ -220,6 +222,57 @@ MWWorld::CellStore* MWWorld::WorldModel::getCell(const ESM::CellId& id)
|
|||
return getInterior(id.mWorldspace);
|
||||
}
|
||||
|
||||
const ESM::Cell* MWWorld::WorldModel::getESMCellByName(const ESM::RefId& name)
|
||||
{
|
||||
const ESM::Cell* cell = mStore.get<ESM::Cell>().search(name); // first try interiors
|
||||
if (!cell) // try named exteriors
|
||||
cell = mStore.get<ESM::Cell>().searchExtByName(name);
|
||||
if (!cell)
|
||||
{
|
||||
// treat "Wilderness" like an empty string
|
||||
static const ESM::RefId defaultName
|
||||
= ESM::RefId::stringRefId(mStore.get<ESM::GameSetting>().find("sDefaultCellname")->mValue.getString());
|
||||
if (name == defaultName)
|
||||
cell = mStore.get<ESM::Cell>().searchExtByName(ESM::RefId::sEmpty);
|
||||
}
|
||||
if (!cell)
|
||||
{
|
||||
// now check for regions
|
||||
for (const ESM::Region& region : mStore.get<ESM::Region>())
|
||||
{
|
||||
if (name == ESM::RefId::stringRefId(region.mName))
|
||||
{
|
||||
cell = mStore.get<ESM::Cell>().searchExtByRegion(region.mId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!cell)
|
||||
throw std::runtime_error(std::string("Can't find cell with name ") + name.getRefIdString());
|
||||
return cell;
|
||||
}
|
||||
|
||||
MWWorld::CellStore* MWWorld::WorldModel::getCell(const ESM::RefId& name)
|
||||
{
|
||||
const ESM::Cell* cell = getESMCellByName(name);
|
||||
if (cell->isExterior())
|
||||
return getExterior(cell->getGridX(), cell->getGridY());
|
||||
else
|
||||
return getInterior(name);
|
||||
}
|
||||
|
||||
MWWorld::CellStore* MWWorld::WorldModel::getCellByPosition(
|
||||
const osg::Vec3f& pos, const ESM::RefId& cellNameInSameWorldSpace)
|
||||
{
|
||||
if (cellNameInSameWorldSpace.empty() || getESMCellByName(cellNameInSameWorldSpace)->isExterior())
|
||||
{
|
||||
const osg::Vec2i cellIndex = positionToCellIndex(pos.x(), pos.y());
|
||||
return getExterior(cellIndex.x(), cellIndex.y());
|
||||
}
|
||||
else
|
||||
return getInterior(cellNameInSameWorldSpace);
|
||||
}
|
||||
|
||||
MWWorld::Ptr MWWorld::WorldModel::getPtr(const ESM::RefId& name, CellStore& cell, bool searchInContainers)
|
||||
{
|
||||
if (cell.getState() == CellStore::State_Unloaded)
|
||||
|
|
|
@ -42,6 +42,7 @@ namespace MWWorld
|
|||
WorldModel(const WorldModel&);
|
||||
WorldModel& operator=(const WorldModel&);
|
||||
|
||||
const ESM::Cell* getESMCellByName(const ESM::RefId& name);
|
||||
CellStore* getCellStore(const ESM::Cell* cell);
|
||||
|
||||
Ptr getPtrAndCache(const ESM::RefId& name, CellStore& cellStore);
|
||||
|
@ -60,11 +61,15 @@ namespace MWWorld
|
|||
explicit WorldModel(const MWWorld::ESMStore& store, ESM::ReadersCache& reader);
|
||||
|
||||
CellStore* getExterior(int x, int y);
|
||||
|
||||
CellStore* getInterior(std::string_view name);
|
||||
|
||||
CellStore* getInterior(const ESM::RefId& name);
|
||||
CellStore* getCell(const ESM::RefId& name); // interior or named exterior
|
||||
CellStore* getCell(const ESM::CellId& id);
|
||||
|
||||
// If cellNameInSameWorldSpace is an interior - returns this interior.
|
||||
// Otherwise returns exterior cell for given position in the same world space.
|
||||
// At the moment multiple world spaces are not supported, so all exteriors are in one world space.
|
||||
CellStore* getCellByPosition(const osg::Vec3f& pos, const ESM::RefId& cellNameInSameWorldSpace);
|
||||
|
||||
void registerPtr(const MWWorld::Ptr& ptr);
|
||||
void deregisterPtr(const MWWorld::Ptr& ptr);
|
||||
ESM::RefNum getLastGeneratedRefNum() const { return mLastGeneratedRefnum; }
|
||||
|
@ -74,7 +79,7 @@ namespace MWWorld
|
|||
|
||||
Ptr getPtr(const ESM::RefNum& refNum) const;
|
||||
|
||||
Ptr getPtr(std::string_view name, CellStore& cellStore, bool searchInContainers = false);
|
||||
Ptr getPtr(const ESM::RefId& name, CellStore& cellStore, bool searchInContainers = false);
|
||||
///< \param searchInContainers Only affect loaded cells.
|
||||
/// @note name must be lower case
|
||||
|
||||
|
|
Loading…
Reference in a new issue