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

Commit 5e17a9e

Browse files
committed
Add mod dependencies
1 parent 3b2c6f8 commit 5e17a9e

4 files changed

Lines changed: 220 additions & 62 deletions

File tree

ModLoader/Loader.cs

Lines changed: 171 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -35,103 +35,203 @@ public static FolderPath ModsFolder
3535
}
3636
}
3737

38+
private List<string> _modsLoaded;
39+
3840
// List of all mods loaded in the folder MODS
39-
private SFSMod[] _modList;
40-
/*public SFSMod[] ModList
41-
{
42-
get
43-
}*/
41+
private Dictionary<string, SFSMod> _modList;
4442

43+
/// <summary>
44+
/// first method executed. Save loader instance in static var and suscribe to scene event.
45+
/// </summary>
4546
private void Awake()
4647
{
4748
Loader.main = this;
48-
this._modList = new SFSMod[] { };
4949
this.suscribeOnChangeScene(this.OnSceneLoaded);
5050
_modsFolder = FileLocations.BaseFolder.Extend("MODS").CreateFolder();
5151
}
5252

53+
/// <summary>
54+
/// This method start to read mods and is executed automatically when this class is created after Awake method.
55+
/// </summary>
5356
private void Start()
5457
{
55-
IEnumerable<FolderPath> modsFolders = _modsFolder.GetFoldersInFolder(false);
56-
string basePath = Path.Combine(FileLocations.BaseFolder, "MODS");
57-
Debug.Log("Reading Mods");
58-
Debug.LogError(new Exception("Error custom"));
59-
60-
foreach (FolderPath folder in modsFolders)
58+
Debug.Log("Reading mods");
59+
this._modList = this.getModList();
60+
this._modsLoaded = new List<string>();
61+
62+
foreach (SFSMod mod in this._modList.Values)
6163
{
62-
string fileModPath = Path.Combine(basePath, folder.FolderName, folder.FolderName+".dll");
64+
if(this._modsLoaded.Contains(mod.ModId))
65+
{
66+
continue;
67+
}
68+
6369
try
6470
{
65-
SFSMod mod = this.loadMod(fileModPath);
66-
this._modList.AddItem(mod);
67-
Debug.Log(mod.Name+" Loaded");
71+
this.loadMod(mod);
6872
}
69-
catch(Exception e)
73+
catch (Exception e)
7074
{
71-
Debug.LogError("Error Reading "+folder.FolderName+" folder");
72-
Debug.LogError(e);
75+
Debug.LogException(e);
7376
}
74-
7577
}
76-
7778
}
7879

79-
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
80+
/// <summary>
81+
/// get mod instance.
82+
/// </summary>
83+
/// <param name="modId">Mod ID you need</param>
84+
/// <returns>instance mod</returns>
85+
public SFSMod getMod(string modId)
8086
{
81-
Debug.Log("Scene change to "+scene.name);
87+
return this._modList[modId];
8288
}
8389

84-
public bool suscribeOnChangeScene(UnityAction<Scene, LoadSceneMode> method)
90+
/// <summary>
91+
/// This method read MODS folder and identify what is the entry point for each folder.
92+
/// </summary>
93+
/// <returns> dictionary whit modid as key and SFSMod instance as value</returns>
94+
private Dictionary<string, SFSMod> getModList()
8595
{
86-
SceneManager.sceneLoaded += method;
87-
return true;
88-
}
96+
Dictionary<string, SFSMod> modList = new Dictionary<string, SFSMod>();
8997

90-
private SFSMod loadMod(string path)
91-
{
92-
Assembly assembly = Assembly.LoadFrom(path);
93-
SFSMod mod = null;
98+
// get list of mod Folders in MODS folder
99+
IEnumerable<FolderPath> modsFolders = _modsFolder.GetFoldersInFolder(false);
100+
string basePath = Path.Combine(FileLocations.BaseFolder, "MODS");
94101

95-
foreach (Type typeClass in assembly.GetTypes())
102+
foreach (FolderPath folder in modsFolders)
96103
{
97-
if (typeClass.IsSubclassOf(typeof(SFSMod)))
104+
string fileModPath = Path.Combine(basePath, folder.FolderName, folder.FolderName + ".dll");
105+
try
98106
{
99-
mod = (Activator.CreateInstance(typeClass) as SFSMod);
100-
break;
107+
// get mod assembly
108+
Assembly assembly = Assembly.LoadFrom(fileModPath);
109+
SFSMod mod = null;
110+
111+
// verfiy if hace SFSMod class
112+
foreach (Type typeClass in assembly.GetTypes())
113+
{
114+
if (typeClass.IsSubclassOf(typeof(SFSMod)))
115+
{
116+
mod = (Activator.CreateInstance(typeClass) as SFSMod);
117+
break;
118+
}
119+
120+
}
121+
122+
if (mod == null)
123+
{
124+
throw new Exception(folder.FolderName+" entry point not found");
125+
126+
}
127+
128+
if (modList.ContainsKey(mod.ModId))
129+
{
130+
throw new Exception("Already existe another mod whit id "+mod.ModId);
131+
}
132+
133+
modList.Add(mod.ModId, mod);
101134
}
102-
135+
catch (Exception e)
136+
{
137+
Debug.LogException(e);
138+
}
139+
103140
}
141+
return modList;
142+
}
104143

105-
if(mod == null)
144+
/// <summary>
145+
/// Load mod dependecies and chec if is already loaded and check their version.
146+
/// </summary>
147+
/// <param name="dependencies"> list of dependecies that you need to load first</param>
148+
/// <returns> true if all dependecies have been loaded </returns>
149+
private bool loadDependencies(SFSModDependencie[] dependencies)
150+
{
151+
// for each mod dependencie
152+
foreach(SFSModDependencie dependencie in dependencies)
106153
{
107-
throw new Exception("SFSmod class not found");
154+
// exist mod in the list?
155+
if (this._modList.ContainsKey(dependencie.ModId))
156+
{
157+
// get mod dependecie
158+
SFSMod dependencieMod = this._modList[dependencie.ModId];
159+
160+
// verify if the dependencie version is the same that mod need
161+
bool versionFlag = false;
162+
foreach(string version in dependencie.Versions)
163+
{
164+
if(verifyVersion(dependencieMod.Version, version))
165+
{
166+
versionFlag = true;
167+
break;
168+
}
169+
}
170+
171+
// the version is valid
172+
if (versionFlag)
173+
{
174+
// start load dependencie first
175+
this.loadMod(dependencieMod);
176+
continue;
177+
}
178+
}
179+
// dependencie not exist or is diferent version
180+
throw new Exception("Is necesary install " + dependencie.ModId +" "+ string.Join(", ", dependencie.Versions));
108181
}
182+
return true;
183+
}
184+
185+
/// <summary>
186+
/// start to check version mod and run load method
187+
/// </summary>
188+
/// <param name="mod">mod to start load</param>
189+
private void loadMod(SFSMod mod)
190+
{
191+
// this mod has been load?, if not start load
192+
if (this._modsLoaded.Contains(mod.ModId))
193+
{
194+
return;
195+
}
196+
197+
Debug.Log("Loading " + mod.Name);
198+
this._modsLoaded.Add(mod.ModId);
109199

110-
if (verifyModLoaderVersion(mod.ModLoderVersion))
200+
// check if the version is valid for this modloader version
201+
if (verifyVersion(mod.ModLoderVersion, modLoderVersion))
111202
{
203+
// Have dependencies?
204+
if(mod.Dependencies != null)
205+
{
206+
// load them
207+
this.loadDependencies(mod.Dependencies);
208+
}
209+
112210
mod.loadAssets();
113211
mod.load();
114-
115-
return mod;
212+
return;
116213
}
117-
throw new Exception(mod.Name+" need ModLoader " + mod.Version);
214+
215+
// the mod loader version is not valid
216+
throw new Exception(mod.Name + " need ModLoader " + mod.Version);
118217
}
119218

120219
/// <summary>
121-
/// get if the mod have a valid version format and valid version for this modloader version
220+
/// check two versions string to identify if are the same
122221
/// </summary>
123-
/// <param name="version"> mod version</param>
124-
/// <returns>true if valid version</returns>
125-
private bool verifyModLoaderVersion(string version)
222+
/// <param name="version1"> version to check</param>
223+
/// <param name="version2"> verison to check</param>
224+
/// <returns>true if are valid versions</returns>
225+
private bool verifyVersion(string version1, string version2)
126226
{
127227
Regex rx = new Regex(@"\bv([0-9]|[1-9][0-9]).([0-9]|[1-9][0-9]|x).([0-9]|[1-9][0-9]|x)\b", RegexOptions.Compiled | RegexOptions.IgnoreCase);
128228
// have the formal v1.x.x
129-
if (rx.IsMatch(version))
229+
if (rx.IsMatch(version1) && rx.IsMatch(version2))
130230
{
131-
string[] modVersion = version.Split('.');
132-
string[] target = modLoderVersion.Split('.');
133-
134-
if(modVersion.Length == target.Length)
231+
string[] modVersion = version1.Split('.');
232+
string[] target = version2.Split('.');
233+
234+
if (modVersion.Length == target.Length)
135235
{
136236
for (short index = 0; index < target.Length; index++)
137237
{
@@ -145,13 +245,30 @@ private bool verifyModLoaderVersion(string version)
145245
}
146246
}
147247
// have the format and is valid version for this modloader version
148-
return true;
248+
return true;
149249

150250
}
151-
251+
152252
}
153253
return false;
154-
}
254+
}
255+
256+
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
257+
{
258+
Debug.Log("Scene change to "+scene.name);
259+
}
260+
261+
/// <summary>
262+
/// suscribe to scene change event
263+
/// </summary>
264+
/// <param name="method">method what do you want to suscribe</param>
265+
/// <returns>true if subscribed</returns>
266+
public bool suscribeOnChangeScene(UnityAction<Scene, LoadSceneMode> method)
267+
{
268+
SceneManager.sceneLoaded += method;
269+
return true;
270+
}
271+
155272

156273
/// <summary>
157274
/// This is the mod loader entry point, this is the method execute after be injected in the game

ModLoader/ModLoader.csproj

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@
3939
<HintPath>..\Dependencies\Assembly-CSharp.dll</HintPath>
4040
<Private>False</Private>
4141
</Reference>
42+
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
43+
<SpecificVersion>False</SpecificVersion>
44+
<HintPath>..\Dependencies\Newtonsoft.Json.dll</HintPath>
45+
</Reference>
4246
<Reference Include="System" />
4347
<Reference Include="System.Core" />
4448
<Reference Include="System.Xml.Linq" />
@@ -67,6 +71,7 @@
6771
<Compile Include="Patcher.cs" />
6872
<Compile Include="Properties\AssemblyInfo.cs" />
6973
<Compile Include="SFSMod.cs" />
74+
<Compile Include="SFSModDependencie.cs" />
7075
</ItemGroup>
7176
<ItemGroup>
7277
<None Include="packages.config" />

ModLoader/SFSMod.cs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,21 @@ namespace ModLoader
1010
/// </summary>
1111
public abstract class SFSMod
1212
{
13-
13+
private string _modId;
1414
private string _name;
1515
private string _author;
1616
private string _modLoderVersion;
1717
private string _version;
1818
private string _description;
19-
//private Type[] _dependencies;
19+
private SFSModDependencie[] _dependencies;
2020
private AssetBundle _assets;
2121
private string _assetsFilename;
2222

23+
public string ModId
24+
{
25+
get { return this._modId; }
26+
}
27+
2328
/// <summary>
2429
/// Get mod name
2530
/// </summary>
@@ -63,10 +68,10 @@ public string Description
6368
/// <summary>
6469
/// get the list of mods need it to work.
6570
/// </summary>
66-
//public Type[] Dependencies
67-
//{
68-
// get { return this._dependencies; }
69-
//}
71+
public SFSModDependencie[] Dependencies
72+
{
73+
get { return this._dependencies; }
74+
}
7075

7176
/// <summary>
7277
/// get the assets used for this mod.
@@ -77,14 +82,15 @@ public AssetBundle Assets
7782
}
7883

7984

80-
protected SFSMod(string name, string author, string modLoderVersion, string version, string description = "", string assetsFilename = null /*,Type[] dependencies = null*/ )
85+
protected SFSMod(string id,string name, string author, string modLoderVersion, string version, string description = "", string assetsFilename = null , SFSModDependencie[] dependencies = null )
8186
{
87+
_modId = id;
8288
_name = name;
8389
_author = author;
8490
_modLoderVersion = modLoderVersion;
8591
_version = version;
8692
_description = description;
87-
//_dependencies = dependencies;
93+
_dependencies = dependencies;
8894
_assetsFilename = assetsFilename;
8995
}
9096

ModLoader/SFSModDependencie.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
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
8+
{
9+
public class SFSModDependencie
10+
{
11+
private string _modid;
12+
private string[] _versions;
13+
14+
public string ModId
15+
{
16+
get { return this._modid; }
17+
}
18+
19+
public string[] Versions
20+
{
21+
get { return this._versions; }
22+
}
23+
24+
public SFSModDependencie(string modid, string[] versions)
25+
{
26+
this._modid = modid;
27+
this._versions = versions;
28+
}
29+
}
30+
}

0 commit comments

Comments
 (0)