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 | |
22 | class CConfig |
23 | { |
24 | public: |
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 | |
40 | extern CConfig g_Config; |
41 | |
42 | enum |
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 | |
62 | struct 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 | |
96 | protected: |
97 | void ExecuteLine(const char *pLine) const; |
98 | bool CheckReadOnly() const; |
99 | }; |
100 | |
101 | struct 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 | |
132 | struct 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 | |
163 | struct 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 | |
183 | class 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 | |
213 | public: |
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 | |