OpenTTD Source 20260206-master-g4d4e37dbf1
script_config.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 "../settings_type.h"
12#include "script_info.hpp"
13#include "api/script_object.hpp"
14#include "../textfile_gui.h"
15#include "../string_func.h"
16#include <charconv>
17
18#include "table/strings.h"
19
20#include "../safeguards.h"
21
22void ScriptConfig::Change(std::optional<std::string_view> name, int version, bool force_exact_match)
23{
24 if (name.has_value()) {
25 this->name = name.value();
26 this->info = this->FindInfo(this->name, version, force_exact_match);
27 } else {
28 this->info = nullptr;
29 }
30 this->version = (info == nullptr) ? -1 : info->GetVersion();
31 this->config_list.reset();
32 this->to_load_data.reset();
33
34 this->ClearConfigList();
35}
36
37ScriptConfig::ScriptConfig(const ScriptConfig &config)
38{
39 this->name = config.name;
40 this->info = config.info;
41 this->version = config.version;
42 this->to_load_data.reset();
43
44 for (const auto &item : config.settings) {
45 this->settings[item.first] = item.second;
46 }
47}
48
50{
51 this->ResetSettings();
52 this->to_load_data.reset();
53}
54
56{
57 return this->info;
58}
59
61{
62 if (this->info != nullptr) return this->info->GetConfigList();
63 if (this->config_list == nullptr) {
64 this->config_list = std::make_unique<ScriptConfigItemList>();
65 }
66 return this->config_list.get();
67}
68
70{
71 this->settings.clear();
72}
73
75{
76 for (const auto &item : *this->GetConfigList()) {
77 if (!item.flags.Test(ScriptConfigFlag::InGame)) {
78 this->SetSetting(item.name, this->GetSetting(item.name));
79 }
80 }
81}
82
83int ScriptConfig::GetSetting(const std::string &name) const
84{
85 const auto it = this->settings.find(name);
86 if (it == this->settings.end()) return this->info->GetSettingDefaultValue(name);
87 return it->second;
88}
89
90void ScriptConfig::SetSetting(std::string_view name, int value)
91{
92 /* You can only set Script specific settings if an Script is selected. */
93 if (this->info == nullptr) return;
94
95 const ScriptConfigItem *config_item = this->info->GetConfigItem(name);
96 if (config_item == nullptr) return;
97
98 value = Clamp(value, config_item->min_value, config_item->max_value);
99
100 this->settings[std::string{name}] = value;
101}
102
104{
105 this->settings.clear();
106}
107
109{
110 if (this->info == nullptr) return ResetSettings();
111
112 for (SettingValueList::iterator it = this->settings.begin(); it != this->settings.end();) {
113 const ScriptConfigItem *config_item = this->info->GetConfigItem(it->first);
114 assert(config_item != nullptr);
115
116 bool editable = yet_to_start || config_item->flags.Test(ScriptConfigFlag::InGame);
117 bool visible = _settings_client.gui.ai_developer_tools || !config_item->flags.Test(ScriptConfigFlag::Developer);
118
119 if (editable && visible) {
120 it = this->settings.erase(it);
121 } else {
122 it++;
123 }
124 }
125}
126
128{
129 return this->info != nullptr;
130}
131
132const std::string &ScriptConfig::GetName() const
133{
134 return this->name;
135}
136
138{
139 return this->version;
140}
141
142void ScriptConfig::StringToSettings(std::string_view value)
143{
144 std::string_view to_process = value;
145 for (;;) {
146 /* Analyze the string ('name=value,name=value\0') */
147 size_t pos = to_process.find_first_of('=');
148 if (pos == std::string_view::npos) return;
149
150 std::string_view item_name = to_process.substr(0, pos);
151
152 to_process.remove_prefix(pos + 1);
153 pos = to_process.find_first_of(',');
154 int item_value = 0;
155 std::from_chars(to_process.data(), to_process.data() + std::min(pos, to_process.size()), item_value);
156
157 this->SetSetting(item_name, item_value);
158
159 if (pos == std::string_view::npos) return;
160 to_process.remove_prefix(pos + 1);
161 }
162}
163
165{
166 if (this->settings.empty()) return {};
167
168 std::string result;
169 for (const auto &item : this->settings) {
170 format_append(result, "{}={},", item.first, item.second);
171 }
172
173 /* Remove the last ','. */
174 result.resize(result.size() - 1);
175 return result;
176}
177
178std::optional<std::string> ScriptConfig::GetTextfile(TextfileType type, CompanyID slot) const
179{
180 if (slot == CompanyID::Invalid() || this->GetInfo() == nullptr) return std::nullopt;
181
182 return ::GetTextfile(type, (slot == OWNER_DEITY) ? GAME_DIR : AI_DIR, this->GetInfo()->GetMainScript());
183}
184
185void ScriptConfig::SetToLoadData(ScriptInstance::ScriptData *data)
186{
187 this->to_load_data.reset(data);
188}
189
190ScriptInstance::ScriptData *ScriptConfig::GetToLoadData()
191{
192 return this->to_load_data.get();
193}
194
195static std::pair<StringParameter, StringParameter> GetValueParams(const ScriptConfigItem &config_item, int value)
196{
197 if (config_item.flags.Test(ScriptConfigFlag::Boolean)) return {value != 0 ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF, {}};
198
199 auto it = config_item.labels.find(value);
200 if (it != std::end(config_item.labels)) return {STR_JUST_RAW_STRING, it->second};
201
202 return {STR_JUST_INT, value};
203}
204
210std::string ScriptConfigItem::GetString(int value) const
211{
212 auto [param1, param2] = GetValueParams(*this, value);
213 return this->description.empty()
214 ? ::GetString(STR_JUST_STRING1, param1, param2)
215 : ::GetString(STR_AI_SETTINGS_SETTING, this->description, param1, param2);
216}
217
223{
224 return this->description.empty() ? TC_ORANGE : TC_LIGHT_BLUE;
225}
226
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
SettingValueList settings
List with all setting=>value pairs that are configure for this Script.
std::optional< std::string > GetTextfile(TextfileType type, CompanyID slot) const
Search a textfile file next to this script.
void AnchorUnchangeableSettings()
As long as the default of a setting has not been changed, the value of the setting is not stored.
bool HasScript() const
Is this config attached to an Script?
void SetSetting(std::string_view name, int value)
Set the value of a setting for this config.
void Change(std::optional< std::string_view > name, int version=-1, bool force_exact_match=false)
Set another Script to be loaded in this slot.
void StringToSettings(std::string_view value)
Convert a string which is stored in the config file or savegames to custom settings of this Script.
virtual ~ScriptConfig()
Delete an Script configuration.
int version
Version of the Script.
virtual ScriptInfo * FindInfo(const std::string &name, int version, bool force_exact_match)=0
This function should call back to the Scanner in charge of this Config, to find the ScriptInfo belong...
const std::string & GetName() const
Get the name of the Script.
class ScriptInfo * info
ScriptInfo object for related to this Script version.
std::unique_ptr< ScriptConfigItemList > config_list
List with all settings defined by this Script.
int GetVersion() const
Get the version of the Script.
void ClearConfigList()
Routine that clears the config list.
std::unique_ptr< ScriptInstance::ScriptData > to_load_data
Data to load after the Script start.
class ScriptInfo * GetInfo() const
Get the ScriptInfo linked to this ScriptConfig.
void ResetSettings()
Reset all settings to their default value.
std::string name
Name of the Script.
const ScriptConfigItemList * GetConfigList()
Get the config list for this ScriptConfig.
int GetSetting(const std::string &name) const
Get the value of a setting for this config.
std::string SettingsToString() const
Convert the custom settings to a string that can be stored in the config file or savegames.
void ResetEditableSettings(bool yet_to_start)
Reset only editable and visible settings to their default value.
All static information from an Script like name, version, etc.
static constexpr Owner OWNER_DEITY
The object is owned by a superuser / goal script.
@ AI_DIR
Subdirectory for all AI files.
Definition fileio_type.h:99
@ GAME_DIR
Subdirectory for all game scripts.
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition gfx_type.h:307
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition math_func.hpp:79
A number of safeguards to prevent using unsafe methods.
std::vector< ScriptConfigItem > ScriptConfigItemList
List of ScriptConfig items.
@ Boolean
This value is a boolean (either 0 (false) or 1 (true) ).
@ Developer
This setting will only be visible when the Script development tools are active.
@ InGame
This setting can be changed while the Script is running.
ScriptInfo keeps track of all information of a script, like Author, Description, ....
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:60
Types related to global configuration settings.
Definition of base types and functions in a cross-platform compatible way.
Functions related to low-level strings.
Info about a single Script setting.
ScriptConfigFlags flags
Flags for the configuration setting.
std::string GetString(int value) const
Get string to display this setting in the configuration interface.
LabelMapping labels
Text labels for the integer values.
int min_value
The minimal value this configuration setting can have.
int max_value
The maximal value this configuration setting can have.
std::string description
The description of the configuration setting.
TextColour GetColour() const
Get text colour to display this setting in the configuration interface.
GUI functions related to textfiles.
TextfileType
Additional text files accompanying Tar archives.