diff --git a/src/lang/english.txt b/src/lang/english.txt index 98234f09a5..ca1baa8aac 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2915,6 +2915,11 @@ STR_NEWGRF_DUPLICATE_GRFID :{WHITE}Cannot a STR_NEWGRF_NOT_FOUND :{RED}Matching file not found STR_NEWGRF_DISABLED :{RED}Disabled +STR_NEWGRF_COMPATIBLE_LOADED :{ORANGE}Matching file not found (compatible GRF loaded) + +STR_NEWGRF_COMPATIBLE_LOAD_WARNING :{WHITE}Compatible GRF(s) loaded for missing files +STR_NEWGRF_DISABLED_WARNING :{WHITE}Missing GRF file(s) have been disabled +STR_NEWGRF_NOT_FOUND_WARNING :{WHITE}Missing GRF file(s) to be able to load game STR_CURRENCY_WINDOW :{WHITE}Custom currency STR_CURRENCY_EXCHANGE_RATE :{LTBLUE}Exchange rate: {ORANGE}{CURRENCY} = £ {COMMA} diff --git a/src/newgrf_config.cpp b/src/newgrf_config.cpp index 22cccaee64..534509e89c 100644 --- a/src/newgrf_config.cpp +++ b/src/newgrf_config.cpp @@ -195,24 +195,45 @@ void ResetGRFConfig(bool defaults) } -/* Check if all GRFs in the GRF Config can be loaded */ -bool IsGoodGRFConfigList(void) +/** Check if all GRFs in the GRF config from a savegame can be loaded. + * @return will return any of the following 3 values:
+ * */ +GCF_Flags IsGoodGRFConfigList(void) { - bool res = true; - GRFConfig *c; + GCF_Flags res = GCF_ACTIVATED; - for (c = _grfconfig; c != NULL; c = c->next) { + for (GRFConfig *c = _grfconfig; c != NULL; c = c->next) { const GRFConfig *f = FindGRFConfig(c->grfid, c->md5sum); if (f == NULL) { - char buf[512], *p = buf; + char buf[256], *p = buf; + + /* If we have not found the exactly matching GRF try to find one with the + * same grfid, as it most likely is compatible */ + f = FindGRFConfig(c->grfid); + if (f != NULL) { + md5sumToString(buf, lastof(buf), c->md5sum); + DEBUG(grf, 1, "NewGRF %08X (%s) not found; checksum %s. Compatibility mode on", BSWAP32(c->grfid), c->filename, buf); + SETBIT(c->flags, GCF_COMPATIBLE); + + /* Non-found has precedence over compatibility load */ + if (res != GCF_NOT_FOUND) res = GCF_COMPATIBLE; + goto compatible_grf; + } - p += snprintf(p, lastof(buf) - p, "Couldn't find NewGRF %08X (%s) checksum ", BSWAP32(c->grfid), c->filename); - md5sumToString(p, lastof(buf), c->md5sum); - ShowInfo(buf); + /* No compatible grf was found, mark it as disabled */ + md5sumToString(buf, lastof(buf), c->md5sum); + DEBUG(grf, 0, "NewGRF %08X (%s) not found; checksum %s", BSWAP32(c->grfid), c->filename, buf); - res = false; + SETBIT(c->flags, GCF_NOT_FOUND); + res = GCF_NOT_FOUND; } else { - DEBUG(grf, 1, "Loading GRF %08X from '%s'", BSWAP32(c->grfid), f->filename); +compatible_grf: + DEBUG(grf, 1, "Loading GRF %08X from %s", BSWAP32(f->grfid), f->filename); /* The filename could be the filename as in the savegame. As we need * to load the GRF here, we need the correct filename, so overwrite that * in any case and set the name and info when it is not set already. @@ -221,6 +242,7 @@ bool IsGoodGRFConfigList(void) if (!HASBIT(c->flags, GCF_COPY)) { free(c->filename); c->filename = strdup(f->filename); + memcpy(c->md5sum, f->md5sum, sizeof(c->md5sum)); if (c->name == NULL) c->name = strdup(f->name); if (c->info == NULL) c->info = strdup(f->info); } diff --git a/src/newgrf_config.h b/src/newgrf_config.h index 7cc90d41f5..0864a63a2d 100644 --- a/src/newgrf_config.h +++ b/src/newgrf_config.h @@ -4,15 +4,16 @@ #define NEWGRF_CONFIG_H /* GRF config bit flags */ -enum { - GCF_DISABLED, - GCF_NOT_FOUND, - GCF_ACTIVATED, - GCF_SYSTEM, - GCF_UNSAFE, - GCF_STATIC, +typedef enum { + GCF_DISABLED, ///< GRF file is disabled + GCF_NOT_FOUND, ///< GRF file was not found in the local cache + GCF_ACTIVATED, ///< GRF file is active + GCF_SYSTEM, ///< GRF file is an openttd-internal system grf + GCF_UNSAFE, ///< GRF file is unsafe for static usage + GCF_STATIC, ///< GRF file is used statically (can be used in any MP game) + GCF_COMPATIBLE,///< GRF file does not exactly match the requested GRF (different MD5SUM), but grfid matches) GCF_COPY, ///< The data is copied from a grf in _all_grfs -}; +} GCF_Flags; typedef struct GRFConfig { char *filename; @@ -48,7 +49,7 @@ void AppendStaticGRFConfigs(GRFConfig **dst); void ClearGRFConfig(GRFConfig **config); void ClearGRFConfigList(GRFConfig **config); void ResetGRFConfig(bool defaults); -bool IsGoodGRFConfigList(void); +GCF_Flags IsGoodGRFConfigList(void); bool FillGRFDetails(GRFConfig *config, bool is_static); char *GRFBuildParamList(char *dst, const GRFConfig *c, const char *last); diff --git a/src/newgrf_gui.cpp b/src/newgrf_gui.cpp index 8b12035637..126b4b4fb2 100644 --- a/src/newgrf_gui.cpp +++ b/src/newgrf_gui.cpp @@ -71,8 +71,9 @@ static void ShowNewGRFInfo(const GRFConfig *c, uint x, uint y, uint w, bool show } /* Show flags */ - if (HASBIT(c->flags, GCF_NOT_FOUND)) y += DrawStringMultiLine(x, y, STR_NEWGRF_NOT_FOUND, w); - if (HASBIT(c->flags, GCF_DISABLED)) y += DrawStringMultiLine(x, y, STR_NEWGRF_DISABLED, w); + if (HASBIT(c->flags, GCF_NOT_FOUND)) y += DrawStringMultiLine(x, y, STR_NEWGRF_NOT_FOUND, w); + if (HASBIT(c->flags, GCF_DISABLED)) y += DrawStringMultiLine(x, y, STR_NEWGRF_DISABLED, w); + if (HASBIT(c->flags, GCF_COMPATIBLE)) y += DrawStringMultiLine(x, y, STR_NEWGRF_COMPATIBLE_LOADED, w); /* Draw GRF info if it exists */ if (c->info != NULL && !StrEmpty(c->info)) { @@ -317,7 +318,9 @@ static void NewGRFWndProc(Window *w, WindowEvent *e) if (HASBIT(c->flags, GCF_NOT_FOUND) || HASBIT(c->flags, GCF_DISABLED)) { pal = PALETTE_TO_RED; } else if (HASBIT(c->flags, GCF_STATIC)) { - pal = PALETTE_TO_YELLOW; + pal = PALETTE_TO_GREY; + } else if (HASBIT(c->flags, GCF_COMPATIBLE)) { + pal = PALETTE_TO_ORANGE; } else if (HASBIT(c->flags, GCF_ACTIVATED)) { pal = PALETTE_TO_GREEN; } else { diff --git a/src/openttd.cpp b/src/openttd.cpp index b07622bf39..3640b0aee1 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -1188,8 +1188,14 @@ bool AfterLoadGame(void) // convert road side to my format. if (_opt.road_side) _opt.road_side = 1; - /* Check all NewGRFs are present */ - if (!IsGoodGRFConfigList()) return false; + /* Check if all NewGRFs are present, we are very strict in MP mode */ + GCF_Flags gcf_res = IsGoodGRFConfigList(); + if (_networking && gcf_res != GCF_ACTIVATED) return false; + + switch (gcf_res) { + case GCF_COMPATIBLE: _switch_mode_errorstr = STR_NEWGRF_COMPATIBLE_LOAD_WARNING; break; + case GCF_NOT_FOUND: _switch_mode_errorstr = STR_NEWGRF_DISABLED_WARNING; break; + } /* Update current year * must be done before loading sprites as some newgrfs check it */