Decompiled source of BigWok v1.5.0

BigWok.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using Mirror;
using UnityEngine;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("BigWok")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BigWok")]
[assembly: AssemblyTitle("BigWok")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
public static class Sfx
{
	private static readonly Dictionary<string, List<AudioSource>> _libraries = new Dictionary<string, List<AudioSource>>();

	private static GameObject _host;

	private static bool _classRegistered = false;

	private static string _defaultLibrary = null;

	public static void Init(string folderName = "sfx")
	{
		//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_005d: Expected O, but got Unknown
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: Expected O, but got Unknown
		if (!_libraries.ContainsKey(folderName))
		{
			if (!_classRegistered)
			{
				ClassInjector.RegisterTypeInIl2Cpp<SfxLoader>();
				_classRegistered = true;
			}
			if ((Object)(object)_host == (Object)null)
			{
				_host = new GameObject("SfxHost")
				{
					hideFlags = (HideFlags)61
				};
				Object.DontDestroyOnLoad((Object)(object)_host);
			}
			if (_defaultLibrary == null)
			{
				_defaultLibrary = folderName;
			}
			_libraries[folderName] = new List<AudioSource>();
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			string path = Path.Combine(directoryName, folderName);
			GameObject val = new GameObject("SfxLoader_" + folderName);
			val.transform.SetParent(_host.transform, false);
			SfxLoader sfxLoader = val.AddComponent<SfxLoader>();
			sfxLoader.BeginLoad(folderName, path);
		}
	}

	public static void PlayRandom(string folderName = null)
	{
		string text = folderName ?? _defaultLibrary;
		if (text == null || !_libraries.TryGetValue(text, out var value) || value.Count == 0)
		{
			Debug.LogWarning(Object.op_Implicit("[Sfx] PlayRandom('" + folderName + "') — no sounds loaded yet for that library. Did you call Sfx.Init()?"));
			return;
		}
		AudioSource val = value[Random.Range(0, value.Count)];
		if ((Object)(object)val == (Object)null || (Object)(object)val.clip == (Object)null)
		{
			Debug.LogWarning(Object.op_Implicit("[Sfx] Picked a null/destroyed clip holder — skipping this play."));
		}
		else
		{
			val.Play();
		}
	}

	public static int GetLoadedCount(string folderName = null)
	{
		string text = folderName ?? _defaultLibrary;
		List<AudioSource> value;
		return (text != null && _libraries.TryGetValue(text, out value)) ? value.Count : 0;
	}

	internal static void RegisterHolder(string folderName, AudioSource holder)
	{
		if (!_libraries.TryGetValue(folderName, out var value))
		{
			value = new List<AudioSource>();
			_libraries[folderName] = value;
		}
		value.Add(holder);
	}
}
internal class SfxLoader : MonoBehaviour
{
	private string libraryKey;

	private string folderPath;

	private readonly Queue<string> pendingFiles = new Queue<string>();

	private UnityWebRequest currentRequest;

	private string currentFile;

	public SfxLoader(IntPtr ptr)
		: base(ptr)
	{
	}

	public void BeginLoad(string key, string path)
	{
		libraryKey = key;
		folderPath = path;
		if (!Directory.Exists(folderPath))
		{
			Debug.LogWarning(Object.op_Implicit($"[Sfx] '{libraryKey}': no folder found at {folderPath} — this library will have no sounds."));
			return;
		}
		string[] files = Directory.GetFiles(folderPath);
		foreach (string text in files)
		{
			string text2 = Path.GetExtension(text).ToLowerInvariant();
			if (text2 == ".wav" || text2 == ".ogg" || text2 == ".mp3")
			{
				pendingFiles.Enqueue(text);
			}
		}
		Debug.Log(Object.op_Implicit($"[Sfx] '{libraryKey}': found {pendingFiles.Count} sound file(s) in {folderPath}, loading..."));
		StartNextLoad();
	}

	private void StartNextLoad()
	{
		//IL_0091: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
		if (pendingFiles.Count == 0)
		{
			Debug.Log(Object.op_Implicit($"[Sfx] '{libraryKey}': finished loading — {Sfx.GetLoadedCount(libraryKey)} sound(s) ready."));
		}
		else
		{
			currentFile = pendingFiles.Dequeue();
			AudioType audioType = GetAudioType(currentFile);
			string absoluteUri = new Uri(currentFile).AbsoluteUri;
			currentRequest = UnityWebRequestMultimedia.GetAudioClip(absoluteUri, audioType);
			currentRequest.SendWebRequest();
		}
	}

	private void Update()
	{
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Invalid comparison between Unknown and I4
		//IL_008c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Expected O, but got Unknown
		if (currentRequest == null || !currentRequest.isDone)
		{
			return;
		}
		try
		{
			if ((int)currentRequest.result == 1)
			{
				AudioClip content = DownloadHandlerAudioClip.GetContent(currentRequest);
				if ((Object)(object)content != (Object)null)
				{
					((Object)content).name = Path.GetFileNameWithoutExtension(currentFile);
					GameObject val = new GameObject("SfxClipHolder_" + libraryKey + "_" + ((Object)content).name);
					val.transform.SetParent(((Component)this).transform, false);
					AudioSource val2 = ((Il2CppObjectBase)val.AddComponent(Il2CppType.Of<AudioSource>())).Cast<AudioSource>();
					val2.clip = content;
					val2.playOnAwake = false;
					val2.spatialBlend = 0f;
					Sfx.RegisterHolder(libraryKey, val2);
					Debug.Log(Object.op_Implicit($"[Sfx] '{libraryKey}': loaded '{((Object)content).name}'."));
				}
				else
				{
					Debug.LogWarning(Object.op_Implicit($"[Sfx] '{libraryKey}': {currentFile} downloaded fine but produced a null AudioClip."));
				}
			}
			else
			{
				Debug.LogWarning(Object.op_Implicit($"[Sfx] '{libraryKey}': failed to load {currentFile}: {currentRequest.error}"));
			}
		}
		catch (Exception value)
		{
			Debug.LogError(Object.op_Implicit($"[Sfx] '{libraryKey}': exception loading {currentFile}: {value}"));
		}
		finally
		{
			currentRequest.Dispose();
			currentRequest = null;
		}
		StartNextLoad();
	}

	private static AudioType GetAudioType(string filePath)
	{
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		return (AudioType)(Path.GetExtension(filePath).ToLowerInvariant() switch
		{
			".mp3" => 13, 
			".ogg" => 14, 
			".wav" => 20, 
			_ => 0, 
		});
	}
}
namespace bigwok
{
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "BigWok";

		public const string PLUGIN_NAME = "BigWok";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace BigWokMod
{
	[HarmonyPatch(typeof(PlayerCharacter), "FixedUpdate")]
	public static class Footstep_Patch
	{
		public static float stepDistance = 1.4f;

		private static Vector3 lastPosition;

		private static bool hasLastPosition = false;

		private static float distanceSinceLastStep = 0f;

		private static void Postfix(PlayerCharacter __instance)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			if (!((NetworkBehaviour)__instance).isLocalPlayer || (Object)(object)__instance.rb == (Object)null || __instance.ground == null)
			{
				return;
			}
			Vector3 position = __instance.rb.position;
			if (!hasLastPosition)
			{
				lastPosition = position;
				hasLastPosition = true;
				return;
			}
			bool isGrounded = __instance.ground.isGrounded;
			float num = Vector3.Distance(position, lastPosition);
			lastPosition = position;
			if (!isGrounded)
			{
				distanceSinceLastStep = 0f;
				return;
			}
			distanceSinceLastStep += num;
			if (distanceSinceLastStep >= stepDistance)
			{
				distanceSinceLastStep = 0f;
				Debug.Log(Object.op_Implicit("Footstep triggered"));
				Sfx.PlayRandom("sfx");
			}
		}
	}
}
namespace BigWok
{
	public enum BodyPartType
	{
		Nose,
		Foot
	}
	[BepInPlugin("deck.bigwalk.bigwok", "BigWok", "1.0.0")]
	public class Plugin : BasePlugin
	{
		public const string Guid = "deck.bigwalk.bigwok";

		public const string Name = "BigWok";

		public const string Version = "1.0.0";

		public static ManualLogSource Log;

		public static ConfigEntry<bool> Enabled;

		public static ConfigEntry<string> FootObjFile;

		public static ConfigEntry<string> NoseObjFile;

		public static ConfigEntry<bool> InvertFaces;

		public static ConfigEntry<bool> ReplaceNose;

		public static ConfigEntry<bool> ReplaceFeet;

		public static ConfigEntry<bool> AutoFit;

		public static ConfigEntry<bool> FlipDirection;

		public static ConfigEntry<float> Scale;

		public static ConfigEntry<float> ScaleX;

		public static ConfigEntry<float> ScaleY;

		public static ConfigEntry<float> ScaleZ;

		public static ConfigEntry<float> RotX;

		public static ConfigEntry<float> RotY;

		public static ConfigEntry<float> RotZ;

		public static ConfigEntry<float> FootRotX;

		public static ConfigEntry<float> FootRotY;

		public static ConfigEntry<float> FootRotZ;

		public static ConfigEntry<float> FootOffsetY;

		public static ConfigEntry<float> FootOffsetZ;

		public static ConfigEntry<float> OffsetX;

		public static ConfigEntry<float> OffsetY;

		public static ConfigEntry<float> OffsetZ;

		public static ConfigEntry<bool> DumpHierarchy;

		public override void Load()
		{
			//IL_0390: Unknown result type (might be due to invalid IL or missing references)
			//IL_0395: Unknown result type (might be due to invalid IL or missing references)
			//IL_039f: Expected O, but got Unknown
			Log = ((BasePlugin)this).Log;
			Enabled = ((BasePlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master toggle to enable or disable BIG WOK.");
			FootObjFile = ((BasePlugin)this).Config.Bind<string>("General", "FootObjFile", "feetwok.obj", "Wavefront .obj file to load for the foot replacement mesh.");
			NoseObjFile = ((BasePlugin)this).Config.Bind<string>("General", "NoseObjFile", "nosewok.obj", "Wavefront .obj file to load for the nose replacement mesh.");
			InvertFaces = ((BasePlugin)this).Config.Bind<bool>("General", "InvertFaces", false, "Invert triangle face winding if model renders inside-out.");
			ReplaceNose = ((BasePlugin)this).Config.Bind<bool>("Body Parts", "ReplaceNose", true, "Replace the character's nose with a wok.");
			ReplaceFeet = ((BasePlugin)this).Config.Bind<bool>("Body Parts", "ReplaceFeet", true, "Replace the character's feet with woks.");
			AutoFit = ((BasePlugin)this).Config.Bind<bool>("Transform", "AutoFit", true, "Automatically scale the wok to fit target mesh bounds.");
			FlipDirection = ((BasePlugin)this).Config.Bind<bool>("Transform", "FlipDirection", true, "Flip model orientation end-for-end.");
			Scale = ((BasePlugin)this).Config.Bind<float>("Transform", "Scale", 1f, "Global scale multiplier.");
			ScaleX = ((BasePlugin)this).Config.Bind<float>("Transform", "ScaleX", 1f, "Scale factor along X axis.");
			ScaleY = ((BasePlugin)this).Config.Bind<float>("Transform", "ScaleY", 1f, "Scale factor along Y axis.");
			ScaleZ = ((BasePlugin)this).Config.Bind<float>("Transform", "ScaleZ", 1f, "Scale factor along Z axis.");
			RotX = ((BasePlugin)this).Config.Bind<float>("Transform", "RotationX", 0f, "Rotation offset around X axis in degrees.");
			RotY = ((BasePlugin)this).Config.Bind<float>("Transform", "RotationY", 0f, "Rotation offset around Y axis in degrees.");
			RotZ = ((BasePlugin)this).Config.Bind<float>("Transform", "RotationZ", -90f, "Rotation offset around Z axis in degrees.");
			FootRotX = ((BasePlugin)this).Config.Bind<float>("Transform", "FootRotationX", -20f, "X-axis tilt correction to keep feet flat when knees bend.");
			FootRotY = ((BasePlugin)this).Config.Bind<float>("Transform", "FootRotationY", 90f, "Extra Y-axis rotation offset applied specifically to feet to face forward.");
			FootRotZ = ((BasePlugin)this).Config.Bind<float>("Transform", "FootRotationZ", 90f, "Z-axis rotation offset to lay the wok flat/forward.");
			FootOffsetY = ((BasePlugin)this).Config.Bind<float>("Transform", "FootOffsetY", 0.18f, "Vertical position nudge to lift woks clear of the ground.");
			FootOffsetZ = ((BasePlugin)this).Config.Bind<float>("Transform", "FootOffsetZ", 0.02f, "Forward/backward position nudge for feet.");
			OffsetX = ((BasePlugin)this).Config.Bind<float>("Transform", "OffsetX", 0f, "Local position offset nudge along X.");
			OffsetY = ((BasePlugin)this).Config.Bind<float>("Transform", "OffsetY", 0f, "Local position offset nudge along Y.");
			OffsetZ = ((BasePlugin)this).Config.Bind<float>("Transform", "OffsetZ", 0f, "Local position offset nudge along Z.");
			DumpHierarchy = ((BasePlugin)this).Config.Bind<bool>("Debug", "DumpHierarchy", false, "Dump full transform hierarchy tree into BepInEx logs.");
			Sfx.Init();
			Harmony.CreateAndPatchAll(typeof(WokPatches), "deck.bigwalk.bigwok");
			Harmony.CreateAndPatchAll(typeof(Footstep_Patch), "deck.bigwalk.bigwok");
			ClassInjector.RegisterTypeInIl2Cpp<WokRuntime>();
			GameObject val = new GameObject("BigWokRuntime")
			{
				hideFlags = (HideFlags)61
			};
			Object.DontDestroyOnLoad((Object)(object)val);
			val.AddComponent<WokRuntime>();
			Log.LogInfo((object)"BIG WOK plugin initialized successfully.");
		}
	}
	[HarmonyPatch]
	internal static class WokPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(PlayerLips), "Initialize")]
		private static void OnLipsInitialized(PlayerLips __instance)
		{
			if (!Plugin.Enabled.Value || __instance == null)
			{
				return;
			}
			Component val = ((Il2CppObjectBase)__instance).Cast<Component>();
			if ((Object)(object)val != (Object)null && (Object)(object)val.gameObject != (Object)null)
			{
				PlayerCharacter componentInParent = val.gameObject.GetComponentInParent<PlayerCharacter>();
				if ((Object)(object)componentInParent != (Object)null)
				{
					WokRuntime.Queue(componentInParent);
				}
			}
		}
	}
	[HarmonyPatch(typeof(PlayerCharacter), "FixedUpdate")]
	public static class Footstep_Patch
	{
		public static float stepDistance = 1.4f;

		private static Vector3 lastPosition;

		private static bool hasLastPosition = false;

		private static float distanceSinceLastStep = 0f;

		private static void Postfix(PlayerCharacter __instance)
		{
			//IL_0076: 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_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.Enabled.Value || !Plugin.ReplaceFeet.Value)
			{
				hasLastPosition = false;
				distanceSinceLastStep = 0f;
			}
			else
			{
				if (!((NetworkBehaviour)__instance).isLocalPlayer || (Object)(object)__instance.rb == (Object)null || __instance.ground == null)
				{
					return;
				}
				Vector3 position = __instance.rb.position;
				if (!hasLastPosition)
				{
					lastPosition = position;
					hasLastPosition = true;
					return;
				}
				bool isGrounded = __instance.ground.isGrounded;
				float num = Vector3.Distance(position, lastPosition);
				lastPosition = position;
				if (!isGrounded)
				{
					distanceSinceLastStep = 0f;
					return;
				}
				distanceSinceLastStep += num;
				if (distanceSinceLastStep >= stepDistance)
				{
					distanceSinceLastStep = 0f;
					Sfx.PlayRandom("sfx");
				}
			}
		}
	}
	public class WokRuntime : MonoBehaviour
	{
		private static readonly List<PlayerCharacter> Pending = new List<PlayerCharacter>();

		private bool _loaded;

		private float _nextSweep;

		public WokRuntime(IntPtr ptr)
			: base(ptr)
		{
		}

		public static void Queue(PlayerCharacter character)
		{
			lock (Pending)
			{
				Pending.Add(character);
			}
		}

		private void Update()
		{
			if (!_loaded)
			{
				_loaded = true;
				WokSwapper.LoadModel();
			}
			WokSwapper.UpdatePreviewInput();
			if (Pending.Count > 0)
			{
				PlayerCharacter[] array;
				lock (Pending)
				{
					array = Pending.ToArray();
					Pending.Clear();
				}
				PlayerCharacter[] array2 = array;
				foreach (PlayerCharacter val in array2)
				{
					if ((Object)(object)val != (Object)null)
					{
						WokSwapper.ApplyCharacter(val);
					}
				}
			}
			if (Time.unscaledTime >= _nextSweep)
			{
				_nextSweep = Time.unscaledTime + 3f;
				SweepNow();
			}
		}

		private static void SweepNow()
		{
			if (!Plugin.Enabled.Value)
			{
				return;
			}
			try
			{
				List<PlayerCharacter> allPlayerCharacters = PlayerCharacter.allPlayerCharacters;
				if (allPlayerCharacters == null)
				{
					return;
				}
				for (int i = 0; i < allPlayerCharacters.Count; i++)
				{
					PlayerCharacter val = allPlayerCharacters[i];
					if ((Object)(object)val != (Object)null)
					{
						WokSwapper.ApplyCharacter(val);
					}
				}
			}
			catch
			{
			}
		}
	}
	internal static class WokSwapper
	{
		private static Mesh _footSource;

		private static Mesh _noseSource;

		private static readonly Dictionary<int, Mesh> Originals = new Dictionary<int, Mesh>();

		private static readonly Dictionary<int, Mesh> Fitted = new Dictionary<int, Mesh>();

		private static GameObject _previewObject;

		private static Vector3 _liveFootRotationOffset = Vector3.zero;

		private static readonly Vector3 BaseFootEuler = new Vector3(0f, 90f, 90f);

		public static bool LoadModel()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Expected O, but got Unknown
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Expected O, but got Unknown
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Expected O, but got Unknown
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Expected O, but got Unknown
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Expected O, but got Unknown
			bool result = true;
			string text = ResolveModelPath(Plugin.FootObjFile.Value);
			bool flag = default(bool);
			if (text == null)
			{
				ManualLogSource log = Plugin.Log;
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(48, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Foot model '");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Plugin.FootObjFile.Value);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' not found next to plugin or under ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Paths.PluginPath);
				}
				log.LogError(val);
				result = false;
			}
			else
			{
				string error;
				Mesh val2 = ObjMesh.Load(text, Plugin.InvertFaces.Value, out error);
				if ((Object)(object)val2 == (Object)null)
				{
					ManualLogSource log2 = Plugin.Log;
					BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(17, 2, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to read ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Path.GetFileName(text));
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(error);
					}
					log2.LogError(val);
					result = false;
				}
				else
				{
					((Object)val2).hideFlags = (HideFlags)61;
					_footSource = val2;
					ManualLogSource log3 = Plugin.Log;
					BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(27, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Successfully loaded ");
						((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(Path.GetFileName(text));
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" (feet)");
					}
					log3.LogInfo(val3);
				}
			}
			string text2 = ResolveModelPath(Plugin.NoseObjFile.Value);
			if (text2 == null)
			{
				ManualLogSource log4 = Plugin.Log;
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(48, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Nose model '");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Plugin.NoseObjFile.Value);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' not found next to plugin or under ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Paths.PluginPath);
				}
				log4.LogError(val);
				result = false;
			}
			else
			{
				string error2;
				Mesh val4 = ObjMesh.Load(text2, Plugin.InvertFaces.Value, out error2);
				if ((Object)(object)val4 == (Object)null)
				{
					ManualLogSource log5 = Plugin.Log;
					BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(17, 2, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to read ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Path.GetFileName(text2));
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(error2);
					}
					log5.LogError(val);
					result = false;
				}
				else
				{
					((Object)val4).hideFlags = (HideFlags)61;
					_noseSource = val4;
					ManualLogSource log6 = Plugin.Log;
					BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(27, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Successfully loaded ");
						((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(Path.GetFileName(text2));
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" (nose)");
					}
					log6.LogInfo(val3);
				}
			}
			Fitted.Clear();
			return result;
		}

		private static string ResolveModelPath(string file)
		{
			if (string.IsNullOrEmpty(file))
			{
				return null;
			}
			if (Path.IsPathRooted(file) && File.Exists(file))
			{
				return file;
			}
			string directoryName = Path.GetDirectoryName(typeof(WokSwapper).Assembly.Location);
			if (!string.IsNullOrEmpty(directoryName))
			{
				string text = Path.Combine(directoryName, file);
				if (File.Exists(text))
				{
					return text;
				}
			}
			try
			{
				if (!string.IsNullOrEmpty(Paths.PluginPath) && Directory.Exists(Paths.PluginPath))
				{
					string[] files = Directory.GetFiles(Paths.PluginPath, Path.GetFileName(file), SearchOption.AllDirectories);
					if (files.Length != 0)
					{
						return files[0];
					}
				}
			}
			catch
			{
			}
			return null;
		}

		public static void ApplyCharacter(PlayerCharacter character)
		{
			if (!((Object)(object)character == (Object)null))
			{
				if (Plugin.ReplaceNose.Value && (Object)(object)_noseSource != (Object)null)
				{
					ApplyPart(character, BodyPartType.Nose);
				}
				if (Plugin.ReplaceFeet.Value && (Object)(object)_footSource != (Object)null)
				{
					ApplyPart(character, BodyPartType.Foot);
				}
			}
		}

		private static Mesh GetSourceForPart(BodyPartType part)
		{
			return (part == BodyPartType.Foot) ? _footSource : _noseSource;
		}

		private static void ApplyPart(PlayerCharacter character, BodyPartType part)
		{
			Mesh sourceForPart = GetSourceForPart(part);
			if ((Object)(object)sourceForPart == (Object)null)
			{
				return;
			}
			List<Renderer> list = FindRenderersForPart(character, part);
			foreach (Renderer item in list)
			{
				if (!((Object)(object)item == (Object)null))
				{
					int instanceID = ((Object)item).GetInstanceID();
					Mesh mesh = GetMesh(item);
					if ((Object)(object)mesh != (Object)null && !Originals.ContainsKey(instanceID))
					{
						Originals[instanceID] = mesh;
					}
					Mesh val = (Originals.ContainsKey(instanceID) ? Originals[instanceID] : mesh);
					if ((Object)(object)val != (Object)null)
					{
						SetMesh(item, BuildFitted(val, sourceForPart, item, part), part);
					}
				}
			}
		}

		private static List<Renderer> FindRenderersForPart(PlayerCharacter character, BodyPartType part)
		{
			List<Renderer> list = new List<Renderer>();
			if (part == BodyPartType.Nose)
			{
				if (character.lips != null)
				{
					try
					{
						Transform lipTransform = character.lips.lipTransform;
						if ((Object)(object)lipTransform != (Object)null)
						{
							Renderer[] array = Il2CppArrayBase<Renderer>.op_Implicit(((Component)lipTransform).GetComponentsInChildren<Renderer>(true));
							Renderer[] array2 = array;
							foreach (Renderer val in array2)
							{
								if ((Object)(object)val != (Object)null)
								{
									list.Add(val);
								}
							}
						}
					}
					catch
					{
					}
				}
				return list;
			}
			Renderer[] array3 = Il2CppArrayBase<Renderer>.op_Implicit(((Component)character).GetComponentsInChildren<Renderer>(true));
			Renderer[] array4 = array3;
			foreach (Renderer val2 in array4)
			{
				if (!((Object)(object)val2 == (Object)null))
				{
					string text = ((Object)((Component)val2).gameObject).name.ToLower();
					if (part == BodyPartType.Foot && (text.Contains("foot") || text.Contains("ankle") || text.Contains("toe")))
					{
						list.Add(val2);
					}
				}
			}
			return list;
		}

		private static Mesh GetMesh(Renderer r)
		{
			SkinnedMeshRenderer val = ((Il2CppObjectBase)r).TryCast<SkinnedMeshRenderer>();
			if ((Object)(object)val != (Object)null)
			{
				return val.sharedMesh;
			}
			MeshFilter component = ((Component)r).GetComponent<MeshFilter>();
			return ((Object)(object)component != (Object)null) ? component.sharedMesh : null;
		}

		private static void SetMesh(Renderer r, Mesh mesh, BodyPartType part)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: 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)
			if ((Object)(object)mesh == (Object)null)
			{
				return;
			}
			SkinnedMeshRenderer val = ((Il2CppObjectBase)r).TryCast<SkinnedMeshRenderer>();
			if ((Object)(object)val != (Object)null)
			{
				((Renderer)val).enabled = false;
				Transform transform = ((Component)val).transform;
				Transform val2 = transform.Find("WokFootInstance");
				if ((Object)(object)val2 == (Object)null)
				{
					GameObject val3 = new GameObject("WokFootInstance");
					val3.transform.SetParent(transform, false);
					val2 = val3.transform;
				}
				if (part == BodyPartType.Foot)
				{
					val2.localPosition = new Vector3(0f, Plugin.FootOffsetY.Value + 1.75f, Plugin.FootOffsetZ.Value - 1.8f);
					val2.localRotation = Quaternion.Euler(BaseFootEuler + _liveFootRotationOffset);
				}
				MeshFilter val4 = ((Component)val2).gameObject.GetComponent<MeshFilter>() ?? ((Component)val2).gameObject.AddComponent<MeshFilter>();
				MeshRenderer val5 = ((Component)val2).gameObject.GetComponent<MeshRenderer>() ?? ((Component)val2).gameObject.AddComponent<MeshRenderer>();
				val4.sharedMesh = mesh;
				((Renderer)val5).sharedMaterials = ((Renderer)val).sharedMaterials;
			}
			else
			{
				MeshFilter component = ((Component)r).GetComponent<MeshFilter>();
				if ((Object)(object)component != (Object)null)
				{
					component.sharedMesh = mesh;
				}
			}
		}

		private static Mesh BuildFitted(Mesh original, Mesh source, Renderer renderer, BodyPartType part)
		{
			//IL_002f: 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_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: 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_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: 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_0183: 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)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: 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_01a1: 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_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: 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_0200: Expected O, but got Unknown
			//IL_0057: 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_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: 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_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			int instanceID = ((Object)original).GetInstanceID();
			if (Fitted.TryGetValue(instanceID, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			Vector3 val = Vector3.zero;
			Quaternion identity = Quaternion.identity;
			float num = 1f;
			if (Plugin.AutoFit.Value)
			{
				Bounds bounds = original.bounds;
				float num2 = Mathf.Max(new float[3]
				{
					((Bounds)(ref bounds)).size.x,
					((Bounds)(ref bounds)).size.y,
					((Bounds)(ref bounds)).size.z
				});
				Bounds bounds2 = source.bounds;
				float num3 = Mathf.Max(new float[3]
				{
					((Bounds)(ref bounds2)).size.x,
					((Bounds)(ref bounds2)).size.y,
					((Bounds)(ref bounds2)).size.z
				});
				num = num2 / Mathf.Max(num3, 0.0001f);
				val = ((Bounds)(ref bounds)).center;
			}
			Vector3 val2 = new Vector3(Plugin.ScaleX.Value, Plugin.ScaleY.Value, Plugin.ScaleZ.Value) * (Plugin.Scale.Value * num);
			Vector3 val3 = default(Vector3);
			((Vector3)(ref val3))..ctor(Plugin.RotX.Value, Plugin.RotY.Value, Plugin.RotZ.Value);
			Quaternion val4 = identity * Quaternion.Euler(val3);
			Vector3 val5 = val + new Vector3(Plugin.OffsetX.Value, Plugin.OffsetY.Value, Plugin.OffsetZ.Value);
			Bounds bounds3 = source.bounds;
			Matrix4x4 val6 = Matrix4x4.Translate(new Vector3(0f - ((Bounds)(ref bounds3)).center.x, 0f - ((Bounds)(ref bounds3)).center.y, 0f - ((Bounds)(ref bounds3)).min.z));
			Matrix4x4 val7 = Matrix4x4.TRS(val5, val4, val2) * val6;
			Mesh val8 = new Mesh
			{
				name = ((Object)source).name + "_fitted",
				hideFlags = (HideFlags)61
			};
			Il2CppStructArray<Vector3> vertices = source.vertices;
			Il2CppStructArray<Vector3> val9 = new Il2CppStructArray<Vector3>((long)((Il2CppArrayBase<Vector3>)(object)vertices).Length);
			for (int i = 0; i < ((Il2CppArrayBase<Vector3>)(object)vertices).Length; i++)
			{
				((Il2CppArrayBase<Vector3>)(object)val9)[i] = ((Matrix4x4)(ref val7)).MultiplyPoint3x4(((Il2CppArrayBase<Vector3>)(object)vertices)[i]);
			}
			val8.vertices = val9;
			if (source.uv != null && ((Il2CppArrayBase<Vector2>)(object)source.uv).Length == ((Il2CppArrayBase<Vector3>)(object)vertices).Length)
			{
				val8.uv = source.uv;
			}
			val8.triangles = source.triangles;
			val8.RecalculateNormals();
			val8.RecalculateTangents();
			val8.RecalculateBounds();
			Fitted[instanceID] = val8;
			return val8;
		}

		public static void UpdatePreviewInput()
		{
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Expected O, but got Unknown
			if (Input.GetKeyDown((KeyCode)96))
			{
				if ((Object)(object)_previewObject != (Object)null)
				{
					DestroyPreview();
				}
				else
				{
					CreatePreview();
				}
			}
			if ((Object)(object)_previewObject == (Object)null)
			{
				return;
			}
			bool flag = false;
			if (Input.GetKeyDown((KeyCode)257))
			{
				_liveFootRotationOffset.x -= 45f;
				flag = true;
			}
			if (Input.GetKeyDown((KeyCode)258))
			{
				_liveFootRotationOffset.x += 45f;
				flag = true;
			}
			if (Input.GetKeyDown((KeyCode)259))
			{
				_liveFootRotationOffset.x = 0f;
				flag = true;
			}
			if (Input.GetKeyDown((KeyCode)260))
			{
				_liveFootRotationOffset.y -= 45f;
				flag = true;
			}
			if (Input.GetKeyDown((KeyCode)261))
			{
				_liveFootRotationOffset.y += 45f;
				flag = true;
			}
			if (Input.GetKeyDown((KeyCode)262))
			{
				_liveFootRotationOffset.y = 0f;
				flag = true;
			}
			if (Input.GetKeyDown((KeyCode)263))
			{
				_liveFootRotationOffset.z -= 45f;
				flag = true;
			}
			if (Input.GetKeyDown((KeyCode)264))
			{
				_liveFootRotationOffset.z += 45f;
				flag = true;
			}
			if (Input.GetKeyDown((KeyCode)265))
			{
				_liveFootRotationOffset.z = 0f;
				flag = true;
			}
			if (flag)
			{
				_liveFootRotationOffset.x = NormalizeAngle(_liveFootRotationOffset.x);
				_liveFootRotationOffset.y = NormalizeAngle(_liveFootRotationOffset.y);
				_liveFootRotationOffset.z = NormalizeAngle(_liveFootRotationOffset.z);
				_previewObject.transform.localRotation = Quaternion.Euler(_liveFootRotationOffset);
				ApplyLiveOffsetToRealFeet();
				ManualLogSource log = Plugin.Log;
				bool flag2 = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(33, 3, ref flag2);
				if (flag2)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("BigWok live foot offset: X=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(_liveFootRotationOffset.x);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" Y=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(_liveFootRotationOffset.y);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" Z=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(_liveFootRotationOffset.z);
				}
				log.LogInfo(val);
			}
		}

		private static void ApplyLiveOffsetToRealFeet()
		{
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			PlayerCharacter val = FindLocalPlayerCharacter();
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			List<Renderer> list = FindRenderersForPart(val, BodyPartType.Foot);
			foreach (Renderer item in list)
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				SkinnedMeshRenderer val2 = ((Il2CppObjectBase)item).TryCast<SkinnedMeshRenderer>();
				if (!((Object)(object)val2 == (Object)null))
				{
					Transform val3 = ((Component)val2).transform.Find("WokFootInstance");
					if (!((Object)(object)val3 == (Object)null))
					{
						val3.localRotation = Quaternion.Euler(BaseFootEuler + _liveFootRotationOffset);
					}
				}
			}
		}

		private static float NormalizeAngle(float degrees)
		{
			degrees %= 360f;
			if (degrees < 0f)
			{
				degrees += 360f;
			}
			return degrees;
		}

		private static void CreatePreview()
		{
			//IL_0091: 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_00a4: Expected O, but got Unknown
			//IL_00af: 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_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_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Expected O, but got Unknown
			if ((Object)(object)_footSource == (Object)null)
			{
				Plugin.Log.LogWarning((object)"BigWok preview: feetwok model isn't loaded yet.");
				return;
			}
			Transform val = null;
			if ((Object)(object)Camera.main != (Object)null)
			{
				val = ((Component)Camera.main).transform;
			}
			else
			{
				PlayerCharacter val2 = FindLocalPlayerCharacter();
				if ((Object)(object)val2 != (Object)null)
				{
					val = ((Component)val2).transform;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)"BigWok preview: couldn't find a camera or local player to anchor to.");
				return;
			}
			_previewObject = new GameObject("BigWok_FootPreview")
			{
				hideFlags = (HideFlags)61
			};
			_previewObject.transform.position = val.position + val.forward * 1.5f;
			_liveFootRotationOffset = Vector3.zero;
			_previewObject.transform.rotation = Quaternion.identity;
			ApplyLiveOffsetToRealFeet();
			MeshFilter val3 = _previewObject.AddComponent<MeshFilter>();
			val3.sharedMesh = _footSource;
			MeshRenderer val4 = _previewObject.AddComponent<MeshRenderer>();
			Shader val5 = FindPreviewShader();
			if ((Object)(object)val5 != (Object)null)
			{
				((Renderer)val4).sharedMaterial = new Material(val5)
				{
					hideFlags = (HideFlags)61
				};
			}
			Plugin.Log.LogInfo((object)"BigWok preview ON. Numpad 1/2=X, 4/5=Y, 7/8=Z (45 deg steps), 3/6/9=reset that axis. ` to hide.");
		}

		private static void DestroyPreview()
		{
			if ((Object)(object)_previewObject != (Object)null)
			{
				Object.Destroy((Object)(object)_previewObject);
				_previewObject = null;
			}
			Plugin.Log.LogInfo((object)"BigWok preview OFF.");
		}

		private static Shader FindPreviewShader()
		{
			string[] array = new string[4] { "Standard", "Universal Render Pipeline/Lit", "Legacy Shaders/Diffuse", "Sprites/Default" };
			string[] array2 = array;
			foreach (string text in array2)
			{
				Shader val = Shader.Find(text);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		private static PlayerCharacter FindLocalPlayerCharacter()
		{
			try
			{
				List<PlayerCharacter> allPlayerCharacters = PlayerCharacter.allPlayerCharacters;
				if (allPlayerCharacters == null)
				{
					return null;
				}
				for (int i = 0; i < allPlayerCharacters.Count; i++)
				{
					PlayerCharacter val = allPlayerCharacters[i];
					if ((Object)(object)val != (Object)null && ((NetworkBehaviour)val).isLocalPlayer)
					{
						return val;
					}
				}
			}
			catch
			{
			}
			return null;
		}
	}
	internal static class ObjMesh
	{
		private static readonly char[] Sep = new char[2] { ' ', '\t' };

		public static Mesh Load(string path, bool invert, out string error)
		{
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Expected O, but got Unknown
			//IL_027e: 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_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Unknown result type (might be due to invalid IL or missing references)
			error = null;
			try
			{
				List<Vector3> list = new List<Vector3>();
				List<Vector2> list2 = new List<Vector2>();
				Dictionary<string, int> remap = new Dictionary<string, int>();
				List<Vector3> list3 = new List<Vector3>();
				List<Vector2> list4 = new List<Vector2>();
				List<int> list5 = new List<int>();
				string[] array = File.ReadAllLines(path);
				for (int i = 0; i < array.Length; i++)
				{
					string text = array[i].Trim();
					if (text.Length == 0 || text[0] == '#')
					{
						continue;
					}
					string[] array2 = text.Split(Sep, StringSplitOptions.RemoveEmptyEntries);
					if (array2.Length == 0)
					{
						continue;
					}
					switch (array2[0])
					{
					case "v":
						if (array2.Length >= 4)
						{
							list.Add(new Vector3(0f - F(array2[1]), F(array2[2]), F(array2[3])));
						}
						break;
					case "vt":
						if (array2.Length >= 3)
						{
							list2.Add(new Vector2(F(array2[1]), F(array2[2])));
						}
						break;
					case "f":
					{
						if (array2.Length < 4)
						{
							break;
						}
						int[] array3 = new int[array2.Length - 1];
						for (int j = 1; j < array2.Length; j++)
						{
							array3[j - 1] = Corner(array2[j], list, list2, remap, list3, list4);
						}
						for (int k = 1; k < array3.Length - 1; k++)
						{
							list5.Add(array3[0]);
							if (invert)
							{
								list5.Add(array3[k]);
								list5.Add(array3[k + 1]);
							}
							else
							{
								list5.Add(array3[k + 1]);
								list5.Add(array3[k]);
							}
						}
						break;
					}
					}
				}
				if (list3.Count == 0 || list5.Count == 0)
				{
					error = "no geometry found in " + Path.GetFileName(path);
					return null;
				}
				Mesh val = new Mesh
				{
					name = "BigWok_" + Path.GetFileNameWithoutExtension(path)
				};
				Il2CppStructArray<Vector3> val2 = new Il2CppStructArray<Vector3>((long)list3.Count);
				for (int l = 0; l < list3.Count; l++)
				{
					((Il2CppArrayBase<Vector3>)(object)val2)[l] = list3[l];
				}
				val.vertices = val2;
				if (list4.Count == list3.Count)
				{
					Il2CppStructArray<Vector2> val3 = new Il2CppStructArray<Vector2>((long)list4.Count);
					for (int m = 0; m < list4.Count; m++)
					{
						((Il2CppArrayBase<Vector2>)(object)val3)[m] = list4[m];
					}
					val.uv = val3;
				}
				Il2CppStructArray<int> val4 = new Il2CppStructArray<int>((long)list5.Count);
				for (int n = 0; n < list5.Count; n++)
				{
					((Il2CppArrayBase<int>)(object)val4)[n] = list5[n];
				}
				val.triangles = val4;
				val.RecalculateNormals();
				val.RecalculateTangents();
				val.RecalculateBounds();
				return val;
			}
			catch (Exception ex)
			{
				error = ex.Message;
				return null;
			}
		}

		private static int Corner(string token, List<Vector3> positions, List<Vector2> texcoords, Dictionary<string, int> remap, List<Vector3> verts, List<Vector2> uvs)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: 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)
			if (remap.TryGetValue(token, out var value))
			{
				return value;
			}
			string[] array = token.Split('/');
			int num = Index(array[0], positions.Count);
			int num2 = ((array.Length > 1 && array[1].Length > 0) ? Index(array[1], texcoords.Count) : (-1));
			verts.Add((num >= 0) ? positions[num] : Vector3.zero);
			uvs.Add((num2 >= 0) ? texcoords[num2] : Vector2.zero);
			return remap[token] = verts.Count - 1;
		}

		private static int Index(string s, int count)
		{
			if (!int.TryParse(s, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result))
			{
				return -1;
			}
			if (result > 0)
			{
				return result - 1;
			}
			if (result < 0)
			{
				return count + result;
			}
			return -1;
		}

		private static float F(string s)
		{
			if (!float.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
			{
				return 0f;
			}
			return result;
		}
	}
}