1/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
2/* If you are missing that file, acquire a complete release at teeworlds.com. */
3#ifndef ENGINE_SHARED_CONFIG_H
4#define ENGINE_SHARED_CONFIG_H
5
6#include <base/detect.h>
7
8#include <engine/config.h>
9#include <engine/console.h>
10#include <engine/shared/memheap.h>
11
12#include <vector>
13
14// include protocol for MAX_CLIENT used in config_variables
15#include <engine/shared/protocol.h>
16
17#define CONFIG_FILE "settings_ddnet.cfg"
18#define AUTOEXEC_FILE "autoexec.cfg"
19#define AUTOEXEC_CLIENT_FILE "autoexec_client.cfg"
20#define AUTOEXEC_SERVER_FILE "autoexec_server.cfg"
21
22class CConfig
23{
24public:
25#define MACRO_CONFIG_INT(Name, ScriptName, Def, Min, Max, Flags, Desc) \
26 static constexpr int ms_##Name = Def; \
27 int m_##Name;
28#define MACRO_CONFIG_COL(Name, ScriptName, Def, Flags, Desc) \
29 static constexpr unsigned ms_##Name = Def; \
30 unsigned m_##Name;
31#define MACRO_CONFIG_STR(Name, ScriptName, Len, Def, Flags, Desc) \
32 static constexpr const char *ms_p##Name = Def; \
33 char m_##Name[Len]; // Flawfinder: ignore
34#include "config_variables.h"
35#undef MACRO_CONFIG_INT
36#undef MACRO_CONFIG_COL
37#undef MACRO_CONFIG_STR
38};
39
40extern CConfig g_Config;
41
42enum
43{
44 CFGFLAG_SAVE = 1 << 0,
45 CFGFLAG_CLIENT = 1 << 1,
46 CFGFLAG_SERVER = 1 << 2,
47 CFGFLAG_STORE = 1 << 3,
48 CFGFLAG_MASTER = 1 << 4,
49 CFGFLAG_ECON = 1 << 5,
50 // DDRace
51
52 CMDFLAG_TEST = 1 << 6,
53 CFGFLAG_CHAT = 1 << 7,
54 CFGFLAG_GAME = 1 << 8,
55 CFGFLAG_NONTEEHISTORIC = 1 << 9,
56 CFGFLAG_COLLIGHT = 1 << 10,
57 CFGFLAG_COLALPHA = 1 << 11,
58 CFGFLAG_INSENSITIVE = 1 << 12,
59 CMDFLAG_PRACTICE = 1 << 13,
60};
61
62struct SConfigVariable
63{
64 enum EVariableType
65 {
66 VAR_INT,
67 VAR_COLOR,
68 VAR_STRING,
69 };
70 IConsole *m_pConsole;
71 const char *m_pScriptName;
72 EVariableType m_Type;
73 int m_Flags;
74 const char *m_pHelp;
75 // Note that this only applies to the console command and the SetValue function,
76 // but the underlying config variable can still be modified programatically.
77 bool m_ReadOnly = false;
78
79 SConfigVariable(IConsole *pConsole, const char *pScriptName, EVariableType Type, int Flags, const char *pHelp) :
80 m_pConsole(pConsole),
81 m_pScriptName(pScriptName),
82 m_Type(Type),
83 m_Flags(Flags),
84 m_pHelp(pHelp)
85 {
86 }
87
88 virtual ~SConfigVariable() = default;
89
90 virtual void Register() = 0;
91 virtual bool IsDefault() const = 0;
92 virtual void Serialize(char *pOut, size_t Size) const = 0;
93 virtual void ResetToDefault() = 0;
94 virtual void ResetToOld() = 0;
95
96protected:
97 void ExecuteLine(const char *pLine) const;
98 bool CheckReadOnly() const;
99};
100
101struct SIntConfigVariable : public SConfigVariable
102{
103 int *m_pVariable;
104 int m_Default;
105 int m_Min;
106 int m_Max;
107 int m_OldValue;
108
109 SIntConfigVariable(IConsole *pConsole, const char *pScriptName, EVariableType Type, int Flags, const char *pHelp, int *pVariable, int Default, int Min, int Max) :
110 SConfigVariable(pConsole, pScriptName, Type, Flags, pHelp),
111 m_pVariable(pVariable),
112 m_Default(Default),
113 m_Min(Min),
114 m_Max(Max),
115 m_OldValue(Default)
116 {
117 *m_pVariable = m_Default;
118 }
119
120 ~SIntConfigVariable() override = default;
121
122 static void CommandCallback(IConsole::IResult *pResult, void *pUserData);
123 void Register() override;
124 bool IsDefault() const override;
125 void Serialize(char *pOut, size_t Size, int Value) const;
126 void Serialize(char *pOut, size_t Size) const override;
127 void SetValue(int Value);
128 void ResetToDefault() override;
129 void ResetToOld() override;
130};
131
132struct SColorConfigVariable : public SConfigVariable
133{
134 unsigned *m_pVariable;
135 unsigned m_Default;
136 bool m_Light;
137 bool m_Alpha;
138 unsigned m_OldValue;
139
140 SColorConfigVariable(IConsole *pConsole, const char *pScriptName, EVariableType Type, int Flags, const char *pHelp, unsigned *pVariable, unsigned Default) :
141 SConfigVariable(pConsole, pScriptName, Type, Flags, pHelp),
142 m_pVariable(pVariable),
143 m_Default(Default),
144 m_Light(Flags & CFGFLAG_COLLIGHT),
145 m_Alpha(Flags & CFGFLAG_COLALPHA),
146 m_OldValue(Default)
147 {
148 *m_pVariable = m_Default;
149 }
150
151 ~SColorConfigVariable() override = default;
152
153 static void CommandCallback(IConsole::IResult *pResult, void *pUserData);
154 void Register() override;
155 bool IsDefault() const override;
156 void Serialize(char *pOut, size_t Size, unsigned Value) const;
157 void Serialize(char *pOut, size_t Size) const override;
158 void SetValue(unsigned Value);
159 void ResetToDefault() override;
160 void ResetToOld() override;
161};
162
163struct SStringConfigVariable : public SConfigVariable
164{
165 char *m_pStr;
166 const char *m_pDefault;
167 size_t m_MaxSize;
168 char *m_pOldValue;
169
170 SStringConfigVariable(IConsole *pConsole, const char *pScriptName, EVariableType Type, int Flags, const char *pHelp, char *pStr, const char *pDefault, size_t MaxSize, char *pOldValue);
171 ~SStringConfigVariable() override = default;
172
173 static void CommandCallback(IConsole::IResult *pResult, void *pUserData);
174 void Register() override;
175 bool IsDefault() const override;
176 void Serialize(char *pOut, size_t Size, const char *pValue) const;
177 void Serialize(char *pOut, size_t Size) const override;
178 void SetValue(const char *pValue);
179 void ResetToDefault() override;
180 void ResetToOld() override;
181};
182
183class CConfigManager : public IConfigManager
184{
185 IConsole *m_pConsole;
186 class IStorage *m_pStorage;
187
188 IOHANDLE m_ConfigFile;
189 bool m_Failed;
190
191 struct SCallback
192 {
193 SAVECALLBACKFUNC m_pfnFunc;
194 void *m_pUserData;
195
196 SCallback(SAVECALLBACKFUNC pfnFunc, void *pUserData) :
197 m_pfnFunc(pfnFunc),
198 m_pUserData(pUserData)
199 {
200 }
201 };
202 std::vector<SCallback> m_vCallbacks;
203
204 std::vector<SConfigVariable *> m_vpAllVariables;
205 std::vector<SConfigVariable *> m_vpGameVariables;
206 std::vector<const char *> m_vpUnknownCommands;
207 CHeap m_ConfigHeap;
208
209 static void Con_Reset(IConsole::IResult *pResult, void *pUserData);
210 static void Con_Toggle(IConsole::IResult *pResult, void *pUserData);
211 static void Con_ToggleStroke(IConsole::IResult *pResult, void *pUserData);
212
213public:
214 CConfigManager();
215
216 void Init() override;
217 void Reset(const char *pScriptName) override;
218 void ResetGameSettings() override;
219 void SetReadOnly(const char *pScriptName, bool ReadOnly) override;
220 bool Save() override;
221 CConfig *Values() override { return &g_Config; }
222
223 void RegisterCallback(SAVECALLBACKFUNC pfnFunc, void *pUserData) override;
224
225 void WriteLine(const char *pLine) override;
226
227 void StoreUnknownCommand(const char *pCommand) override;
228
229 void PossibleConfigVariables(const char *pStr, int FlagMask, POSSIBLECFGFUNC pfnCallback, void *pUserData) override;
230};
231
232#endif
233