OpenMW
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
cellstore.hpp
Go to the documentation of this file.
1 #ifndef GAME_MWWORLD_CELLSTORE_H
2 #define GAME_MWWORLD_CELLSTORE_H
3 
4 #include <algorithm>
5 #include <stdexcept>
6 #include <string>
7 #include <typeinfo>
8 #include <map>
9 #include <memory>
10 
11 #include "livecellref.hpp"
12 #include "cellreflist.hpp"
13 
34 
35 #include "timestamp.hpp"
36 #include "ptr.hpp"
37 
38 namespace ESM
39 {
40  struct Cell;
41  struct CellState;
42  struct FogState;
43  struct CellId;
44 }
45 
46 namespace MWWorld
47 {
48  class ESMStore;
49 
51  class CellStore
52  {
53  public:
54 
55  enum State
56  {
58  };
59 
60  private:
61 
63  std::vector<ESM::ESMReader>& mReader;
64 
65  // Even though fog actually belongs to the player and not cells,
66  // it makes sense to store it here since we need it once for each cell.
67  // Note this is NULL until the cell is explored to save some memory
68  std::shared_ptr<ESM::FogState> mFogState;
69 
70  const ESM::Cell *mCell;
72  bool mHasState;
73  std::vector<std::string> mIds;
74  float mWaterLevel;
75 
77 
78  // List of refs owned by this cell
100 
101  typedef std::map<LiveCellRefBase*, MWWorld::CellStore*> MovedRefTracker;
102  // References owned by a different cell that have been moved here.
103  // <reference, cell the reference originally came from>
105  // References owned by this cell that have been moved to another cell.
106  // <reference, cell the reference was moved to>
108 
109  // Merged list of ref's currently in this cell - i.e. with added refs from mMovedHere, removed refs from mMovedToAnotherCell
110  std::vector<LiveCellRefBase*> mMergedRefs;
111 
112  // Get the Ptr for the given ref which originated from this cell (possibly moved to another cell at this point).
114 
116  void moveFrom(const MWWorld::Ptr& object, MWWorld::CellStore* from);
117 
119  void updateMergedRefs();
120 
121  // helper function for forEachInternal
122  template<class Visitor, class List>
123  bool forEachImp (Visitor& visitor, List& list)
124  {
125  for (typename List::List::iterator iter (list.mList.begin()); iter!=list.mList.end();
126  ++iter)
127  {
128  if (!isAccessible(iter->mData, iter->mRef))
129  continue;
130  if (!visitor (MWWorld::Ptr(&*iter, this)))
131  return false;
132  }
133  return true;
134  }
135 
136  // listing only objects owned by this cell. Internal use only, you probably want to use forEach() so that moved objects are accounted for.
137  template<class Visitor>
138  bool forEachInternal (Visitor& visitor)
139  {
140  return
141  forEachImp (visitor, mActivators) &&
142  forEachImp (visitor, mPotions) &&
143  forEachImp (visitor, mAppas) &&
144  forEachImp (visitor, mArmors) &&
145  forEachImp (visitor, mBooks) &&
146  forEachImp (visitor, mClothes) &&
147  forEachImp (visitor, mContainers) &&
148  forEachImp (visitor, mDoors) &&
149  forEachImp (visitor, mIngreds) &&
150  forEachImp (visitor, mItemLists) &&
151  forEachImp (visitor, mLights) &&
152  forEachImp (visitor, mLockpicks) &&
153  forEachImp (visitor, mMiscItems) &&
154  forEachImp (visitor, mProbes) &&
155  forEachImp (visitor, mRepairs) &&
156  forEachImp (visitor, mStatics) &&
157  forEachImp (visitor, mWeapons) &&
158  forEachImp (visitor, mBodyParts) &&
159  forEachImp (visitor, mCreatures) &&
160  forEachImp (visitor, mNpcs) &&
161  forEachImp (visitor, mCreatureLists);
162  }
163 
166  template <class T>
167  CellRefList<T>& get();
168 
169  public:
170 
175  static bool isAccessible(const MWWorld::RefData& refdata, const MWWorld::CellRef& cref)
176  {
177  return !refdata.isDeletedByContentFile() && (cref.hasContentFile() || refdata.getCount() > 0);
178  }
179 
184  MWWorld::Ptr moveTo(const MWWorld::Ptr& object, MWWorld::CellStore* cellToMoveTo);
185 
186  void rest();
187 
191  template <typename T>
193  {
194  mHasState = true;
195  CellRefList<T>& list = get<T>();
196  LiveCellRefBase* ret = &list.insert(*ref);
198  return ret;
199  }
200 
202  CellStore (const ESM::Cell *cell_,
203  const MWWorld::ESMStore& store,
204  std::vector<ESM::ESMReader>& readerList);
205 
206  const ESM::Cell *getCell() const;
207 
208  State getState() const;
209 
210  const std::vector<std::string>& getPreloadedIds() const;
212 
213  bool hasState() const;
215 
216  bool hasId (const std::string& id) const;
220 
221  Ptr search (const std::string& id);
225 
226  ConstPtr searchConst (const std::string& id) const;
230 
231  Ptr searchViaActorId (int id);
233 
234  float getWaterLevel() const;
235 
236  void setWaterLevel (float level);
237 
238  void setFog (ESM::FogState* fog);
240 
241  ESM::FogState* getFog () const;
242 
243  int count() const;
245 
246  void load ();
248 
249  void preload ();
251 
258  template<class Visitor>
259  bool forEach (Visitor& visitor)
260  {
261  if (mState != State_Loaded)
262  return false;
263 
264  if (mMergedRefs.empty())
265  return true;
266 
267  mHasState = true;
268 
269  for (unsigned int i=0; i<mMergedRefs.size(); ++i)
270  {
271  if (!isAccessible(mMergedRefs[i]->mData, mMergedRefs[i]->mRef))
272  continue;
273 
274  if (!visitor(MWWorld::Ptr(mMergedRefs[i], this)))
275  return false;
276  }
277  return true;
278  }
279 
285  template<class Visitor>
286  bool forEachConst (Visitor& visitor) const
287  {
288  if (mState != State_Loaded)
289  return false;
290 
291  for (unsigned int i=0; i<mMergedRefs.size(); ++i)
292  {
293  if (!isAccessible(mMergedRefs[i]->mData, mMergedRefs[i]->mRef))
294  continue;
295 
296  if (!visitor(MWWorld::ConstPtr(mMergedRefs[i], this)))
297  return false;
298  }
299  return true;
300  }
301 
302 
308  template <class T, class Visitor>
309  bool forEachType(Visitor& visitor)
310  {
311  if (mState != State_Loaded)
312  return false;
313 
314  if (mMergedRefs.empty())
315  return true;
316 
317  mHasState = true;
318 
319  CellRefList<T>& list = get<T>();
320 
321  for (typename CellRefList<T>::List::iterator it (list.mList.begin()); it!=list.mList.end(); ++it)
322  {
323  LiveCellRefBase* base = &*it;
324  if (mMovedToAnotherCell.find(base) != mMovedToAnotherCell.end())
325  continue;
326  if (!isAccessible(base->mData, base->mRef))
327  continue;
328  if (!visitor(MWWorld::Ptr(base, this)))
329  return false;
330  }
331 
332  for (MovedRefTracker::const_iterator it = mMovedHere.begin(); it != mMovedHere.end(); ++it)
333  {
334  LiveCellRefBase* base = it->first;
335  if (dynamic_cast<LiveCellRef<T>*>(base))
336  if (!visitor(MWWorld::Ptr(base, this)))
337  return false;
338  }
339  return true;
340  }
341 
342  // NOTE: does not account for moved references
343  // Should be phased out when we have const version of forEach
345  {
346  return mDoors;
347  }
349  {
350  return mStatics;
351  }
352 
353  bool isExterior() const;
354 
355  Ptr searchInContainer (const std::string& id);
356 
357  void loadState (const ESM::CellState& state);
358 
359  void saveState (ESM::CellState& state) const;
360 
361  void writeFog (ESM::ESMWriter& writer) const;
362 
363  void readFog (ESM::ESMReader& reader);
364 
365  void writeReferences (ESM::ESMWriter& writer) const;
366 
368  {
369  public:
371  virtual CellStore* getCellStore(const ESM::CellId& cellId) = 0;
372  };
373 
375  void readReferences (ESM::ESMReader& reader, const std::map<int, int>& contentFileMap, GetCellStoreCallback* callback);
376 
377  void respawn ();
379 
380  private:
381 
383  void listRefs();
384 
385  void loadRefs();
386 
387  void loadRef (ESM::CellRef& ref, bool deleted, std::map<ESM::RefNum, std::string>& refNumToID);
391  };
392 
393  template<>
394  inline CellRefList<ESM::Activator>& CellStore::get<ESM::Activator>()
395  {
396  mHasState = true;
397  return mActivators;
398  }
399 
400  template<>
401  inline CellRefList<ESM::Potion>& CellStore::get<ESM::Potion>()
402  {
403  mHasState = true;
404  return mPotions;
405  }
406 
407  template<>
408  inline CellRefList<ESM::Apparatus>& CellStore::get<ESM::Apparatus>()
409  {
410  mHasState = true;
411  return mAppas;
412  }
413 
414  template<>
415  inline CellRefList<ESM::Armor>& CellStore::get<ESM::Armor>()
416  {
417  mHasState = true;
418  return mArmors;
419  }
420 
421  template<>
422  inline CellRefList<ESM::Book>& CellStore::get<ESM::Book>()
423  {
424  mHasState = true;
425  return mBooks;
426  }
427 
428  template<>
429  inline CellRefList<ESM::Clothing>& CellStore::get<ESM::Clothing>()
430  {
431  mHasState = true;
432  return mClothes;
433  }
434 
435  template<>
436  inline CellRefList<ESM::Container>& CellStore::get<ESM::Container>()
437  {
438  mHasState = true;
439  return mContainers;
440  }
441 
442  template<>
443  inline CellRefList<ESM::Creature>& CellStore::get<ESM::Creature>()
444  {
445  mHasState = true;
446  return mCreatures;
447  }
448 
449  template<>
450  inline CellRefList<ESM::Door>& CellStore::get<ESM::Door>()
451  {
452  mHasState = true;
453  return mDoors;
454  }
455 
456  template<>
457  inline CellRefList<ESM::Ingredient>& CellStore::get<ESM::Ingredient>()
458  {
459  mHasState = true;
460  return mIngreds;
461  }
462 
463  template<>
464  inline CellRefList<ESM::CreatureLevList>& CellStore::get<ESM::CreatureLevList>()
465  {
466  mHasState = true;
467  return mCreatureLists;
468  }
469 
470  template<>
471  inline CellRefList<ESM::ItemLevList>& CellStore::get<ESM::ItemLevList>()
472  {
473  mHasState = true;
474  return mItemLists;
475  }
476 
477  template<>
478  inline CellRefList<ESM::Light>& CellStore::get<ESM::Light>()
479  {
480  mHasState = true;
481  return mLights;
482  }
483 
484  template<>
485  inline CellRefList<ESM::Lockpick>& CellStore::get<ESM::Lockpick>()
486  {
487  mHasState = true;
488  return mLockpicks;
489  }
490 
491  template<>
492  inline CellRefList<ESM::Miscellaneous>& CellStore::get<ESM::Miscellaneous>()
493  {
494  mHasState = true;
495  return mMiscItems;
496  }
497 
498  template<>
499  inline CellRefList<ESM::NPC>& CellStore::get<ESM::NPC>()
500  {
501  mHasState = true;
502  return mNpcs;
503  }
504 
505  template<>
506  inline CellRefList<ESM::Probe>& CellStore::get<ESM::Probe>()
507  {
508  mHasState = true;
509  return mProbes;
510  }
511 
512  template<>
513  inline CellRefList<ESM::Repair>& CellStore::get<ESM::Repair>()
514  {
515  mHasState = true;
516  return mRepairs;
517  }
518 
519  template<>
520  inline CellRefList<ESM::Static>& CellStore::get<ESM::Static>()
521  {
522  mHasState = true;
523  return mStatics;
524  }
525 
526  template<>
527  inline CellRefList<ESM::Weapon>& CellStore::get<ESM::Weapon>()
528  {
529  mHasState = true;
530  return mWeapons;
531  }
532 
533  template<>
534  inline CellRefList<ESM::BodyPart>& CellStore::get<ESM::BodyPart>()
535  {
536  mHasState = true;
537  return mBodyParts;
538  }
539 
540  bool operator== (const CellStore& left, const CellStore& right);
541  bool operator!= (const CellStore& left, const CellStore& right);
542 }
543 
544 #endif
State
Definition: cellstore.hpp:55
Used to create pointers to hold any type of LiveCellRef<> object.
Definition: livecellref.hpp:22
CellStore(const ESM::Cell *cell_, const MWWorld::ESMStore &store, std::vector< ESM::ESMReader > &readerList)
Definition: cellstore.cpp:333
Encapsulated variant of ESM::CellRef with change tracking.
Definition: cellref.hpp:15
static bool isAccessible(const MWWorld::RefData &refdata, const MWWorld::CellRef &cref)
Definition: cellstore.hpp:175
bool forEachType(Visitor &visitor)
Definition: cellstore.hpp:309
LiveCellRefBase * insert(const LiveCellRef< T > *ref)
Definition: cellstore.hpp:192
const MWWorld::ESMStore & mStore
Definition: cellstore.hpp:62
const ESM::Cell * mCell
Definition: cellstore.hpp:70
CellRefList< ESM::Potion > mPotions
Definition: cellstore.hpp:80
const ESM::Cell * getCell() const
Definition: cellstore.cpp:339
bool operator==(const LiveCellRef< X > &ref, int pRefnum)
Definition: cellstore.cpp:207
const CellRefList< ESM::Static > & getReadOnlyStatics() const
Definition: cellstore.hpp:348
CellRefList< ESM::Repair > mRepairs
Definition: cellstore.hpp:96
CellRefList< ESM::Ingredient > mIngreds
Definition: cellstore.hpp:88
Definition: esmreader.hpp:21
void load()
Load references from content file.
Definition: cellstore.cpp:440
float mWaterLevel
Definition: cellstore.hpp:74
Definition: cellstore.hpp:367
float getWaterLevel() const
Definition: cellstore.cpp:422
Definition: fogstate.hpp:19
bool forEach(Visitor &visitor)
Definition: cellstore.hpp:259
bool mHasState
Definition: cellstore.hpp:72
MWWorld::CellRef mRef
Definition: livecellref.hpp:29
MWWorld::Ptr moveTo(const MWWorld::Ptr &object, MWWorld::CellStore *cellToMoveTo)
Definition: cellstore.cpp:240
CellRefList< ESM::Probe > mProbes
Definition: cellstore.hpp:95
int list(Bsa::BSAFile &bsa, Arguments &info)
Definition: bsatool.cpp:182
void loadRefs()
Definition: cellstore.cpp:519
void updateMergedRefs()
Repopulate mMergedRefs.
Definition: cellstore.cpp:325
CellRefList< ESM::Miscellaneous > mMiscItems
Definition: cellstore.hpp:93
const CellRefList< ESM::Door > & getReadOnlyDoors() const
Definition: cellstore.hpp:344
CellRefList< ESM::Activator > mActivators
Definition: cellstore.hpp:79
Definition: livecellref.hpp:77
State getState() const
Definition: cellstore.cpp:344
bool isExterior() const
Definition: cellstore.cpp:574
bool hasId(const std::string &id) const
Definition: cellstore.cpp:359
bool isDeletedByContentFile() const
Returns true if the object was deleted by a content file.
Definition: refdata.cpp:180
LiveRef & insert(const LiveRef &item)
Definition: cellreflist.hpp:27
Definition: refdata.hpp:29
RefData mData
Definition: livecellref.hpp:32
void moveFrom(const MWWorld::Ptr &object, MWWorld::CellStore *from)
Moves object from the given cell to this cell.
Definition: cellstore.cpp:220
void writeFog(ESM::ESMWriter &writer) const
Definition: cellstore.cpp:695
void saveState(ESM::CellState &state) const
Definition: cellstore.cpp:684
CellRefList< ESM::NPC > mNpcs
Definition: cellstore.hpp:94
Definition: esmwriter.hpp:17
Definition: cellstore.hpp:57
bool forEachConst(Visitor &visitor) const
Definition: cellstore.hpp:286
int count() const
Return total number of references, including deleted ones.
Definition: cellstore.cpp:435
Definition: esmstore.hpp:17
CellRefList< ESM::Clothing > mClothes
Definition: cellstore.hpp:84
void respawn()
Check mLastRespawn and respawn references if necessary. This is a no-op if the cell is not loaded...
Definition: cellstore.cpp:981
void loadRef(ESM::CellRef &ref, bool deleted, std::map< ESM::RefNum, std::string > &refNumToID)
Definition: cellstore.cpp:599
CellRefList< ESM::CreatureLevList > mCreatureLists
Definition: cellstore.hpp:89
int getCount() const
Definition: refdata.cpp:149
ConstPtr searchConst(const std::string &id) const
Definition: cellstore.cpp:394
void listRefs()
Run through references and store IDs.
Definition: cellstore.cpp:463
Ptr search(const std::string &id)
Definition: cellstore.cpp:386
Mutable state of a cell.
Definition: cellstore.hpp:51
std::shared_ptr< ESM::FogState > mFogState
Definition: cellstore.hpp:68
List mList
Definition: cellreflist.hpp:16
bool forEachInternal(Visitor &visitor)
Definition: cellstore.hpp:138
Pointer to a const LiveCellRef.
Definition: ptr.hpp:90
CellRefList< ESM::Book > mBooks
Definition: cellstore.hpp:83
bool forEachImp(Visitor &visitor, List &list)
Definition: cellstore.hpp:123
void preload()
Build ID list from content file.
Definition: cellstore.cpp:453
MovedRefTracker mMovedHere
Definition: cellstore.hpp:104
Definition: cellref.hpp:36
Definition: loadcell.hpp:64
CellRefList< ESM::ItemLevList > mItemLists
Definition: cellstore.hpp:90
std::vector< ESM::ESMReader > & mReader
Definition: cellstore.hpp:63
bool hasState() const
Does this cell have state that needs to be stored in a saved game file?
Definition: cellstore.cpp:354
In-game time stamp.
Definition: timestamp.hpp:14
CellRefList< ESM::Static > mStatics
Definition: cellstore.hpp:97
CellRefList< ESM::Creature > mCreatures
Definition: cellstore.hpp:86
ESM::FogState * getFog() const
Definition: cellstore.cpp:940
void loadState(const ESM::CellState &state)
Definition: cellstore.cpp:674
void setWaterLevel(float level)
Definition: cellstore.cpp:429
CellRefList< ESM::Light > mLights
Definition: cellstore.hpp:91
std::vector< std::string > mIds
Definition: cellstore.hpp:73
std::map< LiveCellRefBase *, MWWorld::CellStore * > MovedRefTracker
Definition: cellstore.hpp:101
CellRefList< ESM::Container > mContainers
Definition: cellstore.hpp:85
void readFog(ESM::ESMReader &reader)
Definition: cellstore.cpp:703
Ptr searchInContainer(const std::string &id)
Definition: cellstore.cpp:579
Definition: cellstore.hpp:57
virtual CellStore * getCellStore(const ESM::CellId &cellId)=0
CellRefList< ESM::Weapon > mWeapons
Definition: cellstore.hpp:98
void setFog(ESM::FogState *fog)
Definition: cellstore.cpp:935
CellRefList< ESM::BodyPart > mBodyParts
Definition: cellstore.hpp:99
void rest()
Definition: cellstore.cpp:958
Definition: cellstore.hpp:57
State mState
Definition: cellstore.hpp:71
CellRefList< ESM::Armor > mArmors
Definition: cellstore.hpp:82
Ptr getCurrentPtr(MWWorld::LiveCellRefBase *ref)
Definition: cellstore.cpp:212
Pointer to a LiveCellRef.
Definition: ptr.hpp:19
void readReferences(ESM::ESMReader &reader, const std::map< int, int > &contentFileMap, GetCellStoreCallback *callback)
Definition: cellstore.cpp:744
bool operator!=(const CellStore &left, const CellStore &right)
Definition: cellstore.cpp:930
CellRefList< ESM::Lockpick > mLockpicks
Definition: cellstore.hpp:92
void writeReferences(ESM::ESMWriter &writer) const
Definition: cellstore.cpp:709
Definition: cellid.hpp:11
MWWorld::TimeStamp mLastRespawn
Definition: cellstore.hpp:76
bool hasContentFile() const
Does the RefNum have a content file?
Definition: cellref.cpp:13
CellRefList< ESM::Apparatus > mAppas
Definition: cellstore.hpp:81
Ptr searchViaActorId(int id)
Will return an empty Ptr if cell is not loaded.
Definition: cellstore.cpp:402
std::vector< LiveCellRefBase * > mMergedRefs
Definition: cellstore.hpp:110
CellRefList< ESM::Door > mDoors
Definition: cellstore.hpp:87
MovedRefTracker mMovedToAnotherCell
Definition: cellstore.hpp:107
const std::vector< std::string > & getPreloadedIds() const
Get Ids of objects in this cell, only valid in State_Preloaded.
Definition: cellstore.cpp:349
Definition: cellstate.hpp:16