Decompiled source of LoquatScrapPack v0.3.4

BepInEx\plugins\LoquatScrapPack\LoquatScrapPack.dll

Decompiled 7 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using LethalLib.Modules;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("LethalLib")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("LoquatScrapPack")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.3.4.0")]
[assembly: AssemblyInformationalVersion("0.3.4")]
[assembly: AssemblyProduct("LoquatScrapPack")]
[assembly: AssemblyTitle("LoquatScrapPack")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.3.4.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[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 LoquatScrapPack
{
	internal sealed class BalbalGlowMarker : MonoBehaviour
	{
		private MeshRenderer targetRenderer;

		private Material runtimeMaterial;

		private Light pointLight;

		private int pulseVersion;

		private Color baseColor = Color.white;

		private static readonly Color GlowColor = new Color(0.23f, 0.64f, 1f, 1f);

		private void Awake()
		{
			try
			{
				InitializeVisuals();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogDebug((object)("Balbal glow setup was disabled: " + ex.GetBaseException().Message));
				((Behaviour)this).enabled = false;
			}
		}

		private void InitializeVisuals()
		{
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Expected O, but got Unknown
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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_008c: Expected O, but got Unknown
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			Transform val = ((Component)this).transform.Find("FGS_Visual");
			targetRenderer = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<MeshRenderer>() : ((Component)this).GetComponentInChildren<MeshRenderer>(true));
			if ((Object)(object)targetRenderer != (Object)null && (Object)(object)((Renderer)targetRenderer).sharedMaterial != (Object)null)
			{
				runtimeMaterial = new Material(((Renderer)targetRenderer).sharedMaterial)
				{
					name = ((Object)((Renderer)targetRenderer).sharedMaterial).name + "_BalbalRuntime"
				};
				((Renderer)targetRenderer).sharedMaterial = runtimeMaterial;
				if (runtimeMaterial.HasProperty("_BaseColor"))
				{
					baseColor = runtimeMaterial.GetColor("_BaseColor");
				}
				else if (runtimeMaterial.HasProperty("_Color"))
				{
					baseColor = runtimeMaterial.GetColor("_Color");
				}
			}
			Transform val2 = ((Component)this).transform.Find("FGS_BalbalGlowLight");
			if ((Object)(object)val2 != (Object)null)
			{
				GameObject gameObject = ((Component)val2).gameObject;
				pointLight = gameObject.GetComponent<Light>() ?? gameObject.AddComponent<Light>();
			}
			else
			{
				GameObject gameObject = new GameObject("FGS_BalbalGlowLight");
				gameObject.transform.SetParent(((Component)this).transform, false);
				gameObject.transform.localPosition = new Vector3(0f, 0.5f, 0f);
				pointLight = gameObject.AddComponent<Light>();
			}
			pointLight.type = (LightType)2;
			pointLight.color = GlowColor;
			pointLight.range = 1.8f;
			pointLight.intensity = 8f;
			pointLight.shadows = (LightShadows)0;
			((Behaviour)pointLight).enabled = false;
			SetGlow(enabled: false);
		}

		internal void Pulse(float seconds)
		{
			pulseVersion++;
			int version = pulseVersion;
			((MonoBehaviour)this).StopAllCoroutines();
			((MonoBehaviour)this).StartCoroutine(PulseRoutine(Mathf.Max(0.25f, seconds), version));
		}

		internal void PulseForCurrentPlayback(float fallbackSeconds = 4f)
		{
			pulseVersion++;
			int version = pulseVersion;
			((MonoBehaviour)this).StopAllCoroutines();
			((MonoBehaviour)this).StartCoroutine(PulseForCurrentPlaybackRoutine(Mathf.Max(0.25f, fallbackSeconds), version));
		}

		private IEnumerator PulseRoutine(float seconds, int version)
		{
			SetGlow(enabled: true);
			yield return (object)new WaitForSeconds(seconds);
			if (version == pulseVersion)
			{
				SetGlow(enabled: false);
			}
		}

		private IEnumerator PulseForCurrentPlaybackRoutine(float fallbackSeconds, int version)
		{
			SetGlow(enabled: true);
			AudioSource active = null;
			float startWait = 0f;
			while ((Object)(object)active == (Object)null && startWait < 0.4f)
			{
				AudioSource[] componentsInChildren = ((Component)this).GetComponentsInChildren<AudioSource>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					if ((Object)(object)componentsInChildren[i] != (Object)null && componentsInChildren[i].isPlaying)
					{
						active = componentsInChildren[i];
						break;
					}
				}
				if ((Object)(object)active != (Object)null)
				{
					break;
				}
				startWait += Time.deltaTime;
				yield return null;
			}
			if ((Object)(object)active == (Object)null)
			{
				yield return (object)new WaitForSeconds(fallbackSeconds);
			}
			else
			{
				float safety = 0f;
				while ((Object)(object)active != (Object)null && active.isPlaying && safety < 60f)
				{
					safety += Time.deltaTime;
					yield return null;
				}
			}
			if (version == pulseVersion)
			{
				SetGlow(enabled: false);
			}
		}

		private void SetGlow(bool enabled)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: 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)
			//IL_0049: 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_008a: 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_00a4: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)pointLight != (Object)null)
			{
				((Behaviour)pointLight).enabled = enabled;
			}
			if ((Object)(object)runtimeMaterial == (Object)null)
			{
				return;
			}
			Color val = (enabled ? Color.Lerp(baseColor, GlowColor, 0.1f) : baseColor);
			if (runtimeMaterial.HasProperty("_BaseColor"))
			{
				runtimeMaterial.SetColor("_BaseColor", val);
			}
			if (runtimeMaterial.HasProperty("_Color"))
			{
				runtimeMaterial.SetColor("_Color", val);
			}
			Color val2 = (enabled ? (GlowColor * 0.65f) : Color.black);
			if (runtimeMaterial.HasProperty("_EmissiveColor"))
			{
				runtimeMaterial.SetColor("_EmissiveColor", val2);
			}
			if (runtimeMaterial.HasProperty("_EmissiveColorLDR"))
			{
				runtimeMaterial.SetColor("_EmissiveColorLDR", val2);
			}
			if (runtimeMaterial.HasProperty("_EmissionColor"))
			{
				runtimeMaterial.SetColor("_EmissionColor", val2);
				if (enabled)
				{
					runtimeMaterial.EnableKeyword("_EMISSION");
				}
				else
				{
					runtimeMaterial.DisableKeyword("_EMISSION");
				}
			}
		}
	}
	internal static class BlumpkinSpawner
	{
		private static int lastAttemptFrame = int.MinValue;

		private static readonly BindingFlags InspectFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

		internal static void TrySpawn()
		{
			//IL_00c0: 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)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ItemFactory.BlumpkinItem == (Object)null || (Object)(object)ItemFactory.BlumpkinItem.spawnPrefab == (Object)null || (Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsListening || !NetworkManager.Singleton.IsServer || Time.frameCount == lastAttemptFrame)
			{
				return;
			}
			lastAttemptFrame = Time.frameCount;
			List<Transform> list = FindPumpkinRoots();
			if (list.Count == 0 && !CurrentLevelSupportsPumpkins())
			{
				return;
			}
			float num = Mathf.Clamp(Plugin.ModConfig.BlumpkinChancePercent.Value, 0f, 100f);
			if (Random.Range(0f, 100f) >= num)
			{
				return;
			}
			Vector3 position;
			if (list.Count > 0)
			{
				position = PositionNear(list[Random.Range(0, list.Count)].position, 0.8f, 1.4f);
			}
			else if (!TryGetOutsideSpawnPosition(out position))
			{
				Plugin.Log.LogWarning((object)"Blumpkin moon was pumpkin-eligible, but no safe outside spawn point was found.");
				return;
			}
			SnapToGround(ref position);
			GameObject val = Object.Instantiate<GameObject>(ItemFactory.BlumpkinItem.spawnPrefab, position, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f));
			GrabbableObject component = val.GetComponent<GrabbableObject>();
			if ((Object)(object)component != (Object)null)
			{
				int val2 = Mathf.RoundToInt((float)ItemFactory.BlumpkinItem.minValue * 0.4f);
				int val3 = Mathf.RoundToInt((float)ItemFactory.BlumpkinItem.maxValue * 0.4f);
				int num2 = Random.Range(Math.Min(val2, val3), Math.Max(val2, val3) + 1);
				try
				{
					MethodInfo methodInfo = AccessTools.Method(typeof(GrabbableObject), "SetScrapValue", (Type[])null, (Type[])null);
					if (methodInfo != null)
					{
						methodInfo.Invoke(component, new object[1] { num2 });
					}
					else
					{
						ReflectionUtil.SetMember(component, "scrapValue", num2);
					}
				}
				catch
				{
					ReflectionUtil.SetMember(component, "scrapValue", num2);
				}
			}
			NetworkObject component2 = val.GetComponent<NetworkObject>();
			if ((Object)(object)component2 == (Object)null)
			{
				Object.Destroy((Object)(object)val);
				Plugin.Log.LogError((object)"Blumpkin prefab has no NetworkObject.");
				return;
			}
			try
			{
				if (!component2.IsSpawned)
				{
					component2.Spawn(false);
				}
				Plugin.Log.LogInfo((object)"A Blumpkin spawned outside on a pumpkin-eligible moon.");
			}
			catch (Exception ex)
			{
				Object.Destroy((Object)(object)val);
				Plugin.Log.LogDebug((object)("Blumpkin network spawn was skipped: " + ex.GetBaseException().Message));
			}
		}

		private static Vector3 PositionNear(Vector3 origin, float minRadius, float maxRadius)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = Random.insideUnitCircle;
			if (((Vector2)(ref val)).sqrMagnitude < 0.01f)
			{
				val = Vector2.right;
			}
			((Vector2)(ref val)).Normalize();
			Vector2 val2 = val * Random.Range(minRadius, maxRadius);
			return origin + new Vector3(val2.x, 1.5f, val2.y);
		}

		private static void SnapToGround(ref Vector3 spawnPosition)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			RaycastHit val = default(RaycastHit);
			if (Physics.Raycast(spawnPosition + Vector3.up * 3f, Vector3.down, ref val, 12f, -1, (QueryTriggerInteraction)1))
			{
				spawnPosition = ((RaycastHit)(ref val)).point + Vector3.up * 0.15f;
			}
		}

		private static bool TryGetOutsideSpawnPosition(out Vector3 position)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			position = Vector3.zero;
			try
			{
				GameObject[] array = GameObject.FindGameObjectsWithTag("OutsideAINode");
				if (array != null && array.Length != 0)
				{
					GameObject val = array[Random.Range(0, array.Length)];
					position = PositionNear(val.transform.position, 0.4f, 2f);
					return true;
				}
			}
			catch
			{
			}
			return false;
		}

		private static bool CurrentLevelSupportsPumpkins()
		{
			if ((Object)(object)StartOfRound.Instance == (Object)null)
			{
				return false;
			}
			object member = ReflectionUtil.GetMember(StartOfRound.Instance, "currentLevel");
			if (member == null)
			{
				return false;
			}
			string[] array = new string[4] { "spawnableMapObjects", "spawnableOutsideObjects", "spawnableOutsideObjectsWithRarity", "randomMapObjects" };
			foreach (string name in array)
			{
				if (ContainsPumpkinReference(ReflectionUtil.GetMember(member, name), 3, new HashSet<object>()))
				{
					return true;
				}
			}
			return false;
		}

		private static bool ContainsPumpkinReference(object value, int depth, HashSet<object> visited)
		{
			if (value == null || depth < 0)
			{
				return false;
			}
			if (value is string text)
			{
				return text.IndexOf("pumpkin", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			Object val = (Object)((value is Object) ? value : null);
			if (val != (Object)null && !string.IsNullOrEmpty(val.name) && val.name.IndexOf("pumpkin", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
			Type type = value.GetType();
			if (type.IsPrimitive || type.IsEnum || type == typeof(decimal))
			{
				return false;
			}
			if (!type.IsValueType)
			{
				if (visited.Contains(value))
				{
					return false;
				}
				visited.Add(value);
			}
			if (value is IEnumerable enumerable && !(value is string))
			{
				int num = 0;
				foreach (object item in enumerable)
				{
					if (ContainsPumpkinReference(item, depth - 1, visited))
					{
						return true;
					}
					if (++num >= 256)
					{
						break;
					}
				}
				return false;
			}
			if (depth == 0)
			{
				return false;
			}
			FieldInfo[] fields = type.GetFields(InspectFlags);
			foreach (FieldInfo fieldInfo in fields)
			{
				if (fieldInfo.Name.IndexOf("pumpkin", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return true;
				}
				object value2;
				try
				{
					value2 = fieldInfo.GetValue(value);
				}
				catch
				{
					continue;
				}
				if (ContainsPumpkinReference(value2, depth - 1, visited))
				{
					return true;
				}
			}
			PropertyInfo[] properties = type.GetProperties(InspectFlags);
			foreach (PropertyInfo propertyInfo in properties)
			{
				if (propertyInfo.CanRead && propertyInfo.GetIndexParameters().Length == 0)
				{
					if (propertyInfo.Name.IndexOf("pumpkin", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return true;
					}
					object value3;
					try
					{
						value3 = propertyInfo.GetValue(value, null);
					}
					catch
					{
						continue;
					}
					if (ContainsPumpkinReference(value3, depth - 1, visited))
					{
						return true;
					}
				}
			}
			return false;
		}

		private static List<Transform> FindPumpkinRoots()
		{
			return Object.FindObjectsOfType<Transform>(true).Where(delegate(Transform transform)
			{
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)transform != (Object)null)
				{
					Scene scene = ((Component)transform).gameObject.scene;
					if (((Scene)(ref scene)).IsValid() && ((Component)transform).gameObject.activeInHierarchy && ((Object)transform).name.IndexOf("pumpkin", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return !AncestorNameContainsPumpkin(transform.parent);
					}
				}
				return false;
			}).ToList();
		}

		private static bool AncestorNameContainsPumpkin(Transform transform)
		{
			while ((Object)(object)transform != (Object)null)
			{
				if (((Object)transform).name.IndexOf("pumpkin", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return true;
				}
				transform = transform.parent;
			}
			return false;
		}
	}
	internal static class ItemFactory
	{
		private static bool buildAttempted;

		private static int successfulBuilds;

		internal static Item BlumpkinItem { get; private set; }

		internal static Item ShumovkaItem { get; private set; }

		internal static Item BaconEggCheeseItem { get; private set; }

		internal static Item BalbalItem { get; private set; }

		internal static Item TvorogItem { get; private set; }

		internal static Item ZubrowkaItem { get; private set; }

		internal static Item MoutaiItem { get; private set; }

		internal static Item KyivCakeItem { get; private set; }

		internal static Item BimbkaItem { get; private set; }

		internal static Item HasbullahItem { get; private set; }

		internal static Item DoshirakItem { get; private set; }

		internal static Item MenorahItem { get; private set; }

		internal static void BuildAll()
		{
			if (buildAttempted)
			{
				return;
			}
			buildAttempted = true;
			ModConfig cfg = Plugin.ModConfig;
			Item shovel = FindTemplateWithComponent<Shovel>(new string[1] { "Shovel" });
			if ((Object)(object)shovel == (Object)null)
			{
				shovel = FindAnyTemplateWithComponent<Shovel>();
			}
			Item clownHorn = FindTemplateWithComponent<NoisemakerProp>(new string[6] { "Clown horn", "Clownhorn", "Clown Horn", "ClownHorn", "Airhorn", "Air horn" });
			if ((Object)(object)clownHorn == (Object)null)
			{
				clownHorn = FindAnyTemplateWithComponent<NoisemakerProp>();
			}
			Item neutralScrap = FindPlainScrapTemplate("Mug", "Toy cube", "ToyCube", "Metal sheet", "MetalSheet", "Large axle", "Big bolt", "BigBolt", "Cog1");
			Item hive = FindTemplate("Hive", "RedLocustHive", "Red locust hive") ?? FindTemplateContains("hive");
			Item bottleSoundDonor = FindTemplate("Flask", "BottleBin", "PerfumeBottle", "Molotov", "Molotov cocktail") ?? FindTemplateContains("bottle");
			Item cakeSoundDonor = FindTemplate("Gift", "Gift box", "Gift Box", "GiftBox") ?? FindTemplateContains("gift");
			LogTemplate("Shovel", shovel);
			LogTemplate("Noisemaker", clownHorn);
			LogTemplate("Neutral scrap", neutralScrap);
			LogTemplate("Hive sound donor", hive);
			float maxSeconds = Mathf.Max(0f, cfg.MusicExcerptSeconds.Value);
			AudioClip val = CreateSilentClip();
			AudioClip baconClip = TryLoadWav("BaconEggCheese.wav", maxSeconds) ?? val;
			AudioClip tvorogClip = TryLoadWav("Tvorog.wav", maxSeconds) ?? val;
			AudioClip menorahSilence = TryLoadWav("MenorahSilence.wav") ?? val;
			AudioClip[] balbalClips = ((IEnumerable<AudioClip>)(object)new AudioClip[4]
			{
				TryLoadWav("Balbal_01.wav"),
				TryLoadWav("Balbal_02.wav"),
				TryLoadWav("Balbal_03.wav"),
				TryLoadWav("Balbal_04.wav")
			}).Where((AudioClip clip) => (Object)(object)clip != (Object)null).ToArray();
			if (balbalClips.Length == 0)
			{
				balbalClips = (AudioClip[])(object)new AudioClip[1] { val };
			}
			ShumovkaItem = TryBuildScrap("Shumovka", cfg.ShumovkaRarity.Value, delegate
			{
				RequireTemplate(shovel, "a shovel-class donor");
				Item obj = CreateItem(shovel, "Shumovka", "Shumovka", cfg.ShumovkaScale.Value, 19f, 95, 185, twoHanded: false, null, preserveTemplateHandling: true);
				Mark(obj, LoquatItemKind.Shumovka);
				return obj;
			});
			BaconEggCheeseItem = TryBuildScrap("Bacon Egg and Cheese Sandwich", cfg.BaconEggCheeseRarity.Value, delegate
			{
				RequireTemplate(clownHorn, "a noisemaker donor");
				Item val2 = CreateItem(clownHorn, "Bacon Egg and Cheese Sandwich", "BaconEggCheese", cfg.BaconEggCheeseScale.Value, 2f, 80, 160, twoHanded: false);
				ConfigureNoisemaker(val2, (AudioClip[])(object)new AudioClip[1] { baconClip });
				ReflectionUtil.SetMember(val2, "useCooldown", Math.Max(0.5f, baconClip.length));
				Mark(val2, LoquatItemKind.BaconEggCheese);
				return val2;
			});
			BalbalItem = TryBuildScrap("Balbal", cfg.BalbalRarity.Value, delegate
			{
				RequireTemplate(clownHorn, "a noisemaker donor");
				Item obj = CreateItem(clownHorn, "Balbal", "Balbal", cfg.BalbalScale.Value, 78f, 150, 290, twoHanded: true);
				ConfigureNoisemaker(obj, balbalClips);
				ReflectionUtil.SetMember(obj, "useCooldown", 1f);
				AddComponentIfMissing<BalbalGlowMarker>(obj.spawnPrefab);
				Mark(obj, LoquatItemKind.Balbal);
				return obj;
			});
			TvorogItem = TryBuildScrap("Tvorog", cfg.TvorogRarity.Value, delegate
			{
				RequireTemplate(clownHorn, "a noisemaker donor");
				Item val2 = CreateItem(clownHorn, "Tvorog", "Tvorog", cfg.TvorogScale.Value, 4f, 90, 175, twoHanded: false);
				ConfigureNoisemaker(val2, (AudioClip[])(object)new AudioClip[1] { tvorogClip });
				ReflectionUtil.SetMember(val2, "useCooldown", Math.Max(0.5f, tvorogClip.length));
				Mark(val2, LoquatItemKind.Tvorog);
				return val2;
			});
			ZubrowkaItem = TryBuildScrap("Żubrówka", cfg.ZubrowkaRarity.Value, delegate
			{
				RequireTemplate(neutralScrap, "a plain scrap donor");
				Item val2 = CreateItem(neutralScrap, "Żubrówka", "Zubrowka", cfg.ZubrowkaScale.Value, 3f, 90, 170, twoHanded: false);
				CopyVanillaHandlingSounds(bottleSoundDonor ?? neutralScrap, val2);
				Mark(val2, LoquatItemKind.Zubrowka);
				return val2;
			});
			MoutaiItem = TryBuildScrap("Kweichow Moutai", cfg.MoutaiRarity.Value, delegate
			{
				RequireTemplate(neutralScrap, "a plain scrap donor");
				Item val2 = CreateItem(neutralScrap, "Kweichow Moutai", "Moutai", cfg.MoutaiScale.Value, 4f, 180, 330, twoHanded: false);
				CopyVanillaHandlingSounds(bottleSoundDonor ?? neutralScrap, val2);
				Mark(val2, LoquatItemKind.Moutai);
				return val2;
			});
			KyivCakeItem = TryBuildScrap("Roshen Київський", cfg.KyivCakeRarity.Value, delegate
			{
				RequireTemplate(neutralScrap, "a plain scrap donor");
				Item val2 = CreateItem(neutralScrap, "Roshen Київський", "KyivCake", cfg.KyivCakeScale.Value, 10f, 105, 200, twoHanded: false, "Roshen Київський");
				CopyVanillaHandlingSounds(cakeSoundDonor ?? neutralScrap, val2);
				Mark(val2, LoquatItemKind.KyivCake);
				return val2;
			});
			BimbkaItem = TryBuildScrap("Bimbka", cfg.BimbkaRarity.Value, delegate
			{
				RequireTemplate(neutralScrap, "a plain scrap donor");
				Item val2 = CreateItem(neutralScrap, "Bimbka", "Bimbka", cfg.BimbkaScale.Value, 72f, 175, 325, twoHanded: true);
				CopyVanillaHandlingSounds(neutralScrap, val2);
				Mark(val2, LoquatItemKind.Bimbka);
				return val2;
			});
			HasbullahItem = TryBuildScrap("Hasbullah", cfg.HasbullahRarity.Value, delegate
			{
				RequireTemplate(neutralScrap, "a plain scrap donor");
				Item val2 = CreateItem(neutralScrap, "Hasbullah", "Hasbullah", cfg.HasbullahScale.Value, 46f, 210, 390, twoHanded: true);
				CopyVanillaHandlingSounds(neutralScrap, val2);
				Mark(val2, LoquatItemKind.Hasbullah);
				return val2;
			});
			DoshirakItem = TryBuildScrap("Doshirak", cfg.DoshirakRarity.Value, delegate
			{
				RequireTemplate(neutralScrap, "a plain scrap donor");
				Item val2 = CreateItem(neutralScrap, "Doshirak", "Doshirak", cfg.DoshirakScale.Value, 2f, 80, 155, twoHanded: false);
				CopyVanillaHandlingSounds(neutralScrap, val2);
				Mark(val2, LoquatItemKind.Doshirak);
				return val2;
			});
			MenorahItem = TryBuildScrap("Menorah", cfg.MenorahRarity.Value, delegate
			{
				RequireTemplate(clownHorn, "a noisemaker donor");
				Item val2 = CreateItem(clownHorn, "Menorah", "Menorah", cfg.MenorahScale.Value, 18f, 145, 275, twoHanded: false);
				ConfigureNoisemaker(val2, (AudioClip[])(object)new AudioClip[1] { menorahSilence });
				ReflectionUtil.SetMember(val2, "useCooldown", 0.75f);
				NoisemakerProp component = val2.spawnPrefab.GetComponent<NoisemakerProp>();
				if ((Object)(object)component != (Object)null)
				{
					ReflectionUtil.SetMember(component, "noiseRange", 0f);
					ReflectionUtil.SetMember(component, "maxLoudness", 0f);
					ReflectionUtil.SetMember(component, "minLoudness", 0f);
					AddComponentIfMissing<MenorahLightMarker>(val2.spawnPrefab);
				}
				CopyVanillaHandlingSounds(neutralScrap, val2);
				Mark(val2, LoquatItemKind.Menorah);
				return val2;
			});
			BlumpkinItem = TryBuildItem("Blumpkin", delegate
			{
				RequireTemplate(neutralScrap, "a plain scrap donor");
				Item val2 = CreateItem(neutralScrap, "Blumpkin", "Blumpkin", cfg.BlumpkinScale.Value, 12f, 230, 420, twoHanded: false, "Blumpkin (blue pumpkin)");
				CopyVanillaHandlingSounds(hive ?? neutralScrap, val2);
				Mark(val2, LoquatItemKind.Blumpkin);
				return val2;
			});
			ConfigureUprightRest(BaconEggCheeseItem, 0f);
			ConfigureUprightRest(BalbalItem, 0f);
			ConfigureUprightRest(TvorogItem, 0f);
			ConfigureUprightRest(ZubrowkaItem, 0f);
			ConfigureUprightRest(MoutaiItem, 0f);
			ConfigureUprightRest(KyivCakeItem, 0f);
			ConfigureUprightRest(BlumpkinItem, 0f);
			ConfigureUprightRest(BimbkaItem, 0f);
			ConfigureUprightRest(HasbullahItem, 0f);
			ConfigureUprightRest(DoshirakItem, 0f);
			ConfigureUprightRest(MenorahItem, 0f);
			float value = cfg.HeldFacingYawDegrees.Value;
			ConfigureHeldFacing(BaconEggCheeseItem, value);
			ConfigureHeldFacing(BalbalItem, value);
			ConfigureHeldFacing(TvorogItem, value);
			ConfigureHeldFacing(ZubrowkaItem, value);
			ConfigureHeldFacing(MoutaiItem, value);
			ConfigureHeldFacing(KyivCakeItem, value);
			ConfigureHeldFacing(BlumpkinItem, value);
			ConfigureHeldFacing(BimbkaItem, value);
			ConfigureHeldFacing(HasbullahItem, value);
			ConfigureHeldFacing(DoshirakItem, value);
			ConfigureHeldFacing(MenorahItem, value);
			Plugin.Log.LogInfo((object)$"Loquat initialization finished: {successfulBuilds}/12 items registered. Failed items were skipped without interrupting game startup.");
		}

		private static Item TryBuildScrap(string label, int rarity, Func<Item> factory)
		{
			Item val = TryCreate(label, factory);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			try
			{
				Items.RegisterScrap(val, Mathf.Max(0, rarity), (LevelTypes)(-1));
				successfulBuilds++;
				return val;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)(label + " was created but could not be added to the scrap table; it will be unavailable this session. " + ex.GetBaseException().Message));
				return null;
			}
		}

		private static Item TryBuildItem(string label, Func<Item> factory)
		{
			Item val = TryCreate(label, factory);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			try
			{
				Items.RegisterItem(val);
				successfulBuilds++;
				return val;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)(label + " was created but could not be registered; it will be unavailable this session. " + ex.GetBaseException().Message));
				return null;
			}
		}

		private static Item TryCreate(string label, Func<Item> factory)
		{
			try
			{
				Item val = factory();
				if ((Object)(object)val == (Object)null || !HasUsableSpawnPrefab(val))
				{
					throw new InvalidOperationException("item creation returned an unusable prefab");
				}
				return val;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Skipping Loquat item '" + label + "': " + ex.GetBaseException().Message));
				return null;
			}
		}

		private static void RequireTemplate(Item item, string description)
		{
			if (!HasUsableSpawnPrefab(item))
			{
				throw new InvalidOperationException("Could not find " + description + " with a usable network prefab.");
			}
		}

		private static T AddComponentIfMissing<T>(GameObject target) where T : Component
		{
			if ((Object)(object)target == (Object)null)
			{
				return default(T);
			}
			return target.GetComponent<T>() ?? target.AddComponent<T>();
		}

		private static void Mark(Item item, LoquatItemKind kind)
		{
			if (!((Object)(object)item == (Object)null) && !((Object)(object)item.spawnPrefab == (Object)null))
			{
				LoquatItemMarker loquatItemMarker = AddComponentIfMissing<LoquatItemMarker>(item.spawnPrefab);
				if ((Object)(object)loquatItemMarker != (Object)null)
				{
					loquatItemMarker.Kind = kind;
				}
			}
		}

		private static AudioClip TryLoadWav(string fileName, float maxSeconds = 0f)
		{
			try
			{
				return RuntimeAssets.LoadWav(fileName, maxSeconds);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Audio asset '" + fileName + "' could not be loaded; a silent fallback will be used. " + ex.GetBaseException().Message));
				return null;
			}
		}

		private static AudioClip CreateSilentClip()
		{
			AudioClip obj = AudioClip.Create("LoquatSilentFallback", 2205, 1, 44100, false);
			obj.SetData(new float[2205], 0);
			return obj;
		}

		private static bool HasUsableSpawnPrefab(Item item)
		{
			if ((Object)(object)item == (Object)null || (Object)(object)item.spawnPrefab == (Object)null)
			{
				return false;
			}
			if ((Object)(object)item.spawnPrefab.GetComponent<GrabbableObject>() != (Object)null)
			{
				return (Object)(object)item.spawnPrefab.GetComponent<NetworkObject>() != (Object)null;
			}
			return false;
		}

		private static bool IsLoquatGenerated(Item item)
		{
			if ((Object)(object)item == (Object)null)
			{
				return false;
			}
			if (string.IsNullOrEmpty(((Object)item).name) || !((Object)item).name.StartsWith("FGS_", StringComparison.Ordinal))
			{
				if ((Object)(object)item.spawnPrefab != (Object)null && !string.IsNullOrEmpty(((Object)item.spawnPrefab).name))
				{
					return ((Object)item.spawnPrefab).name.StartsWith("FGS_", StringComparison.Ordinal);
				}
				return false;
			}
			return true;
		}

		private static Item FindTemplate(params string[] names)
		{
			Item[] source = Resources.FindObjectsOfTypeAll<Item>();
			foreach (string name in names)
			{
				Item val = ((IEnumerable<Item>)(from item in source.Where(HasUsableSpawnPrefab)
					where !IsLoquatGenerated(item)
					orderby MatchScore(item, name) descending
					select item)).FirstOrDefault((Func<Item, bool>)((Item item) => MatchScore(item, name) > 0));
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		private static Item FindTemplateWithComponent<T>(params string[] names) where T : Component
		{
			Item[] source = Resources.FindObjectsOfTypeAll<Item>();
			foreach (string name in names)
			{
				Item val = ((IEnumerable<Item>)(from item in source.Where(HasUsableSpawnPrefab)
					where !IsLoquatGenerated(item)
					where (Object)(object)item.spawnPrefab.GetComponent<T>() != (Object)null
					orderby MatchScore(item, name) descending
					select item)).FirstOrDefault((Func<Item, bool>)((Item item) => MatchScore(item, name) > 0));
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		private static Item FindAnyTemplateWithComponent<T>() where T : Component
		{
			return (from item in Resources.FindObjectsOfTypeAll<Item>().Where(HasUsableSpawnPrefab)
				where !IsLoquatGenerated(item)
				where (Object)(object)item.spawnPrefab.GetComponent<T>() != (Object)null
				select item).OrderBy<Item, string>((Item item) => ((Object)item).name ?? string.Empty, StringComparer.OrdinalIgnoreCase).FirstOrDefault();
		}

		private static Item FindPlainScrapTemplate(params string[] preferredNames)
		{
			Item val = FindTemplate(preferredNames);
			if ((Object)(object)val != (Object)null && IsPlainGrabbable(val))
			{
				return val;
			}
			foreach (string name in preferredNames)
			{
				Item val2 = ((IEnumerable<Item>)(from item in (from item in Resources.FindObjectsOfTypeAll<Item>().Where(HasUsableSpawnPrefab)
						where !IsLoquatGenerated(item)
						select item).Where(IsPlainGrabbable)
					orderby MatchScore(item, name) descending
					select item)).FirstOrDefault((Func<Item, bool>)((Item item) => MatchScore(item, name) > 0));
				if ((Object)(object)val2 != (Object)null)
				{
					return val2;
				}
			}
			return (from item in (from item in Resources.FindObjectsOfTypeAll<Item>().Where(HasUsableSpawnPrefab)
					where !IsLoquatGenerated(item)
					select item).Where(IsPlainGrabbable)
				where item.isScrap
				select item).OrderBy<Item, string>((Item item) => ((Object)item).name ?? string.Empty, StringComparer.OrdinalIgnoreCase).FirstOrDefault();
		}

		private static bool IsPlainGrabbable(Item item)
		{
			if (!HasUsableSpawnPrefab(item))
			{
				return false;
			}
			GrabbableObject component = item.spawnPrefab.GetComponent<GrabbableObject>();
			if ((Object)(object)component != (Object)null)
			{
				return ((object)component).GetType() == typeof(GrabbableObject);
			}
			return false;
		}

		private static Item FindTemplateContains(string fragment)
		{
			string normalized = NormalizeName(fragment);
			return (from item in Resources.FindObjectsOfTypeAll<Item>().Where(HasUsableSpawnPrefab)
				where !IsLoquatGenerated(item)
				where ContainsNormalized(item.itemName, normalized) || ContainsNormalized(((Object)item).name, normalized) || ContainsNormalized(((Object)(object)item.spawnPrefab == (Object)null) ? null : ((Object)item.spawnPrefab).name, normalized)
				select item).OrderBy<Item, string>((Item item) => ((Object)item).name ?? string.Empty, StringComparer.OrdinalIgnoreCase).FirstOrDefault();
		}

		private static int MatchScore(Item item, string requested)
		{
			string text = NormalizeName(requested);
			if (text.Length == 0 || (Object)(object)item == (Object)null)
			{
				return 0;
			}
			string text2 = NormalizeName(item.itemName);
			string text3 = NormalizeName(((Object)item).name);
			string text4 = NormalizeName(((Object)(object)item.spawnPrefab == (Object)null) ? null : ((Object)item.spawnPrefab).name);
			if (text3 == text)
			{
				return 50;
			}
			if (text4 == text)
			{
				return 45;
			}
			if (text2 == text)
			{
				return 30;
			}
			if (text3.EndsWith(text, StringComparison.Ordinal))
			{
				return 20;
			}
			if (text4.EndsWith(text, StringComparison.Ordinal))
			{
				return 15;
			}
			return 0;
		}

		private static bool ContainsNormalized(string value, string normalizedFragment)
		{
			return NormalizeName(value).IndexOf(normalizedFragment, StringComparison.Ordinal) >= 0;
		}

		private static string NormalizeName(string value)
		{
			if (string.IsNullOrEmpty(value))
			{
				return string.Empty;
			}
			StringBuilder stringBuilder = new StringBuilder(value.Length);
			foreach (char c in value)
			{
				if (char.IsLetterOrDigit(c))
				{
					stringBuilder.Append(char.ToLowerInvariant(c));
				}
			}
			return stringBuilder.ToString();
		}

		private static void LogTemplate(string label, Item item)
		{
			if ((Object)(object)item == (Object)null)
			{
				Plugin.Log.LogWarning((object)(label + " donor: not found; dependent Loquat items will be skipped."));
				return;
			}
			string text = (((Object)(object)item.spawnPrefab == (Object)null) ? "<null>" : ((Object)item.spawnPrefab).name);
			string text2 = (((Object)(object)item.spawnPrefab == (Object)null) ? "<none>" : (((object)item.spawnPrefab.GetComponent<GrabbableObject>())?.GetType().Name ?? "<no GrabbableObject>"));
			Plugin.Log.LogInfo((object)(label + " donor: Item '" + item.itemName + "' / asset '" + ((Object)item).name + "' / prefab '" + text + "' / component '" + text2 + "'."));
		}

		private static Item CreateItem(Item template, string displayName, string assetName, float visualScale, float pounds, int minInternalValue, int maxInternalValue, bool twoHanded, string scanHeader = null, bool preserveTemplateHandling = false)
		{
			RequireTemplate(template, "a donor for " + displayName);
			Item val = null;
			GameObject val2 = null;
			try
			{
				val = Object.Instantiate<Item>(template);
				((Object)val).name = "FGS_" + assetName + "_Item";
				val.itemName = displayName;
				val.isScrap = true;
				val.minValue = Math.Min(minInternalValue, maxInternalValue);
				val.maxValue = Math.Max(minInternalValue, maxInternalValue);
				val.weight = Mathf.Clamp(1f + pounds / 105f, 1f, 3.75f);
				if (!preserveTemplateHandling)
				{
					val.twoHanded = twoHanded;
					ReflectionUtil.SetMember(val, "twoHandedAnimation", twoHanded);
					if (twoHanded)
					{
						ReflectionUtil.SetMember(val, "grabAnim", "HoldLung");
					}
				}
				val2 = PrefabUtils.ClonePrefab(template.spawnPrefab, "FGS_" + assetName + "_Prefab");
				if ((Object)(object)val2 == (Object)null)
				{
					throw new InvalidOperationException("Could not clone the donor prefab for " + displayName + ".");
				}
				NetworkObject component = val2.GetComponent<NetworkObject>();
				if ((Object)(object)component == (Object)null)
				{
					throw new InvalidOperationException("Donor prefab for " + displayName + " has no root NetworkObject.");
				}
				GrabbableObject component2 = val2.GetComponent<GrabbableObject>();
				if ((Object)(object)component2 == (Object)null)
				{
					throw new InvalidOperationException("Donor prefab for " + displayName + " has no root GrabbableObject.");
				}
				val.spawnPrefab = val2;
				component2.itemProperties = val;
				ReplaceVisual(val2, component2, assetName, Mathf.Max(0.01f, visualScale), scanHeader ?? displayName);
				AssignDeterministicNetworkHash(component, ((Object)val2).name);
				NetworkPrefabs.RegisterNetworkPrefab(val2);
				return val;
			}
			catch
			{
				if ((Object)(object)val2 != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)val2);
				}
				if ((Object)(object)val != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)val);
				}
				throw;
			}
		}

		private static void AssignDeterministicNetworkHash(NetworkObject networkObject, string prefabName)
		{
			if ((Object)(object)networkObject == (Object)null)
			{
				throw new ArgumentNullException("networkObject");
			}
			string name = typeof(Plugin).Assembly.GetName().Name;
			uint num;
			using (MD5 mD = MD5.Create())
			{
				num = BitConverter.ToUInt32(mD.ComputeHash(Encoding.UTF8.GetBytes(name + prefabName)), 0);
			}
			if (!ReflectionUtil.SetMember(networkObject, "GlobalObjectIdHash", num) && !ReflectionUtil.SetMember(networkObject, "m_GlobalObjectIdHash", num) && !ReflectionUtil.SetMember(networkObject, "<GlobalObjectIdHash>k__BackingField", num))
			{
				throw new InvalidOperationException("Could not assign a deterministic NetworkObject hash to " + prefabName + ".");
			}
		}

		private static void ReplaceVisual(GameObject prefab, GrabbableObject grabbable, string assetName, float visualScale, string scanHeader)
		{
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_0342: Unknown result type (might be due to invalid IL or missing references)
			//IL_0347: Unknown result type (might be due to invalid IL or missing references)
			//IL_0356: Unknown result type (might be due to invalid IL or missing references)
			//IL_0362: Unknown result type (might be due to invalid IL or missing references)
			//IL_036e: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: 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_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f1: 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_02fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0411: Unknown result type (might be due to invalid IL or missing references)
			//IL_0418: Unknown result type (might be due to invalid IL or missing references)
			//IL_0436: Unknown result type (might be due to invalid IL or missing references)
			//IL_043b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0443: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_045d: Unknown result type (might be due to invalid IL or missing references)
			//IL_045f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0461: Unknown result type (might be due to invalid IL or missing references)
			//IL_0481: Unknown result type (might be due to invalid IL or missing references)
			//IL_0483: Unknown result type (might be due to invalid IL or missing references)
			//IL_0485: Unknown result type (might be due to invalid IL or missing references)
			//IL_048a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0492: Unknown result type (might be due to invalid IL or missing references)
			//IL_0494: Unknown result type (might be due to invalid IL or missing references)
			//IL_0496: Unknown result type (might be due to invalid IL or missing references)
			//IL_0498: Unknown result type (might be due to invalid IL or missing references)
			//IL_049f: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f9: Unknown result type (might be due to invalid IL or missing references)
			Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
			Renderer val = (Renderer)(object)grabbable.mainObjectRenderer;
			if ((Object)(object)val == (Object)null)
			{
				val = ((IEnumerable<Renderer>)componentsInChildren).FirstOrDefault((Func<Renderer, bool>)((Renderer renderer) => renderer is MeshRenderer && (Object)(object)((Component)renderer).GetComponent<MeshFilter>() != (Object)null));
			}
			if ((Object)(object)val == (Object)null)
			{
				throw new InvalidOperationException("Could not find a mesh anchor renderer for " + assetName + ".");
			}
			GameObject gameObject = ((Component)val).gameObject;
			int layer = gameObject.layer;
			MeshRenderer val2 = (MeshRenderer)(object)((val is MeshRenderer) ? val : null);
			MeshFilter val3 = gameObject.GetComponent<MeshFilter>();
			if ((Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null)
			{
				val.enabled = false;
				val3 = gameObject.GetComponent<MeshFilter>() ?? gameObject.AddComponent<MeshFilter>();
				val2 = gameObject.GetComponent<MeshRenderer>() ?? gameObject.AddComponent<MeshRenderer>();
			}
			Quaternion localRotation = gameObject.transform.localRotation;
			Vector3 localPosition = gameObject.transform.localPosition;
			gameObject.layer = layer;
			for (int num = gameObject.transform.childCount - 1; num >= 0; num--)
			{
				Transform child = gameObject.transform.GetChild(num);
				if ((Object)(object)child != (Object)null && (((Object)child).name.StartsWith("FGS_Part_", StringComparison.Ordinal) || ((Object)child).name == "FGS_ShumovkaVisual"))
				{
					Object.DestroyImmediate((Object)(object)((Component)child).gameObject);
				}
			}
			MeshFilter val4 = val3;
			MeshRenderer val5 = val2;
			if (assetName == "Shumovka")
			{
				GameObject val6 = new GameObject("FGS_ShumovkaVisual")
				{
					layer = layer
				};
				val6.transform.SetParent(gameObject.transform, false);
				val6.transform.localPosition = Vector3.zero;
				val6.transform.localRotation = Quaternion.identity;
				val6.transform.localScale = Vector3.one;
				val4 = val6.AddComponent<MeshFilter>();
				val5 = val6.AddComponent<MeshRenderer>();
			}
			Bounds val7 = default(Bounds);
			bool flag = false;
			if (RuntimeAssets.HasVisualParts(assetName))
			{
				List<RuntimeAssets.VisualPart> list = RuntimeAssets.LoadVisualParts(assetName);
				if (list.Count == 0)
				{
					throw new InvalidOperationException("Visual-parts manifest for " + assetName + " contained no parts.");
				}
				RuntimeAssets.VisualPart visualPart = list[0];
				val4.sharedMesh = visualPart.Mesh;
				((Renderer)val5).sharedMaterial = visualPart.Material;
				((Renderer)val5).enabled = true;
				val7 = visualPart.Mesh.bounds;
				flag = true;
				for (int num2 = 1; num2 < list.Count; num2++)
				{
					RuntimeAssets.VisualPart visualPart2 = list[num2];
					GameObject val8 = new GameObject("FGS_Part_" + visualPart2.Name)
					{
						layer = layer
					};
					val8.transform.SetParent(((Component)val5).transform, false);
					val8.transform.localPosition = Vector3.zero;
					val8.transform.localRotation = Quaternion.identity;
					val8.transform.localScale = Vector3.one;
					val8.AddComponent<MeshFilter>().sharedMesh = visualPart2.Mesh;
					((Renderer)val8.AddComponent<MeshRenderer>()).sharedMaterial = visualPart2.Material;
					Bounds bounds = visualPart2.Mesh.bounds;
					((Bounds)(ref val7)).Encapsulate(((Bounds)(ref bounds)).min);
					bounds = visualPart2.Mesh.bounds;
					((Bounds)(ref val7)).Encapsulate(((Bounds)(ref bounds)).max);
				}
			}
			else
			{
				Mesh val9 = (val4.sharedMesh = RuntimeAssets.LoadMesh(assetName));
				((Renderer)val5).sharedMaterial = RuntimeAssets.CreateMaterial(assetName);
				((Renderer)val5).enabled = true;
				val7 = val9.bounds;
				flag = true;
			}
			float targetLongestDimensionMetres = GetTargetLongestDimensionMetres(assetName);
			float num3 = Mathf.Max(((Bounds)(ref val7)).size.x, Mathf.Max(((Bounds)(ref val7)).size.y, ((Bounds)(ref val7)).size.z));
			float num4 = ((num3 > 0.0001f) ? (targetLongestDimensionMetres / num3 * Mathf.Max(0.05f, visualScale)) : 1f);
			Transform parent = gameObject.transform.parent;
			float num5 = 1f;
			if ((Object)(object)parent != (Object)null)
			{
				Vector3 lossyScale = parent.lossyScale;
				num5 = Mathf.Max(0.0001f, Mathf.Max(Mathf.Abs(lossyScale.x), Mathf.Max(Mathf.Abs(lossyScale.y), Mathf.Abs(lossyScale.z))));
			}
			float num6 = num4 / num5;
			gameObject.transform.localScale = Vector3.one * num6;
			float value = Plugin.ModConfig.ModelRotationZDegrees.Value;
			Quaternion modelSpaceCorrection = GetModelSpaceCorrection(assetName, value);
			gameObject.transform.localPosition = localPosition;
			if (assetName == "Shumovka")
			{
				gameObject.transform.localRotation = localRotation * modelSpaceCorrection;
				Vector3 val11 = default(Vector3);
				((Vector3)(ref val11))..ctor(0f, 0.16f, 0.31f);
				Vector3 val12 = modelSpaceCorrection * val11;
				gameObject.transform.localPosition = localPosition - localRotation * val12 * num6;
			}
			else
			{
				gameObject.transform.localRotation = modelSpaceCorrection;
			}
			Renderer[] array = componentsInChildren;
			foreach (Renderer val13 in array)
			{
				if ((Object)(object)val13 == (Object)null || (Object)(object)val13 == (Object)(object)val5)
				{
					continue;
				}
				val13.enabled = false;
				MeshRenderer val14 = (MeshRenderer)(object)((val13 is MeshRenderer) ? val13 : null);
				if ((Object)(object)val14 != (Object)null)
				{
					MeshFilter component = ((Component)val14).GetComponent<MeshFilter>();
					if ((Object)(object)component != (Object)null)
					{
						component.sharedMesh = null;
					}
					((Renderer)val14).sharedMaterial = null;
				}
				else
				{
					SkinnedMeshRenderer val15 = (SkinnedMeshRenderer)(object)((val13 is SkinnedMeshRenderer) ? val13 : null);
					if ((Object)(object)val15 != (Object)null)
					{
						val15.sharedMesh = null;
						((Renderer)val15).sharedMaterial = null;
					}
				}
			}
			grabbable.mainObjectRenderer = val5;
			Collider[] componentsInChildren2 = prefab.GetComponentsInChildren<Collider>(true);
			foreach (Collider val16 in componentsInChildren2)
			{
				if ((Object)(object)val16 != (Object)null && !val16.isTrigger)
				{
					val16.enabled = false;
				}
			}
			BoxCollider val17 = gameObject.GetComponent<BoxCollider>() ?? gameObject.AddComponent<BoxCollider>();
			((Collider)val17).enabled = true;
			((Collider)val17).isTrigger = false;
			if (flag)
			{
				val17.center = ((Bounds)(ref val7)).center;
				val17.size = Vector3.Max(((Bounds)(ref val7)).size * 0.9f, new Vector3(0.08f, 0.08f, 0.08f));
			}
			UpdateScanNode(prefab, scanHeader);
			Plugin.Log.LogInfo((object)$"Bound {assetName} to '{((Object)gameObject).name}': target longest dimension {targetLongestDimensionMetres:0.00} m, size multiplier {visualScale:0.##}, extra local Z rotation {value:0.#} deg. Donor anchor preserved; per-model correction applied where required.");
		}

		private static Quaternion GetModelSpaceCorrection(string assetName, float extraZDegrees)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			Quaternion val = Quaternion.identity;
			if (assetName == "Shumovka")
			{
				Quaternion val2 = Quaternion.AngleAxis(-124.5f, Vector3.right);
				val = Quaternion.AngleAxis(Plugin.ModConfig.ShumovkaRollDegrees.Value, Vector3.up) * val2;
			}
			if (Mathf.Abs(extraZDegrees) > 0.001f)
			{
				val *= Quaternion.Euler(0f, 0f, extraZDegrees);
			}
			return val;
		}

		private static void ConfigureHeldFacing(Item item, float yawDegrees)
		{
			//IL_0033: 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_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)item == (Object)null) && !(Mathf.Abs(yawDegrees) < 0.001f))
			{
				object member = ReflectionUtil.GetMember(item, "rotationOffset");
				Vector3 val = (Vector3)((member is Vector3) ? ((Vector3)member) : Vector3.zero);
				val.y = NormalizeDegrees(val.y + yawDegrees);
				ReflectionUtil.SetMember(item, "rotationOffset", val);
				Plugin.Log.LogInfo((object)$"Held-facing correction for {item.itemName}: +{yawDegrees:0.#}° yaw -> rotationOffset {val}.");
			}
		}

		private static float NormalizeDegrees(float degrees)
		{
			degrees %= 360f;
			if (degrees > 180f)
			{
				degrees -= 360f;
			}
			if (degrees < -180f)
			{
				degrees += 360f;
			}
			return degrees;
		}

		private static void ConfigureUprightRest(Item item, float zDegrees)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)item == (Object)null))
			{
				ReflectionUtil.SetMember(item, "restingRotation", (object)new Vector3(0f, 0f, zDegrees));
				ReflectionUtil.SetMember(item, "verticalOffset", 0f);
			}
		}

		private static float GetTargetLongestDimensionMetres(string assetName)
		{
			return assetName switch
			{
				"Shumovka" => 1.1f, 
				"BaconEggCheese" => 0.2f, 
				"Balbal" => 1.2f, 
				"Blumpkin" => 0.42f, 
				"Tvorog" => 0.24f, 
				"Zubrowka" => 0.33f, 
				"Moutai" => 0.25f, 
				"KyivCake" => 0.3f, 
				"Bimbka" => 0.85f, 
				"Hasbullah" => 0.75f, 
				"Doshirak" => 0.24f, 
				"Menorah" => 0.55f, 
				_ => 0.35f, 
			};
		}

		private static void UpdateScanNode(GameObject prefab, string headerText)
		{
			MonoBehaviour[] componentsInChildren = prefab.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !(((object)val).GetType().Name != "ScanNodeProperties"))
				{
					ReflectionUtil.SetMember(val, "headerText", headerText);
					break;
				}
			}
		}

		private static void ConfigureNoisemaker(Item item, AudioClip[] clips)
		{
			NoisemakerProp component = item.spawnPrefab.GetComponent<NoisemakerProp>();
			if ((Object)(object)component == (Object)null)
			{
				throw new InvalidOperationException(item.itemName + " was cloned from a noisemaker but has no NoisemakerProp.");
			}
			ReflectionUtil.SetMember(component, "noiseSFX", clips);
			ReflectionUtil.SetMember(component, "noiseSFXFar", clips);
			ReflectionUtil.SetMember(component, "minPitch", 1f);
			ReflectionUtil.SetMember(component, "maxPitch", 1f);
			ReflectionUtil.SetMember(item, "syncUseFunction", true);
		}

		private static void CopyVanillaHandlingSounds(Item source, Item destination)
		{
			if ((Object)(object)source == (Object)null || (Object)(object)destination == (Object)null)
			{
				return;
			}
			string[] array = new string[4] { "grabSFX", "dropSFX", "pocketSFX", "throwSFX" };
			foreach (string name in array)
			{
				object member = ReflectionUtil.GetMember(source, name);
				if (member != null)
				{
					ReflectionUtil.SetMember(destination, name, member);
				}
			}
		}
	}
	internal enum LoquatItemKind
	{
		Unknown,
		Shumovka,
		BaconEggCheese,
		Balbal,
		Tvorog,
		Zubrowka,
		Moutai,
		KyivCake,
		Bimbka,
		Hasbullah,
		Doshirak,
		Menorah,
		Blumpkin
	}
	internal sealed class LoquatItemMarker : MonoBehaviour
	{
		[SerializeField]
		private LoquatItemKind kind;

		internal LoquatItemKind Kind
		{
			get
			{
				return kind;
			}
			set
			{
				kind = value;
			}
		}
	}
	internal sealed class MenorahLightMarker : MonoBehaviour
	{
		private GameObject flamesRoot;

		private Light warmLight;

		private float lastToggleTime = -10f;

		private bool isLit = true;

		internal bool IsLit => isLit;

		private void Start()
		{
			try
			{
				BuildFlames();
				SetLit(value: true);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogDebug((object)("Menorah visual setup was disabled: " + ex.GetBaseException().Message));
				((Behaviour)this).enabled = false;
			}
		}

		private void BuildFlames()
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Expected O, but got Unknown
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: 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_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Expected O, but got Unknown
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_028c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)flamesRoot != (Object)null)
			{
				return;
			}
			GrabbableObject component = ((Component)this).GetComponent<GrabbableObject>();
			Renderer val = (Renderer)(((Object)(object)component != (Object)null) ? ((object)component.mainObjectRenderer) : ((object)((Component)this).GetComponentInChildren<Renderer>(true)));
			Transform val2 = (((Object)(object)val != (Object)null) ? ((Component)val).transform : ((Component)this).transform);
			MeshFilter component2 = ((Component)val2).GetComponent<MeshFilter>();
			Bounds val3 = (Bounds)(((Object)(object)component2 != (Object)null && (Object)(object)component2.sharedMesh != (Object)null) ? component2.sharedMesh.bounds : new Bounds(new Vector3(0f, 0.5f, 0f), new Vector3(0.8f, 1f, 0.35f)));
			flamesRoot = new GameObject("FGS_MenorahFlames");
			flamesRoot.transform.SetParent(val2, false);
			Material sharedMaterial = CreateFlameMaterial();
			float num = ((Bounds)(ref val3)).extents.x * 0.86f;
			float num2 = ((Bounds)(ref val3)).max.y - ((Bounds)(ref val3)).size.y * 0.05f;
			float num3 = ((Bounds)(ref val3)).max.y + ((Bounds)(ref val3)).size.y * 0.005f;
			float z = ((Bounds)(ref val3)).center.z;
			for (int i = 0; i < 9; i++)
			{
				float num4 = (float)(i - 4) / 4f * num;
				float num5 = ((i == 4) ? num3 : num2);
				GameObject obj = GameObject.CreatePrimitive((PrimitiveType)0);
				((Object)obj).name = "FGS_MenorahFlame_" + i;
				obj.transform.SetParent(flamesRoot.transform, false);
				obj.transform.localPosition = new Vector3(num4, num5, z);
				float num6 = ((Bounds)(ref val3)).size.y * 0.019f;
				obj.transform.localScale = new Vector3(num6 * 0.75f, num6 * 1.55f, num6 * 0.75f);
				Collider component3 = obj.GetComponent<Collider>();
				if ((Object)(object)component3 != (Object)null)
				{
					Object.Destroy((Object)(object)component3);
				}
				Renderer component4 = obj.GetComponent<Renderer>();
				if ((Object)(object)component4 != (Object)null)
				{
					component4.sharedMaterial = sharedMaterial;
				}
			}
			GameObject val4 = new GameObject("FGS_MenorahWarmLight");
			val4.transform.SetParent(val2, false);
			val4.transform.localPosition = new Vector3(0f, ((Bounds)(ref val3)).max.y, z);
			warmLight = val4.AddComponent<Light>();
			warmLight.type = (LightType)2;
			warmLight.color = new Color(1f, 0.48f, 0.16f, 1f);
			warmLight.range = 2.4f;
			warmLight.intensity = 6f;
			warmLight.shadows = (LightShadows)0;
		}

		private static Material CreateFlameMaterial()
		{
			//IL_0033: 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_0044: Expected O, but got Unknown
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			Shader val = Shader.Find("HDRP/Unlit") ?? Shader.Find("Unlit/Color") ?? Shader.Find("Standard");
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Material val2 = new Material(val)
			{
				name = "FGS_MenorahFlameMaterial"
			};
			Color val3 = default(Color);
			((Color)(ref val3))..ctor(1f, 0.34f, 0.06f, 1f);
			if (val2.HasProperty("_BaseColor"))
			{
				val2.SetColor("_BaseColor", val3);
			}
			if (val2.HasProperty("_Color"))
			{
				val2.SetColor("_Color", val3);
			}
			if (val2.HasProperty("_EmissiveColor"))
			{
				val2.SetColor("_EmissiveColor", val3 * 4f);
			}
			if (val2.HasProperty("_EmissionColor"))
			{
				val2.SetColor("_EmissionColor", val3 * 4f);
				val2.EnableKeyword("_EMISSION");
			}
			return val2;
		}

		internal void ToggleFromActivation()
		{
			if (!(Time.unscaledTime - lastToggleTime < 0.65f))
			{
				lastToggleTime = Time.unscaledTime;
				SetLit(!isLit);
			}
		}

		private void SetLit(bool value)
		{
			isLit = value;
			if ((Object)(object)flamesRoot != (Object)null)
			{
				flamesRoot.SetActive(value);
			}
			if ((Object)(object)warmLight != (Object)null)
			{
				((Behaviour)warmLight).enabled = value;
			}
		}

		internal bool CanRelightNearFire()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: 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_0121: Unknown result type (might be due to invalid IL or missing references)
			if (isLit)
			{
				return true;
			}
			Vector3 position = ((Component)this).transform.position;
			MenorahLightMarker[] array = Object.FindObjectsOfType<MenorahLightMarker>();
			foreach (MenorahLightMarker menorahLightMarker in array)
			{
				if ((Object)(object)menorahLightMarker != (Object)null && (Object)(object)menorahLightMarker != (Object)(object)this && menorahLightMarker.IsLit && Vector3.Distance(position, ((Component)menorahLightMarker).transform.position) <= 2.25f)
				{
					return true;
				}
			}
			Collider[] array2 = Physics.OverlapSphere(position, 2.25f, -1, (QueryTriggerInteraction)2);
			foreach (Collider val in array2)
			{
				if (!((Object)(object)val == (Object)null) && LooksLikeFire(((Component)val).transform))
				{
					return true;
				}
			}
			ParticleSystem[] array3 = Object.FindObjectsOfType<ParticleSystem>();
			foreach (ParticleSystem val2 in array3)
			{
				if ((Object)(object)val2 != (Object)null && val2.isPlaying && Vector3.Distance(position, ((Component)val2).transform.position) <= 2.25f && LooksLikeFire(((Component)val2).transform))
				{
					return true;
				}
			}
			MonoBehaviour[] array4 = Object.FindObjectsOfType<MonoBehaviour>();
			foreach (MonoBehaviour val3 in array4)
			{
				if (!((Object)(object)val3 == (Object)null) && !(Vector3.Distance(position, ((Component)val3).transform.position) > 2.25f))
				{
					string text = ((object)val3).GetType().Name.ToLowerInvariant();
					if (!text.Contains("fireexit") && (text.Contains("flame") || text.Contains("campfire") || text.Contains("bonfire") || text.Contains("fireplace") || text.Contains("lighter") || text.Contains("torch")))
					{
						return true;
					}
				}
			}
			return false;
		}

		private static bool LooksLikeFire(Transform transform)
		{
			Transform val = transform;
			while ((Object)(object)val != (Object)null)
			{
				string text = ((Object)val).name.ToLowerInvariant();
				if (!text.Contains("fireexit") && !text.Contains("fire exit") && (text.Contains("flame") || text.Contains("campfire") || text.Contains("bonfire") || text.Contains("fireplace") || text.Contains("lighter") || text.Contains("torch") || text.Contains("candle")))
				{
					return true;
				}
				val = val.parent;
			}
			return false;
		}

		internal void PlayFailedRelightFeedback()
		{
			Plugin.Log.LogInfo((object)"Menorah is extinguished; bring it near an active flame/fire source to relight it.");
		}
	}
	internal sealed class ModConfig
	{
		internal readonly ConfigEntry<int> ShumovkaRarity;

		internal readonly ConfigEntry<int> BaconEggCheeseRarity;

		internal readonly ConfigEntry<int> BalbalRarity;

		internal readonly ConfigEntry<int> TvorogRarity;

		internal readonly ConfigEntry<int> ZubrowkaRarity;

		internal readonly ConfigEntry<int> MoutaiRarity;

		internal readonly ConfigEntry<int> KyivCakeRarity;

		internal readonly ConfigEntry<int> BimbkaRarity;

		internal readonly ConfigEntry<int> HasbullahRarity;

		internal readonly ConfigEntry<int> DoshirakRarity;

		internal readonly ConfigEntry<int> MenorahRarity;

		internal readonly ConfigEntry<float> BlumpkinChancePercent;

		internal readonly ConfigEntry<float> MusicExcerptSeconds;

		internal readonly ConfigEntry<string> BaconEggCheeseEmoteName;

		internal readonly ConfigEntry<string> TvorogEmoteName;

		internal readonly ConfigEntry<float> ShumovkaScale;

		internal readonly ConfigEntry<float> BaconEggCheeseScale;

		internal readonly ConfigEntry<float> BalbalScale;

		internal readonly ConfigEntry<float> BlumpkinScale;

		internal readonly ConfigEntry<float> TvorogScale;

		internal readonly ConfigEntry<float> ZubrowkaScale;

		internal readonly ConfigEntry<float> MoutaiScale;

		internal readonly ConfigEntry<float> KyivCakeScale;

		internal readonly ConfigEntry<float> BimbkaScale;

		internal readonly ConfigEntry<float> HasbullahScale;

		internal readonly ConfigEntry<float> DoshirakScale;

		internal readonly ConfigEntry<float> MenorahScale;

		internal readonly ConfigEntry<float> ShumovkaRollDegrees;

		internal readonly ConfigEntry<float> ModelRotationZDegrees;

		internal readonly ConfigEntry<float> HeldFacingYawDegrees;

		internal ModConfig(ConfigFile config)
		{
			ShumovkaRarity = config.Bind<int>("Spawn", "ShumovkaRarity", 6, "Relative scrap rarity on all moons. Intentionally rare by default.");
			BaconEggCheeseRarity = config.Bind<int>("Spawn", "BaconEggCheeseRarity", 5, "Relative scrap rarity on all moons. Intentionally rare by default.");
			BalbalRarity = config.Bind<int>("Spawn", "BalbalRarity", 3, "Relative scrap rarity on all moons. Very rare by default.");
			TvorogRarity = config.Bind<int>("Spawn", "TvorogRarity", 5, "Relative scrap rarity on all moons. Intentionally rare by default.");
			ZubrowkaRarity = config.Bind<int>("Spawn", "ZubrowkaRarity", 5, "Relative scrap rarity on all moons. Intentionally rare by default.");
			MoutaiRarity = config.Bind<int>("Spawn", "MoutaiRarity", 2, "Relative scrap rarity on all moons. Very rare premium bottle.");
			KyivCakeRarity = config.Bind<int>("Spawn", "KyivCakeRarity", 4, "Relative scrap rarity on all moons. Intentionally rare by default.");
			BimbkaRarity = config.Bind<int>("Spawn", "BimbkaRarity", 3, "Relative scrap rarity on all moons. Heavy and very rare, like Balbal.");
			HasbullahRarity = config.Bind<int>("Spawn", "HasbullahRarity", 1, "Extremely rare two-handed inert scrap.");
			DoshirakRarity = config.Bind<int>("Spawn", "DoshirakRarity", 4, "Rare inert instant-noodle tray scrap.");
			MenorahRarity = config.Bind<int>("Spawn", "MenorahRarity", 3, "Very rare interactive menorah scrap.");
			BlumpkinChancePercent = config.Bind<float>("Spawn", "BlumpkinChancePercent", 1.5f, "Chance per landing to spawn one Blumpkin on pumpkin-eligible moons. It is deliberately rarer than normal custom scrap.");
			MusicExcerptSeconds = config.Bind<float>("Audio", "MusicExcerptSeconds", 0f, "Length of Bacon Egg and Cheese / Tvorog audio used by the item. Set to 0 to play the full source clip (default).");
			BaconEggCheeseEmoteName = config.Bind<string>("TooManyEmotes v2", "BaconEggCheeseEmoteName", "feelin'_jaunty", "One exact TooManyEmotes emote identifier requested by Bacon Egg and Cheese. Upbeat/pop-dance default; no random fallback.");
			TvorogEmoteName = config.Bind<string>("TooManyEmotes v2", "TvorogEmoteName", "smug_dance", "One exact TooManyEmotes emote identifier requested by Tvorog. Smooth/swaying default; no random fallback.");
			ShumovkaScale = config.Bind<float>("Visuals v5", "ShumovkaSizeMultiplier", 1.2f, "Multiplier on the enlarged shovel-class Shumovka target size.");
			BaconEggCheeseScale = config.Bind<float>("Visuals v5", "BaconEggCheeseSizeMultiplier", 1.2f, "Multiplier on the ~0.20 m sandwich target size.");
			BalbalScale = config.Bind<float>("Visuals v5", "BalbalSizeMultiplier", 1.2f, "Multiplier on the ~1.20 m Balbal target size. 1.20 default makes the statue ~1.44 m tall/longest-axis target.");
			BlumpkinScale = config.Bind<float>("Visuals v5", "BlumpkinSizeMultiplier", 1.2f, "Multiplier on the ~0.42 m pumpkin target size.");
			TvorogScale = config.Bind<float>("Visuals v5", "TvorogSizeMultiplier", 1.2f, "Multiplier on the ~0.24 m bowl target size.");
			ZubrowkaScale = config.Bind<float>("Visuals v5", "ZubrowkaSizeMultiplier", 1.2f, "Multiplier on the ~0.33 m bottle target size.");
			MoutaiScale = config.Bind<float>("Visuals v5", "MoutaiSizeMultiplier", 1.2f, "Multiplier on the ~0.25 m bottle target size.");
			KyivCakeScale = config.Bind<float>("Visuals v5", "KyivCakeSizeMultiplier", 1.2f, "Multiplier on the ~0.30 m cake-box target diameter.");
			BimbkaScale = config.Bind<float>("Visuals v5", "BimbkaSizeMultiplier", 1.2f, "Multiplier on the ~0.85 m heavy Bimbka target size.");
			HasbullahScale = config.Bind<float>("Visuals v5", "HasbullahSizeMultiplier", 1.2f, "Multiplier on the ~0.75 m Hasbullah target size.");
			DoshirakScale = config.Bind<float>("Visuals v5", "DoshirakSizeMultiplier", 1.2f, "Multiplier on the ~0.24 m Doshirak tray target size.");
			MenorahScale = config.Bind<float>("Visuals v5", "MenorahSizeMultiplier", 1.2f, "Multiplier on the ~0.55 m menorah target size.");
			ShumovkaRollDegrees = config.Bind<float>("Visuals v5", "ShumovkaRollDegrees", 45f, "Roll around Shumovka's long handle axis. 45 degrees makes the spoon/skimmer bowl perpendicular to the player's torso.");
			ModelRotationZDegrees = config.Bind<float>("Visuals v5", "ModelRotationZDegrees", 0f, "Advanced global model-space Z correction. Leave at 0; floor orientation is now fixed using each Item's resting rotation instead.");
			HeldFacingYawDegrees = config.Bind<float>("Held Poses v1", "HeldFacingYawDegrees", 180f, "Held-only yaw correction for Loquat Scrap Pack items except Shumovka. 180 makes front-facing props face the player while carried; dropped orientation is unaffected.");
		}
	}
	internal static class ModPatches
	{
		internal static bool BeforeNoisemakerActivate(NoisemakerProp __instance, object[] __args)
		{
			try
			{
				if (GetKind((Component)(object)__instance) != LoquatItemKind.Menorah)
				{
					return true;
				}
				if (IsReleaseCallback(__args))
				{
					return true;
				}
				MenorahLightMarker component = ((Component)__instance).GetComponent<MenorahLightMarker>();
				if ((Object)(object)component == (Object)null)
				{
					return true;
				}
				if (component.IsLit || component.CanRelightNearFire())
				{
					return true;
				}
				component.PlayFailedRelightFeedback();
				return false;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogDebug((object)("Menorah activation compatibility fallback: " + ex.GetBaseException().Message));
				return true;
			}
		}

		internal static void BeforeGameNetworkManagerStart()
		{
			try
			{
				ItemFactory.BuildAll();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Loquat item initialization stopped unexpectedly. The game will continue without any remaining Loquat items. " + ex));
			}
		}

		internal static void AfterNoisemakerActivate(NoisemakerProp __instance, object[] __args)
		{
			try
			{
				LoquatItemKind kind = GetKind((Component)(object)__instance);
				switch (kind)
				{
				case LoquatItemKind.Unknown:
					return;
				case LoquatItemKind.Balbal:
					PulseBalbal(__instance);
					break;
				}
				if (kind == LoquatItemKind.Menorah)
				{
					MenorahLightMarker component = ((Component)__instance).GetComponent<MenorahLightMarker>();
					if ((Object)(object)component != (Object)null)
					{
						component.ToggleFromActivation();
					}
				}
				if (!IsReleaseCallback(__args) && (kind == LoquatItemKind.BaconEggCheese || kind == LoquatItemKind.Tvorog))
				{
					object member = ReflectionUtil.GetMember(__instance, "playerHeldBy");
					if ((Object)(object)StartOfRound.Instance != (Object)null && member == StartOfRound.Instance.localPlayerController)
					{
						TooManyEmotesCompat.TryDance((kind == LoquatItemKind.BaconEggCheese) ? Plugin.ModConfig.BaconEggCheeseEmoteName.Value : Plugin.ModConfig.TvorogEmoteName.Value);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogDebug((object)("Loquat noisemaker post-activation hook was skipped: " + ex.GetBaseException().Message));
			}
		}

		internal static void AfterNoisemakerNetworkPlayback(NoisemakerProp __instance)
		{
			try
			{
				switch (GetKind((Component)(object)__instance))
				{
				case LoquatItemKind.Balbal:
					PulseBalbal(__instance);
					break;
				case LoquatItemKind.Menorah:
				{
					MenorahLightMarker component = ((Component)__instance).GetComponent<MenorahLightMarker>();
					if ((Object)(object)component != (Object)null)
					{
						component.ToggleFromActivation();
					}
					break;
				}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogDebug((object)("Remote Loquat noisemaker feedback was skipped: " + ex.GetBaseException().Message));
			}
		}

		internal static void AfterShovelActivate(Shovel __instance)
		{
			try
			{
				if (IsShumovka(__instance))
				{
					object member = ReflectionUtil.GetMember(ReflectionUtil.GetMember(__instance, "playerHeldBy"), "playerBodyAnimator");
					Animator val = (Animator)((member is Animator) ? member : null);
					if (!((Object)(object)val == (Object)null) && ReflectionUtil.GetMember(__instance, "reelingUp") is int num && num != 0)
					{
						val.ResetTrigger("shovelHit");
						val.SetBool("reelingUp", true);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogDebug((object)("Shumovka reel animation compatibility fallback: " + ex.GetBaseException().Message));
			}
		}

		internal static void AfterShovelSwing(Shovel __instance)
		{
			try
			{
				if (IsShumovka(__instance))
				{
					object member = ReflectionUtil.GetMember(ReflectionUtil.GetMember(__instance, "playerHeldBy"), "playerBodyAnimator");
					Animator val = (Animator)((member is Animator) ? member : null);
					if ((Object)(object)val != (Object)null)
					{
						val.SetBool("reelingUp", false);
						val.ResetTrigger("shovelHit");
						val.SetTrigger("shovelHit");
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogDebug((object)("Shumovka swing animation compatibility fallback: " + ex.GetBaseException().Message));
			}
		}

		private static bool IsShumovka(Shovel shovel)
		{
			return GetKind((Component)(object)shovel) == LoquatItemKind.Shumovka;
		}

		private static LoquatItemKind GetKind(Component component)
		{
			if ((Object)(object)component == (Object)null)
			{
				return LoquatItemKind.Unknown;
			}
			LoquatItemMarker component2 = component.GetComponent<LoquatItemMarker>();
			if (!((Object)(object)component2 == (Object)null))
			{
				return component2.Kind;
			}
			return LoquatItemKind.Unknown;
		}

		private static bool IsReleaseCallback(object[] args)
		{
			if (args != null && args.Length != 0 && args[0] is bool && !(bool)args[0])
			{
				return true;
			}
			if (args != null && args.Length > 1 && args[1] is bool && !(bool)args[1])
			{
				return true;
			}
			return false;
		}

		private static void PulseBalbal(NoisemakerProp prop)
		{
			BalbalGlowMarker balbalGlowMarker = (((Object)(object)prop == (Object)null) ? null : ((Component)prop).GetComponent<BalbalGlowMarker>());
			if ((Object)(object)balbalGlowMarker != (Object)null)
			{
				balbalGlowMarker.PulseForCurrentPlayback();
			}
		}

		internal static void AfterSpawnMapObjects()
		{
			try
			{
				BlumpkinSpawner.TrySpawn();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogDebug((object)("Blumpkin spawn attempt skipped: " + ex.GetBaseException().Message));
			}
		}
	}
	[BepInPlugin("sosigelite.loquatscrappack", "Loquat Scrap Pack", "0.3.4")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "sosigelite.loquatscrappack";

		public const string PluginName = "Loquat Scrap Pack";

		public const string PluginVersion = "0.3.4";

		private Harmony harmony;

		internal static Plugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		internal static ModConfig ModConfig { get; private set; }

		internal static string ModDirectory { get; private set; }

		private void Awake()
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			ModDirectory = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
			ModConfig = new ModConfig(((BaseUnityPlugin)this).Config);
			harmony = new Harmony("sosigelite.loquatscrappack");
			if (!TryPatch(typeof(GameNetworkManager), "Start", typeof(ModPatches), "BeforeGameNetworkManagerStart", prefix: true, 800, quietIfMissing: false))
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Could not install the Loquat item-registration hook. The pack will stay disabled for this session, but the game will continue normally.");
			}
			TryPatch(typeof(NoisemakerProp), "ItemActivate", typeof(ModPatches), "BeforeNoisemakerActivate", prefix: true, 200, quietIfMissing: false);
			TryPatch(typeof(NoisemakerProp), "ItemActivate", typeof(ModPatches), "AfterNoisemakerActivate", prefix: false, 200, quietIfMissing: false);
			TryPatchNoisemakerPlaybackRpc();
			TryPatch(typeof(Shovel), "ItemActivate", typeof(ModPatches), "AfterShovelActivate", prefix: false, 200, quietIfMissing: true);
			TryPatch(typeof(Shovel), "SwingShovel", typeof(ModPatches), "AfterShovelSwing", prefix: false, 200, quietIfMissing: true);
			TryPatch(typeof(RoundManager), "SpawnMapObjects", typeof(ModPatches), "AfterSpawnMapObjects", prefix: false, 200, quietIfMissing: true);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Loquat Scrap Pack 0.3.4 loaded.");
		}

		private bool TryPatch(Type targetType, string methodName, Type patchType, string patchName, bool prefix, int priority, bool quietIfMissing)
		{
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Expected O, but got Unknown
			try
			{
				MethodInfo methodInfo = AccessTools.Method(targetType, methodName, (Type[])null, (Type[])null);
				if (methodInfo == null)
				{
					if (!quietIfMissing)
					{
						((BaseUnityPlugin)this).Logger.LogWarning((object)("Patch target " + targetType.Name + "." + methodName + " was not found. Related Loquat functionality will be disabled."));
					}
					else
					{
						((BaseUnityPlugin)this).Logger.LogDebug((object)("Optional patch target " + targetType.Name + "." + methodName + " was not found."));
					}
					return false;
				}
				MethodInfo methodInfo2 = AccessTools.Method(patchType, patchName, (Type[])null, (Type[])null);
				if (methodInfo2 == null)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)("Internal patch method " + patchType.Name + "." + patchName + " was not found."));
					return false;
				}
				HarmonyMethod val = new HarmonyMethod(methodInfo2)
				{
					priority = priority
				};
				harmony.Patch((MethodBase)methodInfo, prefix ? val : null, prefix ? null : val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				return true;
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not patch " + targetType.Name + "." + methodName + "; related Loquat functionality will be disabled. " + ex.GetBaseException().Message));
				return false;
			}
		}

		private void TryPatchNoisemakerPlaybackRpc()
		{
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Expected O, but got Unknown
			try
			{
				MethodInfo methodInfo = (from method in typeof(NoisemakerProp).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
					where method.Name.IndexOf("ClientRpc", StringComparison.OrdinalIgnoreCase) >= 0
					where method.Name.IndexOf("Noise", StringComparison.OrdinalIgnoreCase) >= 0 || method.Name.IndexOf("Sound", StringComparison.OrdinalIgnoreCase) >= 0
					orderby string.Equals(method.Name, "PlayNoiseClientRpc", StringComparison.Ordinal) descending
					select method).FirstOrDefault();
				if (methodInfo == null)
				{
					((BaseUnityPlugin)this).Logger.LogDebug((object)"No compatible NoisemakerProp playback ClientRpc was found; remote Loquat noisemaker visual feedback is disabled.");
					return;
				}
				HarmonyMethod val = new HarmonyMethod(AccessTools.Method(typeof(ModPatches), "AfterNoisemakerNetworkPlayback", (Type[])null, (Type[])null))
				{
					priority = 200
				};
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				((BaseUnityPlugin)this).Logger.LogDebug((object)("Remote noisemaker feedback attached to " + methodInfo.Name + "."));
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogDebug((object)("Remote noisemaker feedback could not be patched and was disabled: " + ex.GetBaseException().Message));
			}
		}
	}
	internal static class ReflectionUtil
	{
		private const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		internal static bool SetMember(object target, string name, object value)
		{
			if (target == null || string.IsNullOrEmpty(name))
			{
				return false;
			}
			try
			{
				Type type = ((target is Type) ? ((Type)target) : target.GetType());
				object obj = ((target is Type) ? null : target);
				FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					field.SetValue(obj, value);
					return true;
				}
				PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (property != null && property.CanWrite)
				{
					property.SetValue(obj, value, null);
					return true;
				}
			}
			catch
			{
			}
			return false;
		}

		internal static object GetMember(object target, string name)
		{
			if (target == null || string.IsNullOrEmpty(name))
			{
				return null;
			}
			try
			{
				Type type = ((target is Type) ? ((Type)target) : target.GetType());
				object obj = ((target is Type) ? null : target);
				FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					return field.GetValue(obj);
				}
				PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (property != null && property.CanRead)
				{
					return property.GetValue(obj, null);
				}
			}
			catch
			{
			}
			return null;
		}

		internal static T GetMember<T>(object target, string name) where T : class
		{
			return GetMember(target, name) as T;
		}
	}
	internal static class RuntimeAssets
	{
		internal sealed class VisualPart
		{
			internal string Name;

			internal Mesh Mesh;

			internal Material Material;

			internal bool Transparent;
		}

		private static string AssetRoot => Path.Combine(Plugin.ModDirectory, "AssetsData");

		internal static Mesh LoadMesh(string assetName)
		{
			return LoadMeshFile(Path.Combine(AssetRoot, "Meshes", assetName + ".meshbin"), "FGS_" + assetName);
		}

		private static Mesh LoadMeshFile(string path, string meshName)
		{
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Expected O, but got Unknown
			using FileStream input = File.OpenRead(path);
			using BinaryReader binaryReader = new BinaryReader(input);
			if (Encoding.ASCII.GetString(binaryReader.ReadBytes(4)) != "FGSM")
			{
				throw new InvalidDataException("Invalid mesh file: " + path);
			}
			uint num = binaryReader.ReadUInt32();
			if (num != 1)
			{
				throw new InvalidDataException($"Unsupported FGSM mesh version {num}: {path}");
			}
			int num2;
			int num3;
			Vector3[] array;
			Vector3[] array2;
			Vector2[] array3;
			int[] array4;
			checked
			{
				num2 = (int)binaryReader.ReadUInt32();
				num3 = (int)binaryReader.ReadUInt32();
				array = (Vector3[])(object)new Vector3[num2];
				array2 = (Vector3[])(object)new Vector3[num2];
				array3 = (Vector2[])(object)new Vector2[num2];
				array4 = new int[num3];
			}
			for (int i = 0; i < num2; i++)
			{
				array[i] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
			}
			for (int j = 0; j < num2; j++)
			{
				array2[j] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
			}
			for (int k = 0; k < num2; k++)
			{
				array3[k] = new Vector2(binaryReader.ReadSingle(), binaryReader.ReadSingle());
			}
			for (int l = 0; l < num3; l++)
			{
				array4[l] = checked((int)binaryReader.ReadUInt32());
			}
			Mesh val = new Mesh
			{
				name = meshName,
				indexFormat = (IndexFormat)(num2 > 65535)
			};
			val.vertices = array;
			val.normals = array2;
			val.uv = array3;
			val.triangles = array4;
			val.RecalculateBounds();
			try
			{
				val.RecalculateTangents();
			}
			catch
			{
			}
			return val;
		}

		internal static bool HasVisualParts(string assetName)
		{
			return File.Exists(Path.Combine(AssetRoot, "Parts", assetName, "parts.tsv"));
		}

		internal static List<VisualPart> LoadVisualParts(string assetName)
		{
			string path = Path.Combine(AssetRoot, "Parts", assetName);
			string path2 = Path.Combine(path, "parts.tsv");
			if (!File.Exists(path2))
			{
				return new List<VisualPart>();
			}
			List<VisualPart> list = new List<VisualPart>();
			string[] array = File.ReadAllLines(path2);
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (text.Length != 0 && !text.StartsWith("#"))
				{
					string[] array2 = text.Split('|');
					if (array2.Length < 6)
					{
						throw new InvalidDataException("Invalid visual-part line for " + assetName + ": " + text);
					}
					string text2 = array2[0];
					string path3 = Path.Combine(path, array2[1]);
					string texturePath = Path.Combine(path, array2[2]);
					bool transparent = array2[3] == "1";
					if (!float.TryParse(array2[4], NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
					{
						result = 0.35f;
					}
					bool doubleSided = array2[5] == "1";
					list.Add(new VisualPart
					{
						Name = text2,
						Mesh = LoadMeshFile(path3, "FGS_" + assetName + "_" + text2),
						Material = CreatePartMaterial(assetName, text2, texturePath, transparent, result, doubleSided),
						Transparent = transparent
					});
				}
			}
			return list;
		}

		internal static Texture2D LoadTexture(string assetName, string suffix, bool linear)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			//IL_0068: Expected O, but got Unknown
			string path = Path.Combine(AssetRoot, "Textures", assetName + "_" + suffix + ".png");
			if (!File.Exists(path))
			{
				return null;
			}
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true, linear)
			{
				name = "FGS_" + assetName + "_" + suffix,
				wrapMode = (TextureWrapMode)0,
				filterMode = (FilterMode)1
			};
			ImageConversion.LoadImage(val, File.ReadAllBytes(path));
			return val;
		}

		private static Texture2D LoadTextureFile(string path, string textureName)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_002d: Expected O, but got Unknown
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true, false)
			{
				name = textureName,
				wrapMode = (TextureWrapMode)1,
				filterMode = (FilterMode)1
			};
			ImageConversion.LoadImage(val, File.ReadAllBytes(path));
			return val;
		}

		private static Material CreatePartMaterial(string assetName, string partName, string texturePath, bool transparent, float smoothness, bool doubleSided)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			Shader obj = Shader.Find("HDRP/Lit") ?? Shader.Find("Standard");
			if ((Object)(object)obj == (Object)null)
			{
				throw new InvalidOperationException("Could not find HDRP/Lit or Standard shader.");
			}
			Material val = new Material(obj);
			((Object)val).name = "FGS_" + assetName + "_" + partName + "_Material";
			Material val2 = val;
			Texture2D val3 = LoadTextureFile(texturePath, "FGS_" + assetName + "_" + partName + "_Base");
			if (val2.HasProperty("_BaseColorMap"))
			{
				val2.SetTexture("_BaseColorMap", (Texture)(object)val3);
			}
			if (val2.HasProperty("_MainTex"))
			{
				val2.SetTexture("_MainTex", (Texture)(object)val3);
			}
			if (val2.HasProperty("_BaseColor"))
			{
				val2.SetColor("_BaseColor", Color.white);
			}
			if (val2.HasProperty("_Color"))
			{
				val2.SetColor("_Color", Color.white);
			}
			if (val2.HasProperty("_Smoothness"))
			{
				val2.SetFloat("_Smoothness", smoothness);
			}
			if (val2.HasProperty("_Glossiness"))
			{
				val2.SetFloat("_Glossiness", smoothness);
			}
			if (doubleSided)
			{
				val2.doubleSidedGI = true;
				if (val2.HasProperty("_DoubleSidedEnable"))
				{
					val2.SetFloat("_DoubleSidedEnable", 1f);
				}
				if (val2.HasProperty("_CullMode"))
				{
					val2.SetFloat("_CullMode", 0f);
				}
				if (val2.HasProperty("_Cull"))
				{
					val2.SetFloat("_Cull", 0f);
				}
				val2.EnableKeyword("_DOUBLESIDED_ON");
			}
			if (transparent)
			{
				ConfigureTransparentMaterial(val2);
			}
			return val2;
		}

		private static void ConfigureTransparentMaterial(Material material)
		{
			material.SetOverrideTag("RenderType", "Transparent");
			material.renderQueue = 3000;
			if (material.HasProperty("_SurfaceType"))
			{
				material.SetFloat("_SurfaceType", 1f);
			}
			if (material.HasProperty("_BlendMode"))
			{
				material.SetFloat("_BlendMode", 0f);
			}
			if (material.HasProperty("_SrcBlend"))
			{
				material.SetFloat("_SrcBlend", 5f);
			}
			if (material.HasProperty("_DstBlend"))
			{
				material.SetFloat("_DstBlend", 10f);
			}
			if (material.HasProperty("_ZWrite"))
			{
				material.SetFloat("_ZWrite", 0f);
			}
			if (material.HasProperty("_AlphaDstBlend"))
			{
				material.SetFloat("_AlphaDstBlend", 10f);
			}
			material.EnableKeyword("_SURFACE_TYPE_TRANSPARENT");
			material.EnableKeyword("_BLENDMODE_ALPHA");
			material.EnableKeyword("_ALPHABLEND_ON");
			material.DisableKeyword("_ALPHATEST_ON");
			material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
		}

		internal static Material CreateMaterial(string assetName)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			Shader obj = Shader.Find("HDRP/Lit") ?? Shader.Find("Standard");
			if ((Object)(object)obj == (Object)null)
			{
				throw new InvalidOperationException("Could not find HDRP/Lit or Standard shader.");
			}
			Material val = new Material(obj)
			{
				name = "FGS_" + assetName + "_Material"
			};
			Texture2D val2 = LoadTexture(assetName, "Base", linear: false);
			Texture2D val3 = LoadTexture(assetName, "Normal", linear: true);
			Texture2D val4 = LoadTexture(assetName, "Mask", linear: true);
			if ((Object)(object)val2 != (Object)null)
			{
				if (val.HasProperty("_BaseColorMap"))
				{
					val.SetTexture("_BaseColorMap", (Texture)(object)val2);
				}
				if (val.HasProperty("_MainTex"))
				{
					val.SetTexture("_MainTex", (Texture)(object)val2);
				}
			}
			if (val.HasProperty("_BaseColor"))
			{
				val.SetColor("_BaseColor", Color.white);
			}
			if (val.HasProperty("_Color"))
			{
				val.SetColor("_Color", Color.white);
			}
			float num = 0.35f;
			switch (assetName)
			{
			case "Zubrowka":
				num = 0.72f;
				break;
			case "Moutai":
				num = 0.48f;
				break;
			case "KyivCake":
				num = 0.18f;
				break;
			case "Hasbullah":
				num = 0.3f;
				break;
			case "Doshirak":
				num = 0.22f;
				break;
			case "Menorah":
				num = 0.68f;
				break;
			case "Shumovka":
				num = 0.38f;
				break;
			}
			if (val.HasProperty("_Smoothness"))
			{
				val.SetFloat("_Smoothness", num);
			}
			if (val.HasProperty("_Glossiness"))
			{
				val.SetFloat("_Glossiness", num);
			}
			if ((Object)(object)val3 != (Object)null)
			{
				if (val.HasProperty("_NormalMap"))
				{
					val.SetTexture("_NormalMap", (Texture)(object)val3);
					val.SetFloat("_NormalScale", 1f);
					val.EnableKeyword("_NORMALMAP_TANGENT_SPACE");
				}
				if (val.HasProperty("_BumpMap"))
				{
					val.SetTexture("_BumpMap", (Texture)(object)val3);
					val.SetFloat("_BumpScale", 1f);
					val.EnableKeyword("_NORMALMAP");
				}
			}
			if ((Object)(object)val4 != (Object)null && val.HasProperty("_MaskMap"))
			{
				val.SetTexture("_MaskMap", (Texture)(object)val4);
			}
			return val;
		}

		internal static AudioClip LoadWav(string fileName, float maxSeconds = 0f)
		{
			byte[] array = File.ReadAllBytes(Path.Combine(AssetRoot, "Audio", fileName));
			int num = 12;
			short num2 = 0;
			short num3 = 0;
			int num4 = 0;
			short num5 = 0;
			int num6 = -1;
			int num7 = 0;
			if (Encoding.ASCII.GetString(array, 0, 4) != "RIFF" || Encoding.ASCII.GetString(array, 8, 4) != "WAVE")
			{
				throw new InvalidDataException(fileName + " is not a RIFF/WAVE file.");
			}
			while (num + 8 <= array.Length)
			{
				string text = Encoding.ASCII.GetString(array, num, 4);
				int num8 = BitConverter.ToInt32(array, num + 4);
				int num