Decompiled source of OathboundExpShare v1.1.1

OathboundExpShare.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using Warrior.Core;
using Warrior.Mod;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace OathboundExpShare
{
	[BepInPlugin("com.aitod.valheim.oathboundexpshare", "Oathbound Exp Share", "1.1.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class OathboundExpSharePlugin : BaseUnityPlugin
	{
		public const string ModGUID = "com.aitod.valheim.oathboundexpshare";

		public const string ModName = "Oathbound Exp Share";

		public const string ModVersion = "1.1.1";

		public static OathboundExpSharePlugin Instance;

		public static ManualLogSource Log;

		private Harmony _harmony;

		public static ConfigEntry<bool> EnableExpShare;

		public static ConfigEntry<bool> EnableDebugLogs;

		public static ConfigEntry<bool> ShareWithDamagers;

		public static ConfigEntry<float> DamagerExpPercent;

		public static ConfigEntry<float> DamagerMaxDistance;

		public static ConfigEntry<bool> ShareWithNearby;

		public static ConfigEntry<float> NearbyRadius;

		public static ConfigEntry<float> NearbyExpPercent;

		private const string ZdoLastUserKey = "Oathbound_LastUser";

		private const string ZdoLastIdKey = "Oathbound_LastID";

		private const string ZdoDamagersKey = "Oathbound_Damagers";

		private static bool _isSyncingConfig = false;

		private static readonly FieldInfo _serverDeathsField = AccessTools.Field(typeof(Plugin), "_serverDeaths");

		private static readonly FieldInfo _xpMultiplierField = AccessTools.Field(typeof(Plugin), "_xpMultiplier");

		private static readonly MethodInfo _receiveRewardMethod = AccessTools.Method(typeof(Plugin), "ReceiveReward", new Type[1] { typeof(ZPackage) }, (Type[])null);

		private static readonly MethodInfo _strongestHitMethod = AccessTools.Method("Warrior.Mod.EnemyThreat:StrongestHit", new Type[2]
		{
			typeof(ZDO),
			typeof(GameObject)
		}, (Type[])null);

		private static readonly MethodInfo _bloodKillOwner = AccessTools.Method(typeof(Plugin), "BloodKillOwner", new Type[1] { typeof(Character) }, (Type[])null);

		private static readonly MethodInfo _hunterKillOwner = AccessTools.Method(typeof(Plugin), "HunterKillOwner", new Type[1] { typeof(Character) }, (Type[])null);

		private static readonly MethodInfo _dragonKillOwner = AccessTools.Method(typeof(Plugin), "DragonKillOwner", new Type[1] { typeof(Character) }, (Type[])null);

		private void Awake()
		{
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			EnableExpShare = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableExpShare", true, "Master switch to enable or disable shared experience and DoT kill fixes for Oathbound.");
			EnableDebugLogs = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableDebugLogs", false, "Log detailed debug messages when damage, DoT kills, and shared EXP are processed.");
			ShareWithDamagers = ((BaseUnityPlugin)this).Config.Bind<bool>("Damagers", "ShareWithDamagers", true, "Award shared EXP to any player who dealt damage to the monster (including DoT).");
			DamagerExpPercent = ((BaseUnityPlugin)this).Config.Bind<float>("Damagers", "DamagerExpPercent", 100f, "Percentage of the full kill EXP awarded to players who damaged the monster (e.g. 100 for 100%, 50 for half).");
			DamagerMaxDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Damagers", "DamagerMaxDistance", 100f, "Maximum distance in meters from the monster for damagers to qualify for EXP (0 = unlimited map-wide).");
			ShareWithNearby = ((BaseUnityPlugin)this).Config.Bind<bool>("Nearby", "ShareWithNearby", true, "Award shared EXP to nearby group/party members even if they did not deal damage.");
			NearbyRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Nearby", "NearbyRadius", 50f, "Radius in meters around the killed monster to award shared experience to nearby players.");
			NearbyExpPercent = ((BaseUnityPlugin)this).Config.Bind<float>("Nearby", "NearbyExpPercent", 100f, "Percentage of the full kill EXP awarded to nearby players (e.g. 100 for full EXP, 75 for 75%).");
			EnableExpShare.SettingChanged += OnSettingChanged;
			ShareWithDamagers.SettingChanged += OnSettingChanged;
			DamagerExpPercent.SettingChanged += OnSettingChanged;
			DamagerMaxDistance.SettingChanged += OnSettingChanged;
			ShareWithNearby.SettingChanged += OnSettingChanged;
			NearbyRadius.SettingChanged += OnSettingChanged;
			NearbyExpPercent.SettingChanged += OnSettingChanged;
			_harmony = new Harmony("com.aitod.valheim.oathboundexpshare");
			_harmony.PatchAll(typeof(OathboundExpSharePlugin));
			_harmony.PatchAll(typeof(Patch_Character_RPC_Damage));
			_harmony.PatchAll(typeof(Patch_Character_OnDeath));
			_harmony.PatchAll(typeof(Patch_RouteDeath));
			_harmony.PatchAll(typeof(Patch_Game_Start));
			Log.LogInfo((object)"Oathbound Exp Share v1.1.1 initialized.");
		}

		private void OnDestroy()
		{
			if (_harmony != null)
			{
				_harmony.UnpatchSelf();
			}
		}

		private void OnSettingChanged(object sender, EventArgs e)
		{
			if (_isSyncingConfig || (Object)(object)ZNet.instance == (Object)null)
			{
				return;
			}
			if (ZNet.instance.IsServer())
			{
				((BaseUnityPlugin)this).Config.Save();
				BroadcastConfig(0L);
			}
			else if (ZNet.instance.LocalPlayerIsAdminOrHost())
			{
				ZPackage val = SerializeConfig();
				ZRoutedRpc.instance.InvokeRoutedRPC(0L, "OathboundExpShare_SyncConfig", new object[1] { val });
				if (EnableDebugLogs.Value)
				{
					Log.LogInfo((object)"Admin pushed updated config to server.");
				}
			}
		}

		public static void RegisterRpcs()
		{
			if (ZRoutedRpc.instance != null)
			{
				ZRoutedRpc.instance.Register<ZPackage>("OathboundExpShare_SyncConfig", (Action<long, ZPackage>)RPC_SyncConfig);
			}
		}

		private static ZPackage SerializeConfig()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: 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_0035: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Write(EnableExpShare.Value);
			val.Write(ShareWithDamagers.Value);
			val.Write(DamagerExpPercent.Value);
			val.Write(DamagerMaxDistance.Value);
			val.Write(ShareWithNearby.Value);
			val.Write(NearbyRadius.Value);
			val.Write(NearbyExpPercent.Value);
			return val;
		}

		private static void BroadcastConfig(long target)
		{
			if (ZRoutedRpc.instance != null)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(target, "OathboundExpShare_SyncConfig", new object[1] { SerializeConfig() });
			}
		}

		private static void RPC_SyncConfig(long sender, ZPackage pkg)
		{
			if (pkg == null || (Object)(object)ZNet.instance == (Object)null)
			{
				return;
			}
			bool flag = ZNet.instance.IsServer();
			if (flag)
			{
				ZNetPeer peer = ZNet.instance.GetPeer(sender);
				bool flag2 = false;
				if (peer != null && peer.m_socket != null)
				{
					string hostName = peer.m_socket.GetHostName();
					if (!string.IsNullOrEmpty(hostName) && ZNet.instance.IsAdmin(hostName))
					{
						flag2 = true;
					}
				}
				if (!flag2)
				{
					if (EnableDebugLogs.Value)
					{
						Log.LogWarning((object)("Unauthorized config sync attempt from sender: " + sender));
					}
					return;
				}
			}
			_isSyncingConfig = true;
			try
			{
				EnableExpShare.Value = pkg.ReadBool();
				ShareWithDamagers.Value = pkg.ReadBool();
				DamagerExpPercent.Value = pkg.ReadSingle();
				DamagerMaxDistance.Value = pkg.ReadSingle();
				ShareWithNearby.Value = pkg.ReadBool();
				NearbyRadius.Value = pkg.ReadSingle();
				NearbyExpPercent.Value = pkg.ReadSingle();
				if (flag)
				{
					((BaseUnityPlugin)Instance).Config.Save();
					Log.LogInfo((object)"Admin configuration saved on server. Broadcasting to clients.");
					BroadcastConfig(0L);
				}
				else if (EnableDebugLogs.Value)
				{
					Log.LogInfo((object)"Client synchronized configuration from server.");
				}
			}
			finally
			{
				_isSyncingConfig = false;
			}
		}

		public static void RecordDamager(ZDO zdo, ZDOID attackerID)
		{
			if (zdo == null || ((ZDOID)(ref attackerID)).IsNone())
			{
				return;
			}
			long num = zdo.GetLong("Oathbound_LastUser", 0L);
			int num2 = zdo.GetInt("Oathbound_LastID", 0);
			if (num != ((ZDOID)(ref attackerID)).UserID || num2 != (int)((ZDOID)(ref attackerID)).ID)
			{
				zdo.Set("Oathbound_LastUser", ((ZDOID)(ref attackerID)).UserID);
				zdo.Set("Oathbound_LastID", (int)((ZDOID)(ref attackerID)).ID);
				string text = ((ZDOID)(ref attackerID)).UserID + ":" + ((ZDOID)(ref attackerID)).ID;
				string text2 = zdo.GetString("Oathbound_Damagers", "");
				if (string.IsNullOrEmpty(text2))
				{
					zdo.Set("Oathbound_Damagers", text);
				}
				else if (!text2.Contains(text))
				{
					zdo.Set("Oathbound_Damagers", text2 + "," + text);
				}
			}
		}

		public static ZDOID GetLastAttacker(ZDO zdo)
		{
			//IL_0003: 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_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			if (zdo == null)
			{
				return ZDOID.None;
			}
			long num = zdo.GetLong("Oathbound_LastUser", 0L);
			int num2 = zdo.GetInt("Oathbound_LastID", 0);
			if (num != 0L || num2 != 0)
			{
				return new ZDOID(num, (uint)num2);
			}
			string text = zdo.GetString("Oathbound_Damagers", "");
			if (!string.IsNullOrEmpty(text))
			{
				string[] array = text.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
				if (array.Length != 0)
				{
					string[] array2 = array[^1].Split(':');
					if (array2.Length == 2 && long.TryParse(array2[0], out var result) && uint.TryParse(array2[1], out var result2))
					{
						return new ZDOID(result, result2);
					}
				}
			}
			return ZDOID.None;
		}

		public static Player ResolvePlayerFromZDOID(ZDOID zdoid)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if (((ZDOID)(ref zdoid)).IsNone())
			{
				return null;
			}
			if ((Object)(object)Player.m_localPlayer != (Object)null && ((Character)Player.m_localPlayer).GetZDOID() == zdoid)
			{
				return Player.m_localPlayer;
			}
			List<Player> allPlayers = Player.GetAllPlayers();
			if (allPlayers != null)
			{
				for (int i = 0; i < allPlayers.Count; i++)
				{
					Player val = allPlayers[i];
					if ((Object)(object)val != (Object)null && ((Character)val).GetZDOID() == zdoid)
					{
						return val;
					}
				}
			}
			return null;
		}

		public static Player ResolvePlayerOwner(Character attackerChar)
		{
			if ((Object)(object)attackerChar == (Object)null)
			{
				return null;
			}
			try
			{
				if (_bloodKillOwner != null)
				{
					object? obj = _bloodKillOwner.Invoke(null, new object[1] { attackerChar });
					Player val = (Player)((obj is Player) ? obj : null);
					if ((Object)(object)val != (Object)null)
					{
						return val;
					}
				}
				if (_hunterKillOwner != null)
				{
					object? obj2 = _hunterKillOwner.Invoke(null, new object[1] { attackerChar });
					Player val2 = (Player)((obj2 is Player) ? obj2 : null);
					if ((Object)(object)val2 != (Object)null)
					{
						return val2;
					}
				}
				if (_dragonKillOwner != null)
				{
					object? obj3 = _dragonKillOwner.Invoke(null, new object[1] { attackerChar });
					Player val3 = (Player)((obj3 is Player) ? obj3 : null);
					if ((Object)(object)val3 != (Object)null)
					{
						return val3;
					}
				}
			}
			catch
			{
			}
			return null;
		}

		public static float ComputeStrongestHit(ZDO victimZDO, GameObject prefab)
		{
			try
			{
				if (_strongestHitMethod != null)
				{
					return (float)_strongestHitMethod.Invoke(null, new object[2] { victimZDO, prefab });
				}
			}
			catch
			{
			}
			return 0f;
		}

		public static void DistributeRewards(Plugin pluginInstance, ZDOID victim, ZDOID killer, float maxHealth, bool isBoss)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			if ((_serverDeathsField != null && (Object)(object)pluginInstance != (Object)null && (!(_serverDeathsField.GetValue(pluginInstance) is HashSet<ZDOID> hashSet) || !hashSet.Contains(victim))) || ZDOMan.instance == null || (Object)(object)ZNetScene.instance == (Object)null)
			{
				return;
			}
			ZDO zDO = ZDOMan.instance.GetZDO(victim);
			if (zDO == null)
			{
				return;
			}
			GameObject prefab = ZNetScene.instance.GetPrefab(zDO.GetPrefab());
			if ((Object)(object)prefab == (Object)null)
			{
				return;
			}
			float num = ComputeStrongestHit(zDO, prefab);
			int num2 = KillRewards.Experience(maxHealth, isBoss, num);
			if (num2 <= 0)
			{
				return;
			}
			float num3 = 1f;
			if (_xpMultiplierField != null && (Object)(object)pluginInstance != (Object)null && _xpMultiplierField.GetValue(pluginInstance) is ConfigEntry<float> val)
			{
				num3 = val.Value;
			}
			int fullReward = Mathf.RoundToInt((float)num2 * num3);
			if (fullReward <= 0)
			{
				return;
			}
			Vector3 mobPos = zDO.GetPosition();
			HashSet<ZDOID> damagerZDOIDs = new HashSet<ZDOID>();
			string text = zDO.GetString("Oathbound_Damagers", "");
			if (!string.IsNullOrEmpty(text))
			{
				string[] array = text.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
				for (int i = 0; i < array.Length; i++)
				{
					string[] array2 = array[i].Split(':');
					if (array2.Length == 2 && long.TryParse(array2[0], out var result) && uint.TryParse(array2[1], out var result2))
					{
						damagerZDOIDs.Add(new ZDOID(result, result2));
					}
				}
			}
			HashSet<ZDOID> rewarded = new HashSet<ZDOID> { killer };
			if ((Object)(object)ZNet.instance != (Object)null)
			{
				List<ZNetPeer> peers = ZNet.instance.GetPeers();
				if (peers != null)
				{
					for (int j = 0; j < peers.Count; j++)
					{
						ZNetPeer val2 = peers[j];
						if (val2 != null && !((ZDOID)(ref val2.m_characterID)).IsNone())
						{
							CheckAndReward(val2.m_characterID, val2.m_refPos, val2.m_rpc, val2.m_playerName);
						}
					}
				}
			}
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				ZDOID zDOID = ((Character)Player.m_localPlayer).GetZDOID();
				if (!((ZDOID)(ref zDOID)).IsNone())
				{
					CheckAndReward(((Character)Player.m_localPlayer).GetZDOID(), ((Component)Player.m_localPlayer).transform.position, null, Player.m_localPlayer.GetPlayerName());
				}
			}
			void CheckAndReward(ZDOID playerId, Vector3 playerPos, ZRpc rpc, string playerName)
			{
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: 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_00f9: 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_0107: Expected O, but got Unknown
				//IL_010b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0117: Unknown result type (might be due to invalid IL or missing references)
				if (!((ZDOID)(ref playerId)).IsNone() && !rewarded.Contains(playerId))
				{
					bool flag = damagerZDOIDs.Contains(playerId);
					float num4 = Vector3.Distance(playerPos, mobPos);
					bool flag2 = ShareWithDamagers.Value && flag && (DamagerMaxDistance.Value <= 0f || num4 <= DamagerMaxDistance.Value);
					bool flag3 = ShareWithNearby.Value && num4 <= NearbyRadius.Value;
					if (flag2 || flag3)
					{
						float num5 = 0f;
						if (flag2)
						{
							num5 = DamagerExpPercent.Value;
						}
						if (flag3 && NearbyExpPercent.Value > num5)
						{
							num5 = NearbyExpPercent.Value;
						}
						if (!(num5 <= 0f))
						{
							int num6 = Mathf.Clamp(Mathf.RoundToInt((float)fullReward * (num5 / 100f)), 1, 3200);
							rewarded.Add(playerId);
							ZPackage val3 = new ZPackage();
							val3.Write(victim);
							val3.Write(playerId);
							val3.Write(num6);
							val3.Write(false);
							if (rpc != null)
							{
								rpc.Invoke("Warrior_Reward_1", new object[1] { val3 });
							}
							else if ((Object)(object)pluginInstance != (Object)null && _receiveRewardMethod != null)
							{
								val3.SetPos(0);
								_receiveRewardMethod.Invoke(pluginInstance, new object[1] { val3 });
							}
							if (EnableDebugLogs.Value)
							{
								Log.LogInfo((object)$"Granted {num6} shared EXP to {playerName} (Damager: {flag}, Dist: {num4:F1}m)");
							}
						}
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(Game), "Start")]
	public static class Patch_Game_Start
	{
		[HarmonyPostfix]
		public static void Postfix()
		{
			OathboundExpSharePlugin.RegisterRpcs();
		}
	}
	[HarmonyPatch(typeof(Character), "RPC_Damage")]
	public static class Patch_Character_RPC_Damage
	{
		[HarmonyPrefix]
		public static void Prefix(Character __instance, long sender, HitData hit)
		{
			//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_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: 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_0065: 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_00bb: Unknown result type (might be due to invalid IL or missing references)
			if (!OathboundExpSharePlugin.EnableExpShare.Value || (Object)(object)__instance == (Object)null || hit == null || __instance.IsPlayer() || __instance.IsTamed())
			{
				return;
			}
			try
			{
				ZDOID attackerID = ZDOID.None;
				Character attacker = hit.GetAttacker();
				if ((Object)(object)attacker != (Object)null)
				{
					Player val = (Player)(object)((attacker is Player) ? attacker : null);
					if (val != null)
					{
						attackerID = ((Character)val).GetZDOID();
					}
					else
					{
						Player val2 = OathboundExpSharePlugin.ResolvePlayerOwner(attacker);
						if ((Object)(object)val2 != (Object)null)
						{
							attackerID = ((Character)val2).GetZDOID();
						}
					}
				}
				if (((ZDOID)(ref attackerID)).IsNone() && !((ZDOID)(ref hit.m_attacker)).IsNone())
				{
					attackerID = hit.m_attacker;
				}
				if (((ZDOID)(ref attackerID)).IsNone())
				{
					return;
				}
				ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
				if ((Object)(object)component != (Object)null && component.IsValid())
				{
					ZDO zDO = component.GetZDO();
					if (zDO != null)
					{
						OathboundExpSharePlugin.RecordDamager(zDO, attackerID);
					}
				}
			}
			catch (Exception ex)
			{
				if (OathboundExpSharePlugin.EnableDebugLogs.Value)
				{
					OathboundExpSharePlugin.Log.LogError((object)("Error in RPC_Damage prefix: " + ex));
				}
			}
		}
	}
	[HarmonyPatch(typeof(Character), "OnDeath")]
	public static class Patch_Character_OnDeath
	{
		[HarmonyPriority(800)]
		[HarmonyPrefix]
		public static void Prefix(Character __instance, ref HitData ___m_lastHit)
		{
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Expected O, but got Unknown
			if (!OathboundExpSharePlugin.EnableExpShare.Value || (Object)(object)__instance == (Object)null || __instance.IsPlayer() || __instance.IsTamed())
			{
				return;
			}
			try
			{
				bool flag = false;
				if (___m_lastHit != null)
				{
					Character attacker = ___m_lastHit.GetAttacker();
					if ((Object)(object)attacker != (Object)null && (attacker is Player || (Object)(object)OathboundExpSharePlugin.ResolvePlayerOwner(attacker) != (Object)null))
					{
						flag = true;
					}
				}
				if (flag)
				{
					return;
				}
				ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
				if (!((Object)(object)component != (Object)null) || !component.IsValid())
				{
					return;
				}
				ZDO zDO = component.GetZDO();
				if (zDO == null)
				{
					return;
				}
				ZDOID lastAttacker = OathboundExpSharePlugin.GetLastAttacker(zDO);
				if (((ZDOID)(ref lastAttacker)).IsNone())
				{
					return;
				}
				Player val = OathboundExpSharePlugin.ResolvePlayerFromZDOID(lastAttacker);
				if ((Object)(object)val != (Object)null)
				{
					if (___m_lastHit == null)
					{
						___m_lastHit = new HitData();
					}
					___m_lastHit.SetAttacker((Character)(object)val);
					___m_lastHit.m_attacker = lastAttacker;
					if (OathboundExpSharePlugin.EnableDebugLogs.Value)
					{
						OathboundExpSharePlugin.Log.LogInfo((object)$"Restored DoT killer for {((Object)__instance).name} -> {val.GetPlayerName()}");
					}
				}
			}
			catch (Exception ex)
			{
				if (OathboundExpSharePlugin.EnableDebugLogs.Value)
				{
					OathboundExpSharePlugin.Log.LogError((object)("Error in OnDeath prefix: " + ex));
				}
			}
		}
	}
	[HarmonyPatch(typeof(Plugin), "RouteDeath")]
	public static class Patch_RouteDeath
	{
		[HarmonyPostfix]
		public static void Postfix(Plugin __instance, long sender, ZPackage packet)
		{
			//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_0020: 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_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			if (!OathboundExpSharePlugin.EnableExpShare.Value || packet == null)
			{
				return;
			}
			try
			{
				packet.SetPos(0);
				ZDOID victim = packet.ReadZDOID();
				ZDOID killer = packet.ReadZDOID();
				float maxHealth = packet.ReadSingle();
				bool isBoss = packet.ReadBool();
				OathboundExpSharePlugin.DistributeRewards(__instance, victim, killer, maxHealth, isBoss);
			}
			catch (Exception ex)
			{
				if (OathboundExpSharePlugin.EnableDebugLogs.Value)
				{
					OathboundExpSharePlugin.Log.LogError((object)("Error in RouteDeath postfix: " + ex));
				}
			}
		}
	}
}