Skip to content
This repository was archived by the owner on Oct 21, 2022. It is now read-only.

Commit cc5cc84

Browse files
committed
Add settings for mods
1 parent 0b0babd commit cc5cc84

4 files changed

Lines changed: 303 additions & 37 deletions

File tree

ModLoader/IO/ModSettings.cs

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
using ModLoader.Mod;
2+
using SFS.Input;
3+
using SFS.IO;
4+
using SFS.Parsers.Json;
5+
using SFS.UI;
6+
using System;
7+
using System.Collections.Generic;
8+
using System.Text;
9+
using TMPro;
10+
using UnityEngine;
11+
12+
namespace ModLoader.IO
13+
{
14+
/// <summary>
15+
/// This class handles the Keybinding buttons in the settings menu. You can also load your configuration and store it if it changes.
16+
/// </summary>
17+
public class ModSettings : MonoBehaviour
18+
{
19+
/// <summary>
20+
/// Main instance of ModSettings. Use this to load settings or add the Keybidings buttons.
21+
/// </summary>
22+
public static ModSettings main;
23+
24+
private Transform _keybindingsHolder;
25+
private GameObject _textPrefab;
26+
private GameObject _spacePrefab;
27+
private GameObject _keybindingPrefab;
28+
private Dictionary<string, List<KeyBinder>> _elements = new Dictionary<string, List<KeyBinder>>();
29+
30+
/// <summary>
31+
/// This prefab is used to add text in the settings menu
32+
/// </summary>
33+
public GameObject TextPrefab
34+
{
35+
set { this._textPrefab = value; }
36+
}
37+
38+
/// <summary>
39+
/// This prefab is used to add space in the settings menu
40+
/// </summary>
41+
public GameObject SpacePrefab
42+
{
43+
set { this._spacePrefab = value; }
44+
}
45+
46+
/// <summary>
47+
/// This prefab is used to add keybinding buttons in the settings menu
48+
/// </summary>
49+
public GameObject KeybindingPrefab
50+
{
51+
set { this._keybindingPrefab = value; }
52+
}
53+
54+
/// <summary>
55+
/// This transforms keep all keybiding buttons.
56+
/// </summary>
57+
public Transform KeybindingsHolder
58+
{
59+
set { this._keybindingsHolder = value; }
60+
}
61+
62+
private void Awake()
63+
{
64+
ModSettings.main = this;
65+
66+
}
67+
68+
/// <summary>
69+
/// This method adds simple hotkey buttons in the settings menu
70+
/// </summary>
71+
/// <param name="key"> Your current key value </param>
72+
/// <param name="defaultKey"> Your default key value </param>
73+
/// <param name="name"> Your key name.</param>
74+
/// <param name="modSettings"> Your mod settings. This used to store your settings</param>
75+
/// <example>
76+
/// ModSettings.main.addKeybinding( MyLoadedSettings.My_Key, MyDefaultSettings.My_Key, "My_Key", MyLoadedSettings);
77+
/// </example>
78+
/// <exception cref="NullReferenceException">If you call this method on early_load</exception>
79+
public void addKeybinding(KeybindingsPC.Key key, KeybindingsPC.Key defaultKey, string name, SFSSettings modSettings)
80+
{
81+
this.addKeybinding(new KeybindingsPC.Key[]
82+
{
83+
key
84+
}, new KeybindingsPC.Key[]
85+
{
86+
defaultKey
87+
}, name, modSettings);
88+
}
89+
90+
/// <summary>
91+
/// This method adds multiple hotkey buttons in the settings menu
92+
/// </summary>
93+
/// <param name="keys"> Your current key values </param>
94+
/// <param name="defaultKeys"> Your default key values </param>
95+
/// <param name="name"> Your key name.</param>
96+
/// <param name="modSettings"> Your mod settings. This used to store your settings</param>
97+
/// <example>
98+
/// ModSettings.main.addKeybinding( MyLoadedSettings.My_Key, MyDefaultSettings.My_Key, "My_Key", MyLoadedSettings);
99+
/// </example>
100+
/// <exception cref="NullReferenceException">If you call this method on early_load</exception>
101+
public void addKeybinding(KeybindingsPC.Key[] keys, KeybindingsPC.Key[] defaultKeys, string name, SFSSettings modSettings)
102+
{
103+
// Code taken from SFS.Input.KeybindingsPC
104+
GameObject gameObject = UnityEngine.Object.Instantiate<GameObject>(this._keybindingPrefab, this._keybindingsHolder);
105+
106+
// change name format
107+
if (name.Contains("_"))
108+
{
109+
StringBuilder stringBuilder = new StringBuilder(name[0].ToString());
110+
for (int i = 1; i < name.Length; i++)
111+
{
112+
stringBuilder.Append(name[i].ToString().ToLower());
113+
}
114+
gameObject.GetComponentInChildren<TMP_Text>().text = stringBuilder.Replace("_", " ").ToString();
115+
}
116+
else
117+
{
118+
gameObject.GetComponentInChildren<TMP_Text>().text = name;
119+
}
120+
121+
List<KeyBinder> list = new List<KeyBinder>
122+
{
123+
gameObject.GetComponentInChildren<KeyBinder>()
124+
};
125+
int num = 0;
126+
127+
while (list.Count < keys.Length && num++ < 20)
128+
{
129+
list.Add(UnityEngine.Object.Instantiate<KeyBinder>(list[0], gameObject.transform));
130+
}
131+
132+
for (int j = 0; j < keys.Length; j++)
133+
{
134+
KeybindingsPC.Key key = keys[j];
135+
KeybindingsPC.Key defaultKey = defaultKeys[j];
136+
137+
// this action saves the key value when it changes
138+
Action save = () =>
139+
{
140+
this.save(modSettings);
141+
};
142+
143+
list[j].Initialize(Menu.settings.menuHolder, key, defaultKey, save );
144+
}
145+
146+
List<KeyBinder> modList;
147+
if(this._elements.TryGetValue(modSettings.getModId(), out modList)){
148+
modList.AddRange(list);
149+
}
150+
else
151+
{
152+
this._elements.Add(modSettings.getModId(), list);
153+
}
154+
}
155+
156+
/// <summary>
157+
/// This method add text in the settings menu
158+
/// </summary>
159+
/// <param name="text">Text you want to add</param>
160+
public void addText(string text)
161+
{
162+
UnityEngine.Object.Instantiate<GameObject>(this._textPrefab, this._keybindingsHolder).GetComponentInChildren<TMP_Text>().text = text;
163+
}
164+
165+
/// <summary>
166+
/// This function resets all mod keybindings
167+
/// </summary>
168+
public void resetKeybindings()
169+
{
170+
foreach (List<KeyBinder> keyBinders in this._elements.Values)
171+
{
172+
foreach(KeyBinder keyBinder in keyBinders)
173+
{
174+
keyBinder.ResetToDefault();
175+
}
176+
}
177+
}
178+
179+
private void save(SFSSettings modSettings)
180+
{
181+
FolderPath folder = new FolderPath(modSettings.getModFolder()).Extend("Settings").CreateFolder();
182+
FilePath settingsFile = folder.ExtendToFile("keybindings.json");
183+
string text = JsonWrapper.ToJson(modSettings, true);
184+
settingsFile.WriteText(text);
185+
}
186+
187+
/// <summary>
188+
/// This method load the current keybindings.
189+
/// </summary>
190+
/// <typeparam name="T">Your keybinding class. This class has all keybindings your mod needs</typeparam>
191+
/// <param name="mod">Your mod instance. This is used to get your modid and modfolder</param>
192+
/// <returns> Return your currents keybinding</returns>
193+
/// <example>
194+
/// MySettings currentSettings = ModSettings.main.loadSettings<MySettings>(MyMod);
195+
/// </example>
196+
public T loadSettings<T>(SFSMod mod)
197+
{
198+
FolderPath folder = new FolderPath(mod.ModFolder).Extend("Settings").CreateFolder();
199+
FilePath settingsFile = folder.ExtendToFile("keybindings.json");
200+
this._elements.Add(mod.ModId, new List<KeyBinder>());
201+
if (settingsFile.FileExists())
202+
{
203+
return JsonWrapper.FromJson<T>(settingsFile.ReadText());
204+
}
205+
206+
return Activator.CreateInstance<T>();
207+
}
208+
209+
}
210+
}

ModLoader/Mod/SFSSettings.cs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace ModLoader.Mod
8+
{
9+
/// <summary>
10+
/// Use this interface to create keybinding settings for your mod
11+
/// </summary>
12+
/// <example>
13+
/// public class MySettings : SFSSettings
14+
/// {
15+
/// public string getModId(){
16+
/// return "ModId";
17+
/// }
18+
///
19+
/// public string getModFolder(){
20+
/// return "path";
21+
/// }
22+
///
23+
/// public KeybindingsPC.Key My_Key = KeyCode.T;
24+
/// }
25+
/// </example>
26+
public interface SFSSettings
27+
{
28+
29+
/// <summary>
30+
/// Get mod id. This is used to identify for keybiding for another mods.
31+
/// </summary>
32+
/// <returns>
33+
/// My unique mod id.
34+
/// </returns>
35+
/// <example>
36+
/// public string getModId(){
37+
/// return MyMod.main.ModId;
38+
/// }
39+
/// </example>
40+
string getModId();
41+
42+
/// <summary>
43+
/// Get mod folder. This is used to load and store your keybindings.
44+
/// </summary>
45+
/// <returns>
46+
/// My folder Path
47+
/// </returns>
48+
/// <example>
49+
/// public string getModFolder(){
50+
/// return MyMod.main.ModFolder;
51+
/// }
52+
/// </example>
53+
string getModFolder();
54+
55+
}
56+
}

ModLoader/ModLoader.csproj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
<DefineConstants>TRACE</DefineConstants>
3232
<ErrorReport>prompt</ErrorReport>
3333
<WarningLevel>4</WarningLevel>
34-
<DocumentationFile>bin\Release\documentation.xml</DocumentationFile>
34+
<DocumentationFile>bin\Release\ModLoader.xml</DocumentationFile>
3535
</PropertyGroup>
3636
<ItemGroup>
3737
<Reference Include="0Harmony, Version=2.2.0.0, Culture=neutral, processorArchitecture=MSIL">
@@ -104,8 +104,10 @@
104104
<Compile Include="IO\ConsoleGUI.cs" />
105105
<Compile Include="Helper.cs" />
106106
<Compile Include="Helpers\KeybindingHelper.cs" />
107+
<Compile Include="IO\ModSettings.cs" />
107108
<Compile Include="Loader.cs" />
108109
<Compile Include="Helpers\SceneHelper.cs" />
110+
<Compile Include="Mod\SFSSettings.cs" />
109111
<Compile Include="UI\ModsMenu.cs" />
110112
<Compile Include="Patcher.cs" />
111113
<Compile Include="Properties\AssemblyInfo.cs" />

ModLoader/Patcher.cs

Lines changed: 34 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
using ModLoader.UI;
77
using System.Reflection;
88
using System;
9+
using ModLoader.Helpers;
10+
using SFS.UI;
911

1012
namespace ModLoader
1113
{
@@ -21,17 +23,23 @@ public static void Postfix(BaseAssigner __instance)
2123
// console start first
2224
GameObject modConsole = new GameObject("ModConsole");
2325
GameObject loader = new GameObject("ModLoader");
26+
GameObject helpers = new GameObject("Helpers");
27+
2428
Loader.root = loader;
2529
IO.Console.root = modConsole;
30+
2631
modConsole.AddComponent<IO.Console>();
2732
modConsole.SetActive(true);
33+
2834
loader.AddComponent<Loader>();
29-
modConsole.AddComponent<Helper>();
3035
modConsole.AddComponent<ModsMenu>();
3136

37+
helpers.AddComponent<SceneHelper>();
38+
helpers.AddComponent<Helper>(); // remove for v2.0.0
3239

3340
UnityEngine.Object.DontDestroyOnLoad(modConsole);
3441
UnityEngine.Object.DontDestroyOnLoad(loader);
42+
UnityEngine.Object.DontDestroyOnLoad(helpers);
3543

3644
loader.SetActive(true);
3745
}
@@ -40,51 +48,41 @@ public static void Postfix(BaseAssigner __instance)
4048
[HarmonyPatch(typeof(KeybindingsPC), "Awake")]
4149
class KeybindingsPCAwake
4250
{
43-
51+
/// <summary>
52+
/// Start after Awake at KeybindingsPC. This is used to create mod key bindings.
53+
/// </summary>
54+
/// <param name="__instance">KeybidnigsPc class instance. is used to get prefabs</param>
4455
[HarmonyPostfix]
4556
public static void Postfix(KeybindingsPC __instance)
4657
{
58+
ModSettings modSettings = __instance.gameObject.AddComponent<ModSettings>();
59+
modSettings.TextPrefab = __instance.textPrefab;
60+
modSettings.KeybindingPrefab = __instance.keybindingPrefab;
61+
modSettings.KeybindingsHolder = __instance.keybindingsHolder;
62+
modSettings.SpacePrefab = __instance.spacePrefab;
63+
}
64+
}
4765

48-
49-
/*Debug.Log("Settings created");
50-
MethodInfo createText = __instance.GetType().GetMethod("CreateText",
51-
BindingFlags.NonPublic | BindingFlags.Instance);
52-
createText.Invoke(__instance, new object[] { "MODS" });
53-
54-
55-
foreach (Component component in __instance.textPrefab.GetComponentsInChildren<Component>())
56-
{
57-
Debug.Log(component);
58-
}
59-
60-
KeybindingsPC.Key openConsole = KeyCode.F1;
61-
string message = "Show_Console";
62-
MethodInfo create = __instance.GetType().GetMethod("Create",
63-
BindingFlags.NonPublic | BindingFlags.Instance,
64-
null, new Type[] { openConsole.GetType(), openConsole.GetType(), message.GetType() }, null);
65-
66-
Debug.Log("Invoke Method");
67-
create.Invoke(__instance, new object[] { openConsole, openConsole, message });*/
68-
Debug.Log("Object");
69-
foreach (Component compoennt in __instance.gameObject.GetComponents<Component>())
70-
{
71-
Debug.Log(compoennt);
72-
}
73-
Debug.Log("Children");
74-
foreach (Component compoennt in __instance.gameObject.GetComponentsInChildren<Component>())
75-
{
76-
Debug.Log(compoennt);
77-
}
78-
79-
80-
66+
[HarmonyPatch(typeof(KeybindingsPC), "ResetKeybindings")]
67+
class KeybindingsPCResetKeybindings
68+
{
69+
/// <summary>
70+
/// Start after ResetKeybindings at KeybindingsPC. This is used to reset keybindings for mods.
71+
/// </summary>
72+
[HarmonyPostfix]
73+
public static void Postfix()
74+
{
75+
ModSettings.main.resetKeybindings();
8176
}
8277
}
8378

8479
[HarmonyPatch(typeof(InputManager), "ApplyDrag")]
8580
class InputManagerApplyDrag
8681
{
87-
82+
/// <summary>
83+
/// Start before ApplyDrag at InputManager. This is used to prevent drag input when the mmodloader console is open.
84+
/// </summary>
85+
/// <returns> False to prevent drag input or true to continue</returns>
8886
[HarmonyPrefix]
8987
public static bool Prefix()
9088
{

0 commit comments

Comments
 (0)