OpenTTD Source: src/newgrf/newgrf_act4.cpp Source File

OpenTTD Source 15.3

newgrf_act4.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
10#include "../stdafx.h"
11#include "../debug.h"
12#include "../engine_base.h"
13#include "../house.h"
14#include "../newgrf_engine.h"
15#include "../newgrf_text.h"
16#include "../newgrf_badge.h"
17#include "../newgrf_badge_type.h"
18#include "../newgrf_cargo.h"
19#include "../newgrf_station.h"
20#include "../newgrf_airporttiles.h"
21#include "../string_func.h"
22#include "newgrf_bytereader.h"
23#include "newgrf_internal_vehicle.h"
24#include "newgrf_internal.h"
25
26#include "table/strings.h"
27
28#include "../safeguards.h"
29
30/* Action 0x04 */
31static void FeatureNewName(ByteReader &buf)
32{
33 /* <04> <veh-type> <language-id> <num-veh> <offset> <data...>
34 *
35 * B veh-type see action 0 (as 00..07, + 0A
36 * But IF veh-type = 48, then generic text
37 * B language-id If bit 6 is set, This is the extended language scheme,
38 * with up to 64 language.
39 * Otherwise, it is a mapping where set bits have meaning
40 * 0 = american, 1 = english, 2 = german, 3 = french, 4 = spanish
41 * Bit 7 set means this is a generic text, not a vehicle one (or else)
42 * B num-veh number of vehicles which are getting a new name
43 * B/W offset number of the first vehicle that gets a new name
44 * Byte : ID of vehicle to change
45 * Word : ID of string to change/add
46 * S data new texts, each of them zero-terminated, after
47 * which the next name begins. */
48
49 bool new_scheme = _cur_gps.grffile->grf_version >= 7;
50
51 GrfSpecFeature feature{buf.ReadByte()};
52 if (feature >= GSF_END && feature != GSF_ORIGINAL_STRINGS) {
53 GrfMsg(1, "FeatureNewName: Unsupported feature 0x{:02X}, skipping", feature);
54 return;
55 }
56
57 uint8_t lang = buf.ReadByte();
58 uint8_t num = buf.ReadByte();
59 bool generic = HasBit(lang, 7);
60 uint16_t id;
61 if (generic) {
62 id = buf.ReadWord();
63 } else if (feature <= GSF_AIRCRAFT || feature == GSF_BADGES) {
64 id = buf.ReadExtendedByte();
65 } else {
66 id = buf.ReadByte();
67 }
68
69 ClrBit(lang, 7);
70
71 uint16_t endid = id + num;
72
73 GrfMsg(6, "FeatureNewName: About to rename engines {}..{} (feature 0x{:02X}) in language 0x{:02X}",
74 id, endid, feature, lang);
75
76 /* Feature overlay to make non-generic strings unique in their feature. We use feature + 1 so that generic strings stay as they are. */
77 uint32_t feature_overlay = generic ? 0 : ((feature + 1) << 16);
78
79 for (; id < endid && buf.HasData(); id++) {
80 std::string_view name = buf.ReadString();
81 GrfMsg(8, "FeatureNewName: 0x{:04X} <- {}", id, StrMakeValid(name));
82
83 switch (feature) {
84 case GSF_TRAINS:
85 case GSF_ROADVEHICLES:
86 case GSF_SHIPS:
87 case GSF_AIRCRAFT:
88 if (!generic) {
89 Engine *e = GetNewEngine(_cur_gps.grffile, (VehicleType)feature, id, _cur_gps.grfconfig->flags.Test(GRFConfigFlag::Static));
90 if (e == nullptr) break;
91 StringID string = AddGRFString(_cur_gps.grffile->grfid, GRFStringID{feature_overlay | e->index.base()}, lang, new_scheme, false, name, e->info.string_id);
92 e->info.string_id = string;
93 } else {
94 AddGRFString(_cur_gps.grffile->grfid, GRFStringID{id}, lang, new_scheme, true, name, STR_UNDEFINED);
95 }
96 break;
97
98 case GSF_BADGES: {
99 if (!generic) {
100 auto found = _cur_gps.grffile->badge_map.find(id);
101 if (found == std::end(_cur_gps.grffile->badge_map)) {
102 GrfMsg(1, "FeatureNewName: Attempt to name undefined badge 0x{:X}, ignoring", id);
103 } else {
104 Badge &badge = *GetBadge(found->second);
105 badge.name = AddGRFString(_cur_gps.grffile->grfid, GRFStringID{feature_overlay | id}, lang, true, false, name, STR_UNDEFINED);
106 }
107 } else {
108 AddGRFString(_cur_gps.grffile->grfid, GRFStringID{id}, lang, new_scheme, true, name, STR_UNDEFINED);
109 }
110 break;
111 }
112
113 default:
114 if (IsInsideMM(id, 0xD000, 0xD400) || IsInsideMM(id, 0xD800, 0x10000)) {
115 AddGRFString(_cur_gps.grffile->grfid, GRFStringID{id}, lang, new_scheme, true, name, STR_UNDEFINED);
116 break;
117 }
118
119 switch (GB(id, 8, 8)) {
120 case 0xC4: // Station class name
121 if (GB(id, 0, 8) >= _cur_gps.grffile->stations.size() || _cur_gps.grffile->stations[GB(id, 0, 8)] == nullptr) {
122 GrfMsg(1, "FeatureNewName: Attempt to name undefined station 0x{:X}, ignoring", GB(id, 0, 8));
123 } else {
124 StationClassID class_index = _cur_gps.grffile->stations[GB(id, 0, 8)]->class_index;
125 StationClass::Get(class_index)->name = AddGRFString(_cur_gps.grffile->grfid, GRFStringID{id}, lang, new_scheme, false, name, STR_UNDEFINED);
126 }
127 break;
128
129 case 0xC5: // Station name
130 if (GB(id, 0, 8) >= _cur_gps.grffile->stations.size() || _cur_gps.grffile->stations[GB(id, 0, 8)] == nullptr) {
131 GrfMsg(1, "FeatureNewName: Attempt to name undefined station 0x{:X}, ignoring", GB(id, 0, 8));
132 } else {
133 _cur_gps.grffile->stations[GB(id, 0, 8)]->name = AddGRFString(_cur_gps.grffile->grfid, GRFStringID{id}, lang, new_scheme, false, name, STR_UNDEFINED);
134 }
135 break;
136
137 case 0xC7: // Airporttile name
138 if (GB(id, 0, 8) >= _cur_gps.grffile->airtspec.size() || _cur_gps.grffile->airtspec[GB(id, 0, 8)] == nullptr) {
139 GrfMsg(1, "FeatureNewName: Attempt to name undefined airport tile 0x{:X}, ignoring", GB(id, 0, 8));
140 } else {
141 _cur_gps.grffile->airtspec[GB(id, 0, 8)]->name = AddGRFString(_cur_gps.grffile->grfid, GRFStringID{id}, lang, new_scheme, false, name, STR_UNDEFINED);
142 }
143 break;
144
145 case 0xC9: // House name
146 if (GB(id, 0, 8) >= _cur_gps.grffile->housespec.size() || _cur_gps.grffile->housespec[GB(id, 0, 8)] == nullptr) {
147 GrfMsg(1, "FeatureNewName: Attempt to name undefined house 0x{:X}, ignoring.", GB(id, 0, 8));
148 } else {
149 _cur_gps.grffile->housespec[GB(id, 0, 8)]->building_name = AddGRFString(_cur_gps.grffile->grfid, GRFStringID{id}, lang, new_scheme, false, name, STR_UNDEFINED);
150 }
151 break;
152
153 default:
154 GrfMsg(7, "FeatureNewName: Unsupported ID (0x{:04X})", id);
155 break;
156 }
157 break;
158 }
159 }
160}
161
162template <> void GrfActionHandler<0x04>::FileScan(ByteReader &) { }
163template <> void GrfActionHandler<0x04>::SafetyScan(ByteReader &) { }
164template <> void GrfActionHandler<0x04>::LabelScan(ByteReader &) { }
165template <> void GrfActionHandler<0x04>::Init(ByteReader &) { }
166template <> void GrfActionHandler<0x04>::Reserve(ByteReader &) { }
167template <> void GrfActionHandler<0x04>::Activation(ByteReader &buf) { FeatureNewName(buf); }
GB
static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
Definition bitmath_func.hpp:32
HasBit
constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
Definition bitmath_func.hpp:103
ClrBit
constexpr T ClrBit(T &x, const uint8_t y)
Clears a bit in a variable.
Definition bitmath_func.hpp:139
Badge
Definition newgrf_badge.h:20
Badge::name
StringID name
Short name.
Definition newgrf_badge.h:26
BaseBitSet::Test
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
Definition base_bitset_type.hpp:141
ByteReader
Class to read from a NewGRF file.
Definition newgrf_bytereader.h:18
ByteReader::ReadWord
uint16_t ReadWord()
Read a single Word (16 bits).
Definition newgrf_bytereader.h:45
ByteReader::ReadString
std::string_view ReadString()
Read a NUL-terminated string.
Definition newgrf_bytereader.h:91
ByteReader::ReadExtendedByte
uint16_t ReadExtendedByte()
Read a single Extended Byte (8 or 16 bits).
Definition newgrf_bytereader.h:56
ByteReader::ReadByte
uint8_t ReadByte()
Read a single byte (8 bits).
Definition newgrf_bytereader.h:34
Engine
Definition engine_base.h:38
NewGRFClass::name
StringID name
Name of this class.
Definition newgrf_class.h:49
NewGRFClass::Get
static NewGRFClass * Get(Tindex class_index)
Get a particular class.
Definition newgrf_class_func.h:82
IsInsideMM
constexpr bool IsInsideMM(const size_t x, const size_t min, const size_t max) noexcept
Checks if a value is in an interval.
Definition math_func.hpp:267
GetNewEngine
Engine * GetNewEngine(const GRFFile *file, VehicleType type, uint16_t internal_id, bool static_access)
Returns the engine associated to a certain internal_id, resp.
Definition newgrf.cpp:214
GrfSpecFeature
GrfSpecFeature
Definition newgrf.h:68
GetBadge
Badge * GetBadge(BadgeID index)
Get a badge if it exists.
Definition newgrf_badge.cpp:113
newgrf_bytereader.h
NewGRF buffer reader definition.
Static
@ Static
GRF file is used statically (can be used in any MP game)
Definition newgrf_config.h:23
newgrf_internal.h
NewGRF internal processing state.
newgrf_internal_vehicle.h
NewGRF internal processing state for vehicles.
StationClassID
StationClassID
Definition newgrf_station.h:103
AddGRFString
StringID AddGRFString(uint32_t grfid, GRFStringID stringid, uint8_t langid_to_add, bool new_scheme, bool allow_newlines, std::string_view text_to_add, StringID def_string)
Add the new read string into our structure.
Definition newgrf_text.cpp:536
StrMakeValid
static void StrMakeValid(Builder &builder, StringConsumer &consumer, StringValidationSettings settings)
Copies the valid (UTF-8) characters from consumer to the builder.
Definition string.cpp:119
StringID
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
Definition strings_type.h:19
EngineInfo::string_id
StringID string_id
Default name of engine.
Definition engine_type.h:213
GRFConfig::flags
GRFConfigFlags flags
NOSAVE: GCF_Flags, bitset.
Definition newgrf_config.h:178
GrfActionHandler
GRF action handler.
Definition newgrf_internal.h:37
GrfProcessingState::grffile
GRFFile * grffile
Currently processed GRF file.
Definition newgrf_internal.h:67
GrfProcessingState::grfconfig
GRFConfig * grfconfig
Config of the currently processed GRF file.
Definition newgrf_internal.h:68
StrongType::Typedef< uint32_t, struct GRFStringIDTag, StrongType::Compare, StrongType::Integer >
VehicleType
VehicleType
Available vehicle types.
Definition vehicle_type.h:22