Decompiled source of FriendScrapStatues v1.0.5

FriendScrapStatues.dll

Decompiled 3 weeks ago
using System;
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.Cryptography;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using LethalLib.Modules;
using Microsoft.CodeAnalysis;
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("FriendScrapStatues")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+9f7cf52b5b2a1d26ef731d2280a3b36f642606d6")]
[assembly: AssemblyProduct("FriendScrapStatues")]
[assembly: AssemblyTitle("FriendScrapStatues")]
[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.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]
	[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]
	[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 FriendScrapStatues
{
	[HarmonyPatch(typeof(GrabbableObject), "LateUpdate")]
	internal static class HoldUprightPatch
	{
		private static void Postfix(GrabbableObject __instance)
		{
			//IL_0071: 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_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			if (__instance.isHeld && !((Object)(object)__instance.parentObject == (Object)null) && !((Object)(object)__instance.playerHeldBy == (Object)null))
			{
				ScrapDefinition scrapDefinition = ScrapDefinition.All.FirstOrDefault((ScrapDefinition d) => d.HoldUpright && (Object)(object)d.Item == (Object)(object)__instance.itemProperties);
				if (scrapDefinition != null)
				{
					Quaternion rotation = ((Component)__instance.playerHeldBy.gameplayCamera).transform.rotation;
					((Component)__instance).transform.rotation = rotation * Quaternion.Euler(0f, scrapDefinition.HeldYaw, 0f);
				}
			}
		}
	}
	internal static class ItemFactory
	{
		[HarmonyPatch(typeof(GameNetworkManager), "Start")]
		private static class GameNetworkManagerStartPatch
		{
			private static void Postfix()
			{
				CreateAll();
			}
		}

		private const string TemplateItemName = "Big bolt";

		private const float GameFloorLift = 0.04f;

		private static GameObject? _templateHolder;

		private static void CreateAll()
		{
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			if ((Object)(object)_templateHolder != (Object)null)
			{
				return;
			}
			NetworkManager singleton = NetworkManager.Singleton;
			GrabbableObject val = singleton.NetworkConfig.Prefabs.Prefabs.Select((NetworkPrefab p) => (!((Object)(object)p.Prefab != (Object)null)) ? null : p.Prefab.GetComponent<GrabbableObject>()).FirstOrDefault((Func<GrabbableObject, bool>)((GrabbableObject g) => (Object)(object)g != (Object)null && (Object)(object)g.itemProperties != (Object)null && g.itemProperties.itemName == "Big bolt"));
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogError((object)"Could not find the vanilla 'Big bolt' to copy. No scrap was added.");
				return;
			}
			_templateHolder = new GameObject("FriendScrapStatues_Templates");
			_templateHolder.SetActive(false);
			((Object)_templateHolder).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)_templateHolder);
			ScrapDefinition[] all = ScrapDefinition.All;
			foreach (ScrapDefinition scrapDefinition in all)
			{
				try
				{
					Item val2 = Build(scrapDefinition, val);
					singleton.AddNetworkPrefab(val2.spawnPrefab);
					Items.RegisterScrap(val2, 1, (LevelTypes)(-1));
					scrapDefinition.Item = val2;
					Plugin.Log.LogInfo((object)("Added scrap '" + scrapDefinition.Name + "'."));
				}
				catch (Exception arg)
				{
					Plugin.Log.LogError((object)$"Failed to build '{scrapDefinition.Name}': {arg}");
				}
			}
		}

		private static Item Build(ScrapDefinition def, GrabbableObject template)
		{
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: 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)
			//IL_012c: Expected O, but got Unknown
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0259: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0282: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0388: Unknown result type (might be due to invalid IL or missing references)
			//IL_038d: Unknown result type (might be due to invalid IL or missing references)
			//IL_039b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0305: Unknown result type (might be due to invalid IL or missing references)
			//IL_030a: Unknown result type (might be due to invalid IL or missing references)
			//IL_043a: Unknown result type (might be due to invalid IL or missing references)
			AssetBundle bundle = Plugin.Bundle;
			MeshFilter componentInChildren = (bundle.LoadAsset<GameObject>(def.AssetName) ?? throw new Exception("model '" + def.AssetName + "' is not in the asset bundle")).GetComponentInChildren<MeshFilter>();
			Mesh val = ((componentInChildren != null) ? componentInChildren.sharedMesh : null) ?? throw new Exception("model '" + def.AssetName + "' has no mesh");
			Texture2D val2 = bundle.LoadAsset<Texture2D>(def.TextureName) ?? throw new Exception("texture '" + def.TextureName + "' is not in the asset bundle");
			GameObject val3 = Object.Instantiate<GameObject>(((Component)template).gameObject, _templateHolder.transform);
			((Object)val3).name = def.AssetName;
			val3.transform.localScale = Vector3.one;
			byte[] value = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes("theOhmbrewer.FriendScrapStatues" + def.AssetName));
			AccessTools.Field(typeof(NetworkObject), "GlobalObjectIdHash").SetValue(val3.GetComponent<NetworkObject>(), BitConverter.ToUInt32(value, 0));
			Material val4 = new Material(((Renderer)val3.GetComponentInChildren<MeshRenderer>()).sharedMaterial)
			{
				name = def.AssetName
			};
			val4.SetColor("_BaseColor", Color.white);
			val4.SetTexture("_BaseColorMap", (Texture)(object)val2);
			val4.mainTexture = (Texture)(object)val2;
			val4.SetFloat("_Metallic", 0f);
			val4.SetFloat("_Smoothness", 0.2f);
			val4.SetTexture("_NormalMap", (Texture)null);
			val4.SetTexture("_MaskMap", (Texture)null);
			val4.DisableKeyword("_NORMALMAP");
			val4.DisableKeyword("_MASKMAP");
			LODGroup[] componentsInChildren = val3.GetComponentsInChildren<LODGroup>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
			MeshRenderer[] componentsInChildren2 = val3.GetComponentsInChildren<MeshRenderer>(true);
			foreach (MeshRenderer obj in componentsInChildren2)
			{
				MeshFilter component = ((Component)obj).GetComponent<MeshFilter>();
				Object.DestroyImmediate((Object)(object)obj);
				if ((Object)(object)component != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)component);
				}
			}
			Bounds bounds = val.bounds;
			float num = def.SizeMeters / Mathf.Max(new float[3]
			{
				((Bounds)(ref bounds)).size.x,
				((Bounds)(ref bounds)).size.y,
				((Bounds)(ref bounds)).size.z
			});
			GameObject val5 = new GameObject("Model")
			{
				layer = val3.layer
			};
			val5.transform.SetParent(val3.transform, false);
			val5.transform.localScale = Vector3.one * num;
			val5.transform.localPosition = -((Bounds)(ref bounds)).center * num;
			val5.AddComponent<MeshFilter>().sharedMesh = val;
			MeshRenderer val6 = val5.AddComponent<MeshRenderer>();
			((Renderer)val6).sharedMaterial = val4;
			BoxCollider component2 = val3.GetComponent<BoxCollider>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.center = Vector3.zero;
				component2.size = Vector3.Max(((Bounds)(ref bounds)).size * num, Vector3.one * 0.1f);
			}
			Item val7 = Object.Instantiate<Item>(template.itemProperties);
			((Object)val7).name = def.AssetName;
			val7.itemName = def.Name;
			val7.spawnPrefab = val3;
			val7.isScrap = true;
			val7.twoHanded = false;
			val7.isConductiveMetal = def.Conductive;
			val7.weight = 1f + def.Pounds / 105f;
			SpawnOddsPatch.SetValueRange(def, val7, 0.4f);
			val7.restingRotation = Vector3.zero;
			val7.verticalOffset = Mathf.Max(0f, ((Bounds)(ref bounds)).size.y * num / 2f - 0.04f);
			AudioClip val8 = LoadSound(def.GrabSound);
			if ((Object)(object)val8 != (Object)null)
			{
				val7.grabSFX = val8;
			}
			AudioClip val9 = LoadSound(def.DropSound);
			if ((Object)(object)val9 != (Object)null)
			{
				val7.dropSFX = val9;
			}
			GrabbableObject component3 = val3.GetComponent<GrabbableObject>();
			component3.itemProperties = val7;
			component3.mainObjectRenderer = val6;
			ScanNodeProperties componentInChildren2 = val3.GetComponentInChildren<ScanNodeProperties>(true);
			if ((Object)(object)componentInChildren2 != (Object)null)
			{
				componentInChildren2.headerText = def.Name;
				((Component)componentInChildren2).transform.localPosition = Vector3.zero;
			}
			return val7;
		}

		private static AudioClip? LoadSound(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return null;
			}
			AudioClip obj = Plugin.Bundle.LoadAsset<AudioClip>(name);
			if ((Object)(object)obj == (Object)null)
			{
				Plugin.Log.LogWarning((object)("Sound '" + name + "' is not in the asset bundle; using the default."));
			}
			return obj;
		}
	}
	[BepInPlugin("theOhmbrewer.FriendScrapStatues", "FriendScrapStatues", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		private const string BundleFileName = "friendscrapstatues";

		internal static ManualLogSource Log;

		internal static AssetBundle Bundle;

		private void Awake()
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			string text = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "friendscrapstatues");
			Bundle = AssetBundle.LoadFromFile(text);
			if ((Object)(object)Bundle == (Object)null)
			{
				Log.LogError((object)("Could not load asset bundle at " + text + ". The mod will not add any scrap."));
				return;
			}
			new Harmony("theOhmbrewer.FriendScrapStatues").PatchAll();
			Log.LogInfo((object)"FriendScrapStatues 1.0.0 loaded.");
		}
	}
	internal class ScrapDefinition
	{
		internal static readonly ScrapDefinition[] All = new ScrapDefinition[2]
		{
			new ScrapDefinition
			{
				Name = "Dez Statue",
				AssetName = "dezstatue",
				TextureName = "dezstatuetexture",
				MinCredits = 150,
				MaxCredits = 210,
				Pounds = 5f,
				AverageDaysBetween = 6.6666665f,
				Conductive = false,
				SizeMeters = 0.6f,
				HoldUpright = true
			},
			new ScrapDefinition
			{
				Name = "Nano Orb",
				AssetName = "nanoorb",
				TextureName = "nanoorbtexture",
				MinCredits = 160,
				MaxCredits = 220,
				Pounds = 7f,
				AverageDaysBetween = 20f,
				Conductive = true,
				SizeMeters = 0.35f
			}
		};

		public string Name = "";

		public string AssetName = "";

		public string TextureName = "";

		public string GrabSound = "";

		public string DropSound = "";

		public int MinCredits;

		public int MaxCredits;

		public float Pounds;

		public float AverageDaysBetween;

		public bool Conductive;

		public float SizeMeters;

		public bool HoldUpright;

		public float HeldYaw = 180f;

		public Item? Item;
	}
	[HarmonyPatch(typeof(RoundManager), "SpawnScrapInLevel")]
	internal static class SpawnOddsPatch
	{
		private const int Precision = 100;

		private static readonly Dictionary<SpawnableItemWithRarity, int> OriginalRarities = new Dictionary<SpawnableItemWithRarity, int>();

		private static void Prefix(RoundManager __instance)
		{
			RestoreRarities();
			SelectableLevel currentLevel = __instance.currentLevel;
			if ((Object)(object)currentLevel == (Object)null)
			{
				return;
			}
			List<(SpawnableItemWithRarity entry, ScrapDefinition def)> ours = (from entry in currentLevel.spawnableScrap
				select (entry: entry, def: ScrapDefinition.All.FirstOrDefault((ScrapDefinition d) => (Object)(object)d.Item != (Object)null && (Object)(object)d.Item == (Object)(object)entry.spawnableItem)) into x
				where x.def != null
				select x).ToList();
			if (ours.Count == 0)
			{
				return;
			}
			float usualScrapCount = (float)(currentLevel.minScrap + currentLevel.maxScrap - 1) / 2f * __instance.scrapAmountMultiplier;
			int num = currentLevel.spawnableScrap.Where((SpawnableItemWithRarity e) => ours.All(((SpawnableItemWithRarity entry, ScrapDefinition def) o) => o.entry != e)).Sum((SpawnableItemWithRarity e) => e.rarity) * 100;
			if (usualScrapCount <= 0f || num <= 0)
			{
				return;
			}
			Dictionary<SpawnableItemWithRarity, float> dictionary = ours.ToDictionary(((SpawnableItemWithRarity entry, ScrapDefinition def) o) => o.entry, ((SpawnableItemWithRarity entry, ScrapDefinition def) o) => 1f / (o.def.AverageDaysBetween * usualScrapCount));
			float num2 = dictionary.Values.Sum();
			if (num2 >= 1f)
			{
				return;
			}
			foreach (SpawnableItemWithRarity item5 in currentLevel.spawnableScrap)
			{
				OriginalRarities[item5] = item5.rarity;
				item5.rarity *= 100;
			}
			float num3 = (float)num / (1f - num2);
			foreach (var item6 in ours)
			{
				SpawnableItemWithRarity item = item6.entry;
				ScrapDefinition item2 = item6.def;
				item.rarity = Mathf.Max(1, Mathf.RoundToInt(dictionary[item] * num3));
				SetValueRange(item2, item2.Item, __instance.scrapValueMultiplier);
			}
			int num4 = num + ours.Sum(((SpawnableItemWithRarity entry, ScrapDefinition def) o) => o.entry.rarity);
			foreach (var item7 in ours)
			{
				SpawnableItemWithRarity item3 = item7.entry;
				ScrapDefinition item4 = item7.def;
				float num5 = (float)item3.rarity / (float)num4;
				Plugin.Log.LogInfo((object)($"{currentLevel.PlanetName}: {item4.Name} {100f * num5:0.000}% per scrap, ~{usualScrapCount:0.#} scrap/day " + $"= one every {1f / (num5 * usualScrapCount):0.0} days (target {item4.AverageDaysBetween:0.0})."));
			}
		}

		private static void Postfix()
		{
			RestoreRarities();
		}

		private static void RestoreRarities()
		{
			foreach (KeyValuePair<SpawnableItemWithRarity, int> originalRarity in OriginalRarities)
			{
				originalRarity.Key.rarity = originalRarity.Value;
			}
			OriginalRarities.Clear();
		}

		internal static void SetValueRange(ScrapDefinition def, Item item, float multiplier)
		{
			if (!(multiplier <= 0f))
			{
				item.minValue = Mathf.CeilToInt((float)def.MinCredits / multiplier);
				item.maxValue = Mathf.FloorToInt((float)def.MaxCredits / multiplier) + 1;
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "theOhmbrewer.FriendScrapStatues";

		public const string PLUGIN_NAME = "FriendScrapStatues";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}