Changeset - r23470:4f54a54295ed
[Not reviewed]
master
0 4 0
peter1138 - 5 years ago 2019-03-10 17:45:15
peter1138@openttd.org
Fix e66cec8f86: Permit loading of industry production callback with invalid cargo type.

It is only an error if the invalid result is actually used. This will be silently ignored at the moment.
It is still an error if a duplicate cargo type is returned.
4 files changed with 24 insertions and 4 deletions:
0 comments (0 inline, 0 general)
src/lang/english.txt
Show inline comments
 
@@ -2999,13 +2999,13 @@ STR_NEWGRF_ERROR_CORRUPT_SPRITE         
 
STR_NEWGRF_ERROR_MULTIPLE_ACTION_8                              :Contains multiple Action 8 entries (sprite {3:NUM})
 
STR_NEWGRF_ERROR_READ_BOUNDS                                    :Read past end of pseudo-sprite (sprite {3:NUM})
 
STR_NEWGRF_ERROR_GRM_FAILED                                     :Requested GRF resources not available (sprite {3:NUM})
 
STR_NEWGRF_ERROR_FORCEFULLY_DISABLED                            :{1:RAW_STRING} was disabled by {2:RAW_STRING}
 
STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT                          :Invalid/unknown sprite layout format (sprite {3:NUM})
 
STR_NEWGRF_ERROR_LIST_PROPERTY_TOO_LONG                         :Too many elements in property value list (sprite {3:NUM}, property {4:HEX})
 
STR_NEWGRF_ERROR_INDPROD_CALLBACK                               :Invalid industry production callback (sprite {3:NUM}, "{1:RAW_STRING}")
 
STR_NEWGRF_ERROR_INDPROD_CALLBACK                               :Invalid industry production callback (sprite {3:NUM}, "{2:RAW_STRING}")
 

	
 
# NewGRF related 'general' warnings
 
STR_NEWGRF_POPUP_CAUTION_CAPTION                                :{WHITE}Caution!
 
STR_NEWGRF_CONFIRMATION_TEXT                                    :{YELLOW}You are about to make changes to a running game. This can crash OpenTTD or break the game state. Do not file bug reports about these issues.{}Are you absolutely sure about this?
 

	
 
STR_NEWGRF_DUPLICATE_GRFID                                      :{WHITE}Can't add file: duplicate GRF ID
 
@@ -3031,12 +3031,13 @@ STR_NEWGRF_BROKEN_CAPACITY              
 
STR_BROKEN_VEHICLE_LENGTH                                       :{WHITE}Train '{VEHICLE}' belonging to '{COMPANY}' has invalid length. It is probably caused by problems with NewGRFs. Game may desync or crash
 

	
 
STR_NEWGRF_BUGGY                                                :{WHITE}NewGRF '{0:RAW_STRING}' provides incorrect information
 
STR_NEWGRF_BUGGY_ARTICULATED_CARGO                              :{WHITE}Cargo/refit information for '{1:ENGINE}' differs from purchase list after construction. This might cause autorenew/-replace to fail refitting correctly
 
STR_NEWGRF_BUGGY_ENDLESS_PRODUCTION_CALLBACK                    :{WHITE}'{1:STRING}' caused an endless loop in the production callback
 
STR_NEWGRF_BUGGY_UNKNOWN_CALLBACK_RESULT                        :{WHITE}Callback {1:HEX} returned unknown/invalid result {2:HEX}
 
STR_NEWGRF_BUGGY_INVALID_CARGO_PRODUCTION_CALLBACK              :{WHITE}'{1:STRING}' returned invalid cargo type in the production callback at {2:HEX}
 

	
 
# 'User removed essential NewGRFs'-placeholders for stuff without specs
 
STR_NEWGRF_INVALID_CARGO                                        :<invalid cargo>
 
STR_NEWGRF_INVALID_CARGO_ABBREV                                 :??
 
STR_NEWGRF_INVALID_CARGO_QUANTITY                               :{COMMA} of <invalid cargo>
 
STR_NEWGRF_INVALID_ENGINE                                       :<invalid vehicle model>
src/newgrf.cpp
Show inline comments
 
@@ -5002,13 +5002,18 @@ static void NewSpriteGroup(ByteReader *b
 
							error->data = stredup("too many inputs (max 16)");
 
							return;
 
						}
 
						for (uint i = 0; i < group->num_input; i++) {
 
							byte rawcargo = buf->ReadByte();
 
							CargoID cargo = GetCargoTranslation(rawcargo, _cur.grffile);
 
							if (std::find(group->cargo_input, group->cargo_input + i, cargo) != group->cargo_input + i) {
 
							if (cargo == CT_INVALID) {
 
								/* The mapped cargo is invalid. This is permitted at this point,
 
								 * as long as the result is not used. Mark it invalid so this
 
								 * can be tested later. */
 
								group->version = 0xFF;
 
							} else if (std::find(group->cargo_input, group->cargo_input + i, cargo) != group->cargo_input + i) {
 
								GRFError *error = DisableGrf(STR_NEWGRF_ERROR_INDPROD_CALLBACK);
 
								error->data = stredup("duplicate input cargo");
 
								return;
 
							}
 
							group->cargo_input[i] = cargo;
 
							group->subtract_input[i] = buf->ReadByte();
 
@@ -5019,13 +5024,16 @@ static void NewSpriteGroup(ByteReader *b
 
							error->data = stredup("too many outputs (max 16)");
 
							return;
 
						}
 
						for (uint i = 0; i < group->num_output; i++) {
 
							byte rawcargo = buf->ReadByte();
 
							CargoID cargo = GetCargoTranslation(rawcargo, _cur.grffile);
 
							if (std::find(group->cargo_output, group->cargo_output + i, cargo) != group->cargo_output + i) {
 
							if (cargo == CT_INVALID) {
 
								/* Mark this result as invalid to use */
 
								group->version = 0xFF;
 
							} else if (std::find(group->cargo_output, group->cargo_output + i, cargo) != group->cargo_output + i) {
 
								GRFError *error = DisableGrf(STR_NEWGRF_ERROR_INDPROD_CALLBACK);
 
								error->data = stredup("duplicate output cargo");
 
								return;
 
							}
 
							group->cargo_output[i] = cargo;
 
							group->add_output[i] = buf->ReadByte();
src/newgrf_industries.cpp
Show inline comments
 
@@ -602,12 +602,23 @@ void IndustryProductionCallback(Industry
 

	
 
		SB(object.callback_param2, 8, 16, loop);
 
		const SpriteGroup *tgroup = object.Resolve();
 
		if (tgroup == NULL || tgroup->type != SGT_INDUSTRY_PRODUCTION) break;
 
		const IndustryProductionSpriteGroup *group = (const IndustryProductionSpriteGroup *)tgroup;
 

	
 
		if (group->version == 0xFF) {
 
			/* Result was marked invalid on load, display error message */
 
			SetDParamStr(0, spec->grf_prop.grffile->filename);
 
			SetDParam(1, spec->name);
 
			SetDParam(2, ind->location.tile);
 
			ShowErrorMessage(STR_NEWGRF_BUGGY, STR_NEWGRF_BUGGY_INVALID_CARGO_PRODUCTION_CALLBACK, WL_WARNING);
 

	
 
			/* abort the function early, this error isn't critical and will allow the game to continue to run */
 
			break;
 
		}
 

	
 
		bool deref = (group->version >= 1);
 

	
 
		if (group->version < 2) {
 
			/* Callback parameters map directly to industry cargo slot indices */
 
			for (uint i = 0; i < group->num_input; i++) {
 
				ind->incoming_cargo_waiting[i] = Clamp(ind->incoming_cargo_waiting[i] - DerefIndProd(group->subtract_input[i], deref) * multiplier, 0, 0xFFFF);
src/newgrf_spritegroup.h
Show inline comments
 
@@ -274,13 +274,13 @@ struct TileLayoutSpriteGroup : SpriteGro
 
	const DrawTileSprites *ProcessRegisters(uint8 *stage) const;
 
};
 

	
 
struct IndustryProductionSpriteGroup : SpriteGroup {
 
	IndustryProductionSpriteGroup() : SpriteGroup(SGT_INDUSTRY_PRODUCTION) {}
 

	
 
	uint8 version;
 
	uint8 version;                              ///< Production callback version used, or 0xFF if marked invalid
 
	uint8 num_input;                            ///< How many subtract_input values are valid
 
	int16 subtract_input[INDUSTRY_NUM_INPUTS];  ///< Take this much of the input cargo (can be negative, is indirect in cb version 1+)
 
	CargoID cargo_input[INDUSTRY_NUM_INPUTS];   ///< Which input cargoes to take from (only cb version 2)
 
	uint8 num_output;                           ///< How many add_output values are valid
 
	uint16 add_output[INDUSTRY_NUM_OUTPUTS];    ///< Add this much output cargo when successful (unsigned, is indirect in cb version 1+)
 
	CargoID cargo_output[INDUSTRY_NUM_OUTPUTS]; ///< Which output cargoes to add to (only cb version 2)
0 comments (0 inline, 0 general)