Elin Decompiled Documentation EA 23.301 Nightly
Loading...
Searching...
No Matches
ModUtil.cs
Go to the documentation of this file.
1using System;
2using System.Collections.Generic;
3using System.Diagnostics;
4using System.IO;
5using System.Linq;
6using System.Reflection;
7using System.Threading;
8using NPOI.SS.UserModel;
9using NPOI.XSSF.UserModel;
10using UnityEngine;
11using UnityEngine.Networking;
12
13public class ModUtil : EClass
14{
16
17 public static Dictionary<string, string> fallbackTypes = new Dictionary<string, string>();
18
19 public static IReadOnlyDictionary<string, SourceData> SourceMapping => (from f in typeof(SourceManager).GetFields()
20 where typeof(SourceData).IsAssignableFrom(f.FieldType)
21 select f).ToDictionary((FieldInfo f) => f.FieldType.Name, (FieldInfo f) => f.GetValue(EClass.sources) as SourceData);
22
23 public static void OnModsActivated()
24 {
25 SoundManager.current.soundLoaders.Add(LoadSoundData);
28 BaseModManager.PublishEvent("elin.mods.activated");
29 BaseModManager.SubscribeEvent("elin.game.post_load", PostLoadCleanup);
30 }
31
32 private static void PostLoadCleanup(object context)
33 {
34 EClass.player.knownBGMs.RemoveWhere((int id) => !EClass.core.refs.dictBGM.ContainsKey(id));
35 }
36
37 public static void LoadTypeFallback()
38 {
39 string text = "type_resolver.txt";
40 string[] array = new string[0];
41 if (File.Exists(CorePath.RootData + text))
42 {
43 array = IO.LoadTextArray(CorePath.RootData + text);
44 }
45 else
46 {
47 array = new string[2] { "TrueArena,ArenaWaveEvent,ZoneEvent", "Elin-GeneRecombinator,Elin_GeneRecombinator.IncubationSacrifice,Chara" };
48 IO.SaveTextArray(CorePath.RootData + text, array);
49 }
50 string[] array2 = array;
51 for (int i = 0; i < array2.Length; i++)
52 {
53 string[] array3 = array2[i].Split(',');
54 if (array3.Length >= 2)
55 {
56 RegisterSerializedTypeFallback(array3[0], array3[1], array3[2]);
57 }
58 }
59 }
60
61 public static void RegisterSerializedTypeFallback(string nameAssembly, string nameType, string nameFallbackType)
62 {
63 fallbackTypes[nameType] = nameFallbackType;
64 }
65
66 public static ModPackage GetModPackage(string modId)
67 {
68 return ModManagerCore.Instance.MappedPackages.GetValueOrDefault(modId) as ModPackage;
69 }
70
71 public static void ImportExcel(string pathToExcelFile, string sheetName, SourceData source)
72 {
73 UnityEngine.Debug.Log("ImportExcel source:" + source?.ToString() + " Path:" + pathToExcelFile);
74 using FileStream @is = File.Open(pathToExcelFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
75 XSSFWorkbook xSSFWorkbook = new XSSFWorkbook((Stream)@is);
76 for (int i = 0; i < xSSFWorkbook.NumberOfSheets; i++)
77 {
78 ISheet sheetAt = xSSFWorkbook.GetSheetAt(i);
79 if (sheetAt.SheetName != sheetName)
80 {
81 continue;
82 }
83 UnityEngine.Debug.Log("Importing Sheet:" + sheetName);
84 try
85 {
86 ExcelParser.path = pathToExcelFile;
87 if (!source.ImportData(sheetAt, new FileInfo(pathToExcelFile).Name, overwrite: true))
88 {
89 UnityEngine.Debug.LogError(ERROR.msg);
90 break;
91 }
92 UnityEngine.Debug.Log("Imported " + sheetAt.SheetName);
93 source.Reset();
94 }
95 catch (Exception ex)
96 {
97 UnityEngine.Debug.LogError("[Error] Skipping import " + sheetAt.SheetName + " :" + ex.Message + "/" + ex.Source + "/" + ex.StackTrace);
98 break;
99 }
100 }
101 }
102
104 {
105 return ModManagerCore.Instance.packages.OfType<ModPackage>().LastOrDefault((ModPackage p) => p.sourceRows.Contains(row));
106 }
107
108 public static SerializableSoundData GetSoundMeta(string soundPath)
109 {
110 string path = Path.ChangeExtension(soundPath, ".json");
111 SerializableSoundData serializableSoundData;
112 if (File.Exists(path))
113 {
114 try
115 {
116 serializableSoundData = IO.LoadFile<SerializableSoundData>(path);
117 if (serializableSoundData.dataVersion == SerializableSoundData.SoundDataMetaVersion.V1)
118 {
119 return serializableSoundData;
120 }
121 }
122 catch
123 {
124 }
125 }
126 serializableSoundData = new SerializableSoundData();
127 if (soundPath.NormalizePath().Contains("/Sound/BGM/"))
128 {
129 serializableSoundData.type = SoundData.Type.BGM;
130 serializableSoundData.bgmDataOptional = new SerializableBGMData
131 {
132 parts = new List<BGMData.Part>
133 {
134 new BGMData.Part()
135 }
136 };
137 }
138 IO.SaveFile(path, serializableSoundData);
139 return serializableSoundData;
140 }
141
142 public static AudioType GetAudioType(string extension)
143 {
144 return extension.ToLowerInvariant().Trim() switch
145 {
146 ".acc" => AudioType.ACC,
147 ".mp3" => AudioType.MPEG,
148 ".ogg" => AudioType.OGGVORBIS,
149 ".wav" => AudioType.WAV,
150 _ => AudioType.UNKNOWN,
151 };
152 }
153
154 public static SoundData LoadSoundData(string soundId)
155 {
156 if (!MOD.sounds.TryGetValue(soundId, out var value) || !value.Exists)
157 {
158 return null;
159 }
160 return LoadSoundData(value);
161 }
162
163 public static SoundData LoadSoundData(FileInfo soundFile)
164 {
165 string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(soundFile.FullName);
166 string fullName = soundFile.FullName;
167 AudioType audioType = GetAudioType(soundFile.Extension);
168 bool stream = fullName.NormalizePath().Contains("/BGM/") && audioType == AudioType.OGGVORBIS;
169 using UnityWebRequest unityWebRequest = AudioClipStream.GetAudioClip("file://" + fullName, audioType, compressed: false, stream);
170 unityWebRequest.SendWebRequest();
171 Stopwatch stopwatch = Stopwatch.StartNew();
172 while (!unityWebRequest.isDone && stopwatch.ElapsedMilliseconds < 5000)
173 {
174 Thread.Sleep(1);
175 }
176 if (unityWebRequest.result != UnityWebRequest.Result.Success)
177 {
178 UnityEngine.Debug.LogError("#sound '" + fileNameWithoutExtension + "' failed to load: " + unityWebRequest.error.IsEmpty("timeout"));
179 return null;
180 }
181 AudioClip content = DownloadHandlerAudioClip.GetContent(unityWebRequest);
182 int? num = content?.samples;
183 if (!num.HasValue || num.GetValueOrDefault() <= 0)
184 {
185 UnityEngine.Debug.LogError($"#sound '{fileNameWithoutExtension}' sample is null: {audioType}");
186 return null;
187 }
188 content.name = fileNameWithoutExtension;
189 SoundData soundData = GetSoundMeta(fullName).ToSoundData();
190 if (soundData is BGMData bGMData)
191 {
192 bGMData._name = Path.GetFileNameWithoutExtension(fullName);
193 if (bGMData.song == null)
194 {
195 bGMData.song = new BGMData.SongData();
196 bGMData.song.parts.Add(new BGMData.Part());
197 }
198 }
199 soundData.clip = content;
200 soundData.name = fileNameWithoutExtension;
201 UnityEngine.Debug.Log($"#sound '{fileNameWithoutExtension}' loaded: {audioType}/{content.length}s");
202 SoundManager.current.dictData[fileNameWithoutExtension] = soundData;
203 return soundData;
204 }
205
206 public static void AddOrReplaceBGM(string bgmId)
207 {
208 List<BGMData> bgms = Core.Instance.refs.bgms;
209 Dictionary<int, BGMData> dictBGM = Core.Instance.refs.dictBGM;
210 BGMData bGMData = SoundManager.current.GetData(bgmId) as BGMData;
211 if (!(bGMData == null))
212 {
213 bGMData.name = bgmId[4..];
214 if (bGMData.id <= 0)
215 {
216 bGMData.id = bgms.Count + 1;
217 UnityEngine.Debug.Log($"#sound bgm unassigned/{bGMData.id}/{bGMData.name}");
218 }
219 if (dictBGM.TryGetValue(bGMData.id, out var value))
220 {
221 value.clip = bGMData.clip;
222 UnityEngine.Debug.Log($"#sound bgm replace/{bGMData.id}/{value.name}/>/{bGMData.name}");
223 }
224 else
225 {
226 bgms.Add(bGMData);
227 dictBGM[bGMData.id] = bGMData;
228 UnityEngine.Debug.Log($"#sound bgm addon/{bGMData.id}/{bGMData.name}");
229 }
230 }
231 }
232
233 public static ModPackage FindSoundPackage(string soundId)
234 {
235 return ModManagerCore.Instance.packages.OfType<ModPackage>().LastOrDefault((ModPackage p) => p.sounds.Keys.Contains(soundId));
236 }
237
238 public static Playlist CreatePlaylist(ref List<int> bgmIds, Playlist mold = null)
239 {
240 Playlist playlist = EClass.Sound.plBlank.Instantiate();
241 if (bgmIds.Count == 0 && (bool)mold)
242 {
243 bgmIds = mold.ToInts();
244 playlist.shuffle = mold.shuffle;
245 playlist.minSwitchTime = mold.minSwitchTime;
246 playlist.nextBGMOnSwitch = mold.nextBGMOnSwitch;
247 playlist.ignoreLoop = mold.ignoreLoop;
248 playlist.keepBGMifSamePlaylist = mold.keepBGMifSamePlaylist;
249 playlist.name = mold.name;
250 }
251 foreach (int bgmId in bgmIds)
252 {
253 if (EClass.core.refs.dictBGM.TryGetValue(bgmId, out var value))
254 {
255 playlist.list.Add(new Playlist.Item
256 {
257 data = value
258 });
259 }
260 }
261 return playlist;
262 }
263
264 public static void SetBGMKnown(int bgmId, bool known = true)
265 {
266 known &= EClass.core.refs.dictBGM.ContainsKey(bgmId);
267 if (known)
268 {
269 EClass.player.knownBGMs.Add(bgmId);
270 }
271 else
272 {
273 EClass.player.knownBGMs.Remove(bgmId);
274 }
275 }
276
277 public static string[] LoadBookList()
278 {
279 return (from d in PackageIterator.GetDirectories("Text").SelectMany((DirectoryInfo d) => d.GetDirectories())
280 select d.FullName).ToArray();
281 }
282
283 public static string[] LoadTopicFiles()
284 {
285 return PackageIterator.GetFiles("Text/Help/_topics.txt").SelectMany((FileInfo f) => IO.LoadTextArray(f.FullName)).ToArray();
286 }
287}
$
Definition: ModManager.cs:87
static void PublishEvent(string eventId, object data=null)
static void SubscribeEvent(string eventId, Action< object > handler)
static List< Func< string[]> > booklistLoaders
Definition: BookList.cs:28
static string RootData
Definition: CorePath.cs:200
Dictionary< int, BGMData > dictBGM
Definition: CoreRef.cs:386
List< BGMData > bgms
Definition: CoreRef.cs:382
Definition: Core.cs:14
CoreRef refs
Definition: Core.cs:51
static new Core Instance
Definition: Core.cs:15
Definition: EClass.cs:6
static Core core
Definition: EClass.cs:7
static SourceManager sources
Definition: EClass.cs:43
static Player player
Definition: EClass.cs:13
static SoundManager Sound
Definition: EClass.cs:47
Definition: ERROR.cs:2
static string msg
Definition: ERROR.cs:3
Definition: MOD.cs:7
static Dictionary< string, FileInfo > sounds
Definition: MOD.cs:24
static SoundData LoadSoundData(string soundId)
Definition: ModUtil.cs:154
static IReadOnlyDictionary< string, SourceData > SourceMapping
Definition: ModUtil.cs:19
static ModPackage GetModPackage(string modId)
Definition: ModUtil.cs:66
static SourceImporter sourceImporter
Definition: ModUtil.cs:15
static AudioType GetAudioType(string extension)
Definition: ModUtil.cs:142
static void AddOrReplaceBGM(string bgmId)
Definition: ModUtil.cs:206
static SerializableSoundData GetSoundMeta(string soundPath)
Definition: ModUtil.cs:108
static string[] LoadBookList()
Definition: ModUtil.cs:277
static void PostLoadCleanup(object context)
Definition: ModUtil.cs:32
static void RegisterSerializedTypeFallback(string nameAssembly, string nameType, string nameFallbackType)
Definition: ModUtil.cs:61
static Playlist CreatePlaylist(ref List< int > bgmIds, Playlist mold=null)
Definition: ModUtil.cs:238
static Dictionary< string, string > fallbackTypes
Definition: ModUtil.cs:17
static ModPackage FindSoundPackage(string soundId)
Definition: ModUtil.cs:233
static ModPackage FindSourceRowPackage(SourceData.BaseRow row)
Definition: ModUtil.cs:103
static SoundData LoadSoundData(FileInfo soundFile)
Definition: ModUtil.cs:163
static void OnModsActivated()
Definition: ModUtil.cs:23
static string[] LoadTopicFiles()
Definition: ModUtil.cs:283
static void LoadTypeFallback()
Definition: ModUtil.cs:37
static void SetBGMKnown(int bgmId, bool known=true)
Definition: ModUtil.cs:264
static void ImportExcel(string pathToExcelFile, string sheetName, SourceData source)
Definition: ModUtil.cs:71
HashSet< int > knownBGMs
Definition: Player.cs:1131
override bool ImportData(ISheet sheet, string bookname, bool overwrite=false)
Definition: SourceData.cs:136
override void Reset()
Definition: SourceData.cs:115
Definition: UIBook.cs:9
static List< Func< string[]> > topicLoaders
Definition: UIBook.cs:332