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 SimpleFishingTrap v0.1.0
SimpleFishingTrap.dll
Decompiled 20 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("SimpleFishingTrap")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0")] [assembly: AssemblyProduct("SimpleFishingTrap")] [assembly: AssemblyTitle("SimpleFishingTrap")] [assembly: AssemblyVersion("0.1.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace SimpleFishingTrap { internal static class ConfigSync { private const string RpcName = "SimpleFishingTrap_SyncConfig"; private const int PackageVersion = 1; private static float _secondsPerFish; private static int _maxFish; private static bool _catchUp; private static string _itemPrefab; private static float _maxDistance; private static float _maxHeight; private static string _recipe; private static string _station; internal static bool HasServerConfig { get; private set; } internal static float SecondsPerFish => Math.Max(1f, HasServerConfig ? _secondsPerFish : Plugin.SecondsPerFish.Value); internal static int MaxFish => Math.Max(1, HasServerConfig ? _maxFish : Plugin.MaxFish.Value); internal static bool CatchUpWhileAway => HasServerConfig ? _catchUp : Plugin.CatchUpWhileAway.Value; internal static string ItemPrefab => HasServerConfig ? _itemPrefab : Plugin.ItemPrefab.Value; internal static float MaxWaterDistance => HasServerConfig ? _maxDistance : Plugin.MaxWaterDistance.Value; internal static float MaxHeightAboveWater => HasServerConfig ? _maxHeight : Plugin.MaxHeightAboveWater.Value; internal static string Recipe => HasServerConfig ? _recipe : Plugin.Recipe.Value; internal static string CraftingStation => HasServerConfig ? _station : Plugin.CraftingStationName.Value; internal static void OnNewConnection_Postfix(ZNetPeer peer) { try { if (peer != null) { ZRpc rpc = peer.m_rpc; if (rpc != null) { rpc.Register<ZPackage>("SimpleFishingTrap_SyncConfig", (Action<ZRpc, ZPackage>)RPC_Receive); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not register sync RPC: " + ex.Message)); } } internal static void RPC_PeerInfo_Postfix(ZNet __instance, ZRpc rpc) { if ((Object)(object)__instance == (Object)null || rpc == null || !__instance.IsServer() || !Plugin.EnforceServerConfig.Value) { return; } try { rpc.Invoke("SimpleFishingTrap_SyncConfig", new object[1] { Build() }); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not send settings to joining player: " + ex.Message)); } } internal static void ZNet_OnDestroy_Postfix() { if (HasServerConfig) { HasServerConfig = false; TrapPrefab.ApplyRecipe(); Plugin.Log.LogInfo((object)"Left server; using local settings again."); } } internal static void BroadcastIfServer() { ZNet instance = ZNet.instance; if ((Object)(object)instance == (Object)null || !instance.IsServer() || !Plugin.EnforceServerConfig.Value) { return; } foreach (ZNetPeer peer in instance.GetPeers()) { if (peer?.m_rpc != null) { try { peer.m_rpc.Invoke("SimpleFishingTrap_SyncConfig", new object[1] { Build() }); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Sync to a peer failed: " + ex.Message)); } } } } private static ZPackage Build() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(1); val.Write(Plugin.SecondsPerFish.Value); val.Write(Plugin.MaxFish.Value); val.Write(Plugin.CatchUpWhileAway.Value); val.Write(Plugin.ItemPrefab.Value ?? "FishRaw"); val.Write(Plugin.MaxWaterDistance.Value); val.Write(Plugin.MaxHeightAboveWater.Value); val.Write(Plugin.Recipe.Value ?? ""); val.Write(Plugin.CraftingStationName.Value ?? ""); return val; } private static void RPC_Receive(ZRpc rpc, ZPackage p) { if ((Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsServer()) { return; } try { int num = p.ReadInt(); if (num != 1) { Plugin.Log.LogWarning((object)($"Server settings format v{num}, expected v{1}. " + "Update the mod to match the server. Using local settings.")); return; } _secondsPerFish = p.ReadSingle(); _maxFish = p.ReadInt(); _catchUp = p.ReadBool(); _itemPrefab = p.ReadString(); _maxDistance = p.ReadSingle(); _maxHeight = p.ReadSingle(); _recipe = p.ReadString(); _station = p.ReadString(); HasServerConfig = true; TrapPrefab.ApplyRecipe(); Plugin.Log.LogInfo((object)"Using server settings for Simple Fishing Trap."); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Bad settings package from server: " + ex.Message)); } } } public class FishTrap : MonoBehaviour, Hoverable, Interactable { private const string KeyCount = "sft_count"; private const string KeyProgress = "sft_progress"; private const string KeyLastTime = "sft_last"; private const string RpcExtract = "SFT_Extract"; private const string RpcGive = "SFT_Give"; private const float TickSeconds = 2f; private const float MaxCatchUpWhenDisabled = 10f; private ZNetView _nview; private Piece _piece; private List<GameObject> _fishVisuals; private bool Valid => (Object)(object)_nview != (Object)null && _nview.IsValid(); private int Count => Valid ? _nview.GetZDO().GetInt("sft_count", 0) : 0; private float Progress => Valid ? _nview.GetZDO().GetFloat("sft_progress", 0f) : 0f; private void Awake() { _nview = ((Component)this).GetComponent<ZNetView>(); _piece = ((Component)this).GetComponent<Piece>(); if (!((Object)(object)_nview == (Object)null) && _nview.GetZDO() != null) { _nview.Register("SFT_Extract", (Action<long>)RPC_Extract); _nview.Register<int>("SFT_Give", (Action<long, int>)RPC_Give); _fishVisuals = (from t in ((Component)this).GetComponentsInChildren<Transform>(true) where ((Object)t).name.StartsWith("FishVisual", StringComparison.OrdinalIgnoreCase) select ((Component)t).gameObject).OrderBy<GameObject, string>((GameObject g) => ((Object)g).name, StringComparer.OrdinalIgnoreCase).ToList(); ((MonoBehaviour)this).InvokeRepeating("Tick", Random.Range(0.5f, 2f), 2f); } } private void Tick() { if (Valid) { if (_nview.IsOwner()) { Advance(); } UpdateFishVisuals(); } } private void Advance() { ZDO zDO = _nview.GetZDO(); long ticks = ZNet.instance.GetTime().Ticks; long num = zDO.GetLong("sft_last", 0L); zDO.Set("sft_last", ticks); if (num == 0) { return; } float num2 = (float)TimeSpan.FromTicks(Math.Max(0L, ticks - num)).TotalSeconds; if (!ConfigSync.CatchUpWhileAway) { num2 = Math.Min(num2, 10f); } int maxFish = ConfigSync.MaxFish; int num3 = zDO.GetInt("sft_count", 0); if (num3 >= maxFish) { if (zDO.GetFloat("sft_progress", 0f) != 0f) { zDO.Set("sft_progress", 0f); } return; } float secondsPerFish = ConfigSync.SecondsPerFish; float num4 = zDO.GetFloat("sft_progress", 0f) + num2; int num5 = (int)(num4 / secondsPerFish); if (num5 > 0) { num3 = Math.Min(maxFish, num3 + num5); num4 -= (float)num5 * secondsPerFish; if (num3 >= maxFish) { num4 = 0f; } zDO.Set("sft_count", num3); } zDO.Set("sft_progress", num4); } private void UpdateFishVisuals() { if (_fishVisuals == null || _fishVisuals.Count == 0) { return; } int maxFish = ConfigSync.MaxFish; int num = ((Count > 0) ? Mathf.CeilToInt((float)_fishVisuals.Count * Mathf.Clamp01((float)Count / (float)maxFish)) : 0); for (int i = 0; i < _fishVisuals.Count; i++) { if ((Object)(object)_fishVisuals[i] != (Object)null && _fishVisuals[i].activeSelf != i < num) { _fishVisuals[i].SetActive(i < num); } } } public string GetHoverName() { return ((Object)(object)_piece != (Object)null) ? _piece.m_name : "Simple Fishing Trap"; } public float GetHoverOffset() { return 0f; } public string GetHoverText() { if (!Valid) { return ""; } int count = Count; int maxFish = ConfigSync.MaxFish; string text = $"{GetHoverName()}\nRaw Fish: {count}/{maxFish}"; if (count >= maxFish) { text += "\n<color=orange>Full — empty it to keep catching</color>"; } else { float num = Mathf.Max(0f, ConfigSync.SecondsPerFish - Progress); TimeSpan timeSpan = TimeSpan.FromSeconds(num); text += $"\n<color=#a0a0a0>Next fish in ~{(int)timeSpan.TotalMinutes}:{timeSpan.Seconds:00}</color>"; } if (count > 0) { text += "\n[<color=yellow><b>$KEY_Use</b></color>] Collect"; } return Loc.Localize(text); } public bool Interact(Humanoid user, bool hold, bool alt) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (hold || !Valid) { return false; } if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false)) { return true; } if (Count <= 0) { ((Character)user).Message((MessageType)2, "The trap is empty", 0, (Sprite)null, false); return true; } _nview.InvokeRPC("SFT_Extract", Array.Empty<object>()); return true; } public bool UseItem(Humanoid user, ItemData item) { return false; } private void RPC_Extract(long sender) { if (Valid && _nview.IsOwner()) { ZDO zDO = _nview.GetZDO(); int num = zDO.GetInt("sft_count", 0); if (num > 0) { zDO.Set("sft_count", 0); zDO.Set("sft_progress", 0f); zDO.Set("sft_last", ZNet.instance.GetTime().Ticks); UpdateFishVisuals(); _nview.InvokeRPC(sender, "SFT_Give", new object[1] { num }); } } } private void RPC_Give(long sender, int count) { //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || count <= 0) { return; } GameObject val = TrapPrefab.Find(ConfigSync.ItemPrefab); ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null); if ((Object)(object)val2 == (Object)null) { Plugin.Log.LogError((object)$"Item prefab '{ConfigSync.ItemPrefab}' not found — {count} fish lost."); return; } Inventory inventory = ((Humanoid)localPlayer).GetInventory(); int val3 = Math.Max(1, val2.m_itemData.m_shared.m_maxStackSize); int num = count; bool flag = false; while (num > 0) { int num2 = Math.Min(num, val3); ItemData val4 = val2.m_itemData.Clone(); val4.m_stack = num2; val4.m_dropPrefab = val; if (inventory.CanAddItem(val4, -1)) { inventory.AddItem(val4); } else { Vector3 val5 = ((Component)localPlayer).transform.position + ((Component)localPlayer).transform.forward * 0.5f + Vector3.up; ItemDrop.DropItem(val4, num2, val5, Quaternion.identity); flag = true; } num -= num2; } string arg = Loc.Localize(val2.m_itemData.m_shared.m_name); ((Character)localPlayer).Message((MessageType)1, $"Collected {arg} x{count}", 0, val2.m_itemData.GetIcon(), false); if (flag) { ((Character)localPlayer).Message((MessageType)2, "Inventory full — some fish dropped at your feet", 0, (Sprite)null, false); } } } internal static class ObjModel { private class ObjObject { public string Name; public readonly List<int[]> Corners = new List<int[]>(); } internal const string ObjFile = "SimpleFishingTrap.obj"; internal const string AlbedoFile = "SimpleFishingTrap_Albedo.png"; internal const string NormalFile = "SimpleFishingTrap_Normal.png"; internal const string IconFile = "SimpleFishingTrap_Icon.png"; private static MethodInfo _loadImage; internal static GameObject Load(string objPath, Material baseMaterial, Transform holder) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Expected O, but got Unknown //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0100: 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_0109: Unknown result type (might be due to invalid IL or missing references) try { List<Vector3> positions; List<Vector2> uvs; List<Vector3> normals; List<ObjObject> list = Parse(objPath, out positions, out uvs, out normals); if (list.Count == 0) { Plugin.Log.LogWarning((object)("'" + objPath + "' has no faces.")); return null; } Material sharedMaterial = MakeMaterial(baseMaterial); GameObject val = new GameObject("SimpleFishingTrap_Model"); val.transform.SetParent(holder, false); bool flag = false; foreach (ObjObject item in list) { Mesh val2 = BuildMesh(item, positions, uvs, normals); if (!((Object)(object)val2 == (Object)null)) { GameObject val3 = new GameObject(item.Name); val3.transform.SetParent(val.transform, false); if (item.Name.StartsWith("Collider", StringComparison.OrdinalIgnoreCase)) { BoxCollider val4 = val3.AddComponent<BoxCollider>(); Bounds bounds = val2.bounds; val4.center = ((Bounds)(ref bounds)).center; bounds = val2.bounds; val4.size = ((Bounds)(ref bounds)).size; flag = true; } else { val3.AddComponent<MeshFilter>().sharedMesh = val2; MeshRenderer val5 = val3.AddComponent<MeshRenderer>(); ((Renderer)val5).sharedMaterial = sharedMaterial; ((Renderer)val5).shadowCastingMode = (ShadowCastingMode)1; ((Renderer)val5).receiveShadows = true; } } } if (!flag) { Plugin.Log.LogInfo((object)"OBJ has no 'Collider' object; a box will be fitted around the mesh."); } Plugin.Log.LogInfo((object)$"Loaded OBJ model ({list.Count} object(s), {positions.Count} vertices)."); return val; } catch (Exception arg) { Plugin.Log.LogError((object)$"Failed to load '{objPath}': {arg}"); return null; } } private static List<ObjObject> Parse(string path, out List<Vector3> positions, out List<Vector2> uvs, out List<Vector3> normals) { //IL_0111: 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_0145: Unknown result type (might be due to invalid IL or missing references) positions = new List<Vector3>(); uvs = new List<Vector2>(); normals = new List<Vector3>(); List<ObjObject> list = new List<ObjObject>(); ObjObject objObject = null; CultureInfo invariantCulture = CultureInfo.InvariantCulture; string[] array = File.ReadAllLines(path); foreach (string text in array) { string text2 = text.Trim(); if (text2.Length == 0 || text2[0] == '#') { continue; } string[] array2 = text2.Split(new char[2] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); switch (array2[0]) { case "v": positions.Add(new Vector3(0f - float.Parse(array2[1], invariantCulture), float.Parse(array2[2], invariantCulture), float.Parse(array2[3], invariantCulture))); break; case "vt": uvs.Add(new Vector2(float.Parse(array2[1], invariantCulture), (array2.Length > 2) ? float.Parse(array2[2], invariantCulture) : 0f)); break; case "vn": normals.Add(new Vector3(0f - float.Parse(array2[1], invariantCulture), float.Parse(array2[2], invariantCulture), float.Parse(array2[3], invariantCulture))); break; case "o": case "g": { string name = ((array2.Length > 1) ? string.Join(" ", array2, 1, array2.Length - 1) : "Mesh"); objObject = new ObjObject { Name = name }; list.Add(objObject); break; } case "f": { if (objObject == null) { objObject = new ObjObject { Name = "Mesh" }; list.Add(objObject); } List<int[]> list2 = new List<int[]>(); for (int j = 1; j < array2.Length; j++) { list2.Add(ParseCorner(array2[j], positions.Count, uvs.Count, normals.Count)); } for (int k = 1; k + 1 < list2.Count; k++) { objObject.Corners.Add(list2[0]); objObject.Corners.Add(list2[k + 1]); objObject.Corners.Add(list2[k]); } break; } } } list.RemoveAll((ObjObject o) => o.Corners.Count == 0); return list; } private static int[] ParseCorner(string token, int vCount, int vtCount, int vnCount) { string[] s = token.Split(new char[1] { '/' }); return new int[3] { Index(s, 0, vCount), Index(s, 1, vtCount), Index(s, 2, vnCount) }; } private static int Index(string[] s, int i, int count) { if (i >= s.Length || s[i].Length == 0) { return -1; } int num = int.Parse(s[i], CultureInfo.InvariantCulture); return (num > 0) ? (num - 1) : (count + num); } private static Mesh BuildMesh(ObjObject o, List<Vector3> pos, List<Vector2> uv, List<Vector3> nrm) { //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00db: 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_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Expected O, but got Unknown //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) List<Vector3> list = new List<Vector3>(); List<Vector2> list2 = new List<Vector2>(); List<Vector3> list3 = new List<Vector3>(); List<int> list4 = new List<int>(); Dictionary<string, int> dictionary = new Dictionary<string, int>(); bool flag = true; foreach (int[] corner in o.Corners) { string key = corner[0] + "/" + corner[1] + "/" + corner[2]; if (!dictionary.TryGetValue(key, out var value)) { value = (dictionary[key] = list.Count); list.Add(pos[corner[0]]); list2.Add((corner[1] >= 0) ? uv[corner[1]] : Vector2.zero); if (corner[2] >= 0) { list3.Add(nrm[corner[2]]); } else { list3.Add(Vector3.up); flag = false; } } list4.Add(value); } if (list.Count == 0) { return null; } Mesh val = new Mesh { name = o.Name }; if (list.Count > 65000) { val.indexFormat = (IndexFormat)1; } val.SetVertices(list); val.SetUVs(0, list2); val.SetTriangles(list4, 0); if (flag) { val.SetNormals(list3); } else { val.RecalculateNormals(); } val.RecalculateTangents(); val.RecalculateBounds(); return val; } private static Material MakeMaterial(Material baseMaterial) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Expected O, but got Unknown //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_0328: Unknown result type (might be due to invalid IL or missing references) //IL_0338: Unknown result type (might be due to invalid IL or missing references) //IL_0479: Unknown result type (might be due to invalid IL or missing references) //IL_0375: Unknown result type (might be due to invalid IL or missing references) //IL_0383: Unknown result type (might be due to invalid IL or missing references) Shader val = null; string[] array = new string[4] { "Standard", "Legacy Shaders/Diffuse", "Diffuse", "Mobile/Diffuse" }; foreach (string text in array) { val = Shader.Find(text); if ((Object)(object)val != (Object)null) { break; } } if ((Object)(object)val != (Object)null) { Material val2 = new Material(val) { name = "SimpleFishingTrap_Mat" }; Texture2D val3 = LoadTexture(TrapPrefab.FindFile("SimpleFishingTrap_Albedo.png"), linear: false); if ((Object)(object)val3 != (Object)null) { val2.mainTexture = (Texture)(object)val3; } else { Plugin.Log.LogWarning((object)"'SimpleFishingTrap_Albedo.png' not found — model will be untextured."); } val2.color = Color.white; if (val2.HasProperty("_Metallic")) { val2.SetFloat("_Metallic", 0f); } if (val2.HasProperty("_Glossiness")) { val2.SetFloat("_Glossiness", 0.1f); } Texture2D val4 = LoadTexture(TrapPrefab.FindFile("SimpleFishingTrap_Normal.png"), linear: true); if ((Object)(object)val4 != (Object)null && val2.HasProperty("_BumpMap")) { val2.SetTexture("_BumpMap", (Texture)(object)val4); val2.EnableKeyword("_NORMALMAP"); } Plugin.Log.LogInfo((object)("Trap material uses shader '" + ((Object)val).name + "'.")); return val2; } Plugin.Log.LogWarning((object)"No plain Unity shader found; falling back to a copy of the chest material."); Material val5 = (((Object)(object)baseMaterial != (Object)null) ? new Material(baseMaterial) : new Material(Shader.Find("Custom/Piece"))); ((Object)val5).name = "SimpleFishingTrap_Mat"; if (val5.HasProperty("_Color")) { val5.SetColor("_Color", Color.white); } Texture2D val6 = LoadTexture(TrapPrefab.FindFile("SimpleFishingTrap_Albedo.png"), linear: false); if ((Object)(object)val6 != (Object)null && val5.HasProperty("_MainTex")) { val5.SetTexture("_MainTex", (Texture)(object)val6); } else if ((Object)(object)val6 == (Object)null) { Plugin.Log.LogWarning((object)"'SimpleFishingTrap_Albedo.png' not found — model will be untextured."); } Texture2D val7 = LoadTexture(TrapPrefab.FindFile("SimpleFishingTrap_Normal.png"), linear: true); if (val5.HasProperty("_BumpMap")) { val5.SetTexture("_BumpMap", (Texture)(object)val7); if ((Object)(object)val7 != (Object)null) { val5.EnableKeyword("_NORMALMAP"); } } string[] array2; try { array2 = val5.GetTexturePropertyNames(); } catch { array2 = new string[2] { "_MainTex", "_BumpMap" }; } StringBuilder stringBuilder = new StringBuilder(); string[] array3 = array2; foreach (string text2 in array3) { if (val5.HasProperty(text2)) { Texture texture = val5.GetTexture(text2); stringBuilder.Append(string.Format("\n {0}: {1}, tiling {2}, offset {3}", text2, ((Object)(object)texture != (Object)null) ? ((Object)texture).name : "none", val5.GetTextureScale(text2), val5.GetTextureOffset(text2))); if (text2 == "_MainTex" || text2 == "_BumpMap") { val5.SetTextureScale(text2, Vector2.one); val5.SetTextureOffset(text2, Vector2.zero); } } } Plugin.Log.LogInfo((object)$"Trap material shader '{((Object)val5.shader).name}', texture slots before reset:{stringBuilder}"); string[] array4 = new string[4] { "_MetallicGlossMap", "_EmissionMap", "_OcclusionMap", "_DetailAlbedoMap" }; foreach (string text3 in array4) { if (val5.HasProperty(text3)) { val5.SetTexture(text3, (Texture)null); } } if (val5.HasProperty("_Metallic")) { val5.SetFloat("_Metallic", 0f); } if (val5.HasProperty("_Glossiness")) { val5.SetFloat("_Glossiness", 0.1f); } if (val5.HasProperty("_EmissionColor")) { val5.SetColor("_EmissionColor", Color.black); } val5.DisableKeyword("_EMISSION"); val5.DisableKeyword("_METALLICGLOSSMAP"); return val5; } private static Texture2D LoadTexture(string path, bool linear) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown if (path == null) { return null; } try { Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true, linear); if (!LoadImage(val, File.ReadAllBytes(path))) { Plugin.Log.LogWarning((object)("Couldn't read image '" + path + "'.")); return null; } ((Object)val).name = Path.GetFileNameWithoutExtension(path); ((Texture)val).wrapMode = (TextureWrapMode)0; ((Texture)val).filterMode = (FilterMode)2; ((Texture)val).anisoLevel = 4; return val; } catch (Exception ex) { Plugin.Log.LogWarning((object)("Couldn't load texture '" + path + "': " + ex.Message)); return null; } } private static bool LoadImage(Texture2D tex, byte[] data) { if (_loadImage == null) { _loadImage = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule")?.GetMethod("LoadImage", new Type[2] { typeof(Texture2D), typeof(byte[]) }); if (_loadImage == null) { Plugin.Log.LogError((object)"UnityEngine.ImageConversion.LoadImage not found — textures can't be loaded."); return false; } } return (bool)_loadImage.Invoke(null, new object[2] { tex, data }); } internal static Sprite LoadSprite(string path) { //IL_0039: 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) Texture2D val = LoadTexture(path, linear: false); if ((Object)(object)val == (Object)null) { return null; } ((Texture)val).wrapMode = (TextureWrapMode)1; return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); } } internal static class Patches { internal static void ApplyAll(Harmony h) { TryPatch(h, typeof(ZNetScene), new string[1] { "Awake" }, Hook(typeof(Patches), "ZNetScene_Awake_Prefix")); TryPatch(h, typeof(Player), new string[1] { "UpdatePlacementGhost" }, null, Hook(typeof(Placement), "UpdatePlacementGhost_Postfix")); TryPatch(h, typeof(Player), new string[2] { "TryPlacePiece", "PlacePiece" }, Hook(typeof(Placement), "TryPlacePiece_Prefix")); TryPatch(h, typeof(ZNet), new string[1] { "OnNewConnection" }, null, Hook(typeof(ConfigSync), "OnNewConnection_Postfix")); TryPatch(h, typeof(ZNet), new string[1] { "RPC_PeerInfo" }, null, Hook(typeof(ConfigSync), "RPC_PeerInfo_Postfix")); TryPatch(h, typeof(ZNet), new string[1] { "OnDestroy" }, null, Hook(typeof(ConfigSync), "ZNet_OnDestroy_Postfix")); } private static void ZNetScene_Awake_Prefix(ZNetScene __instance) { try { TrapPrefab.Register(__instance); } catch (Exception arg) { Plugin.Log.LogError((object)$"Failed to register Simple Fishing Trap: {arg}"); } } private static HarmonyMethod Hook(Type host, string name) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown return new HarmonyMethod(AccessTools.Method(host, name, (Type[])null, (Type[])null)); } private static void TryPatch(Harmony h, Type type, string[] names, HarmonyMethod prefix = null, HarmonyMethod postfix = null) { foreach (string text in names) { MethodInfo methodInfo = AccessTools.Method(type, text, (Type[])null, (Type[])null); if (!(methodInfo == null)) { try { h.Patch((MethodBase)methodInfo, prefix, postfix, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); return; } catch (Exception ex) { Plugin.Log.LogError((object)("Failed to patch " + type.Name + "." + text + ": " + ex.Message)); return; } } } Plugin.Log.LogWarning((object)("Could not find " + type.Name + "." + string.Join("/", names) + " — that feature is disabled (a Valheim update probably renamed it).")); } } internal static class Placement { private static readonly FieldInfo GhostField = AccessTools.Field(typeof(Player), "m_placementGhost"); private static readonly FieldInfo StatusField = AccessTools.Field(typeof(Player), "m_placementStatus"); private static readonly MethodInfo SetGhostValid = AccessTools.Method(typeof(Player), "SetPlacementGhostValid", (Type[])null, (Type[])null); private static object _invalidStatus; private static object _validStatus; private const int RingSamples = 16; private const float MinWaterDepth = 0.05f; internal static bool IsOurs(GameObject go) { return (Object)(object)go != (Object)null && ((Object)go).name.StartsWith("SimpleFishingTrap", StringComparison.Ordinal); } internal static bool NearWater(Vector3 pos) { //IL_0021: 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_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: 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_00e6: Unknown result type (might be due to invalid IL or missing references) ZoneSystem instance = ZoneSystem.instance; if ((Object)(object)instance == (Object)null) { return true; } float waterLevel = instance.m_waterLevel; if (pos.y - waterLevel > ConfigSync.MaxHeightAboveWater) { return false; } if (IsWater(instance, pos, waterLevel)) { return true; } float maxWaterDistance = ConfigSync.MaxWaterDistance; if (maxWaterDistance <= 0f) { return false; } float[] array = new float[2] { maxWaterDistance * 0.5f, maxWaterDistance }; Vector3 p = default(Vector3); foreach (float num in array) { for (int j = 0; j < 16; j++) { float num2 = (float)j * (float)Math.PI * 2f / 16f; ((Vector3)(ref p))..ctor(pos.x + Mathf.Cos(num2) * num, pos.y, pos.z + Mathf.Sin(num2) * num); if (IsWater(instance, p, waterLevel)) { return true; } } } return false; } private static bool IsWater(ZoneSystem zs, Vector3 p, float water) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return zs.GetGroundHeight(p) < water - 0.05f; } private static void EnsureStatusValues() { if (_invalidStatus == null && !(StatusField == null)) { Type fieldType = StatusField.FieldType; _validStatus = Enum.Parse(fieldType, "Valid"); _invalidStatus = Enum.Parse(fieldType, "Invalid"); } } internal static void UpdatePlacementGhost_Postfix(Player __instance) { //IL_0073: Unknown result type (might be due to invalid IL or missing references) try { if (GhostField == null || StatusField == null) { return; } object? value = GhostField.GetValue(__instance); GameObject val = (GameObject)((value is GameObject) ? value : null); if (IsOurs(val)) { EnsureStatusValues(); if (object.Equals(StatusField.GetValue(__instance), _validStatus) && !NearWater(val.transform.position)) { StatusField.SetValue(__instance, _invalidStatus); SetGhostValid?.Invoke(__instance, new object[1] { false }); } } } catch (Exception ex) { Plugin.Log.LogDebug((object)("Placement check error: " + ex.Message)); } } internal static bool TryPlacePiece_Prefix(Player __instance, Piece __0, ref bool __result) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__0 == (Object)null || !IsOurs(((Component)__0).gameObject)) { return true; } object? obj = GhostField?.GetValue(__instance); GameObject val = (GameObject)((obj is GameObject) ? obj : null); if ((Object)(object)val == (Object)null || NearWater(val.transform.position)) { return true; } ((Character)__instance).Message((MessageType)2, $"Must be placed within {ConfigSync.MaxWaterDistance:0.##}m of water", 0, (Sprite)null, false); __result = false; return false; } } internal static class Loc { private static PropertyInfo _instance; private static MethodInfo _localize; private static bool _looked; internal static string Localize(string text) { if (string.IsNullOrEmpty(text)) { return text; } try { if (!_looked) { _looked = true; Type type = AccessTools.TypeByName("Localization"); _instance = ((type == null) ? null : AccessTools.Property(type, "instance")); _localize = ((type == null) ? null : AccessTools.Method(type, "Localize", new Type[1] { typeof(string) }, (Type[])null)); } object obj = _instance?.GetValue(null, null); if (obj != null && _localize != null) { return (_localize.Invoke(obj, new object[1] { text }) as string) ?? text; } } catch { } return text; } } [BepInPlugin("BhimaJenkins.SimpleFishingTrap", "SimpleFishingTrap", "0.1.0")] public class Plugin : BaseUnityPlugin { public const string ModGuid = "BhimaJenkins.SimpleFishingTrap"; public const string ModName = "SimpleFishingTrap"; public const string ModVersion = "0.1.0"; internal static Plugin Instance; internal static ManualLogSource Log; internal static string PluginDir; internal static ConfigEntry<float> SecondsPerFish; internal static ConfigEntry<int> MaxFish; internal static ConfigEntry<bool> CatchUpWhileAway; internal static ConfigEntry<string> ItemPrefab; internal static ConfigEntry<float> MaxWaterDistance; internal static ConfigEntry<float> MaxHeightAboveWater; internal static ConfigEntry<string> Recipe; internal static ConfigEntry<string> CraftingStationName; internal static ConfigEntry<bool> EnforceServerConfig; private Harmony _harmony; private FileSystemWatcher _watcher; private volatile bool _reloadRequested; private void Awake() { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Expected O, but got Unknown //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Expected O, but got Unknown //IL_0313: Unknown result type (might be due to invalid IL or missing references) //IL_031d: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; PluginDir = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); SecondsPerFish = ((BaseUnityPlugin)this).Config.Bind<float>("1 - Catching", "Seconds Per Fish", 180f, new ConfigDescription("How long each Raw Fish takes to catch (180 = 3 minutes).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 3600f), Array.Empty<object>())); MaxFish = ((BaseUnityPlugin)this).Config.Bind<int>("1 - Catching", "Trap Capacity", 10, new ConfigDescription("How many Raw Fish a trap holds. A full trap stops catching until it is emptied.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>())); CatchUpWhileAway = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Catching", "Catch While Away", true, "On: traps keep catching while nobody is nearby (like bee hives), and catch up when you return. Off: traps only catch while their area is loaded."); ItemPrefab = ((BaseUnityPlugin)this).Config.Bind<string>("1 - Catching", "Item Prefab", "FishRaw", "Prefab name of the item the trap produces. Leave as FishRaw for vanilla Raw Fish."); MaxWaterDistance = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Placement", "Max Distance From Water", 0.25f, new ConfigDescription("How close (sideways, in metres) the trap must be to water to be placed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>())); MaxHeightAboveWater = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Placement", "Max Height Above Water", 0.25f, new ConfigDescription("How far above the water surface the trap's base may be. Raise this (to ~1.5) to allow placing traps on docks.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>())); Recipe = ((BaseUnityPlugin)this).Config.Bind<string>("3 - Building", "Recipe", "Wood:6, LeatherScraps:10", "Build cost as ItemPrefab:Amount pairs, comma-separated."); CraftingStationName = ((BaseUnityPlugin)this).Config.Bind<string>("3 - Building", "Crafting Station", "piece_workbench", "Prefab name of the station that must be nearby to build the trap. Leave empty for none."); EnforceServerConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Server", "Enforce Server Settings", true, "SERVER ONLY. Sends the server's settings to every player who joins, so catch rate, capacity, placement rules and build cost are the same for everyone."); Recipe.SettingChanged += delegate { OnSettingsChanged(); }; CraftingStationName.SettingChanged += delegate { OnSettingsChanged(); }; SecondsPerFish.SettingChanged += delegate { OnSettingsChanged(); }; MaxFish.SettingChanged += delegate { OnSettingsChanged(); }; CatchUpWhileAway.SettingChanged += delegate { OnSettingsChanged(); }; ItemPrefab.SettingChanged += delegate { OnSettingsChanged(); }; MaxWaterDistance.SettingChanged += delegate { OnSettingsChanged(); }; MaxHeightAboveWater.SettingChanged += delegate { OnSettingsChanged(); }; _harmony = new Harmony("BhimaJenkins.SimpleFishingTrap"); Patches.ApplyAll(_harmony); SetupConfigWatcher(); Log.LogInfo((object)"SimpleFishingTrap 0.1.0 loaded."); } internal static void OnSettingsChanged() { TrapPrefab.ApplyRecipe(); ConfigSync.BroadcastIfServer(); } private void Update() { if (_reloadRequested) { _reloadRequested = false; try { ((BaseUnityPlugin)this).Config.Reload(); Log.LogInfo((object)"Config reloaded from disk."); } catch (Exception ex) { Log.LogWarning((object)("Could not reload config: " + ex.Message)); } OnSettingsChanged(); } } private void SetupConfigWatcher() { try { _watcher = new FileSystemWatcher(Paths.ConfigPath, Path.GetFileName(((BaseUnityPlugin)this).Config.ConfigFilePath)); _watcher.Changed += delegate { _reloadRequested = true; }; _watcher.Created += delegate { _reloadRequested = true; }; _watcher.Renamed += delegate { _reloadRequested = true; }; _watcher.EnableRaisingEvents = true; } catch (Exception ex) { Log.LogWarning((object)("Config watcher unavailable (" + ex.Message + "); edits apply on restart.")); } } private void OnDestroy() { _watcher?.Dispose(); Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } internal static class TrapPrefab { internal const string PrefabName = "SimpleFishingTrap"; private const string BasePrefabName = "piece_chest_wood"; private const string HammerName = "Hammer"; internal const string BundleFileName = "simplefishingtrap"; internal const string ModelAssetName = "SimpleFishingTrap_Model"; internal const string IconAssetName = "SimpleFishingTrap_Icon"; internal static GameObject Prefab; private static GameObject _holder; private static AssetBundle _bundle; private static bool _bundleTried; private static List<GameObject> _sceneList; internal static void Register(ZNetScene scene) { if (scene?.m_prefabs == null) { return; } _sceneList = scene.m_prefabs; if ((Object)(object)Prefab == (Object)null) { Prefab = Build(); } if (!((Object)(object)Prefab == (Object)null)) { if (!scene.m_prefabs.Contains(Prefab)) { scene.m_prefabs.Add(Prefab); } GameObject obj = Find("Hammer"); PieceTable val = ((obj != null) ? obj.GetComponent<ItemDrop>() : null)?.m_itemData?.m_shared?.m_buildPieces; if ((Object)(object)val == (Object)null) { Plugin.Log.LogError((object)"Couldn't find the Hammer's build table — the trap won't appear in the build menu."); } else if (!val.m_pieces.Contains(Prefab)) { val.m_pieces.Add(Prefab); } ApplyRecipe(); } } internal static GameObject Find(string name) { if (string.IsNullOrEmpty(name)) { return null; } GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(name) : null); if ((Object)(object)val != (Object)null) { return val; } if (_sceneList != null) { foreach (GameObject scene in _sceneList) { if ((Object)(object)scene != (Object)null && ((Object)scene).name == name) { return scene; } } } return ((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(name) : null; } private static GameObject Build() { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown //IL_00d4: Unknown result type (might be due to invalid IL or missing references) GameObject val = Find("piece_chest_wood"); if ((Object)(object)val == (Object)null) { Plugin.Log.LogError((object)"Base prefab 'piece_chest_wood' not found — Simple Fishing Trap disabled."); return null; } if ((Object)(object)_holder == (Object)null) { _holder = new GameObject("SimpleFishingTrap_Prefabs"); _holder.SetActive(false); Object.DontDestroyOnLoad((Object)(object)_holder); } GameObject val2 = Object.Instantiate<GameObject>(val, _holder.transform, false); ((Object)val2).name = "SimpleFishingTrap"; Container[] componentsInChildren = val2.GetComponentsInChildren<Container>(true); foreach (Container val3 in componentsInChildren) { Object.DestroyImmediate((Object)(object)val3); } Piece component = val2.GetComponent<Piece>(); component.m_name = "Simple Fishing Trap"; component.m_description = "Slowly catches Raw Fish. Must be placed right next to water. Holds a limited number of fish — empty it to keep it catching."; component.m_category = (PieceCategory)1; component.m_groundOnly = false; component.m_noInWater = false; WearNTear component2 = val2.GetComponent<WearNTear>(); if ((Object)(object)component2 != (Object)null) { component2.m_noRoofWear = false; } if (!TrySwapInModel(val2, component2, component)) { Plugin.Log.LogInfo((object)"No custom model found ('SimpleFishingTrap.obj' next to the DLL) — using placeholder chest model."); } val2.AddComponent<FishTrap>(); return val2; } private static bool TrySwapInModel(GameObject go, WearNTear wnt, Piece piece) { //IL_02d9: Unknown result type (might be due to invalid IL or missing references) //IL_02eb: Unknown result type (might be due to invalid IL or missing references) Renderer componentInChildren = go.GetComponentInChildren<Renderer>(true); Material baseMaterial = (((Object)(object)componentInChildren != (Object)null) ? componentInChildren.sharedMaterial : null); GameObject val = null; Sprite val2 = null; string text = null; AssetBundle val3 = LoadBundle(); if ((Object)(object)val3 != (Object)null) { val = val3.LoadAsset<GameObject>("SimpleFishingTrap_Model") ?? val3.LoadAllAssets<GameObject>().FirstOrDefault(); val2 = val3.LoadAsset<Sprite>("SimpleFishingTrap_Icon") ?? val3.LoadAllAssets<Sprite>().FirstOrDefault(); if ((Object)(object)val != (Object)null) { text = "AssetBundle"; } } if ((Object)(object)val == (Object)null) { string text2 = FindFile("SimpleFishingTrap.obj"); if (text2 != null) { val = ObjModel.Load(text2, baseMaterial, _holder.transform); if ((Object)(object)val != (Object)null) { text = text2; } } } if ((Object)(object)val2 == (Object)null) { val2 = ObjModel.LoadSprite(FindFile("SimpleFishingTrap_Icon.png")); } if ((Object)(object)val2 != (Object)null) { piece.m_icon = val2; } if ((Object)(object)val == (Object)null) { return false; } Plugin.Log.LogInfo((object)("Using custom trap model from " + text + ".")); LODGroup[] componentsInChildren = go.GetComponentsInChildren<LODGroup>(true); foreach (LODGroup val4 in componentsInChildren) { Object.DestroyImmediate((Object)(object)val4); } Renderer[] componentsInChildren2 = go.GetComponentsInChildren<Renderer>(true); foreach (Renderer val5 in componentsInChildren2) { Object.DestroyImmediate((Object)(object)val5); } MeshFilter[] componentsInChildren3 = go.GetComponentsInChildren<MeshFilter>(true); foreach (MeshFilter val6 in componentsInChildren3) { Object.DestroyImmediate((Object)(object)val6); } Collider[] componentsInChildren4 = go.GetComponentsInChildren<Collider>(true); foreach (Collider val7 in componentsInChildren4) { Object.DestroyImmediate((Object)(object)val7); } List<Transform> list = new List<Transform>(); if ((Object)(object)wnt != (Object)null) { GameObject[] array = (GameObject[])(object)new GameObject[3] { wnt.m_new, wnt.m_worn, wnt.m_broken }; foreach (GameObject val8 in array) { if ((Object)(object)val8 != (Object)null && !list.Contains(val8.transform)) { list.Add(val8.transform); } } } if (list.Count == 0) { list.Add(go.transform); } int num = LayerMask.NameToLayer("piece"); Shader val9 = Shader.Find("Custom/Piece"); foreach (Transform item in list) { GameObject val10 = Object.Instantiate<GameObject>(val, item, false); ((Object)val10).name = "SimpleFishingTrap_Model"; val10.transform.localPosition = Vector3.zero; val10.transform.localRotation = Quaternion.identity; Transform[] componentsInChildren5 = val10.GetComponentsInChildren<Transform>(true); foreach (Transform val11 in componentsInChildren5) { if (num >= 0) { ((Component)val11).gameObject.layer = num; } } if ((Object)(object)val9 != (Object)null) { Renderer[] componentsInChildren6 = val10.GetComponentsInChildren<Renderer>(true); foreach (Renderer val12 in componentsInChildren6) { Material[] sharedMaterials = val12.sharedMaterials; foreach (Material val13 in sharedMaterials) { if ((Object)(object)val13 != (Object)null && (Object)(object)val13.shader != (Object)null && ((Object)val13.shader).name == "Standard") { val13.shader = val9; } } } } if ((Object)(object)val10.GetComponentInChildren<Collider>(true) == (Object)null) { AddFallbackCollider(val10); } } return true; } private static void AddFallbackCollider(GameObject inst) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) MeshFilter componentInChildren = inst.GetComponentInChildren<MeshFilter>(true); BoxCollider val = inst.AddComponent<BoxCollider>(); if ((Object)(object)componentInChildren != (Object)null && (Object)(object)componentInChildren.sharedMesh != (Object)null) { Bounds bounds = componentInChildren.sharedMesh.bounds; val.center = ((Bounds)(ref bounds)).center; val.size = ((Bounds)(ref bounds)).size; } Plugin.Log.LogWarning((object)"Model has no collider; added a box collider around the first mesh."); } internal static string FindFile(string fileName) { List<string> list = new List<string> { Path.Combine(Plugin.PluginDir, fileName), Path.Combine(Path.Combine(Plugin.PluginDir, "Assets"), fileName) }; foreach (string item in list) { if (File.Exists(item)) { return item; } } try { string[] files = Directory.GetFiles(Paths.PluginPath, fileName, SearchOption.AllDirectories); if (files.Length != 0) { return files[0]; } } catch { } return null; } private static AssetBundle LoadBundle() { if (_bundleTried) { return _bundle; } _bundleTried = true; string text = FindFile("simplefishingtrap"); if (text == null) { return null; } try { _bundle = AssetBundle.LoadFromFile(text); if ((Object)(object)_bundle != (Object)null) { Plugin.Log.LogInfo((object)("Loaded model bundle: " + text)); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Couldn't load bundle '" + text + "': " + ex.Message)); } return _bundle; } internal static void ApplyRecipe() { //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Expected O, but got Unknown //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: 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_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Expected O, but got Unknown //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0123: 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_0137: Expected O, but got Unknown if ((Object)(object)Prefab == (Object)null) { return; } Piece component = Prefab.GetComponent<Piece>(); if ((Object)(object)component == (Object)null) { return; } List<Requirement> list = new List<Requirement>(); string[] array = (ConfigSync.Recipe ?? "").Split(new char[2] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries); foreach (string text in array) { string[] array2 = text.Split(new char[1] { ':' }); string text2 = array2[0].Trim(); int result = 1; if (array2.Length > 1 && !int.TryParse(array2[1].Trim(), out result)) { result = 1; } if (text2.Length != 0 && result > 0) { GameObject obj = Find(text2); ItemDrop val = ((obj != null) ? obj.GetComponent<ItemDrop>() : null); if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)("Recipe item '" + text2 + "' not found (prefab names are case-sensitive).")); continue; } list.Add(new Requirement { m_resItem = val, m_amount = result, m_recover = true }); } } if (list.Count == 0) { Plugin.Log.LogWarning((object)"Recipe is empty or invalid — falling back to Wood:6, LeatherScraps:10."); GameObject obj2 = Find("Wood"); ItemDrop val2 = ((obj2 != null) ? obj2.GetComponent<ItemDrop>() : null); GameObject obj3 = Find("LeatherScraps"); ItemDrop val3 = ((obj3 != null) ? obj3.GetComponent<ItemDrop>() : null); if ((Object)(object)val2 != (Object)null) { list.Add(new Requirement { m_resItem = val2, m_amount = 6, m_recover = true }); } if ((Object)(object)val3 != (Object)null) { list.Add(new Requirement { m_resItem = val3, m_amount = 10, m_recover = true }); } } component.m_resources = list.ToArray(); string craftingStation = ConfigSync.CraftingStation; object craftingStation2; if (!string.IsNullOrWhiteSpace(craftingStation)) { GameObject obj4 = Find(craftingStation.Trim()); craftingStation2 = ((obj4 != null) ? obj4.GetComponent<CraftingStation>() : null); } else { craftingStation2 = null; } component.m_craftingStation = (CraftingStation)craftingStation2; if (!string.IsNullOrWhiteSpace(craftingStation) && (Object)(object)component.m_craftingStation == (Object)null) { Plugin.Log.LogWarning((object)("Crafting station '" + craftingStation + "' not found — trap can be built anywhere.")); } } } }