Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of RestlessStorage v0.2.0
RestlessStorage.dll
Decompiled 6 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using RestlessQoL.Api; using RestlessQoL.Core; using RestlessQoL.Storage; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("RestlessStorage")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.2.0.0")] [assembly: AssemblyInformationalVersion("0.2.0+fc26578074e80bad4acba7539fea34f12d89a478")] [assembly: AssemblyProduct("RestlessStorage")] [assembly: AssemblyTitle("RestlessStorage")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.2.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.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] [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] [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 RestlessStorage { [BepInPlugin("restless.storage", "RestlessStorage", "0.2.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "restless.storage"; public const string PluginName = "RestlessStorage"; public const string PluginVersion = "0.2.0"; private Harmony? _harmony; private IDisposable? _page; private IDisposable? _settings; internal static ConfigEntry<bool> WindowEnabled; internal static Plugin Instance { get; private set; } internal static ManualLogSource Log { get; private set; } private void Awake() { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; WindowEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Interface", "StorageWindow", true, "Open the shared storage browser when using a Storekeeper's Table. Local visual preference."); _settings = SettingsPageApi.RegisterSettings("restless.storage", (SettingsSection[])(object)new SettingsSection[1] { new SettingsSection("Storage window", (SettingsOption[])(object)new SettingsOption[1] { new SettingsOption("Open storage browser", (ConfigEntryBase)(object)WindowEnabled, false, "", false) }) }); _page = SettingsPageApi.Register(new SettingsPage("restless.storage", "RestlessStorage", "A table for the stores around you.", "Build a Storekeeper's Table at the workbench. Browse nearby stores, then take a stack into your inventory. The chest owner moves the items. Whatever does not fit goes back.", (Sprite)null, (string)null, (Action)null)); StorekeeperPiece.Load(); _harmony = new Harmony("restless.storage"); _harmony.PatchAll(); Log.LogInfo((object)"RestlessStorage 0.2.0 loaded."); } private void OnDestroy() { Storekeeper.CloseWindow(); _settings?.Dispose(); _page?.Dispose(); Harmony? harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } internal sealed class StorageSource : IStorageWindowSource { private sealed class Group { internal readonly ItemData Item; internal long Count; internal readonly List<StorageLocation> Locations = new List<StorageLocation>(); internal readonly Dictionary<string, long> Pending = new Dictionary<string, long>(StringComparer.Ordinal); internal Group(ItemData item) { Item = item; } } private readonly Storekeeper _table; private readonly Player _player; private string _signature = ""; private long _revision; private bool _busy; public bool IsAvailable { get { //IL_0052: 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_006c: Unknown result type (might be due to invalid IL or missing references) if (Plugin.WindowEnabled.Value && (Object)(object)_table != (Object)null && (Object)(object)_player != (Object)null && (Object)(object)Player.m_localPlayer == (Object)(object)_player && !((Character)_player).IsDead()) { Vector3 val = ((Component)_table).transform.position - ((Component)_player).transform.position; return ((Vector3)(ref val)).sqrMagnitude < 25f; } return false; } } internal StorageSource(Storekeeper table, Player player) { _table = table; _player = player; } public StorageSnapshot Capture() { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Expected O, but got Unknown //IL_035d: Unknown result type (might be due to invalid IL or missing references) //IL_0364: Expected O, but got Unknown //IL_04cc: Unknown result type (might be due to invalid IL or missing references) //IL_04d2: Expected O, but got Unknown Dictionary<string, Group> groups = new Dictionary<string, Group>(StringComparer.Ordinal); int num = 0; foreach (Container item2 in NearbyStorage.ForLocalPlayer()) { Inventory inventory = item2.GetInventory(); if (inventory == null || inventory == ((Humanoid)_player).GetInventory()) { continue; } num++; string location = Local(inventory.GetName()) + " · " + Mathf.RoundToInt(Vector3.Distance(((Component)_player).transform.position, ((Component)item2).transform.position)) + " m"; foreach (ItemData allItem in inventory.GetAllItems()) { if (allItem?.m_shared != null && allItem.m_stack > 0) { Add(allItem, allItem.m_stack, location); } } } List<NearbyLot> list = new List<NearbyLot>(); NearbyLots.Collect(_player, ModConfig.StorageRange.Value, list); foreach (NearbyLot item3 in list) { if (item3.Item?.m_shared != null && item3.Count > 0) { num++; Add(item3.Item, item3.Count, item3.Place); } } foreach (Group value4 in groups.Values) { foreach (KeyValuePair<string, long> item4 in value4.Pending) { value4.Locations.Add(new StorageLocation(item4.Key, item4.Value)); } value4.Pending.Clear(); } List<string> list2 = new List<string>(groups.Keys); list2.Sort(StringComparer.Ordinal); List<StorageResource> list3 = new List<StorageResource>(); StringBuilder stringBuilder = new StringBuilder().Append(num).Append('|').Append(ModConfig.StorageEnabled.Value); foreach (string item5 in list2) { Group obj = groups[item5]; ItemData item = obj.Item; obj.Locations.Sort((StorageLocation a, StorageLocation b) => StringComparer.CurrentCulture.Compare(a.Name, b.Name)); string text = Local(item.m_shared.m_name); if (item.m_quality > 1) { text = text + " · " + item.m_quality; } StorageResource val = new StorageResource(item5, text, Category(item), Local(item.m_shared.m_description), item.GetIcon(), obj.Count, item.m_shared.m_maxStackSize, item.GetWeight(-1) / (float)Math.Max(1, item.m_stack), obj.Locations.ToArray()); list3.Add(val); stringBuilder.Append(item5).Append(':').Append(obj.Count) .Append(':') .Append(text) .Append(val.Description) .Append(val.Category) .Append(val.UnitWeight) .Append(val.StackSize); foreach (StorageLocation location2 in obj.Locations) { stringBuilder.Append(location2.Name).Append(':').Append(location2.Count); } } Touch(_player, groups.Values); string text2 = stringBuilder.ToString(); if (text2 != _signature) { _signature = text2; _revision++; } bool value = ModConfig.StorageEnabled.Value; return new StorageSnapshot(_revision, "Storage network", "Storekeeper's Table · nearby storage", num, ((Humanoid)_player).GetInventory().GetTotalWeight(), _player.GetMaxCarryWeight(), value, value ? "Take from nearby stores" : "Nearby storage is disabled by the host", list3.ToArray()); void Add(ItemData val2, int count, string key2) { if (val2?.m_shared != null && count > 0) { string key = ItemKey.Of(val2); if (!groups.TryGetValue(key, out Group value2)) { groups.Add(key, value2 = new Group(val2)); } value2.Count += count; value2.Pending.TryGetValue(key2, out var value3); value2.Pending[key2] = value3 + count; } } } public void Withdraw(string resourceId, int amount, Action<string> completed) { //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) if (completed == null || _busy) { return; } if (!IsAvailable) { completed("The table is out of reach."); return; } if (!ModConfig.StorageEnabled.Value) { completed("Nearby storage is disabled by the host."); return; } if (amount < 1 || string.IsNullOrEmpty(resourceId)) { completed("Nothing nearby."); return; } List<Container> list = new List<Container>(NearbyStorage.ForLocalPlayer()); Vector3 origin = ((Component)_player).transform.position; list.Sort(delegate(Container a, Container b) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((Component)a).transform.position - origin; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; val = ((Component)b).transform.position - origin; return sqrMagnitude.CompareTo(((Vector3)(ref val)).sqrMagnitude); }); string label = LabelFor(list, resourceId); _busy = true; Walk(list, resourceId, 0, amount, 0, blocked: false, timedOut: false, label, delegate(string message) { _busy = false; completed(message); }); } private void Walk(List<Container> chests, string resourceId, int index, int left, int moved, bool blocked, bool timedOut, string label, Action<string> completed) { if (blocked || timedOut || left <= 0 || index > chests.Count) { completed(Result(label, moved, blocked, timedOut)); return; } if (index == chests.Count) { NearbyLots.Take(_player, resourceId, left, (Action<int>)delegate(int taken) { int num = left - taken; bool blocked2 = num > 0 && ((Humanoid)_player).GetInventory().GetEmptySlots() <= 0; Walk(chests, resourceId, index + 1, num, moved + taken, blocked2, timedOut: false, label, completed); }); return; } Container chest = chests[index]; StorageWithdraw.Request(chest, _player.GetPlayerID(), resourceId, left, (Action<Batch>)delegate(Batch batch) { if (batch.TimedOut) { Walk(chests, resourceId, index + 1, left, moved, blocked, timedOut: true, label, completed); } else { Inventory val = (((Object)(object)_player != (Object)null) ? ((Humanoid)_player).GetInventory() : null); if (val == null) { if (batch.Id == 0) { StorageWithdraw.ReturnTo(chest, batch.Items); } else if (batch.Items.Count > 0) { StorageWithdraw.Acknowledge(chest, batch.Id, batch.Items); } completed("The table is out of reach."); } else { List<ItemData> list = new List<ItemData>(); int num = StorageWithdraw.Give(val, batch.Items, list); if (batch.Id == 0) { StorageWithdraw.ReturnTo(chest, list); } else if (batch.Items.Count > 0) { StorageWithdraw.Acknowledge(chest, batch.Id, list); } Walk(chests, resourceId, index + 1, left - num, moved + num, list.Count > 0, timedOut: false, label, completed); } } }); } private string LabelFor(List<Container> chests, string resourceId) { foreach (Container chest in chests) { Inventory inventory = chest.GetInventory(); if (inventory == null) { continue; } foreach (ItemData allItem in inventory.GetAllItems()) { if (allItem?.m_shared != null && !(ItemKey.Of(allItem) != resourceId)) { string text = Local(allItem.m_shared.m_name); return (allItem.m_quality > 1) ? (text + " " + allItem.m_quality) : text; } } } List<NearbyLot> list = new List<NearbyLot>(); NearbyLots.Collect(_player, ModConfig.StorageRange.Value, list); foreach (NearbyLot item in list) { if (item.Item?.m_shared != null && !(ItemKey.Of(item.Item) != resourceId)) { string text2 = Local(item.Item.m_shared.m_name); return (item.Item.m_quality > 1) ? (text2 + " " + item.Item.m_quality) : text2; } } return "items"; } private static string Result(string label, int moved, bool blocked, bool timedOut) { if (timedOut && moved <= 0) { return "The chest did not answer. Nothing was taken."; } if (timedOut) { return "Took " + moved.ToString("N0") + " " + label + ". A later chest did not answer."; } if (moved <= 0 && blocked) { return "No room in your inventory."; } if (moved <= 0) { return "Nothing nearby."; } if (blocked) { return "Took " + moved.ToString("N0") + " " + label + ". No room for the rest."; } return "Took " + moved.ToString("N0") + " " + label + "."; } private static void Touch(Player player, Dictionary<string, Group>.ValueCollection groups) { if ((Object)(object)player != (Object)(object)Player.m_localPlayer) { return; } bool flag = false; foreach (Group group in groups) { string text = group.Item?.m_shared?.m_name; if (!string.IsNullOrEmpty(text) && !player.m_knownMaterial.Contains(text)) { player.m_knownMaterial.Add(text); flag = true; } } if (flag) { player.UpdateKnownRecipesList(); player.UpdateEvents(); } } private static string Local(string value) { if (Localization.instance == null) { return value; } return Localization.instance.Localize(value); } private static string Category(ItemData item) { if (item.m_shared.m_food > 0f || item.m_shared.m_foodStamina > 0f) { return "Food"; } switch (((object)Unsafe.As<ItemType, ItemType>(ref item.m_shared.m_itemType)/*cast due to .constrained prefix*/).ToString()) { case "Material": return "Materials"; case "Consumable": return "Food"; case "Ammo": case "AmmoNonEquipable": return "Equipment"; case "Shoulder": case "Legs": case "Tool": case "OneHandedWeapon": case "TwoHandedWeapon": case "Helmet": case "Shield": case "TwoHandedWeaponLeft": case "Bow": case "Chest": case "Utility": return "Equipment"; default: return "Other"; } } } public class Storekeeper : MonoBehaviour, Hoverable, Interactable { [HarmonyPatch(typeof(Menu), "Update")] private static class MenuInput { [HarmonyPrefix] private static bool Prefix() { return !StorageWindowApi.BlocksMenuInput; } } private static StorageSource? _openSource; private StorageSource? _source; public string GetHoverName() { return Localization.instance.Localize("Storekeeper's Table"); } public string GetHoverText() { return Localization.instance.Localize("[<color=yellow><b>$KEY_Use</b></color>] Storage network"); } public float GetHoverOffset() { return 0.4f; } public bool Interact(Humanoid user, bool hold, bool alt) { if (!(hold || alt)) { Player val = (Player)(object)((user is Player) ? user : null); if (val != null && !((Object)(object)val != (Object)(object)Player.m_localPlayer)) { if (!Plugin.WindowEnabled.Value) { ((Character)val).Message((MessageType)2, "Enable the storage browser in F8 · RestlessStorage.", 0, (Sprite)null, false); return true; } _source = new StorageSource(this, val); if (StorageWindowApi.Open((IStorageWindowSource)(object)_source)) { _openSource = _source; } return true; } } return false; } public bool UseItem(Humanoid user, ItemData item) { return false; } private void OnDisable() { if (_source != null) { StorageWindowApi.Close((IStorageWindowSource)(object)_source); } } internal static void CloseWindow() { if (_openSource != null) { StorageWindowApi.Close((IStorageWindowSource)(object)_openSource); } _openSource = null; } } internal static class StorekeeperPiece { public const string PrefabName = "piece_restless_storekeeper"; public const string DisplayName = "Storekeeper's Table"; public const string Blurb = "A ledger for the chests you can reach."; private const string Donor = "piece_chest_wood"; private static bool _added; public static void Load() { PrefabManager.OnVanillaPrefabsAvailable += Add; } private static void Add() { //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Expected O, but got Unknown //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Expected O, but got Unknown PrefabManager.OnVanillaPrefabsAvailable -= Add; if (_added) { return; } _added = true; if ((Object)(object)PrefabManager.Instance.GetPrefab("piece_chest_wood") == (Object)null) { Plugin.Log.LogWarning((object)"RestlessStorage skipped the table (no piece_chest_wood)."); return; } GameObject val = PrefabManager.Instance.CreateClonedPrefab("piece_restless_storekeeper", "piece_chest_wood"); if (!((Object)(object)val == (Object)null)) { Container component = val.GetComponent<Container>(); if ((Object)(object)component != (Object)null) { Object.DestroyImmediate((Object)(object)component); } TableVisual.Apply(val); Piece val2 = val.GetComponent<Piece>() ?? val.AddComponent<Piece>(); Sprite icon = (val2.m_icon = TableArt.Icon() ?? val2.m_icon); val2.m_name = "Storekeeper's Table"; val2.m_description = "A ledger for the chests you can reach."; val2.m_groundOnly = false; val2.m_groundPiece = false; val2.m_clipGround = false; val2.m_category = (PieceCategory)4; SitAsFurniture(val); if ((Object)(object)val.GetComponent<Storekeeper>() == (Object)null) { val.AddComponent<Storekeeper>(); } PieceConfig val3 = new PieceConfig { Name = "Storekeeper's Table", Description = "A ledger for the chests you can reach.", PieceTable = PieceTables.Hammer, Category = PieceCategories.Furniture, CraftingStation = "piece_workbench", Icon = icon }; val3.AddRequirement("Wood", 20, true); val3.AddRequirement("FineWood", 10, true); val3.AddRequirement("BronzeNails", 10, true); PieceManager.Instance.AddPiece(new CustomPiece(val, true, val3)); Plugin.Log.LogInfo((object)"RestlessStorage added the Storekeeper's Table."); } } private static void SitAsFurniture(GameObject prefab) { WearNTear component = prefab.GetComponent<WearNTear>(); if (!((Object)(object)component == (Object)null)) { component.m_noSupportWear = false; component.m_supports = true; AccessTools.Method(typeof(WearNTear), "SetupColliders", (Type[])null, (Type[])null)?.Invoke(component, null); } } } internal static class TableArt { public const string Id = "table"; private static Mesh? _mesh; private static Texture2D? _albedo; private static Texture2D? _surface; private static Sprite? _icon; private static string? _folder; private static MethodInfo? _loadImage; private static bool _searched; public static Mesh? Mesh() { if ((Object)(object)_mesh != (Object)null) { return _mesh; } string text = Path.Combine(Folder(), "table.rcm"); if (!File.Exists(text)) { Plugin.Log.LogWarning((object)("table mesh missing " + text)); return null; } _mesh = ReadRcm(File.ReadAllBytes(text)); return _mesh; } public static Texture2D? Albedo() { return Picture(ref _albedo, "table.png", linear: false); } public static Texture2D? Surface() { return Picture(ref _surface, "table.metal.png", linear: true); } public static Sprite? Icon() { //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_icon != (Object)null) { return _icon; } Stream manifestResourceStream = typeof(TableArt).Assembly.GetManifestResourceStream("RestlessStorage.Assets.table.png"); if (manifestResourceStream == null) { Plugin.Log.LogWarning((object)"table icon missing"); return null; } using (manifestResourceStream) { byte[] array = new byte[manifestResourceStream.Length]; int num; for (int i = 0; i < array.Length; i += num) { num = manifestResourceStream.Read(array, i, array.Length - i); if (num <= 0) { break; } } Texture2D val = DecodePng(array, "table.icon"); if ((Object)(object)val == (Object)null) { return null; } _icon = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); ((Object)_icon).name = "table"; return _icon; } } private static Texture2D? Picture(ref Texture2D? slot, string file, bool linear) { if ((Object)(object)slot != (Object)null) { return slot; } string text = Path.Combine(Folder(), file); if (!File.Exists(text)) { Plugin.Log.LogWarning((object)("table picture missing " + text)); return null; } slot = DecodePng(File.ReadAllBytes(text), file, linear); return slot; } private static string Folder() { if (_folder != null) { return _folder; } List<string> list = new List<string>(); Plugin instance = Plugin.Instance; object file; if (instance == null) { file = null; } else { PluginInfo info = ((BaseUnityPlugin)instance).Info; file = ((info != null) ? info.Location : null); } AddRoot(list, (string?)file); AddRoot(list, typeof(TableArt).Assembly.Location); foreach (string item in list) { string text = Path.Combine(item, "mesh"); if (File.Exists(Path.Combine(text, "table.rcm"))) { return Remember(text); } if (File.Exists(Path.Combine(item, "table.rcm"))) { return Remember(item); } } _folder = Path.Combine((list.Count > 0) ? list[0] : ".", "mesh"); Plugin.Log.LogWarning((object)("table mesh folder missing, looking in " + _folder)); return _folder; } private static void AddRoot(List<string> roots, string? file) { string text = (string.IsNullOrEmpty(file) ? "" : (Path.GetDirectoryName(file) ?? "")); if (text.Length == 0) { return; } foreach (string root in roots) { if (string.Equals(root, text, StringComparison.OrdinalIgnoreCase)) { return; } } roots.Add(text); } private static string Remember(string dir) { _folder = dir; Plugin.Log.LogInfo((object)("table mesh folder " + dir)); return dir; } private static Mesh? ReadRcm(byte[] data) { //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Expected O, but got Unknown if (data.Length < 12 || data[0] != 82 || data[1] != 67 || data[2] != 77 || (data[3] != 49 && data[3] != 50)) { Plugin.Log.LogWarning((object)"table mesh bad header"); return null; } bool flag = data[3] == 49; int num = 4; int num2 = BitConverter.ToInt32(data, num); num += 4; int num3 = BitConverter.ToInt32(data, num); num += 4; if (num2 <= 0 || num3 <= 0 || num + num2 * 32 + num3 * 4 > data.Length) { Plugin.Log.LogWarning((object)"table mesh truncated"); return null; } Vector3[] array = (Vector3[])(object)new Vector3[num2]; Vector3[] array2 = (Vector3[])(object)new Vector3[num2]; Vector2[] array3 = (Vector2[])(object)new Vector2[num2]; for (int i = 0; i < num2; i++) { array[i] = new Vector3(BitConverter.ToSingle(data, num), BitConverter.ToSingle(data, num + 4), BitConverter.ToSingle(data, num + 8)); array2[i] = new Vector3(BitConverter.ToSingle(data, num + 12), BitConverter.ToSingle(data, num + 16), BitConverter.ToSingle(data, num + 20)); float num4 = BitConverter.ToSingle(data, num + 28); array3[i] = new Vector2(BitConverter.ToSingle(data, num + 24), flag ? (1f - num4) : num4); num += 32; } int[] array4 = new int[num3]; for (int j = 0; j < num3; j++) { array4[j] = BitConverter.ToInt32(data, num); num += 4; } Mesh val = new Mesh { name = "table", indexFormat = (IndexFormat)(num2 > 65000) }; val.SetVertices(array); val.SetNormals(array2); val.SetUVs(0, array3); val.SetTriangles(array4, 0); val.RecalculateBounds(); return val; } private static Texture2D? DecodePng(byte[] bytes, string name, bool linear = false) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown Texture2D val = (linear ? new Texture2D(2, 2, (TextureFormat)4, true, true) : new Texture2D(2, 2, (TextureFormat)4, true)); MethodInfo methodInfo = LoadImage(); if (methodInfo == null || !(bool)methodInfo.Invoke(null, new object[2] { val, bytes })) { Object.Destroy((Object)(object)val); Plugin.Log.LogWarning((object)("table png decode failed " + name)); return null; } ((Object)val).name = name; ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)1; ((Texture)val).anisoLevel = 4; val.Apply(true, false); return val; } private static MethodInfo? LoadImage() { if (_searched) { return _loadImage; } _searched = true; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { Type type = assemblies[i].GetType("UnityEngine.ImageConversion"); if (!(type == null)) { _loadImage = type.GetMethod("LoadImage", new Type[2] { typeof(Texture2D), typeof(byte[]) }); if (_loadImage != null) { return _loadImage; } } } return null; } } internal static class TableVisual { public const string ChildName = "RestlessStorekeeperMesh"; public static void Apply(GameObject prefab) { //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Expected O, but got Unknown //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) Mesh val = TableArt.Mesh(); if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)"RestlessStorage: no custom model, leaving the chest look."); return; } Material mat = CopyLit(prefab); LODGroup[] componentsInChildren = prefab.GetComponentsInChildren<LODGroup>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } int layer = prefab.layer; Collider componentInChildren = prefab.GetComponentInChildren<Collider>(true); if ((Object)(object)componentInChildren != (Object)null) { layer = ((Component)componentInChildren).gameObject.layer; } Collider[] componentsInChildren2 = prefab.GetComponentsInChildren<Collider>(true); foreach (Collider val2 in componentsInChildren2) { if ((Object)(object)val2 != (Object)null) { Object.DestroyImmediate((Object)(object)val2); } } GameObject val3 = new GameObject("RestlessStorekeeperMesh"); val3.layer = layer; val3.transform.SetParent(prefab.transform, false); val3.transform.localPosition = Vector3.zero; val3.transform.localRotation = Quaternion.identity; val3.transform.localScale = Vector3.one; val3.AddComponent<MeshFilter>().sharedMesh = val; MeshRenderer val4 = val3.AddComponent<MeshRenderer>(); Paint((Renderer)(object)val4, TableArt.Albedo(), TableArt.Surface(), mat); Renderer[] componentsInChildren3 = prefab.GetComponentsInChildren<Renderer>(true); foreach (Renderer val5 in componentsInChildren3) { if (!((Object)(object)val5 == (Object)null) && !((Object)(object)val5 == (Object)(object)val4) && ((val5 is MeshRenderer || val5 is SkinnedMeshRenderer) ? true : false)) { val5.enabled = false; } } BoxCollider obj = val3.AddComponent<BoxCollider>(); Bounds bounds = val.bounds; obj.center = ((Bounds)(ref bounds)).center; bounds = val.bounds; obj.size = Vector3.Max(((Bounds)(ref bounds)).size, new Vector3(0.2f, 0.2f, 0.2f)); } private static void Paint(Renderer renderer, Texture2D? albedo, Texture2D? surface, Material? mat) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)mat == (Object)null) { return; } mat.color = Color.white; SetColor(mat, "_Color", Color.white); SetColor(mat, "_BaseColor", Color.white); if ((Object)(object)albedo != (Object)null) { if (mat.HasProperty("_MainTex")) { mat.SetTexture("_MainTex", (Texture)(object)albedo); } if (mat.HasProperty("_BaseMap")) { mat.SetTexture("_BaseMap", (Texture)(object)albedo); } } if ((Object)(object)surface != (Object)null) { if (mat.HasProperty("_MetallicTex")) { mat.SetTexture("_MetallicTex", (Texture)(object)surface); } if (mat.HasProperty("_MetallicGlossMap")) { mat.SetTexture("_MetallicGlossMap", (Texture)(object)surface); } SetFloat(mat, "_Metallic", 1f); SetFloat(mat, "_MetallicAlphaGloss", 1f); SetFloat(mat, "_Glossiness", 1f); SetFloat(mat, "_Smoothness", 1f); mat.EnableKeyword("_METALLICGLOSSMAP"); } renderer.sharedMaterial = mat; } private static Material? CopyLit(GameObject prefab) { //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Expected O, but got Unknown //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Expected O, but got Unknown Renderer val = null; float num = -1f; Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true); foreach (Renderer val2 in componentsInChildren) { if ((Object)(object)val2 == (Object)null || (!(val2 is MeshRenderer) && !(val2 is SkinnedMeshRenderer))) { continue; } Material sharedMaterial = val2.sharedMaterial; if ((Object)(object)((sharedMaterial != null) ? sharedMaterial.shader : null) == (Object)null || ((Object)sharedMaterial.shader).name == "Standard") { continue; } string text = ((Object)sharedMaterial).name + " " + ((Object)sharedMaterial.shader).name; if (!Has(text, "snow") && !Has(text, "particle") && !Has(text, "glow")) { Bounds bounds = val2.bounds; float x = ((Bounds)(ref bounds)).size.x; bounds = val2.bounds; float num2 = x * ((Bounds)(ref bounds)).size.y; bounds = val2.bounds; float num3 = num2 * ((Bounds)(ref bounds)).size.z; if (!(num3 <= num)) { num = num3; val = val2; } } } if ((Object)(object)((val != null) ? val.sharedMaterial : null) != (Object)null) { Plugin.Log.LogInfo((object)("table lit " + ((Object)val).name + " / " + ((Object)val.sharedMaterial.shader).name)); return new Material(val.sharedMaterial); } PrefabManager instance = PrefabManager.Instance; GameObject val3 = ((instance != null) ? instance.GetPrefab("piece_chest_wood") : null); MeshRenderer val4 = (((Object)(object)val3 != (Object)null) ? val3.GetComponentInChildren<MeshRenderer>(true) : null); if ((Object)(object)((val4 != null) ? ((Renderer)val4).sharedMaterial : null) != (Object)null && ((Object)((Renderer)val4).sharedMaterial.shader).name != "Standard") { return new Material(((Renderer)val4).sharedMaterial); } Plugin.Log.LogWarning((object)"table shader missing"); return null; } private static bool Has(string text, string token) { return text.IndexOf(token, StringComparison.OrdinalIgnoreCase) >= 0; } private static void SetColor(Material mat, string prop, Color color) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (mat.HasProperty(prop)) { mat.SetColor(prop, color); } } private static void SetFloat(Material mat, string prop, float value) { if (mat.HasProperty(prop)) { mat.SetFloat(prop, value); } } } }