Eliminate a GameSave copy in Simulation::Load

This commit is contained in:
Tamás Bálint Misius 2023-06-11 18:12:49 +02:00
parent f805b15ee5
commit 0b0f40ec94
No known key found for this signature in database
GPG Key ID: 5B472A12F6ECA9F2

View File

@ -19,10 +19,8 @@ extern int Element_LOLZ_lolz[XRES/9][YRES/9];
extern int Element_LOVE_RuleTable[9][9];
extern int Element_LOVE_love[XRES/9][YRES/9];
void Simulation::Load(const GameSave *originalSave, bool includePressure, Vec2<int> blockP) // block coordinates
void Simulation::Load(const GameSave *save, bool includePressure, Vec2<int> blockP) // block coordinates
{
auto save = std::unique_ptr<GameSave>(new GameSave(*originalSave));
auto partP = blockP * CELL;
unsigned int pmapmask = (1<<save->pmapbits)-1;
@ -57,40 +55,33 @@ void Simulation::Load(const GameSave *originalSave, bool includePressure, Vec2<i
auto &possiblyCarriesType = Particle::PossiblyCarriesType();
auto &properties = Particle::GetProperties();
bool doFullScan = false;
std::map<unsigned int, unsigned int> soapList;
for (int n = 0; n < NPART && n < save->particlesCount; n++)
{
Particle *tempPart = &save->particles[n];
auto &type = tempPart->type;
if (!type)
Particle tempPart = save->particles[n];
if (tempPart.type <= 0 || tempPart.type >= PT_NUM)
{
continue;
}
tempPart->x += (float)partP.X;
tempPart->y += (float)partP.Y;
int x = int(tempPart->x + 0.5f);
int y = int(tempPart->y + 0.5f);
tempPart.x += (float)partP.X;
tempPart.y += (float)partP.Y;
int x = int(tempPart.x + 0.5f);
int y = int(tempPart.y + 0.5f);
// Check various scenarios where we are unable to spawn the element, and set type to 0 to block spawning later
if (!InBounds(x, y))
{
type = 0;
continue;
}
if (type < 0 || type >= PT_NUM)
{
type = 0;
continue;
}
type = partMap[type];
tempPart.type = partMap[tempPart.type];
for (auto index : possiblyCarriesType)
{
if (elements[type].CarriesTypeIn & (1U << index))
if (elements[tempPart.type].CarriesTypeIn & (1U << index))
{
auto *prop = reinterpret_cast<int *>(reinterpret_cast<char *>(tempPart) + properties[index].Offset);
auto *prop = reinterpret_cast<int *>(reinterpret_cast<char *>(&tempPart) + properties[index].Offset);
auto carriedType = *prop & int(pmapmask);
auto extra = *prop >> save->pmapbits;
if (carriedType >= 0 && carriedType < PT_NUM)
@ -102,73 +93,26 @@ void Simulation::Load(const GameSave *originalSave, bool includePressure, Vec2<i
}
// Ensure we can spawn this element
if ((player.spwn == 1 && type==PT_STKM) || (player2.spwn == 1 && type==PT_STKM2))
if ((player.spwn == 1 && tempPart.type==PT_STKM) || (player2.spwn == 1 && tempPart.type==PT_STKM2))
{
type = 0;
continue;
}
if ((type == PT_SPAWN || type == PT_SPAWN2) && elementCount[type])
if ((tempPart.type == PT_SPAWN || tempPart.type == PT_SPAWN2) && elementCount[tempPart.type])
{
type = 0;
continue;
}
bool Element_FIGH_CanAlloc(Simulation *sim);
if (type == PT_FIGH && !Element_FIGH_CanAlloc(this))
{
type = 0;
continue;
}
if (!elements[type].Enabled)
{
type = 0;
continue;
}
if (pmap[y][x])
{
// Particle already exists in this location. Set pmap to 0, then kill it and all stacked particles in the loop below
pmap[y][x] = 0;
doFullScan = true;
}
else if (photons[y][x])
{
// Particle already exists in this location. Set photons to 0, then kill it and all stacked particles in the loop below
photons[y][x] = 0;
doFullScan = true;
}
}
if (doFullScan)
{
// Loop through particles to find particles in need of being killed
for (int i = 0; i <= parts_lastActiveIndex; i++) {
if (parts[i].type)
{
int x = int(parts[i].x + 0.5f);
int y = int(parts[i].y + 0.5f);
if (elements[parts[i].type].Properties & TYPE_ENERGY)
{
if (!photons[y][x])
kill_part(i);
}
else
{
if (!pmap[y][x])
kill_part(i);
}
}
}
}
// Map of soap particles loaded into this save, old ID -> new ID
std::map<unsigned int, unsigned int> soapList;
for (int n = 0; n < NPART && n < save->particlesCount; n++)
{
Particle tempPart = save->particles[n];
if (!tempPart.type)
if (tempPart.type == PT_FIGH && !Element_FIGH_CanAlloc(this))
{
continue;
}
if (!elements[tempPart.type].Enabled)
{
continue;
}
// Mark location to be cleaned of existing particles.
pmap[y][x] = -1;
if (elements[tempPart.type].CreateAllowed)
{
@ -272,10 +216,35 @@ void Simulation::Load(const GameSave *originalSave, bool includePressure, Vec2<i
{
parts[i].tmp3 = 0;
}
if (!parts[i].type)
{
continue;
}
// Mark to be preserved in the loop below.
parts[i].type |= 1 << PMAPBITS;
}
parts_lastActiveIndex = NPART-1;
force_stacking_check = true;
Element_PPIP_ppip_changed = 1;
// Loop through particles to find particles in need of being killed
for (int i = 0; i <= parts_lastActiveIndex; i++)
{
if (parts[i].type)
{
int x = int(parts[i].x + 0.5f);
int y = int(parts[i].y + 0.5f);
bool preserve = parts[i].type & (1 << PMAPBITS);
parts[i].type &= ~(1 << PMAPBITS);
if (pmap[y][x] == -1 && !preserve)
{
kill_part(i);
}
}
}
RecalcFreeParticles(false);
// fix SOAP links using soapList, a map of old particle ID -> new particle ID