Properly seed rng at load time for saves that don't carry rng state

Also save rngState as a user object rather than two separate i64s.
This commit is contained in:
Tamás Bálint Misius
2023-04-15 23:03:54 +02:00
parent a8604ef579
commit 34e4d90dac
3 changed files with 23 additions and 6 deletions

View File

@@ -25,13 +25,11 @@ static void CheckBsonFieldFloat(bson_iterator iter, const char *field, float *se
GameSave::GameSave(int width, int height)
{
rngState = RNG().state(); // initialize it with something sane
setSize(width, height);
}
GameSave::GameSave(const std::vector<char> &data, bool newWantAuthors)
{
rngState = RNG().state(); // initialize it with something sane
wantAuthors = newWantAuthors;
blockWidth = 0;
blockHeight = 0;
@@ -543,7 +541,19 @@ void GameSave::readOPS(const std::vector<char> &data)
CheckBsonFieldLong(iter, "frameCount", reinterpret_cast<int64_t *>(&frameCount));
CheckBsonFieldLong(iter, "rngState0", reinterpret_cast<int64_t *>(&rngState[0]));
CheckBsonFieldLong(iter, "rngState1", reinterpret_cast<int64_t *>(&rngState[1]));
if (!strcmp(bson_iterator_key(&iter), "signs"))
if (!strcmp(bson_iterator_key(&iter), "rngState"))
{
if (bson_iterator_type(&iter) == BSON_BINDATA && ((unsigned char)bson_iterator_bin_type(&iter)) == BSON_BIN_USER && bson_iterator_bin_len(&iter) == sizeof(rngState))
{
memcpy(&rngState, bson_iterator_bin_data(&iter), sizeof(rngState));
hasRngState = true;
}
else
{
fprintf(stderr, "Invalid datatype for rngState: %d[%d] %d[%d] %d[%d]\n", bson_iterator_type(&iter), bson_iterator_type(&iter)==BSON_BINDATA, (unsigned char)bson_iterator_bin_type(&iter), ((unsigned char)bson_iterator_bin_type(&iter))==BSON_BIN_USER, bson_iterator_bin_len(&iter), bson_iterator_bin_len(&iter)>0);
}
}
else if (!strcmp(bson_iterator_key(&iter), "signs"))
{
if (bson_iterator_type(&iter)==BSON_ARRAY)
{
@@ -2550,8 +2560,7 @@ std::pair<bool, std::vector<char>> GameSave::serialiseOPS() const
bson_append_bool(&b, "ensureDeterminism", ensureDeterminism);
bson_append_binary(&b, "blockAir", (char)BSON_BIN_USER, (const char *)&blockAirData[0], blockAirDataLen);
bson_append_long(&b, "frameCount", int64_t(frameCount));
bson_append_long(&b, "rngState0", int64_t(rngState[0]));
bson_append_long(&b, "rngState1", int64_t(rngState[1]));
bson_append_binary(&b, "rngState", (char)BSON_BIN_USER, (const char *)&rngState, sizeof(rngState));
RESTRICTVERSION(98, 0);
}
unsigned int signsCount = 0;

View File

@@ -97,6 +97,7 @@ public:
bool hasAmbientHeat = false;
bool hasBlockAirMaps = false; // only written by readOPS, never read
bool ensureDeterminism = false; // only taken seriously by serializeOPS; readOPS may set this even if the save does not have everything required for determinism
bool hasRngState = false; // only written by readOPS, never read
RNG::State rngState;
uint64_t frameCount = 0;

View File

@@ -955,7 +955,14 @@ void GameModel::SaveToSimParameters(const GameSave *saveData)
sim->grav->stop_grav_async();
}
sim->frameCount = saveData->frameCount;
sim->rng.state(saveData->rngState);
if (saveData->hasRngState)
{
sim->rng.state(saveData->rngState);
}
else
{
sim->rng = RNG();
}
sim->ensureDeterminism = saveData->ensureDeterminism;
}