Add ensureDeterminism to saves
This commit is contained in:
parent
9c3b966c18
commit
a8604ef579
@ -539,6 +539,7 @@ void GameSave::readOPS(const std::vector<char> &data)
|
|||||||
CheckBsonFieldFloat(iter, "ambientAirTemp", &ambientAirTemp);
|
CheckBsonFieldFloat(iter, "ambientAirTemp", &ambientAirTemp);
|
||||||
CheckBsonFieldInt(iter, "edgeMode", &edgeMode);
|
CheckBsonFieldInt(iter, "edgeMode", &edgeMode);
|
||||||
CheckBsonFieldInt(iter, "pmapbits", &pmapbits);
|
CheckBsonFieldInt(iter, "pmapbits", &pmapbits);
|
||||||
|
CheckBsonFieldBool(iter, "ensureDeterminism", &ensureDeterminism);
|
||||||
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]));
|
||||||
@ -2546,6 +2547,7 @@ std::pair<bool, std::vector<char>> GameSave::serialiseOPS() const
|
|||||||
bson_append_binary(&b, "soapLinks", (char)BSON_BIN_USER, (const char *)&soapLinkData[0], soapLinkDataLen);
|
bson_append_binary(&b, "soapLinks", (char)BSON_BIN_USER, (const char *)&soapLinkData[0], soapLinkDataLen);
|
||||||
if (ensureDeterminism)
|
if (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_long(&b, "rngState0", int64_t(rngState[0]));
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "common/Plane.h"
|
#include "common/Plane.h"
|
||||||
#include "common/String.h"
|
#include "common/String.h"
|
||||||
|
#include "common/tpt-rand.h"
|
||||||
#include "simulation/Sign.h"
|
#include "simulation/Sign.h"
|
||||||
#include "simulation/Particle.h"
|
#include "simulation/Particle.h"
|
||||||
#include "Misc.h"
|
#include "Misc.h"
|
||||||
@ -95,8 +96,8 @@ public:
|
|||||||
bool hasPressure = false;
|
bool hasPressure = false;
|
||||||
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 read by serializeOPS, never written
|
bool ensureDeterminism = false; // only taken seriously by serializeOPS; readOPS may set this even if the save does not have everything required for determinism
|
||||||
std::array<uint64_t, 2> rngState;
|
RNG::State rngState;
|
||||||
uint64_t frameCount = 0;
|
uint64_t frameCount = 0;
|
||||||
|
|
||||||
//Simulation data
|
//Simulation data
|
||||||
|
@ -5,8 +5,11 @@
|
|||||||
|
|
||||||
class RNG
|
class RNG
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
using State = std::array<uint64_t, 2>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::array<uint64_t, 2> s;
|
State s;
|
||||||
uint64_t next();
|
uint64_t next();
|
||||||
public:
|
public:
|
||||||
unsigned int operator()();
|
unsigned int operator()();
|
||||||
@ -18,12 +21,12 @@ public:
|
|||||||
RNG();
|
RNG();
|
||||||
void seed(unsigned int sd);
|
void seed(unsigned int sd);
|
||||||
|
|
||||||
void state(std::array<uint64_t, 2> ns)
|
void state(State ns)
|
||||||
{
|
{
|
||||||
s = ns;
|
s = ns;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<uint64_t, 2> state() const
|
State state() const
|
||||||
{
|
{
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
@ -934,6 +934,31 @@ SaveInfo * GameModel::GetSave()
|
|||||||
return currentSave;
|
return currentSave;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameModel::SaveToSimParameters(const GameSave *saveData)
|
||||||
|
{
|
||||||
|
SetPaused(saveData->paused | GetPaused());
|
||||||
|
sim->gravityMode = saveData->gravityMode;
|
||||||
|
sim->customGravityX = saveData->customGravityX;
|
||||||
|
sim->customGravityY = saveData->customGravityY;
|
||||||
|
sim->air->airMode = saveData->airMode;
|
||||||
|
sim->air->ambientAirTemp = saveData->ambientAirTemp;
|
||||||
|
sim->edgeMode = saveData->edgeMode;
|
||||||
|
sim->legacy_enable = saveData->legacyEnable;
|
||||||
|
sim->water_equal_test = saveData->waterEEnabled;
|
||||||
|
sim->aheat_enable = saveData->aheatEnable;
|
||||||
|
if (saveData->gravityEnable && !sim->grav->IsEnabled())
|
||||||
|
{
|
||||||
|
sim->grav->start_grav_async();
|
||||||
|
}
|
||||||
|
else if (!saveData->gravityEnable && sim->grav->IsEnabled())
|
||||||
|
{
|
||||||
|
sim->grav->stop_grav_async();
|
||||||
|
}
|
||||||
|
sim->frameCount = saveData->frameCount;
|
||||||
|
sim->rng.state(saveData->rngState);
|
||||||
|
sim->ensureDeterminism = saveData->ensureDeterminism;
|
||||||
|
}
|
||||||
|
|
||||||
void GameModel::SetSave(SaveInfo * newSave, bool invertIncludePressure)
|
void GameModel::SetSave(SaveInfo * newSave, bool invertIncludePressure)
|
||||||
{
|
{
|
||||||
if(currentSave != newSave)
|
if(currentSave != newSave)
|
||||||
@ -947,23 +972,10 @@ void GameModel::SetSave(SaveInfo * newSave, bool invertIncludePressure)
|
|||||||
delete currentFile;
|
delete currentFile;
|
||||||
currentFile = NULL;
|
currentFile = NULL;
|
||||||
|
|
||||||
if(currentSave && currentSave->GetGameSave())
|
if (newSave && newSave->GetGameSave())
|
||||||
{
|
{
|
||||||
GameSave * saveData = currentSave->GetGameSave();
|
GameSave *saveData = newSave->GetGameSave();
|
||||||
SetPaused(saveData->paused | GetPaused());
|
SaveToSimParameters(saveData);
|
||||||
sim->gravityMode = saveData->gravityMode;
|
|
||||||
sim->customGravityX = saveData->customGravityX;
|
|
||||||
sim->customGravityY = saveData->customGravityY;
|
|
||||||
sim->air->airMode = saveData->airMode;
|
|
||||||
sim->air->ambientAirTemp = saveData->ambientAirTemp;
|
|
||||||
sim->edgeMode = saveData->edgeMode;
|
|
||||||
sim->legacy_enable = saveData->legacyEnable;
|
|
||||||
sim->water_equal_test = saveData->waterEEnabled;
|
|
||||||
sim->aheat_enable = saveData->aheatEnable;
|
|
||||||
if(saveData->gravityEnable)
|
|
||||||
sim->grav->start_grav_async();
|
|
||||||
else
|
|
||||||
sim->grav->stop_grav_async();
|
|
||||||
sim->clear_sim();
|
sim->clear_sim();
|
||||||
ren->ClearAccumulation();
|
ren->ClearAccumulation();
|
||||||
if (!sim->Load(saveData, !invertIncludePressure))
|
if (!sim->Load(saveData, !invertIncludePressure))
|
||||||
@ -1011,27 +1023,10 @@ void GameModel::SetSaveFile(SaveFile * newSave, bool invertIncludePressure)
|
|||||||
delete currentSave;
|
delete currentSave;
|
||||||
currentSave = NULL;
|
currentSave = NULL;
|
||||||
|
|
||||||
if(newSave && newSave->GetGameSave())
|
if (newSave && newSave->GetGameSave())
|
||||||
{
|
{
|
||||||
GameSave * saveData = newSave->GetGameSave();
|
GameSave *saveData = newSave->GetGameSave();
|
||||||
SetPaused(saveData->paused | GetPaused());
|
SaveToSimParameters(saveData);
|
||||||
sim->gravityMode = saveData->gravityMode;
|
|
||||||
sim->customGravityX = saveData->customGravityX;
|
|
||||||
sim->customGravityY = saveData->customGravityY;
|
|
||||||
sim->air->airMode = saveData->airMode;
|
|
||||||
sim->air->ambientAirTemp = saveData->ambientAirTemp;
|
|
||||||
sim->edgeMode = saveData->edgeMode;
|
|
||||||
sim->legacy_enable = saveData->legacyEnable;
|
|
||||||
sim->water_equal_test = saveData->waterEEnabled;
|
|
||||||
sim->aheat_enable = saveData->aheatEnable;
|
|
||||||
if(saveData->gravityEnable && !sim->grav->IsEnabled())
|
|
||||||
{
|
|
||||||
sim->grav->start_grav_async();
|
|
||||||
}
|
|
||||||
else if(!saveData->gravityEnable && sim->grav->IsEnabled())
|
|
||||||
{
|
|
||||||
sim->grav->stop_grav_async();
|
|
||||||
}
|
|
||||||
sim->clear_sim();
|
sim->clear_sim();
|
||||||
ren->ClearAccumulation();
|
ren->ClearAccumulation();
|
||||||
if (!sim->Load(saveData, !invertIncludePressure))
|
if (!sim->Load(saveData, !invertIncludePressure))
|
||||||
|
@ -114,6 +114,9 @@ private:
|
|||||||
void notifyToolTipChanged();
|
void notifyToolTipChanged();
|
||||||
void notifyQuickOptionsChanged();
|
void notifyQuickOptionsChanged();
|
||||||
void notifyLastToolChanged();
|
void notifyLastToolChanged();
|
||||||
|
|
||||||
|
void SaveToSimParameters(const GameSave *saveData);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GameModel();
|
GameModel();
|
||||||
~GameModel();
|
~GameModel();
|
||||||
|
@ -214,6 +214,17 @@ static int simHash(lua_State *l)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int simEnsureDeterminism(lua_State *l)
|
||||||
|
{
|
||||||
|
if (lua_gettop(l))
|
||||||
|
{
|
||||||
|
luacon_sim->ensureDeterminism = lua_toboolean(l, 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
lua_pushboolean(l, luacon_sim->ensureDeterminism);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
LuaScriptInterface::LuaScriptInterface(GameController * c, GameModel * m):
|
LuaScriptInterface::LuaScriptInterface(GameController * c, GameModel * m):
|
||||||
TPTScriptInterface(c, m),
|
TPTScriptInterface(c, m),
|
||||||
luacon_mousex(0),
|
luacon_mousex(0),
|
||||||
@ -1003,6 +1014,7 @@ void LuaScriptInterface::initSimulationAPI()
|
|||||||
{"temperatureScale", simulation_temperatureScale},
|
{"temperatureScale", simulation_temperatureScale},
|
||||||
{"randomseed", simRandomseed},
|
{"randomseed", simRandomseed},
|
||||||
{"hash", simHash},
|
{"hash", simHash},
|
||||||
|
{"ensureDeterminism", simEnsureDeterminism},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
luaL_register(l, "simulation", simulationAPIMethods);
|
luaL_register(l, "simulation", simulationAPIMethods);
|
||||||
|
@ -64,8 +64,6 @@ int Simulation::Load(const GameSave * originalSave, bool includePressure, int fu
|
|||||||
}
|
}
|
||||||
|
|
||||||
RecalcFreeParticles(false);
|
RecalcFreeParticles(false);
|
||||||
frameCount = save->frameCount;
|
|
||||||
rng.state(save->rngState);
|
|
||||||
|
|
||||||
auto &possiblyCarriesType = Particle::PossiblyCarriesType();
|
auto &possiblyCarriesType = Particle::PossiblyCarriesType();
|
||||||
auto &properties = Particle::GetProperties();
|
auto &properties = Particle::GetProperties();
|
||||||
@ -490,15 +488,12 @@ GameSave * Simulation::Save(bool includePressure, int fullX, int fullY, int full
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (includePressure)
|
if (includePressure || ensureDeterminism)
|
||||||
{
|
{
|
||||||
newSave->hasPressure = true;
|
newSave->hasPressure = true;
|
||||||
newSave->hasAmbientHeat = true;
|
newSave->hasAmbientHeat = true;
|
||||||
}
|
}
|
||||||
if (true) // TODO: tie to an option maybe?
|
newSave->ensureDeterminism = ensureDeterminism;
|
||||||
{
|
|
||||||
newSave->ensureDeterminism = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
newSave->stkm.rocketBoots1 = player.rocketBoots;
|
newSave->stkm.rocketBoots1 = player.rocketBoots;
|
||||||
newSave->stkm.rocketBoots2 = player2.rocketBoots;
|
newSave->stkm.rocketBoots2 = player2.rocketBoots;
|
||||||
@ -1092,6 +1087,7 @@ int Simulation::parts_avg(int ci, int ni,int t)
|
|||||||
|
|
||||||
void Simulation::clear_sim(void)
|
void Simulation::clear_sim(void)
|
||||||
{
|
{
|
||||||
|
ensureDeterminism = false;
|
||||||
frameCount = 0;
|
frameCount = 0;
|
||||||
debug_nextToUpdate = 0;
|
debug_nextToUpdate = 0;
|
||||||
debug_mostRecentlyUpdated = -1;
|
debug_mostRecentlyUpdated = -1;
|
||||||
|
@ -119,6 +119,7 @@ public:
|
|||||||
int sandcolour_frame;
|
int sandcolour_frame;
|
||||||
int deco_space;
|
int deco_space;
|
||||||
uint64_t frameCount;
|
uint64_t frameCount;
|
||||||
|
bool ensureDeterminism;
|
||||||
|
|
||||||
int Load(const GameSave * save, bool includePressure);
|
int Load(const GameSave * save, bool includePressure);
|
||||||
int Load(const GameSave * save, bool includePressure, int x, int y);
|
int Load(const GameSave * save, bool includePressure, int x, int y);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "Particle.h"
|
#include "Particle.h"
|
||||||
#include "Sign.h"
|
#include "Sign.h"
|
||||||
#include "Stickman.h"
|
#include "Stickman.h"
|
||||||
|
#include "common/tpt-rand.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <json/json.h>
|
#include <json/json.h>
|
||||||
@ -36,7 +37,7 @@ public:
|
|||||||
std::vector<sign> signs;
|
std::vector<sign> signs;
|
||||||
|
|
||||||
uint64_t FrameCount;
|
uint64_t FrameCount;
|
||||||
std::array<uint64_t, 2> RngState;
|
RNG::State RngState;
|
||||||
|
|
||||||
uint32_t Hash() const;
|
uint32_t Hash() const;
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ struct SnapshotDelta
|
|||||||
HunkVector<uint32_t> stickmen;
|
HunkVector<uint32_t> stickmen;
|
||||||
SingleDiff<std::vector<sign>> signs;
|
SingleDiff<std::vector<sign>> signs;
|
||||||
SingleDiff<uint64_t> FrameCount;
|
SingleDiff<uint64_t> FrameCount;
|
||||||
SingleDiff<std::array<uint64_t, 2>> RngState;
|
SingleDiff<RNG::State> RngState;
|
||||||
|
|
||||||
SingleDiff<Json::Value> Authors;
|
SingleDiff<Json::Value> Authors;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user