Merge branch 'master' into jgrpp-beta

# Conflicts:
#	.github/workflows/commit-checker.yml
#	src/company_cmd.cpp
#	src/console_cmds.cpp
#	src/crashlog.cpp
#	src/lang/english.txt
#	src/lang/german.txt
#	src/lang/indonesian.txt
#	src/lang/japanese.txt
#	src/lang/korean.txt
#	src/lang/swedish.txt
#	src/linkgraph/linkgraphjob.cpp
#	src/linkgraph/mcf.cpp
#	src/network/core/tcp.cpp
#	src/network/core/tcp.h
#	src/network/core/tcp_game.h
#	src/network/core/udp.h
#	src/network/network.cpp
#	src/network/network_admin.cpp
#	src/network/network_admin.h
#	src/network/network_chat_gui.cpp
#	src/network/network_client.cpp
#	src/network/network_client.h
#	src/network/network_func.h
#	src/network/network_internal.h
#	src/network/network_server.cpp
#	src/network/network_server.h
#	src/newgrf.cpp
#	src/newgrf_station.cpp
#	src/order_gui.cpp
#	src/rail_cmd.cpp
#	src/saveload/saveload.cpp
#	src/settings.cpp
#	src/settings_gui.cpp
#	src/settings_internal.h
#	src/settings_type.h
#	src/station_cmd.cpp
#	src/stdafx.h
#	src/table/currency_settings.ini
#	src/table/misc_settings.ini
#	src/table/settings.h.preamble
#	src/table/settings.ini
#	src/terraform_cmd.cpp
#	src/timetable_gui.cpp
#	src/train_cmd.cpp
#	src/tree_cmd.cpp
#	src/water_cmd.cpp
This commit is contained in:
Jonathan G Rennison
2021-09-27 22:47:13 +01:00
204 changed files with 1829 additions and 1549 deletions

View File

@@ -2667,6 +2667,22 @@ static ChangeInfoResult LoadTranslationTable(uint gvid, int numinfo, ByteReader
return CIR_SUCCESS;
}
/**
* Helper to read a DWord worth of bytes from the reader
* and to return it as a valid string.
* @param reader The source of the DWord.
* @return The read DWord as string.
*/
static std::string ReadDWordAsString(ByteReader *reader)
{
char output[5];
for (int i = 0; i < 4; i++) output[i] = reader->ReadByte();
output[4] = '\0';
str_validate(output, lastof(output));
return std::string(output);
}
/**
* Define properties for global variables
* @param gvid ID of the global variable.
@@ -2754,11 +2770,10 @@ static ChangeInfoResult GlobalVarChangeInfo(uint gvid, int numinfo, int prop, co
case 0x0D: { // Currency prefix symbol
uint curidx = GetNewgrfCurrencyIdConverted(gvid + i);
uint32 tempfix = buf->ReadDWord();
std::string prefix = ReadDWordAsString(buf);
if (curidx < CURRENCY_END) {
memcpy(_currency_specs[curidx].prefix, &tempfix, 4);
_currency_specs[curidx].prefix[4] = 0;
_currency_specs[curidx].prefix = prefix;
} else {
grfmsg(1, "GlobalVarChangeInfo: Currency symbol %d out of range, ignoring", curidx);
}
@@ -2767,11 +2782,10 @@ static ChangeInfoResult GlobalVarChangeInfo(uint gvid, int numinfo, int prop, co
case 0x0E: { // Currency suffix symbol
uint curidx = GetNewgrfCurrencyIdConverted(gvid + i);
uint32 tempfix = buf->ReadDWord();
std::string suffix = ReadDWordAsString(buf);
if (curidx < CURRENCY_END) {
memcpy(&_currency_specs[curidx].suffix, &tempfix, 4);
_currency_specs[curidx].suffix[4] = 0;
_currency_specs[curidx].suffix = suffix;
} else {
grfmsg(1, "GlobalVarChangeInfo: Currency symbol %d out of range, ignoring", curidx);
}
@@ -3268,7 +3282,7 @@ static ChangeInfoResult IndustrytilesChangeInfo(uint indtid, int numinfo, int pr
/* A copied tile should not have the animation infos copied too.
* The anim_state should be left untouched, though
* It is up to the author to animate them himself */
* It is up to the author to animate them */
tsp->anim_production = INDUSTRYTILE_NOANIM;
tsp->anim_next = INDUSTRYTILE_NOANIM;
@@ -4960,6 +4974,7 @@ static void FeatureChangeInfo(ByteReader *buf)
/* GSF_ROADTYPES */ RoadTypeChangeInfo,
/* GSF_TRAMTYPES */ TramTypeChangeInfo,
};
static_assert(GSF_END == lengthof(handler));
static_assert(lengthof(handler) == lengthof(_cur.grffile->action0_property_remaps), "Action 0 feature list length mismatch");
uint8 feature = buf->ReadByte();
@@ -4975,7 +4990,7 @@ static void FeatureChangeInfo(ByteReader *buf)
grfmsg(6, "FeatureChangeInfo: Feature 0x%02X, %d properties, to apply to %d+%d",
feature, numprops, engine, numinfo);
if (feature >= lengthof(handler) || handler[feature] == nullptr) {
if (handler[feature] == nullptr) {
if (feature != GSF_CARGOES) grfmsg(1, "FeatureChangeInfo: Unsupported feature 0x%02X, skipping", feature);
return;
}
@@ -8036,9 +8051,7 @@ static void TranslateGRFStrings(ByteReader *buf)
* and disable this file. */
GRFError *error = DisableGrf(STR_NEWGRF_ERROR_LOAD_AFTER);
char tmp[256];
GetString(tmp, STR_NEWGRF_ERROR_AFTER_TRANSLATED_FILE, lastof(tmp));
error->data = tmp;
error->data = GetString(STR_NEWGRF_ERROR_AFTER_TRANSLATED_FILE);
return;
}
@@ -9481,59 +9494,116 @@ GRFFile::~GRFFile()
}
/**
* List of what cargo labels are refittable for the given the vehicle-type.
* Only currently active labels are applied.
*/
static const CargoLabel _default_refitmasks_rail[] = {
'PASS', 'COAL', 'MAIL', 'LVST', 'GOOD', 'GRAI', 'WHEA', 'MAIZ', 'WOOD',
'IORE', 'STEL', 'VALU', 'GOLD', 'DIAM', 'PAPR', 'FOOD', 'FRUT', 'CORE',
'WATR', 'SUGR', 'TOYS', 'BATT', 'SWET', 'TOFF', 'COLA', 'CTCD', 'BUBL',
'PLST', 'FZDR',
0 };
static const CargoLabel _default_refitmasks_road[] = {
0 };
static const CargoLabel _default_refitmasks_ships[] = {
'COAL', 'MAIL', 'LVST', 'GOOD', 'GRAI', 'WHEA', 'MAIZ', 'WOOD', 'IORE',
'STEL', 'VALU', 'GOLD', 'DIAM', 'PAPR', 'FOOD', 'FRUT', 'CORE', 'WATR',
'RUBR', 'SUGR', 'TOYS', 'BATT', 'SWET', 'TOFF', 'COLA', 'CTCD', 'BUBL',
'PLST', 'FZDR',
0 };
static const CargoLabel _default_refitmasks_aircraft[] = {
'PASS', 'MAIL', 'GOOD', 'VALU', 'GOLD', 'DIAM', 'FOOD', 'FRUT', 'SUGR',
'TOYS', 'BATT', 'SWET', 'TOFF', 'COLA', 'CTCD', 'BUBL', 'PLST', 'FZDR',
0 };
static const CargoLabel * const _default_refitmasks[] = {
_default_refitmasks_rail,
_default_refitmasks_road,
_default_refitmasks_ships,
_default_refitmasks_aircraft,
};
/**
* Precalculate refit masks from cargo classes for all vehicles.
*/
static void CalculateRefitMasks()
{
CargoTypes original_known_cargoes = 0;
for (int ct = 0; ct != NUM_ORIGINAL_CARGO; ++ct) {
CargoID cid = GetDefaultCargoID(_settings_game.game_creation.landscape, static_cast<CargoType>(ct));
if (cid != CT_INVALID) SetBit(original_known_cargoes, cid);
}
for (Engine *e : Engine::Iterate()) {
EngineID engine = e->index;
EngineInfo *ei = &e->info;
bool only_defaultcargo; ///< Set if the vehicle shall carry only the default cargo
/* Did the newgrf specify any refitting? If not, use defaults. */
if (_gted[engine].refittability != GRFTempEngineData::UNSET) {
/* If the NewGRF did not set any cargo properties, we apply default values. */
if (_gted[engine].defaultcargo_grf == nullptr) {
/* If the vehicle has any capacity, apply the default refit masks */
if (e->type != VEH_TRAIN || e->u.rail.capacity != 0) {
static constexpr byte T = 1 << LT_TEMPERATE;
static constexpr byte A = 1 << LT_ARCTIC;
static constexpr byte S = 1 << LT_TROPIC;
static constexpr byte Y = 1 << LT_TOYLAND;
static const struct DefaultRefitMasks {
byte climate;
CargoType cargo_type;
CargoTypes cargo_allowed;
CargoTypes cargo_disallowed;
} _default_refit_masks[] = {
{T | A | S | Y, CT_PASSENGERS, CC_PASSENGERS, 0},
{T | A | S , CT_MAIL, CC_MAIL, 0},
{T | A | S , CT_VALUABLES, CC_ARMOURED, CC_LIQUID},
{ Y, CT_MAIL, CC_MAIL | CC_ARMOURED, CC_LIQUID},
{T | A , CT_COAL, CC_BULK, 0},
{ S , CT_COPPER_ORE, CC_BULK, 0},
{ Y, CT_SUGAR, CC_BULK, 0},
{T | A | S , CT_OIL, CC_LIQUID, 0},
{ Y, CT_COLA, CC_LIQUID, 0},
{T , CT_GOODS, CC_PIECE_GOODS | CC_EXPRESS, CC_LIQUID | CC_PASSENGERS},
{ A | S , CT_GOODS, CC_PIECE_GOODS | CC_EXPRESS, CC_LIQUID | CC_PASSENGERS | CC_REFRIGERATED},
{ A | S , CT_FOOD, CC_REFRIGERATED, 0},
{ Y, CT_CANDY, CC_PIECE_GOODS | CC_EXPRESS, CC_LIQUID | CC_PASSENGERS},
};
if (e->type == VEH_AIRCRAFT) {
/* Aircraft default to "light" cargoes */
_gted[engine].cargo_allowed = CC_PASSENGERS | CC_MAIL | CC_ARMOURED | CC_EXPRESS;
_gted[engine].cargo_disallowed = CC_LIQUID;
} else if (e->type == VEH_SHIP) {
switch (ei->cargo_type) {
case CT_PASSENGERS:
/* Ferries */
_gted[engine].cargo_allowed = CC_PASSENGERS;
_gted[engine].cargo_disallowed = 0;
break;
case CT_OIL:
/* Tankers */
_gted[engine].cargo_allowed = CC_LIQUID;
_gted[engine].cargo_disallowed = 0;
break;
default:
/* Cargo ships */
if (_settings_game.game_creation.landscape == LT_TOYLAND) {
/* No tanker in toyland :( */
_gted[engine].cargo_allowed = CC_MAIL | CC_ARMOURED | CC_EXPRESS | CC_BULK | CC_PIECE_GOODS | CC_LIQUID;
_gted[engine].cargo_disallowed = CC_PASSENGERS;
} else {
_gted[engine].cargo_allowed = CC_MAIL | CC_ARMOURED | CC_EXPRESS | CC_BULK | CC_PIECE_GOODS;
_gted[engine].cargo_disallowed = CC_LIQUID | CC_PASSENGERS;
}
break;
}
e->u.ship.old_refittable = true;
} else if (e->type == VEH_TRAIN && e->u.rail.railveh_type != RAILVEH_WAGON) {
/* Train engines default to all cargoes, so you can build single-cargo consists with fast engines.
* Trains loading multiple cargoes may start stations accepting unwanted cargoes. */
_gted[engine].cargo_allowed = CC_PASSENGERS | CC_MAIL | CC_ARMOURED | CC_EXPRESS | CC_BULK | CC_PIECE_GOODS | CC_LIQUID;
_gted[engine].cargo_disallowed = 0;
} else {
/* Train wagons and road vehicles are classified by their default cargo type */
for (const auto &drm : _default_refit_masks) {
if (!HasBit(drm.climate, _settings_game.game_creation.landscape)) continue;
if (drm.cargo_type != ei->cargo_type) continue;
_gted[engine].cargo_allowed = drm.cargo_allowed;
_gted[engine].cargo_disallowed = drm.cargo_disallowed;
break;
}
/* All original cargoes have specialised vehicles, so exclude them */
_gted[engine].ctt_exclude_mask = original_known_cargoes;
}
}
_gted[engine].UpdateRefittability(_gted[engine].cargo_allowed != 0);
/* Translate cargo_type using the original climate-specific cargo table. */
ei->cargo_type = GetDefaultCargoID(_settings_game.game_creation.landscape, static_cast<CargoType>(ei->cargo_type));
if (ei->cargo_type != CT_INVALID) ClrBit(_gted[engine].ctt_exclude_mask, ei->cargo_type);
}
/* Compute refittability */
{
CargoTypes mask = 0;
CargoTypes not_mask = 0;
CargoTypes xor_mask = ei->refit_mask;
/* If the original masks set by the grf are zero, the vehicle shall only carry the default cargo.
* Note: After applying the translations, the vehicle may end up carrying no defined cargo. It becomes unavailable in that case. */
only_defaultcargo = _gted[engine].refittability == GRFTempEngineData::EMPTY;
only_defaultcargo = _gted[engine].refittability != GRFTempEngineData::NONEMPTY;
if (_gted[engine].cargo_allowed != 0) {
/* Build up the list of cargo types from the set cargo classes. */
@@ -9548,26 +9618,6 @@ static void CalculateRefitMasks()
/* Apply explicit refit includes/excludes. */
ei->refit_mask |= _gted[engine].ctt_include_mask;
ei->refit_mask &= ~_gted[engine].ctt_exclude_mask;
} else {
CargoTypes xor_mask = 0;
/* Don't apply default refit mask to wagons nor engines with no capacity */
if (e->type != VEH_TRAIN || (e->u.rail.capacity != 0 && e->u.rail.railveh_type != RAILVEH_WAGON)) {
const CargoLabel *cl = _default_refitmasks[e->type];
for (uint i = 0;; i++) {
if (cl[i] == 0) break;
CargoID cargo = GetCargoIDByLabel(cl[i]);
if (cargo == CT_INVALID) continue;
SetBit(xor_mask, cargo);
}
}
ei->refit_mask = xor_mask & _cargo_mask;
/* If the mask is zero, the vehicle shall only carry the default cargo */
only_defaultcargo = (ei->refit_mask == 0);
}
/* Clear invalid cargoslots (from default vehicles or pre-NewCargo GRFs) */