11 [
Attribute(
desc:
"Unique extension added in front of .json extension.\nUsed for identifying save types without opening files.\n\nMust contain only letters!")]
12 protected string m_sExtension;
14 [
Attribute(
"-",
desc:
"Character added between mission name and custom name.\nWhen empty, custom name will not be used.")]
15 protected string m_sCustomNameDelimiter;
17 [
Attribute(
desc:
"When enabled, save file will never be saved in cloud.")]
18 protected bool m_bAlwaysLocal;
20 [
Attribute(
desc:
"When enabled, save of this type will also become the latest save for given mission.")]
21 protected bool m_bRegisterLatestSave;
27 protected bool m_bLoadPreview;
28 protected string m_sCurrentFileName;
58 bool SaveSession(
string missionFileName,
string customName =
string.Empty)
60 string fileName = GetFileName(missionFileName, customName);
62 if (!IsCompatible(fileName))
65 SessionStorage storage =
GetGame().GetBackendApi().GetStorage();
66 storage.AssignFileIDCallback(fileName,
this);
70 Print(
string.Format(
"SCR_DSSessionCallback: RequestSave: %1", fileName), LogLevel.VERBOSE);
71 storage.RequestSave(fileName);
75 Print(
string.Format(
"SCR_DSSessionCallback: LocalSave: %1", fileName), LogLevel.VERBOSE);
76 storage.LocalSave(fileName);
87 bool LoadSession(
string fileName)
89 if (!IsCompatible(fileName))
92 m_bLoadPreview =
false;
93 SessionStorage storage =
GetGame().GetBackendApi().GetStorage();
94 if (!storage.CheckFileID(fileName))
96 Print(
string.Format(
"SCR_DSSessionCallback: Cannot load save file '%1', it does not exist!", fileName), LogLevel.WARNING);
100 storage.AssignFileIDCallback(fileName,
this);
104 Print(
string.Format(
"SCR_DSSessionCallback: RequestLoad: %1", fileName), LogLevel.VERBOSE);
105 storage.RequestLoad(fileName);
109 Print(
string.Format(
"SCR_DSSessionCallback: LocalLoad: %1", fileName), LogLevel.VERBOSE);
110 storage.LocalLoad(fileName);
122 bool Delete(
string missionFileName,
string customName)
124 string fileName = GetFileName(missionFileName, customName);
125 return IsCompatible(fileName) && Delete(fileName);
134 bool Delete(
string fileName)
136 if (!
GetGame().GetBackendApi().GetStorage().CheckFileID(fileName))
139 GetGame().GetSaveManager().GetOnDeleted().Invoke(
m_eType, fileName);
140 GetGame().GetBackendApi().GetStorage().LocalDelete(fileName);
141 Print(
string.Format(
"SCR_DSSessionCallback: LocalDelete: '%1'", fileName), LogLevel.VERBOSE);
152 bool FileExists(
string fileName,
string customName =
string.Empty)
154 return GetGame().GetBackendApi().GetStorage().CheckFileID(GetFileName(fileName, customName));
165 if (!IsCompatible(fileName))
168 m_Struct.ClearCache();
170 m_bLoadPreview =
true;
171 SessionStorage storage =
GetGame().GetBackendApi().GetStorage();
172 storage.AssignFileIDCallback(fileName,
this);
173 storage.LocalLoad(fileName);
175 return m_Struct.GetMeta();
212 return m_Struct !=
null;
221 bool IsCompatible(
string fileName)
228 FilePath.StripExtension(fileName, ext);
229 return ext.StartsWith(m_sExtension);
238 string GetMissionFileName(
string fileName)
240 if (!m_sCustomNameDelimiter)
242 return FilePath.StripExtension(fileName);
245 int delimiterIndex = fileName.IndexOf(m_sCustomNameDelimiter);
246 if (delimiterIndex >= 0)
247 return fileName.Substring(0, delimiterIndex);
259 string GetCustomName(
string fileName)
261 if (!m_sCustomNameDelimiter)
264 int delimiterIndex = fileName.IndexOf(m_sCustomNameDelimiter);
265 if (delimiterIndex < 0)
268 delimiterIndex += m_sCustomNameDelimiter.Length();
269 int length = fileName.Length() - delimiterIndex;
270 fileName = fileName.Substring(delimiterIndex, length);
273 return FilePath.StripExtension(fileName, ext);
280 string GetCurrentCustomName()
282 return GetCustomName(m_sCurrentFileName);
291 string GetFileName(
string missionFileName,
string customName)
293 if (m_sCustomNameDelimiter)
296 missionFileName += m_sCustomNameDelimiter + customName;
299 return FilePath.AppendExtension(missionFileName, m_sExtension);
303 void OnGameStart(
string missionFileName)
308 void OnGameEnd(
string missionFileName)
310 m_sCurrentFileName =
string.Empty;
315 protected void OnLatestSave(
string fileName)
318 GetGame().GetSaveManager().GetOnLatestSave().Remove(OnLatestSave);
319 GetGame().GetCallqueue().CallLater(InvokeOnSaved);
323 protected void InvokeOnSaved()
325 GetGame().GetSaveManager().GetOnSaved().Invoke(
m_eType, m_sCurrentFileName);
331 override void OnSaving(
string fileName)
333 if (m_Struct.Serialize())
334 GetGame().GetBackendApi().GetStorage().ProcessSave(m_Struct, fileName);
338 override void OnSaveSuccess(
string fileName)
340 m_sCurrentFileName = fileName;
342 if (m_bRegisterLatestSave)
345 GetGame().GetSaveManager().GetOnLatestSave().Insert(OnLatestSave);
353 Print(
string.Format(
"SCR_DSSessionCallback: Saving save file of type %1 in '%2' succeeded!",
typename.EnumToString(
ESaveType,
m_eType), fileName), LogLevel.VERBOSE);
357 override void OnSaveFailed(
string fileName)
359 Print(
string.Format(
"SCR_DSSessionCallback: Saving save file of type %1 in '%2' failed!",
typename.EnumToString(
ESaveType,
m_eType), fileName), LogLevel.WARNING);
363 override void OnLoaded(
string fileName)
365 m_Struct.ClearCache();
366 GetGame().GetBackendApi().GetStorage().ProcessLoad(m_Struct, fileName);
370 Print(
string.Format(
"SCR_DSSessionCallback: Previewing save file of type %1 from '%2' succeeded!",
typename.EnumToString(
ESaveType,
m_eType), fileName), LogLevel.VERBOSE);
374 m_Struct.Deserialize();
376 m_sCurrentFileName = fileName;
378 GetGame().GetSaveManager().GetOnLoaded().Invoke(
m_eType, fileName);
380 Print(
string.Format(
"SCR_DSSessionCallback: Loading save file of type %1 from '%2' succeeded!",
typename.EnumToString(
ESaveType,
m_eType), fileName), LogLevel.VERBOSE);
385 override void OnLoadFailed(
string fileName)
387 Print(
string.Format(
"SCR_DSSessionCallback: Loading save file of type %1 from '%2' failed!",
typename.EnumToString(
ESaveType,
m_eType), fileName), LogLevel.WARNING);
391 override void OnDeleteSuccess(
string fileName )
393 if (m_sCurrentFileName == fileName)
394 m_sCurrentFileName =
string.Empty;
396 Print(
string.Format(
"SCR_DSSessionCallback: Deleting save file of type %1 at '%2' succeeded!",
typename.EnumToString(
ESaveType,
m_eType), fileName), LogLevel.VERBOSE);
400 override void OnDeleteFailed(
string fileName )
402 Print(
string.Format(
"SCR_DSSessionCallback: Deleting save file of type %1 at '%2' failed!",
typename.EnumToString(
ESaveType,
m_eType), fileName), LogLevel.WARNING);
417 protected int m_iMaxSaves;
420 override protected string GetFileName(
string missionFileName,
string customName)
426 string latestSaveName;
428 saveId = GetCustomName(latestSaveName).ToInt();
430 saveId = (saveId % m_iMaxSaves) + 1;
431 customName = saveId.ToString();
437 return super.GetFileName(missionFileName, customName);
445 protected void DeleteDelayed(
string fileName)
449 protected void DeleteIfNotToLoad(
string missionFileName)
452 string fileNameToLoad;
454 Delete(missionFileName,
string.Empty);
458 override void OnLoaded(
string fileName)
460 super.OnLoaded(fileName);
463 GetGame().GetCallqueue().CallLater(DeleteDelayed, 1,
false, fileName);
466 override void OnGameStart(
string missionFileName)
468 DeleteIfNotToLoad(missionFileName);
469 super.OnGameStart(missionFileName);
473 override void OnGameEnd(
string missionFileName)
475 DeleteIfNotToLoad(missionFileName);
476 super.OnGameEnd(missionFileName);