load and save of reference in cells (without CustomData state)

actorid
Marc Zinnschlag 11 years ago
parent e0de76a6f7
commit 29c3a288e3

@ -127,7 +127,7 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
if(!paused && player.getClass().getCreatureStats(player).isDead())
MWBase::Environment::get().getStateManager()->endGame();
}
// update world
MWBase::Environment::get().getWorld()->update(frametime, paused);
@ -282,12 +282,7 @@ void OMW::Engine::setCell (const std::string& cellName)
void OMW::Engine::addContentFile(const std::string& file)
{
if (file.find_last_of(".") == std::string::npos)
{
throw std::runtime_error("Missing extension in content file!");
}
mContentFiles.push_back(file);
mContentFiles.push_back(file);
}
void OMW::Engine::setScriptsVerbosity(bool scriptsVerbosity)

@ -2,6 +2,7 @@
#define GAME_MWBASE_WORLD_H
#include <vector>
#include <map>
#include <components/settings/settings.hpp>
@ -102,7 +103,8 @@ namespace MWBase
virtual void write (ESM::ESMWriter& writer) const = 0;
virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0;
virtual void readRecord (ESM::ESMReader& reader, int32_t type,
const std::map<int, int>& contentFileMap) = 0;
virtual OEngine::Render::Fader* getFader() = 0;
///< \todo remove this function. Rendering details should not be exposed.

@ -6,6 +6,8 @@
#include <components/esm/cellid.hpp>
#include <components/esm/loadcell.hpp>
#include <components/misc/stringops.hpp>
#include <components/settings/settings.hpp>
#include <OgreImage.h>
@ -43,6 +45,31 @@ void MWState::StateManager::cleanup (bool force)
}
}
std::map<int, int> MWState::StateManager::buildContentFileIndexMap (const ESM::ESMReader& reader)
const
{
const std::vector<std::string>& current =
MWBase::Environment::get().getWorld()->getContentFiles();
const std::vector<ESM::Header::MasterData>& prev = reader.getGameFiles();
std::map<int, int> map;
for (int iPrev = 0; iPrev<static_cast<int> (prev.size()); ++iPrev)
{
std::string id = Misc::StringUtils::lowerCase (prev[iPrev].name);
for (int iCurrent = 0; iCurrent<static_cast<int> (current.size()); ++iCurrent)
if (id==Misc::StringUtils::lowerCase (current[iCurrent]))
{
map.insert (std::make_pair (iPrev, iCurrent));
break;
}
}
return map;
}
MWState::StateManager::StateManager (const boost::filesystem::path& saves, const std::string& game)
: mQuitRequest (false), mAskLoadRecent(false), mState (State_NoGame), mCharacterManager (saves, game), mTimePlayed (0)
{
@ -167,7 +194,16 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot
slot = mCharacterManager.getCurrentCharacter()->updateSlot (slot, profile);
std::ofstream stream (slot->mPath.string().c_str());
ESM::ESMWriter writer;
const std::vector<std::string>& current =
MWBase::Environment::get().getWorld()->getContentFiles();
for (std::vector<std::string>::const_iterator iter (current.begin()); iter!=current.end();
++iter)
writer.addMaster (*iter, 0); // not using the size information anyway -> use value of 0
writer.setFormat (ESM::Header::CurrentFormat);
writer.setRecordCount (
1 // saved game header
@ -205,6 +241,8 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl
ESM::ESMReader reader;
reader.open (slot->mPath.string());
std::map<int, int> contentFileMap = buildContentFileIndexMap (reader);
while (reader.hasMoreRecs())
{
ESM::NAME n = reader.getRecName();
@ -237,7 +275,7 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl
case ESM::REC_PLAY:
case ESM::REC_CSTA:
MWBase::Environment::get().getWorld()->readRecord (reader, n.val);
MWBase::Environment::get().getWorld()->readRecord (reader, n.val, contentFileMap);
break;
case ESM::REC_GSCR:

@ -1,6 +1,8 @@
#ifndef GAME_STATE_STATEMANAGER_H
#define GAME_STATE_STATEMANAGER_H
#include <map>
#include "../mwbase/statemanager.hpp"
#include <boost/filesystem/path.hpp>
@ -21,6 +23,8 @@ namespace MWState
void cleanup (bool force = false);
std::map<int, int> buildContentFileIndexMap (const ESM::ESMReader& reader) const;
public:
StateManager (const boost::filesystem::path& saves, const std::string& game);

@ -352,7 +352,8 @@ void MWWorld::Cells::write (ESM::ESMWriter& writer) const
writeCell (writer, iter->second);
}
bool MWWorld::Cells::readRecord (ESM::ESMReader& reader, int32_t type)
bool MWWorld::Cells::readRecord (ESM::ESMReader& reader, int32_t type,
const std::map<int, int>& contentFileMap)
{
if (type==ESM::REC_CSTA)
{
@ -373,7 +374,11 @@ bool MWWorld::Cells::readRecord (ESM::ESMReader& reader, int32_t type)
state.load (reader);
cellStore->loadState (state);
reader.skipRecord();
if (cellStore->mState!=CellStore::State_Loaded)
cellStore->load (mStore, mReader);
cellStore->readReferences (reader, contentFileMap);
return true;
}

@ -73,7 +73,8 @@ namespace MWWorld
void write (ESM::ESMWriter& writer) const;
bool readRecord (ESM::ESMReader& reader, int32_t type);
bool readRecord (ESM::ESMReader& reader, int32_t type,
const std::map<int, int>& contentFileMap);
};
}

@ -41,9 +41,6 @@ namespace
{
if (!collection.mList.empty())
{
// section header
writer.writeHNT ("CSEC", collection.mList.front().mBase->sRecordId);
// references
for (typename MWWorld::CellRefList<T>::List::const_iterator
iter (collection.mList.begin());
@ -55,12 +52,51 @@ namespace
RecordType state;
iter->save (state);
writer.startRecord (ESM::REC_OBJE);
writer.writeHNT ("OBJE", collection.mList.front().mBase->sRecordId);
state.save (writer);
writer.endRecord (ESM::REC_OBJE);
}
}
}
template<typename RecordType, typename T>
void readReferenceCollection (ESM::ESMReader& reader,
MWWorld::CellRefList<T>& collection, const std::map<int, int>& contentFileMap)
{
const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore();
RecordType state;
state.load (reader);
std::map<int, int>::const_iterator iter =
contentFileMap.find (state.mRef.mRefNum.mContentFile);
if (iter==contentFileMap.end())
return; // content file has been removed -> skip
state.mRef.mRefNum.mContentFile = iter->second;
if (!MWWorld::LiveCellRef<T>::checkState (state))
return; // not valid anymore with current content files -> skip
const T *record = esmStore.get<T>().search (state.mRef.mRefID);
if (!record)
return;
for (typename MWWorld::CellRefList<T>::List::iterator iter (collection.mList.begin());
iter!=collection.mList.end(); ++iter)
if (iter->mRef.mRefNum==state.mRef.mRefNum)
{
// overwrite existing reference
iter->load (state);
return;
}
// new reference
MWWorld::LiveCellRef<T> ref (record);
ref.load (state);
collection.mList.push_back (ref);
}
}
namespace MWWorld
@ -304,4 +340,121 @@ namespace MWWorld
writeReferenceCollection<ESM::ObjectState> (writer, mStatics);
writeReferenceCollection<ESM::ObjectState> (writer, mWeapons);
}
void CellStore::readReferences (ESM::ESMReader& reader,
const std::map<int, int>& contentFileMap)
{
while (reader.isNextSub ("OBJE"))
{
unsigned int id = 0;
reader.getHT (id);
switch (id)
{
case ESM::REC_ACTI:
readReferenceCollection<ESM::ObjectState> (reader, mActivators, contentFileMap);
break;
case ESM::REC_ALCH:
readReferenceCollection<ESM::ObjectState> (reader, mPotions, contentFileMap);
break;
case ESM::REC_APPA:
readReferenceCollection<ESM::ObjectState> (reader, mAppas, contentFileMap);
break;
case ESM::REC_ARMO:
readReferenceCollection<ESM::ObjectState> (reader, mArmors, contentFileMap);
break;
case ESM::REC_BOOK:
readReferenceCollection<ESM::ObjectState> (reader, mBooks, contentFileMap);
break;
case ESM::REC_CLOT:
readReferenceCollection<ESM::ObjectState> (reader, mClothes, contentFileMap);
break;
case ESM::REC_CONT:
readReferenceCollection<ESM::ObjectState> (reader, mContainers, contentFileMap);
break;
case ESM::REC_CREA:
readReferenceCollection<ESM::ObjectState> (reader, mCreatures, contentFileMap);
break;
case ESM::REC_DOOR:
readReferenceCollection<ESM::ObjectState> (reader, mDoors, contentFileMap);
break;
case ESM::REC_INGR:
readReferenceCollection<ESM::ObjectState> (reader, mIngreds, contentFileMap);
break;
case ESM::REC_LEVC:
readReferenceCollection<ESM::ObjectState> (reader, mCreatureLists, contentFileMap);
break;
case ESM::REC_LEVI:
readReferenceCollection<ESM::ObjectState> (reader, mItemLists, contentFileMap);
break;
case ESM::REC_LIGH:
readReferenceCollection<ESM::ObjectState> (reader, mLights, contentFileMap);
break;
case ESM::REC_LOCK:
readReferenceCollection<ESM::ObjectState> (reader, mLockpicks, contentFileMap);
break;
case ESM::REC_MISC:
readReferenceCollection<ESM::ObjectState> (reader, mMiscItems, contentFileMap);
break;
case ESM::REC_NPC_:
readReferenceCollection<ESM::ObjectState> (reader, mNpcs, contentFileMap);
break;
case ESM::REC_PROB:
readReferenceCollection<ESM::ObjectState> (reader, mProbes, contentFileMap);
break;
case ESM::REC_REPA:
readReferenceCollection<ESM::ObjectState> (reader, mRepairs, contentFileMap);
break;
case ESM::REC_STAT:
readReferenceCollection<ESM::ObjectState> (reader, mStatics, contentFileMap);
break;
case ESM::REC_WEAP:
readReferenceCollection<ESM::ObjectState> (reader, mWeapons, contentFileMap);
break;
default:
throw std::runtime_error ("unknown type in cell reference section");
}
}
}
}

@ -144,6 +144,8 @@ namespace MWWorld
void writeReferences (ESM::ESMWriter& writer) const;
void readReferences (ESM::ESMReader& reader, const std::map<int, int>& contentFileMap);
private:
template<class Functor, class List>

@ -324,12 +324,13 @@ namespace MWWorld
mPlayer->write (writer);
}
void World::readRecord (ESM::ESMReader& reader, int32_t type)
void World::readRecord (ESM::ESMReader& reader, int32_t type,
const std::map<int, int>& contentFileMap)
{
if (!mStore.readRecord (reader, type) &&
!mGlobalVariables.readRecord (reader, type) &&
!mPlayer->readRecord (reader, type) &&
!mCells.readRecord (reader, type))
!mCells.readRecord (reader, type, contentFileMap))
{
throw std::runtime_error ("unknown record in saved game");
}

@ -179,7 +179,8 @@ namespace MWWorld
virtual void write (ESM::ESMWriter& writer) const;
virtual void readRecord (ESM::ESMReader& reader, int32_t type);
virtual void readRecord (ESM::ESMReader& reader, int32_t type,
const std::map<int, int>& contentFileMap);
virtual OEngine::Render::Fader* getFader();
///< \todo remove this function. Rendering details should not be exposed.

@ -90,7 +90,6 @@ enum RecNameInts
REC_GSCR = 0x52435347,
REC_PLAY = 0x59414c50,
REC_CSTA = 0x41545343,
REC_OBJE = 0x454a424f,
REC_GMAP = 0x50414d47,
// format 1

Loading…
Cancel
Save