Decompiled source of BlackBox v1.0.2

BlackBox.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
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 HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using REPOLib.Modules;
using TMPro;
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: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("Autodesk.Fbx")]
[assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")]
[assembly: IgnoresAccessChecksTo("FbxBuildTestAssets")]
[assembly: IgnoresAccessChecksTo("Klattersynth")]
[assembly: IgnoresAccessChecksTo("Photon3Unity3D")]
[assembly: IgnoresAccessChecksTo("PhotonChat")]
[assembly: IgnoresAccessChecksTo("PhotonRealtime")]
[assembly: IgnoresAccessChecksTo("PhotonUnityNetworking")]
[assembly: IgnoresAccessChecksTo("PhotonUnityNetworking.Utilities")]
[assembly: IgnoresAccessChecksTo("PhotonVoice.API")]
[assembly: IgnoresAccessChecksTo("PhotonVoice")]
[assembly: IgnoresAccessChecksTo("PhotonVoice.PUN")]
[assembly: IgnoresAccessChecksTo("SingularityGroup.HotReload.Runtime")]
[assembly: IgnoresAccessChecksTo("SingularityGroup.HotReload.Runtime.Public")]
[assembly: IgnoresAccessChecksTo("Sirenix.OdinInspector.Attributes")]
[assembly: IgnoresAccessChecksTo("Sirenix.Serialization.Config")]
[assembly: IgnoresAccessChecksTo("Sirenix.Serialization")]
[assembly: IgnoresAccessChecksTo("Sirenix.Utilities")]
[assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")]
[assembly: IgnoresAccessChecksTo("Unity.Formats.Fbx.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")]
[assembly: IgnoresAccessChecksTo("Unity.Postprocessing.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")]
[assembly: IgnoresAccessChecksTo("Unity.Timeline")]
[assembly: IgnoresAccessChecksTo("Unity.VisualScripting.Antlr3.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.VisualScripting.Core")]
[assembly: IgnoresAccessChecksTo("Unity.VisualScripting.Flow")]
[assembly: IgnoresAccessChecksTo("Unity.VisualScripting.State")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UI")]
[assembly: IgnoresAccessChecksTo("websocket-sharp")]
[assembly: AssemblyCompany("Roemi")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BlackBox")]
[assembly: AssemblyTitle("BlackBox")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 Blackbox
{
	[BepInPlugin("Roemi.Blackbox", "Blackbox", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Blackbox : BaseUnityPlugin
	{
		internal static class BlackBoxConfig
		{
			public static ConfigEntry<bool>? DisplayRemainingValue { get; private set; }

			public static void Initialize(ConfigFile configFile)
			{
				DisplayRemainingValue = configFile.Bind<bool>("General", "DisplayRemainingValue", true, "Display the current value remaining on the map in the top right of the UI when in the truck.");
			}

			public static bool shouldDisplayRemainingValue()
			{
				if (DisplayRemainingValue == null)
				{
					return false;
				}
				return DisplayRemainingValue.Value;
			}
		}

		public GameObject? itemDmgMonitorShop;

		public GameObject? itemDmgMonitorLevel;

		public MonitorTest? itemDmgMonitorScriptLevel;

		public MonitorTest? itemDmgMonitorScriptShop;

		public ValuableEventTracker valueEventTracker = new ValuableEventTracker();

		public string PostRunStatString = "";

		public string ItemDamageStringShort = "";

		public bool updateShopMonitorFlag = false;

		public Dictionary<string, string> ItemDamageStringDetaied = new Dictionary<string, string>();

		public int currPlayerDisplayed = 0;

		internal static Blackbox Instance { get; private set; }

		internal static ManualLogSource Logger => Instance._logger;

		private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger;

		internal Harmony? Harmony { get; set; }

		private void Awake()
		{
			Instance = this;
			((Component)this).gameObject.transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			AssetBundle val = AssetBundle.LoadFromFile(Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)Instance).Info.Location), "mydamagecanvasbundle"));
			if ((Object)(object)val == (Object)null)
			{
				Logger.LogError((object)("Assetbundle required for " + ((BaseUnityPlugin)this).Info.Metadata.GUID + " not found!"));
				return;
			}
			itemDmgMonitorShop = val.LoadAsset<GameObject>("DamageCanvasMultiplayerShop");
			itemDmgMonitorLevel = val.LoadAsset<GameObject>("DamageCanvasMultiplayer");
			NetworkPrefabs.RegisterNetworkPrefab(itemDmgMonitorLevel);
			NetworkPrefabs.RegisterNetworkPrefab(itemDmgMonitorShop);
			Patch();
			Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!");
		}

		internal void Patch()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_0032: Expected O, but got Unknown
			BlackBoxConfig.Initialize(((BaseUnityPlugin)this).Config);
			if (Harmony == null)
			{
				Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
				Harmony val2 = val;
				Harmony = val;
			}
			Harmony.PatchAll(typeof(PhysGrabObjectImpactDetectorPatch));
			Harmony.PatchAll(typeof(PhysGrabObjectPatch));
			Harmony.PatchAll(typeof(ValuableObjectPatch));
			Harmony.PatchAll(typeof(TruckScreenTextPatch));
			Harmony.PatchAll(typeof(ShopManagerPatch));
			Harmony.PatchAll(typeof(RunManagerPatch));
			Harmony.PatchAll(typeof(SemiFuncPatch));
			Harmony.PatchAll(typeof(HaulUIPatch));
			Harmony.PatchAll(typeof(PlayerHealthPatch));
			Harmony.PatchAll(typeof(HurtColliderPatch));
			Harmony.PatchAll(typeof(EnemyBangPatch));
			Harmony.PatchAll(typeof(EnemyUpscreamAnimPatch));
			Harmony.PatchAll(typeof(FloaterAttackLogicPatch));
			Harmony.PatchAll(typeof(LevelGeneratorPatch));
		}

		internal void Unpatch()
		{
			Harmony? harmony = Harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		public void addBreakEvent(PhysGrabObjectImpactDetector __instance, float valueLost, bool broken = false)
		{
			valueEventTracker.addBreakEvent(__instance, valueLost, broken);
			updateStrings();
		}

		public void updateStrings()
		{
			ItemDamageStringShort = valueEventTracker.getStatsByPlayerValueLost();
			ItemDamageStringDetaied = valueEventTracker.getDetailedStatsByValueLost();
			PostRunStatString = getPostRunStatString();
		}

		public void updateLevelMonitor()
		{
			Instance.updateStrings();
			string text = "DAMAGE DONE TO ITEMS:\n\n" + ItemDamageStringShort;
			MonitorTest? obj = itemDmgMonitorScriptLevel;
			if (obj != null)
			{
				obj.setText(text.ToUpper(), SemiFunc.IsMultiplayer());
			}
		}

		public void updateShopMonitor()
		{
			string postRunStatString = Instance.PostRunStatString;
			string playerSpecificText = Instance.getPlayerSpecificText();
			string text = postRunStatString + playerSpecificText;
			MonitorTest? obj = itemDmgMonitorScriptShop;
			if (obj != null)
			{
				obj.setText(text.ToUpper(), SemiFunc.IsMultiplayer());
			}
			switchPlayerOnMonitor();
		}

		public string getPlayerSpecificText()
		{
			if (Instance.ItemDamageStringDetaied.Count == 0)
			{
				return "";
			}
			if (currPlayerDisplayed >= 0 && currPlayerDisplayed < Instance.ItemDamageStringDetaied.Count)
			{
				KeyValuePair<string, string> keyValuePair = Instance.ItemDamageStringDetaied.ElementAt(currPlayerDisplayed);
				string text = "<b>" + keyValuePair.Key + "</b>:\n";
				return text + keyValuePair.Value;
			}
			return "";
		}

		public void switchPlayerOnMonitor()
		{
			if (Instance.ItemDamageStringDetaied.Count < 2)
			{
				currPlayerDisplayed = 0;
			}
			else
			{
				currPlayerDisplayed = (currPlayerDisplayed + 1) % Instance.ItemDamageStringDetaied.Count;
			}
		}

		public string getPostRunStatString()
		{
			ValuableEventTracker valuableEventTracker = valueEventTracker;
			string text = "<color=#008000>";
			string text2 = "<color=#BA8E23>";
			string text3 = "<color=#FF0000>";
			string text4 = "</color>";
			string text5 = SemiFunc.DollarGetString((int)Math.Round(valuableEventTracker.totalValueExtracted));
			string text6 = SemiFunc.DollarGetString((int)Math.Round(valuableEventTracker.totalValueSpawnedOnMap));
			string text7 = SemiFunc.DollarGetString((int)Math.Round(valuableEventTracker.totalValueLost));
			return $"Extracted {text}${text5}{text4}({valuableEventTracker.totalNumItemsExtracted} item(s)) / {text}${text6}{text4}({valuableEventTracker.totalNumItems} item(s))\n" + $"Lost {text3}${text7}{text4} in value with {text3}{valuableEventTracker.itemsDestroyed}{text4} item(s) destroyed.\n" + $"Discovered {text2}{valuableEventTracker.itemsDiscovered}{text4} out of {text2}{valuableEventTracker.totalNumItems}{text4} item(s).\n";
		}

		public void CompletedExtraction()
		{
			Instance.updateStrings();
			Logger.LogDebug((object)"Completed Extraction, leaving level!");
		}
	}
	public static class BlackboxHelper
	{
		public static string getCleanedValuableObjectName(string name)
		{
			name = name.Replace("Valuable", "");
			name = name.Replace("(Clone)", "");
			if (name.Contains("Enemy"))
			{
				string[] array = name.Split(" - ");
				name = "ORB ";
				if (array.Length != 2)
				{
					return name;
				}
				name += array[1];
			}
			name = name.TrimStart();
			name = name.TrimEnd();
			return name;
		}

		public static string getNameOfEnemey(Enemy enemy)
		{
			string text = "";
			if (enemy.HasRigidbody)
			{
				return enemy.Rigidbody.enemyParent.enemyName;
			}
			if (Object.op_Implicit((Object)(object)enemy.EnemyParent))
			{
				return enemy.EnemyParent.enemyName;
			}
			return ((Object)enemy).name;
		}
	}
	public class ValuableEventTracker
	{
		public class ItemBreakEvent
		{
			public int ItemID;

			public string ItemName;

			public float ValueOriginal;

			public float ValueLost;

			public List<string> PlayerNamesCausedDamage;

			public bool broke;

			public ItemBreakEvent(int _itemID, string _itemName, float _valueOriginal, float _valueLost, List<string> _playerNamesCausedDamage, bool _broke)
			{
				ItemID = _itemID;
				ItemName = _itemName;
				ValueOriginal = _valueOriginal;
				ValueLost = _valueLost;
				PlayerNamesCausedDamage = _playerNamesCausedDamage;
				broke = _broke;
			}
		}

		public class PlayerDamageEvent
		{
			public enum EntityDamagedType
			{
				Enemy,
				Player,
				TumbleHit,
				Unknown
			}

			public string playerDamaged;

			public string damageSourceEntityName;

			public EntityDamagedType entityType;

			public int damageDone;

			public PlayerDamageEvent(string _playerDamaged, string _damageSourceEntityName, EntityDamagedType _entityType, int _damageDone)
			{
				playerDamaged = _playerDamaged;
				damageSourceEntityName = _damageSourceEntityName;
				entityType = _entityType;
				damageDone = _damageDone;
			}
		}

		public List<ItemBreakEvent> itemBreakEvents = new List<ItemBreakEvent>();

		public List<PlayerDamageEvent> playerDamageEvent = new List<PlayerDamageEvent>();

		public Dictionary<PlayerTumble, string> impactHurtTracker = new Dictionary<PlayerTumble, string>();

		public List<ValuableObject> levelItems = new List<ValuableObject>();

		public float totalValueSpawnedOnMap = 0f;

		public float totalValueLeftOnMap = 0f;

		public float totalValueExtracted = 0f;

		public float totalValueLost = 0f;

		public int totalNumItemsExtracted = 0;

		public int totalNumItems = 0;

		public int itemsDiscovered = 0;

		public int itemsDestroyed = 0;

		public void resetRunStats()
		{
			Blackbox.Logger.LogDebug((object)"Resetting stats.");
			itemBreakEvents.Clear();
			impactHurtTracker.Clear();
			playerDamageEvent.Clear();
			levelItems.Clear();
			totalValueSpawnedOnMap = 0f;
			totalValueLeftOnMap = 0f;
			totalValueExtracted = 0f;
			totalNumItemsExtracted = 0;
			totalValueLost = 0f;
			totalNumItems = 0;
			itemsDiscovered = 0;
			itemsDestroyed = 0;
			Blackbox.Instance.PostRunStatString = "";
			Blackbox.Instance.ItemDamageStringShort = "";
			Blackbox.Instance.ItemDamageStringDetaied.Clear();
		}

		public void runLevelComplete()
		{
			Blackbox.Logger.LogDebug((object)"Leaving run level, clearing references to level objects");
			levelItems.Clear();
			impactHurtTracker.Clear();
			totalValueLeftOnMap = 0f;
		}

		public void addBreakEvent(PhysGrabObjectImpactDetector __instance, float valueLost, bool broken)
		{
			List<string> list = new List<string>();
			foreach (PhysGrabber item2 in __instance.physGrabObject.playerGrabbing)
			{
				list.Add(item2.playerAvatar.playerName);
			}
			if (list.Count == 0)
			{
				if (Object.op_Implicit((Object)(object)__instance.physGrabObject.lastPlayerGrabbing))
				{
					list.Add(__instance.physGrabObject.lastPlayerGrabbing.playerName);
				}
				else
				{
					list.Add("Unknown");
				}
			}
			string cleanedValuableObjectName = BlackboxHelper.getCleanedValuableObjectName(((Object)__instance.valuableObject).name);
			ItemBreakEvent item = new ItemBreakEvent(((Object)__instance).GetInstanceID(), BlackboxHelper.getCleanedValuableObjectName(((Object)__instance.valuableObject).name), __instance.valuableObject.dollarValueOriginal, valueLost, list, broken);
			itemBreakEvents.Add(item);
			totalValueLeftOnMap -= valueLost;
			totalValueLost += valueLost;
			Blackbox.Logger.LogDebug((object)(string.Join(" and ", list) + " damaged " + cleanedValuableObjectName + ". It lost $" + (broken ? __instance.valuableObject.dollarValueCurrent : valueLost) + " in value " + (broken ? "and broke." : ".")));
		}

		public void itemExtractedEvent(ValuableObject valueObj)
		{
			totalNumItemsExtracted++;
			totalValueExtracted += valueObj.dollarValueCurrent;
			totalValueLeftOnMap -= valueObj.dollarValueCurrent;
			levelItems.Remove(valueObj);
		}

		public void discoveredObjectEvent(ValuableObject valueObj)
		{
			itemsDiscovered++;
		}

		public void valuableItemDestroyed(ValuableObject destroyedObj)
		{
			levelItems.Remove(destroyedObj);
			itemsDestroyed++;
		}

		public void addValuableObject(ValuableObject item)
		{
			levelItems.Add(item);
			totalNumItems++;
			totalValueLeftOnMap += item.dollarValueCurrent;
			if (!((Object)item).name.Contains("surplus"))
			{
				totalValueSpawnedOnMap += item.dollarValueCurrent;
			}
		}

		public Dictionary<string, string> getDetailedStatsByValueLost()
		{
			Dictionary<string, Dictionary<int, float>> dictionary = new Dictionary<string, Dictionary<int, float>>();
			Dictionary<int, bool> dictionary2 = new Dictionary<int, bool>();
			Dictionary<int, string> dictionary3 = new Dictionary<int, string>();
			Dictionary<string, string> dictionary4 = new Dictionary<string, string>();
			foreach (ItemBreakEvent itemBreakEvent in itemBreakEvents)
			{
				float num = itemBreakEvent.ValueLost / (float)itemBreakEvent.PlayerNamesCausedDamage.Count;
				if (!dictionary3.ContainsKey(itemBreakEvent.ItemID))
				{
					dictionary3[itemBreakEvent.ItemID] = itemBreakEvent.ItemName;
					dictionary2[itemBreakEvent.ItemID] = itemBreakEvent.broke;
				}
				if (!dictionary2[itemBreakEvent.ItemID])
				{
					dictionary2[itemBreakEvent.ItemID] = itemBreakEvent.broke;
				}
				foreach (string item in itemBreakEvent.PlayerNamesCausedDamage)
				{
					if (!dictionary.ContainsKey(item))
					{
						dictionary[item] = new Dictionary<int, float>();
					}
					if (!dictionary[item].ContainsKey(itemBreakEvent.ItemID))
					{
						dictionary[item][itemBreakEvent.ItemID] = 0f;
					}
					dictionary[item][itemBreakEvent.ItemID] += num;
				}
			}
			foreach (KeyValuePair<string, Dictionary<int, float>> item2 in dictionary)
			{
				string text = "";
				int num2 = 0;
				foreach (KeyValuePair<int, float> item3 in item2.Value)
				{
					string text2 = (dictionary2[item3.Key] ? " - <color=#FF0000>DESTROYED</color>" : "");
					string text3 = SemiFunc.DollarGetString((int)Mathf.Round(item3.Value));
					string cleanedValuableObjectName = BlackboxHelper.getCleanedValuableObjectName(dictionary3[item3.Key]);
					text = text + "   " + cleanedValuableObjectName + " <color=#FF0000>-$<u>" + text3 + "</color></u>" + text2 + "\n";
					num2 += (int)Mathf.Round(item3.Value);
				}
				dictionary4[item2.Key] = "Total: <color=#FF0000>-$<u>" + SemiFunc.DollarGetString(num2) + "</color></u>\n<size=0.1>" + text + "</size>";
			}
			return dictionary4;
		}

		public string getStatsByPlayerValueLost()
		{
			Dictionary<string, float> dictionary = new Dictionary<string, float>();
			Dictionary<int, string> dictionary2 = new Dictionary<int, string>();
			foreach (ItemBreakEvent itemBreakEvent in itemBreakEvents)
			{
				float num = itemBreakEvent.ValueLost / (float)itemBreakEvent.PlayerNamesCausedDamage.Count;
				foreach (string item in itemBreakEvent.PlayerNamesCausedDamage)
				{
					if (!dictionary.ContainsKey(item))
					{
						dictionary[item] = num;
					}
					else
					{
						dictionary[item] += num;
					}
				}
			}
			Dictionary<string, float> dictionary3 = dictionary.OrderByDescending((KeyValuePair<string, float> pair) => pair.Value).ToDictionary((KeyValuePair<string, float> pair) => pair.Key, (KeyValuePair<string, float> pair) => pair.Value);
			StringBuilder stringBuilder = new StringBuilder();
			foreach (KeyValuePair<string, float> item2 in dictionary3)
			{
				string text = SemiFunc.DollarGetString((int)Mathf.Round(item2.Value));
				if (item2.Key == "Unknown")
				{
					stringBuilder.AppendLine("Unknown <color=#FF0000>-$<u>" + text + "</color></u>");
				}
				else
				{
					stringBuilder.AppendLine(item2.Key + " <color=#FF0000>-$<u>" + text + "</color></u>");
				}
			}
			return stringBuilder.ToString();
		}

		public void addNewImpactSource(PlayerTumble target, string sourceName)
		{
			impactHurtTracker[target] = sourceName;
		}

		public void addNewPlayerDamageEvent(string _playerDamaged, string _damageSourceEntityName, PlayerDamageEvent.EntityDamagedType _entityType, int _damageDone)
		{
			PlayerDamageEvent item = new PlayerDamageEvent(_playerDamaged, _damageSourceEntityName, _entityType, _damageDone);
			playerDamageEvent.Add(item);
		}

		public string getTargetCausedTumbleDamage(PlayerTumble target)
		{
			if (impactHurtTracker.ContainsKey(target))
			{
				string result = impactHurtTracker[target];
				impactHurtTracker.Remove(target);
				return result;
			}
			return "";
		}
	}
	[HarmonyPatch(typeof(PhysGrabObjectImpactDetector))]
	internal static class PhysGrabObjectImpactDetectorPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("BreakRPC")]
		private static void Start_Prefix(PhysGrabObjectImpactDetector __instance, float valueLost, Vector3 _contactPoint, int breakLevel, bool _loseValue)
		{
			if (SemiFunc.RunIsLevel() && _loseValue && Object.op_Implicit((Object)(object)__instance.valuableObject))
			{
				if (__instance.valuableObject.dollarValueCurrent - valueLost < __instance.valuableObject.dollarValueOriginal * 0.15f)
				{
					Blackbox.Instance.addBreakEvent(__instance, __instance.valuableObject.dollarValueCurrent, broken: true);
				}
				else
				{
					Blackbox.Instance.addBreakEvent(__instance, valueLost);
				}
				if (SemiFunc.IsMasterClientOrSingleplayer())
				{
					Blackbox.Instance.updateLevelMonitor();
				}
			}
		}
	}
	[HarmonyPatch(typeof(PhysGrabObject))]
	internal static class PhysGrabObjectPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("DestroyPhysGrabObjectRPC")]
		private static void DestroyPhysGrabObjectRPC_Prefix(PhysGrabObject __instance)
		{
			if (!SemiFunc.RunIsLevel() || !SemiFunc.IsMasterClientOrSingleplayer())
			{
				return;
			}
			ValuableObject component = ((Component)__instance).GetComponent<ValuableObject>();
			if (!((Object)(object)component == (Object)null))
			{
				if (component.dollarValueCurrent < component.dollarValueOriginal * 0.15f)
				{
					Blackbox.Instance.valueEventTracker.valuableItemDestroyed(component);
					return;
				}
				string cleanedValuableObjectName = BlackboxHelper.getCleanedValuableObjectName(((Object)component).name);
				Blackbox.Logger.LogDebug((object)("Item " + cleanedValuableObjectName + " got extracted"));
				Blackbox.Instance.valueEventTracker.itemExtractedEvent(component);
			}
		}
	}
	[HarmonyPatch(typeof(ValuableObject))]
	internal static class ValuableObjectPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("DollarValueSetLogic")]
		private static void DollarValueSetLogic_Postfix(ValuableObject __instance)
		{
			if (SemiFunc.RunIsLevel())
			{
				string cleanedValuableObjectName = BlackboxHelper.getCleanedValuableObjectName(((Object)__instance).name);
				Blackbox.Instance.valueEventTracker.addValuableObject(__instance);
				Blackbox.Logger.LogDebug((object)$"Valuable item \"{cleanedValuableObjectName}\" spawned, worth ${__instance.dollarValueCurrent}.");
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("DollarValueSetRPC")]
		private static void DollarValueSetRPC_Postfix(ValuableObject __instance)
		{
			if (SemiFunc.RunIsLevel())
			{
				string cleanedValuableObjectName = BlackboxHelper.getCleanedValuableObjectName(((Object)__instance).name);
				Blackbox.Instance.valueEventTracker.addValuableObject(__instance);
				Blackbox.Logger.LogDebug((object)$"Valuable item \"{cleanedValuableObjectName}\" spawned, worth ${__instance.dollarValueCurrent}.");
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("DiscoverRPC")]
		private static void DiscoverRPC_Prefix(ValuableObject __instance)
		{
			string cleanedValuableObjectName = BlackboxHelper.getCleanedValuableObjectName(((Object)__instance).name);
			Blackbox.Instance.valueEventTracker.discoveredObjectEvent(__instance);
			Blackbox.Logger.LogDebug((object)$"Valuable item \"{cleanedValuableObjectName}\" worth ${__instance.dollarValueCurrent} discovered.");
		}
	}
	[HarmonyPatch(typeof(TruckScreenText))]
	internal static class TruckScreenTextPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("GotoNextLevel")]
		private static void GotoNextLevelPrefix(TruckScreenText __instance)
		{
			Blackbox.Instance.CompletedExtraction();
		}
	}
	[HarmonyPatch(typeof(ShopManager))]
	internal static class ShopManagerPatch
	{
		[CompilerGenerated]
		private sealed class <repeating>d__1 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <repeating>d__1(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				//IL_003e: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (SemiFunc.RunIsShop() && Blackbox.Instance.updateShopMonitorFlag)
				{
					Blackbox.Instance.updateShopMonitor();
					<>2__current = (object)new WaitForSeconds(4f);
					<>1__state = 1;
					return true;
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("ShopInitialize")]
		private static void ShopInitialize_Postfix(ShopManager __instance)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//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_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			if (!SemiFunc.RunIsShop() || (Object)(object)Blackbox.Instance.itemDmgMonitorShop == (Object)null || !SemiFunc.IsMasterClientOrSingleplayer())
			{
				return;
			}
			Vector3 position = Blackbox.Instance.itemDmgMonitorShop.transform.position;
			Quaternion rotation = Blackbox.Instance.itemDmgMonitorShop.transform.rotation;
			GameObject val = (GameManager.Multiplayer() ? PhotonNetwork.Instantiate(((Object)Blackbox.Instance.itemDmgMonitorShop).name, position, rotation, (byte)0, (object[])null) : Object.Instantiate<GameObject>(Blackbox.Instance.itemDmgMonitorShop));
			if ((Object)(object)val == (Object)null)
			{
				Blackbox.Logger.LogError((object)"Unable to instantiate Loss Monitor!");
				return;
			}
			Blackbox.Instance.itemDmgMonitorScriptShop = val.GetComponent<MonitorTest>();
			Blackbox.Instance.currPlayerDisplayed = 0;
			Blackbox.Instance.updateShopMonitor();
			if (SemiFunc.IsMultiplayer())
			{
				Blackbox.Instance.updateShopMonitorFlag = true;
				((MonoBehaviour)__instance).StartCoroutine(repeating());
			}
		}

		[IteratorStateMachine(typeof(<repeating>d__1))]
		private static IEnumerator repeating()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <repeating>d__1(0);
		}
	}
	[HarmonyPatch(typeof(RunManager))]
	internal static class RunManagerPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("LeaveToMainMenu")]
		private static void LeaveToMainMenu_Postfix(ShopManager __instance)
		{
			Blackbox.Instance.valueEventTracker.resetRunStats();
			Blackbox.Instance.updateShopMonitorFlag = false;
		}

		[HarmonyPostfix]
		[HarmonyPatch("UpdateLevel")]
		private static void UpdateLevel_Postfix(RunManager __instance)
		{
			if ((Object)(object)__instance.levelCurrent == (Object)(object)__instance.levelShop)
			{
				Blackbox.Instance.valueEventTracker.runLevelComplete();
				return;
			}
			foreach (Level level in __instance.levels)
			{
				if (((Object)level).name == ((Object)__instance.levelCurrent).name)
				{
					Blackbox.Instance.valueEventTracker.resetRunStats();
					Blackbox.Instance.updateShopMonitorFlag = false;
					break;
				}
			}
		}
	}
	[HarmonyPatch(typeof(SemiFunc))]
	internal static class SemiFuncPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("StatSetSaveLevel")]
		private static void StatSetSaveLevel_Prefix()
		{
			if ((Object)(object)RunManager.instance == (Object)null)
			{
				return;
			}
			if ((Object)(object)RunManager.instance.levelCurrent == (Object)(object)RunManager.instance.levelShop)
			{
				Blackbox.Instance.valueEventTracker.runLevelComplete();
				return;
			}
			foreach (Level level in RunManager.instance.levels)
			{
				if (((Object)level).name == ((Object)RunManager.instance.levelCurrent).name)
				{
					Blackbox.Instance.valueEventTracker.resetRunStats();
					Blackbox.Instance.updateShopMonitorFlag = false;
					break;
				}
			}
		}
	}
	[HarmonyPatch(typeof(LevelGenerator))]
	internal static class LevelGeneratorPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("GenerateDone")]
		private static void GenerateDone_Postfix(LevelGenerator __instance)
		{
			//IL_0052: 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_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: 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_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			if (!SemiFunc.RunIsLevel() || (Object)(object)Blackbox.Instance.itemDmgMonitorLevel == (Object)null || !SemiFunc.IsMasterClientOrSingleplayer())
			{
				return;
			}
			Vector3 val = Blackbox.Instance.itemDmgMonitorLevel.transform.position;
			Quaternion val2 = Blackbox.Instance.itemDmgMonitorLevel.transform.rotation;
			GameObject val3 = GameObject.Find("cctv");
			if ((Object)(object)val3 == (Object)null)
			{
				Blackbox.Logger.LogWarning((object)"Couldnt find CCTV object, Monitor most likely in the wrong spot now.");
			}
			else
			{
				val += val3.transform.position;
				val2 *= val3.transform.rotation;
			}
			GameObject val4 = (GameManager.Multiplayer() ? PhotonNetwork.Instantiate(((Object)Blackbox.Instance.itemDmgMonitorLevel).name, val, val2, (byte)0, (object[])null) : Object.Instantiate<GameObject>(Blackbox.Instance.itemDmgMonitorLevel, val, val2));
			if ((Object)(object)val4 == (Object)null)
			{
				Blackbox.Logger.LogError((object)"Unable to instantiate Loss Monitor!");
				return;
			}
			Blackbox.Instance.itemDmgMonitorScriptLevel = val4.GetComponent<MonitorTest>();
			MonitorTest? itemDmgMonitorScriptLevel = Blackbox.Instance.itemDmgMonitorScriptLevel;
			if (itemDmgMonitorScriptLevel != null)
			{
				itemDmgMonitorScriptLevel.setText("DAMAGE DONE TO ITEMS:\n\n", SemiFunc.IsMultiplayer());
			}
		}
	}
	[HarmonyPatch(typeof(HaulUI))]
	internal static class HaulUIPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("Update")]
		private static void Update_Postfix(HaulUI __instance)
		{
			if (Blackbox.BlackBoxConfig.shouldDisplayRemainingValue() && SemiFunc.RunIsLevel() && RoundDirector.instance.extractionPointActive && PlayerAvatar.instance.RoomVolumeCheck.inTruck)
			{
				string text = "<color=#558B2F>$</color>";
				int num = (int)Mathf.Round(Blackbox.Instance.valueEventTracker.totalValueLeftOnMap);
				TextMeshProUGUI text2 = __instance.Text;
				((TMP_Text)text2).text = ((TMP_Text)text2).text + "</u> <size=45>//</size> </color>" + text + "<u>" + SemiFunc.DollarGetString(num) + " left";
			}
		}
	}
	[HarmonyPatch(typeof(PlayerHealth))]
	internal static class PlayerHealthPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("Hurt")]
		private static void Hurt_Prefix(PlayerHealth __instance, int damage, bool savingGrace, int enemyIndex)
		{
			if (__instance.invincibleTimer > 0f || damage <= 0 || (GameManager.Multiplayer() && !__instance.photonView.IsMine) || __instance.playerAvatar.deadSet || __instance.godMode)
			{
				return;
			}
			string playerName = __instance.playerAvatar.playerName;
			Enemy val = SemiFunc.EnemyGetFromIndex(enemyIndex);
			if (Object.op_Implicit((Object)(object)val))
			{
				string nameOfEnemey = BlackboxHelper.getNameOfEnemey(val);
				Blackbox.Instance.valueEventTracker.addNewPlayerDamageEvent(playerName, nameOfEnemey, ValuableEventTracker.PlayerDamageEvent.EntityDamagedType.Enemy, damage);
				return;
			}
			string targetCausedTumbleDamage = Blackbox.Instance.valueEventTracker.getTargetCausedTumbleDamage(__instance.playerAvatar.tumble);
			if (targetCausedTumbleDamage != "")
			{
				Blackbox.Instance.valueEventTracker.addNewPlayerDamageEvent(playerName, targetCausedTumbleDamage, ValuableEventTracker.PlayerDamageEvent.EntityDamagedType.Enemy, damage);
			}
			else if (savingGrace && damage == 5)
			{
				Blackbox.Instance.valueEventTracker.addNewPlayerDamageEvent(playerName, "Unknown", ValuableEventTracker.PlayerDamageEvent.EntityDamagedType.TumbleHit, damage);
			}
		}
	}
	[HarmonyPatch(typeof(HurtCollider))]
	internal static class HurtColliderPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("PlayerHurt")]
		private static void PlayerHurt_Prefix(HurtCollider __instance, PlayerAvatar _player)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			if ((!GameManager.Multiplayer() || _player.photonView.IsMine) && !((Object)(object)__instance.enemyHost == (Object)null) && !__instance.playerKill && CanHitOnlyInfo(__instance, ((Component)_player).gameObject, -1f, __instance.playerRayCast, _player.PlayerVisionTarget.VisionTransform.position, (HitType)0) && __instance.playerTumbleTime > 0f)
			{
				string nameOfEnemey = BlackboxHelper.getNameOfEnemey(__instance.enemyHost);
				Blackbox.Instance.valueEventTracker.addNewImpactSource(_player.tumble, nameOfEnemey);
			}
		}

		private static bool CanHitOnlyInfo(HurtCollider __instance, GameObject hitObject, float cooldown, bool raycast, Vector3 hitPosition, HitType hitType)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: 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)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: 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_00d4: Unknown result type (might be due to invalid IL or missing references)
			foreach (Hit hit in __instance.hits)
			{
				if ((Object)(object)hit.hitObject == (Object)(object)hitObject)
				{
					return false;
				}
			}
			if (raycast)
			{
				Bounds bounds = __instance.Collider.bounds;
				Vector3 val = hitPosition - ((Bounds)(ref bounds)).center;
				Vector3 normalized = ((Vector3)(ref val)).normalized;
				bounds = __instance.Collider.bounds;
				float num = Vector3.Distance(hitPosition, ((Bounds)(ref bounds)).center);
				bounds = __instance.Collider.bounds;
				RaycastHit[] array = Physics.RaycastAll(((Bounds)(ref bounds)).center, normalized, num, LayerMask.op_Implicit(__instance.RayMask), (QueryTriggerInteraction)2);
				for (int i = 0; i < array.Length; i++)
				{
					RaycastHit val2 = array[i];
					if (((Component)((RaycastHit)(ref val2)).collider).gameObject.CompareTag("Wall"))
					{
						PhysGrabObject componentInParent = hitObject.GetComponentInParent<PhysGrabObject>();
						PhysGrabObject componentInParent2 = ((Component)((RaycastHit)(ref val2)).collider).gameObject.GetComponentInParent<PhysGrabObject>();
						if (!Object.op_Implicit((Object)(object)componentInParent) || (Object)(object)componentInParent != (Object)(object)componentInParent2)
						{
							return false;
						}
					}
				}
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(EnemyBang))]
	internal static class EnemyBangPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("OnDeath")]
		private static void OnDeath_Postfix(EnemyBang __instance)
		{
			if (Object.op_Implicit((Object)(object)__instance.explosionScript))
			{
				__instance.explosionScript.HurtCollider.enemyHost = __instance.enemy;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("ExplodeRPC")]
		private static void ExplodeRPC_Postfix(EnemyBang __instance)
		{
			if (Object.op_Implicit((Object)(object)__instance.explosionScript))
			{
				__instance.explosionScript.HurtCollider.enemyHost = __instance.enemy;
			}
		}
	}
	[HarmonyPatch(typeof(EnemyUpscreamAnim))]
	internal static class EnemyUpscreamAnimPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("AttackImpulse")]
		private static void AttackImpulse_Prefix(EnemyUpscreamAnim __instance)
		{
			if ((!SemiFunc.IsMultiplayer() || SemiFunc.IsMasterClient()) && Object.op_Implicit((Object)(object)__instance.controller.targetPlayer))
			{
				string nameOfEnemey = BlackboxHelper.getNameOfEnemey(__instance.enemy);
				Blackbox.Instance.valueEventTracker.addNewImpactSource(__instance.controller.targetPlayer.tumble, nameOfEnemey);
			}
		}
	}
	[HarmonyPatch(typeof(FloaterAttackLogic))]
	internal static class FloaterAttackLogicPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("StateSmash")]
		private static void StateSmash_Prefix(FloaterAttackLogic __instance)
		{
			if (!__instance.stateStart || !SemiFunc.IsMasterClientOrSingleplayer())
			{
				return;
			}
			foreach (PlayerAvatar capturedPlayerAvatar in __instance.capturedPlayerAvatars)
			{
				if (Object.op_Implicit((Object)(object)capturedPlayerAvatar) && capturedPlayerAvatar.tumble.isTumbling)
				{
					string nameOfEnemey = BlackboxHelper.getNameOfEnemey(__instance.controller.enemy);
					Blackbox.Instance.valueEventTracker.addNewImpactSource(__instance.controller.targetPlayer.tumble, nameOfEnemey);
				}
			}
		}
	}
}

MonitorTest.dll

Decompiled 3 days ago
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using Photon.Pun;
using TMPro;
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("MonitorTest")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("MonitorTest")]
[assembly: AssemblyTitle("MonitorTest")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Blackbox;

public class MonitorTest : MonoBehaviour
{
	public TextMeshProUGUI textObj;

	public void Start()
	{
		textObj = ((Component)this).GetComponentInChildren<TextMeshProUGUI>();
		PhotonView component = ((Component)this).GetComponent<PhotonView>();
	}

	[PunRPC]
	public void setTextRPC(string text)
	{
		((TMP_Text)textObj).text = text;
	}

	public void setText(string text, bool multiplayer = true)
	{
		if (!multiplayer)
		{
			setTextRPC(text);
			return;
		}
		PhotonView component = ((Component)this).GetComponent<PhotonView>();
		component.RPC("setTextRPC", (RpcTarget)0, new object[1] { text });
	}
}