Remove GameSave::Collapse and GameSave::originalData

... and everything built around them.

A GameSave would hold at least one but sometimes two representations of a save:
one serialized, and one "friendly", accessible for modification. Thus, a
GameSave would have three states:

 - "Collapsed": only the serialized representation was present; this was the
   initial state of GameSaves loaded from files;
 - "Expanded With Data": both the serialized and the friendly representations
   were present; this was the state of GameSaves loaded from files after a call
   to Expand;
 - "Expanded Without Data": only the friendly representation was present; this
   was the initial state of GameSaves being prepared for being saved to files.

A GameSave would be able to go from Collapsed to Expanded With Data with a call
to Expand, and back with a call to Collapse. Of course, this latter transition
would discard any changes made to the friendly representation, for example with
Translate. A GameSave would however be unable to go from Expanded Without Data
to any other state; a call to Collapse in this state would have been a no-op.

There were two instances of Collapse being called, one in the GameSave
constructor taking the serialized representation, immediately after a call to
Expand, and another in SaveRenderer, which would Collapse a save "back down" if
it had originally been Collapsed. Now, consider that there reasons for
constructing a GameSave from the serialized representation are as follows:

 - loading an online save at startup from the command line;
 - loading a local save at startup from the command line;
 - loading a local save when it is dropped into the window;
 - loading a local save for placement of the most recently used stamp;
 - loading a local save for stamp placement via Lua;
 - loading an online save for preview generation while browsing;
 - loading a local save in the stamp browser for thumbnail generation;
 - loading a local save in the local save browser for thumbnail generation.

In some cases, the friendly representation is needed for thumbnail generation
by ThumbnailRendererTask. ThumbnailRendererTask operates on its own copy of the
GameSave, because it runs SaveRenderer on a thread different from the main one
and cannot be sure of the lifetime of the original GameSave. It destroys this
copy when it is done rendering, so the call SaveRenderer makes to Collapse is
pointless.

In all other cases, the friendly representation is needed immediately. In some
of these, SaveRenderer is used from the main thread, but since the friendly
representation of the GameSave will be needed for pasting anyway, the call
SaveRenderer makes to Collapse is pointless again.

So, Collapse goes away. This also means that it is pointless for GameSaves to
hold on to the serialized representation, since in all cases in which they have
access to it, the friendly representation is needed immediately, and with
Collapse gone, they will never need it again.
This commit is contained in:
Tamás Bálint Misius 2022-11-10 12:02:27 +01:00
parent 630db0ef6b
commit f70cc705cb
No known key found for this signature in database
GPG Key ID: 5B472A12F6ECA9F2
5 changed files with 24 additions and 92 deletions

View File

@ -34,16 +34,11 @@ GameSave::GameSave(const GameSave & save):
signs(save.signs), signs(save.signs),
stkm(save.stkm), stkm(save.stkm),
palette(save.palette), palette(save.palette),
pmapbits(save.pmapbits), pmapbits(save.pmapbits)
expanded(save.expanded),
hasOriginalData(save.hasOriginalData),
originalData(save.originalData)
{ {
InitData(); InitData();
hasPressure = save.hasPressure; hasPressure = save.hasPressure;
hasAmbientHeat = save.hasAmbientHeat; hasAmbientHeat = save.hasAmbientHeat;
if (save.expanded)
{
setSize(save.blockWidth, save.blockHeight); setSize(save.blockWidth, save.blockHeight);
std::copy(save.particles, save.particles+NPART, particles); std::copy(save.particles, save.particles+NPART, particles);
@ -57,12 +52,6 @@ GameSave::GameSave(const GameSave & save):
std::copy(save.velocityY[j], save.velocityY[j]+blockWidth, velocityY[j]); std::copy(save.velocityY[j], save.velocityY[j]+blockWidth, velocityY[j]);
std::copy(save.ambientHeat[j], save.ambientHeat[j]+blockWidth, ambientHeat[j]); std::copy(save.ambientHeat[j], save.ambientHeat[j]+blockWidth, ambientHeat[j]);
} }
}
else
{
blockWidth = save.blockWidth;
blockHeight = save.blockHeight;
}
particlesCount = save.particlesCount; particlesCount = save.particlesCount;
authors = save.authors; authors = save.authors;
} }
@ -71,24 +60,19 @@ GameSave::GameSave(int width, int height)
{ {
InitData(); InitData();
InitVars(); InitVars();
hasOriginalData = false;
expanded = true;
setSize(width, height); setSize(width, height);
} }
GameSave::GameSave(std::vector<char> data) GameSave::GameSave(const std::vector<char> &data)
{ {
blockWidth = 0; blockWidth = 0;
blockHeight = 0; blockHeight = 0;
InitData(); InitData();
InitVars(); InitVars();
expanded = false;
hasOriginalData = true;
originalData = data;
try try
{ {
Expand(); Expand(data);
} }
catch(ParseException & e) catch(ParseException & e)
{ {
@ -96,7 +80,6 @@ GameSave::GameSave(std::vector<char> data)
dealloc(); //Free any allocated memory dealloc(); //Free any allocated memory
throw; throw;
} }
Collapse();
} }
// Called on every new GameSave, including the copy constructor // Called on every new GameSave, including the copy constructor
@ -136,32 +119,13 @@ void GameSave::InitVars()
pmapbits = 8; // default to 8 bits for older saves pmapbits = 8; // default to 8 bits for older saves
} }
bool GameSave::Collapsed() void GameSave::Expand(const std::vector<char> &data)
{
return !expanded;
}
void GameSave::Expand()
{
if(hasOriginalData && !expanded)
{ {
InitVars(); InitVars();
expanded = true; read(&data[0], data.size());
read(&originalData[0], originalData.size());
}
} }
void GameSave::Collapse() void GameSave::read(const char * data, int dataSize)
{
if(expanded && hasOriginalData)
{
expanded = false;
dealloc();
signs.clear();
}
}
void GameSave::read(char * data, int dataSize)
{ {
if(dataSize > 15) if(dataSize > 15)
{ {
@ -242,8 +206,6 @@ char * GameSave::Serialise(unsigned int & dataSize)
vector2d GameSave::Translate(vector2d translate) vector2d GameSave::Translate(vector2d translate)
{ {
if (Collapsed())
Expand();
float nx, ny; float nx, ny;
vector2d pos; vector2d pos;
vector2d translateReal = translate; vector2d translateReal = translate;
@ -313,9 +275,6 @@ vector2d GameSave::Translate(vector2d translate)
void GameSave::Transform(matrix2d transform, vector2d translate) void GameSave::Transform(matrix2d transform, vector2d translate)
{ {
if (Collapsed())
Expand();
int width = blockWidth*CELL, height = blockHeight*CELL, newWidth, newHeight; int width = blockWidth*CELL, height = blockHeight*CELL, newWidth, newHeight;
vector2d tmp, ctl, cbr; vector2d tmp, ctl, cbr;
vector2d cornerso[4]; vector2d cornerso[4];
@ -347,9 +306,6 @@ void GameSave::Transform(matrix2d transform, vector2d translate)
// translateReal is the original amount we tried to translate, used to calculate wall shifting // translateReal is the original amount we tried to translate, used to calculate wall shifting
void GameSave::Transform(matrix2d transform, vector2d translate, vector2d translateReal, int newWidth, int newHeight) void GameSave::Transform(matrix2d transform, vector2d translate, vector2d translateReal, int newWidth, int newHeight)
{ {
if (Collapsed())
Expand();
if (newWidth>XRES) newWidth = XRES; if (newWidth>XRES) newWidth = XRES;
if (newHeight>YRES) newHeight = YRES; if (newHeight>YRES) newHeight = YRES;
@ -558,7 +514,7 @@ void GameSave::CheckBsonFieldFloat(bson_iterator iter, const char *field, float
} }
} }
void GameSave::readOPS(char * data, int dataLength) void GameSave::readOPS(const char * data, int dataLength)
{ {
unsigned char *inputData = (unsigned char*)data, *bsonData = NULL, *partsData = NULL, *partsPosData = NULL, *fanData = NULL, *wallData = NULL, *soapLinkData = NULL; unsigned char *inputData = (unsigned char*)data, *bsonData = NULL, *partsData = NULL, *partsPosData = NULL, *fanData = NULL, *wallData = NULL, *soapLinkData = NULL;
unsigned char *pressData = NULL, *vxData = NULL, *vyData = NULL, *ambientData = NULL; unsigned char *pressData = NULL, *vxData = NULL, *vyData = NULL, *ambientData = NULL;
@ -1390,7 +1346,7 @@ void GameSave::readOPS(char * data, int dataLength)
} }
} }
void GameSave::readPSv(char * saveDataChar, int dataLength) void GameSave::readPSv(const char * saveDataChar, int dataLength)
{ {
unsigned char * saveData = (unsigned char *)saveDataChar; unsigned char * saveData = (unsigned char *)saveDataChar;
int q,j,k,x,y,p=0, ver, pty, ty, legacy_beta=0; int q,j,k,x,y,p=0, ver, pty, ty, legacy_beta=0;

View File

@ -117,7 +117,7 @@ public:
GameSave(); GameSave();
GameSave(const GameSave & save); GameSave(const GameSave & save);
GameSave(int width, int height); GameSave(int width, int height);
GameSave(std::vector<char> data); GameSave(const std::vector<char> &data);
~GameSave(); ~GameSave();
void setSize(int width, int height); void setSize(int width, int height);
char * Serialise(unsigned int & dataSize); char * Serialise(unsigned int & dataSize);
@ -126,9 +126,7 @@ public:
void Transform(matrix2d transform, vector2d translate); void Transform(matrix2d transform, vector2d translate);
void Transform(matrix2d transform, vector2d translate, vector2d translateReal, int newWidth, int newHeight); void Transform(matrix2d transform, vector2d translate, vector2d translateReal, int newWidth, int newHeight);
void Expand(); void Expand(const std::vector<char> &data);
void Collapse();
bool Collapsed();
static bool TypeInCtype(int type, int ctype); static bool TypeInCtype(int type, int ctype);
static bool TypeInTmp(int type); static bool TypeInTmp(int type);
@ -139,13 +137,9 @@ public:
GameSave& operator << (sign &v); GameSave& operator << (sign &v);
private: private:
bool expanded;
bool hasOriginalData;
// number of pixels translated. When translating CELL pixels, shift all CELL grids // number of pixels translated. When translating CELL pixels, shift all CELL grids
vector2d translated; vector2d translated;
std::vector<char> originalData;
void InitData(); void InitData();
void InitVars(); void InitVars();
void CheckBsonFieldUser(bson_iterator iter, const char *field, unsigned char **data, unsigned int *fieldLen); void CheckBsonFieldUser(bson_iterator iter, const char *field, unsigned char **data, unsigned int *fieldLen);
@ -155,9 +149,9 @@ private:
template <typename T> T ** Allocate2DArray(int blockWidth, int blockHeight, T defaultVal); template <typename T> T ** Allocate2DArray(int blockWidth, int blockHeight, T defaultVal);
template <typename T> void Deallocate2DArray(T ***array, int blockHeight); template <typename T> void Deallocate2DArray(T ***array, int blockHeight);
void dealloc(); void dealloc();
void read(char * data, int dataSize); void read(const char * data, int dataSize);
void readOPS(char * data, int dataLength); void readOPS(const char * data, int dataLength);
void readPSv(char * data, int dataLength); void readPSv(const char * data, int dataLength);
char * serialiseOPS(unsigned int & dataSize); char * serialiseOPS(unsigned int & dataSize);
void ConvertJsonToBson(bson *b, Json::Value j, int depth = 0); void ConvertJsonToBson(bson *b, Json::Value j, int depth = 0);
void ConvertBsonToJson(bson_iterator *b, Json::Value *j, int depth = 0); void ConvertBsonToJson(bson_iterator *b, Json::Value *j, int depth = 0);

View File

@ -432,16 +432,12 @@ bool GameController::LoadClipboard()
if (!clip) if (!clip)
return false; return false;
gameModel->SetPlaceSave(clip); gameModel->SetPlaceSave(clip);
if (gameModel->GetPlaceSave() && gameModel->GetPlaceSave()->Collapsed())
gameModel->GetPlaceSave()->Expand();
return true; return true;
} }
void GameController::LoadStamp(GameSave *stamp) void GameController::LoadStamp(GameSave *stamp)
{ {
gameModel->SetPlaceSave(stamp); gameModel->SetPlaceSave(stamp);
if(gameModel->GetPlaceSave() && gameModel->GetPlaceSave()->Collapsed())
gameModel->GetPlaceSave()->Expand();
} }
void GameController::TranslateSave(ui::Point point) void GameController::TranslateSave(ui::Point point)

View File

@ -37,7 +37,6 @@ VideoBuffer * SaveRenderer::Render(GameSave * save, bool decorations, bool fire,
VideoBuffer * tempThumb = NULL; VideoBuffer * tempThumb = NULL;
width = save->blockWidth; width = save->blockWidth;
height = save->blockHeight; height = save->blockHeight;
bool doCollapse = save->Collapsed();
g->Clear(); g->Clear();
sim->clear_sim(); sim->clear_sim();
@ -79,8 +78,6 @@ VideoBuffer * SaveRenderer::Render(GameSave * save, bool decorations, bool fire,
tempThumb = new VideoBuffer(pData, width*CELL, height*CELL); tempThumb = new VideoBuffer(pData, width*CELL, height*CELL);
free(pData); free(pData);
} }
if(doCollapse)
save->Collapse();
return tempThumb; return tempThumb;
} }

View File

@ -53,17 +53,6 @@ int Simulation::Load(const GameSave * originalSave, bool includePressure, int fu
if (!originalSave) if (!originalSave)
return 1; return 1;
auto save = std::unique_ptr<GameSave>(new GameSave(*originalSave)); auto save = std::unique_ptr<GameSave>(new GameSave(*originalSave));
try
{
save->Expand();
}
catch (const ParseException &e)
{
#ifdef LUACONSOLE
luacon_ci->SetLastError(ByteString(e.what()).FromUtf8());
#endif
return 1;
}
//Align to blockMap //Align to blockMap
int blockX = (fullX + CELL/2)/CELL; int blockX = (fullX + CELL/2)/CELL;