Decompiled source of IBGameplay v0.5.37
BepInEx/plugins/stasy-IBGameplay/IBGameplay.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Security.Cryptography; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using ExitGames.Client.Photon; using HarmonyLib; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using Photon.Pun; using Photon.Realtime; using Stasy.PeakHostUi; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.Rendering; using UnityEngine.SceneManagement; using UnityEngine.UI; using Zorro.Core; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyVersion("0.0.0.0")] namespace IBGameplay { internal sealed class BoundaryColliderHighlight { private const int Steps = 24; internal readonly BoxCollider Owner; private readonly GameObject visual; private readonly Mesh mesh; private readonly MeshRenderer renderer; private readonly Vector3[] vertices = (Vector3[])(object)new Vector3[625]; private readonly Vector2[] uv = (Vector2[])(object)new Vector2[625]; private readonly Color[] colors = (Color[])(object)new Color[625]; internal BoundaryColliderHighlight(BoxCollider owner, Material material) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown Owner = owner; visual = new GameObject("IBGameplay boundary highlight"); ((Object)visual).hideFlags = (HideFlags)61; visual.layer = 0; visual.transform.SetParent(((Component)owner).transform, false); mesh = new Mesh(); ((Object)mesh).name = "IBGameplay nearby boundary surface"; ((Object)mesh).hideFlags = (HideFlags)61; mesh.MarkDynamic(); visual.AddComponent<MeshFilter>().sharedMesh = mesh; renderer = visual.AddComponent<MeshRenderer>(); ((Renderer)renderer).sharedMaterial = material; ((Renderer)renderer).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)renderer).receiveShadows = false; ((Renderer)renderer).lightProbeUsage = (LightProbeUsage)0; ((Renderer)renderer).reflectionProbeUsage = (ReflectionProbeUsage)0; ((Renderer)renderer).enabled = false; int[] array = new int[3456]; int num = 0; for (int i = 0; i < 24; i++) { for (int j = 0; j < 24; j++) { int num2 = i * 25 + j; int num3 = num2 + 1; int num4 = num2 + 24 + 1; int num5 = num4 + 1; array[num++] = num2; array[num++] = num4; array[num++] = num3; array[num++] = num3; array[num++] = num4; array[num++] = num5; } } mesh.vertices = vertices; mesh.triangles = array; } internal void Update(Vector3 eye) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: 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_00da: 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_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: Unknown result type (might be due to invalid IL or missing references) //IL_0329: Unknown result type (might be due to invalid IL or missing references) //IL_032e: Unknown result type (might be due to invalid IL or missing references) //IL_0333: Unknown result type (might be due to invalid IL or missing references) //IL_0335: Unknown result type (might be due to invalid IL or missing references) //IL_0337: Unknown result type (might be due to invalid IL or missing references) //IL_0366: Unknown result type (might be due to invalid IL or missing references) //IL_036b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Owner == (Object)null || !((Collider)Owner).enabled || !((Component)Owner).gameObject.activeInHierarchy || Vector3.Distance(eye, ((Collider)Owner).ClosestPoint(eye)) >= 10f) { ((Renderer)renderer).enabled = false; return; } Transform transform = ((Component)Owner).transform; Vector3 lossyScale = transform.lossyScale; ((Vector3)(ref lossyScale))..ctor(Mathf.Abs(lossyScale.x), Mathf.Abs(lossyScale.y), Mathf.Abs(lossyScale.z)); if (lossyScale.x < 0.0001f || lossyScale.y < 0.0001f || lossyScale.z < 0.0001f) { ((Renderer)renderer).enabled = false; return; } Vector3 size = Owner.size; Vector3 center = Owner.center; Vector3 val = transform.InverseTransformPoint(eye); int num = BoundaryProximityRules.ThinAxis(size.x * lossyScale.x, size.y * lossyScale.y, size.z * lossyScale.z); int num2 = (num + 1) % 3; int num3 = (num + 2) % 3; float num4 = ((((Vector3)(ref val))[num] >= ((Vector3)(ref center))[num]) ? 1f : (-1f)); float num5 = ((Vector3)(ref center))[num] + num4 * (((Vector3)(ref size))[num] * 0.5f + 0.035f / ((Vector3)(ref lossyScale))[num]); float num6 = 10f; float num7 = Mathf.Max(((Vector3)(ref center))[num2] - ((Vector3)(ref size))[num2] * 0.5f, ((Vector3)(ref val))[num2] - num6 / ((Vector3)(ref lossyScale))[num2]); float num8 = Mathf.Min(((Vector3)(ref center))[num2] + ((Vector3)(ref size))[num2] * 0.5f, ((Vector3)(ref val))[num2] + num6 / ((Vector3)(ref lossyScale))[num2]); float num9 = Mathf.Max(((Vector3)(ref center))[num3] - ((Vector3)(ref size))[num3] * 0.5f, ((Vector3)(ref val))[num3] - num6 / ((Vector3)(ref lossyScale))[num3]); float num10 = Mathf.Min(((Vector3)(ref center))[num3] + ((Vector3)(ref size))[num3] * 0.5f, ((Vector3)(ref val))[num3] + num6 / ((Vector3)(ref lossyScale))[num3]); if (num7 >= num8 || num9 >= num10) { ((Renderer)renderer).enabled = false; return; } bool flag = false; for (int i = 0; i <= 24; i++) { for (int j = 0; j <= 24; j++) { int num11 = i * 25 + j; Vector3 val2 = center; ((Vector3)(ref val2))[num] = num5; ((Vector3)(ref val2))[num2] = Mathf.Lerp(num7, num8, (float)j / 24f); ((Vector3)(ref val2))[num3] = Mathf.Lerp(num9, num10, (float)i / 24f); vertices[num11] = val2; ref Vector2 reference = ref uv[num11]; reference = new Vector2(((Vector3)(ref val2))[num2] * ((Vector3)(ref lossyScale))[num2] / 1.5f, ((Vector3)(ref val2))[num3] * ((Vector3)(ref lossyScale))[num3] / 1.5f); float num12 = BoundaryProximityRules.Alpha(Vector3.Distance(eye, transform.TransformPoint(val2))); ref Color reference2 = ref colors[num11]; reference2 = new Color(1f, 0.32f, 0.035f, num12); flag = flag || num12 > 0f; } } mesh.vertices = vertices; mesh.uv = uv; mesh.colors = colors; mesh.RecalculateBounds(); ((Renderer)renderer).enabled = flag; } internal void Dispose() { if ((Object)(object)renderer != (Object)null) { ((Renderer)renderer).enabled = false; } if ((Object)(object)visual != (Object)null) { Object.Destroy((Object)(object)visual); } if ((Object)(object)mesh != (Object)null) { Object.Destroy((Object)(object)mesh); } } internal string Diagnostic(Camera camera) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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) float num = (((Object)(object)Owner == (Object)null) ? (-1f) : Vector3.Distance(((Component)camera).transform.position, ((Collider)Owner).ClosestPoint(((Component)camera).transform.position))); return "wall=" + (((Object)(object)Owner == (Object)null) ? "missing" : ((Object)Owner).name) + " distance=" + num.ToString("F2", CultureInfo.InvariantCulture) + " colliderLayer=" + (((Object)(object)Owner == (Object)null) ? (-1) : ((Component)Owner).gameObject.layer) + " visualLayer=" + (((Object)(object)visual == (Object)null) ? (-1) : visual.layer) + " cameraLayerVisible=" + ((Object)(object)visual != (Object)null && (camera.cullingMask & (1 << visual.layer)) != 0) + " enabled=" + ((Object)(object)renderer != (Object)null && ((Renderer)renderer).enabled) + " active=" + ((Object)(object)visual != (Object)null && visual.activeInHierarchy); } } internal static class BoundaryProximityRules { internal const float Distance = 10f; internal const float CellSize = 1.5f; internal const int VisualLayer = 0; internal static float Alpha(float distance) { if (float.IsNaN(distance) || float.IsInfinity(distance) || distance >= 10f) { return 0f; } float num = Math.Max(0f, Math.Min(1f, (10f - distance) / 8f)); return 0.7f * num * num * (3f - 2f * num); } internal static int ThinAxis(float x, float y, float z) { if (!(x <= y) || !(x <= z)) { if (!(y <= z)) { return 2; } return 1; } return 0; } internal static bool Wall(string parent, string name) { if (string.Equals(parent, "EdgeWalls", StringComparison.Ordinal)) { return string.Equals(name, "EdgeWall", StringComparison.Ordinal); } return false; } } internal sealed class BoundarySurfacePalette { internal readonly MeshRenderer Owner; internal readonly int Slot; private readonly MaterialPropertyBlock original = new MaterialPropertyBlock(); private readonly MaterialPropertyBlock work = new MaterialPropertyBlock(); private readonly bool hadIndexedBlock; internal BoundarySurfacePalette(MeshRenderer owner, int slot) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown Owner = owner; Slot = slot; ((Renderer)owner).GetPropertyBlock(original, slot); hadIndexedBlock = !original.isEmpty; } internal void Apply(Color top, Color mid, Color bottom) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_005d: 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) if (!((Object)(object)Owner == (Object)null)) { if (hadIndexedBlock) { ((Renderer)Owner).GetPropertyBlock(work, Slot); } else { ((Renderer)Owner).GetPropertyBlock(work); } work.SetColor("SkyTopColor", top); work.SetColor("SkyMidColor", mid); work.SetColor("SkyBottomColor", bottom); ((Renderer)Owner).SetPropertyBlock(work, Slot); } } internal void Restore() { if ((Object)(object)Owner != (Object)null && Slot < ((Renderer)Owner).sharedMaterials.Length) { ((Renderer)Owner).SetPropertyBlock(hadIndexedBlock ? original : null, Slot); } } } internal static class CalderaBoundaryRules { internal static bool Active(bool running, bool loading, bool mapReady, bool calderaSegment, bool volcanoBiome) { if (running && !loading && mapReady && calderaSegment) { return volcanoBiome; } return false; } internal static bool Surface(string origin, string objectName, string shader) { if (string.Equals(origin, "Caldera", StringComparison.OrdinalIgnoreCase) && shader == "FogWall") { if (!string.Equals(objectName, "Fogwall_Prev", StringComparison.OrdinalIgnoreCase)) { return string.Equals(objectName, "Fogwall_Next", StringComparison.OrdinalIgnoreCase); } return true; } return false; } } internal sealed class CampArrivalRules { private readonly HashSet<int> reached = new HashSet<int>(); private int segment = -1; internal void Reset() { reached.Clear(); segment = -1; } internal void UpdateSegment(int current) { if (segment != current) { reached.Clear(); segment = current; } } internal void Reach(int actor) { if (actor > 0) { reached.Add(actor); } } internal bool Protected(int actor) { return reached.Contains(actor); } } internal static class CampfireGuard { [HarmonyPatch] private static class Interaction { private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(Campfire), "Interact", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(Campfire), "Interact_CastFinished", (Type[])null, (Type[])null); } [HarmonyPriority(800)] [HarmonyPrefix] private static bool Prefix(Campfire __instance, Character __0) { return Allowed(__instance, __0); } } [HarmonyPatch] private static class Availability { private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(Campfire), "IsInteractible", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(Campfire), "IsConstantlyInteractable", (Type[])null, (Type[])null); } [HarmonyPriority(0)] [HarmonyPostfix] private static void Postfix(Campfire __instance, Character __0, ref bool __result) { if (!Allowed(__instance, __0)) { __result = false; } } } [HarmonyPatch(typeof(Campfire), "GetInteractionText")] private static class Prompt { [HarmonyPostfix] private static void Postfix(Campfire __instance, ref string __result) { if (Restricted && PhotonNetwork.InRoom && !__instance.Lit && !PhotonNetwork.IsMasterClient) { __result = "ЗАЖИГАЕТ ТОЛЬКО ХОСТ"; } } } [HarmonyPatch(typeof(PhotonNetwork), "ExecuteRpc", new Type[] { typeof(Hashtable), typeof(Player) })] private static class NetworkLight { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(Hashtable __0, Player __1) { if (!Restricted || !PhotonNetwork.InRoom) { return true; } IList<string> names = (((Object)(object)PhotonNetwork.PhotonServerSettings == (Object)null) ? null : PhotonNetwork.PhotonServerSettings.RpcList); string text = CampfireRules.RpcName((IDictionary<object, object>)__0, names); if (text != "Light_Rpc") { return true; } if (__0 == null || !((Dictionary<object, object>)(object)__0).TryGetValue((object)(byte)0, out object value) || !(value is int)) { return true; } PhotonView photonView = PhotonNetwork.GetPhotonView((int)value); bool campfire = (Object)(object)photonView != (Object)null && (Object)(object)((Component)photonView).GetComponent<Campfire>() != (Object)null; return CampfireRules.AllowRpc(restricted: true, inRoom: true, campfire, text, (__1 != null) ? __1.ActorNumber : 0, Master); } } private static bool Restricted { get { if ((Object)(object)Plugin.Instance != (Object)null) { return Plugin.Instance.HostOnlyCampfires; } return false; } } private static int Master { get { if (!PhotonNetwork.InRoom || PhotonNetwork.MasterClient == null) { return 0; } return PhotonNetwork.MasterClient.ActorNumber; } } private static bool Allowed(Campfire fire, Character character) { return CampfireRules.CanInteract(Restricted, PhotonNetwork.InRoom, fire.Lit, Plugin.Actor(character), Master); } } internal static class CampfireRules { internal static bool IsHost(int actor, int master) { if (actor > 0 && master > 0) { return actor == master; } return false; } internal static bool CanInteract(bool restricted, bool inRoom, bool lit, int actor, int master) { if (restricted && inRoom && !lit) { return IsHost(actor, master); } return true; } internal static bool AllowRpc(bool restricted, bool inRoom, bool campfire, string method, int sender, int master) { if (restricted && inRoom && campfire && !(method != "Light_Rpc")) { return IsHost(sender, master); } return true; } internal static string RpcName(IDictionary<object, object> data, IList<string> names) { if (data == null) { return null; } if (data.TryGetValue((byte)5, out var value)) { if (!(value is byte) || names == null) { return null; } int num = (byte)value; if (num >= names.Count) { return null; } return names[num]; } if (!data.TryGetValue((byte)3, out value)) { return null; } return value as string; } } internal sealed class ChainAdapter { private static ChainAdapter current; private BaseUnityPlugin engine; private Type type; private MethodInfo stableKey; private FieldInfo enabled; private FieldInfo groupSize; private bool wasActive; private readonly HashSet<int> released = new HashSet<int>(); private readonly Harmony runtime = new Harmony("stasy.ibgameplay.chain"); private static bool Active { get { if ((Object)(object)Plugin.Instance != (Object)null && PhotonNetwork.InRoom && Plugin.Instance.State.Mode == Mode.Chains) { return Plugin.Instance.State.Armed; } return false; } } internal void TakeControl(Assembly assembly, Harmony guards) { //IL_0317: Unknown result type (might be due to invalid IL or missing references) //IL_0415: Unknown result type (might be due to invalid IL or missing references) //IL_0428: Unknown result type (might be due to invalid IL or missing references) //IL_0435: Expected O, but got Unknown //IL_0435: Expected O, but got Unknown current = this; engine = Chainloader.PluginInfos["patchnote.chainbound"].Instance; this.type = assembly.GetType("Chainbound.ChainboundPlugin", throwOnError: true); enabled = Field("_roomEnabled"); groupSize = Field("_roomMaxGroupSize"); stableKey = Method("GetUniquePlayerStableKey"); string[] array = new string[3] { "ClearChainLines", "ClearProxyChain", "ClearApiGroups" }; foreach (string name in array) { Method(name); } guards.Patch((MethodBase)Method("RefreshRoomSettings"), (HarmonyMethod)null, Hook("RoomSettings"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); guards.Patch((MethodBase)Method("ShouldRunHostEnabledGameplay"), Hook("Gameplay"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); guards.Patch((MethodBase)Method("get_ApiEnabled"), Hook("Gameplay"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); guards.Patch((MethodBase)Method("GetEffectiveChainOrder"), Hook("Order"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); guards.Patch((MethodBase)Method("GetPublishedChainOrder"), Hook("Order"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); guards.Patch((MethodBase)Method("IsPlayerOptedIntoChain"), (HarmonyMethod)null, Hook("Participant"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); guards.Patch((MethodBase)Method("CanLinkConnect"), (HarmonyMethod)null, Hook("LinkOnlySelectedLivingPair"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); guards.Patch((MethodBase)Method("HasInstalledCompatibleMod"), Hook("Compatible"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); guards.Patch((MethodBase)Method("DrawStatusOverlay"), Hook("ShowOverlay"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Type nestedType = this.type.GetNestedType("<>c", BindingFlags.NonPublic); MethodInfo methodInfo = ((nestedType == null) ? null : nestedType.GetMethod("<CollectActiveChainMembers>b__257_0", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)); if (methodInfo == null) { throw new MissingMethodException("Chainbound member collection predicate"); } guards.Patch((MethodBase)methodInfo, (HarmonyMethod)null, Hook("Participant"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); string[] array2 = new string[4] { "MaintainHostChainOrderIfNeeded", "ShuffleChainOrder", "UpdateHostShuffleInput", "HandleCampfireSegmentAdvanced" }; foreach (string name2 in array2) { guards.Patch((MethodBase)Method(name2), Hook("SuppressAutoGroups"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } string[] array3 = new string[2] { "CharacterMovementCheckFallDamagePatch", "CharacterClimbingCheckFallDamagePatch" }; foreach (string text in array3) { Type nestedType2 = this.type.GetNestedType(text, BindingFlags.NonPublic); if (nestedType2 == null) { throw new MissingMemberException(this.type.FullName, text); } guards.Patch((MethodBase)nestedType2.GetMethod("Prefix", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic), (HarmonyMethod)null, (HarmonyMethod)null, Hook("ReplaceFallDamageCall"), (HarmonyMethod)null, (HarmonyMethod)null); } new Harmony("patchnote.chainbound").UnpatchSelf(); Type[] types = assembly.GetTypes(); foreach (Type type in types) { if (type.GetCustomAttributes(typeof(HarmonyPatch), inherit: false).Length == 0) { continue; } if (type.Name == "CharacterAfflictionsAddStatusPatch") { MethodInfo methodInfo2 = AccessTools.Method(typeof(CharacterAfflictions), "AddStatus", new Type[7] { typeof(STATUSTYPE), typeof(float), typeof(bool), typeof(bool), typeof(bool), typeof(bool), typeof(bool) }, (Type[])null); if (methodInfo2 == null) { throw new MissingMethodException("CharacterAfflictions.AddStatus current signature"); } runtime.Patch((MethodBase)methodInfo2, new HarmonyMethod(AccessTools.Method(type, "Prefix", (Type[])null, (Type[])null)), new HarmonyMethod(AccessTools.Method(type, "Postfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } else { runtime.CreateClassProcessor(type).Patch(); } } Refresh(); Clear(); Plugin.Instance.LoggerForAdapter("Chainbound original rules bound to current PEAK API."); } private FieldInfo Field(string name) { FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.NonPublic); if (field == null) { throw new MissingFieldException(type.FullName, name); } return field; } private MethodInfo Method(string name) { MethodInfo method = type.GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (method == null) { throw new MissingMethodException(type.FullName, name); } return method; } private static HarmonyMethod Hook(string name) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown return new HarmonyMethod(typeof(ChainAdapter), name, (Type[])null); } private static bool Gameplay(ref bool __result) { __result = Active; return false; } private static bool SuppressAutoGroups() { return false; } private static bool ShowOverlay(string __0) { return __0 != "Chainbound Lobby Check"; } private static bool Compatible(Player __0, ref bool __1, ref bool __result) { if (!Active) { return true; } __1 = false; __result = Plugin.Instance.PeerReady(__0); return false; } private static void Participant(Player __0, ref bool __result) { if (current != null) { current.ReleaseDeadPairs(); } __result = __result && Active && current != null && __0 != null && ChainSelection.IsLinked(Plugin.Instance.State, __0.ActorNumber, current.released); } private static void LinkOnlySelectedLivingPair(Character __0, Character __1, ref bool __result) { if (current != null) { current.ReleaseDeadPairs(); } __result = __result && Active && current != null && (Object)(object)__0 != (Object)null && (Object)(object)__1 != (Object)null && ChainSelection.CanConnect(Plugin.Instance.State, Plugin.Actor(__0), Plugin.Actor(__1), current.released); } private void ReleaseDeadPairs() { if (!Active) { return; } Pair[] pairs = Plugin.Instance.State.Pairs; foreach (Pair pair in pairs) { if (!released.Contains(pair.A)) { Character val = Plugin.CharacterFor(pair.A); Character val2 = Plugin.CharacterFor(pair.B); if (((Object)(object)val != (Object)null && (Object)(object)val.data != (Object)null && val.data.dead) || ((Object)(object)val2 != (Object)null && (Object)(object)val2.data != (Object)null && val2.data.dead)) { released.Add(pair.A); Plugin.Instance.LoggerForAdapter("Chained pair released after death: " + pair.A + "/" + pair.B + ". Other pairs remain linked."); } } } } private static void RoomSettings() { if (current != null) { current.Refresh(); } } private static IEnumerable<CodeInstruction> ReplaceFallDamageCall(IEnumerable<CodeInstruction> instructions) { int replaced = 0; foreach (CodeInstruction instruction in instructions) { MethodInfo call = instruction.operand as MethodInfo; if (call != null && call.DeclaringType.FullName == "Chainbound.ChainboundPlugin" && call.Name == "ApplySpeedBasedFallDamage") { instruction.opcode = OpCodes.Call; instruction.operand = typeof(ChainAdapter).GetMethod("ApplyCurrentFallDamage", BindingFlags.Static | BindingFlags.NonPublic); replaced++; } yield return instruction; } if (replaced != 1) { throw new InvalidOperationException("Expected exactly one Chainbound legacy fall-damage call."); } } private static void ApplyCurrentFallDamage(object engine, Character character, float extraSpeed, string source) { if (!Active || current == null || (Object)(object)character == (Object)null || !character.IsLocal || (Object)(object)character.data == (Object)null || character.refs == null || (Object)(object)character.refs.afflictions == (Object)null) { return; } object[] array = new object[2] { character, 0f }; bool flag = (bool)current.Method("TryGetRecentCenterDownSpeed").Invoke(engine, array); float num = Mathf.Max(extraSpeed, flag ? ((float)array[1]) : Mathf.Max(0f, 0f - character.data.avarageVelocity.y)); float num2 = (float)current.Field("_roomFallDamageMinSpeed").GetValue(engine); float num3 = (float)current.Field("_roomFallDamageMaxSpeed").GetValue(engine); float num4 = (float)current.Field("_roomFallDamageMultiplier").GetValue(engine); float num5 = Mathf.Clamp01(Mathf.Pow(Mathf.InverseLerp(Mathf.Min(num2, num3 - 0.1f), num3, num), 1.5f) * num4); if (!(num5 < 0.025f) && !(bool)current.Method("ShouldSuppressProtectedLandingDamage").Invoke(engine, new object[4] { character, num5, num, source })) { if (num5 > 0.3f) { character.refs.view.RPC("RPCA_Fall", (RpcTarget)0, new object[1] { num5 * 5f }); } character.refs.afflictions.AddStatus((STATUSTYPE)0, num5 * Ascents.fallDamageMultiplier / Mathf.Max(0.001f, Ascents.etcDamageMultiplier), false, true, true, false, false); } } private static bool Order(ref List<string> __result) { __result = new List<string>(); if (!Active || current == null) { return false; } current.ReleaseDeadPairs(); HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal); Dictionary<int, string> dictionary = new Dictionary<int, string>(); foreach (Player item in from p in PhotonNetwork.PlayerList where ChainSelection.IsLinked(Plugin.Instance.State, p.ActorNumber, current.released) orderby p.ActorNumber select p) { dictionary[item.ActorNumber] = (string)current.stableKey.Invoke(null, new object[2] { item, hashSet }); } __result = ChainSelection.MakeOrder(Plugin.Instance.State, dictionary); return false; } internal void Refresh() { if (!((Object)(object)engine == (Object)null) && !(enabled == null)) { bool active = Active; ReleaseDeadPairs(); enabled.SetValue(engine, active); groupSize.SetValue(engine, 2); Field("_roomHasChainboundHost").SetValue(engine, PhotonNetwork.InRoom); if (!active && wasActive) { Clear(); } wasActive = active; } } internal void Clear() { released.Clear(); if (!((Object)(object)engine == (Object)null) && !(type == null)) { enabled.SetValue(engine, false); string[] array = new string[3] { "ClearChainLines", "ClearProxyChain", "ClearApiGroups" }; foreach (string name in array) { Method(name).Invoke(engine, null); } string[] array2 = new string[2] { "_chainFallProtectedUntil", "_chainClimbDamageProtectedUntil" }; foreach (string name2 in array2) { Field(name2).SetValue(engine, 0f); } wasActive = false; } } internal void Dispose() { Clear(); runtime.UnpatchSelf(); } } internal static class ChainSelection { internal static bool IsLinked(ScenarioState state, int actor, ISet<int> released) { if (state.Mode == Mode.Chains && state.Armed) { return state.Pairs.Any((Pair p) => p.Contains(actor) && !released.Contains(p.A)); } return false; } internal static bool CanConnect(ScenarioState state, int a, int b, ISet<int> released) { if (a != b && IsLinked(state, a, released)) { return state.Pairs.Any((Pair p) => p.Contains(a) && p.Contains(b)); } return false; } internal static List<string> MakeOrder(ScenarioState state, IDictionary<int, string> keys) { List<string> list = new List<string>(); if (state.Mode != Mode.Chains || !state.Armed) { return list; } Pair[] pairs = state.Pairs; foreach (Pair pair in pairs) { list.Add(keys.ContainsKey(pair.A) ? keys[pair.A] : ("ibgameplay.missing." + pair.A)); list.Add(keys.ContainsKey(pair.B) ? keys[pair.B] : ("ibgameplay.missing." + pair.B)); } return list; } } internal static class ConfigJson { private static JsonSerializerSettings Settings() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown JsonSerializerSettings val = new JsonSerializerSettings(); val.ContractResolver = (IContractResolver)new DefaultContractResolver(); val.ConstructorHandling = (ConstructorHandling)1; val.TypeNameHandling = (TypeNameHandling)0; val.MissingMemberHandling = (MissingMemberHandling)1; val.CheckAdditionalContent = true; val.MaxDepth = 32; val.Culture = CultureInfo.InvariantCulture; val.DateParseHandling = (DateParseHandling)0; return val; } internal static T Read<T>(string json) { return JsonConvert.DeserializeObject<T>(json, Settings()); } internal static string Write<T>(T value) { return JsonConvert.SerializeObject((object)value, (Formatting)1, Settings()); } } internal static class EggCompatibility { [HarmonyPatch(typeof(Item), "Awake")] private static class Flags { [HarmonyPostfix] [HarmonyPriority(800)] private static void Postfix(Item __instance) { if (Active && Plugin.IsEgg(__instance)) { Plugin.Instance.PrepareEgg(__instance); } } } private static MethodInfo serialize; internal static bool Active { get { if ((Object)(object)Plugin.Instance != (Object)null) { return Plugin.Instance.State.Mode == Mode.Egg; } return false; } } internal static bool ProtectGroundEgg(Item __0) { if (Active) { return !Plugin.IsEgg(__0); } return true; } internal static bool OriginalEggHud() { return !Active; } internal static bool WorldMarker(Component __instance) { return !Active; } internal static bool GrantHands(Player player, Item prefab, ItemInstanceData data, out ItemSlot slot, bool egg = true) { //IL_00f9: Unknown result type (might be due to invalid IL or missing references) slot = null; if (!PhotonNetwork.IsMasterClient || (Object)(object)player == (Object)null || (Object)(object)prefab == (Object)null || data == null || player.tempFullSlot == null || !player.tempFullSlot.IsEmpty()) { return false; } if (egg) { Plugin.Instance.PrepareEgg(prefab); } if (serialize == null) { serialize = typeof(InventorySyncData).GetInterfaces().Single((Type t) => t.FullName == "Zorro.Core.Serizalization.IBinarySerializable").GetMethods(BindingFlags.Static | BindingFlags.Public) .Single((MethodInfo m) => m.Name == "ToManagedArray") .MakeGenericMethod(typeof(InventorySyncData)); } player.tempFullSlot.SetItem(prefab, data); try { byte[] array = (byte[])serialize.Invoke(null, new object[1] { (object)new InventorySyncData(player.itemSlots, player.backpackSlot, player.tempFullSlot) }); ((MonoBehaviourPun)player).photonView.RPC("SyncInventoryRPC", (RpcTarget)1, new object[2] { array, false }); slot = player.tempFullSlot; } catch { player.tempFullSlot.SetItem((Item)null, (ItemInstanceData)null); throw; } return true; } } internal static class EggSlotPresence { internal static bool Contains(ItemSlot slot, string guid) { if (slot != null && !slot.IsEmpty() && !string.IsNullOrEmpty(guid)) { return Plugin.GuidOf(slot.data) == guid; } return false; } } internal sealed class EggWorldHud { private sealed class Entry { internal TextMeshProUGUI Marker; internal TextMeshProUGUI Heading; internal TextMeshProUGUI Names; internal Image Accent; internal RectTransform Card; internal int Frame; } private GameObject root; private RectTransform canvasRect; private TextMeshProUGUI source; private readonly Dictionary<string, Entry> entries = new Dictionary<string, Entry>(); private int frame; internal bool Begin(bool active) { //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Expected O, but got Unknown //IL_00dd: Unknown result type (might be due to invalid IL or missing references) if (!active) { Clear(); return false; } if ((Object)(object)root == (Object)null) { Clear(); AscentUI val = Object.FindFirstObjectByType<AscentUI>(); if ((Object)(object)val == (Object)null || (Object)(object)val.text == (Object)null || (Object)(object)((TMP_Text)val.text).font == (Object)null) { return false; } source = val.text; root = new GameObject("IBGameplayEggWorldHud", new Type[3] { typeof(RectTransform), typeof(Canvas), typeof(CanvasScaler) }); Canvas component = root.GetComponent<Canvas>(); component.renderMode = (RenderMode)0; component.sortingOrder = 100; CanvasScaler component2 = root.GetComponent<CanvasScaler>(); component2.uiScaleMode = (ScaleMode)1; component2.referenceResolution = new Vector2(1920f, 1080f); component2.matchWidthOrHeight = 0.5f; canvasRect = root.GetComponent<RectTransform>(); } frame++; foreach (Entry value in entries.Values) { ((Component)value.Marker).gameObject.SetActive(false); ((Component)value.Card).gameObject.SetActive(false); } return true; } internal void Marker(string guid, int pair, Color color, Vector2 screen) { //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)root == (Object)null) && !string.IsNullOrEmpty(guid)) { if (!entries.TryGetValue(guid, out var value)) { value = new Entry(); value.Marker = TextAt("EggMarker", root.transform, new Vector2(180f, 60f), 22f); value.Card = RectAt("EggPairCard", root.transform, new Vector2(400f, 92f)); Image val = ((Component)value.Card).gameObject.AddComponent<Image>(); ((Graphic)val).color = new Color(0.12f, 0.22f, 0.23f, 0.38f); ((Graphic)val).raycastTarget = false; RectTransform val2 = RectAt("TeamAccent", (Transform)(object)value.Card, new Vector2(4f, 72f)); val2.anchoredPosition = new Vector2(-190f, 0f); value.Accent = ((Component)val2).gameObject.AddComponent<Image>(); ((Graphic)value.Accent).raycastTarget = false; value.Heading = TextAt("EggPairTitle", (Transform)(object)value.Card, new Vector2(362f, 32f), 24f); ((TMP_Text)value.Heading).rectTransform.anchoredPosition = new Vector2(4f, 22f); ((TMP_Text)value.Heading).enableAutoSizing = true; ((TMP_Text)value.Heading).fontSizeMin = 18f; ((TMP_Text)value.Heading).fontSizeMax = 24f; value.Names = TextAt("EggPairNames", (Transform)(object)value.Card, new Vector2(362f, 44f), 20f); ((TMP_Text)value.Names).rectTransform.anchoredPosition = new Vector2(4f, -15f); ((TMP_Text)value.Names).enableAutoSizing = true; ((TMP_Text)value.Names).fontSizeMin = 16f; ((TMP_Text)value.Names).fontSizeMax = 20f; ((Component)value.Card).gameObject.SetActive(false); entries.Add(guid, value); } value.Frame = frame; ((TMP_Text)value.Marker).text = "●\nЯЙЦО · " + (pair + 1); ((Graphic)value.Marker).color = color; ((TMP_Text)value.Marker).rectTransform.anchoredPosition = Local(screen, new Vector2(98f, 110f)); ((Component)value.Marker).gameObject.SetActive(true); } } internal void Popup(string guid, string title, string names, Color color, Vector2 screen) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)root == (Object)null) && entries.TryGetValue(guid, out var value)) { ((TMP_Text)value.Heading).text = title; ((Graphic)value.Heading).color = color; ((TMP_Text)value.Names).text = names; ((Graphic)value.Names).color = new Color(0.96f, 0.92f, 0.78f, 1f); ((Graphic)value.Accent).color = new Color(color.r, color.g, color.b, 0.7f); Vector2 anchoredPosition = Local(screen, new Vector2(208f, 54f)); anchoredPosition.y += 46f; Rect rect = canvasRect.rect; float num = Mathf.Max(0f, ((Rect)(ref rect)).height * 0.5f - 54f); anchoredPosition.y = Mathf.Clamp(anchoredPosition.y, 0f - num, num); value.Card.anchoredPosition = anchoredPosition; ((Component)value.Card).gameObject.SetActive(true); } } private Vector2 Local(Vector2 screen, Vector2 margin) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) Vector2 val = default(Vector2); RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRect, screen, (Camera)null, ref val); Rect rect = canvasRect.rect; float num = Mathf.Max(0f, ((Rect)(ref rect)).width * 0.5f - margin.x); Rect rect2 = canvasRect.rect; Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(num, Mathf.Max(0f, ((Rect)(ref rect2)).height * 0.5f - margin.y)); return new Vector2(Mathf.Clamp(val.x, 0f - val2.x, val2.x), Mathf.Clamp(val.y, 0f - val2.y, val2.y)); } private static RectTransform RectAt(string name, Transform parent, Vector2 size) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) }); val.transform.SetParent(parent, false); RectTransform component = val.GetComponent<RectTransform>(); Vector2 val2 = (component.pivot = new Vector2(0.5f, 0.5f)); Vector2 anchorMin = (component.anchorMax = val2); component.anchorMin = anchorMin; component.sizeDelta = size; return component; } private TextMeshProUGUI TextAt(string name, Transform parent, Vector2 size, float fontSize) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) RectTransform val = RectAt(name, parent, size); TextMeshProUGUI val2 = ((Component)val).gameObject.AddComponent<TextMeshProUGUI>(); ((TMP_Text)val2).font = ((TMP_Text)source).font; ((TMP_Text)val2).fontSharedMaterial = ((TMP_Text)source).fontSharedMaterial; ((TMP_Text)val2).fontStyle = ((TMP_Text)source).fontStyle; ((TMP_Text)val2).fontSize = fontSize; ((TMP_Text)val2).alignment = (TextAlignmentOptions)514; ((Graphic)val2).raycastTarget = false; ((TMP_Text)val2).richText = false; ((TMP_Text)val2).textWrappingMode = (TextWrappingModes)0; ((TMP_Text)val2).overflowMode = (TextOverflowModes)1; return val2; } internal void End() { string[] array = (from p in entries where p.Value.Frame != frame select p.Key).ToArray(); foreach (string key in array) { Entry entry = entries[key]; Object.Destroy((Object)(object)((Component)entry.Marker).gameObject); Object.Destroy((Object)(object)((Component)entry.Card).gameObject); entries.Remove(key); } } internal void Clear() { if ((Object)(object)root != (Object)null) { Object.Destroy((Object)(object)root); } root = null; canvasRect = null; source = null; entries.Clear(); frame = 0; } } internal sealed class Engines { internal Assembly Egg; internal Assembly Coop; internal Assembly Chain; internal readonly GhostAdapter Ghost = new GhostAdapter(); internal readonly PitchBlackAdapter PitchBlack = new PitchBlackAdapter(); private BaseUnityPlugin coopPlugin; private readonly Harmony eggHarmony = new Harmony("stasy.ibgameplay.egg"); private readonly Harmony piggyHarmony = new Harmony("stasy.ibgameplay.piggyback"); private readonly ChainAdapter chain = new ChainAdapter(); private readonly List<Character[]> carried = new List<Character[]>(); private readonly Dictionary<ItemUIData, bool[]> itemFlags = new Dictionary<ItemUIData, bool[]>(); private static readonly string[] Modules = new string[11] { "ShareAlive", "ShareDeath", "ItemFix", "ShareInventory", "SeparateRole", "Rolechanger", "Latejoin", "Piggyback", "OnlyEven", "ShareStamina", "Freepass" }; private bool coopRunning; private Type eggTimerType; private PropertyInfo eggRemaining; internal void TakeControl(Harmony guards, BaseUnityPlugin owner) { //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Unknown result type (might be due to invalid IL or missing references) //IL_02cd: Expected O, but got Unknown //IL_030a: Unknown result type (might be due to invalid IL or missing references) //IL_0318: Expected O, but got Unknown //IL_0442: Unknown result type (might be due to invalid IL or missing references) //IL_044f: Expected O, but got Unknown //IL_04af: Unknown result type (might be due to invalid IL or missing references) //IL_04bd: Expected O, but got Unknown PitchBlack.TakeControl(guards); Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "IBGameplay.Bootstrap"); if (assembly == null || !(bool)assembly.GetType("IBGameplayStartup.Patcher", throwOnError: true).GetProperty("Ready").GetValue(null, null)) { throw new InvalidOperationException((assembly == null) ? "IBGameplay startup helper missing. Install the complete package, including BepInEx/patchers." : "IBGameplay startup helper loaded but did not activate. Check the controller DLL location and startup log."); } Egg = ((object)Chainloader.PluginInfos["sapphire009.watchegg"].Instance).GetType().Assembly; coopPlugin = Chainloader.PluginInfos["com.peak.coopmod"].Instance; Coop = ((object)coopPlugin).GetType().Assembly; Chain = ((object)Chainloader.PluginInfos["patchnote.chainbound"].Instance).GetType().Assembly; new Harmony("sapphire009.watchegg").UnpatchSelf(); new Harmony("Sapphire009.StaminaFull").UnpatchSelf(); string[] array = new string[3] { "sapphire009.watchegg", "Sapphire009.StaminaFull", "com.peak.coopmod" }; foreach (string key in array) { ((Behaviour)Chainloader.PluginInfos[key].Instance).enabled = false; } string[] modules = Modules; foreach (string type in modules) { Call(Coop, type, "Shutdown"); } chain.TakeControl(Chain, guards); PinnedDependencies.Verify(Egg, "14AE4F3AF4C8FE8C34F95A87F19D07904CC1E8406DD1A604072667BEE0CD2852"); PinnedDependencies.Verify(Coop, "02D0CFDE61FCD6C9D91DC66A8FBFF7ECB55B770EE2ABF9F38D5A79C873843C47"); PinnedDependencies.Verify(Chain, "793C8933E329D856121F3F689EB6E8A9C0FF06728D012E3183EEF89EC61779D4"); Ghost.TakeControl(guards); eggTimerType = Egg.GetType("Sapphire009.WatchEgg.Timer", throwOnError: true); eggRemaining = AccessTools.Property(eggTimerType, "RemainingTime"); if (eggRemaining == null || eggRemaining.PropertyType != typeof(float) || !eggRemaining.CanRead) { throw new MissingMemberException("WatchEgg timer RemainingTime"); } string[] array2 = new string[2] { "TimerUI", "CountUI" }; foreach (string text in array2) { guards.Patch((MethodBase)MethodLookup.Require(Egg.GetType("Sapphire009.WatchEgg." + text, throwOnError: true), "OnGUI", 0, isStatic: false), new HarmonyMethod(typeof(EggCompatibility), "OriginalEggHud", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } guards.Patch((MethodBase)MethodLookup.Require(Egg.GetType("Sapphire009.WatchEgg.BrighteningEgg", throwOnError: true), "OnGUI", 0, isStatic: false), new HarmonyMethod(typeof(EggCompatibility), "WorldMarker", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Require(Coop, "Rolechanger", "ApplyCarriedState", 2); Require(Coop, "Rolechanger", "ClearCarriedState", 2); string[] modules2 = Modules; foreach (string type2 in modules2) { Require(Coop, type2, "Shutdown", 0); } string[] array3 = new string[7] { "Freepass", "SeparateRole", "ShareStamina", "ShareInventory", "ItemFix", "ShareDeath", "ShareAlive" }; foreach (string type3 in array3) { Require(Coop, type3, "Initialize", 1); } Type type4 = Egg.GetType("StaminaFull", throwOnError: true); guards.Patch((MethodBase)type4.GetMethod("CanApplyProtection", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(Character) }, null), (HarmonyMethod)null, new HarmonyMethod(typeof(Guards), "Protection", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); string[] array4 = new string[2] { "EnsureTimedDespawn", "TryMarkSpawnedItem" }; foreach (string text2 in array4) { guards.Patch((MethodBase)Require(Egg, "Sapphire009.WatchEgg.NoEat", text2, (!(text2 == "EnsureTimedDespawn")) ? 1 : 2), new HarmonyMethod(typeof(EggCompatibility), "ProtectGroundEgg", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } internal void StartEgg() { //IL_02e5: Unknown result type (might be due to invalid IL or missing references) //IL_02f3: Expected O, but got Unknown Item item = default(Item); if (ItemDatabase.TryGetItem("NestEgg", ref item)) { RememberFlags(item); } string[] source = new string[12] { "StaminaFull", "Sapphire009.WatchEgg.AutoDrop", "Sapphire009.WatchEgg.NoInventory", "Sapphire009.WatchEgg.Timer", "Sapphire009.WatchEgg.TimerSound", "Sapphire009.WatchEgg.TimerUI", "Sapphire009.WatchEgg.BrighteningEgg", "Sapphire009.WatchEgg.NoBody", "Sapphire009.WatchEgg.NoEat", "Sapphire009.WatchEgg.Magma", "Sapphire009.WatchEgg.MagmaLavaHitPlayerPatch", "Sapphire009.WatchEgg.MagmaStaminaFullProtectionPatch" }; Type[] types = Egg.GetTypes(); foreach (Type type in types) { Func<string, bool> predicate = (string root) => type.FullName == root || type.FullName.StartsWith(root + "+", StringComparison.Ordinal); if (!source.Any(predicate) || type.FullName == "Sapphire009.WatchEgg.NoInventory+EquipSlotPatch" || type.FullName == "Sapphire009.WatchEgg.NoInventory+SyncInventoryPatch" || type.FullName == "Sapphire009.WatchEgg.NoInventory+PickupAcceptedPatch") { continue; } if (type.FullName == "StaminaFull+CharacterAfflictionsAddStatusPatch" || type.FullName == "StaminaFull+CharacterAfflictionsAddThornPositionPatch" || type.FullName == "StaminaFull+CharacterAfflictionsAddThornIndexPatch") { Type[] types2 = (type.FullName.EndsWith("AddStatusPatch", StringComparison.Ordinal) ? new Type[7] { typeof(STATUSTYPE), typeof(float), typeof(bool), typeof(bool), typeof(bool), typeof(bool), typeof(bool) } : (type.FullName.EndsWith("PositionPatch", StringComparison.Ordinal) ? new Type[2] { typeof(Vector3), typeof(int) } : new Type[3] { typeof(int), typeof(ushort), typeof(bool) })); string text = (type.FullName.EndsWith("AddStatusPatch", StringComparison.Ordinal) ? "AddStatus" : "AddThorn"); MethodInfo method = typeof(CharacterAfflictions).GetMethod(text, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, types2, null); if (method == null) { throw new MissingMethodException("CharacterAfflictions", text); } eggHarmony.Patch((MethodBase)method, new HarmonyMethod(type.GetMethod("Prefix", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } else if (type.GetCustomAttributes(typeof(HarmonyPatch), inherit: false).Length != 0) { eggHarmony.CreateClassProcessor(type).Patch(); } } Call(Egg, "Sapphire009.WatchEgg.TimerUI", "EnsureTimerUIExists"); } internal void RememberFlags(Item item) { if ((Object)(object)item != (Object)null && item.UIData != null && !itemFlags.ContainsKey(item.UIData)) { itemFlags.Add(item.UIData, new bool[2] { item.UIData.canPocket, item.UIData.canDrop }); } } internal bool TryEggTime(Item item, out float seconds) { seconds = 0f; if (!Plugin.IsEgg(item) || eggTimerType == null || eggRemaining == null) { return false; } Component component = ((Component)item).GetComponent(eggTimerType); if ((Object)(object)component == (Object)null) { return false; } seconds = (float)eggRemaining.GetValue(component, null); return true; } internal void StartCoop() { //IL_0144: Unknown result type (might be due to invalid IL or missing references) coopRunning = true; Type[] types = Coop.GetTypes(); foreach (Type type in types) { if (type.FullName.StartsWith("Piggyback+CharacterCarrying_", StringComparison.Ordinal)) { piggyHarmony.CreateClassProcessor(type).Patch(); } } string[] array = new string[7] { "Freepass", "ShareStamina", "SeparateRole", "ShareInventory", "ItemFix", "ShareDeath", "ShareAlive" }; foreach (string type2 in array) { Call(Coop, type2, "Initialize", coopPlugin); } Type type3 = Coop.GetType("ShareInventory+Campfire_LightRpc_SafeDrop_Patch", throwOnError: true); MethodInfo[] methods = type3.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name == "Prefix" || methodInfo.Name == "Postfix") { MethodBase[] array2 = Harmony.GetAllPatchedMethods().ToArray(); foreach (MethodBase methodBase in array2) { new Harmony("com.peak.coopmod.shareinventory").Unpatch(methodBase, methodInfo); } } } } internal void Link(Character carrier, Character rider) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) if (!carried.Any((Character[] p) => (Object)(object)p[0] == (Object)(object)carrier && (Object)(object)p[1] == (Object)(object)rider)) { if (carrier.IsLocal) { carrier.refs.items.EquipSlot(Optionable<byte>.None); } Call(Coop, "Rolechanger", "ApplyCarriedState", carrier, rider); carried.Add((Character[])(object)new Character[2] { carrier, rider }); Call(Coop, "Piggyback", "RegisterLockedPair", carrier, rider); Call(Coop, "ShareDeath", "RegisterPair", carrier, rider); Call(Coop, "ShareAlive", "RegisterPair", carrier, rider); } } internal void Stop() { //IL_0138: Unknown result type (might be due to invalid IL or missing references) List<Exception> list = new List<Exception>(); try { PitchBlack.Stop(); } catch (Exception item) { list.Add(item); } try { Ghost.Stop(); } catch (Exception item2) { list.Add(item2); } chain.Clear(); if (coopRunning) { string[] modules = Modules; foreach (string type in modules) { try { Call(Coop, type, "Shutdown"); } catch (Exception item3) { list.Add(item3); } } coopRunning = false; } piggyHarmony.UnpatchSelf(); HashSet<string> hashSet = new HashSet<string>(); MethodBase[] array = Harmony.GetAllPatchedMethods().ToArray(); foreach (MethodBase methodBase in array) { Patches patchInfo = Harmony.GetPatchInfo(methodBase); if (patchInfo == null) { continue; } foreach (string owner in patchInfo.Owners) { if (owner.StartsWith("com.peak.coopmod.", StringComparison.Ordinal)) { hashSet.Add(owner); } } } foreach (string item5 in hashSet) { new Harmony(item5).UnpatchSelf(); } foreach (Character[] item6 in carried) { if ((Object)(object)item6[0] != (Object)null && (Object)(object)item6[1] != (Object)null) { try { Call(Coop, "Rolechanger", "ClearCarriedState", item6[0], item6[1]); } catch (Exception item4) { list.Add(item4); } } } carried.Clear(); eggHarmony.UnpatchSelf(); foreach (KeyValuePair<ItemUIData, bool[]> itemFlag in itemFlags) { itemFlag.Key.canPocket = itemFlag.Value[0]; itemFlag.Key.canDrop = itemFlag.Value[1]; } itemFlags.Clear(); if (Egg != null) { MonoBehaviour[] array2 = Resources.FindObjectsOfTypeAll<MonoBehaviour>(); foreach (MonoBehaviour val in array2) { if ((Object)(object)val != (Object)null && ((object)val).GetType().Assembly == Egg && !(val is BaseUnityPlugin)) { ((Behaviour)val).enabled = false; Object.Destroy((Object)(object)val); } } } if (list.Count != 0) { throw new AggregateException("Engine cleanup failed", list); } } internal void Dispose() { PitchBlack.Stop(); if (Egg != null && Coop != null) { Stop(); } chain.Dispose(); } internal bool GiveEgg(Player player, string guid) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown Item prefab = default(Item); if (!ItemDatabase.TryGetItem("NestEgg", ref prefab)) { return false; } ItemInstanceData val = new ItemInstanceData(Guid.ParseExact(guid, "N")); ItemInstanceDataHandler.AddInstanceData(val); ItemSlot slot; bool flag = EggCompatibility.GrantHands(player, prefab, val, out slot); if (flag) { ((MonoBehaviourPun)player.character.refs.items).photonView.RPC("OnPickupAccepted", ((MonoBehaviourPun)player).photonView.Owner, new object[1] { (byte)250 }); } return flag; } internal void RefreshChain() { chain.Refresh(); } internal static MethodInfo Require(Assembly assembly, string type, string name, int count) { MethodInfo[] array = (from m in assembly.GetType(type, throwOnError: true).GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) where m.Name == name && m.GetParameters().Length == count select m).ToArray(); if (array.Length != 1) { throw new MissingMethodException(type, name); } return array[0]; } internal static object Call(Assembly assembly, string type, string name, params object[] args) { return Require(assembly, type, name, args.Length).Invoke(null, args); } } } namespace Stasy.PeakHostUi { internal sealed class FogControl : IDisposable { private readonly FogVisualValue<float> height = new FogVisualValue<float>(); private readonly FogVisualValue<bool> builtin = new FogVisualValue<bool>(); private readonly FogVisualValue<float> band = new FogVisualValue<float>(); private readonly FogVisualValue<float> haze = new FogVisualValue<float>(); private bool subscribed; private bool pitchBlack; internal static bool DirectorDisabled { get { if (PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom != null && PhotonNetwork.MasterClient != null && ((Dictionary<object, object>)(object)((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties).TryGetValue((object)"ibgameplay.director.fog.v1", out object value)) { return FogRules.Disabled(value, PhotonNetwork.MasterClient.ActorNumber); } return false; } } internal static bool SetDirectorDisabled(bool disabled) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown if (!PhotonNetwork.InRoom || !PhotonNetwork.IsMasterClient || PhotonNetwork.CurrentRoom == null) { return false; } Room currentRoom = PhotonNetwork.CurrentRoom; Hashtable val = new Hashtable(); ((Dictionary<object, object>)(object)val).Add((object)"ibgameplay.director.fog.v1", (object)new object[2] { PhotonNetwork.LocalPlayer.ActorNumber, disabled }); return currentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); } internal void Start() { if (!subscribed) { subscribed = true; RenderPipelineManager.beginCameraRendering += BeforeCamera; } } internal void SetPitchBlack(bool active) { pitchBlack = active; Tick(); } internal void Tick() { bool directorDisabled = DirectorDisabled; if (FogRules.Suppressed(directorDisabled, pitchBlack && PhotonNetwork.InRoom)) { height.Apply(() => Shader.GetGlobalFloat("HeightFogAmount"), delegate(float value) { Shader.SetGlobalFloat("HeightFogAmount", value); }, 0f); builtin.Apply(() => RenderSettings.fog, delegate(bool value) { RenderSettings.fog = value; }, forced: false); } else { Restore(); } if (directorDisabled) { band.Apply(() => Shader.GetGlobalFloat("BandFogAmount"), delegate(float value) { Shader.SetGlobalFloat("BandFogAmount", value); }, 0f); haze.Apply(() => Shader.GetGlobalFloat("_GlobalHazeAmount"), delegate(float value) { Shader.SetGlobalFloat("_GlobalHazeAmount", value); }, 0f); } else { band.Restore(delegate(float value) { Shader.SetGlobalFloat("BandFogAmount", value); }); haze.Restore(delegate(float value) { Shader.SetGlobalFloat("_GlobalHazeAmount", value); }); } } private void BeforeCamera(ScriptableRenderContext context, Camera camera) { Tick(); } private void Restore() { height.Restore(delegate(float value) { Shader.SetGlobalFloat("HeightFogAmount", value); }); builtin.Restore(delegate(bool value) { RenderSettings.fog = value; }); band.Restore(delegate(float value) { Shader.SetGlobalFloat("BandFogAmount", value); }); haze.Restore(delegate(float value) { Shader.SetGlobalFloat("_GlobalHazeAmount", value); }); } public void Dispose() { if (subscribed) { RenderPipelineManager.beginCameraRendering -= BeforeCamera; } subscribed = false; pitchBlack = false; Restore(); } } internal static class FogRules { internal const string Key = "ibgameplay.director.fog.v1"; internal static bool Disabled(object raw, int master) { object[] array = raw as object[]; if (master > 0 && array != null && array.Length == 2 && array[0] is int && (int)array[0] == master && array[1] is bool) { return (bool)array[1]; } return false; } internal static bool Suppressed(bool director, bool pitchBlack) { return director; } } internal sealed class FogVisualValue<T> { private bool captured; private T baseline; internal void Apply(Func<T> read, Action<T> write, T forced) { T x = read(); if (!captured || !EqualityComparer<T>.Default.Equals(x, forced)) { baseline = x; } captured = true; write(forced); } internal void Restore(Action<T> write) { if (captured) { write(baseline); captured = false; } } } } namespace IBGameplay { internal static class GameplayHudText { internal const float EggHoldSeconds = 20f; internal static string Observer => "Вы наблюдатель"; internal static string ModeCaption(string mode) { if (!string.IsNullOrEmpty(mode)) { return "Режим: " + mode; } return ""; } internal static string GhostPickup(double seconds) { if (double.IsNaN(seconds) || double.IsInfinity(seconds) || seconds <= 0.0) { return "Подбор предмета доступен"; } int num = (int)Math.Min(180.0, Math.Ceiling(seconds)); return "Следующий предмет: " + (num / 60).ToString(CultureInfo.InvariantCulture) + ":" + (num % 60).ToString("00", CultureInfo.InvariantCulture); } internal static float EggSeconds(float seconds) { if (!float.IsNaN(seconds) && !float.IsInfinity(seconds)) { return Math.Max(0f, Math.Min(20f, seconds)); } return 0f; } internal static string EggCountdown(float seconds) { return "До сброса яйца: " + EggSeconds(seconds).ToString("0.0", CultureInfo.InvariantCulture).Replace('.', ',') + " с"; } internal static int EggUrgency(float seconds) { seconds = EggSeconds(seconds); if (!(seconds <= 2f)) { if (!(seconds <= 5f)) { return 0; } return 1; } return 2; } internal static string EggCounters(int[] counts) { if (counts == null || counts.Length == 0) { return ""; } if (counts.Length == 1) { return "Разбито яиц: " + Math.Max(0, counts[0]).ToString(CultureInfo.InvariantCulture); } return "Разбито яиц\n" + string.Join("\n", counts.Select((int count, int index) => "<color=#" + PairIdentity.ColorRgb(index).ToString("X6", CultureInfo.InvariantCulture) + ">Пара " + (index + 1).ToString(CultureInfo.InvariantCulture) + ": " + Math.Max(0, count).ToString(CultureInfo.InvariantCulture) + "</color>").ToArray()); } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInIncompatibility("stasy.idlpro")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInIncompatibility("stasy.pairmodes")] [BepInPlugin("stasy.ibgameplay", "IBGameplay", "0.5.37")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInIncompatibility("com.github.Quaree.Chained")] [BepInIncompatibility("stasy.watchegg.rescue")] public sealed class Plugin : BaseUnityPlugin { private const string GhostReportKey = "ibgameplay.ghostreport.v1"; private const string OptionsKey = "ibgameplay.options.v1"; private const string OffersKey = "ibgameplay.offers.v4"; private const string TimerKey = "ibgameplay.timer.v1"; private const byte ActionEvent = 182; private const string ActionTag = "IBGameplay.actions.v1"; public const string Id = "stasy.ibgameplay"; public const string Version = "0.5.37"; public const int HostPanelApiVersion = 1; private const string StateKey = "ibgameplay.state.v1"; private const string ReadyKey = "ibgameplay.version"; private const string AckKey = "ibgameplay.ack"; private const string ErrorKey = "ibgameplay.error"; private const string LoadedKey = "ibgameplay.loaded.v1"; private readonly CampArrivalRules campArrivals = new CampArrivalRules(); private readonly GhostTargetRotation ghostTargets = new GhostTargetRotation(); private ActionCatalog actionCatalog; private string catalogNotice = "Набор действий ещё не загружен."; private readonly GhostObserverHud ghostObserverHud = new GhostObserverHud(); private GhostRoundReport hostGhostReport; private GhostRoundReport observedGhostReport; private string ghostReportWire; private string observedReportWire; private int observedReportHost; private int observedReportEpoch = -1; internal LiveOptions Options = new LiveOptions(); private ConfigEntry<float> ghostRadius; private ConfigEntry<float> ghostSpeed; private ConfigEntry<float> ghostInterval; private ConfigEntry<float> ghostChoiceDuration; private ConfigEntry<float> lanternRange; private ConfigEntry<float> lanternPower; private ConfigEntry<float> campProtectionRadius; private ConfigEntry<bool> ghostOpponents; private ConfigEntry<bool> ghostDynamite; private readonly GhostChoiceView ghostChoiceView = new GhostChoiceView(); private readonly ConfiguredOffers actionOffers = new ConfiguredOffers(); private readonly SharedGhostRounds sharedRounds = new SharedGhostRounds(); private readonly Random offerRandom = new Random(); private readonly LiveHud liveHud = new LiveHud(); private LoadBalancingClient actionClient; private object liveRoom; private int liveHost; private int offerEpoch = -1; private int offerSerial; private int popupSerial; private int requestSerial; private int selectedEnemy; private int selectedEnemy2; private float nextLivePoll; private float nextRequest; private string optionsWire; private string offersWire; private string actionNotice = ""; private GameObject choiceCursorObject; private MenuWindow choiceCursor; private ConfiguredOffer localOffer; private bool choiceOpen; private string pendingEquip = ""; private int equipEpoch; private float equipUntil; private float equipRetry; private bool liveSettingsOpen; private readonly HostPanel hostPanel = new HostPanel(); private readonly MenuToggleGate menuToggleGate = new MenuToggleGate(); internal static Plugin Instance; internal ScenarioState State = new ScenarioState(); private readonly Harmony guards = new Harmony("stasy.ibgameplay"); private readonly Engines engines = new Engines(); private readonly HashSet<string> owned = new HashSet<string>(); private readonly HashSet<string> counted = new HashSet<string>(); private readonly Dictionary<string, float> brokenRecovery = new Dictionary<string, float>(); private readonly Dictionary<string, float> missingEggs = new Dictionary<string, float>(); private readonly Dictionary<string, string> recoveryBlocks = new Dictionary<string, string>(); private readonly ModeHud modeHud = new ModeHud(); private readonly EggWorldHud eggWorldHud = new EggWorldHud(); private readonly FogControl fogControl = new FogControl(); private bool rescueOpen; private readonly List<LineRenderer> lines = new List<LineRenderer>(); private readonly PairEggCheckpoints<Vector3> checkpoints = new PairEggCheckpoints<Vector3>(delegate(Vector3 a, Vector3 b) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: 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) Vector3 val = a - b; return ((Vector3)(ref val)).sqrMagnitude; }); private readonly List<Pair> draft = new List<Pair>(); private readonly HashSet<int> observers = new HashSet<int>(); private Item[] visibleEggs = (Item[])(object)new Item[0]; private ConfigEntry<KeyCode> menuKey; private ConfigEntry<KeyCode> rescueKey; private bool ready; private bool menuOpen; private bool busy; private bool linked; private bool metadataDirty; private int appliedEpoch = -1; private int blockedEpoch = -1; private int lastHost; private int lastRoster; private string lastWire = ""; private string error = ""; private string message = "Готово. Выберите пары и режим."; private string readyToken; private float nextPoll; private float nextCheckpoint; private float nextEggScan; private float nextMissingScan; private float noticeUntil; private int recoveryPair = -1; private int recoveryEpoch; private string recoveryGuid = ""; private bool recoveryCheckpoint; private Rect window = new Rect(70f, 55f, 960f, 700f); private Vector2 scroll; private int choosingPair = -1; private bool choosingB; private GUIStyle label; private GUIStyle button; private GUIStyle title; private GUIStyle panel; private GUIStyle choicePanel; private GUIStyle sectionPanel; private GUIStyle modePanel; private GUIStyle goodLabel; private GUIStyle badLabel; private GUIStyle stopButton; private GUIStyle[] pairLabels; private Texture2D background; private Texture2D buttonBackground; private Texture2D buttonHover; private Texture2D buttonActive; private Texture2D sectionBackground; private Texture2D modeBackground; private Texture2D stopBackground; private Texture2D stopHover; private Texture2D stopActive; private GameObject cursorObject; private MenuWindow cursorProxy; private ConfigEntry<KeyCode> sharedTimerKey; private ConfigEntry<int> sharedTimerSeconds; private float nextSharedTimerToggle; private readonly TaskSession tasks = new TaskSession(); private readonly TaskHud taskHud = new TaskHud(); private TaskCatalog taskCatalog; private object taskRoom; private int taskHost; private int selectedTask; private string taskScene = ""; private string taskNotice = ""; private string selectedTaskId = ""; private string taskGeneration = ""; private string taskRequest = ""; private bool taskSynced; private bool taskListOpen; private Vector2 taskListScroll; private float nextTaskRequest; private static string GhostActionsPath => Path.Combine(Paths.ConfigPath, "IBGameplay.GhostActions.json"); private static bool EnemyBridgeAvailable { get { if (Chainloader.PluginInfos.TryGetValue("stasy.PEAKDirector", out var value) && (Object)(object)value.Instance != (Object)null) { return ((object)value.Instance).GetType().GetMethod("SpawnForGhostAction") != null; } return false; } } public bool HostMenuOpen { get { if (menuOpen) { return Host; } return false; } } public float HostPanelWidth => UiLayout.DirectorWidth(((Rect)(ref window)).width); public float HostPanelHeight => Math.Max(1f, ((Rect)(ref window)).height - 120f); internal bool HostOnlyCampfires => ready; private bool Host { get { if (PhotonNetwork.InRoom) { return PhotonNetwork.IsMasterClient; } return false; } } private bool InRun { get { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) Scene activeScene = SceneManager.GetActiveScene(); return ((Scene)(ref activeScene)).name.StartsWith("Level_", StringComparison.OrdinalIgnoreCase); } } private static string TasksPath => Path.Combine(Paths.ConfigPath, "IBGameplay.Tasks.json"); private void UpdateCampArrivals() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected I4, but got Unknown //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) if (!Host || !InRun || LoadingScreenHandler.loading || !MapHandler.ExistsAndInitialized) { return; } campArrivals.UpdateSegment((int)MapHandler.CurrentSegmentNumber); Campfire currentCampfire; try { currentCampfire = MapHandler.CurrentCampfire; } catch (NullReferenceException) { return; } if ((Object)(object)currentCampfire == (Object)null) { return; } float value = campProtectionRadius.Value; Player[] playerList = PhotonNetwork.PlayerList; foreach (Player val in playerList) { Character val2 = CharacterFor(val.ActorNumber); if (Living(val2)) { Vector3 val3 = val2.Center - currentCampfire.Center(); if (((Vector3)(ref val3)).sqrMagnitude <= value * value) { campArrivals.Reach(val.ActorNumber); } } } } private int[] EligibleEnemies(int actor, int targetCount = 1) { int partner = GhostRules.Partner(State, actor); if (partner == 0 || !Options.Opponents) { return new int[0]; } return (from a in (from p in State.Pairs select p.A into a where a != partner && !State.IsGhostObserver(a) && Living(CharacterFor(a)) && !campArrivals.Protected(a) && ghostTargets.Allowed(actor, a, targetCount) select a).Distinct() orderby a select a).ToArray(); } private string ActionUnavailable(int actor, ActionDefinition action) { if (GhostRules.Partner(State, actor) == 0) { return "Пара больше не активна."; } if (action.IsEnemy) { if (!Options.Opponents) { return "Взаимодействие с соперниками выключено."; } if (EligibleEnemies(actor, action.targetCount).Length < action.targetCount) { if (action.targetCount != 2) { return "Нет доступных соперников: живых, до костра, не выбранных уже дважды подряд."; } return "Нужны 2 живых соперника, ещё не достигших костра."; } } if (action.type == "spawn" && !EnemyBridgeAvailable) { return "У хоста недоступен PEAKDirector."; } if (action.type == "item") { if (!ResolveActionItem(action.item, out var prefab)) { return "Предмет недоступен в текущей игре."; } if (action.target == "ghost" && !GhostRewardSupported(prefab)) { return "Этот предмет призрак не может использовать."; } } return ""; } private bool RefreshActionAvailability() { bool result = false; foreach (ConfiguredOffer item in actionOffers.All.Where((ConfiguredOffer o) => o.Pending)) { string text = ActionUnavailable(item.Actor, item.Left); string text2 = ActionUnavailable(item.Actor, item.Right); int[] array = EligibleEnemies(item.Actor, 2); int num = ghostTargets.Excluded(item.Actor); if (item.LeftUnavailable != text || item.RightUnavailable != text2 || !item.Enemies.SequenceEqual(array) || item.SingleExcluded != num) { result = true; } item.LeftUnavailable = text; item.RightUnavailable = text2; item.Enemies = array; item.SingleExcluded = num; } return result; } private void ReloadGhostActions() { //IL_00e2: Unknown result type (might be due to invalid IL or missing references) if (!Host) { return; } try { if (!File.Exists(GhostActionsPath)) { Directory.CreateDirectory(Paths.ConfigPath); using FileStream stream = new FileStream(GhostActionsPath, FileMode.CreateNew, FileAccess.Write); using StreamWriter streamWriter = new StreamWriter(stream, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); streamWriter.Write(ConfigJson.Write(ActionCatalog.Defaults())); } if (new FileInfo(GhostActionsPath).Length > 262144) { throw new ArgumentException("Файл действий слишком большой (максимум 256 КБ)."); } string json = File.ReadAllText(GhostActionsPath, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true)); ActionCatalog actionCatalog = ConfigJson.Read<ActionCatalog>(json); if (actionCatalog == null) { throw new ArgumentException("Пустой JSON."); } actionCatalog.Validate(); ActionDefinition[] actions = actionCatalog.actions; foreach (ActionDefinition actionDefinition in actions) { if (actionDefinition.type == "status") { ResolveActionStatus(actionDefinition.status); } if (actionDefinition.type == "item" && (Object)(object)SingletonAsset<ItemDatabase>.Instance != (Object)null && SingletonAsset<ItemDatabase>.Instance.itemLookup != null && SingletonAsset<ItemDatabase>.Instance.itemLookup.Count > 0) { if (!ResolveActionItem(actionDefinition.item, out var prefab)) { throw new ArgumentException(actionDefinition.id + ": неизвестный предмет " + actionDefinition.item); } if (actionDefinition.target == "ghost" && !GhostRewardSupported(prefab)) { throw new ArgumentException(actionDefinition.id + ": этот предмет выдавайте живому (target: partner или enemy); призрак использует еду, лечение и динамит."); } } } this.actionCatalog = actionCatalog; catalogNotice = "Действий: " + actionCatalog.actions.Length + ". Режим: " + actionCatalog.selectionMode + ". Общие раунды; новые правила — со следующего раунда."; ((BaseUnityPlugin)this).Logger.LogInfo((object)("Host action catalog loaded: " + GhostActionsPath + "; actions=" + actionCatalog.actions.Length + "; fixedPairs=" + actionCatalog.offers.Length)); message = catalogNotice; } catch (Exception ex) { catalogNotice = "Ошибка файла действий: " + ex.Message + ((this.actionCatalog == null) ? ". Выбор действий недоступен до исправления файла." : ". Предыдущий набор сохранён."); message = catalogNotice; ((BaseUnityPlugin)this).Logger.LogWarning((object)catalogNotice); } } private bool GhostRewardSupported(Item prefab) { if (!engines.Ghost.Feedable(prefab)) { if (Options.Dynamite) { return (Object)(object)((Component)prefab).GetComponent<Dynamite>() != (Object)null; } return false; } return true; } private static STATUSTYPE ResolveActionStatus(string value) { //IL_017d: Unknown result type (might be due to invalid IL or missing references) string name = (value ?? "").Trim(); switch (name.ToLowerInvariant()) { case "голод": name = "Hunger"; break; case "отравление": case "яд": name = "Poison"; break; case "травма": name = "Injury"; break; case "холод": name = "Cold"; break; case "жара": name = "Hot"; break; case "сонливость": name = "Drowsy"; break; case "проклятие": name = "Curse"; break; } string text = Enum.GetNames(typeof(STATUSTYPE)).FirstOrDefault((string n) => string.Equals(n, name, StringComparison.OrdinalIgnoreCase)); if (text == null) { throw new ArgumentException("Неизвестный статус: " + value); } return (STATUSTYPE)Enum.Parse(typeof(STATUSTYPE), text); } private static bool ResolveActionItem(string value, out Item prefab) { prefab = null; if ((Object)(object)SingletonAsset<ItemDatabase>.Instance == (Object)null || SingletonAsset<ItemDatabase>.Instance.itemLookup == null) { return false; } if (!ushort.TryParse(value, out var result)) { return ItemDatabase.TryGetItem(value, ref prefab); } return ItemDatabase.TryGetItem(result, ref prefab); } private void GrantLivingActionItem(Character target, Item prefab) { //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: 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) //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) //IL_00c4: 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_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_012a: 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_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_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0119: 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) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) if (!Host || !Living(target) || (Object)(object)target.player == (Object)null) { throw new InvalidOperationException("Получатель предмета недоступен."); } if (target.player.itemSlots != null && target.player.itemSlots.Take(3).Any((ItemSlot s) => s != null && s.IsEmpty())) { ItemSlot val = default(ItemSlot); if (!target.player.AddItem(prefab.itemID, (ItemInstanceData)null, ref val) || val == null || val.itemSlotID >= 3) { throw new InvalidOperationException("Выдача в инвентарь отклонена."); } return; } Vector3 val2 = target.Center + Vector3.up * 0.2f; RaycastHit val3 = default(RaycastHit); if (Physics.Raycast(target.Center + Vector3.up * 0.5f, Vector3.down, ref val3, 3f, LayerMask.GetMask(new string[2] { "Terrain", "Default" }), (QueryTriggerInteraction)1)) { val2 = ((RaycastHit)(ref val3)).point + Vector3.up * 0.3f; } GameObject val4 = PhotonNetwork.InstantiateItemRoom(((Object)((Component)prefab).gameObject).name, val2, Quaternion.identity, true); if ((Object)(object)val4 == (Object)null) { throw new InvalidOperationException("Не удалось создать предмет рядом с получателем."); } Item component = val4.GetComponent<Item>(); if ((Object)(object)component == (Object)null) { PhotonNetwork.Destroy(val4); throw new InvalidOperationException("Созданный объект не является предметом."); } component.SetKinematicNetworked(false, val2, Quaternion.identity); } private void ExportActionItems() { if (!Host || (Object)(object)SingletonAsset<ItemDatabase>.Instance == (Object)null || SingletonAsset<ItemDatabase>.Instance.itemLookup == null) { return; } try { IEnumerable<string> second = from p in SingletonAsset<ItemDatabase>.Instance.itemLookup where (Object)(object)p.Value != (Object)null orderby p.Key select p.Key + "\t" + ((Object)((Component)p.Value).gameObject).name; File.WriteAllLines(Path.Combine(Paths.ConfigPath, "IBGameplay.Items.txt"), new string[1] { "ID\titem (exact prefab name)" }.Concat(second), new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); message = "Список ID и названий сохранён: BepInEx/config/IBGameplay.Items.txt"; } catch (Exception ex) { message = "Не удалось сохранить список: " + ex.Message; } } private void StartGhostReport(int[] actors, ActionDefinition left, ActionDefinition right, double until, double next) { if (Host) { hostGhostReport = GhostRoundReport.Start(liveHost, State.Epoch, offerSerial, left.label, right.label, until, next, actors); } } private void RecordGhostDecision(int actor, int choice, ActionDefinition action, int target, int target2) { if (Host && hostGhostReport != null && hostGhostReport.Epoch == State.Epoch && hostGhostReport.Serial == offerSerial) { int target3 = ((action.target == "ghost") ? actor : ((action.target == "partner") ? GhostRules.Partner(State, actor) : target)); hostGhostReport.Decide(actor, choice, target3, (action.targetCount == 2) ? target2 : 0); } } private void PublishGhostReport() { //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Expected O, but got Unknown if (!Host) { return; } if (hostGhostReport != null) { if (State.Mode != Mode.Ghost || !State.Armed || hostGhostReport.Epoch != State.Epoch) { hostGhostReport = null; } else { GhostRoundDecision[] rows = hostGhostReport.Rows; foreach (GhostRoundDecision row in rows) { row.Active = GhostRules.Partner(State, row.Actor) != 0 && PhotonNetwork.PlayerList.Any((Player p) => p.ActorNumber == row.Actor); } } } string text = ((hostGhostReport == null) ? null : hostGhostReport.Encode()); if (!(text == ghostReportWire)) { Room currentRoom = PhotonNetwork.CurrentRoom; Hashtable val = new Hashtable(); ((Dictionary<object, object>)(object)val).Add((object)"ibgameplay.ghostreport.v1", (object)text); if (currentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null)) { ghostReportWire = text; } } } private void ResetGhostReport() { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown bool flag = hostGhostReport != null || ghostReportWire != null; hostGhostReport = (observedGhostReport = null); observedReportWire = null; observedReportHost = 0; observedReportEpoch = -1; ghostObserverHud.Clear(); if (Host && PhotonNetwork.CurrentRoom != null && (flag || (((Dictionary<object, object>)(object)((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties).TryGetValue((object)"ibgameplay.ghostreport.v1", out object value) && value != null))) { Room currentRoom = PhotonNetwork.CurrentRoom; Hashtable val = new Hashtable(); ((Dictionary<object, object>)(object)val).Add((object)"ibgameplay.ghostreport.v1", (object)null); currentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); } ghostReportWire = null; } private void UpdateGhostObserverHud(float offset) { int actor = ((PhotonNetwork.LocalPlayer != null) ? PhotonNetwork.LocalPlayer.ActorNumber : 0); if (!ready || !InRun || LoadingScreenHandler.loading || !PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null || PhotonNetwork.MasterClient == null || !GhostRoundReport.Observer(State, actor)) { ghostObserverHud.Hide(); return; } int actorNumber = PhotonNetwork.MasterClient.ActorNumber; object value; string text = (((Dictionary<object, object>)(object)((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties).TryGetValue((object)"ibgameplay.ghostreport.v1", out value) ? (value as string) : null); if (text != observedReportWire || actorNumber != observedReportHost || State.Epoch != observedReportEpoch) { observedReportWire = text; observedReportHost = actorNumber; observedReportEpoch = State.Epoch; GhostRoundReport.TryRead(text, actorNumber, State.Epoch, out observedGhostReport); } GhostRoundReport ghostRoundReport = (Host ? hostGhostReport : observedGhostReport); if (ghostRoundReport == null || ghostRoundReport.Host != actorNumber || ghostRoundReport.Epoch != State.Epoch || ghostRoundReport.Rows.Any((GhostRoundDecision row) => !State.Pairs.Any((Pair p) => p.B == row.Actor))) { ghostObserverHud.Hide(); return; } ghostObserverHud.Show(ghostRoundReport, PhotonNetwork.Time, offset, GhostObserverName, (int ghost) => Array.FindIndex(State.Pairs, (Pair p) => p.B == ghost) + 1); } private static string GhostObserverName(int actor) { Player val = ((IEnumerable<Player>)PhotonNetwork.PlayerList).FirstOrDefault((Func<Player, bool>)((Player p) => p.ActorNumber == actor)); string source = ((val == null || string.IsNullOrWhiteSpace(val.NickName)) ? ("Игрок #" + actor) : val.NickName); source = new string(source.Where((char c) => !char.IsControl(c)).ToArray()); if (source.Length <= 36) { return source; } return source.Substring(0, 35) + "…"; } private static bool FinitePose(Vector3 p, Quaternion q) { if (GhostOffers.Finite(p.x) && GhostOffers.Finite(p.y) && GhostOffers.Finite(p.z) && GhostOffers.Finite(q.x) && GhostOffers.Finite(q.y) && GhostOffers.Finite(q.z) && GhostOffers.Finite(q.w) && q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w > 0.5f) { return q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w < 1.5f; } return false; } private void DropOldGhostReward(Character c) { //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Expected O, but got Unknown //IL_013a: 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) if (!Host || (Object)(object)c == (Object)null || (Object)(object)c.player == (Object)null || c.player.tempFullSlot == null) { throw new InvalidOperationException("Не удалось проверить руку призрака."); } if (!c.player.tempFullSlot.IsEmpty()) { if ((Object)(object)c.player.tempFullSlot.prefab == (Object)null) { throw new InvalidOperationException("Предыдущий предмет ещё не загружен. Повторите выбор."); } string text = GuidOf(c.player.tempFullSlot.data); if (!Guid.TryParseExact(text, "N", out var _) || !GhostAdapter.Instance.RewardPose(c, out var position, out var rotation) || !FinitePose(position, rotation)) { throw new InvalidOperationException("Положение призрака ещё не синхронизировано. Повторите выбор."); } if (!GhostAdapter.Instance.DropReplacement(c, text, position, rotation, master: true)) { throw new InvalidOperationException("Предыдущий предмет ещё не синхронизирован. Повторите выбор."); } object[] obj = new object[7] { "IBGameplay.actions.v1", "replacement-drop", State.Epoch, Actor(c), text, position, rotation }; RaiseEventOptions val = new RaiseEventOptions(); val.Receivers = (ReceiverGroup)0; if (!PhotonNetwork.RaiseEvent((byte)182, (object)obj, val, SendOptions.SendReliable)) { throw new InvalidOperationException("Старый предмет сброшен, но сеть недоступна. Повторите выбор после восстановления связи."); } GhostAdapter.Instance.ResetRewardSelection(c); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Ghost reward replaced actor=" + Actor(c) + "; old item dropped at flying ghost.")); } } private void ReceiveGhostReplacement(EventData data, object[] p) { //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) if (data.Sender != PhotonNetwork.MasterClient.ActorNumber || Host || !InRun || LoadingScreenHandler.loading || State.Mode != Mode.Ghost || !State.Armed || p.Length != 7 || !(p[2] is int) || (int)p[2] != State.Epoch || !(p[3] is int) || !(p[4] is string) || !(p[5] is Vector3) || !(p[6] is Quaternion)) { return; } int actor = (int)p[3]; string text = (string)p[4]; if (GhostRules.Partner(State, actor) != 0 && Guid.TryParseExact(text, "N", out var _) && FinitePose((Vector3)p[5], (Quaternion)p[6])) { Character c = CharacterFor(actor); if (GhostAdapter.Instance.DropReplacement(c, text, (Vector3)p[5], (Quaternion)p[6], master: false)) { GhostAdapter.Instance.ResetRewardSelection(c); } } } internal void DrawGroundEggMarker(Item egg) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: 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) //IL_00b0: 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_00d3: 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) if ((Object)(object)egg == (Object)null || !((Component)egg).gameObject.activeInHierarchy || (int)egg.itemState != 0) { return; } string guid = GuidOf(egg.data); int num = Array.FindIndex(State.Pairs, (Pair p) => p.Egg == guid && guid != ""); if (num < 0) { return; } Camera val = (((Object)(object)MainCamera.instance != (Object)null) ? ((Component)MainCamera.instance).GetComponent<Camera>() : Camera.main); if ((Object)(object)val == (Object)null) { val = Camera.main; } if (!((Object)(object)val == (Object)null)) { Vector3 val2 = val.WorldToScreenPoint(egg.transform.position + Vector3.up * 0.35f); if (!(val2.z <= 0f)) { eggWorldHud.Marker(guid, num, TeamColor(num), new Vector2(val2.x, val2.y)); } } } private void InitializeLiveControls() { InitializeSharedTimer(); ghostRadius = LiveFloat("Призрак", "Дальность полёта", 20f, 5f, 200f, "Метры от напарника. Изменения хост применяет в общем меню."); ghostSpeed = LiveFloat("Призрак", "Скорость полёта", 12f, 1f, 40f, "Скорость призрака."); ghostInterval = LiveFloat("Призрак", "Интервал выбора", 180f, 15f, 900f, "Общий интервал раундов: старый выбор заменяется новым у всех одновременно. Изменение интервала действует после следующей границы раунда."); ghostChoiceDuration = LiveFloat("Призрак", "Время на выбор действия", 20f, 5f, 120f, "Сколько секунд открыто окно выбора. Без выбора ничего не происходит. Новое значение действует со следующего раунда; окно не дольше интервала раундов."); campProtectionRadius = LiveFloat("Призрак", "Радиус достижения костра", 8f, 2f, 30f, "С этого расстояния до текущего костра игрок защищён от действий соперников до следующего биома."); ghostOpponents = ((BaseUnityPlugin)this).Config.Bind<bool>("Призрак", "Взаимодействие с соперниками", true, "Применение еды/лечения также на живых участников других пар. Не на наблюдателей."); ghostDynamite = ((BaseUnityPlugin)this).Config.Bind<bool>("Призрак", "Динамит", true, "Разрешить брать, зажигать и бросать динамит. Другие предметы бросать нельзя."); lanternRange = LiveFloat("Pitch Black", "Дальность фонаря", 30f, 5f, 80f, "Радиус света в метрах, в руках и на поясе. Только в Pitch Black."); lanternPower = LiveFloat("Pitch Black", "Яркость фонаря", 2.5f, 0.25f, 10f, "Множитель яркости от штатного фонаря. Только в Pitch Black."); Options = ConfigOptions(); } private ConfigEntry<float> LiveFloat(string section, string key, float value, float min, float max, string description) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown return ((BaseUnityPlugin)this).Config.Bind<float>(section, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(min, max), new object[0])); } private LiveOptions ConfigOptions() { LiveOptions liveOptions = new LiveOptions(); liveOptions.Radius = ghostRadius.Value; liveOptions.Speed = ghostSpeed.Value; liveOptions.Interval = ghostInterval.Value; liveOptions.Opponents = ghostOpponents.Value; liveOptions.Dynamite = ghostDynamite.Value; liveOptions.LanternRange = lanternRange.Value; liveO
BepInEx/patchers/IBGameplay/IBGameplay.Bootstrap.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Mono.Cecil; [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: AssemblyVersion("0.0.0.0")] namespace IBGameplayStartup; public static class Patcher { public static IEnumerable<string> TargetDLLs => new string[0]; public static bool Ready { get; private set; } public static void Patch(AssemblyDefinition assembly) { } public static void Finish() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown string text = FindController(Paths.PluginPath); if (text == null) { Logger.CreateLogSource("IBGameplay startup").LogInfo((object)"No active IBGameplay.dll under plugins; startup guards skipped."); return; } Harmony val = new Harmony("stasy.ibgameplay.startup"); MethodInfo[] methods = typeof(Harmony).GetMethods(BindingFlags.Instance | BindingFlags.Public); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name == "PatchAll") { val.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(Patcher), "AllowPatchAll", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } Ready = true; Logger.CreateLogSource("IBGameplay startup").LogInfo((object)("WatchEgg and Chainbound automatic PatchAll parked; IBGameplay binds compatible rules. Original DLLs unchanged. Controller: " + text)); } public static string FindController(string pluginRoot) { if (string.IsNullOrEmpty(pluginRoot) || !Directory.Exists(pluginRoot)) { return null; } string[] files = Directory.GetFiles(pluginRoot, "IBGameplay.dll", SearchOption.AllDirectories); if (files.Length != 0) { return files[0]; } return null; } private static bool AllowPatchAll(Harmony __instance) { return AllowOwner(__instance.Id); } public static bool AllowOwner(string owner) { if (owner != "sapphire009.watchegg" && owner != "Sapphire009.StaminaFull") { return owner != "patchnote.chainbound"; } return false; } }