using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LethalRegeneration.config;
using LethalRegeneration.patches;
using LethalRegeneration.utils;
using Microsoft.CodeAnalysis;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.6", FrameworkDisplayName = ".NET Framework 4.6")]
[assembly: AssemblyCompany("LethalRegeneration")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Natural health regeneration mod with customizable parameters that syncs with host")]
[assembly: AssemblyFileVersion("1.2.0.0")]
[assembly: AssemblyInformationalVersion("1.2.0+4c3a2fec85925ed84ea5f29c722c886eeed1977f")]
[assembly: AssemblyProduct("LethalRegeneration")]
[assembly: AssemblyTitle("LethalRegeneration")]
[assembly: AssemblyVersion("1.2.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.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;
}
}
}
namespace LethalRegeneration
{
[BepInPlugin("Toskan4134.LethalRegeneration", "LethalRegeneration", "1.3.0")]
public class LethalRegenerationBase : BaseUnityPlugin
{
private const string modGUID = "Toskan4134.LethalRegeneration";
private const string modName = "LethalRegeneration";
private const string modVersion = "1.3.0";
private readonly Harmony patcher = new Harmony("Toskan4134.LethalRegeneration");
public static LethalRegenerationBase Instance;
public static Configuration Config { get; internal set; }
public static ManualLogSource Logger { get; private set; }
private void Awake()
{
if ((Object)(object)Instance == (Object)null)
{
Instance = this;
}
Logger = Logger.CreateLogSource("LethalRegeneration");
Config = new Configuration(((BaseUnityPlugin)this).Config);
try
{
patcher.PatchAll(typeof(HUDManagerPatch));
patcher.PatchAll(typeof(Configuration));
patcher.PatchAll(typeof(TerminalPatch));
patcher.PatchAll(typeof(GameNetworkManagerPatch));
patcher.PatchAll(typeof(StartOfRoundPatch));
patcher.PatchAll(typeof(StartMatchLeverPatch));
Logger.LogInfo((object)"Loaded Succesfully\r\n ___________________\r\n / |\r\n |_______ _______|\r\n ___ | |\r\n | |___| |______\r\n | \\\r\n \\______ ___ |\r\n ___ | | | |\r\n | |__ | | __| |\r\n | || || |\r\n \\_____||____||_____/\r\n LethalRegeneration 1.3.0\r\n By Toskan4134\r\n");
}
catch (Exception ex)
{
Logger.LogError((object)ex);
}
}
}
}
namespace LethalRegeneration.utils
{
public class TerminalUtils
{
public static TerminalKeyword CreateTerminalKeyword(string word, bool isVerb = false, CompatibleNoun[] compatibleNouns = null, TerminalNode specialKeywordResult = null, TerminalKeyword defaultVerb = null, bool accessTerminalObjects = false)
{
TerminalKeyword val = ScriptableObject.CreateInstance<TerminalKeyword>();
((Object)val).name = word;
val.word = word;
val.isVerb = isVerb;
val.compatibleNouns = compatibleNouns;
val.specialKeywordResult = specialKeywordResult;
val.defaultVerb = defaultVerb;
val.accessTerminalObjects = accessTerminalObjects;
return val;
}
public static TerminalKeyword GetTerminalKeyword(Terminal __instance, string word)
{
return __instance.terminalNodes.allKeywords.First((TerminalKeyword keyword) => keyword.word == word);
}
}
}
namespace LethalRegeneration.patches
{
[HarmonyPatch(typeof(GameNetworkManager))]
public class GameNetworkManagerPatch
{
[HarmonyPatch("SaveGameValues")]
[HarmonyPostfix]
public static void SaveGameValuesPatch(GameNetworkManager __instance)
{
if (!__instance.isHostingGame)
{
return;
}
try
{
ES3.Save<bool>("LethalRegeneration_healingUpgradeUnlocked", ConfigurationSync<Configuration>.Instance.HealingUpgradeUnlocked, __instance.currentSaveFileName);
}
catch (Exception arg)
{
Debug.LogError((object)$"Error while trying to save game values when disconnecting as host: {arg}");
}
}
}
[HarmonyPatch(typeof(HUDManager))]
internal class HUDManagerPatch
{
private static PlayerControllerB playerControllerB;
private static int currentTicksPerRegeneration = 0;
private static int currentTicksPerRegenerationOutsideShip = 0;
public static int currentRegenerationLimitPerPlayer = regenerationLimitPerPlayer;
private static int ticksPerRegeneration => ConfigurationSync<Configuration>.Instance.TicksPerRegeneration;
private static int regenerationPower => ConfigurationSync<Configuration>.Instance.RegenerationPower;
private static bool regenerationOutsideShip => ConfigurationSync<Configuration>.Instance.RegenerationOutsideShip;
private static int ticksPerRegenerationOutsideShip => ConfigurationSync<Configuration>.Instance.TicksPerRegenerationOutsideShip;
private static int regenerationPowerOutsideShip => ConfigurationSync<Configuration>.Instance.RegenerationPowerOutsideShip;
private static bool healingUpgradeUnlocked => ConfigurationSync<Configuration>.Instance.HealingUpgradeUnlocked;
private static bool healingUpgradeEnabled => ConfigurationSync<Configuration>.Instance.HealingUpgradeEnabled;
private static int maxHealth => StartMatchLeverPatch.maxHealth;
public static int regenerationLimitPerPlayer => ConfigurationSync<Configuration>.Instance.RegenerationLimitPerPlayer;
[HarmonyPatch("SetClock")]
[HarmonyPostfix]
public static void healingPostfix()
{
playerControllerB = GameNetworkManager.Instance.localPlayerController;
if ((healingUpgradeEnabled && !healingUpgradeUnlocked) || (regenerationLimitPerPlayer != -1 && currentRegenerationLimitPerPlayer <= 0) || !((NetworkBehaviour)playerControllerB).IsOwner || playerControllerB.isPlayerDead || !playerControllerB.AllowPlayerDeath() || playerControllerB.health >= maxHealth)
{
return;
}
if (playerControllerB.isInHangarShipRoom)
{
if (currentTicksPerRegeneration == 0)
{
currentTicksPerRegeneration = ticksPerRegeneration;
LethalRegenerationBase.Logger.LogInfo((object)("Healed " + regenerationPower));
int num = playerControllerB.health + regenerationPower;
currentRegenerationLimitPerPlayer -= regenerationPower;
playerControllerB.health = ((num > maxHealth) ? maxHealth : num);
HUDManager.Instance.UpdateHealthUI(playerControllerB.health, false);
playerControllerB.DamagePlayerClientRpc(-regenerationPower, playerControllerB.health);
if (playerControllerB.health >= 10 && playerControllerB.criticallyInjured)
{
playerControllerB.MakeCriticallyInjured(false);
}
}
currentTicksPerRegeneration--;
}
else
{
if (!regenerationOutsideShip || playerControllerB.isInHangarShipRoom)
{
return;
}
if (currentTicksPerRegenerationOutsideShip == 0)
{
currentTicksPerRegenerationOutsideShip = ticksPerRegenerationOutsideShip;
LethalRegenerationBase.Logger.LogInfo((object)("Healed " + regenerationPowerOutsideShip));
int num2 = playerControllerB.health + regenerationPowerOutsideShip;
currentRegenerationLimitPerPlayer -= regenerationPowerOutsideShip;
playerControllerB.health = ((num2 > maxHealth) ? maxHealth : num2);
HUDManager.Instance.UpdateHealthUI(playerControllerB.health, false);
playerControllerB.DamagePlayerClientRpc(-regenerationPowerOutsideShip, playerControllerB.health);
if (playerControllerB.health >= 10 && playerControllerB.criticallyInjured)
{
playerControllerB.MakeCriticallyInjured(false);
}
}
currentTicksPerRegenerationOutsideShip--;
}
}
}
[HarmonyPatch(typeof(StartMatchLever))]
public class StartMatchLeverPatch
{
public static int maxHealth = 100;
[HarmonyPatch("PlayLeverPullEffectsClientRpc")]
[HarmonyPostfix]
public static void StartGameHpPostfix(ref StartOfRound ___playersManager, ref bool ___leverHasBeenPulled)
{
if (___leverHasBeenPulled)
{
maxHealth = ___playersManager.localPlayerController.health;
HUDManagerPatch.currentRegenerationLimitPerPlayer = HUDManagerPatch.regenerationLimitPerPlayer;
}
}
}
[HarmonyPatch(typeof(StartOfRound))]
public class StartOfRoundPatch
{
[HarmonyPatch("ResetShip")]
[HarmonyPostfix]
public static void ResetShip()
{
ConfigurationSync<Configuration>.Instance.HealingUpgradeUnlocked = false;
}
}
[HarmonyPatch(typeof(Terminal))]
public class TerminalPatch
{
private static Item item;
private static TerminalNode buyNode1;
private static TerminalNode buyNode2;
private static TerminalNode CannotAfford;
private static TerminalNode AlreadyUnlocked;
[HarmonyPatch("Start")]
[HarmonyPrefix]
public static void StartTerminalPatch(Terminal __instance)
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Expected O, but got Unknown
//IL_0380: Unknown result type (might be due to invalid IL or missing references)
//IL_0385: Unknown result type (might be due to invalid IL or missing references)
//IL_03ba: Unknown result type (might be due to invalid IL or missing references)
//IL_03c6: Expected O, but got Unknown
//IL_03c8: Unknown result type (might be due to invalid IL or missing references)
//IL_03cd: Unknown result type (might be due to invalid IL or missing references)
//IL_0402: Unknown result type (might be due to invalid IL or missing references)
//IL_040a: Expected O, but got Unknown
//IL_0450: Unknown result type (might be due to invalid IL or missing references)
//IL_0455: Unknown result type (might be due to invalid IL or missing references)
//IL_0461: Unknown result type (might be due to invalid IL or missing references)
//IL_0471: Expected O, but got Unknown
//IL_05a5: Unknown result type (might be due to invalid IL or missing references)
//IL_05aa: Unknown result type (might be due to invalid IL or missing references)
//IL_05b6: Unknown result type (might be due to invalid IL or missing references)
//IL_05c3: Expected O, but got Unknown
if (ConfigurationSync<Configuration>.Instance.HealingUpgradeEnabled)
{
item = new Item
{
itemName = "Natural Regeneration",
creditsWorth = ConfigurationSync<Configuration>.Instance.HealingUpgradePrice,
saveItemVariable = true
};
TerminalKeyword terminalKeyword = TerminalUtils.GetTerminalKeyword(__instance, "buy");
TerminalNode result = terminalKeyword.compatibleNouns[0].result.terminalOptions[1].result;
CannotAfford = ScriptableObject.CreateInstance<TerminalNode>();
((Object)CannotAfford).name = "LethalRegeneration_CannotAfford";
CannotAfford.displayText = $"You could not afford these items!\nYour balance is [playerCredits]. Total cost of these items is ${item.creditsWorth}\r\n\r\n";
CannotAfford.clearPreviousText = false;
CannotAfford.maxCharactersToType = 25;
CannotAfford.playSyncedClip = 1;
AlreadyUnlocked = ScriptableObject.CreateInstance<TerminalNode>();
((Object)AlreadyUnlocked).name = "LethalRegeneration_AlreadyUnlocked";
AlreadyUnlocked.displayText = "This has already been unlocked for your ship!\r\n\r\n";
AlreadyUnlocked.clearPreviousText = true;
AlreadyUnlocked.maxCharactersToType = 25;
AlreadyUnlocked.playSyncedClip = 1;
TerminalKeyword terminalKeyword2 = TerminalUtils.GetTerminalKeyword(__instance, "info");
string itemName = item.itemName;
TerminalKeyword keyword3 = TerminalUtils.CreateTerminalKeyword(itemName.ToLowerInvariant().Replace(" ", "-"), isVerb: false, null, null, terminalKeyword);
if (__instance.terminalNodes.allKeywords.Any((TerminalKeyword kw) => kw.word == keyword3.word))
{
LethalRegenerationBase.Logger.LogInfo((object)("Keyword " + keyword3.word + " already registed, skipping."));
}
int shipUnlockableID = StartOfRound.Instance.unlockablesList.unlockables.FindIndex((UnlockableItem unlockable) => unlockable.unlockableName == item.itemName);
buyNode2 = ScriptableObject.CreateInstance<TerminalNode>();
((Object)buyNode2).name = "LethalRegeneration_" + itemName.Replace(" ", "-") + "BuyNode2";
buyNode2.displayText = "Ordered the " + itemName + ". Your new balance is [playerCredits].\n\nFrom now on you will regenerate health as time goes by.\r\n\r\n";
buyNode2.clearPreviousText = true;
buyNode2.maxCharactersToType = 15;
buyNode2.buyItemIndex = -1;
buyNode2.shipUnlockableID = shipUnlockableID;
buyNode2.buyUnlockable = true;
buyNode2.creatureName = itemName;
buyNode2.isConfirmationNode = false;
buyNode2.itemCost = item.creditsWorth;
buyNode2.playSyncedClip = 0;
buyNode1 = ScriptableObject.CreateInstance<TerminalNode>();
((Object)buyNode1).name = "LethalRegeneration_" + itemName.Replace(" ", "-") + "BuyNode1";
buyNode1.displayText = "You have requested to order the " + itemName + " upgrade.\nTotal cost of items: " + item.creditsWorth + ".\n\nPlease CONFIRM or DENY.\r\n\r\n";
buyNode1.clearPreviousText = true;
buyNode1.maxCharactersToType = 35;
buyNode1.buyItemIndex = -1;
buyNode1.shipUnlockableID = shipUnlockableID;
buyNode1.creatureName = itemName;
buyNode1.isConfirmationNode = true;
buyNode1.overrideOptions = true;
buyNode1.itemCost = item.creditsWorth;
buyNode1.terminalOptions = (CompatibleNoun[])(object)new CompatibleNoun[2]
{
new CompatibleNoun
{
noun = __instance.terminalNodes.allKeywords.First((TerminalKeyword keyword2) => keyword2.word == "confirm"),
result = buyNode2
},
new CompatibleNoun
{
noun = __instance.terminalNodes.allKeywords.First((TerminalKeyword keyword2) => keyword2.word == "deny"),
result = result
}
};
List<TerminalKeyword> list = __instance.terminalNodes.allKeywords.ToList();
list.Add(keyword3);
__instance.terminalNodes.allKeywords = list.ToArray();
List<CompatibleNoun> list2 = terminalKeyword.compatibleNouns.ToList();
list2.Add(new CompatibleNoun
{
noun = keyword3,
result = buyNode1
});
terminalKeyword.compatibleNouns = list2.ToArray();
TerminalNode val = ScriptableObject.CreateInstance<TerminalNode>();
((Object)val).name = "LethalRegeneration_" + itemName.Replace(" ", "-") + "InfoNode";
if (ConfigurationSync<Configuration>.Instance.RegenerationOutsideShip)
{
val.displayText = $"Your health regenerates inside and outside the ship\n\nINSIDE THE SHIP\nThe healing is activated each {ConfigurationSync<Configuration>.Instance.TicksPerRegeneration} ticks\nThe healing power is {ConfigurationSync<Configuration>.Instance.RegenerationPower}hp per tick\n\nOUTSIDE THE SHIP\nThe healing is activated each {ConfigurationSync<Configuration>.Instance.TicksPerRegenerationOutsideShip} ticks\nThe healing power is {ConfigurationSync<Configuration>.Instance.RegenerationPowerOutsideShip}hp per tick\nThe regeneration limit per player is {ConfigurationSync<Configuration>.Instance.RegenerationLimitPerPlayer}hp per round\n\n";
}
else
{
val.displayText = $"Your health regenerates only inside the ship\n\nThe healing is activated each {ConfigurationSync<Configuration>.Instance.TicksPerRegeneration} ticks\nThe healing power is {ConfigurationSync<Configuration>.Instance.RegenerationPower}hp per tick\nThe regeneration limit per player is {ConfigurationSync<Configuration>.Instance.RegenerationLimitPerPlayer}hp per round\n\n";
}
val.clearPreviousText = true;
val.maxCharactersToType = 25;
__instance.terminalNodes.allKeywords = list.ToArray();
List<CompatibleNoun> list3 = terminalKeyword2.compatibleNouns.ToList();
list3.Add(new CompatibleNoun
{
noun = keyword3,
result = val
});
terminalKeyword2.compatibleNouns = list3.ToArray();
LethalRegenerationBase.Logger.LogInfo((object)("Registered " + itemName));
}
}
[HarmonyPatch("TextPostProcess")]
[HarmonyPrefix]
public static void TextPostProcessPatch_Prefix(ref string modifiedDisplayText, TerminalNode node, ref string __result)
{
if (ConfigurationSync<Configuration>.Instance.HealingUpgradeEnabled && modifiedDisplayText.Contains("[buyableItemsList]") && modifiedDisplayText.Contains("[unlockablesSelectionList]"))
{
int num = modifiedDisplayText.IndexOf(":");
string itemName = item.itemName;
int creditsWorth = item.creditsWorth;
string value = $"\n* {itemName} // Price: ${creditsWorth}";
modifiedDisplayText = modifiedDisplayText.Insert(num + 1, value);
}
}
[HarmonyPatch("LoadNewNode")]
[HarmonyPrefix]
public static void LoadNewNodePatch_Prefix(ref TerminalNode node, Terminal __instance)
{
if (!((Object)node).name.StartsWith("LethalRegeneration"))
{
return;
}
string text = ((Object)node).name.Split(new char[1] { '_' })[1];
string text2 = text;
string text3 = text2;
if (!(text3 == "Natural-RegenerationBuyNode2"))
{
if (text3 == "Natural-RegenerationBuyNode1" && __instance.groupCredits < item.creditsWorth)
{
node = CannotAfford;
}
return;
}
if (ConfigurationSync<Configuration>.Instance.HealingUpgradeUnlocked)
{
node = AlreadyUnlocked;
return;
}
int num = __instance.groupCredits - item.creditsWorth;
__instance.SyncGroupCreditsServerRpc(num, __instance.numberOfItemsInDropship);
ConfigurationSync<Configuration>.Instance.HealingUpgradeUnlocked = true;
ConfigurationSync<Configuration>.Synced = false;
if (ConfigurationSync<Configuration>.IsHost)
{
ConfigurationSync<Configuration>.Instance.BroadcastHealingUpgradeStatusToClients();
}
else
{
ConfigurationSync<Configuration>.Instance.SendHealingUpgradeStatusToHost();
}
}
}
}
namespace LethalRegeneration.config
{
[Serializable]
public class Configuration : ConfigurationSync<Configuration>
{
[CompilerGenerated]
private static class <>O
{
public static HandleNamedMessageDelegate <0>__OnReceiveBroadcastedHealingUpgradeStatus;
public static HandleNamedMessageDelegate <1>__OnRequestSync;
public static HandleNamedMessageDelegate <2>__OnReceiveHealingUpgradeStatus;
public static HandleNamedMessageDelegate <3>__OnReceiveSync;
}
public const int DefaultTicksPerRegeneration = 2;
public const int DefaultRegenerationPower = 5;
public const bool DefaultregenerationOutsideShip = false;
public const bool DefaultHealingUpgradeEnabled = false;
public const int DefaultHealingUpgradePrice = 800;
[NonSerialized]
private readonly ConfigFile configFile;
public bool HealingUpgradeUnlocked { get; set; }
public int TicksPerRegeneration { get; private set; }
public int RegenerationPower { get; private set; }
public bool RegenerationOutsideShip { get; private set; }
public int TicksPerRegenerationOutsideShip { get; private set; }
public int RegenerationPowerOutsideShip { get; private set; }
public bool HealingUpgradeEnabled { get; private set; }
public int HealingUpgradePrice { get; private set; }
public int RegenerationLimitPerPlayer { get; private set; }
public Configuration(ConfigFile cfg)
{
ConfigurationSync<Configuration>.Instance = this;
configFile = cfg;
InitConfigEntries();
LethalRegenerationBase.Logger.LogInfo((object)"Configuration Set");
}
private void InitConfigEntries()
{
RegenerationPower = NewEntry("Values", "Regeneration Power", 5, "Amount of health regenerated INSIDE the ship each time triggered (Between 1 an 100)");
TicksPerRegeneration = NewEntry("Values", "Ticks Per Regeneration", 2, "Number of ticks until the regeneration is triggered INSIDE the ship (1 tick equals each time the minutes of the clock are changed)");
RegenerationOutsideShip = NewEntry("Values", "Enable Regeneration Outside Ship", defaultVal: false, "Whether health is regenerated also outside the ship or only inside.");
RegenerationPowerOutsideShip = NewEntry("Values", "Regeneration Power Outside Ship", 5, "Amount of health regenerated OUTSIDE the ship each time triggered, requires Regeneration Outside The Ship enabled (Between 1 an 100)");
TicksPerRegenerationOutsideShip = NewEntry("Values", "Ticks Per Regeneration Outside Ship", 2, "Number of ticks until the regeneration is triggered OUTSIDE the ship, requires Regeneration Outside The Ship enabled (1 tick equals each time the minutes of the clock are changed)");
HealingUpgradeEnabled = NewEntry("Values", "Regeneration As Upgrade", defaultVal: false, "Makes natural health regeneration an upgrade for the ship and has to be purchased to make it work.");
HealingUpgradePrice = NewEntry("Values", "Upgrade Price", 800, "Changes the price of ship upgrade for health regeneration. Only works if ship upgrade is enabled");
RegenerationLimitPerPlayer = NewEntry("Values", "Regeneration Limit Per Player", -1, "Regeneration limit in a round (If the value is '-1' this option will be unlimited)");
RegenerationPower = ((100 >= RegenerationPower && RegenerationPower > 0) ? RegenerationPower : 5);
TicksPerRegeneration = ((TicksPerRegeneration > 0) ? TicksPerRegeneration : 2);
RegenerationPowerOutsideShip = ((100 >= RegenerationPowerOutsideShip && RegenerationPowerOutsideShip > 0) ? RegenerationPowerOutsideShip : 5);
TicksPerRegenerationOutsideShip = ((TicksPerRegenerationOutsideShip > 0) ? TicksPerRegenerationOutsideShip : 2);
HealingUpgradePrice = ((HealingUpgradePrice > 0) ? HealingUpgradePrice : 800);
}
private T NewEntry<T>(string category, string key, T defaultVal, string desc)
{
return configFile.Bind<T>(category, key, defaultVal, desc).Value;
}
public static void RequestSync()
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
if (!ConfigurationSync<Configuration>.IsClient)
{
return;
}
FastBufferWriter val = default(FastBufferWriter);
((FastBufferWriter)(ref val))..ctor(4, (Allocator)2, -1);
try
{
ConfigurationSync<Configuration>.MessageManager.SendNamedMessage("LethalRegeneration_OnRequestConfigSync", 0uL, val, (NetworkDelivery)3);
}
finally
{
((IDisposable)(FastBufferWriter)(ref val)).Dispose();
}
}
public static void OnRequestSync(ulong clientId, FastBufferReader _)
{
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
if (!ConfigurationSync<Configuration>.IsHost)
{
return;
}
LethalRegenerationBase.Logger.LogInfo((object)$"Config sync request received from client: {clientId}");
byte[] array = ConfigurationSync<Configuration>.SerializeToBytes(ConfigurationSync<Configuration>.Instance);
int num = array.Length;
FastBufferWriter val = default(FastBufferWriter);
((FastBufferWriter)(ref val))..ctor(array.Length + 4, (Allocator)2, -1);
try
{
((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num, default(ForPrimitives));
((FastBufferWriter)(ref val)).WriteBytesSafe(array, -1, 0);
ConfigurationSync<Configuration>.MessageManager.SendNamedMessage("LethalRegeneration_OnReceiveConfigSync", clientId, val, (NetworkDelivery)3);
}
catch (Exception arg)
{
LethalRegenerationBase.Logger.LogInfo((object)$"Error occurred syncing config with client: {clientId}\n{arg}");
}
finally
{
((IDisposable)(FastBufferWriter)(ref val)).Dispose();
}
}
public static void OnReceiveSync(ulong _, FastBufferReader reader)
{
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
if (!((FastBufferReader)(ref reader)).TryBeginRead(4))
{
LethalRegenerationBase.Logger.LogError((object)"Config sync error: Could not begin reading buffer.");
return;
}
int num = default(int);
((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives));
if (!((FastBufferReader)(ref reader)).TryBeginRead(num))
{
LethalRegenerationBase.Logger.LogError((object)"Config sync error: Host could not sync.");
return;
}
byte[] data = new byte[num];
((FastBufferReader)(ref reader)).ReadBytesSafe(ref data, num, 0);
ConfigurationSync<Configuration>.UpdateInstance(data);
LethalRegenerationBase.Logger.LogInfo((object)"Successfully synced config with host.");
}
public void SendHealingUpgradeStatusToHost()
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
if (ConfigurationSync<Configuration>.IsClient)
{
FastBufferWriter val = default(FastBufferWriter);
((FastBufferWriter)(ref val))..ctor(4, (Allocator)2, -1);
try
{
int num = (HealingUpgradeUnlocked ? 1 : 0);
((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num, default(ForPrimitives));
ConfigurationSync<Configuration>.MessageManager.SendNamedMessage("LethalRegeneration_SendHealingUpgradeStatus", 0uL, val, (NetworkDelivery)3);
}
finally
{
((IDisposable)(FastBufferWriter)(ref val)).Dispose();
}
}
}
public static void OnReceiveHealingUpgradeStatus(ulong _, FastBufferReader reader)
{
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
if (ConfigurationSync<Configuration>.IsHost)
{
if (((FastBufferReader)(ref reader)).TryBeginRead(4))
{
int num = default(int);
((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives));
ConfigurationSync<Configuration>.Instance.HealingUpgradeUnlocked = num == 1;
LethalRegenerationBase.Logger.LogInfo((object)$"Received sent HealingUpgrade status: {ConfigurationSync<Configuration>.Instance.HealingUpgradeUnlocked}");
ConfigurationSync<Configuration>.Instance.BroadcastHealingUpgradeStatusToClients();
}
else
{
LethalRegenerationBase.Logger.LogError((object)"Error reading healingUpgradeUnlocked status.");
}
}
}
public void BroadcastHealingUpgradeStatusToClients()
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: 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 (!ConfigurationSync<Configuration>.IsHost)
{
return;
}
FastBufferWriter val = default(FastBufferWriter);
((FastBufferWriter)(ref val))..ctor(4, (Allocator)2, -1);
try
{
int num = (HealingUpgradeUnlocked ? 1 : 0);
((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num, default(ForPrimitives));
foreach (ulong key in NetworkManager.Singleton.ConnectedClients.Keys)
{
ConfigurationSync<Configuration>.MessageManager.SendNamedMessage("LethalRegeneration_BroadcastHealingUpgradeStatus", key, val, (NetworkDelivery)3);
}
}
finally
{
((IDisposable)(FastBufferWriter)(ref val)).Dispose();
}
}
public static void OnReceiveBroadcastedHealingUpgradeStatus(ulong _, FastBufferReader reader)
{
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
if (ConfigurationSync<Configuration>.IsClient && !ConfigurationSync<Configuration>.IsHost)
{
if (((FastBufferReader)(ref reader)).TryBeginRead(4))
{
int num = default(int);
((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives));
ConfigurationSync<Configuration>.Instance.HealingUpgradeUnlocked = num == 1;
LethalRegenerationBase.Logger.LogInfo((object)$"Received broadcasted healingUpgradeUnlocked status: {ConfigurationSync<Configuration>.Instance.HealingUpgradeUnlocked}");
ConfigurationSync<Configuration>.Synced = true;
}
else
{
LethalRegenerationBase.Logger.LogError((object)"Error reading broadcasted healingUpgradeUnlocked status.");
}
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")]
public static void InitializeLocalPlayer()
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Expected O, but got Unknown
//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ee: Expected O, but got Unknown
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Expected O, but got Unknown
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_009a: Expected O, but got Unknown
ConfigurationSync<Configuration>.Instance.HealingUpgradeUnlocked = false;
CustomMessagingManager customMessagingManager = NetworkManager.Singleton.CustomMessagingManager;
object obj = <>O.<0>__OnReceiveBroadcastedHealingUpgradeStatus;
if (obj == null)
{
HandleNamedMessageDelegate val = OnReceiveBroadcastedHealingUpgradeStatus;
<>O.<0>__OnReceiveBroadcastedHealingUpgradeStatus = val;
obj = (object)val;
}
customMessagingManager.RegisterNamedMessageHandler("LethalRegeneration_BroadcastHealingUpgradeStatus", (HandleNamedMessageDelegate)obj);
if (ConfigurationSync<Configuration>.IsHost)
{
CustomMessagingManager messageManager = ConfigurationSync<Configuration>.MessageManager;
object obj2 = <>O.<1>__OnRequestSync;
if (obj2 == null)
{
HandleNamedMessageDelegate val2 = OnRequestSync;
<>O.<1>__OnRequestSync = val2;
obj2 = (object)val2;
}
messageManager.RegisterNamedMessageHandler("LethalRegeneration_OnRequestConfigSync", (HandleNamedMessageDelegate)obj2);
CustomMessagingManager messageManager2 = ConfigurationSync<Configuration>.MessageManager;
object obj3 = <>O.<2>__OnReceiveHealingUpgradeStatus;
if (obj3 == null)
{
HandleNamedMessageDelegate val3 = OnReceiveHealingUpgradeStatus;
<>O.<2>__OnReceiveHealingUpgradeStatus = val3;
obj3 = (object)val3;
}
messageManager2.RegisterNamedMessageHandler("LethalRegeneration_SendHealingUpgradeStatus", (HandleNamedMessageDelegate)obj3);
ConfigurationSync<Configuration>.Synced = true;
ConfigurationSync<Configuration>.Instance.HealingUpgradeUnlocked = ES3.Load<bool>("LethalRegeneration_healingUpgradeUnlocked", GameNetworkManager.Instance.currentSaveFileName, false);
}
else
{
CustomMessagingManager messageManager3 = ConfigurationSync<Configuration>.MessageManager;
object obj4 = <>O.<3>__OnReceiveSync;
if (obj4 == null)
{
HandleNamedMessageDelegate val4 = OnReceiveSync;
<>O.<3>__OnReceiveSync = val4;
obj4 = (object)val4;
}
messageManager3.RegisterNamedMessageHandler("LethalRegeneration_OnReceiveConfigSync", (HandleNamedMessageDelegate)obj4);
ConfigurationSync<Configuration>.Synced = false;
RequestSync();
}
}
}
[Serializable]
public class ConfigurationSync<T>
{
public static T Instance { get; internal set; }
public static bool Synced { get; internal set; }
internal static CustomMessagingManager MessageManager => NetworkManager.Singleton.CustomMessagingManager;
internal static bool IsClient => NetworkManager.Singleton.IsClient;
internal static bool IsHost => NetworkManager.Singleton.IsHost;
internal static byte[] SerializeToBytes(T val)
{
BinaryFormatter binaryFormatter = new BinaryFormatter();
using MemoryStream memoryStream = new MemoryStream();
try
{
binaryFormatter.Serialize(memoryStream, val);
return memoryStream.ToArray();
}
catch (Exception arg)
{
LethalRegenerationBase.Logger.LogError((object)$"Error serializing instance: {arg}");
return null;
}
}
internal static T DeserializeFromBytes(byte[] data)
{
BinaryFormatter binaryFormatter = new BinaryFormatter();
using MemoryStream serializationStream = new MemoryStream(data);
try
{
return (T)binaryFormatter.Deserialize(serializationStream);
}
catch (Exception arg)
{
LethalRegenerationBase.Logger.LogError((object)$"Error deserializing instance: {arg}");
return default(T);
}
}
internal static void UpdateInstance(byte[] data)
{
Instance = DeserializeFromBytes(data);
Synced = true;
}
}
}