List element IDs that don't have an identifier associated in a save

36800a76cd lists missing element identifiers but neglects to handle IDs that don't even have one associated.
This commit is contained in:
Tamás Bálint Misius 2023-12-05 10:19:13 +01:00
parent 66136c8866
commit 9f8449357f
No known key found for this signature in database
GPG Key ID: 5B472A12F6ECA9F2
7 changed files with 54 additions and 18 deletions

View File

@ -488,10 +488,24 @@ void PreviewView::ShowLoadError()
void PreviewView::ShowMissingCustomElements()
{
StringBuilder sb;
sb << "This save uses custom elements that are not currently available. Make sure that you use the mod and/or have all the scripts the save requires to fully load. A list of identifiers of missing custom elements follows, which may help you determine how to fix this problem.\n";
for (auto &identifier : missingElementTypes)
sb << "This save uses custom elements that are not currently available. Make sure that you use the mod and/or have all the scripts the save requires to fully load.";
auto remainingIds = missingElements.ids;
if (missingElements.identifiers.size())
{
sb << "\n - " << identifier.FromUtf8();
sb << "\n\nA list of identifiers of missing custom elements follows, which may help you determine how to fix this problem.\n";
for (auto &[ identifier, id ] : missingElements.identifiers)
{
sb << "\n - " << identifier.FromUtf8();
remainingIds.erase(id); // remove ids from the missing id set that are already covered by unknown identifiers
}
}
if (remainingIds.size())
{
sb << "\n\nA list of element IDs of missing custom elements with no identifier associated follows. This can only be fixed by the author of the save.\n";
for (auto id : remainingIds)
{
sb << "\n - " << id;
}
}
new InformationMessage("Missing custom elements", sb.Build(), true);
}
@ -556,10 +570,10 @@ void PreviewView::NotifySaveChanged(PreviewModel * sender)
if(save->GetGameSave())
{
std::tie(savePreview, missingElementTypes) = SaveRenderer::Ref().Render(save->GetGameSave(), false, true);
std::tie(savePreview, missingElements) = SaveRenderer::Ref().Render(save->GetGameSave(), false, true);
if (savePreview)
savePreview->ResizeToFit(RES / 2, true);
missingElementsButton->Visible = missingElementTypes.size();
missingElementsButton->Visible = missingElements.identifiers.size() || missingElements.ids.size();
UpdateLoadStatus();
}
else if (!sender->GetCanOpen())

View File

@ -4,6 +4,7 @@
#include <vector>
#include "common/String.h"
#include "gui/interface/Window.h"
#include "simulation/MissingElements.h"
namespace http
{
@ -27,7 +28,7 @@ class PreviewController;
class PreviewView: public ui::Window
{
PreviewController *c{};
std::vector<ByteString> missingElementTypes;
MissingElements missingElements;
std::unique_ptr<VideoBuffer> savePreview;
ui::Button *openButton{};
ui::Button *browserOpenButton{};

View File

@ -0,0 +1,10 @@
#pragma once
#include <set>
#include <map>
#include "common/String.h"
struct MissingElements
{
std::map<ByteString, int> identifiers;
std::set<int> ids;
};

View File

@ -20,7 +20,7 @@ void SaveRenderer::Flush(int begin, int end)
std::fill(ren->graphicscache + begin, ren->graphicscache + end, gcache_item());
}
std::pair<std::unique_ptr<VideoBuffer>, std::vector<ByteString>> SaveRenderer::Render(const GameSave *save, bool decorations, bool fire, Renderer *renderModeSource)
std::pair<std::unique_ptr<VideoBuffer>, MissingElements> SaveRenderer::Render(const GameSave *save, bool decorations, bool fire, Renderer *renderModeSource)
{
std::lock_guard<std::mutex> gx(renderMutex);

View File

@ -5,6 +5,7 @@
#include <vector>
#include "common/ExplicitSingleton.h"
#include "common/String.h"
#include "MissingElements.h"
class GameSave;
class VideoBuffer;
@ -18,7 +19,7 @@ class SaveRenderer: public ExplicitSingleton<SaveRenderer> {
std::mutex renderMutex;
public:
SaveRenderer();
std::pair<std::unique_ptr<VideoBuffer>, std::vector<ByteString>> Render(const GameSave *save, bool decorations = true, bool fire = true, Renderer *renderModeSource = nullptr);
std::pair<std::unique_ptr<VideoBuffer>, MissingElements> Render(const GameSave *save, bool decorations = true, bool fire = true, Renderer *renderModeSource = nullptr);
void Flush(int begin, int end);
virtual ~SaveRenderer();
};

View File

@ -19,9 +19,9 @@ 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];
std::vector<ByteString> Simulation::Load(const GameSave *save, bool includePressure, Vec2<int> blockP) // block coordinates
MissingElements Simulation::Load(const GameSave *save, bool includePressure, Vec2<int> blockP) // block coordinates
{
std::vector<ByteString> missingElementTypes;
MissingElements missingElements;
auto partP = blockP * CELL;
unsigned int pmapmask = (1<<save->pmapbits)-1;
@ -54,11 +54,23 @@ std::vector<ByteString> Simulation::Load(const GameSave *save, bool includePress
}
else
{
missingElementTypes.push_back(pi.first);
missingElements.identifiers.insert(pi);
}
}
}
}
auto paletteLookup = [&partMap, &missingElements](int type) {
if (type > 0 && type < PT_NUM)
{
auto carriedType = partMap[type];
if (!carriedType) // type is not 0 so this shouldn't be 0 either
{
missingElements.ids.insert(type);
}
type = carriedType;
}
return type;
};
RecalcFreeParticles(false);
@ -86,7 +98,7 @@ std::vector<ByteString> Simulation::Load(const GameSave *save, bool includePress
continue;
}
tempPart.type = partMap[tempPart.type];
tempPart.type = paletteLookup(tempPart.type);
for (auto index : possiblyCarriesType)
{
if (elements[tempPart.type].CarriesTypeIn & (1U << index))
@ -94,10 +106,7 @@ std::vector<ByteString> Simulation::Load(const GameSave *save, bool includePress
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)
{
carriedType = partMap[carriedType];
}
carriedType = paletteLookup(carriedType);
*prop = PMAP(extra, carriedType);
}
}
@ -329,7 +338,7 @@ std::vector<ByteString> Simulation::Load(const GameSave *save, bool includePress
air->ApproximateBlockAirMaps();
}
return missingElementTypes;
return missingElements;
}
std::unique_ptr<GameSave> Simulation::Save(bool includePressure, Rect<int> partR) // particle coordinates

View File

@ -11,6 +11,7 @@
#include "common/tpt-rand.h"
#include "Element.h"
#include "SimulationConfig.h"
#include "MissingElements.h"
#include <cstring>
#include <cstddef>
#include <vector>
@ -121,7 +122,7 @@ public:
uint64_t frameCount;
bool ensureDeterminism;
std::vector<ByteString> Load(const GameSave *save, bool includePressure, Vec2<int> blockP); // block coordinates
MissingElements Load(const GameSave *save, bool includePressure, Vec2<int> blockP); // block coordinates
std::unique_ptr<GameSave> Save(bool includePressure, Rect<int> partR); // particle coordinates
void SaveSimOptions(GameSave &gameSave);
SimulationSample GetSample(int x, int y);