OpenTTD Source 20260206-master-g4d4e37dbf1
newgrf_stringmapping.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
9
10#include "../stdafx.h"
11#include "../debug.h"
12#include "../newgrf.h"
13#include "../newgrf_text.h"
14#include "../newgrf_text_type.h"
15#include "../strings_type.h"
16#include "newgrf_internal.h"
18
19#include "table/strings.h"
20
21#include "../safeguards.h"
22
26struct StringIDMapping {
27 uint32_t grfid;
29 std::function<void(StringID)> func;
30
31 StringIDMapping(uint32_t grfid, GRFStringID source, std::function<void(StringID)> &&func) : grfid(grfid), source(source), func(std::move(func)) { }
32};
33
35static std::vector<StringIDMapping> _string_to_grf_mapping;
36
42void AddStringForMapping(GRFStringID source, std::function<void(StringID)> &&func)
43{
44 func(STR_UNDEFINED);
45 _string_to_grf_mapping.emplace_back(_cur_gps.grffile->grfid, source, std::move(func));
46}
47
54{
55 AddStringForMapping(source, [target](StringID str) { *target = str; });
56}
57
66{
67 /* StringID table for TextIDs 0x4E->0x6D */
68 static const StringID units_volume[] = {
69 STR_ITEMS, STR_PASSENGERS, STR_TONS, STR_BAGS,
70 STR_LITERS, STR_ITEMS, STR_CRATES, STR_TONS,
71 STR_TONS, STR_TONS, STR_TONS, STR_BAGS,
72 STR_TONS, STR_TONS, STR_TONS, STR_BAGS,
73 STR_TONS, STR_TONS, STR_BAGS, STR_LITERS,
74 STR_TONS, STR_LITERS, STR_TONS, STR_ITEMS,
75 STR_BAGS, STR_LITERS, STR_TONS, STR_ITEMS,
76 STR_TONS, STR_ITEMS, STR_LITERS, STR_ITEMS
77 };
78
79 /* A string straight from a NewGRF; this was already translated by MapGRFStringID(). */
80 assert(!IsInsideMM(str.base(), 0xD000, 0xD7FF));
81
82#define TEXTID_TO_STRINGID(begin, end, stringid, stringend) \
83 static_assert(stringend - stringid == end - begin); \
84 if (str.base() >= begin && str.base() <= end) return StringID{str.base() + (stringid - begin)}
85
86 /* We have some changes in our cargo strings, resulting in some missing. */
87 TEXTID_TO_STRINGID(0x000E, 0x002D, STR_CARGO_PLURAL_NOTHING, STR_CARGO_PLURAL_FIZZY_DRINKS);
88 TEXTID_TO_STRINGID(0x002E, 0x004D, STR_CARGO_SINGULAR_NOTHING, STR_CARGO_SINGULAR_FIZZY_DRINK);
89 if (str.base() >= 0x004E && str.base() <= 0x006D) return units_volume[str.base() - 0x004E];
90 TEXTID_TO_STRINGID(0x006E, 0x008D, STR_QUANTITY_NOTHING, STR_QUANTITY_FIZZY_DRINKS);
91 TEXTID_TO_STRINGID(0x008E, 0x00AD, STR_ABBREV_NOTHING, STR_ABBREV_FIZZY_DRINKS);
92 TEXTID_TO_STRINGID(0x00D1, 0x00E0, STR_COLOUR_DARK_BLUE, STR_COLOUR_WHITE);
93
94 /* Map building names according to our lang file changes. There are several
95 * ranges of house ids, all of which need to be remapped to allow newgrfs
96 * to use original house names. */
97 TEXTID_TO_STRINGID(0x200F, 0x201F, STR_TOWN_BUILDING_NAME_TALL_OFFICE_BLOCK_1, STR_TOWN_BUILDING_NAME_OLD_HOUSES_1);
98 TEXTID_TO_STRINGID(0x2036, 0x2041, STR_TOWN_BUILDING_NAME_COTTAGES_1, STR_TOWN_BUILDING_NAME_SHOPPING_MALL_1);
99 TEXTID_TO_STRINGID(0x2059, 0x205C, STR_TOWN_BUILDING_NAME_IGLOO_1, STR_TOWN_BUILDING_NAME_PIGGY_BANK_1);
100
101 /* Same thing for industries */
102 TEXTID_TO_STRINGID(0x4802, 0x4826, STR_INDUSTRY_NAME_COAL_MINE, STR_INDUSTRY_NAME_SUGAR_MINE);
103 TEXTID_TO_STRINGID(0x482D, 0x482E, STR_NEWS_INDUSTRY_CONSTRUCTION, STR_NEWS_INDUSTRY_PLANTED);
104 TEXTID_TO_STRINGID(0x4832, 0x4834, STR_NEWS_INDUSTRY_CLOSURE_GENERAL, STR_NEWS_INDUSTRY_CLOSURE_LACK_OF_TREES);
105 TEXTID_TO_STRINGID(0x4835, 0x4838, STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_GENERAL, STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_FARM);
106 TEXTID_TO_STRINGID(0x4839, 0x483A, STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_GENERAL, STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_FARM);
107
108 switch (str.base()) {
109 case 0x4830: return STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY;
110 case 0x4831: return STR_ERROR_FOREST_CAN_ONLY_BE_PLANTED;
111 case 0x483B: return STR_ERROR_CAN_ONLY_BE_POSITIONED;
112 }
113#undef TEXTID_TO_STRINGID
114
115 if (str.base() == 0) return STR_EMPTY;
116
117 Debug(grf, 0, "Unknown StringID 0x{:04X} remapped to STR_EMPTY. Please open a Feature Request if you need it", str);
118
119 return STR_EMPTY;
120}
121
130{
131 if (IsInsideMM(str.base(), 0xD800, 0x10000)) {
132 /* General text provided by NewGRF.
133 * In the specs this is called the 0xDCxx range (misc persistent texts),
134 * but we meanwhile extended the range to 0xD800-0xFFFF.
135 * Note: We are not involved in the "persistent" business, since we do not store
136 * any NewGRF strings in savegames. */
137 return GetGRFStringID(grfid, str);
138 } else if (IsInsideMM(str.base(), 0xD000, 0xD800)) {
139 /* Callback text provided by NewGRF.
140 * In the specs this is called the 0xD0xx range (misc graphics texts).
141 * These texts can be returned by various callbacks.
142 *
143 * Due to how TTDP implements the GRF-local- to global-textid translation
144 * texts included via 0x80 or 0x81 control codes have to add 0x400 to the textid.
145 * We do not care about that difference and just mask out the 0x400 bit.
146 */
147 str = GRFStringID(str.base() & ~0x400);
148 return GetGRFStringID(grfid, str);
149 } else {
150 /* The NewGRF wants to include/reference an original TTD string.
151 * Try our best to find an equivalent one. */
153 }
154}
155
160{
162 it.func(MapGRFStringID(it.grfid, it.source));
163 }
165}
Functions related to debugging.
#define Debug(category, level, format_string,...)
Output a line of debugging information.
Definition debug.h:37
constexpr bool IsInsideMM(const size_t x, const size_t min, const size_t max) noexcept
Checks if a value is in an interval.
Base for the NewGRF implementation.
NewGRF internal processing state.
void AddStringForMapping(GRFStringID source, std::function< void(StringID)> &&func)
Record a static StringID for getting translated later.
static std::vector< StringIDMapping > _string_to_grf_mapping
Strings to be mapped during load.
StringID MapGRFStringID(uint32_t grfid, GRFStringID str)
Used when setting an object's property to map to the GRF's strings while taking in consideration the ...
static StringID TTDPStringIDToOTTDStringIDMapping(GRFStringID str)
Perform a mapping from TTDPatch's string IDs to OpenTTD's string IDs, but only for the ones we are aw...
void FinaliseStringMapping()
Finalise all string mappings.
NewGRF string mapping definition.
StringID GetGRFStringID(uint32_t grfid, GRFStringID stringid)
Returns the index for this stringid associated with its grfID.
Header of Action 04 "universal holder" structure and functions.
Header of Action 04 "universal holder" structure.
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.
Definition of base types and functions in a cross-platform compatible way.
Types related to strings.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
Information for mapping static StringIDs.
uint32_t grfid
Source NewGRF.
std::function< void(StringID)> func
Function for mapping result.
GRFStringID source
Source grf-local GRFStringID.