2016-01-28 14:52:40 +01:00
|
|
|
/** @file
|
|
|
|
|
*
|
|
|
|
|
* @par History
|
|
|
|
|
*/
|
2016-02-11 22:54:43 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "mapserver.h"
|
|
|
|
|
|
2018-01-29 21:55:48 +01:00
|
|
|
#include <stddef.h>
|
|
|
|
|
#include <stdexcept>
|
|
|
|
|
#include <string>
|
2016-02-11 22:54:43 +01:00
|
|
|
|
|
|
|
|
#include "../clib/binaryfile.h"
|
|
|
|
|
#include "../clib/passert.h"
|
|
|
|
|
#include "../clib/strutil.h"
|
2018-01-29 21:55:48 +01:00
|
|
|
#include "filemapserver.h"
|
|
|
|
|
#include "inmemorymapserver.h"
|
|
|
|
|
#include "mapcell.h"
|
|
|
|
|
#include "mapshape.h"
|
|
|
|
|
#include "mapsolid.h"
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
namespace Pol
|
|
|
|
|
{
|
|
|
|
|
namespace Plib
|
|
|
|
|
{
|
|
|
|
|
MapServer::MapServer( const RealmDescriptor& descriptor ) : _descriptor( descriptor )
|
|
|
|
|
{
|
|
|
|
|
LoadSolids();
|
|
|
|
|
|
|
|
|
|
// the first-level index points into the second-level index, so load the second-level index first.
|
|
|
|
|
LoadSecondLevelIndex();
|
|
|
|
|
|
|
|
|
|
LoadFirstLevelIndex();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MapServer::LoadSolids()
|
|
|
|
|
{
|
|
|
|
|
std::string filename = _descriptor.path( "solids.dat" );
|
|
|
|
|
|
|
|
|
|
Clib::BinaryFile infile( filename, std::ios::in );
|
|
|
|
|
infile.ReadVector( _shapedata );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MapServer::LoadSecondLevelIndex()
|
|
|
|
|
{
|
|
|
|
|
std::string filename = _descriptor.path( "solidx2.dat" );
|
|
|
|
|
|
|
|
|
|
Clib::BinaryFile infile( filename, std::ios::in );
|
|
|
|
|
std::fstream::pos_type filesize = infile.FileSize();
|
|
|
|
|
if ( filesize < std::fstream::pos_type( SOLIDX2_FILLER_SIZE ) )
|
|
|
|
|
throw std::runtime_error( filename + " must have size of at least " +
|
2018-10-28 09:31:58 +01:00
|
|
|
Clib::tostring( SOLIDX2_FILLER_SIZE ) + " bytes." );
|
2016-02-19 19:26:35 +01:00
|
|
|
|
|
|
|
|
std::fstream::pos_type databytes = filesize - std::fstream::pos_type( SOLIDX2_FILLER_SIZE );
|
|
|
|
|
if ( ( databytes % sizeof( SOLIDX2_ELEM ) ) != 0 )
|
|
|
|
|
throw std::runtime_error( filename + " does not contain an integral number of elements." );
|
|
|
|
|
|
|
|
|
|
size_t count = static_cast<size_t>( databytes / sizeof( SOLIDX2_ELEM ) );
|
|
|
|
|
_index2.resize( count );
|
|
|
|
|
infile.Seek( SOLIDX2_FILLER_SIZE );
|
|
|
|
|
infile.Read( &_index2[0], count );
|
|
|
|
|
|
|
|
|
|
// integrity check
|
|
|
|
|
for ( const auto& elem : _index2 )
|
|
|
|
|
{
|
|
|
|
|
passert( elem.baseindex < _shapedata.size() );
|
|
|
|
|
|
|
|
|
|
for ( unsigned x = 0; x < SOLIDX_X_SIZE; ++x )
|
2016-02-11 22:54:43 +01:00
|
|
|
{
|
2016-02-19 19:26:35 +01:00
|
|
|
for ( unsigned y = 0; y < SOLIDX_Y_SIZE; ++y )
|
|
|
|
|
{
|
|
|
|
|
size_t idx = elem.baseindex + elem.addindex[x][y];
|
|
|
|
|
passert( idx < _shapedata.size() );
|
|
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
}
|
|
|
|
|
}
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MapServer::LoadFirstLevelIndex()
|
|
|
|
|
{
|
|
|
|
|
std::string filename = _descriptor.path( "solidx1.dat" );
|
|
|
|
|
|
|
|
|
|
Clib::BinaryFile infile( filename, std::ios::in );
|
|
|
|
|
|
|
|
|
|
size_t n_blocks = ( _descriptor.width / SOLIDX_X_SIZE ) * ( _descriptor.height / SOLIDX_Y_SIZE );
|
|
|
|
|
_index1.resize( n_blocks );
|
|
|
|
|
|
|
|
|
|
for ( size_t i = 0; i < n_blocks; ++i )
|
|
|
|
|
{
|
|
|
|
|
unsigned int tmp;
|
|
|
|
|
infile.Read( tmp );
|
|
|
|
|
if ( tmp )
|
|
|
|
|
{
|
|
|
|
|
// tmp is an offset, in the file.. turn it into a pointer into the second-level index.
|
|
|
|
|
tmp = ( tmp - SOLIDX2_FILLER_SIZE ) / sizeof( SOLIDX2_ELEM );
|
|
|
|
|
_index1[i] = &_index2.at( tmp );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-10-09 16:36:35 +02:00
|
|
|
_index1[i] = nullptr;
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MapServer::GetMapShapes( MapShapeList& shapes, unsigned short x, unsigned short y,
|
|
|
|
|
unsigned int anyflags ) const
|
|
|
|
|
{
|
|
|
|
|
passert( x < _descriptor.width && y < _descriptor.height );
|
|
|
|
|
|
|
|
|
|
MAPCELL cell = GetMapCell( x, y );
|
|
|
|
|
MapShape shape;
|
|
|
|
|
|
|
|
|
|
if ( cell.flags & anyflags )
|
|
|
|
|
{
|
|
|
|
|
shape.flags = cell.flags;
|
|
|
|
|
shape.z = cell.z - 1; // assume now map is at z-1 with height 1 for solidity
|
|
|
|
|
shape.height = 1;
|
|
|
|
|
shapes.push_back( shape );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( cell.flags & FLAG::MORE_SOLIDS )
|
|
|
|
|
{
|
|
|
|
|
unsigned short xblock = x >> SOLIDX_X_SHIFT;
|
|
|
|
|
unsigned short xcell = x & SOLIDX_X_CELLMASK;
|
|
|
|
|
unsigned short yblock = y >> SOLIDX_Y_SHIFT;
|
|
|
|
|
unsigned short ycell = y & SOLIDX_Y_CELLMASK;
|
|
|
|
|
|
2016-12-09 20:12:12 +01:00
|
|
|
size_t block = static_cast<size_t>( yblock ) * ( _descriptor.width >> SOLIDX_X_SHIFT ) + xblock;
|
2016-02-19 19:26:35 +01:00
|
|
|
SOLIDX2_ELEM* pIndex2 = _index1[block];
|
|
|
|
|
unsigned int index = pIndex2->baseindex + pIndex2->addindex[xcell][ycell];
|
|
|
|
|
const SOLIDS_ELEM* pElem = &_shapedata[index];
|
|
|
|
|
for ( ;; )
|
|
|
|
|
{
|
|
|
|
|
if ( pElem->flags & anyflags )
|
|
|
|
|
{
|
|
|
|
|
shape.z = pElem->z;
|
|
|
|
|
shape.height = pElem->height;
|
|
|
|
|
shape.flags = pElem->flags;
|
|
|
|
|
shapes.push_back( shape );
|
|
|
|
|
}
|
|
|
|
|
if ( pElem->flags & FLAG::MORE_SOLIDS )
|
|
|
|
|
++pElem;
|
|
|
|
|
else
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MapServer* MapServer::Create( const RealmDescriptor& descriptor )
|
|
|
|
|
{
|
|
|
|
|
if ( descriptor.mapserver_type == "memory" )
|
|
|
|
|
{
|
|
|
|
|
return new InMemoryMapServer( descriptor );
|
|
|
|
|
}
|
|
|
|
|
else if ( descriptor.mapserver_type == "file" )
|
|
|
|
|
{
|
|
|
|
|
return new FileMapServer( descriptor );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
throw std::runtime_error( "Undefined mapserver type: " + descriptor.mapserver_type );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t MapServer::sizeEstimate() const
|
|
|
|
|
{
|
|
|
|
|
size_t size = sizeof( *this );
|
|
|
|
|
size += _descriptor.sizeEstimate();
|
|
|
|
|
size += 3 * sizeof( SOLIDX2_ELEM** ) + _index1.capacity() * sizeof( SOLIDX2_ELEM* );
|
|
|
|
|
size += 3 * sizeof( SOLIDX2_ELEM* ) + _index2.capacity() * sizeof( SOLIDX2_ELEM );
|
|
|
|
|
size += 3 * sizeof( SOLIDS_ELEM* ) + _shapedata.capacity() * sizeof( SOLIDS_ELEM );
|
|
|
|
|
return size;
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-12-09 20:12:12 +01:00
|
|
|
}
|