Change: Record and show multiple errors for each NewGRF. (#14658)
This commit is contained in:
@@ -148,9 +148,12 @@ GRFError *DisableGrf(StringID message, GRFConfig *config)
|
||||
|
||||
if (message == STR_NULL) return nullptr;
|
||||
|
||||
config->error = {STR_NEWGRF_ERROR_MSG_FATAL, message};
|
||||
if (config == _cur_gps.grfconfig) config->error->param_value[0] = _cur_gps.nfo_line;
|
||||
return &config->error.value();
|
||||
auto it = std::ranges::find(config->errors, _cur_gps.nfo_line, &GRFError::nfo_line);
|
||||
if (it == std::end(config->errors)) {
|
||||
it = config->errors.emplace(it, STR_NEWGRF_ERROR_MSG_FATAL, _cur_gps.nfo_line, message);
|
||||
}
|
||||
if (config == _cur_gps.grfconfig) it->param_value[0] = _cur_gps.nfo_line;
|
||||
return &*it;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -392,7 +395,7 @@ static void ResetNewGRF()
|
||||
static void ResetNewGRFErrors()
|
||||
{
|
||||
for (const auto &c : _grfconfig) {
|
||||
c->error.reset();
|
||||
c->errors.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1841,7 +1844,7 @@ void LoadNewGRF(SpriteID load_index, uint num_baseset)
|
||||
if (num_non_static == NETWORK_MAX_GRF_COUNT) {
|
||||
Debug(grf, 0, "'{}' is not loaded as the maximum number of non-static GRFs has been reached", c->filename);
|
||||
c->status = GCS_DISABLED;
|
||||
c->error = {STR_NEWGRF_ERROR_MSG_FATAL, STR_NEWGRF_ERROR_TOO_MANY_NEWGRFS_LOADED};
|
||||
c->errors.emplace_back(STR_NEWGRF_ERROR_MSG_FATAL, 0, STR_NEWGRF_ERROR_TOO_MANY_NEWGRFS_LOADED);
|
||||
continue;
|
||||
}
|
||||
num_non_static++;
|
||||
|
||||
@@ -73,9 +73,6 @@ static void GRFLoadError(ByteReader &buf)
|
||||
/* This is a fatal error, so make sure the GRF is deactivated and no
|
||||
* more of it gets loaded. */
|
||||
DisableGrf();
|
||||
|
||||
/* Make sure we show fatal errors, instead of silly infos from before */
|
||||
_cur_gps.grfconfig->error.reset();
|
||||
}
|
||||
|
||||
if (message_id >= lengthof(msgstr) && message_id != 0xFF) {
|
||||
@@ -88,39 +85,41 @@ static void GRFLoadError(ByteReader &buf)
|
||||
return;
|
||||
}
|
||||
|
||||
/* For now we can only show one message per newgrf file. */
|
||||
if (_cur_gps.grfconfig->error.has_value()) return;
|
||||
/* An error may be emitted multiple times in different loading stages. Re-use if so. */
|
||||
auto it = std::ranges::find(_cur_gps.grfconfig->errors, _cur_gps.nfo_line, &GRFError::nfo_line);
|
||||
if (it == std::end(_cur_gps.grfconfig->errors)) {
|
||||
it = _cur_gps.grfconfig->errors.emplace(it, sevstr[severity], _cur_gps.nfo_line);
|
||||
}
|
||||
|
||||
_cur_gps.grfconfig->error = {sevstr[severity]};
|
||||
GRFError *error = &_cur_gps.grfconfig->error.value();
|
||||
GRFError &error = *it;
|
||||
|
||||
if (message_id == 0xFF) {
|
||||
/* This is a custom error message. */
|
||||
if (buf.HasData()) {
|
||||
std::string_view message = buf.ReadString();
|
||||
|
||||
error->custom_message = TranslateTTDPatchCodes(_cur_gps.grffile->grfid, lang, true, message, SCC_RAW_STRING_POINTER);
|
||||
error.custom_message = TranslateTTDPatchCodes(_cur_gps.grffile->grfid, lang, true, message, SCC_RAW_STRING_POINTER);
|
||||
} else {
|
||||
GrfMsg(7, "GRFLoadError: No custom message supplied.");
|
||||
error->custom_message.clear();
|
||||
error.custom_message.clear();
|
||||
}
|
||||
} else {
|
||||
error->message = msgstr[message_id];
|
||||
error.message = msgstr[message_id];
|
||||
}
|
||||
|
||||
if (buf.HasData()) {
|
||||
std::string_view data = buf.ReadString();
|
||||
|
||||
error->data = TranslateTTDPatchCodes(_cur_gps.grffile->grfid, lang, true, data);
|
||||
error.data = TranslateTTDPatchCodes(_cur_gps.grffile->grfid, lang, true, data);
|
||||
} else {
|
||||
GrfMsg(7, "GRFLoadError: No message data supplied.");
|
||||
error->data.clear();
|
||||
error.data.clear();
|
||||
}
|
||||
|
||||
/* Only two parameter numbers can be used in the string. */
|
||||
for (uint i = 0; i < error->param_value.size() && buf.HasData(); i++) {
|
||||
for (uint i = 0; i < error.param_value.size() && buf.HasData(); i++) {
|
||||
uint param_number = buf.ReadByte();
|
||||
error->param_value[i] = _cur_gps.grffile->GetParam(param_number);
|
||||
error.param_value[i] = _cur_gps.grffile->GetParam(param_number);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ GRFConfig::GRFConfig(const GRFConfig &config) :
|
||||
name(config.name),
|
||||
info(config.info),
|
||||
url(config.url),
|
||||
error(config.error),
|
||||
errors(config.errors),
|
||||
version(config.version),
|
||||
min_loadable_version(config.min_loadable_version),
|
||||
flags(config.flags),
|
||||
@@ -156,15 +156,6 @@ GRFConfigList _grfconfig_newgame;
|
||||
GRFConfigList _grfconfig_static;
|
||||
uint _missing_extra_graphics = 0;
|
||||
|
||||
/**
|
||||
* Construct a new GRFError.
|
||||
* @param severity The severity of this error.
|
||||
* @param message The actual error-string.
|
||||
*/
|
||||
GRFError::GRFError(StringID severity, StringID message) : message(message), severity(severity)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the given user-changeable parameter.
|
||||
* @param info The grf parameter info to get the value for.
|
||||
@@ -472,7 +463,7 @@ compatible_grf:
|
||||
c->ident.md5sum = f->ident.md5sum;
|
||||
c->name = f->name;
|
||||
c->info = f->name;
|
||||
c->error.reset();
|
||||
c->errors.clear();
|
||||
c->version = f->version;
|
||||
c->min_loadable_version = f->min_loadable_version;
|
||||
c->num_valid_params = f->num_valid_params;
|
||||
|
||||
@@ -107,12 +107,14 @@ struct GRFIdentifier {
|
||||
|
||||
/** Information about why GRF had problems during initialisation */
|
||||
struct GRFError {
|
||||
GRFError(StringID severity, StringID message = {});
|
||||
GRFError(StringID severity, uint32_t nfo_line, StringID message = {})
|
||||
: message(message), severity(severity), nfo_line(nfo_line) {}
|
||||
|
||||
std::string custom_message{}; ///< Custom message (if present)
|
||||
std::string data{}; ///< Additional data for message and custom_message
|
||||
StringID message{}; ///< Default message
|
||||
StringID severity{}; ///< Info / Warning / Error / Fatal
|
||||
uint32_t nfo_line; ///< Line within NewGRF of error.
|
||||
std::array<uint32_t, 2> param_value{}; ///< Values of GRF parameters to show for message and custom_message
|
||||
};
|
||||
|
||||
@@ -169,7 +171,7 @@ struct GRFConfig {
|
||||
GRFTextWrapper name{}; ///< NOSAVE: GRF name (Action 0x08)
|
||||
GRFTextWrapper info{}; ///< NOSAVE: GRF info (author, copyright, ...) (Action 0x08)
|
||||
GRFTextWrapper url{}; ///< NOSAVE: URL belonging to this GRF.
|
||||
std::optional<GRFError> error = std::nullopt; ///< NOSAVE: Error/Warning during GRF loading (Action 0x0B)
|
||||
std::vector<GRFError> errors; ///< NOSAVE: Error/Warning during GRF loading (Action 0x0B)
|
||||
|
||||
uint32_t version = 0; ///< NOSAVE: Version a NewGRF can set so only the newest NewGRF is shown
|
||||
uint32_t min_loadable_version = 0; ///< NOSAVE: Minimum compatible version a NewGRF can define
|
||||
|
||||
@@ -51,17 +51,20 @@ void ShowNewGRFError()
|
||||
|
||||
for (const auto &c : _grfconfig) {
|
||||
/* Only show Fatal and Error level messages */
|
||||
if (!c->error.has_value() || (c->error->severity != STR_NEWGRF_ERROR_MSG_FATAL && c->error->severity != STR_NEWGRF_ERROR_MSG_ERROR)) continue;
|
||||
if (c->errors.empty()) continue;
|
||||
|
||||
const GRFError &error = c->errors.back();
|
||||
if (error.severity != STR_NEWGRF_ERROR_MSG_FATAL && error.severity != STR_NEWGRF_ERROR_MSG_ERROR) continue;
|
||||
|
||||
std::vector<StringParameter> params;
|
||||
params.emplace_back(c->GetName());
|
||||
params.emplace_back(c->error->message != STR_NULL ? c->error->message : STR_JUST_RAW_STRING);
|
||||
params.emplace_back(c->error->custom_message);
|
||||
params.emplace_back(error.message != STR_NULL ? error.message : STR_JUST_RAW_STRING);
|
||||
params.emplace_back(error.custom_message);
|
||||
params.emplace_back(c->filename);
|
||||
params.emplace_back(c->error->data);
|
||||
for (const uint32_t &value : c->error->param_value) params.emplace_back(value);
|
||||
params.emplace_back(error.data);
|
||||
for (const uint32_t &value : error.param_value) params.emplace_back(value);
|
||||
|
||||
if (c->error->severity == STR_NEWGRF_ERROR_MSG_FATAL) {
|
||||
if (error.severity == STR_NEWGRF_ERROR_MSG_FATAL) {
|
||||
ShowErrorMessage(GetEncodedStringWithArgs(STR_NEWGRF_ERROR_FATAL_POPUP, params), {}, WL_CRITICAL);
|
||||
} else {
|
||||
ShowErrorMessage(GetEncodedStringWithArgs(STR_NEWGRF_ERROR_POPUP, params), {}, WL_ERROR);
|
||||
@@ -81,15 +84,15 @@ static StringID GetGRFPaletteString(uint8_t palette)
|
||||
static void ShowNewGRFInfo(const GRFConfig &c, const Rect &r, bool show_params)
|
||||
{
|
||||
Rect tr = r.Shrink(WidgetDimensions::scaled.frametext);
|
||||
if (c.error.has_value()) {
|
||||
std::array<StringParameter, 3 + std::tuple_size_v<decltype(c.error->param_value)>> params{};
|
||||
for (const GRFError &error : c.errors) {
|
||||
std::array<StringParameter, 3 + std::tuple_size_v<decltype(error.param_value)>> params{};
|
||||
auto it = params.begin();
|
||||
*it++ = c.error->custom_message; // is skipped by built-in messages
|
||||
*it++ = error.custom_message; // is skipped by built-in messages
|
||||
*it++ = c.filename;
|
||||
*it++ = c.error->data;
|
||||
for (const uint32_t &value : c.error->param_value) *it++ = value;
|
||||
*it++ = error.data;
|
||||
for (const uint32_t &value : error.param_value) *it++ = value;
|
||||
|
||||
tr.top = DrawStringMultiLine(tr, GetString(c.error->severity, GetStringWithArgs(c.error->message != STR_NULL ? c.error->message : STR_JUST_RAW_STRING, {params.begin(), it})));
|
||||
tr.top = DrawStringMultiLine(tr, GetString(error.severity, GetStringWithArgs(error.message != STR_NULL ? error.message : STR_JUST_RAW_STRING, {params.begin(), it})));
|
||||
}
|
||||
|
||||
/* Draw filename or not if it is not known (GRF sent over internet) */
|
||||
@@ -868,8 +871,8 @@ struct NewGRFWindow : public Window, NewGRFScanCallback {
|
||||
}
|
||||
}
|
||||
DrawSprite(SPR_SQUARE, pal, square_left, tr.top + square_offset_y);
|
||||
if (c->error.has_value()) DrawSprite(SPR_WARNING_SIGN, 0, warning_left, tr.top + warning_offset_y);
|
||||
uint txtoffset = !c->error.has_value() ? 0 : warning.width;
|
||||
if (!c->errors.empty()) DrawSprite(SPR_WARNING_SIGN, 0, warning_left, tr.top + warning_offset_y);
|
||||
uint txtoffset = c->errors.empty() ? 0 : warning.width;
|
||||
DrawString(text_left + (rtl ? 0 : txtoffset), text_right - (rtl ? txtoffset : 0), tr.top + offset_y, std::move(text), h ? TC_WHITE : TC_ORANGE);
|
||||
tr.top += step_height;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user