Decompiled source of SalvageStation v0.2.9

SalvageStation.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("SalvageStation")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.9.0")]
[assembly: AssemblyInformationalVersion("0.2.9+901b84ab23f2f10926b13865f9b40bb283490874")]
[assembly: AssemblyProduct("SalvageStation")]
[assembly: AssemblyTitle("SalvageStation")]
[assembly: AssemblyVersion("0.2.9.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 SalvageStation
{
	public static class SalvageGlb
	{
		[Serializable]
		private class GLTFRoot
		{
			public GLTFMesh[] meshes;

			public GLTFNode[] nodes;

			public GLTFMaterial[] materials;

			public GLTFAccessor[] accessors;

			public GLTFBufferView[] bufferViews;

			public GLTFImage[] images;

			public GLTFTexture[] textures;

			public GLTFScene[] scenes;
		}

		[Serializable]
		private class GLTFMesh
		{
			public string name;

			public GLTFPrimitive[] primitives;
		}

		[Serializable]
		private class GLTFPrimitive
		{
			public GLTFAttributes attributes;

			public int indices = -1;

			public int material = -1;
		}

		[Serializable]
		private class GLTFAttributes
		{
			public int POSITION = -1;

			public int NORMAL = -1;

			public int TEXCOORD_0 = -1;
		}

		[Serializable]
		private class GLTFNode
		{
			public string name;

			public int mesh = -1;

			public float[] translation;

			public float[] rotation;

			public float[] scale;

			public int[] children;
		}

		[Serializable]
		private class GLTFMaterial
		{
			public string name;

			public GLTFPBR pbrMetallicRoughness;

			public GLTFTextureInfo normalTexture;
		}

		[Serializable]
		private class GLTFPBR
		{
			public float[] baseColorFactor;

			public float? metallicFactor;

			public float? roughnessFactor;

			public GLTFTextureInfo baseColorTexture;
		}

		[Serializable]
		private class GLTFTextureInfo
		{
			public int index = -1;
		}

		[Serializable]
		private class GLTFImage
		{
			public string mimeType;

			public int bufferView = -1;

			public string name;

			public string uri;
		}

		[Serializable]
		private class GLTFTexture
		{
			public int source = -1;
		}

		[Serializable]
		private class GLTFAccessor
		{
			public int bufferView;

			public int byteOffset;

			public int componentType;

			public int count;

			public string type;
		}

		[Serializable]
		private class GLTFBufferView
		{
			public int buffer;

			public int byteOffset;

			public int byteLength;

			public int byteStride;
		}

		[Serializable]
		private class GLTFScene
		{
			public int[] nodes;
		}

		private static bool s_warnedShader;

		public static GameObject Load(string glbPath, Material template)
		{
			if (string.IsNullOrEmpty(glbPath) || !File.Exists(glbPath))
			{
				Logger.LogWarning((object)("Salvage Station: model file not found: " + glbPath));
				return null;
			}
			Logger.LogInfo((object)("Salvage Station: loading model: " + glbPath));
			byte[] data;
			try
			{
				data = File.ReadAllBytes(glbPath);
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("Salvage Station: could not read model file: " + ex.Message));
				return null;
			}
			return ParseGLB(data, template, glbPath);
		}

		private static GameObject ParseGLB(byte[] data, Material template, string path)
		{
			if (data == null || data.Length < 20)
			{
				return null;
			}
			if (BitConverter.ToUInt32(data, 0) != 1179937895)
			{
				Logger.LogWarning((object)("Salvage Station: '" + path + "' is not a GLB file (bad magic)."));
				return null;
			}
			Logger.LogInfo((object)("Salvage Station: GLB version " + BitConverter.ToUInt32(data, 4) + ", total length " + data.Length));
			int num = 12;
			string text = null;
			byte[] array = null;
			while (num + 8 <= data.Length)
			{
				uint num2 = BitConverter.ToUInt32(data, num);
				uint num3 = BitConverter.ToUInt32(data, num + 4);
				num += 8;
				if ((int)num2 > data.Length - num)
				{
					break;
				}
				switch (num3)
				{
				case 1313821514u:
					text = Encoding.UTF8.GetString(data, num, (int)num2);
					break;
				case 5130562u:
					array = new byte[num2];
					Buffer.BlockCopy(data, num, array, 0, (int)num2);
					break;
				}
				num += (int)num2;
				num = (num + 3) & -4;
			}
			if (string.IsNullOrEmpty(text))
			{
				Logger.LogWarning((object)"Salvage Station: no JSON chunk found in GLB.");
				return null;
			}
			return ParseGLTF(text, array, template);
		}

		private static GameObject ParseGLTF(string json, byte[] binData, Material template)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_05a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_05af: Expected O, but got Unknown
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Expected O, but got Unknown
			//IL_0894: Unknown result type (might be due to invalid IL or missing references)
			//IL_060b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0657: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Expected O, but got Unknown
			//IL_08b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_08b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_08b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_08be: Unknown result type (might be due to invalid IL or missing references)
			//IL_0698: Unknown result type (might be due to invalid IL or missing references)
			//IL_094a: Unknown result type (might be due to invalid IL or missing references)
			//IL_094f: Unknown result type (might be due to invalid IL or missing references)
			//IL_096f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0974: Unknown result type (might be due to invalid IL or missing references)
			//IL_0994: Unknown result type (might be due to invalid IL or missing references)
			//IL_0999: Unknown result type (might be due to invalid IL or missing references)
			//IL_08ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_08d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_08dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_046b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0470: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("SalvageModel");
			try
			{
				GLTFRoot gLTFRoot = JsonConvert.DeserializeObject<GLTFRoot>(json);
				if (gLTFRoot == null)
				{
					Logger.LogWarning((object)"Salvage Station: failed to parse GLTF JSON.");
					return null;
				}
				Logger.LogInfo((object)("Salvage Station: GLTF " + ((gLTFRoot.meshes != null) ? gLTFRoot.meshes.Length : 0) + " meshes, " + ((gLTFRoot.nodes != null) ? gLTFRoot.nodes.Length : 0) + " nodes, " + ((gLTFRoot.materials != null) ? gLTFRoot.materials.Length : 0) + " materials."));
				GLTFBufferView[] bufferViews = gLTFRoot.bufferViews ?? new GLTFBufferView[0];
				GLTFAccessor[] array = gLTFRoot.accessors ?? new GLTFAccessor[0];
				GLTFMesh[] array2 = gLTFRoot.meshes ?? new GLTFMesh[0];
				GLTFMaterial[] array3 = gLTFRoot.materials ?? new GLTFMaterial[0];
				GLTFNode[] array4 = gLTFRoot.nodes ?? new GLTFNode[0];
				GLTFTexture[] array5 = gLTFRoot.textures ?? new GLTFTexture[0];
				GLTFImage[] images = gLTFRoot.images ?? new GLTFImage[0];
				Dictionary<int, Texture2D> texCache = new Dictionary<int, Texture2D>();
				Func<int, Texture2D> func = delegate(int imageIndex)
				{
					//IL_0097: Unknown result type (might be due to invalid IL or missing references)
					//IL_009e: Expected O, but got Unknown
					if (imageIndex < 0 || imageIndex >= images.Length)
					{
						return (Texture2D)null;
					}
					if (texCache.TryGetValue(imageIndex, out var value3))
					{
						return value3;
					}
					GLTFImage gLTFImage = images[imageIndex];
					if (gLTFImage.bufferView < 0 || gLTFImage.bufferView >= bufferViews.Length)
					{
						return (Texture2D)null;
					}
					GLTFBufferView gLTFBufferView = bufferViews[gLTFImage.bufferView];
					if (gLTFBufferView.byteOffset + gLTFBufferView.byteLength > binData.Length)
					{
						return (Texture2D)null;
					}
					byte[] array10 = new byte[gLTFBufferView.byteLength];
					Buffer.BlockCopy(binData, gLTFBufferView.byteOffset, array10, 0, gLTFBufferView.byteLength);
					Texture2D val9 = new Texture2D(2, 2, (TextureFormat)4, false);
					if (!ImageConversion.LoadImage(val9, array10))
					{
						Object.Destroy((Object)(object)val9);
						return (Texture2D)null;
					}
					((Object)val9).name = ((!string.IsNullOrEmpty(gLTFImage.name)) ? gLTFImage.name : ("img_" + imageIndex));
					texCache[imageIndex] = val9;
					return val9;
				};
				Dictionary<int, GameObject> dictionary = new Dictionary<int, GameObject>();
				Dictionary<int, string> dictionary2 = new Dictionary<int, string>();
				if (array4 != null)
				{
					foreach (GLTFNode gLTFNode in array4)
					{
						if (gLTFNode != null && gLTFNode.mesh >= 0 && !dictionary2.ContainsKey(gLTFNode.mesh))
						{
							dictionary2[gLTFNode.mesh] = gLTFNode.name;
						}
					}
				}
				for (int num2 = 0; num2 < array2.Length; num2++)
				{
					GLTFMesh gLTFMesh = array2[num2];
					if (gLTFMesh == null || gLTFMesh.primitives == null || gLTFMesh.primitives.Length == 0)
					{
						continue;
					}
					string value;
					string text = ((dictionary2.TryGetValue(num2, out value) && !string.IsNullOrEmpty(value)) ? value : ((!string.IsNullOrEmpty(gLTFMesh.name)) ? gLTFMesh.name : ("Mesh_" + num2)));
					GameObject val2 = new GameObject(text);
					val2.transform.SetParent(val.transform, false);
					for (int num3 = 0; num3 < gLTFMesh.primitives.Length; num3++)
					{
						GLTFPrimitive gLTFPrimitive = gLTFMesh.primitives[num3];
						if (gLTFPrimitive == null)
						{
							continue;
						}
						GameObject val3 = new GameObject(text + "_p" + num3);
						val3.transform.SetParent(val2.transform, false);
						MeshFilter val4 = val3.AddComponent<MeshFilter>();
						MeshRenderer val5 = val3.AddComponent<MeshRenderer>();
						Mesh val6 = new Mesh();
						val6.indexFormat = (IndexFormat)1;
						((Object)val6).name = (gLTFMesh.name ?? ("Mesh_" + num2)) + "_" + num3;
						if (gLTFPrimitive.attributes != null && gLTFPrimitive.attributes.POSITION >= 0 && gLTFPrimitive.attributes.POSITION < array.Length)
						{
							val6.vertices = ReadVec3Accessor(array[gLTFPrimitive.attributes.POSITION], bufferViews, binData);
						}
						if (gLTFPrimitive.attributes != null && gLTFPrimitive.attributes.NORMAL >= 0 && gLTFPrimitive.attributes.NORMAL < array.Length)
						{
							val6.normals = ReadVec3Accessor(array[gLTFPrimitive.attributes.NORMAL], bufferViews, binData);
						}
						else
						{
							val6.RecalculateNormals();
						}
						if (gLTFPrimitive.attributes != null && gLTFPrimitive.attributes.TEXCOORD_0 >= 0 && gLTFPrimitive.attributes.TEXCOORD_0 < array.Length)
						{
							val6.uv = ReadVec2Accessor(array[gLTFPrimitive.attributes.TEXCOORD_0], bufferViews, binData);
						}
						if (gLTFPrimitive.indices >= 0 && gLTFPrimitive.indices < array.Length)
						{
							int[] array6 = ReadIndicesAccessor(array[gLTFPrimitive.indices], bufferViews, binData);
							if (array6 != null)
							{
								for (int num4 = 0; num4 + 2 < array6.Length; num4 += 3)
								{
									int num5 = array6[num4];
									array6[num4] = array6[num4 + 1];
									array6[num4 + 1] = num5;
								}
								val6.triangles = array6;
							}
						}
						int vertexCount = val6.vertexCount;
						if (vertexCount > 0)
						{
							Color[] array7 = (Color[])(object)new Color[vertexCount];
							for (int num6 = 0; num6 < vertexCount; num6++)
							{
								array7[num6] = Color.white;
							}
							val6.colors = array7;
						}
						val6.RecalculateBounds();
						val4.mesh = val6;
						if (gLTFPrimitive.material >= 0 && gLTFPrimitive.material < array3.Length)
						{
							GLTFMaterial gLTFMaterial = array3[gLTFPrimitive.material];
							Texture2D baseTexture = null;
							int num7 = ((gLTFMaterial.pbrMetallicRoughness != null && gLTFMaterial.pbrMetallicRoughness.baseColorTexture != null) ? gLTFMaterial.pbrMetallicRoughness.baseColorTexture.index : (-1));
							if (num7 >= 0 && num7 < array5.Length)
							{
								baseTexture = func(array5[num7].source);
							}
							((Renderer)val5).sharedMaterials = CreateMaterial(gLTFMaterial, template, baseTexture);
						}
						else
						{
							((Renderer)val5).sharedMaterial = CreateFallbackMaterial(template);
						}
					}
					dictionary[num2] = val2;
				}
				if (array4.Length != 0)
				{
					GameObject[] array8 = (GameObject[])(object)new GameObject[array4.Length];
					for (int num8 = 0; num8 < array4.Length; num8++)
					{
						array8[num8] = new GameObject((!string.IsNullOrEmpty(array4[num8].name)) ? array4[num8].name : ("Node_" + num8));
					}
					for (int num9 = 0; num9 < array4.Length; num9++)
					{
						GLTFNode gLTFNode2 = array4[num9];
						GameObject val7 = array8[num9];
						if (gLTFNode2.translation != null && gLTFNode2.translation.Length == 3)
						{
							val7.transform.localPosition = new Vector3(gLTFNode2.translation[0], gLTFNode2.translation[1], 0f - gLTFNode2.translation[2]);
						}
						if (gLTFNode2.rotation != null && gLTFNode2.rotation.Length == 4)
						{
							val7.transform.localRotation = new Quaternion(gLTFNode2.rotation[0], gLTFNode2.rotation[1], 0f - gLTFNode2.rotation[2], 0f - gLTFNode2.rotation[3]);
						}
						if (gLTFNode2.scale != null && gLTFNode2.scale.Length == 3)
						{
							val7.transform.localScale = new Vector3(gLTFNode2.scale[0], gLTFNode2.scale[1], gLTFNode2.scale[2]);
						}
						if (gLTFNode2.mesh >= 0 && gLTFNode2.mesh < array2.Length && dictionary.TryGetValue(gLTFNode2.mesh, out var value2))
						{
							value2.transform.SetParent(val7.transform, false);
						}
						if (gLTFNode2.children == null)
						{
							continue;
						}
						for (int num10 = 0; num10 < gLTFNode2.children.Length; num10++)
						{
							int num11 = gLTFNode2.children[num10];
							if (num11 >= 0 && num11 < array8.Length)
							{
								array8[num11].transform.SetParent(val7.transform, false);
							}
						}
					}
					bool flag = false;
					if (gLTFRoot.scenes != null)
					{
						for (int num12 = 0; num12 < gLTFRoot.scenes.Length; num12++)
						{
							if (flag)
							{
								break;
							}
							GLTFScene gLTFScene = gLTFRoot.scenes[num12];
							if (gLTFScene == null || gLTFScene.nodes == null)
							{
								continue;
							}
							for (int num13 = 0; num13 < gLTFScene.nodes.Length; num13++)
							{
								int num14 = gLTFScene.nodes[num13];
								if (num14 >= 0 && num14 < array8.Length)
								{
									array8[num14].transform.SetParent(val.transform, false);
									flag = true;
								}
							}
						}
					}
					if (!flag)
					{
						for (int num15 = 0; num15 < array8.Length; num15++)
						{
							if ((Object)(object)array8[num15].transform.parent == (Object)null)
							{
								array8[num15].transform.SetParent(val.transform, false);
							}
						}
					}
				}
				else
				{
					foreach (GameObject value4 in dictionary.Values)
					{
						value4.transform.SetParent(val.transform, false);
					}
				}
				int num16 = 0;
				MeshRenderer[] componentsInChildren = val.GetComponentsInChildren<MeshRenderer>(true);
				for (int num17 = 0; num17 < componentsInChildren.Length; num17++)
				{
					num16 += ((((Renderer)componentsInChildren[num17]).sharedMaterials != null) ? ((Renderer)componentsInChildren[num17]).sharedMaterials.Length : 0);
				}
				Bounds val8 = default(Bounds);
				bool flag2 = true;
				Renderer[] componentsInChildren2 = val.GetComponentsInChildren<Renderer>(true);
				Vector3 size;
				for (int num18 = 0; num18 < componentsInChildren2.Length; num18++)
				{
					Bounds bounds = componentsInChildren2[num18].bounds;
					size = ((Bounds)(ref bounds)).size;
					if (!(((Vector3)(ref size)).sqrMagnitude < 0.0001f))
					{
						if (flag2)
						{
							val8 = componentsInChildren2[num18].bounds;
							flag2 = false;
						}
						else
						{
							((Bounds)(ref val8)).Encapsulate(componentsInChildren2[num18].bounds);
						}
					}
				}
				string[] obj = new string[6]
				{
					"Salvage Station: model ready - ",
					componentsInChildren.Length.ToString(),
					" renderers, ",
					num16.ToString(),
					" primitives, bounds ",
					null
				};
				object obj2;
				if (!flag2)
				{
					string[] array9 = new string[5];
					size = ((Bounds)(ref val8)).size;
					array9[0] = size.x.ToString("0.##");
					array9[1] = " x ";
					size = ((Bounds)(ref val8)).size;
					array9[2] = size.y.ToString("0.##");
					array9[3] = " x ";
					size = ((Bounds)(ref val8)).size;
					array9[4] = size.z.ToString("0.##");
					obj2 = string.Concat(array9);
				}
				else
				{
					obj2 = "none";
				}
				obj[5] = (string)obj2;
				Logger.LogInfo((object)string.Concat(obj));
				return val;
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("Salvage Station: error parsing GLTF: " + ex));
				return null;
			}
		}

		private static Vector3[] ReadVec3Accessor(GLTFAccessor accessor, GLTFBufferView[] bufferViews, byte[] binData)
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			if (accessor == null || accessor.bufferView < 0 || accessor.bufferView >= bufferViews.Length || accessor.count <= 0)
			{
				return null;
			}
			GLTFBufferView gLTFBufferView = bufferViews[accessor.bufferView];
			int num = gLTFBufferView.byteOffset + accessor.byteOffset;
			int count = accessor.count;
			int num2 = ((gLTFBufferView.byteStride > 0) ? gLTFBufferView.byteStride : 12);
			Vector3[] array = (Vector3[])(object)new Vector3[count];
			for (int i = 0; i < count; i++)
			{
				int num3 = num + i * num2;
				if (num3 + 12 <= binData.Length)
				{
					array[i] = new Vector3(BitConverter.ToSingle(binData, num3), BitConverter.ToSingle(binData, num3 + 4), 0f - BitConverter.ToSingle(binData, num3 + 8));
				}
			}
			return array;
		}

		private static Vector2[] ReadVec2Accessor(GLTFAccessor accessor, GLTFBufferView[] bufferViews, byte[] binData)
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			if (accessor == null || accessor.bufferView < 0 || accessor.bufferView >= bufferViews.Length || accessor.count <= 0)
			{
				return null;
			}
			GLTFBufferView gLTFBufferView = bufferViews[accessor.bufferView];
			int num = gLTFBufferView.byteOffset + accessor.byteOffset;
			int count = accessor.count;
			int num2 = ((gLTFBufferView.byteStride > 0) ? gLTFBufferView.byteStride : 8);
			Vector2[] array = (Vector2[])(object)new Vector2[count];
			for (int i = 0; i < count; i++)
			{
				int num3 = num + i * num2;
				if (num3 + 8 <= binData.Length)
				{
					array[i] = new Vector2(BitConverter.ToSingle(binData, num3), 1f - BitConverter.ToSingle(binData, num3 + 4));
				}
			}
			return array;
		}

		private static int[] ReadIndicesAccessor(GLTFAccessor accessor, GLTFBufferView[] bufferViews, byte[] binData)
		{
			if (accessor == null || accessor.bufferView < 0 || accessor.bufferView >= bufferViews.Length || accessor.count <= 0)
			{
				return null;
			}
			GLTFBufferView gLTFBufferView = bufferViews[accessor.bufferView];
			int num = gLTFBufferView.byteOffset + accessor.byteOffset;
			int count = accessor.count;
			int[] array = new int[count];
			if (accessor.componentType == 5125)
			{
				int num2 = ((gLTFBufferView.byteStride > 0) ? gLTFBufferView.byteStride : 4);
				for (int i = 0; i < count; i++)
				{
					int num3 = num + i * num2;
					if (num3 + 4 <= binData.Length)
					{
						array[i] = BitConverter.ToInt32(binData, num3);
					}
				}
			}
			else if (accessor.componentType == 5123)
			{
				int num4 = ((gLTFBufferView.byteStride > 0) ? gLTFBufferView.byteStride : 2);
				for (int j = 0; j < count; j++)
				{
					int num5 = num + j * num4;
					if (num5 + 2 <= binData.Length)
					{
						array[j] = BitConverter.ToUInt16(binData, num5);
					}
				}
			}
			else if (accessor.componentType == 5121)
			{
				int num6 = ((gLTFBufferView.byteStride <= 0) ? 1 : gLTFBufferView.byteStride);
				for (int k = 0; k < count; k++)
				{
					int num7 = num + k * num6;
					if (num7 < binData.Length)
					{
						array[k] = binData[num7];
					}
				}
			}
			return array;
		}

		private static Material[] CreateMaterial(GLTFMaterial mat, Material template, Texture2D baseTexture)
		{
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			Material val = CreateBaseMaterial(template);
			((Object)val).name = ((!string.IsNullOrEmpty(mat.name)) ? mat.name : "SalvageMaterial");
			if ((Object)(object)baseTexture != (Object)null)
			{
				val.mainTexture = (Texture)(object)baseTexture;
				if (val.HasProperty("_MainTex"))
				{
					val.SetTexture("_MainTex", (Texture)(object)baseTexture);
				}
				if (val.HasProperty("_BaseMap"))
				{
					val.SetTexture("_BaseMap", (Texture)(object)baseTexture);
				}
				if (val.HasProperty("_Albedo"))
				{
					val.SetTexture("_Albedo", (Texture)(object)baseTexture);
				}
			}
			val.color = Color.white;
			if (val.HasProperty("_Color"))
			{
				val.SetColor("_Color", Color.white);
			}
			if (val.HasProperty("_BaseColor"))
			{
				val.SetColor("_BaseColor", Color.white);
			}
			val.DisableKeyword("_ALPHABLEND_ON");
			val.DisableKeyword("_ALPHAPREMULTIPLY_ON");
			val.renderQueue = 2000;
			if (val.HasProperty("_Metallic"))
			{
				val.SetFloat("_Metallic", 0f);
			}
			if (val.HasProperty("_Glossiness"))
			{
				val.SetFloat("_Glossiness", 0.15f);
			}
			if (val.HasProperty("_Cutoff"))
			{
				val.SetFloat("_Cutoff", 0f);
			}
			if (val.HasProperty("_Cull"))
			{
				val.SetFloat("_Cull", 0f);
			}
			val.DisableKeyword("_ALPHATEST_ON");
			if (mat.pbrMetallicRoughness != null)
			{
				GLTFPBR pbrMetallicRoughness = mat.pbrMetallicRoughness;
				if (pbrMetallicRoughness.baseColorFactor != null && pbrMetallicRoughness.baseColorFactor.Length == 4)
				{
					val.color = new Color(pbrMetallicRoughness.baseColorFactor[0], pbrMetallicRoughness.baseColorFactor[1], pbrMetallicRoughness.baseColorFactor[2], pbrMetallicRoughness.baseColorFactor[3]);
				}
				if (pbrMetallicRoughness.metallicFactor.HasValue)
				{
					val.SetFloat("_Metallic", pbrMetallicRoughness.metallicFactor.Value);
				}
				if (pbrMetallicRoughness.roughnessFactor.HasValue)
				{
					val.SetFloat("_Glossiness", 1f - pbrMetallicRoughness.roughnessFactor.Value);
				}
			}
			return (Material[])(object)new Material[1] { val };
		}

		private static Material CreateFallbackMaterial(Material template)
		{
			return CreateBaseMaterial(template);
		}

		private static Material CreateBaseMaterial(Material template)
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			if ((Object)(object)template != (Object)null && (Object)(object)template.shader != (Object)null && ((Object)template.shader).name.IndexOf("InternalError", StringComparison.Ordinal) < 0)
			{
				return new Material(template);
			}
			Shader val = Shader.Find("Custom/StaticObject");
			if ((Object)(object)val == (Object)null)
			{
				val = Shader.Find("Standard");
			}
			if ((Object)(object)val == (Object)null)
			{
				if (!s_warnedShader)
				{
					s_warnedShader = true;
					Logger.LogWarning((object)"Salvage Station: no usable shader; material will render magenta.");
				}
				val = Shader.Find("Hidden/InternalErrorShader");
			}
			return new Material(val);
		}
	}
	public class SalvageStationMarker : MonoBehaviour
	{
		private sealed class RefundStack
		{
			public ItemDrop Source;

			public int Count;
		}

		private Transform _lever;

		private Transform _cog;

		private Vector3 _cogAxis = Vector3.up;

		private GameObject _smoke;

		private Quaternion _rest;

		private Quaternion _pulled;

		private Coroutine _motion;

		private bool _busy;

		private bool _running;

		private bool _working;

		private bool _leverPosed;

		private static Dictionary<string, ItemDrop> s_smelted;

		private static MethodInfo s_stopAoe;

		private static ZNetView View(Incinerator incinerator)
		{
			if (!((Object)(object)incinerator != (Object)null))
			{
				return null;
			}
			return ((Component)incinerator).GetComponent<ZNetView>();
		}

		private void Awake()
		{
			EnsureParts();
		}

		private void Update()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if (_working && !((Object)(object)_cog == (Object)null))
			{
				_cog.Rotate(_cogAxis, 240f * Time.deltaTime, (Space)1);
			}
		}

		public bool RequestSalvage(Incinerator incinerator, Humanoid user)
		{
			if ((Object)(object)incinerator == (Object)null || _busy || _running)
			{
				return false;
			}
			Inventory val = (((Object)(object)incinerator.m_container != (Object)null) ? incinerator.m_container.GetInventory() : null);
			if (val == null || val.NrOfItems() == 0)
			{
				if ((Object)(object)user != (Object)null)
				{
					((Character)user).Message((MessageType)2, "The salvage station is empty.", 0, (Sprite)null, false);
				}
				return false;
			}
			ZNetView val2 = View(incinerator);
			if ((Object)(object)val2 == (Object)null)
			{
				return false;
			}
			_busy = true;
			if (!val2.IsOwner())
			{
				val2.ClaimOwnership();
			}
			long num = 0L;
			Player val3 = (Player)(object)((user is Player) ? user : null);
			if ((Object)(object)val3 != (Object)null)
			{
				num = val3.GetPlayerID();
			}
			val2.InvokeRPC("RPC_RequestIncinerate", new object[1] { num });
			if ((Object)(object)user != (Object)null)
			{
				((Character)user).Message((MessageType)2, "Salvaging...", 0, (Sprite)null, false);
			}
			return true;
		}

		public void StartSalvage(Incinerator incinerator)
		{
			if (!((Object)(object)incinerator == (Object)null) && !_running)
			{
				((MonoBehaviour)this).StartCoroutine(SalvageRoutine(incinerator));
			}
		}

		public void PullLever()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			EnsureParts();
			SetWorking(on: true);
			SwingTo(_pulled);
		}

		public void ReturnLever()
		{
			//IL_0016: 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_0042: Unknown result type (might be due to invalid IL or missing references)
			_busy = false;
			EnsureParts();
			SetWorking(on: false);
			SwingTo(_rest);
			if ((Object)(object)Player.m_localPlayer != (Object)null && Vector3.Distance(((Component)Player.m_localPlayer).transform.position, ((Component)this).transform.position) < 10f)
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "Salvage complete.", 0, (Sprite)null, false);
			}
		}

		private IEnumerator SalvageRoutine(Incinerator incinerator)
		{
			_running = true;
			ZNetView nview = View(incinerator);
			if ((Object)(object)nview != (Object)null)
			{
				nview.InvokeRPC(ZNetView.Everybody, "RPC_AnimateLever", Array.Empty<object>());
			}
			float num = Mathf.Max(0.5f, incinerator.m_effectDelayMin);
			yield return (object)new WaitForSeconds(num);
			SalvageStationPlugin.LogInfo("Salvage Station: salvaged " + Refund(incinerator) + " stack(s).");
			if ((Object)(object)nview != (Object)null)
			{
				nview.InvokeRPC(ZNetView.Everybody, "RPC_AnimateLeverReturn", Array.Empty<object>());
			}
			yield return (object)new WaitForSeconds(0.6f);
			if (s_stopAoe == null)
			{
				s_stopAoe = AccessTools.Method(typeof(Incinerator), "StopAOE", (Type[])null, (Type[])null);
			}
			if (s_stopAoe != null)
			{
				s_stopAoe.Invoke(incinerator, null);
			}
			_running = false;
		}

		private int Refund(Incinerator incinerator)
		{
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0320: Unknown result type (might be due to invalid IL or missing references)
			//IL_034f: Unknown result type (might be due to invalid IL or missing references)
			Inventory val = (((Object)(object)incinerator.m_container != (Object)null) ? incinerator.m_container.GetInventory() : null);
			if (val == null)
			{
				return 0;
			}
			List<ItemData> list = new List<ItemData>();
			List<ItemData> allItems = val.GetAllItems();
			for (int i = 0; i < allItems.Count; i++)
			{
				if (allItems[i] != null)
				{
					list.Add(allItems[i].Clone());
				}
			}
			Dictionary<string, RefundStack> dictionary = new Dictionary<string, RefundStack>();
			List<ItemData> list2 = new List<ItemData>();
			int num = 0;
			for (int j = 0; j < list.Count; j++)
			{
				ItemData val2 = list[j];
				if (val2 == null || val2.m_shared == null || val2.m_stack <= 0)
				{
					continue;
				}
				Recipe val3 = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetRecipe(val2) : null);
				if ((Object)(object)val3 != (Object)null && val3.m_resources != null && val3.m_resources.Length != 0)
				{
					int num2 = ((val3.m_amount <= 0) ? 1 : val3.m_amount);
					int num3 = val2.m_stack / num2;
					int num4 = val2.m_stack % num2;
					if (num3 <= 0)
					{
						list2.Add(val2);
						continue;
					}
					int quality = ((val2.m_quality <= 0) ? 1 : val2.m_quality);
					SalvageStationPlugin.LogInfo("Salvage Station: " + val2.m_shared.m_name + " quality " + quality + " x" + val2.m_stack);
					bool requireOnlyOneIngredient = val3.m_requireOnlyOneIngredient;
					bool flag = false;
					for (int k = 0; k < val3.m_resources.Length; k++)
					{
						Requirement val4 = val3.m_resources[k];
						if (val4 == null || (Object)(object)val4.m_resItem == (Object)null || val4.m_resItem.m_itemData == null || val4.m_resItem.m_itemData.m_shared == null)
						{
							continue;
						}
						int num5 = CraftedAmount(val4, quality) * num3;
						if (num5 > 0)
						{
							AddRefund(dictionary, val4.m_resItem, num5);
							flag = true;
							if (requireOnlyOneIngredient)
							{
								break;
							}
						}
					}
					if (!flag)
					{
						list2.Add(val2);
						continue;
					}
					num++;
					if (num4 > 0)
					{
						ItemData val5 = val2.Clone();
						val5.m_stack = num4;
						list2.Add(val5);
					}
				}
				else
				{
					ItemDrop val6 = SmeltedSource(val2);
					if ((Object)(object)val6 != (Object)null)
					{
						AddRefund(dictionary, val6, val2.m_stack);
						num++;
					}
					else
					{
						list2.Add(val2);
					}
				}
			}
			val.RemoveAll();
			Vector3 dropAt = ((Component)this).transform.position + ((Component)this).transform.forward * 1.4f + Vector3.up * 0.35f;
			foreach (KeyValuePair<string, RefundStack> item in dictionary)
			{
				SalvageStationPlugin.LogInfo("Salvage Station: refund " + item.Key + " x" + item.Value.Count);
				GiveMaterial(val, item.Value, dropAt);
			}
			for (int l = 0; l < list2.Count; l++)
			{
				GiveItemBack(val, list2[l], dropAt);
			}
			SalvageStationPlugin.LogInfo("Salvage Station: " + dictionary.Count + " material type(s), " + list2.Count + " stack(s) returned unchanged.");
			return num;
		}

		private static int CraftedAmount(Requirement req, int quality)
		{
			if (req == null)
			{
				return 0;
			}
			int num = 0;
			if (!req.m_upgraderResource)
			{
				num += req.GetAmount(1);
			}
			int num2 = ((quality <= 1) ? 1 : quality);
			for (int i = 2; i <= num2; i++)
			{
				num += req.GetAmount(i);
			}
			return num;
		}

		private static void AddRefund(Dictionary<string, RefundStack> refunds, ItemDrop source, int amount)
		{
			if (!((Object)(object)source == (Object)null) && source.m_itemData != null && source.m_itemData.m_shared != null && amount > 0)
			{
				string name = source.m_itemData.m_shared.m_name;
				if (!refunds.TryGetValue(name, out var value))
				{
					value = (refunds[name] = new RefundStack
					{
						Source = source,
						Count = 0
					});
				}
				value.Count += amount;
			}
		}

		private static void GiveMaterial(Inventory inventory, RefundStack stack, Vector3 dropAt)
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			if (stack == null || (Object)(object)stack.Source == (Object)null || stack.Count <= 0)
			{
				return;
			}
			int num = stack.Source.m_itemData.m_shared.m_maxStackSize;
			if (num < 1)
			{
				num = 1;
			}
			int num2 = stack.Count;
			while (num2 > 0)
			{
				int num3 = ((num2 > num) ? num : num2);
				if (inventory == null || !inventory.AddItem(((Component)stack.Source).gameObject, num3))
				{
					DropPrefab(((Component)stack.Source).gameObject, num3, 1, dropAt);
				}
				num2 -= num3;
			}
		}

		private static void GiveItemBack(Inventory inventory, ItemData item, Vector3 dropAt)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			if (item != null)
			{
				item.m_equipped = false;
				if (inventory == null || !inventory.AddItem(item))
				{
					DropPrefab(((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(item.m_shared) : null, item.m_stack, (item.m_quality <= 0) ? 1 : item.m_quality, dropAt);
				}
			}
		}

		private static void DropPrefab(GameObject prefab, int stack, int quality, Vector3 dropAt)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: 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)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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)
			if (!((Object)(object)prefab == (Object)null) && stack > 0)
			{
				Vector3 val = dropAt + Random.insideUnitSphere * 0.25f;
				val.y = dropAt.y;
				ItemDrop component = Object.Instantiate<GameObject>(prefab, val, Quaternion.identity).GetComponent<ItemDrop>();
				if ((Object)(object)component != (Object)null && component.m_itemData != null)
				{
					component.m_itemData.m_stack = stack;
					component.m_itemData.m_quality = quality;
				}
			}
		}

		private static ItemDrop SmeltedSource(ItemData item)
		{
			if (item == null || item.m_shared == null)
			{
				return null;
			}
			if (s_smelted == null)
			{
				s_smelted = new Dictionary<string, ItemDrop>();
				Smelter[] array = Resources.FindObjectsOfTypeAll<Smelter>();
				for (int i = 0; i < array.Length; i++)
				{
					if ((Object)(object)array[i] == (Object)null || array[i].m_conversion == null)
					{
						continue;
					}
					for (int j = 0; j < array[i].m_conversion.Count; j++)
					{
						ItemConversion val = array[i].m_conversion[j];
						if (val != null && !((Object)(object)val.m_from == (Object)null) && !((Object)(object)val.m_to == (Object)null) && val.m_to.m_itemData != null && val.m_to.m_itemData.m_shared != null)
						{
							string name = val.m_to.m_itemData.m_shared.m_name;
							if (!s_smelted.ContainsKey(name))
							{
								s_smelted[name] = val.m_from;
							}
						}
					}
				}
			}
			s_smelted.TryGetValue(item.m_shared.m_name, out var value);
			return value;
		}

		private void EnsureParts()
		{
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_lever != (Object)null && (Object)(object)_cog != (Object)null && (Object)(object)_smoke != (Object)null)
			{
				return;
			}
			Transform[] componentsInChildren = ((Component)this).GetComponentsInChildren<Transform>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if ((Object)(object)_lever == (Object)null && ((Object)componentsInChildren[i]).name == "SalvageLever")
				{
					_lever = componentsInChildren[i];
				}
				else if ((Object)(object)_cog == (Object)null && ((Object)componentsInChildren[i]).name == "SalvageCog")
				{
					_cog = componentsInChildren[i];
				}
				else if ((Object)(object)_smoke == (Object)null && ((Object)componentsInChildren[i]).name == "SalvageSmoke")
				{
					_smoke = ((Component)componentsInChildren[i]).gameObject;
				}
			}
			if ((Object)(object)_lever != (Object)null && !_leverPosed)
			{
				_rest = _lever.localRotation;
				_pulled = _rest * Quaternion.Euler(-55f, 0f, 0f);
				_leverPosed = true;
			}
			if ((Object)(object)_cog != (Object)null)
			{
				_cogAxis = ThinnestAxis(_cog);
			}
		}

		private static Vector3 ThinnestAxis(Transform cog)
		{
			//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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: 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)
			Renderer componentInChildren = ((Component)cog).GetComponentInChildren<Renderer>(true);
			if ((Object)(object)componentInChildren == (Object)null)
			{
				return Vector3.up;
			}
			Bounds localBounds = componentInChildren.localBounds;
			Vector3 size = ((Bounds)(ref localBounds)).size;
			if (size.x <= size.y && size.x <= size.z)
			{
				return Vector3.right;
			}
			if (size.z <= size.y)
			{
				return Vector3.forward;
			}
			return Vector3.up;
		}

		private void SetWorking(bool on)
		{
			_working = on;
			if ((Object)(object)_smoke == (Object)null)
			{
				return;
			}
			_smoke.SetActive(on);
			if (on)
			{
				ParticleSystem[] componentsInChildren = _smoke.GetComponentsInChildren<ParticleSystem>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					componentsInChildren[i].Play(true);
				}
			}
		}

		private void SwingTo(Quaternion target)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_lever == (Object)null))
			{
				if (_motion != null)
				{
					((MonoBehaviour)this).StopCoroutine(_motion);
				}
				_motion = ((MonoBehaviour)this).StartCoroutine(Swing(target));
			}
		}

		private IEnumerator Swing(Quaternion target)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			Quaternion from = _lever.localRotation;
			float t = 0f;
			while (t < 0.35f)
			{
				t += Time.deltaTime;
				_lever.localRotation = Quaternion.Slerp(from, target, Mathf.Clamp01(t / 0.35f));
				yield return null;
			}
			_lever.localRotation = target;
		}
	}
	[HarmonyPatch(typeof(Incinerator), "OnIncinerate")]
	internal static class SalvageOnIncineratePatch
	{
		private static bool Prefix(Incinerator __instance, Humanoid user, ref bool __result)
		{
			SalvageStationMarker salvageStationMarker = (((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponent<SalvageStationMarker>() : null);
			if ((Object)(object)salvageStationMarker == (Object)null)
			{
				return true;
			}
			__result = salvageStationMarker.RequestSalvage(__instance, user);
			return false;
		}
	}
	[HarmonyPatch(typeof(Incinerator), "RPC_RequestIncinerate")]
	internal static class SalvageRequestPatch
	{
		private static bool Prefix(Incinerator __instance)
		{
			SalvageStationMarker salvageStationMarker = (((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponent<SalvageStationMarker>() : null);
			if ((Object)(object)salvageStationMarker == (Object)null)
			{
				return true;
			}
			ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
			if ((Object)(object)component != (Object)null && component.IsOwner())
			{
				salvageStationMarker.StartSalvage(__instance);
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(Incinerator), "RPC_AnimateLever")]
	internal static class SalvageLeverPullPatch
	{
		private static void Postfix(Incinerator __instance)
		{
			SalvageStationMarker salvageStationMarker = (((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponent<SalvageStationMarker>() : null);
			if ((Object)(object)salvageStationMarker != (Object)null)
			{
				salvageStationMarker.PullLever();
			}
		}
	}
	[HarmonyPatch(typeof(Incinerator), "RPC_AnimateLeverReturn")]
	internal static class SalvageLeverReturnPatch
	{
		private static void Postfix(Incinerator __instance)
		{
			SalvageStationMarker salvageStationMarker = (((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponent<SalvageStationMarker>() : null);
			if ((Object)(object)salvageStationMarker != (Object)null)
			{
				salvageStationMarker.ReturnLever();
			}
		}
	}
	[BepInPlugin("com.dfg.salvagestation", "Salvage Station", "0.2.9")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class SalvageStationPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.dfg.salvagestation";

		public const string PluginName = "Salvage Station";

		public const string PluginVersion = "0.2.9";

		public static SalvageStationPlugin Instance;

		private bool _prefabReady;

		private bool _pieceAdded;

		private bool _inHammer;

		private bool _known;

		private bool _liveSwept;

		private float _retry;

		private Sprite _icon;

		private Requirement[] _cost = (Requirement[])(object)new Requirement[0];

		private static MethodInfo s_addKnownPiece;

		private static MethodInfo s_updateAvailablePieces;

		private static MethodInfo s_refreshCategories;

		private static readonly FieldInfo s_namedPrefabs = typeof(ZNetScene).GetField("m_namedPrefabs", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		internal static void LogInfo(string message)
		{
			if ((Object)(object)Instance != (Object)null)
			{
				((BaseUnityPlugin)Instance).Logger.LogInfo((object)message);
			}
		}

		private void Awake()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Salvage Station loading.");
			new Harmony("com.dfg.salvagestation").PatchAll(typeof(SalvageStationPlugin).Assembly);
			PieceManager.OnPiecesRegistered += OnPiecesRegistered;
		}

		private void OnDestroy()
		{
			PieceManager.OnPiecesRegistered -= OnPiecesRegistered;
		}

		private void OnPiecesRegistered()
		{
			TryRegister();
		}

		private void Update()
		{
			if (!_inHammer)
			{
				_retry -= Time.deltaTime;
				if (_retry <= 0f)
				{
					_retry = 1f;
					TryRegister();
				}
				return;
			}
			if (!_liveSwept && (Object)(object)Player.m_localPlayer != (Object)null)
			{
				_liveSwept = true;
				SalvageStationPrefab.CatchUpLiveStations(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), ((BaseUnityPlugin)this).Logger);
			}
			if (!_known && !((Object)(object)Player.m_localPlayer == (Object)null))
			{
				_retry -= Time.deltaTime;
				if (_retry <= 0f)
				{
					_retry = 1.5f;
					_known = UnlockForLocalPlayer();
				}
			}
		}

		private void TryRegister()
		{
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: 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)
			//IL_01d8: Expected O, but got Unknown
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Expected O, but got Unknown
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			if (_inHammer || (Object)(object)ZNetScene.instance == (Object)null || ZNetScene.instance.m_prefabs == null || ZNetScene.instance.m_prefabs.Count == 0 || PieceManager.Instance == null)
			{
				return;
			}
			PieceTable pieceTable;
			try
			{
				pieceTable = PieceManager.Instance.GetPieceTable("Hammer");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Salvage Station: Hammer table not ready (" + ex.Message + ")."));
				return;
			}
			if ((Object)(object)pieceTable == (Object)null)
			{
				return;
			}
			if (!_prefabReady)
			{
				GameObject val = SalvageStationPrefab.FindIncinerator();
				if ((Object)(object)val == (Object)null)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"Salvage Station: piece_incinerator was not in ZNetScene. Retrying.");
					return;
				}
				GameObject val2 = PrefabManager.Instance.CreateClonedPrefab("piece_salvagestation", val);
				if ((Object)(object)val2 == (Object)null)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"Salvage Station: failed to clone piece_incinerator. Retrying.");
					return;
				}
				_icon = SalvageStationPrefab.CopyIcon(val);
				_cost = SalvageStationPrefab.CopyValidRequirements(val);
				string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
				SalvageStationPrefab.AttachPresentation(val2, directoryName, ((BaseUnityPlugin)this).Logger);
				PrefabManager.Instance.AddPrefab(val2);
				val2.SetActive(true);
				ForceRegisterInZNetScene(val2);
				_prefabReady = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Salvage Station: cloned 'piece_salvagestation' from '" + ((Object)val).name + "'."));
			}
			GameObject prefab = PrefabManager.Instance.GetPrefab("piece_salvagestation");
			if ((Object)(object)prefab == (Object)null)
			{
				prefab = ZNetScene.instance.GetPrefab("piece_salvagestation");
			}
			if ((Object)(object)prefab == (Object)null)
			{
				return;
			}
			try
			{
				PieceCategory category = PieceManager.Instance.AddPieceCategory("DFG");
				if (!_pieceAdded)
				{
					PieceConfig val3 = new PieceConfig
					{
						Name = "Salvage Station",
						Description = "Pull the lever to recover the materials that went into the items inside.",
						PieceTable = "Hammer",
						Category = "DFG",
						Enabled = true
					};
					PieceManager.Instance.AddPiece(new CustomPiece(prefab, false, val3));
					_pieceAdded = true;
				}
				if (!TableContains(pieceTable, prefab))
				{
					PieceManager.Instance.RegisterPieceInPieceTable(prefab, "Hammer", "DFG");
				}
				SalvageStationPrefab.FinalizePiece(prefab, category, _icon, _cost);
				RefreshCategories();
				_inHammer = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Salvage Station: added to the Hammer menu under DFG.");
			}
			catch (Exception ex2)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Salvage Station: still waiting to join the Hammer menu: " + ex2.Message));
			}
		}

		private static bool TableContains(PieceTable table, GameObject prefab)
		{
			if ((Object)(object)table == (Object)null || table.m_pieces == null || (Object)(object)prefab == (Object)null)
			{
				return false;
			}
			for (int i = 0; i < table.m_pieces.Count; i++)
			{
				GameObject val = table.m_pieces[i];
				if ((Object)(object)val == (Object)(object)prefab || ((Object)(object)val != (Object)null && ((Object)val).name == ((Object)prefab).name))
				{
					return true;
				}
			}
			return false;
		}

		private bool UnlockForLocalPlayer()
		{
			GameObject val = PrefabManager.Instance.GetPrefab("piece_salvagestation");
			if ((Object)(object)val == (Object)null)
			{
				val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab("piece_salvagestation") : null);
			}
			Piece val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<Piece>() : null);
			if ((Object)(object)val2 == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				return false;
			}
			if (!Player.m_localPlayer.IsRecipeKnown(val2.m_name))
			{
				if (s_addKnownPiece == null)
				{
					s_addKnownPiece = typeof(Player).GetMethod("AddKnownPiece", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
				if (s_updateAvailablePieces == null)
				{
					s_updateAvailablePieces = typeof(Player).GetMethod("UpdateAvailablePiecesList", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
				try
				{
					s_addKnownPiece?.Invoke(Player.m_localPlayer, new object[1] { val2 });
					s_updateAvailablePieces?.Invoke(Player.m_localPlayer, null);
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Salvage Station: could not unlock the piece: " + ex.Message));
					return false;
				}
			}
			if (!Player.m_localPlayer.IsRecipeKnown(val2.m_name))
			{
				return false;
			}
			RefreshCategories();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Salvage Station: unlocked in the Hammer menu.");
			return true;
		}

		private static void RefreshCategories()
		{
			try
			{
				if (s_refreshCategories == null)
				{
					s_refreshCategories = typeof(PieceManager).GetMethod("RefreshCategories", BindingFlags.Instance | BindingFlags.NonPublic);
				}
				s_refreshCategories?.Invoke(PieceManager.Instance, null);
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("Salvage Station: could not refresh piece categories: " + ex.Message));
			}
		}

		private static void ForceRegisterInZNetScene(GameObject prefab)
		{
			ZNetScene instance = ZNetScene.instance;
			if ((Object)(object)prefab == (Object)null || (Object)(object)instance == (Object)null || instance.m_prefabs == null)
			{
				return;
			}
			if (!instance.m_prefabs.Contains(prefab))
			{
				instance.m_prefabs.Add(prefab);
			}
			if (s_namedPrefabs == null)
			{
				return;
			}
			try
			{
				IDictionary dictionary = (IDictionary)s_namedPrefabs.GetValue(instance);
				if (dictionary != null)
				{
					dictionary[StringExtensionMethods.GetStableHashCode(((Object)prefab).name)] = prefab;
				}
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("Salvage Station: could not register '" + ((Object)prefab).name + "' in ZNetScene: " + ex.Message));
			}
		}
	}
	public static class SalvageStationPrefab
	{
		public const string PrefabName = "piece_salvagestation";

		public const string DisplayName = "Salvage Station";

		public const string Description = "Pull the lever to recover the materials that went into the items inside.";

		public static GameObject FindIncinerator()
		{
			if ((Object)(object)ZNetScene.instance == (Object)null)
			{
				return null;
			}
			GameObject prefab = ZNetScene.instance.GetPrefab("piece_incinerator");
			if ((Object)(object)prefab != (Object)null)
			{
				return prefab;
			}
			if (ZNetScene.instance.m_prefabs == null)
			{
				return null;
			}
			foreach (GameObject prefab2 in ZNetScene.instance.m_prefabs)
			{
				if (!((Object)(object)prefab2 == (Object)null) && !string.IsNullOrEmpty(((Object)prefab2).name) && ((Object)prefab2).name.IndexOf("incinerator", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return prefab2;
				}
			}
			return null;
		}

		public static Requirement[] CopyValidRequirements(GameObject source)
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Expected O, but got Unknown
			Piece val = (((Object)(object)source != (Object)null) ? source.GetComponent<Piece>() : null);
			if ((Object)(object)val == (Object)null || val.m_resources == null)
			{
				return (Requirement[])(object)new Requirement[0];
			}
			List<Requirement> list = new List<Requirement>();
			for (int i = 0; i < val.m_resources.Length; i++)
			{
				Requirement val2 = val.m_resources[i];
				if (val2 != null && !((Object)(object)val2.m_resItem == (Object)null) && val2.m_resItem.m_itemData != null && val2.m_resItem.m_itemData.m_shared != null)
				{
					list.Add(new Requirement
					{
						m_resItem = val2.m_resItem,
						m_amount = val2.m_amount,
						m_amountPerLevel = val2.m_amountPerLevel,
						m_recover = val2.m_recover
					});
				}
			}
			return list.ToArray();
		}

		public static Sprite CopyIcon(GameObject source)
		{
			Piece val = (((Object)(object)source != (Object)null) ? source.GetComponent<Piece>() : null);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return val.m_icon;
		}

		public static void FinalizePiece(GameObject prefab, PieceCategory category, Sprite icon, Requirement[] cost)
		{
			//IL_003b: 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)
			Piece val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Piece>() : null);
			if (!((Object)(object)val == (Object)null))
			{
				val.m_name = "Salvage Station";
				val.m_description = "Pull the lever to recover the materials that went into the items inside.";
				val.m_enabled = true;
				val.m_category = category;
				val.m_craftingStation = null;
				if ((Object)(object)icon != (Object)null)
				{
					val.m_icon = icon;
				}
				val.m_resources = (Requirement[])(((object)cost) ?? ((object)new Requirement[0]));
			}
		}

		public static void CatchUpLiveStations(string pluginDirectory, ManualLogSource log)
		{
			Incinerator[] array = Object.FindObjectsOfType<Incinerator>();
			foreach (Incinerator val in array)
			{
				if ((Object)(object)val == (Object)null || ((Object)val).name.IndexOf("salvage", StringComparison.OrdinalIgnoreCase) < 0)
				{
					continue;
				}
				GameObject gameObject = ((Component)val).gameObject;
				if ((Object)(object)gameObject.GetComponent<SalvageStationMarker>() == (Object)null)
				{
					gameObject.AddComponent<SalvageStationMarker>();
				}
				Transform[] componentsInChildren = gameObject.GetComponentsInChildren<Transform>(true);
				bool flag = false;
				for (int j = 0; j < componentsInChildren.Length; j++)
				{
					if (((Object)componentsInChildren[j]).name == "SalvageModel")
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					AttachPresentation(gameObject, pluginDirectory, log);
					log.LogInfo((object)"Salvage Station: updated an already placed station.");
				}
			}
		}

		public static void AttachPresentation(GameObject prefab, string pluginDirectory, ManualLogSource log)
		{
			if ((Object)(object)prefab == (Object)null)
			{
				return;
			}
			Incinerator component = prefab.GetComponent<Incinerator>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.m_container != (Object)null)
			{
				component.m_container.m_width = 8;
				component.m_container.m_height = 4;
				component.m_container.m_name = "Salvage Station";
			}
			if ((Object)(object)prefab.GetComponent<SalvageStationMarker>() == (Object)null)
			{
				prefab.AddComponent<SalvageStationMarker>();
			}
			Material val = FindLitMaterial(prefab);
			MeshRenderer[] componentsInChildren = prefab.GetComponentsInChildren<MeshRenderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				((Renderer)componentsInChildren[i]).enabled = false;
			}
			string text = Path.Combine(pluginDirectory ?? "", "sal.glb");
			if (!File.Exists(text))
			{
				text = "C:\\Users\\dhugh\\Documents\\MyMods\\SalvageStation\\sal.glb";
			}
			if (!File.Exists(text))
			{
				log.LogWarning((object)"Salvage Station: sal.glb was not next to the plugin. The lever model is missing.");
				return;
			}
			if ((Object)(object)val != (Object)null)
			{
				log.LogInfo((object)("Salvage Station: model shader '" + ((Object)val.shader).name + "'."));
			}
			GameObject val2 = SalvageGlb.Load(text, val);
			if ((Object)(object)val2 == (Object)null)
			{
				log.LogWarning((object)"Salvage Station: sal.glb did not load.");
				return;
			}
			((Object)val2).name = "SalvageModel";
			val2.transform.SetParent(prefab.transform, false);
			int layer = prefab.layer;
			Transform[] componentsInChildren2 = val2.GetComponentsInChildren<Transform>(true);
			for (int j = 0; j < componentsInChildren2.Length; j++)
			{
				((Component)componentsInChildren2[j]).gameObject.layer = layer;
			}
			PlaceModel(val2, log);
			AttachSmoke(prefab, val2, log);
			BuildCog(val2.transform, log);
			Transform val3 = BuildLever(val2.transform, log);
			if ((Object)(object)val3 != (Object)null && (Object)(object)component != (Object)null && (Object)(object)component.m_incinerateSwitch != (Object)null)
			{
				PlaceSwitchOnLever(component.m_incinerateSwitch, val3);
			}
		}

		private static void PlaceModel(GameObject model, ManualLogSource log)
		{
			//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_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: 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_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: 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_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: 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_012b: Unknown result type (might be due to invalid IL or missing references)
			Bounds val = MeasureRenderers(model);
			if (((Bounds)(ref val)).size.y > 0.05f)
			{
				model.transform.localScale = Vector3.one * (1.6f / ((Bounds)(ref val)).size.y);
				val = MeasureRenderers(model);
			}
			Vector3 size = ((Bounds)(ref val)).size;
			if (!(((Vector3)(ref size)).sqrMagnitude < 0.0001f) && !((Object)(object)model.transform.parent == (Object)null))
			{
				Vector3 position = model.transform.parent.position;
				Vector3 val2 = default(Vector3);
				((Vector3)(ref val2))..ctor(((Bounds)(ref val)).center.x, ((Bounds)(ref val)).min.y, ((Bounds)(ref val)).center.z);
				Transform transform = model.transform;
				transform.position += position - val2;
				string[] obj = new string[7] { "Salvage Station: model placed at ", null, null, null, null, null, null };
				size = ((Bounds)(ref val)).size;
				obj[1] = size.x.ToString("0.00");
				obj[2] = " x ";
				size = ((Bounds)(ref val)).size;
				obj[3] = size.y.ToString("0.00");
				obj[4] = " x ";
				size = ((Bounds)(ref val)).size;
				obj[5] = size.z.ToString("0.00");
				obj[6] = " m.";
				log.LogInfo((object)string.Concat(obj));
			}
		}

		private static Material FindLitMaterial(GameObject prefab)
		{
			Material val = FirstLit(prefab);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			if ((Object)(object)ZNetScene.instance == (Object)null)
			{
				return null;
			}
			string[] array = new string[3] { "piece_workbench", "piece_stonecutter", "piece_chest_wood" };
			for (int i = 0; i < array.Length; i++)
			{
				val = FirstLit(ZNetScene.instance.GetPrefab(array[i]));
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		private static Material FirstLit(GameObject root)
		{
			if ((Object)(object)root == (Object)null)
			{
				return null;
			}
			Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
			Material val = null;
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Material val2 = (((Object)(object)componentsInChildren[i] != (Object)null) ? componentsInChildren[i].sharedMaterial : null);
				if ((Object)(object)val2 == (Object)null || (Object)(object)val2.shader == (Object)null)
				{
					continue;
				}
				string name = ((Object)val2.shader).name;
				if (name.IndexOf("Error", StringComparison.Ordinal) < 0 && name.IndexOf("Hidden/", StringComparison.Ordinal) < 0)
				{
					if ((Object)(object)val == (Object)null)
					{
						val = val2;
					}
					if (name.IndexOf("Particle", StringComparison.Ordinal) < 0 && name.IndexOf("Effect", StringComparison.Ordinal) < 0 && name.IndexOf("Transparent", StringComparison.Ordinal) < 0 && name.IndexOf("Sprite", StringComparison.Ordinal) < 0)
					{
						return val2;
					}
				}
			}
			return val;
		}

		private static void BuildCog(Transform model, ManualLogSource log)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Expected O, but got Unknown
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			Transform val = FindNamed(model, "tripo_part_19");
			if ((Object)(object)val == (Object)null)
			{
				log.LogWarning((object)"Salvage Station: cog tripo_part_19 was not in the model.");
				return;
			}
			Renderer[] componentsInChildren = ((Component)val).GetComponentsInChildren<Renderer>(true);
			Bounds val2 = default(Bounds);
			bool flag = false;
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if ((Object)(object)componentsInChildren[i] == (Object)null)
				{
					continue;
				}
				Bounds bounds = componentsInChildren[i].bounds;
				Vector3 size = ((Bounds)(ref bounds)).size;
				if (!(((Vector3)(ref size)).sqrMagnitude < 1E-06f))
				{
					if (!flag)
					{
						val2 = componentsInChildren[i].bounds;
						flag = true;
					}
					else
					{
						((Bounds)(ref val2)).Encapsulate(componentsInChildren[i].bounds);
					}
				}
			}
			if (!flag)
			{
				log.LogWarning((object)"Salvage Station: cog has no mesh bounds.");
				return;
			}
			GameObject val3 = new GameObject("SalvageCog");
			val3.transform.SetParent(model, false);
			val3.transform.position = ((Bounds)(ref val2)).center;
			val3.transform.rotation = model.rotation;
			val.SetParent(val3.transform, true);
			log.LogInfo((object)"Salvage Station: cog pivots at its center.");
		}

		private static void AttachSmoke(GameObject prefab, GameObject model, ManualLogSource log)
		{
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ZNetScene.instance == (Object)null)
			{
				return;
			}
			GameObject prefab2 = ZNetScene.instance.GetPrefab("piece_spinningwheel");
			CraftingStation val = (((Object)(object)prefab2 != (Object)null) ? prefab2.GetComponentInChildren<CraftingStation>(true) : null);
			GameObject val2 = (((Object)(object)val != (Object)null) ? val.m_inUseObject : null);
			if ((Object)(object)val2 == (Object)null && (Object)(object)prefab2 != (Object)null)
			{
				Transform[] componentsInChildren = prefab2.GetComponentsInChildren<Transform>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					if (((Object)componentsInChildren[i]).name.IndexOf("smoke", StringComparison.OrdinalIgnoreCase) >= 0 && (Object)(object)((Component)componentsInChildren[i]).GetComponentInChildren<ParticleSystem>(true) != (Object)null)
					{
						val2 = ((Component)componentsInChildren[i]).gameObject;
						break;
					}
				}
			}
			if ((Object)(object)val2 == (Object)null)
			{
				log.LogWarning((object)"Salvage Station: piece_spinningwheel has no smoke to copy.");
				return;
			}
			GameObject val3 = Object.Instantiate<GameObject>(val2, prefab.transform);
			((Object)val3).name = "SalvageSmoke";
			ZNetView component = val3.GetComponent<ZNetView>();
			if ((Object)(object)component != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)component);
			}
			MeshRenderer[] componentsInChildren2 = val3.GetComponentsInChildren<MeshRenderer>(true);
			for (int j = 0; j < componentsInChildren2.Length; j++)
			{
				((Renderer)componentsInChildren2[j]).enabled = false;
			}
			SkinnedMeshRenderer[] componentsInChildren3 = val3.GetComponentsInChildren<SkinnedMeshRenderer>(true);
			for (int k = 0; k < componentsInChildren3.Length; k++)
			{
				((Renderer)componentsInChildren3[k]).enabled = false;
			}
			Bounds val4 = MeasureRenderers(model);
			Vector3 size = ((Bounds)(ref val4)).size;
			if (((Vector3)(ref size)).sqrMagnitude > 0.0001f)
			{
				val3.transform.position = new Vector3(((Bounds)(ref val4)).center.x, ((Bounds)(ref val4)).max.y, ((Bounds)(ref val4)).center.z);
			}
			val3.SetActive(false);
			int num = val3.GetComponentsInChildren<ParticleSystem>(true).Length;
			log.LogInfo((object)("Salvage Station: smoke '" + ((Object)val2).name + "' from the spinning wheel (" + num + " particle system(s))."));
		}

		private static Transform BuildLever(Transform model, ManualLogSource log)
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Expected O, but got Unknown
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: 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_00c8: 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_00f6: 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 = FindNamed(model, "tripo_part_16");
			Transform val2 = FindNamed(model, "tripo_part_48");
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
			{
				log.LogWarning((object)("Salvage Station: lever parts missing (16=" + ((Object)(object)val != (Object)null) + ", 48=" + ((Object)(object)val2 != (Object)null) + ")."));
				return null;
			}
			Bounds val3 = default(Bounds);
			bool flag = false;
			Renderer[] componentsInChildren = ((Component)val).GetComponentsInChildren<Renderer>(true);
			Renderer[] componentsInChildren2 = ((Component)val2).GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < 2; i++)
			{
				Renderer[] array = ((i == 0) ? componentsInChildren : componentsInChildren2);
				for (int j = 0; j < array.Length; j++)
				{
					if ((Object)(object)array[j] == (Object)null)
					{
						continue;
					}
					Bounds bounds = array[j].bounds;
					Vector3 size = ((Bounds)(ref bounds)).size;
					if (!(((Vector3)(ref size)).sqrMagnitude < 1E-06f))
					{
						if (!flag)
						{
							val3 = array[j].bounds;
							flag = true;
						}
						else
						{
							((Bounds)(ref val3)).Encapsulate(array[j].bounds);
						}
					}
				}
			}
			if (!flag)
			{
				log.LogWarning((object)"Salvage Station: lever parts have no mesh bounds.");
				return null;
			}
			GameObject val4 = new GameObject("SalvageLever");
			val4.transform.SetParent(model, false);
			val4.transform.position = new Vector3(((Bounds)(ref val3)).center.x, ((Bounds)(ref val3)).min.y, ((Bounds)(ref val3)).center.z);
			val4.transform.rotation = model.rotation;
			val.SetParent(val4.transform, true);
			val2.SetParent(val4.transform, true);
			log.LogInfo((object)"Salvage Station: lever is tripo_part_16 and tripo_part_48.");
			return val4.transform;
		}

		private static void PlaceSwitchOnLever(Switch sw, Transform lever)
		{
			//IL_0010: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_010c: 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_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: 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_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = ((Component)sw).transform;
			transform.SetParent(lever, false);
			transform.localPosition = Vector3.zero;
			transform.localRotation = Quaternion.identity;
			transform.localScale = Vector3.one;
			Collider[] components = ((Component)sw).GetComponents<Collider>();
			for (int i = 0; i < components.Length; i++)
			{
				components[i].enabled = false;
			}
			BoxCollider val = ((Component)sw).gameObject.AddComponent<BoxCollider>();
			Renderer[] componentsInChildren = ((Component)lever).GetComponentsInChildren<Renderer>(true);
			Bounds val2 = default(Bounds);
			bool flag = false;
			for (int j = 0; j < componentsInChildren.Length; j++)
			{
				if (!((Object)(object)componentsInChildren[j] == (Object)null) && componentsInChildren[j].enabled)
				{
					if (!flag)
					{
						val2 = componentsInChildren[j].bounds;
						flag = true;
					}
					else
					{
						((Bounds)(ref val2)).Encapsulate(componentsInChildren[j].bounds);
					}
				}
			}
			if (!flag)
			{
				val.center = new Vector3(0f, 0.4f, 0f);
				val.size = new Vector3(0.35f, 0.8f, 0.35f);
			}
			else
			{
				val.center = transform.InverseTransformPoint(((Bounds)(ref val2)).center);
				Vector3 lossyScale = transform.lossyScale;
				val.size = new Vector3(Mathf.Max(0.2f, ((Bounds)(ref val2)).size.x / Mathf.Max(0.001f, Mathf.Abs(lossyScale.x))), Mathf.Max(0.2f, ((Bounds)(ref val2)).size.y / Mathf.Max(0.001f, Mathf.Abs(lossyScale.y))), Mathf.Max(0.2f, ((Bounds)(ref val2)).size.z / Mathf.Max(0.001f, Mathf.Abs(lossyScale.z))));
			}
		}

		private static Transform FindNamed(Transform root, string name)
		{
			Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if (((Object)componentsInChildren[i]).name == name)
				{
					return componentsInChildren[i];
				}
			}
			return null;
		}

		private static Bounds MeasureRenderers(GameObject root)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
			Bounds result = default(Bounds);
			bool flag = false;
			foreach (Renderer val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null || !val.enabled || ((object)val).GetType().Name.IndexOf("Particle", StringComparison.Ordinal) >= 0)
				{
					continue;
				}
				Bounds bounds = val.bounds;
				Vector3 size = ((Bounds)(ref bounds)).size;
				if (!(((Vector3)(ref size)).sqrMagnitude < 0.0001f))
				{
					if (!flag)
					{
						result = val.bounds;
						flag = true;
					}
					else
					{
						((Bounds)(ref result)).Encapsulate(val.bounds);
					}
				}
			}
			return result;
		}
	}
}