using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using FishNet; using FishNet.Connection; using FishNet.Managing; using FishNet.Managing.Object; using FishNet.Object; using HarmonyLib; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("SeagullFishing")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("钓海鸥")] [assembly: AssemblyFileVersion("1.2.0.0")] [assembly: AssemblyInformationalVersion("1.2.0")] [assembly: AssemblyProduct("SeagullFishing")] [assembly: AssemblyTitle("SeagullFishing")] [assembly: AssemblyVersion("1.2.0.0")] namespace SeagullFishing; [HarmonyPatch(typeof(CreatureManager), "HookItem")] internal static class Patch_CreatureManager_HookItem { private static bool Prefix(CreatureManager __instance, Item itemPrefab, Bait bait) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) try { if (!Plugin.Enabled.Value) { return true; } Creature val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.Creature : null); if ((Object)(object)val != (Object)null && (int)val.BossType != 0) { return true; } if (Random.value < Plugin.DynamiteChance.Value) { Item dynamitePrefab = SeagullLogic.GetDynamitePrefab(); if ((Object)(object)dynamitePrefab != (Object)null) { SeagullLogic.HookDynamite(__instance, dynamitePrefab, bait); return false; } Plugin.LogWarn("Dynamite prefab not found; falling through to the seagull roll"); } if (Random.value < Plugin.CatchChance.Value) { Item seagullPrefab = SeagullLogic.GetSeagullPrefab(); if ((Object)(object)seagullPrefab != (Object)null) { SeagullLogic.HookSeagull(__instance, seagullPrefab, bait); return false; } Plugin.LogWarn("Seagull prefab not found; this catch falls back to a normal fish"); } return true; } catch (Exception ex) { Plugin.LogWarn("HookItem Prefix error: " + ex.Message); return true; } } } [HarmonyPatch(typeof(BirdManager), "SimulateBird")] internal static class Patch_BirdManager_SimulateBird { private static bool Prefix(Bird bird) { try { if (Plugin.Enabled.Value && SeagullLogic.TrySprint(bird)) { return false; } } catch (Exception ex) { Plugin.LogWarn("SimulateBird Prefix error: " + ex.Message); } return true; } } [HarmonyPatch(typeof(Bird), "SetAttackingFood")] internal static class Patch_Bird_SetAttackingFood { private static bool Prefix(Bird __instance, Item item) { try { if (Plugin.Enabled.Value && (Object)(object)item != (Object)null && SeagullLogic.IsModSeagull(__instance)) { return false; } } catch (Exception ex) { Plugin.LogWarn("SetAttackingFood Prefix error: " + ex.Message); } return true; } } [HarmonyPatch(typeof(Bird), "OnStopClient")] internal static class Patch_Bird_OnStopClient { private static void Postfix(Bird __instance) { try { if (Plugin.Enabled.Value) { SeagullLogic.RemoveModSeagull(__instance); } } catch (Exception ex) { Plugin.LogWarn("Bird.OnStopClient Postfix error: " + ex.Message); } } } [HarmonyPatch(typeof(Item), "RemoveBaitJointOnItemReleased")] internal static class Patch_Item_RemoveBaitJointOnItemReleased { private static void Postfix(Item __instance) { try { if (Plugin.Enabled.Value) { Bird val = (Bird)(object)((__instance is Bird) ? __instance : null); if (val != null && ((NetworkBehaviour)val).IsServerInitialized) { SeagullLogic.ReleaseSeagullToSky(val); } } } catch (Exception ex) { Plugin.LogWarn("RemoveBaitJointOnItemReleased Postfix error: " + ex.Message); } } } [HarmonyPatch(typeof(Explosive), "ServerExplode")] internal static class Patch_Explosive_ServerExplode { private static void Prefix(Explosive __instance) { try { if (Plugin.Enabled.Value) { SeagullLogic.CleanupExplodedDynamite(__instance); } } catch (Exception ex) { Plugin.LogWarn("ServerExplode Prefix error: " + ex.Message); } } } [BepInPlugin("com.yw.seagullfishing", "Seagull Fishing", "1.2.0")] public class Plugin : BaseUnityPlugin { internal static ManualLogSource Log; internal static ConfigEntry Enabled; internal static ConfigEntry CatchChance; internal static ConfigEntry DynamiteChance; internal static ConfigEntry DynamiteFuse; internal static ConfigEntry SeagullFlyHeight; internal static void LogInfo(string msg) { try { Log.LogInfo((object)msg); } catch { } } internal static void LogWarn(string msg) { try { Log.LogWarning((object)msg); } catch { } } private void Awake() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_005c: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; InitConfig(); Harmony val = new Harmony("com.yw.seagullfishing"); int num = 0; int num2 = 0; Type[] types = typeof(Plugin).Assembly.GetTypes(); foreach (Type type in types) { if (type.GetCustomAttributes(typeof(HarmonyPatch), inherit: false).Length != 0) { try { new PatchClassProcessor(val, type).Patch(); num++; } catch (Exception ex) { num2++; LogWarn("Patch apply failed: " + type.Name + " => " + ex.GetType().Name + ": " + ex.Message); } } } LogInfo("Harmony patches applied (ok " + num + ", failed " + num2 + ")"); LogInfo("Seagull Fishing loaded! (cfg: " + Paths.ConfigPath + ")"); } private void InitConfig() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Expected O, but got Unknown //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Expected O, but got Unknown Enabled = ((BaseUnityPlugin)this).Config.Bind("General", "Enabled", true, "总开关(Master switch;关闭后钓鱼行为与原版完全一致)"); CatchChance = ((BaseUnityPlugin)this).Config.Bind("General", "CatchChance", 0.15f, new ConfigDescription("咬钩替换为海鸥的概率,0-1(Chance to catch a seagull instead of a fish, 0-1;默认 0.15 = 15%)", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1f), Array.Empty())); DynamiteChance = ((BaseUnityPlugin)this).Config.Bind("General", "DynamiteChance", 0.05f, new ConfigDescription("咬钩替换为点燃炸药的概率,0-1(Chance to hook a lit dynamite instead of a fish, 0-1;默认 0.05 = 5%)", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1f), Array.Empty())); DynamiteFuse = ((BaseUnityPlugin)this).Config.Bind("General", "DynamiteFuse", 10f, new ConfigDescription("钓上的炸药引信时长,秒(Fuse duration of hooked dynamite in seconds;默认 10)", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 30f), Array.Empty())); SeagullFlyHeight = ((BaseUnityPlugin)this).Config.Bind("General", "SeagullFlyHeight", 50f, new ConfigDescription("海鸥脱钩后向上飞行的天空高度,米(相对释放点/水面;Sky height a released seagull flies up to, in meters above the release point/water;默认 50)", (AcceptableValueBase)(object)new AcceptableValueRange(10f, 100f), Array.Empty())); } } internal static class SeagullLogic { private static Item _cachedSeagull; private static Item _cachedDynamite; private static float _lastSeagullFail; private static float _lastDynamiteFail; private const float RetryCooldown = 5f; private static readonly HashSet ModSeagulls = new HashSet(); public const float SeagullSprintSpeed = 60f; private static readonly HashSet SprintingSeagulls = new HashSet(); private static readonly FieldInfo ExplosiveActivatedDelayField = AccessTools.Field(typeof(Explosive), "_activatedExplosionDelay"); private static readonly PropertyInfo FlyHeigthProperty = AccessTools.Property(typeof(Bird), "FlyHeigth"); private static readonly MethodInfo FlyHeigthSetter = ((FlyHeigthProperty != null) ? FlyHeigthProperty.GetSetMethod(nonPublic: true) : null); private static readonly FieldInfo FlyHeigthBackingField = AccessTools.Field(typeof(Bird), "k__BackingField"); public static bool IsModSeagull(Bird bird) { if ((Object)(object)bird != (Object)null) { return ModSeagulls.Contains(bird); } return false; } public static void RemoveModSeagull(Bird bird) { if ((Object)(object)bird != (Object)null) { ModSeagulls.Remove(bird); SprintingSeagulls.Remove(bird); } } public static bool TrySprint(Bird bird) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)bird == (Object)null || !SprintingSeagulls.Contains(bird)) { return false; } if (((Creature)bird)._hp.Value <= 0 || ((Component)bird).transform.position.y >= bird.FlyHeigth) { SprintingSeagulls.Remove(bird); ModSeagulls.Remove(bird); return true; } Transform transform = ((Component)bird).transform; transform.position += Vector3.up * (60f * Time.deltaTime); bird.SetAnimState((byte)4); ((Component)bird).transform.rotation = Quaternion.FromToRotation(((Component)bird).transform.forward, Vector3.up) * ((Component)bird).transform.rotation; return true; } catch (Exception ex) { Plugin.LogWarn("TrySprint error: " + ex.Message); return false; } } public static Item GetSeagullPrefab() { return GetPrefab(ref _cachedSeagull, ref _lastSeagullFail, "Seagull"); } public static Item GetDynamitePrefab() { return GetPrefab(ref _cachedDynamite, ref _lastDynamiteFail, "Dynamite"); } private static Item GetPrefab(ref Item cache, ref float lastFail, string name) where T : Component { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)cache != (Object)null) { return cache; } if (Time.time - lastFail < 5f) { return null; } T[] array = Resources.FindObjectsOfTypeAll(); T val = default(T); int num = 0; T[] array2 = array; foreach (T val2 in array2) { if ((Object)(object)val2 == (Object)null || (Object)(object)((Component)val2).gameObject == (Object)null) { continue; } Scene scene = ((Component)val2).gameObject.scene; if (((Scene)(ref scene)).IsValid()) { continue; } num++; if ((Object)(object)val == (Object)null) { val = val2; } if (((Object)((Component)val2).gameObject).name == name) { Item component = ((Component)val2).GetComponent(); if ((Object)(object)component != (Object)null) { Cache(ref cache, component, name); return component; } } } if (num == 1 && (Object)(object)val != (Object)null) { Item component2 = ((Component)val).GetComponent(); if ((Object)(object)component2 != (Object)null) { Cache(ref cache, component2, name); return component2; } } Item val3 = TryGetFromSpawnablePrefabs(name); if ((Object)(object)val3 != (Object)null) { Cache(ref cache, val3, name); return val3; } lastFail = Time.time; return null; } catch (Exception ex) { Plugin.LogWarn("GetPrefab(" + name + ") error: " + ex.Message); lastFail = Time.time; return null; } } private static void Cache(ref Item cache, Item prefab, string name) { cache = prefab; TryEnsureRegistered(prefab, name); Plugin.LogInfo(name + " prefab cached: " + ((Object)((Component)prefab).gameObject).name); } private static Item TryGetFromSpawnablePrefabs(string name) { try { NetworkManager networkManager = InstanceFinder.NetworkManager; if ((Object)(object)networkManager == (Object)null) { return null; } PrefabObjects spawnablePrefabs = networkManager.SpawnablePrefabs; if ((Object)(object)spawnablePrefabs == (Object)null) { return null; } Type type = ((object)spawnablePrefabs).GetType(); MethodInfo method = type.GetMethod("GetObjectMatches", new Type[2] { typeof(bool), typeof(string) }); object obj = null; if (method != null) { obj = method.Invoke(spawnablePrefabs, new object[2] { false, name }); } else { method = type.GetMethod("GetObjectMatches", new Type[1] { typeof(string) }); if (method != null) { obj = method.Invoke(spawnablePrefabs, new object[1] { name }); } } if (obj is IEnumerable enumerable) { foreach (object item in enumerable) { GameObject val = (GameObject)((item is GameObject) ? item : null); if (val != null && (Object)(object)val != (Object)null) { Item component = val.GetComponent(); if ((Object)(object)component != (Object)null) { return component; } } } } return null; } catch { return null; } } private static void TryEnsureRegistered(Item prefab, string name) { try { NetworkManager networkManager = InstanceFinder.NetworkManager; if ((Object)(object)networkManager == (Object)null) { return; } PrefabObjects spawnablePrefabs = networkManager.SpawnablePrefabs; if ((Object)(object)spawnablePrefabs == (Object)null) { return; } Type type = ((object)spawnablePrefabs).GetType(); MethodInfo method = type.GetMethod("Contains", new Type[1] { typeof(GameObject) }); if (!(method != null) || !(bool)method.Invoke(spawnablePrefabs, new object[1] { ((Component)prefab).gameObject })) { MethodInfo method2 = type.GetMethod("Add", new Type[1] { typeof(GameObject) }); if (method2 != null) { method2.Invoke(spawnablePrefabs, new object[1] { ((Component)prefab).gameObject }); Plugin.LogInfo(name + " prefab registered to FishNet spawnables"); } } } catch (Exception ex) { Plugin.LogWarn("TryEnsureRegistered error: " + ex.Message); } } public static void HookSeagull(CreatureManager manager, Item prefab, Bait bait) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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_0074: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) try { Vector3 position = ((Component)bait).transform.position; position.y = WaterManager.WaterHeight + Random.Range(3f, 6f); Item val = Object.Instantiate(prefab, position, Quaternion.identity); val.SetAttachedRod(bait.FishingRod); bait.AddItemOnBait(val, true); val.RigidbodySync.ServerSetSyncedSimulator(((NetworkBehaviour)((Item)bait.FishingRod).Holder).Owner); ((NetworkBehaviour)manager).Spawn(((Component)val).gameObject, (NetworkConnection)null, default(Scene)); Creature creature = val.Creature; Bird val2 = (Bird)(object)((creature is Bird) ? creature : null); if ((Object)(object)val2 != (Object)null) { ModSeagulls.Add(val2); } Plugin.LogInfo("Seagull hooked! (bait at " + ((object)((Component)bait).transform.position/*cast due to .constrained prefix*/).ToString() + ")"); } catch (Exception ex) { Plugin.LogWarn("HookSeagull error: " + ex.Message); } } public static void ReleaseSeagullToSky(Bird bird) { //IL_0027: 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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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) try { if (!((Object)(object)bird == (Object)null) && ((Creature)bird)._hp.Value > 0) { if (((Component)bird).transform.position.y < WaterManager.WaterHeight + 0.5f) { Vector3 position = ((Component)bird).transform.position; position.y = WaterManager.WaterHeight + 0.5f; ((Component)bird).transform.position = position; } float num = Mathf.Max(((Component)bird).transform.position.y, WaterManager.WaterHeight) + Plugin.SeagullFlyHeight.Value; if (FlyHeigthSetter != null) { FlyHeigthSetter.Invoke(bird, new object[1] { num }); } else if (FlyHeigthBackingField != null) { FlyHeigthBackingField.SetValue(bird, num); } if ((Object)(object)BirdManager.Instance != (Object)null) { BirdManager.Instance.AddFlyingBird(bird); } ((Item)bird).RigidbodySync.Freeze(true, false); SprintingSeagulls.Add(bird); Plugin.LogInfo("Seagull escaped: sprinting up to " + num + "m"); } } catch (Exception ex) { Plugin.LogWarn("ReleaseSeagullToSky error: " + ex.Message); } } public static void ReleaseFromRod(Item item) { try { if (!((Object)(object)item == (Object)null)) { FishingRod attachedRod = item.AttachedRod; if (!((Object)(object)attachedRod == (Object)null) && !((Object)(object)attachedRod.Bait == (Object)null)) { item.SetAttachedRod((FishingRod)null); attachedRod.Bait.AddItemOnBait((Item)null, true); } } } catch (Exception ex) { Plugin.LogWarn("ReleaseFromRod error: " + ex.Message); } } public static void CleanupExplodedDynamite(Explosive ex) { try { ReleaseFromRod((Item)(object)ex); } catch (Exception ex2) { Plugin.LogWarn("CleanupExplodedDynamite error: " + ex2.Message); } } public static void HookDynamite(CreatureManager manager, Item prefab, Bait bait) { //IL_0007: 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_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) try { Item val = Object.Instantiate(prefab, ((Component)bait).transform.position, Quaternion.identity); Explosive val2 = (Explosive)(object)((val is Explosive) ? val : null); if ((Object)(object)val2 == (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); Plugin.LogWarn("Hooked prefab is not an Explosive; dynamite catch aborted"); return; } float num = Mathf.Max(1f, Plugin.DynamiteFuse.Value); if (ExplosiveActivatedDelayField != null) { ExplosiveActivatedDelayField.SetValue(val2, num); } val.SetAttachedRod(bait.FishingRod); bait.AddItemOnBait(val, true); val.RigidbodySync.ServerSetSyncedSimulator(((NetworkBehaviour)((Item)bait.FishingRod).Holder).Owner); ((NetworkBehaviour)manager).Spawn(((Component)val).gameObject, (NetworkConnection)null, default(Scene)); val2.ObserverActivate(InstanceFinder.TimeManager.Tick, false, false, (Player)null); Plugin.LogInfo("Lit dynamite hooked! (fuse " + num + "s)"); } catch (Exception ex) { Plugin.LogWarn("HookDynamite error: " + ex.Message); } } }