Decompiled source of Pitchit v0.1.1

plugins/Pitchit/Pitchit.dll

Decompiled 11 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: InternalsVisibleTo("Pitchit.RuntimeProbe")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("Pitchit")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.1.0")]
[assembly: AssemblyInformationalVersion("0.1.1")]
[assembly: AssemblyProduct("Pitchit")]
[assembly: AssemblyTitle("Pitchit")]
[assembly: AssemblyVersion("0.1.1.0")]
[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 Pitchit
{
	internal static class Coating
	{
		internal const string Key = "smeagsmods.pitchit.coated.v1";

		internal const string Lease = "smeagsmods.pitchit.lease.v1";

		internal const string Rpc = "Pitchit_Request_v1";

		private static readonly Func<WearNTear, bool> NativeWet = AccessTools.MethodDelegate<Func<WearNTear, bool>>(AccessTools.Method(typeof(WearNTear), "IsWet", (Type[])null, (Type[])null), (object)null, true);

		private static readonly Func<WearNTear, bool> Underwater = AccessTools.MethodDelegate<Func<WearNTear, bool>>(AccessTools.Method(typeof(WearNTear), "IsUnderWater", (Type[])null, (Type[])null), (object)null, true);

		private static readonly Func<PrivateArea, long, bool> Permitted = AccessTools.MethodDelegate<Func<PrivateArea, long, bool>>(AccessTools.Method(typeof(PrivateArea), "IsPermitted", (Type[])null, (Type[])null), (object)null, true);

		private static readonly Func<PrivateArea, bool> Enabled = AccessTools.MethodDelegate<Func<PrivateArea, bool>>(AccessTools.Method(typeof(PrivateArea), "IsEnabled", (Type[])null, (Type[])null), (object)null, true);

		private static readonly Func<PrivateArea, Vector3, float, bool> Inside = AccessTools.MethodDelegate<Func<PrivateArea, Vector3, float, bool>>(AccessTools.Method(typeof(PrivateArea), "IsInside", (Type[])null, (Type[])null), (object)null, true);

		private static readonly FieldInfo Areas = AccessTools.Field(typeof(PrivateArea), "m_allAreas");

		private static WearNTear pending;

		private static ItemData pendingItem;

		private static string token;

		private static float deadline;

		private static long Now
		{
			get
			{
				if (!((Object)(object)ZNet.instance == (Object)null))
				{
					return ZNet.instance.GetTime().Ticks;
				}
				return 0L;
			}
		}

		internal static bool IsCoated(WearNTear w)
		{
			ZNetView val = (Object.op_Implicit((Object)(object)w) ? ((Component)w).GetComponent<ZNetView>() : null);
			if (Object.op_Implicit((Object)(object)val) && val.IsValid())
			{
				return val.GetZDO().GetInt("smeagsmods.pitchit.coated.v1", 0) == 1;
			}
			return false;
		}

		internal static bool WetForWear(WearNTear w)
		{
			if (!Plugin.Running || !IsCoated(w))
			{
				return NativeWet(w);
			}
			return Underwater(w);
		}

		internal static bool Eligible(WearNTear w)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Invalid comparison between Unknown and I4
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Invalid comparison between Unknown and I4
			if (!Object.op_Implicit((Object)(object)w) || !w.m_noRoofWear)
			{
				return false;
			}
			if ((int)w.m_materialType != 0 && (int)w.m_materialType != 3 && (int)w.m_materialType != 8)
			{
				return false;
			}
			Piece component = ((Component)w).GetComponent<Piece>();
			ZNetView component2 = ((Component)w).GetComponent<ZNetView>();
			if (Object.op_Implicit((Object)(object)component) && component.IsPlacedByPlayer() && Object.op_Implicit((Object)(object)component2))
			{
				return component2.IsValid();
			}
			return false;
		}

		internal static bool Access(WearNTear w, Player p)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			foreach (PrivateArea item in (List<PrivateArea>)Areas.GetValue(null))
			{
				if (Object.op_Implicit((Object)(object)item) && Enabled(item) && Inside(item, ((Component)w).transform.position, 0f))
				{
					Piece component = ((Component)item).GetComponent<Piece>();
					if ((!Object.op_Implicit((Object)(object)component) || component.GetCreator() != p.GetPlayerID()) && !Permitted(item, p.GetPlayerID()))
					{
						return false;
					}
				}
			}
			return true;
		}

		internal static bool Reach(WearNTear w, Player p)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: 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_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_0039: 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)
			float maxInteractDistance = p.m_maxInteractDistance;
			Vector3 eyePoint = ((Character)p).GetEyePoint();
			Collider[] componentsInChildren = ((Component)w).GetComponentsInChildren<Collider>();
			foreach (Collider val in componentsInChildren)
			{
				if (val.enabled && !val.isTrigger)
				{
					Vector3 val2 = val.ClosestPoint(eyePoint) - eyePoint;
					if (((Vector3)(ref val2)).sqrMagnitude < maxInteractDistance * maxInteractDistance)
					{
						return true;
					}
				}
			}
			return false;
		}

		private static bool Targeted(WearNTear w, Player p)
		{
			GameObject hoverObject = ((Humanoid)p).GetHoverObject();
			if (Object.op_Implicit((Object)(object)hoverObject) && (Object)(object)hoverObject.GetComponentInParent<WearNTear>() == (Object)(object)w)
			{
				return Reach(w, p);
			}
			return false;
		}

		private static bool Reserved(ZNetView v)
		{
			string[] array = v.GetZDO().GetString("smeagsmods.pitchit.lease.v1", "").Split(new char[1] { '|' });
			if (array.Length == 2 && long.TryParse(array[1], out var result) && result > Now)
			{
				return result - Now <= 50000000;
			}
			return false;
		}

		internal static void Attach(WearNTear w)
		{
			ZNetView component = ((Component)w).GetComponent<ZNetView>();
			if (Object.op_Implicit((Object)(object)component) && component.IsValid())
			{
				component.Register<ZDOID, string>("Pitchit_Request_v1", (Action<long, ZDOID, string>)delegate(long sender, ZDOID id, string t)
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					Request(w, sender, id, t);
				});
			}
		}

		private static void Request(WearNTear w, long sender, ZDOID id, string t)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			ZNetView val = (Object.op_Implicit((Object)(object)w) ? ((Component)w).GetComponent<ZNetView>() : null);
			if (Plugin.Running && Object.op_Implicit((Object)(object)val) && val.IsValid() && val.IsOwner() && Eligible(w) && !IsCoated(w) && !Reserved(val) && !string.IsNullOrEmpty(t) && t.Length == 32)
			{
				GameObject val2 = ZNetScene.instance.FindInstance(id);
				Player val3 = (Object.op_Implicit((Object)(object)val2) ? val2.GetComponent<Player>() : null);
				ZNetView val4 = (Object.op_Implicit((Object)(object)val3) ? ((Component)val3).GetComponent<ZNetView>() : null);
				if (Object.op_Implicit((Object)(object)val3) && Object.op_Implicit((Object)(object)val4) && val4.IsValid() && val4.GetZDO().GetOwner() == sender && !((Character)val3).IsDead() && Reach(w, val3) && Access(w, val3))
				{
					val.GetZDO().Set("smeagsmods.pitchit.lease.v1", t + "|" + (Now + 50000000));
					val.GetZDO().SetOwner(sender);
					ZDOMan.instance.ForceSendZDO(sender, val.GetZDO().m_uid);
				}
			}
		}

		internal static void Use(Player p, Inventory inv, ItemData item, bool gui)
		{
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)p) || (Object)(object)p != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			if (gui)
			{
				Say(p, "Put pitch on the hotbar, look at a wooden piece and press its slot.");
			}
			else
			{
				if (((Character)p).IsDead() || ((Character)p).IsTeleporting() || ((Character)p).InAttack() || (inv != null && inv != ((Humanoid)p).GetInventory()) || !((Humanoid)p).GetInventory().ContainsItem(item))
				{
					return;
				}
				GameObject hoverObject = ((Humanoid)p).GetHoverObject();
				WearNTear val = (Object.op_Implicit((Object)(object)hoverObject) ? hoverObject.GetComponentInParent<WearNTear>() : null);
				if (!Eligible(val) || !Targeted(val, p))
				{
					Say(p, "Aim at a nearby player-built wooden piece that takes rain damage.");
					return;
				}
				if (!Access(val, p))
				{
					Say(p, "You do not have permission in this ward.");
					return;
				}
				if (IsCoated(val))
				{
					Say(p, "This piece is already rainproof. Your pitch was kept.");
					return;
				}
				ZNetView component = ((Component)val).GetComponent<ZNetView>();
				if (Object.op_Implicit((Object)(object)pending) || Reserved(component))
				{
					Say(p, "A coating request is already pending. Your pitch was kept.");
					return;
				}
				if (component.IsOwner())
				{
					Apply(val, p, item);
					return;
				}
				pending = val;
				pendingItem = item;
				token = Guid.NewGuid().ToString("N");
				deadline = Time.unscaledTime + 5f;
				component.InvokeRPC("Pitchit_Request_v1", new object[2]
				{
					((Character)p).GetZDOID(),
					token
				});
			}
		}

		internal static void Tick()
		{
			if (!Object.op_Implicit((Object)(object)pending))
			{
				return;
			}
			WearNTear val = pending;
			Player localPlayer = Player.m_localPlayer;
			ZNetView component = ((Component)val).GetComponent<ZNetView>();
			if (!Plugin.Running || !Object.op_Implicit((Object)(object)localPlayer) || !Object.op_Implicit((Object)(object)component) || !component.IsValid() || Time.unscaledTime > deadline)
			{
				Cancel();
				if (Object.op_Implicit((Object)(object)localPlayer))
				{
					Say(localPlayer, "Coating timed out; your pitch was kept.");
				}
			}
			else if (component.IsOwner() && Reserved(component) && component.GetZDO().GetString("smeagsmods.pitchit.lease.v1", "").StartsWith(token + "|", StringComparison.Ordinal))
			{
				if (!((Character)localPlayer).IsDead() && !((Character)localPlayer).IsTeleporting() && !((Character)localPlayer).InAttack() && Targeted(val, localPlayer))
				{
					Apply(val, localPlayer, pendingItem);
				}
				component.GetZDO().Set("smeagsmods.pitchit.lease.v1", "");
				Cancel();
			}
		}

		internal static bool Apply(WearNTear w, Player p, ItemData item)
		{
			if (!Eligible(w) || IsCoated(w) || !Object.op_Implicit((Object)(object)p) || !Targeted(w, p) || !Access(w, p) || Grades.Get(item) == null)
			{
				return false;
			}
			ZNetView component = ((Component)w).GetComponent<ZNetView>();
			ZNetView component2 = ((Component)p).GetComponent<ZNetView>();
			Inventory inventory = ((Humanoid)p).GetInventory();
			if (!component.IsOwner() || !Object.op_Implicit((Object)(object)component2) || !component2.IsValid() || !component2.IsOwner() || !inventory.ContainsItem(item) || item.m_stack < 1)
			{
				return false;
			}
			if (!inventory.RemoveItem(item, 1))
			{
				return false;
			}
			component.GetZDO().Set("smeagsmods.pitchit.coated.v1", 1);
			Say(p, "Rainproofed. This piece will not need recoating.");
			return true;
		}

		private static void Say(Player p, string s)
		{
			((Character)p).Message((MessageType)2, s, 0, (Sprite)null, false);
		}

		internal static void Cancel()
		{
			pending = null;
			pendingItem = null;
			token = null;
		}
	}
	internal sealed class Grade
	{
		internal string Prefab;

		internal string Name;

		internal Color Color;

		internal int Amount;

		internal Ingredient[] Ingredients;

		internal Grade(string id, string name, Color c, int amount, params Ingredient[] ingredients)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			Prefab = id;
			Name = name;
			Color = c;
			Amount = amount;
			Ingredients = ingredients;
		}
	}
	internal sealed class Ingredient
	{
		internal string Prefab;

		internal int Amount;

		internal Ingredient(string id, int n)
		{
			Prefab = id;
			Amount = n;
		}
	}
	internal static class Grades
	{
		internal static readonly Grade[] All = new Grade[3]
		{
			new Grade("Pitchit_ResinPitch", "Resin pitch", new Color(0.8f, 0.47f, 0.12f), 3, new Ingredient("Resin", 4)),
			new Grade("Pitchit_TarPitch", "Tar pitch", new Color(0.24f, 0.16f, 0.1f), 6, new Ingredient("Resin", 4), new Ingredient("Tar", 2)),
			new Grade("Pitchit_SapPitch", "Sap pitch", new Color(0.36f, 0.75f, 0.57f), 9, new Ingredient("Resin", 4), new Ingredient("Tar", 2), new Ingredient("Sap", 2))
		};

		internal static Grade Get(ItemData item)
		{
			if ((Object)(object)item?.m_dropPrefab == (Object)null)
			{
				return null;
			}
			Grade[] all = All;
			foreach (Grade grade in all)
			{
				if (((Object)item.m_dropPrefab).name == grade.Prefab)
				{
					return grade;
				}
			}
			return null;
		}
	}
	[BepInPlugin("smeagsmods.pitchit", "Pitchit", "0.1.1")]
	public sealed class Plugin : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(ObjectDB), "Awake")]
		private class DB
		{
			private static void Postfix(ObjectDB __instance)
			{
				Registration.RegisterItems(__instance);
			}
		}

		[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
		private class DBCopy
		{
			private static void Postfix(ObjectDB __instance)
			{
				Registration.RegisterItems(__instance);
			}
		}

		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		private class Scene
		{
			private static void Postfix(ZNetScene __instance)
			{
				Registration.RegisterNetwork(__instance);
			}
		}

		[HarmonyPatch(typeof(WearNTear), "Awake")]
		private class WearAwake
		{
			private static void Postfix(WearNTear __instance)
			{
				Coating.Attach(__instance);
			}
		}

		[HarmonyPatch(typeof(Humanoid), "UseItem")]
		private class Use
		{
			private static bool Prefix(Humanoid __instance, Inventory inventory, ItemData item, bool fromInventoryGui)
			{
				if (!Running || Grades.Get(item) == null)
				{
					return true;
				}
				Coating.Use((Player)(object)((__instance is Player) ? __instance : null), inventory, item, fromInventoryGui);
				return false;
			}
		}

		[HarmonyPatch(typeof(WearNTear), "UpdateWear")]
		private class Weather
		{
			private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> source)
			{
				List<CodeInstruction> list = source.ToList();
				MethodInfo wet = AccessTools.Method(typeof(WearNTear), "IsWet", (Type[])null, (Type[])null);
				CodeInstruction[] array = list.Where((CodeInstruction c) => CodeInstructionExtensions.Calls(c, wet)).ToArray();
				if (array.Length != 1)
				{
					throw new InvalidOperationException("Pitchit native weather layout changed; refusing unsafe patch.");
				}
				array[0].opcode = OpCodes.Call;
				array[0].operand = AccessTools.Method(typeof(Coating), "WetForWear", (Type[])null, (Type[])null);
				return list;
			}
		}

		public const string Id = "smeagsmods.pitchit";

		internal static Plugin Instance;

		private Harmony harmony;

		private bool quitting;

		internal static bool Running
		{
			get
			{
				if ((Object)(object)Instance != (Object)null)
				{
					return ((Behaviour)Instance).isActiveAndEnabled;
				}
				return false;
			}
		}

		private void Awake()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			Instance = this;
			harmony = new Harmony("smeagsmods.pitchit");
			harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Pitchit 0.1.1 loaded. All peers require the same mod version.");
		}

		private void Update()
		{
			Coating.Tick();
		}

		private void OnApplicationQuit()
		{
			quitting = true;
		}

		private void OnDisable()
		{
			Coating.Cancel();
		}

		private void OnDestroy()
		{
			Coating.Cancel();
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			Registration.Dispose(quitting);
			Instance = null;
		}

		internal static void Warn(string s)
		{
			Plugin instance = Instance;
			if (instance != null)
			{
				((BaseUnityPlugin)instance).Logger.LogWarning((object)s);
			}
		}
	}
	internal static class Registration
	{
		private static GameObject root;

		private static readonly Dictionary<string, GameObject> prefabs = new Dictionary<string, GameObject>();

		private static readonly List<Object> owned = new List<Object>();

		private static readonly List<Recipe> recipes = new List<Recipe>();

		private static readonly List<ObjectDB> databases = new List<ObjectDB>();

		private static readonly MethodInfo updateRegisters = AccessTools.Method(typeof(ObjectDB), "UpdateRegisters", (Type[])null, (Type[])null);

		private static readonly FieldInfo namedPrefabs = AccessTools.Field(typeof(ZNetScene), "m_namedPrefabs");

		internal static void RegisterItems(ObjectDB db)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Expected O, but got Unknown
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Expected O, but got Unknown
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Expected O, but got Unknown
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.Running || (Object)(object)db == (Object)null || (Object)(object)db.GetItemPrefab("Resin") == (Object)null)
			{
				return;
			}
			if (!databases.Contains(db))
			{
				databases.Add(db);
			}
			if ((Object)(object)root == (Object)null)
			{
				root = new GameObject("Pitchit_Prefabs");
				root.SetActive(false);
				Object.DontDestroyOnLoad((Object)(object)root);
			}
			Grade[] all = Grades.All;
			foreach (Grade grade in all)
			{
				if (!prefabs.TryGetValue(grade.Prefab, out var value))
				{
					if ((Object)(object)db.GetItemPrefab(grade.Prefab) != (Object)null)
					{
						throw new InvalidOperationException("Pitchit prefab name is already registered: " + grade.Prefab);
					}
					value = Object.Instantiate<GameObject>(db.GetItemPrefab("Resin"), root.transform, false);
					((Object)value).name = grade.Prefab;
					value.transform.localPosition = Vector3.zero;
					value.transform.localRotation = Quaternion.identity;
					ItemDrop component = value.GetComponent<ItemDrop>();
					ItemData val = new ItemData();
					val.m_dropPrefab = value;
					SharedData val2 = new SharedData();
					val2.m_name = grade.Name;
					val2.m_description = "Permanent rain protection for one player-built wooden piece. Look at the piece and press this hotbar slot. Does not repair, prevent combat/structural damage or stop submersion damage. Higher grades craft more doses. Workbench batch: " + grade.Amount + " pieces.";
					val2.m_itemType = (ItemType)1;
					val2.m_icons = (Sprite[])(object)new Sprite[1] { MakeIcon(grade) };
					val2.m_maxStackSize = 100;
					val2.m_weight = 0.1f;
					val2.m_maxQuality = 1;
					val2.m_autoStack = true;
					val2.m_teleportable = true;
					val.m_shared = val2;
					component.m_itemData = val;
					component.m_autoPickup = true;
					MeshRenderer[] componentsInChildren = value.GetComponentsInChildren<MeshRenderer>(true);
					foreach (MeshRenderer val3 in componentsInChildren)
					{
						Material[] sharedMaterials = ((Renderer)val3).sharedMaterials;
						for (int k = 0; k < sharedMaterials.Length; k++)
						{
							if (!((Object)(object)sharedMaterials[k] == (Object)null))
							{
								Material val4 = new Material(sharedMaterials[k])
								{
									name = grade.Prefab + "_Placeholder"
								};
								if (val4.HasProperty("_Color"))
								{
									val4.SetColor("_Color", grade.Color);
								}
								sharedMaterials[k] = val4;
								owned.Add((Object)(object)val4);
							}
						}
						((Renderer)val3).sharedMaterials = sharedMaterials;
					}
					prefabs.Add(grade.Prefab, value);
				}
				if (!db.m_items.Contains(value))
				{
					db.m_items.Add(value);
				}
			}
			updateRegisters.Invoke(db, null);
			AddRecipes(db);
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				AddNetworkPrefabs(ZNetScene.instance);
			}
		}

		private static Sprite MakeIcon(Grade salt)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: 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: Expected O, but got Unknown
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: 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_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: 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_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: 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)
			Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false)
			{
				name = salt.Prefab + "_Icon",
				filterMode = (FilterMode)1
			};
			Color[] array = (Color[])(object)new Color[4096];
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					bool num = i >= 12 && i <= 43 && j >= 12 + (43 - i) / 12 && j <= 51 - (43 - i) / 12;
					bool flag = i >= 41 && i <= 47 && j >= 10 && j <= 53;
					bool flag2 = j >= 36 && j <= 41 && i >= 43 && i <= 61;
					if (num)
					{
						array[i * 64 + j] = Color.Lerp(salt.Color * 0.45f, salt.Color, (float)(j - 12) / 40f);
					}
					if (flag)
					{
						array[i * 64 + j] = new Color(0.72f, 0.57f, 0.3f);
					}
					if (flag2)
					{
						array[i * 64 + j] = new Color(0.6f, 0.35f, 0.16f);
					}
					int num2 = Array.IndexOf(Grades.All, salt) + 1;
					for (int k = 0; k < num2; k++)
					{
						if (j >= 22 + k * 7 && j <= 25 + k * 7 && i >= 22 && i <= 33)
						{
							array[i * 64 + j] = new Color(1f, 0.9f, 0.6f);
						}
					}
				}
			}
			val.SetPixels(array);
			val.Apply();
			Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 64f);
			owned.Add((Object)(object)val);
			owned.Add((Object)(object)val2);
			return val2;
		}

		private static void AddRecipes(ObjectDB db)
		{
			CraftingStation val = (from r in db.m_recipes
				where (Object)(object)r != (Object)null && (Object)(object)r.m_craftingStation != (Object)null
				select r.m_craftingStation).FirstOrDefault((Func<CraftingStation, bool>)((CraftingStation s) => ((Object)s).name == "piece_workbench"));
			if ((Object)(object)val == (Object)null && (Object)(object)ZNetScene.instance != (Object)null)
			{
				GameObject prefab = ZNetScene.instance.GetPrefab("piece_workbench");
				val = ((prefab != null) ? prefab.GetComponent<CraftingStation>() : null);
			}
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Grade[] all = Grades.All;
			foreach (Grade salt in all)
			{
				string name = "Recipe_" + salt.Prefab;
				if (db.m_recipes.Any((Recipe r) => (Object)(object)r != (Object)null && ((Object)r).name == name))
				{
					continue;
				}
				GameObject[] source = salt.Ingredients.Select((Ingredient r) => db.GetItemPrefab(r.Prefab)).ToArray();
				if (source.Any((GameObject p) => (Object)(object)p == (Object)null))
				{
					Plugin.Warn("Recipe deferred: missing ingredient for " + name);
					continue;
				}
				Recipe val2 = ((IEnumerable<Recipe>)recipes).FirstOrDefault((Func<Recipe, bool>)((Recipe r) => ((Object)r).name == name));
				if ((Object)(object)val2 == (Object)null)
				{
					val2 = ScriptableObject.CreateInstance<Recipe>();
					((Object)val2).name = name;
					val2.m_item = prefabs[salt.Prefab].GetComponent<ItemDrop>();
					val2.m_amount = salt.Amount;
					val2.m_craftingStation = val;
					val2.m_minStationLevel = 1;
					val2.m_enabled = true;
					val2.m_resources = source.Select((GameObject p, int i) => Requirement(p, salt.Ingredients[i].Amount)).ToArray();
					recipes.Add(val2);
				}
				db.m_recipes.Add(val2);
			}
		}

		private static Requirement Requirement(GameObject item, int amount)
		{
			//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_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_0027: Expected O, but got Unknown
			return new Requirement
			{
				m_resItem = item.GetComponent<ItemDrop>(),
				m_amount = amount,
				m_amountPerLevel = 0,
				m_recover = false
			};
		}

		internal static void RegisterNetwork(ZNetScene scene)
		{
			RegisterItems(ObjectDB.instance);
			AddNetworkPrefabs(scene);
			if ((Object)(object)ObjectDB.instance != (Object)null)
			{
				AddRecipes(ObjectDB.instance);
			}
		}

		private static void AddNetworkPrefabs(ZNetScene scene)
		{
			Dictionary<int, GameObject> dictionary = (Dictionary<int, GameObject>)namedPrefabs.GetValue(scene);
			foreach (KeyValuePair<string, GameObject> prefab in prefabs)
			{
				int stableHashCode = StringExtensionMethods.GetStableHashCode(prefab.Key);
				if (dictionary.TryGetValue(stableHashCode, out var value) && (Object)(object)value != (Object)(object)prefab.Value)
				{
					throw new InvalidOperationException("Pitchit network prefab hash collision: " + prefab.Key);
				}
				dictionary[stableHashCode] = prefab.Value;
				if (!scene.m_prefabs.Contains(prefab.Value))
				{
					scene.m_prefabs.Add(prefab.Value);
				}
			}
		}

		internal static void Dispose(bool quitting = false)
		{
			if (!quitting)
			{
				foreach (ObjectDB database in databases)
				{
					if (!((Object)(object)database == (Object)null))
					{
						database.m_items.RemoveAll((GameObject p) => prefabs.Values.Contains(p));
						database.m_recipes.RemoveAll((Recipe r) => recipes.Contains(r));
						updateRegisters.Invoke(database, null);
					}
				}
			}
			if (!quitting && (Object)(object)ZNetScene.instance != (Object)null)
			{
				ZNetScene instance = ZNetScene.instance;
				Dictionary<int, GameObject> dictionary = (Dictionary<int, GameObject>)namedPrefabs.GetValue(instance);
				foreach (KeyValuePair<string, GameObject> prefab in prefabs)
				{
					int stableHashCode = StringExtensionMethods.GetStableHashCode(prefab.Key);
					if (dictionary.TryGetValue(stableHashCode, out var value) && (Object)(object)value == (Object)(object)prefab.Value)
					{
						dictionary.Remove(stableHashCode);
					}
					instance.m_prefabs.Remove(prefab.Value);
				}
			}
			foreach (Recipe recipe in recipes)
			{
				Object.Destroy((Object)(object)recipe);
			}
			if ((Object)(object)root != (Object)null)
			{
				Object.Destroy((Object)(object)root);
			}
			foreach (Object item in owned)
			{
				if (item != (Object)null)
				{
					Object.Destroy(item);
				}
			}
			recipes.Clear();
			prefabs.Clear();
			owned.Clear();
			databases.Clear();
			root = null;
		}
	}
}