Elin Decompiled Documentation EA 23.357 Nightly
Loading...
Searching...
No Matches
GameIO.cs
Go to the documentation of this file.
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.IO.Compression;
5using System.Linq;
6using Newtonsoft.Json;
7using Newtonsoft.Json.Serialization;
8using UnityEngine;
9
10public class GameIO : EClass
11{
12 public static JsonSerializerSettings jsReadGame = new JsonSerializerSettings
13 {
14 NullValueHandling = NullValueHandling.Ignore,
15 DefaultValueHandling = DefaultValueHandling.Ignore,
16 PreserveReferencesHandling = PreserveReferencesHandling.Objects,
17 TypeNameHandling = TypeNameHandling.Auto,
18 Error = IO.OnError,
19 SerializationBinder = GameSerializationBinder.Instance
20 };
21
22 public static JsonSerializerSettings jsWriteGame = new JsonSerializerSettings
23 {
24 NullValueHandling = NullValueHandling.Ignore,
25 DefaultValueHandling = DefaultValueHandling.Ignore,
26 PreserveReferencesHandling = PreserveReferencesHandling.Objects,
27 TypeNameHandling = TypeNameHandling.Auto,
29 Error = IO.OnError
30 };
31
32 public static Formatting formatting = Formatting.Indented;
33
34 public static string pathCurrentSave => (EClass.core.game.isCloud ? CorePath.RootSaveCloud : CorePath.RootSave) + Game.id + "/";
35
36 public static string pathTemp => pathCurrentSave + "Temp/";
37
38 public static int NumBackup => (int)MathF.Max(5f, EClass.core.config.game.numBackup);
39
41
42 public static void Init()
43 {
44 JsonSerializerSettings jsonSerializerSettings = jsReadGame;
45 jsonSerializerSettings.Error = (EventHandler<Newtonsoft.Json.Serialization.ErrorEventArgs>)Delegate.Combine(jsonSerializerSettings.Error, (EventHandler<Newtonsoft.Json.Serialization.ErrorEventArgs>)delegate(object sender, Newtonsoft.Json.Serialization.ErrorEventArgs args)
46 {
47 if (args.ErrorContext.Error.Message.Contains("UnknownTypePlaceholder"))
48 {
49 args.ErrorContext.Handled = true;
50 }
51 });
52 }
53
54 public static void ResetTemp()
55 {
56 DirectoryInfo directoryInfo = new DirectoryInfo(pathTemp);
57 if (directoryInfo.Exists)
58 {
59 directoryInfo.Delete(recursive: true);
60 }
61 IO.CreateDirectory(pathTemp);
62 }
63
64 public static void ClearTemp()
65 {
66 DirectoryInfo directoryInfo = new DirectoryInfo(pathTemp);
67 if (directoryInfo.Exists)
68 {
69 DirectoryInfo[] directories = directoryInfo.GetDirectories();
70 for (int i = 0; i < directories.Length; i++)
71 {
72 directories[i].Delete(recursive: true);
73 }
74 FileInfo[] files = directoryInfo.GetFiles();
75 for (int i = 0; i < files.Length; i++)
76 {
77 files[i].Delete();
78 }
79 }
80 }
81
82 public static GameIndex SaveGame()
83 {
85 DirectoryInfo[] directories = new DirectoryInfo(pathCurrentSave).GetDirectories();
86 foreach (DirectoryInfo directoryInfo in directories)
87 {
88 if (int.TryParse(directoryInfo.Name, out var result) && !EClass.game.spatials.map.ContainsKey(result))
89 {
90 IO.DeleteDirectory(directoryInfo.FullName);
91 Debug.Log("Deleting unused map:" + directoryInfo.FullName);
92 }
93 }
94 ClearTemp();
95 if (gameIndex.cloud)
96 {
97 PrepareSteamCloud(gameIndex.id);
98 }
99 return gameIndex;
100 }
101
102 public static void SaveGameCopy(string path)
103 {
104 IO.CopyDir(pathCurrentSave, path, (string s) => s == "Temp");
105 IO.DeleteFile(path + "cloud.zip");
106 foreach (Zone zone in EClass.game.spatials.Zones)
107 {
108 if (zone.map != null)
109 {
110 zone.map.Save(path + zone.uid + "/");
111 }
112 }
113 EClass.game.version = EClass.core.version;
114 WriteGame(path);
115 }
116
117 public static GameIndex WriteGame(string root)
118 {
119 string text = JsonConvert.SerializeObject(EClass.core.game, formatting, jsWriteGame);
120 string path = root + "game.txt";
121 GameIndex gameIndex = new GameIndex().Create(EClass.core.game);
122 gameIndex.id = Game.id;
123 gameIndex.cloud = EClass.game.isCloud;
124 IO.SaveFile(root + "index.txt", gameIndex);
125 if (compressSave)
126 {
127 IO.Compress(path, text);
128 }
129 else
130 {
131 File.WriteAllText(path, text);
132 }
133 return gameIndex;
134 }
135
136 public static void MakeBackup(GameIndex index, string suffix = "")
137 {
138 Debug.Log("Start backup:" + index.id);
139 string id = index.id;
140 bool cloud = index.cloud;
141 IO.CreateDirectory(cloud ? CorePath.PathBackupCloud : CorePath.PathBackup);
142 string text = (cloud ? CorePath.PathBackupCloud : CorePath.PathBackup) + id;
143 IO.CreateDirectory(text);
144 Debug.Log(text);
145 List<DirectoryInfo> dirs = new DirectoryInfo(text).GetDirectories().ToList();
146 dirs.ForeachReverse(delegate(DirectoryInfo i)
147 {
148 if (!int.TryParse(i.Name, out var _))
149 {
150 dirs.Remove(i);
151 }
152 });
153 dirs.Sort((DirectoryInfo a, DirectoryInfo b) => int.Parse(a.Name) - int.Parse(b.Name));
154 int count = dirs.Count;
155 Debug.Log("Deleting excess backup:" + dirs.Count + "/" + NumBackup);
156 if (count > NumBackup)
157 {
158 for (int num = 0; num < count - NumBackup; num++)
159 {
160 IO.DeleteDirectory(dirs[num].FullName);
161 }
162 }
163 Debug.Log("Copying backup:");
164 string newId = GetNewId(text + "/", "", (dirs.Count == 0) ? 1 : int.Parse(dirs.LastItem().Name));
165 IO.CopyDir((cloud ? CorePath.RootSaveCloud : CorePath.RootSave) + id + "/", text + "/" + newId, (string s) => s == "Temp");
166 }
167
168 public static bool CanLoad(string root)
169 {
170 GameIndex gameIndex = IO.LoadFile<GameIndex>(root + "/index.txt");
171 return EClass.core.version.IsSaveCompatible(gameIndex.version);
172 }
173
174 public static Game LoadGame(string id, string root, bool cloud)
175 {
176 Game.id = id;
177 GameIndex gameIndex = IO.LoadFile<GameIndex>(root + "/index.txt");
178 string path = root + "/game.txt";
179 foreach (KeyValuePair<string, string> fallbackType in gameIndex.fallbackTypes)
180 {
181 ModUtil.fallbackTypes[fallbackType.Key] = fallbackType.Value;
182 }
183 if (cloud)
184 {
185 gameIndex.cloud = true;
186 Debug.Log(TryLoadSteamCloud(root));
187 }
188 else if (!File.Exists(path))
189 {
190 Debug.Log(TryLoadSteamCloud(root));
191 }
192 return JsonConvert.DeserializeObject<Game>(IO.IsCompressed(path) ? IO.Decompress(path) : File.ReadAllText(path), jsReadGame);
193 }
194
195 public static void PrepareSteamCloud(string id, string path = "")
196 {
197 if (path.IsEmpty())
198 {
199 path = CorePath.RootSaveCloud + "/" + id;
200 }
201 Debug.Log("Prepareing Steam Cloud:" + id + ": " + path);
202 string text = CorePath.RootSaveCloud + "/cloud.zip";
203 string text2 = path + "/cloud.zip";
204 try
205 {
206 if (File.Exists(text))
207 {
208 File.Delete(text);
209 }
210 if (File.Exists(text2))
211 {
212 File.Delete(text2);
213 }
214 ZipFile.CreateFromDirectory(path, text);
215 if (File.Exists(text2))
216 {
217 File.Delete(text2);
218 }
219 File.Move(text, text2);
220 }
221 catch (Exception ex)
222 {
223 EClass.ui.Say(ex.Message);
224 }
225 }
226
227 public static bool TryLoadSteamCloud(string pathSave)
228 {
229 Debug.Log("LoadGame using cloud save");
230 string text = pathSave + "/cloud.zip";
231 string text2 = CorePath.RootSaveCloud + "/cloud.zip";
232 bool flag = false;
233 try
234 {
235 if (!File.Exists(text))
236 {
237 EClass.ui.Say("Steam Cloud save not found:" + text);
238 return true;
239 }
240 if (File.Exists(text2))
241 {
242 File.Delete(text2);
243 }
244 File.Move(text, text2);
245 IO.DeleteDirectory(pathSave);
246 flag = true;
247 Directory.CreateDirectory(pathSave);
248 ZipFile.ExtractToDirectory(text2, pathSave);
249 if (File.Exists(text))
250 {
251 File.Delete(text);
252 }
253 File.Move(text2, text);
254 }
255 catch (Exception ex)
256 {
257 EClass.ui.Say(ex.Message);
258 if (flag)
259 {
260 Debug.Log("Try restore backup:");
261 if (Directory.Exists(pathSave))
262 {
263 Directory.Delete(pathSave);
264 }
265 File.Move(text2, text);
266 return true;
267 }
268 return false;
269 }
270 return true;
271 }
272
273 public static void UpdateGameIndex(GameIndex i)
274 {
275 IO.SaveFile(i.path + "/index.txt", i);
276 }
277
278 public static void SaveFile(string path, object obj)
279 {
280 IO.SaveFile(path, obj, compressSave, jsWriteGame);
281 }
282
283 public static T LoadFile<T>(string path) where T : new()
284 {
285 return IO.LoadFile<T>(path, compressSave, jsReadGame);
286 }
287
288 public static void DeleteGame(string id, bool cloud, bool deleteBackup = true)
289 {
290 string path = (cloud ? CorePath.RootSaveCloud : CorePath.RootSave) + id;
291 if (!Directory.Exists(path))
292 {
293 return;
294 }
295 DirectoryInfo directoryInfo = new DirectoryInfo(path);
296 if (directoryInfo.Exists)
297 {
298 directoryInfo.Delete(recursive: true);
299 }
300 if (deleteBackup)
301 {
302 directoryInfo = new DirectoryInfo((cloud ? CorePath.PathBackupCloud : CorePath.PathBackup) + id);
303 if (directoryInfo.Exists)
304 {
305 directoryInfo.Delete(recursive: true);
306 }
307 }
308 }
309
310 public static List<GameIndex> GetGameList(string path, bool sortByName = false, bool includeEmptyFolder = false)
311 {
312 List<GameIndex> list = new List<GameIndex>();
313 DirectoryInfo directoryInfo = new DirectoryInfo(path);
314 if (!directoryInfo.Exists)
315 {
316 return list;
317 }
318 DirectoryInfo[] directories = directoryInfo.GetDirectories();
319 foreach (DirectoryInfo directoryInfo2 in directories)
320 {
321 if (File.Exists(directoryInfo2?.ToString() + "/index.txt"))
322 {
323 try
324 {
325 GameIndex gameIndex = IO.LoadFile<GameIndex>(directoryInfo2?.ToString() + "/index.txt");
326 gameIndex.id = directoryInfo2.Name;
327 gameIndex.path = directoryInfo2.FullName;
328 list.Add(gameIndex);
329 }
330 catch (Exception message)
331 {
332 Debug.Log(message);
333 goto IL_0097;
334 }
335 continue;
336 }
337 goto IL_0097;
338 IL_0097:
339 if (includeEmptyFolder && Directory.Exists(CorePath.PathBackup + directoryInfo2.Name))
340 {
341 GameIndex gameIndex2 = new GameIndex();
342 gameIndex2.id = directoryInfo2.Name;
343 gameIndex2.path = directoryInfo2.FullName;
344 gameIndex2.date = (gameIndex2.real = new Date());
345 list.Add(gameIndex2);
346 }
347 }
348 if (sortByName)
349 {
350 list.Sort(delegate(GameIndex a, GameIndex b)
351 {
352 int.TryParse(a.id, out var result);
353 int.TryParse(b.id, out var result2);
354 return result2 - result;
355 });
356 }
357 else
358 {
359 list.Sort((GameIndex a, GameIndex b) => b.real.GetRawReal() - a.real.GetRawReal());
360 }
361 return list;
362 }
363
364 public static void DeleteEmptyGameFolders(string path)
365 {
366 DirectoryInfo[] directories = new DirectoryInfo(path).GetDirectories();
367 foreach (DirectoryInfo directoryInfo in directories)
368 {
369 if (!File.Exists(directoryInfo?.ToString() + "/game.txt"))
370 {
371 directoryInfo.Delete(recursive: true);
372 }
373 }
374 }
375
376 public static string GetNewId(string path, string prefix = "", int start = 1)
377 {
378 string text = "";
379 for (int i = start; i < 999999; i++)
380 {
381 text = prefix + i;
382 if (!Directory.Exists(path + text))
383 {
384 break;
385 }
386 }
387 return text;
388 }
389}
Version version
Definition: BaseCore.cs:17
new GameConfig game
Definition: CoreConfig.cs:629
static string RootSave
Definition: CorePath.cs:202
static string RootSaveCloud
Definition: CorePath.cs:204
static string PathBackup
Definition: CorePath.cs:218
static string PathBackupCloud
Definition: CorePath.cs:220
Game game
Definition: Core.cs:72
CoreConfig config
Definition: Core.cs:70
Definition: Date.cs:4
int GetRawReal(int offsetHours=0)
Definition: Date.cs:323
Definition: EClass.cs:6
static Game game
Definition: EClass.cs:9
static Core core
Definition: EClass.cs:7
static UI ui
Definition: EClass.cs:17
Definition: GameIO.cs:11
static void SaveFile(string path, object obj)
Definition: GameIO.cs:278
static void DeleteGame(string id, bool cloud, bool deleteBackup=true)
Definition: GameIO.cs:288
static T LoadFile< T >(string path)
Definition: GameIO.cs:283
static bool compressSave
Definition: GameIO.cs:40
static int NumBackup
Definition: GameIO.cs:38
static string GetNewId(string path, string prefix="", int start=1)
Definition: GameIO.cs:376
static void DeleteEmptyGameFolders(string path)
Definition: GameIO.cs:364
static string pathCurrentSave
Definition: GameIO.cs:34
static bool CanLoad(string root)
Definition: GameIO.cs:168
static JsonSerializerSettings jsWriteGame
Definition: GameIO.cs:22
static void UpdateGameIndex(GameIndex i)
Definition: GameIO.cs:273
static GameIndex SaveGame()
Definition: GameIO.cs:82
static Formatting formatting
Definition: GameIO.cs:32
static void ClearTemp()
Definition: GameIO.cs:64
static GameIndex WriteGame(string root)
Definition: GameIO.cs:117
static JsonSerializerSettings jsReadGame
Definition: GameIO.cs:12
static Game LoadGame(string id, string root, bool cloud)
Definition: GameIO.cs:174
static void Init()
Definition: GameIO.cs:42
static void PrepareSteamCloud(string id, string path="")
Definition: GameIO.cs:195
static bool TryLoadSteamCloud(string pathSave)
Definition: GameIO.cs:227
static void ResetTemp()
Definition: GameIO.cs:54
static string pathTemp
Definition: GameIO.cs:36
static void SaveGameCopy(string path)
Definition: GameIO.cs:102
static List< GameIndex > GetGameList(string path, bool sortByName=false, bool includeEmptyFolder=false)
Definition: GameIO.cs:310
static void MakeBackup(GameIndex index, string suffix="")
Definition: GameIO.cs:136
GameIndex Create(Game game)
Definition: GameIndex.cs:70
string id
Definition: GameIndex.cs:13
bool cloud
Definition: GameIndex.cs:41
Date real
Definition: GameIndex.cs:11
Version version
Definition: GameIndex.cs:21
Dictionary< string, string > fallbackTypes
Definition: GameIndex.cs:45
string path
Definition: GameIndex.cs:48
Definition: Game.cs:9
static string id
Definition: Game.cs:148
SpatialManager spatials
Definition: Game.cs:153
bool isCloud
Definition: Game.cs:246
void Save(string path, ZoneExportData export=null, PartialMap partial=null)
Definition: Map.cs:381
static readonly ShouldSerializeContractResolver Instance
List< Zone > Zones
GlobalSpatialList map
int uid
Definition: Spatial.cs:70
Definition: Zone.cs:12
Map map
Definition: Zone.cs:66
bool IsSaveCompatible(Version v)
Definition: Version.cs:102