21#include "table/strings.h"
79 GrfMsg(1,
"IndustryTilesChangeInfo: Too many industry tiles loaded ({}), max ({}). Ignoring.", last,
NUM_INDUSTRYTILES_PER_GRF);
84 if (_cur_gps.grffile->indtspec.size() < last) _cur_gps.grffile->indtspec.resize(last);
86 for (uint
id = first;
id < last; ++id) {
87 auto &tsp = _cur_gps.grffile->indtspec[id];
89 if (prop != 0x08 && tsp ==
nullptr) {
91 if (cir > ret) ret = cir;
100 GrfMsg(2,
"IndustryTilesChangeInfo: Attempt to use new industry tile {} as substitute industry tile for {}. Ignoring.", subs_id,
id);
105 if (tsp ==
nullptr) {
106 tsp = std::make_unique<IndustryTileSpec>(_industry_tile_specs[subs_id]);
116 tsp->grf_prop.local_id = id;
117 tsp->grf_prop.subst_id = subs_id;
118 tsp->grf_prop.SetGRFFile(_cur_gps.grffile);
119 _industile_mngr.AddEntityID(
id, _cur_gps.grffile->grfid, subs_id);
129 GrfMsg(2,
"IndustryTilesChangeInfo: Attempt to override new industry tile {} with industry tile id {}. Ignoring.", ovrid,
id);
133 _industile_mngr.Add(
id, _cur_gps.grffile->grfid, ovrid);
142 tsp->acceptance[prop - 0x0A] =
Clamp(
GB(acctp, 8, 8), 0, 16);
143 tsp->accepts_cargo_label[prop - 0x0A] =
CT_INVALID;
152 tsp->callback_mask =
static_cast<IndustryTileCallbackMasks
>(buf.
ReadByte());
156 tsp->animation.frames = buf.
ReadByte();
161 tsp->animation.speed = buf.
ReadByte();
165 tsp->animation.triggers =
static_cast<IndustryAnimationTriggers
>(buf.
ReadByte());
169 tsp->special_flags = IndustryTileSpecialFlags{buf.
ReadByte()};
173 uint8_t num_cargoes = buf.
ReadByte();
174 if (num_cargoes > std::size(tsp->acceptance)) {
179 for (uint i = 0; i < std::size(tsp->acceptance); i++) {
180 if (i < num_cargoes) {
183 tsp->acceptance[i] = (int8_t)buf.
ReadByte();
185 tsp->accepts_cargo[i] = INVALID_CARGO;
186 tsp->acceptance[i] = 0;
188 if (i < std::size(tsp->accepts_cargo_label)) tsp->accepts_cargo_label[i] =
CT_INVALID;
253 for (uint8_t j = 0; j < num_table; j++) {
254 for (uint k = 0;; k++) {
256 if (x == 0xFE && k == 0) {
263 if (x == 0 && y == 0x80)
break;
286 buf.Skip(num_inputs * num_outputs * 2);
308 const size_t size = layout.size();
309 if (size == 0)
return false;
311 for (
size_t i = 0; i < size - 1; i++) {
312 for (
size_t j = i + 1; j < size; j++) {
313 if (layout[i].ti.x == layout[j].ti.x &&
314 layout[i].ti.y == layout[j].ti.y) {
320 bool have_regular_tile =
false;
321 for (
const auto &tilelayout : layout) {
323 have_regular_tile =
true;
328 return have_regular_tile;
344 GrfMsg(1,
"IndustriesChangeInfo: Too many industries loaded ({}), max ({}). Ignoring.", last,
NUM_INDUSTRYTYPES_PER_GRF);
349 if (_cur_gps.grffile->industryspec.size() < last) _cur_gps.grffile->industryspec.resize(last);
351 for (uint
id = first;
id < last; ++id) {
352 auto &indsp = _cur_gps.grffile->industryspec[id];
354 if (prop != 0x08 && indsp ==
nullptr) {
356 if (cir > ret) ret = cir;
363 if (subs_id == 0xFF) {
366 _industry_specs[id].enabled =
false;
370 GrfMsg(2,
"_industry_specs: Attempt to use new industry {} as substitute industry for {}. Ignoring.", subs_id,
id);
377 if (indsp ==
nullptr) {
380 indsp->enabled =
true;
381 indsp->grf_prop.local_id = id;
382 indsp->grf_prop.subst_id = subs_id;
383 indsp->grf_prop.SetGRFFile(_cur_gps.grffile);
396 GrfMsg(2,
"IndustriesChangeInfo: Attempt to override new industry {} with industry id {}. Ignoring.", ovrid,
id);
399 indsp->grf_prop.override_id = ovrid;
400 _industry_mngr.Add(
id, _cur_gps.grffile->grfid, ovrid);
405 uint8_t new_num_layouts = buf.
ReadByte();
406 uint32_t definition_size = buf.
ReadDWord();
407 uint32_t bytes_read = 0;
408 std::vector<IndustryTileLayout> new_layouts;
411 for (uint8_t j = 0; j < new_num_layouts; j++) {
414 for (uint k = 0;; k++) {
415 if (bytes_read >= definition_size) {
416 GrfMsg(3,
"IndustriesChangeInfo: Incorrect size for industry tile layout definition for industry {}.",
id);
418 definition_size = UINT32_MAX;
426 if (it.ti.
x == 0xFE && k == 0) {
433 GrfMsg(1,
"IndustriesChangeInfo: Invalid original industry number for layout import, industry {}",
id);
438 GrfMsg(1,
"IndustriesChangeInfo: Invalid original industry layout index for layout import, industry {}",
id);
449 if (it.ti.
x == 0 && it.ti.
y == 0x80) {
458 if (it.gfx == 0xFE) {
464 int tempid = _industile_mngr.GetID(local_tile_id, _cur_gps.grffile->grfid);
467 GrfMsg(2,
"IndustriesChangeInfo: Attempt to use industry tile {} with industry id {}, not yet defined. Ignoring.", local_tile_id,
id);
473 it.ti.
x = (int8_t)
GB(it.ti.
x, 0, 8);
474 it.ti.
y = (int8_t)
GB(it.ti.
y, 0, 8);
483 if (_cur_gps.grffile->grf_version < 8 && it.ti.
x < 0) it.ti.
y += 1;
489 GrfMsg(1,
"IndustriesChangeInfo: Invalid industry layout for industry id {}. Ignoring",
id);
491 new_layouts.push_back(layout);
496 indsp->layouts = std::move(new_layouts);
501 indsp->life_type = IndustryLifeTypes{buf.
ReadByte()};
517 indsp->cost_multiplier = buf.
ReadByte();
537 indsp->production_rate[prop - 0x12] = buf.
ReadByte();
541 indsp->minimal_cargo = buf.
ReadByte();
545 uint8_t num_sounds = buf.
ReadByte();
547 std::vector<uint8_t> sounds;
548 sounds.reserve(num_sounds);
549 for (uint8_t j = 0; j < num_sounds; ++j) {
553 indsp->random_sounds = std::move(sounds);
558 for (uint8_t j = 0; j < 3; j++) indsp->conflicting[j] = buf.
ReadByte();
574 indsp->behaviour = IndustryBehaviours{buf.
ReadDWord()};
585 indsp->input_cargo_multiplier[prop - 0x1C][0] =
GB(multiples, 0, 16);
586 indsp->input_cargo_multiplier[prop - 0x1C][1] =
GB(multiples, 16, 16);
595 indsp->prospecting_chance = buf.
ReadDWord();
600 auto mask = indsp->callback_mask.base();
601 SB(mask, (prop - 0x21) * 8, 8, buf.
ReadByte());
602 indsp->callback_mask = IndustryCallbackMasks{mask};
607 indsp->removal_cost_multiplier = buf.
ReadDWord();
613 indsp->station_name = STR_NULL;
621 uint8_t num_cargoes = buf.
ReadByte();
622 if (num_cargoes > std::size(indsp->produced_cargo)) {
627 for (
size_t i = 0; i < std::size(indsp->produced_cargo); i++) {
628 if (i < num_cargoes) {
630 indsp->produced_cargo[i] = cargo;
632 indsp->produced_cargo[i] = INVALID_CARGO;
634 if (i < std::size(indsp->produced_cargo_label)) indsp->produced_cargo_label[i] =
CT_INVALID;
640 uint8_t num_cargoes = buf.
ReadByte();
641 if (num_cargoes > std::size(indsp->accepts_cargo)) {
646 for (
size_t i = 0; i < std::size(indsp->accepts_cargo); i++) {
647 if (i < num_cargoes) {
649 indsp->accepts_cargo[i] = cargo;
651 indsp->accepts_cargo[i] = INVALID_CARGO;
653 if (i < std::size(indsp->accepts_cargo_label)) indsp->accepts_cargo_label[i] =
CT_INVALID;
659 uint8_t num_cargoes = buf.
ReadByte();
660 if (num_cargoes >
lengthof(indsp->production_rate)) {
665 for (uint i = 0; i <
lengthof(indsp->production_rate); i++) {
666 if (i < num_cargoes) {
667 indsp->production_rate[i] = buf.
ReadByte();
669 indsp->production_rate[i] = 0;
676 uint8_t num_inputs = buf.
ReadByte();
677 uint8_t num_outputs = buf.
ReadByte();
678 if (num_inputs > std::size(indsp->accepts_cargo) || num_outputs > std::size(indsp->produced_cargo)) {
683 for (
size_t i = 0; i < std::size(indsp->accepts_cargo); i++) {
684 for (
size_t j = 0; j < std::size(indsp->produced_cargo); j++) {
686 if (i < num_inputs && j < num_outputs) mult = buf.
ReadWord();
687 indsp->input_cargo_multiplier[i][j] = mult;
constexpr T SB(T &x, const uint8_t s, const uint8_t n, const U d)
Set n bits in x starting at bit s to d.
static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
static constexpr CargoLabel CT_INVALID
Invalid cargo type.
uint8_t CargoType
Cargo slots to indicate a cargo type within a game.
Class to read from a NewGRF file.
uint32_t ReadDWord()
Read a single DWord (32 bits).
uint16_t ReadWord()
Read a single Word (16 bits).
uint8_t ReadByte()
Read a single byte (8 bits).
Functions related to debugging.
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23).
Accessors to map for industries.
@ GFX_WATERTILE_SPECIALCHECK
not really a tile, but rather a very special check
static const IndustryGfx NEW_INDUSTRYTILEOFFSET
original number of tiles
static const IndustryGfx INDUSTRYTILE_NOANIM
flag to mark industry tiles as having no animation
static const IndustryType NEW_INDUSTRYOFFSET
original number of industry types
static const int INDUSTRY_ORIGINAL_NUM_INPUTS
Original number of accepted cargo types.
static const IndustryGfx NUM_INDUSTRYTILES_PER_GRF
Maximum number of industry tiles per NewGRF; limited to 255 to allow extending Action3 with an extend...
static const IndustryGfx INVALID_INDUSTRYTILE
one above amount is considered invalid
static const int INDUSTRY_ORIGINAL_NUM_OUTPUTS
Original number of produced cargo types.
static const IndustryType NUM_INDUSTRYTYPES_PER_GRF
maximum number of industry types per NewGRF; limited to 128 because bit 7 has a special meaning in so...
std::vector< IndustryTileLayoutTile > IndustryTileLayout
A complete tile layout for an industry is a list of tiles.
@ CHECK_NOTHING
Always succeeds.
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
GRFError * DisableGrf(StringID message, GRFConfig *config)
Disable a GRF.
std::vector< BadgeID > ReadBadgeList(ByteReader &buf, GrfSpecFeature feature)
Read a list of badges.
void SkipBadgeList(ByteReader &buf)
Skip a list of badges.
const IndustrySpec _origin_industry_specs[NEW_INDUSTRYOFFSET]
Extern declaration for _origin_industry_specs in table/build_industry.h.
static ChangeInfoResult IgnoreIndustryProperty(int prop, ByteReader &buf)
Ignore an industry property.
static ChangeInfoResult IndustriesChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for industries.
static ChangeInfoResult IndustrytilesChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for industry tiles.
static bool ValidateIndustryLayout(const IndustryTileLayout &layout)
Validate the industry layout; e.g.
static ChangeInfoResult IgnoreIndustryTileProperty(int prop, ByteReader &buf)
Ignore an industry tile property.
AnimationStatus
Statuses of animation within NewGRFs.
NewGRF buffer reader definition.
CargoType GetCargoTranslation(uint8_t cargo, const GRFFile *grffile, bool usebit)
Translate a GRF-local cargo slot/bitnum into a CargoType.
Cargo support for NewGRFs.
Functions for NewGRF industries.
NewGRF internal processing state.
ChangeInfoResult
Possible return values for the GrfChangeInfoHandler functions.
@ CIR_INVALID_ID
Attempt to modify an invalid ID.
@ CIR_DISABLED
GRF was disabled due to error.
@ CIR_UNKNOWN
Variable is unknown.
@ CIR_UNHANDLED
Variable was parsed but unread.
@ CIR_SUCCESS
Variable was parsed and read.
void AddStringForMapping(GRFStringID source, std::function< void(StringID)> &&func)
Record a static StringID for getting translated later.
NewGRF string mapping definition.
StrongType::Typedef< uint32_t, struct GRFStringIDTag, StrongType::Compare, StrongType::Integer > GRFStringID
Type for GRF-internal string IDs.
A number of safeguards to prevent using unsafe methods.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Slope
Enumeration for the slope-type.
Definition of base types and functions in a cross-platform compatible way.
#define lengthof(array)
Return the length of an fixed size array.
Information about why GRF had problems during initialisation.
std::array< uint32_t, 2 > param_value
Values of GRF parameters to show for message and custom_message.
Defines the data structure for constructing industry.
Definition of one tile in an industry tile layout.
Colour for pixel/line drawing.
int16_t x
The x value of the coordinate.
int16_t y
The y value of the coordinate.