Decompiled source of GunCaseFix v1.0.0

NGA.GunCaseFix.dll

Decompiled 4 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FistVR;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyCompany("NGA")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Persistent player progression! Raid, stash loot, and deploy with seemless scene/loadout saving.")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("NGA.GunCaseFix")]
[assembly: AssemblyTitle("BepInEx Plugin Title")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string id = null, string name = null, string version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string id = null, string name = null, string version = null)
		{
		}
	}
}
namespace NGA
{
	[BepInPlugin("NGA.GunCaseFix", "GunCaseFix", "0.1.0")]
	[BepInDependency("nrgill28.Sodalite", "1.4.1")]
	[BepInProcess("h3vr.exe")]
	public class GunCaseFix : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(SaveableGunCase))]
		[HarmonyPatch("OpenCase")]
		private class SaveableGunCaseOpenCaseHook
		{
			private static void Postfix(SaveableGunCase __instance)
			{
				if ((Object)(object)__instance == (Object)null)
				{
					Logger.LogMessage((object)"SaveableGunCase is null!?");
				}
				__instance.m_containedPositions.Clear();
				__instance.m_containedRotations.Clear();
			}
		}

		[HarmonyPatch(typeof(SaveableGunCase))]
		[HarmonyPatch("CloseCase")]
		private class SaveableGunCloseCaseHook
		{
			private static void Postfix(SaveableGunCase __instance)
			{
				if ((Object)(object)__instance == (Object)null)
				{
					Logger.LogMessage((object)"SaveableGunCase is null!?");
				}
			}
		}

		[HarmonyPatch(typeof(VaultSystem))]
		[HarmonyPatch("WriteToVaultFileObject")]
		private class VaultSystemWriteToVaultFileObjectHook
		{
			private static bool Prefix(List<FVRPhysicalObject> objs, VaultFile f, bool savePositionsRelativeToSpawner, bool saveworldPositions, bool encodeAsLoadout, Transform ScanRoot)
			{
				Logger.LogMessage((object)"VaultSystem WriteToVaultFileObject Postfix HOOKED!");
				f.Objects.Clear();
				if (encodeAsLoadout)
				{
					f.QuickbeltLayoutName = ((Object)ManagerSingleton<GM>.Instance.QuickbeltConfigurations[GM.Options.QuickbeltOptions.QuickbeltPreset]).name;
				}
				Dictionary<FVRPhysicalObject, int> dictionary = new Dictionary<FVRPhysicalObject, int>();
				Dictionary<FVRPhysicalObject, int> dictionary2 = new Dictionary<FVRPhysicalObject, int>();
				Dictionary<FVRPhysicalObject, int> dictionary3 = new Dictionary<FVRPhysicalObject, int>();
				Dictionary<FVRPhysicalObject, int> dictionary4 = new Dictionary<FVRPhysicalObject, int>();
				List<FVRPhysicalObject> list = new List<FVRPhysicalObject>();
				for (int i = 0; i < objs.Count; i++)
				{
					List<FVRPhysicalObject> containedObjectsRecursively = objs[i].GetContainedObjectsRecursively();
					list.Add(objs[i]);
					for (int j = 0; j < containedObjectsRecursively.Count; j++)
					{
						if (list.Contains(containedObjectsRecursively[j]))
						{
							list.Remove(containedObjectsRecursively[j]);
						}
						list.Add(containedObjectsRecursively[j]);
					}
				}
				objs = list;
				for (int k = 0; k < objs.Count; k++)
				{
					dictionary.Add(objs[k], k);
					VaultObject val = VaultSystem.SavePhysicalObjectToVaultObject(objs[k], savePositionsRelativeToSpawner, saveworldPositions, dictionary2, dictionary3, dictionary4, k, ScanRoot);
					val.Index = k;
					f.Objects.Add(val);
				}
				for (int l = 0; l < objs.Count; l++)
				{
					List<FVRPhysicalObject> containedObjects = objs[l].GetContainedObjects();
					if (containedObjects.Count > 0)
					{
						Logger.LogMessage((object)("Object of index:" + l + " has " + containedObjects.Count + " children"));
					}
					for (int m = 0; m < containedObjects.Count; m++)
					{
						int num = dictionary[containedObjects[m]];
						Logger.LogMessage((object)("While writing file, Object of index:" + num + " is contained in object of index" + l));
						f.Objects[num].IsContainedIn = l;
					}
				}
				for (int n = 0; n < objs.Count; n++)
				{
					bool flag = false;
					if (dictionary2.ContainsKey(objs[n]))
					{
						f.Objects[n].InSlotOfRootObjectIndex = dictionary2[objs[n]];
						flag = true;
					}
					if (dictionary3.ContainsKey(objs[n]))
					{
						f.Objects[n].InSlotOfElementIndex = dictionary3[objs[n]];
						flag = true;
					}
					if (dictionary4.ContainsKey(objs[n]))
					{
						f.Objects[n].QuickbeltSlotIndex = dictionary4[objs[n]];
						flag = true;
					}
					if (flag)
					{
						Logger.LogMessage((object)(((Object)objs[n]).name + " was encoded on root object index:" + f.Objects[n].InSlotOfRootObjectIndex + " and element index:" + f.Objects[n].InSlotOfElementIndex + " in slot index:" + f.Objects[n].QuickbeltSlotIndex));
					}
				}
				for (int num2 = 0; num2 < objs.Count; num2++)
				{
					if ((Object)(object)objs[num2].QuickbeltSlot != (Object)null && GM.CurrentPlayerBody.IsSlotInternal(objs[num2].QuickbeltSlot))
					{
						int num3 = GM.CurrentPlayerBody.QBSlots_Internal.IndexOf(objs[num2].QuickbeltSlot);
						Logger.LogMessage((object)("Encoding Object:" + f.Objects[num2].Elements[0].ObjectID + " into player internal quickbelt slot: " + num3));
						f.Objects[num2].QuickbeltSlotIndex = num3;
					}
				}
				f.ModsUsed.Clear();
				for (int num4 = 0; num4 < f.Objects.Count; num4++)
				{
					for (int num5 = 0; num5 < f.Objects[num4].Elements.Count; num5++)
					{
						string objectID = f.Objects[num4].Elements[num5].ObjectID;
						FVRObject val2 = IM.OD[objectID];
						string spawnedFromId = val2.SpawnedFromId;
						if (IM.HasSpawnedID(spawnedFromId))
						{
							ItemSpawnerID spawnerID = IM.GetSpawnerID(spawnedFromId);
							string fromMod = spawnerID.FromMod;
							if (fromMod != string.Empty && !f.ModsUsed.Contains(fromMod))
							{
								f.ModsUsed.Add(fromMod);
							}
						}
					}
				}
				Logger.LogMessage((object)"Printing VaultObjects in order after SAVE:");
				foreach (VaultObject @object in f.Objects)
				{
					Logger.LogMessage((object)@object);
				}
				return false;
			}
		}

		[HarmonyPatch(typeof(VaultSystem))]
		[HarmonyPatch("SpawnVaultFileRoutine")]
		private class VaultSystemSpawnVaultFileRoutineHook
		{
			private static bool Prefixfix(IEnumerator __result, VaultFile f, Transform SpawnRelativeTo, bool spawnRelativeTo, bool decodeAsLoadout, bool clearScene, Vector3 spawnOffset, ReturnObjectListDelegate del, bool displayFileLoad)
			{
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				Logger.LogMessage((object)"VaultSystem SpawnVaultFileRoutine Postfix HOOKED!");
				__result = SpawnVaultFileRoutine(f, SpawnRelativeTo, spawnRelativeTo, decodeAsLoadout, clearScene, spawnOffset, del, displayFileLoad);
				return false;
			}

			private static IEnumerator SpawnVaultFileRoutine(VaultFile f, Transform SpawnRelativeTo, bool spawnRelativeTo, bool decodeAsLoadout, bool clearScene, Vector3 spawnOffset, ReturnObjectListDelegate del, bool displayFileLoad)
			{
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				//IL_002d: Unknown result type (might be due to invalid IL or missing references)
				if (displayFileLoad)
				{
					GM.IsAsyncLoading = true;
				}
				Logger.LogMessage((object)("Initiating Spawn Routine for: " + f.Objects.Count + " root objects"));
				if (displayFileLoad)
				{
					GM.CurrentPlayerBody.ShowLoadingBar();
				}
				if (decodeAsLoadout)
				{
					GM.CurrentPlayerBody.WipeQuickbeltContents();
				}
				yield return null;
				if (clearScene)
				{
					VaultSystem.ClearExistingSaveableObjects(true);
				}
				yield return null;
				FVRPhysicalObject[] spawnedObjs = (FVRPhysicalObject[])(object)new FVRPhysicalObject[f.Objects.Count];
				if (decodeAsLoadout)
				{
					string quickbeltLayoutName = f.QuickbeltLayoutName;
					if (GM.CurrentPlayerBody.DoesQuickbeltNameExist(quickbeltLayoutName))
					{
						int num = 0;
						if (GM.CurrentPlayerBody.SetQuickbeltBasedOnStringName(quickbeltLayoutName, ref num))
						{
							GM.Options.QuickbeltOptions.QuickbeltPreset = num;
							GM.Options.SaveToFile();
						}
					}
				}
				Dictionary<VaultElement, FVRPhysicalObject> dicElementToObj = new Dictionary<VaultElement, FVRPhysicalObject>();
				OrderedDictionary dicObjectsContainedInIndex = new OrderedDictionary();
				for (int o = 0; o < f.Objects.Count; o++)
				{
					VaultObject obj = f.Objects[o];
					if (!IM.OD.ContainsKey(obj.Elements[0].ObjectID) || !IM.HasSpawnedID(IM.OD[obj.Elements[0].ObjectID].SpawnedFromId))
					{
						continue;
					}
					for (int e = 0; e < f.Objects[o].Elements.Count; e++)
					{
						if (IM.HasSpawnedID(IM.OD[obj.Elements[e].ObjectID].SpawnedFromId))
						{
							yield return ((AnvilAsset)IM.OD[obj.Elements[e].ObjectID]).GetGameObjectAsync();
						}
					}
				}
				for (int o2 = 0; o2 < f.Objects.Count; o2++)
				{
					VaultObject obj2 = f.Objects[o2];
					if (!IM.OD.ContainsKey(obj2.Elements[0].ObjectID) || !IM.HasSpawnedID(IM.OD[obj2.Elements[0].ObjectID].SpawnedFromId))
					{
						continue;
					}
					GameObject rootObj = null;
					List<GameObject> toDealWith = new List<GameObject>();
					List<int> validIndexes = new List<int>();
					Dictionary<GameObject, VaultElement> dicGO = new Dictionary<GameObject, VaultElement>();
					Dictionary<int, GameObject> dicByIndex = new Dictionary<int, GameObject>();
					Dictionary<GameObject, int> dicByObj = new Dictionary<GameObject, int>();
					List<AnvilCallback<GameObject>> callbackList = new List<AnvilCallback<GameObject>>();
					for (int i = 0; i < obj2.Elements.Count; i++)
					{
						callbackList.Add(((AnvilAsset)IM.OD[obj2.Elements[i].ObjectID]).GetGameObjectAsync());
					}
					yield return callbackList;
					for (int j = 0; j < obj2.Elements.Count; j++)
					{
						GameObject gameObject = Object.Instantiate<GameObject>(callbackList[j].Result);
						if (j == 0)
						{
							rootObj = gameObject;
						}
						FVRPhysicalObject component = gameObject.GetComponent<FVRPhysicalObject>();
						dicGO.Add(gameObject, obj2.Elements[j]);
						dicByIndex.Add(obj2.Elements[j].Index, gameObject);
						dicByObj.Add(gameObject, obj2.Elements[j].Index);
						dicElementToObj.Add(obj2.Elements[j], component);
						component.SetGenericInts(obj2.Elements[j].GenericInts);
						component.SetGenericStrings(obj2.Elements[j].GenericStrings);
						component.SetGenericVector3s(obj2.Elements[j].GenericVector3s);
						component.SetGenericRotations(obj2.Elements[j].GenericRotations);
						component.ConfigureFromFlagDic(obj2.Elements[j].Flags.dictionary);
						if (j == 0)
						{
							validIndexes.Add(j);
						}
						if (obj2.Elements[j].Type == "firearm")
						{
							FVRFireArm myGun = gameObject.GetComponent<FVRFireArm>();
							Vector3 vector = Vector3.zero;
							if ((Object)(object)SpawnRelativeTo != (Object)null)
							{
								vector = SpawnRelativeTo.position;
							}
							gameObject.transform.position = vector;
							gameObject.transform.rotation = Quaternion.identity;
							if ((Object)(object)myGun.Magazine != (Object)null && myGun.Magazine.IsIntegrated)
							{
								myGun.Magazine.ReloadMagWithList(obj2.Elements[j].LoadedRoundsInMag);
							}
							myGun.SetLoadedChambers(obj2.Elements[j].LoadedRoundsInChambers);
						}
						else if (obj2.Elements[j].Type == "magazine")
						{
							toDealWith.Add(gameObject);
							FVRFireArmMagazine component2 = gameObject.GetComponent<FVRFireArmMagazine>();
							component2.ReloadMagWithList(obj2.Elements[j].LoadedRoundsInMag);
						}
						else if (obj2.Elements[j].Type == "attachment")
						{
							toDealWith.Add(gameObject);
						}
						else if ((Object)(object)gameObject.GetComponent<Speedloader>() != (Object)null && obj2.Elements[j].LoadedRoundsInMag.Count > 0)
						{
							Speedloader component3 = gameObject.GetComponent<Speedloader>();
							component3.ReloadSpeedLoaderWithList(obj2.Elements[j].LoadedRoundsInMag);
						}
						else if ((Object)(object)gameObject.GetComponent<FVRFireArmClip>() != (Object)null && obj2.Elements[j].LoadedRoundsInMag.Count > 0)
						{
							FVRFireArmClip component4 = gameObject.GetComponent<FVRFireArmClip>();
							component4.ReloadClipWithList(obj2.Elements[j].LoadedRoundsInMag);
						}
					}
					int BreakIterator = 400;
					while (toDealWith.Count > 0 && BreakIterator > 0)
					{
						BreakIterator--;
						for (int k = toDealWith.Count - 1; k >= 0; k--)
						{
							VaultElement vaultElement = dicGO[toDealWith[k]];
							if (validIndexes.Contains(vaultElement.ObjectAttachedTo))
							{
								GameObject gameObject2 = toDealWith[k];
								if ((Object)(object)gameObject2.GetComponent<FVRFireArmAttachment>() != (Object)null)
								{
									FVRFireArmAttachment component5 = gameObject2.GetComponent<FVRFireArmAttachment>();
									FVRFireArmAttachmentMount mount = VaultSystem.GetMount(dicByIndex[vaultElement.ObjectAttachedTo], vaultElement.MountAttachedTo);
									gameObject2.transform.rotation = Quaternion.LookRotation(vaultElement.OrientationForward, vaultElement.OrientationUp);
									gameObject2.transform.position = VaultSystem.GetPositionRelativeToGun(vaultElement, rootObj.transform);
									if (component5.CanScaleToMount && mount.CanThisRescale())
									{
										component5.ScaleToMount(mount);
									}
									component5.AttachToMount(mount, false);
									if (component5 is Suppressor)
									{
										((Suppressor)((component5 is Suppressor) ? component5 : null)).AutoMountWell();
									}
									validIndexes.Add(vaultElement.Index);
									toDealWith.RemoveAt(k);
								}
								else if ((Object)(object)gameObject2.GetComponent<FVRFireArmMagazine>() != (Object)null)
								{
									FVRFireArmMagazine component6 = gameObject2.GetComponent<FVRFireArmMagazine>();
									GameObject gameObject3 = dicByIndex[vaultElement.ObjectAttachedTo];
									FVRFireArm component7 = gameObject3.GetComponent<FVRFireArm>();
									AttachableFirearmPhysicalObject component8 = gameObject3.GetComponent<AttachableFirearmPhysicalObject>();
									VaultElement vaultElement2 = dicGO[gameObject2];
									if (vaultElement2.MountAttachedTo < 0)
									{
										if ((Object)(object)component7 != (Object)null)
										{
											((Component)component6).transform.position = component7.GetMagMountPos(component6.IsBeltBox).position;
											((Component)component6).transform.rotation = component7.GetMagMountPos(component6.IsBeltBox).rotation;
											component6.Load(component7);
										}
										if ((Object)(object)component8 != (Object)null)
										{
											((Component)component6).transform.position = component8.FA.MagazineMountPos.position;
											((Component)component6).transform.rotation = component8.FA.MagazineMountPos.rotation;
											component6.Load(component8.FA);
										}
									}
									else if ((Object)(object)component7 != (Object)null)
									{
										((Component)component6).transform.position = component7.SecondaryMagazineSlots[vaultElement2.MountAttachedTo].MagazineMountPos.position;
										((Component)component6).transform.rotation = component7.SecondaryMagazineSlots[vaultElement2.MountAttachedTo].MagazineMountPos.rotation;
										component6.LoadIntoSecondary(component7, vaultElement2.MountAttachedTo);
									}
									toDealWith.RemoveAt(k);
								}
							}
						}
					}
					if (spawnRelativeTo)
					{
						rootObj.transform.position = SpawnRelativeTo.TransformPoint(obj2.Elements[0].PosOffset) + spawnOffset;
						rootObj.transform.rotation = Quaternion.LookRotation(SpawnRelativeTo.TransformDirection(obj2.Elements[0].OrientationForward), SpawnRelativeTo.TransformDirection(obj2.Elements[0].OrientationUp));
					}
					else if (decodeAsLoadout)
					{
						rootObj.transform.position = SpawnRelativeTo.position + Vector3.up * 0.3f * (float)o2;
						rootObj.transform.rotation = SpawnRelativeTo.rotation;
					}
					else if (!decodeAsLoadout)
					{
						rootObj.transform.position = obj2.Elements[0].PosOffset;
						rootObj.transform.rotation = Quaternion.LookRotation(obj2.Elements[0].OrientationForward, obj2.Elements[0].OrientationUp);
					}
					if (obj2.IsContainedIn > -1)
					{
						Logger.LogMessage((object)(((Object)rootObj.gameObject).name + " is contained in index " + obj2.IsContainedIn));
						rootObj.SetActive(false);
						dicObjectsContainedInIndex.Add(rootObj, obj2.IsContainedIn);
					}
					spawnedObjs[obj2.Index] = rootObj.GetComponent<FVRPhysicalObject>();
				}
				yield return null;
				for (int l = 0; l < spawnedObjs.Length; l++)
				{
					if (f.Objects[l].QuickbeltSlotIndex != -1)
					{
						if (f.Objects[l].InSlotOfRootObjectIndex == -1 && (Object)(object)spawnedObjs[l].QuickbeltSlot == (Object)null && decodeAsLoadout)
						{
							Logger.LogMessage((object)(((Object)((Component)spawnedObjs[l]).gameObject).name + " is in a player internal quickbelt slot: " + f.Objects[l].QuickbeltSlotIndex));
							spawnedObjs[l].SetQuickBeltSlot(GM.CurrentPlayerBody.QBSlots_Internal[f.Objects[l].QuickbeltSlotIndex]);
						}
						else if ((Object)(object)spawnedObjs[l].QuickbeltSlot == (Object)null)
						{
							VaultElement vaultElement3 = f.Objects[f.Objects[l].InSlotOfRootObjectIndex].Elements[f.Objects[l].InSlotOfElementIndex];
							FVRPhysicalObject fvrphysicalObject = dicElementToObj[vaultElement3];
							FVRQuickBeltSlot fvrquickBeltSlot = fvrphysicalObject.Slots[f.Objects[l].QuickbeltSlotIndex];
							spawnedObjs[l].SetQuickBeltSlot(fvrquickBeltSlot);
						}
					}
				}
				foreach (KeyValuePair<GameObject, int> keyValuePair in dicObjectsContainedInIndex)
				{
					FVRPhysicalObject fvrphysicalObject2 = spawnedObjs[keyValuePair.Value];
					fvrphysicalObject2.ContainOtherObject(keyValuePair.Key.GetComponent<FVRPhysicalObject>());
				}
				if (del != null)
				{
					List<FVRPhysicalObject> list = new List<FVRPhysicalObject>();
					for (int m = 0; m < spawnedObjs.Length; m++)
					{
						list.Add(spawnedObjs[m]);
					}
					Logger.LogMessage((object)("Delegate found in spawn routine with " + spawnedObjs.Length + " possible objects spawned"));
					del.Invoke(list);
				}
				GM.IsAsyncLoading = false;
				GM.CurrentPlayerBody.HideLoadingBar();
			}
		}

		private static ConfigEntry<bool> config_enable_vanilla;

		private static ConfigEntry<bool> config_enable_tnh;

		private static ConfigEntry<bool> config_enable_modded;

		private static ConfigEntry<string> config_exclude_ids;

		private static ConfigEntry<string> config_include_ids;

		internal static ManualLogSource Logger { get; private set; }

		private void Awake()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			Logger = ((BaseUnityPlugin)this).Logger;
			Harmony val = new Harmony("NGA.GunCaseFix");
			Logger.LogMessage((object)"New harmony");
			SetUpConfigFields();
			Logger.LogMessage((object)"Setted the fields");
			val.PatchAll();
			Logger.LogMessage((object)"Hello, world! Sent from NGA.GunCaseFix 0.0.1");
		}

		private void SetUpConfigFields()
		{
		}
	}
}