Skip to content

Commit

Permalink
Change: Remove landscape-dependent cargo types.
Browse files Browse the repository at this point in the history
Cargo types of default engines, industries and houses are now specified in terms of label.
  • Loading branch information
PeterN committed Jan 8, 2024
1 parent 067721e commit a5d6e2c
Show file tree
Hide file tree
Showing 32 changed files with 383 additions and 268 deletions.
9 changes: 7 additions & 2 deletions src/aircraft_cmd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -305,11 +305,16 @@ CommandCost CmdBuildAircraft(DoCommandFlag flags, TileIndex tile, const Engine *

v->cargo_cap = avi->passenger_capacity;
v->refit_cap = 0;
u->cargo_cap = avi->mail_capacity;
u->refit_cap = 0;

v->cargo_type = e->GetDefaultCargoType();
u->cargo_type = CT_MAIL;
assert(IsValidCargoID(v->cargo_type));

CargoID mail = GetCargoIDByLabel(CT_MAIL);
if (IsValidCargoID(mail)) {
u->cargo_type = mail;
u->cargo_cap = avi->mail_capacity;
}

v->name.clear();
v->last_station_visited = INVALID_STATION;
Expand Down
1 change: 1 addition & 0 deletions src/articulated_vehicles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ void AddArticulatedParts(Vehicle *first)
rv->spritenum = e_artic->u.road.image_index;
if (e_artic->CanCarryCargo()) {
rv->cargo_type = e_artic->GetDefaultCargoType();
assert(IsValidCargoID(rv->cargo_type));
rv->cargo_cap = e_artic->u.road.capacity; // Callback 36 is called when the consist is finished
} else {
rv->cargo_type = front->cargo_type; // Needed for livery selection
Expand Down
8 changes: 6 additions & 2 deletions src/build_vehicle_gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -824,7 +824,7 @@ static int DrawAircraftPurchaseInfo(int left, int right, int y, EngineID engine_
if (te.mail_capacity > 0) {
SetDParam(0, te.cargo);
SetDParam(1, te.capacity);
SetDParam(2, CT_MAIL);
SetDParam(2, GetCargoIDByLabel(CT_MAIL));
SetDParam(3, te.mail_capacity);
DrawString(left, right, y, STR_PURCHASE_INFO_AIRCRAFT_CAPACITY);
} else {
Expand Down Expand Up @@ -906,7 +906,11 @@ void TestedEngineDetails::FillDefaultCapacities(const Engine *e)
} else {
this->capacity = e->GetDisplayDefaultCapacity(&this->mail_capacity);
this->all_capacities[this->cargo] = this->capacity;
this->all_capacities[CT_MAIL] = this->mail_capacity;
if (IsValidCargoID(GetCargoIDByLabel(CT_MAIL))) {
this->all_capacities[GetCargoIDByLabel(CT_MAIL)] = this->mail_capacity;
} else {
this->mail_capacity = 0;
}
}
if (this->all_capacities.GetCount() == 0) this->cargo = INVALID_CARGO;
}
Expand Down
101 changes: 53 additions & 48 deletions src/cargo_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,58 +11,63 @@
#define CARGO_TYPE_H

#include "core/enum_type.hpp"
#include "core/strong_typedef_type.hpp"

/** Globally unique label of a cargo type. */
using CargoLabel = StrongType::Typedef<uint32_t, struct CargoLabelTag, false, StrongType::CompareSelf>;

/**
* Cargo slots to indicate a cargo type within a game.
*/
using CargoID = byte;

/**
* Available types of cargo
* Numbers are re-used between different climates.
* @see CargoTypes
*/
typedef byte CargoID;

/** Available types of cargo */
enum CargoType {
/* Temperate */
CT_PASSENGERS = 0,
CT_COAL = 1,
CT_MAIL = 2,
CT_OIL = 3,
CT_LIVESTOCK = 4,
CT_GOODS = 5,
CT_GRAIN = 6,
CT_WOOD = 7,
CT_IRON_ORE = 8,
CT_STEEL = 9,
CT_VALUABLES = 10,

/* Arctic */
CT_WHEAT = 6,
CT_HILLY_UNUSED = 8,
CT_PAPER = 9,
CT_GOLD = 10,
CT_FOOD = 11,

/* Tropic */
CT_RUBBER = 1,
CT_FRUIT = 4,
CT_MAIZE = 6,
CT_COPPER_ORE = 8,
CT_WATER = 9,
CT_DIAMONDS = 10,

/* Toyland */
CT_SUGAR = 1,
CT_TOYS = 3,
CT_BATTERIES = 4,
CT_CANDY = 5,
CT_TOFFEE = 6,
CT_COLA = 7,
CT_COTTON_CANDY = 8,
CT_BUBBLES = 9,
CT_PLASTIC = 10,
CT_FIZZY_DRINKS = 11,

CT_INVALID = 0xFF, ///< Invalid cargo type.
};

/* Temperate */
static constexpr CargoLabel CT_PASSENGERS = CargoLabel('PASS');
static constexpr CargoLabel CT_COAL = CargoLabel('COAL');
static constexpr CargoLabel CT_MAIL = CargoLabel('MAIL');
static constexpr CargoLabel CT_OIL = CargoLabel('OIL_');
static constexpr CargoLabel CT_LIVESTOCK = CargoLabel('LVST');
static constexpr CargoLabel CT_GOODS = CargoLabel('GOOD');
static constexpr CargoLabel CT_GRAIN = CargoLabel('GRAI');
static constexpr CargoLabel CT_WOOD = CargoLabel('WOOD');
static constexpr CargoLabel CT_IRON_ORE = CargoLabel('IORE');
static constexpr CargoLabel CT_STEEL = CargoLabel('STEL');
static constexpr CargoLabel CT_VALUABLES = CargoLabel('VALU');

/* Arctic */
static constexpr CargoLabel CT_WHEAT = CargoLabel('WHEA');
static constexpr CargoLabel CT_PAPER = CargoLabel('PAPR');
static constexpr CargoLabel CT_GOLD = CargoLabel('GOLD');
static constexpr CargoLabel CT_FOOD = CargoLabel('FOOD');

/* Tropic */
static constexpr CargoLabel CT_RUBBER = CargoLabel('RUBR');
static constexpr CargoLabel CT_FRUIT = CargoLabel('FRUI');
static constexpr CargoLabel CT_MAIZE = CargoLabel('MAIZ');
static constexpr CargoLabel CT_COPPER_ORE = CargoLabel('CORE');
static constexpr CargoLabel CT_WATER = CargoLabel('WATR');
static constexpr CargoLabel CT_DIAMONDS = CargoLabel('DIAM');

/* Toyland */
static constexpr CargoLabel CT_SUGAR = CargoLabel('SUGR');
static constexpr CargoLabel CT_TOYS = CargoLabel('TOYS');
static constexpr CargoLabel CT_BATTERIES = CargoLabel('BATT');
static constexpr CargoLabel CT_CANDY = CargoLabel('SWET');
static constexpr CargoLabel CT_TOFFEE = CargoLabel('TOFF');
static constexpr CargoLabel CT_COLA = CargoLabel('COLA');
static constexpr CargoLabel CT_COTTON_CANDY = CargoLabel('CTCD');
static constexpr CargoLabel CT_BUBBLES = CargoLabel('BUBL');
static constexpr CargoLabel CT_PLASTIC = CargoLabel('PLST');
static constexpr CargoLabel CT_FIZZY_DRINKS = CargoLabel('FZDR');

static constexpr CargoLabel CT_NONE = CT_PASSENGERS;

static constexpr CargoLabel CT_INVALID = CargoLabel(UINT32_MAX); ///< Invalid cargo type.

static const CargoID NUM_ORIGINAL_CARGO = 12; ///< Original number of cargo types.
static const CargoID NUM_CARGO = 64; ///< Maximal number of cargo types in a game.
Expand All @@ -73,7 +78,7 @@ static const CargoID CARGO_NO_REFIT = 0xFE; ///< Do not refit cargo of a vehicle
static const CargoID INVALID_CARGO = UINT8_MAX;

/** Test whether cargo type is not CT_INVALID */
inline bool IsValidCargoType(CargoType t) { return t != CT_INVALID; }
inline bool IsValidCargoType(CargoLabel t) { return t != CT_INVALID; }
/** Test whether cargo type is not INVALID_CARGO */
inline bool IsValidCargoID(CargoID t) { return t != INVALID_CARGO; }

Expand Down
68 changes: 40 additions & 28 deletions src/cargotype.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,16 @@ void SetupCargoForClimate(LandscapeID l)

/* Copy from default cargo by label or index. */
auto insert = std::begin(CargoSpec::array);
for (const CargoLabel &cl : _default_climate_cargo[l]) {
for (const auto &cl : _default_climate_cargo[l]) {

/* Check if value is an index into the cargo table */
if (cl < lengthof(_default_cargo)) {
if (std::holds_alternative<int>(cl)) {
/* Copy the default cargo by index. */
*insert = _default_cargo[cl];
*insert = _default_cargo[std::get<int>(cl)];
} else {
/* Search for label in default cargo types and copy if found. */
auto found = std::find_if(std::begin(_default_cargo), std::end(_default_cargo), [&cl](const CargoSpec &cs) { return cs.label == cl; });
CargoLabel label = std::get<CargoLabel>(cl);
auto found = std::find_if(std::begin(_default_cargo), std::end(_default_cargo), [&label](const CargoSpec &cs) { return cs.label == label; });
if (found != std::end(_default_cargo)) {
*insert = *found;
} else {
Expand All @@ -63,12 +64,43 @@ void SetupCargoForClimate(LandscapeID l)
}
}

if (insert->IsValid()) SetBit(_cargo_mask, insert->Index());
if (insert->IsValid()) {
SetBit(_cargo_mask, insert->Index());
}
++insert;
}

/* Reset and disable remaining cargo types. */
std::fill(insert, std::end(CargoSpec::array), CargoSpec{});

BuildCargoLabelMap();
}

/**
* Build cargo label map.
* This is called multiple times during NewGRF initialization as cargos are defined, so that TranslateRefitMask() and
* GetCargoTranslation(), also used during initialization, get the correct information.
*/
void BuildCargoLabelMap()
{
CargoSpec::label_map.clear();
for (const CargoSpec &cs : CargoSpec::array) {
/* During initialization, CargoSpec can be marked valid before the label has been set. */
if (!cs.IsValid() || cs.label == CargoLabel(0)) continue;
/* Label already exists, don't addd again. */
if (CargoSpec::label_map.count(cs.label) != 0) continue;

CargoSpec::label_map.insert(std::make_pair(cs.label, cs.Index()));
}
}

bool IsDefaultCargo(CargoID cid)
{
auto cs = CargoSpec::Get(cid);
if (!cs->IsValid()) return false;

CargoLabel label = cs->label;
return std::any_of(std::begin(_default_cargo), std::end(_default_cargo), [&label](const CargoSpec &cs) { return cs.label == label; });
}

/**
Expand All @@ -84,35 +116,15 @@ Dimension GetLargestCargoIconSize()
return size;
}

/**
* Get the cargo ID of a default cargo, if present.
* @param l Landscape
* @param ct Default cargo type.
* @return ID number if the cargo exists, else #INVALID_CARGO
*/
CargoID GetDefaultCargoID(LandscapeID l, CargoType ct)
{
assert(l < lengthof(_default_climate_cargo));

if (!IsValidCargoType(ct)) return INVALID_CARGO;

assert(ct < lengthof(_default_climate_cargo[0]));
CargoLabel cl = _default_climate_cargo[l][ct];
/* Bzzt: check if cl is just an index into the cargo table */
if (cl < lengthof(_default_cargo)) {
cl = _default_cargo[cl].label;
}

return GetCargoIDByLabel(cl);
}

/**
* Get the cargo ID by cargo label.
* @param cl Cargo type to get.
* @return ID number if the cargo exists, else #INVALID_CARGO
*/
CargoID GetCargoIDByLabel(CargoLabel cl)
CargoID SearchCargoIDByLabel(CargoLabel cl)
{
if (cl == CT_INVALID) return INVALID_CARGO;

for (const CargoSpec *cs : CargoSpec::Iterate()) {
if (cs->label == cl) return cs->Index();
}
Expand Down
19 changes: 14 additions & 5 deletions src/cargotype.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@
#include "core/bitmath_func.hpp"
#include "core/span_type.hpp"

/** Globally unique label of a cargo type. */
typedef uint32_t CargoLabel;

/** Town growth effect when delivering cargo. */
enum TownAcceptanceEffect : byte {
TAE_BEGIN = 0,
Expand Down Expand Up @@ -192,17 +189,29 @@ struct CargoSpec {

private:
static CargoSpec array[NUM_CARGO]; ///< Array holding all CargoSpecs
static inline std::map<CargoLabel, CargoID> label_map{}; ///< Translation map from CargoLabel to Cargo ID.

friend void SetupCargoForClimate(LandscapeID l);
friend void BuildCargoLabelMap();
friend inline CargoID GetCargoIDByLabel(CargoLabel ct);
friend void FinaliseCargoArray();
};

extern CargoTypes _cargo_mask;
extern CargoTypes _standard_cargo_mask;

void SetupCargoForClimate(LandscapeID l);
CargoID GetCargoIDByLabel(CargoLabel cl);
void BuildCargoLabelMap();
CargoID SearchCargoIDByLabel(CargoLabel label);
CargoID GetCargoIDByBitnum(uint8_t bitnum);
CargoID GetDefaultCargoID(LandscapeID l, CargoType ct);

inline CargoID GetCargoIDByLabel(CargoLabel label)
{
auto found = CargoSpec::label_map.find(label);
if (found != std::end(CargoSpec::label_map)) return found->second;
return INVALID_CARGO;
}

Dimension GetLargestCargoIconSize();

void InitializeSortedCargoSpecs();
Expand Down
2 changes: 1 addition & 1 deletion src/console_cmds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2450,7 +2450,7 @@ static void ConDumpCargoTypes()
IConsolePrint(CC_DEFAULT, " {:02d} Bit: {:2d}, Label: {:c}{:c}{:c}{:c}, Callback mask: 0x{:02X}, Cargo class: {}{}{}{}{}{}{}{}{}{}{}, GRF: {:08X}, {}",
spec->Index(),
spec->bitnum,
spec->label >> 24, spec->label >> 16, spec->label >> 8, spec->label,
spec->label.base() >> 24, spec->label.base() >> 16, spec->label.base() >> 8, spec->label.base(),
spec->callback_mask,
(spec->classes & CC_PASSENGERS) != 0 ? 'p' : '-',
(spec->classes & CC_MAIL) != 0 ? 'm' : '-',
Expand Down
10 changes: 6 additions & 4 deletions src/engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,8 +242,10 @@ uint Engine::DetermineCapacity(const Vehicle *v, uint16_t *mail_capacity) const
if (!IsCargoInClass(cargo_type, CC_PASSENGERS)) {
extra_mail_cap = GetEngineProperty(this->index, PROP_AIRCRAFT_MAIL_CAPACITY, this->u.air.mail_capacity, v);
}
if (!new_multipliers && cargo_type == CT_MAIL) return capacity + extra_mail_cap;
default_cargo = CT_PASSENGERS; // Always use 'passengers' wrt. cargo multipliers
if (IsValidCargoID(GetCargoIDByLabel(CT_MAIL))) {
if (!new_multipliers && cargo_type == GetCargoIDByLabel(CT_MAIL)) return capacity + extra_mail_cap;
}
default_cargo = GetCargoIDByLabel(CT_PASSENGERS); // Always use 'passengers' wrt. cargo multipliers
break;

default: NOT_REACHED();
Expand All @@ -260,8 +262,8 @@ uint Engine::DetermineCapacity(const Vehicle *v, uint16_t *mail_capacity) const
uint16_t default_multiplier = new_multipliers ? 0x100 : CargoSpec::Get(default_cargo)->multiplier;
uint16_t cargo_multiplier = CargoSpec::Get(cargo_type)->multiplier;
capacity *= cargo_multiplier;
if (extra_mail_cap > 0) {
uint mail_multiplier = CargoSpec::Get(CT_MAIL)->multiplier;
if (extra_mail_cap > 0 && IsValidCargoID(GetCargoIDByLabel(CT_MAIL))) {
uint mail_multiplier = CargoSpec::Get(GetCargoIDByLabel(CT_MAIL))->multiplier;
capacity += (default_multiplier * extra_mail_cap * cargo_multiplier + mail_multiplier / 2) / mail_multiplier;
}
capacity = (capacity + default_multiplier / 2) / default_multiplier;
Expand Down
2 changes: 1 addition & 1 deletion src/engine_gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ static StringID GetAircraftEngineInfoString(const Engine *e)
SetDParam(i++, capacity);

if (mail_capacity > 0) {
SetDParam(i++, CT_MAIL);
SetDParam(i++, GetCargoIDByLabel(CT_MAIL));
SetDParam(i++, mail_capacity);
SetDParam(i++, e->GetRunningCost());
return range > 0 ? STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_RANGE_CAP_CAP_RUNCOST : STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_CAP_CAP_RUNCOST;
Expand Down
1 change: 1 addition & 0 deletions src/engine_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ struct EngineInfo {
byte load_amount;
byte climates; ///< Climates supported by the engine.
CargoID cargo_type;
CargoLabel cargo_label;
CargoTypes refit_mask;
byte refit_cost;
byte misc_flags; ///< Miscellaneous flags. @see EngineMiscFlags
Expand Down
1 change: 1 addition & 0 deletions src/house.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ struct HouseSpec {
byte mail_generation; ///< mail generation multiplier (tile based, as the acceptances below)
byte cargo_acceptance[HOUSE_NUM_ACCEPTS]; ///< acceptance level for the cargo slots
CargoID accepts_cargo[HOUSE_NUM_ACCEPTS]; ///< input cargo slots
CargoLabel accepts_cargo_label[HOUSE_NUM_ACCEPTS]; ///< input landscape cargo slots
BuildingFlags building_flags; ///< some flags that describe the house (size, stadium etc...)
HouseZones building_availability; ///< where can it be built (climates, zones)
bool enabled; ///< the house is available to build (true by default, but can be disabled by newgrf)
Expand Down

0 comments on commit a5d6e2c

Please sign in to comment.