Elin Decompiled Documentation EA 23.318 Nightly
Loading...
Searching...
No Matches
ModManager.cs
Go to the documentation of this file.
1using System;
2using System.Collections;
3using System.Collections.Generic;
4using System.IO;
5using System.Linq;
6using HeathenEngineering.SteamworksIntegration;
7using HeathenEngineering.SteamworksIntegration.API;
8using IniParser.Model;
9using Steamworks;
10using UnityEngine;
11
12[Serializable]
13public class ModManager : ModManagerCore
14{
15 public static List<object> ListPluginObject = new List<object>();
16
17 public static bool disableMod;
18
20
21 public List<FileInfo> replaceFiles = new List<FileInfo>();
22
23 public static List<string> ListChainLoad => BaseModManager.listChainLoad;
24
25 public static DirectoryInfo DirWorkshop => Instance.dirWorkshop;
26
28
30
31 public override void Init(string path, string defaultPackage = "_Elona")
32 {
33 base.Init(path, defaultPackage);
34 Debug.Log("IsOffline:" + BaseCore.IsOffline);
35 IniData elinIni = Core.GetElinIni();
36 if (elinIni != null)
37 {
39 {
40 string key = elinIni.GetKey("path_workshop");
41 if (!key.IsEmpty())
42 {
43 dirWorkshop = new DirectoryInfo(key);
44 }
45 }
46 else
47 {
48 string path2 = Path.Combine(App.Client.GetAppInstallDirectory(SteamSettings.behaviour.settings.applicationId), "../../workshop/content/2135150");
49 dirWorkshop = new DirectoryInfo(path2);
50 elinIni.Global["path_workshop"] = dirWorkshop.FullName;
51 Core.SaveElinIni(elinIni);
52 }
53 }
54 if ((!(dirWorkshop?.Exists)) ?? true)
55 {
56 dirWorkshop = null;
57 }
58 Debug.Log("Workshop:" + dirWorkshop);
59 Debug.Log("Packages:" + BaseModManager.rootMod);
60 Debug.Log("Core Mod:" + BaseModManager.rootDefaultPacakge);
61 }
62
63 public void SaveLoadOrder()
64 {
65 if (!disableMod)
66 {
67 List<string> contents = (from p in packages
68 where !p.builtin && p.dirInfo.Exists
69 select $"{p.dirInfo.FullName},{(p.willActivate ? 1 : 0)}").ToList();
70 File.WriteAllLines(CorePath.rootExe + "loadorder.txt", contents);
71 }
72 }
73
74 public void LoadLoadOrder()
75 {
76 string path = CorePath.rootExe + "loadorder.txt";
77 if (!File.Exists(path))
78 {
79 return;
80 }
81 Dictionary<string, BaseModPackage> dictionary = new Dictionary<string, BaseModPackage>();
82 foreach (BaseModPackage package in packages)
83 {
84 if (!package.builtin)
85 {
86 dictionary[package.dirInfo.FullName] = package;
87 }
88 }
89 int num = 0;
90 string[] array = File.ReadAllLines(path);
91 for (int i = 0; i < array.Length; i++)
92 {
93 string[] array2 = array[i].Split(',');
94 if (dictionary.TryGetValue(array2[0], out var value))
95 {
96 value.loadPriority = num;
97 value.willActivate = array2[1] == "1";
98 }
99 num++;
100 }
101 }
102
103 public IEnumerator RefreshMods(Action onComplete, bool syncMods)
104 {
105 bool flag = !BaseCore.IsOffline && syncMods && UserGeneratedContent.Client.GetNumSubscribedItems() != 0;
106 _loading = Util.Instantiate<LoadingScreen>("LoadingScreen");
107 WaitForEndOfFrame awaiter = new WaitForEndOfFrame();
108 packages.Clear();
109 disableMod |= Application.isEditor && EClass.debug.skipMod;
112 if (!disableMod && dirWorkshop != null)
113 {
114 _loading.Log("Loading workshop contents...");
115 if (flag)
116 {
117 yield return LoadWorkshopPackages();
118 }
119 else
120 {
121 DirectoryInfo[] directories = dirWorkshop.GetDirectories();
122 foreach (DirectoryInfo dir in directories)
123 {
124 AddPackage(dir);
125 }
126 }
127 }
130 packages.Sort((BaseModPackage a, BaseModPackage b) => a.loadPriority - b.loadPriority);
131 foreach (BaseModPackage item in packages.Where((BaseModPackage p) => !p.isInPackages && p.willActivate && !p.id.IsEmpty()))
132 {
133 if (mappedPackages.TryGetValue(item.id, out var value) && value.isInPackages)
134 {
135 value.hasPublishedPackage = true;
136 }
137 }
138 _loading.Log($"Total number of mods:{packages.Count}");
139 _loading.Log("Activating Mods...");
140 yield return awaiter;
142 foreach (BaseModPackage package in packages)
143 {
144 if (package.activated)
145 {
146 mappedPackages[package.id] = package as ModPackage;
147 }
148 }
149 BaseModManager.isInitialized = true;
150 yield return awaiter;
151 onComplete?.Invoke();
152 if ((bool)_loading)
153 {
154 UnityEngine.Object.Destroy(_loading.gameObject);
155 }
156 yield return null;
157 }
158
159 public ModPackage AddPackage(DirectoryInfo dir, bool isInPackages = false)
160 {
161 ModPackage modPackage = new ModPackage
162 {
163 dirInfo = new DirectoryInfo(dir.FullName.NormalizePath()),
164 installed = true,
165 isInPackages = isInPackages,
166 loadPriority = priorityIndex,
167 Mapping = new FileMapping(dir)
168 };
169 packages.Add(modPackage);
170 priorityIndex++;
171 return modPackage;
172 }
173
174 public ModPackage AddWorkshopPackage(WorkshopItem item, bool isInPackages = false)
175 {
176 bool itemInstallInfo = UserGeneratedContent.Client.GetItemInstallInfo(item.FileId, out var _, out var folderPath, out var _);
177 if (folderPath == null)
178 {
179 folderPath = Path.Combine(DirWorkshop.FullName, item.FileId.ToString());
180 }
181 DirectoryInfo directoryInfo = new DirectoryInfo(folderPath);
182 itemInstallInfo &= directoryInfo.Exists;
183 ModPackage modPackage = AddPackage(directoryInfo, isInPackages);
184 modPackage.installed = itemInstallInfo;
185 modPackage.banned = item.IsBanned;
186 modPackage.workshopId = item.FileId.ToString();
187 modPackage.item = item;
188 return modPackage;
189 }
190
191 public int CountUserMod()
192 {
193 return packages.Count((BaseModPackage p) => !p.builtin);
194 }
195
196 public void LoadLocalPackages()
197 {
198 _loading.Log("Loading local Package...");
199 DirectoryInfo[] directories = new DirectoryInfo(BaseModManager.rootMod).GetDirectories();
200 Array.Reverse(directories);
201 DirectoryInfo[] array = directories;
202 foreach (DirectoryInfo directoryInfo in array)
203 {
204 if (!disableMod || !(directoryInfo.Name != "_Elona") || !(directoryInfo.Name != "_Lang_Chinese"))
205 {
206 if (directoryInfo.Name == "Mod_FixedPackageLoader")
207 {
208 IO.DeleteDirectory(directoryInfo.FullName);
209 }
210 else
211 {
212 AddPackage(directoryInfo, isInPackages: true);
213 }
214 }
215 }
216 }
217
218 public void LoadCustomPackage()
219 {
220 _loading.Log("Loading user Custom...");
221 DirectoryInfo[] directories = new DirectoryInfo(CorePath.custom).GetDirectories();
222 ModPackage package = new ModPackage();
223 DirectoryInfo[] array = directories;
224 foreach (DirectoryInfo dir in array)
225 {
226 ParseExtra(dir, package);
227 }
228 }
229
230 public IEnumerator LoadWorkshopPackages()
231 {
232 WaitForEndOfFrame awaiter = new WaitForEndOfFrame();
233 UgcQuery activeQuery = UgcQuery.GetSubscribed(withLongDescription: false, withMetadata: false, withKeyValueTags: false, withAdditionalPreviews: false, 0u);
234 activeQuery.Execute(HandleWorkshopQuery);
235 _loading.Log("Fetching subscriptions...(Hit ESC to cancel)");
236 while (activeQuery.handle != UGCQueryHandle_t.Invalid && !UnityEngine.Input.GetKey(KeyCode.Escape))
237 {
238 yield return awaiter;
239 }
240 yield return UpdateWorkshopPackages();
241 void HandleWorkshopQuery(UgcQuery query)
242 {
243 foreach (WorkshopItem results in query.ResultsList)
244 {
245 AddWorkshopPackage(results);
246 }
247 }
248 }
249
250 private IEnumerator UpdateWorkshopPackages()
251 {
252 _loading?.Log("Updating subscriptions...");
253 WaitForEndOfFrame awaiter = new WaitForEndOfFrame();
254 while (true)
255 {
256 bool flag = false;
257 foreach (BaseModPackage item in packages.Where((BaseModPackage p) => !p.installed))
258 {
259 if (!(item.item is WorkshopItem { IsBanned: false } workshopItem))
260 {
261 continue;
262 }
263 flag = true;
264 string text = "Downloading " + workshopItem.Title + ": ";
265 BaseModPackage baseModPackage = item;
266 if ((object)baseModPackage.progressText == null)
267 {
268 baseModPackage.progressText = _loading?.Log(text);
269 }
270 if (item.downloadStarted && workshopItem.DownloadCompletion >= 1f)
271 {
272 item.installed = true;
273 if ((bool)item.progressText)
274 {
275 item.progressText.text = text + "Done!";
276 }
277 }
278 else if (workshopItem.IsDownloading || workshopItem.IsDownloadPending)
279 {
280 int num = Mathf.FloorToInt(workshopItem.DownloadCompletion * 100f);
281 if ((bool)item.progressText)
282 {
283 item.progressText.text = text + num + "%";
284 }
285 }
286 else if (!item.downloadStarted)
287 {
288 item.downloadStarted = true;
289 workshopItem.DownloadItem(highPriority: true);
290 Debug.Log("Start downloading: " + workshopItem.Title + " | " + $"Installed={workshopItem.IsInstalled}, " + $"Downloading={workshopItem.IsDownloading}, " + $"Pending={workshopItem.IsDownloadPending}");
291 }
292 }
293 if (!flag)
294 {
295 yield break;
296 }
297 if (UnityEngine.Input.GetKey(KeyCode.Escape))
298 {
299 break;
300 }
301 yield return awaiter;
302 }
303 Debug.Log("Workshop updating cancelled");
304 }
305
306 public void InitPackagesMeta()
307 {
308 foreach (BaseModPackage package in packages)
309 {
310 try
311 {
312 if (package.Init())
313 {
314 mappedPackages[package.id] = package as ModPackage;
315 }
316 _loading?.Log(package.ToString());
317 }
318 catch (Exception ex)
319 {
320 package.willActivate = false;
321 _loading?.Log("Mod " + package.title + "/" + package.id + " has failed to initialize, reason: " + ex.Message);
322 }
323 }
324 }
325
326 public void ActivatePackages()
327 {
329 ListPluginObject.Clear();
330 foreach (ModPackage package in packages)
331 {
332 if ((disableMod && !package.builtin) || !package.IsValidVersion())
333 {
334 continue;
335 }
336 try
337 {
338 package.Activate();
339 if (package.activated)
340 {
341 BaseModManager.listChainLoad.Add(package.dirInfo.FullName);
342 }
343 }
344 catch (Exception ex)
345 {
346 _loading.Log("Failed to activate mod: " + package.title + ", reason: " + ex.Message);
347 }
348 }
349 ModUtil.OnModsActivated();
350 ModUtil.LoadTypeFallback();
351 }
352
353 public override void ParseExtra(DirectoryInfo dir, BaseModPackage package)
354 {
355 ModPackage modPackage = (ModPackage)package;
356 switch (dir.Name.ToLower())
357 {
358 case "talktext":
359 modPackage.ParseTalkText(dir);
360 break;
361 case "map":
362 if (!package.builtin)
363 {
364 modPackage.ParseMap(dir);
365 }
366 break;
367 case "map piece":
368 if (!package.builtin)
369 {
370 modPackage.ParseMapPiece(dir);
371 }
372 break;
373 case "texture replace":
374 replaceFiles.AddRange(modPackage.ParseTextureReplace(dir));
375 break;
376 case "texture":
377 modPackage.ParseTexture(dir);
378 break;
379 case "portrait":
380 modPackage.ParsePortrait(dir);
381 break;
382 case "langmod":
383 modPackage.ParseLangMod(dir);
384 break;
385 case "sound":
386 modPackage.ParseSound(dir);
387 break;
388 case "lang":
389 modPackage.AddOrUpdateLang(dir);
390 break;
391 }
392 }
393}
$
Definition: ModManager.cs:74
static bool IsOffline
Definition: BaseCore.cs:9
static bool isInitialized
static string rootDefaultPacakge
static BaseModManager Instance
static string rootMod
static List< string > listChainLoad
DirectoryInfo dirInfo
bool skipMod
Definition: CoreDebug.cs:149
static string custom
Definition: CorePath.cs:159
static string rootExe
Definition: CorePath.cs:168
Definition: Core.cs:14
static void SaveElinIni(IniData ini)
Definition: Core.cs:814
static IniData GetElinIni()
Definition: Core.cs:780
Definition: EClass.cs:6
static CoreDebug debug
Definition: EClass.cs:49
Text Log(string s)
static new ModManager Instance
Definition: ModManager.cs:27
override void ParseExtra(DirectoryInfo dir, BaseModPackage package)
Definition: ModManager.cs:353
LoadingScreen _loading
Definition: ModManager.cs:19
static bool IsInitialized
Definition: ModManager.cs:29
static List< string > ListChainLoad
Definition: ModManager.cs:23
void ActivatePackages()
Definition: ModManager.cs:326
List< FileInfo > replaceFiles
Definition: ModManager.cs:21
void LoadLoadOrder()
Definition: ModManager.cs:74
ModPackage AddWorkshopPackage(WorkshopItem item, bool isInPackages=false)
Definition: ModManager.cs:174
IEnumerator UpdateWorkshopPackages()
Definition: ModManager.cs:250
override void Init(string path, string defaultPackage="_Elona")
Definition: ModManager.cs:31
void LoadCustomPackage()
Definition: ModManager.cs:218
IEnumerator RefreshMods(Action onComplete, bool syncMods)
Definition: ModManager.cs:103
static bool disableMod
Definition: ModManager.cs:17
IEnumerator LoadWorkshopPackages()
Definition: ModManager.cs:230
void LoadLocalPackages()
Definition: ModManager.cs:196
ModPackage AddPackage(DirectoryInfo dir, bool isInPackages=false)
Definition: ModManager.cs:159
static List< object > ListPluginObject
Definition: ModManager.cs:15
int CountUserMod()
Definition: ModManager.cs:191
void SaveLoadOrder()
Definition: ModManager.cs:63
static DirectoryInfo DirWorkshop
Definition: ModManager.cs:25
void InitPackagesMeta()
Definition: ModManager.cs:306
IReadOnlyList< FileInfo > ParseTalkText(DirectoryInfo dir)
Definition: ModPackage.cs:26
void ParseLangMod(DirectoryInfo dir)
Definition: ModPackage.cs:161
IReadOnlyList< FileInfo > ParseTexture(DirectoryInfo dir)
Definition: ModPackage.cs:103
void AddOrUpdateLang(DirectoryInfo dir)
Definition: ModPackage.cs:335
IReadOnlyList< FileInfo > ParseMapPiece(DirectoryInfo dir, bool addToList=true)
Definition: ModPackage.cs:65
IReadOnlyList< FileInfo > ParseTextureReplace(DirectoryInfo dir)
Definition: ModPackage.cs:86
IReadOnlyList< FileInfo > ParsePortrait(DirectoryInfo dir)
Definition: ModPackage.cs:123
IReadOnlyList< FileInfo > ParseMap(DirectoryInfo dir, bool addToList=true)
Definition: ModPackage.cs:44
IReadOnlyList< FileInfo > ParseSound(DirectoryInfo dir)
Definition: ModPackage.cs:176