mirror of
https://github.com/misternebula/quantum-space-buddies.git
synced 2025-01-29 00:32:43 +00:00
Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
fe33962b08
@ -1,9 +1,9 @@
|
||||
using System;
|
||||
|
||||
namespace QSB.Patches;
|
||||
namespace QSB;
|
||||
|
||||
[Flags]
|
||||
public enum PatchVendor
|
||||
public enum GameVendor
|
||||
{
|
||||
None = 0,
|
||||
Epic = 1,
|
@ -134,7 +134,7 @@ internal class MenuManager : MonoBehaviour, IAddComponentOnStart
|
||||
var text = QSBCore.DebugSettings.UseKcpTransport ? QSBLocalization.Current.PublicIPAddress : QSBLocalization.Current.ProductUserID;
|
||||
ConnectPopup.SetUpPopup(text, InputLibrary.menuConfirm, InputLibrary.cancel, new ScreenPrompt(QSBLocalization.Current.Connect), new ScreenPrompt(QSBLocalization.Current.Cancel), false);
|
||||
ConnectPopup.SetInputFieldPlaceholderText(text);
|
||||
ExistingNewCopyPopup.SetUpPopup(QSBLocalization.Current.HostExistingOrNew,
|
||||
ExistingNewCopyPopup.SetUpPopup(QSBLocalization.Current.HostExistingOrNewOrCopy,
|
||||
InputLibrary.menuConfirm,
|
||||
InputLibrary.confirm2,
|
||||
InputLibrary.signalscope,
|
||||
@ -370,7 +370,7 @@ internal class MenuManager : MonoBehaviour, IAddComponentOnStart
|
||||
TwoButtonInfoPopup.OnPopupConfirm += () => OnCloseInfoPopup(true);
|
||||
TwoButtonInfoPopup.OnPopupCancel += () => OnCloseInfoPopup(false);
|
||||
|
||||
ExistingNewCopyPopup = CreateFourChoicePopup(QSBLocalization.Current.HostExistingOrNew,
|
||||
ExistingNewCopyPopup = CreateFourChoicePopup(QSBLocalization.Current.HostExistingOrNewOrCopy,
|
||||
QSBLocalization.Current.ExistingSave,
|
||||
QSBLocalization.Current.NewSave,
|
||||
QSBLocalization.Current.CopySave,
|
||||
@ -381,7 +381,18 @@ internal class MenuManager : MonoBehaviour, IAddComponentOnStart
|
||||
{
|
||||
DebugLog.DebugWrite("Replacing multiplayer save with singleplayer save");
|
||||
QSBCore.IsInMultiplayer = true;
|
||||
StandaloneProfileManager.SharedInstance.SaveGame(QSBProfileManager._currentProfile.gameSave, null, null, null);
|
||||
|
||||
if (QSBCore.IsStandalone)
|
||||
{
|
||||
var currentProfile = QSBStandaloneProfileManager.SharedInstance.currentProfile;
|
||||
QSBStandaloneProfileManager.SharedInstance.SaveGame(currentProfile.gameSave, null, null, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
var gameSave = QSBMSStoreProfileManager.SharedInstance.currentProfileGameSave;
|
||||
QSBMSStoreProfileManager.SharedInstance.SaveGame(gameSave, null, null, null);
|
||||
}
|
||||
|
||||
Host(false);
|
||||
};
|
||||
|
||||
@ -394,7 +405,18 @@ internal class MenuManager : MonoBehaviour, IAddComponentOnStart
|
||||
{
|
||||
DebugLog.DebugWrite("Replacing multiplayer save with singleplayer save");
|
||||
QSBCore.IsInMultiplayer = true;
|
||||
StandaloneProfileManager.SharedInstance.SaveGame(QSBProfileManager._currentProfile.gameSave, null, null, null);
|
||||
|
||||
if (QSBCore.IsStandalone)
|
||||
{
|
||||
var currentProfile = QSBStandaloneProfileManager.SharedInstance.currentProfile;
|
||||
QSBStandaloneProfileManager.SharedInstance.SaveGame(currentProfile.gameSave, null, null, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
var gameSave = QSBMSStoreProfileManager.SharedInstance.currentProfileGameSave;
|
||||
QSBMSStoreProfileManager.SharedInstance.SaveGame(gameSave, null, null, null);
|
||||
}
|
||||
|
||||
Host(false);
|
||||
};
|
||||
|
||||
@ -544,9 +566,20 @@ internal class MenuManager : MonoBehaviour, IAddComponentOnStart
|
||||
|
||||
private void PreHost()
|
||||
{
|
||||
var profile = QSBProfileManager._currentProfile;
|
||||
var doesSingleplayerSaveExist = profile.gameSave.loopCount > 1;
|
||||
var doesMultiplayerSaveExist = profile.multiplayerGameSave.loopCount > 1;
|
||||
bool doesSingleplayerSaveExist = false;
|
||||
bool doesMultiplayerSaveExist = false;
|
||||
if (!QSBCore.IsStandalone)
|
||||
{
|
||||
var manager = QSBMSStoreProfileManager.SharedInstance;
|
||||
doesSingleplayerSaveExist = manager.currentProfileGameSave.loopCount > 1;
|
||||
doesMultiplayerSaveExist = manager.currentProfileMultiplayerGameSave.loopCount > 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
var profile = QSBStandaloneProfileManager.SharedInstance.currentProfile;
|
||||
doesSingleplayerSaveExist = profile.gameSave.loopCount > 1;
|
||||
doesMultiplayerSaveExist = profile.multiplayerGameSave.loopCount > 1;
|
||||
}
|
||||
|
||||
if (doesSingleplayerSaveExist && doesMultiplayerSaveExist)
|
||||
{
|
||||
@ -587,8 +620,16 @@ internal class MenuManager : MonoBehaviour, IAddComponentOnStart
|
||||
else
|
||||
{
|
||||
DebugLog.DebugWrite("Loading multiplayer game...");
|
||||
var profile = QSBProfileManager._currentProfile;
|
||||
PlayerData.Init(profile.multiplayerGameSave, profile.settingsSave, profile.graphicsSettings, profile.inputJSON);
|
||||
if (QSBCore.IsStandalone)
|
||||
{
|
||||
var profile = QSBStandaloneProfileManager.SharedInstance.currentProfile;
|
||||
PlayerData.Init(profile.multiplayerGameSave, profile.settingsSave, profile.graphicsSettings, profile.inputJSON);
|
||||
}
|
||||
else
|
||||
{
|
||||
var manager = QSBMSStoreProfileManager.SharedInstance;
|
||||
PlayerData.Init(manager.currentProfileMultiplayerGameSave, manager.currentProfileGameSettings, manager.currentProfileGraphicsSettings, manager.currentProfileInputJSON);
|
||||
}
|
||||
}
|
||||
|
||||
_intentionalDisconnect = false;
|
||||
@ -629,8 +670,16 @@ internal class MenuManager : MonoBehaviour, IAddComponentOnStart
|
||||
QSBCore.IsInMultiplayer = true;
|
||||
_intentionalDisconnect = false;
|
||||
|
||||
var profile = QSBProfileManager._currentProfile;
|
||||
PlayerData.Init(profile.multiplayerGameSave, profile.settingsSave, profile.graphicsSettings, profile.inputJSON);
|
||||
if (QSBCore.IsStandalone)
|
||||
{
|
||||
var profile = QSBStandaloneProfileManager.SharedInstance.currentProfile;
|
||||
PlayerData.Init(profile.multiplayerGameSave, profile.settingsSave, profile.graphicsSettings, profile.inputJSON);
|
||||
}
|
||||
else
|
||||
{
|
||||
var manager = QSBMSStoreProfileManager.SharedInstance;
|
||||
PlayerData.Init(manager.currentProfileMultiplayerGameSave, manager.currentProfileGameSettings, manager.currentProfileGraphicsSettings, manager.currentProfileInputJSON);
|
||||
}
|
||||
|
||||
var address = ConnectPopup.GetInputText();
|
||||
if (address == string.Empty)
|
||||
|
@ -8,7 +8,7 @@ public abstract class QSBPatch
|
||||
{
|
||||
public abstract QSBPatchTypes Type { get; }
|
||||
|
||||
public virtual PatchVendor PatchVendor => PatchVendor.Epic | PatchVendor.Steam | PatchVendor.Gamepass;
|
||||
public virtual GameVendor PatchVendor => GameVendor.Epic | GameVendor.Steam | GameVendor.Gamepass;
|
||||
|
||||
public void DoPatches(Harmony instance) => instance.PatchAll(GetType());
|
||||
|
||||
|
@ -14,7 +14,6 @@ public static class QSBPatchManager
|
||||
|
||||
private static readonly List<QSBPatch> _patchList = new();
|
||||
private static readonly List<QSBPatchTypes> _patchedTypes = new();
|
||||
private static PatchVendor _vendor = PatchVendor.None;
|
||||
|
||||
public static Dictionary<QSBPatchTypes, Harmony> TypeToInstance = new();
|
||||
|
||||
@ -30,30 +29,6 @@ public static class QSBPatchManager
|
||||
TypeToInstance.Add(type, new Harmony(type.ToString()));
|
||||
}
|
||||
|
||||
var gameAssemblyTypes = typeof(AstroObject).Assembly.GetTypes();
|
||||
var isEpic = gameAssemblyTypes.Any(x => x.Name == "EpicEntitlementRetriever");
|
||||
var isSteam = gameAssemblyTypes.Any(x => x.Name == "SteamEntitlementRetriever");
|
||||
var isUWP = gameAssemblyTypes.Any(x => x.Name == "MSStoreEntitlementRetriever");
|
||||
|
||||
if (isEpic && !isSteam && !isUWP)
|
||||
{
|
||||
_vendor = PatchVendor.Epic;
|
||||
}
|
||||
else if (!isEpic && isSteam && !isUWP)
|
||||
{
|
||||
_vendor = PatchVendor.Steam;
|
||||
}
|
||||
else if (!isEpic && !isSteam && isUWP)
|
||||
{
|
||||
_vendor = PatchVendor.Gamepass;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ???
|
||||
DebugLog.ToConsole($"FATAL - Could not determine game vendor.", MessageType.Fatal);
|
||||
}
|
||||
|
||||
DebugLog.DebugWrite($"Determined game vendor as {_vendor}", MessageType.Info);
|
||||
DebugLog.DebugWrite("Patch Manager ready.", MessageType.Success);
|
||||
}
|
||||
|
||||
@ -67,7 +42,7 @@ public static class QSBPatchManager
|
||||
|
||||
OnPatchType?.SafeInvoke(type);
|
||||
//DebugLog.DebugWrite($"Patch block {Enum.GetName(typeof(QSBPatchTypes), type)}", MessageType.Info);
|
||||
foreach (var patch in _patchList.Where(x => x.Type == type && x.PatchVendor.HasFlag(_vendor)))
|
||||
foreach (var patch in _patchList.Where(x => x.Type == type && x.PatchVendor.HasFlag(QSBCore.GameVendor)))
|
||||
{
|
||||
//DebugLog.DebugWrite($" - Patching in {patch.GetType().Name}", MessageType.Info);
|
||||
try
|
||||
|
@ -90,7 +90,7 @@
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="OuterWildsGameLibs" Version="1.1.12.168" IncludeAssets="compile" />
|
||||
<PackageReference Include="OuterWildsGameLibs" Version="1.1.12.201" IncludeAssets="compile" />
|
||||
<Reference Include="..\Mirror\*.dll" />
|
||||
<Reference Include="..\UniTask\*.dll" />
|
||||
<ProjectReference Include="..\EpicOnlineTransport\EpicOnlineTransport.csproj" />
|
||||
|
@ -6,6 +6,7 @@ using QSB.Localization;
|
||||
using QSB.Menus;
|
||||
using QSB.Patches;
|
||||
using QSB.QuantumSync;
|
||||
using QSB.SaveSync;
|
||||
using QSB.Utility;
|
||||
using QSB.WorldSync;
|
||||
using System;
|
||||
@ -55,6 +56,11 @@ public class QSBCore : ModBehaviour
|
||||
Application.version.Split('.').Take(3).Join(delimiter: ".");
|
||||
public static bool DLCInstalled => EntitlementsManager.IsDlcOwned() == EntitlementsManager.AsyncOwnershipStatus.Owned;
|
||||
public static bool IncompatibleModsAllowed { get; private set; }
|
||||
public static GameVendor GameVendor { get; private set; } = GameVendor.None;
|
||||
public static bool IsStandalone => GameVendor is GameVendor.Epic or GameVendor.Steam;
|
||||
public static IProfileManager ProfileManager => IsStandalone
|
||||
? QSBStandaloneProfileManager.SharedInstance
|
||||
: QSBMSStoreProfileManager.SharedInstance;
|
||||
public static IMenuAPI MenuApi { get; private set; }
|
||||
public static DebugSettings DebugSettings { get; private set; } = new();
|
||||
public static Storage Storage { get; private set; } = new();
|
||||
@ -70,6 +76,34 @@ public class QSBCore : ModBehaviour
|
||||
"Vesper.AutoResume"
|
||||
};
|
||||
|
||||
private static void DetermineGameVendor()
|
||||
{
|
||||
var gameAssemblyTypes = typeof(AstroObject).Assembly.GetTypes();
|
||||
var isEpic = gameAssemblyTypes.Any(x => x.Name == "EpicEntitlementRetriever");
|
||||
var isSteam = gameAssemblyTypes.Any(x => x.Name == "SteamEntitlementRetriever");
|
||||
var isUWP = gameAssemblyTypes.Any(x => x.Name == "MSStoreEntitlementRetriever");
|
||||
|
||||
if (isEpic && !isSteam && !isUWP)
|
||||
{
|
||||
GameVendor = GameVendor.Epic;
|
||||
}
|
||||
else if (!isEpic && isSteam && !isUWP)
|
||||
{
|
||||
GameVendor = GameVendor.Steam;
|
||||
}
|
||||
else if (!isEpic && !isSteam && isUWP)
|
||||
{
|
||||
GameVendor = GameVendor.Gamepass;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ???
|
||||
DebugLog.ToConsole($"FATAL - Could not determine game vendor.", MessageType.Fatal);
|
||||
}
|
||||
|
||||
DebugLog.DebugWrite($"Determined game vendor as {GameVendor}", MessageType.Info);
|
||||
}
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
EpicRerouter.ModSide.Interop.Go();
|
||||
@ -77,6 +111,11 @@ public class QSBCore : ModBehaviour
|
||||
// no, we cant localize this - languages are loaded after the splash screen
|
||||
UIHelper.ReplaceUI(UITextType.PleaseUseController,
|
||||
"<color=orange>Quantum Space Buddies</color> is best experienced with friends...");
|
||||
|
||||
DetermineGameVendor();
|
||||
|
||||
QSBPatchManager.Init();
|
||||
QSBPatchManager.DoPatchType(QSBPatchTypes.OnModStart);
|
||||
}
|
||||
|
||||
public void Start()
|
||||
@ -133,7 +172,6 @@ public class QSBCore : ModBehaviour
|
||||
return;
|
||||
}
|
||||
|
||||
QSBPatchManager.Init();
|
||||
DeterministicManager.Init();
|
||||
QSBLocalization.Init();
|
||||
|
||||
@ -144,8 +182,6 @@ public class QSBCore : ModBehaviour
|
||||
QSBWorldSync.Managers = components.OfType<WorldObjectManager>().ToArray();
|
||||
QSBPatchManager.OnPatchType += OnPatchType;
|
||||
QSBPatchManager.OnUnpatchType += OnUnpatchType;
|
||||
|
||||
QSBPatchManager.DoPatchType(QSBPatchTypes.OnModStart);
|
||||
}
|
||||
|
||||
private static void OnPatchType(QSBPatchTypes type)
|
||||
|
@ -102,7 +102,7 @@ public class QSBNetworkManager : NetworkManager, IAddComponentOnStart
|
||||
base.Awake();
|
||||
|
||||
InitPlayerName();
|
||||
StandaloneProfileManager.SharedInstance.OnProfileSignInComplete += _ => InitPlayerName();
|
||||
QSBCore.ProfileManager.OnProfileSignInComplete += _ => InitPlayerName();
|
||||
|
||||
playerPrefab = QSBCore.NetworkAssetBundle.LoadAsset<GameObject>("Assets/Prefabs/NETWORK_Player_Body.prefab");
|
||||
playerPrefab.GetRequiredComponent<NetworkIdentity>().SetValue("m_AssetId", 1.ToGuid().ToString("N"));
|
||||
@ -157,15 +157,22 @@ public class QSBNetworkManager : NetworkManager, IAddComponentOnStart
|
||||
{
|
||||
try
|
||||
{
|
||||
var titleScreenManager = FindObjectOfType<TitleScreenManager>();
|
||||
var profileManager = titleScreenManager._profileManager;
|
||||
if (profileManager.GetType().Name == "MSStoreProfileManager")
|
||||
if (!QSBCore.IsStandalone)
|
||||
{
|
||||
PlayerName = (string)profileManager.GetType().GetProperty("userDisplayName").GetValue(profileManager);
|
||||
PlayerName = QSBMSStoreProfileManager.SharedInstance.userDisplayName;
|
||||
}
|
||||
else
|
||||
{
|
||||
PlayerName = QSBProfileManager._currentProfile.profileName;
|
||||
var currentProfile = QSBStandaloneProfileManager.SharedInstance.currentProfile;
|
||||
|
||||
if (currentProfile == null)
|
||||
{
|
||||
// probably havent created a profile yet
|
||||
Delay.RunWhen(() => QSBStandaloneProfileManager.SharedInstance.currentProfile != null, () => InitPlayerName());
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerName = currentProfile.profileName;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
33
QSB/SaveSync/Patches/InGameProfileMenuManagerPatches.cs
Normal file
33
QSB/SaveSync/Patches/InGameProfileMenuManagerPatches.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using HarmonyLib;
|
||||
using QSB.Patches;
|
||||
|
||||
namespace QSB.SaveSync.Patches;
|
||||
|
||||
[HarmonyPatch(typeof(InGameProfileMenuManager))]
|
||||
internal class InGameProfileMenuManagerPatches : QSBPatch
|
||||
{
|
||||
public override QSBPatchTypes Type => QSBPatchTypes.OnModStart;
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(nameof(InGameProfileMenuManager.InitializeOnAwake))]
|
||||
public static bool InitializeOnAwake(InGameProfileMenuManager __instance)
|
||||
{
|
||||
if (!__instance._initialized)
|
||||
{
|
||||
TextTranslation.Get().OnLanguageChanged += __instance.UpdateLanguage;
|
||||
__instance.UpdateLanguage();
|
||||
__instance._profileManager = QSBCore.ProfileManager;
|
||||
__instance._profileManager.OnProfileSignInComplete += __instance.OnProfileSignInComplete;
|
||||
__instance._profileManager.OnProfileSignOutComplete += __instance.OnProfileSignOutComplete;
|
||||
__instance._profileManager.OnProfileReadDone += __instance.OnProfileReadDone;
|
||||
__instance._returnToGameSubmitAction.OnSubmitAction += __instance.OnResumeGameBtnSubmit;
|
||||
__instance._returnToTitleSubmitAction.OnSubmitAction += __instance.OnTitleSubmitAction;
|
||||
LoadManager.OnStartSceneLoad += __instance.OnStartSceneLoad;
|
||||
LoadManager.OnCompleteSceneLoad += __instance.OnCompleteSceneLoad;
|
||||
GlobalMessenger.AddListener("PlayerResurrection", new Callback(__instance.OnPlayerResurrection));
|
||||
__instance._initialized = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
54
QSB/SaveSync/Patches/PlayerDataPatches.cs
Normal file
54
QSB/SaveSync/Patches/PlayerDataPatches.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using HarmonyLib;
|
||||
using QSB.Patches;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QSB.SaveSync.Patches;
|
||||
|
||||
[HarmonyPatch(typeof(PlayerData))]
|
||||
internal class PlayerDataPatches : QSBPatch
|
||||
{
|
||||
public override QSBPatchTypes Type => QSBPatchTypes.OnModStart;
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(nameof(PlayerData.ResetGame))]
|
||||
public static bool ResetGame()
|
||||
{
|
||||
PlayerData._currentGameSave = new GameSave();
|
||||
QSBCore.ProfileManager.SaveGame(PlayerData._currentGameSave, null, null, null);
|
||||
return false;
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(nameof(PlayerData.SaveCurrentGame))]
|
||||
public static bool SaveCurrentGame()
|
||||
{
|
||||
PlayerData._currentGameSave.version = Application.version;
|
||||
QSBCore.ProfileManager.SaveGame(PlayerData._currentGameSave, null, null, null);
|
||||
return false;
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(nameof(PlayerData.SaveInputSettings))]
|
||||
public static bool SaveInputSettings()
|
||||
{
|
||||
QSBCore.ProfileManager.SaveGame(null, null, null, PlayerData.inputJSON);
|
||||
return false;
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(nameof(PlayerData.SaveSettings))]
|
||||
public static bool SaveSettings()
|
||||
{
|
||||
QSBCore.ProfileManager.SaveGame(null, PlayerData._settingsSave, PlayerData._graphicsSettings, PlayerData.inputJSON);
|
||||
return false;
|
||||
}
|
||||
|
||||
// this is actually still StandaloneProfileManager in the gamepass dll. game bug?
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(nameof(PlayerData.IsBusy))]
|
||||
public static bool IsBusy(ref bool __result)
|
||||
{
|
||||
__result = QSBCore.ProfileManager.isBusyWithFileOps;
|
||||
return false;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
19
QSB/SaveSync/Patches/ProfileManagerUpdaterPatches.cs
Normal file
19
QSB/SaveSync/Patches/ProfileManagerUpdaterPatches.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using HarmonyLib;
|
||||
using QSB.Patches;
|
||||
|
||||
namespace QSB.SaveSync.Patches;
|
||||
|
||||
[HarmonyPatch(typeof(ProfileManagerUpdater))]
|
||||
internal class ProfileManagerUpdaterPatches : QSBPatch
|
||||
{
|
||||
public override QSBPatchTypes Type => QSBPatchTypes.OnModStart;
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(nameof(ProfileManagerUpdater.Start))]
|
||||
public static bool Start(ProfileManagerUpdater __instance)
|
||||
{
|
||||
__instance._profileManager = QSBCore.ProfileManager;
|
||||
__instance.enabled = true;
|
||||
return false;
|
||||
}
|
||||
}
|
212
QSB/SaveSync/Patches/ProfileMenuManagerPatches.cs
Normal file
212
QSB/SaveSync/Patches/ProfileMenuManagerPatches.cs
Normal file
@ -0,0 +1,212 @@
|
||||
using HarmonyLib;
|
||||
using QSB.Patches;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace QSB.SaveSync.Patches;
|
||||
|
||||
[HarmonyPatch(typeof(ProfileMenuManager))]
|
||||
internal class ProfileMenuManagerPatches : QSBPatch
|
||||
{
|
||||
public override QSBPatchTypes Type => QSBPatchTypes.OnModStart;
|
||||
public override GameVendor PatchVendor => GameVendor.Epic | GameVendor.Steam;
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(nameof(ProfileMenuManager.OnCreateProfileConfirm))]
|
||||
public static bool OnCreateProfileConfirm(ProfileMenuManager __instance)
|
||||
{
|
||||
__instance._inputPopupActivated = false;
|
||||
var inputPopup = __instance._createProfileAction.GetInputPopup();
|
||||
inputPopup.OnPopupValidate -= __instance.OnCreateProfileValidate;
|
||||
inputPopup.OnInputPopupValidateChar -= __instance.OnValidateChar;
|
||||
__instance._createProfileAction.OnSubmitAction -= __instance.OnCreateProfileConfirm;
|
||||
QSBStandaloneProfileManager.SharedInstance.TryCreateProfile(__instance._createProfileAction.GetInputString());
|
||||
inputPopup.CloseMenuOnOk(true);
|
||||
__instance.PopulateProfiles();
|
||||
__instance.SetCurrentProfileLabel();
|
||||
inputPopup.EnableMenu(false);
|
||||
if (__instance._firstTimeProfileCreation)
|
||||
{
|
||||
__instance._firstTimeProfileCreation = false;
|
||||
__instance.UpdatePopupPrompts();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(nameof(ProfileMenuManager.OnCreateProfileValidate))]
|
||||
public static bool OnCreateProfileValidate(ProfileMenuManager __instance, ref bool __result)
|
||||
{
|
||||
var inputPopup = __instance._createProfileAction.GetInputPopup();
|
||||
__result = QSBStandaloneProfileManager.SharedInstance.ValidateProfileName(inputPopup.GetInputText());
|
||||
return false;
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(nameof(ProfileMenuManager.OnDeleteProfile))]
|
||||
public static bool OnDeleteProfile(ProfileMenuManager __instance)
|
||||
{
|
||||
if (__instance._lastSelectedProfileAction != null)
|
||||
{
|
||||
__instance._deleteProfileConfirmPopup = null;
|
||||
QSBStandaloneProfileManager.SharedInstance.DeleteProfile(__instance._lastSelectedProfileAction.GetLabelText());
|
||||
__instance.PopulateProfiles();
|
||||
__instance._lastSelectedProfileAction = null;
|
||||
Locator.GetMenuInputModule().SelectOnNextUpdate(__instance._createProfileButton);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(nameof(ProfileMenuManager.OnSwitchProfile))]
|
||||
public static bool OnSwitchProfile(ProfileMenuManager __instance)
|
||||
{
|
||||
if (__instance._lastSelectedProfileAction != null)
|
||||
{
|
||||
__instance._switchProfileConfirmPopup = null;
|
||||
if (QSBStandaloneProfileManager.SharedInstance.SwitchProfile(__instance._lastSelectedProfileAction.GetLabelText()))
|
||||
{
|
||||
__instance.PopulateProfiles();
|
||||
__instance.SetCurrentProfileLabel();
|
||||
__instance._lastSelectedProfileAction = null;
|
||||
Locator.GetMenuInputModule().SelectOnNextUpdate(__instance._createProfileButton);
|
||||
return false;
|
||||
}
|
||||
|
||||
QSBStandaloneProfileManager.SharedInstance.OnBackupDataRestored += __instance.OnSwitchProfileDataRecoveryCompleted;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(nameof(ProfileMenuManager.OnSwitchProfileDataRecoveryCompleted))]
|
||||
public static bool OnSwitchProfileDataRecoveryCompleted(ProfileMenuManager __instance)
|
||||
{
|
||||
QSBStandaloneProfileManager.SharedInstance.OnBackupDataRestored -= __instance.OnSwitchProfileDataRecoveryCompleted;
|
||||
__instance.PopulateProfiles();
|
||||
__instance.SetCurrentProfileLabel();
|
||||
__instance._lastSelectedProfileAction = null;
|
||||
Locator.GetMenuInputModule().SelectOnNextUpdate(__instance._createProfileButton);
|
||||
return false;
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(nameof(ProfileMenuManager.OnValidateChar))]
|
||||
public static bool OnValidateChar(ProfileMenuManager __instance, char c, ref bool __result)
|
||||
{
|
||||
__result = __instance._createProfileAction.GetInputPopup().GetInputText().Length < QSBStandaloneProfileManager.SharedInstance.profileNameCharacterLimit
|
||||
&& QSBStandaloneProfileManager.SharedInstance.IsValidCharacterForProfileName(c);
|
||||
return false;
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(nameof(ProfileMenuManager.PopulateProfiles))]
|
||||
public static bool PopulateProfiles(ProfileMenuManager __instance)
|
||||
{
|
||||
if (__instance._listProfileElements == null)
|
||||
{
|
||||
__instance._listProfileElements = new List<GameObject>();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < __instance._listProfileElements.Count; i++)
|
||||
{
|
||||
TwoButtonActionElement requiredComponent = __instance._listProfileElements[i].GetRequiredComponent<TwoButtonActionElement>();
|
||||
__instance.ClearProfileElementListeners(requiredComponent);
|
||||
Object.Destroy(__instance._listProfileElements[i]);
|
||||
}
|
||||
__instance._listProfileElements.Clear();
|
||||
}
|
||||
|
||||
if (__instance._listProfileUIElementLookup == null)
|
||||
{
|
||||
__instance._listProfileUIElementLookup = new List<ProfileMenuManager.ProfileElementLookup>();
|
||||
}
|
||||
else
|
||||
{
|
||||
__instance._listProfileUIElementLookup.Clear();
|
||||
}
|
||||
|
||||
var array = QSBStandaloneProfileManager.SharedInstance.profiles.ToArray();
|
||||
var profileName = QSBStandaloneProfileManager.SharedInstance.currentProfile.profileName;
|
||||
var num = 0;
|
||||
Selectable selectable = null;
|
||||
for (int j = 0; j < array.Length; j++)
|
||||
{
|
||||
if (!(array[j].profileName == profileName))
|
||||
{
|
||||
GameObject gameObject = Object.Instantiate<GameObject>(__instance._profileItemTemplate);
|
||||
gameObject.gameObject.SetActive(true);
|
||||
gameObject.transform.SetParent(__instance._profileListRoot.transform);
|
||||
gameObject.transform.localScale = new Vector3(1f, 1f, 1f);
|
||||
Text[] componentsInChildren = gameObject.gameObject.GetComponentsInChildren<Text>();
|
||||
for (int k = 0; k < componentsInChildren.Length; k++)
|
||||
{
|
||||
__instance._fontController.AddTextElement(componentsInChildren[k], true, true, false);
|
||||
}
|
||||
|
||||
num++;
|
||||
TwoButtonActionElement requiredComponent2 = gameObject.GetRequiredComponent<TwoButtonActionElement>();
|
||||
Selectable requiredComponent3 = requiredComponent2.GetRequiredComponent<Selectable>();
|
||||
__instance.SetUpProfileElementListeners(requiredComponent2);
|
||||
requiredComponent2.SetLabelText(array[j].profileName);
|
||||
Text component = requiredComponent2.GetButtonOne().GetComponent<Text>();
|
||||
if (component != null)
|
||||
{
|
||||
__instance._fontController.AddTextElement(component, true, true, false);
|
||||
}
|
||||
|
||||
component = requiredComponent2.GetButtonTwo().GetComponent<Text>();
|
||||
if (component != null)
|
||||
{
|
||||
__instance._fontController.AddTextElement(component, true, true, false);
|
||||
}
|
||||
|
||||
if (num == 1)
|
||||
{
|
||||
Navigation navigation = __instance._createProfileButton.navigation;
|
||||
navigation.selectOnDown = gameObject.GetRequiredComponent<Selectable>();
|
||||
__instance._createProfileButton.navigation = navigation;
|
||||
Navigation navigation2 = requiredComponent3.navigation;
|
||||
navigation2.selectOnUp = __instance._createProfileButton;
|
||||
requiredComponent3.navigation = navigation2;
|
||||
}
|
||||
else
|
||||
{
|
||||
Navigation navigation3 = requiredComponent3.navigation;
|
||||
Navigation navigation4 = selectable.navigation;
|
||||
navigation3.selectOnUp = selectable;
|
||||
navigation3.selectOnDown = null;
|
||||
navigation4.selectOnDown = requiredComponent3;
|
||||
requiredComponent3.navigation = navigation3;
|
||||
selectable.navigation = navigation4;
|
||||
}
|
||||
|
||||
__instance._listProfileElements.Add(gameObject);
|
||||
selectable = requiredComponent3;
|
||||
ProfileMenuManager.ProfileElementLookup profileElementLookup = new ProfileMenuManager.ProfileElementLookup();
|
||||
profileElementLookup.profileName = array[j].profileName;
|
||||
profileElementLookup.lastModifiedTime = array[j].lastModifiedTime;
|
||||
profileElementLookup.confirmSwitchAction = requiredComponent2.GetSubmitActionOne() as SubmitActionConfirm;
|
||||
profileElementLookup.confirmDeleteAction = requiredComponent2.GetSubmitActionTwo() as SubmitActionConfirm;
|
||||
__instance._listProfileUIElementLookup.Add(profileElementLookup);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(nameof(ProfileMenuManager.SetCurrentProfileLabel))]
|
||||
public static bool SetCurrentProfileLabel(ProfileMenuManager __instance)
|
||||
{
|
||||
__instance._currenProfileLabel.text = UITextLibrary.GetString(UITextType.MenuProfile)
|
||||
+ " "
|
||||
+ QSBStandaloneProfileManager.SharedInstance.currentProfile.profileName;
|
||||
return false;
|
||||
}
|
||||
}
|
90
QSB/SaveSync/Patches/TitleScreenManagerPatchesCommon.cs
Normal file
90
QSB/SaveSync/Patches/TitleScreenManagerPatchesCommon.cs
Normal file
@ -0,0 +1,90 @@
|
||||
using HarmonyLib;
|
||||
using QSB.Patches;
|
||||
using QSB.Utility;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace QSB.SaveSync.Patches;
|
||||
|
||||
[HarmonyPatch(typeof(TitleScreenManager))]
|
||||
internal class TitleScreenManagerPatchesCommon : QSBPatch
|
||||
{
|
||||
public override QSBPatchTypes Type => QSBPatchTypes.OnModStart;
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(nameof(TitleScreenManager.Awake))]
|
||||
public static bool Awake(TitleScreenManager __instance)
|
||||
{
|
||||
__instance._profileManager = QSBCore.ProfileManager;
|
||||
__instance._profileManager.PreInitialize();
|
||||
LoadManager.OnStartSceneLoad += __instance.OnStartSceneLoad;
|
||||
LoadManager.OnCompleteSceneLoad += __instance.OnCompleteSceneLoad;
|
||||
MenuStackManager.SharedInstance.OnMenuPush += __instance.OnMenuPush;
|
||||
MenuStackManager.SharedInstance.OnMenuPop += __instance.OnMenuPop;
|
||||
__instance._resumeGameTextSetter = __instance._resumeGameObject.GetComponentInChildren<ResumeGameLocalizedText>();
|
||||
__instance.InitializePopupPrompts();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(nameof(TitleScreenManager.InitializeProfileManagerCallbacks))]
|
||||
public static bool InitializeProfileManagerCallbacks(TitleScreenManager __instance)
|
||||
{
|
||||
if (QSBCore.IsStandalone)
|
||||
{
|
||||
QSBStandaloneProfileManager.SharedInstance.OnNoProfilesExist += __instance.OnNoStandaloneProfilesExist;
|
||||
QSBStandaloneProfileManager.SharedInstance.OnUpdatePlayerProfiles += __instance.OnUpdatePlayerProfiles;
|
||||
QSBStandaloneProfileManager.SharedInstance.OnBrokenDataExists += __instance.OnBrokenDataExists;
|
||||
}
|
||||
else
|
||||
{
|
||||
QSBMSStoreProfileManager.SharedInstance.OnBrokenDataExists += __instance.OnBrokenDataExists;
|
||||
}
|
||||
|
||||
__instance._profileManager.OnProfileSignInStart += __instance.OnProfileSignInStart;
|
||||
__instance._profileManager.OnProfileSignInComplete += __instance.OnProfileSignInComplete;
|
||||
__instance._profileManager.OnProfileSignOutStart += __instance.OnProfileSignOutStart;
|
||||
__instance._profileManager.OnProfileSignOutComplete += __instance.OnProfileSignOutComplete;
|
||||
__instance._profileManager.OnProfileReadDone += __instance.OnProfileManagerReadDone;
|
||||
__instance._profileManager.Initialize();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(nameof(TitleScreenManager.OnDestroy))]
|
||||
public static bool OnDestroy(TitleScreenManager __instance)
|
||||
{
|
||||
if (QSBCore.IsStandalone)
|
||||
{
|
||||
QSBStandaloneProfileManager.SharedInstance.OnNoProfilesExist -= __instance.OnNoStandaloneProfilesExist;
|
||||
QSBStandaloneProfileManager.SharedInstance.OnUpdatePlayerProfiles -= __instance.OnUpdatePlayerProfiles;
|
||||
QSBStandaloneProfileManager.SharedInstance.OnBrokenDataExists -= __instance.OnBrokenDataExists;
|
||||
}
|
||||
else
|
||||
{
|
||||
QSBMSStoreProfileManager.SharedInstance.OnBrokenDataExists -= __instance.OnBrokenDataExists;
|
||||
}
|
||||
|
||||
__instance._profileManager.OnProfileSignInStart -= __instance.OnProfileSignInStart;
|
||||
__instance._profileManager.OnProfileSignInComplete -= __instance.OnProfileSignInComplete;
|
||||
__instance._profileManager.OnProfileSignOutStart -= __instance.OnProfileSignOutStart;
|
||||
__instance._profileManager.OnProfileSignOutComplete -= __instance.OnProfileSignOutComplete;
|
||||
__instance._profileManager.OnProfileReadDone -= __instance.OnProfileManagerReadDone;
|
||||
LoadManager.OnStartSceneLoad -= __instance.OnStartSceneLoad;
|
||||
LoadManager.OnCompleteSceneLoad -= __instance.OnCompleteSceneLoad;
|
||||
TextTranslation.Get().OnLanguageChanged -= __instance.OnLanguageChanged;
|
||||
__instance._newGameAction.OnSubmitAction -= __instance.OnNewGameSubmit;
|
||||
__instance._newGameAction.OnPostSetupPopup -= __instance.OnNewGameSetupPopup;
|
||||
__instance._resetGameAction.OnSubmitAction -= __instance.OnResetGameSubmit;
|
||||
__instance._accountPickerSubmitAction.OnAccountPickerSubmitEvent -= __instance.OnAccountPickerSubmitEvent;
|
||||
MenuStackManager.SharedInstance.OnMenuPush -= __instance.OnMenuPush;
|
||||
MenuStackManager.SharedInstance.OnMenuPop -= __instance.OnMenuPop;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
23
QSB/SaveSync/Patches/TitleScreenManagerPatchesGamepass.cs
Normal file
23
QSB/SaveSync/Patches/TitleScreenManagerPatchesGamepass.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using HarmonyLib;
|
||||
using QSB.Patches;
|
||||
using System.Reflection;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace QSB.SaveSync.Patches;
|
||||
|
||||
[HarmonyPatch(typeof(TitleScreenManager))]
|
||||
internal class TitleScreenManagerPatchesGamepass : QSBPatch
|
||||
{
|
||||
public override QSBPatchTypes Type => QSBPatchTypes.OnModStart;
|
||||
public override GameVendor PatchVendor => GameVendor.Gamepass;
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch("SetUserAccountDisplayInfo")]
|
||||
public static bool SetUserAccountDisplayInfo(TitleScreenManager __instance)
|
||||
{
|
||||
var text = (Text)__instance.GetType().GetField("_gamertagDisplay", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);
|
||||
text.text = ""; // no idea why, mobius be like
|
||||
text.text = QSBMSStoreProfileManager.SharedInstance.userDisplayName;
|
||||
return false;
|
||||
}
|
||||
}
|
45
QSB/SaveSync/Patches/TitleScreenManagerPatchesStandalone.cs
Normal file
45
QSB/SaveSync/Patches/TitleScreenManagerPatchesStandalone.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using HarmonyLib;
|
||||
using QSB.Patches;
|
||||
|
||||
namespace QSB.SaveSync.Patches;
|
||||
|
||||
[HarmonyPatch(typeof(TitleScreenManager))]
|
||||
internal class TitleScreenManagerPatchesStandalone : QSBPatch
|
||||
{
|
||||
public override QSBPatchTypes Type => QSBPatchTypes.OnModStart;
|
||||
public override GameVendor PatchVendor => GameVendor.Epic | GameVendor.Steam;
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(nameof(TitleScreenManager.OnBrokenDataExists))]
|
||||
public static bool OnBrokenDataExists(TitleScreenManager __instance)
|
||||
{
|
||||
__instance._titleMenuRaycastBlocker.blocksRaycasts = false;
|
||||
__instance._inputModule.EnableInputs();
|
||||
__instance._waitingOnBrokenDataResponse = true;
|
||||
var flag = QSBStandaloneProfileManager.SharedInstance.BackupExistsForBrokenData();
|
||||
var text = UITextLibrary.GetString(UITextType.SaveRestore_CorruptedMsg);
|
||||
if (flag)
|
||||
{
|
||||
text = text + " " + UITextLibrary.GetString(UITextType.SaveRestore_LoadPreviousMsg);
|
||||
}
|
||||
|
||||
__instance._okCancelPopup.ResetPopup();
|
||||
__instance._okCancelPopup.SetUpPopup(text, InputLibrary.confirm, InputLibrary.cancel, __instance._confirmActionPrompt, __instance._cancelActionPrompt, true, flag);
|
||||
__instance._okCancelPopup.OnPopupConfirm += __instance.OnUserConfirmRestoreData;
|
||||
__instance._okCancelPopup.OnPopupCancel += __instance.OnUserCancelRestoreData;
|
||||
__instance._okCancelPopup.EnableMenu(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(nameof(TitleScreenManager.OnUserConfirmRestoreData))]
|
||||
public static bool OnUserConfirmRestoreData(TitleScreenManager __instance)
|
||||
{
|
||||
__instance._waitingOnBrokenDataResponse = false;
|
||||
QSBStandaloneProfileManager.SharedInstance.RestoreCurrentProfileBackup();
|
||||
__instance.OnProfileManagerReadDone();
|
||||
__instance._okCancelPopup.OnPopupConfirm -= __instance.OnUserConfirmRestoreData;
|
||||
__instance._okCancelPopup.OnPopupCancel -= __instance.OnUserCancelRestoreData;
|
||||
return false;
|
||||
}
|
||||
}
|
429
QSB/SaveSync/QSBMSStoreProfileManager.cs
Normal file
429
QSB/SaveSync/QSBMSStoreProfileManager.cs
Normal file
@ -0,0 +1,429 @@
|
||||
using Microsoft.Xbox;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Xml.Serialization;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
namespace QSB.SaveSync;
|
||||
|
||||
internal class QSBMSStoreProfileManager : IProfileManager
|
||||
{
|
||||
private const string OW_SAVE_CONTAINER_NAME = "GameSave";
|
||||
private const string OW_GAME_SAVE_BLOB_NAME = "Outer Wilds Converted";
|
||||
private const string OW_GAME_SETTINGS_BLOB_NAME = "PCGameSettings";
|
||||
|
||||
private static QSBMSStoreProfileManager _sharedInstance;
|
||||
private QSBX1SaveData _saveData;
|
||||
private const string c_containerName = "OuterWildsConnectedStorage";
|
||||
private GameSave _pendingGameSave;
|
||||
private SettingsSave _pendingSettingsSave;
|
||||
private GraphicSettings _pendingGfxSettingsSave;
|
||||
private string _pendingInputActionsSave = "";
|
||||
private JsonSerializer _jsonSerializer;
|
||||
private bool _initialized;
|
||||
private int _fileOpsBusyLocks;
|
||||
private bool _preInitialized;
|
||||
private bool _isLoadingGameBlob;
|
||||
private bool _isLoadingSettingsBlob;
|
||||
|
||||
public static QSBMSStoreProfileManager SharedInstance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_sharedInstance == null)
|
||||
{
|
||||
_sharedInstance = new QSBMSStoreProfileManager();
|
||||
}
|
||||
|
||||
return _sharedInstance;
|
||||
}
|
||||
}
|
||||
|
||||
public GameSave currentProfileGameSave => _saveData.gameSave;
|
||||
public GameSave currentProfileMultiplayerGameSave => _saveData.gameMultSave;
|
||||
public SettingsSave currentProfileGameSettings => _saveData.settings;
|
||||
public GraphicSettings currentProfileGraphicsSettings => _saveData.gfxSettings;
|
||||
public string currentProfileInputJSON => _saveData.inputActionsJson;
|
||||
public bool isInitialized { get; }
|
||||
public bool isBusyWithFileOps => _fileOpsBusyLocks > 0;
|
||||
public bool hasPendingSaveOperation => _pendingGameSave != null || _pendingSettingsSave != null || _pendingGfxSettingsSave != null || _pendingInputActionsSave != null;
|
||||
public bool saveSystemAvailable { get; private set; }
|
||||
public string userDisplayName => Gdk.Helpers.currentGamertag;
|
||||
|
||||
public delegate void BrokenDataExistsEvent();
|
||||
|
||||
public event BrokenDataExistsEvent OnBrokenDataExists;
|
||||
public event ProfileDataSavedEvent OnProfileDataSaved;
|
||||
public event ProfileReadDoneEvent OnProfileReadDone;
|
||||
public event ProfileSignInCompleteEvent OnProfileSignInComplete;
|
||||
public event ProfileSignInStartEvent OnProfileSignInStart;
|
||||
public event ProfileSignOutCompleteEvent OnProfileSignOutComplete;
|
||||
public event ProfileSignOutStartEvent OnProfileSignOutStart;
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
Gdk.Helpers.SignIn();
|
||||
SpinnerUI.Show();
|
||||
Debug.Log("MSStoreProfileManager.Initialize");
|
||||
Gdk.Helpers.OnGameSaveSucceeded += OnGameSaveComplete;
|
||||
Gdk.Helpers.OnGameSaveFailed += OnGameSaveFailed;
|
||||
Gdk.Helpers.OnGameSaveLoaded += OnGameSaveLoaded;
|
||||
Gdk.Helpers.OnGameSaveLoadFailed += OnGameSaveLoadFailed;
|
||||
Achievements.Init();
|
||||
var serializationBinder = new VersionDeserializationBinder();
|
||||
_jsonSerializer = new JsonSerializer
|
||||
{
|
||||
SerializationBinder = serializationBinder
|
||||
};
|
||||
_initialized = true;
|
||||
return;
|
||||
}
|
||||
|
||||
OnProfileSignInComplete?.Invoke(ProfileManagerSignInResult.COMPLETE);
|
||||
|
||||
var onProfileReadDone = OnProfileReadDone;
|
||||
if (onProfileReadDone == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
onProfileReadDone();
|
||||
}
|
||||
|
||||
public void PreInitialize()
|
||||
{
|
||||
if (_preInitialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_fileOpsBusyLocks = 0;
|
||||
_pendingGameSave = null;
|
||||
_pendingSettingsSave = null;
|
||||
_pendingGfxSettingsSave = null;
|
||||
_pendingInputActionsSave = null;
|
||||
_preInitialized = true;
|
||||
}
|
||||
|
||||
public void InvokeProfileSignInComplete()
|
||||
{
|
||||
var onProfileSignInComplete = OnProfileSignInComplete;
|
||||
if (onProfileSignInComplete == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
onProfileSignInComplete(ProfileManagerSignInResult.COMPLETE);
|
||||
}
|
||||
|
||||
public void InvokeSaveSetupComplete()
|
||||
{
|
||||
saveSystemAvailable = true;
|
||||
_isLoadingGameBlob = true;
|
||||
_saveData = new QSBX1SaveData();
|
||||
LoadGame(OW_GAME_SAVE_BLOB_NAME);
|
||||
}
|
||||
|
||||
public void InitializeForEditor()
|
||||
{
|
||||
}
|
||||
|
||||
public void SaveGame(GameSave gameSave, SettingsSave settSave, GraphicSettings gfxSettings, string inputJSON)
|
||||
{
|
||||
Debug.Log("MSStoreProfileManager.SaveGame");
|
||||
if (isBusyWithFileOps || LoadManager.IsBusy())
|
||||
{
|
||||
_pendingGameSave = gameSave;
|
||||
_pendingSettingsSave = settSave;
|
||||
_pendingGfxSettingsSave = gfxSettings;
|
||||
_pendingInputActionsSave = inputJSON;
|
||||
return;
|
||||
}
|
||||
|
||||
var gameSaveData = new QSBX1SaveData();
|
||||
var settingsSaveData = new QSBX1SaveData();
|
||||
var saveGameSave = false;
|
||||
if (gameSave != null)
|
||||
{
|
||||
saveGameSave = true;
|
||||
|
||||
if (QSBCore.IsInMultiplayer)
|
||||
{
|
||||
_saveData.gameMultSave = gameSave;
|
||||
gameSaveData.gameMultSave = gameSave;
|
||||
}
|
||||
else
|
||||
{
|
||||
_saveData.gameSave = gameSave;
|
||||
gameSaveData.gameSave = gameSave;
|
||||
}
|
||||
}
|
||||
|
||||
var saveGameSettings = false;
|
||||
if (settSave != null)
|
||||
{
|
||||
saveGameSettings = true;
|
||||
_saveData.settings = settSave;
|
||||
settingsSaveData.settings = settSave;
|
||||
}
|
||||
else
|
||||
{
|
||||
settingsSaveData.settings = _saveData.settings;
|
||||
}
|
||||
|
||||
if (gfxSettings != null)
|
||||
{
|
||||
saveGameSettings = true;
|
||||
_saveData.gfxSettings = gfxSettings;
|
||||
settingsSaveData.gfxSettings = gfxSettings;
|
||||
}
|
||||
else
|
||||
{
|
||||
settingsSaveData.gfxSettings = _saveData.gfxSettings;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(inputJSON))
|
||||
{
|
||||
saveGameSettings = true;
|
||||
_saveData.inputActionsJson = inputJSON;
|
||||
settingsSaveData.inputActionsJson = inputJSON;
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(_saveData.inputActionsJson))
|
||||
{
|
||||
settingsSaveData.inputActionsJson = _saveData.inputActionsJson;
|
||||
}
|
||||
else
|
||||
{
|
||||
settingsSaveData.inputActionsJson = ((InputManager)OWInput.SharedInputManager).commandManager.DefaultInputActions.ToJson();
|
||||
}
|
||||
|
||||
if (saveGameSave)
|
||||
{
|
||||
WriteSaveToStorage(gameSaveData, OW_GAME_SAVE_BLOB_NAME);
|
||||
}
|
||||
|
||||
if (saveGameSettings)
|
||||
{
|
||||
WriteSaveToStorage(settingsSaveData, OW_GAME_SETTINGS_BLOB_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadGame(string blobName)
|
||||
{
|
||||
_fileOpsBusyLocks++;
|
||||
Gdk.Helpers.LoadSaveData(blobName);
|
||||
}
|
||||
|
||||
private void WriteSaveToStorage(QSBX1SaveData saveData, string blobName)
|
||||
{
|
||||
Debug.Log("Saving to storage: " + blobName);
|
||||
_fileOpsBusyLocks++;
|
||||
var memoryStream = new MemoryStream();
|
||||
using (JsonWriter jsonWriter = new JsonTextWriter(new StreamWriter(memoryStream)))
|
||||
{
|
||||
_jsonSerializer.Serialize(jsonWriter, saveData);
|
||||
}
|
||||
|
||||
var buffer = memoryStream.GetBuffer();
|
||||
Gdk.Helpers.Save(buffer, blobName);
|
||||
}
|
||||
|
||||
public void PerformPendingSaveOperation()
|
||||
{
|
||||
if (!isBusyWithFileOps && !LoadManager.IsBusy())
|
||||
{
|
||||
SaveGame(_pendingGameSave, _pendingSettingsSave, _pendingGfxSettingsSave, _pendingInputActionsSave);
|
||||
_pendingGameSave = null;
|
||||
_pendingSettingsSave = null;
|
||||
_pendingGfxSettingsSave = null;
|
||||
_pendingInputActionsSave = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnGameSaveComplete(object sender, string blobName)
|
||||
{
|
||||
_fileOpsBusyLocks--;
|
||||
Debug.Log("[GDK] save to blob " + blobName + " complete");
|
||||
}
|
||||
|
||||
private void OnGameSaveFailed(object sender, string blobName)
|
||||
{
|
||||
_fileOpsBusyLocks--;
|
||||
Debug.Log("[GDK] save to blob " + blobName + " failed");
|
||||
}
|
||||
|
||||
private void OnGameSaveLoaded(object sender, string blobName, GameSaveLoadedArgs saveData)
|
||||
{
|
||||
_fileOpsBusyLocks--;
|
||||
Debug.Log("[GDK] save file load complete! blob name: " + blobName);
|
||||
var memoryStream = new MemoryStream(saveData.Data);
|
||||
memoryStream.Seek(0L, SeekOrigin.Begin);
|
||||
using (var jsonTextReader = new JsonTextReader(new StreamReader(memoryStream)))
|
||||
{
|
||||
var x1SaveData = _jsonSerializer.Deserialize<QSBX1SaveData>(jsonTextReader);
|
||||
if (_isLoadingGameBlob)
|
||||
{
|
||||
if (x1SaveData != null)
|
||||
{
|
||||
if (x1SaveData.gameSave == null)
|
||||
{
|
||||
Debug.Log("[GDK] tempSaveData.gameSave is null (oh no)");
|
||||
}
|
||||
|
||||
_saveData.gameSave = x1SaveData.gameSave ?? new GameSave();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("[GDK] tempSaveData is null (oh no)");
|
||||
_saveData.gameSave = new GameSave();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (x1SaveData != null)
|
||||
{
|
||||
_saveData.gfxSettings = x1SaveData.gfxSettings ?? new GraphicSettings(true);
|
||||
_saveData.settings = x1SaveData.settings ?? new SettingsSave();
|
||||
_saveData.inputActionsJson = x1SaveData.inputActionsJson ?? ((InputManager)OWInput.SharedInputManager).commandManager.DefaultInputActions.ToJson();
|
||||
}
|
||||
else
|
||||
{
|
||||
_saveData.gfxSettings = new GraphicSettings(true);
|
||||
_saveData.settings = new SettingsSave();
|
||||
_saveData.inputActionsJson = ((InputManager)OWInput.SharedInputManager).commandManager.DefaultInputActions.ToJson();
|
||||
}
|
||||
|
||||
Debug.Log(string.Format("after settings load, _saveData.gameSave is null: {0}", _saveData.gameSave == null));
|
||||
Debug.Log(string.Format("_saveData loopCount: {0}", _saveData.gameSave.loopCount));
|
||||
}
|
||||
}
|
||||
|
||||
if (_isLoadingGameBlob)
|
||||
{
|
||||
_isLoadingGameBlob = false;
|
||||
LoadGame(OW_GAME_SETTINGS_BLOB_NAME);
|
||||
_isLoadingSettingsBlob = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_isLoadingSettingsBlob)
|
||||
{
|
||||
_isLoadingSettingsBlob = false;
|
||||
var onProfileReadDone = OnProfileReadDone;
|
||||
if (onProfileReadDone == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
onProfileReadDone();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnGameSaveLoadFailed(object sender, string blobName)
|
||||
{
|
||||
_fileOpsBusyLocks--;
|
||||
if (_isLoadingGameBlob)
|
||||
{
|
||||
_saveData.gameSave = new GameSave();
|
||||
SaveGame(_saveData.gameSave, null, null, null);
|
||||
_isLoadingGameBlob = false;
|
||||
LoadGame(OW_GAME_SETTINGS_BLOB_NAME);
|
||||
_isLoadingSettingsBlob = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_isLoadingSettingsBlob)
|
||||
{
|
||||
_saveData.settings = new SettingsSave();
|
||||
_saveData.gfxSettings = new GraphicSettings(true);
|
||||
_saveData.inputActionsJson = ((InputManager)OWInput.SharedInputManager).commandManager.DefaultInputActions.ToJson();
|
||||
SaveGame(null, _saveData.settings, _saveData.gfxSettings, _saveData.inputActionsJson);
|
||||
_isLoadingSettingsBlob = false;
|
||||
var onProfileReadDone = OnProfileReadDone;
|
||||
if (onProfileReadDone == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
onProfileReadDone();
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class QSBX1SaveData
|
||||
{
|
||||
[XmlElement("gameSave")]
|
||||
public GameSave gameSave;
|
||||
|
||||
[XmlElement("gameMultSave")]
|
||||
[OptionalField(VersionAdded = 5)]
|
||||
public GameSave gameMultSave;
|
||||
|
||||
[XmlElement("settings")]
|
||||
public SettingsSave settings;
|
||||
|
||||
[XmlElement("gfxSettings")]
|
||||
[OptionalField(VersionAdded = 2)]
|
||||
public GraphicSettings gfxSettings;
|
||||
|
||||
[OptionalField(VersionAdded = 3)]
|
||||
[NonSerialized]
|
||||
public InputRebindableData bindingSettings;
|
||||
|
||||
[OptionalField(VersionAdded = 4)]
|
||||
public string inputActionsPacked;
|
||||
|
||||
private InputActionAsset _inputActionsSave;
|
||||
|
||||
[JsonIgnore]
|
||||
public string inputActionsJson
|
||||
{
|
||||
get => inputActionsPacked;
|
||||
set
|
||||
{
|
||||
inputActionsPacked = value;
|
||||
if (!string.IsNullOrEmpty(inputActionsPacked))
|
||||
{
|
||||
_inputActionsSave = InputActionAsset.FromJson(inputActionsPacked);
|
||||
return;
|
||||
}
|
||||
|
||||
_inputActionsSave = ((InputManager)OWInput.SharedInputManager).commandManager.DefaultInputActions;
|
||||
}
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public InputActionAsset inputActionsSave
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_inputActionsSave == null && !string.IsNullOrEmpty(inputActionsPacked))
|
||||
{
|
||||
try
|
||||
{
|
||||
_inputActionsSave = InputActionAsset.FromJson(inputActionsPacked);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
_inputActionsSave = null;
|
||||
}
|
||||
}
|
||||
|
||||
return _inputActionsSave;
|
||||
}
|
||||
}
|
||||
|
||||
[OnDeserializing]
|
||||
private void SetDefaultValuesOnDeserializing(StreamingContext context)
|
||||
{
|
||||
gfxSettings = null;
|
||||
bindingSettings = null;
|
||||
inputActionsPacked = null;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
using QSB.Utility;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QSB.SaveSync;
|
||||
|
||||
public static class QSBProfileManager
|
||||
{
|
||||
public static readonly List<QSBProfileData> _profiles = new();
|
||||
public static QSBProfileData _currentProfile;
|
||||
public static QSBProfileData mostRecentProfile
|
||||
=> _profiles.MaxBy(x => x.lastModifiedTime);
|
||||
}
|
1121
QSB/SaveSync/QSBStandaloneProfileManager.cs
Normal file
1121
QSB/SaveSync/QSBStandaloneProfileManager.cs
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user