mirror of
https://github.com/The-Powder-Toy/The-Powder-Toy.git
synced 2025-08-11 19:04:05 +02:00
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:
@@ -25,13 +25,11 @@ static void CheckBsonFieldFloat(bson_iterator iter, const char *field, float *se
|
|||||||
|
|
||||||
GameSave::GameSave(int width, int height)
|
GameSave::GameSave(int width, int height)
|
||||||
{
|
{
|
||||||
rngState = RNG().state(); // initialize it with something sane
|
|
||||||
setSize(width, height);
|
setSize(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
GameSave::GameSave(const std::vector<char> &data, bool newWantAuthors)
|
GameSave::GameSave(const std::vector<char> &data, bool newWantAuthors)
|
||||||
{
|
{
|
||||||
rngState = RNG().state(); // initialize it with something sane
|
|
||||||
wantAuthors = newWantAuthors;
|
wantAuthors = newWantAuthors;
|
||||||
blockWidth = 0;
|
blockWidth = 0;
|
||||||
blockHeight = 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, "frameCount", reinterpret_cast<int64_t *>(&frameCount));
|
||||||
CheckBsonFieldLong(iter, "rngState0", reinterpret_cast<int64_t *>(&rngState[0]));
|
CheckBsonFieldLong(iter, "rngState0", reinterpret_cast<int64_t *>(&rngState[0]));
|
||||||
CheckBsonFieldLong(iter, "rngState1", reinterpret_cast<int64_t *>(&rngState[1]));
|
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)
|
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_bool(&b, "ensureDeterminism", ensureDeterminism);
|
||||||
bson_append_binary(&b, "blockAir", (char)BSON_BIN_USER, (const char *)&blockAirData[0], blockAirDataLen);
|
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, "frameCount", int64_t(frameCount));
|
||||||
bson_append_long(&b, "rngState0", int64_t(rngState[0]));
|
bson_append_binary(&b, "rngState", (char)BSON_BIN_USER, (const char *)&rngState, sizeof(rngState));
|
||||||
bson_append_long(&b, "rngState1", int64_t(rngState[1]));
|
|
||||||
RESTRICTVERSION(98, 0);
|
RESTRICTVERSION(98, 0);
|
||||||
}
|
}
|
||||||
unsigned int signsCount = 0;
|
unsigned int signsCount = 0;
|
||||||
|
@@ -97,6 +97,7 @@ public:
|
|||||||
bool hasAmbientHeat = false;
|
bool hasAmbientHeat = false;
|
||||||
bool hasBlockAirMaps = false; // only written by readOPS, never read
|
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 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;
|
RNG::State rngState;
|
||||||
uint64_t frameCount = 0;
|
uint64_t frameCount = 0;
|
||||||
|
|
||||||
|
@@ -955,7 +955,14 @@ void GameModel::SaveToSimParameters(const GameSave *saveData)
|
|||||||
sim->grav->stop_grav_async();
|
sim->grav->stop_grav_async();
|
||||||
}
|
}
|
||||||
sim->frameCount = saveData->frameCount;
|
sim->frameCount = saveData->frameCount;
|
||||||
|
if (saveData->hasRngState)
|
||||||
|
{
|
||||||
sim->rng.state(saveData->rngState);
|
sim->rng.state(saveData->rngState);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sim->rng = RNG();
|
||||||
|
}
|
||||||
sim->ensureDeterminism = saveData->ensureDeterminism;
|
sim->ensureDeterminism = saveData->ensureDeterminism;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user