Decompiled source of WeatherReroll v1.0.0

WeatherReroll.dll

Decompiled 2 days ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
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("WeatherReroll")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("WeatherReroll")]
[assembly: AssemblyTitle("WeatherReroll")]
[assembly: AssemblyVersion("1.0.0.0")]
[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 WeatherReroll
{
	[HarmonyPatch]
	internal static class GamePatches
	{
		[HarmonyPatch(typeof(StartOfRound), "Start")]
		[HarmonyPostfix]
		private static void StartOfRound_Start_Postfix()
		{
			RerollService.ResetDailyUses();
			RerollService.RegisterMessageHandlers();
		}

		[HarmonyPatch(typeof(TimeOfDay), "OnDayChanged")]
		[HarmonyPostfix]
		private static void TimeOfDay_OnDayChanged_Postfix()
		{
			RerollService.ResetDailyUses();
		}
	}
	[BepInPlugin("BLUJAY.WeatherReroll", "Weather Reroll", "1.0.0")]
	public class WeatherRerollPlugin : BaseUnityPlugin
	{
		public const string Guid = "BLUJAY.WeatherReroll";

		public const string Name = "Weather Reroll";

		public const string Version = "1.0.0";

		internal static ManualLogSource Log;

		internal static ConfigEntry<int> StartingCost;

		internal static ConfigEntry<int> CostIncrease;

		private void Awake()
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			StartingCost = ((BaseUnityPlugin)this).Config.Bind<int>("Pricing", "StartingCost", 1000, "Cost of the first weather reroll of the day. The host's settings are authoritative in multiplayer.");
			CostIncrease = ((BaseUnityPlugin)this).Config.Bind<int>("Pricing", "CostIncrease", 2000, "How much the price goes up with each reroll purchased that day (1000 -> 3000 -> 5000 -> ...). Resets when the day ends.");
			Harmony val = new Harmony("BLUJAY.WeatherReroll");
			val.PatchAll(typeof(TerminalPatches));
			val.PatchAll(typeof(GamePatches));
			Log.LogInfo((object)"Weather Reroll v1.0.0 loaded. Type REROLL in the terminal while in orbit.");
		}
	}
	internal static class RerollService
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static HandleNamedMessageDelegate <0>__OnRequestReceived;

			public static HandleNamedMessageDelegate <1>__OnSyncReceived;

			public static HandleNamedMessageDelegate <2>__OnDeniedReceived;
		}

		private const string MsgRequest = "WeatherReroll.Request";

		private const string MsgSync = "WeatherReroll.Sync";

		private const string MsgDenied = "WeatherReroll.Denied";

		internal static int RerollsUsedToday;

		internal static int CurrentCost => CostFor(RerollsUsedToday);

		internal static bool InOrbit
		{
			get
			{
				if ((Object)(object)StartOfRound.Instance != (Object)null && StartOfRound.Instance.inShipPhase)
				{
					return !StartOfRound.Instance.travellingToNewLevel;
				}
				return false;
			}
		}

		internal static int CostFor(int usedCount)
		{
			return Mathf.Max(1, WeatherRerollPlugin.StartingCost.Value + usedCount * WeatherRerollPlugin.CostIncrease.Value);
		}

		internal static string FormatMoney(int amount)
		{
			return "$" + amount.ToString("N0");
		}

		internal static void ResetDailyUses()
		{
			RerollsUsedToday = 0;
		}

		internal static void RegisterMessageHandlers()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Expected O, but got Unknown
			NetworkManager singleton = NetworkManager.Singleton;
			if (!((Object)(object)singleton == (Object)null) && singleton.CustomMessagingManager != null)
			{
				CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager;
				object obj = <>O.<0>__OnRequestReceived;
				if (obj == null)
				{
					HandleNamedMessageDelegate val = OnRequestReceived;
					<>O.<0>__OnRequestReceived = val;
					obj = (object)val;
				}
				customMessagingManager.RegisterNamedMessageHandler("WeatherReroll.Request", (HandleNamedMessageDelegate)obj);
				CustomMessagingManager customMessagingManager2 = singleton.CustomMessagingManager;
				object obj2 = <>O.<1>__OnSyncReceived;
				if (obj2 == null)
				{
					HandleNamedMessageDelegate val2 = OnSyncReceived;
					<>O.<1>__OnSyncReceived = val2;
					obj2 = (object)val2;
				}
				customMessagingManager2.RegisterNamedMessageHandler("WeatherReroll.Sync", (HandleNamedMessageDelegate)obj2);
				CustomMessagingManager customMessagingManager3 = singleton.CustomMessagingManager;
				object obj3 = <>O.<2>__OnDeniedReceived;
				if (obj3 == null)
				{
					HandleNamedMessageDelegate val3 = OnDeniedReceived;
					<>O.<2>__OnDeniedReceived = val3;
					obj3 = (object)val3;
				}
				customMessagingManager3.RegisterNamedMessageHandler("WeatherReroll.Denied", (HandleNamedMessageDelegate)obj3);
			}
		}

		internal unsafe static void PurchaseReroll(Terminal terminal)
		{
			//IL_0038: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null)
			{
				return;
			}
			if (singleton.IsServer)
			{
				ServerPerformReroll(terminal, singleton.LocalClientId);
				return;
			}
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(4, (Allocator)2, -1);
			try
			{
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref RerollsUsedToday, default(ForPrimitives));
				singleton.CustomMessagingManager.SendNamedMessage("WeatherReroll.Request", 0uL, val, (NetworkDelivery)3);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private unsafe static void OnRequestReceived(ulong senderClientId, 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)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || !singleton.IsServer)
			{
				return;
			}
			int num = default(int);
			((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives));
			Terminal val = Object.FindObjectOfType<Terminal>();
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			if (num != RerollsUsedToday || !InOrbit || val.groupCredits < CurrentCost)
			{
				FastBufferWriter val2 = default(FastBufferWriter);
				((FastBufferWriter)(ref val2))..ctor(1, (Allocator)2, -1);
				try
				{
					byte b = 0;
					((FastBufferWriter)(ref val2)).WriteValueSafe<byte>(ref b, default(ForPrimitives));
					singleton.CustomMessagingManager.SendNamedMessage("WeatherReroll.Denied", senderClientId, val2, (NetworkDelivery)3);
					return;
				}
				finally
				{
					((IDisposable)(*(FastBufferWriter*)(&val2))/*cast due to .constrained prefix*/).Dispose();
				}
			}
			ServerPerformReroll(val, senderClientId);
		}

		private unsafe static void ServerPerformReroll(Terminal terminal, ulong purchaserClientId)
		{
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: 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_011e: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			if (!InOrbit || terminal.groupCredits < CurrentCost)
			{
				return;
			}
			int currentCost = CurrentCost;
			int num = new Random().Next(2, 100000000);
			int num2 = RerollsUsedToday + 1;
			int newCredits = Mathf.Clamp(terminal.groupCredits - currentCost, 0, 10000000);
			WeatherRerollPlugin.Log.LogInfo((object)$"Weather reroll #{num2} purchased for {FormatMoney(currentCost)} by client {purchaserClientId}; new seed {num}.");
			Apply(terminal, num, num2, newCredits, purchaserClientId);
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(20, (Allocator)2, -1);
			try
			{
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num2, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref newCredits, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref purchaserClientId, default(ForPrimitives));
				foreach (ulong connectedClientsId in singleton.ConnectedClientsIds)
				{
					if (connectedClientsId != singleton.LocalClientId)
					{
						singleton.CustomMessagingManager.SendNamedMessage("WeatherReroll.Sync", connectedClientsId, val, (NetworkDelivery)3);
					}
				}
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private static void OnSyncReceived(ulong senderClientId, FastBufferReader reader)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//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_003f: 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)
			int newSeed = default(int);
			((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref newSeed, default(ForPrimitives));
			int newCount = default(int);
			((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref newCount, default(ForPrimitives));
			int newCredits = default(int);
			((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref newCredits, default(ForPrimitives));
			ulong purchaserClientId = default(ulong);
			((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref purchaserClientId, default(ForPrimitives));
			Terminal val = Object.FindObjectOfType<Terminal>();
			if (!((Object)(object)val == (Object)null))
			{
				Apply(val, newSeed, newCount, newCredits, purchaserClientId);
			}
		}

		private static void OnDeniedReceived(ulong senderClientId, FastBufferReader reader)
		{
			if ((Object)(object)HUDManager.Instance != (Object)null)
			{
				HUDManager.Instance.DisplayTip("Weather reroll failed", "The transaction was rejected by the server. Check the moons catalogue and try again.", true, false, "LC_Tip1");
			}
		}

		private static void Apply(Terminal terminal, int newSeed, int newCount, int newCredits, ulong purchaserClientId)
		{
			StartOfRound instance = StartOfRound.Instance;
			if (!((Object)(object)instance == (Object)null))
			{
				RerollsUsedToday = newCount;
				terminal.groupCredits = newCredits;
				instance.randomMapSeed = newSeed;
				instance.SetPlanetsWeather(0);
				instance.SetMapScreenInfoToCurrentLevel();
				NetworkManager singleton = NetworkManager.Singleton;
				if ((!((Object)(object)singleton != (Object)null) || singleton.LocalClientId != purchaserClientId) && (Object)(object)HUDManager.Instance != (Object)null)
				{
					HUDManager.Instance.DisplayTip("Weather rerolled", "A crewmate purchased a weather reroll for " + FormatMoney(CostFor(newCount - 1)) + ". All forecasts have been updated.", false, false, "LC_Tip1");
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class TerminalPatches
	{
		private static TerminalKeyword rerollKeyword;

		private static TerminalNode promptNode;

		private static TerminalNode successNode;

		private static TerminalNode cancelNode;

		private static TerminalNode errorNode;

		[HarmonyPatch(typeof(Terminal), "Awake")]
		[HarmonyPostfix]
		private static void Terminal_Awake_Postfix(Terminal __instance)
		{
			TerminalNodesList terminalNodes = __instance.terminalNodes;
			if ((Object)(object)terminalNodes == (Object)null || terminalNodes.allKeywords == null)
			{
				return;
			}
			TerminalKeyword val = FindKeyword(terminalNodes.allKeywords, "confirm");
			TerminalKeyword val2 = FindKeyword(terminalNodes.allKeywords, "deny");
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
			{
				WeatherRerollPlugin.Log.LogError((object)"Could not find the vanilla CONFIRM/DENY keywords; REROLL command not registered.");
				return;
			}
			EnsureNodesExist(val, val2);
			if ((Object)(object)FindKeyword(terminalNodes.allKeywords, "reroll") == (Object)null)
			{
				terminalNodes.allKeywords = CollectionExtensions.AddToArray<TerminalKeyword>(terminalNodes.allKeywords, rerollKeyword);
				WeatherRerollPlugin.Log.LogInfo((object)"REROLL terminal command registered.");
			}
		}

		private static void EnsureNodesExist(TerminalKeyword confirmKeyword, TerminalKeyword denyKeyword)
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Expected O, but got Unknown
			if (!((Object)(object)promptNode != (Object)null))
			{
				successNode = CreateNode("WeatherRerollSuccess");
				successNode.playSyncedClip = 0;
				cancelNode = CreateNode("WeatherRerollCancel");
				cancelNode.displayText = "Cancelled weather reroll.\n\n";
				errorNode = CreateNode("WeatherRerollError");
				promptNode = CreateNode("WeatherRerollPrompt");
				promptNode.overrideOptions = true;
				promptNode.terminalOptions = (CompatibleNoun[])(object)new CompatibleNoun[2]
				{
					new CompatibleNoun(confirmKeyword, successNode),
					new CompatibleNoun(denyKeyword, cancelNode)
				};
				rerollKeyword = ScriptableObject.CreateInstance<TerminalKeyword>();
				((Object)rerollKeyword).hideFlags = (HideFlags)61;
				((Object)rerollKeyword).name = "WeatherRerollKeyword";
				rerollKeyword.word = "reroll";
				rerollKeyword.isVerb = false;
				rerollKeyword.specialKeywordResult = promptNode;
			}
		}

		private static TerminalNode CreateNode(string nodeName)
		{
			TerminalNode obj = ScriptableObject.CreateInstance<TerminalNode>();
			((Object)obj).hideFlags = (HideFlags)61;
			((Object)obj).name = nodeName;
			obj.clearPreviousText = true;
			obj.maxCharactersToType = 50;
			obj.buyItemIndex = -1;
			obj.buyVehicleIndex = -1;
			obj.buyRerouteToMoon = -1;
			obj.displayPlanetInfo = -1;
			obj.shipUnlockableID = -1;
			obj.creatureFileID = -1;
			obj.storyLogFileID = -1;
			obj.playSyncedClip = -1;
			return obj;
		}

		private static TerminalKeyword FindKeyword(TerminalKeyword[] keywords, string word)
		{
			foreach (TerminalKeyword val in keywords)
			{
				if ((Object)(object)val != (Object)null && val.word == word)
				{
					return val;
				}
			}
			return null;
		}

		[HarmonyPatch(typeof(Terminal), "LoadNewNode")]
		[HarmonyPrefix]
		private static void Terminal_LoadNewNode_Prefix(Terminal __instance, ref TerminalNode node)
		{
			if ((Object)(object)promptNode == (Object)null || (Object)(object)node == (Object)null)
			{
				return;
			}
			if ((Object)(object)node == (Object)(object)promptNode)
			{
				if (IsBlocked(__instance, out var reason))
				{
					errorNode.displayText = reason;
					node = errorNode;
				}
				else
				{
					promptNode.displayText = "You have requested to reroll the weather conditions of all moons.\nTotal cost of this service: " + RerollService.FormatMoney(RerollService.CurrentCost) + ".\n\nPlease CONFIRM or DENY.\n\n";
				}
			}
			else if ((Object)(object)node == (Object)(object)successNode)
			{
				if (IsBlocked(__instance, out var reason2))
				{
					errorNode.displayText = reason2;
					node = errorNode;
					return;
				}
				int currentCost = RerollService.CurrentCost;
				int amount = Mathf.Max(0, __instance.groupCredits - currentCost);
				int amount2 = RerollService.CostFor(RerollService.RerollsUsedToday + 1);
				successNode.displayText = "Weather systems rerolled. Your new balance is " + RerollService.FormatMoney(amount) + ".\n\nUpdated forecasts are available in the moons catalogue.\nThe next reroll today will cost " + RerollService.FormatMoney(amount2) + ".\n\n";
				RerollService.PurchaseReroll(__instance);
			}
		}

		private static bool IsBlocked(Terminal terminal, out string reason)
		{
			if (!RerollService.InOrbit)
			{
				reason = "Weather can only be rerolled while the ship is in orbit.\n\n";
				return true;
			}
			if (terminal.groupCredits < RerollService.CurrentCost)
			{
				reason = "You do not have enough credits to reroll the weather.\nCost: " + RerollService.FormatMoney(RerollService.CurrentCost) + "  //  Your balance: " + RerollService.FormatMoney(terminal.groupCredits) + ".\n\n";
				return true;
			}
			reason = null;
			return false;
		}

		[HarmonyPatch(typeof(Terminal), "TextPostProcess")]
		[HarmonyPostfix]
		private static void Terminal_TextPostProcess_Postfix(Terminal __instance, TerminalNode node, ref string __result)
		{
			if (!((Object)(object)node == (Object)null) && !((Object)(object)__instance.terminalNodes == (Object)null))
			{
				TerminalKeyword val = FindKeyword(__instance.terminalNodes.allKeywords, "moons");
				if (!((Object)(object)val == (Object)null) && !((Object)(object)node != (Object)(object)val.specialKeywordResult))
				{
					int rerollsUsedToday = RerollService.RerollsUsedToday;
					string text = rerollsUsedToday switch
					{
						0 => "The price rises with each use and resets daily.", 
						1 => "Rerolled 1 time today. Prices reset at the end of the day.", 
						_ => $"Rerolled {rerollsUsedToday} times today. Prices reset at the end of the day.", 
					};
					__result = __result + "\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\n\n* Weather reroll   //   Price: " + RerollService.FormatMoney(RerollService.CurrentCost) + "\nType REROLL to randomize the weather of all moons.\n" + text + "\n";
				}
			}
		}
	}
}