using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using PauseMenuSave.Logic;
using Sons.Gameplay.GameSetup;
using Sons.Gui;
using Sons.Multiplayer;
using Sons.Save;
using TMPro;
using TheForest.Utils;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Localization;
using UnityEngine.Localization.Components;
using UnityEngine.Localization.Settings;
using UnityEngine.Localization.Tables;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("PauseMenuSave")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.23.0")]
[assembly: AssemblyInformationalVersion("0.1.23+6366f4cb357066890da8b40938c52810a7bd1d8f")]
[assembly: AssemblyProduct("PauseMenuSave")]
[assembly: AssemblyTitle("PauseMenuSave")]
[assembly: AssemblyVersion("0.1.23.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
internal static class SettingMove
{
internal static void Move(ConfigFile config, string oldSection, string oldKey, ConfigEntryBase to)
{
bool saveOnConfigSet = config.SaveOnConfigSet;
config.SaveOnConfigSet = false;
try
{
ConfigEntry<string> val = config.Bind<string>(oldSection, oldKey, "\u0001", "Old place of a moved setting.");
bool num = val.Value != "\u0001";
if (num)
{
to.SetSerializedValue(((ConfigEntryBase)val).GetSerializedValue());
}
config.Remove(((ConfigEntryBase)val).Definition);
if (num)
{
config.Save();
}
}
finally
{
config.SaveOnConfigSet = saveOnConfigSet;
}
}
}
namespace PauseMenuSave
{
public class AutoSaver : MonoBehaviour
{
[HarmonyPatch(typeof(SaveGameManager), "Save", new Type[]
{
typeof(string),
typeof(string),
typeof(bool)
})]
private static class GameSaveDone
{
private static void Postfix(string dir, bool savePlayerOnly)
{
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Expected O, but got Unknown
if (!savePlayerOnly && uint.TryParse(Path.GetFileName(dir?.TrimEnd('/', '\\')), out var result) && result != 0 && result != _lastWrittenSlot)
{
_lastWrittenSlot = result;
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(70, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Game saved to slot ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<uint>(result);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": auto-save will save there (game's own slot id: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<uint>(GameSetupManager.GetSelectedSaveId());
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(").");
}
logger.LogInfo(val);
}
if (_awaitingGame)
{
_gameReacted = true;
Plugin.Trace("Game save finished, its after-save callbacks ran: the game confirms the save itself.");
}
}
}
internal static AutoSaver Instance;
private const float CheckSeconds = 1f;
private float _nextCheck;
private float _nextSave = -1f;
private static bool _awaitingGame;
private static bool _gameReacted;
private static uint _lastWrittenSlot;
private float _confirmAt = -1f;
public AutoSaver(IntPtr ptr)
: base(ptr)
{
}
private void Update()
{
//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
if (Time.unscaledTime < _nextCheck)
{
return;
}
_nextCheck = Time.unscaledTime + 1f;
if (_confirmAt >= 0f && Time.unscaledTime >= _confirmAt)
{
Confirm();
}
float num = Plugin.AutoSaveMinutes.Value;
if ((Object)(object)LocalPlayer.Inventory == (Object)null)
{
_lastWrittenSlot = 0u;
}
if (!Plugin.AutoSaveEnabled.Value || (Object)(object)LocalPlayer.Inventory == (Object)null)
{
_nextSave = -1f;
}
else if (_nextSave < 0f)
{
_nextSave = Time.unscaledTime + num * 60f;
}
else
{
if (Time.unscaledTime < _nextSave)
{
return;
}
if (!LocalPlayer.IsInWorld)
{
Plugin.Trace($"Auto-save waiting: player view {LocalPlayer.CurrentView}.");
return;
}
if (IsDown())
{
Plugin.Trace("Auto-save waiting: player not alive.");
return;
}
_nextSave = Time.unscaledTime + num * 60f;
if (PauseMenu.IsActive)
{
Plugin.Trace("Auto-save skipped: pause menu open, next one in " + num + " min.");
}
else if (BoltNetwork.isClient)
{
Plugin.Trace("Auto-save skipped: multiplayer guest, the host saves the world.");
}
else
{
Save();
}
}
}
internal static bool IsDown()
{
PlayerStats stats = LocalPlayer.Stats;
if (!((Object)(object)LocalPlayer.Vitals != (Object)null) || LocalPlayer.Vitals.IsAlive())
{
if ((Object)(object)stats != (Object)null)
{
if (!stats.IsDead() && !stats.IsDying())
{
return stats.PlayerIsDowned;
}
return true;
}
return false;
}
return true;
}
private static string GameSlotByGuid()
{
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
try
{
string text = CoopLobbyManager.ActiveGuid();
return $"game's lookup for world '{text}': slot {CoopSaveUtils.GetSaveIdForGuid(GameSetupManager.GetSaveGameType(), text)}";
}
catch (Exception ex)
{
return "game's lookup failed: " + ex.Message;
}
}
private void Save()
{
//IL_0151: Unknown result type (might be due to invalid IL or missing references)
//IL_0158: Expected O, but got Unknown
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Expected O, but got Unknown
//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
//IL_00e7: Expected O, but got Unknown
bool flag = default(bool);
try
{
uint num = ((_lastWrittenSlot != 0) ? _lastWrittenSlot : GameSetupManager.GetSelectedSaveId());
if (num == 0)
{
Show(Plugin.Text(Plugin.NoSlotMessage, "NoSlot"));
ManualLogSource logger = Plugin.Logger;
BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(48, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Auto-save skipped: game has no save slot yet (");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(GameSlotByGuid());
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(").");
}
logger.LogWarning(val);
return;
}
PauseMenu instance = PauseMenu._instance;
SaveMenu val2 = (((Object)(object)instance != (Object)null) ? instance._saveMenu : null);
string text = (((Object)(object)val2 != (Object)null) ? val2.GetCurrentGameSaveName() : null);
if (string.IsNullOrEmpty(text))
{
throw new InvalidOperationException("current game save name not found");
}
_awaitingGame = true;
_gameReacted = false;
SaveGameManager.SaveToSlot((int)num, text);
_confirmAt = Time.unscaledTime + 1f;
ManualLogSource logger2 = Plugin.Logger;
BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(25, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Auto-saved to slot ");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<uint>(num);
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" ('");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(text);
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("').");
}
logger2.LogInfo(val3);
}
catch (Exception ex)
{
_awaitingGame = false;
Show(Plugin.Text(Plugin.FailedMessage, "Failed"));
ManualLogSource logger3 = Plugin.Logger;
BepInExErrorLogInterpolatedStringHandler val4 = new BepInExErrorLogInterpolatedStringHandler(18, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("Auto-save failed: ");
((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<Exception>(ex);
}
logger3.LogError(val4);
}
}
private void Confirm()
{
_confirmAt = -1f;
_awaitingGame = false;
if (!_gameReacted)
{
Plugin.Trace("Game did not announce the auto-save: showing its own 'Game Saved' message.");
Show(Plugin.Text(Plugin.SavedMessage, "Saved", "ScreenPrompts", "GAME_SAVED"));
}
}
internal void Show(string text)
{
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Expected O, but got Unknown
float value = Plugin.MessageSeconds.Value;
if (value <= 0f)
{
return;
}
HudGui instance = HudGui._instance;
if (!PauseMenu.IsActive && (Object)(object)instance != (Object)null)
{
try
{
instance.DisplayGeneralMessage(text, value, (ItemUiData)null);
return;
}
catch (Exception ex)
{
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(38, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Game HUD message failed, using a box: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
}
logger.LogWarning(val);
}
}
MessageBox obj = ((Component)this).GetComponent<MessageBox>() ?? ((Component)this).gameObject.AddComponent<MessageBox>();
obj.Message = text;
obj.Until = Time.unscaledTime + value;
((Behaviour)obj).enabled = true;
}
}
public class MessageBox : MonoBehaviour
{
internal string Message;
internal float Until;
public MessageBox(IntPtr ptr)
: base(ptr)
{
}
private void OnGUI()
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Expected O, but got Unknown
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
if (Time.unscaledTime > Until || string.IsNullOrEmpty(Message))
{
((Behaviour)this).enabled = false;
return;
}
GUIContent val = new GUIContent(Message);
Vector2 val2 = GUI.skin.box.CalcSize(val);
GUI.Box(new Rect(((float)Screen.width - val2.x) / 2f, Plugin.MessageTop.Value, val2.x, val2.y), val);
}
}
[BepInPlugin("aznan.sotf.pausemenusave", "PauseMenuSave", "0.1.23")]
public class Plugin : BasePlugin
{
internal const string Version = "0.1.23";
internal static ManualLogSource Logger;
internal static ConfigEntry<bool> FullLogging;
internal static ConfigEntry<string> ButtonText;
internal static ConfigEntry<int> ButtonPosition;
internal static ConfigEntry<bool> AutoSaveEnabled;
internal static ConfigEntry<int> AutoSaveMinutes;
internal static ConfigEntry<string> SavedMessage;
internal static ConfigEntry<string> NoSlotMessage;
internal static ConfigEntry<string> FailedMessage;
internal static ConfigEntry<string> CharacterSavedMessage;
internal static ConfigEntry<float> MessageSeconds;
internal static ConfigEntry<float> MessageTop;
private const string Automatic = "Empty = automatic, in the game's language.";
private static string LocaleCode
{
get
{
Locale selectedLocale = LocalizationSettings.SelectedLocale;
if (selectedLocale == null)
{
return null;
}
return selectedLocale.Identifier.Code;
}
}
internal static void Trace(string message)
{
if (FullLogging.Value)
{
Logger.LogInfo((object)message);
}
}
private static void Refuse(ConfigEntry<int> e, Func<int, bool> breaks, string why)
{
Check();
e.SettingChanged += delegate
{
Check();
};
void Check()
{
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Expected O, but got Unknown
if (breaks(e.Value))
{
ManualLogSource logger = Logger;
bool flag = default(bool);
BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(28, 5, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((ConfigEntryBase)e).Definition.Section);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("] ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((ConfigEntryBase)e).Definition.Key);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" = ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(e.Value);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" refused (");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(why);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("); back to ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<object>(((ConfigEntryBase)e).DefaultValue);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
}
logger.LogWarning(val);
e.Value = (int)((ConfigEntryBase)e).DefaultValue;
}
}
}
public override void Load()
{
//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
//IL_0303: Unknown result type (might be due to invalid IL or missing references)
//IL_0309: Expected O, but got Unknown
//IL_0309: Unknown result type (might be due to invalid IL or missing references)
//IL_0325: Unknown result type (might be due to invalid IL or missing references)
//IL_032b: Expected O, but got Unknown
Logger = ((BasePlugin)this).Log;
Texts.SelfCheck();
ButtonPosition = ((BasePlugin)this).Config.Bind<int>("General", "ButtonPosition", -1, "Place of the save button in the pause menu bar, counted from 0 at the left. -1 = right after the entry it is copied from. Advised: -1 to 20.");
ConfigEntry<float> val = ((BasePlugin)this).Config.Bind<float>("Auto-save", "AutoSaveMinutes", 10f, "Old form of the setting, replaced below.");
float value = val.Value;
((BasePlugin)this).Config.Remove(((ConfigEntryBase)val).Definition);
AutoSaveEnabled = ((BasePlugin)this).Config.Bind<bool>("Auto-save", "AutoSaveEnabled", value > 0f, "True = the game is saved automatically (single player or host).");
AutoSaveMinutes = ((BasePlugin)this).Config.Bind<int>("Auto-save", "AutoSaveMinutes", 10, "Minutes between auto-saves. Advised: 1 to 60.");
Refuse(AutoSaveMinutes, (int m) => m < 1, "less than a minute would save over your game every second; AutoSaveEnabled turns auto-save off");
int num = Math.Max(1, (int)Math.Round(value));
if (value > 0f && num != AutoSaveMinutes.Value)
{
AutoSaveMinutes.Value = num;
}
ButtonText = ((BasePlugin)this).Config.Bind<string>("Texts", "ButtonText", "", "Text of the save button added to the pause menu. Empty = automatic, in the game's language.");
SavedMessage = ((BasePlugin)this).Config.Bind<string>("Texts", "SavedMessage", "", "Message shown after an auto-save. Empty = automatic, in the game's language.");
NoSlotMessage = ((BasePlugin)this).Config.Bind<string>("Texts", "NoSlotMessage", "", "Message shown when a new game has no save slot yet. Empty = automatic, in the game's language.");
FailedMessage = ((BasePlugin)this).Config.Bind<string>("Texts", "FailedMessage", "", "Message shown when a save fails. Empty = automatic, in the game's language.");
CharacterSavedMessage = ((BasePlugin)this).Config.Bind<string>("Texts", "CharacterSavedMessage", "", "Message shown when a multiplayer guest saves their character with the button. Empty = automatic, in the game's language.");
MessageSeconds = ((BasePlugin)this).Config.Bind<float>("Texts", "MessageSeconds", 3f, "How long messages stay on screen, in seconds (the game's own message in game, a box in the pause menu). 0 = no message. Advised: 0 to 30.");
MessageTop = ((BasePlugin)this).Config.Bind<float>("Texts", "MessageTop", 40f, "Distance of the pause menu message box from the top of the screen, in pixels. Advised: 0 to 2000.");
FullLogging = ((BasePlugin)this).Config.Bind<bool>("Debug", "FullLogging", false, "True = the BepInEx log gets every step useful to diagnose a problem (decisions, values read, object aimed at, failures with their cause). False = only loading, version and errors.");
SettingMove.Move(((BasePlugin)this).Config, "General", "ButtonText", (ConfigEntryBase)(object)ButtonText);
SettingMove.Move(((BasePlugin)this).Config, "Auto-save", "SavedMessage", (ConfigEntryBase)(object)SavedMessage);
SettingMove.Move(((BasePlugin)this).Config, "Auto-save", "NoSlotMessage", (ConfigEntryBase)(object)NoSlotMessage);
SettingMove.Move(((BasePlugin)this).Config, "Message", "FailedMessage", (ConfigEntryBase)(object)FailedMessage);
SettingMove.Move(((BasePlugin)this).Config, "Message", "CharacterSavedMessage", (ConfigEntryBase)(object)CharacterSavedMessage);
SettingMove.Move(((BasePlugin)this).Config, "Message", "MessageSeconds", (ConfigEntryBase)(object)MessageSeconds);
SettingMove.Move(((BasePlugin)this).Config, "Message", "MessageTop", (ConfigEntryBase)(object)MessageTop);
new Harmony("aznan.sotf.pausemenusave").PatchAll();
ClassInjector.RegisterTypeInIl2Cpp<AutoSaver>();
ClassInjector.RegisterTypeInIl2Cpp<MessageBox>();
GameObject val2 = new GameObject("PauseMenuSave");
Object.DontDestroyOnLoad((Object)val2);
((Object)val2).hideFlags = (HideFlags)61;
AutoSaver.Instance = val2.AddComponent<AutoSaver>();
ManualLogSource logger = Logger;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(21, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("PauseMenuSave ");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>("0.1.23");
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" loaded");
}
logger.LogInfo(val3);
}
internal static string Text(ConfigEntry<string> setting, string modKey, string gameTable = null, string gameKey = null)
{
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Expected O, but got Unknown
if (!string.IsNullOrEmpty(setting.Value))
{
return setting.Value;
}
if (gameTable != null)
{
try
{
string localizedString = LocalizationSettings.StringDatabase.GetLocalizedString(TableReference.op_Implicit(gameTable), TableEntryReference.op_Implicit(gameKey), (Locale)null, (FallbackBehavior)0, (Il2CppReferenceArray<Object>)null);
if (!string.IsNullOrEmpty(localizedString))
{
return localizedString;
}
}
catch (Exception ex)
{
ManualLogSource logger = Logger;
bool flag = default(bool);
BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(40, 3, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Game text ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(gameTable);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("/");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(gameKey);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" not found, using the mod's: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
}
logger.LogWarning(val);
}
}
return Texts.Get(LocaleCode, modKey);
}
}
}
namespace PauseMenuSave.Patches
{
[HarmonyPatch(typeof(PauseMenu), "Open")]
public static class SaveButtonInjector
{
private const string ButtonObjectName = "PauseMenuSave_Button";
public static void Postfix(PauseMenu __instance)
{
Button val = null;
foreach (Button componentsInChild in ((Component)__instance).GetComponentsInChildren<Button>(true))
{
if (((Object)componentsInChild).name == "PauseMenuSave_Button")
{
val = componentsInChild;
}
}
Button val2 = val ?? AddButton(__instance);
if ((Object)(object)val2 != (Object)null)
{
SetLabel(val2, Plugin.Text(Plugin.ButtonText, "Save", "Menus", "SAVE"));
}
}
private static Button AddButton(PauseMenu __instance)
{
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00a9: Expected O, but got Unknown
List<Button> singlePlayerMenuButtons = __instance._singlePlayerMenuButtons;
Button val = ((singlePlayerMenuButtons != null && singlePlayerMenuButtons.Count > 0) ? singlePlayerMenuButtons[0] : null);
if ((Object)(object)val == (Object)null)
{
Plugin.Logger.LogError((object)"Pause menu has no button to copy; save button not added.");
return null;
}
Button component = Object.Instantiate<GameObject>(((Component)val).gameObject, ((Component)val).transform.parent).GetComponent<Button>();
((Object)component).name = "PauseMenuSave_Button";
int value = Plugin.ButtonPosition.Value;
((Component)component).transform.SetSiblingIndex((value >= 0) ? value : (((Component)val).transform.GetSiblingIndex() + 1));
component.onClick = new ButtonClickedEvent();
((UnityEvent)component.onClick).AddListener(UnityAction.op_Implicit((Action)delegate
{
OpenSaveScreen(__instance);
}));
foreach (LocalizeStringEvent componentsInChild in ((Component)component).GetComponentsInChildren<LocalizeStringEvent>(true))
{
Object.DestroyImmediate((Object)(object)componentsInChild);
}
foreach (LocalizedLinkText componentsInChild2 in ((Component)component).GetComponentsInChildren<LocalizedLinkText>(true))
{
Object.DestroyImmediate((Object)(object)componentsInChild2);
}
Plugin.Trace($"Save button added next to '{((Object)val).name}' under '{((Object)((Component)val).transform.parent).name}'.");
return component;
}
private static void SetLabel(Button button, string text)
{
LinkTextGui component = ((Component)button).GetComponent<LinkTextGui>();
if ((Object)(object)component != (Object)null)
{
component.SetText(text);
}
TMP_Text componentInChildren = ((Component)button).GetComponentInChildren<TMP_Text>(true);
if ((Object)(object)componentInChildren != (Object)null)
{
componentInChildren.text = text;
}
}
private static void OpenSaveScreen(PauseMenu menu)
{
Plugin.Trace("Save button clicked.");
if (BoltNetwork.isClient)
{
SaveGuestCharacter();
return;
}
menu.SetSaveMenuActive(true);
Plugin.Trace("Save screen opened from pause menu.");
}
private static void SaveGuestCharacter()
{
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Expected O, but got Unknown
//IL_008e: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: Expected O, but got Unknown
bool flag = default(bool);
try
{
CoopSaveUtils.SavePlayerData();
AutoSaver.Instance?.Show(Plugin.Text(Plugin.CharacterSavedMessage, "CharacterSaved"));
ManualLogSource logger = Plugin.Logger;
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(51, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Multiplayer guest: character saved (player down: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(AutoSaver.IsDown());
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(").");
}
logger.LogInfo(val);
}
catch (Exception ex)
{
AutoSaver.Instance?.Show(Plugin.Text(Plugin.FailedMessage, "Failed"));
ManualLogSource logger2 = Plugin.Logger;
BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(23, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Character save failed: ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Exception>(ex);
}
logger2.LogError(val2);
}
}
}
}
namespace PauseMenuSave.Logic
{
public static class Texts
{
public const string Save = "Save";
public const string Saved = "Saved";
public const string NoSlot = "NoSlot";
public const string Failed = "Failed";
public const string CharacterSaved = "CharacterSaved";
private static readonly Dictionary<string, Dictionary<string, string>> ByLanguage = new Dictionary<string, Dictionary<string, string>>
{
["en"] = new Dictionary<string, string>
{
["Save"] = "Save",
["Saved"] = "Game saved",
["NoSlot"] = "Auto-save skipped: save this game once first",
["Failed"] = "Save failed (see BepInEx log)",
["CharacterSaved"] = "Character saved"
},
["fr"] = new Dictionary<string, string>
{
["Save"] = "Sauvegarder",
["Saved"] = "Partie sauvegardée",
["NoSlot"] = "Sauvegarde auto ignorée : sauvegardez d'abord cette partie une fois",
["Failed"] = "Échec de la sauvegarde (voir le journal BepInEx)",
["CharacterSaved"] = "Personnage sauvegardé"
}
};
public static string Get(string localeCode, string key)
{
string key2 = (localeCode ?? "en").Split('-')[0].ToLowerInvariant();
if (!ByLanguage.TryGetValue(key2, out var value) || !value.TryGetValue(key, out var value2))
{
return ByLanguage["en"][key];
}
return value2;
}
public static void SelfCheck()
{
foreach (string key in ByLanguage["fr"].Keys)
{
if (!ByLanguage["en"].ContainsKey(key))
{
throw new InvalidOperationException("Texts: '" + key + "' missing in English.");
}
}
if (Get("fr", "CharacterSaved") != "Personnage sauvegardé" || Get("ja", "Save") != "Save" || Get(null, "Save") != "Save")
{
throw new InvalidOperationException("Texts lookup is wrong.");
}
}
}
}