12#include "../newgrf_cargo.h"
13#include "../industry.h"
14#include "../industrytype.h"
15#include "../industry_map.h"
16#include "../newgrf_industries.h"
21#include "table/strings.h"
22#include "../table/build_industry.h"
24#include "../safeguards.h"
77 GrfMsg(1,
"IndustryTilesChangeInfo: Too many industry tiles loaded ({}), max ({}). Ignoring.", last,
NUM_INDUSTRYTILES_PER_GRF);
82 if (_cur.
grffile->indtspec.size() < last) _cur.
grffile->indtspec.resize(last);
84 for (uint
id = first;
id < last; ++id) {
85 auto &tsp = _cur.
grffile->indtspec[id];
87 if (prop != 0x08 && tsp ==
nullptr) {
89 if (cir > ret) ret = cir;
98 GrfMsg(2,
"IndustryTilesChangeInfo: Attempt to use new industry tile {} as substitute industry tile for {}. Ignoring.", subs_id,
id);
103 if (tsp ==
nullptr) {
104 tsp = std::make_unique<IndustryTileSpec>(_industry_tile_specs[subs_id]);
114 tsp->grf_prop.local_id = id;
115 tsp->grf_prop.subst_id = subs_id;
116 tsp->grf_prop.SetGRFFile(_cur.
grffile);
127 GrfMsg(2,
"IndustryTilesChangeInfo: Attempt to override new industry tile {} with industry tile id {}. Ignoring.", ovrid,
id);
131 _industile_mngr.
Add(
id, _cur.
grffile->grfid, ovrid);
140 tsp->acceptance[prop - 0x0A] =
Clamp(
GB(acctp, 8, 8), 0, 16);
141 tsp->accepts_cargo_label[prop - 0x0A] =
CT_INVALID;
154 tsp->animation.frames = buf.
ReadByte();
155 tsp->animation.status = buf.
ReadByte();
159 tsp->animation.speed = buf.
ReadByte();
163 tsp->animation.triggers = buf.
ReadByte();
171 uint8_t num_cargoes = buf.
ReadByte();
172 if (num_cargoes > std::size(tsp->acceptance)) {
177 for (uint i = 0; i < std::size(tsp->acceptance); i++) {
178 if (i < num_cargoes) {
181 tsp->acceptance[i] = (int8_t)buf.
ReadByte();
183 tsp->accepts_cargo[i] = INVALID_CARGO;
184 tsp->acceptance[i] = 0;
186 if (i < std::size(tsp->accepts_cargo_label)) tsp->accepts_cargo_label[i] =
CT_INVALID;
251 for (uint8_t j = 0; j < num_table; j++) {
252 for (uint k = 0;; k++) {
254 if (x == 0xFE && k == 0) {
261 if (x == 0 && y == 0x80)
break;
284 buf.Skip(num_inputs * num_outputs * 2);
306 const size_t size = layout.size();
307 if (size == 0)
return false;
309 for (
size_t i = 0; i < size - 1; i++) {
310 for (
size_t j = i + 1; j < size; j++) {
311 if (layout[i].ti.x == layout[j].ti.x &&
312 layout[i].ti.y == layout[j].ti.y) {
318 bool have_regular_tile =
false;
319 for (
const auto &tilelayout : layout) {
321 have_regular_tile =
true;
326 return have_regular_tile;
342 GrfMsg(1,
"IndustriesChangeInfo: Too many industries loaded ({}), max ({}). Ignoring.", last,
NUM_INDUSTRYTYPES_PER_GRF);
347 if (_cur.
grffile->industryspec.size() < last) _cur.
grffile->industryspec.resize(last);
349 for (uint
id = first;
id < last; ++id) {
350 auto &indsp = _cur.
grffile->industryspec[id];
352 if (prop != 0x08 && indsp ==
nullptr) {
354 if (cir > ret) ret = cir;
361 if (subs_id == 0xFF) {
364 _industry_specs[id].
enabled =
false;
368 GrfMsg(2,
"_industry_specs: Attempt to use new industry {} as substitute industry for {}. Ignoring.", subs_id,
id);
375 if (indsp ==
nullptr) {
376 indsp = std::make_unique<IndustrySpec>(_origin_industry_specs[subs_id]);
378 indsp->enabled =
true;
379 indsp->grf_prop.local_id = id;
380 indsp->grf_prop.subst_id = subs_id;
381 indsp->grf_prop.SetGRFFile(_cur.
grffile);
394 GrfMsg(2,
"IndustriesChangeInfo: Attempt to override new industry {} with industry id {}. Ignoring.", ovrid,
id);
397 indsp->grf_prop.override = ovrid;
398 _industry_mngr.
Add(
id, _cur.
grffile->grfid, ovrid);
403 uint8_t new_num_layouts = buf.
ReadByte();
404 uint32_t definition_size = buf.
ReadDWord();
405 uint32_t bytes_read = 0;
406 std::vector<IndustryTileLayout> new_layouts;
409 for (uint8_t j = 0; j < new_num_layouts; j++) {
412 for (uint k = 0;; k++) {
413 if (bytes_read >= definition_size) {
414 GrfMsg(3,
"IndustriesChangeInfo: Incorrect size for industry tile layout definition for industry {}.",
id);
416 definition_size = UINT32_MAX;
424 if (it.ti.
x == 0xFE && k == 0) {
430 if (type >=
lengthof(_origin_industry_specs)) {
431 GrfMsg(1,
"IndustriesChangeInfo: Invalid original industry number for layout import, industry {}",
id);
435 if (laynbr >= _origin_industry_specs[type].layouts.size()) {
436 GrfMsg(1,
"IndustriesChangeInfo: Invalid original industry layout index for layout import, industry {}",
id);
440 layout = _origin_industry_specs[type].layouts[laynbr];
447 if (it.ti.
x == 0 && it.ti.
y == 0x80) {
456 if (it.gfx == 0xFE) {
462 int tempid = _industile_mngr.
GetID(local_tile_id, _cur.
grffile->grfid);
465 GrfMsg(2,
"IndustriesChangeInfo: Attempt to use industry tile {} with industry id {}, not yet defined. Ignoring.", local_tile_id,
id);
471 it.ti.
x = (int8_t)
GB(it.ti.
x, 0, 8);
472 it.ti.
y = (int8_t)
GB(it.ti.
y, 0, 8);
481 if (_cur.
grffile->grf_version < 8 && it.ti.
x < 0) it.ti.
y += 1;
487 GrfMsg(1,
"IndustriesChangeInfo: Invalid industry layout for industry id {}. Ignoring",
id);
489 new_layouts.push_back(layout);
494 indsp->layouts = std::move(new_layouts);
515 indsp->cost_multiplier = buf.
ReadByte();
535 indsp->production_rate[prop - 0x12] = buf.
ReadByte();
539 indsp->minimal_cargo = buf.
ReadByte();
543 uint8_t num_sounds = buf.
ReadByte();
545 std::vector<uint8_t> sounds;
546 sounds.reserve(num_sounds);
547 for (uint8_t j = 0; j < num_sounds; ++j) {
551 indsp->random_sounds = std::move(sounds);
556 for (uint8_t j = 0; j < 3; j++) indsp->conflicting[j] = buf.
ReadByte();
583 indsp->input_cargo_multiplier[prop - 0x1C][0] =
GB(multiples, 0, 16);
584 indsp->input_cargo_multiplier[prop - 0x1C][1] =
GB(multiples, 16, 16);
593 indsp->prospecting_chance = buf.
ReadDWord();
598 auto mask = indsp->callback_mask.base();
599 SB(mask, (prop - 0x21) * 8, 8, buf.
ReadByte());
605 indsp->removal_cost_multiplier = buf.
ReadDWord();
611 indsp->station_name = STR_NULL;
619 uint8_t num_cargoes = buf.
ReadByte();
620 if (num_cargoes > std::size(indsp->produced_cargo)) {
625 for (
size_t i = 0; i < std::size(indsp->produced_cargo); i++) {
626 if (i < num_cargoes) {
628 indsp->produced_cargo[i] = cargo;
630 indsp->produced_cargo[i] = INVALID_CARGO;
632 if (i < std::size(indsp->produced_cargo_label)) indsp->produced_cargo_label[i] =
CT_INVALID;
638 uint8_t num_cargoes = buf.
ReadByte();
639 if (num_cargoes > std::size(indsp->accepts_cargo)) {
644 for (
size_t i = 0; i < std::size(indsp->accepts_cargo); i++) {
645 if (i < num_cargoes) {
647 indsp->accepts_cargo[i] = cargo;
649 indsp->accepts_cargo[i] = INVALID_CARGO;
651 if (i < std::size(indsp->accepts_cargo_label)) indsp->accepts_cargo_label[i] =
CT_INVALID;
657 uint8_t num_cargoes = buf.
ReadByte();
658 if (num_cargoes >
lengthof(indsp->production_rate)) {
663 for (uint i = 0; i <
lengthof(indsp->production_rate); i++) {
664 if (i < num_cargoes) {
665 indsp->production_rate[i] = buf.
ReadByte();
667 indsp->production_rate[i] = 0;
674 uint8_t num_inputs = buf.
ReadByte();
675 uint8_t num_outputs = buf.
ReadByte();
676 if (num_inputs > std::size(indsp->accepts_cargo) || num_outputs > std::size(indsp->produced_cargo)) {
681 for (
size_t i = 0; i < std::size(indsp->accepts_cargo); i++) {
682 for (
size_t j = 0; j < std::size(indsp->produced_cargo); j++) {
684 if (i < num_inputs && j < num_outputs) mult = buf.
ReadWord();
685 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.
debug_inline 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).
virtual uint16_t GetID(uint16_t grf_local_id, uint32_t grfid) const
Return the ID (if ever available) of a previously inserted entity.
void Add(uint16_t local_id, uint32_t grfid, uint entity_type)
Since the entity IDs defined by the GRF file does not necessarily correlate to those used by the game...
virtual uint16_t AddEntityID(uint16_t grf_local_id, uint32_t grfid, uint16_t substitute_id)
Reserves a place in the mapping array for an entity to be installed.
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23)
@ 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.
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.
NewGRF buffer reader definition.
CargoType GetCargoTranslation(uint8_t cargo, const GRFFile *grffile, bool usebit)
Translate a GRF-local cargo slot/bitnum into a CargoType.
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.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Slope
Enumeration for the slope-type.
#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.
LandscapeType landscape
the landscape we're currently in
GameCreationSettings game_creation
settings used during the creation of a game (map)
GRFFile * grffile
Currently processed GRF file.
bool enabled
entity still available (by default true).newgrf can disable it, though
Definition of one tile in an industry tile layout.
int16_t x
The x value of the coordinate.
int16_t y
The y value of the coordinate.