Add a hash mechanism to BaseMapSource.
This is needed to recognize what type of tiles a layer contains. Client code has to fill in a map of hash => add_layer<T>() pointers. As a layer is loaded, the correct add_layer<T>() is called based on the hash saved with the layer itself.
This commit is contained in:
parent
d21a567fb7
commit
fd8a1cbabc
20 changed files with 1647 additions and 40 deletions
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "doorkeeper/implem/maptypes.hpp"
|
||||
#include "doorkeeper/primitivetypes.hpp"
|
||||
#include "doorkeeper/helpers/hashing.hpp"
|
||||
#include "doorkeeper/implem/coords_utils.hpp"
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
@ -33,6 +34,7 @@ namespace dk {
|
|||
virtual MapTypes mapType ( void ) const = 0;
|
||||
virtual int layersCount ( void ) const = 0;
|
||||
virtual void chainedMaps ( std::vector<std::string>& parOut ) const = 0;
|
||||
virtual HashType layerTypeHash ( int parIndex ) const = 0;
|
||||
|
||||
protected:
|
||||
virtual void fetch_raw ( char* parOut, const coords& parFrom, const coords& parTo, std::size_t parSize ) = 0;
|
||||
|
|
|
@ -29,9 +29,11 @@ namespace dk {
|
|||
const coords& map_size ( void ) const { return m_size; }
|
||||
|
||||
template <typename T>
|
||||
Layer<T, D>& push_layer ( BaseMapSource<D>* parTilemap );
|
||||
Layer<T, D>& push_layer ( BaseMapSource<D>* parTilemap, int parIndex );
|
||||
template <typename T>
|
||||
Layer<T, D>& push_layer ( BaseMapSource<D>* parTilemap, const coords& parSubdiv );
|
||||
Layer<T, D>& push_layer ( BaseMapSource<D>* parTilemap, const coords& parSubdiv, int parIndex );
|
||||
template <typename T>
|
||||
void push_layer_void ( BaseMapSource<D>* parTilemap, int parIndex );
|
||||
|
||||
void preload ( const coords& parFrom, const coords& parTo );
|
||||
|
||||
|
|
|
@ -13,11 +13,11 @@ namespace dk {
|
|||
} //namespace dk
|
||||
|
||||
namespace dkh {
|
||||
template <typename T, uint32_t D, typename C>
|
||||
template <uint32_t D, typename C>
|
||||
struct MapLoaderPool;
|
||||
|
||||
template <typename T, typename C>
|
||||
using MapLoaderPool2d = MapLoaderPool<T, 2, C>;
|
||||
template <typename C>
|
||||
using MapLoaderPool2d = MapLoaderPool<2, C>;
|
||||
} //namespace dkh
|
||||
|
||||
#endif
|
||||
|
|
|
@ -33,6 +33,7 @@ namespace dkh {
|
|||
virtual int layersCount ( void ) const;
|
||||
virtual const coords& tileSize ( void ) const;
|
||||
virtual void chainedMaps ( std::vector<std::string>& parOut ) const;
|
||||
virtual dk::HashType layerTypeHash ( int parIndex ) const;
|
||||
|
||||
private:
|
||||
void parse_map_data ( std::istream& parSrc );
|
||||
|
|
30
include/doorkeeper/helpers/hashing.hpp
Normal file
30
include/doorkeeper/helpers/hashing.hpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
#ifndef id4E5F8A0ABA6047BA988D512351B9DD2D
|
||||
#define id4E5F8A0ABA6047BA988D512351B9DD2D
|
||||
|
||||
//#include "doorkeeper/implem/string_bt.hpp"
|
||||
#include "doorkeeper/implem/compatibility.h"
|
||||
#include <cstdint>
|
||||
#include <ciso646>
|
||||
|
||||
namespace dk {
|
||||
namespace implem {
|
||||
struct HashType {
|
||||
uint64_t a;
|
||||
uint64_t b;
|
||||
uint64_t c;
|
||||
|
||||
bool operator< ( const HashType& parOther ) const;
|
||||
};
|
||||
|
||||
HashType hash_string ( const char* parString, std::size_t parLen ) a_pure;
|
||||
} //namespace implem
|
||||
|
||||
typedef dk::implem::HashType HashType;
|
||||
|
||||
template <typename T, uint32_t D>
|
||||
implem::HashType make_signature_hash ( void ) a_pure;
|
||||
} //namespace dk
|
||||
|
||||
#include "doorkeeper/implem/hashing.inl"
|
||||
|
||||
#endif
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include "doorkeeper/components/tyler.hpp"
|
||||
#include "doorkeeper/components/basemapsource.hpp"
|
||||
#include "doorkeeper/helpers/hashing.hpp"
|
||||
#include "doorkeeper/components/exception.hpp"
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
|
@ -12,14 +14,16 @@
|
|||
#include <ciso646>
|
||||
|
||||
namespace dkh {
|
||||
template <typename T, uint32_t D, typename C>
|
||||
template <uint32_t D>
|
||||
using PushLayerMapType = std::map<dk::HashType, void(dk::Tyler<D>::*)(dk::BaseMapSource<D>*,int)>;
|
||||
|
||||
template <uint32_t D, typename C>
|
||||
struct MapLoaderPool {
|
||||
typedef std::unique_ptr<dk::BaseMapSource<D>> BaseMapSourceUPtr;
|
||||
typedef std::map<std::string, BaseMapSourceUPtr> PoolMapType;
|
||||
|
||||
enum { dimensions = D };
|
||||
typedef C opener_type;
|
||||
typedef T tile_type;
|
||||
|
||||
PoolMapType pool;
|
||||
C opener;
|
||||
|
@ -27,17 +31,25 @@ namespace dkh {
|
|||
dk::BaseMapSource<D>* operator() ( const std::string& parName );
|
||||
};
|
||||
|
||||
template <typename M>
|
||||
dk::Tyler<M::dimensions> call_map_load ( M& parFileOpener, const std::string& parOpen );
|
||||
class UnknownLayerTemplateException : public dk::DoorKeeperException {
|
||||
};
|
||||
|
||||
template <typename M>
|
||||
dk::Tyler<M::dimensions> call_map_load ( dk::Tyler<M::dimensions>& parTyler, M& parFileOpener, const std::string& parOpen );
|
||||
dk::Tyler<M::dimensions> call_map_load ( M& parFileOpener, const std::string& parOpen, const PushLayerMapType<M::dimensions>& parPusher );
|
||||
|
||||
template <typename T, uint32_t D, typename C>
|
||||
dk::Tyler<D> map_load ( C& parFileOpener, const std::string& parOpen );
|
||||
template <typename M>
|
||||
dk::Tyler<M::dimensions> call_map_load ( dk::Tyler<M::dimensions>& parTyler, M& parFileOpener, const std::string& parOpen, const PushLayerMapType<M::dimensions>& parPusher );
|
||||
|
||||
template <typename T, uint32_t D, typename C>
|
||||
dk::Tyler<D>& map_load ( dk::Tyler<D>& parTyler, C& parFileOpener, const std::string& parOpen );
|
||||
template <uint32_t D, typename C>
|
||||
dk::Tyler<D> map_load ( C& parFileOpener, const std::string& parOpen, const PushLayerMapType<D>& parPusher );
|
||||
|
||||
template <uint32_t D, typename C>
|
||||
dk::Tyler<D>& map_load ( dk::Tyler<D>& parTyler, C& parFileOpener, const std::string& parOpen, const PushLayerMapType<D>& parPusher );
|
||||
|
||||
namespace implem {
|
||||
template <uint32_t D>
|
||||
void call_push_layer ( dk::Tyler<D>& parTyler, const PushLayerMapType<D>& parPusher, dk::BaseMapSource<D>* parReader, int parIndex );
|
||||
} //namespace implem
|
||||
} //namespace dkh
|
||||
|
||||
#include "doorkeeper/implem/maploader.inl"
|
||||
|
|
|
@ -5,13 +5,13 @@
|
|||
#include "doorkeeper/implem/vector.hpp"
|
||||
#include "doorkeeper/components/basemapsource.hpp"
|
||||
#include "doorkeeper/implem/maptypes.hpp"
|
||||
#include "doorkeeper/components/exception.hpp"
|
||||
#include <fstream>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <ciso646>
|
||||
#include <exception>
|
||||
|
||||
#if !defined(NDEBUG) && !defined(WITH_TYLERMAP_WRITER)
|
||||
# define WITH_TYLERMAP_WRITER
|
||||
|
@ -40,14 +40,18 @@ namespace dkh {
|
|||
virtual dk::MapTypes mapType ( void ) const;
|
||||
virtual int layersCount ( void ) const;
|
||||
virtual void chainedMaps ( std::vector<std::string>& parOut ) const;
|
||||
virtual dk::HashType layerTypeHash ( int parIndex ) const;
|
||||
|
||||
private:
|
||||
struct LayerInfo;
|
||||
|
||||
void parse_map_data ( std::istream& parSrc );
|
||||
virtual void fetch_raw ( char* parOut, const coords& parFrom, const coords& parTo, std::size_t parSize );
|
||||
|
||||
std::unique_ptr<std::istream> m_stream;
|
||||
|
||||
std::map<std::string, std::string> m_comments;
|
||||
std::vector<LayerInfo> m_layers_info;
|
||||
coords m_map_size;
|
||||
coords m_tile_size;
|
||||
pos_type m_stream_start;
|
||||
|
@ -70,9 +74,9 @@ namespace dkh {
|
|||
};
|
||||
#endif
|
||||
|
||||
class InvalidMapFileException : public std::exception {
|
||||
class InvalidMapFileException : public dk::DoorKeeperException {
|
||||
};
|
||||
class InvalidMapDimensionsException : public std::exception {
|
||||
class InvalidMapDimensionsException : public dk::DoorKeeperException {
|
||||
};
|
||||
|
||||
namespace implem {
|
||||
|
@ -83,7 +87,7 @@ namespace dkh {
|
|||
uint16_t version_minor;
|
||||
uint8_t layer_count;
|
||||
uint8_t map_type;
|
||||
uint8_t map_info_type;
|
||||
uint8_t hashing_algorithm;
|
||||
uint8_t dimensions;
|
||||
uint32_t dimensions_start;
|
||||
uint32_t comment_start;
|
||||
|
|
|
@ -28,6 +28,7 @@ typedef DK_COORD_SCALAR_TYPE MAKE_DK_NAME(CoordinateScalarType);
|
|||
# include <cassert>
|
||||
# define DK_ASSERT(a) assert(a)
|
||||
# endif
|
||||
# define DK_ASSERTIONS_ENABLED
|
||||
#else
|
||||
# if !defined(DK_ASSERT)
|
||||
# define DK_ASSERT(a)
|
||||
|
|
15
include/doorkeeper/implem/hashing.inl
Normal file
15
include/doorkeeper/implem/hashing.inl
Normal file
|
@ -0,0 +1,15 @@
|
|||
namespace dk {
|
||||
template <typename T, uint32_t D>
|
||||
HashType make_signature_hash() {
|
||||
#if defined(__GNUC__)
|
||||
//TODO: use bt::string if possible
|
||||
const char* const pf = __PRETTY_FUNCTION__;
|
||||
const std::size_t len = sizeof(__PRETTY_FUNCTION__) - 1;
|
||||
//constexpr bt::string<sizeof(__PRETTY_FUNCTION__)-1> func_pretty(pf);
|
||||
#else
|
||||
# error "Unknown compiler"
|
||||
#endif
|
||||
//return implem::hash_string(func_pretty.data(), func_pretty.size());
|
||||
return implem::hash_string(pf, len);
|
||||
}
|
||||
} //namespace dk
|
|
@ -1,19 +1,21 @@
|
|||
namespace dkh {
|
||||
template <typename T, uint32_t D, typename C>
|
||||
dk::Tyler<D> map_load (C& parFileOpener, const std::string& parOpen) {
|
||||
template <uint32_t D, typename C>
|
||||
dk::Tyler<D> map_load (C& parFileOpener, const std::string& parOpen, const PushLayerMapType<D>& parPusher) {
|
||||
dk::BaseMapSource<D>* reader = parFileOpener(parOpen);
|
||||
dk::Tyler<D> tyler(reader->tileSize());
|
||||
tyler.template push_layer<T>(reader);
|
||||
for (int z = 0; z < reader->layersCount(); ++z) {
|
||||
implem::call_push_layer<D>(tyler, parPusher, reader, z);
|
||||
}
|
||||
std::vector<std::string> submaps;
|
||||
reader->chainedMaps(submaps);
|
||||
for (const auto& name : submaps) {
|
||||
map_load<T, D, C>(tyler, parFileOpener, name);
|
||||
map_load<D, C>(tyler, parFileOpener, name, parPusher);
|
||||
}
|
||||
return std::move(tyler);
|
||||
}
|
||||
|
||||
template <typename T, uint32_t D, typename C>
|
||||
dk::Tyler<D>& map_load (dk::Tyler<D>& parTyler, C& parFileOpener, const std::string& parOpen) {
|
||||
template <uint32_t D, typename C>
|
||||
dk::Tyler<D>& map_load (dk::Tyler<D>& parTyler, C& parFileOpener, const std::string& parOpen, const PushLayerMapType<D>& parPusher) {
|
||||
std::stack<std::string, std::vector<std::string>> name_stack;
|
||||
std::vector<std::string> submaps;
|
||||
name_stack.push(parOpen);
|
||||
|
@ -28,13 +30,15 @@ namespace dkh {
|
|||
name_stack.emplace(std::move(curr_name));
|
||||
}
|
||||
|
||||
parTyler.template push_layer<T>(reader);
|
||||
for (int z = 0; z < reader->layersCount(); ++z) {
|
||||
implem::call_push_layer<D>(parTyler, parPusher, reader, z);
|
||||
}
|
||||
} while (not name_stack.empty());
|
||||
return parTyler;
|
||||
}
|
||||
|
||||
template <typename T, uint32_t D, typename C>
|
||||
dk::BaseMapSource<D>* MapLoaderPool<T, D, C>::operator() (const std::string& parName) {
|
||||
template <uint32_t D, typename C>
|
||||
dk::BaseMapSource<D>* MapLoaderPool<D, C>::operator() (const std::string& parName) {
|
||||
auto it_found = pool.find(parName);
|
||||
if (pool.end() != it_found) {
|
||||
return it_found->second.get();
|
||||
|
@ -48,12 +52,23 @@ namespace dkh {
|
|||
}
|
||||
|
||||
template <typename M>
|
||||
dk::Tyler<M::dimensions> call_map_load (M& parFileOpener, const std::string& parOpen) {
|
||||
return map_load<typename M::tile_type, M::dimensions, M>(parFileOpener, parOpen);
|
||||
dk::Tyler<M::dimensions> call_map_load (M& parFileOpener, const std::string& parOpen, const PushLayerMapType<M::dimensions>& parPusher) {
|
||||
return map_load<M::dimensions, M>(parFileOpener, parOpen, parPusher);
|
||||
}
|
||||
|
||||
template <typename M>
|
||||
dk::Tyler<M::dimensions> call_map_load (dk::Tyler<M::dimensions>& parTyler, M& parFileOpener, const std::string& parOpen) {
|
||||
return map_load<typename M::tile_type, M::dimensions, M>(parTyler, parFileOpener, parOpen);
|
||||
dk::Tyler<M::dimensions> call_map_load (dk::Tyler<M::dimensions>& parTyler, M& parFileOpener, const std::string& parOpen, const PushLayerMapType<M::dimensions>& parPusher) {
|
||||
return map_load<M::dimensions, M>(parTyler, parFileOpener, parOpen, parPusher);
|
||||
}
|
||||
|
||||
namespace implem {
|
||||
template <uint32_t D>
|
||||
void call_push_layer (dk::Tyler<D>& parTyler, const PushLayerMapType<D>& parPusher, dk::BaseMapSource<D>* parReader, int parLayerIndex) {
|
||||
auto it_found = parPusher.find(parReader->layerTypeHash(parLayerIndex));
|
||||
if (parPusher.end() == it_found)
|
||||
throw UnknownLayerTemplateException();
|
||||
|
||||
(parTyler.*(it_found->second))(parReader, parLayerIndex);
|
||||
}
|
||||
} //namespace implem
|
||||
} //namespace dkh
|
||||
|
|
|
@ -23,15 +23,18 @@ namespace dk {
|
|||
///--------------------------------------------------------------------------
|
||||
template <uint32_t D>
|
||||
template <typename T>
|
||||
Layer<T, D>& Tyler<D>::push_layer (BaseMapSource<D>* parTilemap) {
|
||||
return push_layer<T>(parTilemap, coords(static_cast<CoordinateScalarType>(1)));
|
||||
Layer<T, D>& Tyler<D>::push_layer (BaseMapSource<D>* parTilemap, int parIndex) {
|
||||
return push_layer<T>(parTilemap, coords(static_cast<CoordinateScalarType>(1)), parIndex);
|
||||
}
|
||||
|
||||
///--------------------------------------------------------------------------
|
||||
///--------------------------------------------------------------------------
|
||||
template <uint32_t D>
|
||||
template <typename T>
|
||||
Layer<T, D>& Tyler<D>::push_layer (BaseMapSource<D>* parTilemap, const coords& parSubdiv) {
|
||||
Layer<T, D>& Tyler<D>::push_layer (BaseMapSource<D>* parTilemap, const coords& parSubdiv, int parIndex) {
|
||||
//TODO: store the index
|
||||
(void)parIndex;
|
||||
|
||||
auto newLayer = new Layer<T, D>(m_tilesize / parSubdiv, m_tilesize, parTilemap);
|
||||
if (m_size == coords(0)) {
|
||||
m_size = newLayer->mapSize();
|
||||
|
@ -47,6 +50,14 @@ namespace dk {
|
|||
return *newLayer;
|
||||
}
|
||||
|
||||
///--------------------------------------------------------------------------
|
||||
///--------------------------------------------------------------------------
|
||||
template <uint32_t D>
|
||||
template <typename T>
|
||||
void Tyler<D>::push_layer_void (BaseMapSource<D>* parTilemap, int parIndex) {
|
||||
push_layer<T>(parTilemap, parIndex);
|
||||
}
|
||||
|
||||
///--------------------------------------------------------------------------
|
||||
///--------------------------------------------------------------------------
|
||||
template <uint32_t D>
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
namespace dkh {
|
||||
template <uint32_t D>
|
||||
struct TylerMapSource<D>::LayerInfo {
|
||||
dk::HashType hash;
|
||||
uint32_t data_start;
|
||||
uint32_t data_length;
|
||||
};
|
||||
|
||||
template <uint32_t D>
|
||||
TylerMapSource<D>::TylerMapSource (const char* parFilename) :
|
||||
m_stream(new std::ifstream(parFilename)),
|
||||
|
@ -100,4 +107,11 @@ namespace dkh {
|
|||
void TylerMapSource<D>::chainedMaps (std::vector<std::string>& parOut) const {
|
||||
implem::extract_array_from_comments(parOut, "chained_map", m_comments);
|
||||
}
|
||||
|
||||
template <uint32_t D>
|
||||
dk::HashType TylerMapSource<D>::layerTypeHash (int parIndex) const {
|
||||
DK_ASSERT(parIndex >= 0);
|
||||
DK_ASSERT(static_cast<std::size_t>(parIndex) < m_layers_info.size());
|
||||
return m_layers_info[parIndex].hash;
|
||||
}
|
||||
} //namespace dkh
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue