Changeset - r27979:37253e20ef1d
[Not reviewed]
master
0 3 0
frosch - 12 months ago 2023-10-01 13:21:57
frosch@openttd.org
Fix #8846: When upgrading NewGRF presets, copy NewGRF parameters only if the NewGRF are compatible. Otherwise reset to defaults.
3 files changed with 15 insertions and 2 deletions:
0 comments (0 inline, 0 general)
src/newgrf_config.cpp
Show inline comments
 
@@ -58,24 +58,32 @@ GRFConfig::GRFConfig(const GRFConfig &co
 
	status(config.status),
 
	grf_bugs(config.grf_bugs),
 
	param(config.param),
 
	num_params(config.num_params),
 
	num_valid_params(config.num_valid_params),
 
	palette(config.palette),
 
	param_info(config.param_info),
 
	has_param_defaults(config.has_param_defaults)
 
{
 
}
 

	
 
/**
 
 * Return whether this NewGRF can replace an older version of the same NewGRF.
 
 */
 
bool GRFConfig::IsCompatible(uint32_t old_version) const
 
{
 
	return this->min_loadable_version <= old_version && old_version <= this->version;
 
}
 

	
 
/**
 
 * Copy the parameter information from the \a src config.
 
 * @param src Source config.
 
 */
 
void GRFConfig::CopyParams(const GRFConfig &src)
 
{
 
	this->num_params = src.num_params;
 
	this->param = src.param;
 
}
 

	
 
/**
 
 * Get the name of this grf. In case the name isn't known
 
 * the filename is returned.
 
@@ -676,25 +684,25 @@ void ScanNewGRFFiles(NewGRFScanCallback 
 
const GRFConfig *FindGRFConfig(uint32_t grfid, FindGRFConfigMode mode, const MD5Hash *md5sum, uint32_t desired_version)
 
{
 
	assert((mode == FGCM_EXACT) != (md5sum == nullptr));
 
	const GRFConfig *best = nullptr;
 
	for (const GRFConfig *c = _all_grfs; c != nullptr; c = c->next) {
 
		/* if md5sum is set, we look for an exact match and continue if not found */
 
		if (!c->ident.HasGrfIdentifier(grfid, md5sum)) continue;
 
		/* return it, if the exact same newgrf is found, or if we do not care about finding "the best" */
 
		if (md5sum != nullptr || mode == FGCM_ANY) return c;
 
		/* Skip incompatible stuff, unless explicitly allowed */
 
		if (mode != FGCM_NEWEST && HasBit(c->flags, GCF_INVALID)) continue;
 
		/* check version compatibility */
 
		if (mode == FGCM_COMPATIBLE && (c->version < desired_version || c->min_loadable_version > desired_version)) continue;
 
		if (mode == FGCM_COMPATIBLE && !c->IsCompatible(desired_version)) continue;
 
		/* remember the newest one as "the best" */
 
		if (best == nullptr || c->version > best->version) best = c;
 
	}
 

	
 
	return best;
 
}
 

	
 
/**
 
 * Retrieve a NewGRF from the current config by its grfid.
 
 * @param grfid grf to look for.
 
 * @param mask  GRFID mask to allow for partial matching.
 
 * @return The grf config, if it exists, else \c nullptr.
src/newgrf_config.h
Show inline comments
 
@@ -164,24 +164,25 @@ struct GRFConfig : ZeroedMemoryAllocator
 
	uint8_t flags; ///< NOSAVE: GCF_Flags, bitset
 
	GRFStatus status; ///< NOSAVE: GRFStatus, enum
 
	uint32_t grf_bugs; ///< NOSAVE: bugs in this GRF in this run, @see enum GRFBugs
 
	std::array<uint32_t, 0x80> param; ///< GRF parameters
 
	uint8_t num_params; ///< Number of used parameters
 
	uint8_t num_valid_params; ///< NOSAVE: Number of valid parameters (action 0x14)
 
	uint8_t palette; ///< GRFPalette, bitset
 
	std::vector<std::optional<GRFParameterInfo>> param_info; ///< NOSAVE: extra information about the parameters
 
	bool has_param_defaults; ///< NOSAVE: did this newgrf specify any defaults for it's parameters
 

	
 
	struct GRFConfig *next; ///< NOSAVE: Next item in the linked list
 

	
 
	bool IsCompatible(uint32_t old_version) const;
 
	void CopyParams(const GRFConfig &src);
 

	
 
	std::optional<std::string> GetTextfile(TextfileType type) const;
 
	const char *GetName() const;
 
	const char *GetDescription() const;
 
	const char *GetURL() const;
 

	
 
	void SetParameterDefaults();
 
	void SetSuitablePalette();
 
	void FinalizeParameterInfo();
 
};
 

	
src/newgrf_gui.cpp
Show inline comments
 
@@ -714,25 +714,29 @@ struct NewGRFWindow : public Window, New
 
	{
 
		GrfIdMap grfid_map;
 
		FillGrfidMap(this->actives, &grfid_map);
 

	
 
		for (const GRFConfig *a = _all_grfs; a != nullptr; a = a->next) {
 
			GrfIdMap::iterator iter = grfid_map.find(a->ident.grfid);
 
			if (iter == grfid_map.end() || iter->second->version >= a->version) continue;
 

	
 
			GRFConfig **c = &this->actives;
 
			while (*c != iter->second) c = &(*c)->next;
 
			GRFConfig *d = new GRFConfig(*a);
 
			d->next = (*c)->next;
 
			d->CopyParams(**c);
 
			if (d->IsCompatible((*c)->version)) {
 
				d->CopyParams(**c);
 
			} else {
 
				d->SetParameterDefaults();
 
			}
 
			if (this->active_sel == *c) {
 
				CloseWindowByClass(WC_GRF_PARAMETERS);
 
				CloseWindowByClass(WC_TEXTFILE);
 
				this->active_sel = nullptr;
 
			}
 
			delete *c;
 
			*c = d;
 
			iter->second = d;
 
		}
 
	}
 

	
 
	void UpdateWidgetSize(int widget, Dimension *size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension *fill, [[maybe_unused]] Dimension *resize) override
0 comments (0 inline, 0 general)