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 System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using FacilityMeltdown.API; using FacilityMeltdown.MeltdownSequence.Behaviours; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using PizzaProbability.Config; using PizzaProbability.Patches; using PizzaTowerEscapeMusic; using Unity.Collections; using Unity.Netcode; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("PizzaProbability")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Adds per-moon chance to the FacilityMeltdown mod. Improves interoperability with PizzaTowerEscapeMusic. Includes optional extras.")] [assembly: AssemblyFileVersion("1.2.3.0")] [assembly: AssemblyInformationalVersion("1.2.3")] [assembly: AssemblyProduct("PizzaProbability")] [assembly: AssemblyTitle("PizzaProbability")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.2.3.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [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; } } } namespace PizzaProbability { [BepInPlugin("PizzaProbability", "PizzaProbability", "1.2.4")] public class PizzaProbabilityMod : BaseUnityPlugin { internal static ManualLogSource Logger; internal static PizzaProbabilityConfig Config; private static Random solarFlares; private static Random stockMarket; private static bool coreUnstable; private readonly Harmony harmony = new Harmony("PizzaProbability"); private void Awake() { Logger = ((BaseUnityPlugin)this).Logger; Logger.LogInfo((object)"Is today pizza day?"); Config = new PizzaProbabilityConfig(((BaseUnityPlugin)this).Config); try { harmony.PatchAll(typeof(StartOfRoundPatch)); } catch { Logger.LogError((object)"Failed to patch StartOfRound. PizzaProbability is now disabled."); return; } try { MethodInfo methodInfo = typeof(LungProp).GetMethod("EquipItem"); foreach (Patch prefix in Harmony.GetPatchInfo((MethodBase)methodInfo).Prefixes) { if (prefix.owner == "me.loaforc.facilitymeltdown") { harmony.Unpatch((MethodBase)methodInfo, prefix.PatchMethod); methodInfo = null; break; } } if (methodInfo != null) { Logger.LogError((object)"Failed to locate FacilityMeltdown. PizzaProbability is now disabled."); return; } } catch (Exception arg) { Logger.LogError((object)$"Failed to unpatch LungProp. PizzaProbability is now disabled.\n{arg}"); return; } try { harmony.PatchAll(typeof(LungPropPatch)); } catch { Logger.LogError((object)"Failed to patch LungProp. PizzaProbability is now disabled."); return; } PizzaProbabilityConfig.ActiveSettings.OutputForecast(); PizzaProbabilityConfig.ActiveSettings.OutputEconomy(); try { harmony.PatchAll(typeof(GameNetworkManagerPatch)); try { harmony.PatchAll(typeof(PlayerControllerBPatch)); } catch { Logger.LogError((object)"Failed to patch PlayerControllerB. Config sync is now disabled."); } } catch { Logger.LogError((object)"Failed to patch GameNetworkManager. Config sync is now disabled."); } if (PizzaProbabilityConfig.PizzaPatch) { try { harmony.PatchAll(typeof(GameEventListenerPatch)); try { harmony.PatchAll(typeof(MeltdownHandlerPatch)); return; } catch { Logger.LogError((object)"Failed to patch FacilityMeltdown. Default music and voice will not be muted."); return; } } catch { Logger.LogInfo((object)"Failed to patch PizzaTowerEscapeMusic. Ignore this if not using PTEM."); return; } } Logger.LogInfo((object)"Skipping PizzaTowerEscapeMusic patch. PizzaPatch is disabled via config."); } internal static void Randomize(StartOfRound round) { solarFlares = new Random(round.randomMapSeed); stockMarket = new Random(round.randomMapSeed - 100); if (solarFlares.Next(0, 100) < PizzaProbabilityConfig.GetMoonSettings(round.currentLevel.PlanetName).MeltdownChance) { coreUnstable = true; Logger.LogInfo((object)"Today is pizza day. (Apparatus is unsafe.)"); } else { coreUnstable = false; Logger.LogInfo((object)"Today is not pizza day. (Apparatus is safe.)"); } } internal static void FindOut(LungProp apparatus) { if (!((Object)(object)apparatus != (Object)null) || !apparatus.isLungDocked || MeltdownAPI.MeltdownStarted) { return; } if (coreUnstable) { if (stockMarket != null && PizzaProbabilityConfig.ActiveSettings.ApparatusValueMultiplier) { ((GrabbableObject)apparatus).SetScrapValue(stockMarket.Next(Convert.ToInt32(PizzaProbabilityConfig.ActiveSettings.SpicyApparatusMinFactor * (float)PizzaProbabilityConfig.ActiveSettings.ApparatusValueBase), 1 + Convert.ToInt32(PizzaProbabilityConfig.ActiveSettings.SpicyApparatusMaxFactor * (float)PizzaProbabilityConfig.ActiveSettings.ApparatusValueBase))); stockMarket = null; Logger.LogInfo((object)$"Added extra cheese to the pizza. (Set apparatus value to ${((GrabbableObject)apparatus).scrapValue}.)"); } Logger.LogInfo((object)"The pizza is spicy! (Meltdown may proceed.)"); MeltdownAPI.StartMeltdown("PizzaProbability"); } else { if (stockMarket != null && PizzaProbabilityConfig.ActiveSettings.ApparatusValueMultiplier) { ((GrabbableObject)apparatus).SetScrapValue(stockMarket.Next(Convert.ToInt32(PizzaProbabilityConfig.ActiveSettings.SafeApparatusMinFactor * (float)PizzaProbabilityConfig.ActiveSettings.ApparatusValueBase), 1 + Convert.ToInt32(PizzaProbabilityConfig.ActiveSettings.SafeApparatusMaxFactor * (float)PizzaProbabilityConfig.ActiveSettings.ApparatusValueBase))); stockMarket = null; Logger.LogInfo((object)$"Added extra sauce to the pizza. (Set apparatus value to ${((GrabbableObject)apparatus).scrapValue}.)"); } Logger.LogInfo((object)"The pizza is basic. (Meltdown was blocked.)"); } } internal static void MuteDefaultSounds(AudioSource music, AudioSource voice) { music.volume = 0f; if (PizzaProbabilityConfig.MuteWarnings) { voice.volume = 0f; } } } public static class PluginInfo { public const string PLUGIN_GUID = "PizzaProbability"; public const string PLUGIN_NAME = "PizzaProbability"; public const string PLUGIN_VERSION = "1.2.4"; } } namespace PizzaProbability.Patches { [HarmonyPatch(typeof(GameEventListener))] internal class GameEventListenerPatch { [HarmonyPrefix] [HarmonyPatch("CheckApparatusTaken")] private static bool CheckApparatusPatch() { return MeltdownAPI.MeltdownStarted; } } [HarmonyPatch(typeof(GameNetworkManager))] internal class GameNetworkManagerPatch { [HarmonyPostfix] [HarmonyPatch("StartDisconnect")] public static void StartDisconnectPatch() { SyncedInstance.RevertSync(); } } [HarmonyPatch(typeof(LungProp))] internal class LungPropPatch { [HarmonyPrefix] [HarmonyPatch("EquipItem")] private static void ApparatusEquipPatch(LungProp __instance) { PizzaProbabilityMod.FindOut(__instance); } } [HarmonyPatch(typeof(MeltdownHandler))] internal class MeltdownHandlerPatch { [HarmonyPostfix] [HarmonyPatch("Update")] private static void UpdatePatch(AudioSource ___meltdownMusic, AudioSource ___warningSource) { PizzaProbabilityMod.MuteDefaultSounds(___meltdownMusic, ___warningSource); } } [HarmonyPatch(typeof(PlayerControllerB))] internal class PlayerControllerBPatch { [HarmonyPostfix] [HarmonyPatch("ConnectClientToPlayerObject")] public static void ConnectClientPatch() { PizzaProbabilityConfig.InitializeLocalPlayer(); } } [HarmonyPatch(typeof(StartOfRound))] internal class StartOfRoundPatch { [HarmonyPostfix] [HarmonyPatch("Start")] private static void StartPatch(StartOfRound __instance) { PizzaProbabilityConfig.RegisterMoons(__instance); } [HarmonyPrefix] [HarmonyPatch("OnShipLandedMiscEvents")] private static void ShipLandedPatch(StartOfRound __instance) { PizzaProbabilityMod.Randomize(__instance); } } } namespace PizzaProbability.Config { [Serializable] internal class MoonConfig { internal readonly string MoonName = ""; [NonSerialized] private readonly ConfigEntry meltdownChance; [NonSerialized] private readonly ConfigEntry apparatusValueBase; [NonSerialized] private readonly ConfigEntry apparatusValueMultiplier; [NonSerialized] private readonly ConfigEntry useMoonSettings; [NonSerialized] private readonly ConfigEntry safeApparatusMinFactor; [NonSerialized] private readonly ConfigEntry safeApparatusMaxFactor; [NonSerialized] private readonly ConfigEntry spicyApparatusMinFactor; [NonSerialized] private readonly ConfigEntry spicyApparatusMaxFactor; internal readonly int MeltdownChance = 50; internal readonly int ApparatusValueBase = 80; internal readonly bool ApparatusValueMultiplier = true; internal readonly bool UseMoonSettings; internal readonly float SafeApparatusMinFactor = 1f; internal readonly float SafeApparatusMaxFactor = 3f; internal readonly float SpicyApparatusMinFactor = 2f; internal readonly float SpicyApparatusMaxFactor = 4f; internal MoonConfig(ConfigFile config, string moonName) { MoonName = moonName; if (moonName == "") { moonName = "Global"; meltdownChance = config.Bind("FacilityMeltdown", "MeltdownChance", MeltdownChance, (ConfigDescription)null); apparatusValueMultiplier = config.Bind("PizzaProbability", "ApparatusValueMultiplier", ApparatusValueMultiplier, (ConfigDescription)null); apparatusValueBase = config.Bind("PizzaProbability", "ApparatusValueBase", ApparatusValueBase, (ConfigDescription)null); safeApparatusMinFactor = config.Bind("PizzaProbability", "SafeApparatusMinFactor", SafeApparatusMinFactor, (ConfigDescription)null); safeApparatusMaxFactor = config.Bind("PizzaProbability", "SafeApparatusMaxFactor", SafeApparatusMaxFactor, (ConfigDescription)null); spicyApparatusMinFactor = config.Bind("PizzaProbability", "SpicyApparatusMinFactor", SpicyApparatusMinFactor, (ConfigDescription)null); spicyApparatusMaxFactor = config.Bind("PizzaProbability", "SpicyApparatusMaxFactor", SpicyApparatusMaxFactor, (ConfigDescription)null); MeltdownChance = meltdownChance.Value; ApparatusValueMultiplier = apparatusValueMultiplier.Value; ApparatusValueBase = apparatusValueBase.Value; SafeApparatusMinFactor = safeApparatusMinFactor.Value; SafeApparatusMaxFactor = safeApparatusMaxFactor.Value; SpicyApparatusMinFactor = spicyApparatusMinFactor.Value; SpicyApparatusMaxFactor = spicyApparatusMaxFactor.Value; config.Remove(((ConfigEntryBase)meltdownChance).Definition); config.Remove(((ConfigEntryBase)apparatusValueMultiplier).Definition); config.Remove(((ConfigEntryBase)apparatusValueBase).Definition); config.Remove(((ConfigEntryBase)safeApparatusMinFactor).Definition); config.Remove(((ConfigEntryBase)safeApparatusMaxFactor).Definition); config.Remove(((ConfigEntryBase)spicyApparatusMinFactor).Definition); config.Remove(((ConfigEntryBase)spicyApparatusMaxFactor).Definition); config.Clear(); } else { moonName = "Moon - "; useMoonSettings = config.Bind(moonName + MoonName, "Use" + MoonName + "Settings", UseMoonSettings, "Enables moon-specific settings for " + MoonName + ". When disabled, global settings are used for " + MoonName + "."); UseMoonSettings = useMoonSettings.Value; } meltdownChance = config.Bind(moonName + MoonName, "MeltdownChance", MeltdownChance, "Sets the percentage chance of a meltdown occuring when the apparatus is taken."); apparatusValueMultiplier = config.Bind(moonName + MoonName, "ApparatusValueMultiplier", ApparatusValueMultiplier, "Enables apparatus value multipliers."); apparatusValueBase = config.Bind(moonName + MoonName, "ApparatusValueBase", ApparatusValueBase, "Sets the base value of an apparatus before applying multipliers."); safeApparatusMinFactor = config.Bind(moonName + MoonName, "SafeApparatusMinFactor", SafeApparatusMinFactor, "Minimum value multiplier for a safe apparatus."); safeApparatusMaxFactor = config.Bind(moonName + MoonName, "SafeApparatusMaxFactor", SafeApparatusMaxFactor, "Maximum value multiplier for a safe apparatus."); spicyApparatusMinFactor = config.Bind(moonName + MoonName, "SpicyApparatusMinFactor", SpicyApparatusMinFactor, "Minimum value multiplier for an unsafe apparatus."); spicyApparatusMaxFactor = config.Bind(moonName + MoonName, "SpicyApparatusMaxFactor", SpicyApparatusMaxFactor, "Maximum value multiplier for an unsafe apparatus."); MeltdownChance = meltdownChance.Value; ApparatusValueMultiplier = apparatusValueMultiplier.Value; ApparatusValueBase = apparatusValueBase.Value; SafeApparatusMinFactor = safeApparatusMinFactor.Value; SafeApparatusMaxFactor = safeApparatusMaxFactor.Value; SpicyApparatusMinFactor = spicyApparatusMinFactor.Value; SpicyApparatusMaxFactor = spicyApparatusMaxFactor.Value; } internal void OutputForecast() { PizzaProbabilityMod.Logger.LogInfo((object)$"Forecast: {MeltdownChance}% chance of pizza."); } internal void OutputEconomy() { if (ApparatusValueMultiplier) { PizzaProbabilityMod.Logger.LogInfo((object)$"Cost of pizza: ${ApparatusValueBase}"); PizzaProbabilityMod.Logger.LogInfo((object)$"Basic pizza stocks: {SafeApparatusMinFactor}-{SafeApparatusMaxFactor}x"); PizzaProbabilityMod.Logger.LogInfo((object)$"Spicy pizza stocks: {SpicyApparatusMinFactor}-{SpicyApparatusMaxFactor}x"); } } internal void OutputAll() { OutputForecast(); OutputEconomy(); } } [Serializable] internal class MoonConfigList { [NonSerialized] private readonly ConfigFile config; private readonly List moonConfigList; [NonSerialized] private readonly ConfigEntry validMoonList; [NonSerialized] private List validMoonBuffer; private List ValidMoonList { get { return validMoonBuffer ?? (validMoonBuffer = validMoonList.Value.Split(",").ToList()); } set { value.Sort(); validMoonList.Value = string.Join(",", value); validMoonBuffer = null; } } internal MoonConfigList(ConfigFile config) { this.config = config; moonConfigList = new List(1) { new MoonConfig(config, "") }; validMoonList = config.Bind("Restricted", "MoonList", "Adamance,Artifice,Assurance,Dine,Embrion,Experimentation,Liquidation,March,Offense,Rend,Titan,Vow", "Automatically generated by PizzaProbability. Do not touch."); foreach (string validMoon in ValidMoonList) { moonConfigList.Add(new MoonConfig(config, validMoon)); } validMoonBuffer = new List(); } private void TruncateMoonName(ref string moonName) { moonName = new string(moonName.Where(char.IsLetter).ToArray()); } internal void Add(string moonName) { TruncateMoonName(ref moonName); if (!ValidMoonList.Contains(moonName)) { if (moonName == "Gordion") { return; } ValidMoonList.Add(moonName); ValidMoonList = ValidMoonList; } foreach (MoonConfig moonConfig in moonConfigList) { if (moonConfig.MoonName == moonName) { return; } } moonConfigList.Add(new MoonConfig(config, moonName)); } internal MoonConfig Get() { return moonConfigList[0]; } internal MoonConfig Get(string moonName) { TruncateMoonName(ref moonName); foreach (MoonConfig moonConfig in moonConfigList) { if (moonConfig.MoonName == moonName) { if (moonConfig.UseMoonSettings) { return moonConfig; } break; } } return Get(); } } [Serializable] internal class PizzaProbabilityConfig : SyncedInstance { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnRequestSync; public static HandleNamedMessageDelegate <1>__OnReceiveSync; } private readonly MoonConfigList moonConfigList; [NonSerialized] private readonly ConfigEntry pizzaPatch; [NonSerialized] private readonly ConfigEntry muteWarnings; internal static MoonConfig ActiveSettings { get; private set; } internal static bool PizzaPatch { get; private set; } = true; internal static bool MuteWarnings { get; private set; } = true; internal PizzaProbabilityConfig(ConfigFile config) { InitInstance(this); moonConfigList = new MoonConfigList(config); ActiveSettings = moonConfigList.Get(); pizzaPatch = config.Bind("PizzaTowerEscapeMusic", "PizzaPatch", PizzaPatch, (ConfigDescription)null); PizzaPatch = pizzaPatch.Value; config.Remove(((ConfigEntryBase)pizzaPatch).Definition); pizzaPatch = config.Bind("Global", "PizzaPatch", PizzaPatch, "Patches PizzaTowerEscapeMusic's 'ApparatusTaken' event to only activate when a meltdown occurs. Disables FacilityMeltdown's music if PizzaTowerEscapeMusic is installed."); PizzaPatch = pizzaPatch.Value; muteWarnings = config.Bind("Global", "MuteWarnings", MuteWarnings, "Disables FacilityMeltdown's warning voice if PizzaTowerEscapeMusic is installed and 'PizzaPatch' is enabled. Use this if your escape music includes a warning voice."); MuteWarnings = muteWarnings.Value; } internal static void RegisterMoons(StartOfRound round) { SelectableLevel[] levels = round.levels; foreach (SelectableLevel val in levels) { SyncedInstance.Default.moonConfigList.Add(val.PlanetName); } } internal static MoonConfig GetGlobalSettings() { return ActiveSettings = SyncedInstance.Instance.moonConfigList.Get(); } internal static MoonConfig GetMoonSettings(string moonName) { ActiveSettings = SyncedInstance.Instance.moonConfigList.Get(moonName); if (ActiveSettings.MoonName == "") { PizzaProbabilityMod.Logger.LogInfo((object)("No special offers are available in " + moonName + ". (Using global settings.)")); } else { PizzaProbabilityMod.Logger.LogInfo((object)("Special offers are available in " + moonName + ". (Using moon-specific settings.)")); ActiveSettings.OutputAll(); } return ActiveSettings; } internal static void InitializeLocalPlayer() { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown if (SyncedInstance.IsHost) { CustomMessagingManager messageManager = SyncedInstance.MessageManager; object obj = <>O.<0>__OnRequestSync; if (obj == null) { HandleNamedMessageDelegate val = OnRequestSync; <>O.<0>__OnRequestSync = val; obj = (object)val; } messageManager.RegisterNamedMessageHandler("PizzaProbability_OnRequestConfigSync", (HandleNamedMessageDelegate)obj); return; } CustomMessagingManager messageManager2 = SyncedInstance.MessageManager; object obj2 = <>O.<1>__OnReceiveSync; if (obj2 == null) { HandleNamedMessageDelegate val2 = OnReceiveSync; <>O.<1>__OnReceiveSync = val2; obj2 = (object)val2; } messageManager2.RegisterNamedMessageHandler("PizzaProbability_OnReceiveConfigSync", (HandleNamedMessageDelegate)obj2); RequestSync(); } private unsafe static void RequestSync() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) if (!SyncedInstance.IsClient) { return; } PizzaProbabilityMod.Logger.LogInfo((object)"Ordering a pizza... (Config requested from host.)"); FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(SyncedInstance.IntSize, (Allocator)2, -1); try { SyncedInstance.MessageManager.SendNamedMessage("PizzaProbability_OnRequestConfigSync", 0uL, val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private unsafe static void OnRequestSync(ulong clientId, FastBufferReader _) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: 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 (!SyncedInstance.IsHost) { return; } PizzaProbabilityMod.Logger.LogInfo((object)$"Recieved an order from customer #{clientId}. (Config requested by client.)"); byte[] array = SyncedInstance.SerializeToBytes(SyncedInstance.Instance); int num = array.Length; FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(num + SyncedInstance.IntSize, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe(ref num, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteBytesSafe(array, -1, 0); SyncedInstance.MessageManager.SendNamedMessage("PizzaProbability_OnReceiveConfigSync", clientId, val, (NetworkDelivery)4); PizzaProbabilityMod.Logger.LogInfo((object)$"Sent a pizza to customer #{clientId}. (Config sent to client.)"); } catch (Exception arg) { PizzaProbabilityMod.Logger.LogError((object)$"Cannot to deliver to customer #{clientId}. (Config failed to sync with client.)\n{arg}"); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private static void OnReceiveSync(ulong _, FastBufferReader reader) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) if (!((FastBufferReader)(ref reader)).TryBeginRead(SyncedInstance.IntSize)) { PizzaProbabilityMod.Logger.LogError((object)"Recieved the wrong order. (Config failed to sync with host.)"); return; } int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); if (!((FastBufferReader)(ref reader)).TryBeginRead(num)) { PizzaProbabilityMod.Logger.LogError((object)"Recieved a cold pizza. (Config failed to sync with host.)"); return; } byte[] data = new byte[num]; ((FastBufferReader)(ref reader)).ReadBytesSafe(ref data, num, 0); SyncedInstance.SyncInstance(data); PizzaProbabilityMod.Logger.LogInfo((object)"The pizza is here! (Config received from host.)"); GetGlobalSettings().OutputAll(); } } [Serializable] internal class SyncedInstance { [NonSerialized] protected static int IntSize = 4; protected static T Default { get; private set; } protected static T Instance { get; private set; } protected static bool IsHost => NetworkManager.Singleton.IsHost; protected static bool IsClient => NetworkManager.Singleton.IsClient; protected static CustomMessagingManager MessageManager => NetworkManager.Singleton.CustomMessagingManager; protected void InitInstance(T instance) { Default = instance; Instance = instance; IntSize = 4; } protected static void SyncInstance(byte[] data) { Instance = DeserializeFromBytes(data); } internal static void RevertSync() { Instance = Default; } protected 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) { PizzaProbabilityMod.Logger.LogError((object)$"Is cereal a pizza topping? (Error serializing instance.)\n{arg}"); return null; } } private static T DeserializeFromBytes(byte[] data) { BinaryFormatter binaryFormatter = new BinaryFormatter(); using MemoryStream serializationStream = new MemoryStream(data); try { return (T)binaryFormatter.Deserialize(serializationStream); } catch (Exception arg) { PizzaProbabilityMod.Logger.LogError((object)$"Why is there cereal on my pizza? (Error deserializing instance.)\n{arg}"); return default(T); } } } }