Decompiled source of ValueRace Fix v1.0.0

ValueRaceFix.dll

Decompiled 2 hours ago
using System;
using System.Collections;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace ValueRaceFix;

[BepInPlugin("valuerace.fix.runtime", "ValueRace Fix", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class Plugin : BaseUnityPlugin
{
	internal static ManualLogSource Log;

	internal static ConfigEntry<bool> DebugLogging;

	private void Awake()
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		DebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DebugLogging", false, "Enable extra logs for ValueRace Fix.");
		Harmony harmony = new Harmony("valuerace.fix.runtime");
		ValueRaceGenerateDoneGuard.Apply(harmony);
	}
}
internal static class ModLog
{
	private static bool loggedMissingTarget;

	private static bool loggedMissingUiPrefab;

	private static bool loggedPatchFailure;

	public static void Info(string message)
	{
		if (Plugin.Log != null)
		{
			Plugin.Log.LogInfo((object)message);
		}
	}

	public static void Warning(string message)
	{
		if (Plugin.Log != null)
		{
			Plugin.Log.LogWarning((object)message);
		}
	}

	public static void Debug(string message)
	{
		if (Plugin.DebugLogging != null && Plugin.DebugLogging.Value && Plugin.Log != null)
		{
			Plugin.Log.LogInfo((object)("[Debug] " + message));
		}
	}

	public static void MissingTarget()
	{
		if (!loggedMissingTarget)
		{
			Warning("REPO_ValueRace GenerateDone patch target was not found.");
			loggedMissingTarget = true;
		}
	}

	public static void MissingUiPrefab()
	{
		if (!loggedMissingUiPrefab)
		{
			Warning("REPO_ValueRace UI prefab was not available; leaderboard display will wait for the original mod to load it.");
			loggedMissingUiPrefab = true;
		}
	}

	public static void PatchFailure(Exception ex)
	{
		if (loggedPatchFailure)
		{
			Debug("ValueRace GenerateDone guard failed again: " + ex.GetType().Name + ": " + ex.Message);
			return;
		}
		Warning("ValueRace GenerateDone guard handled an unexpected error: " + ex.GetType().Name + ": " + ex.Message);
		loggedPatchFailure = true;
	}
}
internal static class ValueRaceGenerateDoneGuard
{
	private const string PatchTypeName = "REPO_ValueRace.Patch";

	private const string PatchNestedTypeName = "REPO_ValueRace.Patch+LevelGenerator_Patch";

	private const string UiManagerTypeName = "REPO_ValueRace.ValueRaceUIManager";

	private const string PluginTypeName = "REPO_ValueRace.Plugin";

	public static void Apply(Harmony harmony)
	{
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Expected O, but got Unknown
		Type type = AccessTools.TypeByName("REPO_ValueRace.Patch+LevelGenerator_Patch");
		MethodInfo methodInfo = AccessTools.Method(type, "GenerateDone_Postfix", (Type[])null, (Type[])null);
		MethodInfo methodInfo2 = AccessTools.Method(typeof(ValueRaceGenerateDoneGuard), "Prefix", (Type[])null, (Type[])null);
		if (methodInfo == null || methodInfo2 == null)
		{
			ModLog.MissingTarget();
			return;
		}
		harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		ModLog.Info("Patched REPO_ValueRace level generation guard.");
	}

	private static bool Prefix()
	{
		try
		{
			RunSafeGenerateDone();
		}
		catch (Exception ex)
		{
			ModLog.PatchFailure(ex);
		}
		return false;
	}

	private static void RunSafeGenerateDone()
	{
		if (SemiFunc.RunIsLevel())
		{
			SetDateDone(value: false);
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				ResetRoundState();
			}
		}
		else if (SemiFunc.RunIsShop())
		{
			object obj = EnsureUiManager();
			if (obj != null && GetStaticBool("REPO_ValueRace.Patch", "hasRankData"))
			{
				ApplyStoredRankData(obj);
			}
		}
	}

	private static object EnsureUiManager()
	{
		object uiManagerInstance = GetUiManagerInstance();
		if (uiManagerInstance != null)
		{
			return uiManagerInstance;
		}
		Type ownerType = AccessTools.TypeByName("REPO_ValueRace.Plugin");
		object staticField = GetStaticField(ownerType, "instance");
		object instanceField = GetInstanceField(staticField, "mainUI");
		GameObject val = (GameObject)((instanceField is GameObject) ? instanceField : null);
		if ((Object)(object)val == (Object)null)
		{
			ModLog.MissingUiPrefab();
			return null;
		}
		GameObject val2 = Object.Instantiate<GameObject>(val);
		Type type = AccessTools.TypeByName("REPO_ValueRace.ValueRaceUIManager");
		if (type == null)
		{
			return null;
		}
		uiManagerInstance = val2.GetComponent(type) ?? val2.AddComponent(type);
		Object.DontDestroyOnLoad((Object)(object)val2);
		if (GetUiManagerInstance() == null && uiManagerInstance != null)
		{
			SetStaticField(type, "instance", uiManagerInstance);
		}
		ModLog.Debug("Created REPO_ValueRace UI manager safely.");
		return uiManagerInstance;
	}

	private static object GetUiManagerInstance()
	{
		Type ownerType = AccessTools.TypeByName("REPO_ValueRace.ValueRaceUIManager");
		return GetStaticField(ownerType, "instance");
	}

	private static void SetDateDone(bool value)
	{
		object uiManagerInstance = GetUiManagerInstance();
		if (uiManagerInstance != null)
		{
			SetInstanceField(uiManagerInstance, "dateDone", value);
		}
	}

	private static void ResetRoundState()
	{
		Type ownerType = AccessTools.TypeByName("REPO_ValueRace.Patch");
		ClearStaticCollection(ownerType, "playerGained");
		ClearStaticCollection(ownerType, "playerDamaged");
		ClearStaticCollection(ownerType, "playerFinal");
		ClearStaticCollection(ownerType, "extractionPointValueable");
		SetStaticField(ownerType, "hasRankData", false);
		SetStaticField(ownerType, "lastRanks", null);
		SetStaticField(ownerType, "lastNames", null);
		SetStaticField(ownerType, "lastValues", null);
		SetStaticField(ownerType, "lastDamages", null);
		SetStaticField(ownerType, "lastFinals", null);
		ModLog.Debug("Reset REPO_ValueRace round state.");
	}

	private static void ApplyStoredRankData(object manager)
	{
		Type ownerType = AccessTools.TypeByName("REPO_ValueRace.Patch");
		object[] parameters = new object[5]
		{
			GetStaticField(ownerType, "lastRanks"),
			GetStaticField(ownerType, "lastNames"),
			GetStaticField(ownerType, "lastValues"),
			GetStaticField(ownerType, "lastDamages"),
			GetStaticField(ownerType, "lastFinals")
		};
		MethodInfo methodInfo = AccessTools.Method(manager.GetType(), "ApplyRankData", (Type[])null, (Type[])null);
		if (methodInfo != null)
		{
			methodInfo.Invoke(manager, parameters);
		}
		MethodInfo methodInfo2 = AccessTools.Method(manager.GetType(), "ShowUI", (Type[])null, (Type[])null);
		if (methodInfo2 != null)
		{
			methodInfo2.Invoke(manager, new object[1] { 5f });
		}
		ModLog.Debug("Applied stored REPO_ValueRace leaderboard data.");
	}

	private static void ClearStaticCollection(Type ownerType, string fieldName)
	{
		object staticField = GetStaticField(ownerType, fieldName);
		if (staticField == null)
		{
			return;
		}
		if (staticField is IDictionary dictionary)
		{
			dictionary.Clear();
			return;
		}
		MethodInfo methodInfo = AccessTools.Method(staticField.GetType(), "Clear", Type.EmptyTypes, (Type[])null);
		if (methodInfo != null)
		{
			methodInfo.Invoke(staticField, null);
		}
	}

	private static bool GetStaticBool(string typeName, string fieldName)
	{
		object staticField = GetStaticField(AccessTools.TypeByName(typeName), fieldName);
		if (staticField is bool)
		{
			return (bool)staticField;
		}
		return false;
	}

	private static object GetStaticField(Type ownerType, string fieldName)
	{
		FieldInfo fieldInfo = AccessTools.Field(ownerType, fieldName);
		if (!(fieldInfo == null))
		{
			return fieldInfo.GetValue(null);
		}
		return null;
	}

	private static void SetStaticField(Type ownerType, string fieldName, object value)
	{
		FieldInfo fieldInfo = AccessTools.Field(ownerType, fieldName);
		if (fieldInfo != null)
		{
			fieldInfo.SetValue(null, value);
		}
	}

	private static object GetInstanceField(object owner, string fieldName)
	{
		if (owner == null)
		{
			return null;
		}
		FieldInfo fieldInfo = AccessTools.Field(owner.GetType(), fieldName);
		if (!(fieldInfo == null))
		{
			return fieldInfo.GetValue(owner);
		}
		return null;
	}

	private static void SetInstanceField(object owner, string fieldName, object value)
	{
		if (owner != null)
		{
			FieldInfo fieldInfo = AccessTools.Field(owner.GetType(), fieldName);
			if (fieldInfo != null)
			{
				fieldInfo.SetValue(owner, value);
			}
		}
	}
}