changeset 6113:5cf0c6849eee draft

(svn r8849) -Codechange: Replace hardcoded global/climate cargo mapping tables with dynamically generated data. Change associated code to use new functions.
author peter1138 <peter1138@openttd.org>
date Thu, 22 Feb 2007 22:09:51 +0000
parents c1f929f6b1a5
children 466aa6880749
files projects/openttd.vcproj projects/openttd_vs80.vcproj source.list src/cargotype.cpp src/cargotype.h src/newgrf.cpp src/newgrf_cargo.cpp src/newgrf_cargo.h src/newgrf_engine.cpp src/newgrf_station.cpp src/vehicle.cpp src/vehicle_gui.cpp
diffstat 12 files changed, 74 insertions(+), 130 deletions(-) [+]
line wrap: on
line diff
--- a/projects/openttd.vcproj
+++ b/projects/openttd.vcproj
@@ -914,9 +914,6 @@
 				RelativePath=".\..\src\newgrf.cpp">
 			</File>
 			<File
-				RelativePath=".\..\src\newgrf_cargo.cpp">
-			</File>
-			<File
 				RelativePath=".\..\src\newgrf_config.cpp">
 			</File>
 			<File
--- a/projects/openttd_vs80.vcproj
+++ b/projects/openttd_vs80.vcproj
@@ -1440,10 +1440,6 @@
 				>
 			</File>
 			<File
-				RelativePath=".\..\src\newgrf_cargo.cpp"
-				>
-			</File>
-			<File
 				RelativePath=".\..\src\newgrf_config.cpp"
 				>
 			</File>
--- a/source.list
+++ b/source.list
@@ -275,7 +275,6 @@
 
 # NewGRF
 newgrf.cpp
-newgrf_cargo.cpp
 newgrf_config.cpp
 newgrf_engine.cpp
 newgrf_sound.cpp
--- a/src/cargotype.cpp
+++ b/src/cargotype.cpp
@@ -14,6 +14,12 @@
 
 static const byte INVALID_CARGO = 0xFF;
 
+/* Quick mapping from cargo type 'bitnums' to real cargo IDs */
+static CargoID _cargo_bitnum_map[32];
+
+/* Bitmask of cargo type 'bitnums' availabe */
+uint32 _cargo_mask;
+
 
 void SetupCargoForClimate(LandscapeID l)
 {
@@ -23,6 +29,9 @@
 	memset(_cargo, 0, sizeof(_cargo));
 	for (CargoID i = 0; i < lengthof(_cargo); i++) _cargo[i].bitnum = INVALID_CARGO;
 
+	memset(_cargo_bitnum_map, CT_INVALID, sizeof(_cargo_bitnum_map));
+	_cargo_mask = 0;
+
 	for (CargoID i = 0; i < lengthof(_default_climate_cargo[l]); i++) {
 		CargoLabel cl = _default_climate_cargo[l][i];
 
@@ -31,6 +40,13 @@
 		for (uint j = 0; j < lengthof(_default_cargo); j++) {
 			if (_default_cargo[j].label == cl) {
 				_cargo[i] = _default_cargo[j];
+
+				/* Populate the bitnum map and masks */
+				byte bitnum = _cargo[i].bitnum;
+				if (bitnum < lengthof(_cargo_bitnum_map)) {
+					_cargo_bitnum_map[bitnum] = i;
+					SETBIT(_cargo_mask, bitnum);
+				}
 				break;
 			}
 		}
@@ -44,3 +60,10 @@
 	return &_cargo[c];
 }
 
+
+CargoID GetCargoIDByBitnum(byte bitnum)
+{
+	assert(bitnum < lengthof(_cargo_bitnum_map));
+	assert(_cargo_bitnum_map[bitnum] != CT_INVALID);
+	return _cargo_bitnum_map[bitnum];
+}
--- a/src/cargotype.h
+++ b/src/cargotype.h
@@ -34,9 +34,15 @@
 } CargoSpec;
 
 
+extern uint32 _cargo_mask;
+
+
 /* Set up the default cargo types for the given landscape type */
 void SetupCargoForClimate(LandscapeID l);
 /* Retrieve cargo details for the given cargo ID */
 const CargoSpec *GetCargo(CargoID c);
+/* Get the cargo ID of a cargo bitnum */
+CargoID GetCargoIDByBitnum(byte bitnum);
+
 
 #endif /* CARGOTYPE_H */
--- a/src/newgrf.cpp
+++ b/src/newgrf.cpp
@@ -3658,9 +3658,10 @@
 
 		if (cargo_allowed[engine] != 0) {
 			// Build up the list of cargo types from the set cargo classes.
-			for (i = 0; i < lengthof(cargo_classes); i++) {
-				if (HASBIT(cargo_allowed[engine], i)) mask |= cargo_classes[i];
-				if (HASBIT(cargo_disallowed[engine], i)) not_mask |= cargo_classes[i];
+			for (i = 0; i < NUM_CARGO; i++) {
+				const CargoSpec *cs = GetCargo(i);
+				if (cargo_allowed[engine]    & cs->classes) SETBIT(mask,     cs->bitnum);
+				if (cargo_disallowed[engine] & cs->classes) SETBIT(not_mask, cs->bitnum);
 			}
 		} else {
 			// Don't apply default refit mask to wagons or engines with no capacity
@@ -3673,7 +3674,7 @@
 				xor_mask = _default_refitmasks[GetEngine(engine)->type];
 			}
 		}
-		_engine_info[engine].refit_mask = ((mask & ~not_mask) ^ xor_mask) & _landscape_global_cargo_mask[_opt.landscape];
+		_engine_info[engine].refit_mask = ((mask & ~not_mask) ^ xor_mask) & _cargo_mask;
 	}
 }
 
deleted file mode 100644
--- a/src/newgrf_cargo.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/* $Id$ */
-
-#include "stdafx.h"
-#include "openttd.h"
-#include "newgrf_cargo.h"
-
-/** TRANSLATE FROM LOCAL CARGO TO GLOBAL CARGO ID'S.
- * This maps the per-landscape cargo ID's to globally unique cargo ID's usable ie. in
- * the custom GRF  files. It is basically just a transcribed table from TTDPatch's newgrf.txt.
- */
-const CargoID _global_cargo_id[NUM_LANDSCAPE][NUM_CARGO] = {
-	/* LT_NORMAL */ {GC_PASSENGERS, GC_COAL,   GC_MAIL, GC_OIL,  GC_LIVESTOCK, GC_GOODS, GC_GRAIN,  GC_WOOD, GC_IRON_ORE,     GC_STEEL,   GC_VALUABLES, GC_PAPER_TEMP},
-	/* LT_HILLY */  {GC_PASSENGERS, GC_COAL,   GC_MAIL, GC_OIL,  GC_LIVESTOCK, GC_GOODS, GC_GRAIN,  GC_WOOD, GC_INVALID,      GC_PAPER,   GC_VALUABLES, GC_FOOD },
-	/* LT_DESERT */ {GC_PASSENGERS, GC_RUBBER, GC_MAIL, GC_OIL,  GC_FRUIT,     GC_GOODS, GC_GRAIN,  GC_WOOD, GC_COPPER_ORE,   GC_WATER,   GC_VALUABLES, GC_FOOD },
-	/* LT_CANDY */  {GC_PASSENGERS, GC_SUGAR,  GC_MAIL, GC_TOYS, GC_BATTERIES, GC_CANDY, GC_TOFFEE, GC_COLA, GC_COTTON_CANDY, GC_BUBBLES, GC_PLASTIC,   GC_FIZZY_DRINKS },
-	/**
-	 * - GC_INVALID (255) means that  cargo is not available for that climate
-	 * - GC_PAPER_TEMP (27) is paper in  temperate climate in TTDPatch
-	 * Following can  be renumbered:
-	 * - GC_DEFAULT (29) is the defa ult cargo for the purpose of spritesets
-	 * - GC_PURCHASE (30) is the purchase list image (the equivalent of 0xff) for the purpose of spritesets
-	 */
-};
-
-/** BEGIN --- TRANSLATE FROM GLOBAL CARGO TO LOCAL CARGO ID'S **/
-/** Map global cargo ID's to local-cargo ID's */
-const CargoID _local_cargo_id_ctype[NUM_GLOBAL_CID] = {
-	CT_PASSENGERS, CT_COAL,    CT_MAIL,         CT_OIL,       CT_LIVESTOCK, CT_GOODS,  CT_GRAIN,      CT_WOOD,         /*  0- 7 */
-	CT_IRON_ORE,   CT_STEEL,   CT_VALUABLES,    CT_PAPER,     CT_FOOD,      CT_FRUIT,  CT_COPPER_ORE, CT_WATER,        /*  8-15 */
-	CT_RUBBER,     CT_SUGAR,   CT_TOYS,         CT_BATTERIES, CT_CANDY,     CT_TOFFEE, CT_COLA,       CT_COTTON_CANDY, /* 16-23 */
-	CT_BUBBLES,    CT_PLASTIC, CT_FIZZY_DRINKS, CT_PAPER      /* unsup. */, CT_HILLY_UNUSED,                           /* 24-28 */
-	CT_INVALID,    CT_INVALID                                                                                          /* 29-30 */
-};
-
-/** Bitmasked value where the global cargo ID is available in landscape
- * 0: LT_NORMAL, 1: LT_HILLY, 2: LT_DESERT, 3: LT_CANDY */
-#define MC(cargo) (1 << cargo)
-const uint32 _landscape_global_cargo_mask[NUM_LANDSCAPE] =
-{ /* LT_NORMAL: temperate */
-	MC(GC_PASSENGERS) | MC(GC_COAL) | MC(GC_MAIL)  | MC(GC_OIL)   | MC(GC_LIVESTOCK) | MC(GC_GOODS) | MC(GC_GRAIN)     | MC(GC_WOOD) | MC(GC_IRON_ORE)     | MC(GC_STEEL)      | MC(GC_VALUABLES),
-	/* LT_HILLY: arctic */
-	MC(GC_PASSENGERS) | MC(GC_COAL) | MC(GC_MAIL)  | MC(GC_OIL)   | MC(GC_LIVESTOCK) | MC(GC_GOODS) | MC(GC_GRAIN)     | MC(GC_WOOD) | MC(GC_VALUABLES)    | MC(GC_PAPER)      | MC(GC_FOOD),
-	/* LT_DESERT: rainforest/desert */
-	MC(GC_PASSENGERS) | MC(GC_MAIL) | MC(GC_OIL)   | MC(GC_GOODS) | MC(GC_GRAIN)     | MC(GC_WOOD)  | MC(GC_VALUABLES) | MC(GC_FOOD) | MC(GC_FRUIT)        | MC(GC_COPPER_ORE) | MC(GC_WATER)   | MC(GC_RUBBER),
-	/* LT_CANDY: toyland */
-	MC(GC_PASSENGERS) | MC(GC_MAIL) | MC(GC_SUGAR) | MC(GC_TOYS)  | MC(GC_BATTERIES) | MC(GC_CANDY) | MC(GC_TOFFEE)    | MC(GC_COLA) | MC(GC_COTTON_CANDY) | MC(GC_BUBBLES)    | MC(GC_PLASTIC) | MC(GC_FIZZY_DRINKS)
-};
-/** END   --- TRANSLATE FROM GLOBAL CARGO TO LOCAL CARGO ID'S **/
-
-/**
- * Bitmask of classes for cargo types.
- */
-const uint32 cargo_classes[16] = {
-	/* Passengers */ MC(GC_PASSENGERS),
-	/* Mail       */ MC(GC_MAIL),
-	/* Express    */ MC(GC_GOODS)     | MC(GC_FOOD)  | MC(GC_CANDY),
-	/* Armoured   */ MC(GC_VALUABLES),
-	/* Bulk       */ MC(GC_COAL)      | MC(GC_GRAIN) | MC(GC_IRON_ORE) | MC(GC_COPPER_ORE) | MC(GC_FRUIT)   | MC(GC_SUGAR)     | MC(GC_TOFFEE)  | MC(GC_COTTON_CANDY),
-	/* Piece      */ MC(GC_LIVESTOCK) | MC(GC_WOOD)  | MC(GC_STEEL)    | MC(GC_PAPER)      | MC(GC_TOYS)    | MC(GC_BATTERIES) | MC(GC_BUBBLES) | MC(GC_FIZZY_DRINKS),
-	/* Liquids    */ MC(GC_OIL)       | MC(GC_WATER) | MC(GC_RUBBER)   | MC(GC_COLA)       | MC(GC_PLASTIC),
-	/* Chilled    */ MC(GC_FOOD)      | MC(GC_FRUIT),
-	/* Undefined  */ 0, 0, 0, 0, 0, 0, 0, 0
-};
-#undef MC
-
-/**
- *there are 32 slots available per climate with newcargo.*/
-#define MAXSLOTS 32
--- a/src/newgrf_cargo.h
+++ b/src/newgrf_cargo.h
@@ -52,9 +52,4 @@
 	NUM_GLOBAL_CID  =  32
 };
 
-extern const CargoID _global_cargo_id[NUM_LANDSCAPE][NUM_CARGO];
-extern const uint32 _landscape_global_cargo_mask[NUM_LANDSCAPE];
-extern const CargoID _local_cargo_id_ctype[NUM_GLOBAL_CID];
-extern const uint32 cargo_classes[16];
-
 #endif /* NEWGRF_CARGO_H */
--- a/src/newgrf_engine.cpp
+++ b/src/newgrf_engine.cpp
@@ -539,10 +539,9 @@
 			const Vehicle *u;
 			byte cargo_classes = 0;
 			uint common_cargo_best = 0;
-			uint common_cargos[NUM_GLOBAL_CID];
+			uint common_cargos[NUM_CARGO];
 			byte user_def_data = 0;
-			CargoID cargo;
-			CargoID common_cargo_type = GC_PASSENGERS;
+			CargoID common_cargo_type = CT_PASSENGERS;
 
 			/* Reset our arrays */
 			memset(common_cargos, 0, sizeof(common_cargos));
@@ -550,18 +549,17 @@
 			for (u = v; u != NULL; u = u->next) {
 				/* Skip empty engines */
 				if (u->cargo_cap == 0) continue;
-				/* Map from climate to global cargo ID */
-				cargo = _global_cargo_id[_opt.landscape][u->cargo_type];
-				cargo_classes |= GetCargo(cargo)->classes;
-				common_cargos[cargo]++;
+
+				cargo_classes |= GetCargo(u->cargo_type)->classes;
+				common_cargos[u->cargo_type]++;
 				user_def_data |= RailVehInfo(u->engine_type)->user_def_data;
 			}
 
 			/* Pick the most common cargo type */
-			for (cargo = 0; cargo < NUM_GLOBAL_CID; cargo++) {
+			for (CargoID cargo = 0; cargo < NUM_CARGO; cargo++) {
 				if (common_cargos[cargo] > common_cargo_best) {
 					common_cargo_best = common_cargos[cargo];
-					common_cargo_type = cargo;
+					common_cargo_type = GetCargo(cargo)->bitnum;
 				}
 			}
 
@@ -608,10 +606,9 @@
 			 * ww - cargo unit weight in 1/16 tons, same as cargo prop. 0F.
 			 * cccc - the cargo class value of the cargo transported by the vehicle.
 			 */
-			CargoID cid = _global_cargo_id[_opt.landscape][v->cargo_type];
 			const CargoSpec *cs = GetCargo(v->cargo_type);
 
-			return (cs->classes << 16) | (cs->weight << 8) | cid;
+			return (cs->classes << 16) | (cs->weight << 8) | cs->bitnum;
 		}
 
 		case 0x48: return GetVehicleTypeInfo(v->engine_type); /* Vehicle Type Info */
@@ -823,7 +820,7 @@
 	if (v == NULL) {
 		cargo = GC_PURCHASE;
 	} else {
-		cargo = _global_cargo_id[_opt.landscape][v->cargo_type];
+		cargo = GetCargo(v->cargo_type)->bitnum;
 		assert(cargo != GC_INVALID);
 
 		if (v->type == VEH_Train) {
@@ -889,7 +886,7 @@
 bool UsesWagonOverride(const Vehicle* v)
 {
 	assert(v->type == VEH_Train);
-	return GetWagonOverrideSpriteSet(v->engine_type, _global_cargo_id[_opt.landscape][v->cargo_type], v->u.rail.first_engine) != NULL;
+	return GetWagonOverrideSpriteSet(v->engine_type, GetCargo(v->cargo_type)->bitnum, v->u.rail.first_engine) != NULL;
 }
 
 /**
--- a/src/newgrf_station.cpp
+++ b/src/newgrf_station.cpp
@@ -18,6 +18,7 @@
 #include "newgrf_spritegroup.h"
 #include "date.h"
 #include "helpers.hpp"
+#include "cargotype.h"
 
 static StationClass station_classes[STAT_CLASS_MAX];
 
@@ -459,7 +460,7 @@
 			break;
 
 		default:
-			cargo = GB(st->goods[_local_cargo_id_ctype[cargo_type]].waiting_acceptance, 0, 12);
+			cargo = GB(st->goods[GetCargoIDByBitnum(cargo_type)].waiting_acceptance, 0, 12);
 			break;
 	}
 
@@ -511,15 +512,12 @@
 		/* No station, so we are in a purchase list */
 		ctype = GC_PURCHASE;
 	} else {
-		CargoID cargo;
-
 		/* Pick the first cargo that we have waiting */
-		for (cargo = 0; cargo < NUM_GLOBAL_CID; cargo++) {
-			CargoID lcid = _local_cargo_id_ctype[cargo];
-			if (lcid != CT_INVALID &&
-					object->u.station.statspec->spritegroup[cargo] != NULL &&
-					GB(object->u.station.st->goods[lcid].waiting_acceptance, 0, 12) != 0) {
-				ctype = cargo;
+		for (CargoID cargo = 0; cargo < NUM_CARGO; cargo++) {
+			const CargoSpec *cs = GetCargo(cargo);
+			if (cs->bitnum != 0xFF && object->u.station.statspec->spritegroup[cs->bitnum] != NULL &&
+					GB(object->u.station.st->goods[cargo].waiting_acceptance, 0, 12) != 0) {
+				ctype = cs->bitnum;
 				break;
 			}
 		}
--- a/src/vehicle.cpp
+++ b/src/vehicle.cpp
@@ -37,6 +37,7 @@
 #include "newgrf_engine.h"
 #include "newgrf_sound.h"
 #include "helpers.hpp"
+#include "cargotype.h"
 
 #define INVALID_COORD (-0x8000)
 #define GEN_HASH(x, y) ((GB((y), 6, 6) << 6) + GB((x), 7, 6))
@@ -761,7 +762,7 @@
  */
 bool CanRefitTo(EngineID engine_type, CargoID cid_to)
 {
-	CargoID cid = _global_cargo_id[_opt_ptr->landscape][cid_to];
+	CargoID cid = GetCargo(cid_to)->bitnum;
 	return HASBIT(EngInfo(engine_type)->refit_mask, cid);
 }
 
@@ -771,12 +772,11 @@
  */
 CargoID FindFirstRefittableCargo(EngineID engine_type)
 {
-	CargoID cid;
 	uint32 refit_mask = EngInfo(engine_type)->refit_mask;
 
 	if (refit_mask != 0) {
-		for (cid = CT_PASSENGERS; cid < NUM_CARGO; cid++) {
-			if (HASBIT(refit_mask, _global_cargo_id[_opt_ptr->landscape][cid])) return cid;
+		for (CargoID cid = CT_PASSENGERS; cid < NUM_CARGO; cid++) {
+			if (HASBIT(refit_mask, GetCargo(cid)->bitnum)) return cid;
 		}
 	}
 
--- a/src/vehicle_gui.cpp
+++ b/src/vehicle_gui.cpp
@@ -202,7 +202,6 @@
 	uint i;
 
 	do {
-		CargoID cid;
 		uint32 cmask = EngInfo(u->engine_type)->refit_mask;
 		byte callbackmask = EngInfo(u->engine_type)->callbackmask;
 
@@ -210,14 +209,11 @@
 		if (u->cargo_cap == 0) continue;
 
 		/* Loop through all cargos in the refit mask */
-		for (cid = 0; cmask != 0 && num_lines < max_lines; cmask >>= 1, cid++) {
-			CargoID lcid;
+		for (CargoID cid = 0; cid != NUM_CARGO && num_lines < max_lines; cid++) {
+			const CargoSpec *cs = GetCargo(cid);
 
 			/* Skip cargo type if it's not listed */
-			if (!HASBIT(cmask, 0)) continue;
-
-			lcid = _local_cargo_id_ctype[cid];
-			if (lcid == CT_INVALID) continue;
+			if (!HASBIT(cmask, cs->bitnum)) continue;
 
 			/* Check the vehicle's callback mask for cargo suffixes */
 			if (HASBIT(callbackmask, CBM_CARGO_SUFFIX)) {
@@ -227,7 +223,7 @@
 				byte temp_subtype  = u->cargo_subtype;
 				byte refit_cyc;
 
-				u->cargo_type = lcid;
+				u->cargo_type = cid;
 
 				for (refit_cyc = 0; refit_cyc < 16 && num_lines < max_lines; refit_cyc++) {
 					bool duplicate = false;
@@ -241,12 +237,12 @@
 
 					/* Check if this cargo and subtype combination are listed */
 					for (i = 0; i < num_lines && !duplicate; i++) {
-						if (refit[i].cargo == lcid && refit[i].value == callback) duplicate = true;
+						if (refit[i].cargo == cid && refit[i].value == callback) duplicate = true;
 					}
 
 					if (duplicate) continue;
 
-					refit[num_lines].cargo   = lcid;
+					refit[num_lines].cargo   = cid;
 					refit[num_lines].subtype = refit_cyc;
 					refit[num_lines].value   = callback;
 					refit[num_lines].engine  = u->engine_type;
@@ -261,11 +257,11 @@
 				bool duplicate = false;
 
 				for (i = 0; i < num_lines && !duplicate; i++) {
-					if (refit[i].cargo == lcid && refit[i].value == CALLBACK_FAILED) duplicate = true;
+					if (refit[i].cargo == cid && refit[i].value == CALLBACK_FAILED) duplicate = true;
 				}
 
 				if (!duplicate) {
-					refit[num_lines].cargo   = lcid;
+					refit[num_lines].cargo   = cid;
 					refit[num_lines].subtype = 0;
 					refit[num_lines].value   = CALLBACK_FAILED;
 					refit[num_lines].engine  = INVALID_ENGINE;
@@ -497,7 +493,7 @@
 	/* List of cargo types of this engine */
 	uint32 cmask = EngInfo(engine)->refit_mask;
 	/* List of cargo types available in this climate */
-	uint32 lmask = _landscape_global_cargo_mask[_opt.landscape];
+	uint32 lmask = _cargo_mask;
 	char *b = _userstring;
 
 	/* Draw nothing if the engine is not refittable */
@@ -509,8 +505,6 @@
 		/* Engine can be refitted to all types in this climate */
 		b = InlineString(b, STR_PURCHASE_INFO_ALL_TYPES);
 	} else {
-		CargoID cid;
-
 		/* Check if we are able to refit to more cargo types and unable to. If
 		 * so, invert the cargo types to list those that we can't refit to. */
 		if (CountBits(cmask ^ lmask) < CountBits(cmask)) {
@@ -518,12 +512,18 @@
 			b = InlineString(b, STR_PURCHASE_INFO_ALL_BUT);
 		}
 
+		bool first = true;
+
 		/* Add each cargo type to the list */
-		for (cid = 0; cmask != 0; cmask >>= 1, cid++) {
-			if (!HASBIT(cmask, 0)) continue;
+		for (CargoID cid = 0; cid < NUM_CARGO; cid++) {
+			const CargoSpec *cs = GetCargo(cid);
+
+			if (!HASBIT(cmask, cs->bitnum)) continue;
 
-			b = InlineString(b, GetCargo(_local_cargo_id_ctype[cid])->name);
-			if (cmask > 1) b = strecpy(b, ", ", lastof(_userstring));
+			if (!first) b = strecpy(b, ", ", lastof(_userstring));
+			first = false;
+
+			b = InlineString(b, GetCargo(cid)->name);
 		}
 	}