1
0
forked from 0ad/0ad

Serialize RNG state

This was SVN commit r7564.
This commit is contained in:
Ykkrosh 2010-05-22 01:32:11 +00:00
parent 386f322b1c
commit 4e661a205d
2 changed files with 37 additions and 4 deletions

View File

@ -30,10 +30,28 @@
#include "ps/CLogger.h"
std::string SerializeRNG(const boost::rand48& rng)
{
std::stringstream s;
s << rng;
return s.str();
}
void DeserializeRNG(const std::string& str, boost::rand48& rng)
{
std::stringstream s;
s << str;
s >> rng;
}
bool CComponentManager::DumpDebugState(std::ostream& stream)
{
CDebugSerializer serializer(m_ScriptInterface, stream);
serializer.StringASCII("rng", SerializeRNG(m_RNG), 0, 32);
serializer.TextLine("entities:");
// We want the output to be grouped by entity ID, so invert the CComponentManager data structures
std::map<entity_id_t, std::map<ComponentTypeId, IComponent*> > components;
std::map<ComponentTypeId, std::string> names;
@ -77,8 +95,13 @@ bool CComponentManager::DumpDebugState(std::ostream& stream)
bool CComponentManager::ComputeStateHash(std::string& outHash)
{
// Hash serialization: this includes the minimal data necessary to detect
// differences in the state, and ignores things like counts and names
CHashSerializer serializer(m_ScriptInterface);
serializer.StringASCII("rng", SerializeRNG(m_RNG), 0, 32);
std::map<ComponentTypeId, std::map<entity_id_t, IComponent*> >::const_iterator cit = m_ComponentsByTypeId.begin();
for (; cit != m_ComponentsByTypeId.end(); ++cit)
{
@ -136,6 +159,7 @@ bool CComponentManager::SerializeState(std::ostream& stream)
// and it's (hopefully) easier to just expect callers to flush the queue before serializing
debug_assert(m_DestructionQueue.empty());
serializer.StringASCII("rng", SerializeRNG(m_RNG), 0, 32);
serializer.NumberU32_Unbounded("next entity id", m_NextEntityId);
uint32_t numComponentTypes = 0;
@ -204,6 +228,10 @@ bool CComponentManager::DeserializeState(std::istream& stream)
ResetState();
std::string rng;
deserializer.StringASCII(rng, 0, 32);
DeserializeRNG(rng, m_RNG);
deserializer.NumberU32_Unbounded(m_NextEntityId); // TODO: use sensible bounds
uint32_t numComponentTypes;

View File

@ -567,6 +567,8 @@ public:
std::stringstream debugStream;
TS_ASSERT(man.DumpDebugState(debugStream));
TS_ASSERT_STR_EQUALS(debugStream.str(),
"rng: \"78606\"\n"
"entities:\n"
"- id: 1\n"
" Test1A:\n"
" x: 11000\n"
@ -587,13 +589,14 @@ public:
std::string hash;
TS_ASSERT(man.ComputeStateHash(hash));
TS_ASSERT_EQUALS(hash.length(), (size_t)16);
TS_ASSERT_SAME_DATA(hash.data(), "\xea\xd8\xe6\x94\xc0\x6b\x2a\xa1\xcc\x6d\x5d\xab\x48\x45\x75\xed", 16);
// echo -en "\x01\0\0\0\x01\0\0\0\xf8\x2a\0\0\x02\0\0\0\xd2\x04\0\0\x04\0\0\0\x01\0\0\0\x08\x52\0\0" | openssl md5 | perl -pe 's/(..)/\\x$1/g'
// ^^Test1A^^ ^^^ent1^^ ^^^11000^^^ ^^^ent2^^ ^^^1234^^^ ^^Test2A^^ ^^ent1^^ ^^^21000^^^
TS_ASSERT_SAME_DATA(hash.data(), "\x1c\x45\x2b\x20\x1f\x0c\x00\x93\x60\x78\xe2\x63\xb1\x47\x08\x19", 16);
// echo -en "\x05\x00\x00\x0078606\x01\0\0\0\x01\0\0\0\xf8\x2a\0\0\x02\0\0\0\xd2\x04\0\0\x04\0\0\0\x01\0\0\0\x08\x52\0\0" | openssl md5 | perl -pe 's/(..)/\\x$1/g'
// ^^^^^^^^ rng ^^^^^^^^ ^^Test1A^^ ^^^ent1^^ ^^^11000^^^ ^^^ent2^^ ^^^1234^^^ ^^Test2A^^ ^^ent1^^ ^^^21000^^^
std::stringstream stateStream;
TS_ASSERT(man.SerializeState(stateStream));
TS_ASSERT_STREAM(stateStream, 60,
TS_ASSERT_STREAM(stateStream, 69,
"\x05\x00\x00\x00\x37\x38\x36\x30\x36" // RNG
"\x02\x00\x00\x00" // next entity ID
"\x02\x00\x00\x00" // num component types
"\x06\x00\x00\x00Test1A"
@ -652,6 +655,8 @@ public:
std::stringstream debugStream;
TS_ASSERT(man.DumpDebugState(debugStream));
TS_ASSERT_STR_EQUALS(debugStream.str(),
"rng: \"78606\"\n"
"entities:\n"
"- id: 1\n"
" TestScript1_values:\n"
" object: ({x:1234, str:\"this is a string\", things:{a:1, b:\"2\", c:[3, \"4\", [5, []]]}})\n"