Decompiled source of DvergrDiplomacy v0.1.217

DvergrDiplomacy.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("DvergrDiplomacy")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("DvergrDiplomacy")]
[assembly: AssemblyTitle("DvergrDiplomacy")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Pix.DvergrDiplomacy;

[BepInPlugin("Pix.DvergrDiplomacy", "DvergrDiplomacy", "0.1.217")]
public sealed class DvergrDiplomacyTruceWedge : BaseUnityPlugin
{
	[Serializable]
	[CompilerGenerated]
	private sealed class <>c
	{
		public static readonly <>c <>9 = new <>c();

		public static ConsoleEvent <>9__85_0;

		internal void <TryRegisterConsoleCommand>b__85_0(ConsoleEventArgs args)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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_007f: Expected O, but got Unknown
			//IL_0080: 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)
			try
			{
				if ((Object)(object)Player.m_localPlayer == (Object)null)
				{
					args.Context.AddString("No local player.");
					return;
				}
				if ((Object)(object)ZNet.instance == (Object)null || ZRoutedRpc.instance == null)
				{
					args.Context.AddString("Network not ready.");
					return;
				}
				Vector3 val = ((Component)Player.m_localPlayer).transform.position + ((Component)Player.m_localPlayer).transform.forward * 2f;
				ZPackage val2 = new ZPackage();
				val2.Write(val);
				val2.Write(Quaternion.identity);
				ZRoutedRpc.instance.InvokeRoutedRPC(0L, "DD_SpawnDverger_Test", new object[1] { val2 });
				args.Context.AddString("Requested server spawn.");
			}
			catch (Exception ex)
			{
				args.Context.AddString("dd_spawn_dverger failed: " + ex.Message);
			}
		}
	}

	public const string PluginGuid = "Pix.DvergrDiplomacy";

	public const string PluginName = "DvergrDiplomacy";

	public const string PluginVersion = "0.1.217";

	private const string BuildId = "DD_TRUCEWEDGE_0.3.117_CLEAN";

	private const string RpcSpawnTest = "DD_SpawnDverger_Test";

	private const string CmdSpawnDverger = "dd_spawn_dverger";

	internal static DvergrDiplomacyTruceWedge Self;

	internal static ManualLogSource Log;

	private Harmony _harmony;

	private ConfigEntry<bool> _enabled;

	private ConfigEntry<float> _hostileSeconds;

	private ConfigEntry<int> _forgivenessFreeStrikes;

	private ConfigEntry<float> _forgivenessWindowSeconds;

	private ConfigEntry<float> _joinGraceSeconds;

	private ConfigEntry<float> _calmHoldSeconds;

	private ConfigEntry<float> _updateTargetHoldSeconds;

	private ConfigEntry<bool> _serverTriggerOnFindEnemy;

	private ConfigEntry<bool> _serverTriggerOnSetTarget;

	private ConfigEntry<bool> _showMessagesClient;

	private ConfigEntry<string> _warningPhrases;

	private ConfigEntry<bool> _spawnTestEnabled;

	private ConfigEntry<bool> _logEnabled;

	private ConfigEntry<float> _perAiLogEverySeconds;

	private ConfigEntry<bool> _traceAllAis;

	private ConfigEntry<bool> _clientSimWarning;

	private static MethodInfo MI_FindEnemy;

	private static MethodInfo MI_SetTarget;

	private static MethodInfo MI_UpdateAI;

	private static MethodInfo MI_CharacterDamage;

	private static MethodInfo MI_SetAlertedBool;

	private static MethodInfo MI_GetTargetCreature;

	private static FieldRef<MonsterAI, Character> FR_TargetCreature;

	private static bool FR_TargetCreatureOk;

	private static FieldInfo FI_Alerted;

	private static FieldInfo FI_Aggravated;

	private static FieldInfo FI_LastKnownTargetPos;

	private static FieldInfo FI_TargetStatic;

	private static FieldInfo FI_UpdateTargetTimer;

	private static readonly object _lock = new object();

	private static readonly Dictionary<long, long> HostileUntilMsByPlayerId = new Dictionary<long, long>();

	private static readonly Dictionary<long, long> JoinGraceUntilMsByPlayerId = new Dictionary<long, long>();

	private static readonly Dictionary<long, int> StrikeCountByPlayerId = new Dictionary<long, int>();

	private static readonly Dictionary<long, long> StrikeGraceUntilMsByPlayerId = new Dictionary<long, long>();

	private static readonly HashSet<int> ActivatedAiIds = new HashSet<int>();

	private static readonly Dictionary<int, long> CalmLockUntilMsByAiId = new Dictionary<int, long>();

	private static readonly Dictionary<int, long> AiPlayerIdByAiId = new Dictionary<int, long>();

	private static readonly Dictionary<int, float> NextLogAtByAiId = new Dictionary<int, float>();

	private static readonly HashSet<int> ClientSimWarnedAiIds = new HashSet<int>();

	private static bool _rpcsRegistered;

	private static bool _consoleRegistered;

	private string[] _phrases = new string[1] { "Hold your hand, outsider." };

	private Random _rng = new Random();

	private void Awake()
	{
		//IL_024e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0258: Expected O, but got Unknown
		Self = this;
		Log = ((BaseUnityPlugin)this).Logger;
		_enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable DvergrDiplomacy.");
		_hostileSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Diplomacy", "HostileSeconds", 180f, "How long they stay hostile after diplomacy breaks.");
		_forgivenessFreeStrikes = ((BaseUnityPlugin)this).Config.Bind<int>("Forgiveness", "FreeStrikes", 1, "Number of forgiven strikes before diplomacy breaks.");
		_forgivenessWindowSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Forgiveness", "WindowSeconds", 30f, "Second strike within this window breaks diplomacy.");
		_joinGraceSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Safety", "JoinGraceSeconds", 15f, "Grace period after contact to prevent instant death.");
		_calmHoldSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Wedge", "CalmHoldSeconds", 12f, "Hold calm this long (refreshes while hot).");
		_updateTargetHoldSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Wedge", "UpdateTargetHoldSeconds", 30f, "Clamp update target timer while holding calm.");
		_serverTriggerOnFindEnemy = ((BaseUnityPlugin)this).Config.Bind<bool>("ServerTriggers", "TriggerOnFindEnemy", true, "Server: treat FindEnemy->Player as contact (starts join grace).");
		_serverTriggerOnSetTarget = ((BaseUnityPlugin)this).Config.Bind<bool>("ServerTriggers", "TriggerOnSetTarget", true, "Server: treat SetTarget(Player) as contact (starts join grace).");
		_showMessagesClient = ((BaseUnityPlugin)this).Config.Bind<bool>("Client", "ShowMessages", true, "Client: show warning popup on forgiven strike.");
		_warningPhrases = ((BaseUnityPlugin)this).Config.Bind<string>("Client", "WarningPhrases", "Careful|Hold your hand, outsider.|Odin is watching.", "Pipe-separated list of warning phrases.");
		_spawnTestEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("SpawnTest", "Enabled", true, "Enable dd_spawn_dverger and server RPC spawn test.");
		_logEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Logging", "Log", true, "Enable logs (throttled).");
		_perAiLogEverySeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Logging", "PerAiLogEverySeconds", 1f, "Minimum seconds between logs per AI.");
		_traceAllAis = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "TraceAllAis", false, "Apply to all MonsterAI (debug).");
		_clientSimWarning = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "ClientSimWarning", true, "Client: warn once per AI if AI sim is client-side.");
		ParsePhrases();
		ResolveHandles();
		_harmony = new Harmony("Pix.DvergrDiplomacy");
		ApplyPatches();
		TryRegisterRpcs();
		TryRegisterConsoleCommand();
		Log.LogInfo((object)"[DD_TRUCEWEDGE_0.3.117_CLEAN] Loaded v0.1.217.");
	}

	private void Update()
	{
		try
		{
			if (EnabledNow())
			{
				TryRegisterRpcs();
				TryRegisterConsoleCommand();
			}
		}
		catch
		{
		}
	}

	private void OnDestroy()
	{
		try
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
		catch
		{
		}
	}

	private bool EnabledNow()
	{
		if (_enabled != null)
		{
			return _enabled.Value;
		}
		return false;
	}

	private void ParsePhrases()
	{
		try
		{
			string text = ((_warningPhrases != null) ? (_warningPhrases.Value ?? "") : "");
			string[] array = text.Split(new char[1] { '|' }, StringSplitOptions.RemoveEmptyEntries);
			List<string> list = new List<string>();
			for (int i = 0; i < array.Length; i++)
			{
				string text2 = ((array[i] != null) ? array[i].Trim() : "");
				if (text2.Length > 0)
				{
					list.Add(text2);
				}
			}
			if (list.Count > 0)
			{
				_phrases = list.ToArray();
			}
		}
		catch
		{
			_phrases = new string[1] { "Hold your hand, outsider." };
		}
	}

	private static void ResolveHandles()
	{
		try
		{
			FR_TargetCreature = AccessTools.FieldRefAccess<MonsterAI, Character>("m_targetCreature");
			FR_TargetCreatureOk = true;
		}
		catch
		{
			FR_TargetCreatureOk = false;
			FR_TargetCreature = null;
		}
		Type typeFromHandle = typeof(MonsterAI);
		FI_Alerted = AccessTools.Field(typeFromHandle, "m_alerted");
		FI_Aggravated = AccessTools.Field(typeFromHandle, "m_aggravated");
		FI_LastKnownTargetPos = AccessTools.Field(typeFromHandle, "m_lastKnownTargetPos");
		FI_TargetStatic = AccessTools.Field(typeFromHandle, "m_targetStatic");
		FI_UpdateTargetTimer = AccessTools.Field(typeFromHandle, "m_updateTargetTimer");
		MI_SetAlertedBool = AccessTools.Method(typeof(BaseAI), "SetAlerted", new Type[1] { typeof(bool) }, (Type[])null);
		MI_GetTargetCreature = AccessTools.Method(typeof(BaseAI), "GetTargetCreature", Type.EmptyTypes, (Type[])null);
		MI_FindEnemy = AccessTools.Method(typeof(BaseAI), "FindEnemy", Type.EmptyTypes, (Type[])null);
		MI_SetTarget = AccessTools.Method(typeof(MonsterAI), "SetTarget", new Type[1] { typeof(Character) }, (Type[])null);
		MI_UpdateAI = AccessTools.Method(typeof(MonsterAI), "UpdateAI", new Type[1] { typeof(float) }, (Type[])null);
		MI_CharacterDamage = ResolveCharacterDamageHitData();
	}

	private static MethodInfo ResolveCharacterDamageHitData()
	{
		try
		{
			Type typeFromHandle = typeof(Character);
			MethodInfo[] methods = typeFromHandle.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo methodInfo in methods)
			{
				if (!(methodInfo == null) && !(methodInfo.Name != "Damage"))
				{
					ParameterInfo[] parameters = methodInfo.GetParameters();
					if (parameters.Length == 1 && parameters[0].ParameterType.Name == "HitData")
					{
						return methodInfo;
					}
				}
			}
		}
		catch
		{
		}
		return null;
	}

	private void ApplyPatches()
	{
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Expected O, but got Unknown
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Expected O, but got Unknown
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Expected O, but got Unknown
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: Expected O, but got Unknown
		if (MI_FindEnemy != null)
		{
			_harmony.Patch((MethodBase)MI_FindEnemy, (HarmonyMethod)null, new HarmonyMethod(typeof(DvergrDiplomacyTruceWedge), "FindEnemy_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}
		if (MI_SetTarget != null)
		{
			_harmony.Patch((MethodBase)MI_SetTarget, new HarmonyMethod(typeof(DvergrDiplomacyTruceWedge), "SetTarget_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}
		if (MI_UpdateAI != null)
		{
			_harmony.Patch((MethodBase)MI_UpdateAI, new HarmonyMethod(typeof(DvergrDiplomacyTruceWedge), "UpdateAI_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}
		if (MI_CharacterDamage != null)
		{
			_harmony.Patch((MethodBase)MI_CharacterDamage, new HarmonyMethod(typeof(DvergrDiplomacyTruceWedge), "CharacterDamage_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}
		else
		{
			Log.LogWarning((object)"[DD_TRUCEWEDGE_0.3.117_CLEAN] Could not resolve Character.Damage(HitData). Forgiveness will not detect attacks.");
		}
	}

	private static bool IsServer()
	{
		try
		{
			return (Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer();
		}
		catch
		{
			return false;
		}
	}

	private static long NowMs()
	{
		try
		{
			double num = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetTimeSeconds() : ((double)Time.realtimeSinceStartup));
			if (num < 0.0)
			{
				num = 0.0;
			}
			return (long)(num * 1000.0);
		}
		catch
		{
			return (long)((double)Time.realtimeSinceStartup * 1000.0);
		}
	}

	private bool ShouldAct(Character owner)
	{
		if (!EnabledNow())
		{
			return false;
		}
		if (_traceAllAis != null && _traceAllAis.Value)
		{
			return true;
		}
		return IsDverger(owner);
	}

	private static bool IsDverger(Character c)
	{
		if ((Object)(object)c == (Object)null)
		{
			return false;
		}
		try
		{
			string text = ((object)(Faction)(ref c.m_faction)).ToString();
			if (!string.IsNullOrEmpty(text) && text.IndexOf("Dverger", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
		}
		catch
		{
		}
		try
		{
			string text2 = ((Object)c).name ?? "";
			if (text2.IndexOf("dver", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
		}
		catch
		{
		}
		return false;
	}

	private static bool IsPlayerChar(Character c)
	{
		if ((Object)(object)c == (Object)null)
		{
			return false;
		}
		try
		{
			return c.IsPlayer();
		}
		catch
		{
			return (Object)(object)((c is Player) ? c : null) != (Object)null;
		}
	}

	private static long GetStablePlayerId(Player p)
	{
		if ((Object)(object)p == (Object)null)
		{
			return 0L;
		}
		try
		{
			return p.GetPlayerID();
		}
		catch
		{
			return 0L;
		}
	}

	private bool ShouldLog(int aiId)
	{
		if (_logEnabled == null || !_logEnabled.Value)
		{
			return false;
		}
		float num = Mathf.Max(0.1f, (_perAiLogEverySeconds != null) ? _perAiLogEverySeconds.Value : 1f);
		float time = Time.time;
		if (NextLogAtByAiId.TryGetValue(aiId, out var value) && time < value)
		{
			return false;
		}
		NextLogAtByAiId[aiId] = time + num;
		return true;
	}

	private void ClientMessage(string msg)
	{
		if (_showMessagesClient == null || !_showMessagesClient.Value)
		{
			return;
		}
		try
		{
			if ((Object)(object)MessageHud.instance != (Object)null)
			{
				MessageHud.instance.ShowMessage((MessageType)2, msg, 0, (Sprite)null, false);
			}
		}
		catch
		{
		}
	}

	private void PopupForgiven()
	{
		if (_phrases == null || _phrases.Length == 0)
		{
			ClientMessage("Hold your hand, outsider.");
			return;
		}
		int num = 0;
		try
		{
			num = _rng.Next(0, _phrases.Length);
		}
		catch
		{
			num = 0;
		}
		string msg = _phrases[num] ?? "Hold your hand, outsider.";
		ClientMessage(msg);
	}

	private bool IsHostileActive(long playerId, long nowMs)
	{
		if (playerId == 0L)
		{
			return false;
		}
		lock (_lock)
		{
			if (HostileUntilMsByPlayerId.TryGetValue(playerId, out var value))
			{
				return nowMs < value;
			}
		}
		return false;
	}

	private void EnsureJoinGrace(long playerId, long nowMs, string reason)
	{
		if (playerId == 0L)
		{
			return;
		}
		long num = nowMs + (long)(Mathf.Max(0.1f, _joinGraceSeconds.Value) * 1000f);
		bool flag = false;
		lock (_lock)
		{
			if (!JoinGraceUntilMsByPlayerId.TryGetValue(playerId, out var value) || value < nowMs)
			{
				JoinGraceUntilMsByPlayerId[playerId] = num;
				flag = true;
			}
		}
		if (flag && IsServer())
		{
			Log.LogInfo((object)string.Format("[{0}] JOIN-GRACE start playerId={1} untilMs={2} reason={3}", "DD_TRUCEWEDGE_0.3.117_CLEAN", playerId, num, reason));
		}
	}

	private int GetStrikeCountResetIfExpired(long playerId, long nowMs)
	{
		if (playerId == 0L)
		{
			return 0;
		}
		lock (_lock)
		{
			StrikeGraceUntilMsByPlayerId.TryGetValue(playerId, out var value);
			if (value != 0L && nowMs > value)
			{
				StrikeCountByPlayerId[playerId] = 0;
				StrikeGraceUntilMsByPlayerId[playerId] = 0L;
			}
			StrikeCountByPlayerId.TryGetValue(playerId, out var value2);
			return value2;
		}
	}

	private void SetStrikeCount(long playerId, int strikes)
	{
		if (playerId == 0L)
		{
			return;
		}
		lock (_lock)
		{
			StrikeCountByPlayerId[playerId] = strikes;
		}
	}

	private void EnsureForgivenessWindow(long playerId, long nowMs)
	{
		if (playerId == 0L)
		{
			return;
		}
		long num = (long)(Mathf.Max(1f, _forgivenessWindowSeconds.Value) * 1000f);
		long value = nowMs + num;
		lock (_lock)
		{
			StrikeGraceUntilMsByPlayerId[playerId] = value;
		}
	}

	private void StartHostile(long playerId, long nowMs, string reason)
	{
		if (playerId != 0L)
		{
			long num = nowMs + (long)(Mathf.Max(1f, _hostileSeconds.Value) * 1000f);
			lock (_lock)
			{
				HostileUntilMsByPlayerId[playerId] = num;
				StrikeCountByPlayerId[playerId] = 0;
				StrikeGraceUntilMsByPlayerId[playerId] = 0L;
				JoinGraceUntilMsByPlayerId[playerId] = 0L;
			}
			if (IsServer())
			{
				Log.LogInfo((object)string.Format("[{0}] HOSTILE START playerId={1} untilMs={2} reason={3}", "DD_TRUCEWEDGE_0.3.117_CLEAN", playerId, num, reason));
			}
		}
	}

	private bool ShouldWedgeProtect(long playerId, long nowMs)
	{
		if (playerId == 0L)
		{
			return true;
		}
		return !IsHostileActive(playerId, nowMs);
	}

	private void ActivateOrRefreshWedge(int aiId, long playerId, long nowMs, string reason)
	{
		long num = nowMs + (long)(Mathf.Max(0.1f, _calmHoldSeconds.Value) * 1000f);
		lock (_lock)
		{
			ActivatedAiIds.Add(aiId);
			CalmLockUntilMsByAiId[aiId] = num;
			AiPlayerIdByAiId[aiId] = playerId;
		}
		if (IsServer() && ShouldLog(aiId))
		{
			Log.LogInfo((object)string.Format("[{0}] WEDGE ENGAGE aiId={1} playerId={2} untilMs={3} reason={4}", "DD_TRUCEWEDGE_0.3.117_CLEAN", aiId, playerId, num, reason));
		}
	}

	private void ReleaseWedge(int aiId, string reason)
	{
		lock (_lock)
		{
			ActivatedAiIds.Remove(aiId);
			CalmLockUntilMsByAiId.Remove(aiId);
			AiPlayerIdByAiId.Remove(aiId);
		}
		if (IsServer() && ShouldLog(aiId))
		{
			Log.LogInfo((object)string.Format("[{0}] WEDGE RELEASE aiId={1} reason={2}", "DD_TRUCEWEDGE_0.3.117_CLEAN", aiId, reason));
		}
	}

	private void ForceNeutral(MonsterAI ai)
	{
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			try
			{
				if (FI_Alerted != null)
				{
					FI_Alerted.SetValue(ai, false);
				}
			}
			catch
			{
			}
			try
			{
				if (FI_Aggravated != null)
				{
					FI_Aggravated.SetValue(ai, false);
				}
			}
			catch
			{
			}
			try
			{
				if (FI_LastKnownTargetPos != null)
				{
					FI_LastKnownTargetPos.SetValue(ai, Vector3.zero);
				}
			}
			catch
			{
			}
			try
			{
				if (FI_TargetStatic != null)
				{
					FI_TargetStatic.SetValue(ai, null);
				}
			}
			catch
			{
			}
			try
			{
				if (FI_UpdateTargetTimer != null)
				{
					FI_UpdateTargetTimer.SetValue(ai, Mathf.Max(0f, _updateTargetHoldSeconds.Value));
				}
			}
			catch
			{
			}
			if (FR_TargetCreatureOk && FR_TargetCreature != null)
			{
				try
				{
					FR_TargetCreature.Invoke(ai) = null;
				}
				catch
				{
				}
			}
			try
			{
				if (MI_SetAlertedBool != null)
				{
					MI_SetAlertedBool.Invoke(ai, new object[1] { false });
				}
			}
			catch
			{
			}
		}
		catch
		{
		}
	}

	private static Character GetTargetCreature(MonsterAI ai)
	{
		if ((Object)(object)ai == (Object)null)
		{
			return null;
		}
		if (FR_TargetCreatureOk && FR_TargetCreature != null)
		{
			try
			{
				return FR_TargetCreature.Invoke(ai);
			}
			catch
			{
			}
		}
		if (MI_GetTargetCreature != null)
		{
			try
			{
				object? obj2 = MI_GetTargetCreature.Invoke(ai, null);
				return (Character)((obj2 is Character) ? obj2 : null);
			}
			catch
			{
			}
		}
		return null;
	}

	public static void FindEnemy_Postfix(BaseAI __instance, ref Character __result)
	{
		try
		{
			if ((Object)(object)Self == (Object)null || (Object)(object)__instance == (Object)null || (Object)(object)__result == (Object)null || !Self.EnabledNow())
			{
				return;
			}
			Character component = ((Component)__instance).GetComponent<Character>();
			if (!Self.ShouldAct(component) || !IsPlayerChar(__result))
			{
				return;
			}
			Character obj = __result;
			Player val = (Player)(object)((obj is Player) ? obj : null);
			if (!((Object)(object)val == (Object)null))
			{
				long nowMs = NowMs();
				long stablePlayerId = GetStablePlayerId(val);
				if (IsServer() && Self._serverTriggerOnFindEnemy != null && Self._serverTriggerOnFindEnemy.Value)
				{
					Self.EnsureJoinGrace(stablePlayerId, nowMs, "FindEnemy");
				}
				if (Self.ShouldWedgeProtect(stablePlayerId, nowMs))
				{
					int instanceID = ((Object)__instance).GetInstanceID();
					Self.ActivateOrRefreshWedge(instanceID, stablePlayerId, nowMs, "FindEnemy->Player");
					__result = null;
				}
			}
		}
		catch
		{
		}
	}

	public static bool SetTarget_Prefix(MonsterAI __instance, Character attacker)
	{
		try
		{
			if ((Object)(object)Self == (Object)null)
			{
				return true;
			}
			if ((Object)(object)__instance == (Object)null || (Object)(object)attacker == (Object)null)
			{
				return true;
			}
			if (!Self.EnabledNow())
			{
				return true;
			}
			Character component = ((Component)__instance).GetComponent<Character>();
			if (!Self.ShouldAct(component))
			{
				return true;
			}
			if (!IsPlayerChar(attacker))
			{
				return true;
			}
			Player val = (Player)(object)((attacker is Player) ? attacker : null);
			if ((Object)(object)val == (Object)null)
			{
				return true;
			}
			long nowMs = NowMs();
			long stablePlayerId = GetStablePlayerId(val);
			if (IsServer() && Self._serverTriggerOnSetTarget != null && Self._serverTriggerOnSetTarget.Value)
			{
				Self.EnsureJoinGrace(stablePlayerId, nowMs, "SetTarget");
			}
			if (Self.ShouldWedgeProtect(stablePlayerId, nowMs))
			{
				int instanceID = ((Object)__instance).GetInstanceID();
				Self.ActivateOrRefreshWedge(instanceID, stablePlayerId, nowMs, "SetTarget->Player");
				Self.ForceNeutral(__instance);
				return false;
			}
			return true;
		}
		catch
		{
			return true;
		}
	}

	public static void UpdateAI_Prefix(MonsterAI __instance, float dt)
	{
		//IL_025e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0263: 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_02a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f2: 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)
		try
		{
			if ((Object)(object)Self == (Object)null || (Object)(object)__instance == (Object)null || !Self.EnabledNow())
			{
				return;
			}
			Character component = ((Component)__instance).GetComponent<Character>();
			if (!Self.ShouldAct(component))
			{
				return;
			}
			int instanceID = ((Object)__instance).GetInstanceID();
			if (!IsServer() && Self._clientSimWarning != null && Self._clientSimWarning.Value)
			{
				bool flag;
				lock (_lock)
				{
					flag = ClientSimWarnedAiIds.Add(instanceID);
				}
				if (flag)
				{
					Log.LogWarning((object)string.Format("[{0}] CLIENT-SIM WARNING aiId={1} ownerGO='{2}'.", "DD_TRUCEWEDGE_0.3.117_CLEAN", instanceID, ((Object)(object)component != (Object)null && (Object)(object)((Component)component).gameObject != (Object)null) ? ((Object)((Component)component).gameObject).name : (((Object)(object)component != (Object)null) ? ((Object)component).name : "(null)")));
				}
			}
			long num = NowMs();
			Character targetCreature = GetTargetCreature(__instance);
			Player val = (Player)(object)((targetCreature is Player) ? targetCreature : null);
			if ((Object)(object)val != (Object)null)
			{
				long stablePlayerId = GetStablePlayerId(val);
				Self.EnsureJoinGrace(stablePlayerId, num, "UpdateAI(TargetPlayer)");
				if (Self.ShouldWedgeProtect(stablePlayerId, num))
				{
					Self.ActivateOrRefreshWedge(instanceID, stablePlayerId, num, "UpdateAI(SafetyNet)");
					Self.ForceNeutral(__instance);
					return;
				}
			}
			bool flag2;
			long value;
			long value2;
			lock (_lock)
			{
				flag2 = ActivatedAiIds.Contains(instanceID);
				AiPlayerIdByAiId.TryGetValue(instanceID, out value);
				CalmLockUntilMsByAiId.TryGetValue(instanceID, out value2);
			}
			if (!flag2)
			{
				return;
			}
			if (!Self.ShouldWedgeProtect(value, num))
			{
				Self.ReleaseWedge(instanceID, "HostileActive");
				return;
			}
			bool flag3 = false;
			bool flag4 = false;
			Vector3 val2 = Vector3.zero;
			object obj = null;
			try
			{
				if (FI_Alerted != null)
				{
					flag3 = (bool)FI_Alerted.GetValue(__instance);
				}
			}
			catch
			{
			}
			try
			{
				if (FI_Aggravated != null)
				{
					flag4 = (bool)FI_Aggravated.GetValue(__instance);
				}
			}
			catch
			{
			}
			try
			{
				if (FI_LastKnownTargetPos != null)
				{
					val2 = (Vector3)FI_LastKnownTargetPos.GetValue(__instance);
				}
			}
			catch
			{
			}
			try
			{
				if (FI_TargetStatic != null)
				{
					obj = FI_TargetStatic.GetValue(__instance);
				}
			}
			catch
			{
			}
			bool flag5 = (Object)(object)targetCreature != (Object)null;
			if (flag3 || flag4 || obj != null || val2 != Vector3.zero || flag5)
			{
				long num2 = num + (long)(Mathf.Max(0.1f, Self._calmHoldSeconds.Value) * 1000f);
				lock (_lock)
				{
					CalmLockUntilMsByAiId[instanceID] = num2;
				}
				value2 = num2;
			}
			if (num < value2)
			{
				Self.ForceNeutral(__instance);
			}
		}
		catch
		{
		}
	}

	public static void CharacterDamage_Prefix(Character __instance, object hit)
	{
		try
		{
			if ((Object)(object)Self == (Object)null || !Self.EnabledNow() || (Object)(object)__instance == (Object)null || !IsDverger(__instance))
			{
				return;
			}
			Character val = null;
			try
			{
				if (hit != null)
				{
					MethodInfo method = hit.GetType().GetMethod("GetAttacker", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (method != null)
					{
						object? obj = method.Invoke(hit, null);
						val = (Character)((obj is Character) ? obj : null);
					}
				}
			}
			catch
			{
				val = null;
			}
			Player val2 = (Player)(object)((val is Player) ? val : null);
			if ((Object)(object)val2 == (Object)null)
			{
				return;
			}
			long nowMs = NowMs();
			long stablePlayerId = GetStablePlayerId(val2);
			if (Self.IsHostileActive(stablePlayerId, nowMs))
			{
				return;
			}
			int strikeCountResetIfExpired = Self.GetStrikeCountResetIfExpired(stablePlayerId, nowMs);
			int num = Mathf.Max(0, Self._forgivenessFreeStrikes.Value);
			int num2 = strikeCountResetIfExpired + 1;
			Self.EnsureForgivenessWindow(stablePlayerId, nowMs);
			Self.SetStrikeCount(stablePlayerId, num2);
			Self.EnsureJoinGrace(stablePlayerId, nowMs, "Strike");
			if (num2 <= num)
			{
				if (!IsServer())
				{
					if ((Object)(object)Player.m_localPlayer != (Object)null && GetStablePlayerId(Player.m_localPlayer) == stablePlayerId)
					{
						Self.PopupForgiven();
					}
				}
				else
				{
					Log.LogInfo((object)string.Format("[{0}] STRIKE FORGIVEN playerId={1} strike={2}/{3}", "DD_TRUCEWEDGE_0.3.117_CLEAN", stablePlayerId, num2, num));
				}
			}
			else if (IsServer())
			{
				Self.StartHostile(stablePlayerId, nowMs, "SecondStrike");
			}
			else
			{
				Self.StartHostile(stablePlayerId, nowMs, "SecondStrike(client)");
			}
		}
		catch
		{
		}
	}

	private void TryRegisterRpcs()
	{
		if (_rpcsRegistered || _spawnTestEnabled == null || !_spawnTestEnabled.Value)
		{
			return;
		}
		try
		{
			if (ZRoutedRpc.instance != null)
			{
				if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
				{
					ZRoutedRpc.instance.Register<ZPackage>("DD_SpawnDverger_Test", (Action<long, ZPackage>)RPC_ServerSpawnDvergerTest);
					Log.LogInfo((object)"[DD_TRUCEWEDGE_0.3.117_CLEAN] Registered RPC DD_SpawnDverger_Test");
				}
				_rpcsRegistered = true;
			}
		}
		catch
		{
		}
	}

	private void TryRegisterConsoleCommand()
	{
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Expected O, but got Unknown
		if (_consoleRegistered || _spawnTestEnabled == null || !_spawnTestEnabled.Value)
		{
			return;
		}
		try
		{
			object obj = <>c.<>9__85_0;
			if (obj == null)
			{
				ConsoleEvent val = delegate(ConsoleEventArgs args)
				{
					//IL_0055: Unknown result type (might be due to invalid IL or missing references)
					//IL_0064: Unknown result type (might be due to invalid IL or missing references)
					//IL_006e: Unknown result type (might be due to invalid IL or missing references)
					//IL_0073: Unknown result type (might be due to invalid IL or missing references)
					//IL_0078: 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_007f: Expected O, but got Unknown
					//IL_0080: 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)
					try
					{
						if ((Object)(object)Player.m_localPlayer == (Object)null)
						{
							args.Context.AddString("No local player.");
						}
						else if ((Object)(object)ZNet.instance == (Object)null || ZRoutedRpc.instance == null)
						{
							args.Context.AddString("Network not ready.");
						}
						else
						{
							Vector3 val2 = ((Component)Player.m_localPlayer).transform.position + ((Component)Player.m_localPlayer).transform.forward * 2f;
							ZPackage val3 = new ZPackage();
							val3.Write(val2);
							val3.Write(Quaternion.identity);
							ZRoutedRpc.instance.InvokeRoutedRPC(0L, "DD_SpawnDverger_Test", new object[1] { val3 });
							args.Context.AddString("Requested server spawn.");
						}
					}
					catch (Exception ex)
					{
						args.Context.AddString("dd_spawn_dverger failed: " + ex.Message);
					}
				};
				<>c.<>9__85_0 = val;
				obj = (object)val;
			}
			new ConsoleCommand("dd_spawn_dverger", "Ask the server to spawn a Dverger near you.", (ConsoleEvent)obj, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
			_consoleRegistered = true;
			Log.LogInfo((object)"[DD_TRUCEWEDGE_0.3.117_CLEAN] Registered console command dd_spawn_dverger");
		}
		catch
		{
		}
	}

	private static void RPC_ServerSpawnDvergerTest(long sender, ZPackage pkg)
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (!((Object)(object)Self == (Object)null) && !((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer())
			{
				Vector3 pos = pkg.ReadVector3();
				Quaternion rot = pkg.ReadQuaternion();
				SpawnDvergerServer(pos, rot, "RPC(sender=" + sender + ")");
			}
		}
		catch
		{
		}
	}

	private static void SpawnDvergerServer(Vector3 pos, Quaternion rot, string reason)
	{
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || (Object)(object)ZNetScene.instance == (Object)null)
			{
				return;
			}
			GameObject prefab = ZNetScene.instance.GetPrefab("Dverger");
			if ((Object)(object)prefab == (Object)null)
			{
				prefab = ZNetScene.instance.GetPrefab("DvergerArbalest");
			}
			if ((Object)(object)prefab == (Object)null)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogWarning((object)("[DD_TRUCEWEDGE_0.3.117_CLEAN] Dverger prefab not found (" + reason + ")"));
				}
				return;
			}
			GameObject val = Object.Instantiate<GameObject>(prefab, pos, rot);
			ZNetView component = val.GetComponent<ZNetView>();
			if ((Object)(object)component != (Object)null && component.IsValid() && !component.IsOwner())
			{
				component.ClaimOwnership();
			}
			ManualLogSource log2 = Log;
			if (log2 != null)
			{
				log2.LogInfo((object)string.Format("[{0}] Server spawned Dverger ({1}) at {2}", "DD_TRUCEWEDGE_0.3.117_CLEAN", reason, pos));
			}
		}
		catch
		{
		}
	}
}