Decompiled source of Chats Revenge Schedule I v1.2.1

Mods/chatsRevenge.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using ChatsRevenge.Utils;
using FishNet;
using FishNet.Connection;
using FishNet.Object;
using HarmonyLib;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using ScheduleOne.Casino;
using ScheduleOne.Combat;
using ScheduleOne.DevUtilities;
using ScheduleOne.Dialogue;
using ScheduleOne.Economy;
using ScheduleOne.GameTime;
using ScheduleOne.Growing;
using ScheduleOne.Interaction;
using ScheduleOne.ItemFramework;
using ScheduleOne.Law;
using ScheduleOne.Messaging;
using ScheduleOne.Money;
using ScheduleOne.NPCs;
using ScheduleOne.NPCs.Behaviour;
using ScheduleOne.NPCs.Relation;
using ScheduleOne.NPCs.Responses;
using ScheduleOne.Persistence;
using ScheduleOne.PlayerScripts;
using ScheduleOne.Police;
using ScheduleOne.Product;
using ScheduleOne.Properties;
using ScheduleOne.Quests;
using ScheduleOne.Trash;
using ScheduleOne.UI;
using ScheduleOne.UI.Phone.ContactsApp;
using ScheduleOne.UI.Phone.Messages;
using ScheduleOne.VoiceOver;
using TMPro;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using chatsRevenge;
using chatsRevenge.Patches;
using chatsRevenge.Utils;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(Plugin), "chatsRevenge", "1.2.1", "ziedyt", null)]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("chatsRevenge")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+e3b4af787f2bc1ed8209f1e72eeb0462ee8bb790")]
[assembly: AssemblyProduct("chatsRevenge")]
[assembly: AssemblyTitle("chatsRevenge")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ChatsRevenge.Utils
{
	public class pythonSocket
	{
		private static pythonSocket _instance;

		[SerializeField]
		private string IP = "127.0.0.1";

		[SerializeField]
		private int rxPort = 7885;

		[SerializeField]
		private int txPort = 7886;

		private int indx = -1;

		private bool running = true;

		private UdpClient client;

		private IPEndPoint pythonHost;

		private Thread readDataThread;

		private Thread connectionWatchdogThread;

		private bool isConnected = false;

		private DateTime lastSuccessfulCommunication;

		private readonly int reconnectInterval = 5000;

		public static pythonSocket Instance
		{
			get
			{
				if (_instance == null)
				{
					_instance = new pythonSocket();
				}
				return _instance;
			}
		}

		public static Plugin plugin { get; set; }

		private pythonSocket()
		{
		}

		public void SendData(string message)
		{
			try
			{
				byte[] bytes = Encoding.UTF8.GetBytes(message);
				client.Send(bytes, bytes.Length, pythonHost);
				lastSuccessfulCommunication = DateTime.Now;
				isConnected = true;
			}
			catch (Exception ex)
			{
				Plugin.Instance.log("Send error: " + ex.ToString());
				isConnected = false;
				TryReconnect();
			}
		}

		public void start()
		{
			InitializeConnection();
			connectionWatchdogThread = new Thread(ConnectionWatchdog);
			connectionWatchdogThread.IsBackground = true;
			connectionWatchdogThread.Start();
		}

		private void InitializeConnection()
		{
			try
			{
				if (client != null)
				{
					try
					{
						client.Close();
					}
					catch
					{
					}
				}
				pythonHost = new IPEndPoint(IPAddress.Parse(IP), txPort);
				client = new UdpClient(rxPort);
				client.Client.ReceiveTimeout = 10000;
				if (readDataThread == null || !readDataThread.IsAlive)
				{
					running = true;
					readDataThread = new Thread(readData);
					readDataThread.IsBackground = true;
					readDataThread.Start();
				}
				lastSuccessfulCommunication = DateTime.Now;
				isConnected = true;
				Plugin.Instance.log("Socket connection initialized");
			}
			catch (Exception ex)
			{
				Plugin.Instance.log("Connection initialization error: " + ex.ToString());
				isConnected = false;
			}
		}

		private void TryReconnect()
		{
			try
			{
				Plugin.Instance.log("Attempting to reconnect socket...");
				InitializeConnection();
			}
			catch (Exception ex)
			{
				Plugin.Instance.log("Reconnection attempt failed: " + ex.ToString());
			}
		}

		private void ConnectionWatchdog()
		{
			while (running)
			{
				try
				{
					if (isConnected && (DateTime.Now - lastSuccessfulCommunication).TotalSeconds > 30.0)
					{
						Plugin.Instance.log("Socket connection timeout detected");
						isConnected = false;
					}
					if (!isConnected)
					{
						TryReconnect();
					}
					Thread.Sleep(reconnectInterval);
				}
				catch (Exception ex)
				{
					Plugin.Instance.log("Watchdog error: " + ex.ToString());
				}
			}
		}

		public void OnDestroy()
		{
			running = false;
			try
			{
				if (client != null)
				{
					client.Close();
					client = null;
				}
			}
			catch
			{
			}
		}

		private void readData()
		{
			while (running)
			{
				try
				{
					IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0);
					byte[] bytes = client.Receive(ref remoteEP);
					string @string = Encoding.UTF8.GetString(bytes);
					string[] array = @string.Split(';');
					int num = int.Parse(array[0]);
					string text = array[1];
					string text2 = array[2];
					string text3 = array[3];
					string text4 = array[4];
					int num2 = int.Parse(array[5]);
					string text5 = array[6];
					string text6 = array[7];
					lastSuccessfulCommunication = DateTime.Now;
					if (!text.Contains("scheduleI"))
					{
						continue;
					}
					if (indx == -1 || (indx != num && num == 0))
					{
						indx = num;
						SendData("scheduleI " + Plugin.Instance.version);
					}
					else
					{
						if (num == indx)
						{
							continue;
						}
						Plugin.Instance.log("received");
						indx = num;
						if (text == "scheduleI_creds")
						{
							if (Plugin.Instance.Token != text6 || Plugin.Instance.channelName != text3 || Plugin.Instance.streamerID != text5)
							{
								Plugin.Instance.log("scheduleI_creds");
								Plugin.Instance.Token = text6;
								Plugin.Instance.channelName = text3;
								Plugin.Instance.streamerID = text5;
								ChatterManager.Instance.StopBot();
								ChatterManager.Instance.StartBot();
							}
						}
						else
						{
							API.bufferedCMD.Add("ProcessInput#" + @string);
						}
						continue;
					}
				}
				catch (SocketException ex)
				{
					Plugin.Instance.log("Socket read error: " + ex.ToString());
					isConnected = false;
					Thread.Sleep(1000);
				}
				catch (Exception ex2)
				{
					Plugin.Instance.log("General read error: " + ex2.ToString());
					Thread.Sleep(1000);
				}
			}
		}
	}
}
namespace chatsRevenge
{
	public class Plugin : MelonMod
	{
		private static MelonPreferences_Category myCategory;

		public string channelName = "";

		public string Token = "";

		public string streamerID = "";

		public static MelonPreferences_Entry<int> inactiveThreshold;

		public static MelonPreferences_Entry<int> phoneMessagesRate;

		public const string VersionString = "1.2.1";

		public string version = "1.2.1";

		public string client_id = "o8psoh7xmn5zflmbj5g41vb7o3w8kb";

		public IDictionary<string, AudioClip> clips = new Dictionary<string, AudioClip>();

		public int freeSlotSpins = 0;

		public long betterSlotOddsEnd = 0L;

		public long profilingEnd = 0L;

		public List<string> propertiesnames = new List<string>
		{
			"Anti-Gravity", "Balding", "Bright-Eyed", "Calming", "Calorie-Dense", "Cyclopean", "Disorienting", "Energizing", "Euphoric", "Explosive",
			"Focused", "Foggy", "Gingeritis", "Glowie", "Jennerising", "Laxative", "Refreshing", "Schizophrenic", "Sedating", "Seizure",
			"Slippery", "Smelly", "Sneaky", "Spicy", "Thought-Provoking", "Toxic", "Tropic Thunder", "Zombifying"
		};

		public List<Property> properties = new List<Property>();

		public static Plugin Instance { get; private set; }

		public override void OnInitializeMelon()
		{
			((MelonBase)this).LoggerInstance.Msg("Initialized.");
			myCategory = MelonPreferences.CreateCategory("chatsRevenge");
			inactiveThreshold = myCategory.CreateEntry<int>("inactiveThreshold", 15, "Minutes until inactive chatter can be claimed by another chatter", (string)null, false, false, (ValueValidator)null, (string)null);
			phoneMessagesRate = myCategory.CreateEntry<int>("phoneMessagesRate", 0, "Seconds until a viewer charater can send you a message in game. 0 = disabled", (string)null, false, false, (ValueValidator)null, (string)null);
			if (Instance == null)
			{
				Instance = this;
				((MelonBase)this).HarmonyInstance.PatchAll(typeof(PlayerPatches));
			}
			MelonLogger.Msg("Config loaded!");
			pythonSocket.Instance.start();
			betterSlotOddsEnd = API.secondsEpochNow();
			if (!clips.ContainsKey("gamble"))
			{
				AudioClip audioFromFile = API.GetAudioFromFile("https://audio.jukehost.co.uk/Pm6dtuoWyUr16onL9zlIraAWKPZS6Xvj");
				clips["gamble"] = audioFromFile;
			}
		}

		public override void OnPreferencesLoaded()
		{
			((MelonBase)this).OnPreferencesLoaded();
		}

		public override void OnApplicationQuit()
		{
			((MelonBase)this).OnApplicationQuit();
			pythonSocket.Instance.OnDestroy();
			ChatterManager.Instance.StopBot();
		}

		public void log(string msg)
		{
			((MelonBase)this).LoggerInstance.Msg(msg);
		}

		public void logError(string msg)
		{
			((MelonBase)this).LoggerInstance.Error(msg);
		}

		public void sendMessagePlayerPhone(string data)
		{
			string[] array = data.Split('#');
			string text = array[0];
			string text2 = array[1];
			ChatterData viewerData = API.getViewerData(text, text);
			if (viewerData != null)
			{
				API.sendMessagePlayerPhone(viewerData.customer, text2);
			}
		}

		public void setBetterSlotOddsEnd(string data)
		{
			log("setBetterSlotOddsEnd");
			betterSlotOddsEnd = long.Parse(data);
		}

		public void claimCharacterRPC(string rpcdata)
		{
			string[] array = rpcdata.Split("#");
			string text = array[0];
			string text2 = array[1];
			string text3 = array[2];
			string text4 = array[3];
			log("claimCharacterRPC " + rpcdata);
			Customer val = null;
			Customer[] array2 = Object.FindObjectsOfType<Customer>();
			Customer[] array3 = array2;
			foreach (Customer val2 in array3)
			{
				if (val2.NPC.fullName == text2 || val2.NPC.ID == text)
				{
					val = val2;
					break;
				}
			}
			ChatterData chatterData = new ChatterData();
			chatterData.customer = val;
			chatterData.twitchId = text4;
			chatterData.displayName = text3;
			chatterData.lastEpoch = API.secondsEpochNow();
			val.NPC.FirstName = text3;
			val.NPC.LastName = text4;
			if (val.NPC.MSGConversation != null)
			{
				val.NPC.MSGConversation.contactName = text3;
				if ((Object)(object)val.NPC.MSGConversation.entry != (Object)null && (Object)(object)((Transform)val.NPC.MSGConversation.entry).Find("Name") != (Object)null && (Object)(object)((Component)((Transform)val.NPC.MSGConversation.entry).Find("Name")).GetComponent<Text>() != (Object)null)
				{
					((Component)((Transform)val.NPC.MSGConversation.entry).Find("Name")).GetComponent<Text>().text = val.NPC.FirstName;
				}
			}
			ChatterManager.Instance.chatters.Add(chatterData);
			ChatterManager.Instance.SendMessage("@" + text3 + " claimed a character!");
			val.NPC.RelationData.Unlock((EUnlockType)0, false);
			if (val.NPC.RelationData.Unlocked)
			{
				val.NPC.RelationData.onUnlocked((EUnlockType)0, arg2: true);
			}
			else
			{
				val.NPC.RelationData.Unlock((EUnlockType)0, true);
			}
			API.SendNotificationDelayed("Chat's revenge", text3 + " claimed a character!", 10, 2);
		}

		public void removeViewerDataRPC(string userID)
		{
			for (int i = 0; i < ChatterManager.Instance.chatters.Count; i++)
			{
				if (ChatterManager.Instance.chatters[i].twitchId == userID)
				{
					ChatterManager.Instance.chatters.RemoveAt(i);
					break;
				}
			}
		}

		public void viewerActiveRPC(string data)
		{
			long lastEpoch = API.secondsEpochNow();
			for (int i = 0; i < ChatterManager.Instance.chatters.Count; i++)
			{
				if (ChatterManager.Instance.chatters[i].twitchId == data || ChatterManager.Instance.chatters[i].displayName.ToLower() == data.ToLower())
				{
					ChatterManager.Instance.chatters[i].lastEpoch = lastEpoch;
					break;
				}
			}
		}

		public void setProfilingEndRPC(string data)
		{
			long num = long.Parse(data);
			profilingEnd = num;
		}

		public void callCopsRPC(string userID)
		{
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Expected O, but got Unknown
			ChatterData viewerData = API.getViewerData(userID);
			Customer val = null;
			if (viewerData != null)
			{
				val = viewerData.customer;
			}
			if ((Object)(object)val == (Object)null)
			{
				List<Customer> list = API.unlockedCustomers();
				Random random = new Random();
				if (list.Count > 0)
				{
					int index = random.Next(list.Count);
					val = list[index];
				}
			}
			if (!((Object)(object)val == (Object)null))
			{
				val.NPC.actions.SetCallPoliceBehaviourCrime((Crime)new AttemptingToSell());
				if (((NetworkBehaviour)Player.Local).IsHost)
				{
					val.NPC.actions.CallPolice_Networked(Player.Local);
				}
			}
		}

		public void SendNotificationRPC(string data)
		{
			string[] array = data.Split('#');
			string title = array[0];
			string subtitle = array[1];
			int duration = int.Parse(array[2]);
			API.SendNotification(title, subtitle, duration);
		}

		public void unlockAllCustomersRPC(string filler)
		{
			Customer[] array = Object.FindObjectsOfType<Customer>();
			Customer[] array2 = array;
			foreach (Customer val in array2)
			{
				val.NPC.RelationData.Unlock((EUnlockType)0, true);
			}
		}

		public void fakeCrashRPC(string user)
		{
			Thread.Sleep(5000);
			API.SendNotification("Chat's revenge", user + " caused a fake game crash lol", 10);
		}

		public void doubleHalfCash5050()
		{
			log("doubleHalfCash5050");
			float cashBalance = NetworkSingleton<MoneyManager>.Instance.cashBalance;
			if (Random.Range(0f, 1f) < 0.6f)
			{
				NetworkSingleton<MoneyManager>.Instance.ChangeCashBalance(cashBalance, true, true);
			}
			else
			{
				NetworkSingleton<MoneyManager>.Instance.ChangeCashBalance((0f - cashBalance) / 2f, true, true);
			}
		}

		public void destroyRandomPlantRPC(string user)
		{
			Plant[] array = Object.FindObjectsOfType<Plant>();
			if (array.Length != 0)
			{
				int num = Random.Range(0, array.Length);
				array[num].Destroy(false);
			}
		}

		public void PlaySoundPlayerLocationRPC(string data)
		{
			string[] array = data.Split('#');
			string clipName = array[0];
			string s = array[1];
			float stopTime = float.Parse(array[2]);
			float volume = float.Parse(array[3]);
			Player val = null;
			foreach (Player player in Player.PlayerList)
			{
				if (((NetworkBehaviour)player).OwnerId == int.Parse(s))
				{
					val = player;
					break;
				}
			}
			if (!((Object)(object)val == (Object)null))
			{
				PlaySoundPlayerLocation(clipName, val, stopTime, volume);
			}
		}

		public void PlaySoundPlayerLocation(string clipName, Player player, float stopTime = 9999f, float volume = 10f)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				AudioClip val = clips[clipName];
				AudioSource val2 = (AudioSource)((Component)player).gameObject.AddComponent(typeof(AudioSource));
				val2.clip = val;
				val2.spatialBlend = 1f;
				val2.volume = volume;
				((Component)val2).transform.position = ((Component)player).transform.position;
				val2.Play();
				float num = val.length * ((Time.timeScale < 0.01f) ? 0.01f : Time.timeScale);
				if (num > stopTime)
				{
					num = stopTime;
				}
				API.delayedFunction(this, "stopAudio", num, val2);
			}
			catch
			{
			}
		}

		public void stopAudio(AudioSource audioSource)
		{
			audioSource.Stop();
			Object.Destroy((Object)(object)audioSource);
		}

		public void NPCAttackPlayerCMD(string user)
		{
			NPCAttackPlayer(user);
		}

		public void NPCAttackPlayer(string user, string userid = "buh", bool others = false)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			float num = 30f;
			Customer val = null;
			Customer val2 = null;
			ChatterData viewerData = API.getViewerData(user, userid);
			if (viewerData != null && Vector3.Distance(viewerData.customer.NPC.Avatar.CenterPoint, Player.Local.Avatar.CenterPoint) <= num)
			{
				val = viewerData.customer;
			}
			if (others && (Object)(object)val == (Object)null)
			{
				List<Customer> list = API.unclaimedCustomers();
				if (list.Count > 0)
				{
					float num2 = Vector3.Distance(list[0].NPC.Avatar.CenterPoint, Player.Local.Avatar.CenterPoint);
					foreach (Customer item in list)
					{
						float num3 = Vector3.Distance(item.NPC.Avatar.CenterPoint, Player.Local.Avatar.CenterPoint);
						if (num3 <= num2)
						{
							val2 = item;
							num2 = num3;
						}
					}
				}
			}
			if ((Object)(object)val != (Object)null)
			{
				npcAttack(val.NPC);
				API.SendNotificationAll("Chat's revenge", user + " is attacking " + channelName, 8);
			}
			else if ((Object)(object)val2 != (Object)null)
			{
				npcAttack(val2.NPC);
				API.SendNotificationAll("Chat's revenge", user + " made " + val2.NPC.FirstName + " attack " + channelName, 8);
			}
			else if (others)
			{
				API.SendNotificationAll("Chat's revenge", user + " tried to attack " + channelName + " but no one was around", 8);
			}
		}

		public void npcAttack(NPC npc)
		{
			npc.behaviour.CombatBehaviour.SetTarget((NetworkConnection)null, ((NetworkBehaviour)Player.Local).NetworkObject);
			((Behaviour)npc.behaviour.CombatBehaviour).Enable_Networked((NetworkConnection)null);
			npc.VoiceOverEmitter.Play((EVOLineType)10);
			npc.VoiceOverEmitter.Play((EVOLineType)9);
			npc.dialogueHandler.PlayReaction("annoyed", 2.5f, false);
			if (InstanceFinder.IsServer)
			{
				npc.behaviour.FacePlayerBehaviour.SetTarget(((NetworkBehaviour)Player.Local).NetworkObject, 5f);
				((Behaviour)npc.behaviour.FacePlayerBehaviour).SendEnable();
			}
		}

		public void groupAttack(string user, string userid)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
			API.SendNotificationAll("Chat's revenge", user + " started a mob attack against " + channelName, 8);
			float num = 40f;
			ChatterData viewerData = API.getViewerData(user, userid);
			if (viewerData != null && Vector3.Distance(viewerData.customer.NPC.Avatar.CenterPoint, Player.Local.Avatar.CenterPoint) <= num)
			{
				npcAttack(viewerData.customer.NPC);
			}
			List<Customer> list = API.unclaimedCustomers();
			foreach (Customer item in list)
			{
				if (Vector3.Distance(item.NPC.Avatar.CenterPoint, Player.Local.Avatar.CenterPoint) <= num)
				{
					npcAttack(item.NPC);
				}
			}
		}

		public void trashRainLoop(int remaining)
		{
			//IL_001d: 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_0040: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: 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)
			if (remaining != 0)
			{
				remaining--;
				Vector3 position = ((Component)PlayerSingleton<PlayerCamera>.Instance).transform.position + ((Component)PlayerSingleton<PlayerCamera>.Instance).transform.right * Random.Range(-2f, 2f) + ((Component)PlayerSingleton<PlayerCamera>.Instance).transform.forward * 2f + ((Component)PlayerSingleton<PlayerCamera>.Instance).transform.up * Random.Range(1f, 3f);
				float delaySeconds = Random.Range(0.2f, 0.8f);
				API.delayedFunction(this, "trashRainLoop", delaySeconds, remaining);
				createRandomTrash(position);
			}
		}

		public void createRandomTrash(Vector3 position)
		{
			//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_001f: 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)
			TrashItem randomGeneratableTrashPrefab = NetworkSingleton<TrashManager>.Instance.GetRandomGeneratableTrashPrefab();
			TrashItem val = NetworkSingleton<TrashManager>.Instance.CreateTrashItem(randomGeneratableTrashPrefab.ID, position, Quaternion.identity, default(Vector3), "", false);
			val.SellValue = 0;
		}

		public void randomStatus(string user, int duration)
		{
			int index = Random.Range(0, propertiesnames.Count);
			string arg = propertiesnames[index];
			Property val = properties[index];
			val.ApplyToPlayer(Player.Local);
			API.SendNotification("Chat's revenge", $"{user} applied {arg} status effect for {duration} secs!", 10);
			API.delayedFunction<Property>(val, "ClearFromPlayer", duration, new object[1] { Player.Local });
		}
	}
}
namespace chatsRevenge.Utils
{
	internal class API
	{
		[CompilerGenerated]
		private sealed class <>c__DisplayClass12_0<T>
		{
			public string functionName;

			internal bool <DelayedInvoke>b__0(MethodInfo m)
			{
				return m.Name == functionName;
			}
		}

		[CompilerGenerated]
		private sealed class <DelayedInvoke>d__12<T> : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public T instance;

			public string functionName;

			public float delaySeconds;

			public object[] parameters;

			private <>c__DisplayClass12_0<T> <>8__1;

			private List<MethodInfo> <methods>5__2;

			private MethodInfo <matchingMethod>5__3;

			private List<MethodInfo>.Enumerator <>s__4;

			private MethodInfo <method>5__5;

			private ParameterInfo[] <methodParams>5__6;

			private bool <allMatch>5__7;

			private int <i>5__8;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <DelayedInvoke>d__12(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>8__1 = null;
				<methods>5__2 = null;
				<matchingMethod>5__3 = null;
				<>s__4 = default(List<MethodInfo>.Enumerator);
				<method>5__5 = null;
				<methodParams>5__6 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0043: Unknown result type (might be due to invalid IL or missing references)
				//IL_004d: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>8__1 = new <>c__DisplayClass12_0<T>();
					<>8__1.functionName = functionName;
					<>2__current = (object)new WaitForSeconds(delaySeconds);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					Plugin.Instance.log("DelayedInvoke waiting done");
					<methods>5__2 = (from m in instance.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
						where m.Name == <>8__1.functionName
						select m).ToList();
					<matchingMethod>5__3 = null;
					<>s__4 = <methods>5__2.GetEnumerator();
					try
					{
						while (<>s__4.MoveNext())
						{
							<method>5__5 = <>s__4.Current;
							<methodParams>5__6 = <method>5__5.GetParameters();
							if (<methodParams>5__6.Length != parameters.Length)
							{
								continue;
							}
							<allMatch>5__7 = true;
							<i>5__8 = 0;
							while (<i>5__8 < parameters.Length)
							{
								if (parameters[<i>5__8] == null)
								{
									if (<methodParams>5__6[<i>5__8].ParameterType.IsValueType && Nullable.GetUnderlyingType(<methodParams>5__6[<i>5__8].ParameterType) == null)
									{
										<allMatch>5__7 = false;
										break;
									}
								}
								else if (!<methodParams>5__6[<i>5__8].ParameterType.IsAssignableFrom(parameters[<i>5__8].GetType()))
								{
									<allMatch>5__7 = false;
									break;
								}
								<i>5__8++;
							}
							if (<allMatch>5__7)
							{
								<matchingMethod>5__3 = <method>5__5;
								break;
							}
							<methodParams>5__6 = null;
							<method>5__5 = null;
						}
					}
					finally
					{
						((IDisposable)<>s__4).Dispose();
					}
					<>s__4 = default(List<MethodInfo>.Enumerator);
					if (<matchingMethod>5__3 != null)
					{
						Plugin.Instance.log("Found matching method: " + <matchingMethod>5__3.Name);
						<matchingMethod>5__3.Invoke(instance, parameters);
					}
					else
					{
						Plugin.Instance.logError($"No matching method '{<>8__1.functionName}' with {parameters.Length} parameter(s) found in {instance.GetType().Name}.");
					}
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <HideNotification>d__24 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public DeaddropQuest component;

			public int duration;

			private GameDateTime <expiry>5__1;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <HideNotification>d__24(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				//IL_0032: Expected O, but got Unknown
				//IL_0048: Unknown result type (might be due to invalid IL or missing references)
				//IL_004d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0059: Unknown result type (might be due to invalid IL or missing references)
				//IL_0067: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds((float)duration);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<expiry>5__1 = NetworkSingleton<TimeManager>.instance.GetDateTime();
					((GameDateTime)(ref <expiry>5__1)).AddMins(2);
					((Quest)component).ConfigureExpiry(true, <expiry>5__1);
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <SendNotificationDelayedCoroutine>d__26 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public string title;

			public string subtitle;

			public int duration;

			public int delay;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <SendNotificationDelayedCoroutine>d__26(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				//IL_0032: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds((float)delay);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					SendNotification(title, subtitle, duration);
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		public static List<string> bufferedCMD { get; set; } = new List<string>();


		public static void ProcessInput(string dataString)
		{
			//IL_0456: Unknown result type (might be due to invalid IL or missing references)
			//IL_078b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0795: Unknown result type (might be due to invalid IL or missing references)
			//IL_08cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_08d2: Expected O, but got Unknown
			//IL_092f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0936: Expected O, but got Unknown
			//IL_0993: Unknown result type (might be due to invalid IL or missing references)
			//IL_099a: Expected O, but got Unknown
			//IL_09f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_09fe: Expected O, but got Unknown
			string[] array = dataString.Split(';');
			int num = int.Parse(array[0]);
			string text = array[1];
			string text2 = array[2];
			string text3 = array[3];
			string text4 = array[4];
			int num2 = int.Parse(array[5]);
			if (num2 < 0)
			{
				num2 = 1;
			}
			string text5 = array[6];
			string text6 = array[7];
			if (!Singleton<LoadManager>.Instance.IsGameLoaded)
			{
				return;
			}
			ChatterData viewerData = getViewerData(text2, text4);
			if (viewerData != null)
			{
				sendRPCAll("viewerActiveRPC#" + text4);
			}
			if (text == "scheduleI_unlockAll")
			{
				sendRPCAll("unlockAllCustomersRPC#filler");
				SendNotificationAll("Chat's revenge", text2 + " unlocked all customers!", 10);
			}
			if (text == "scheduleI_50double50halfCash")
			{
				Plugin.Instance.log("buh");
				delayedFunction(Plugin.Instance, "doubleHalfCash5050", 4f);
				Plugin.Instance.PlaySoundPlayerLocation("gamble", Player.Local, 4f, 0.2f);
				SendNotification("Chat's revenge", text2 + " gambled to either half or double your pocket money!", 10);
			}
			if (text == "scheduleI_doubleCash")
			{
				float cashBalance = NetworkSingleton<MoneyManager>.Instance.cashBalance;
				NetworkSingleton<MoneyManager>.Instance.ChangeCashBalance(cashBalance, true, true);
				SendNotification("Chat's revenge", text2 + " doubled your pocket money!", 10);
			}
			if (text == "scheduleI_halfCash")
			{
				float cashBalance2 = NetworkSingleton<MoneyManager>.Instance.cashBalance;
				NetworkSingleton<MoneyManager>.Instance.ChangeCashBalance((0f - cashBalance2) / 2f, true, true);
				SendNotification("Chat's revenge", text2 + " halved your pocket money!", 10);
			}
			if (text == "scheduleI_claimCharacter")
			{
				if (viewerData != null)
				{
					ChatterManager.Instance.SendMessage("@" + text2 + " you already have a character!");
					return;
				}
				Customer val = null;
				List<Customer> list = unclaimedCustomers();
				Plugin.Instance.log($"unclaimed characters: {list.Count}");
				if (list.Count > 0)
				{
					val = list[0];
				}
				if ((Object)(object)val == (Object)null)
				{
					Plugin.Instance.log("All characters claimed! looking for unactive chatters.");
					List<ChatterData> list2 = inactiveChatters();
					if (list2.Count > 0)
					{
						val = list2[0].customer;
						sendRPCAll("removeViewerDataRPC#" + text4);
					}
				}
				if ((Object)(object)val == (Object)null)
				{
					ChatterManager.Instance.SendMessage("Sorry @" + text2 + " no available characters to claim!");
					return;
				}
				string text7 = val.NPC.ID + "#" + val.NPC.fullName + "#" + text2 + "#" + text4;
				Plugin.Instance.log(text7);
				sendRPCAll("claimCharacterRPC#" + text7);
			}
			if (text == "scheduleI_sendContract")
			{
				Customer val2 = null;
				if (viewerData != null)
				{
					val2 = viewerData.customer;
				}
				else
				{
					List<Customer> list3 = unlockedCustomers();
					Random random = new Random();
					if (list3.Count > 0)
					{
						int index = random.Next(list3.Count);
						val2 = list3[index];
						SendNotification("Chat's revenge", "Someone told " + val2.NPC.FirstName + " you got the good stuff", 10);
					}
				}
				if ((Object)(object)val2 == (Object)null)
				{
					return;
				}
				ContractInfo val3 = val2.CheckContractGeneration(true);
				int num3 = 0;
				if (val3 != null)
				{
					if ((Object)(object)val2.AssignedDealer != (Object)null)
					{
						if (val2.AssignedDealer.ShouldAcceptContract(val3, val2))
						{
							num3 = val2.OfferedDeals;
							val2.OfferedDeals = num3 + 1;
							val2.TimeSinceLastDealOffered = 0;
							val2.OfferedContractInfo = val3;
							val2.OfferedContractTime = NetworkSingleton<TimeManager>.Instance.GetDateTime();
							val2.HasChanged = true;
							val2.AssignedDealer.ContractedOffered(val3, val2);
						}
					}
					else
					{
						val2.OfferContract(val3);
					}
				}
			}
			if (text == "scheduleI_sendMessage")
			{
				if (viewerData == null)
				{
					ChatterManager.Instance.SendMessage("@" + text2 + " you don't have a character claimed!");
					return;
				}
				sendMessagePlayerPhone(viewerData.customer, text6);
			}
			if (text == "scheduleI_freeSlotSpin")
			{
				Plugin.Instance.freeSlotSpins += 3;
				SendNotification("Chat's revenge", text2 + " gave you 3 free slot spins!", 10);
			}
			if (text == "scheduleI_betterSlotodds")
			{
				long num4 = secondsEpochNow();
				if (Plugin.Instance.betterSlotOddsEnd > num4)
				{
					num4 = Plugin.Instance.betterSlotOddsEnd;
				}
				num4 += num2;
				sendRPCAll($"setBetterSlotOddsEnd#{num4}");
				SendNotificationAll("Chat's revenge", $"{text2} gave everyone {num2} seconds of extra slots luck!", 10);
			}
			if (text == "scheduleI_callCops")
			{
				sendRPCAll("callCopsRPC#" + text4);
				SendNotificationAll("Chat's revenge", text2 + " snitched on " + Plugin.Instance.channelName + "!", 10);
			}
			if (text == "scheduleI_profiling")
			{
				long num5 = secondsEpochNow();
				if (Plugin.Instance.betterSlotOddsEnd > num5)
				{
					num5 = Plugin.Instance.betterSlotOddsEnd;
				}
				num5 += num2 * 60;
				SendNotificationAll("Chat's revenge", $"{text2} made everyone start suspiciously profiling you for {num2} seconds!", 10);
				sendRPCAll($"setProfilingEndRPC#{num5}");
			}
			if (text == "scheduleI_fakeCrash")
			{
				sendRPCAll("fakeCrashRPC#" + text2);
			}
			if (text == "scheduleI_destroyRandomPlant")
			{
				SendNotificationAll("Chat's revenge", text2 + " destroyed a random plant!", 10);
				sendRPCServer("destroyRandomPlantRPC#" + text2);
			}
			if (text == "scheduleI_attack")
			{
				Plugin.Instance.NPCAttackPlayer(text2, text4, others: true);
			}
			if (text == "scheduleI_attackGroup")
			{
				Plugin.Instance.groupAttack(text2, text4);
			}
			if (text == "scheduleI_trashRain")
			{
				Plugin.Instance.trashRainLoop(10);
				Plugin.Instance.trashRainLoop(10);
				SendNotificationAll("Chat's revenge", text2 + " made it rain trash on " + Plugin.Instance.channelName + "!", 10);
			}
			if (text == "scheduleI_heal")
			{
				if (Player.Local.Health.CurrentHealth == 0f)
				{
					Player.Local.Health.Revive(Player.Local.CameraPosition, Player.Local.CameraRotation);
				}
				else
				{
					Player.Local.Health.RecoverHealth(100f);
				}
				SendNotification("Chat's revenge", text2 + " healed you!", 10);
			}
			if (text == "scheduleI_damage")
			{
				if (Player.Local.Health.CanTakeDamage)
				{
					Player.Local.Health.TakeDamage(10f, true, true);
					SendNotification("Chat's revenge", text2 + " damaged you!", 10);
				}
				else
				{
					SendNotification("Chat's revenge", text2 + " tried to damage you!", 10);
				}
			}
			if (text == "scheduleI_reduceWanted")
			{
				Player.Local.CrimeData.Deescalate();
				SendNotification("Chat's revenge", text2 + " reduced your wanted level!", 10);
			}
			if (text == "scheduleI_escalateWanted")
			{
				Player.Local.CrimeData.Escalate();
				SendNotification("Chat's revenge", text2 + " increased your wanted level!", 10);
			}
			if (text == "scheduleI_antiGravity")
			{
				AntiGravity val4 = new AntiGravity();
				((Property)val4).ApplyToPlayer(Player.Local);
				delayedFunction<AntiGravity>(val4, "ClearFromPlayer", num2, new object[1] { Player.Local });
				SendNotification("Chat's revenge", $"{text2} gave you anti gravity for {num2} secs!", 10);
			}
			if (text == "scheduleI_seizure")
			{
				Seizure val5 = new Seizure();
				((Property)val5).ApplyToPlayer(Player.Local);
				delayedFunction<Seizure>(val5, "ClearFromPlayer", num2, new object[1] { Player.Local });
				SendNotification("Chat's revenge", $"{text2} gave you a Seizure for {num2} secs!", 10);
			}
			if (text == "scheduleI_disorienting")
			{
				Disorienting val6 = new Disorienting();
				((Property)val6).ApplyToPlayer(Player.Local);
				delayedFunction<Disorienting>(val6, "ClearFromPlayer", num2, new object[1] { Player.Local });
				SendNotification("Chat's revenge", $"{text2} made you disoriented for {num2} secs!", 10);
			}
			if (text == "scheduleI_athletic")
			{
				Athletic val7 = new Athletic();
				((Property)val7).ApplyToPlayer(Player.Local);
				delayedFunction<Athletic>(val7, "ClearFromPlayer", num2, new object[1] { Player.Local });
				SendNotification("Chat's revenge", $"{text2} made you a super fast athlete for {num2} secs!", 10);
			}
			if (text == "scheduleI_randomStatusEffect")
			{
				SendNotification("Chat's revenge", text2 + " is going to give you a random effect!", 10);
				Plugin.Instance.PlaySoundPlayerLocation("gamble", Player.Local, 5f, 0.2f);
				delayedFunction(Plugin.Instance, "randomStatus", 5f, text2, num2);
			}
		}

		public static AudioClip GetAudioFromFile(string audiopath)
		{
			UnityWebRequest audioClip = UnityWebRequestMultimedia.GetAudioClip(audiopath, (AudioType)13);
			audioClip.SendWebRequest();
			while (!audioClip.isDone)
			{
			}
			return DownloadHandlerAudioClip.GetContent(audioClip);
		}

		public static void handleRPC(Message m)
		{
			string text = m.text;
			Plugin.Instance.log("handleRPC " + text);
			string[] array = text.Split('#');
			string text2 = array[0];
			string text3 = string.Join("#", array.Skip(1));
			if (text2 == "ProcessInput")
			{
				ProcessInput(text3);
			}
			else if (array.Length > 1)
			{
				InvokeMethod(Plugin.Instance, text2, text3);
			}
			else
			{
				InvokeMethod(Plugin.Instance, text2, "filler");
			}
		}

		public static void sendRPCServer(string data)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			Message val = new Message();
			val.text = data;
			NetworkSingleton<MessagingManager>.Instance.SendMessage(val, false, "chatsrevenge#server");
		}

		public static void sendRPCAll(string data)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			Message val = new Message();
			val.text = data;
			Plugin.Instance.log("sendRPCAll " + data);
			NetworkSingleton<MessagingManager>.Instance.SendMessage(val, false, "chatsrevenge#all");
		}

		public static void sendRPC(string data, string targetID)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			Message val = new Message();
			val.text = data;
			NetworkSingleton<MessagingManager>.Instance.SendMessage(val, false, "chatsrevenge#" + targetID);
		}

		public static void delayedFunction<T>(T instance, string functionName, float delaySeconds)
		{
			Plugin.Instance.log("DelayedInvoke " + functionName);
			((MonoBehaviour)Player.Local).StartCoroutine(DelayedInvoke(instance, functionName, delaySeconds, new object[0]));
		}

		public static void delayedFunction<T>(T instance, string functionName, float delaySeconds, params object[] parameters)
		{
			Plugin.Instance.log("DelayedInvoke " + functionName);
			((MonoBehaviour)Player.Local).StartCoroutine(DelayedInvoke(instance, functionName, delaySeconds, parameters));
		}

		[IteratorStateMachine(typeof(<DelayedInvoke>d__12<>))]
		public static IEnumerator DelayedInvoke<T>(T instance, string functionName, float delaySeconds, object[] parameters)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <DelayedInvoke>d__12<T>(0)
			{
				instance = instance,
				functionName = functionName,
				delaySeconds = delaySeconds,
				parameters = parameters
			};
		}

		public static string GetChatToken()
		{
			if (Plugin.Instance.Token.StartsWith("oauth:"))
			{
				return Plugin.Instance.Token;
			}
			return "oauth:" + Plugin.Instance.Token;
		}

		public static string GetTimeoutToken()
		{
			if (Plugin.Instance.Token.StartsWith("oauth:"))
			{
				return Plugin.Instance.Token.Substring(6);
			}
			return Plugin.Instance.Token;
		}

		public static void sendMessagePlayerPhone(Customer customer, string text)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			customer.NPC.MSGConversation.SendMessage(new Message(text, (ESenderType)1, false, -1), true, true);
		}

		public static List<Customer> unlockedCustomers()
		{
			List<Customer> list = new List<Customer>();
			Customer[] array = Object.FindObjectsOfType<Customer>();
			Customer[] array2 = array;
			foreach (Customer val in array2)
			{
				if (val.NPC.RelationData.Unlocked)
				{
					list.Add(val);
				}
			}
			return list;
		}

		public static List<Customer> unclaimedCustomers()
		{
			List<Customer> list = new List<Customer>();
			Customer[] array = Object.FindObjectsOfType<Customer>();
			Customer[] array2 = array;
			foreach (Customer val in array2)
			{
				bool flag = false;
				foreach (ChatterData chatter in ChatterManager.Instance.chatters)
				{
					if ((Object)(object)chatter.customer == (Object)(object)val)
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					list.Add(val);
				}
			}
			return list;
		}

		public static ChatterData getViewerData(string name, string userid = "none")
		{
			foreach (ChatterData chatter in ChatterManager.Instance.chatters)
			{
				if (chatter.displayName.ToLower() == name.ToLower())
				{
					return chatter;
				}
				if (chatter.twitchId == userid)
				{
					return chatter;
				}
			}
			return null;
		}

		public static List<ChatterData> inactiveChatters()
		{
			long num = secondsEpochNow();
			List<ChatterData> list = new List<ChatterData>();
			bool flag = true;
			while (flag)
			{
				flag = false;
				foreach (ChatterData chatter in ChatterManager.Instance.chatters)
				{
					if (num - chatter.lastEpoch > Plugin.inactiveThreshold.Value * 60)
					{
						list.Add(chatter);
						flag = true;
					}
				}
			}
			list.Sort((ChatterData a, ChatterData b) => b.lastEpoch.CompareTo(a.lastEpoch));
			return list;
		}

		public static long secondsEpochNow()
		{
			return DateTimeOffset.UtcNow.ToUnixTimeSeconds();
		}

		public static void InvokeMethod<T>(T instance, string functionName, string argument)
		{
			MethodInfo method = typeof(T).GetMethod(functionName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null);
			if (method != null)
			{
				method.Invoke(instance, new object[1] { argument });
			}
			else
			{
				Plugin.Instance.logError("Function " + functionName + " with a single string argument not found!");
			}
		}

		public static void SendNotificationAll(string title, string subtitle, int duration)
		{
			string text = $"{title}#{subtitle}#{duration}";
			sendRPCAll("SendNotificationRPC#" + text);
		}

		public static void SendNotification(string title, string subtitle, int duration)
		{
			try
			{
				Plugin.Instance.log($"SendNotification {title} {subtitle} {duration}");
				DeaddropQuest component = Object.Instantiate<GameObject>(((Component)NetworkSingleton<QuestManager>.instance.DeaddropCollectionPrefab).gameObject, NetworkSingleton<QuestManager>.instance.QuestContainer).GetComponent<DeaddropQuest>();
				((Quest)component).title = title;
				((Quest)component).Description = title;
				((Quest)component).Subtitle = "";
				((Quest)component).CompletionXP = 0;
				((Quest)component).Begin(true);
				if (Object.op_Implicit((Object)(object)PlayerSingleton<MessagesApp>.Instance))
				{
					PlayerSingleton<MessagesApp>.Instance.MessageReceivedSound.Play();
				}
				if (Object.op_Implicit((Object)(object)Singleton<NotificationsManager>.Instance))
				{
					Singleton<NotificationsManager>.Instance.Sound.Play();
				}
				MelonCoroutines.Start(HideNotification(component, duration));
				foreach (QuestEntry entry in ((Quest)component).Entries)
				{
					if (Object.op_Implicit((Object)(object)entry))
					{
						entry.EntryTitle = subtitle;
						if (Object.op_Implicit((Object)(object)entry.entryUI) && Object.op_Implicit((Object)(object)entry.entryUI.MainLabel))
						{
							((TMP_Text)entry.entryUI.MainLabel).text = subtitle;
						}
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Instance.logError(ex.ToString());
			}
		}

		[IteratorStateMachine(typeof(<HideNotification>d__24))]
		private static IEnumerator HideNotification(DeaddropQuest component, int duration)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <HideNotification>d__24(0)
			{
				component = component,
				duration = duration
			};
		}

		public static void SendNotificationDelayed(string title, string subtitle, int duration, int delay)
		{
			((MonoBehaviour)Player.Local).StartCoroutine(SendNotificationDelayedCoroutine(title, subtitle, duration, delay));
		}

		[IteratorStateMachine(typeof(<SendNotificationDelayedCoroutine>d__26))]
		private static IEnumerator SendNotificationDelayedCoroutine(string title, string subtitle, int duration, int delay)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <SendNotificationDelayedCoroutine>d__26(0)
			{
				title = title,
				subtitle = subtitle,
				duration = duration,
				delay = delay
			};
		}

		public static ESymbol GetRandomSymbol()
		{
			//IL_001b: 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)
			return (ESymbol)Random.Range(0, Enum.GetValues(typeof(ESymbol)).Length);
		}

		public static bool IsFruit(ESymbol symbol)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Invalid comparison between Unknown and I4
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Invalid comparison between Unknown and I4
			if ((int)symbol != 0 && (int)symbol != 1 && (int)symbol != 2)
			{
				return (int)symbol == 3;
			}
			return true;
		}

		public static bool IsUniform(ESymbol[] symbols)
		{
			for (int i = 1; i < symbols.Length; i++)
			{
				if ((int)symbols[i] != (int)symbols[i - 1])
				{
					return false;
				}
			}
			return true;
		}

		public static EOutcome EvaluateOutcome(ESymbol[] outcome)
		{
			//IL_0050: 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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: 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_003a: Unknown result type (might be due to invalid IL or missing references)
			if (IsUniform(outcome))
			{
				if ((int)outcome[0] == 5)
				{
					return (EOutcome)0;
				}
				if ((int)outcome[0] == 4)
				{
					return (EOutcome)1;
				}
				if (IsFruit(outcome[0]))
				{
					return (EOutcome)2;
				}
			}
			if (IsAllFruit(outcome))
			{
				return (EOutcome)3;
			}
			return (EOutcome)4;
		}

		public static bool IsAllFruit(ESymbol[] symbols)
		{
			for (int i = 0; i < symbols.Length; i++)
			{
				if (!IsFruit(symbols[i]))
				{
					return false;
				}
			}
			return true;
		}

		public static ESymbol[] generateSymbols(int size)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			List<ESymbol> list = new List<ESymbol>();
			for (int i = 0; i < size; i++)
			{
				list.Add(GetRandomSymbol());
			}
			return list.ToArray();
		}

		public static ESymbol[] generateBetterSymbols(int size)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Expected I4, but got Unknown
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Expected I4, but got Unknown
			List<ESymbol> list = new List<ESymbol>();
			for (int i = 0; i < size; i++)
			{
				list.Add(GetRandomSymbol());
			}
			ESymbol[] array = list.ToArray();
			if (array.Length != 0)
			{
				List<ESymbol> list2 = new List<ESymbol>
				{
					(ESymbol)0,
					(ESymbol)0,
					(ESymbol)1,
					(ESymbol)1,
					(ESymbol)3,
					(ESymbol)3,
					(ESymbol)5,
					(ESymbol)5,
					(ESymbol)4
				};
				int index = Random.Range(0, list2.Count);
				array[0] = (ESymbol)(int)list2[index];
			}
			if (array.Length > 1)
			{
				if (IsFruit(array[0]) && !IsFruit(array[1]))
				{
					if (33 > Random.Range(0, 100))
					{
						array[1] = array[0];
					}
				}
				else if ((int)array[0] != (int)array[1] && 33 > Random.Range(0, 100))
				{
					array[1] = array[0];
				}
			}
			if (array.Length > 2)
			{
				if (IsFruit(array[0]) && IsFruit(array[1]) && !IsFruit(array[^1]))
				{
					if (25 > Random.Range(0, 100))
					{
						array[^1] = array[0];
					}
				}
				else if ((int)array[0] == (int)array[1] && !IsUniform(array.ToArray()) && 25 > Random.Range(0, 100))
				{
					array[^1] = array[0];
				}
				int num = 0;
				for (int j = 0; j <= 3; j++)
				{
					ESymbol randomSymbol = GetRandomSymbol();
					ESymbol[] array2 = (ESymbol[])(object)new ESymbol[array.Length];
					Array.Copy(array, array2, array.Length);
					int num2 = symbolsValue(array2);
					if (num2 > num)
					{
						num = num2;
						array[^1] = (ESymbol)(int)randomSymbol;
					}
				}
			}
			return array;
		}

		public static int symbolsValue(ESymbol[] array)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//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_000d: 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)
			//IL_0024: Expected I4, but got Unknown
			int result = 0;
			EOutcome val = EvaluateOutcome(array);
			EOutcome val2 = val;
			EOutcome val3 = val2;
			switch ((int)val3)
			{
			case 0:
				result = 100;
				break;
			case 1:
				result = 25;
				break;
			case 2:
				result = 10;
				break;
			case 3:
				result = 2;
				break;
			}
			return result;
		}

		public static void timeout(string userdID, int duration)
		{
			pythonSocket.Instance.SendData($"scheduleI_timeout {userdID} {duration}");
		}

		public static void spaceWorldText(NPC npc, string line, float duration)
		{
			if (line == string.Empty)
			{
				npc.dialogueHandler.HideWorldspaceDialogue();
				return;
			}
			if (duration == -1f)
			{
				duration = Mathf.Clamp((float)line.Length * 0.2f, 1.5f, 5f);
			}
			npc.dialogueHandler.WorldspaceRend.ShowText(line, duration);
		}
	}
	public class ChatterData
	{
		public string displayName;

		public string twitchId;

		public long lastEpoch;

		public Customer customer;
	}
	public class ChatterManager
	{
		private TcpClient tcpClient;

		private StreamReader reader;

		private StreamWriter writer;

		private Thread botThread;

		private bool isRunning = false;

		private static ChatterManager _instance;

		public List<ChatterData> chatters = new List<ChatterData>();

		public static Dictionary<string, long> phoneMessagesTimestamp = new Dictionary<string, long>();

		public static ChatterManager Instance
		{
			get
			{
				if (_instance == null)
				{
					_instance = new ChatterManager();
				}
				return _instance;
			}
		}

		public void StartBot()
		{
			if (!isRunning)
			{
				isRunning = true;
				botThread = new Thread(BotLoop);
				botThread.IsBackground = true;
				botThread.Start();
				MelonLogger.Msg("Chatbot started");
			}
		}

		public void StopBot()
		{
			if (isRunning)
			{
				isRunning = false;
				if (writer != null)
				{
					writer.Flush();
					writer.Close();
				}
				if (reader != null)
				{
					reader.Close();
				}
				if (tcpClient != null)
				{
					tcpClient.Close();
				}
				MelonLogger.Msg("Chatbot stopped");
			}
		}

		private void BotLoop()
		{
			try
			{
				ConnectToTwitch();
				while (isRunning)
				{
					if (!tcpClient.Connected)
					{
						MelonLogger.Warning("Lost connection to Twitch, attempting to reconnect...");
						ConnectToTwitch();
					}
					try
					{
						string text = reader.ReadLine();
						if (text != null)
						{
							if (text.StartsWith("PING"))
							{
								writer.WriteLine("PONG" + text.Substring(4));
								writer.Flush();
							}
							else
							{
								ProcessMessage(text);
							}
						}
					}
					catch (Exception ex)
					{
						MelonLogger.Error("Error processing message: " + ex.Message);
					}
				}
			}
			catch (Exception ex2)
			{
				MelonLogger.Error("Bot thread error: " + ex2.Message);
			}
		}

		public void SendMessage(string msg)
		{
			writer.WriteLine("PRIVMSG #" + Plugin.Instance.channelName.ToLower() + " :#ChatsRevenge: " + msg + ".");
		}

		private void ConnectToTwitch()
		{
			try
			{
				tcpClient = new TcpClient("irc.chat.twitch.tv", 6667);
				reader = new StreamReader(tcpClient.GetStream());
				writer = new StreamWriter(tcpClient.GetStream())
				{
					AutoFlush = true
				};
				writer.WriteLine("PASS " + API.GetChatToken());
				writer.WriteLine("NICK " + Plugin.Instance.channelName.ToLower());
				writer.WriteLine("JOIN #" + Plugin.Instance.channelName.ToLower());
				MelonLogger.Msg("Connected to Twitch channel #" + Plugin.Instance.channelName);
				writer.WriteLine("PRIVMSG #" + Plugin.Instance.channelName.ToLower() + " :#ChatsRevenge: started Schedule I with chat's revenge twitch integration.");
			}
			catch (Exception ex)
			{
				MelonLogger.Error("Failed to connect to Twitch: " + ex.Message);
				Thread.Sleep(5000);
			}
		}

		private void ProcessMessage(string message)
		{
			if (!message.Contains("PRIVMSG"))
			{
				return;
			}
			try
			{
				int num = message.IndexOf('!');
				int num2 = message.IndexOf("PRIVMSG");
				if (num == -1 || num2 == -1)
				{
					return;
				}
				string text = message.Substring(1, num - 1).ToLower();
				int num3 = message.IndexOf(':', num2);
				if (num3 == -1)
				{
					return;
				}
				string text2 = message.Substring(num3 + 1);
				ChatterData viewerData = API.getViewerData(text);
				if (viewerData != null)
				{
					API.sendRPCAll("viewerActiveRPC#" + text);
				}
				if (text2 == "!character")
				{
					if (viewerData == null)
					{
						List<Customer> list = API.unclaimedCustomers();
						List<ChatterData> list2 = API.inactiveChatters();
						SendMessage($"@{text} you don't have a character. There are {list.Count} unclaimed and {list2.Count} inactive characters. Claim yours with bits/points!");
						return;
					}
					SendMessage($"@{text} you have a character. Health:{viewerData.customer.NPC.Health.Health}/{viewerData.customer.NPC.Health.MaxHealth}. IsConscious:{viewerData.customer.NPC.IsConscious}. relationship:{(int)(viewerData.customer.NPC.RelationData.NormalizedRelationDelta * 100f)}");
				}
				if (viewerData == null || (Object)(object)viewerData.customer == (Object)null)
				{
					return;
				}
				if (text2 == "!accept")
				{
					if (viewerData != null)
					{
						Plugin.Instance.log("offer accepted");
						if (PlayerPatches.pendingOfferResult.ContainsKey(viewerData.customer))
						{
							PlayerPatches.pendingOfferResult[viewerData.customer] = 1;
						}
						else
						{
							Plugin.Instance.log("no offer cashed");
						}
					}
				}
				else if (text2 == "!decline")
				{
					if (viewerData != null)
					{
						Plugin.Instance.log("offer declined");
						if (PlayerPatches.pendingOfferResult.ContainsKey(viewerData.customer))
						{
							PlayerPatches.pendingOfferResult[viewerData.customer] = 0;
						}
						else
						{
							Plugin.Instance.log("no offer cashed");
						}
					}
				}
				else if (text2.StartsWith("!message"))
				{
					if (Plugin.phoneMessagesRate.Value <= 0 || viewerData == null)
					{
						return;
					}
					long num4 = API.secondsEpochNow();
					List<string> list3 = new List<string>();
					foreach (string key in phoneMessagesTimestamp.Keys)
					{
						if (num4 - phoneMessagesTimestamp[key] > Plugin.phoneMessagesRate.Value)
						{
							list3.Add(key);
						}
					}
					foreach (string item in list3)
					{
						phoneMessagesTimestamp.Remove(item);
					}
					if (!phoneMessagesTimestamp.ContainsKey(text))
					{
						string text3 = text2.Substring("!message".Length).Trim();
						phoneMessagesTimestamp[text] = num4;
						API.bufferedCMD.Add("sendMessagePlayerPhone#" + viewerData.displayName + "#" + text3);
					}
					else
					{
						Plugin.Instance.log(text + " is spamming messages");
					}
				}
				else if (text2 == "!attack")
				{
					if (viewerData != null)
					{
						API.bufferedCMD.Add("NPCAttackPlayerCMD#" + viewerData.displayName);
					}
				}
				else if (text2[0] != '!')
				{
					if (text2.Length > 30)
					{
						text2 = text2.Substring(0, 27) + "...";
					}
					if ((Object)(object)viewerData.customer != (Object)null)
					{
						API.spaceWorldText(viewerData.customer.NPC, text2, 4f);
					}
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Error("Error parsing message: " + ex.Message);
			}
		}
	}
}
namespace chatsRevenge.Patches
{
	internal class PlayerPatches
	{
		[CompilerGenerated]
		private sealed class <SendCounterofferDelayed>d__9 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public Customer __instance;

			public ProductDefinition product;

			public int quantity;

			public float price;

			private string <text>5__1;

			private int <i>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <SendCounterofferDelayed>d__9(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<text>5__1 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e5: Expected O, but got Unknown
				//IL_011f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0129: Expected O, but got Unknown
				int num = <>1__state;
				if (num != 0)
				{
					if (num != 1)
					{
						return false;
					}
					<>1__state = -1;
					if (pendingOfferResult[__instance] >= 0)
					{
						goto IL_0178;
					}
					<i>5__2++;
				}
				else
				{
					<>1__state = -1;
					Plugin.Instance.log("SendCounterofferDelayed");
					if (__instance.OfferedContractInfo == null || __instance.OfferedContractInfo.IsCounterOffer)
					{
						goto IL_01a3;
					}
					<text>5__1 = "How about " + quantity + "x " + ((ItemDefinition)product).Name + " for " + MoneyManager.FormatAmount(price, false, false) + "?";
					__instance.NPC.MSGConversation.SendMessage(new Message(<text>5__1, (ESenderType)0, false, -1), true, true);
					__instance.NPC.MSGConversation.ClearResponses(false);
					pendingOfferResult[__instance] = -1;
					<i>5__2 = 0;
				}
				if (<i>5__2 < 40)
				{
					<>2__current = (object)new WaitForSeconds(0.5f);
					<>1__state = 1;
					return true;
				}
				goto IL_0178;
				IL_01a3:
				return false;
				IL_0178:
				__instance.ProcessCounterOfferServerSide(((ItemDefinition)product).ID, quantity, price);
				<text>5__1 = null;
				goto IL_01a3;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		public static Dictionary<Customer, int> pendingOfferResult = new Dictionary<Customer, int>();

		[HarmonyPatch(typeof(Player), "Update")]
		[HarmonyPostfix]
		public static void loopOnce()
		{
			if (API.bufferedCMD.Count <= 0)
			{
				return;
			}
			string text = API.bufferedCMD[0];
			API.bufferedCMD.RemoveAt(0);
			string[] array = text.Split('#');
			string text2 = array[0];
			string text3 = string.Join("#", array.Skip(1));
			if (text2 == "ProcessInput")
			{
				try
				{
					API.ProcessInput(text3);
					return;
				}
				catch (Exception ex)
				{
					Plugin.Instance.logError(ex.ToString());
					return;
				}
			}
			if (array.Length > 1)
			{
				API.InvokeMethod(Plugin.Instance, text2, text3);
			}
			else
			{
				API.InvokeMethod(Plugin.Instance, text2, "filler");
			}
		}

		[HarmonyPatch(typeof(Player), "PlayerLoaded")]
		[HarmonyPostfix]
		public static void PlayerLoaded()
		{
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Expected O, but got Unknown
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Expected O, but got Unknown
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Expected O, but got Unknown
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Expected O, but got Unknown
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Expected O, but got Unknown
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Expected O, but got Unknown
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Expected O, but got Unknown
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Expected O, but got Unknown
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Expected O, but got Unknown
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Expected O, but got Unknown
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Expected O, but got Unknown
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Expected O, but got Unknown
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Expected O, but got Unknown
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Expected O, but got Unknown
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Expected O, but got Unknown
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Expected O, but got Unknown
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Expected O, but got Unknown
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Expected O, but got Unknown
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Expected O, but got Unknown
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Expected O, but got Unknown
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Expected O, but got Unknown
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Expected O, but got Unknown
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Expected O, but got Unknown
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Expected O, but got Unknown
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Expected O, but got Unknown
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Expected O, but got Unknown
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Expected O, but got Unknown
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Expected O, but got Unknown
			ChatterManager.Instance.chatters.Clear();
			Customer[] array = Object.FindObjectsOfType<Customer>();
			Customer[] array2 = array;
			foreach (Customer val in array2)
			{
				if (int.TryParse(val.NPC.LastName, out var _))
				{
					ChatterData chatterData = new ChatterData();
					chatterData.twitchId = val.NPC.LastName;
					chatterData.displayName = val.NPC.FirstName;
					chatterData.lastEpoch = API.secondsEpochNow();
					chatterData.customer = val;
				}
			}
			Plugin.Instance.properties.Clear();
			Plugin.Instance.properties = new List<Property>
			{
				(Property)new AntiGravity(),
				(Property)new Balding(),
				(Property)new BrightEyed(),
				(Property)new Calming(),
				(Property)new CalorieDense(),
				(Property)new Disorienting(),
				(Property)new Cyclopean(),
				(Property)new Energizing(),
				(Property)new Euphoric(),
				(Property)new Explosive(),
				(Property)new Focused(),
				(Property)new Foggy(),
				(Property)new Gingeritis(),
				(Property)new Glowie(),
				(Property)new Jennerising(),
				(Property)new Laxative(),
				(Property)new Refreshing(),
				(Property)new Schizophrenic(),
				(Property)new Sedating(),
				(Property)new Seizure(),
				(Property)new Slippery(),
				(Property)new Smelly(),
				(Property)new Sneaky(),
				(Property)new Spicy(),
				(Property)new ThoughtProvoking(),
				(Property)new Toxic(),
				(Property)new TropicThunder(),
				(Property)new Zombifying()
			};
		}

		[HarmonyPatch(typeof(NPC), "get_fullName")]
		[HarmonyPrefix]
		public static bool PrefixGetFullName(NPC __instance, ref string __result)
		{
			if (int.TryParse(__instance.LastName, out var _))
			{
				__result = __instance.FirstName;
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(NPC), "get_fullName")]
		[HarmonyPrefix]
		public static void Postfix(NPC __instance, ref string __result)
		{
			if (int.TryParse(__instance.LastName, out var _))
			{
				__result = __instance.FirstName;
			}
		}

		[HarmonyPatch(typeof(NPC), "CreateMessageConversation")]
		[HarmonyPrefix]
		public static bool CreateMessageConversation_prefix(NPC __instance)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			if (int.TryParse(__instance.LastName, out var _))
			{
				__instance.MSGConversation = new MSGConversation(__instance, __instance.FirstName);
				__instance.MSGConversation.SetCategories(__instance.ConversationCategories);
				if (__instance.onConversationCreated != null)
				{
					__instance.onConversationCreated();
				}
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(ContactsDetailPanel), "Open")]
		[HarmonyPostfix]
		public static void contactDetailPanelOpen_postfix(ContactsDetailPanel __instance, NPC npc)
		{
			if (int.TryParse(npc.LastName, out var _) && npc.RelationData.Unlocked)
			{
				__instance.NameLabel.text = npc.FirstName;
			}
		}

		[HarmonyPatch(typeof(Customer), "EvaluateCounteroffer")]
		[HarmonyPostfix]
		public static void EvaluateCounteroffer_postfix(Customer __instance, ref bool __result, ProductDefinition product, int quantity, float price)
		{
			if (int.TryParse(__instance.NPC.LastName, out var _))
			{
				if (pendingOfferResult.ContainsKey(__instance) && pendingOfferResult[__instance] >= 0)
				{
					__result = pendingOfferResult[__instance] > 0;
				}
				pendingOfferResult.Remove(__instance);
			}
		}

		[HarmonyPatch(typeof(Customer), "SendCounteroffer")]
		[HarmonyPrefix]
		public static bool SendCounteroffer_prefix(Customer __instance, ProductDefinition product, int quantity, float price)
		{
			if (!int.TryParse(__instance.NPC.LastName, out var _))
			{
				return true;
			}
			ChatterManager.Instance.SendMessage("@" + __instance.NPC.FirstName + " you got a counter offer !accept or !decline");
			MelonCoroutines.Start(SendCounterofferDelayed(__instance, product, quantity, price));
			return false;
		}

		[IteratorStateMachine(typeof(<SendCounterofferDelayed>d__9))]
		private static IEnumerator SendCounterofferDelayed(Customer __instance, ProductDefinition product, int quantity, float price)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <SendCounterofferDelayed>d__9(0)
			{
				__instance = __instance,
				product = product,
				quantity = quantity,
				price = price
			};
		}

		[HarmonyPatch(typeof(NPCHealth), "Die")]
		[HarmonyPostfix]
		public static void NPCHealthDie_postfix(NPCHealth __instance)
		{
			if (__instance.Invincible && int.TryParse(__instance.npc.LastName, out var _))
			{
				API.timeout(__instance.npc.FirstName, 900);
			}
		}

		[HarmonyPatch(typeof(SlotMachine), "HandleHovered")]
		[HarmonyPrefix]
		public static bool HandleHovered_prefix_free(SlotMachine __instance)
		{
			if (Plugin.Instance.freeSlotSpins <= 0)
			{
				return true;
			}
			if (__instance.IsSpinning)
			{
				__instance.HandleIntObj.SetInteractableState((EInteractableState)2);
				return false;
			}
			__instance.HandleIntObj.SetInteractableState((EInteractableState)0);
			if (Plugin.Instance.freeSlotSpins == 1)
			{
				__instance.HandleIntObj.SetMessage("Free spin from chat");
			}
			else
			{
				__instance.HandleIntObj.SetMessage($"{Plugin.Instance.freeSlotSpins} free spins from chat");
			}
			return false;
		}

		[HarmonyPatch(typeof(SlotMachine), "HandleHovered")]
		[HarmonyPostfix]
		public static void HandleHovered_postfix(SlotMachine __instance)
		{
			long num = API.secondsEpochNow();
			long num2 = Plugin.Instance.betterSlotOddsEnd - num;
			if (num2 > 1)
			{
				__instance.HandleIntObj.message = __instance.HandleIntObj.message + $"\n{num2} seconds of extra luck!";
			}
			else if (num2 == 1)
			{
				__instance.HandleIntObj.message = __instance.HandleIntObj.message + "\n1 second of extra luck!";
			}
		}

		[HarmonyPatch(typeof(SlotMachine), "HandleInteracted")]
		[HarmonyPrefix]
		public static bool HandleInteracted_prefix_free(SlotMachine __instance)
		{
			if (__instance.IsSpinning)
			{
				return false;
			}
			if (Plugin.Instance.freeSlotSpins > 0)
			{
				Plugin.Instance.freeSlotSpins--;
				if (__instance.onHandlePulled != null)
				{
					__instance.onHandlePulled.Invoke();
				}
				__instance.SendStartSpin(((NetworkBehaviour)Player.Local).LocalConnection, __instance.currentBetAmount);
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(SlotMachine), "StartSpin")]
		[HarmonyPrefix]
		public static void StartSpin_prefix(SlotMachine __instance, NetworkConnection spinner, ref ESymbol[] symbols, ref int betAmount)
		{
			long num = API.secondsEpochNow();
			long num2 = Plugin.Instance.betterSlotOddsEnd - num;
			if (num2 <= 0)
			{
				return;
			}
			int num3 = API.symbolsValue(symbols);
			for (int i = 0; i <= 5; i++)
			{
				ESymbol[] array = API.generateSymbols(symbols.Length);
				if (Random.Range(0f, 1f) < 0.1f)
				{
					array = API.generateBetterSymbols(symbols.Length);
				}
				int num4 = API.symbolsValue(array);
				if (num4 > num3)
				{
					num3 = num4;
					for (int j = 0; j < symbols.Length; j++)
					{
						symbols[j] = array[j];
					}
				}
			}
		}

		[HarmonyPatch(typeof(MessagingManager), "ReceiveMessage")]
		[HarmonyPrefix]
		public static bool recieveRPC(MessagingManager __instance, Message m, bool notify, string npcID)
		{
			if (npcID.Contains("chatsrevenge"))
			{
				string text = npcID.Split('#')[1];
				if (text == "all")
				{
					API.handleRPC(m);
				}
				else if (text == "server")
				{
					if (((NetworkBehaviour)__instance).IsHost)
					{
						API.handleRPC(m);
					}
				}
				else if (int.Parse(text) == ((NetworkBehaviour)Player.Local).OwnerId)
				{
					API.handleRPC(m);
				}
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(PoliceOfficer), "CheckNewInvestigation")]
		[HarmonyPrefix]
		public static bool CheckNewInvestigation_prefix(PoliceOfficer __instance)
		{
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Expected O, but got Unknown
			long num = API.secondsEpochNow();
			if (Plugin.Instance.profilingEnd < num)
			{
				return true;
			}
			float num2 = __instance.BodySearchChance * 1.5f + 0.2f;
			float num3 = __instance.Suspicion * 1.5f;
			if (__instance.currentBodySearchInvestigation != null)
			{
				return false;
			}
			if (!__instance.CanInvestigate())
			{
				return false;
			}
			if (num2 <= 0f)
			{
				return false;
			}
			foreach (Player player in Player.PlayerList)
			{
				if (!__instance.CanInvestigatePlayer(player) || !(Vector3.Distance(((NPC)__instance).Avatar.CenterPoint, player.Avatar.CenterPoint) <= 8f))
				{
					continue;
				}
				float playerVisibility = ((NPC)__instance).awareness.VisionCone.GetPlayerVisibility(player);
				if (playerVisibility >= 0.2f)
				{
					float suspiciousness = player.VisualState.Suspiciousness;
					float num4 = Mathf.Lerp(0.2f, 2f, suspiciousness);
					float num5 = Mathf.Lerp(0.4f, 1f, playerVisibility);
					float num6 = Mathf.Lerp(0.5f, 1f, num3);
					float num7 = Mathf.Clamp01(num2 * num4 * num5 * num6 * 1f);
					if (Random.Range(0f, 1f) < num7)
					{
						__instance.currentBodySearchInvestigation = new Investigation(player);
						break;
					}
				}
			}
			return false;
		}

		[HarmonyPatch(typeof(NPCResponses_Civilian), "PlayerFailedPickpocket")]
		[HarmonyPrefix]
		public static bool PlayerFailedPickpocket_prefix(NPCResponses_Civilian __instance, Player player)
		{
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Expected O, but got Unknown
			long num = API.secondsEpochNow();
			if (Plugin.Instance.profilingEnd < num)
			{
				return true;
			}
			((NPCResponses)__instance).PlayerFailedPickpocket(player);
			string line = ((NPCResponses)__instance).npc.dialogueHandler.Database.GetLine((EDialogueModule)2, "noticed_pickpocket");
			((NPCResponses)__instance).npc.dialogueHandler.ShowWorldspaceDialogue(line, 3f);
			((NPCResponses)__instance).npc.Avatar.EmotionManager.AddEmotionOverride("Angry", "noticed_pickpocket", 20f, 3);
			if (((NPCResponses)__instance).npc.Aggression > 0.5f && Random.value < ((NPCResponses)__instance).npc.Aggression)
			{
				((NPCResponses)__instance).npc.behaviour.CombatBehaviour.SetTarget((NetworkConnection)null, ((NetworkBehaviour)player).NetworkObject);
				((Behaviour)((NPCResponses)__instance).npc.behaviour.CombatBehaviour).Enable_Networked((NetworkConnection)null);
				((NPCResponses)__instance).npc.VoiceOverEmitter.Play((EVOLineType)10);
				return false;
			}
			float num2 = Random.value * 1.5f;
			if (num2 > 0.3f && __instance.CanCallPolice)
			{
				((NPCResponses)__instance).actions.SetCallPoliceBehaviourCrime((Crime)new Theft());
				((NPCResponses)__instance).actions.CallPolice_Networked(player);
				((NPCResponses)__instance).npc.PlayVO((EVOLineType)4);
				return false;
			}
			if (num2 > 0.1f)
			{
				((NPCResponses)__instance).npc.PlayVO((EVOLineType)4);
				((NPCResponses)__instance).npc.behaviour.FacePlayerBehaviour.SetTarget(((NetworkBehaviour)player).NetworkObject, 5f);
				((Behaviour)((NPCResponses)__instance).npc.behaviour.FacePlayerBehaviour).SendEnable();
				return false;
			}
			((NPCResponses)__instance).npc.PlayVO((EVOLineType)4);
			((NPCResponses)__instance).npc.behaviour.FleeBehaviour.SetEntityToFlee(((NetworkBehaviour)player).NetworkObject);
			((Behaviour)((NPCResponses)__instance).npc.behaviour.FleeBehaviour).Enable_Networked((NetworkConnection)null);
			return false;
		}

		[HarmonyPatch(typeof(NPCResponses_Civilian), "RespondToLethalOrRepeatedAttack")]
		[HarmonyPrefix]
		public static bool RespondToLethalOrRepeatedAttack_prefix(NPCResponses_Civilian __instance, Player perpetrator, Impact impact)
		{
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Expected O, but got Unknown
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Expected O, but got Unknown
			long num = API.secondsEpochNow();
			if (Plugin.Instance.profilingEnd < num)
			{
				return true;
			}
			float num2 = Random.value * 1.5f;
			float num3 = ((NPCResponses)__instance).npc.Aggression * 1.2f;
			if (num3 > 0.5f && num2 < num3)
			{
				((NPCResponses)__instance).npc.behaviour.CombatBehaviour.SetTarget((NetworkConnection)null, ((NetworkBehaviour)perpetrator).NetworkObject);
				((Behaviour)((NPCResponses)__instance).npc.behaviour.CombatBehaviour).Enable_Networked((NetworkConnection)null);
				((NPCResponses)__instance).npc.VoiceOverEmitter.Play((EVOLineType)10);
				return false;
			}
			if (num2 > 0.5f && __instance.CanCallPolice)
			{
				if (Impact.IsLethal(impact.ImpactType))
				{
					((NPCResponses)__instance).actions.SetCallPoliceBehaviourCrime((Crime)new DeadlyAssault());
				}
				else
				{
					((NPCResponses)__instance).actions.SetCallPoliceBehaviourCrime((Crime)new Assault());
				}
				((NPCResponses)__instance).actions.CallPolice_Networked(perpetrator);
				return false;
			}
			((NPCResponses)__instance).npc.SetPanicked();
			((NPCResponses)__instance).npc.dialogueHandler.PlayReaction("panic_start", 3f, false);
			if (num2 > 0.2f)
			{
				((NPCResponses)__instance).npc.behaviour.FleeBehaviour.SetEntityToFlee(((NetworkBehaviour)perpetrator).NetworkObject);
				((Behaviour)((NPCResponses)__instance).npc.behaviour.FleeBehaviour).Enable_Networked((NetworkConnection)null);
			}
			return false;
		}

		[HarmonyPatch(typeof(Customer), "DirectApproachRejected")]
		[HarmonyPrefix]
		public static bool DirectApproachRejected_postfix(Customer __instance)
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Expected O, but got Unknown
			long num = API.secondsEpochNow();
			if (Plugin.Instance.profilingEnd < num)
			{
				return true;
			}
			float num2 = __instance.customerData.CallPoliceChance * 1.3f;
			if (Random.Range(0f, 1f) <= num2)
			{
				__instance.NPC.PlayVO((EVOLineType)10);
				__instance.NPC.dialogueHandler.ShowWorldspaceDialogue(__instance.dialogueDatabase.GetLine((EDialogueModule)3, "sample_offer_rejected_police"), 5f);
				__instance.NPC.actions.SetCallPoliceBehaviourCrime((Crime)new AttemptingToSell());
				__instance.NPC.actions.CallPolice_Networked(Player.Local);
				return false;
			}
			__instance.NPC.PlayVO((EVOLineType)9);
			__instance.NPC.dialogueHandler.ShowWorldspaceDialogue(__instance.dialogueDatabase.GetLine((EDialogueModule)3, "sample_offer_rejected"), 5f);
			return false;
		}
	}
}