1/*
2 * LegacyClonk
3 *
4 * Copyright (c) 1998-2000, Matthes Bender (RedWolf Design)
5 * Copyright (c) 2017-2022, The LegacyClonk Team and contributors
6 *
7 * Distributed under the terms of the ISC license; see accompanying file
8 * "COPYING" for details.
9 *
10 * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11 * See accompanying file "TRADEMARK" for details.
12 *
13 * To redistribute this file separately, substitute the full license texts
14 * for the above references.
15 */
16
17/* Game configuration as stored in registry */
18
19#pragma once
20
21#include "C4Constants.h"
22#include "C4Cooldown.h"
23#include "C4InputValidation.h"
24#include "StdConfig.h"
25
26#ifdef C4ENGINE
27#include "C4AulScriptStrict.h"
28#include "C4Log.h"
29#include "StdWindow.h"
30#endif
31
32#define C4CFG_Company "LegacyClonk Team"
33#define C4CFG_Product "LegacyClonk"
34
35#define C4CFG_OfficialLeagueServer "league.clonkspot.org"
36#define C4CFG_LeagueServer "https://" C4CFG_OfficialLeagueServer
37#define C4CFG_FallbackServer C4CFG_LeagueServer
38
39#define C4CFG_UpdateServer "https://update.clonkspot.org/lc/update" // for download files, replace 'update' with the below
40
41#define C4CFG_UpdateEngine "lc_{}_{}.c4u"
42#define C4CFG_UpdateObjects "lc_{}{}{}{}_{}_{}.c4u"
43#define C4CFG_UpdateMajor "lc_{}{}{}{}_{}.c4u"
44
45class C4ConfigGeneral
46{
47public:
48 enum { ConfigResetSafetyVal = 42 };
49
50 uint32_t Version; // config version number for compatibility changes
51 char Name[CFG_MaxString + 1];
52 char Language[CFG_MaxString + 1]; // entered by user in frontend options (may contain comma separated list or long language descriptions)
53 char LanguageEx[CFG_MaxString + 1]; // full fallback list composed by frontend options (condensed comma separated list)
54 char LanguageCharset[CFG_MaxString + 1];
55 char Definitions[CFG_MaxString + 1];
56 char Participants[CFG_MaxString + 1];
57 bool AlwaysDebug; // if set: turns on debugmode whenever engine is started
58 bool AllowScriptingInReplays; // allow /script in replays (scripts can cause desyncs)
59 char RXFontName[CFG_MaxString + 1];
60 int32_t RXFontSize;
61 char PlayerPath[CFG_MaxString + 1];
62 char DefinitionPath[CFG_MaxString + 1];
63 char UserPath[CFG_MaxString + 1]; // absolute path; environment variables are stored and only expanded upon evaluation
64 StdStrBuf SaveGameFolder;
65 StdStrBuf SaveDemoFolder;
66 StdStrBuf ScreenshotFolder;
67 char MissionAccess[CFG_MaxString + 1];
68 bool FPS;
69 bool Record;
70 bool FairCrew; // don't use permanent crew physicals
71 int32_t FairCrewStrength; // strength of clonks in fair crew mode
72 int32_t MouseAScroll; // auto scroll strength
73 int32_t ScrollSmooth; // view movement smoothing
74 int32_t ConfigResetSafety; // safety value: If this value is screwed, the config got currupted and must be reset
75 // Determined at run-time
76 char ExePath[CFG_MaxString + 1];
77 char TempPath[CFG_MaxString + 1];
78 char LogPath[CFG_MaxString + 1];
79 char ScreenshotPath[CFG_MaxString + 1];
80 bool GamepadEnabled;
81 bool FirstStart;
82 bool fUTF8;
83 bool UserPortraitsWritten; // set when default portraits have been copied to the UserPath (this is only done once)
84 bool UseWhiteIngameChat;
85 bool UseWhiteLobbyChat;
86 bool ShowLogTimestamps;
87 bool Preloading;
88#ifndef _WIN32
89 std::uint32_t ThreadPoolThreadCount;
90#endif
91
92public:
93 static int GetLanguageSequence(const char *strSource, char *strTarget);
94 void DefaultLanguage();
95 bool CreateSaveFolder(const char *strDirectory, const char *strLanguageTitle);
96 void DeterminePaths(bool forceWorkingDirectory);
97 void CompileFunc(StdCompiler *pComp);
98};
99
100#ifdef C4ENGINE
101
102class C4ConfigDeveloper
103{
104public:
105 struct ConsoleScriptStrictnessWrapper
106 {
107 C4AulScriptStrict Strictness;
108
109 void CompileFunc(StdCompiler *comp);
110
111 operator C4AulScriptStrict() const noexcept { return Strictness == MaxStrictSentinel ? C4AulScriptStrict::MAXSTRICT : Strictness; }
112
113 static constexpr auto MaxStrictSentinel = static_cast<C4AulScriptStrict>(255);
114 };
115
116public:
117 bool AutoFileReload;
118 ConsoleScriptStrictnessWrapper ConsoleScriptStrictness;
119
120 void CompileFunc(StdCompiler *pComp);
121};
122
123class C4ConfigGraphics
124{
125public:
126 enum RenderInactive : uint32_t
127 {
128 Fullscreen = 1 << 0,
129 Console = 1 << 1
130 };
131
132 int32_t SplitscreenDividers;
133 bool ShowPlayerHUDAlways;
134 bool ShowCommands;
135 bool ShowCommandKeys;
136 bool ShowPortraits;
137 bool AddNewCrewPortraits;
138 bool SaveDefaultPortraits;
139 int32_t VerboseObjectLoading;
140 bool ColorAnimation;
141 int32_t SmokeLevel;
142 int32_t UpperBoard;
143 bool ShowClock;
144 int32_t ResX, ResY;
145 int32_t Scale;
146 bool ShowCrewNames; // show player name above clonks?
147 bool ShowCrewCNames; // show clonk names above clonks?
148 bool NoAlphaAdd; // always modulate alpha values instead of assing them (->no custom modulated alpha)
149 bool PointFiltering; // don't use linear filtering, because some crappy graphic cards can't handle it...
150 bool NoBoxFades; // map all DrawBoxFade-calls to DrawBoxDw
151 uint32_t AllowedBlitModes; // bit mask for allowed blitting modes
152 bool NoAcceleration; // whether direct rendering is used (X11)
153 bool Shader; // whether to use pixelshaders
154 bool MsgBoard;
155 bool PXSGfx; // show PXS-graphics (instead of sole pixels)
156 int32_t Engine; // 0: OpenGL; 3: disabled graphics
157 std::int32_t BlitOffset; // blit offset (percent) (OpenGL)
158 std::int32_t TexIndent; // blit offset (per mille) (OpenGL)
159 int32_t Gamma1, Gamma2, Gamma3; // gamma ramps
160 uint32_t RenderInactive; // draw viewports even if inactive. 1 = Fullscreen, 2 = EM, 1 | 2 = both
161 bool DisableGamma;
162 int32_t Monitor; // monitor index to play on
163 bool FireParticles; // draw extended fire particles if enabled (defualt on)
164 int32_t MaxRefreshDelay; // minimum time after which graphics should be refreshed (ms)
165 bool AutoFrameSkip; // if true, gfx frames are skipped when they would slow down the game
166 int32_t CacheTexturesInRAM; // -1 for disabled; otherwise after CacheTexturesInRAM times of Locking, Unlock(true) keeps the texture in RAM
167 DisplayMode UseDisplayMode;
168#ifdef _WIN32
169 bool Maximized;
170 int PositionX;
171 int PositionY;
172#endif
173 bool ShowFolderMaps; // if true, folder maps are shown
174 bool UseShaderGamma; // whether to use shader-based gamma correction
175
176 void CompileFunc(StdCompiler *pComp);
177};
178
179class C4ConfigSound
180{
181public:
182 bool RXSound;
183 bool RXMusic;
184 bool FEMusic;
185 bool FESamples;
186 int32_t MusicVolume;
187 int32_t SoundVolume;
188 int32_t MaxChannels;
189 bool PreferLinearResampling;
190 bool MuteSoundCommand; // whether to mute /sound by default
191 void CompileFunc(StdCompiler *pComp);
192};
193
194class C4ConfigNetwork
195{
196public:
197 int32_t ControlRate;
198 bool NoRuntimeJoin;
199 int32_t MaxResSearchRecursion;
200 char WorkPath[CFG_MaxString + 1];
201 ValidatedStdStrBuf<C4InVal::VAL_Comment> Comment;
202 bool MasterServerSignUp;
203 int32_t MasterReferencePeriod;
204 bool LeagueServerSignUp;
205 bool UseAlternateServer;
206 int32_t PortTCP, PortUDP, PortDiscovery, PortRefServer;
207 int32_t ControlMode;
208 ValidatedStdStrBuf<C4InVal::VAL_NameNoEmpty> LocalName;
209 ValidatedStdStrBuf<C4InVal::VAL_NameAllowEmpty> Nick;
210 int32_t MaxLoadFileSize;
211 char LastPassword[CFG_MaxString + 1];
212 char ServerAddress[CFG_MaxString + 1];
213 char AlternateServerAddress[CFG_MaxString + 1];
214 char UpdateServerAddress[CFG_MaxString + 1];
215 char PuncherAddress[CFG_MaxString + 1];
216
217 StdStrBuf LeagueAccount;
218 StdStrBuf LeaguePassword;
219 bool LeagueAutoLogin;
220
221 bool AutomaticUpdate;
222 uint64_t LastUpdateTime;
223 int32_t AsyncMaxWait;
224 bool UseCurl;
225 bool EnableUPnP;
226
227 static constexpr auto DefaultPuncherServer = "netpuncher.openclonk.org:11115";
228
229public:
230 void CompileFunc(StdCompiler *pComp);
231 const char *GetLeagueServerAddress();
232};
233
234class C4ConfigStartup
235{
236public:
237 // config for do-not-show-this-msg-again-messages
238 bool HideMsgStartDedicated;
239 bool HideMsgPlrTakeOver;
240 bool HideMsgPlrNoTakeOver;
241 bool HideMsgNoOfficialLeague;
242 bool HideMsgIRCDangerous;
243 bool AlphabeticalSorting; // if set, Folder.txt-sorting is ignored in scenario selection
244 int32_t LastPortraitFolderIdx;
245 void CompileFunc(StdCompiler *pComp);
246};
247
248class C4ConfigLobby
249{
250public:
251 int32_t CountdownTime;
252 bool AllowPlayerSave; // whether save-to-disk function is enabled for player ressources
253 void CompileFunc(StdCompiler *pComp);
254};
255
256class C4ConfigIRC
257{
258public:
259 char Server[CFG_MaxString + 1];
260 char Nick[CFG_MaxString + 1];
261 char RealName[CFG_MaxString + 1];
262 char Channel[CFG_MaxString + 1];
263 void CompileFunc(StdCompiler *pComp);
264};
265
266const int C4ConfigMaxGamepads = 4;
267
268class C4ConfigGamepad
269{
270public:
271 int32_t Button[C4MaxKey];
272 uint32_t AxisMin[6], AxisMax[6];
273 bool AxisCalibrated[6];
274 void CompileFunc(StdCompiler *pComp, bool fButtonsOnly = false);
275 void Reset(); // reset all buttons and axis calibration to default
276};
277
278class C4ConfigControls
279{
280public:
281 int32_t GamepadGuiControl;
282 int32_t MouseAScroll; // auto scroll strength
283 int32_t Keyboard[C4MaxKeyboardSet][C4MaxKey];
284 void CompileFunc(StdCompiler *pComp, bool fKeysOnly = false);
285 void ResetKeys(); // reset all keys to default
286};
287
288class C4ConfigCooldowns
289{
290public:
291 C4CooldownSeconds SoundCommand;
292 C4CooldownSeconds ReadyCheck;
293 void CompileFunc(StdCompiler *comp);
294};
295
296class C4ConfigToasts
297{
298public:
299 bool ReadyCheck;
300 void CompileFunc(StdCompiler *comp);
301};
302
303class C4ConfigLogging
304{
305public:
306 spdlog::level::level_enum LogLevelStdout;
307
308 C4LoggerConfig::Config<class C4AudioSystem> AudioSystem;
309 C4LoggerConfig::Config<class C4AulExec> AulExec;
310 C4LoggerConfig::Config<class C4AulProfiler> AulProfiler;
311 C4LoggerConfig::Config<class CStdDDraw> DDraw;
312 C4LoggerConfig::Config<class C4GameControl> GameControl;
313 C4LoggerConfig::Config<class C4Network2> Network;
314 C4LoggerConfig::Config<class C4Network2IO> Network2IO;
315 C4LoggerConfig::Config<class C4Network2HTTPClient> Network2HTTPClient;
316 C4LoggerConfig::Config<class C4Network2UPnP> Network2UPnP;
317 C4LoggerConfig::Config<class C4Playback> Playback;
318 C4LoggerConfig::Config<class CPNGFile> PNGFile;
319
320#ifdef WITH_GLIB
321 C4LoggerConfig::Config<struct _GMainLoop> GLib;
322#endif
323
324 void CompileFunc(StdCompiler *comp);
325};
326
327#endif
328
329class C4Config
330{
331public:
332 C4Config();
333 ~C4Config();
334
335public:
336 C4ConfigGeneral General;
337#ifdef C4ENGINE
338 C4ConfigDeveloper Developer;
339 C4ConfigGraphics Graphics;
340 C4ConfigSound Sound;
341 C4ConfigNetwork Network;
342 C4ConfigLobby Lobby;
343 C4ConfigIRC IRC;
344 C4ConfigGamepad Gamepads[C4ConfigMaxGamepads];
345 C4ConfigControls Controls;
346 C4ConfigStartup Startup;
347 C4ConfigCooldowns Cooldowns;
348 C4ConfigToasts Toasts;
349 C4ConfigLogging Logging;
350#endif
351 bool fConfigLoaded; // true if config has been successfully loaded
352 StdStrBuf ConfigFilename; // set for configs loaded from a nondefault config file
353
354public:
355 const char *GetSubkeyPath(const char *strSubkey);
356 void Default();
357 bool Save();
358 bool Load(bool forceWorkingDirectory = true, const char *szConfigFile = nullptr);
359 bool Init();
360 const char *AtExePath(const char *szFilename);
361 const char *AtTempPath(const char *szFilename);
362#ifdef C4ENGINE
363 const char *AtNetworkPath(const char *szFilename);
364#endif
365 const char *AtExeRelativePath(const char *szFilename);
366 const char *AtScreenshotPath(const char *szFilename);
367 const char *AtUserPath(const char *szFilename); // this one will expand environment variables on-the-fly
368 void ForceRelativePath(StdStrBuf *sFilename); // try AtExeRelativePath; force GetC4Filename if not possible
369 void CompileFunc(StdCompiler *pComp);
370 bool IsCorrupted()
371 {
372 return (General.ConfigResetSafety != C4ConfigGeneral::ConfigResetSafetyVal)
373#ifdef C4ENGINE
374 || !Graphics.ResX
375#endif
376 ;
377 }
378
379 static const char *GetCharsetCodeName(const char *charset) noexcept;
380 static std::uint8_t GetCharsetCode(const char *charset) noexcept;
381 static std::int32_t GetCharsetCodePage(const char *charset) noexcept;
382
383protected:
384 void ExpandEnvironmentVariables(char *strPath, int iMaxLen);
385
386#ifdef C4ENGINE
387private:
388 void AdaptToCurrentVersion();
389#endif
390};
391
392extern C4Config Config;
393