mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-06-16 05:13:58 -07:00
Use templates to replace explicit serialization helpers.
By using templates appripriately we can remove the need for explicit specification of serializers, making it easier to serialize container types and to write new serialization helpers. Direct serialization calls haven't been replaced in this diff. Comments by: vladislavbelov Differential Revision: https://code.wildfiregames.com/D3207 This was SVN commit r24427.
This commit is contained in:
parent
974d4a4e25
commit
5b46ce0778
13 changed files with 138 additions and 379 deletions
|
|
@ -42,9 +42,9 @@
|
|||
#include "simulation2/helpers/HierarchicalPathfinder.h"
|
||||
#include "simulation2/helpers/LongPathfinder.h"
|
||||
#include "simulation2/serialization/DebugSerializer.h"
|
||||
#include "simulation2/serialization/SerializedTypes.h"
|
||||
#include "simulation2/serialization/StdDeserializer.h"
|
||||
#include "simulation2/serialization/StdSerializer.h"
|
||||
#include "simulation2/serialization/SerializeTemplates.h"
|
||||
|
||||
extern void QuitEngine();
|
||||
|
||||
|
|
@ -705,8 +705,8 @@ public:
|
|||
}
|
||||
|
||||
// AI pathfinder
|
||||
SerializeMap<SerializeString, SerializeU16_Unbounded>()(serializer, "non pathfinding pass classes", m_NonPathfindingPassClasses);
|
||||
SerializeMap<SerializeString, SerializeU16_Unbounded>()(serializer, "pathfinding pass classes", m_PathfindingPassClasses);
|
||||
Serializer(serializer, "non pathfinding pass classes", m_NonPathfindingPassClasses);
|
||||
Serializer(serializer, "pathfinding pass classes", m_PathfindingPassClasses);
|
||||
serializer.NumberU16_Unbounded("pathfinder grid w", m_PassabilityMap.m_W);
|
||||
serializer.NumberU16_Unbounded("pathfinder grid h", m_PassabilityMap.m_H);
|
||||
serializer.RawBytes("pathfinder grid data", (const u8*)m_PassabilityMap.m_Data,
|
||||
|
|
@ -790,8 +790,8 @@ public:
|
|||
}
|
||||
|
||||
// AI pathfinder
|
||||
SerializeMap<SerializeString, SerializeU16_Unbounded>()(deserializer, "non pathfinding pass classes", m_NonPathfindingPassClasses);
|
||||
SerializeMap<SerializeString, SerializeU16_Unbounded>()(deserializer, "pathfinding pass classes", m_PathfindingPassClasses);
|
||||
Serializer(deserializer, "non pathfinding pass classes", m_NonPathfindingPassClasses);
|
||||
Serializer(deserializer, "pathfinding pass classes", m_PathfindingPassClasses);
|
||||
u16 mapW, mapH;
|
||||
deserializer.NumberU16_Unbounded("pathfinder grid w", mapW);
|
||||
deserializer.NumberU16_Unbounded("pathfinder grid h", mapH);
|
||||
|
|
|
|||
|
|
@ -17,16 +17,26 @@
|
|||
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "simulation2/system/Component.h"
|
||||
#include "ICmpObstruction.h"
|
||||
|
||||
#include "ps/CLogger.h"
|
||||
#include "simulation2/MessageTypes.h"
|
||||
#include "simulation2/components/ICmpObstructionManager.h"
|
||||
#include "simulation2/components/ICmpTerrain.h"
|
||||
#include "simulation2/components/ICmpUnitMotion.h"
|
||||
#include "simulation2/components/ICmpWaterManager.h"
|
||||
#include "simulation2/serialization/SerializeTemplates.h"
|
||||
#include "simulation2/serialization/SerializedTypes.h"
|
||||
|
||||
#include "ps/CLogger.h"
|
||||
|
||||
template<>
|
||||
struct SerializeHelper<ICmpObstructionManager::tag_t>
|
||||
{
|
||||
template<typename S>
|
||||
void operator()(S& serialize, const char* UNUSED(name), Serialize::qualify<S, ICmpObstructionManager::tag_t> value)
|
||||
{
|
||||
serialize.NumberU32_Unbounded("tag", value.n);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Obstruction implementation. This keeps the ICmpPathfinder's model of the world updated when the
|
||||
|
|
@ -261,15 +271,6 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
struct SerializeTag
|
||||
{
|
||||
template<typename S>
|
||||
void operator()(S& serialize, const char* UNUSED(name), tag_t& value)
|
||||
{
|
||||
serialize.NumberU32_Unbounded("tag", value.n);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename S>
|
||||
void SerializeCommon(S& serialize)
|
||||
{
|
||||
|
|
@ -280,7 +281,7 @@ public:
|
|||
serialize.NumberU32_Unbounded("tag", m_Tag.n);
|
||||
serialize.NumberU8_Unbounded("flags", m_Flags);
|
||||
if (m_Type == CLUSTER)
|
||||
SerializeVector<SerializeTag>()(serialize, "cluster tags", m_ClusterTags);
|
||||
Serializer(serialize, "cluster tags", m_ClusterTags);
|
||||
if (m_Type == UNIT)
|
||||
serialize.NumberFixed_Unbounded("clearance", m_Clearance);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
#include "simulation2/helpers/Rasterize.h"
|
||||
#include "simulation2/helpers/Render.h"
|
||||
#include "simulation2/helpers/Spatial.h"
|
||||
#include "simulation2/serialization/SerializeTemplates.h"
|
||||
#include "simulation2/serialization/SerializedTypes.h"
|
||||
|
||||
#include "graphics/Overlay.h"
|
||||
#include "graphics/Terrain.h"
|
||||
|
|
@ -77,10 +77,11 @@ struct StaticShape
|
|||
/**
|
||||
* Serialization helper template for UnitShape
|
||||
*/
|
||||
struct SerializeUnitShape
|
||||
template<>
|
||||
struct SerializeHelper<UnitShape>
|
||||
{
|
||||
template<typename S>
|
||||
void operator()(S& serialize, const char* UNUSED(name), UnitShape& value) const
|
||||
void operator()(S& serialize, const char* UNUSED(name), Serialize::qualify<S, UnitShape> value) const
|
||||
{
|
||||
serialize.NumberU32_Unbounded("entity", value.entity);
|
||||
serialize.NumberFixed_Unbounded("x", value.x);
|
||||
|
|
@ -94,10 +95,11 @@ struct SerializeUnitShape
|
|||
/**
|
||||
* Serialization helper template for StaticShape
|
||||
*/
|
||||
struct SerializeStaticShape
|
||||
template<>
|
||||
struct SerializeHelper<StaticShape>
|
||||
{
|
||||
template<typename S>
|
||||
void operator()(S& serialize, const char* UNUSED(name), StaticShape& value) const
|
||||
void operator()(S& serialize, const char* UNUSED(name), Serialize::qualify<S, StaticShape> value) const
|
||||
{
|
||||
serialize.NumberU32_Unbounded("entity", value.entity);
|
||||
serialize.NumberFixed_Unbounded("x", value.x);
|
||||
|
|
@ -180,13 +182,13 @@ public:
|
|||
template<typename S>
|
||||
void SerializeCommon(S& serialize)
|
||||
{
|
||||
SerializeSpatialSubdivision()(serialize, "unit subdiv", m_UnitSubdivision);
|
||||
SerializeSpatialSubdivision()(serialize, "static subdiv", m_StaticSubdivision);
|
||||
Serializer(serialize, "unit subdiv", m_UnitSubdivision);
|
||||
Serializer(serialize, "static subdiv", m_StaticSubdivision);
|
||||
|
||||
serialize.NumberFixed_Unbounded("max clearance", m_MaxClearance);
|
||||
|
||||
SerializeMap<SerializeU32_Unbounded, SerializeUnitShape>()(serialize, "unit shapes", m_UnitShapes);
|
||||
SerializeMap<SerializeU32_Unbounded, SerializeStaticShape>()(serialize, "static shapes", m_StaticShapes);
|
||||
Serializer(serialize, "unit shapes", m_UnitShapes);
|
||||
Serializer(serialize, "static shapes", m_StaticShapes);
|
||||
serialize.NumberU32_Unbounded("unit shape next", m_UnitShapeNext);
|
||||
serialize.NumberU32_Unbounded("static shape next", m_StaticShapeNext);
|
||||
|
||||
|
|
|
|||
|
|
@ -24,11 +24,6 @@
|
|||
|
||||
#include "CCmpPathfinder_Common.h"
|
||||
|
||||
#include "ps/CLogger.h"
|
||||
#include "ps/CStr.h"
|
||||
#include "ps/Profile.h"
|
||||
#include "ps/XML/Xeromyces.h"
|
||||
#include "renderer/Scene.h"
|
||||
#include "simulation2/MessageTypes.h"
|
||||
#include "simulation2/components/ICmpObstruction.h"
|
||||
#include "simulation2/components/ICmpObstructionManager.h"
|
||||
|
|
@ -39,7 +34,14 @@
|
|||
#include "simulation2/helpers/MapEdgeTiles.h"
|
||||
#include "simulation2/helpers/Rasterize.h"
|
||||
#include "simulation2/helpers/VertexPathfinder.h"
|
||||
#include "simulation2/serialization/SerializeTemplates.h"
|
||||
#include "simulation2/serialization/SerializedPathfinder.h"
|
||||
#include "simulation2/serialization/SerializedTypes.h"
|
||||
|
||||
#include "ps/CLogger.h"
|
||||
#include "ps/CStr.h"
|
||||
#include "ps/Profile.h"
|
||||
#include "ps/XML/Xeromyces.h"
|
||||
#include "renderer/Scene.h"
|
||||
|
||||
REGISTER_COMPONENT_TYPE(Pathfinder)
|
||||
|
||||
|
|
@ -113,31 +115,33 @@ void CCmpPathfinder::Deinit()
|
|||
SAFE_DELETE(m_TerrainOnlyGrid);
|
||||
}
|
||||
|
||||
struct SerializeLongRequest
|
||||
template<>
|
||||
struct SerializeHelper<LongPathRequest>
|
||||
{
|
||||
template<typename S>
|
||||
void operator()(S& serialize, const char* UNUSED(name), LongPathRequest& value)
|
||||
void operator()(S& serialize, const char* UNUSED(name), Serialize::qualify<S, LongPathRequest> value)
|
||||
{
|
||||
serialize.NumberU32_Unbounded("ticket", value.ticket);
|
||||
serialize.NumberFixed_Unbounded("x0", value.x0);
|
||||
serialize.NumberFixed_Unbounded("z0", value.z0);
|
||||
SerializeGoal()(serialize, "goal", value.goal);
|
||||
Serializer(serialize, "goal", value.goal);
|
||||
serialize.NumberU16_Unbounded("pass class", value.passClass);
|
||||
serialize.NumberU32_Unbounded("notify", value.notify);
|
||||
}
|
||||
};
|
||||
|
||||
struct SerializeShortRequest
|
||||
template<>
|
||||
struct SerializeHelper<ShortPathRequest>
|
||||
{
|
||||
template<typename S>
|
||||
void operator()(S& serialize, const char* UNUSED(name), ShortPathRequest& value)
|
||||
void operator()(S& serialize, const char* UNUSED(name), Serialize::qualify<S, ShortPathRequest> value)
|
||||
{
|
||||
serialize.NumberU32_Unbounded("ticket", value.ticket);
|
||||
serialize.NumberFixed_Unbounded("x0", value.x0);
|
||||
serialize.NumberFixed_Unbounded("z0", value.z0);
|
||||
serialize.NumberFixed_Unbounded("clearance", value.clearance);
|
||||
serialize.NumberFixed_Unbounded("range", value.range);
|
||||
SerializeGoal()(serialize, "goal", value.goal);
|
||||
Serializer(serialize, "goal", value.goal);
|
||||
serialize.NumberU16_Unbounded("pass class", value.passClass);
|
||||
serialize.Bool("avoid moving units", value.avoidMovingUnits);
|
||||
serialize.NumberU32_Unbounded("group", value.group);
|
||||
|
|
@ -148,8 +152,8 @@ struct SerializeShortRequest
|
|||
template<typename S>
|
||||
void CCmpPathfinder::SerializeCommon(S& serialize)
|
||||
{
|
||||
SerializeVector<SerializeLongRequest>()(serialize, "long requests", m_LongPathRequests);
|
||||
SerializeVector<SerializeShortRequest>()(serialize, "short requests", m_ShortPathRequests);
|
||||
Serializer(serialize, "long requests", m_LongPathRequests);
|
||||
Serializer(serialize, "short requests", m_ShortPathRequests);
|
||||
serialize.NumberU32_Unbounded("next ticket", m_NextAsyncTicket);
|
||||
serialize.NumberU16_Unbounded("map size", m_MapSize);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#include "simulation2/helpers/MapEdgeTiles.h"
|
||||
#include "simulation2/helpers/Render.h"
|
||||
#include "simulation2/helpers/Spatial.h"
|
||||
#include "simulation2/serialization/SerializedTypes.h"
|
||||
|
||||
#include "graphics/Overlay.h"
|
||||
#include "graphics/Terrain.h"
|
||||
|
|
@ -237,10 +238,11 @@ cassert(sizeof(EntityData) == 24);
|
|||
/**
|
||||
* Serialization helper template for Query
|
||||
*/
|
||||
struct SerializeQuery
|
||||
template<>
|
||||
struct SerializeHelper<Query>
|
||||
{
|
||||
template<typename S>
|
||||
void Common(S& serialize, const char* UNUSED(name), Query& value)
|
||||
void Common(S& serialize, const char* UNUSED(name), Serialize::qualify<S, Query> value)
|
||||
{
|
||||
serialize.Bool("enabled", value.enabled);
|
||||
serialize.Bool("parabolic",value.parabolic);
|
||||
|
|
@ -249,7 +251,7 @@ struct SerializeQuery
|
|||
serialize.NumberFixed_Unbounded("elevation bonus", value.elevationBonus);
|
||||
serialize.NumberU32_Unbounded("owners mask", value.ownersMask);
|
||||
serialize.NumberI32_Unbounded("interface", value.interface);
|
||||
SerializeVector<SerializeU32_Unbounded>()(serialize, "last match", value.lastMatch);
|
||||
Serializer(serialize, "last match", value.lastMatch);
|
||||
serialize.NumberU8_Unbounded("flagsMask", value.flagsMask);
|
||||
}
|
||||
|
||||
|
|
@ -276,10 +278,11 @@ struct SerializeQuery
|
|||
/**
|
||||
* Serialization helper template for EntityData
|
||||
*/
|
||||
struct SerializeEntityData
|
||||
template<>
|
||||
struct SerializeHelper<EntityData>
|
||||
{
|
||||
template<typename S>
|
||||
void operator()(S& serialize, const char* UNUSED(name), EntityData& value)
|
||||
void operator()(S& serialize, const char* UNUSED(name), Serialize::qualify<S, EntityData> value)
|
||||
{
|
||||
serialize.NumberFixed_Unbounded("x", value.x);
|
||||
serialize.NumberFixed_Unbounded("z", value.z);
|
||||
|
|
@ -455,25 +458,25 @@ public:
|
|||
serialize.NumberFixed_Unbounded("world z1", m_WorldZ1);
|
||||
|
||||
serialize.NumberU32_Unbounded("query next", m_QueryNext);
|
||||
SerializeMap<SerializeU32_Unbounded, SerializeQuery>()(serialize, "queries", m_Queries, GetSimContext());
|
||||
SerializeEntityMap<SerializeEntityData>()(serialize, "entity data", m_EntityData);
|
||||
Serializer(serialize, "queries", m_Queries, GetSimContext());
|
||||
Serializer(serialize, "entity data", m_EntityData);
|
||||
|
||||
SerializeArray<SerializeBool>()(serialize, "los reveal all", m_LosRevealAll);
|
||||
Serializer(serialize, "los reveal all", m_LosRevealAll);
|
||||
serialize.Bool("los circular", m_LosCircular);
|
||||
serialize.NumberI32_Unbounded("terrain verts per side", m_TerrainVerticesPerSide);
|
||||
|
||||
serialize.Bool("global visibility update", m_GlobalVisibilityUpdate);
|
||||
SerializeArray<SerializeBool>()(serialize, "global player visibility update", m_GlobalPlayerVisibilityUpdate);
|
||||
SerializedGridCompressed<SerializeU16_Unbounded>()(serialize, "dirty visibility", m_DirtyVisibility);
|
||||
SerializeVector<SerializeU32_Unbounded>()(serialize, "modified entities", m_ModifiedEntities);
|
||||
Serializer(serialize, "global player visibility update", m_GlobalPlayerVisibilityUpdate);
|
||||
Serializer(serialize, "dirty visibility", m_DirtyVisibility);
|
||||
Serializer(serialize, "modified entities", m_ModifiedEntities);
|
||||
|
||||
// We don't serialize m_Subdivision, m_LosPlayerCounts or m_LosTiles
|
||||
// since they can be recomputed from the entity data when deserializing;
|
||||
// m_LosState must be serialized since it depends on the history of exploration
|
||||
|
||||
SerializedGridCompressed<SerializeU32_Unbounded>()(serialize, "los state", m_LosState);
|
||||
SerializeArray<SerializeU32_Unbounded>()(serialize, "shared los masks", m_SharedLosMasks);
|
||||
SerializeArray<SerializeU16_Unbounded>()(serialize, "shared dirty visibility masks", m_SharedDirtyVisibilityMasks);
|
||||
Serializer(serialize, "los state", m_LosState);
|
||||
Serializer(serialize, "shared los masks", m_SharedLosMasks);
|
||||
Serializer(serialize, "shared dirty visibility masks", m_SharedDirtyVisibilityMasks);
|
||||
}
|
||||
|
||||
virtual void Serialize(ISerializer& serialize)
|
||||
|
|
|
|||
|
|
@ -17,16 +17,14 @@
|
|||
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "simulation2/system/Component.h"
|
||||
#include "ICmpTemplateManager.h"
|
||||
|
||||
#include "simulation2/MessageTypes.h"
|
||||
#include "simulation2/serialization/SerializeTemplates.h"
|
||||
|
||||
#include "ps/TemplateLoader.h"
|
||||
#include "simulation2/serialization/SerializedTypes.h"
|
||||
|
||||
#include "lib/utf8.h"
|
||||
#include "ps/CLogger.h"
|
||||
#include "ps/TemplateLoader.h"
|
||||
#include "ps/XML/RelaxNG.h"
|
||||
|
||||
class CCmpTemplateManager : public ICmpTemplateManager
|
||||
|
|
@ -65,7 +63,7 @@ public:
|
|||
if (!ENTITY_IS_LOCAL(templateEnt.first))
|
||||
templateMap[templateEnt.second].push_back(templateEnt.first);
|
||||
|
||||
SerializeMap<SerializeString, SerializeVector<SerializeU32_Unbounded>>()(serialize, "templates", templateMap);
|
||||
Serializer(serialize, "templates", templateMap);
|
||||
}
|
||||
|
||||
virtual void Deserialize(const CParamNode& paramNode, IDeserializer& deserialize)
|
||||
|
|
@ -73,7 +71,7 @@ public:
|
|||
Init(paramNode);
|
||||
|
||||
std::map<CStr, std::vector<entity_id_t>> templateMap;
|
||||
SerializeMap<SerializeString, SerializeVector<SerializeU32_Unbounded>>()(deserialize, "templates", templateMap);
|
||||
Serializer(deserialize, "templates", templateMap);
|
||||
for (const std::pair<CStr, std::vector<entity_id_t>>& mapEl : templateMap)
|
||||
for (entity_id_t id : mapEl.second)
|
||||
m_LatestTemplates[id] = mapEl.first;
|
||||
|
|
|
|||
|
|
@ -31,7 +31,8 @@
|
|||
#include "simulation2/helpers/Geometry.h"
|
||||
#include "simulation2/helpers/Render.h"
|
||||
#include "simulation2/MessageTypes.h"
|
||||
#include "simulation2/serialization/SerializeTemplates.h"
|
||||
#include "simulation2/serialization/SerializedPathfinder.h"
|
||||
#include "simulation2/serialization/SerializedTypes.h"
|
||||
|
||||
#include "graphics/Overlay.h"
|
||||
#include "graphics/Terrain.h"
|
||||
|
|
@ -261,12 +262,12 @@ public:
|
|||
serialize.StringASCII("pass class", m_PassClassName, 0, 64);
|
||||
|
||||
serialize.NumberU32_Unbounded("ticket", m_ExpectedPathTicket.m_Ticket);
|
||||
SerializeU8_Enum<Ticket::Type, Ticket::Type::LONG_PATH>()(serialize, "ticket type", m_ExpectedPathTicket.m_Type);
|
||||
Serializer(serialize, "ticket type", m_ExpectedPathTicket.m_Type, Ticket::Type::LONG_PATH);
|
||||
|
||||
serialize.NumberU8_Unbounded("failed path computations", m_FailedPathComputations);
|
||||
serialize.NumberU8_Unbounded("followknownimperfectpath", m_FollowKnownImperfectPathCountdown);
|
||||
|
||||
SerializeU8_Enum<MoveRequest::Type, MoveRequest::Type::OFFSET>()(serialize, "target type", m_MoveRequest.m_Type);
|
||||
Serializer(serialize, "target type", m_MoveRequest.m_Type, MoveRequest::Type::OFFSET);
|
||||
serialize.NumberU32_Unbounded("target entity", m_MoveRequest.m_Entity);
|
||||
serialize.NumberFixed_Unbounded("target pos x", m_MoveRequest.m_Position.X);
|
||||
serialize.NumberFixed_Unbounded("target pos y", m_MoveRequest.m_Position.Y);
|
||||
|
|
@ -279,8 +280,8 @@ public:
|
|||
|
||||
serialize.Bool("facePointAfterMove", m_FacePointAfterMove);
|
||||
|
||||
SerializeVector<SerializeWaypoint>()(serialize, "long path", m_LongPath.m_Waypoints);
|
||||
SerializeVector<SerializeWaypoint>()(serialize, "short path", m_ShortPath.m_Waypoints);
|
||||
Serializer(serialize, "long path", m_LongPath.m_Waypoints);
|
||||
Serializer(serialize, "short path", m_ShortPath.m_Waypoints);
|
||||
}
|
||||
|
||||
virtual void Serialize(ISerializer& serialize)
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include "ICmpVisual.h"
|
||||
|
||||
#include "simulation2/MessageTypes.h"
|
||||
#include "simulation2/serialization/SerializedTypes.h"
|
||||
|
||||
#include "ICmpFootprint.h"
|
||||
#include "ICmpIdentity.h"
|
||||
|
|
@ -35,8 +36,6 @@
|
|||
#include "ICmpVisibility.h"
|
||||
#include "ICmpSound.h"
|
||||
|
||||
#include "simulation2/serialization/SerializeTemplates.h"
|
||||
|
||||
#include "graphics/Decal.h"
|
||||
#include "graphics/Frustum.h"
|
||||
#include "graphics/Model.h"
|
||||
|
|
@ -246,7 +245,7 @@ public:
|
|||
serialize.NumberFixed_Unbounded("anim sync repeat time", m_AnimSyncRepeatTime);
|
||||
serialize.NumberFixed_Unbounded("anim sync offset time", m_AnimSyncOffsetTime);
|
||||
|
||||
SerializeMap<SerializeString, SerializeString>()(serialize, "variation", m_VariantSelections);
|
||||
Serializer(serialize, "variation", m_VariantSelections);
|
||||
|
||||
serialize.NumberU32_Unbounded("seed", m_Seed);
|
||||
serialize.String("actor", m_ActorName, 0, 256);
|
||||
|
|
|
|||
|
|
@ -18,8 +18,7 @@
|
|||
#ifndef INCLUDED_GRID
|
||||
#define INCLUDED_GRID
|
||||
|
||||
#include "simulation2/serialization/IDeserializer.h"
|
||||
#include "simulation2/serialization/ISerializer.h"
|
||||
#include "simulation2/serialization/SerializeTemplates.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
|
|
@ -29,9 +28,6 @@
|
|||
#define GRID_BOUNDS_DEBUG 1
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
struct SerializedGridCompressed;
|
||||
|
||||
/**
|
||||
* Basic 2D array, intended for storing tile data, plus support for lazy updates
|
||||
* by ICmpObstructionManager.
|
||||
|
|
@ -40,7 +36,7 @@ struct SerializedGridCompressed;
|
|||
template<typename T>
|
||||
class Grid
|
||||
{
|
||||
friend struct SerializedGridCompressed<T>;
|
||||
friend struct SerializeHelper<Grid<T>>;
|
||||
protected:
|
||||
// Tag-dispatching internal utilities for convenience.
|
||||
struct default_type{};
|
||||
|
|
@ -258,10 +254,9 @@ public:
|
|||
/**
|
||||
* Serialize a grid, applying a simple RLE compression that is assumed efficient.
|
||||
*/
|
||||
template<typename ELEM>
|
||||
struct SerializedGridCompressed
|
||||
template<typename T>
|
||||
struct SerializeHelper<Grid<T>>
|
||||
{
|
||||
template<typename T>
|
||||
void operator()(ISerializer& serialize, const char* name, Grid<T>& value)
|
||||
{
|
||||
size_t len = value.m_H * value.m_W;
|
||||
|
|
@ -279,15 +274,14 @@ struct SerializedGridCompressed
|
|||
continue;
|
||||
}
|
||||
serialize.NumberU32_Unbounded("#", count);
|
||||
ELEM()(serialize, name, prevVal);
|
||||
Serializer(serialize, name, prevVal);
|
||||
count = 1;
|
||||
prevVal = value.m_Data[i];
|
||||
}
|
||||
serialize.NumberU32_Unbounded("#", count);
|
||||
ELEM()(serialize, name, prevVal);
|
||||
Serializer(serialize, name, prevVal);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void operator()(IDeserializer& deserialize, const char* name, Grid<T>& value)
|
||||
{
|
||||
u16 w, h;
|
||||
|
|
@ -300,7 +294,7 @@ struct SerializedGridCompressed
|
|||
u32 count;
|
||||
deserialize.NumberU32_Unbounded("#", count);
|
||||
T el;
|
||||
ELEM()(deserialize, name, el);
|
||||
Serializer(deserialize, name, el);
|
||||
std::fill(&value.m_Data[i], &value.m_Data[i+count], el);
|
||||
i += count;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ class SpatialSubdivision
|
|||
uint32_t m_DivisionsW;
|
||||
uint32_t m_DivisionsH;
|
||||
|
||||
friend struct SerializeSpatialSubdivision;
|
||||
friend struct SerializeHelper<SpatialSubdivision>;
|
||||
|
||||
public:
|
||||
SpatialSubdivision() : m_Divisions(NULL), m_DivisionsW(0), m_DivisionsH(0)
|
||||
|
|
@ -316,7 +316,8 @@ private:
|
|||
/**
|
||||
* Serialization helper template for SpatialSubdivision
|
||||
*/
|
||||
struct SerializeSpatialSubdivision
|
||||
template<>
|
||||
struct SerializeHelper<SpatialSubdivision>
|
||||
{
|
||||
void operator()(ISerializer& serialize, const char* UNUSED(name), SpatialSubdivision& value)
|
||||
{
|
||||
|
|
@ -326,7 +327,7 @@ struct SerializeSpatialSubdivision
|
|||
|
||||
size_t count = value.m_DivisionsH * value.m_DivisionsW;
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
SerializeVector<SerializeU32_Unbounded>()(serialize, "subdiv items", value.m_Divisions[i].items);
|
||||
Serializer(serialize, "subdiv items", value.m_Divisions[i].items);
|
||||
}
|
||||
|
||||
void operator()(IDeserializer& serialize, const char* UNUSED(name), SpatialSubdivision& value)
|
||||
|
|
@ -338,7 +339,7 @@ struct SerializeSpatialSubdivision
|
|||
size_t count = value.m_DivisionsW * value.m_DivisionsH;
|
||||
value.Create(count);
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
SerializeVector<SerializeU32_Unbounded>()(serialize, "subdiv items", value.m_Divisions[i].items);
|
||||
Serializer(serialize, "subdiv items", value.m_Divisions[i].items);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -20,295 +20,50 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* Helper templates for serializing/deserializing common objects.
|
||||
* Helper templates definitions for serializing/deserializing common objects.
|
||||
*
|
||||
* Usage:
|
||||
* You need to (partially) specialize SerializeHelper for your type.
|
||||
* The optional SFINAE argument can be used to provide generic specializations
|
||||
* via std::enable_if_t<T>.
|
||||
* If both paths are common, you can templatize operator()'s first argument,
|
||||
* but you will need to templatize the passed value to account for different value categories.
|
||||
*
|
||||
* See SerializedTypes.h for some examples.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "simulation2/components/ICmpPathfinder.h"
|
||||
#include "simulation2/serialization/IDeserializer.h"
|
||||
#include "simulation2/serialization/ISerializer.h"
|
||||
#include "simulation2/serialization/IDeserializer.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
template<typename ELEM>
|
||||
struct SerializeArray
|
||||
// SFINAE is just there to allow SFINAE-partial specializations.
|
||||
template <typename T, typename SFINAE = void>
|
||||
struct SerializeHelper
|
||||
{
|
||||
template<typename T, size_t N>
|
||||
void operator()(ISerializer& serialize, const char* name, std::array<T, N>& value)
|
||||
{
|
||||
for (size_t i = 0; i < N; ++i)
|
||||
ELEM()(serialize, name, value[i]);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
void operator()(IDeserializer& deserialize, const char* name, std::array<T, N>& value)
|
||||
{
|
||||
for (size_t i = 0; i < N; ++i)
|
||||
ELEM()(deserialize, name, value[i]);
|
||||
}
|
||||
template<typename... Args>
|
||||
void operator()(ISerializer& serialize, const char* name, T value, Args&&...);
|
||||
template<typename... Args>
|
||||
void operator()(IDeserializer& serialize, const char* name, T& value, Args&&...);
|
||||
};
|
||||
|
||||
template<typename ELEM>
|
||||
struct SerializeVector
|
||||
// This is the variant for an explicitly specified T (where what you pass is another type).
|
||||
template <typename T, typename S, typename... Args>
|
||||
void Serializer(S& serialize, const char* name, Args&&... args)
|
||||
{
|
||||
template<typename T>
|
||||
void operator()(ISerializer& serialize, const char* name, std::vector<T>& value)
|
||||
{
|
||||
size_t len = value.size();
|
||||
serialize.NumberU32_Unbounded("length", (u32)len);
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
ELEM()(serialize, name, value[i]);
|
||||
}
|
||||
SerializeHelper<std::remove_const_t<std::remove_reference_t<T>>>()(serialize, name, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void operator()(IDeserializer& deserialize, const char* name, std::vector<T>& value)
|
||||
{
|
||||
value.clear();
|
||||
u32 len;
|
||||
deserialize.NumberU32_Unbounded("length", len);
|
||||
value.reserve(len); // TODO: watch out for out-of-memory
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
{
|
||||
T el;
|
||||
ELEM()(deserialize, name, el);
|
||||
value.emplace_back(el);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ELEM>
|
||||
struct SerializeSet
|
||||
// This lets T be deduced from the argument.
|
||||
template <typename T, typename S, typename... Args>
|
||||
void Serializer(S& serialize, const char* name, T&& value, Args&&... args)
|
||||
{
|
||||
template<typename T>
|
||||
void operator()(ISerializer& serialize, const char* name, const std::set<T>& value)
|
||||
{
|
||||
serialize.NumberU32_Unbounded("size", static_cast<u32>(value.size()));
|
||||
for (const T& elem : value)
|
||||
ELEM()(serialize, name, elem);
|
||||
}
|
||||
SerializeHelper<std::remove_const_t<std::remove_reference_t<T>>>()(serialize, name, std::forward<T>(value), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void operator()(IDeserializer& deserialize, const char* name, std::set<T>& value)
|
||||
{
|
||||
value.clear();
|
||||
u32 size;
|
||||
deserialize.NumberU32_Unbounded("size", size);
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
T el;
|
||||
ELEM()(deserialize, name, el);
|
||||
value.emplace(std::move(el));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename KS, typename VS>
|
||||
struct SerializeMap
|
||||
namespace Serialize
|
||||
{
|
||||
template<typename K, typename V>
|
||||
void operator()(ISerializer& serialize, const char* UNUSED(name), std::map<K, V>& value)
|
||||
{
|
||||
size_t len = value.size();
|
||||
serialize.NumberU32_Unbounded("length", (u32)len);
|
||||
for (typename std::map<K, V>::iterator it = value.begin(); it != value.end(); ++it)
|
||||
{
|
||||
KS()(serialize, "key", it->first);
|
||||
VS()(serialize, "value", it->second);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename K, typename V, typename C>
|
||||
void operator()(ISerializer& serialize, const char* UNUSED(name), std::map<K, V>& value, C& context)
|
||||
{
|
||||
size_t len = value.size();
|
||||
serialize.NumberU32_Unbounded("length", (u32)len);
|
||||
for (typename std::map<K, V>::iterator it = value.begin(); it != value.end(); ++it)
|
||||
{
|
||||
KS()(serialize, "key", it->first);
|
||||
VS()(serialize, "value", it->second, context);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename M>
|
||||
void operator()(IDeserializer& deserialize, const char* UNUSED(name), M& value)
|
||||
{
|
||||
typedef typename M::key_type K;
|
||||
typedef typename M::value_type::second_type V; // M::data_type gives errors with gcc
|
||||
value.clear();
|
||||
u32 len;
|
||||
deserialize.NumberU32_Unbounded("length", len);
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
{
|
||||
K k;
|
||||
V v;
|
||||
KS()(deserialize, "key", k);
|
||||
VS()(deserialize, "value", v);
|
||||
value.emplace(std::move(k), std::move(v));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename M, typename C>
|
||||
void operator()(IDeserializer& deserialize, const char* UNUSED(name), M& value, C& context)
|
||||
{
|
||||
typedef typename M::key_type K;
|
||||
typedef typename M::value_type::second_type V; // M::data_type gives errors with gcc
|
||||
value.clear();
|
||||
u32 len;
|
||||
deserialize.NumberU32_Unbounded("length", len);
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
{
|
||||
K k;
|
||||
V v;
|
||||
KS()(deserialize, "key", k);
|
||||
VS()(deserialize, "value", v, context);
|
||||
value.emplace(std::move(k), std::move(v));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// We have to order the map before serializing to make things consistent
|
||||
template<typename KS, typename VS>
|
||||
struct SerializeUnorderedMap
|
||||
{
|
||||
template<typename K, typename V>
|
||||
void operator()(ISerializer& serialize, const char* name, std::unordered_map<K, V>& value)
|
||||
{
|
||||
std::map<K, V> ordered_value(value.begin(), value.end());
|
||||
SerializeMap<KS, VS>()(serialize, name, ordered_value);
|
||||
}
|
||||
|
||||
template<typename K, typename V>
|
||||
void operator()(IDeserializer& deserialize, const char* name, std::unordered_map<K, V>& value)
|
||||
{
|
||||
SerializeMap<KS, VS>()(deserialize, name, value);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, T max>
|
||||
struct SerializeU8_Enum
|
||||
{
|
||||
void operator()(ISerializer& serialize, const char* name, T value)
|
||||
{
|
||||
serialize.NumberU8(name, value, 0, max);
|
||||
}
|
||||
|
||||
void operator()(IDeserializer& deserialize, const char* name, T& value)
|
||||
{
|
||||
u8 val;
|
||||
deserialize.NumberU8(name, val, 0, max);
|
||||
value = static_cast<T>(val);
|
||||
}
|
||||
};
|
||||
|
||||
struct SerializeU8_Unbounded
|
||||
{
|
||||
void operator()(ISerializer& serialize, const char* name, u8 value)
|
||||
{
|
||||
serialize.NumberU8_Unbounded(name, value);
|
||||
}
|
||||
|
||||
void operator()(IDeserializer& deserialize, const char* name, u8& value)
|
||||
{
|
||||
deserialize.NumberU8_Unbounded(name, value);
|
||||
}
|
||||
};
|
||||
|
||||
struct SerializeU16_Unbounded
|
||||
{
|
||||
void operator()(ISerializer& serialize, const char* name, u16 value)
|
||||
{
|
||||
serialize.NumberU16_Unbounded(name, value);
|
||||
}
|
||||
|
||||
void operator()(IDeserializer& deserialize, const char* name, u16& value)
|
||||
{
|
||||
deserialize.NumberU16_Unbounded(name, value);
|
||||
}
|
||||
};
|
||||
|
||||
struct SerializeU32_Unbounded
|
||||
{
|
||||
void operator()(ISerializer& serialize, const char* name, u32 value)
|
||||
{
|
||||
serialize.NumberU32_Unbounded(name, value);
|
||||
}
|
||||
|
||||
void operator()(IDeserializer& deserialize, const char* name, u32& value)
|
||||
{
|
||||
deserialize.NumberU32_Unbounded(name, value);
|
||||
}
|
||||
};
|
||||
|
||||
struct SerializeI32_Unbounded
|
||||
{
|
||||
void operator()(ISerializer& serialize, const char* name, i32 value)
|
||||
{
|
||||
serialize.NumberI32_Unbounded(name, value);
|
||||
}
|
||||
|
||||
void operator()(IDeserializer& deserialize, const char* name, i32& value)
|
||||
{
|
||||
deserialize.NumberI32_Unbounded(name, value);
|
||||
}
|
||||
};
|
||||
|
||||
struct SerializeBool
|
||||
{
|
||||
void operator()(ISerializer& serialize, const char* name, bool value)
|
||||
{
|
||||
serialize.Bool(name, value);
|
||||
}
|
||||
|
||||
void operator()(IDeserializer& deserialize, const char* name, bool& value)
|
||||
{
|
||||
deserialize.Bool(name, value);
|
||||
}
|
||||
};
|
||||
|
||||
struct SerializeString
|
||||
{
|
||||
void operator()(ISerializer& serialize, const char* name, const std::string& value)
|
||||
{
|
||||
serialize.StringASCII(name, value, 0, UINT32_MAX);
|
||||
}
|
||||
|
||||
void operator()(IDeserializer& deserialize, const char* name, std::string& value)
|
||||
{
|
||||
deserialize.StringASCII(name, value, 0, UINT32_MAX);
|
||||
}
|
||||
};
|
||||
|
||||
struct SerializeWaypoint
|
||||
{
|
||||
void operator()(ISerializer& serialize, const char* UNUSED(name), const Waypoint& value)
|
||||
{
|
||||
serialize.NumberFixed_Unbounded("waypoint x", value.x);
|
||||
serialize.NumberFixed_Unbounded("waypoint z", value.z);
|
||||
}
|
||||
|
||||
void operator()(IDeserializer& deserialize, const char* UNUSED(name), Waypoint& value)
|
||||
{
|
||||
deserialize.NumberFixed_Unbounded("waypoint x", value.x);
|
||||
deserialize.NumberFixed_Unbounded("waypoint z", value.z);
|
||||
}
|
||||
};
|
||||
|
||||
struct SerializeGoal
|
||||
{
|
||||
template<typename S>
|
||||
void operator()(S& serialize, const char* UNUSED(name), PathGoal& value)
|
||||
{
|
||||
SerializeU8_Enum<PathGoal::Type, PathGoal::INVERTED_SQUARE>()(serialize, "type", value.type);
|
||||
serialize.NumberFixed_Unbounded("goal x", value.x);
|
||||
serialize.NumberFixed_Unbounded("goal z", value.z);
|
||||
serialize.NumberFixed_Unbounded("goal u x", value.u.X);
|
||||
serialize.NumberFixed_Unbounded("goal u z", value.u.Y);
|
||||
serialize.NumberFixed_Unbounded("goal v x", value.v.X);
|
||||
serialize.NumberFixed_Unbounded("goal v z", value.v.Y);
|
||||
serialize.NumberFixed_Unbounded("goal hw", value.hw);
|
||||
serialize.NumberFixed_Unbounded("goal hh", value.hh);
|
||||
serialize.NumberFixed_Unbounded("maxdist", value.maxdist);
|
||||
}
|
||||
};
|
||||
template<typename S, class T>
|
||||
using qualify = std::conditional_t<std::is_same_v<S, ISerializer&>, const T&, T&>;
|
||||
}
|
||||
|
||||
#endif // INCLUDED_SERIALIZETEMPLATES
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#include "Entity.h"
|
||||
|
||||
#include "simulation2/serialization/SerializeTemplates.h"
|
||||
|
||||
/**
|
||||
* A fast replacement for map<entity_id_t, T>.
|
||||
* We make the following assumptions:
|
||||
|
|
@ -241,19 +243,18 @@ fill_gaps:
|
|||
}
|
||||
};
|
||||
|
||||
template<class VSerializer>
|
||||
struct SerializeEntityMap
|
||||
template<typename T>
|
||||
struct SerializeHelper<EntityMap<T>>
|
||||
{
|
||||
template<class V>
|
||||
void operator()(ISerializer& serialize, const char* UNUSED(name), EntityMap<V>& value)
|
||||
void operator()(ISerializer& serialize, const char* UNUSED(name), EntityMap<T>& value)
|
||||
{
|
||||
size_t len = value.size();
|
||||
serialize.NumberU32_Unbounded("length", (u32)len);
|
||||
size_t count = 0;
|
||||
for (typename EntityMap<V>::iterator it = value.begin(); it != value.end(); ++it)
|
||||
for (typename EntityMap<T>::iterator it = value.begin(); it != value.end(); ++it)
|
||||
{
|
||||
serialize.NumberU32_Unbounded("key", it->first);
|
||||
VSerializer()(serialize, "value", it->second);
|
||||
Serializer(serialize, "value", it->second);
|
||||
count++;
|
||||
}
|
||||
// test to see if the entityMap count wasn't wrong
|
||||
|
|
@ -261,8 +262,7 @@ struct SerializeEntityMap
|
|||
ENSURE(count == len);
|
||||
}
|
||||
|
||||
template<class V>
|
||||
void operator()(IDeserializer& deserialize, const char* UNUSED(name), EntityMap<V>& value)
|
||||
void operator()(IDeserializer& deserialize, const char* UNUSED(name), EntityMap<T>& value)
|
||||
{
|
||||
value.clear();
|
||||
uint32_t len;
|
||||
|
|
@ -270,9 +270,9 @@ struct SerializeEntityMap
|
|||
for (size_t i = 0; i < len; ++i)
|
||||
{
|
||||
entity_id_t k;
|
||||
V v;
|
||||
T v;
|
||||
deserialize.NumberU32_Unbounded("key", k);
|
||||
VSerializer()(deserialize, "value", v);
|
||||
Serializer(deserialize, "value", v);
|
||||
value.insert(k, v);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,12 +20,13 @@
|
|||
#include "scriptinterface/ScriptInterface.h"
|
||||
#include "simulation2/helpers/Grid.h"
|
||||
#include "simulation2/serialization/DebugSerializer.h"
|
||||
#include "simulation2/serialization/SerializeTemplates.h"
|
||||
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#include "simulation2/serialization/SerializedTypes.h"
|
||||
|
||||
class TestSerializeTemplates : public CxxTest::TestSuite
|
||||
{
|
||||
public:
|
||||
|
|
@ -38,7 +39,7 @@ public:
|
|||
std::array<u32, 6> value = {
|
||||
3, 0, 1, 4, 1, 5
|
||||
};
|
||||
SerializeArray<SerializeU32_Unbounded>()(serialize, "E", value);
|
||||
Serializer(serialize, "E", value);
|
||||
TS_ASSERT_STR_EQUALS(stream.str(), "E: 3\nE: 0\nE: 1\nE: 4\nE: 1\nE: 5\n");
|
||||
}
|
||||
|
||||
|
|
@ -51,7 +52,7 @@ public:
|
|||
std::vector<u32> value = {
|
||||
3, 0, 1, 4, 1, 5
|
||||
};
|
||||
SerializeVector<SerializeU32_Unbounded>()(serialize, "E", value);
|
||||
Serializer(serialize, "E", value);
|
||||
TS_ASSERT_STR_EQUALS(stream.str(), "length: 6\nE: 3\nE: 0\nE: 1\nE: 4\nE: 1\nE: 5\n");
|
||||
}
|
||||
|
||||
|
|
@ -64,7 +65,7 @@ public:
|
|||
std::set<u32> value = {
|
||||
3, 0, 1, 4, 1, 5
|
||||
};
|
||||
SerializeSet<SerializeU32_Unbounded>()(serialize, "E", value);
|
||||
Serializer(serialize, "E", value);
|
||||
TS_ASSERT_STR_EQUALS(stream.str(), "size: 5\nE: 0\nE: 1\nE: 3\nE: 4\nE: 5\n");
|
||||
}
|
||||
|
||||
|
|
@ -81,7 +82,7 @@ public:
|
|||
for (u8 i = 0; i < value.width(); ++i)
|
||||
value.set(i, j, ((i % 2) + (j % 2)) % 2);
|
||||
|
||||
SerializedGridCompressed<SerializeU16_Unbounded>()(serialize, "E", value);
|
||||
Serializer(serialize, "E", value);
|
||||
TS_ASSERT_STR_EQUALS(stream.str(), "width: 3\nheight: 2\n"
|
||||
"#: 1\nE: 0\n#: 1\nE: 1\n#: 1\nE: 0\n"
|
||||
"#: 1\nE: 1\n#: 1\nE: 0\n#: 1\nE: 1\n");
|
||||
|
|
|
|||
Loading…
Reference in a new issue