Skip to content

Commit 2da93a4

Browse files
committed
[CONFIGURATION] Implement base support for save/load of user configuration settings
1 parent 7eda9f3 commit 2da93a4

File tree

4 files changed

+479
-7
lines changed

4 files changed

+479
-7
lines changed

COTLMP/Api/Configuration.cs

Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
/*
2+
* PROJECT: Cult of the Lamb Multiplayer Mod
3+
* LICENSE: MIT (https://spdx.org/licenses/MIT)
4+
* PURPOSE: Save/Load user configuration settings and data support
5+
* COPYRIGHT: Copyright 2025 GeoB99 <[email protected]>
6+
*/
7+
8+
/* IMPORTS ********************************************************************/
9+
10+
using COTLMP;
11+
using COTLMP.Debug;
12+
using BepInEx;
13+
using BepInEx.Configuration;
14+
using System;
15+
using HarmonyLib;
16+
using UnityEngine.Assertions;
17+
18+
/* CLASSES & CODE *************************************************************/
19+
20+
namespace COTLMP.Api
21+
{
22+
internal static class Configuration
23+
{
24+
public enum CONFIGURATION_SECTION
25+
{
26+
ServerSettings = 0,
27+
ModSettings
28+
}
29+
30+
internal enum TYPE_DATA
31+
{
32+
StringType = 0,
33+
IntType,
34+
BoolType
35+
}
36+
37+
internal struct ConfigurationData
38+
{
39+
internal readonly CONFIGURATION_SECTION Section;
40+
internal string ValueName;
41+
internal string ValueDescription;
42+
internal readonly TYPE_DATA TypeData;
43+
internal string ValueStringData;
44+
internal bool ValueBoolData;
45+
internal int ValueIntData;
46+
47+
internal ConfigurationData(CONFIGURATION_SECTION Sect,
48+
string ValName,
49+
string ValDesc,
50+
TYPE_DATA Type,
51+
string StringData,
52+
bool BoolData,
53+
int IntData)
54+
{
55+
Section = Sect;
56+
ValueName = ValName;
57+
ValueDescription = ValDesc;
58+
TypeData = Type;
59+
ValueStringData = StringData;
60+
ValueBoolData = BoolData;
61+
ValueIntData = IntData;
62+
}
63+
}
64+
65+
private static string ConfigSectionToLabel(CONFIGURATION_SECTION Section)
66+
{
67+
string LabelName;
68+
69+
switch (Section)
70+
{
71+
case CONFIGURATION_SECTION.ServerSettings:
72+
{
73+
LabelName = "Server Settings";
74+
break;
75+
}
76+
77+
case CONFIGURATION_SECTION.ModSettings:
78+
{
79+
LabelName = "Mod Settings";
80+
break;
81+
}
82+
83+
default:
84+
{
85+
LabelName = null;
86+
break;
87+
}
88+
}
89+
90+
return LabelName;
91+
}
92+
93+
private static ConfigEntry<bool> LoadSettingAsBool(ConfigurationData SettingData)
94+
{
95+
string LabelName;
96+
ConfigEntry<bool> BoolSettingEntry;
97+
98+
/* We only support boolean settings here */
99+
if (SettingData.TypeData != TYPE_DATA.BoolType)
100+
{
101+
COTLMP.Debug.PrintLogger.Print(DebugLevel.ERROR_LEVEL, DebugComponent.CONFIGURATION_COMPONENT,
102+
$"{SettingData.TypeData} cannot be used when calling this function!");
103+
return null;
104+
}
105+
106+
/* Retrieve the category label of the config setting */
107+
LabelName = ConfigSectionToLabel(SettingData.Section);
108+
Assert.IsNotNull(LabelName);
109+
110+
/* Create the setting if it doesn't exist or load it */
111+
BoolSettingEntry = Plugin.Config.Bind(LabelName,
112+
SettingData.ValueName,
113+
SettingData.ValueBoolData,
114+
SettingData.ValueDescription);
115+
if (BoolSettingEntry == null)
116+
{
117+
COTLMP.Debug.PrintLogger.Print(DebugLevel.ERROR_LEVEL, DebugComponent.CONFIGURATION_COMPONENT,
118+
$"Failed to initialize or load the {SettingData.ValueName} setting!");
119+
return null;
120+
}
121+
122+
return BoolSettingEntry;
123+
}
124+
125+
private static ConfigEntry<string> LoadSettingAsString(ConfigurationData SettingData)
126+
{
127+
string LabelName;
128+
ConfigEntry<string> StringSettingEntry;
129+
130+
/* We only support string settings here */
131+
if (SettingData.TypeData != TYPE_DATA.StringType)
132+
{
133+
COTLMP.Debug.PrintLogger.Print(DebugLevel.ERROR_LEVEL, DebugComponent.CONFIGURATION_COMPONENT,
134+
$"{SettingData.TypeData} cannot be used when calling this function!");
135+
return null;
136+
}
137+
138+
/* Retrieve the category label of the config setting */
139+
LabelName = ConfigSectionToLabel(SettingData.Section);
140+
Assert.IsNotNull(LabelName);
141+
142+
/* Create the setting if it doesn't exist or load it */
143+
StringSettingEntry = Plugin.Config.Bind(LabelName,
144+
SettingData.ValueName,
145+
SettingData.ValueStringData,
146+
SettingData.ValueDescription);
147+
if (StringSettingEntry == null)
148+
{
149+
COTLMP.Debug.PrintLogger.Print(DebugLevel.ERROR_LEVEL, DebugComponent.CONFIGURATION_COMPONENT,
150+
$"Failed to initialize or load the {SettingData.ValueName} setting!");
151+
return null;
152+
}
153+
154+
return StringSettingEntry;
155+
}
156+
157+
private static ConfigEntry<int> LoadSettingAsInt(ConfigurationData SettingData)
158+
{
159+
string LabelName;
160+
ConfigEntry<int> IntSettingEntry;
161+
162+
/* We only support string settings here */
163+
if (SettingData.TypeData != TYPE_DATA.IntType)
164+
{
165+
COTLMP.Debug.PrintLogger.Print(DebugLevel.ERROR_LEVEL, DebugComponent.CONFIGURATION_COMPONENT,
166+
$"{SettingData.TypeData} cannot be used when calling this function!");
167+
return null;
168+
}
169+
170+
/* Retrieve the category label of the config setting */
171+
LabelName = ConfigSectionToLabel(SettingData.Section);
172+
Assert.IsNotNull(LabelName);
173+
174+
/* Create the setting if it doesn't exist or load it */
175+
IntSettingEntry = Plugin.Config.Bind(LabelName,
176+
SettingData.ValueName,
177+
SettingData.ValueIntData,
178+
SettingData.ValueDescription);
179+
if (IntSettingEntry == null)
180+
{
181+
COTLMP.Debug.PrintLogger.Print(DebugLevel.ERROR_LEVEL, DebugComponent.CONFIGURATION_COMPONENT,
182+
$"Failed to initialize or load the {SettingData.ValueName} setting!");
183+
return null;
184+
}
185+
186+
return IntSettingEntry;
187+
}
188+
189+
public static Object LoadSetting<T>(CONFIGURATION_SECTION ConfigSection, string ValueName, string ValueDescription, T ValueData)
190+
{
191+
Object ReturnedData;
192+
ConfigEntry<bool> BoolSetting;
193+
ConfigEntry<string> StringSetting;
194+
ConfigEntry<int> IntSetting;
195+
ConfigurationData SettingData;
196+
197+
/* Determine the value type provided and call the specific method accordingly */
198+
if (ValueData is bool)
199+
{
200+
/* This is a boolean value, build the internal data for this setting */
201+
SettingData = new ConfigurationData(ConfigSection,
202+
ValueName,
203+
ValueDescription,
204+
TYPE_DATA.BoolType,
205+
null,
206+
Convert.ToBoolean(ValueData),
207+
0);
208+
209+
/* And invoke the API helper to do the deed */
210+
BoolSetting = LoadSettingAsBool(SettingData);
211+
if (BoolSetting == null)
212+
{
213+
return null;
214+
}
215+
216+
/* And retrieve the value returned by the method */
217+
ReturnedData = BoolSetting.Value;
218+
}
219+
else if (ValueData is string)
220+
{
221+
/* This is a string value, build the internal data for this setting */
222+
SettingData = new ConfigurationData(ConfigSection,
223+
ValueName,
224+
ValueDescription,
225+
TYPE_DATA.StringType,
226+
Convert.ToString(ValueData),
227+
false,
228+
0);
229+
230+
/* And invoke the API helper to do the deed */
231+
StringSetting = LoadSettingAsString(SettingData);
232+
if (StringSetting == null)
233+
{
234+
return null;
235+
}
236+
237+
/* And retrieve the value returned by the method */
238+
ReturnedData = StringSetting.Value;
239+
}
240+
else if (ValueData is int)
241+
{
242+
/* This is an integer value, build the internal data for this setting */
243+
SettingData = new ConfigurationData(ConfigSection,
244+
ValueName,
245+
ValueDescription,
246+
TYPE_DATA.IntType,
247+
null,
248+
false,
249+
Convert.ToInt32(ValueData));
250+
251+
/* And invoke the API helper to do the deed */
252+
IntSetting = LoadSettingAsInt(SettingData);
253+
if (IntSetting == null)
254+
{
255+
return null;
256+
}
257+
258+
/* And retrieve the value returned by the method */
259+
ReturnedData = IntSetting.Value;
260+
}
261+
else
262+
{
263+
/* Other configuration settings are unsupported, bail out with no data */
264+
COTLMP.Debug.PrintLogger.Print(DebugLevel.WARNING_LEVEL, DebugComponent.CONFIGURATION_COMPONENT,
265+
$"Unknown value data type has been passed (Type -> {ValueData.GetType()})");
266+
ReturnedData = null;
267+
}
268+
269+
return ReturnedData;
270+
}
271+
272+
public static void FlushSettings()
273+
{
274+
/* Execute the Config API call to flush all the settings to disk */
275+
Plugin.Config.Save();
276+
}
277+
278+
public static T GetSettingData<T>(Object ConfigObject)
279+
{
280+
/* NULL objects is illegal here */
281+
Assert.IsNotNull(ConfigObject);
282+
283+
/* Cast the object immediately to the generic type if possible */
284+
if (ConfigObject is T)
285+
{
286+
return (T)ConfigObject;
287+
}
288+
289+
/* Otherwise change the type of the object and return it */
290+
return (T)Convert.ChangeType(ConfigObject, typeof(T));
291+
}
292+
}
293+
}
294+
295+
/* EOF */

COTLMP/Data/ModDataGlobals.cs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* PROJECT: Cult of the Lamb Multiplayer Mod
3+
* LICENSE: MIT (https://spdx.org/licenses/MIT)
4+
* PURPOSE: Globals data of the mod
5+
* COPYRIGHT: Copyright 2025 GeoB99 <[email protected]>
6+
*/
7+
8+
/* IMPORTS ********************************************************************/
9+
10+
using COTLMP;
11+
12+
/* CLASSES & CODE *************************************************************/
13+
14+
namespace COTLMP.Data
15+
{
16+
internal class ModDataGlobals
17+
{
18+
public bool EnableMod;
19+
public string GameMode;
20+
public string PlayerName;
21+
public string ServerName;
22+
public int MaxNumPlayers;
23+
public bool EnableVoiceChat;
24+
public bool EnableSayChat;
25+
26+
internal bool VerboseDebug = false;
27+
internal const int MaxPlayersPerServerInternal = 8;
28+
29+
public ModDataGlobals(bool Enable,
30+
string Mode,
31+
string PlName,
32+
string SvName,
33+
int PlNum,
34+
bool EnableVC,
35+
bool EnableSC)
36+
{
37+
EnableMod = Enable;
38+
GameMode = Mode;
39+
PlayerName = PlName;
40+
ServerName = SvName;
41+
MaxNumPlayers = PlNum;
42+
EnableVoiceChat = EnableVC;
43+
EnableSayChat = EnableSC;
44+
}
45+
}
46+
}
47+
48+
/* EOF */

COTLMP/Debug/PrintLogger.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ public enum DebugComponent
8080
INIT_COMPONENT = 0,
8181
UI_COMPONENT,
8282
NETWORK_STACK_COMPONENT,
83-
LOCALIZATION_COMPONENT
83+
LOCALIZATION_COMPONENT,
84+
CONFIGURATION_COMPONENT
8485
}
8586

8687
public class PrintLogger

0 commit comments

Comments
 (0)