Decompiled source of Soulmates v0.3.1

plugins/com.github.Wesmania.Soulmates.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Peak.Afflictions;
using Photon.Pun;
using Photon.Realtime;
using TMPro;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.UI;
using pworld.Scripts.Extensions;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("com.github.Wesmania.Soulmates")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.3.1.0")]
[assembly: AssemblyInformationalVersion("0.3.1+e5a3f6a0259291e7a9c30643057bd278ff9f4ec4")]
[assembly: AssemblyProduct("com.github.Wesmania.Soulmates")]
[assembly: AssemblyTitle("Soulmates")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.3.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace Soulmates
{
	internal static class AfflictionUtil
	{
		public static void OnSharedAfflictionEvent(int sender, string json)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.LocalCharIsReady() || !Plugin.globalSoulmates.PidIsSoulmate(sender))
			{
				return;
			}
			SharedAffliction sharedAffliction = SharedAffliction.Deserialize(json);
			Character localCharacter = Character.localCharacter;
			if (sharedAffliction.type.HasValue)
			{
				Affliction val = Affliction.CreateBlankAffliction(sharedAffliction.type.Value);
				val.totalTime = sharedAffliction.totalTime;
				AfflictionPatch.skipMessage = true;
				localCharacter.refs.afflictions.AddAffliction(val, false);
				AfflictionPatch.skipMessage = false;
			}
			else
			{
				if (!sharedAffliction.other_type.HasValue)
				{
					return;
				}
				OtherAfflictions value = sharedAffliction.other_type.Value;
				if ((uint)value <= 1u)
				{
					GameObject gameObject = ((Component)localCharacter).gameObject;
					ShroomBehaviourCopy shroomBehaviourCopy = gameObject.GetComponent<ShroomBehaviourCopy>() ?? gameObject.AddComponent<ShroomBehaviourCopy>();
					switch (value)
					{
					case OtherAfflictions.PARALYSIS:
						shroomBehaviourCopy.ApplyParalysis();
						break;
					case OtherAfflictions.INDIGESTION:
						shroomBehaviourCopy.ApplyIndigestion();
						break;
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(CharacterAfflictions))]
	public static class AfflictionPatch
	{
		public static bool skipMessage;

		[HarmonyPostfix]
		[HarmonyPatch("AddAffliction", new Type[]
		{
			typeof(Affliction),
			typeof(bool)
		})]
		public static void AddAfflictionPostfix(CharacterAfflictions __instance, Affliction affliction, bool fromRPC)
		{
			//IL_00b9: 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_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			if (__instance.character.IsLocal && __instance.character.isLiv() && !skipMessage)
			{
				Dictionary<AfflictionType, Func<bool>> dictionary = new Dictionary<AfflictionType, Func<bool>>
				{
					{
						(AfflictionType)1,
						Plugin.config.SharedLolli
					},
					{
						(AfflictionType)2,
						Plugin.config.SharedEnergol
					},
					{
						(AfflictionType)18,
						Plugin.config.SharedBlindness
					},
					{
						(AfflictionType)17,
						Plugin.config.SharedFloating
					},
					{
						(AfflictionType)16,
						Plugin.config.SharedMilk
					},
					{
						(AfflictionType)19,
						Plugin.config.SharedSporedMeter
					}
				};
				AfflictionType afflictionType = affliction.GetAfflictionType();
				if (dictionary.ContainsKey(afflictionType) && dictionary[afflictionType]())
				{
					SharedAffliction e = default(SharedAffliction);
					e.type = afflictionType;
					e.other_type = null;
					e.totalTime = affliction.totalTime;
					Events.SendSharedAfflictionEvent(e);
				}
			}
		}
	}
	public class ShroomBehaviourCopy : MonoBehaviour
	{
		public void ApplyParalysis()
		{
			if (Plugin.LocalCharIsReady())
			{
				Character localCharacter = Character.localCharacter;
				((MonoBehaviour)this).StartCoroutine(ParalysisCoroutine(localCharacter));
			}
			static IEnumerator ParalysisCoroutine(Character character)
			{
				yield return (object)new WaitForSeconds(3f);
				character.Fall(8f, 0f);
			}
		}

		public void ApplyIndigestion()
		{
			if (Plugin.LocalCharIsReady())
			{
				Character localCharacter = Character.localCharacter;
				((MonoBehaviour)this).StartCoroutine(IndigestionCoroutine(localCharacter));
			}
			static IEnumerator IndigestionCoroutine(Character character)
			{
				yield return (object)new WaitForSeconds(3f);
				GameUtils.instance.SpawnResourceAtPositionNetworked("VFX_SporeExploExploEdibleSpawn", character.Center, (RpcTarget)1);
				GameUtils.instance.RPC_SpawnResourceAtPosition("VFX_SporeExploExploEdibleSpawn_NoKnockback", character.Center);
				character.AddForceToBodyPart(character.GetBodypartRig((BodypartType)0), Vector3.zero, Vector3.up * 100f);
			}
		}
	}
	[HarmonyPatch(typeof(Action_RandomMushroomEffect))]
	public static class MushroomEffectPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("RunRandomEffect", new Type[] { typeof(int) })]
		public static void RunRandomEffectPrefix(Action_RandomMushroomEffect __instance, int effect)
		{
			if (((ItemActionBase)__instance).character.IsLocal)
			{
				SharedAffliction e = default(SharedAffliction);
				e.type = null;
				e.totalTime = 0f;
				OtherAfflictions? otherAfflictions = null;
				if (effect == 5 && Plugin.config.SharedFarts())
				{
					otherAfflictions = OtherAfflictions.INDIGESTION;
				}
				if (effect == 7 && Plugin.config.SharedParalysis())
				{
					otherAfflictions = OtherAfflictions.PARALYSIS;
				}
				if (otherAfflictions.HasValue)
				{
					e.other_type = otherAfflictions.Value;
					Events.SendSharedAfflictionEvent(e);
				}
			}
		}
	}
	public static class Bonk
	{
		public static void OnSharedBonkEvent(int sender, string json)
		{
			//IL_0041: 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)
			SharedBonk sharedBonk = SharedBonk.Deserialize(json);
			if (Plugin.LocalCharIsReady())
			{
				Character localCharacter = Character.localCharacter;
				if (Plugin.globalSoulmates.PidIsSoulmate(sharedBonk.victim))
				{
					localCharacter.Fall(sharedBonk.ragdollTime, 0f);
					localCharacter.AddForceAtPosition(sharedBonk.force.toVector3(), sharedBonk.contactPoint.toVector3(), sharedBonk.range);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Bonkable))]
	public static class BonkPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("Bonk", new Type[] { typeof(Collision) })]
		public static void BonkPrefix(Bonkable __instance, Collision coll)
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: 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)
			//IL_007b: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
			Character componentInParent = coll.gameObject.GetComponentInParent<Character>();
			if (Object.op_Implicit((Object)(object)componentInParent) && Time.time > __instance.lastBonkedTime + __instance.bonkCooldown && Plugin.config.SharedBonk())
			{
				int actorNumber = ((MonoBehaviourPun)componentInParent).photonView.Owner.ActorNumber;
				int? num = SteamComms.PhotonIdToPid(actorNumber);
				if (num.HasValue)
				{
					SharedBonk e = default(SharedBonk);
					e.ragdollTime = __instance.ragdollTime;
					Vector3 relativeVelocity = coll.relativeVelocity;
					e.force = new V3(-((Vector3)(ref relativeVelocity)).normalized * __instance.bonkForce);
					e.contactPoint = new V3(((ContactPoint)(ref coll.contacts[0])).point);
					e.range = __instance.bonkRange;
					e.victim = num.Value;
					Events.SendSharedBonkEvent(e);
				}
			}
		}
	}
	public static class Colors
	{
		public static Color soulmateColor = new Color(3f / 32f, 0.86328125f, 0.15234375f);

		public static Color[] c = (Color[])(object)new Color[10]
		{
			new Color(0.83984375f, 0.12890625f, 0.12890625f),
			new Color(51f / 128f, 31f / 64f, 0.99609375f),
			new Color(0.91015625f, 0.8125f, 0.3125f),
			new Color(0.63671875f, 11f / 32f, 57f / 64f),
			new Color(19f / 64f, 0.90234375f, 57f / 64f),
			new Color(0.80859375f, 0.40234375f, 3f / 32f),
			new Color(127f / 128f, 0.23828125f, 109f / 128f),
			new Color(0.59765625f, 0.59765625f, 0.59765625f),
			new Color(69f / 128f, 11f / 32f, 0f),
			new Color(7f / 64f, 0.09765625f, 0.52734375f)
		};

		public static Color getColor(int idx)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			if (idx < c.Length)
			{
				return c[idx];
			}
			return Color.white;
		}
	}
	public class ModConfig
	{
		private ConfigEntry<bool> CEnabled { get; set; }

		private ConfigEntry<int> CSoulmateGroupSize { get; set; }

		private ConfigEntry<float> CSoulmateStrength { get; set; }

		private ConfigEntry<string> CFixedSoulmates { get; set; }

		private ConfigEntry<bool> CEnableSharedBonk { get; set; }

		private ConfigEntry<bool> CEnableSharedSlip { get; set; }

		private ConfigEntry<bool> CEnableSharedExtraStaminaGain { get; set; }

		private ConfigEntry<bool> CEnableSharedExtraStaminaUse { get; set; }

		private ConfigEntry<bool> CEnableSharedLolli { get; set; }

		private ConfigEntry<bool> CEnableSharedEnergol { get; set; }

		private ConfigEntry<bool> CEnableSharedBlindness { get; set; }

		private ConfigEntry<bool> CEnableSharedFloating { get; set; }

		private ConfigEntry<bool> CEnableSharedMilk { get; set; }

		private ConfigEntry<bool> CEnableSharedParalysis { get; set; }

		private ConfigEntry<bool> CEnableSharedFarts { get; set; }

		private ConfigEntry<bool> CEnableSharedSporedMeter { get; set; }

		public Config? ReceivedConfig { get; private set; }

		public ModConfig()
		{
		}

		public ModConfig(ConfigFile pluginConfig)
		{
			CEnabled = pluginConfig.Bind<bool>("Config", "Enabled", true, "Enable/disable the mod with this");
			CSoulmateGroupSize = pluginConfig.Bind<int>("Config", "SoulmateGroupSize", 2, "How many people are bound in one group. Defaults to 2.");
			CSoulmateStrength = pluginConfig.Bind<float>("Config", "SoulmateStrength", 1f, "How much of soulmate's status is applied to you");
			CFixedSoulmates = pluginConfig.Bind<string>("Config", "FixedSoulmates", "", "Fixed soulmate assignments, matched by nick. Format is \"name1,name2;name3,name4\".\nThis will match name1 with name2 and name3 with name4.");
			CEnableSharedBonk = pluginConfig.Bind<bool>("Config", "EnableSharedBonk", true, "Bonking a player bonks his soulmate too");
			CEnableSharedSlip = pluginConfig.Bind<bool>("Config", "EnableSharedSlip", true, "Slipping on something makes the soulmate slip too");
			CEnableSharedExtraStaminaGain = pluginConfig.Bind<bool>("Config", "EnableSharedExtraStaminaGain", true, "Soulmates share extra stamina gained");
			CEnableSharedExtraStaminaUse = pluginConfig.Bind<bool>("Config", "EnableSharedExtraStaminaUse", true, "Soulmates use a single extra stamina pool");
			CEnableSharedLolli = pluginConfig.Bind<bool>("Config", "EnableSharedLolli", true, "Soulmates share lollipop boost");
			CEnableSharedEnergol = pluginConfig.Bind<bool>("Config", "EnableSharedEnergol", true, "Soulmates share energy drink boost");
			CEnableSharedBlindness = pluginConfig.Bind<bool>("Config", "EnableSharedBlindness", true, "Soulmates share blind status");
			CEnableSharedFloating = pluginConfig.Bind<bool>("Config", "EnableSharedFloating", true, "Soulmates share the floating mushroom effect");
			CEnableSharedMilk = pluginConfig.Bind<bool>("Config", "EnableSharedMilk", true, "Soulmates share invincibility from milk and mushrooms");
			CEnableSharedParalysis = pluginConfig.Bind<bool>("Config", "EnableSharedParalysis", true, "Soulmates share mushroom paralysis");
			CEnableSharedFarts = pluginConfig.Bind<bool>("Config", "EnableSharedFarts", true, "Soulmates share mushroom indigestion");
			CEnableSharedSporedMeter = pluginConfig.Bind<bool>("Config", "EnableSharedSporedMeter", true, "Soulmates share stamina meter sporification");
		}

		public bool Enabled()
		{
			return CEnabled.Value;
		}

		public void SetReceivedConfig(Config c)
		{
			ReceivedConfig = c;
		}

		public void ClearReceivedConfig()
		{
			ReceivedConfig = null;
		}

		public Config GetConfigToSend()
		{
			if (ReceivedConfig.HasValue)
			{
				return ReceivedConfig.Value;
			}
			Config result = default(Config);
			result.sharedBonk = CEnableSharedBonk.Value;
			result.sharedSlip = CEnableSharedSlip.Value;
			result.sharedExtraStaminaGain = CEnableSharedExtraStaminaGain.Value;
			result.sharedExtraStaminaUse = CEnableSharedExtraStaminaUse.Value;
			result.sharedLolli = CEnableSharedLolli.Value;
			result.sharedEnergol = CEnableSharedEnergol.Value;
			result.sharedBlindness = CEnableSharedBlindness.Value;
			result.sharedFloating = CEnableSharedFloating.Value;
			result.sharedMilk = CEnableSharedMilk.Value;
			result.sharedParalysis = CEnableSharedParalysis.Value;
			result.sharedFarts = CEnableSharedFarts.Value;
			result.sharedSporedMeter = CEnableSharedSporedMeter.Value;
			result.soulmateGroupSize = CSoulmateGroupSize.Value;
			result.soulmateStrength = CSoulmateStrength.Value;
			return result;
		}

		public int SoulmateGroupSize()
		{
			if (!ReceivedConfig.HasValue)
			{
				Plugin.Log.LogError((object)"SoulmateGroupSize accessed without active soulmate config!");
				return 2;
			}
			return ReceivedConfig.Value.soulmateGroupSize;
		}

		public float SoulmateStrength()
		{
			if (!ReceivedConfig.HasValue)
			{
				Plugin.Log.LogError((object)"SoulmateStrength accessed without active soulmate config!");
				return 1f;
			}
			return ReceivedConfig.Value.soulmateStrength;
		}

		public bool SharedBonk()
		{
			if (ReceivedConfig.HasValue)
			{
				return ReceivedConfig.Value.sharedBonk;
			}
			return false;
		}

		public bool SharedSlip()
		{
			if (ReceivedConfig.HasValue)
			{
				return ReceivedConfig.Value.sharedSlip;
			}
			return false;
		}

		public bool SharedExtraStaminaGain()
		{
			if (ReceivedConfig.HasValue)
			{
				return ReceivedConfig.Value.sharedExtraStaminaGain;
			}
			return false;
		}

		public bool SharedExtraStaminaUse()
		{
			if (ReceivedConfig.HasValue)
			{
				return ReceivedConfig.Value.sharedExtraStaminaUse;
			}
			return false;
		}

		public bool SharedLolli()
		{
			if (ReceivedConfig.HasValue)
			{
				return ReceivedConfig.Value.sharedLolli;
			}
			return false;
		}

		public bool SharedEnergol()
		{
			if (ReceivedConfig.HasValue)
			{
				return ReceivedConfig.Value.sharedEnergol;
			}
			return false;
		}

		public bool SharedBlindness()
		{
			if (ReceivedConfig.HasValue)
			{
				return ReceivedConfig.Value.sharedBlindness;
			}
			return false;
		}

		public bool SharedFloating()
		{
			if (ReceivedConfig.HasValue)
			{
				return ReceivedConfig.Value.sharedFloating;
			}
			return false;
		}

		public bool SharedMilk()
		{
			if (ReceivedConfig.HasValue)
			{
				return ReceivedConfig.Value.sharedMilk;
			}
			return false;
		}

		public bool SharedParalysis()
		{
			if (ReceivedConfig.HasValue)
			{
				return ReceivedConfig.Value.sharedParalysis;
			}
			return false;
		}

		public bool SharedFarts()
		{
			if (ReceivedConfig.HasValue)
			{
				return ReceivedConfig.Value.sharedFarts;
			}
			return false;
		}

		public bool SharedSporedMeter()
		{
			if (ReceivedConfig.HasValue)
			{
				return ReceivedConfig.Value.sharedSporedMeter;
			}
			return false;
		}

		public bool HasFixedSoulmates()
		{
			return CFixedSoulmates.Value != "";
		}

		public List<List<string>> GetFixedSoulmates()
		{
			return (from s in CFixedSoulmates.Value.Split(";").ToList()
				select s.Split(",").ToList()).ToList();
		}
	}
	public static class ConnectSoulmate
	{
		private static int globalConnectedSoulmateCount;

		public static int ConnectedToSoulmateCount()
		{
			if (!Plugin.LocalCharIsReady())
			{
				return 0;
			}
			if (!Character.localCharacter.isLiv())
			{
				return 0;
			}
			return Plugin.globalSoulmates.LiveSoulmateCount();
		}

		public static void UpdateSoulmateStatus()
		{
			if (!((Object)(object)Character.localCharacter == (Object)null))
			{
				int num = ConnectedToSoulmateCount();
				if (num != globalConnectedSoulmateCount)
				{
					UpdateConnectedSoulmates();
				}
			}
		}

		private static void UpdateConnectedSoulmates()
		{
			if (Plugin.LocalCharIsReady())
			{
				Character localCharacter = Character.localCharacter;
				localCharacter.refs.afflictions.UpdateWeight();
			}
		}
	}
	public class EventCache
	{
		public static EventCache instance = new EventCache();

		private Dictionary<(STATUSTYPE, SharedDamageKind), float> cache = new Dictionary<(STATUSTYPE, SharedDamageKind), float>
		{
			{
				((STATUSTYPE)1, SharedDamageKind.ADD),
				0f
			},
			{
				((STATUSTYPE)1, SharedDamageKind.SUBTRACT),
				0f
			},
			{
				((STATUSTYPE)2, SharedDamageKind.ADD),
				0f
			},
			{
				((STATUSTYPE)2, SharedDamageKind.SUBTRACT),
				0f
			},
			{
				((STATUSTYPE)8, SharedDamageKind.ADD),
				0f
			},
			{
				((STATUSTYPE)8, SharedDamageKind.SUBTRACT),
				0f
			},
			{
				((STATUSTYPE)3, SharedDamageKind.ADD),
				0f
			},
			{
				((STATUSTYPE)3, SharedDamageKind.SUBTRACT),
				0f
			},
			{
				((STATUSTYPE)10, SharedDamageKind.ADD),
				0f
			},
			{
				((STATUSTYPE)10, SharedDamageKind.SUBTRACT),
				0f
			},
			{
				((STATUSTYPE)6, SharedDamageKind.ADD),
				0f
			},
			{
				((STATUSTYPE)6, SharedDamageKind.SUBTRACT),
				0f
			},
			{
				((STATUSTYPE)11, SharedDamageKind.SUBTRACT),
				0f
			}
		};

		private float staminaCache;

		public SharedDamage? cacheEvent(SharedDamage e)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			(STATUSTYPE, SharedDamageKind) key = (e.type, e.kind);
			if (!cache.ContainsKey(key))
			{
				return e;
			}
			cache[key] += e.value;
			if (cache[key] < 0.0125001f)
			{
				return null;
			}
			e.value = cache[key];
			cache[key] = 0f;
			return e;
		}

		public SharedExtraStamina? cacheStamina(SharedExtraStamina e)
		{
			if (e.diff > 0f)
			{
				return e;
			}
			staminaCache += e.diff;
			if (staminaCache > -0.01f)
			{
				return null;
			}
			e.diff = staminaCache;
			staminaCache = 0f;
			return e;
		}
	}
	public static class Events
	{
		private static void SendEvent(SoulmateEventType eventType, string e, ReceiverGroup who, bool reliable = false)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			SteamComms.SendEvent(eventType, e, who, reliable);
		}

		private static void SendEventTo(SoulmateEventType eventType, string e, int[] targets, bool reliable = false)
		{
			SteamComms.SendEventTo(eventType, e, targets, reliable);
		}

		private static void SendToSoulmates(SoulmateEventType eventType, string e, bool reliable = false)
		{
			if (!Plugin.globalSoulmates.NoSoulmates())
			{
				SendEventTo(eventType, e, Plugin.globalSoulmates.MySoulmatePids().ToArray(), reliable);
			}
		}

		public static void SendRecalculateSoulmateEvent(RecalculateSoulmatesEvent e)
		{
			Plugin.Log.LogInfo((object)"Sending recalculate soulmate event...");
			SendEvent(SoulmateEventType.RECALCULATE, e.Serialize(), (ReceiverGroup)1, reliable: true);
		}

		private static bool IsUselessSubtract(SharedDamage e)
		{
			if (e.kind == SharedDamageKind.SUBTRACT)
			{
				return Plugin.globalSoulmates.MySoulmateCharacters().All(delegate(PlayerCharacterInfo c)
				{
					//IL_0018: 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)
					CharacterAfflictions afflictions = c.c.refs.afflictions;
					return afflictions.GetCurrentStatus(e.type) == 0f && afflictions.GetIncrementalStatus(e.type) == 0f;
				});
			}
			return false;
		}

		public static void SendSharedDamageEvent(SharedDamage e)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			if (!e.type.isShared() || e.type.isAbsolute())
			{
				Plugin.Log.LogInfo((object)"$Tried to send a non-shared or absolute status type {statusType}");
				return;
			}
			SharedDamage? sharedDamage = EventCache.instance.cacheEvent(e);
			if (!sharedDamage.HasValue)
			{
				return;
			}
			e = sharedDamage.Value;
			if (!IsUselessSubtract(e))
			{
				bool reliable = true;
				if (e.kind != SharedDamageKind.SET && (double)math.abs(e.value) < 0.01)
				{
					reliable = false;
				}
				EventStats.instance.CountSharedDamage(e);
				SendToSoulmates(SoulmateEventType.DAMAGE, e.Serialize(), reliable);
			}
		}

		public static void SendUpdateWeightEvent(UpdateWeight e)
		{
			EventStats.instance.CountUpdateWeight();
			SendEvent(SoulmateEventType.UPDATE_WEIGHT, e.Serialize(), (ReceiverGroup)0, reliable: true);
		}

		public static void SendSharedBonkEvent(SharedBonk e)
		{
			EventStats.instance.CountSharedBonk();
			SendEvent(SoulmateEventType.SHARED_BONK, e.Serialize(), (ReceiverGroup)1);
		}

		public static void SendSharedExtraStaminaEvent(SharedExtraStamina e)
		{
			SharedExtraStamina? sharedExtraStamina = EventCache.instance.cacheStamina(e);
			if (sharedExtraStamina.HasValue)
			{
				e = sharedExtraStamina.Value;
				EventStats.instance.CountSharedExtraStamina();
				SendToSoulmates(SoulmateEventType.SHARED_EXTRA_STAMINA, e.Serialize());
			}
		}

		public static void SendSharedAfflictionEvent(SharedAffliction e)
		{
			EventStats.instance.CountSharedAffliction();
			SendToSoulmates(SoulmateEventType.SHARED_AFFLICTION, e.Serialize());
		}

		public static void SendWhoIsMySoulmatesEvent()
		{
			WhoIsMySoulmate whoIsMySoulmate = default(WhoIsMySoulmate);
			SendEvent(SoulmateEventType.WHO_IS_MY_SOULMATES, whoIsMySoulmate.Serialize(), (ReceiverGroup)2, reliable: true);
		}

		public static void SendThisIsYourSoulmatesEvent(RecalculateSoulmatesEvent e, int target)
		{
			SendEventTo(SoulmateEventType.RECALCULATE, e.Serialize(), new int[1] { target }, reliable: true);
		}
	}
	internal class SharedDamageRecord
	{
		private readonly STATUSTYPE type;

		private readonly SharedDamageKind kind;

		public SharedDamageRecord(SharedDamage e)
		{
			//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)
			type = e.type;
			kind = e.kind;
		}

		public override string ToString()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return $"Shared Damage({type}, {kind})";
		}

		public override bool Equals(object obj)
		{
			//IL_000b: 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)
			if (obj is SharedDamageRecord sharedDamageRecord)
			{
				if (type == sharedDamageRecord.type)
				{
					return kind == sharedDamageRecord.kind;
				}
				return false;
			}
			return false;
		}

		public override int GetHashCode()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return HashCode.Combine<STATUSTYPE, SharedDamageKind>(type, kind);
		}
	}
	public class EventStats
	{
		public static EventStats instance = new EventStats();

		private Dictionary<SharedDamageRecord, int> sharedDamageCounts = new Dictionary<SharedDamageRecord, int>();

		private int updateWeightCount;

		private int sharedBonkCount;

		private int sharedExtraStaminaCount;

		private int sharedAfflictionCount;

		public void CountSharedDamage(SharedDamage e)
		{
			SharedDamageRecord key = new SharedDamageRecord(e);
			if (!sharedDamageCounts.ContainsKey(key))
			{
				sharedDamageCounts[key] = 0;
			}
			sharedDamageCounts[key]++;
		}

		public void CountUpdateWeight()
		{
			updateWeightCount++;
		}

		public void CountSharedBonk()
		{
			sharedBonkCount++;
		}

		public void CountSharedExtraStamina()
		{
			sharedExtraStaminaCount++;
		}

		public void CountSharedAffliction()
		{
			sharedAfflictionCount++;
		}

		public void PrintStats()
		{
			Plugin.Log.LogInfo((object)"Event stats:");
			foreach (KeyValuePair<SharedDamageRecord, int> sharedDamageCount in sharedDamageCounts)
			{
				Plugin.Log.LogInfo((object)$"{sharedDamageCount.Key}: {sharedDamageCount.Value}");
			}
			Plugin.Log.LogInfo((object)$"UpdateWeight: {updateWeightCount}");
			Plugin.Log.LogInfo((object)$"SharedBonk: {sharedBonkCount}");
			Plugin.Log.LogInfo((object)$"SharedExtraStamina: {sharedExtraStaminaCount}");
			Plugin.Log.LogInfo((object)$"SharedAffliction: {sharedAfflictionCount}");
		}

		public void Reset()
		{
			sharedDamageCounts.Clear();
			updateWeightCount = 0;
			sharedBonkCount = 0;
			sharedExtraStaminaCount = 0;
			sharedAfflictionCount = 0;
		}
	}
	internal static class StamUtil
	{
		public static float SingleStaminaMult()
		{
			return Plugin.config.SoulmateStrength();
		}

		public static bool sharedExtraStaminaUse()
		{
			return Plugin.config.SharedExtraStaminaUse();
		}

		public static bool sharedExtraStaminaGain()
		{
			return Plugin.config.SharedExtraStaminaGain();
		}

		public static bool onlySharesGain()
		{
			if (sharedExtraStaminaGain())
			{
				return !sharedExtraStaminaUse();
			}
			return false;
		}

		public static void OnSharedExtraStaminaEvent(int sender, string json)
		{
			SharedExtraStamina sharedExtraStamina = SharedExtraStamina.Deserialize(json);
			if (Plugin.LocalCharIsReady() && Plugin.globalSoulmates.PidIsSoulmate(sender))
			{
				Character localCharacter = Character.localCharacter;
				StaminaPatch.skipMessage++;
				localCharacter.AddExtraStamina(sharedExtraStamina.diff * SingleStaminaMult());
				StaminaPatch.skipMessage--;
			}
		}

		public static float MyStaminaGain()
		{
			float num = Plugin.config.SoulmateStrength();
			int num2 = Plugin.config.SoulmateGroupSize();
			float num3 = 1f + num * (float)(num2 - 1);
			return 1f / num3;
		}

		public static float TheirStaminaGain()
		{
			float num = Plugin.config.SoulmateStrength();
			int num2 = Plugin.config.SoulmateGroupSize();
			float num3 = 1f + num * (float)(num2 - 1);
			return num / num3;
		}
	}
	[HarmonyPatch(typeof(Character))]
	public static class StaminaPatch
	{
		public static int skipMessage;

		public static void SendStaminaDiff(Character __instance, float _diff)
		{
			if (!__instance.IsLocal || skipMessage > 0)
			{
				return;
			}
			float num = _diff;
			if (num != 0f && (!(num < 0f) || StamUtil.sharedExtraStaminaUse()) && (!(num > 0f) || StamUtil.sharedExtraStaminaGain()))
			{
				if (num > 0f)
				{
					num = ((!StamUtil.onlySharesGain()) ? (num * Plugin.config.SoulmateStrength()) : (num * StamUtil.TheirStaminaGain()));
				}
				if (num < 0f)
				{
					num *= Plugin.config.SoulmateStrength();
				}
				SharedExtraStamina e = default(SharedExtraStamina);
				e.diff = num;
				Events.SendSharedExtraStaminaEvent(e);
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("UseStamina", new Type[]
		{
			typeof(float),
			typeof(bool)
		})]
		public static void UseStaminaPrefix(Character __instance, float usage, bool useBonusStamina, out float __state)
		{
			__state = __instance.data.extraStamina;
		}

		[HarmonyPostfix]
		[HarmonyPatch("UseStamina", new Type[]
		{
			typeof(float),
			typeof(bool)
		})]
		public static void UseStaminaSuffix(Character __instance, float usage, bool useBonusStamina, float __state)
		{
			if (__instance.IsLocal)
			{
				SendStaminaDiff(__instance, __instance.data.extraStamina - __state);
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("SetExtraStamina", new Type[] { typeof(float) })]
		public static void SetExtraStaminaPrefix(Character __instance, float amt, out float __state)
		{
			__state = __instance.data.extraStamina;
		}

		[HarmonyPostfix]
		[HarmonyPatch("SetExtraStamina", new Type[] { typeof(float) })]
		public static void SetExtraStaminaSuffix(Character __instance, float amt, float __state)
		{
			if (__instance.IsLocal)
			{
				float num = __instance.data.extraStamina - __state;
				if (num > 0f && StamUtil.onlySharesGain())
				{
					skipMessage++;
					float num2 = num * StamUtil.MyStaminaGain();
					__instance.AddExtraStamina(num2 - num);
					skipMessage--;
				}
				SendStaminaDiff(__instance, num);
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("AddExtraStamina", new Type[] { typeof(float) })]
		public static void AddExtraStaminaPrefix(Character __instance, ref float add, out float __state)
		{
			__state = add;
			if (__instance.IsLocal && add > 0f && StamUtil.onlySharesGain())
			{
				add *= StamUtil.MyStaminaGain();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("AddExtraStamina", new Type[] { typeof(float) })]
		public static void AddExtraStaminaSuffix(Character __instance, float add, float __state)
		{
			if (__instance.IsLocal)
			{
				SendStaminaDiff(__instance, __state);
			}
		}
	}
	[HarmonyPatch(typeof(CharacterAfflictions))]
	public class SharedDamagePatch
	{
		internal static readonly HashSet<int> isReceivingSharedDamage = new HashSet<int>();

		internal static readonly Dictionary<int, int> isRecursiveStatusCall = new Dictionary<int, int>();

		private static HashSet<float> SoulmateValues = new HashSet<float>();

		public static void StatusPostfix(CharacterAfflictions __instance, SharedDamage _e)
		{
			//IL_0057: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Invalid comparison between Unknown and I4
			try
			{
				if (__instance.character.IsLocal && !__instance.character.data.dead && !__instance.character.warping && !isReceivingSharedDamage.Contains(((MonoBehaviourPun)__instance.character).photonView.ViewID))
				{
					SharedDamage e = _e;
					if (!e.type.isAbsolute() && e.type.isShared() && ((int)e.type != 1 || e.kind != 0 || !((e.value < 0.01f) & (e.value >= 0f))))
					{
						Events.SendSharedDamageEvent(e);
					}
				}
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Error in SetStatusPostfix: {arg}");
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("SetStatus", new Type[]
		{
			typeof(STATUSTYPE),
			typeof(float),
			typeof(bool)
		})]
		public static void SetStatusPrefix(CharacterAfflictions __instance, STATUSTYPE statusType, ref float amount, bool pushStatus, out float __state)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			__state = __instance.GetCurrentStatus(statusType);
			if (statusType.isAbsolute())
			{
				amount = Weight.PreSetWeight(__instance, statusType, amount);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("SetStatus", new Type[]
		{
			typeof(STATUSTYPE),
			typeof(float),
			typeof(bool)
		})]
		public static void SetStatusPostfix(CharacterAfflictions __instance, STATUSTYPE statusType, float amount, bool pushStatus, float __state)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			float currentStatus = __instance.GetCurrentStatus(statusType);
			float num = currentStatus - __state;
			if (num != 0f)
			{
				if (!statusType.isAbsolute())
				{
					SharedDamage e = default(SharedDamage);
					e.type = statusType;
					e.value = num;
					e.kind = SharedDamageKind.SET;
					StatusPostfix(__instance, e);
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("AddStatus", new Type[]
		{
			typeof(STATUSTYPE),
			typeof(float),
			typeof(bool),
			typeof(bool),
			typeof(bool)
		})]
		public static void AddStatusPrefix(CharacterAfflictions __instance, STATUSTYPE statusType, float amount, bool fromRPC, bool playEffects, bool notify, out SharedDamage __state)
		{
			//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)
			__state.type = statusType;
			__state.value = amount;
			__state.kind = SharedDamageKind.ADD;
			if (!isRecursiveStatusCall.ContainsKey(((MonoBehaviourPun)__instance.character).photonView.ViewID))
			{
				isRecursiveStatusCall[((MonoBehaviourPun)__instance.character).photonView.ViewID] = 0;
			}
			isRecursiveStatusCall[((MonoBehaviourPun)__instance.character).photonView.ViewID]++;
		}

		[HarmonyPostfix]
		[HarmonyPatch("AddStatus", new Type[]
		{
			typeof(STATUSTYPE),
			typeof(float),
			typeof(bool),
			typeof(bool),
			typeof(bool)
		})]
		public static void AddStatusPostfix(CharacterAfflictions __instance, STATUSTYPE statusType, float amount, bool fromRPC, bool playEffects, bool notify, SharedDamage __state)
		{
			isRecursiveStatusCall[((MonoBehaviourPun)__instance.character).photonView.ViewID]--;
			if (isRecursiveStatusCall[((MonoBehaviourPun)__instance.character).photonView.ViewID] == 0)
			{
				StatusPostfix(__instance, __state);
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("SubtractStatus", new Type[]
		{
			typeof(STATUSTYPE),
			typeof(float),
			typeof(bool),
			typeof(bool)
		})]
		public static void SubtractStatusPrefix(CharacterAfflictions __instance, STATUSTYPE statusType, float amount, bool fromRPC, bool decreasedNaturally, out SharedDamage __state)
		{
			//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)
			__state.type = statusType;
			__state.value = amount;
			__state.kind = SharedDamageKind.SUBTRACT;
			if (!isRecursiveStatusCall.ContainsKey(((MonoBehaviourPun)__instance.character).photonView.ViewID))
			{
				isRecursiveStatusCall[((MonoBehaviourPun)__instance.character).photonView.ViewID] = 0;
			}
			isRecursiveStatusCall[((MonoBehaviourPun)__instance.character).photonView.ViewID]++;
		}

		[HarmonyPostfix]
		[HarmonyPatch("SubtractStatus", new Type[]
		{
			typeof(STATUSTYPE),
			typeof(float),
			typeof(bool),
			typeof(bool)
		})]
		public static void SubtractStatusPostfix(CharacterAfflictions __instance, STATUSTYPE statusType, float amount, bool fromRPC, bool decreasedNaturally, SharedDamage __state)
		{
			isRecursiveStatusCall[((MonoBehaviourPun)__instance.character).photonView.ViewID]--;
			if (isRecursiveStatusCall[((MonoBehaviourPun)__instance.character).photonView.ViewID] == 0)
			{
				StatusPostfix(__instance, __state);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("UpdateNormalStatuses")]
		public static void UpdateNormalStatusesPostfix(CharacterAfflictions __instance)
		{
			if (!((MonoBehaviourPun)__instance).photonView.IsMine || !__instance.character.data.fullyConscious)
			{
				return;
			}
			foreach (PlayerCharacterInfo item in Plugin.globalSoulmates.MySoulmateCharacters())
			{
				Character c = item.c;
				if (c.data.fullyConscious && !c.data.isSkeleton)
				{
					float num = Time.deltaTime * __instance.hungerPerSecond * Ascents.hungerRateMultiplier * Plugin.config.SoulmateStrength();
					__instance.AddStatus((STATUSTYPE)1, num, false, true, true);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Character))]
	public static class RecalculateSoulmatesPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("StartPassedOutOnTheBeach")]
		public static void StartPassedOutOnTheBeachPostfix(Character __instance)
		{
			if (__instance.IsLocal)
			{
				RecalculateSoulmatesEvent? recalculateSoulmatesEvent = Plugin.RecalculateSoulmate(firstTime: true);
				if (recalculateSoulmatesEvent.HasValue)
				{
					Events.SendRecalculateSoulmateEvent(recalculateSoulmatesEvent.Value);
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("Update")]
		public static void UpdatePostfix(Character __instance)
		{
			if (__instance.IsLocal)
			{
				ConnectSoulmate.UpdateSoulmateStatus();
				Weight.MaybeSendWeight();
			}
		}
	}
	[HarmonyPatch(typeof(Campfire))]
	public static class RecalculateSoulmatesPatch2
	{
		[HarmonyPostfix]
		[HarmonyPatch("Light_Rpc")]
		public static void LightPostfix(Campfire __instance)
		{
			RecalculateSoulmatesEvent? recalculateSoulmatesEvent = Plugin.RecalculateSoulmate(firstTime: false);
			if (recalculateSoulmatesEvent.HasValue)
			{
				Events.SendRecalculateSoulmateEvent(recalculateSoulmatesEvent.Value);
			}
		}
	}
	public static class Extensions
	{
		public static bool isAbsolute(this STATUSTYPE t)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			if ((int)t != 7)
			{
				return (int)t == 9;
			}
			return true;
		}

		public static bool isShared(this STATUSTYPE t)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			return (int)t != 5;
		}

		public static bool isLiv(this Character c)
		{
			if (!c.data.dead)
			{
				return !c.warping;
			}
			return false;
		}
	}
	[BepInPlugin("com.github.Wesmania.Soulmates", "Soulmates", "0.3.1")]
	public class Plugin : BaseUnityPlugin
	{
		public static Soulmates globalSoulmates = new Soulmates(new Dictionary<string, int>(), "None", -1);

		public static ModConfig config = new ModConfig();

		public const string Id = "com.github.Wesmania.Soulmates";

		internal static ManualLogSource Log { get; private set; } = null;


		public static string Name => "Soulmates";

		public static string Version => "0.3.1";

		private void Awake()
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Log.LogInfo((object)("Plugin " + Name + " version 0.3.1 is loaded!"));
			config = new ModConfig(((BaseUnityPlugin)this).Config);
			if (!config.Enabled())
			{
				Log.LogInfo((object)"Soulmates disabled");
				return;
			}
			Harmony val = new Harmony("com.github.Wesmania.Soulmates");
			try
			{
				val.PatchAll();
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Failed to load mod: {arg}");
			}
			SteamComms.Awake(OnEvent);
		}

		private void OnDestroy()
		{
			if (config.Enabled())
			{
				SteamComms.OnDestroy();
			}
		}

		public static bool LocalCharIsReady()
		{
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)localCharacter == (Object)null || !localCharacter.isLiv())
			{
				return false;
			}
			return true;
		}

		private void OnEvent(int sender, SoulmateEventType eventType, string json)
		{
			switch (eventType)
			{
			case SoulmateEventType.RECALCULATE:
				OnRecalculateSoulmateEvent(sender, json);
				break;
			case SoulmateEventType.DAMAGE:
				OnSharedDamageEvent(sender, json);
				break;
			case SoulmateEventType.UPDATE_WEIGHT:
				Weight.OnUpdateWeightEvent(sender, json);
				break;
			case SoulmateEventType.SHARED_BONK:
				Bonk.OnSharedBonkEvent(sender, json);
				break;
			case SoulmateEventType.SHARED_EXTRA_STAMINA:
				StamUtil.OnSharedExtraStaminaEvent(sender, json);
				break;
			case SoulmateEventType.SHARED_AFFLICTION:
				AfflictionUtil.OnSharedAfflictionEvent(sender, json);
				break;
			case SoulmateEventType.WHO_IS_MY_SOULMATES:
				TellMeMySoulmate.OnWhoIsMySoulmate(sender, json);
				break;
			case (SoulmateEventType)3:
				break;
			}
		}

		private void OnSharedDamageEvent(int sender, string json)
		{
			//IL_002b: 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)
			//IL_0042: 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_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			SharedDamage sharedDamage = SharedDamage.Deserialize(json);
			if (!LocalCharIsReady())
			{
				return;
			}
			Character localCharacter = Character.localCharacter;
			if (globalSoulmates == null || !globalSoulmates.PidIsSoulmate(sender))
			{
				return;
			}
			if (!sharedDamage.type.isShared())
			{
				Log.LogInfo((object)$"Received update for non-shared damage type {sharedDamage.type}");
				return;
			}
			if (sharedDamage.type.isAbsolute())
			{
				Log.LogInfo((object)$"Received an update request for an absolute damage type {sharedDamage.type}");
				return;
			}
			SharedDamagePatch.isReceivingSharedDamage.Add(((MonoBehaviourPun)localCharacter).photonView.ViewID);
			CharacterAfflictions afflictions = localCharacter.refs.afflictions;
			sharedDamage.value *= config.SoulmateStrength();
			try
			{
				switch (sharedDamage.kind)
				{
				case SharedDamageKind.ADD:
					afflictions.AddStatus(sharedDamage.type, sharedDamage.value, false, true, true);
					break;
				case SharedDamageKind.SUBTRACT:
					afflictions.SubtractStatus(sharedDamage.type, sharedDamage.value, false, false);
					break;
				case SharedDamageKind.SET:
				{
					float currentStatus = afflictions.GetCurrentStatus(sharedDamage.type);
					afflictions.SetStatus(sharedDamage.type, currentStatus + sharedDamage.value, true);
					break;
				}
				}
			}
			finally
			{
				SharedDamagePatch.isReceivingSharedDamage.Remove(((MonoBehaviourPun)localCharacter).photonView.ViewID);
			}
		}

		public static Character? GetSoulmate(int actor)
		{
			return SteamComms.IdToCharacter(actor);
		}

		private static void OnRecalculateSoulmateEvent(int sender, string json)
		{
			globalSoulmates = SoulmateProtocol.instance.OnNewSoulmates(json) ?? new Soulmates();
			EventStats.instance.PrintStats();
			EventStats.instance.Reset();
		}

		public static RecalculateSoulmatesEvent? RecalculateSoulmate(bool firstTime)
		{
			return SoulmateProtocol.instance.PrepareNewSoulmates(firstTime);
		}
	}
	[HarmonyPatch(typeof(SlipperyJellyfish))]
	public static class SlipPatch1
	{
		[HarmonyPrefix]
		[HarmonyPatch("OnTriggerEnter", new Type[] { typeof(Collider) })]
		public static void OnTriggerEnterPrefix(SlipperyJellyfish __instance, Collider other)
		{
			if (!Plugin.config.SharedSlip() || __instance.counter < 3f)
			{
				return;
			}
			Character componentInParent = ((Component)other).GetComponentInParent<Character>();
			if (Object.op_Implicit((Object)(object)componentInParent))
			{
				int actorNumber = ((MonoBehaviourPun)componentInParent).photonView.Owner.ActorNumber;
				int? num = SteamComms.PhotonIdToPid(actorNumber);
				if (num.HasValue && Plugin.globalSoulmates.PidIsSoulmate(num.Value))
				{
					__instance.counter = 0f;
					__instance.relay.view.RPC("RPCA_TriggerWithTarget", (RpcTarget)0, new object[2]
					{
						((Component)__instance).transform.GetSiblingIndex(),
						Character.localCharacter.refs.view.ViewID
					});
				}
			}
		}
	}
	[HarmonyPatch(typeof(BananaPeel))]
	public static class SlipPatch2
	{
		[HarmonyPrefix]
		[HarmonyPatch("Update")]
		public static void UpdatePrefix(BananaPeel __instance)
		{
			//IL_0030: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.config.SharedSlip())
			{
				return;
			}
			foreach (PlayerCharacterInfo item in Plugin.globalSoulmates.MySoulmateCharacters())
			{
				if ((int)__instance.item.itemState == 0)
				{
					__instance.counter += Time.deltaTime;
					if (!(__instance.counter < 3f) && !(Vector3.Distance(item.c.Center, ((Component)__instance).transform.position) > 1f) && item.c.data.isGrounded && !(((Vector3)(ref item.c.data.avarageVelocity)).magnitude < 1.5f))
					{
						__instance.counter = 0f;
						((Component)__instance).GetComponent<PhotonView>().RPC("RPCA_TriggerBanana", (RpcTarget)0, new object[1] { Character.localCharacter.refs.view.ViewID });
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(UIPlayerNames))]
	public class SoulmateNickPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("UpdateName", new Type[]
		{
			typeof(int),
			typeof(Vector3),
			typeof(bool),
			typeof(int)
		})]
		public static void UpdateNamePostfix(UIPlayerNames __instance, int index, Vector3 position, bool visible, int speakingAmplitude)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)Character.localCharacter) || index >= __instance.playerNameText.Length)
			{
				return;
			}
			Character character = __instance.playerNameText[index].characterInteractable.character;
			int actorNumber = ((MonoBehaviourPun)character).photonView.Owner.ActorNumber;
			TextMeshProUGUI text = __instance.playerNameText[index].text;
			((Graphic)text).color = Color.white;
			int? num = SteamComms.PhotonIdToPid(actorNumber);
			if (!num.HasValue)
			{
				return;
			}
			if (Plugin.globalSoulmates.PidIsSoulmate(num.Value))
			{
				((Graphic)text).color = Colors.soulmateColor;
				return;
			}
			int? num2 = Plugin.globalSoulmates.NickToSoulmateGroup(((MonoBehaviourPun)character).photonView.Owner.NickName);
			if (num2.HasValue)
			{
				((Graphic)text).color = Colors.getColor(num2.Value);
			}
		}
	}
	public class Soulmates
	{
		private Dictionary<string, int> soulmatesByName;

		private Dictionary<int, HashSet<string>> soulmatesByGroup;

		private readonly string myName;

		private readonly int myGroup;

		public Soulmates()
			: this(new Dictionary<string, int>(), "None", 0)
		{
		}

		public Soulmates(Dictionary<string, int> soulmatesByName, string myName, int myGroup)
		{
			this.soulmatesByName = soulmatesByName;
			this.myName = myName;
			this.myGroup = myGroup;
			soulmatesByGroup = (from kv in soulmatesByName
				group kv by kv.Value).ToDictionary((IGrouping<int, KeyValuePair<string, int>> g) => g.Key, (IGrouping<int, KeyValuePair<string, int>> g) => g.Select((KeyValuePair<string, int> kv) => kv.Key).ToHashSet());
		}

		public HashSet<string> MySoulmates()
		{
			if (soulmatesByGroup.ContainsKey(myGroup))
			{
				HashSet<string> hashSet = new HashSet<string>();
				foreach (string item in soulmatesByGroup[myGroup].Where((string n) => n != myName))
				{
					hashSet.Add(item);
				}
				return hashSet;
			}
			return new HashSet<string>();
		}

		public HashSet<int> MySoulmatePids()
		{
			HashSet<string> source = MySoulmates();
			Dictionary<string, PlayerInfo> ps = SteamComms.AllPlayers().ToDictionary((PlayerInfo p) => p.nickname);
			HashSet<int> hashSet = new HashSet<int>();
			foreach (int item in source.SelectMany((string sn) => ps.ContainsKey(sn) ? ((IEnumerable<int>)new int[1] { ps[sn].id }) : ((IEnumerable<int>)Array.Empty<int>())))
			{
				hashSet.Add(item);
			}
			return hashSet;
		}

		public HashSet<PlayerCharacterInfo> MySoulmateCharacters()
		{
			HashSet<PlayerCharacterInfo> hashSet = new HashSet<PlayerCharacterInfo>();
			PlayerCharacterInfo[] array = SteamComms.NicksToInfos(MySoulmates());
			foreach (PlayerCharacterInfo item in array)
			{
				hashSet.Add(item);
			}
			return hashSet;
		}

		public int? NickToSoulmateGroup(string nick)
		{
			if (!soulmatesByName.ContainsKey(nick))
			{
				return null;
			}
			return soulmatesByName[nick];
		}

		public bool PidIsSoulmate(int id)
		{
			return MySoulmatePids().Contains(id);
		}

		public bool NoSoulmates()
		{
			return MySoulmates().Count == 0;
		}

		public string SoulmateLog()
		{
			return string.Join(", ", MySoulmates());
		}

		public string SoulmateText()
		{
			HashSet<string> hashSet = MySoulmates();
			if (hashSet.Count == 0)
			{
				return "Soulmate: None";
			}
			if (hashSet.Count == 1)
			{
				return "Soulmate: " + hashSet.First();
			}
			return "Soulmates:\n" + string.Join("\n", hashSet);
		}

		public int LiveSoulmateCount()
		{
			return MySoulmatePids().Count(delegate(int n)
			{
				Character val = SteamComms.IdToCharacter(n);
				return (Object)(object)val != (Object)null && val.isLiv();
			});
		}
	}
	public class SoulmateProtocol
	{
		public static SoulmateProtocol instance = new SoulmateProtocol();

		public RecalculateSoulmatesEvent? previousSoulmates;

		public Soulmates? OnNewSoulmates(string json)
		{
			Plugin.Log.LogInfo((object)"Received recalculate soulmate event");
			RecalculateSoulmatesEvent recalculateSoulmatesEvent = RecalculateSoulmatesEvent.Deserialize(json);
			Plugin.config.SetReceivedConfig(recalculateSoulmatesEvent.config);
			Soulmates soulmates = findSoulmates(recalculateSoulmatesEvent.soulmates);
			if (soulmates == null)
			{
				Plugin.Log.LogWarning((object)"Failed to processs new soulmates!");
				previousSoulmates = null;
				Plugin.config.ClearReceivedConfig();
				return null;
			}
			previousSoulmates = recalculateSoulmatesEvent;
			if (soulmates.NoSoulmates())
			{
				Plugin.Log.LogInfo((object)"No soulmates");
			}
			else
			{
				Plugin.Log.LogInfo((object)("New soulmates: " + soulmates.SoulmateLog()));
			}
			if (recalculateSoulmatesEvent.firstTime)
			{
				Weight.Clear();
			}
			else
			{
				ConnectToNewSoulmate(recalculateSoulmatesEvent);
			}
			SoulmateTextPatch.SetSoulmateText(soulmates.SoulmateText(), recalculateSoulmatesEvent.firstTime ? 10 : 15);
			return soulmates;
		}

		private static void ConnectToNewSoulmate(RecalculateSoulmatesEvent e)
		{
			if (Plugin.LocalCharIsReady())
			{
				Character localCharacter = Character.localCharacter;
				localCharacter.refs.afflictions.UpdateWeight();
			}
		}

		private Soulmates? findSoulmates(List<int> soulmates)
		{
			int groupSize = Plugin.config.SoulmateGroupSize();
			Dictionary<string, int> soulmatesByName = (from p in soulmates.Select((int id, int idx) => (idx / groupSize, SteamComms.IdToNick(id)))
				where p.Item2 != null
				select (p.Item1, p.Item2)).ToDictionary(((int, string) p) => p.Item2, ((int, string) p) => p.Item1);
			int my_pid = SteamComms.MyNumber();
			int num = soulmates.FindIndex((int x) => x == my_pid);
			if (num == -1)
			{
				Plugin.Log.LogInfo((object)$"Did not find myself ({my_pid}) on soulmate list!");
				return null;
			}
			Plugin.Log.LogInfo((object)$"Found my index: {num}");
			int myGroup = num / groupSize;
			Soulmates soulmates2 = new Soulmates(soulmatesByName, SteamComms.MyNick(), myGroup);
			Plugin.Log.LogInfo((object)string.Format($"Soulmate group size: {soulmates2.MySoulmates().Count + 1}"));
			return soulmates2;
		}

		private static void ReorderForFixedPairings(ref List<int> actors)
		{
			if (!Plugin.config.HasFixedSoulmates())
			{
				return;
			}
			Dictionary<string, int> actorsWithNames = actors.ToDictionary((int a) => SteamComms.IdToNick(a));
			List<List<string>> fixedSoulmates = Plugin.config.GetFixedSoulmates();
			if (fixedSoulmates.Count == 0)
			{
				return;
			}
			if (!fixedSoulmates.All((List<string> l) => l.Count == Plugin.config.SoulmateGroupSize()))
			{
				Plugin.Log.LogWarning((object)"Fixed soulmate groups don't match soulmate group size! FIXME we should be able to handle this.");
				return;
			}
			IEnumerable<List<string>> source = fixedSoulmates.Where((List<string> l) => l.All((string s) => actorsWithNames.ContainsKey(s)));
			List<int> list = source.SelectMany((List<string> l) => l.Select((string s) => actorsWithNames[s])).ToList();
			HashSet<int> fixedSet = list.ToHashSet();
			if (fixedSet.Count < list.Count)
			{
				Plugin.Log.LogWarning((object)"Fixed soulmate groups have repeating names!");
				return;
			}
			IEnumerable<int> collection = actors.Where((int a) => !fixedSet.Contains(a));
			List<int> list2 = new List<int>();
			list2.AddRange(list);
			list2.AddRange(collection);
			actors = list2;
		}

		public RecalculateSoulmatesEvent? PrepareNewSoulmates(bool firstTime)
		{
			if (!SteamComms.IAmHost())
			{
				return null;
			}
			Plugin.Log.LogInfo((object)"I am master client, preparing new soulmate list");
			PlayerInfo[] source = SteamComms.AllPlayers();
			List<int> actors = source.Select((PlayerInfo x) => x.id).ToList();
			List<string> list = source.Select((PlayerInfo x) => x.nickname).ToList();
			list.Sort();
			string arg = string.Join(" ", list);
			Plugin.Log.LogInfo((object)$"Character count: {list.Count()}, Characters: {arg}");
			ExtCollections.Shuffle<int>((IList<int>)actors);
			ReorderForFixedPairings(ref actors);
			RecalculateSoulmatesEvent value = default(RecalculateSoulmatesEvent);
			value.soulmates = actors;
			value.firstTime = firstTime;
			if (firstTime)
			{
				Plugin.config.ClearReceivedConfig();
				previousSoulmates = null;
			}
			value.config = Plugin.config.GetConfigToSend();
			return value;
		}
	}
	[HarmonyPatch(typeof(GUIManager))]
	public static class SoulmateTextPatch
	{
		public static Canvas? SoulmatePrompt;

		public static TextMeshProUGUI? text;

		public static TMP_FontAsset? darumaDropOneFont;

		public static TextSetter? text_setter;

		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		public static void StartPostfix(GUIManager __instance)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: 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)
			Transform transform = ((Component)__instance).transform;
			GameObject val = new GameObject("SoulmatePrompt");
			val.transform.SetParent(transform, false);
			SoulmatePrompt = val.AddComponent<Canvas>();
			SoulmatePrompt.renderMode = (RenderMode)1;
			CanvasScaler val2 = ((Component)SoulmatePrompt).gameObject.GetComponent<CanvasScaler>() ?? ((Component)SoulmatePrompt).gameObject.AddComponent<CanvasScaler>();
			val2.referencePixelsPerUnit = 100f;
			val2.matchWidthOrHeight = 1f;
			val2.referenceResolution = new Vector2(1920f, 1080f);
			val2.scaleFactor = 1f;
			val2.screenMatchMode = (ScreenMatchMode)0;
			val2.uiScaleMode = (ScaleMode)1;
			GameObject val3 = new GameObject("TextChat");
			val3.transform.SetParent(((Component)SoulmatePrompt).transform, false);
			text = val3.AddComponent<TextMeshProUGUI>();
			RectTransform component = ((Component)text).GetComponent<RectTransform>();
			Vector2 sizeDelta = component.sizeDelta;
			sizeDelta.x *= 2f;
			component.sizeDelta = sizeDelta;
			text_setter = val3.AddComponent<TextSetter>();
			try
			{
				GUIManager instance = GUIManager.instance;
				object obj;
				if (instance == null)
				{
					obj = null;
				}
				else
				{
					TextMeshProUGUI itemPromptDrop = instance.itemPromptDrop;
					obj = ((itemPromptDrop != null) ? ((TMP_Text)itemPromptDrop).font : null);
				}
				darumaDropOneFont = (TMP_FontAsset?)obj;
			}
			catch
			{
			}
			((TMP_Text)text).text = "";
			if ((Object)(object)darumaDropOneFont != (Object)null)
			{
				((TMP_Text)text).font = darumaDropOneFont;
			}
			((TMP_Text)text).horizontalAlignment = (HorizontalAlignmentOptions)2;
		}

		public static void SetSoulmateText(string text, float delay)
		{
			if ((Object)(object)text_setter != (Object)null)
			{
				text_setter.SetSoulmateText(text, delay);
			}
		}
	}
	public class TextSetter : MonoBehaviour
	{
		public void SetSoulmateText(string text, float delay)
		{
			string text2 = text;
			((MonoBehaviour)this).StartCoroutine(TextCoroutine());
			IEnumerator TextCoroutine()
			{
				yield return (object)new WaitForSeconds(delay);
				if ((Object)(object)SoulmateTextPatch.text != (Object)null)
				{
					((TMP_Text)SoulmateTextPatch.text).text = text2;
				}
				yield return (object)new WaitForSeconds(10f);
				if ((Object)(object)SoulmateTextPatch.text != (Object)null)
				{
					((TMP_Text)SoulmateTextPatch.text).text = "";
				}
			}
		}
	}
	public struct PlayerInfo
	{
		public int id;

		public string nickname;
	}
	public struct PlayerCharacterInfo
	{
		public PlayerInfo p;

		public Character c;
	}
	public class SteamComms
	{
		public static SteamComms instance = new SteamComms();

		internal const byte SHARED_DAMAGE_EVENT_CODE = 198;

		private Action<int, SoulmateEventType, string>? eventHandle;

		public static void Awake(Action<int, SoulmateEventType, string> handle)
		{
			instance.eventHandle = handle;
			PhotonNetwork.NetworkingClient.EventReceived += OnEvent;
		}

		public static void OnDestroy()
		{
			instance.eventHandle = null;
			PhotonNetwork.NetworkingClient.EventReceived -= OnEvent;
		}

		public static int MyNumber()
		{
			return PhotonNetwork.LocalPlayer.ActorNumber;
		}

		public static string MyNick()
		{
			return PhotonNetwork.LocalPlayer.NickName;
		}

		public static bool IAmHost()
		{
			return PhotonNetwork.IsMasterClient;
		}

		public static int[] AllPlayerNumbers()
		{
			List<int> list = new List<int>();
			list.AddRange(PhotonNetwork.PlayerList.Select((Player c) => c.ActorNumber));
			return list.ToArray();
		}

		public static PlayerInfo[] AllPlayers()
		{
			List<PlayerInfo> list = new List<PlayerInfo>();
			list.AddRange(PhotonNetwork.PlayerList.Select(delegate(Player c)
			{
				PlayerInfo result = default(PlayerInfo);
				result.id = c.ActorNumber;
				result.nickname = c.NickName;
				return result;
			}));
			return list.ToArray();
		}

		public static string? IdToNick(int id)
		{
			Player? obj = ((IEnumerable<Player>)PhotonNetwork.PlayerList).FirstOrDefault((Func<Player, bool>)((Player c) => c.ActorNumber == id));
			if (obj == null)
			{
				return null;
			}
			return obj.NickName;
		}

		public static Character? IdToCharacter(int id)
		{
			List<Character> allCharacters = Character.AllCharacters;
			PlayerInfo? players = AllPlayers().FirstOrDefault((PlayerInfo p) => p.id == id);
			if (!players.HasValue)
			{
				return null;
			}
			return ((IEnumerable<Character>)allCharacters).FirstOrDefault((Func<Character, bool>)((Character c) => ((MonoBehaviourPun)c).photonView.Owner.NickName == players.Value.nickname));
		}

		public static int? PhotonIdToPid(int actorNumber)
		{
			Player val = ((IEnumerable<Player>)PhotonNetwork.PlayerList).FirstOrDefault((Func<Player, bool>)((Player c) => c.ActorNumber == actorNumber));
			if (val == null)
			{
				return null;
			}
			string nickName = val.NickName;
			Dictionary<string, int> dictionary = AllPlayers().ToDictionary((PlayerInfo p) => p.nickname, (PlayerInfo p) => p.id);
			if (!dictionary.ContainsKey(nickName))
			{
				return null;
			}
			return dictionary[nickName];
		}

		public static PlayerCharacterInfo[] NicksToInfos(IEnumerable<string> nicks)
		{
			Dictionary<string, PlayerInfo> players = AllPlayers().ToDictionary((PlayerInfo p) => p.nickname);
			Dictionary<string, Character> chars = Character.AllCharacters.ToDictionary((Character c) => ((MonoBehaviourPun)c).photonView.Owner.NickName);
			List<PlayerCharacterInfo> list = new List<PlayerCharacterInfo>();
			list.AddRange(nicks.Where((string n) => players.ContainsKey(n) && chars.ContainsKey(n)).Select(delegate(string n)
			{
				PlayerCharacterInfo result = default(PlayerCharacterInfo);
				result.p = players[n];
				result.c = chars[n];
				return result;
			}));
			return list.ToArray();
		}

		public static void SendEvent(SoulmateEventType eventType, string e, ReceiverGroup who, bool reliable = false)
		{
			//IL_0014: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: 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_0038: Unknown result type (might be due to invalid IL or missing references)
			object[] array = new object[2]
			{
				(int)eventType,
				e
			};
			RaiseEventOptions val = new RaiseEventOptions
			{
				Receivers = who
			};
			SendOptions val2 = (reliable ? SendOptions.SendReliable : SendOptions.SendUnreliable);
			PhotonNetwork.RaiseEvent((byte)198, (object)array, val, val2);
		}

		public static void SendEventTo(SoulmateEventType eventType, string e, int[] targets, bool reliable = false)
		{
			//IL_0014: 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_001b: 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_0028: Expected O, but got Unknown
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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_003f: Unknown result type (might be due to invalid IL or missing references)
			object[] array = new object[2]
			{
				(int)eventType,
				e
			};
			RaiseEventOptions val = new RaiseEventOptions
			{
				Receivers = (ReceiverGroup)0,
				TargetActors = targets
			};
			SendOptions val2 = (reliable ? SendOptions.SendReliable : SendOptions.SendUnreliable);
			PhotonNetwork.RaiseEvent((byte)198, (object)array, val, val2);
		}

		public static void OnEvent(EventData e)
		{
			if (e.Code == 198)
			{
				object[] array = (object[])e.CustomData;
				int sender = e.Sender;
				SoulmateEventType eventType = (SoulmateEventType)(int)array[0];
				string e2 = (string)array[1];
				HandleEvent(sender, eventType, e2);
			}
		}

		public static void HandleEvent(int sender, SoulmateEventType eventType, string e)
		{
			instance.eventHandle?.Invoke(sender, eventType, e);
		}
	}
	[Serializable]
	public struct Config
	{
		public bool sharedBonk;

		public bool sharedSlip;

		public bool sharedExtraStaminaGain;

		public bool sharedExtraStaminaUse;

		public bool sharedLolli;

		public bool sharedEnergol;

		public bool sharedBlindness;

		public bool sharedFloating;

		public bool sharedMilk;

		public bool sharedParalysis;

		public bool sharedFarts;

		public bool sharedSporedMeter;

		public int soulmateGroupSize;

		public float soulmateStrength;
	}
	[Serializable]
	public struct RecalculateSoulmatesEvent
	{
		public Config config;

		public List<int> soulmates;

		public bool firstTime;

		public string Serialize()
		{
			return JsonConvert.SerializeObject((object)this);
		}

		public static RecalculateSoulmatesEvent Deserialize(string s)
		{
			return JsonConvert.DeserializeObject<RecalculateSoulmatesEvent>(s);
		}
	}
	[Serializable]
	public enum SharedDamageKind
	{
		ADD,
		SUBTRACT,
		SET
	}
	[Serializable]
	public struct SharedDamage
	{
		public STATUSTYPE type;

		public float value;

		public SharedDamageKind kind;

		public string Serialize()
		{
			return JsonConvert.SerializeObject((object)this);
		}

		public static SharedDamage Deserialize(string s)
		{
			return JsonConvert.DeserializeObject<SharedDamage>(s);
		}
	}
	[Serializable]
	public struct UpdateWeight
	{
		public float weight;

		public float thorns;

		public UpdateWeight()
		{
			weight = 0f;
			thorns = 0f;
		}

		public string Serialize()
		{
			return JsonConvert.SerializeObject((object)this);
		}

		public static UpdateWeight Deserialize(string s)
		{
			return JsonConvert.DeserializeObject<UpdateWeight>(s);
		}
	}
	[Serializable]
	public struct V3
	{
		public float x;

		public float y;

		public float z;

		public V3(Vector3 v)
		{
			//IL_0001: 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_0019: Unknown result type (might be due to invalid IL or missing references)
			x = v.x;
			y = v.y;
			z = v.z;
		}

		public Vector3 toVector3()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(x, y, z);
		}
	}
	[Serializable]
	public struct SharedBonk
	{
		public int victim;

		public float ragdollTime;

		public V3 force;

		public V3 contactPoint;

		public float range;

		public string Serialize()
		{
			return JsonConvert.SerializeObject((object)this);
		}

		public static SharedBonk Deserialize(string s)
		{
			return JsonConvert.DeserializeObject<SharedBonk>(s);
		}
	}
	public struct SharedExtraStamina
	{
		public float diff;

		public string Serialize()
		{
			return JsonConvert.SerializeObject((object)this);
		}

		public static SharedExtraStamina Deserialize(string s)
		{
			return JsonConvert.DeserializeObject<SharedExtraStamina>(s);
		}
	}
	public enum OtherAfflictions
	{
		PARALYSIS,
		INDIGESTION
	}
	public struct SharedAffliction
	{
		public AfflictionType? type;

		public OtherAfflictions? other_type;

		public float totalTime;

		public readonly string Serialize()
		{
			return JsonConvert.SerializeObject((object)this);
		}

		public static SharedAffliction Deserialize(string s)
		{
			return JsonConvert.DeserializeObject<SharedAffliction>(s);
		}
	}
	[StructLayout(LayoutKind.Sequential, Size = 1)]
	public struct WhoIsMySoulmate
	{
		public string Serialize()
		{
			return JsonConvert.SerializeObject((object)this);
		}

		public static WhoIsMySoulmate Deserialize(string s)
		{
			return JsonConvert.DeserializeObject<WhoIsMySoulmate>(s);
		}
	}
	public enum SoulmateEventType
	{
		RECALCULATE = 0,
		DAMAGE = 1,
		UPDATE_WEIGHT = 2,
		SHARED_BONK = 4,
		SHARED_EXTRA_STAMINA = 5,
		SHARED_AFFLICTION = 6,
		WHO_IS_MY_SOULMATES = 7
	}
	public static class Weight
	{
		private static Dictionary<int, UpdateWeight> playerWeights = new Dictionary<int, UpdateWeight>();

		public static bool shouldSendWeight;

		public static void Clear()
		{
			playerWeights.Clear();
			shouldSendWeight = false;
		}

		private static bool updateLocalWeightAndCheckIfChanged(UpdateWeight w)
		{
			int key = SteamComms.MyNumber();
			if (!playerWeights.ContainsKey(key))
			{
				playerWeights[key] = w;
				return true;
			}
			UpdateWeight updateWeight = playerWeights[key];
			playerWeights[key] = w;
			if (updateWeight.weight == w.weight)
			{
				return updateWeight.thorns != w.thorns;
			}
			return true;
		}

		public static UpdateWeight getLocalWeight()
		{
			UpdateWeight result = default(UpdateWeight);
			result.weight = 0f;
			result.thorns = 0f;
			int key = SteamComms.MyNumber();
			if (!playerWeights.ContainsKey(key))
			{
				return result;
			}
			return playerWeights[key];
		}

		public static void OnUpdateWeightEvent(int sender, string json)
		{
			UpdateWeight value = UpdateWeight.Deserialize(json);
			playerWeights[sender] = value;
			if (sender != SteamComms.MyNumber() && Plugin.globalSoulmates.PidIsSoulmate(sender) && Plugin.LocalCharIsReady())
			{
				Character.localCharacter.refs.afflictions.UpdateWeight();
			}
		}

		public static UpdateWeight RecalculateSharedWeight(UpdateWeight original)
		{
			if (!Plugin.LocalCharIsReady())
			{
				return original;
			}
			if (!Plugin.config.ReceivedConfig.HasValue)
			{
				return original;
			}
			Character localCharacter = Character.localCharacter;
			CharacterAfflictions afflictions = localCharacter.refs.afflictions;
			HashSet<PlayerCharacterInfo> hashSet = Plugin.globalSoulmates.MySoulmateCharacters();
			float num = hashSet.Count;
			UpdateWeight updateWeight = default(UpdateWeight);
			updateWeight.weight = 0f;
			updateWeight.thorns = 0f;
			foreach (PlayerCharacterInfo item in hashSet)
			{
				if (item.c.isLiv() && playerWeights.ContainsKey(item.p.id))
				{
					updateWeight.weight += playerWeights[item.p.id].weight;
					updateWeight.thorns += playerWeights[item.p.id].thorns;
				}
			}
			float num2 = Plugin.config.SoulmateStrength();
			original.weight = (original.weight + updateWeight.weight * num2) / (num2 * num + 1f);
			original.thorns += updateWeight.thorns * num2;
			return original;
		}

		private static bool ShouldSendWeight()
		{
			if (!Plugin.config.ReceivedConfig.HasValue)
			{
				return false;
			}
			bool result = shouldSendWeight;
			shouldSendWeight = false;
			return result;
		}

		public static void MaybeSendWeight()
		{
			if (ShouldSendWeight())
			{
				UpdateWeight localWeight = getLocalWeight();
				Events.SendUpdateWeightEvent(localWeight);
			}
		}

		public static float PreSetWeight(CharacterAfflictions c, STATUSTYPE kind, float value)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Invalid comparison between Unknown and I4
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Invalid comparison between Unknown and I4
			if (!c.character.IsLocal)
			{
				return value;
			}
			if (!kind.isAbsolute())
			{
				return value;
			}
			UpdateWeight localWeight = getLocalWeight();
			if ((int)kind == 7)
			{
				localWeight.weight = value;
			}
			else
			{
				localWeight.thorns = value;
			}
			if (updateLocalWeightAndCheckIfChanged(localWeight))
			{
				shouldSendWeight = true;
			}
			localWeight = RecalculateSharedWeight(localWeight);
			if ((int)kind == 7)
			{
				return localWeight.weight;
			}
			return localWeight.thorns;
		}
	}
	internal class TellMeMySoulmate
	{
		public static void OnWhoIsMySoulmate(int sender, string json)
		{
			WhoIsMySoulmate whoIsMySoulmate = WhoIsMySoulmate.Deserialize(json);
			if (PhotonNetwork.IsMasterClient && SoulmateProtocol.instance.previousSoulmates.HasValue)
			{
				Events.SendThisIsYourSoulmatesEvent(SoulmateProtocol.instance.previousSoulmates.Value, sender);
			}
		}
	}
	[HarmonyPatch(typeof(NetworkConnector))]
	internal class WhoIsMySoulmatePatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("OnJoinedRoom")]
		public static void OnJoinedRoomPostfix(ReconnectHandler __instance)
		{
			if (!SoulmateProtocol.instance.previousSoulmates.HasValue)
			{
				Events.SendWhoIsMySoulmatesEvent();
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}