mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-03-03 20:19:40 +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(NIF nif/nif_file.cpp nifogre/ogre_nif_loader.cpp)
|
||||||
set(TOOLS tools/stringops.cpp)
|
set(TOOLS tools/stringops.cpp)
|
||||||
set(MANGLE_VFS mangle/vfs/servers/ogre_vfs.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
|
# Platform specific
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
|
|
|
@ -162,12 +162,16 @@ struct Cell
|
||||||
// somewhere other than the file system, you need to pre-open the
|
// somewhere other than the file system, you need to pre-open the
|
||||||
// ESMReader, and the filename must match the stored filename
|
// ESMReader, and the filename must match the stored filename
|
||||||
// exactly.
|
// exactly.
|
||||||
void restore(ESMReader &esm)
|
void restore(ESMReader &esm) const
|
||||||
{ esm.restoreContext(context); }
|
{ esm.restoreContext(context); }
|
||||||
|
|
||||||
// Get the next reference in this cell, if any. Returns false when
|
/* Get the next reference in this cell, if any. Returns false when
|
||||||
// there are no more references in the cell.
|
there are no more references in the cell.
|
||||||
bool getNextRef(ESMReader &esm, CellRef &ref)
|
|
||||||
|
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;
|
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 "esm/records.hpp"
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
namespace ESMS
|
namespace ESMS
|
||||||
{
|
{
|
||||||
|
@ -24,6 +25,7 @@ namespace ESMS
|
||||||
|
|
||||||
MapType list;
|
MapType list;
|
||||||
|
|
||||||
|
// Load one object of this type
|
||||||
void load(ESMReader &esm)
|
void load(ESMReader &esm)
|
||||||
{
|
{
|
||||||
std::string id = esm.getHNString("NAME");
|
std::string id = esm.getHNString("NAME");
|
||||||
|
@ -32,6 +34,14 @@ namespace ESMS
|
||||||
ref.load(esm);
|
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(); }
|
int getSize() { return list.size(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -67,10 +77,22 @@ namespace ESMS
|
||||||
int getSize() { return count; }
|
int getSize() { return count; }
|
||||||
|
|
||||||
// List of interior cells. Indexed by cell name.
|
// 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].
|
// 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)
|
void load(ESMReader &esm)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,19 @@
|
||||||
#ifndef _GAME_ESM_STORE_H
|
#ifndef _GAME_ESM_STORE_H
|
||||||
#define _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/records.hpp"
|
||||||
#include "esm_reclists.hpp"
|
#include "esm_reclists.hpp"
|
||||||
|
|
||||||
|
|
|
@ -1,45 +1,28 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "bsa/bsa_archive.h"
|
|
||||||
#include "esm_store.hpp"
|
#include "esm_store.hpp"
|
||||||
|
#include "cell_store.hpp"
|
||||||
#include "Ogre.h"
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
// Absolute minimal OGRE setup
|
// See setup.cpp
|
||||||
void ogre_setup()
|
void main_setup(const char* bsaFile);
|
||||||
{
|
|
||||||
using namespace Ogre;
|
|
||||||
|
|
||||||
// Disable Ogre logging
|
|
||||||
new LogManager;
|
|
||||||
Log *log = LogManager::getSingleton().createLog("");
|
|
||||||
log->setDebugOutputEnabled(false);
|
|
||||||
|
|
||||||
// Set up Root.
|
|
||||||
new Root();
|
|
||||||
}
|
|
||||||
|
|
||||||
void maintest()
|
void maintest()
|
||||||
{
|
{
|
||||||
const char* bsaFile = "data/Morrowind.bsa";
|
|
||||||
const char* esmFile = "data/Morrowind.esm";
|
const char* esmFile = "data/Morrowind.esm";
|
||||||
|
const char* bsaFile = "data/Morrowind.bsa";
|
||||||
|
|
||||||
cout << "Hello, fellow traveler!\n";
|
main_setup(bsaFile);
|
||||||
|
|
||||||
cout << "Initializing OGRE\n";
|
|
||||||
ogre_setup();
|
|
||||||
|
|
||||||
cout << "Adding " << bsaFile << endl;
|
|
||||||
addBSA(bsaFile);
|
|
||||||
|
|
||||||
cout << "Loading ESM " << esmFile << "\n";
|
cout << "Loading ESM " << esmFile << "\n";
|
||||||
ESM::ESMReader esm;
|
ESM::ESMReader esm;
|
||||||
esm.open(esmFile);
|
|
||||||
ESMS::ESMStore store;
|
ESMS::ESMStore store;
|
||||||
|
ESMS::CellStore cell;
|
||||||
|
|
||||||
|
esm.open(esmFile);
|
||||||
store.load(esm);
|
store.load(esm);
|
||||||
esm.close();
|
cell.loadInt("Beshara", store, esm);
|
||||||
|
|
||||||
cout << "\nThat's all for now!\n";
|
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