Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of BotanicPupPatch v2.1.0
BotanicPupPatch.dll
Decompiled 3 days 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.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Security.Cryptography; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyVersion("2.1.0.0")] namespace BotanicPupPatch; internal abstract class CellReadiness { internal abstract bool Ready(Vector3 point, float radius); internal static CellReadiness Create(MonoBehaviour pup) { Type type = ((object)pup).GetType(); Type type2 = type.GetField("multiplayerRemoteCells", BindingFlags.Instance | BindingFlags.NonPublic).FieldType.GetGenericArguments()[1]; Type type3 = type.GetField("fastColliderCells", BindingFlags.Instance | BindingFlags.NonPublic).FieldType.GetGenericArguments()[1]; Type type4 = type.GetField("records", BindingFlags.Instance | BindingFlags.NonPublic).FieldType.GetGenericArguments()[1].GetGenericArguments()[0]; return (CellReadiness)Activator.CreateInstance(typeof(TypedCellReadiness<, , >).MakeGenericType(type2, type3, type4), pup); } } internal sealed class TypedCellReadiness<R, F, B> : CellReadiness where R : class where F : class { private readonly MonoBehaviour pup; private readonly Func<object, Dictionary<Vector2Int, List<B>>> records; private readonly Func<object, Dictionary<Vector2Int, R>> remotes; private readonly Func<object, Dictionary<Vector2Int, F>> fasts; private readonly Func<object, Dictionary<Vector2Int, GameObject>> roots; private readonly Func<object, Dictionary<Vector2Int, string>> ids; private readonly Func<object, Dictionary<GameObject, string>> validated; private readonly Func<object, Dictionary<Vector2Int, bool>> active; private readonly Func<object, Dictionary<Vector2Int, HashSet<string>>> loaded; private readonly Func<object, HashSet<Vector2Int>> physics; private readonly Func<object, HashSet<Vector2Int>> verified; private readonly Func<object, HashSet<Vector2Int>> worldRestores; private readonly Func<object, HashSet<Vector2Int>> vanillaRestores; private readonly Func<object, HashSet<Vector2Int>> loading; private readonly Func<object, int> queued; private readonly Func<R, string> remoteId; private readonly Func<F, string> fastId; private readonly Func<F, GameObject> fastRoot; private readonly Func<F, HashSet<string>> required; private readonly Func<Vector2Int, bool> pending; public TypedCellReadiness(MonoBehaviour value) { pup = value; Type type = ((object)pup).GetType(); records = Read<Dictionary<Vector2Int, List<B>>>(type, "records"); remotes = Read<Dictionary<Vector2Int, R>>(type, "multiplayerRemoteCells"); fasts = Read<Dictionary<Vector2Int, F>>(type, "fastColliderCells"); roots = Read<Dictionary<Vector2Int, GameObject>>(type, "clusters"); ids = Read<Dictionary<Vector2Int, string>>(type, "cacheIds"); validated = Read<Dictionary<GameObject, string>>(type, "validatedReplacementCacheIds"); active = Read<Dictionary<Vector2Int, bool>>(type, "colliderCellActive"); loaded = Read<Dictionary<Vector2Int, HashSet<string>>>(type, "fastLoadedSubclusters"); physics = Read<HashSet<Vector2Int>>(type, "multiplayerRemotePhysicsReady"); verified = Read<HashSet<Vector2Int>>(type, "verifiedRemoteReplacements"); worldRestores = Read<HashSet<Vector2Int>>(type, "pendingWorldSaveRestores"); vanillaRestores = Read<HashSet<Vector2Int>>(type, "multiplayerPendingVanillaRestore"); loading = Read<HashSet<Vector2Int>>(type, "loadingCells"); queued = Read<int>(type, "queuedColliderCount"); remoteId = FieldReader.Create<R, string>(Field(typeof(R), "cacheId")); fastId = FieldReader.Create<F, string>(Field(typeof(F), "cacheId")); fastRoot = FieldReader.Create<F, GameObject>(Field(typeof(F), "root")); required = FieldReader.Create<F, HashSet<string>>(Field(typeof(F), "required")); pending = (Func<Vector2Int, bool>)Delegate.CreateDelegate(typeof(Func<Vector2Int, bool>), pup, type.GetMethod("HasPendingCollidersForCell", BindingFlags.Instance | BindingFlags.NonPublic)); } private static FieldInfo Field(Type type, string name) { return type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } private static Func<object, T> Read<T>(Type type, string name) { return FieldReader.Create<object, T>(Field(type, name)); } internal override bool Ready(Vector3 point, float radius) { //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_02a9: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_0392: Unknown result type (might be due to invalid IL or missing references) //IL_0306: Unknown result type (might be due to invalid IL or missing references) //IL_03c0: Unknown result type (might be due to invalid IL or missing references) //IL_0338: Unknown result type (might be due to invalid IL or missing references) //IL_03f0: Unknown result type (might be due to invalid IL or missing references) //IL_03e3: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.FloorToInt((point.x - radius) / 64f); int num2 = Mathf.FloorToInt((point.x + radius) / 64f); int num3 = Mathf.FloorToInt((point.z - radius) / 64f); int num4 = Mathf.FloorToInt((point.z + radius) / 64f); Dictionary<Vector2Int, R> dictionary = remotes(pup); Dictionary<Vector2Int, GameObject> dictionary2 = roots(pup); Dictionary<Vector2Int, bool> dictionary3 = active(pup); Vector2Int val = default(Vector2Int); for (int i = num; i <= num2; i++) { for (int j = num3; j <= num4; j++) { float num5 = Mathf.Max(0f, Mathf.Max((float)i * 64f - point.x, point.x - (float)(i + 1) * 64f)); float num6 = Mathf.Max(0f, Mathf.Max((float)j * 64f - point.z, point.z - (float)(j + 1) * 64f)); if (num5 * num5 + num6 * num6 > radius * radius) { continue; } ((Vector2Int)(ref val))..ctor(i, j); R value; bool flag = dictionary.TryGetValue(val, out value); List<B> value2; bool flag2 = records(pup).TryGetValue(val, out value2); if (!flag && !flag2) { continue; } if (worldRestores(pup).Contains(val) || vanillaRestores(pup).Contains(val) || !flag2 || value2 == null || value2.Count == 0 || !ids(pup).TryGetValue(val, out var value3) || string.IsNullOrEmpty(value3) || value3 == "RESTORE_PENDING" || (flag && value3 != remoteId(value))) { return false; } GameObject value4; if (flag) { if (!physics(pup).Contains(val) || !verified(pup).Contains(val) || !dictionary2.TryGetValue(val, out value4) || !Object.op_Implicit((Object)(object)value4) || !value4.activeInHierarchy || !validated(pup).TryGetValue(value4, out var value5) || value5 != remoteId(value)) { return false; } } else { if (ZNet.instance.IsDedicated() || (!ids(pup).ContainsKey(val) && !dictionary2.ContainsKey(val))) { continue; } if (fasts(pup).TryGetValue(val, out var value6)) { value4 = fastRoot(value6); if (!Object.op_Implicit((Object)(object)value4) || !value4.activeInHierarchy || !ids(pup).TryGetValue(val, out var value7) || value7 != fastId(value6) || !loaded(pup).TryGetValue(val, out var value8)) { return false; } foreach (string item in required(value6)) { if (!value8.Contains(item)) { return false; } } } else if (!dictionary2.TryGetValue(val, out value4) || !Object.op_Implicit((Object)(object)value4) || !value4.activeInHierarchy || loading(pup).Contains(val) || (queued(pup) > 0 && pending(val))) { return false; } } if (dictionary3.TryGetValue(val, out var value9) && !value9) { return false; } } } return true; } } internal static class FgnAttackRetry { private sealed class Ticket { internal Humanoid Mob; internal ZDO Data; internal ZDOMan World; internal ZNet Network; internal long Owner; internal long Epoch; internal uint Revision; } private static ConditionalWeakTable<Attack, Ticket> waiting = new ConditionalWeakTable<Attack, Ticket>(); private static Func<Humanoid, Attack> currentAttack; private static SynchronizationContext context; private static Action<Humanoid, ZDO> retry; private static Action<Exception> fail; private static readonly SendOrPostCallback dispatch = Dispatch; private static long epoch; private static int armedCount; internal static void Install(Harmony harmony, Action<Humanoid, ZDO> onEnd, Action<Exception> onFailure) { //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Expected O, but got Unknown SynchronizationContext current = SynchronizationContext.Current; FieldInfo fieldInfo = AccessTools.Field(typeof(Humanoid), "m_currentAttack"); MethodInfo methodInfo = AccessTools.Method(typeof(Attack), "Stop", Type.EmptyTypes, (Type[])null); if (current == null || current.GetType().FullName != "UnityEngine.UnitySynchronizationContext" || fieldInfo == null || fieldInfo.IsStatic || fieldInfo.FieldType != typeof(Attack) || methodInfo == null || methodInfo.IsStatic || methodInfo.ReturnType != typeof(void)) { throw new NotSupportedException("Native attack-end retry contract unavailable."); } currentAttack = FieldReader.Create<Humanoid, Attack>(fieldInfo); context = current; retry = onEnd; fail = onFailure; Reset(); harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(FgnAttackRetry), "Stopped", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } internal static bool Arm(Character mob, ZDO data) { Humanoid val = (Humanoid)(object)((mob is Humanoid) ? mob : null); if (!Object.op_Implicit((Object)(object)val) || data == null || currentAttack == null || context == null) { return false; } Attack val2 = currentAttack(val); if (val2 == null || val2.IsDone()) { return false; } if (waiting.TryGetValue(val2, out var value)) { if (value.Epoch == epoch && object.ReferenceEquals(value.Data, data) && object.ReferenceEquals(value.World, ZDOMan.instance) && object.ReferenceEquals(value.Network, ZNet.instance) && value.Owner == data.GetOwner() && value.Revision == data.OwnerRevision) { return true; } waiting.Remove(val2); armedCount--; } waiting.Add(val2, new Ticket { Mob = val, Data = data, World = ZDOMan.instance, Network = ZNet.instance, Owner = data.GetOwner(), Revision = data.OwnerRevision, Epoch = epoch }); armedCount++; return true; } private static void Stopped(Attack __instance) { if (armedCount == 0) { return; } try { if (__instance.IsDone() && waiting.TryGetValue(__instance, out var value)) { waiting.Remove(__instance); armedCount--; context.Post(dispatch, value); } } catch (Exception error) { Failed(error); } } private static void Dispatch(object state) { //IL_006c: Unknown result type (might be due to invalid IL or missing references) try { Ticket ticket = (Ticket)state; if (ticket.Epoch == epoch && object.ReferenceEquals(ticket.World, ZDOMan.instance) && object.ReferenceEquals(ticket.Network, ZNet.instance) && ticket.World != null && Object.op_Implicit((Object)(object)ticket.Mob) && ticket.Data.IsValid() && object.ReferenceEquals(ticket.World.GetZDO(ticket.Data.m_uid), ticket.Data) && ticket.Data.GetOwner() == ticket.Owner && ticket.Data.OwnerRevision == ticket.Revision && ticket.Owner == ZDOMan.GetSessionID()) { retry(ticket.Mob, ticket.Data); } } catch (Exception error) { Failed(error); } } private static void Failed(Exception error) { try { if (fail != null) { fail(error); } } catch { } } internal static void Reset() { epoch++; waiting = new ConditionalWeakTable<Attack, Ticket>(); armedCount = 0; } } internal sealed class FgnCombatBridge { internal delegate bool EchoRtt(ZNetPeer peer, out float milliseconds); private const BindingFlags Flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; internal readonly MethodInfo Balance; internal readonly MethodInfo TryHandOff; internal readonly MethodInfo Veto; internal readonly MethodInfo OnResult; internal readonly Func<ZDO, double, bool> TryTransfer; internal readonly Func<bool> Active; internal readonly Func<bool> Simulation; internal readonly Func<double> NextPass; internal readonly Func<ZNetPeer, bool> Matched; internal readonly Func<ZNetPeer, float> Rtt; internal readonly EchoRtt MeasuredEcho; internal readonly Func<ZNetPeer, int> SocketPing; internal readonly Func<ZDO, bool> Held; internal readonly Func<ZDO, bool> Possessed; internal readonly Func<ZDOID, double, bool> Pending; internal readonly Action<ZDOID, long, double> MarkPending; internal readonly Action<ZDOID> ClearStreak; internal readonly Action<ZDOID> ClearOwned; internal readonly Dictionary<long, int> PerOwner; internal readonly Dictionary<ZDOID, double> Cooldowns; internal readonly List<ZNetPeer> Candidates; internal readonly MethodInfo TargetReader; internal FgnCombatBridge(Assembly assembly) { Type type = assembly.GetType("FiresGhettoNetworkMod.CreatureOwnership", throwOnError: true); RequireConstant(type, "PassSeconds", 2.0); RequireConstant(type, "PendingSeconds", 5.0); RequireConstant(type, "DeclinedCooldownSeconds", 6.0); RequireConstant(type, "ForwardHitsSeconds", 5.0); RequireConstant(type, "MaxHandOffsPerPass", 16); RequireConstant(type, "MaxHandOffsPerOwner", 6); Balance = Method(type, "Balance", typeof(void), typeof(ZDOMan)); TryHandOff = Method(type, "TryHandOffCreature", typeof(bool), typeof(ZDO), typeof(double)); TryTransfer = Bind<Func<ZDO, double, bool>>(TryHandOff); Veto = Method(type, "Veto", typeof(string), typeof(ZDO), typeof(long)); OnResult = Method(type, "OnResult", typeof(void), typeof(ZRpc), typeof(ZDOID), typeof(bool), typeof(string)); Active = Bind<Func<bool>>(Method(type, "Active", typeof(bool))); NextPass = Static<double>(Field(type, "s_nextPass", typeof(double))); Rtt = Bind<Func<ZNetPeer, float>>(Method(type, "Rtt", typeof(float), typeof(ZNetPeer))); Held = Bind<Func<ZDO, bool>>(Method(type, "IsHeld", typeof(bool), typeof(ZDO))); Type type2 = assembly.GetType("FiresGhettoNetworkMod.ValcastPossession", throwOnError: false); Possessed = ((type2 == null) ? new Func<ZDO, bool>(NoPossession) : Bind<Func<ZDO, bool>>(Method(type2, "IsPossessed", typeof(bool), typeof(ZDO)))); Type type3 = assembly.GetType("FiresGhettoNetworkMod.FgnVersionGate", throwOnError: true); Matched = Bind<Func<ZNetPeer, bool>>(Method(type3, "IsMatched", typeof(bool), typeof(ZNetPeer))); Type type4 = assembly.GetType("FiresGhettoNetworkMod.ServerAuthorityPatches", throwOnError: true); Simulation = Static<bool>(Field(type4, "SimulationActive", typeof(bool))); Type type5 = assembly.GetType("FiresGhettoNetworkMod.FiresGhettoNetworkMod", throwOnError: true); ConfigEntry<bool> val = (ConfigEntry<bool>)Field(type5, "ConfigEnableServerOwnership", typeof(ConfigEntry<bool>)).GetValue(null); ConfigEntry<bool> val2 = (ConfigEntry<bool>)Field(type5, "ConfigEnableServerOwnershipSelective", typeof(ConfigEntry<bool>)).GetValue(null); if (val == null || val2 == null || val.Value || val2.Value) { throw new NotSupportedException("FGN AI ownership requires both FGN server ZDO ownership options OFF."); } Type type6 = assembly.GetType("FiresGhettoNetworkMod.ConnectionEcho", throwOnError: true); MeasuredEcho = Bind<EchoRtt>(Method(type6, "TryRtt", typeof(bool), typeof(ZNetPeer), typeof(float).MakeByRefType())); Type type7 = assembly.GetType("FiresGhettoNetworkMod.LinkController", throwOnError: true); SocketPing = Bind<Func<ZNetPeer, int>>(Method(type7, "PingMs", typeof(int), typeof(ZNetPeer))); PerOwner = (Dictionary<long, int>)Field(type, "s_perOwner", typeof(Dictionary<long, int>)).GetValue(null); Cooldowns = (Dictionary<ZDOID, double>)Field(type, "s_cooldowns", typeof(Dictionary<ZDOID, double>)).GetValue(null); Candidates = (List<ZNetPeer>)Field(type, "s_candidates", typeof(List<ZNetPeer>)).GetValue(null); FieldInfo field = type.GetField("s_pending", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo field2 = type.GetField("s_lastHitBy", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field == null || field2 == null || field.FieldType != field2.FieldType || !field.IsStatic) { throw new NotSupportedException("FGN stamp dictionary contract changed."); } Type type8 = field.FieldType.GetGenericArguments()[1]; if (!type8.IsValueType || field.FieldType != typeof(Dictionary<, >).MakeGenericType(typeof(ZDOID), type8) || type8.GetField("Peer").FieldType != typeof(long) || type8.GetField("At").FieldType != typeof(double)) { throw new NotSupportedException("FGN stamp contract changed."); } Pending = PendingReader(field, type8); MarkPending = StampWriter(field, type8); FieldInfo field3 = type.GetField("s_streaks", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field3 == null || !field3.IsStatic || !field3.FieldType.IsGenericType || field3.FieldType.GetGenericTypeDefinition() != typeof(Dictionary<, >) || field3.FieldType.GetGenericArguments()[0] != typeof(ZDOID)) { throw new NotSupportedException("FGN ping streak contract changed."); } DynamicMethod dynamicMethod = new DynamicMethod("BotanicCombatClearStreak", typeof(void), new Type[1] { typeof(ZDOID) }, typeof(FgnCombatBridge).Module, skipVisibility: true); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); iLGenerator.Emit(OpCodes.Ldsfld, field3); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Callvirt, field3.FieldType.GetMethod("Remove", new Type[1] { typeof(ZDOID) })); iLGenerator.Emit(OpCodes.Pop); iLGenerator.Emit(OpCodes.Ret); ClearStreak = (Action<ZDOID>)dynamicMethod.CreateDelegate(typeof(Action<ZDOID>)); FieldInfo field4 = type.GetField("s_owned", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field4 == null || !field4.IsStatic || !field4.FieldType.IsGenericType || field4.FieldType.GetGenericTypeDefinition() != typeof(Dictionary<, >) || field4.FieldType.GetGenericArguments()[0] != typeof(ZDOID)) { throw new NotSupportedException("FGN ownership hold contract changed."); } DynamicMethod dynamicMethod2 = new DynamicMethod("BotanicCombatClearOwned", typeof(void), new Type[1] { typeof(ZDOID) }, typeof(FgnCombatBridge).Module, skipVisibility: true); ILGenerator iLGenerator2 = dynamicMethod2.GetILGenerator(); iLGenerator2.Emit(OpCodes.Ldsfld, field4); iLGenerator2.Emit(OpCodes.Ldarg_0); iLGenerator2.Emit(OpCodes.Callvirt, field4.FieldType.GetMethod("Remove", new Type[1] { typeof(ZDOID) })); iLGenerator2.Emit(OpCodes.Pop); iLGenerator2.Emit(OpCodes.Ret); ClearOwned = (Action<ZDOID>)dynamicMethod2.CreateDelegate(typeof(Action<ZDOID>)); TargetReader = typeof(FgnTargetReader<>).MakeGenericType(type8).GetMethod("TryGetValue", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); TargetReader.DeclaringType.GetMethod("Initialize", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).Invoke(null, null); } internal bool TryMeasuredRtt(ZNetPeer peer, out float value) { if (MeasuredEcho(peer, out value) && value > 0f && !float.IsNaN(value) && !float.IsInfinity(value)) { return true; } int num = SocketPing(peer); value = num; return num > 0; } private static T Bind<T>(MethodInfo method) where T : class { return (T)(object)Delegate.CreateDelegate(typeof(T), method); } private static bool NoPossession(ZDO data) { return false; } private static void RequireConstant(Type type, string name, object expected) { FieldInfo field = type.GetField(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field == null || !field.IsLiteral || !object.Equals(field.GetRawConstantValue(), expected)) { throw new NotSupportedException("FGN ownership contract changed: " + name); } } private static MethodInfo Method(Type type, string name, Type returns, params Type[] args) { MethodInfo method = type.GetMethod(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, args, null); if (method == null || method.ReturnType != returns) { throw new NotSupportedException("FGN method changed: " + name); } return method; } private static FieldInfo Field(Type type, string name, Type value) { FieldInfo field = type.GetField(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field == null || field.FieldType != value || !field.IsStatic) { throw new NotSupportedException("FGN field changed: " + name); } return field; } private static Func<T> Static<T>(FieldInfo field) { DynamicMethod dynamicMethod = new DynamicMethod("BotanicCombatRead_" + field.Name, typeof(T), Type.EmptyTypes, typeof(FgnCombatBridge).Module, skipVisibility: true); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); iLGenerator.Emit(OpCodes.Ldsfld, field); iLGenerator.Emit(OpCodes.Ret); return (Func<T>)dynamicMethod.CreateDelegate(typeof(Func<T>)); } private static Func<ZDOID, double, bool> PendingReader(FieldInfo field, Type stamp) { DynamicMethod dynamicMethod = new DynamicMethod("BotanicCombatPending", typeof(bool), new Type[2] { typeof(ZDOID), typeof(double) }, typeof(FgnCombatBridge).Module, skipVisibility: true); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); LocalBuilder local = iLGenerator.DeclareLocal(stamp); Label label = iLGenerator.DefineLabel(); iLGenerator.Emit(OpCodes.Ldsfld, field); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Ldloca, local); iLGenerator.Emit(OpCodes.Callvirt, field.FieldType.GetMethod("TryGetValue")); iLGenerator.Emit(OpCodes.Brfalse, label); iLGenerator.Emit(OpCodes.Ldarg_1); iLGenerator.Emit(OpCodes.Ldloca, local); iLGenerator.Emit(OpCodes.Ldfld, stamp.GetField("At")); iLGenerator.Emit(OpCodes.Sub); iLGenerator.Emit(OpCodes.Ldc_R8, 5.0); iLGenerator.Emit(OpCodes.Clt); iLGenerator.Emit(OpCodes.Ret); iLGenerator.MarkLabel(label); iLGenerator.Emit(OpCodes.Ldc_I4_0); iLGenerator.Emit(OpCodes.Ret); return (Func<ZDOID, double, bool>)dynamicMethod.CreateDelegate(typeof(Func<ZDOID, double, bool>)); } private static Action<ZDOID, long, double> StampWriter(FieldInfo field, Type stamp) { DynamicMethod dynamicMethod = new DynamicMethod("BotanicCombatPendingWrite", typeof(void), new Type[3] { typeof(ZDOID), typeof(long), typeof(double) }, typeof(FgnCombatBridge).Module, skipVisibility: true); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); LocalBuilder local = iLGenerator.DeclareLocal(stamp); iLGenerator.Emit(OpCodes.Ldloca, local); iLGenerator.Emit(OpCodes.Initobj, stamp); iLGenerator.Emit(OpCodes.Ldloca, local); iLGenerator.Emit(OpCodes.Ldarg_1); iLGenerator.Emit(OpCodes.Stfld, stamp.GetField("Peer")); iLGenerator.Emit(OpCodes.Ldloca, local); iLGenerator.Emit(OpCodes.Ldarg_2); iLGenerator.Emit(OpCodes.Stfld, stamp.GetField("At")); iLGenerator.Emit(OpCodes.Ldsfld, field); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Ldloc, local); iLGenerator.Emit(OpCodes.Callvirt, field.FieldType.GetProperty("Item").GetSetMethod()); iLGenerator.Emit(OpCodes.Ret); return (Action<ZDOID, long, double>)dynamicMethod.CreateDelegate(typeof(Action<ZDOID, long, double>)); } } internal static class FgnTargetReader<TStamp> { private static readonly Func<long, double, TStamp> create = Create(); internal static void Initialize() { if (create == null) { throw new NotSupportedException(); } } internal static bool TryGetValue(Dictionary<ZDOID, TStamp> unused, ZDOID id, out TStamp value) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (!FgnCombatOwnership.ShouldOverride(id)) { return unused.TryGetValue(id, out value); } if (!FgnCombatOwnership.TryTargetPeer(id, out var peer) || peer == 0) { value = default(TStamp); return false; } value = create(peer, Time.realtimeSinceStartupAsDouble); return true; } private static Func<long, double, TStamp> Create() { DynamicMethod dynamicMethod = new DynamicMethod("BotanicCombatTargetStamp", typeof(TStamp), new Type[2] { typeof(long), typeof(double) }, typeof(FgnCombatBridge).Module, skipVisibility: true); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); LocalBuilder local = iLGenerator.DeclareLocal(typeof(TStamp)); iLGenerator.Emit(OpCodes.Ldloca, local); iLGenerator.Emit(OpCodes.Initobj, typeof(TStamp)); iLGenerator.Emit(OpCodes.Ldloca, local); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Stfld, typeof(TStamp).GetField("Peer")); iLGenerator.Emit(OpCodes.Ldloca, local); iLGenerator.Emit(OpCodes.Ldarg_1); iLGenerator.Emit(OpCodes.Stfld, typeof(TStamp).GetField("At")); iLGenerator.Emit(OpCodes.Ldloc, local); iLGenerator.Emit(OpCodes.Ret); return (Func<long, double, TStamp>)dynamicMethod.CreateDelegate(typeof(Func<long, double, TStamp>)); } } internal static class FgnCombatOwnership { private sealed class Report { internal ZDO Data; internal long Owner; internal uint Revision; internal ZDOID Target; } private sealed class Lease { internal ZDO Data; internal long ReturnPeer; internal long SourceOwner; internal uint SourceRevision; internal double Requested; internal uint Pass; } private sealed class Forward { internal ZDO Data; internal long Owner; internal double Until; } private sealed class Watch { internal ZDO Data; internal long Owner; internal uint Revision; internal uint Pass; internal bool Acknowledged; internal bool AttackRejected; internal bool AttackReady; } private const long Protocol = 3L; internal static bool Enabled; internal static FgnCombatBridge Fgn; private static ConfigEntry<bool> configured; private static Version detectedVersion; internal static string InstallationStatus = "not initialized"; private static ConfigEntry<int> maximumPing; private static ConfigEntry<float> nearbyRadius; private static Harmony harmony; private static Harmony sessionHarmony; private static bool serverConfirmed; private static ZDO localCapability; private static ConditionalWeakTable<BaseAI, Report> reports = new ConditionalWeakTable<BaseAI, Report>(); private static readonly Dictionary<ZDOID, Lease> managed = new Dictionary<ZDOID, Lease>(); private static readonly Dictionary<ZDOID, Forward> forwarded = new Dictionary<ZDOID, Forward>(); private static readonly Dictionary<ZDOID, Watch> watching = new Dictionary<ZDOID, Watch>(); private static readonly Dictionary<ZDOID, Report> receivedTargets = new Dictionary<ZDOID, Report>(); private static readonly List<ZDOID> scratch = new List<ZDOID>(); private static readonly KeyValuePair<int, int> targetHash = ZDO.GetHashZDOID("botanic.fgn.ai.target"); private static readonly int sourceHash = StringExtensionMethods.GetStableHashCode("botanic.fgn.ai.source"); private static readonly int revisionHash = StringExtensionMethods.GetStableHashCode("botanic.fgn.ai.revision"); private static readonly int capabilityHash = StringExtensionMethods.GetStableHashCode("botanic.fgn.ai.protocol"); private static readonly Func<BaseAI, ZNetView> aiView = FieldReader.Create<BaseAI, ZNetView>(AccessTools.Field(typeof(BaseAI), "m_nview")); private static ZDOMan world; private static ZNet network; private static int passMoves; private static uint pass; private static double forwardExpiry; private static bool collecting; private static bool Active { get { if (Enabled && Fgn != null) { return Fgn.Active(); } return false; } } internal static void Install(ConfigFile config, Assembly assembly, Version version) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Expected O, but got Unknown //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Expected O, but got Unknown configured = config.Bind<bool>("FGN AI Ownership", "EnableAIOwnership", assembly != null, "Use the mob's active AI player target instead of its last attacker for FGN ownership. The existing two-second scan enables target-change events only with two eligible nearby players. Ongoing attacks block transfer; attack rejection adds no cooldown and retries once after native attack end, even without a target change. All FGN protections and periodic retries remain. Default: on with FGN. Same version on server and clients; restart required. False keeps normal FGN ownership."); maximumPing = config.Bind<int>("FGN AI Ownership", "ServerFallbackPingMs", 200, new ConfigDescription("Target ping limit in milliseconds. Above it, server takeover requires another eligible player within ServerFallbackRadius and active FGN SSS. 0: target ping must exceed the best other active candidate's ping by 250 ms. Server setting.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 2000), new object[0])); nearbyRadius = config.Bind<float>("FGN AI Ownership", "ServerFallbackRadius", 6f, new ConfigDescription("Maximum distance in metres from the mob to another eligible player for high-ping server takeover. Only existing FGN candidates whose 3x3-sector scan includes the mob count. Otherwise the AI target keeps ownership. Server setting.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), new object[0])); detectedVersion = version; InstallationStatus = ((assembly == null) ? "FGN absent" : "disabled in config"); if (assembly != null) { try { sessionHarmony = new Harmony("botanic.pup.patch.fgn.aimode"); sessionHarmony.Patch((MethodBase)AccessTools.Method(typeof(ZNet), "OnNewConnection", (Type[])null, (Type[])null), Hook("SessionConnection"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } catch (Exception ex) { if (sessionHarmony != null) { try { sessionHarmony.UnpatchSelf(); } catch { } } InstallationStatus = "mode endpoint failed: " + ex.GetBaseException().Message; if (Plugin.Diagnostics) { Plugin.Warn("Optional FGN AI mode unavailable: " + ex.Message); } return; } } if (!configured.Value || assembly == null) { return; } try { Fgn = new FgnCombatBridge(assembly); RewriteTarget(PatchProcessor.GetOriginalInstructions((MethodBase)Fgn.TryHandOff, (ILGenerator)null)); RewriteVeto(PatchProcessor.GetOriginalInstructions((MethodBase)Fgn.Veto, (ILGenerator)null)); MethodInfo methodInfo = AccessTools.Method(typeof(ZDOMan), "ReleaseNearbyZDOS", (Type[])null, (Type[])null); RewriteNativeOwner(PatchProcessor.GetOriginalInstructions((MethodBase)methodInfo, (ILGenerator)null)); harmony = new Harmony("botanic.pup.patch.fgn.aiownership"); harmony.Patch((MethodBase)Fgn.TryHandOff, Hook("TryPrefix"), Hook("TryPostfix"), Hook("RewriteTarget"), (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)Fgn.Veto, (HarmonyMethod)null, Hook("VetoPostfix"), Hook("RewriteVeto"), (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)Fgn.OnResult, Hook("ResultPrefix"), Hook("ResultPostfix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)Fgn.Balance, Hook("BalancePrefix"), Hook("BalancePostfix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, Hook("RewriteNativeOwner"), (HarmonyMethod)null, (HarmonyMethod)null); FgnTargetEvents.Install(harmony, assembly, Watching, Observe, Fail); FgnAttackRetry.Install(harmony, OnAttackEnded, Fail); harmony.Patch((MethodBase)AccessTools.Method(typeof(BaseAI), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, Hook("AiAwakePostfix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(Player), "OnDestroy", (Type[])null, (Type[])null), Hook("PlayerDestroyPrefix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(ZNet), "SetCharacterID", (Type[])null, (Type[])null), (HarmonyMethod)null, Hook("CapabilityPostfix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(Character), "RPC_Damage", (Type[])null, (Type[])null), Hook("DamagePrefix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(ZNet), "Shutdown", (Type[])null, (Type[])null), Hook("Reset"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Enabled = true; InstallationStatus = "installed"; } catch (Exception ex2) { Enabled = false; if (harmony != null) { try { harmony.UnpatchSelf(); } catch { } } Fgn = null; InstallationStatus = "installation failed: " + ex2.GetBaseException().Message; if (Plugin.Diagnostics) { Plugin.Warn("Optional FGN AI ownership not installed: " + ex2.Message); } } } private static HarmonyMethod Hook(string name) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown return new HarmonyMethod(AccessTools.Method(typeof(FgnCombatOwnership), name, (Type[])null, (Type[])null)); } internal static IEnumerable<string> DescribeStatus() { yield return "BotanicPupPatch 2.1.0; FGN " + ((detectedVersion == null) ? "absent" : detectedVersion.ToString()); yield return "AI ownership: config=" + ((configured == null) ? "unknown" : configured.Value.ToString()) + "; hooks=" + Enabled + "; " + InstallationStatus; bool server = Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsDedicated(); yield return "Mode: " + ((!Object.op_Implicit((Object)(object)ZNet.instance)) ? "no session" : (server ? "dedicated server" : "client/local game")) + "; server balance=" + (server ? Active.ToString() : "n/a") + "; server confirmed=" + serverConfirmed; bool current = ZDOMan.instance != null && object.ReferenceEquals(world, ZDOMan.instance) && object.ReferenceEquals(network, ZNet.instance); yield return "Current session=" + current + "; watched=" + watching.Count + "; reports=" + receivedTargets.Count + "; server leases=" + managed.Count; if (!current || !Object.op_Implicit((Object)(object)ZNet.instance)) { yield break; } if (!server) { ZDO player = world.GetZDO(ZNet.instance.LocalPlayerCharacterID); yield return string.Concat("Local peer=", ZDOMan.GetSessionID(), "; player=", ZNet.instance.LocalPlayerCharacterID, "; protocol=", (player == null) ? "missing player ZDO" : player.GetLong(capabilityHash, 0L).ToString(), " (required: ", 3L, ")"); } else { if (Fgn == null) { yield break; } foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (peer != null) { ZDO player2 = world.GetZDO(peer.m_characterID); yield return string.Concat("Peer ", peer.m_uid, "; player=", peer.m_characterID, ": ready=", peer.IsReady(), "; FGN matched=", Fgn.Matched(peer), "; protocol=", (player2 == null) ? "missing player ZDO" : player2.GetLong(capabilityHash, 0L).ToString()); } } } } internal unsafe static string DescribeMob(ZDO data, BaseAI ai) { //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) if (data == null || !data.IsValid()) { return "mob ZDO unavailable"; } ZDOID target; string text = ((!ReadTarget(data, out target)) ? "missing/stale" : (((ZDOID)(ref target)).IsNone() ? "none/non-player" : ((object)(*(ZDOID*)(&target))/*cast due to .constrained prefix*/).ToString())); string text2 = "unavailable"; ZNetView val = (Object.op_Implicit((Object)(object)ai) ? aiView(ai) : null); if (Object.op_Implicit((Object)(object)ai) && Object.op_Implicit((Object)(object)val) && val.IsValid() && object.ReferenceEquals(val.GetZDO(), data)) { Character targetCreature = ai.GetTargetCreature(); text2 = ((Object.op_Implicit((Object)(object)targetCreature) && targetCreature is Player && !targetCreature.IsDead()) ? ((object)targetCreature.GetZDOID()/*cast due to .constrained prefix*/).ToString() : "none/non-player") + (val.IsOwner() ? " (authoritative)" : " (replica; not authoritative)"); } return string.Concat("mob=", data.m_uid, "; owner=", data.GetOwner(), "; revision=", data.OwnerRevision, "; rule=", DiagnosticRule(data), "; AI=", text2, "; report=", text, DiagnosticLastHit(data.m_uid)); } private static string DiagnosticRule(ZDO data) { //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) if (!Enabled || Fgn == null) { return "stock FGN: " + InstallationStatus; } if (!object.ReferenceEquals(world, ZDOMan.instance) || !object.ReferenceEquals(network, ZNet.instance) || !Object.op_Implicit((Object)(object)ZNet.instance)) { return "stock FGN: session not initialized"; } bool flag = ZNet.instance.IsDedicated(); if (flag && !Active) { return "stock FGN: server balance inactive"; } if (!flag && !serverConfirmed) { return "stock FGN: server mode unconfirmed"; } if (data.GetBool(ZDOVars.s_tamed, false)) { return "outside AI policy: tamed (ownership unchanged)"; } if (data.GetLong(ZDOVars.s_user, 0L) != 0) { return "outside AI policy: controlled/ridden"; } if (Fgn.Held(data)) { return "outside AI policy: FGN combat hold"; } if (Fgn.Possessed(data)) { return "outside AI policy: Valcast possessed"; } if (flag && data.GetOwner() == ZDOMan.GetSessionID() && !managed.ContainsKey(data.m_uid)) { return "outside AI policy: server-owned"; } if (flag && data.GetOwner() == ZDOMan.GetSessionID() && ShouldOverride(data.m_uid)) { return "AI target (temporary server lease)"; } if (flag && data.GetOwner() != ZDOMan.GetSessionID() && !Participating(ZNet.instance.GetPeer(data.GetOwner()))) { return "stock FGN: owner protocol/FGN participation missing"; } if (!flag && data.GetOwner() != ZDOMan.GetSessionID()) { return "observer: only the current owner receives the server watch"; } if (!Watched(data)) { return "stock FGN: not marked by two-player scan; check SERVER row"; } Watch watch = watching[data.m_uid]; if (flag && !watch.Acknowledged) { return "waiting for owner's initial target report"; } if (!ShouldOverride(data.m_uid)) { return "stock FGN: no valid target report"; } return "AI target"; } private static string DiagnosticLastHit(ZDOID id) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) if (Fgn == null) { return ""; } FieldInfo fieldInfo = AccessTools.Field(Fgn.TryHandOff.DeclaringType, "s_lastHitBy"); IDictionary dictionary = ((fieldInfo == null) ? null : (fieldInfo.GetValue(null) as IDictionary)); if (dictionary == null || !dictionary.Contains(id)) { return "; last attacker=none"; } object obj = dictionary[id]; Type type = obj.GetType(); long num = (long)type.GetField("Peer").GetValue(obj); double num2 = (double)type.GetField("At").GetValue(obj); return "; last attacker=" + num + "; age=" + (Time.realtimeSinceStartupAsDouble - num2).ToString("F1", CultureInfo.InvariantCulture) + "s"; } internal static string DescribeServerMob(ZDOID id) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_02ff: Unknown result type (might be due to invalid IL or missing references) //IL_0379: Unknown result type (might be due to invalid IL or missing references) //IL_03ef: Unknown result type (might be due to invalid IL or missing references) //IL_0488: Unknown result type (might be due to invalid IL or missing references) //IL_04c4: Unknown result type (might be due to invalid IL or missing references) //IL_04eb: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsDedicated()) { return "SERVER: dedicated session unavailable"; } if (Fgn == null || !Enabled) { return "SERVER: " + InstallationStatus; } ZDO val = ((ZDOMan.instance == null) ? null : ZDOMan.instance.GetZDO(id)); if (val == null || !val.IsValid()) { return string.Concat("SERVER mob=", id, ": ZDO unavailable"); } string text = "SERVER " + DescribeMob(val, null) + "; scan pass=" + pass; Type declaringType = Fgn.Balance.DeclaringType; FieldInfo fieldInfo = AccessTools.Field(declaringType, "s_prefabsScanned"); FieldInfo fieldInfo2 = AccessTools.Field(declaringType, "s_creaturePrefabs"); FieldInfo fieldInfo3 = AccessTools.Field(declaringType, "s_creatureTypeMask"); FieldInfo fieldInfo4 = AccessTools.Field(declaringType, "s_visited"); HashSet<int> hashSet = ((fieldInfo2 == null) ? null : (fieldInfo2.GetValue(null) as HashSet<int>)); HashSet<ZDOID> hashSet2 = ((fieldInfo4 == null) ? null : (fieldInfo4.GetValue(null) as HashSet<ZDOID>)); string text2 = text; text = text2 + "; next scan=" + (Fgn.NextPass() - Time.realtimeSinceStartupAsDouble).ToString("F1", CultureInfo.InvariantCulture) + "s; prefabs scanned=" + ((fieldInfo == null) ? "unknown" : fieldInfo.GetValue(null).ToString()) + "; prefab=" + ((hashSet == null) ? "unknown" : hashSet.Contains(val.GetPrefab()).ToString()) + "; type=" + ((fieldInfo3 == null) ? "unknown" : (((int)fieldInfo3.GetValue(null) & (1 << (int)val.Type)) != 0).ToString()) + "; visited=" + ((hashSet2 == null) ? "unknown" : hashSet2.Contains(id).ToString()); int num = 0; foreach (ZNetPeer candidate in Fgn.Candidates) { if (Candidate(candidate, val.GetPosition())) { num++; } } object obj = text; text = string.Concat(obj, "; FGN candidates=", Fgn.Candidates.Count, "; eligible near mob=", num); ZNetPeer peer = ZNet.instance.GetPeer(val.GetOwner()); ZDO val2 = ((ZDOMan.instance == null || peer == null) ? null : ZDOMan.instance.GetZDO(peer.m_characterID)); object obj2 = text; text = string.Concat(obj2, "; owner ready=", peer != null && peer.IsReady(), "; owner matched=", peer != null && Fgn.Matched(peer), "; owner in area=", Candidate(peer, val.GetPosition()), "; owner protocol=", (val2 == null) ? "missing player ZDO" : val2.GetLong(capabilityHash, 0L).ToString(), "; player ZDO owner=", (val2 == null) ? "missing" : val2.GetOwner().ToString()); if (watching.TryGetValue(id, out var value)) { object obj3 = text; text = string.Concat(obj3, "; watch owner=", value.Owner, "; watch revision=", value.Revision, "; acknowledged=", value.Acknowledged); } else { text += "; server watch=missing"; } object obj4 = text; long peer2; double value2; return string.Concat(obj4, "; reported target peer=", (!TryTargetPeer(id, out peer2)) ? "missing/stale" : ((peer2 == 0) ? "none/non-player" : peer2.ToString()), "; transfer pending=", Fgn.Pending(id, Time.realtimeSinceStartupAsDouble), "; cooldown=", (Fgn.Cooldowns.TryGetValue(id, out value2) ? Math.Max(0.0, value2 - Time.realtimeSinceStartupAsDouble) : 0.0).ToString("F1", CultureInfo.InvariantCulture), "s"); } private static void EnsureWorld() { if (!object.ReferenceEquals(world, ZDOMan.instance) || !object.ReferenceEquals(network, ZNet.instance)) { Reset(); world = ZDOMan.instance; network = ZNet.instance; if (world != null) { KeyValuePair<int, int> keyValuePair = targetHash; ZDOExtraData.AddSessionHash(keyValuePair.Key); KeyValuePair<int, int> keyValuePair2 = targetHash; ZDOExtraData.AddSessionHash(keyValuePair2.Value); ZDOExtraData.AddSessionHash(sourceHash); ZDOExtraData.AddSessionHash(revisionHash); ZDOExtraData.AddSessionHash(capabilityHash); } } } private static void Reset() { managed.Clear(); forwarded.Clear(); watching.Clear(); receivedTargets.Clear(); scratch.Clear(); reports = new ConditionalWeakTable<BaseAI, Report>(); FgnTargetEvents.Reset(); FgnAttackRetry.Reset(); collecting = false; FgnCombatStatus.Reset(); serverConfirmed = false; localCapability = null; world = null; network = null; passMoves = 0; forwardExpiry = 0.0; } internal static void Stop() { bool enabled = Enabled; Enabled = false; if (enabled) { InstallationStatus = "stopped"; } if (enabled) { NotifyServerOff(); } try { RevokeCapability(); ReleaseManaged(); } catch (Exception ex) { if (Plugin.Diagnostics) { Plugin.Warn("Optional FGN AI cleanup: " + ex.Message); } } finally { Enabled = false; Reset(); } if (harmony != null) { try { harmony.UnpatchSelf(); } catch (Exception ex2) { if (Plugin.Diagnostics) { Plugin.Warn(ex2.Message); } } } harmony = null; Fgn = null; if (sessionHarmony != null) { try { sessionHarmony.UnpatchSelf(); } catch (Exception ex3) { if (Plugin.Diagnostics) { Plugin.Warn(ex3.Message); } } } sessionHarmony = null; } private static void Fail(Exception error) { bool enabled = Enabled; Enabled = false; InstallationStatus = "runtime failure: " + error.GetBaseException().Message; if (enabled) { NotifyServerOff(); } try { RevokeCapability(); Enabled = false; ReleaseManaged(); } catch (Exception ex) { if (Plugin.Diagnostics) { Plugin.Warn("Optional FGN AI cleanup: " + ex.Message); } } finally { Enabled = false; managed.Clear(); forwarded.Clear(); watching.Clear(); receivedTargets.Clear(); FgnTargetEvents.Reset(); FgnAttackRetry.Reset(); forwardExpiry = 0.0; } if (Plugin.Diagnostics) { Plugin.Warn("Optional FGN AI ownership disabled: " + error.Message); } } private static void NotifyServerOff() { try { if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsDedicated()) { return; } foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (peer == null || !peer.IsReady() || peer.m_rpc == null) { continue; } try { peer.m_rpc.Invoke("Botanic_AI_Mode", new object[1] { 3 }); } catch (Exception ex) { if (Plugin.Diagnostics) { Plugin.Warn(ex.Message); } } } } catch (Exception ex2) { if (Plugin.Diagnostics) { Plugin.Warn(ex2.Message); } } } private static void ReleaseManaged() { //IL_00ad: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsDedicated() && object.ReferenceEquals(world, ZDOMan.instance)) { foreach (Lease value in managed.Values) { if (value.Data.IsValid() && value.Data.GetOwner() == ZDOMan.GetSessionID() && (Fgn == null || !Fgn.Possessed(value.Data))) { value.Data.SetOwner(0L); if (Fgn != null) { Fgn.ClearOwned(value.Data.m_uid); } } } } managed.Clear(); } private static void SessionConnection(ZNetPeer __0) { if (__0 == null || __0.m_rpc == null) { return; } ZNetPeer peer = __0; FgnCombatStatus.Connect(peer); peer.m_rpc.Register<int>("Botanic_AI_Mode", (Action<ZRpc, int>)delegate(ZRpc rpc, int mode) { //IL_00aa: Unknown result type (might be due to invalid IL or missing references) try { if (Object.op_Implicit((Object)(object)ZNet.instance)) { if (ZNet.instance.IsDedicated()) { if (mode == 1) { peer.m_rpc.Invoke("Botanic_AI_Mode", new object[1] { Active ? 5 : 3 }); } } else if (peer.m_server && object.ReferenceEquals(ZNet.instance.GetServerPeer(), peer) && (mode == 2 || mode == 3 || mode == 4 || mode == 5)) { EnsureWorld(); serverConfirmed = mode == 5; if (!serverConfirmed) { RevokeCapability(); } else { PublishCapability(ZNet.instance.LocalPlayerCharacterID); } } } } catch (Exception error) { Fail(error); } }); peer.m_rpc.Register<ZDOID, long, long>("Botanic_AI_Watch", (Action<ZRpc, ZDOID, long, long>)delegate(ZRpc rpc, ZDOID id, long owner, long revision) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) try { ReceiveWatch(peer, id, owner, revision); } catch (Exception error) { Fail(error); } }); peer.m_rpc.Register<ZDOID, ZDOID, long>("Botanic_AI_Target", (Action<ZRpc, ZDOID, ZDOID, long>)delegate(ZRpc rpc, ZDOID id, ZDOID target, long revision) { //IL_0006: 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) try { ReceiveTarget(peer, id, target, revision); } catch (Exception error) { Fail(error); } }); peer.m_rpc.Register<ZDOID, long>("Botanic_AI_AttackReady", (Action<ZRpc, ZDOID, long>)delegate(ZRpc rpc, ZDOID id, long revision) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) try { ReceiveAttackReady(peer, id, revision); } catch (Exception error) { Fail(error); } }); } private static void CapabilityPostfix(ZDOID __0) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) if (!Enabled || ZDOMan.instance == null || ((ZDOID)(ref __0)).IsNone()) { return; } try { EnsureWorld(); if (!ZNet.instance.IsDedicated()) { ZNetPeer serverPeer = ZNet.instance.GetServerPeer(); if (serverPeer != null && serverPeer.IsReady()) { serverPeer.m_rpc.Invoke("Botanic_AI_Mode", new object[1] { 1 }); } if (serverConfirmed) { PublishCapability(__0); } } } catch (Exception error) { Fail(error); } } private static void PublishCapability(ZDOID id) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (Enabled && serverConfirmed && world != null) { ZDO zDO = world.GetZDO(id); if (zDO != null && zDO.IsValid() && zDO.GetOwner() == ZDOMan.GetSessionID()) { zDO.Set(capabilityHash, 3L); localCapability = zDO; } } } private static void RevokeCapability() { if (localCapability != null && localCapability.IsValid() && object.ReferenceEquals(world, ZDOMan.instance) && localCapability.GetOwner() == ZDOMan.GetSessionID()) { localCapability.Set(capabilityHash, 0L); } localCapability = null; serverConfirmed = false; if (Object.op_Implicit((Object)(object)ZNet.instance) && !ZNet.instance.IsDedicated()) { watching.Clear(); receivedTargets.Clear(); FgnTargetEvents.Reset(); FgnAttackRetry.Reset(); } } internal static bool ShouldOverride(ZDOID mob) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) if (!Enabled || Fgn == null || ZDOMan.instance == null || !Object.op_Implicit((Object)(object)ZNet.instance)) { return false; } ZDO zDO = ZDOMan.instance.GetZDO(mob); if (zDO == null || !zDO.IsValid() || Fgn.Possessed(zDO)) { return false; } if (ZNet.instance.IsDedicated() && zDO.GetOwner() == ZDOMan.GetSessionID() && managed.TryGetValue(mob, out var value) && object.ReferenceEquals(value.Data, zDO)) { return true; } ZNetPeer peer = ZNet.instance.GetPeer(zDO.GetOwner()); if (!ZNet.instance.IsDedicated()) { ZDOID target; if (serverConfirmed && Watched(zDO)) { return ReadTarget(zDO, out target); } return false; } if (Participating(peer) && Watched(zDO) && watching.TryGetValue(mob, out var value2)) { return value2.Acknowledged; } return false; } private static bool Participating(ZNetPeer peer) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) if (peer == null || !peer.IsReady() || !Fgn.Matched(peer) || ((ZDOID)(ref peer.m_characterID)).IsNone()) { return false; } ZDO zDO = world.GetZDO(peer.m_characterID); if (zDO != null && zDO.IsValid() && zDO.GetOwner() == peer.m_uid) { return zDO.GetLong(capabilityHash, 0L) == 3; } return false; } private static void AiAwakePostfix(BaseAI __instance) { if (Watching(__instance)) { FgnTargetEvents.Schedule(__instance); } } private static void PlayerDestroyPrefix(Player __instance) { if (!Enabled || watching.Count == 0 || object.ReferenceEquals(__instance, null) || !Object.op_Implicit((Object)(object)ZNetScene.instance) || !object.ReferenceEquals(world, ZDOMan.instance) || !object.ReferenceEquals(network, ZNet.instance)) { return; } try { long sessionID = ZDOMan.GetSessionID(); foreach (Watch value in watching.Values) { if (value.Owner == sessionID) { ZNetView val = ((value.Data == null) ? null : ZNetScene.instance.FindInstance(value.Data)); BaseAI val2 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<BaseAI>() : null); if (Watching(val2) && object.ReferenceEquals(val2.GetTargetCreature(), __instance)) { FgnTargetEvents.Schedule(val2); } } } } catch (Exception error) { Fail(error); } } private static bool Watched(ZDO data) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (data != null && watching.TryGetValue(data.m_uid, out var value) && (value.Data == null || object.ReferenceEquals(value.Data, data)) && value.Owner == data.GetOwner()) { return value.Revision == data.OwnerRevision; } return false; } internal static bool Watching(BaseAI ai) { if (!Enabled || !Object.op_Implicit((Object)(object)ai) || !((Behaviour)ai).isActiveAndEnabled || !Object.op_Implicit((Object)(object)ZNet.instance) || ZDOMan.instance == null || (!ZNet.instance.IsDedicated() && !serverConfirmed)) { return false; } ZNetView val = aiView(ai); if (Object.op_Implicit((Object)(object)val) && val.IsValid() && val.IsOwner() && object.ReferenceEquals(world, ZDOMan.instance) && object.ReferenceEquals(network, ZNet.instance)) { return Watched(val.GetZDO()); } return false; } internal static void Observe(BaseAI ai) { //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0175: 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_0193: 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_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_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) if (!Watching(ai)) { return; } try { if (!Object.op_Implicit((Object)(object)ZNet.instance) || (!ZNet.instance.IsDedicated() && !serverConfirmed)) { return; } ZNetView val = aiView(ai); if (!Object.op_Implicit((Object)(object)val) || !val.IsValid() || !val.IsOwner()) { return; } ZDO zDO = val.GetZDO(); if (zDO.GetBool(ZDOVars.s_tamed, false) || zDO.GetLong(ZDOVars.s_user, 0L) != 0) { return; } EnsureWorld(); Watch watch = watching[zDO.m_uid]; if (watch.Data == null) { watch.Data = zDO; } Character targetCreature = ai.GetTargetCreature(); ZDOID val2 = ((Object.op_Implicit((Object)(object)targetCreature) && targetCreature is Player && !targetCreature.IsDead()) ? targetCreature.GetZDOID() : ZDOID.None); Report orCreateValue = reports.GetOrCreateValue(ai); long owner = zDO.GetOwner(); if (object.ReferenceEquals(orCreateValue.Data, zDO) && orCreateValue.Owner == owner && orCreateValue.Revision == zDO.OwnerRevision && orCreateValue.Target == val2) { return; } zDO.Set(targetHash, val2); zDO.Set(sourceHash, owner); zDO.Set(revisionHash, (long)zDO.OwnerRevision); orCreateValue.Data = zDO; orCreateValue.Owner = owner; orCreateValue.Revision = zDO.OwnerRevision; orCreateValue.Target = val2; if (ZNet.instance.IsDedicated()) { watch.Acknowledged = true; receivedTargets[zDO.m_uid] = orCreateValue; ProcessTargetEvent(zDO, val2); return; } ZNetPeer serverPeer = ZNet.instance.GetServerPeer(); if (serverPeer != null && serverPeer.IsReady()) { serverPeer.m_rpc.Invoke("Botanic_AI_Target", new object[3] { zDO.m_uid, val2, (long)zDO.OwnerRevision }); } } catch (Exception error) { Fail(error); } } internal static bool ReadTarget(ZDO data, out ZDOID target) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) target = ZDOID.None; if (data != null && data.IsValid() && Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsDedicated() && object.ReferenceEquals(world, ZDOMan.instance) && receivedTargets.TryGetValue(data.m_uid, out var value) && object.ReferenceEquals(value.Data, data) && value.Owner == data.GetOwner() && value.Revision == data.OwnerRevision) { target = value.Target; return true; } if (data == null || !data.IsValid() || data.GetOwner() == 0 || data.GetLong(sourceHash, 0L) != data.GetOwner() || data.GetLong(revisionHash, -1L) != data.OwnerRevision) { return false; } target = data.GetZDOID(targetHash); return true; } internal static bool TryTargetPeer(ZDOID mob, out long peer) { //IL_0010: 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_0057: Unknown result type (might be due to invalid IL or missing references) peer = 0L; if (ZDOMan.instance == null || !ReadTarget(ZDOMan.instance.GetZDO(mob), out var target)) { return false; } if (((ZDOID)(ref target)).IsNone()) { return true; } foreach (ZNetPeer peer2 in ZNet.instance.GetPeers()) { if (peer2 != null && peer2.IsReady() && peer2.m_characterID == target) { peer = peer2.m_uid; return true; } } return false; } private static void ReceiveWatch(ZNetPeer peer, ZDOID id, long owner, long revision) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) if (Enabled && Object.op_Implicit((Object)(object)ZNet.instance) && !ZNet.instance.IsDedicated() && serverConfirmed && peer.m_server && object.ReferenceEquals(ZNet.instance.GetServerPeer(), peer) && !((ZDOID)(ref id)).IsNone() && revision >= 0 && revision <= 65535) { EnsureWorld(); if (owner == 0) { watching.Remove(id); receivedTargets.Remove(id); } else if (owner == ZDOMan.GetSessionID()) { watching[id] = new Watch { Data = world.GetZDO(id), Owner = owner, Revision = (uint)revision }; QueueBootstrap(world.GetZDO(id)); } } } private static void ReceiveTarget(ZNetPeer peer, ZDOID id, ZDOID target, long revision) { //IL_0070: 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_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) if (!Active || !ZNet.instance.IsDedicated() || world == null || !object.ReferenceEquals(world, ZDOMan.instance) || !object.ReferenceEquals(network, ZNet.instance) || revision < 0 || revision > 65535 || !Participating(peer) || !object.ReferenceEquals(network.GetPeer(peer.m_uid), peer)) { return; } ZDO zDO = world.GetZDO(id); if (Eligible(zDO) && zDO.GetOwner() == peer.m_uid && zDO.OwnerRevision == revision && Watched(zDO) && watching.TryGetValue(id, out var value)) { Report value2; bool flag = receivedTargets.TryGetValue(id, out value2) && object.ReferenceEquals(value2.Data, zDO) && value2.Owner == peer.m_uid && value2.Revision == revision; value.Acknowledged = true; if (!flag || !(value2.Target == target)) { receivedTargets[id] = new Report { Data = zDO, Owner = peer.m_uid, Revision = (uint)revision, Target = target }; ProcessTargetEvent(zDO, target); } } } private static void ProcessTargetEvent(ZDO data, ZDOID target) { if (!((ZDOID)(ref target)).IsNone() && Active && Watched(data)) { Fgn.TryTransfer(data, Time.realtimeSinceStartupAsDouble); } } private static void RememberAttack(ZDO data, Character mob) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) if (Enabled && Fgn != null && Object.op_Implicit((Object)(object)ZNet.instance) && ZDOMan.instance != null && (ZNet.instance.IsDedicated() || serverConfirmed) && object.ReferenceEquals(world, ZDOMan.instance) && object.ReferenceEquals(network, ZNet.instance) && Eligible(data) && data.GetOwner() == ZDOMan.GetSessionID() && ShouldOverride(data.m_uid) && ReadTarget(data, out var target) && !((ZDOID)(ref target)).IsNone()) { if (!Object.op_Implicit((Object)(object)mob)) { mob = LoadedCharacter(data); } if (Object.op_Implicit((Object)(object)mob)) { FgnAttackRetry.Arm(mob, data); } } } private static void OnAttackEnded(Humanoid mob, ZDO data) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) if (!Enabled || Fgn == null || !Object.op_Implicit((Object)(object)ZNet.instance) || !Eligible(data) || !object.ReferenceEquals(world, ZDOMan.instance) || !object.ReferenceEquals(network, ZNet.instance) || !object.ReferenceEquals(LoadedCharacter(data), mob) || data.GetOwner() != ZDOMan.GetSessionID() || !ShouldOverride(data.m_uid)) { return; } if (((Character)mob).InAttack()) { FgnAttackRetry.Arm((Character)(object)mob, data); return; } BaseAI component = ((Component)mob).GetComponent<BaseAI>(); Player val = (Player)(Object.op_Implicit((Object)(object)component) ? /*isinst with value type is only supported in some contexts*/: null); if (!Object.op_Implicit((Object)(object)val) || ((Character)val).IsDead()) { return; } if (ZNet.instance.IsDedicated()) { if (Active) { CaptureLeaseTarget(data); Fgn.TryTransfer(data, Time.realtimeSinceStartupAsDouble); } } else { if (!serverConfirmed || !Watching(component)) { return; } ZDOID zDOID = ((Character)val).GetZDOID(); if (!ReadTarget(data, out var target) || target != zDOID) { Observe(component); return; } ZNetPeer serverPeer = ZNet.instance.GetServerPeer(); if (serverPeer != null && serverPeer.IsReady()) { serverPeer.m_rpc.Invoke("Botanic_AI_AttackReady", new object[2] { data.m_uid, (long)data.OwnerRevision }); } } } private static void ReceiveAttackReady(ZNetPeer peer, ZDOID id, long revision) { //IL_0070: 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_00d4: 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 (!Active || !ZNet.instance.IsDedicated() || world == null || !object.ReferenceEquals(world, ZDOMan.instance) || !object.ReferenceEquals(network, ZNet.instance) || revision < 0 || revision > 65535 || !Participating(peer) || !object.ReferenceEquals(network.GetPeer(peer.m_uid), peer)) { return; } ZDO zDO = world.GetZDO(id); if (Eligible(zDO) && zDO.GetOwner() == peer.m_uid && zDO.OwnerRevision == revision && Watched(zDO) && watching.TryGetValue(id, out var value) && value.Acknowledged && ReadTarget(zDO, out var target) && !((ZDOID)(ref target)).IsNone()) { if (Fgn.Pending(id, Time.realtimeSinceStartupAsDouble)) { value.AttackReady = true; } else if (value.AttackRejected) { value.AttackReady = (value.AttackRejected = false); ProcessTargetEvent(zDO, target); } } } private static void QueueBootstrap(ZDO data) { ZNetView val = ((data != null && Object.op_Implicit((Object)(object)ZNetScene.instance)) ? ZNetScene.instance.FindInstance(data) : null); BaseAI val2 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<BaseAI>() : null); if (Object.op_Implicit((Object)(object)val2)) { reports.Remove(val2); FgnTargetEvents.Schedule(val2); } } private static bool TwoCandidates(ZDO data) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: 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) int num = 0; Vector3 position = data.GetPosition(); foreach (ZNetPeer candidate in Fgn.Candidates) { if (Candidate(candidate, position) && ++num >= 2) { return true; } } return false; } private static bool MarkWatch(ZDO data) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_009f: 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_0129: Unknown result type (might be due to invalid IL or missing references) long owner = data.GetOwner(); bool flag = owner == ZDOMan.GetSessionID() && managed.ContainsKey(data.m_uid); ZNetPeer peer = ZNet.instance.GetPeer(owner); if (!Eligible(data) || (!flag && (!Participating(peer) || !Candidate(peer, data.GetPosition()))) || !TwoCandidates(data)) { RemoveWatch(data.m_uid); return false; } if (!watching.TryGetValue(data.m_uid, out var value) || !object.ReferenceEquals(value.Data, data) || value.Owner != owner || value.Revision != data.OwnerRevision) { RemoveWatch(data.m_uid); Watch watch = new Watch(); watch.Data = data; watch.Owner = owner; watch.Revision = data.OwnerRevision; value = watch; watching[data.m_uid] = value; } value.Pass = pass; if (!value.Acknowledged) { if (owner == ZDOMan.GetSessionID()) { QueueBootstrap(data); } else { ZNetPeer peer2 = ZNet.instance.GetPeer(owner); peer2.m_rpc.Invoke("Botanic_AI_Watch", new object[3] { data.m_uid, owner, (long)data.OwnerRevision }); } } return true; } private static void RemoveWatch(ZDOID id) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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_00ad: Unknown result type (might be due to invalid IL or missing references) if (!watching.TryGetValue(id, out var value)) { return; } watching.Remove(id); if (!managed.ContainsKey(id) || value.Data == null || value.Data.GetOwner() != ZDOMan.GetSessionID()) { receivedTargets.Remove(id); } if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsDedicated() && value.Owner != ZDOMan.GetSessionID()) { ZNetPeer peer = ZNet.instance.GetPeer(value.Owner); if (peer != null && peer.IsReady() && peer.m_rpc != null) { peer.m_rpc.Invoke("Botanic_AI_Watch", new object[3] { id, 0L, (long)value.Revision }); } } } private static void BalancePrefix(out bool __state) { __state = false; if (!Enabled || !Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsDedicated()) { return; } collecting = false; try { EnsureWorld(); if (!Active) { ReleaseManaged(); ClearWatches(); PruneForwarded(); return; } __state = Time.realtimeSinceStartupAsDouble >= Fgn.NextPass(); if (__state) { passMoves = 0; pass++; Fgn.PerOwner.Clear(); collecting = true; } } catch (Exception error) { Fail(error); } } private static void BalancePostfix(bool __state) { //IL_0030: 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_003b: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) collecting = false; if (!__state || !Active) { return; } try { scratch.Clear(); foreach (ZDOID key in watching.Keys) { scratch.Add(key); } foreach (ZDOID item in scratch) { if (watching.TryGetValue(item, out var value) && value.Pass != pass) { ZDO zDO = world.GetZDO(item); if (object.ReferenceEquals(zDO, value.Data) && zDO.IsValid()) { MarkWatch(zDO); } else { RemoveWatch(item); } } } scratch.Clear(); PruneForwarded(); scratch.Clear(); foreach (ZDOID key2 in managed.Keys) { scratch.Add(key2); } foreach (ZDOID item2 in scratch) { if (!managed.TryGetValue(item2, out var value2)) { continue; } ZDO zDO2 = world.GetZDO(item2); if (!object.ReferenceEquals(zDO2, value2.Data) || !Eligible(zDO2) || !Object.op_Implicit((Object)(object)LoadedCharacter(zDO2))) { managed.Remove(item2); if (!watching.ContainsKey(item2)) { receivedTargets.Remove(item2); } } else if (zDO2.GetOwner() != ZDOMan.GetSessionID()) { if (Time.realtimeSinceStartupAsDouble - value2.Requested >= 5.0) { managed.Remove(item2); if (!watching.ContainsKey(item2)) { receivedTargets.Remove(item2); } } } else if (passMoves < 16 && value2.Pass != pass) { bool result = false; Handle(zDO2, Time.realtimeSinceStartupAsDouble, ref result); if (result) { passMoves++; } } } scratch.Clear(); } catch (Exception error) { Fail(error); } } private static void ClearWatches() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) if (watching.Count == 0 && receivedTargets.Count == 0) { return; } scratch.Clear(); foreach (ZDOID key in watching.Keys) { scratch.Add(key); } foreach (ZDOID item in scratch) { RemoveWatch(item); } scratch.Clear(); receivedTargets.Clear(); FgnTargetEvents.Reset(); FgnAttackRetry.Reset(); } private static void CaptureLeaseTarget(ZDO data) { //IL_006e: 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_0083: 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_00cf: 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_0076: Unknown result type (might be due to invalid IL or missing references) Character val = LoadedCharacter(data); BaseAI val2 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<BaseAI>() : null); ZNetView val3 = (Object.op_Implicit((Object)(object)val2) ? aiView(val2) : null); if (Object.op_Implicit((Object)(object)val3) && val3.IsOwner() && object.ReferenceEquals(val3.GetZDO(), data)) { Character targetCreature = val2.GetTargetCreature(); ZDOID target = ((Object.op_Implicit((Object)(object)targetCreature) && targetCreature is Player && !targetCreature.IsDead()) ? targetCreature.GetZDOID() : ZDOID.None); if (!receivedTargets.TryGetValue(data.m_uid, out var value)) { value = (receivedTargets[data.m_uid] = new Report()); } value.Data = data; value.Owner = data.GetOwner(); value.Revision = data.OwnerRevision; value.Target = target; } } private static void PruneForwarded() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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) //IL_008d: 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_00a2: Unknown result type (might be due to invalid IL or missing references) double realtimeSinceStartupAsDouble = Time.realtimeSinceStartupAsDouble; if (forwarded.Count == 0 || realtimeSinceStartupAsDouble < forwardExpiry) { return; } scratch.Clear(); foreach (ZDOID key in forwarded.Keys) { scratch.Add(key); } forwardExpiry = double.MaxValue; foreach (ZDOID item in scratch) { Forward forward = forwarded[item]; if (realtimeSinceStartupAsDouble >= forward.Until || !object.ReferenceEquals(world.GetZDO(item), forward.Data) || forward.Data.GetOwner() != forward.Owner) { forwarded.Remove(item); } else { forwardExpiry = Math.Min(forwardExpiry, forward.Until); } } scratch.Clear(); } private static bool TryPrefix(ZDO __0, double __1, ref bool __result) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (!Active) { return true; } try { if (__0 == null) { return true; } if (collecting && __0 != null && __0.IsValid()) { MarkWatch(__0); } if (watching.TryGetValue(__0.m_uid, out var value) && Watched(__0) && !value.Acknowledged) { __result = false; return false; } if (passMoves >= 16) { __result = false; return false; } return Handle(__0, __1, ref __result); } catch (Exception error) { Fail(error); return true; } } private static void TryPostfix(bool __result) { if (Enabled && __result) { passMoves++; } } private static bool Handle(ZDO data, double now, ref bool result) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_010e: 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_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) result = false; if (!Eligible(data)) { if (data != null) { managed.Remove(data.m_uid); if (!watching.ContainsKey(data.m_uid)) { receivedTargets.Remove(data.m_uid); } } return false; } long owner = data.GetOwner(); long sessionID = ZDOMan.GetSessionID(); Lease value; bool flag = managed.TryGetValue(data.m_uid, out value) && object.ReferenceEquals(value.Data, data); if (flag) { value.Pass = pass; } if (owner == sessionID && !flag) { return true; } if (owner == sessionID && flag && !Watched(data)) { CaptureLeaseTarget(data); } if (owner != sessionID && !Candidate(ZNet.instance.GetPeer(owner), data.GetPosition())) { return true; } if (!ShouldOverride(data.m_uid)) { return true; } if (!TryTargetPeer(data.m_uid, out var peer)) { return false; } ZNetPeer val = ((peer == 0) ? null : ZNet.instance.GetPeer(peer)); if (val != null && !Candidate(val, data.GetPosition())) { if (owner == sessionID) { ZNetPeer val2 = BestCandidate(data.GetPosition()); if (val2 != null) { result = Request(data, val2.m_uid, now); } else { managed.Remove(data.m_uid); receivedTargets.Remove(data.m_uid); data.SetOwner(0L); Fgn.ClearOwned(data.m_uid); } } return false; } if (val == null) { if (owner != sessionID) { return true; } ZNetPeer val3 = ZNet.instance.GetPeer(value.ReturnPeer); if (!Candidate(val3, data.GetPosition())) { val3 = BestCandidate(data.GetPosition()); } if (val3 != null) { result = Request(data, val3.m_uid, now); } else { managed.Remove(data.m_uid); receivedTargets.Remove(data.m_uid); data.SetOwner(0L); Fgn.ClearOwned(data.m_uid); } return false; } bool flag2 = HighPing(val, data.GetPosition()); bool flag3 = flag2 && OtherPlayerNearby(val, data); if (flag2 && flag3 && Fgn.Simulation()) { if (owner == sessionID) { return false; } if (!ServerReady(data)) { return false; } result = Request(data, sessionID, now); if (result) { managed[data.m_uid] = new Lease { Data = data, ReturnPeer = val.m_uid, SourceOwner = owner, SourceRevision = data.OwnerRevision, Requested = now, Pass = pass }; } return false; } if (owner == sessionID || flag2) { if (owner != val.m_uid) { result = Request(data, val.m_uid, now); } return false; } return true; } private static bool HighPing(ZNetPeer target, Vector3 position) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) if (!Fgn.TryMeasuredRtt(target, out var value)) { return false; } if (maximumPing.Value > 0) { return value > (float)maximumPing.Value; } float num = float.MaxValue; foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (peer != target && Candidate(peer, position) && Fgn.TryMeasuredRtt(peer, out var value2)) { num = Math.Min(num, value2); } } if (num < float.MaxValue) { return value > num + 250f; } return false; } private static bool OtherPlayerNearby(ZNetPeer target, ZDO data) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00de: 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_00e9: 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_00ef: Unknown result type (might be due to invalid IL or missing references) Vector3 position = data.GetPosition(); Vector2s sector = data.GetSector(); foreach (ZNetPeer candidate in Fgn.Candidates) { if (candidate == target || !Candidate(candidate, position) || ((ZDOID)(ref candidate.m_characterID)).IsNone()) { continue; } Vector2s zone = ZoneSystem.GetZone(candidate.GetRefPos()); if (Math.Abs(sector.x - zone.x) > 1 || Math.Abs(sector.y - zone.y) > 1) { continue; } ZDO zDO = world.GetZDO(candidate.m_characterID); if (zDO == null || !zDO.IsValid() || zDO.GetOwner() != candidate.m_uid || zDO.GetFloat(ZDOVars.s_health, 1f) <= 0f) { continue; } Vector3 position2 = zDO.GetPosition(); if (Finite(position2)) { Vector3 val = position2 - position; if (((Vector3)(ref val)).sqrMagnitude <= nearbyRadius.Value * nearbyRadius.Value) { return true; } } } return false; } private static bool Candidate(ZNetPeer peer, Vector3 position) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) if (peer != null && peer.IsReady() && Finite(peer.GetRefPos()) && peer.GetRefPos() != Vector3.zero && Fgn.Matched(peer)) { return ZNetScene.InActiveArea(position, peer.GetRefPos()); } return false; } private static ZNetPeer BestCandidate(Vector3 position) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) ZNetPeer result = null; float num = float.MaxValue; foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (Candidate(peer, position) && Fgn.Rtt(peer) < num) { result = peer; num = Fgn.Rtt(peer); } } return result; } private static bool Eligible(ZDO data) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (data != null && data.IsValid() && !((ZDOID)(ref data.m_uid)).IsNone() && data.GetOwner() != 0 && Finite(data.GetPosition()) && !data.GetBool(ZDOVars.s_tamed, false) && data.GetLong(ZDOVars.s_user, 0L) == 0 && !Fgn.Held(data)) { return !Fgn.Possessed(data); } return false; } private static Character LoadedCharacter(ZDO data) { ZNetView val = (Object.op_Implicit((Object)(object)ZNetScene.instance) ? ZNetScene.instance.FindInstance(data) : null); if (!Object.op_Implicit((Object)(object)val) || !val.IsValid() || val.m_distant || !((Component)val).gameObject.activeInHierarchy || (Object)(object)((Component)val).transform.parent != (Object)null || !object.ReferenceEquals(val.GetZDO(), data)) { return null; } Character component = ((Component)val).GetComponent<Character>(); if (!Object.op_Implicit((Object)(object)component) || component is Player || !((Behaviour)component).isActiveAndEnabled || component.IsDead() || component.IsBoss() || component.IsTamed() || component.IsAttached() || component.IsRiding()) { return null; } BaseAI component2 = ((Component)val).GetComponent<BaseAI>(); ZSyncTransform component3 = ((Component)val).GetComponent<ZSyncTransform>(); if (!Object.op_Implicit((Object)(object)component2) || !((Behaviour)component2).isActiveAndEnabled || component2.HaveRider() || !Object.op_Implicit((Object)(object)component3) || !((Behaviour)component3).isActiveAndEnabled || !component3.m_syncPosition) { return null; } return component; } private static bool ServerReady(ZDO data) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_002c: 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_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_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) Character val = LoadedCharacter(data); NativePup native = Plugin.Native; Vector3 position = data.GetPosition(); if (Object.op_Implicit((Object)(object)val) && native != null && native.Active && ZNetScene.instance.IsAreaReady(position) && native.ReadyPoint(position, 16f)) { Vector3 position2 = ((Component)val).transform.position; if ((((Vector3)(ref position2)).Equals(position) || native.ReadyPoint(((Component)val).transform.position, 16f)) && data.IsValid() && data.GetPosition() == position) { return Eligible(data); } } return false; } private static bool Finite(Vector3 point) { if (!float.IsNaN(point.x) && !float.IsNaN(point.y) && !float.IsNaN(point.z) && !float.IsInfinity(point.x) && !float.IsInfinity(point.y)) { return !float.IsInfinity(point.z); } return false; } private static bool Request(ZDO data, long target, double now) { //IL_002a: 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_0191: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: 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_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) long owner = data.GetOwner(); long sessionID = ZDOMan.GetSessionID(); if (target == 0 || target == owner || passMoves >= 16 || Fgn.Pending(data.m_uid, now) || (Fgn.Cooldowns.TryGetValue(data.m_uid, out var value) && now < value)) { return false; } Fgn.PerOwner.TryGetValue(owner, out var value2); if (value2 >= 6) { return false; } if (owner == sessionID) { Character val = LoadedCharacter(data); if (!Object.op_Implicit((Object)(object)val)) { return false; } if (val.InAttack()) { RememberAttack(data, val); return false; } if (val.IsStaggering() || !ServerReady(data) || !Candidate(ZNet.instance.GetPeer(target), data.GetPosition())) { return false; } world.ForceSendZDO(data.m_uid); data.SetOwner(target); managed.Remove(data.m_uid); receivedTargets.Remove(data.m_uid); Fgn.ClearOwned(data.m_uid); forwarded[data.m_uid] = new Forward { Data = data, Owner = target, Until = now + 5.0 }; if (forwarded.Count == 1 || forwardExpiry > now + 5.0) { forwardExpiry = now + 5.0; } } else { ZNetPeer peer = ZNet.instance.GetPeer(owner); if (!Candidate(peer, data.GetPosition())) { return false; } peer.m_rpc.Invoke("FGN_HandOff", new object[2] { data.m_uid, target }); } Fgn.PerOwner[owner] = value2 + 1; Fgn.MarkPending(data.m_uid, target, now); Fgn.ClearStreak(data.m_uid); return true; } private static void NativeSetOwner(ZDO data, long owner) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: 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_00f9: Unknown result type (might be due to invalid IL or missing references) if (!Enabled || managed.Count == 0 || !object.ReferenceEquals(world, ZDOMan.instance) || !object.ReferenceEquals(network, ZNet.instance) || !managed.TryGetValue(data.m_uid, out var value) || !object.ReferenceEquals(value.Data, data) || !Active || !Eligible(data) || (data.GetOwner() != ZDOMan.GetSessionID() && (data.GetOwner() != value.SourceOwner || data.OwnerRevision != value.SourceRevision || !(Time.realtimeSinceStartupAsDouble - value.Requested < 5.0) || !Fgn.Pending(data.m_uid, Time.realtimeSinceStartupAsDouble) || !Candidate(ZNet.instance.GetPeer(value.SourceOwner), data.GetPosition()) || !ShouldOverride(data.m_uid)))) { data.SetOwner(owner); } } private static bool LocalHit(Dictionary<ZDOID, double> hits, ZDOID id, out double value) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) if (ShouldOverride(id) && ReadTarget(ZDOMan.instance.GetZDO(id), out var _)) { value = 0.0; return false; } return hits.TryGetValue(id, out value); } private static void ResultPrefix(ZRpc __0, ZDOID __1, bool __2, string __3, out double __state) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) __state = 0.0; if (__2 || __3 != "attacking" || __0 == null || !Enabled || Fgn == null || ZDOMan.instance == null || !Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsDedicated() || !object.ReferenceEquals(world, ZDOMan.instance) || !object.ReferenceEquals(network, ZNet.instance)) { return; } try { if (!Active) { return; } ZDO zDO = world.GetZDO(__1); if (!Eligible(zDO) || !ShouldOverride(__1) || !ReadTarget(zDO, out var target) || ((ZDOID)(ref target)).IsNone()) { return; } ZNetPeer peer = network.GetPeer(zDO.GetOwner()); if (peer != null && object.ReferenceEquals(peer.m_rpc, __0)) { double realtimeSinceStartupAsDouble = Time.realtimeSinceStartupAsDouble; if (Fgn.Pending(__1, realtimeSinceStartupAsDouble)) { __state = realtimeSinceStartupAsDouble + 6.0; } } } catch (Exception error) { Fail(error); } } private static void ResultPostfix(ZDOID __1, double __state) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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_009d: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) if (__state <= 0.0 || !Enabled || Fgn == null || !object.ReferenceEquals(world, ZDOMan.instance) || !object.ReferenceEquals(network, ZNet.instance)) { return; } double realtimeSinceStartupAsDouble = Time.realtimeSinceStartupAsDouble; if (Fgn.Cooldowns.TryGetValue(__1, out var value) && value >= __state && value <= realtimeSinceStartupAsDouble + 6.0) { Fgn.Cooldowns.Remove(__1); } try { ZDO zDO = world.GetZDO(__1); if (Watched(zDO) && watching.TryGetValue(__1, out var value2) && ShouldOverride(__1) && ReadTarget(zDO, out var target) && !((ZDOID)(ref target)).IsNone()) { value2.AttackRejected = true; if (value2.AttackReady) { value2.AttackReady = (value2.AttackRejected = false); ProcessTargetEvent(zDO, target); } } } catch (Exception error) { Fail(error); } } private static void VetoPostfix(ZDO __0, long __1, ref string __result) { //IL_0155: Unknown result type (might be due to invalid IL or missing references) if (__result == "attacking") { try { RememberAttack(__0, null); return; } catch (Exception error) { Fail(error); return; } } if (__result != null || !Enabled || !Object.op_Implicit((Object)(object)ZNet.instance) || ZNet.instance.IsDedicated() || !serverConfirmed || !object.ReferenceEquals(world, ZDOMan.instance) || !object.ReferenceEquals(network, ZNet.instance) || __0 == null || !Watched(__0) || __0.GetOwner() != ZDOMan.GetSessionID()) { return; } try { if (!Eligible(__0)) { return; } ZNetPeer serverPeer = ZNet.instance.GetServerPeer(); if (serverPeer != null && serverPeer.m_server && serverPeer.IsReady() && __1 == serverPeer.m_uid) { return; } ZNetView val = (Object.op_Implicit((Object)(object)ZNetScene.instance) ? ZNetScene.instance.FindInstance(__0) : null); BaseAI val2 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<BaseAI>() : null); if (!Watching(val2)) { return; } Character targetCreature = val2.GetTargetCreature(); Player val3 = (Player)(object)((targetCreature is Player) ? targetCreature : null); if (!Object.op_Implicit((Object)(object)val3) || ((Character)val3).IsDead()) { return; } ZNetView component = ((Component)val3).GetComponent<ZNetView>(); ZDO val4 = ((Object.op_Implicit((Object)(object)component) && component.IsValid()) ? component.GetZDO() : null); if (val4 != null && val4.IsValid() && object.ReferenceEquals(world.GetZDO(val4.m_uid), val4)) { long owner = val4.GetOwner(); if (owner != 0 && __1 != owner) { __result = "AI target changed"; } } } catch (Exception error2) { Fail(error2); } } private static bool DamagePrefix(Character __instance, HitData hit) { //IL_006c: 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) if (!Enabled || forwarded.Count == 0 || !Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsDedicated() || !Object.op_Implicit((Object)(object)__instance) || hit == null) { return true; } try { ZNetView component = ((Component)__instance).GetComponent<ZNetView>(); if (!Object.op_Implicit((Object)(object)component) || !component.