Decompiled source of ResourcefulHands v0.11.0
plugins/monksilly.ResourcefulHands.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
#define DEBUG using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using ResourcefulHands.Assets; using ResourcefulHands.Core; using ResourcefulHands.Systems; using ResourcefulHands.UI; using ResourcefulHands.Utility; using Steamworks; using UnityEngine; using UnityEngine.Networking; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: AssemblyCompany("monksilly.ResourcefulHands")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("0.11.0.0")] [assembly: AssemblyInformationalVersion("0.11.0+10846c9c044bed2547b40b01f049c83ef2a10115")] [assembly: AssemblyProduct("Resourceful Hands")] [assembly: AssemblyTitle("monksilly.ResourcefulHands")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.11.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.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 ResourcefulHands { [BepInPlugin("monksilly.resourcefulhands", "Resourceful Hands", "0.11.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string Guid = "monksilly.resourcefulhands"; public const string Name = "Resourceful Hands"; public const string Version = "0.11.0"; public const string DeprecatedRHGuid = "triggeredidiot.wkd.resourcefulhands"; public GameObject? ofHolder; internal static int TargetFps = 60; private static int _mainThreadId; public static Plugin Instance { get; private set; } = null; private Harmony? Harmony { get; set; } public static bool IsWindows => RuntimeInformation.IsOSPlatform(OSPlatform.Windows); public static bool IsMainThread => Thread.CurrentThread.ManagedThreadId == _mainThreadId; public void Awake() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown ModLogger.InitLog(((BaseUnityPlugin)this).Logger); ModLogger.Debug("Patching...", 50, "/home/galfar/RiderProjects/ResourcefulHands/Plugin.cs"); Harmony = new Harmony("monksilly.resourcefulhands"); Harmony.PatchAll(); CheckDeprecation(); VersionChecker.Check(); Task.Run((Func<Task?>)ResourcePacksManager.InitLoad); _mainThreadId = Thread.CurrentThread.ManagedThreadId; Instance = this; RHConfig.InitConfigs(); ModLogger.Debug("Hooking loaded event...", 64, "/home/galfar/RiderProjects/ResourcefulHands/Plugin.cs"); bool flag = false; SceneManager.sceneLoaded += SceneHandler.OnSceneLoaded; ModLogger.Info("Resourceful Hands has loaded!", 68, "/home/galfar/RiderProjects/ResourcefulHands/Plugin.cs"); } private void CheckDeprecation() { if (Chainloader.PluginInfos.ContainsKey("triggeredidiot.wkd.resourcefulhands")) { PluginInfo val = Chainloader.PluginInfos["triggeredidiot.wkd.resourcefulhands"]; ModLogger.Warning("Detected deprecated mod [" + val.Metadata.Name + "]. Disabling it...", 76, "/home/galfar/RiderProjects/ResourcefulHands/Plugin.cs"); BaseUnityPlugin instance = val.Instance; if (!((Object)(object)instance == (Object)null)) { ((Behaviour)instance).enabled = false; Harmony.UnpatchID("triggeredidiot.wkd.resourcefulhands"); Object.Destroy((Object)(object)((Component)instance).gameObject); } } } } internal class CoroutineDispatcher : MonoBehaviour { private static CoroutineDispatcher? _instance; private static Dictionary<string, Action> updateActions = new Dictionary<string, Action>(); public static Queue<Action> threadQueue = new Queue<Action>(); public static Coroutine? Dispatch(IEnumerator routine) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) IEnumerator routine2 = routine; if (!Plugin.IsMainThread) { RunOnMainThread(delegate { Dispatch(routine2); }); return null; } if ((Object)(object)_instance == (Object)null) { _instance = new GameObject("CoroutineDispatcher").AddComponent<CoroutineDispatcher>(); Object.DontDestroyOnLoad((Object)(object)_instance); } return ((MonoBehaviour)_instance).StartCoroutine(routine2); } public static bool StopDispatch(Coroutine routine) { Coroutine routine2 = routine; if (!Plugin.IsMainThread) { RunOnMainThread(delegate { StopDispatch(routine2); }); return false; } if ((Object)(object)_instance == (Object)null) { return false; } ((MonoBehaviour)_instance).StopCoroutine(routine2); return true; } public static async Task RunOnMainThreadAndWait(Action action, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string file = "") { string file2 = file; Action action2 = action; bool hasRan = false; threadQueue.Enqueue(delegate { ModLogger.Debug($"Running [{Path.GetFileName(file2)}:{lineNumber}] on the main thread...", 73, "/home/galfar/RiderProjects/ResourcefulHands/Utility/CoroutineDispatcher.cs"); try { action2(); } catch (Exception data) { ModLogger.Error(data, 77, "/home/galfar/RiderProjects/ResourcefulHands/Utility/CoroutineDispatcher.cs"); } hasRan = true; }); int fps = Mathf.Clamp(Plugin.TargetFps, -1, 120); if (fps < 1) { fps = 60; } while (!hasRan) { await Task.Delay(Mathf.FloorToInt(1f / (float)fps * 1000f)); } ModLogger.Debug($"[{Path.GetFileName(file2)}:{lineNumber}] has executed!", 89, "/home/galfar/RiderProjects/ResourcefulHands/Utility/CoroutineDispatcher.cs"); } public static void RunOnMainThread(Action action) { threadQueue.Enqueue(action); } public static void RunOnMainThreadOrCurrent(Action action) { if (Plugin.IsMainThread) { action(); } else { threadQueue.Enqueue(action); } } public static string AddToUpdate(Action action) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_instance == (Object)null) { _instance = new GameObject("CoroutineDispatcher").AddComponent<CoroutineDispatcher>(); Object.DontDestroyOnLoad((Object)(object)_instance); } string text = Guid.NewGuid().ToString(); updateActions.Add(text, action); return text; } public static void RemoveFromUpdate(string guid) { updateActions.Remove(guid); } public void LateUpdate() { foreach (Action value in updateActions.Values) { value(); } while (threadQueue.Count > 0) { threadQueue.Dequeue()?.Invoke(); } } } public class RHDispatcher : MonoBehaviour { private static RHDispatcher? _instance; private static readonly Queue<Action> ExecutionQueue = new Queue<Action>(); public static void Initialize() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)_instance)) { GameObject val = new GameObject("RH_Dispatcher"); _instance = val.AddComponent<RHDispatcher>(); Object.DontDestroyOnLoad((Object)(object)val); } } public static void RunOnMainThread(Action action) { lock (ExecutionQueue) { ExecutionQueue.Enqueue(action); } } private void Update() { lock (ExecutionQueue) { while (ExecutionQueue.Count > 0) { ExecutionQueue.Dequeue()(); } } } public static Coroutine? StartStaticCoroutine(IEnumerator routine) { RHDispatcher? instance = _instance; return (instance != null) ? ((MonoBehaviour)instance).StartCoroutine(routine) : null; } } } namespace ResourcefulHands.Utility { public static class AudioUtils { public static AudioClip CreateAudioClip(float[] samples, int sampleRate, int channels, string name = "GeneratedClip") { int num = samples.Length / channels; AudioClip val = AudioClip.Create(name, num, channels, sampleRate, true); val.SetData(samples, 0); return val; } } public class CosmeticSettings { public string ID { get; set; } = null; public List<SwapSpriteEntry>? SwapSprites { get; set; } public List<InteractSwapEntry>? InteractSwaps { get; set; } public List<SecondaryTextureEntry>? GlobalSecondary { get; set; } } public class SwapSpriteEntry { public string SpriteName { get; set; } = null; public List<string> ReplacementSpriteNames { get; set; } = null; } public class InteractSwapEntry { public string ReplacementSpriteName { get; set; } = null; } public class SecondaryTextureEntry { public List<string> SecondaryTextureNames { get; set; } = null; } public static class FileUtils { public static string GetSHA256Checksum(string filePath) { using FileStream inputStream = File.OpenRead(filePath); using SHA256 sHA = SHA256.Create(); byte[] array = sHA.ComputeHash(inputStream); StringBuilder stringBuilder = new StringBuilder(); byte[] array2 = array; foreach (byte b in array2) { stringBuilder.Append(b.ToString("x2")); } return stringBuilder.ToString(); } } public static class RHExtensions { public static void WriteString(this Stream stream, string value) { foreach (char c in value) { stream.WriteByte((byte)c); } } public static void WriteInteger(this Stream stream, uint value) { stream.WriteByte((byte)(value & 0xFFu)); stream.WriteByte((byte)((value >> 8) & 0xFFu)); stream.WriteByte((byte)((value >> 16) & 0xFFu)); stream.WriteByte((byte)((value >> 24) & 0xFFu)); } public static void WriteShort(this Stream stream, ushort value) { stream.WriteByte((byte)(value & 0xFFu)); stream.WriteByte((byte)((uint)(value >> 8) & 0xFFu)); } public static RenderTexture ConvertToARGB32(this RenderTexture self) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 if ((int)self.format == 0) { return self; } RenderTexture temporary = RenderTexture.GetTemporary(((Texture)self).width, ((Texture)self).height, 0, (RenderTextureFormat)0); Graphics.Blit((Texture)(object)self, temporary); return temporary; } public static string CleanString(string str) { char[] invalidFileNameChars = Path.GetInvalidFileNameChars(); char[] array = invalidFileNameChars; foreach (char c in array) { str = str.Replace(c.ToString(), ""); } StringBuilder stringBuilder = new StringBuilder(); string text = str; foreach (char c2 in text) { if (c2 <= '\u007f') { stringBuilder.Append(c2); } } return stringBuilder.ToString(); } } public static class TransformExtensions { public static Transform? FindParentWithName(this Transform current, string name) { while ((Object)(object)current != (Object)null && ((Object)current).name != name) { current = current.parent; } return current; } public static Transform? FindTopmostParent(this Transform current) { while ((Object)(object)current.parent != (Object)null) { current = current.parent; } return current; } public static T? FindAt<T>(this Transform t, string path) where T : Component { string[] array = path.Split('/'); string[] array2 = array; foreach (string text in array2) { t = t.Find(text); if ((Object)(object)t == (Object)null) { return default(T); } } return ((Component)t).GetComponentInChildren<T>(); } } } namespace ResourcefulHands.UI { public class OF_CosmeticPage : MonoBehaviour { [CompilerGenerated] private sealed class <InitializeCosmeticsRoutine>d__17 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public OF_CosmeticPage <>4__this; private Task <packTask>5__1; private GameObject <candidate>5__2; private UI_CosmeticsMenu <menu>5__3; object? IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <InitializeCosmeticsRoutine>d__17(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <packTask>5__1 = null; <candidate>5__2 = null; <menu>5__3 = null; <>1__state = -2; } private bool MoveNext() { //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; ModLogger.Info("Waiting for Resource Packs to finish loading...", 80, "/home/galfar/RiderProjects/ResourcefulHands/UI/OF_CosmeticPage.cs"); <packTask>5__1 = ResourcePacksManager.InitialLoadTask; goto IL_006f; case 1: <>1__state = -1; goto IL_006f; case 2: <>1__state = -1; goto IL_00ce; case 3: { <>1__state = -1; break; } IL_006f: if (!<packTask>5__1.IsCompleted) { <>2__current = null; <>1__state = 1; return true; } ModLogger.Info("Packs loaded. Now waiting for Unity Cosmetics Menu to initialize...", 88, "/home/galfar/RiderProjects/ResourcefulHands/UI/OF_CosmeticPage.cs"); <candidate>5__2 = null; goto IL_00ce; IL_00ce: if ((Object)(object)<candidate>5__2 == (Object)null) { <candidate>5__2 = GameObject.Find("Canvas - Screens/Screens/Canvas - Screen - Other/Cosmetics"); <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 2; return true; } <menu>5__3 = <candidate>5__2.GetComponent<UI_CosmeticsMenu>(); break; } if ((Object)(object)<menu>5__3 == (Object)null || <menu>5__3.cosmeticPages == null) { <>2__current = null; <>1__state = 3; return true; } ModLogger.Info("Game UI ready. Injecting RH Cosmetic Page...", 104, "/home/galfar/RiderProjects/ResourcefulHands/UI/OF_CosmeticPage.cs"); <>4__this.FindCosmeticsTemplate(); <>4__this.PrepareCosmeticPage(); <>4__this.PrepareCosmetics(); <>4__this.IsReady = true; ModLogger.Info("RH Cosmetics are ready.", 111, "/home/galfar/RiderProjects/ResourcefulHands/UI/OF_CosmeticPage.cs"); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public static OF_CosmeticPage instance; private CosmeticPage? cosmeticPage; private GameObject? cosmeticsMenuObject; private UI_CosmeticsMenu? cosmeticsMenu; private UI_Page? pageTemplate; private UI_PageHolder? pageHolder; private GameObject? RHPage; private Tab? RHTab; public List<Cosmetic_Base> RHHands = new List<Cosmetic_Base>(); public bool IsReady { get; private set; } = false; private void Awake() { } private void OnSceneLoadedDelegate(Scene scene, LoadSceneMode mode) { OnSceneLoaded(((Scene)(ref scene)).name); } private void OnSceneLoaded(string sceneName) { if (!((Object)(object)instance != (Object)(object)this)) { if (sceneName != "Main-Menu") { cosmeticPage = null; cosmeticsMenuObject = null; cosmeticsMenu = null; pageTemplate = null; RHPage = null; RHTab = null; ((MonoBehaviour)instance).StopAllCoroutines(); } else if (!Object.op_Implicit((Object)(object)RHPage)) { ((MonoBehaviour)instance).StartCoroutine(InitializeCosmeticsRoutine()); } } } private void OnDestroy() { SceneManager.sceneLoaded -= OnSceneLoadedDelegate; } [IteratorStateMachine(typeof(<InitializeCosmeticsRoutine>d__17))] private IEnumerator InitializeCosmeticsRoutine() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <InitializeCosmeticsRoutine>d__17(0) { <>4__this = this }; } private void FindCosmeticsTemplate() { if (Object.op_Implicit((Object)(object)cosmeticsMenuObject) && Object.op_Implicit((Object)(object)cosmeticsMenu)) { return; } ModLogger.Debug("Finding Cosmetics Template", 119, "/home/galfar/RiderProjects/ResourcefulHands/UI/OF_CosmeticPage.cs"); GameObject val = GameObject.Find("Canvas - Screens/Screens/Canvas - Screen - Other/Cosmetics"); if (!Object.op_Implicit((Object)(object)val)) { ModLogger.Error("Cosmetics template game object not found", 123, "/home/galfar/RiderProjects/ResourcefulHands/UI/OF_CosmeticPage.cs"); return; } UI_CosmeticsMenu component = val.GetComponent<UI_CosmeticsMenu>(); if (!Object.op_Implicit((Object)(object)component)) { ModLogger.Error("Cosmetics menu template not found", 129, "/home/galfar/RiderProjects/ResourcefulHands/UI/OF_CosmeticPage.cs"); return; } ModLogger.Debug("Cosmetics template found", 132, "/home/galfar/RiderProjects/ResourcefulHands/UI/OF_CosmeticPage.cs"); cosmeticsMenuObject = val; cosmeticsMenu = component; } private void PrepareCosmeticPage() { //IL_0069: 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_0084: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown if (cosmeticPage == null) { CosmeticPage val = cosmeticsMenu?.cosmeticPages.Find((CosmeticPage p) => p.cosmeticType == "hand"); ModLogger.Error($"Cosmetic page: {val} | ", 218, "/home/galfar/RiderProjects/ResourcefulHands/UI/OF_CosmeticPage.cs"); cosmeticPage = new CosmeticPage { name = "Hands", cosmeticType = "hand", pageHolder = val?.pageHolder }; } } public void PrepareCosmetics() { //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_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Expected O, but got Unknown //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Expected O, but got Unknown //IL_0431: Unknown result type (might be due to invalid IL or missing references) //IL_0498: Unknown result type (might be due to invalid IL or missing references) //IL_049d: Unknown result type (might be due to invalid IL or missing references) //IL_04a5: Unknown result type (might be due to invalid IL or missing references) //IL_04ad: Unknown result type (might be due to invalid IL or missing references) //IL_04b7: Expected O, but got Unknown //IL_030f: Unknown result type (might be due to invalid IL or missing references) //IL_0314: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Unknown result type (might be due to invalid IL or missing references) //IL_0331: Unknown result type (might be due to invalid IL or missing references) //IL_0332: Unknown result type (might be due to invalid IL or missing references) //IL_0337: Unknown result type (might be due to invalid IL or missing references) //IL_033e: Expected O, but got Unknown if (RHHands.Count > 0) { return; } foreach (ResourcePack loadedPack in ResourcePacksManager.LoadedPacks) { bool flag = false; foreach (KeyValuePair<string, Texture2D> texture in loadedPack.Textures) { if (!texture.Key.Contains("Sprite_Library")) { continue; } flag = true; break; } if (!flag) { continue; } ModLogger.Debug("Loading " + loadedPack.name + " in Experimental Menu", 250, "/home/galfar/RiderProjects/ResourcefulHands/UI/OF_CosmeticPage.cs"); Cosmetic_HandItem val = ScriptableObject.CreateInstance<Cosmetic_HandItem>(); ((Object)val).name = loadedPack.name; val.currentEmoteIds = new List<int>(2) { 0, 0 }; val.currentPaletteId = 0; Sprite val2 = ((IEnumerable<Sprite>)Resources.FindObjectsOfTypeAll<Sprite>()).FirstOrDefault((Func<Sprite, bool>)((Sprite s) => ((Object)s).name == "card-blank-foreground")); ModLogger.Debug($"Card template: {val2}", 257, "/home/galfar/RiderProjects/ResourcefulHands/UI/OF_CosmeticPage.cs"); Texture2D tex = TextureCompositor.CreatePackCard(loadedPack.Icon, TextureCompositor.SpriteToTexture(val2)); ((Cosmetic_Base)val).cosmeticInfo = new Cosmetic_Info { id = loadedPack.guid, cosmeticName = loadedPack.name, tag = "hand", author = loadedPack.author, description = loadedPack.desc, unlock = "", cardForeground = TextureCompositor.TextureToSprite(tex) }; val.cosmeticData = new Cosmetic_HandItem_Data { swapSprites = new List<SwapSprite>(), cosmeticName = loadedPack.name, author = loadedPack.author, description = loadedPack.desc, unlock = "", id = loadedPack.guid }; Dictionary<string, SwapSprite> dictionary = new Dictionary<string, SwapSprite>(); Dictionary<string, InteractSwap> dictionary2 = new Dictionary<string, InteractSwap>(); ModLogger.Debug("Loading swaps", 286, "/home/galfar/RiderProjects/ResourcefulHands/UI/OF_CosmeticPage.cs"); foreach (KeyValuePair<string, Texture2D> texture2 in loadedPack.Textures) { if (texture2.Value == null) { continue; } if (texture2.Key.Contains("Sprite_Library")) { int layer = int.Parse(texture2.Key.Split('_')[^1]); DynamicHandSlicer.SheetType sheetType = ((!texture2.Key.Contains("Background")) ? DynamicHandSlicer.SheetType.Foreground : DynamicHandSlicer.SheetType.Background); Dictionary<Vector2, Texture2D> slices = DynamicHandSlicer.SliceSheet(texture2.Value, 4, 4); Dictionary<string, Texture2D> namedSlicesFromSlicedSheet = DynamicHandSlicer.GetNamedSlicesFromSlicedSheet(sheetType, slices, layer); foreach (KeyValuePair<string, Texture2D> item in namedSlicesFromSlicedSheet) { string key = item.Key; Texture2D value = item.Value; ModLogger.Debug(key ?? "", 302, "/home/galfar/RiderProjects/ResourcefulHands/UI/OF_CosmeticPage.cs"); SwapSprite val3 = new SwapSprite { framerate = 1f, hand = -1, loopTimeOffset = 0f, offset = Vector2.zero }; Sprite val4 = TextureCompositor.TextureToSprite(value); ((Object)val4).name = key; val3.materialBase = ""; val3.replacementSpriteNames = new List<string>(1) { key }; val3.replacementSprites = new List<Sprite>(1) { val4 }; val3.rotation = 0f; val3.scale = 1f; val3.secondaryTextures = new List<SecondaryTextures>(); val3.spriteName = key; val3.usePalette = true; dictionary.TryAdd(val3.spriteName, val3); } } if (!texture2.Key.Contains("hand-sheet")) { continue; } Dictionary<Vector2, Texture2D> dictionary3 = DynamicHandSlicer.SliceSheet(texture2.Value, 4, 4); for (int i = 0; i < 4; i++) { dictionary3.TryGetValue(new Vector2(0f, (float)i), out var value2); Sprite replacementSprite = TextureCompositor.TextureToSprite(value2); string text = ""; switch (i) { case 0: text = "interact-hand-open"; break; case 1: text = "interact-hand-grabbed"; break; case 2: text = "interact-hand-point"; break; case 3: text = "interact-hand-item"; break; } InteractSwap val5 = new InteractSwap { replacementSprite = replacementSprite, replacementSpriteName = text, spriteName = text }; dictionary2.TryAdd(val5.spriteName, val5); } } Cosmetic_HandItem_Data cosmeticData = val.cosmeticData; if (cosmeticData.swapSprites == null) { cosmeticData.swapSprites = new List<SwapSprite>(); } cosmeticData = val.cosmeticData; if (cosmeticData.interactSwaps == null) { cosmeticData.interactSwaps = new List<InteractSwap>(); } foreach (string key2 in dictionary.Keys) { ModLogger.Debug(key2, 374, "/home/galfar/RiderProjects/ResourcefulHands/UI/OF_CosmeticPage.cs"); } foreach (string key3 in dictionary2.Keys) { ModLogger.Debug(key3, 379, "/home/galfar/RiderProjects/ResourcefulHands/UI/OF_CosmeticPage.cs"); } val.cosmeticData.swapSprites.AddRange(dictionary.Values); val.cosmeticData.interactSwaps.AddRange(dictionary2.Values); RHHands.Add((Cosmetic_Base)(object)val); SafeInitialize(val); } } private void SafeInitialize(Cosmetic_HandItem item) { if (!(typeof(Cosmetic_HandItem).GetField("swapDict", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(item) is IDictionary dictionary) || dictionary.Count == 0) { ModLogger.Debug("Initializing " + ((Object)item).name + "...", 401, "/home/galfar/RiderProjects/ResourcefulHands/UI/OF_CosmeticPage.cs"); InvokePrivateMethod(item, "Initialize"); } else { ModLogger.Warning(((Object)item).name + " was already initialized! Skipping to avoid Dictionary crash.", 406, "/home/galfar/RiderProjects/ResourcefulHands/UI/OF_CosmeticPage.cs"); } } private void ApplyCosmetics() { if (!Object.op_Implicit((Object)(object)cosmeticsMenu) || RHHands.Count == 0) { return; } InjectIntoCosmeticManager(); FieldInfo field = typeof(CosmeticPage).GetField("cosmetics", BindingFlags.Instance | BindingFlags.NonPublic); if (cosmeticPage != null && field != null) { List<Cosmetic_Base> list = new List<Cosmetic_Base>(); list.AddRange(RHHands); field.SetValue(cosmeticPage, list); } try { cosmeticsMenu.FillCosmeticPage(RHHands, "Only RH", cosmeticPage); } catch (Exception ex) { ModLogger.Error("FillCosmeticPage failed: " + ex.Message, 433, "/home/galfar/RiderProjects/ResourcefulHands/UI/OF_CosmeticPage.cs"); } } public void InjectIntoCosmeticManager() { try { Type typeFromHandle = typeof(CL_CosmeticManager); FieldInfo field = typeFromHandle.GetField("cosmeticHands", BindingFlags.Static | BindingFlags.NonPublic); FieldInfo field2 = typeFromHandle.GetField("cosmeticHandDict", BindingFlags.Static | BindingFlags.NonPublic); FieldInfo field3 = typeFromHandle.GetField("loadedCosmetics", BindingFlags.Static | BindingFlags.NonPublic); List<Cosmetic_HandItem> list = (List<Cosmetic_HandItem>)field.GetValue(null); Dictionary<string, Cosmetic_HandItem> dictionary = (Dictionary<string, Cosmetic_HandItem>)field2.GetValue(null); List<Cosmetic_Base> list2 = (List<Cosmetic_Base>)field3.GetValue(null); foreach (Cosmetic_Base rHHand in RHHands) { Cosmetic_HandItem val = (Cosmetic_HandItem)(object)((rHHand is Cosmetic_HandItem) ? rHHand : null); if (!((Object)(object)val == (Object)null) && !dictionary.ContainsKey(((Cosmetic_Base)val).cosmeticInfo.id)) { list.Add(val); dictionary.Add(((Cosmetic_Base)val).cosmeticInfo.id, val); list2.Add((Cosmetic_Base)(object)val); SettingsManager.settings.cosmeticSaveData.FillNewCosmeticInfo((Cosmetic_Base)(object)val); ModLogger.Info("Successfully injected " + ((Object)val).name + " into CL_CosmeticManager", 469, "/home/galfar/RiderProjects/ResourcefulHands/UI/OF_CosmeticPage.cs"); } } } catch (Exception ex) { ModLogger.Error("Failed to inject into CL_CosmeticManager: " + ex.Message, 475, "/home/galfar/RiderProjects/ResourcefulHands/UI/OF_CosmeticPage.cs"); } } public static void InvokePrivateMethod(object obj, string methodName, params object[] args) { MethodInfo method = obj.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null) { method.Invoke(obj, args); } else { ModLogger.Error("Method '" + methodName + "' not found on " + obj.GetType().Name, 493, "/home/galfar/RiderProjects/ResourcefulHands/UI/OF_CosmeticPage.cs"); } } } } namespace ResourcefulHands.Systems { public static class RHCommands { private static readonly string[] ordinals = new string[6] { "first", "second", "third", "fourth", "fifth", "sixth" }; public const string DumpCommand = "dumptopack"; public const string ReloadCommand = "reloadpacks"; public const string MoveCommand = "reorderpack"; public const string ListCommand = "listpacks"; public const string EnableCommand = "enablepack"; public const string DisableCommand = "disablepack"; public const string EnableAllCommand = "enablepack_all"; public const string DisableAllCommand = "disablepack_all"; public const string ToggleDebug = "rhtoggledebug"; public const string DumpPackInfo = "dumppackinfo"; public const string AssignHandPack = "assignhandpack"; public const string ClearHandPack = "clearhandpack"; public const string ListHandPacks = "listhandpacks"; public static void RefreshCommands() { CommandConsole instance = CommandConsole.instance; if (!Object.op_Implicit((Object)(object)instance)) { return; } CommandConsole.RemoveCommand("dumptopack"); CommandConsole.RemoveCommand("reloadpacks"); CommandConsole.RemoveCommand("reorderpack"); CommandConsole.RemoveCommand("listpacks"); CommandConsole.RemoveCommand("enablepack"); CommandConsole.RemoveCommand("disablepack"); CommandConsole.RemoveCommand("enablepack_all"); CommandConsole.RemoveCommand("disablepack_all"); CommandConsole.RemoveCommand("rhtoggledebug"); CommandConsole.RemoveCommand("dumppackinfo"); CommandConsole.AddCommand("dumptopack", (Action<string[]>)DumpAllToPack, false); CommandConsole.AddCommand("reloadpacks", (Action<string[]>)ReloadPacks, false); CommandConsole.AddCommand("reorderpack", (Action<string[]>)MovePacks, false); CommandConsole.AddCommand("listpacks", (Action<string[]>)ListPacks, false); CommandConsole.AddCommand("enablepack", (Action<string[]>)EnablePack, false); CommandConsole.AddCommand("disablepack", (Action<string[]>)DisablePack, false); CommandConsole.AddCommand("enablepack_all", (Action<string[]>)EnableAll, false); CommandConsole.AddCommand("disablepack_all", (Action<string[]>)DisableAll, false); CommandConsole.AddCommand("rhtoggledebug", (Action<string[]>)delegate { RHDebugTools.isOn = !RHDebugTools.isOn; }, false); CommandConsole.AddCommand("dumppackinfo", (Action<string[]>)delegate(string[] args) { ResourcePack packFromArgs = GetPackFromArgs(args, ModLogger.Player.Error); if (packFromArgs == null) { ModLogger.Player.Info("The first argument must be a pack!"); } else { ModLogger.Player.Info("-- " + packFromArgs.name + " --"); ModLogger.Player.Info("- [textures] -"); ModLogger.Player.Info(packFromArgs.relativeTexturesPath ?? ""); foreach (KeyValuePair<string, Texture2D> texture in packFromArgs.Textures) { ModLogger.Player.Info($"{texture.Key}: {texture.Value}"); } ModLogger.Player.Info("- [sounds] -"); ModLogger.Player.Info(packFromArgs.relativeSoundsPath ?? ""); foreach (KeyValuePair<string, AudioClip> sound in packFromArgs.Sounds) { ModLogger.Player.Info($"{sound.Key}: {sound.Value}"); } ModLogger.Player.Info("- [misc] -"); ModLogger.Player.Info($"{packFromArgs.relativeIconPath}: {packFromArgs.Icon}"); ModLogger.Player.Info("packVer: " + packFromArgs.packVersion); ModLogger.Player.Info("gameVer: " + packFromArgs.gameVersionString); ModLogger.Player.Info($"frmtVer: {packFromArgs.formatVersion}"); } }, false); CommandConsole.AddCommand("assignhandpack", (Action<string[]>)AssignHandResourcePack, false); CommandConsole.AddCommand("clearhandpack", (Action<string[]>)ClearHandResourcePack, false); CommandConsole.AddCommand("listhandpacks", (Action<string[]>)ListHandResourcePack, false); } private static void MovePacks(string[] args) { if (args.Length != 2) { ModLogger.Player.Error("Invalid number of arguments!"); ModLogger.Player.Info("Usage: reorderpack [pack guid/pack index] [up/down]\nResource packs at the bottom of the loaded list will override textures at the top, use this command to move a resource pack up or down the list."); return; } ResourcePack pack = GetPackFromArgs(args, ModLogger.Player.Error); if (pack == null) { ModLogger.Player.Info("Usage: reorderpack [pack guid/pack index] [up/down]\nResource packs at the bottom of the loaded list will override textures at the top, use this command to move a resource pack up or down the list."); return; } string text = args[1].ToLower(); bool flag; switch (text) { case "up": case "down": case "u": case "d": flag = true; break; default: flag = false; break; } if (!flag) { ModLogger.Player.Error("Invalid second argument!\nExpected: up or down"); ModLogger.Player.Info("Usage: reorderpack [pack guid/pack index] [up/down]\nResource packs at the bottom of the loaded list will override textures at the top, use this command to move a resource pack up or down the list."); return; } flag = ((text == "up" || text == "u") ? true : false); bool isUp = flag; ResourcePacksManager.MovePack(pack, isUp); ModLogger.Player.Info("Reloading packs..."); ResourcePacksManager.ReloadPacks(waitTillReady: true, delegate { ModLogger.Player.Info(string.Format("Moved {0} {1}{2}{3} {4} successfully!", pack.name, '{', pack.guid, '}', isUp ? "up" : "down")); }); } private static void ListPacks(string[] args) { for (int i = 0; i < ResourcePacksManager.LoadedPacks.Count; i++) { ResourcePack resourcePack = ResourcePacksManager.LoadedPacks[i]; ModLogger.Player.Info(((!resourcePack.IsActive) ? "[DISABLED] " : $"[{i}] ") + resourcePack.name + " by " + resourcePack.author + "\n-- description:\n" + resourcePack.desc + "\n-- guid: '" + resourcePack.guid + "'\n____"); } } private static void ReloadPacks(string[] args) { ResourcePacksManager.ReloadPacks(waitTillReady: true, delegate { ModLogger.Player.Info("Resource packs reloaded successfully!"); }); } private static ResourcePack? GetPackFromArgs(string[] args, Action<string> logErr, int indexOverride = 0) { string text = "first"; if (indexOverride != 0) { text = ((indexOverride > 6) ? indexOverride.ToString() : ordinals[indexOverride - 1]); } ResourcePack resourcePack = null; if (int.TryParse(args[indexOverride], out var result)) { resourcePack = ((result >= 0 && result < ResourcePacksManager.LoadedPacks.Count) ? ResourcePacksManager.LoadedPacks[result] : null); if (resourcePack == null) { logErr($"Invalid {text} argument!\nThe resource pack at index {result} doesn't exist!"); return null; } } else { string packName = args[indexOverride].ToLower(); resourcePack = ResourcePacksManager.LoadedPacks.FirstOrDefault((ResourcePack p) => p.guid.ToLower() == packName); if (resourcePack == null) { logErr("Invalid " + text + " argument!\nThe resource pack with guid '" + packName + "' doesn't exist!"); return null; } } return resourcePack; } private static void DisablePack(string[] args) { ResourcePack pack = GetPackFromArgs(args, ModLogger.Player.Error); if (pack == null) { ModLogger.Player.Info("Usage: disablepack [pack guid/pack index]\nDisables a resource pack."); return; } pack.IsActive = false; ModLogger.Player.Info("Reloading packs..."); ResourcePacksManager.ReloadPacks(waitTillReady: true, delegate { ModLogger.Player.Info($"Disabled {pack.name} {'{'}{pack.guid}{'}'} successfully!"); }); } private static void EnablePack(string[] args) { ResourcePack pack = GetPackFromArgs(args, ModLogger.Player.Error); if (pack == null) { ModLogger.Player.Info("Usage: enablepack [pack guid/pack index]\nEnables a resource pack."); return; } pack.IsActive = true; ModLogger.Player.Info("Reloading packs..."); ResourcePacksManager.ReloadPacks(waitTillReady: true, delegate { ModLogger.Player.Info($"Enabled {pack.name} {'{'}{pack.guid}{'}'} successfully!"); }); ModLogger.Player.Info($"Enabled {pack.name} {'{'}{pack.guid}{'}'} successfully!"); } private static void DisableAll(string[] args) { ResourcePacksManager.LoadedPacks.ForEach(delegate(ResourcePack p) { p.IsActive = false; }); ModLogger.Player.Info("Reloading packs..."); ResourcePacksManager.ReloadPacks(waitTillReady: true, delegate { ModLogger.Player.Info("Disabled all packs successfully!"); }); } private static void EnableAll(string[] args) { ResourcePacksManager.LoadedPacks.ForEach(delegate(ResourcePack p) { p.IsActive = true; }); ModLogger.Player.Info("Reloading packs..."); ResourcePacksManager.ReloadPacks(waitTillReady: true, delegate { ModLogger.Player.Info("Enabled all packs successfully!"); }); } private static void DumpAllToPack(string[] args) { if (args.Any((string arg) => arg.ToLower() == "help")) { ModLogger.Player.Info("Use this command to generate a resource pack that contains every in-game asset. Good to find assets to replace but beware that there will probably be unused assets!"); return; } if (!args.Any((string arg) => arg.ToLower() == "confirm")) { ModLogger.Player.Error("Warning: This takes up alot of storage space due to uncompressed audio!\nTHIS WILL ALSO END YOUR RUN AND LOAD YOU BACK TO THE MAIN MENU!!\nARE YOU SURE? (type 'dumptopack confirm')"); return; } ModLogger.Player.Info("Dumping all resources to a template resource pack [this will take some time]..."); List<Texture2D> textures = new List<Texture2D>(); List<Texture2D> spriteTextures = new List<Texture2D>(); List<AudioClip> sounds = new List<AudioClip>(); Texture2D[] source = Resources.FindObjectsOfTypeAll<Texture2D>(); textures.AddRange(source.Where((Texture2D tex) => !textures.Contains(tex))); AudioClip[] source2 = Resources.FindObjectsOfTypeAll<AudioClip>(); sounds.AddRange(source2.Where((AudioClip sound) => !sounds.Contains(sound))); Sprite[] source3 = Resources.FindObjectsOfTypeAll<Sprite>(); spriteTextures.AddRange(from sprite in source3 where Object.op_Implicit((Object)(object)sprite.texture) && !spriteTextures.Contains(sprite.texture) select sprite.texture); ModLogger.Player.Info("Loading Playground [to extract assets]"); SceneManager.LoadScene("Playground"); source = Resources.FindObjectsOfTypeAll<Texture2D>(); textures.AddRange(source.Where((Texture2D tex) => !textures.Contains(tex))); source2 = Resources.FindObjectsOfTypeAll<AudioClip>(); sounds.AddRange(source2.Where((AudioClip sound) => !sounds.Contains(sound))); source3 = Resources.FindObjectsOfTypeAll<Sprite>(); spriteTextures.AddRange(from sprite in source3 where Object.op_Implicit((Object)(object)sprite.texture) && !spriteTextures.Contains(sprite.texture) select sprite.texture); ModLogger.Player.Info("Loading Training-Level [to extract assets]"); SceneManager.LoadScene("Training-Level"); source = Resources.FindObjectsOfTypeAll<Texture2D>(); textures.AddRange(source.Where((Texture2D tex) => !textures.Contains(tex))); source2 = Resources.FindObjectsOfTypeAll<AudioClip>(); sounds.AddRange(source2.Where((AudioClip sound) => !sounds.Contains(sound))); source3 = Resources.FindObjectsOfTypeAll<Sprite>(); spriteTextures.AddRange(from sprite in source3 where Object.op_Implicit((Object)(object)sprite.texture) && !spriteTextures.Contains(sprite.texture) select sprite.texture); ModLogger.Player.Info("Loading Main-Menu [to extract assets and finish]"); SceneManager.LoadScene("Main-Menu"); source = Resources.FindObjectsOfTypeAll<Texture2D>(); textures.AddRange(source.Where((Texture2D tex) => !textures.Contains(tex))); source2 = Resources.FindObjectsOfTypeAll<AudioClip>(); sounds.AddRange(source2.Where((AudioClip sound) => !sounds.Contains(sound))); source3 = Resources.FindObjectsOfTypeAll<Sprite>(); spriteTextures.AddRange(from sprite in source3 where Object.op_Implicit((Object)(object)sprite.texture) && !spriteTextures.Contains(sprite.texture) select sprite.texture); ModLogger.Player.Info("Packing assets..."); int count = textures.Count; int count2 = spriteTextures.Count; int count3 = sounds.Count; string text = Path.Combine(RHConfig.PacksFolder, $"extracted-assets-{count + count3 + count2}-{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}"); if (!Directory.Exists(text)) { Directory.CreateDirectory(text); } string texturesPath = Path.Combine(text, "Textures"); string path = Path.Combine(texturesPath, "Sprites"); string text2 = Path.Combine(text, "Sounds"); if (!Directory.Exists(texturesPath)) { Directory.CreateDirectory(texturesPath); } if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } if (!Directory.Exists(text2)) { Directory.CreateDirectory(text2); } StringBuilder stringBuilder = new StringBuilder(); StringBuilder stringBuilder2 = new StringBuilder(); StringBuilder stringBuilder3 = new StringBuilder(); stringBuilder.AppendLine("-- ingame textures list --"); stringBuilder2.AppendLine("-- ingame sprite textures list --"); stringBuilder3.AppendLine("-- ingame sounds list --"); int num = 0; int num2 = 0; int num3 = 0; for (int i = 0; i < count; i++) { Texture2D val = textures[i]; ModLogger.Player.Info($"Saving textures ({i}/{count})"); stringBuilder.Append(((Object)val).name); bool flag = false; try { flag = ExportTexture(val); } catch (Exception ex) { ModLogger.Player.Error(((Object)val).name + " failed because " + ex.Message); } if (flag) { num++; } stringBuilder.AppendLine(flag ? "" : " [failed to extract]"); } for (int j = 0; j < count2; j++) { Texture2D val2 = spriteTextures[j]; ModLogger.Player.Info($"Saving textures ({j}/{count2})"); stringBuilder2.Append(((Object)val2).name); bool flag2 = false; try { flag2 = ExportTexture(val2); } catch (Exception ex2) { ModLogger.Player.Error(((Object)val2).name + " failed because " + ex2.Message); } if (flag2) { num3++; } stringBuilder2.AppendLine(flag2 ? "" : " [failed to extract]"); } for (int k = 0; k < count3; k++) { AudioClip val3 = sounds[k]; ModLogger.Player.Info($"Saving sounds ({k}/{count3})"); stringBuilder3.Append(((Object)val3).name); bool flag3 = false; try { string path2 = Path.Combine(text2, ((Object)val3).name + ".wav"); float[] array = new float[val3.samples * val3.channels]; if (!val3.GetData(array, 0)) { ModLogger.Player.Error("Failed to access " + ((Object)val3).name + "'s audio data!"); stringBuilder3.AppendLine(" [failed to extract]"); continue; } using (FileStream stream = new FileStream(path2, FileMode.CreateNew, FileAccess.Write)) { ushort num4 = 16; string value = "RIFF"; string value2 = "WAVE"; string value3 = "fmt "; uint value4 = 16u; ushort value5 = 1; ushort num5 = (ushort)val3.channels; uint frequency = (uint)val3.frequency; uint value6 = (uint)(frequency * val3.channels * num4 / 8); ushort value7 = (ushort)(num5 * num4 / 8); string value8 = "data"; uint num6 = (uint)(array.Length * val3.channels * num4 / 8); uint value9 = 36 + num6; stream.WriteString(value); stream.WriteInteger(value9); stream.WriteString(value2); stream.WriteString(value3); stream.WriteInteger(value4); stream.WriteShort(value5); stream.WriteShort(num5); stream.WriteInteger(frequency); stream.WriteInteger(value6); stream.WriteShort(value7); stream.WriteShort(num4); stream.WriteString(value8); stream.WriteInteger(num6); float[] array2 = array; foreach (float num7 in array2) { short num8 = 0; if (num7 > 0f) { float num9 = num7 * 32767f; if (num9 > 32767f) { num9 = 32767f; } num8 = (short)num9; } if (num7 < 0f) { float num10 = num7 * 32768f; if (num10 < -32768f) { num10 = -32768f; } num8 = (short)num10; } stream.WriteShort((ushort)num8); } num2++; flag3 = true; } goto IL_088c; } catch (Exception ex3) { ModLogger.Player.Info(((Object)val3).name + " failed because " + ex3.Message); goto IL_088c; } IL_088c: stringBuilder3.AppendLine(flag3 ? "" : " [failed to extract]"); } ModLogger.Player.Info("Writing data files"); File.WriteAllText(Path.Combine(text, "info.json"), "{\n \"name\":\"generated-game-assets\",\n \"desc\":\"Every game asset\",\n \"author\":\"Dark Machine Games\",\n \n \"pack-version\":\"0.50\",\n \"steamid\":0,\n \n \"guid\":\"generated.game.assets.unique\",\n \"hidden-from-list\":true,\n \"only-in-full-game\":false,\n \n \"game-string\":\"b0.50p\",\n \n \"textures-folder\":\"Textures\",\n \"sounds-folder\":\"Sounds\",\n \"icon-file\":\"pack.png\",\n \"icon-filter\":false,\n \n \"format-version\":3\n}"); File.WriteAllText(Path.Combine(text, "textures_list.txt"), stringBuilder.ToString()); File.WriteAllText(Path.Combine(text, "sprite_textures_list.txt"), stringBuilder2.ToString()); File.WriteAllText(Path.Combine(text, "audio_list.txt"), stringBuilder3.ToString()); ModLogger.Player.Info($"Successfully saved {num} of {count} textures!"); ModLogger.Player.Info($"Successfully saved {num3} of {count2} sprite textures!"); ModLogger.Player.Info($"Successfully saved {num2} of {count3} sounds!"); ModLogger.Player.Info("Packed all assets to '" + text + "'"); bool ExportTexture(Texture2D texture) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_0099: Unknown result type (might be due to invalid IL or missing references) bool result = false; try { if (!((Texture)texture).isReadable) { ModLogger.Player.Info(((Object)texture).name + " isn't readable, saving the slow way..."); RenderTexture val4 = new RenderTexture(((Texture)texture).width, ((Texture)texture).height, 24); RenderTexture active = RenderTexture.active; try { RenderTexture.active = val4; Graphics.Blit((Texture)(object)texture, val4); RenderTexture val6 = (RenderTexture.active = val4.ConvertToARGB32()); Texture2D val7 = new Texture2D(((Texture)texture).width, ((Texture)texture).height, texture.format, false); val7.ReadPixels(new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), 0, 0); val7.Apply(); val6.Release(); byte[] bytes = ImageConversion.EncodeToPNG(val7); File.WriteAllBytes(Path.Combine(texturesPath, ((Object)texture).name + ".png"), bytes); result = true; } catch { } RenderTexture.active = active; val4.Release(); } else { byte[] bytes2 = ImageConversion.EncodeToPNG(texture); File.WriteAllBytes(Path.Combine(texturesPath, ((Object)texture).name + ".png"), bytes2); result = true; } } catch (Exception ex4) { ModLogger.Player.Error(((Object)texture).name + " failed because " + ex4.Message); } return result; } } private static void AssignHandResourcePack(string[] args) { if (args.Length != 2) { ModLogger.Player.Error("Invalid number of arguments!"); ModLogger.Player.Info("Usage: assignhandpack [hand] [pack guid/pack index]\nHand: left or right (case insensitive)\nUse 'listpacks' to see available pack GUIDs"); return; } int handIdFromString = GetHandIdFromString(args[0]); if (handIdFromString < 0) { ModLogger.Player.Error("Invalid hand! Must be 'left' or 'right'"); ModLogger.Player.Info("Usage: assignhandpack [hand] [pack guid/pack index]\nHand: left or right (case insensitive)\nUse 'listpacks' to see available pack GUIDs"); return; } ResourcePack packFromArgs = GetPackFromArgs(args, ModLogger.Player.Error, 1); if (packFromArgs == null) { ModLogger.Player.Error("Invalid pack!"); ModLogger.Player.Info("Usage: assignhandpack [hand] [pack guid/pack index]\nHand: left or right (case insensitive)\nUse 'listpacks' to see available pack GUIDs"); return; } RHSpriteManager.OverrideHands(packFromArgs.guid, handIdFromString == 0); if (handIdFromString == 0) { RHConfig.PackPrefs.LeftHandPack = packFromArgs.guid; } else { RHConfig.PackPrefs.RightHandPack = packFromArgs.guid; } RHSpriteManager.ClearHandSprites(); string text = ((handIdFromString == 0) ? "left" : "right"); ModLogger.Player.Info("Assigned resource pack '" + packFromArgs.guid + "' to " + text + " hand"); } private static void ClearHandResourcePack(string[] args) { if (args.Length != 1) { ModLogger.Player.Error("Invalid number of arguments!"); ModLogger.Player.Info("Usage: clearhandpack [hand]\nHand: left or right (case insensitive)"); return; } int handIdFromString = GetHandIdFromString(args[0]); if (handIdFromString < 0) { ModLogger.Player.Error("Invalid hand! Must be 'left' or 'right'"); ModLogger.Player.Info("Usage: clearhandpack [hand]\nHand: left or right (case insensitive)"); return; } RHSpriteManager.ClearHandsOverride(handIdFromString == 0); if (handIdFromString == 0) { RHConfig.PackPrefs.LeftHandPack = ""; } else { RHConfig.PackPrefs.RightHandPack = ""; } RHSpriteManager.ClearHandSprites(); string text = ((handIdFromString == 0) ? "left" : "right"); ModLogger.Player.Info("Cleared resource pack from " + text + " hand"); } private static void ListHandResourcePack(string[] args) { ModLogger.Player.Info("Hand Resource Pack Assignments:"); for (int i = 0; i < 2; i++) { string text = ((i == 0) ? "Left" : "Right"); string packGuid = RHSpriteManager.GetHandsOverride(i == 0); if (string.IsNullOrEmpty(packGuid)) { ModLogger.Player.Info(text + " Hand: No custom pack assigned"); continue; } string text2 = ResourcePacksManager.LoadedPacks.FirstOrDefault((ResourcePack p) => p.guid == packGuid)?.name ?? "Unknown Pack"; ModLogger.Player.Info(text + " Hand: " + text2 + " (" + packGuid + ")"); } ModLogger.Player.Info("Use 'assignhandpack [hand] [pack guid/pack index]' to assign a pack"); ModLogger.Player.Info("Use 'clearhandpack [hand]' to clear a hand's pack"); } private static int GetHandIdFromString(string handString) { if (string.IsNullOrEmpty(handString)) { return -1; } string text = handString.Trim().ToLowerInvariant(); if (text == "left" || text == "l") { return 0; } if (text == "right" || text == "r") { return 1; } return -1; } } public static class CosmeticStructureRepairer { private static readonly HashSet<string> ProcessedFolders = new HashSet<string>(); private static readonly HashSet<string> ReservedNames = new HashSet<string> { "icon", "manifest", "readme", "card-foreground", "card-background" }; public static bool NeedsFixing(string modFolderPath) { return !Directory.Exists(Path.Combine(modFolderPath, "Sprites")) || !Directory.Exists(Path.Combine(modFolderPath, "Interacts")); } public static void FixModStructure(string modFolderPath, string jsonFileName = "cosmetic-handitem-settings.json") { if (string.IsNullOrEmpty(modFolderPath) || !Directory.Exists(modFolderPath)) { ModLogger.Warning("[Fixer] Provided path is invalid: " + modFolderPath, 41, "/home/galfar/RiderProjects/ResourcefulHands/Systems/CosmeticStructureRepairer.cs"); } else { if (ProcessedFolders.Contains(modFolderPath)) { return; } try { string text = Path.Combine(modFolderPath, jsonFileName); if (!File.Exists(text)) { ModLogger.Debug("[Fixer] No settings JSON found in " + modFolderPath + ". Skipping...", 52, "/home/galfar/RiderProjects/ResourcefulHands/Systems/CosmeticStructureRepairer.cs"); return; } ModLogger.Info("[Fixer] Checking structure for mod: " + Path.GetFileName(modFolderPath), 56, "/home/galfar/RiderProjects/ResourcefulHands/Systems/CosmeticStructureRepairer.cs"); string text2 = File.ReadAllText(text); CosmeticSettings cosmeticSettings = JsonConvert.DeserializeObject<CosmeticSettings>(text2); if (cosmeticSettings == null) { ModLogger.Error("[Fixer] Failed to deserialize JSON at " + text, 63, "/home/galfar/RiderProjects/ResourcefulHands/Systems/CosmeticStructureRepairer.cs"); return; } string path = Path.Combine(modFolderPath, "Sprites"); string path2 = Path.Combine(modFolderPath, "Interacts"); string text3 = Path.Combine(modFolderPath, "Palettes"); Directory.CreateDirectory(path); Directory.CreateDirectory(path2); Directory.CreateDirectory(text3); HashSet<string> hashSet = new HashSet<string>(); if (cosmeticSettings.SwapSprites != null) { foreach (SwapSpriteEntry swapSprite in cosmeticSettings.SwapSprites) { foreach (string replacementSpriteName in swapSprite.ReplacementSpriteNames) { hashSet.Add(replacementSpriteName.ToLower()); } } } HashSet<string> hashSet2 = new HashSet<string>(); if (cosmeticSettings.InteractSwaps != null) { foreach (InteractSwapEntry interactSwap in cosmeticSettings.InteractSwaps) { hashSet2.Add(interactSwap.ReplacementSpriteName.ToLower()); } } HashSet<string> hashSet3 = new HashSet<string>(); if (cosmeticSettings.GlobalSecondary != null) { foreach (SecondaryTextureEntry item2 in cosmeticSettings.GlobalSecondary) { foreach (string secondaryTextureName in item2.SecondaryTextureNames) { hashSet3.Add(secondaryTextureName.ToLower()); } } } ModLogger.Debug($"[Fixer] JSON parsed. Found {hashSet.Count} sprites, {hashSet2.Count} interacts, {hashSet3.Count} secondary textures.", 100, "/home/galfar/RiderProjects/ResourcefulHands/Systems/CosmeticStructureRepairer.cs"); MoveMatchingFiles(modFolderPath, hashSet, "Sprites", "HND_"); MoveMatchingFiles(modFolderPath, hashSet, "Sprites", "stamina_"); MoveMatchingFiles(modFolderPath, hashSet2, "Interacts", "interact-"); MoveMatchingFiles(modFolderPath, hashSet3, "Palettes", "stamina"); string[] files = Directory.GetFiles(modFolderPath, "*.png"); string[] array = files; foreach (string text4 in array) { string item = Path.GetFileNameWithoutExtension(text4).ToLower(); if (ReservedNames.Contains(item)) { continue; } try { string fileName = Path.GetFileName(text4); string text5 = Path.Combine(text3, fileName); if (File.Exists(text5)) { File.Delete(text5); } File.Move(text4, text5); ModLogger.Debug("[Fixer] Moving leftover file " + fileName + " -> Palettes/", 125, "/home/galfar/RiderProjects/ResourcefulHands/Systems/CosmeticStructureRepairer.cs"); } catch (Exception ex) { ModLogger.Error("[Fixer] Failed to move leftover file " + text4 + ": " + ex.Message, 129, "/home/galfar/RiderProjects/ResourcefulHands/Systems/CosmeticStructureRepairer.cs"); } } ModLogger.Info("[Fixer] Finished organizing " + Path.GetFileName(modFolderPath), 133, "/home/galfar/RiderProjects/ResourcefulHands/Systems/CosmeticStructureRepairer.cs"); ProcessedFolders.Add(modFolderPath); } catch (Exception ex2) { ModLogger.Error("[Fixer] CRITICAL ERROR fixing structure at " + modFolderPath + ": " + ex2.Message + "\n" + ex2.StackTrace, 138, "/home/galfar/RiderProjects/ResourcefulHands/Systems/CosmeticStructureRepairer.cs"); } } } private static void MoveMatchingFiles(string root, HashSet<string> targets, string subFolder, string prefixFallback = null) { string text = Path.Combine(root, subFolder); string[] files = Directory.GetFiles(root, "*.png"); string[] array = files; foreach (string text2 in array) { string text3 = Path.GetFileNameWithoutExtension(text2).ToLower(); string fileName = Path.GetFileName(text2); bool flag = targets.Contains(text3); if (!flag && !string.IsNullOrEmpty(prefixFallback) && text3.StartsWith(prefixFallback.ToLower())) { flag = true; } if (!flag) { continue; } try { if (!Directory.Exists(text)) { Directory.CreateDirectory(text); } string text4 = Path.Combine(text, fileName); ModLogger.Debug("[Fixer] Moving " + fileName + " -> " + subFolder + "/", 175, "/home/galfar/RiderProjects/ResourcefulHands/Systems/CosmeticStructureRepairer.cs"); if (File.Exists(text4)) { ModLogger.Warning("[Fixer] File " + fileName + " already exists in " + subFolder + ". Overwriting.", 179, "/home/galfar/RiderProjects/ResourcefulHands/Systems/CosmeticStructureRepairer.cs"); File.Delete(text4); } File.Move(text2, text4); } catch (IOException ex) { ModLogger.Error("[Fixer] Failed to move " + fileName + ". File may be in use. Error: " + ex.Message, 187, "/home/galfar/RiderProjects/ResourcefulHands/Systems/CosmeticStructureRepairer.cs"); } } } } public static class CosmeticSystem { private static GameObject? _holder; public static void EnsureExists() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown if (!((Object)(object)_holder != (Object)null)) { _holder = new GameObject("RHCosmeticSystem"); _holder.AddComponent<OF_CosmeticPage>(); Object.DontDestroyOnLoad((Object)(object)_holder); ModLogger.Info("Official Cosmetic Integration initialized.", 19, "/home/galfar/RiderProjects/ResourcefulHands/Systems/CosmeticSystem.cs"); } } } public class RHDebugTools : MonoBehaviour { [CompilerGenerated] private sealed class <_queueSound>d__7 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public AudioClip clip; public bool force; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <_queueSound>d__7(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (!force && PlayingClips.Contains(clip)) { return false; } PlayingClips.Add(clip); <>2__current = (object)new WaitForSeconds(1f); <>1__state = 1; return true; case 1: <>1__state = -1; if (Object.op_Implicit((Object)(object)clip)) { PlayingClips.Remove(clip); } return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public static RHDebugTools? Instance; public static bool isOn; private static readonly List<AudioClip> PlayingClips = new List<AudioClip>(); private GUIStyle _style = GUIStyle.none; private bool _enableNextFrame; internal static void Create() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) Instance = new GameObject("DebugTools").AddComponent<RHDebugTools>(); Object.DontDestroyOnLoad((Object)(object)Instance); } public static void QueueSound(AudioClip clip, bool force = false) { CoroutineDispatcher.Dispatch(_queueSound(clip, force)); } [IteratorStateMachine(typeof(<_queueSound>d__7))] private static IEnumerator _queueSound(AudioClip clip, bool force) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <_queueSound>d__7(0) { clip = clip, force = force }; } public void Awake() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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_0047: 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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_0064: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)Instance)) { Instance = this; } else { Object.Destroy((Object)(object)this); } if (RHConfig.AlwaysDebug) { isOn = true; } _style = new GUIStyle { fontSize = 32, fontStyle = (FontStyle)1, normal = new GUIStyleState { textColor = Color.white } }; SceneManager.sceneUnloaded += delegate { _enableNextFrame |= isOn; isOn = false; }; SceneManager.sceneLoaded += delegate(Scene _, LoadSceneMode mode) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 if ((int)mode <= 0) { PlayingClips.Clear(); _enableNextFrame |= isOn; isOn = false; } }; } public void OnGUI() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) if (!isOn) { return; } Color contentColor = GUI.contentColor; GUI.contentColor = Color.white; GUILayout.Label("Recent sounds:", _style, Array.Empty<GUILayoutOption>()); for (int num = PlayingClips.Count - 1; num >= 0; num--) { if ((Object)(object)PlayingClips[num] == (Object)null) { PlayingClips.RemoveAt(num); } } foreach (AudioClip playingClip in PlayingClips) { GUILayout.Label(((Object)playingClip).name, _style, Array.Empty<GUILayoutOption>()); } GUI.contentColor = contentColor; } public void LateUpdate() { if (_enableNextFrame) { isOn = true; _enableNextFrame = false; } } } [HarmonyPatch(typeof(Object))] public static class DEBUG_InstantiatePatches { private static void OnInstantiated(Object result, Object original) { if (!Object.op_Implicit(result)) { return; } GameObject val = (GameObject)(object)((result is GameObject) ? result : null); if (val == null) { Component val2 = (Component)(object)((result is Component) ? result : null); if (val2 != null) { Component[] componentsInChildren = val2.GetComponentsInChildren<Component>(); Component[] array = componentsInChildren; foreach (Component obj2 in array) { PatchObject((Object)(object)obj2); } } } else { Component[] componentsInChildren2 = val.GetComponentsInChildren<Component>(); Component[] array2 = componentsInChildren2; foreach (Component obj3 in array2) { PatchObject((Object)(object)obj3); } } static void PatchObject(Object obj) { AudioSource val3 = (AudioSource)(object)((obj is AudioSource) ? obj : null); if (val3 != null && val3 != null && ((Behaviour)val3).isActiveAndEnabled && val3.playOnAwake) { RHDebugTools.QueueSound(val3.clip); } } } [HarmonyPostfix] [HarmonyPatch("Instantiate", new Type[] { typeof(Object) })] private static void Postfix_1(Object __result, Object original) { OnInstantiated(__result, original); } [HarmonyPostfix] [HarmonyPatch("Instantiate", new Type[] { typeof(Object), typeof(Scene) })] private static void Postfix_2(Object __result, Object original) { OnInstantiated(__result, original); } [HarmonyPostfix] [HarmonyPatch("Instantiate", new Type[] { typeof(Object), typeof(Transform) })] private static void Postfix_3(Object __result, Object original) { OnInstantiated(__result, original); } [HarmonyPostfix] [HarmonyPatch("Instantiate", new Type[] { typeof(Object), typeof(Transform), typeof(bool) })] private static void Postfix_4(Object __result, Object original) { OnInstantiated(__result, original); } [HarmonyPostfix] [HarmonyPatch("Instantiate", new Type[] { typeof(Object), typeof(Vector3), typeof(Quaternion) })] private static void Postfix_5(Object __result, Object original) { OnInstantiated(__result, original); } [HarmonyPostfix] [HarmonyPatch("Instantiate", new Type[] { typeof(Object), typeof(Vector3), typeof(Quaternion), typeof(Transform) })] private static void Postfix_6(Object __result, Object original) { OnInstantiated(__result, original); } } [HarmonyPatch(typeof(AudioSource))] [HarmonyPriority(200)] public static class DEBUG_AudioSourcePatches { [HarmonyPatch("Play", new Type[] { })] [HarmonyPrefix] private static void Play_NoArgs_Postfix(AudioSource __instance) { LogClip(__instance); } [HarmonyPatch("Play", new Type[] { typeof(double) })] [HarmonyPrefix] private static void Play_DelayDouble_Postfix(AudioSource __instance) { LogClip(__instance); } [HarmonyPatch("Play", new Type[] { typeof(ulong) })] [HarmonyPrefix] private static void Play_DelayUlong_Postfix(AudioSource __instance) { LogClip(__instance); } [HarmonyPatch("PlayOneShot", new Type[] { typeof(AudioClip) })] [HarmonyPrefix] private static void PlayOneShot_ClipOnly_Postfix(AudioSource __instance, ref AudioClip __0) { LogClip(null, __0); } [HarmonyPatch("PlayOneShot", new Type[] { typeof(AudioClip), typeof(float) })] [HarmonyPrefix] private static void PlayOneShot_ClipAndVolume_Postfix(AudioSource __instance, ref AudioClip __0) { LogClip(null, __0); } private static void LogClip(AudioSource src = null, AudioClip clip = null) { if (RHDebugTools.isOn && Object.op_Implicit((Object)(object)clip)) { if (Object.op_Implicit((Object)(object)src)) { clip = src.clip; } RHDebugTools.QueueSound(clip); } } } public static class DynamicHandSlicer { public enum SheetType { Background, Foreground } public static Dictionary<Vector2, Texture2D> SliceSheet(Texture2D sheet, int cols, int rows) { //IL_002d: 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_003c: Expected O, but got Unknown //IL_006d: Unknown result type (might be due to invalid IL or missing references) Dictionary<Vector2, Texture2D> dictionary = new Dictionary<Vector2, Texture2D>(); int num = ((Texture)sheet).width / cols; int num2 = ((Texture)sheet).height / rows; Vector2 key = default(Vector2); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { int num3 = rows - 1 - i; Texture2D val = new Texture2D(num, num2) { filterMode = (FilterMode)0 }; Color[] pixels = sheet.GetPixels(j * num, num3 * num2, num, num2); val.SetPixels(pixels); val.Apply(); ((Vector2)(ref key))..ctor((float)i, (float)j); dictionary.Add(key, val); } } return dictionary; } public static Dictionary<string, Texture2D> GetNamedSlicesFromSlicedSheet(SheetType sheetType, Dictionary<Vector2, Texture2D> slices, int layer = 1) { //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_003f: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) Dictionary<string, Texture2D> dictionary = new Dictionary<string, Texture2D>(); string text = ((sheetType == SheetType.Background) ? "B" : "F"); foreach (KeyValuePair<Vector2, Texture2D> slice in slices) { Vector2 key = slice.Key; Texture2D value = slice.Value; int num = (int)Mathf.Abs(key.x); string text2 = ""; text2 = num switch { 0 => "A", 1 => "B", 2 => "C", 3 => "D", _ => "A", }; string key2 = $"HND_{text}{layer}{text2}{key.y + 1f}"; dictionary.Add(key2, value); } return dictionary; } } public static class SceneHandler { private static bool _hasLoadedIntro; public static void OnSceneLoaded(Scene scene, LoadSceneMode mode) { CosmeticSystem.EnsureExists(); if (!((Scene)(ref scene)).name.ToLower().Contains("intro") && !_hasLoadedIntro) { _hasLoadedIntro = true; InitializeFirstTimeLoad(); } if (_hasLoadedIntro) { UpdateGlobalSystems(); } } private static void InitializeFirstTimeLoad() { AssetLoader.LoadBundle(); SpriteSystem.StartReplacementThreads(); RHDebugTools.Create(); } private static void UpdateGlobalSystems() { RHCommands.RefreshCommands(); AssetRefresher.RefreshAll(); } } public static class SpriteSystem { [CompilerGenerated] private sealed class <SpriteDiscoveryRoutine>d__5 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <SpriteDiscoveryRoutine>d__5(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; break; } _activeRenderers = Object.FindObjectsByType<SpriteRenderer>((FindObjectsSortMode)0); _lastDiscoveryTime = Time.time; <>2__current = (object)new WaitForSeconds(1f / 60f); <>1__state = 1; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static SpriteRenderer[] _activeRenderers = Array.Empty<SpriteRenderer>(); private static float _lastDiscoveryTime; private const float DiscoveryInterval = 1f / 60f; public static void StartReplacementThreads() { if (RHConfig.UseOldSprReplace) { ModLogger.Log.LogInfo((object)"Using Legacy Sprite Replacement."); CoroutineDispatcher.AddToUpdate(UpdateSpritesLegacy); } else { ModLogger.Log.LogInfo((object)"Starting Modern Sprite Discovery Service."); CoroutineDispatcher.Dispatch(SpriteDiscoveryRoutine()); CoroutineDispatcher.AddToUpdate(UpdateSpritesModern); } } public static void SyncWithOfficialCosmetics() { OF_CosmeticPage oF_CosmeticPage = Object.FindAnyObjectByType<OF_CosmeticPage>(); if ((Object)(object)oF_CosmeticPage != (Object)null) { ModLogger.Log.LogDebug((object)"Syncing with Official Cosmetic System..."); } } [IteratorStateMachine(typeof(<SpriteDiscoveryRoutine>d__5))] private static IEnumerator SpriteDiscoveryRoutine() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <SpriteDiscoveryRoutine>d__5(0); } private static void UpdateSpritesModern() { if (Time.time - _lastDiscoveryTime > 8f / 15f) { ModLogger.Log.LogWarning((object)"Sprite discovery thread stalled. Restarting..."); CoroutineDispatcher.Dispatch(SpriteDiscoveryRoutine()); } SpriteRenderer[] activeRenderers = _activeRenderers; foreach (SpriteRenderer val in activeRenderers) { } } private static void UpdateSpritesLegacy() { SpriteRenderer[] array = Object.FindObjectsByType<SpriteRenderer>((FindObjectsSortMode)0); SpriteRenderer[] array2 = array; foreach (SpriteRenderer val in array2) { } } } } namespace ResourcefulHands.Patches { [HarmonyPatch(typeof(Image))] public static class ImagePatches { [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyPostfix] public static void Getter_sprite_Postfix(Image __instance, ref Sprite __result) { if (Object.op_Implicit((Object)(object)__result) && !(((Object)__result.texture).name == "hand-sheet")) { __result = RHSpriteManager.GetReplacementSprite(__result) ?? __result; } } } [HarmonyPatch] public class ResourcefulHandsPatches { [HarmonyPatch(typeof(CL_CosmeticManager))] public static class CL_CosmeticManager_Patches { private static readonly HashSet<string> ProcessedFolders = new HashSet<string>(); [HarmonyPrefix] [HarmonyPatch("ScanForCosmetics")] public static bool ScanForCosmeticsPrefix() { FixStructures(); return true; } [HarmonyPostfix] [HarmonyPatch("ScanForCosmetics")] public static void ScanForCosmeticsPostfix() { ScanHandCosmetics(); ScanVoiceCosmetics(); } private static void FixStructures() { ModLogger.Info("Harmony Patch: Starting Cosmetic Structure Fix...", 43, "/home/galfar/RiderProjects/ResourcefulHands/Patches/ResourcefulHandsPatches.cs"); string directoryName = Path.GetDirectoryName(Paths.PluginPath); if (!Directory.Exists(directoryName)) { return; } string[] directories = Directory.GetDirectories(directoryName, "*", SearchOption.AllDirectories); string[] array = directories; foreach (string text in array) { if (File.Exists(Path.Combine(text, "cosmetic-handitem-settings.json"))) { CosmeticStructureRepairer.FixModStructure(text); } } } private static void ScanHandCosmetics() { string pluginPath = Paths.PluginPath; if (!Directory.Exists(pluginPath)) { return; } string[] directories = Directory.GetDirectories(pluginPath, "*", SearchOption.AllDirectories); Debug.Log((object)"Scanning For Hand Cosmetics Scattered Across BepInEx Plugins..."); MethodInfo methodInfo = AccessTools.Method(typeof(CL_CosmeticManager), "CreateHandCosmetics", (Type[])null, (Type[])null); Action<string, List<string>> action = AccessTools.MethodDelegate<Action<string, List<string>>>(methodInfo, (object)null, true); string[] array = directories; foreach (string text in array) { if (File.Exists(Path.Combine(text, "cosmetic-handitem-settings.json"))) { string fullName = Directory.GetParent(text).FullName; if (ProcessedFolders.Add(fullName)) { List<string> list = CL_CosmeticManager.ScanSubfoldersForJson(fullName, action, "cosmetic-handitem-settings.json"); ModLogger.Info("Found pack at " + text, 88, "/home/galfar/RiderProjects/ResourcefulHands/Patches/ResourcefulHandsPatches.cs"); } } } Debug.Log((object)"Finished Scanning For Hand Cosmetics From BepInEx Plugins."); } private static void ScanVoiceCosmetics() { string pluginPath = Paths.PluginPath; if (!Directory.Exists(pluginPath)) { return; } string[] directories = Directory.GetDirectories(pluginPath, "*", SearchOption.AllDirectories); Debug.Log((object)"Scanning For Voice Cosmetics Scattered Across BepInEx Plugins..."); MethodInfo methodInfo = AccessTools.Method(typeof(CL_CosmeticManager), "CreateVoiceCosmetics", (Type[])null, (Type[])null); Action<string, List<string>> action = AccessTools.MethodDelegate<Action<string, List<string>>>(methodInfo, (object)null, true); string[] array = directories; foreach (string text in array) { if (File.Exists(Path.Combine(text, "cosmetic-voice-settings.json"))) { string fullName = Directory.GetParent(text).FullName; if (ProcessedFolders.Add(fullName)) { List<string> list = CL_CosmeticManager.ScanSubfoldersForJson(fullName, action, "cosmetic-voice-settings.json"); } } } Debug.Log((object)"Finished Scanning For Voice Cosmetics From BepInEx Plugins."); } } public static Traverse Trv(object obj) { return Traverse.Create(obj); } } public class StaticCoroutine : MonoBehaviour { private static StaticCoroutine _instance; public static void Start(IEnumerator routine) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_instance == (Object)null) { _instance = new GameObject("RH_StaticCoroutine").AddComponent<StaticCoroutine>(); Object.DontDestroyOnLoad((Object)(object)((Component)_instance).gameObject); } ((MonoBehaviour)_instance).StartCoroutine(routine); } } } namespace ResourcefulHands.Core { public static class RHConfig { public static class PackPrefs { [Serializable] internal class PrefsObject { [JsonProperty(/*Could not decode attribute arguments.*/)] public string[] disabledPacks = Array.Empty<string>(); [JsonProperty(/*Could not decode attribute arguments.*/)] public string[] packOrder = Array.Empty<string>(); [JsonProperty(/*Could not decode attribute arguments.*/)] public string leftHandPack = string.Empty; [JsonProperty(/*Could not decode attribute arguments.*/)] public string rightHandPack = string.Empty; public static PrefsObject? FromJson(string json) { return JsonConvert.DeserializeObject<PrefsObject>(json); } public string ToJson() { return JsonConvert.SerializeObject((object)this); } } public static string[] DisabledPacks = Array.Empty<string>(); public static string[] PackOrder = Array.Empty<string>(); public static string LeftHandPack = string.Empty; public static string RightHandPack = string.Empty; public static ResourcePack? GetLeftHandPack() { return ResourcePacksManager.LoadedPacks.FirstOrDefault((ResourcePack pack) => pack.guid == LeftHandPack && pack.IsActive); } public static ResourcePack? GetRightHandPack() { return ResourcePacksManager.LoadedPacks.FirstOrDefault((ResourcePack pack) => pack.guid == RightHandPack && pack.IsActive); } internal static string GetFile() { string text = Path.Combine(GenericFolder, "prefs.json"); if (!File.Exists(text)) { File.WriteAllText(text, ""); } return text; } public static void Load() { string file = GetFile(); PrefsObject prefsObject = PrefsObject.FromJson(File.ReadAllText(file)) ?? new PrefsObject(); DisabledPacks = prefsObject.disabledPacks; PackOrder = prefsObject.packOrder; LeftHandPack = prefsObject.leftHandPack; RightHandPack = prefsObject.rightHandPack; if (!string.IsNullOrEmpty(LeftHandPack)) { RHSpriteManager.OverrideHands(LeftHandPack, isLeft: true); } if (!string.IsNullOrEmpty(RightHandPack)) { RHSpriteManager.OverrideHands(RightHandPack, isLeft: false); } } public static void Save() { string file = GetFile(); PrefsObject prefsObject = new PrefsObject { disabledPacks = DisabledPacks, packOrder = PackOrder, leftHandPack = LeftHandPack, rightHandPack = RightHandPack }; File.WriteAllText(file, prefsObject.ToJson()); } } private static ConfigEntry<bool>? lazyManip; private static ConfigEntry<bool>? useOldSpr; private static ConfigEntry<bool>? useOutdatedPacks; private static ConfigEntry<bool>? colorConsole; private static ConfigEntry<bool>? alwaysDebug; public static bool LazyManip => lazyManip?.Value ?? false; public static bool UseOldSprReplace => useOldSpr?.Value ?? false; public static bool UseOutdatedPacks => useOutdatedPacks?.Value ?? false; public static bool ColoredConsole => colorConsole?.Value ?? false; public static bool AlwaysDebug => alwaysDebug?.Value ?? false; public static string PacksFolder => Path.Combine(Paths.ConfigPath, "RHPacks"); public static string GenericFolder => Path.Combine(Paths.ConfigPath, "RHConfig"); internal static void InitConfigs() { ModLogger.Info("Initialising configs...", 116, "/home/galfar/RiderProjects/ResourcefulHands/Core/Config.cs"); ModLogger.Debug("Checking generic folder...", 118, "/home/galfar/RiderProjects/ResourcefulHands/Core/Config.cs"); if (!Directory.Exists(GenericFolder)) { Directory.CreateDirectory(GenericFolder); } ModLogger.Debug("Loading packs prefs...", 122, "/home/galfar/RiderProjects/ResourcefulHands/Core/Config.cs"); PackPrefs.Load(); Application.quitting += delegate { ModLogger.Info("Saving pack prefs...", 126, "/home/galfar/RiderProjects/ResourcefulHands/Core/Config.cs"); ResourcePacksManager.SavePackOrder(); ResourcePacksManager.SaveDisabledPacks(); PackPrefs.Save(); }; ModLogger.Debug("Binding configs with bepinex...", 133, "/home/galfar/RiderProjects/ResourcefulHands/Core/Config.cs"); lazyManip = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("General", "Lazy Loading", true, "When enabled every pack doesn't get reloaded when reordering or enabling/disabling packs in the settings menu."); ModLogger.Debug("Bound lazyManip", 142, "/home/galfar/RiderProjects/ResourcefulHands/Core/Config.cs"); useOldSpr = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("General", "Use Old Sprite Replacer", false, "A new sprite replacer (the thing that lets you have custom hands) has been added, hopefully this should improve performance. However, if you do have issues with this new replacer, turn this on to disable it."); ModLogger.Debug("Bound useOldSpr", 149, "/home/galfar/RiderProjects/ResourcefulHands/Core/Config.cs"); useOutdatedPacks = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("General", "Load outdated packs?", true, "When enabled packs that are made with an older pack-version/game-version won't be loaded."); ModLogger.Debug("Bound useOutdatedPacks", 156, "/home/galfar/RiderProjects/ResourcefulHands/Core/Config.cs"); colorConsole = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Debugging", "Colored Console", false, "When enabled certain logs are given colors, disable if this is causing issues. Additionally, only works on windows."); ModLogger.Debug("Bound colorConsole", 167, "/home/galfar/RiderProjects/ResourcefulHands/Core/Config.cs"); alwaysDebug = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Debugging", "Always debug mode", false, "When enabled pack debug mode is always enabled unless toggled via the command (rhtoggledebug)."); ModLogger.Debug("Bound alwaysDebug", 174, "/home/galfar/RiderProjects/ResourcefulHands/Core/Config.cs"); } } public static class ModLogger { public static class Player { private static void Message(string message) { CommandConsole.Log("[Resourceful Hands] " + message); } public static void Info(string message) { Message(message); } public static void Warning(string message) { Message("[Resourceful Hands] [WARNING] " + message); } public static void Error(string message) { CommandConsole.LogError("[Resourceful Hands] " + message); } } public static ManualLogSource Log; private const string Prefix = "[Resourceful Hands] "; public static void InitLog(ManualLogSource log) { Log = log; } [Conditional("DEBUG")] public static void Debug(object data, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string file = "") { string file2 = file; object data2 = data; CoroutineDispatcher.RunOnMainThreadOrCurrent(delegate { Log.LogInfo((object)$"[{Path.GetFileName(file2)}:{lineNumber}] {data2}"); }); } public static void Info(object data, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string file = "") { string file2 = file; object data2 = data; CoroutineDispatcher.RunOnMainThreadOrCurrent(delegate { Log.LogInfo((object)$"[{Path.GetFileName(file2)}:{lineNumber}] {data2}"); }); } public static void Message(object data, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string file = "") { string file2 = file; object data2 = data; CoroutineDispatcher.RunOnMainThreadOrCurrent(delegate { Log.LogMessage((object)$"[{Path.GetFileName(file2)}:{lineNumber}] {data2}"); }); } public static void Warning(object data, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string file = "") { string file2 = file; object data2 = data; CoroutineDispatcher.RunOnMainThreadOrCurrent(delegate { Log.LogWarning((object)$"[{Path.GetFileName(file2)}:{lineNumber}] {data2}"); }); } public static void Error(object data, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string file = "") { string file2 = file; object data2 = data; CoroutineDispatcher.RunOnMainThreadOrCurrent(delegate { Log.LogError((object)$"[{Path.GetFileName(file2)}:{lineNumber}] {data2}"); }); } } public static class ModState { private static int _mainThreadId; public static bool IsWindows => RuntimeInformation.IsOSPlatform(OSPlatform.Windows); public static bool IsMainThread => Thread.CurrentThread.ManagedThreadId == _mainThreadId; public static void Initialize() { _mainThreadId = Thread.CurrentThread.ManagedThreadId; } public static bool IsDemo() { //IL_0002: Unknown result type (might be due to invalid IL or missing references) try { return SteamClient.AppId.Value == 3218540; } catch { return false; } } } public static class VersionChecker { public static bool IsCompatible = false; private static readonly WKVersion MinVersion = new WKVersion("0.55i"); private static readonly WKVersion MaxVersion = new WKVersion("0.55m"); public static void Check() { WKVersion wKVersion = new WKVersion(Application.version); if (wKVersion < MinVersion) { ModLogger.Error($"Mod incompatible! Game too old ({Application.version}). Need {MinVersion}.", 16, "/home/galfar/RiderProjects/ResourcefulHands/Core/VersionChecker.cs"); } else if (wKVersion > MaxVersion) { ModLogger.Warning($"Mod made for {MaxVersion}, but game is {Application.version}. Expect issues.", 19, "/home/galfar/RiderProjects/ResourcefulHands/Core/VersionChecker.cs"); IsCompatible = true; } } } public struct WKVersion : IComparable<WKVersion> { public int Major; public int Minor; public string Suffix; public WKVersion(string version) { Match match = Regex.Match(version, "v?(\\d+)\\.(\\d+)([a-z]?)"); if (match.Success) { Major = int.Parse(match.Groups[1].Value); Minor = int.Parse(match.Groups[2].Value); Suffix = (string.IsNullOrEmpty(match.Groups[3].Value) ? "a" : match.Groups[3].Value); } else { Major = (Minor = 0); Suffix = "a"; } } public int CompareTo(WKVersion other) { if (Major != other.Major) { return Major.CompareTo(other.Major); } if (Minor != other.Minor) { return Minor.CompareTo(other.Minor); } return string.Compare(Suffix, other.Suffix, StringComparison.Ordinal); } public static bool operator >=(WKVersion a, WKVersion b) { return a.CompareTo(b) >= 0; } public static bool operator <=(WKVersion a, WKVersion b) { return a.CompareTo(b) <= 0; } public static bool operator >(WKVersion a, WKVersion b) { return a.CompareTo(b) > 0; } public static bool operator <(WKVersion a, WKVersion b) { return a.CompareTo(b) < 0; } } } namespace ResourcefulHands.Assets { public static class AssetLoader { private static AssetBundle? _bundle; public static Texture2D? CorruptionTexture { get; private set; } public static Texture2D? Icon { get; private set; } public static void LoadBundle() { _bundle = null; } public static void Unload() { AssetBundle? bundle = _bundle; if (bundle != null) { bundle.Unload(true); } } } public static class AssetRefresher { public static List<AudioSource> AllAudioSources = new List<AudioSource>(); public static void RefreshAll() { RefreshTextures(); RefreshSounds(); } public static void RefreshTextures() { RHSpriteManager.ClearSpriteCache(); } private static void RefreshSounds() { foreach (AudioSource allAudioSource in AllAudioSources) { if (allAudioSource.isPlaying && (double)allAudioSource.time < 0.1 && ((Behaviour)allAudioSource).enabled && ((Component)allAudioSource).gameObject.activeInHierarchy) { RHDebugTools.QueueSound(allAudioSource.clip); } } } } public class PackManager { public List<Cosmetic_HandItem> handCosmetics = new List<Cosmetic_HandItem>(); public List<Cosmetic_Voice> voiceCosmetics = new List<Cosmetic_Voice>(); public void GatherHands() { handCosmetics = CL_CosmeticManager.cosmeticHands; } public void GatherVoices() { voiceCosmetics = CL_CosmeticManager.cosmeticVoices; } } [Serializable] public class ResourcePack { [CompilerGenerated] private sealed class <LoadSoundRoutine>d__35 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string filepath; public ResourcePack pack; public AudioType audioType; private string <clipName>5__1; private AudioClip <audioClip>5__2; private UnityWebRequest <uwr>5__3; private DownloadHandlerAudioClip <dh>5__4; private Exception <e>5__5; private Dictionary<string, AudioClip> <>s__6; private bool <>s__7; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <LoadSoundRoutine>d__35(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <clipName>5__1 = null; <audioClip>5__2 = null; <uwr>5__3 = null; <dh>5__4 = null; <e>5__5 = null; <>s__6 = null; <>1__state = -2; } private bool MoveNext() { //IL_0055: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_0077: Expected O, but got Unknown //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Expected O, but got Unknown //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_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Invalid comparison between Unknown and I4 switch (<>1__state) { default: return false; case 0: <>1__state = -1; <clipName>5__1 = Path.GetFileNameWithoutExtension(filepath); <audioClip>5__2 = null; <uwr>5__3 = null; <dh>5__4 = null; <uwr>5__3 = new UnityWebRequest(filepath, "GET") { downloadHandler = (DownloadHandler)new DownloadHandlerAudioClip(filepath, audioType) }; <dh>5__4 = (DownloadHandlerAudioClip)<uwr>5__3.downloadHandler; <dh>5__4.streamAudio = false; <dh>5__4.compressed = true; <>2__current = <uwr>5__3.SendWebRequest(); <>1__state = 1; return true; case 1: <>1__state = -1; try { Result result = <uwr>5__3.result; bool flag = result - 2 <= 1; if (flag || (Object)(object)<dh>5__4.audioClip == (Object)null) { ModLogger.Error("Error while loading " + <clipName>5__1 + " [at: " + filepath + "]", 414, "/home/galfar/RiderProjects/ResourcefulHands/Assets/ResourcePack.cs"); } else { <audioClip>5__2 = <dh>5__4.audioClip; } } catch (Exception ex) { <e>5__5 = ex; ModLogger.Error("Error while loading " + <clipName>5__1 + " [at: " + filepath + "]\n" + <e>5__5.Message, 420, "/home/galfar/RiderProjects/ResourcefulHands/Assets/ResourcePack.cs"); } if ((Object)(object)<audioClip>5__2 == (Object)null) { return false; } pack.RawSounds.Add(<audioClip>5__2); ((Object)<audioClip>5__2).name = <clipName>5__1; if (ResourcePacksManager.OldNewSpriteNames.ContainsKey(<clipName>5__1)) { <clipName>5__1 = ResourcePacksManager.OldNewSoundNames[<clipName>5__1]; } <>s__6 = pack.Sounds; <>s__7 = false; try { Monitor.Enter(<>s__6, ref <>s__7); if (!pack.Sounds.TryAdd(<clipName>5__1, <audioClip>5__2)) { ModLogger.Error("Failed to add " + <clipName>5__1 + " because sound of that name already exists in the same pack! [at: " + filepath + "]", 433, "/home/galfar/RiderProjects/ResourcefulHands/Assets/ResourcePack.cs"); } } finally { if (<>s__7) { Monitor.Exit(<>s__6); } } <>s__6 = null; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public string name = string.Empty; public string desc = string.Empty; public string author = string.Empty; [JsonProperty(/*Could not decode attribute arguments.*/)] public string packVersion = string.Empty; [JsonProperty(/*Could not decode attribute arguments.*/)] public ulong steamId = 0uL; [JsonProperty(/*Could not decode attribute arguments.*/)] public string guid = string.Empty; [JsonProperty(/*Could not decode attribute arguments.*/)] public bool hiddenFromList = false; [JsonProperty(/*Could not decode attribute arguments.*/)] public bool onlyInFullGame = false; [JsonProperty(/*Could not decode attribute arguments.*/)] public string gameVersionString = string.Empty; [JsonProperty(/*Could not decode attribute arguments.*/)] public string relativeTexturesPath = "Textures"; [JsonProperty(/*Could not decode attribute arguments.*/)] public string relativeSoundsPath = "Sounds"; [JsonProperty(/*Could not decode attribute arguments.*/)] public string relativeIconPath = "pack.png"; [JsonProperty(/*Could not decode attribute arguments.*/)] public bool enableFilter = false; [JsonProperty(/*Could not decode attribute arguments.*/)] public int formatVersion = 3; [NonSerialized] [JsonIgnore] public const int CurrentFormatVersion = 3; [NonSerialized] [JsonIgnore] public bool IsActive = true; [NonSerialized] [JsonIgnore] public Dictionary<string, Texture2D> Textures = new Dictionary<string, Texture2D>(); [NonSerialized] [JsonIgnore] public Dictionary<string, AudioClip> Sounds = new Dictionary<string, AudioClip>(); [NonSerialized] [JsonIgnore] protected List<AudioClip> RawSounds = new List<AudioClip>(); [NonSerialized] [JsonIgnore] public bool IsConfigFolderPack = true; [NonSerialized] [JsonIgnore] public const string DefaultJson = "{\n \"name\":\"generated-game-assets\",\n \"desc\":\"Every game asset\",\n \"author\":\"Dark Machine Games\",\n \n \"pack-version\":\"0.50\",\n \"steamid\":0,\n \n \"guid\":\"generated.game.assets.unique\",\n \"hidden-from-list\":true,\n \"only-in-full-game\":false,\n \n \"game-string\":\"b0.50p\",\n \n \"textures-folder\":\"Textures\",\n \"sounds-folder\":\"Sounds\",\n \"icon-file\":\"pack.png\",\n \"icon-filter\":false,\n \n \"format-version\":3\n}"; [JsonIgnore] public string PackPath { get; private set; } = string.Empty; [JsonIgnore] public Texture2D Icon { get; private set; } = null; public Texture2D? GetTexture(string textureName) { Textures.TryGetValue(textureName, out Texture2D value); return value; } public bool HasHandTextures() { string[] handSpriteNames = RHSpriteManager.HandSpriteNames; foreach (string text in handSpriteNames) { if (Textures.ContainsKey(text)) { return true; } if (Textures.ContainsKey(RHSpriteManager.GetHandPrefix(0) + text)) { return true; } if (Textures.ContainsKey(RHSpriteManager.GetHandPrefix(1) + text)) { return true;