Pol  Revision:3cfda13
mapserver.cpp
Go to the documentation of this file.
1 
7 #include "mapserver.h"
8 
9 #include <stddef.h>
10 #include <stdexcept>
11 #include <string>
12 
13 #include "../clib/binaryfile.h"
14 #include "../clib/passert.h"
15 #include "../clib/strutil.h"
16 #include "filemapserver.h"
17 #include "inmemorymapserver.h"
18 #include "mapcell.h"
19 #include "mapshape.h"
20 #include "mapsolid.h"
21 
22 namespace Pol
23 {
24 namespace Plib
25 {
26 MapServer::MapServer( const RealmDescriptor& descriptor ) : _descriptor( descriptor )
27 {
28  LoadSolids();
29 
30  // the first-level index points into the second-level index, so load the second-level index first.
32 
34 }
35 
37 
39 {
40  std::string filename = _descriptor.path( "solids.dat" );
41 
42  Clib::BinaryFile infile( filename, std::ios::in );
43  infile.ReadVector( _shapedata );
44 }
45 
47 {
48  std::string filename = _descriptor.path( "solidx2.dat" );
49 
50  Clib::BinaryFile infile( filename, std::ios::in );
51  std::fstream::pos_type filesize = infile.FileSize();
52  if ( filesize < std::fstream::pos_type( SOLIDX2_FILLER_SIZE ) )
53  throw std::runtime_error( filename + " must have size of at least " +
54  Clib::decint( SOLIDX2_FILLER_SIZE ) + " bytes." );
55 
56  std::fstream::pos_type databytes = filesize - std::fstream::pos_type( SOLIDX2_FILLER_SIZE );
57  if ( ( databytes % sizeof( SOLIDX2_ELEM ) ) != 0 )
58  throw std::runtime_error( filename + " does not contain an integral number of elements." );
59 
60  size_t count = static_cast<size_t>( databytes / sizeof( SOLIDX2_ELEM ) );
61  _index2.resize( count );
62  infile.Seek( SOLIDX2_FILLER_SIZE );
63  infile.Read( &_index2[0], count );
64 
65  // integrity check
66  for ( const auto& elem : _index2 )
67  {
68  passert( elem.baseindex < _shapedata.size() );
69 
70  for ( unsigned x = 0; x < SOLIDX_X_SIZE; ++x )
71  {
72  for ( unsigned y = 0; y < SOLIDX_Y_SIZE; ++y )
73  {
74  size_t idx = elem.baseindex + elem.addindex[x][y];
75  passert( idx < _shapedata.size() );
76  }
77  }
78  }
79 }
80 
82 {
83  std::string filename = _descriptor.path( "solidx1.dat" );
84 
85  Clib::BinaryFile infile( filename, std::ios::in );
86 
87  size_t n_blocks = ( _descriptor.width / SOLIDX_X_SIZE ) * ( _descriptor.height / SOLIDX_Y_SIZE );
88  _index1.resize( n_blocks );
89 
90  for ( size_t i = 0; i < n_blocks; ++i )
91  {
92  unsigned int tmp;
93  infile.Read( tmp );
94  if ( tmp )
95  {
96  // tmp is an offset, in the file.. turn it into a pointer into the second-level index.
97  tmp = ( tmp - SOLIDX2_FILLER_SIZE ) / sizeof( SOLIDX2_ELEM );
98  _index1[i] = &_index2.at( tmp );
99  }
100  else
101  {
102  _index1[i] = NULL;
103  }
104  }
105 }
106 
107 void MapServer::GetMapShapes( MapShapeList& shapes, unsigned short x, unsigned short y,
108  unsigned int anyflags ) const
109 {
111 
112  MAPCELL cell = GetMapCell( x, y );
113  MapShape shape;
114 
115  if ( cell.flags & anyflags )
116  {
117  shape.flags = cell.flags;
118  shape.z = cell.z - 1; // assume now map is at z-1 with height 1 for solidity
119  shape.height = 1;
120  shapes.push_back( shape );
121  }
122 
123  if ( cell.flags & FLAG::MORE_SOLIDS )
124  {
125  unsigned short xblock = x >> SOLIDX_X_SHIFT;
126  unsigned short xcell = x & SOLIDX_X_CELLMASK;
127  unsigned short yblock = y >> SOLIDX_Y_SHIFT;
128  unsigned short ycell = y & SOLIDX_Y_CELLMASK;
129 
130  size_t block = static_cast<size_t>( yblock ) * ( _descriptor.width >> SOLIDX_X_SHIFT ) + xblock;
131  SOLIDX2_ELEM* pIndex2 = _index1[block];
132  unsigned int index = pIndex2->baseindex + pIndex2->addindex[xcell][ycell];
133  const SOLIDS_ELEM* pElem = &_shapedata[index];
134  for ( ;; )
135  {
136  if ( pElem->flags & anyflags )
137  {
138  shape.z = pElem->z;
139  shape.height = pElem->height;
140  shape.flags = pElem->flags;
141  shapes.push_back( shape );
142  }
143  if ( pElem->flags & FLAG::MORE_SOLIDS )
144  ++pElem;
145  else
146  break;
147  }
148  }
149 }
150 
152 {
153  if ( descriptor.mapserver_type == "memory" )
154  {
155  return new InMemoryMapServer( descriptor );
156  }
157  else if ( descriptor.mapserver_type == "file" )
158  {
159  return new FileMapServer( descriptor );
160  }
161  else
162  {
163  throw std::runtime_error( "Undefined mapserver type: " + descriptor.mapserver_type );
164  }
165 }
166 
168 {
169  size_t size = sizeof( *this );
170  size += _descriptor.sizeEstimate();
171  size += 3 * sizeof( SOLIDX2_ELEM** ) + _index1.capacity() * sizeof( SOLIDX2_ELEM* );
172  size += 3 * sizeof( SOLIDX2_ELEM* ) + _index2.capacity() * sizeof( SOLIDX2_ELEM );
173  size += 3 * sizeof( SOLIDS_ELEM* ) + _shapedata.capacity() * sizeof( SOLIDS_ELEM );
174  return size;
175 }
176 }
177 }
MapServer(const RealmDescriptor &descriptor)
Definition: mapserver.cpp:26
virtual ~MapServer()
Definition: mapserver.cpp:36
void LoadSecondLevelIndex()
Definition: mapserver.cpp:46
unsigned int flags
Definition: mapshape.h:20
void GetMapShapes(MapShapeList &list, unsigned short x, unsigned short y, unsigned int anyflags) const
Definition: mapserver.cpp:107
#define SOLIDX_Y_SHIFT
Definition: mapblob.h:15
#define SOLIDX_X_SIZE
Definition: mapblob.h:10
std::string decint(unsigned short v)
Definition: strutil.cpp:64
signed char z
Definition: mapblob.h:33
static MapServer * Create(const RealmDescriptor &descriptor)
Definition: mapserver.cpp:151
std::fstream::pos_type FileSize()
Definition: binaryfile.cpp:65
unsigned short addindex[SOLIDX_X_SIZE][SOLIDX_Y_SIZE]
Definition: mapblob.h:29
signed char z
Definition: mapcell.h:50
#define SOLIDX_Y_CELLMASK
Definition: mapblob.h:16
#define SOLIDX_X_SHIFT
Definition: mapblob.h:11
virtual size_t sizeEstimate() const
Definition: mapserver.cpp:167
int filesize(const char *fname)
Definition: fileutil.cpp:127
std::vector< SOLIDS_ELEM > _shapedata
Definition: mapserver.h:43
std::vector< SOLIDX2_ELEM > _index2
Definition: mapserver.h:42
#define passert(exp)
Definition: passert.h:62
virtual MAPCELL GetMapCell(unsigned short x, unsigned short y) const =0
unsigned char flags
Definition: mapcell.h:51
#define SOLIDX_Y_SIZE
Definition: mapblob.h:14
const RealmDescriptor _descriptor
Definition: mapserver.h:37
std::vector< SOLIDX2_ELEM * > _index1
Definition: mapserver.h:41
unsigned char flags
Definition: mapblob.h:35
void Seek(std::fstream::pos_type abs_offset)
Definition: binaryfile.cpp:50
std::string path(const std::string &filename) const
void LoadFirstLevelIndex()
Definition: mapserver.cpp:81
unsigned char height
Definition: mapblob.h:34
void Read(T &val)
Definition: binaryfile.h:29
unsigned int baseindex
Definition: mapblob.h:28
const unsigned SOLIDX2_FILLER_SIZE
Definition: mapblob.h:43
void ReadVector(std::vector< T > &vec)
Definition: binaryfile.h:41
Definition: berror.cpp:12
#define SOLIDX_X_CELLMASK
Definition: mapblob.h:12