@ -96,6 +96,245 @@ void Store<ESM::Cell>::load(ESM::ESMReader &esm)
wipecell - > mLeasedRefs . erase ( it_lease ) ;
* itold = * it ;
}
+ + sharedIter ;
}
mStatic . erase ( it ) ;
}
return true ;
}
template < typename T >
bool Store < T > : : erase ( const std : : string & id )
{
std : : string key = Misc : : StringUtils : : lowerCase ( id ) ;
typename Dynamic : : iterator it = mDynamic . find ( key ) ;
if ( it = = mDynamic . end ( ) ) {
return false ;
}
mDynamic . erase ( it ) ;
// have to reinit the whole shared part
assert ( mShared . size ( ) > = mStatic . size ( ) ) ;
mShared . erase ( mShared . begin ( ) + mStatic . size ( ) , mShared . end ( ) ) ;
for ( it = mDynamic . begin ( ) ; it ! = mDynamic . end ( ) ; + + it ) {
mShared . push_back ( & it - > second ) ;
}
return true ;
}
template < typename T >
bool Store < T > : : erase ( const T & item )
{
return erase ( item . mId ) ;
}
template < typename T >
void Store < T > : : write ( ESM : : ESMWriter & writer , Loading : : Listener & progress ) const
{
for ( typename Dynamic : : const_iterator iter ( mDynamic . begin ( ) ) ; iter ! = mDynamic . end ( ) ;
+ + iter )
{
writer . startRecord ( T : : sRecordId ) ;
iter - > second . save ( writer ) ;
writer . endRecord ( T : : sRecordId ) ;
}
}
template < typename T >
RecordId Store < T > : : read ( ESM : : ESMReader & reader )
{
T record ;
bool isDeleted = false ;
record . load ( reader , isDeleted ) ;
insert ( record ) ;
return RecordId ( record . mId , isDeleted ) ;
}
// LandTexture
//=========================================================================
Store < ESM : : LandTexture > : : Store ( )
{
mStatic . push_back ( LandTextureList ( ) ) ;
LandTextureList & ltexl = mStatic [ 0 ] ;
// More than enough to hold Morrowind.esm. Extra lists for plugins will we
// added on-the-fly in a different method.
ltexl . reserve ( 128 ) ;
}
const ESM : : LandTexture * Store < ESM : : LandTexture > : : search ( size_t index , size_t plugin ) const
{
assert ( plugin < mStatic . size ( ) ) ;
const LandTextureList & ltexl = mStatic [ plugin ] ;
if ( index > = ltexl . size ( ) )
return NULL ;
return & ltexl [ index ] ;
}
const ESM : : LandTexture * Store < ESM : : LandTexture > : : find ( size_t index , size_t plugin ) const
{
const ESM : : LandTexture * ptr = search ( index , plugin ) ;
if ( ptr = = 0 ) {
std : : ostringstream msg ;
msg < < " Land texture with index " < < index < < " not found " ;
throw std : : runtime_error ( msg . str ( ) ) ;
}
return ptr ;
}
size_t Store < ESM : : LandTexture > : : getSize ( ) const
{
return mStatic . size ( ) ;
}
size_t Store < ESM : : LandTexture > : : getSize ( size_t plugin ) const
{
assert ( plugin < mStatic . size ( ) ) ;
return mStatic [ plugin ] . size ( ) ;
}
RecordId Store < ESM : : LandTexture > : : load ( ESM : : ESMReader & esm , size_t plugin )
{
ESM : : LandTexture lt ;
bool isDeleted = false ;
lt . load ( esm , isDeleted ) ;
assert ( plugin < mStatic . size ( ) ) ;
LandTextureList & ltexl = mStatic [ plugin ] ;
if ( lt . mIndex + 1 > ( int ) ltexl . size ( ) )
ltexl . resize ( lt . mIndex + 1 ) ;
// Store it
ltexl [ lt . mIndex ] = lt ;
return RecordId ( lt . mId , isDeleted ) ;
}
RecordId Store < ESM : : LandTexture > : : load ( ESM : : ESMReader & esm )
{
return load ( esm , esm . getIndex ( ) ) ;
}
Store < ESM : : LandTexture > : : iterator Store < ESM : : LandTexture > : : begin ( size_t plugin ) const
{
assert ( plugin < mStatic . size ( ) ) ;
return mStatic [ plugin ] . begin ( ) ;
}
Store < ESM : : LandTexture > : : iterator Store < ESM : : LandTexture > : : end ( size_t plugin ) const
{
assert ( plugin < mStatic . size ( ) ) ;
return mStatic [ plugin ] . end ( ) ;
}
void Store < ESM : : LandTexture > : : resize ( size_t num )
{
if ( mStatic . size ( ) < num )
mStatic . resize ( num ) ;
}
// Land
//=========================================================================
Store < ESM : : Land > : : ~ Store ( )
{
for ( std : : vector < ESM : : Land * > : : const_iterator it =
mStatic . begin ( ) ; it ! = mStatic . end ( ) ; + + it )
{
delete * it ;
}
}
size_t Store < ESM : : Land > : : getSize ( ) const
{
return mStatic . size ( ) ;
}
Store < ESM : : Land > : : iterator Store < ESM : : Land > : : begin ( ) const
{
return iterator ( mStatic . begin ( ) ) ;
}
Store < ESM : : Land > : : iterator Store < ESM : : Land > : : end ( ) const
{
return iterator ( mStatic . end ( ) ) ;
}
ESM : : Land * Store < ESM : : Land > : : search ( int x , int y ) const
{
ESM : : Land land ;
land . mX = x , land . mY = y ;
std : : vector < ESM : : Land * > : : const_iterator it =
std : : lower_bound ( mStatic . begin ( ) , mStatic . end ( ) , & land , Compare ( ) ) ;
if ( it ! = mStatic . end ( ) & & ( * it ) - > mX = = x & & ( * it ) - > mY = = y ) {
return const_cast < ESM : : Land * > ( * it ) ;
}
return 0 ;
}
ESM : : Land * Store < ESM : : Land > : : find ( int x , int y ) const
{
ESM : : Land * ptr = search ( x , y ) ;
if ( ptr = = 0 ) {
std : : ostringstream msg ;
msg < < " Land at ( " < < x < < " , " < < y < < " ) not found " ;
throw std : : runtime_error ( msg . str ( ) ) ;
}
return ptr ;
}
RecordId Store < ESM : : Land > : : load ( ESM : : ESMReader & esm )
{
ESM : : Land * ptr = new ESM : : Land ( ) ;
bool isDeleted = false ;
ptr - > load ( esm , isDeleted ) ;
// Same area defined in multiple plugins? -> last plugin wins
// Can't use search() because we aren't sorted yet - is there any other way to speed this up?
for ( std : : vector < ESM : : Land * > : : iterator it = mStatic . begin ( ) ; it ! = mStatic . end ( ) ; + + it )
{
if ( ( * it ) - > mX = = ptr - > mX & & ( * it ) - > mY = = ptr - > mY )
{
delete * it ;
mStatic . erase ( it ) ;
break ;
}
}
mStatic . push_back ( ptr ) ;
return RecordId ( " " , isDeleted ) ;
}
void Store < ESM : : Land > : : setUp ( )
{
std : : sort ( mStatic . begin ( ) , mStatic . end ( ) , Compare ( ) ) ;
}
// Cell
//=========================================================================
const ESM : : Cell * Store < ESM : : Cell > : : search ( const ESM : : Cell & cell ) const
{
if ( cell . isExterior ( ) ) {
return search ( cell . getGridX ( ) , cell . getGridY ( ) ) ;
}
return search ( cell . mName ) ;
}
void Store < ESM : : Cell > : : handleMovedCellRefs ( ESM : : ESMReader & esm , ESM : : Cell * cell )
{
//Handling MovedCellRefs, there is no way to do it inside loadcell
while ( esm . isNextSub ( " MVRF " ) ) {
ESM : : CellRef ref ;
ESM : : MovedCellRef cMRef ;
cell - > getNextMVRF ( esm , cMRef ) ;
ESM : : Cell * cellAlt = const_cast < ESM : : Cell * > ( searchOrCreate ( cMRef . mTarget [ 0 ] , cMRef . mTarget [ 1 ] ) ) ;
// Get regular moved reference data. Adapted from CellStore::loadRefs. Maybe we can optimize the following
// implementation when the oher implementation works as well.
bool deleted = false ;
cell - > getNextRef ( esm , ref , deleted ) ;
// Add data required to make reference appear in the correct cell.
// We should not need to test for duplicates, as this part of the code is pre-cell merge.
cell - > mMovedRefs . push_back ( cMRef ) ;
// But there may be duplicates here!
if ( ! deleted )
{
ESM : : CellRefTracker : : iterator iter = std : : find ( cellAlt - > mLeasedRefs . begin ( ) , cellAlt - > mLeasedRefs . end ( ) , ref . mRefNum ) ;
if ( iter = = cellAlt - > mLeasedRefs . end ( ) )
cellAlt - > mLeasedRefs . push_back ( ref ) ;
else
oldcell - > mMovedRefs . push_back ( * it ) ;
}