mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-20 23:09:42 +00:00
Created (a very slow) cell loader. Will optimize.
This commit is contained in:
parent
46e09c5c75
commit
bdb6896c3f
8 changed files with 257 additions and 33 deletions
|
@ -11,7 +11,7 @@ set(BSA bsa/bsa_archive.cpp bsa/bsa_file.cpp)
|
|||
set(NIF nif/nif_file.cpp nifogre/ogre_nif_loader.cpp)
|
||||
set(TOOLS tools/stringops.cpp)
|
||||
set(MANGLE_VFS mangle/vfs/servers/ogre_vfs.cpp)
|
||||
set(GAME game/main.cpp game/esm_store.cpp)
|
||||
set(GAME game/main.cpp game/esm_store.cpp game/cell_store.cpp game/setup.cpp)
|
||||
|
||||
# Platform specific
|
||||
if (WIN32)
|
||||
|
|
|
@ -162,12 +162,16 @@ struct Cell
|
|||
// somewhere other than the file system, you need to pre-open the
|
||||
// ESMReader, and the filename must match the stored filename
|
||||
// exactly.
|
||||
void restore(ESMReader &esm)
|
||||
void restore(ESMReader &esm) const
|
||||
{ esm.restoreContext(context); }
|
||||
|
||||
// Get the next reference in this cell, if any. Returns false when
|
||||
// there are no more references in the cell.
|
||||
bool getNextRef(ESMReader &esm, CellRef &ref)
|
||||
/* Get the next reference in this cell, if any. Returns false when
|
||||
there are no more references in the cell.
|
||||
|
||||
All fields of the CellRef struct are overwritten. You can safely
|
||||
reuse one memory location without blanking it between calls.
|
||||
*/
|
||||
static bool getNextRef(ESMReader &esm, CellRef &ref)
|
||||
{
|
||||
if(!esm.hasMoreSubs()) return false;
|
||||
|
||||
|
|
63
game/cell_store.cpp
Normal file
63
game/cell_store.cpp
Normal file
|
@ -0,0 +1,63 @@
|
|||
#include "cell_store.hpp"
|
||||
#include <iostream>
|
||||
#include "mangle/tools/str_exception.h"
|
||||
|
||||
using namespace ESMS;
|
||||
using namespace std;
|
||||
|
||||
void CellStore::loadInt(const std::string &name, const ESMStore &store, ESMReader &esm)
|
||||
{
|
||||
cout << "loading cell '" << name << "'\n";
|
||||
|
||||
const Cell *ref = store.cells.findInt(name);
|
||||
|
||||
if(ref == NULL)
|
||||
throw str_exception("Cell not found - " + name);
|
||||
|
||||
loadRefs(*ref, store, esm);
|
||||
}
|
||||
|
||||
void CellStore::loadExt(int X, int Y, const ESMStore &store, ESMReader &esm)
|
||||
{
|
||||
}
|
||||
|
||||
void CellStore::loadRefs(const Cell &cell, const ESMStore &store, ESMReader &esm)
|
||||
{
|
||||
// Reopen the ESM reader and seek to the right position.
|
||||
cell.restore(esm);
|
||||
|
||||
CellRef ref;
|
||||
|
||||
// Get each reference in turn
|
||||
while(cell.getNextRef(esm, ref))
|
||||
{
|
||||
cout << "Reference: " << ref.refID;
|
||||
|
||||
// Check each list in turn. Potential for optimization.
|
||||
if(
|
||||
activators .find(ref, store.activators) &&
|
||||
potions .find(ref, store.potions) &&
|
||||
appas .find(ref, store.appas) &&
|
||||
armors .find(ref, store.armors) &&
|
||||
books .find(ref, store.books) &&
|
||||
clothes .find(ref, store.clothes) &&
|
||||
containers .find(ref, store.containers) &&
|
||||
creatures .find(ref, store.creatures) &&
|
||||
doors .find(ref, store.doors) &&
|
||||
ingreds .find(ref, store.ingreds) &&
|
||||
creatureLists .find(ref, store.creatureLists) &&
|
||||
itemLists .find(ref, store.itemLists) &&
|
||||
lights .find(ref, store.lights) &&
|
||||
lockpicks .find(ref, store.lockpicks) &&
|
||||
miscItems .find(ref, store.miscItems) &&
|
||||
npcs .find(ref, store.npcs) &&
|
||||
probes .find(ref, store.probes) &&
|
||||
repairs .find(ref, store.repairs) &&
|
||||
statics .find(ref, store.statics) &&
|
||||
weapons .find(ref, store.weapons)
|
||||
|
||||
) cout << " (NOT FOUND)";
|
||||
|
||||
cout << endl;
|
||||
}
|
||||
}
|
103
game/cell_store.hpp
Normal file
103
game/cell_store.hpp
Normal file
|
@ -0,0 +1,103 @@
|
|||
#ifndef _GAME_CELL_STORE_H
|
||||
#define _GAME_CELL_STORE_H
|
||||
|
||||
/*
|
||||
Cell storage.
|
||||
|
||||
Used to load, look up and store all references in a single cell.
|
||||
|
||||
Depends on esm/loadcell.hpp (loading from ESM) and esm_store.hpp
|
||||
(looking up references.) Neither of these modules depend on us.
|
||||
*/
|
||||
|
||||
#include "esm_store.hpp"
|
||||
#include "esm/records.hpp"
|
||||
#include <list>
|
||||
|
||||
namespace ESMS
|
||||
{
|
||||
using namespace ESM;
|
||||
|
||||
/// A reference to one object (of any type) in a cell.
|
||||
template <typename X>
|
||||
struct LiveCellRef
|
||||
{
|
||||
// The object that this instance is based on.
|
||||
const X* base;
|
||||
|
||||
/* Information about this instance, such as 3D location and
|
||||
rotation and individual type-dependent data.
|
||||
*/
|
||||
CellRef ref;
|
||||
|
||||
/* Pointer to any user-defined or engine-specific object. Eg. a
|
||||
Sound object for sound sources.
|
||||
*/
|
||||
void *custom;
|
||||
};
|
||||
|
||||
/// A list of cell references
|
||||
template <typename X>
|
||||
struct CellRefList
|
||||
{
|
||||
typedef LiveCellRef<X> LiveRef;
|
||||
std::list<LiveRef> list;
|
||||
|
||||
// Search for the given reference in the given reclist from
|
||||
// ESMStore. Insert the reference into the list if a match is
|
||||
// found, and returns false. Returns true if no match is found.
|
||||
template <typename Y>
|
||||
bool find(CellRef &ref, Y recList)
|
||||
{
|
||||
const X* obj = recList.find(ref.refID);
|
||||
if(obj == NULL) return true;
|
||||
|
||||
LiveRef lr;
|
||||
lr.ref = ref;
|
||||
lr.base = obj;
|
||||
lr.custom = NULL;
|
||||
|
||||
list.push_back(lr);
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/// A storage struct for one single cell reference.
|
||||
struct CellStore
|
||||
{
|
||||
// Lists for each individual object type
|
||||
CellRefList<Activator> activators;
|
||||
CellRefList<Potion> potions;
|
||||
CellRefList<Apparatus> appas;
|
||||
CellRefList<Armor> armors;
|
||||
CellRefList<Book> books;
|
||||
CellRefList<Clothing> clothes;
|
||||
CellRefList<Container> containers;
|
||||
CellRefList<Creature> creatures;
|
||||
CellRefList<Door> doors;
|
||||
CellRefList<Ingredient> ingreds;
|
||||
CellRefList<CreatureLevList> creatureLists;
|
||||
CellRefList<ItemLevList> itemLists;
|
||||
CellRefList<Light> lights;
|
||||
CellRefList<Tool> lockpicks;
|
||||
CellRefList<Misc> miscItems;
|
||||
CellRefList<NPC> npcs;
|
||||
CellRefList<Tool> probes;
|
||||
CellRefList<Tool> repairs;
|
||||
CellRefList<Static> statics;
|
||||
CellRefList<Weapon> weapons;
|
||||
|
||||
/** Look up and load an interior cell from the given ESM data
|
||||
storage. */
|
||||
void loadInt(const std::string &name, const ESMStore &data, ESMReader &esm);
|
||||
|
||||
/** Ditto for exterior cell. */
|
||||
void loadExt(int X, int Y, const ESMStore &data, ESMReader &esm);
|
||||
|
||||
private:
|
||||
void loadRefs(const Cell &cell, const ESMStore &data, ESMReader &esm);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -4,6 +4,7 @@
|
|||
#include "esm/records.hpp"
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <assert.h>
|
||||
|
||||
namespace ESMS
|
||||
{
|
||||
|
@ -24,6 +25,7 @@ namespace ESMS
|
|||
|
||||
MapType list;
|
||||
|
||||
// Load one object of this type
|
||||
void load(ESMReader &esm)
|
||||
{
|
||||
std::string id = esm.getHNString("NAME");
|
||||
|
@ -32,6 +34,14 @@ namespace ESMS
|
|||
ref.load(esm);
|
||||
}
|
||||
|
||||
// Find the given object ID, or return NULL if not found.
|
||||
const X* find(const std::string &id) const
|
||||
{
|
||||
if(list.find(id) == list.end())
|
||||
return NULL;
|
||||
return &list.find(id)->second;
|
||||
}
|
||||
|
||||
int getSize() { return list.size(); }
|
||||
};
|
||||
|
||||
|
@ -67,10 +77,22 @@ namespace ESMS
|
|||
int getSize() { return count; }
|
||||
|
||||
// List of interior cells. Indexed by cell name.
|
||||
std::map<std::string,Cell> intCells;
|
||||
typedef std::map<std::string,Cell> IntCells;
|
||||
IntCells intCells;
|
||||
|
||||
// List of exterior cells. Indexed as extCells[gridX][gridY].
|
||||
std::map<int, std::map<int, Cell> > extCells;
|
||||
typedef std::map<int, std::map<int, Cell> > ExtCells;
|
||||
ExtCells extCells;
|
||||
|
||||
const Cell* findInt(const std::string &id) const
|
||||
{
|
||||
IntCells::const_iterator it = intCells.find(id);
|
||||
|
||||
if(it == intCells.end())
|
||||
return NULL;
|
||||
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
void load(ESMReader &esm)
|
||||
{
|
||||
|
|
|
@ -1,6 +1,19 @@
|
|||
#ifndef _GAME_ESM_STORE_H
|
||||
#define _GAME_ESM_STORE_H
|
||||
|
||||
/*
|
||||
The ESM storage module.
|
||||
|
||||
This is separate from the ESM loader module, located in esm/. It is
|
||||
also unaware of the cell loading and storage module.
|
||||
|
||||
The advantage of this, as with all other modularizations, is that
|
||||
you can replace the storage method later without touching the
|
||||
loading code. Cutting down dependencies also help on the general
|
||||
maintainability.
|
||||
|
||||
*/
|
||||
|
||||
#include "esm/records.hpp"
|
||||
#include "esm_reclists.hpp"
|
||||
|
||||
|
|
|
@ -1,45 +1,28 @@
|
|||
#include <iostream>
|
||||
|
||||
#include "bsa/bsa_archive.h"
|
||||
#include "esm_store.hpp"
|
||||
|
||||
#include "Ogre.h"
|
||||
#include "cell_store.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Absolute minimal OGRE setup
|
||||
void ogre_setup()
|
||||
{
|
||||
using namespace Ogre;
|
||||
|
||||
// Disable Ogre logging
|
||||
new LogManager;
|
||||
Log *log = LogManager::getSingleton().createLog("");
|
||||
log->setDebugOutputEnabled(false);
|
||||
|
||||
// Set up Root.
|
||||
new Root();
|
||||
}
|
||||
// See setup.cpp
|
||||
void main_setup(const char* bsaFile);
|
||||
|
||||
void maintest()
|
||||
{
|
||||
const char* bsaFile = "data/Morrowind.bsa";
|
||||
const char* esmFile = "data/Morrowind.esm";
|
||||
const char* bsaFile = "data/Morrowind.bsa";
|
||||
|
||||
cout << "Hello, fellow traveler!\n";
|
||||
|
||||
cout << "Initializing OGRE\n";
|
||||
ogre_setup();
|
||||
|
||||
cout << "Adding " << bsaFile << endl;
|
||||
addBSA(bsaFile);
|
||||
main_setup(bsaFile);
|
||||
|
||||
cout << "Loading ESM " << esmFile << "\n";
|
||||
ESM::ESMReader esm;
|
||||
esm.open(esmFile);
|
||||
ESMS::ESMStore store;
|
||||
ESMS::CellStore cell;
|
||||
|
||||
esm.open(esmFile);
|
||||
store.load(esm);
|
||||
esm.close();
|
||||
cell.loadInt("Beshara", store, esm);
|
||||
|
||||
cout << "\nThat's all for now!\n";
|
||||
}
|
||||
|
|
36
game/setup.cpp
Normal file
36
game/setup.cpp
Normal file
|
@ -0,0 +1,36 @@
|
|||
/* Split off into a separate file just to increase compile
|
||||
speed. Parsing Ogre.h takes a long time, and the Ogre-dependent
|
||||
part doesn't change much. This entire layout will change later.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include "bsa/bsa_archive.h"
|
||||
#include "Ogre.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Absolute minimal OGRE setup
|
||||
void ogre_setup()
|
||||
{
|
||||
using namespace Ogre;
|
||||
|
||||
// Disable Ogre logging
|
||||
new LogManager;
|
||||
Log *log = LogManager::getSingleton().createLog("");
|
||||
log->setDebugOutputEnabled(false);
|
||||
|
||||
// Set up Root.
|
||||
new Root();
|
||||
}
|
||||
|
||||
void main_setup(const char* bsaFile)
|
||||
{
|
||||
cout << "Hello, fellow traveler!\n";
|
||||
|
||||
cout << "Initializing OGRE\n";
|
||||
ogre_setup();
|
||||
|
||||
cout << "Adding " << bsaFile << endl;
|
||||
addBSA(bsaFile);
|
||||
}
|
||||
|
Loading…
Reference in a new issue