using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Dawn;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using MoonProgression.Helpers;
using MoonProgression.Main;
using MoonProgression.Patches;
using QuotaMoonUnlocker.NetcodePatcher;
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(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("QuotaMoonUnlocker")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("0.0.1.0")]
[assembly: AssemblyInformationalVersion("0.0.1")]
[assembly: AssemblyProduct("QuotaMoonUnlocker")]
[assembly: AssemblyTitle("QuotaMoonUnlocker")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[module: NetcodePatchedAssembly]
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 MoonProgression
{
[BepInPlugin("MrHat.QuotaMoonUnlocker", "QuotaMoonUnlocker", "0.0.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : BaseUnityPlugin
{
internal const string modGUID = "MrHat.QuotaMoonUnlocker";
internal const string modName = "QuotaMoonUnlocker";
internal const string modVersion = "0.0.1";
internal static Harmony _harmony;
internal static ManualLogSource mls;
internal static Plugin Instance;
internal static ConfigEntry<bool> DebugEnabled { get; private set; }
internal static ConfigEntry<string> UnlockPlan { get; private set; }
private void Awake()
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Expected O, but got Unknown
Instance = this;
mls = Logger.CreateLogSource("MrHat.QuotaMoonUnlocker");
_harmony = new Harmony("MrHat.QuotaMoonUnlocker");
DebugEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "Enabled", false, "Enables debug logging.");
UnlockPlan = ((BaseUnityPlugin)this).Config.Bind<string>("Moon Unlocking", "Unlock Plan", "0:Experimentation;Assurance,1:Vow;Offense,2:March;Rend;Dine,4:Titan", "Format: QuotaCount:Moon1;Moon3,QuotaCount:Moon2");
MoonUnlocker.UpdateConfig(UnlockPlan.Value);
_harmony.PatchAll(typeof(HarmonyPatches));
}
internal static void LogDebug(string message)
{
if (DebugEnabled.Value)
{
mls.LogDebug((object)message);
}
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "QuotaMoonUnlocker";
public const string PLUGIN_NAME = "QuotaMoonUnlocker";
public const string PLUGIN_VERSION = "0.0.1";
}
}
namespace MoonProgression.Patches
{
internal static class HarmonyPatches
{
[HarmonyPatch(typeof(StartOfRound), "Awake")]
[HarmonyPrefix]
private static void StartOfRoundAwakePrefix()
{
MoonUnlocker.EnsureQuotaMessageRegistered();
}
[HarmonyPatch(typeof(StartOfRound), "Start")]
[HarmonyPostfix]
private static void StartOfRoundStartPostfix()
{
MoonUnlocker.ApplyPredicatesToAllLevels();
if (((NetworkBehaviour)StartOfRound.Instance).IsServer)
{
MoonUnlocker.BroadcastQuota();
}
}
[HarmonyPatch(typeof(StartOfRound), "PlayerLoadedServerRpc")]
[HarmonyPostfix]
private static void PlayerLoadedServerRpcPostfix(ulong clientId)
{
if (((NetworkBehaviour)StartOfRound.Instance).IsServer)
{
MoonUnlocker.SyncQuota(clientId);
}
}
[HarmonyPatch(typeof(StartOfRound), "OnDestroy")]
[HarmonyPostfix]
private static void StartOfRoundOnDestroyPostfix()
{
MoonUnlocker.ResetQuotaSync();
}
[HarmonyPatch(typeof(TimeOfDay), "SetNewProfitQuota")]
[HarmonyPostfix]
private static void SetNewProfitQuotaPostfix()
{
MoonUnlocker.OnNewQuotaSet();
}
}
}
namespace MoonProgression.Main
{
internal static class MoonUnlocker
{
private readonly struct UnlockGroup
{
public readonly int RequiredCompletedQuotas;
public readonly string[] Moons;
public UnlockGroup(int requiredCompletedQuotas, string[] moons)
{
RequiredCompletedQuotas = requiredCompletedQuotas;
Moons = moons;
}
}
[CompilerGenerated]
private static class <>O
{
public static HandleNamedMessageDelegate <0>__OnQuotaSyncMessage;
}
private static readonly Dictionary<string, int> moonUnlockQuotaByKey = new Dictionary<string, int>();
private static readonly Dictionary<string, string> originalMoonNameByKey = new Dictionary<string, string>();
private const string QuotaSyncMessage = "MrHat.QuotaMoonUnlocker.Sync";
private static NetworkManager registeredNetworkManager;
private static readonly bool quotaMessageRegistered;
private static int syncedCompletedQuotas = -1;
private static int lastSeenCompletedQuotas = 0;
private static bool loggedInitialSync;
internal static void UpdateConfig(string unlockPlanText)
{
moonUnlockQuotaByKey.Clear();
originalMoonNameByKey.Clear();
List<UnlockGroup> list = ParseUnlockPlan(unlockPlanText);
foreach (UnlockGroup item in list)
{
string[] moons = item.Moons;
foreach (string text in moons)
{
string key = NormaliseKey(text);
if (moonUnlockQuotaByKey.TryGetValue(key, out var value))
{
if (item.RequiredCompletedQuotas < value)
{
moonUnlockQuotaByKey[key] = item.RequiredCompletedQuotas;
}
}
else
{
moonUnlockQuotaByKey[key] = item.RequiredCompletedQuotas;
originalMoonNameByKey[key] = text;
}
}
}
Plugin.LogDebug($"Unlock plan entries: {moonUnlockQuotaByKey.Count}");
}
internal static void ApplyPredicatesToAllLevels()
{
SelectableLevel[] levels = StartOfRound.Instance.levels;
int num = 0;
SelectableLevel[] array = levels;
foreach (SelectableLevel val in array)
{
string key = NormaliseKey(val.PlanetName);
if (moonUnlockQuotaByKey.TryGetValue(key, out var value))
{
DawnMoonInfo dawnInfo = DawnHelper.GetDawnInfo(val);
DawnPurchaseInfo dawnPurchaseInfo = dawnInfo.DawnPurchaseInfo;
ITerminalPurchasePredicate purchasePredicate = dawnPurchaseInfo.PurchasePredicate;
if (!(purchasePredicate is QuotaUnlockPredicate))
{
string planetName = val.PlanetName;
QuotaUnlockPredicate predicate = new QuotaUnlockPredicate(val.PlanetName, purchasePredicate, value);
DawnHelper.SetPurchasePredicate(dawnPurchaseInfo, (ITerminalPurchasePredicate)(object)predicate);
num++;
}
}
}
Plugin.LogDebug($"Applied predicates: {num}");
}
internal static void OnNewQuotaSet()
{
int timesFulfilledQuota = TimeOfDay.Instance.timesFulfilledQuota;
if (!NetworkManager.Singleton.IsServer && syncedCompletedQuotas >= 0 && timesFulfilledQuota > syncedCompletedQuotas)
{
syncedCompletedQuotas = timesFulfilledQuota;
}
if (timesFulfilledQuota != lastSeenCompletedQuotas)
{
lastSeenCompletedQuotas = timesFulfilledQuota;
Plugin.LogDebug($"Quota now: {timesFulfilledQuota}");
if (((NetworkBehaviour)StartOfRound.Instance).IsServer)
{
BroadcastQuota();
}
}
}
internal static void EnsureQuotaMessageRegistered()
{
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_0070: Expected O, but got Unknown
NetworkManager singleton = NetworkManager.Singleton;
if (!((Object)(object)singleton == (Object)null) && !((Object)(object)registeredNetworkManager == (Object)(object)singleton))
{
NetworkManager obj = registeredNetworkManager;
if (obj != null)
{
obj.CustomMessagingManager.UnregisterNamedMessageHandler("MrHat.QuotaMoonUnlocker.Sync");
}
registeredNetworkManager = singleton;
CustomMessagingManager customMessagingManager = registeredNetworkManager.CustomMessagingManager;
object obj2 = <>O.<0>__OnQuotaSyncMessage;
if (obj2 == null)
{
HandleNamedMessageDelegate val = OnQuotaSyncMessage;
<>O.<0>__OnQuotaSyncMessage = val;
obj2 = (object)val;
}
customMessagingManager.RegisterNamedMessageHandler("MrHat.QuotaMoonUnlocker.Sync", (HandleNamedMessageDelegate)obj2);
}
}
private static void OnQuotaSyncMessage(ulong senderClientId, FastBufferReader reader)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
int num = default(int);
((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives));
if (num > syncedCompletedQuotas)
{
syncedCompletedQuotas = num;
}
if (!loggedInitialSync)
{
loggedInitialSync = true;
Plugin.LogDebug($"Synced quota from host: {syncedCompletedQuotas}");
}
}
internal static int GetCompletedQuotas()
{
if ((Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsServer)
{
return TimeOfDay.Instance.timesFulfilledQuota;
}
if (syncedCompletedQuotas >= 0)
{
return syncedCompletedQuotas;
}
return ((Object)(object)TimeOfDay.Instance != (Object)null) ? TimeOfDay.Instance.timesFulfilledQuota : 0;
}
internal static void SyncQuota(ulong clientId)
{
//IL_0032: 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_004f: Unknown result type (might be due to invalid IL or missing references)
if (!NetworkManager.Singleton.IsServer)
{
return;
}
EnsureQuotaMessageRegistered();
FastBufferWriter val = default(FastBufferWriter);
((FastBufferWriter)(ref val))..ctor(4, (Allocator)2, -1);
try
{
((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref TimeOfDay.Instance.timesFulfilledQuota, default(ForPrimitives));
NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("MrHat.QuotaMoonUnlocker.Sync", clientId, val, (NetworkDelivery)3);
}
finally
{
((IDisposable)(FastBufferWriter)(ref val)).Dispose();
}
}
internal static void BroadcastQuota()
{
if (NetworkManager.Singleton.IsServer)
{
IReadOnlyList<ulong> connectedClientsIds = NetworkManager.Singleton.ConnectedClientsIds;
for (int i = 0; i < connectedClientsIds.Count; i++)
{
SyncQuota(connectedClientsIds[i]);
}
}
}
internal static void ResetQuotaSync()
{
syncedCompletedQuotas = -1;
lastSeenCompletedQuotas = 0;
loggedInitialSync = false;
registeredNetworkManager = null;
}
private static string NormaliseKey(string raw)
{
StringBuilder stringBuilder = new StringBuilder(raw.Length);
foreach (char c in raw)
{
if (char.IsLetter(c))
{
stringBuilder.Append(char.ToUpperInvariant(c));
}
}
return stringBuilder.ToString();
}
private static List<UnlockGroup> ParseUnlockPlan(string text)
{
List<UnlockGroup> list = new List<UnlockGroup>();
if (string.IsNullOrWhiteSpace(text))
{
return list;
}
int num = text.IndexOf(':');
if (num < 0)
{
return list;
}
int num2 = text.IndexOf(',', num + 1);
int num3 = text.IndexOf(';', num + 1);
bool flag = num3 != -1 && (num2 == -1 || num3 < num2);
char c = (flag ? ',' : ';');
char c2 = (flag ? ';' : ',');
string[] array = text.Split(new char[1] { c }, StringSplitOptions.RemoveEmptyEntries);
string[] array2 = array;
foreach (string text2 in array2)
{
string[] array3 = text2.Split(new char[1] { ':' }, 2);
if (array3.Length == 2 && int.TryParse(array3[0].Trim(), out var result))
{
string[] array4 = (from m in array3[1].Split(new char[1] { c2 }, StringSplitOptions.RemoveEmptyEntries)
select m.Trim() into m
where m.Length > 0
select m).ToArray();
if (array4.Length != 0)
{
list.Add(new UnlockGroup(result, array4));
}
}
}
return list;
}
}
internal sealed class QuotaUnlockPredicate : ITerminalPurchasePredicate
{
private readonly string moonNameForLogs;
private readonly ITerminalPurchasePredicate basePredicate;
private readonly int requiredCompletedQuotas;
private readonly TerminalNode lockedNode;
private int lastSeenQuotas = 0;
private bool lastSeenUnlocked;
internal QuotaUnlockPredicate(string moonNameForLogs, ITerminalPurchasePredicate basePredicate, int requiredCompletedQuotas)
{
this.moonNameForLogs = moonNameForLogs;
this.basePredicate = basePredicate;
this.requiredCompletedQuotas = requiredCompletedQuotas;
lockedNode = ScriptableObject.CreateInstance<TerminalNode>();
lockedNode.clearPreviousText = true;
}
private static string BuildLockedText(int requiredQuota, int currentQuota)
{
return $"This moon is locked until quota {requiredQuota}, you are currently on quota {currentQuota}. Back to work, you slacker!";
}
public TerminalPurchaseResult CanPurchase()
{
TerminalPurchaseResult val = basePredicate.CanPurchase();
if (val is HiddenPurchaseResult)
{
return val;
}
if (val is FailedPurchaseResult)
{
return val;
}
int completedQuotas = MoonUnlocker.GetCompletedQuotas();
bool flag = completedQuotas >= requiredCompletedQuotas;
if (completedQuotas != lastSeenQuotas || flag != lastSeenUnlocked)
{
Plugin.LogDebug($"Predicate check '{moonNameForLogs}': CompletedQuotas={completedQuotas}, Required={requiredCompletedQuotas}, Unlocked={flag}");
lastSeenQuotas = completedQuotas;
lastSeenUnlocked = flag;
}
if (flag)
{
return (TerminalPurchaseResult)(object)TerminalPurchaseResult.Success();
}
lockedNode.displayText = BuildLockedText(requiredCompletedQuotas, completedQuotas);
HiddenPurchaseResult val2 = TerminalPurchaseResult.Hidden();
val2.SetFailure(true);
val2.SetFailNode(lockedNode);
return (TerminalPurchaseResult)(object)val2;
}
}
}
namespace MoonProgression.Helpers
{
internal static class DawnHelper
{
private static readonly MethodInfo setPurchasePredicate = AccessTools.PropertySetter(typeof(DawnPurchaseInfo), "PurchasePredicate");
private static bool reportedMissingSetter;
internal static DawnMoonInfo GetDawnInfo(SelectableLevel level)
{
return SelectableLevelExtensions.GetDawnInfo(level);
}
internal static bool SetPurchasePredicate(DawnPurchaseInfo purchaseInfo, ITerminalPurchasePredicate predicate)
{
if (setPurchasePredicate == null)
{
if (!reportedMissingSetter)
{
reportedMissingSetter = true;
Plugin.LogDebug("DawnHelper: PurchasePredicate setter not found. Predicate cannot be replaced.");
}
return false;
}
setPurchasePredicate.Invoke(purchaseInfo, new object[1] { predicate });
return true;
}
}
}
namespace __GEN
{
internal class NetworkVariableSerializationHelper
{
[RuntimeInitializeOnLoadMethod]
internal static void InitializeSerialization()
{
}
}
}
namespace QuotaMoonUnlocker.NetcodePatcher
{
[AttributeUsage(AttributeTargets.Module)]
internal class NetcodePatchedAssemblyAttribute : Attribute
{
}
}