Elin Decompiled Documentation EA 23.286 Nightly Patch 1
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 Newtonsoft.Json;
10using Steamworks;
11using UnityEngine;
12
13[Serializable]
14public class ModManager : ModManagerCore
15{
16 public static List<object> ListPluginObject = new List<object>();
17
18 public static bool disableMod;
19
21
22 public List<FileInfo> replaceFiles = new List<FileInfo>();
23
24 private Action ImportModGodTalks;
25
26 public static List<string> ListChainLoad => BaseModManager.listChainLoad;
27
28 public static DirectoryInfo DirWorkshop => Instance.dirWorkshop;
29
31
33
34 public override void Init(string path, string defaultPackage = "_Elona")
35 {
36 base.Init(path, defaultPackage);
37 Debug.Log("IsOffline:" + BaseCore.IsOffline);
38 IniData elinIni = Core.GetElinIni();
39 if (elinIni != null)
40 {
42 {
43 string key = elinIni.GetKey("path_workshop");
44 if (!key.IsEmpty())
45 {
46 dirWorkshop = new DirectoryInfo(key);
47 }
48 }
49 else
50 {
51 string path2 = Path.Combine(App.Client.GetAppInstallDirectory(SteamSettings.behaviour.settings.applicationId), "../../workshop/content/2135150");
52 dirWorkshop = new DirectoryInfo(path2);
53 elinIni.Global["path_workshop"] = dirWorkshop.FullName;
54 Core.SaveElinIni(elinIni);
55 }
56 }
57 if (!dirWorkshop.Exists)
58 {
59 dirWorkshop = null;
60 }
61 Debug.Log("Workshop:" + dirWorkshop);
62 Debug.Log("Packages:" + BaseModManager.rootMod);
63 Debug.Log("Core Mod:" + BaseModManager.rootDefaultPacakge);
64 BaseModManager.SubscribeEvent("elin.source.lang_set", delegate(object lang)
65 {
66 if (ModManagerCore.useLocalizations)
67 {
68 ImportSourceLocalizations(lang as string);
69 }
71 });
72 }
73
74 public void SaveLoadOrder()
75 {
76 if (!disableMod)
77 {
78 List<string> contents = (from p in packages
79 where !p.builtin && p.dirInfo.Exists
80 select $"{p.dirInfo.FullName},{(p.willActivate ? 1 : 0)}").ToList();
81 File.WriteAllLines(CorePath.rootExe + "loadorder.txt", contents);
82 }
83 }
84
85 public void LoadLoadOrder()
86 {
87 string path = CorePath.rootExe + "loadorder.txt";
88 if (!File.Exists(path))
89 {
90 return;
91 }
92 Dictionary<string, BaseModPackage> dictionary = new Dictionary<string, BaseModPackage>();
93 foreach (BaseModPackage package in packages)
94 {
95 if (!package.builtin)
96 {
97 dictionary[package.dirInfo.FullName] = package;
98 }
99 }
100 int num = 0;
101 string[] array = File.ReadAllLines(path);
102 for (int i = 0; i < array.Length; i++)
103 {
104 string[] array2 = array[i].Split(',');
105 if (dictionary.TryGetValue(array2[0], out var value))
106 {
107 value.loadPriority = num;
108 value.willActivate = array2[1] == "1";
109 }
110 num++;
111 }
112 }
113
114 public void ImportSourceLocalizations(string lang)
115 {
116 string text = lang + "/SourceLocalization.json";
117 (FileInfo file, EMod package)[] filesEx = PackageIterator.GetFilesEx(text);
118 SortedDictionary<string, string> sortedDictionary = new SortedDictionary<string, string>();
119 Dictionary<string, SortedDictionary<string, string>> dictionary = new Dictionary<string, SortedDictionary<string, string>>();
120 (FileInfo, EMod)[] array = filesEx;
121 string key;
122 string value;
123 for (int i = 0; i < array.Length; i++)
124 {
125 var (fileInfo, eMod) = array[i];
126 try
127 {
128 SortedDictionary<string, string> sortedDictionary2 = IO.LoadFile<SortedDictionary<string, string>>(fileInfo.FullName);
129 foreach (KeyValuePair<string, string> item in sortedDictionary2)
130 {
131 item.Deconstruct(out key, out value);
132 string key2 = key;
133 string value2 = value;
134 sortedDictionary[key2] = value2;
135 }
136 dictionary[eMod.id] = sortedDictionary2;
137 }
138 catch (Exception arg)
139 {
140 Debug.LogError($"#source localization failed to load {fileInfo.ShortPath()}\n{arg}");
141 }
142 }
143 JsonSerializerSettings setting = new JsonSerializerSettings
144 {
145 PreserveReferencesHandling = PreserveReferencesHandling.None,
146 NullValueHandling = NullValueHandling.Ignore
147 };
148 foreach (EMod value4 in base.MappedPackages.Values)
149 {
150 if (!(value4 is ModPackage modPackage) || value4.builtin || !value4.activated)
151 {
152 continue;
153 }
154 HashSet<SourceData.BaseRow> sourceRows = value4.sourceRows;
155 if (sourceRows == null || sourceRows.Count <= 0)
156 {
157 continue;
158 }
159 modPackage.ImportSourceLocalizations(sortedDictionary);
160 if (!ModManagerCore.generateLocalizations || (!modPackage.isInPackages && !Application.isEditor))
161 {
162 continue;
163 }
164 if (Lang.IsBuiltin(lang))
165 {
166 break;
167 }
168 try
169 {
170 SortedDictionary<string, string> sortedDictionary3 = dictionary.GetValueOrDefault(modPackage.id) ?? new SortedDictionary<string, string>();
171 SortedDictionary<string, string> sortedDictionary4 = modPackage.ExportSourceLocalizations();
172 SortedDictionary<string, string> final = new SortedDictionary<string, string>();
173 foreach (KeyValuePair<string, string> item2 in sortedDictionary4)
174 {
175 item2.Deconstruct(out value, out key);
176 string key3 = value;
177 string defaultValue = key;
178 final[key3] = sortedDictionary3.GetValueOrDefault(key3, defaultValue);
179 }
180 if (sortedDictionary3.Count != final.Count || sortedDictionary3.Any((KeyValuePair<string, string> kv) => !final.TryGetValue(kv.Key, out var value3) || value3 != kv.Value))
181 {
182 IO.SaveFile(Path.Combine(modPackage.dirInfo.FullName, "LangMod", text), final, compress: false, setting);
183 Debug.Log($"#source localization updated {text} / {modPackage}");
184 }
185 }
186 catch (Exception arg2)
187 {
188 Debug.LogError($"#source localization failed to generate {modPackage}\n{arg2}");
189 }
190 }
191 }
192
194 {
195 try
196 {
197 SourceCache.InvalidateCacheVersion();
199 {
201 EClass.sources.materials
202 });
203 List<string> list = new List<string>();
204 foreach (EMod value in base.MappedPackages.Values)
205 {
206 if (value.builtin || !value.activated)
207 {
208 continue;
209 }
210 foreach (FileInfo sourceSheet in value.Mapping.SourceSheets)
211 {
212 if (!sourceSheet.Name.StartsWith(".") && !sourceSheet.Name.Contains("~"))
213 {
214 ModUtil.sourceImporter.fileProviders[sourceSheet.FullName] = value;
215 list.Add(sourceSheet.FullName);
216 }
217 }
218 }
220 SourceCache.FinalizeCache();
221 SourceCache.InvalidateCacheBlobs();
222 SourceCache.ClearDetail();
223 }
224 catch (Exception message)
225 {
226 Debug.LogError(message);
227 }
228 Debug.Log("#source finished importing workbooks");
229 }
230
232 {
233 Lang.extraExcelDialogs = new HashSet<string>(PathComparer.Default);
234 Lang.excelDialog = null;
235 FileInfo[] files = PackageIterator.GetFiles("Dialog/dialog.xlsx");
236 foreach (FileInfo fileInfo in files)
237 {
238 Lang.extraExcelDialogs.Add(fileInfo.FullName);
239 Debug.Log("#dialog loaded " + fileInfo.ShortPath());
240 }
241 }
242
244 {
245 if (Lang.setting?.dir == null)
246 {
247 return;
248 }
249 Dictionary<string, Dictionary<string, string>> map = EClass.sources.dataGodTalk.sheets["_default"].map;
250 foreach (ExcelData item in from f in PackageIterator.GetFiles("Data/god_talk.xlsx")
251 select new ExcelData(f.FullName, 3))
252 {
253 foreach (KeyValuePair<string, Dictionary<string, string>> item2 in map)
254 {
255 item2.Deconstruct(out var key, out var _);
256 string text = key;
257 if (text.IsEmpty())
258 {
259 continue;
260 }
261 Dictionary<string, string> valueOrDefault = item.sheets["_default"].map.GetValueOrDefault(text);
262 if (valueOrDefault == null)
263 {
264 continue;
265 }
266 foreach (KeyValuePair<string, string> item3 in valueOrDefault)
267 {
268 item3.Deconstruct(out key, out var value2);
269 string text2 = key;
270 string value3 = value2;
271 if (text2 != "id")
272 {
273 map[text][text2] = value3;
274 }
275 }
276 }
277 Debug.Log("#dialog loaded " + item.path.ShortPath());
278 }
279 }
280
281 public IEnumerator RefreshMods(Action onComplete, bool syncMods)
282 {
283 bool flag = !BaseCore.IsOffline && syncMods && UserGeneratedContent.Client.GetNumSubscribedItems() != 0;
284 _loading = Util.Instantiate<LoadingScreen>("LoadingScreen");
285 WaitForEndOfFrame awaiter = new WaitForEndOfFrame();
286 packages.Clear();
287 disableMod |= Application.isEditor && EClass.debug.skipMod;
290 if (!disableMod)
291 {
292 _loading.Log("Loading workshop contents...");
293 if (flag)
294 {
295 yield return LoadWorkshopPackages();
296 }
297 else if (dirWorkshop != null)
298 {
299 DirectoryInfo[] directories = dirWorkshop.GetDirectories();
300 foreach (DirectoryInfo dir in directories)
301 {
302 AddPackage(dir);
303 }
304 }
305 }
308 packages.Sort((BaseModPackage a, BaseModPackage b) => a.loadPriority - b.loadPriority);
309 foreach (BaseModPackage item in packages.Where((BaseModPackage p) => !p.isInPackages && p.willActivate && !p.id.IsEmpty()))
310 {
311 if (mappedPackages.TryGetValue(item.id, out var value) && value.isInPackages)
312 {
313 value.hasPublishedPackage = true;
314 }
315 }
316 _loading.Log($"Total number of mods:{packages.Count}");
317 _loading.Log("Activating Mods...");
318 yield return awaiter;
320 foreach (BaseModPackage package in packages)
321 {
322 if (package.activated)
323 {
324 mappedPackages[package.id] = package as ModPackage;
325 }
326 }
327 BaseModManager.isInitialized = true;
328 yield return awaiter;
329 onComplete?.Invoke();
330 if ((bool)_loading)
331 {
332 UnityEngine.Object.Destroy(_loading.gameObject);
333 }
334 yield return null;
335 }
336
337 public ModPackage AddPackage(DirectoryInfo dir, bool isInPackages = false)
338 {
339 ModPackage modPackage = new ModPackage
340 {
341 dirInfo = dir,
342 installed = true,
343 isInPackages = isInPackages,
344 loadPriority = priorityIndex,
345 Mapping = new FileMapping(dir)
346 };
347 packages.Add(modPackage);
348 priorityIndex++;
349 return modPackage;
350 }
351
352 public ModPackage AddWorkshopPackage(WorkshopItem item, bool isInPackages = false)
353 {
354 ulong sizeOnDisk;
355 string folderPath;
356 DateTime timeStamp;
357 bool itemInstallInfo = UserGeneratedContent.Client.GetItemInstallInfo(item.FileId, out sizeOnDisk, out folderPath, out timeStamp);
358 DirectoryInfo dir = new DirectoryInfo(folderPath);
359 ModPackage modPackage = AddPackage(dir, isInPackages);
360 modPackage.installed = itemInstallInfo;
361 modPackage.banned = item.IsBanned;
362 return modPackage;
363 }
364
365 public int CountUserMod()
366 {
367 return packages.Count((BaseModPackage p) => !p.builtin);
368 }
369
370 public void LoadLocalPackages()
371 {
372 _loading.Log("Loading local Package...");
373 DirectoryInfo[] directories = new DirectoryInfo(BaseModManager.rootMod).GetDirectories();
374 Array.Reverse(directories);
375 DirectoryInfo[] array = directories;
376 foreach (DirectoryInfo directoryInfo in array)
377 {
378 if (!disableMod || !(directoryInfo.Name != "_Elona") || !(directoryInfo.Name != "_Lang_Chinese"))
379 {
380 AddPackage(directoryInfo, isInPackages: true);
381 }
382 }
383 }
384
385 public void LoadCustomPackage()
386 {
387 _loading.Log("Loading user Custom...");
388 DirectoryInfo[] directories = new DirectoryInfo(CorePath.custom).GetDirectories();
389 ModPackage package = new ModPackage();
390 DirectoryInfo[] array = directories;
391 foreach (DirectoryInfo dir in array)
392 {
393 ParseExtra(dir, package);
394 }
395 }
396
397 public IEnumerator LoadWorkshopPackages()
398 {
399 WaitForEndOfFrame awaiter = new WaitForEndOfFrame();
400 UgcQuery activeQuery = UgcQuery.GetSubscribed(withLongDescription: false, withMetadata: false, withKeyValueTags: false, withAdditionalPreviews: false, 0u);
401 activeQuery.Execute(HandleWorkshopQuery);
402 _loading.Log("Fetching subscriptions...(Hit ESC to cancel)");
403 while (activeQuery.handle != UGCQueryHandle_t.Invalid && !UnityEngine.Input.GetKey(KeyCode.Escape))
404 {
405 yield return awaiter;
406 }
407 yield return UpdateWorkshopPackages();
408 void HandleWorkshopQuery(UgcQuery query)
409 {
410 foreach (WorkshopItem results in query.ResultsList)
411 {
412 AddWorkshopPackage(results);
413 }
414 }
415 }
416
417 private IEnumerator UpdateWorkshopPackages()
418 {
419 _loading?.Log("Updating subscriptions...");
420 WaitForEndOfFrame awaiter = new WaitForEndOfFrame();
421 while (true)
422 {
423 bool flag = false;
424 foreach (BaseModPackage item in packages.Where((BaseModPackage p) => !p.installed))
425 {
426 if (!(item.item is WorkshopItem { IsBanned: false } workshopItem))
427 {
428 continue;
429 }
430 flag = true;
431 string text = "Downloading " + workshopItem.Title + ": ";
432 BaseModPackage baseModPackage = item;
433 if ((object)baseModPackage.progressText == null)
434 {
435 baseModPackage.progressText = _loading?.Log(text);
436 }
437 if (item.downloadStarted && workshopItem.DownloadCompletion >= 1f)
438 {
439 item.installed = true;
440 if ((bool)item.progressText)
441 {
442 item.progressText.text = text + "Done!";
443 }
444 }
445 else if (workshopItem.IsDownloading || workshopItem.IsDownloadPending)
446 {
447 int num = Mathf.FloorToInt(workshopItem.DownloadCompletion * 100f);
448 if ((bool)item.progressText)
449 {
450 item.progressText.text = text + num + "%";
451 }
452 }
453 else if (!item.downloadStarted)
454 {
455 item.downloadStarted = true;
456 workshopItem.DownloadItem(highPriority: true);
457 Debug.Log("Start downloading: " + workshopItem.Title + " | " + $"Installed={workshopItem.IsInstalled}, " + $"Downloading={workshopItem.IsDownloading}, " + $"Pending={workshopItem.IsDownloadPending}");
458 }
459 }
460 if (!flag)
461 {
462 yield break;
463 }
464 if (UnityEngine.Input.GetKey(KeyCode.Escape))
465 {
466 break;
467 }
468 yield return awaiter;
469 }
470 Debug.Log("Workshop updating cancelled");
471 }
472
473 public void InitPackagesMeta()
474 {
475 foreach (BaseModPackage package in packages)
476 {
477 try
478 {
479 package.Init();
480 mappedPackages[package.id] = package as ModPackage;
481 _loading?.Log(package.ToString());
482 }
483 catch (Exception ex)
484 {
485 package.willActivate = false;
486 _loading?.Log("Mod " + package.title + "/" + package.id + " has failed to initialize, reason: " + ex.Message);
487 }
488 }
489 }
490
491 public void ActivatePackages()
492 {
494 ListPluginObject.Clear();
495 foreach (ModPackage package in packages)
496 {
497 if ((disableMod && !package.builtin) || !package.IsValidVersion())
498 {
499 continue;
500 }
501 try
502 {
503 package.Activate();
504 if (package.activated)
505 {
506 BaseModManager.listChainLoad.Add(package.dirInfo.FullName);
507 }
508 }
509 catch (Exception ex)
510 {
511 _loading.Log("Failed to activate mod: " + package.title + ", reason: " + ex.Message);
512 }
513 }
516 }
517
518 public override void ParseExtra(DirectoryInfo dir, BaseModPackage package)
519 {
520 ModPackage modPackage = (ModPackage)package;
521 switch (dir.Name)
522 {
523 case "TalkText":
524 modPackage.ParseTalkText(dir);
525 break;
526 case "Map":
527 if (!package.builtin)
528 {
529 modPackage.ParseMap(dir);
530 }
531 break;
532 case "Map Piece":
533 if (!package.builtin)
534 {
535 modPackage.ParseMapPiece(dir);
536 }
537 break;
538 case "Texture Replace":
539 replaceFiles.AddRange(modPackage.ParseTextureReplace(dir));
540 break;
541 case "Texture":
542 modPackage.ParseTexture(dir);
543 break;
544 case "Portrait":
545 modPackage.ParsePortrait(dir);
546 break;
547 case "LangMod":
548 modPackage.ParseLangMod(dir);
549 break;
550 case "Sound":
551 modPackage.ParseSound(dir);
552 break;
553 case "Lang":
554 modPackage.AddOrUpdateLang(dir);
555 break;
556 }
557 }
558}
$
Definition: ModManager.cs:85
static bool IsOffline
Definition: BaseCore.cs:9
static bool isInitialized
static string rootDefaultPacakge
static BaseModManager Instance
static string rootMod
static List< string > listChainLoad
static void SubscribeEvent(string eventId, Action< object > handler)
DirectoryInfo dirInfo
bool skipMod
Definition: CoreDebug.cs:134
static string custom
Definition: CorePath.cs:167
static string rootExe
Definition: CorePath.cs:176
Definition: Core.cs:14
static void SaveElinIni(IniData ini)
Definition: Core.cs:813
static IniData GetElinIni()
Definition: Core.cs:779
Definition: EClass.cs:6
static SourceManager sources
Definition: EClass.cs:43
static CoreDebug debug
Definition: EClass.cs:49
Dictionary< string, Sheet > sheets
Definition: ExcelData.cs:25
string dir
Definition: LangSetting.cs:28
Definition: Lang.cs:7
static LangSetting setting
Definition: Lang.cs:55
static bool IsBuiltin(string id)
Definition: Lang.cs:65
static HashSet< string > extraExcelDialogs
Definition: Lang.cs:63
Text Log(string s)
void ImportAllModSourceSheets()
Definition: ModManager.cs:193
static new ModManager Instance
Definition: ModManager.cs:30
override void ParseExtra(DirectoryInfo dir, BaseModPackage package)
Definition: ModManager.cs:518
LoadingScreen _loading
Definition: ModManager.cs:20
void ImportAllModDialogs()
Definition: ModManager.cs:231
static bool IsInitialized
Definition: ModManager.cs:32
void ImportSourceLocalizations(string lang)
Definition: ModManager.cs:114
Action ImportModGodTalks
Definition: ModManager.cs:24
static List< string > ListChainLoad
Definition: ModManager.cs:26
void ActivatePackages()
Definition: ModManager.cs:491
List< FileInfo > replaceFiles
Definition: ModManager.cs:22
void ImportAllModGodTalks()
Definition: ModManager.cs:243
void LoadLoadOrder()
Definition: ModManager.cs:85
ModPackage AddWorkshopPackage(WorkshopItem item, bool isInPackages=false)
Definition: ModManager.cs:352
IEnumerator UpdateWorkshopPackages()
Definition: ModManager.cs:417
override void Init(string path, string defaultPackage="_Elona")
Definition: ModManager.cs:34
void LoadCustomPackage()
Definition: ModManager.cs:385
IEnumerator RefreshMods(Action onComplete, bool syncMods)
Definition: ModManager.cs:281
static bool disableMod
Definition: ModManager.cs:18
IEnumerator LoadWorkshopPackages()
Definition: ModManager.cs:397
void LoadLocalPackages()
Definition: ModManager.cs:370
ModPackage AddPackage(DirectoryInfo dir, bool isInPackages=false)
Definition: ModManager.cs:337
static List< object > ListPluginObject
Definition: ModManager.cs:16
int CountUserMod()
Definition: ModManager.cs:365
void SaveLoadOrder()
Definition: ModManager.cs:74
static DirectoryInfo DirWorkshop
Definition: ModManager.cs:28
void InitPackagesMeta()
Definition: ModManager.cs:473
IReadOnlyList< FileInfo > ParseTalkText(DirectoryInfo dir)
Definition: ModPackage.cs:18
void ParseLangMod(DirectoryInfo dir)
Definition: ModPackage.cs:153
IReadOnlyList< FileInfo > ParseTexture(DirectoryInfo dir)
Definition: ModPackage.cs:95
void AddOrUpdateLang(DirectoryInfo dir)
Definition: ModPackage.cs:237
IReadOnlyList< FileInfo > ParseMapPiece(DirectoryInfo dir, bool addToList=true)
Definition: ModPackage.cs:57
IReadOnlyList< FileInfo > ParseTextureReplace(DirectoryInfo dir)
Definition: ModPackage.cs:78
IReadOnlyList< FileInfo > ParsePortrait(DirectoryInfo dir)
Definition: ModPackage.cs:115
IReadOnlyList< FileInfo > ParseMap(DirectoryInfo dir, bool addToList=true)
Definition: ModPackage.cs:36
IReadOnlyList< FileInfo > ParseSound(DirectoryInfo dir)
Definition: ModPackage.cs:168
static SourceImporter sourceImporter
Definition: ModUtil.cs:15
static void OnModsActivated()
Definition: ModUtil.cs:23
static void LoadTypeFallback()
Definition: ModUtil.cs:29
IEnumerable< SourceData > ImportFilesCached(IEnumerable< string > imports, bool resetData=true)
static void HotInit(IEnumerable< SourceData > sourceData)
Dictionary< string, EMod > fileProviders
ExcelData dataGodTalk
SourceElement elements