Decompiled source of VoiceCurseZh v1.1.0

plugins/com.github.jie65535.VoiceCurse.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
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 System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using Photon.Voice;
using Photon.Voice.PUN;
using Photon.Voice.Unity;
using UnityEngine;
using VoiceCurse.Events;
using VoiceCurse.Handlers;
using VoiceCurse.Interfaces;
using VoiceCurse.Voice;
using Vosk;

[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.jie65535.VoiceCurse")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0+d782a3491609b85ef23bb070dcbc3738bd7cc45a")]
[assembly: AssemblyProduct("com.github.jie65535.VoiceCurse")]
[assembly: AssemblyTitle("VoiceCurse")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.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.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 VoiceCurse
{
	public class Config
	{
		public ConfigEntry<bool> EnableDebugLogs { get; private set; }

		public ConfigEntry<float> GlobalCooldown { get; private set; }

		public ConfigEntry<bool> LaunchEnabled { get; private set; }

		public ConfigEntry<string> LaunchKeywords { get; private set; }

		public ConfigEntry<float> LaunchStunDuration { get; private set; }

		public ConfigEntry<float> LaunchForceLowerBound { get; private set; }

		public ConfigEntry<float> LaunchForceHigherBound { get; private set; }

		public ConfigEntry<bool> AfflictionEnabled { get; private set; }

		public ConfigEntry<float> AfflictionMinPercent { get; private set; }

		public ConfigEntry<float> AfflictionMaxPercent { get; private set; }

		public ConfigEntry<bool> AfflictionTemperatureSwapEnabled { get; private set; }

		public ConfigEntry<string> AfflictionKeywordsInjury { get; private set; }

		public ConfigEntry<string> AfflictionKeywordsHunger { get; private set; }

		public ConfigEntry<string> AfflictionKeywordsCold { get; private set; }

		public ConfigEntry<string> AfflictionKeywordsHot { get; private set; }

		public ConfigEntry<string> AfflictionKeywordsPoison { get; private set; }

		public ConfigEntry<string> AfflictionKeywordsSpores { get; private set; }

		public ConfigEntry<bool> TransmuteEnabled { get; private set; }

		public ConfigEntry<bool> TransmuteDeathEnabled { get; private set; }

		public ConfigEntry<bool> TransmuteMilkEnabled { get; private set; }

		public ConfigEntry<bool> TransmuteCactusEnabled { get; private set; }

		public ConfigEntry<bool> TransmuteCoconutEnabled { get; private set; }

		public ConfigEntry<bool> TransmuteAppleEnabled { get; private set; }

		public ConfigEntry<bool> TransmuteBananaEnabled { get; private set; }

		public ConfigEntry<bool> TransmuteEggEnabled { get; private set; }

		public ConfigEntry<bool> TransmuteFruitEnabled { get; private set; }

		public ConfigEntry<bool> TransmuteMushroomEnabled { get; private set; }

		public ConfigEntry<bool> TransmuteBallEnabled { get; private set; }

		public ConfigEntry<bool> DeathEnabled { get; private set; }

		public ConfigEntry<string> DeathKeywords { get; private set; }

		public ConfigEntry<bool> ZombifyEnabled { get; private set; }

		public ConfigEntry<string> ZombifyKeywords { get; private set; }

		public ConfigEntry<bool> SleepEnabled { get; private set; }

		public ConfigEntry<string> SleepKeywords { get; private set; }

		public ConfigEntry<bool> DropEnabled { get; private set; }

		public ConfigEntry<string> DropKeywords { get; private set; }

		public ConfigEntry<bool> ExplodeEnabled { get; private set; }

		public ConfigEntry<string> ExplodeKeywords { get; private set; }

		public ConfigEntry<float> ExplodeRadius { get; private set; }

		public ConfigEntry<float> ExplodeDamage { get; private set; }

		public ConfigEntry<float> ExplodeStunDuration { get; private set; }

		public ConfigEntry<float> ExplodeForceLowerBound { get; private set; }

		public ConfigEntry<float> ExplodeForceHigherBound { get; private set; }

		public ConfigEntry<bool> SlipEnabled { get; private set; }

		public ConfigEntry<string> SlipKeywords { get; private set; }

		public ConfigEntry<float> SlipStunDuration { get; private set; }

		public ConfigEntry<bool> BananaBombEnabled { get; private set; }

		public ConfigEntry<float> BananaBombChance { get; private set; }

		public ConfigEntry<int> BananaBombAmount { get; private set; }

		public ConfigEntry<bool> SacrificeEnabled { get; private set; }

		public ConfigEntry<string> SacrificeKeywords { get; private set; }

		public ConfigEntry<float> SacrificeCooldown { get; private set; }

		public ConfigEntry<bool> BlindEnabled { get; private set; }

		public ConfigEntry<string> BlindKeywords { get; private set; }

		public ConfigEntry<float> BlindDuration { get; private set; }

		public Config(ConfigFile config)
		{
			EnableDebugLogs = config.Bind<bool>("Global", "EnableDebugLogs", true, "启用语音识别的调试日志。");
			GlobalCooldown = config.Bind<float>("Global", "GlobalCooldown", 2f, "在另一个语音事件可以被触发之前必须经过的时间(以秒为单位)。");
			LaunchEnabled = config.Bind<bool>("Event.Launch", "Enabled", true, "启用发射事件。");
			LaunchKeywords = config.Bind<string>("Event.Launch", "Keywords", "发射,飞,升空,火箭,弹射,推进,弹跳,喷射,弹起,左,右,前,后,上,下,冲天,蹦极,弹簧,投掷,抛射,加速,猛冲,升天,弹射器,导弹,太空,轨道", "触发发射事件的关键字列表,用逗号分隔。");
			LaunchForceLowerBound = config.Bind<float>("Event.Launch", "ForceLowerBound", 1500f, "发射时施加给玩家的最低力值。");
			LaunchForceHigherBound = config.Bind<float>("Event.Launch", "ForceHigherBound", 3000f, "发射时施加给玩家的最高力值。");
			LaunchStunDuration = config.Bind<float>("Event.Launch", "StunDuration", 3f, "发射后玩家被眩晕/物理击倒的持续时间(以秒为单位)。");
			AfflictionEnabled = config.Bind<bool>("Event.Affliction", "Enabled", true, "启用负面状态事件。");
			AfflictionMinPercent = config.Bind<float>("Event.Affliction", "MinPercent", 0.2f, "触发时状态条填充的最小百分比 (0.0 到 1.0)。");
			AfflictionMaxPercent = config.Bind<float>("Event.Affliction", "MaxPercent", 0.6f, "触发时状态条填充的最大百分比 (0.0 到 1.0)。");
			AfflictionTemperatureSwapEnabled = config.Bind<bool>("Event.Affliction", "TemperatureSwapEnabled", true, "如果启用,尝试通过说出相反的词来摆脱热或冷状态,只会将现有效果切换到新的,并在顶部叠加,以防止滥用。");
			AfflictionKeywordsInjury = config.Bind<string>("Event.Affliction", "KeywordsInjury", "受伤,伤害,疼痛,创伤,流血,骨折,扭伤,割伤,淤青,伤口,刺痛,酸痛,痛楚,内伤,外伤,重伤,轻伤,伤痛,痛感,橙色", "触发物理伤害的关键字。");
			AfflictionKeywordsHunger = config.Bind<string>("Event.Affliction", "KeywordsHunger", "饿,饥渴,吃饭,食物,进食,食欲,想吃,黄色,营养,进食,用餐,零食,大餐,喂食", "触发饥饿状态的关键字。");
			AfflictionKeywordsCold = config.Bind<string>("Event.Affliction", "KeywordsCold", "寒冷,冷,冰冻,冰凉,结冰,霜冻,发抖,哆嗦,打颤,寒颤,刺骨,降温,冰雪,冰川,冰柱,低温,冻僵,蓝色,北极,极地", "触发寒冷状态的关键字。");
			AfflictionKeywordsHot = config.Bind<string>("Event.Affliction", "KeywordsHot", "热,火烧,火烤,烫,火焰,夏天,红色,地狱,灼烧,沸腾,烘烤,炙烤,烈火,燃烧,点燃", "触发炎热状态的关键字。");
			AfflictionKeywordsPoison = config.Bind<string>("Event.Affliction", "KeywordsPoison", "中毒,毒药,毒素,毒液,恶心,想吐,呕吐,头晕,晕眩,不适,难受,污染,感染,疾病,生病,病症,病毒,紫色,病态,疾患", "触发中毒状态的关键字。");
			AfflictionKeywordsSpores = config.Bind<string>("Event.Affliction", "KeywordsSpores", "孢子,真菌,霉菌,菌类,粉红,粉色,发霉,霉变", "触发孢子状态的关键字。");
			TransmuteEnabled = config.Bind<bool>("Event.Transmute", "Enabled", true, "启用转换事件。");
			TransmuteDeathEnabled = config.Bind<bool>("Event.Transmute", "EnableDeath", false, "启用转换触发时的即时死亡(使用你的身体作为转换材料)。如果禁用,你只会受到伤害(你的身体部分转换)。");
			TransmuteMilkEnabled = config.Bind<bool>("Event.Transmute", "EnableMilk", true, "启用 'milk/calcium/奶/钙' -> 奶白金");
			TransmuteCactusEnabled = config.Bind<bool>("Event.Transmute", "EnableCactus", true, "启用 'cactus/仙人掌' -> 仙人球");
			TransmuteCoconutEnabled = config.Bind<bool>("Event.Transmute", "EnableCoconut", true, "启用 'coconut/椰子' -> 椰子");
			TransmuteAppleEnabled = config.Bind<bool>("Event.Transmute", "EnableApple", true, "启用 'apple/berry/苹果/浆果' -> 脆莓");
			TransmuteBananaEnabled = config.Bind<bool>("Event.Transmute", "EnableBanana", true, "启用 'banana/香蕉' -> 莓蕉皮");
			TransmuteEggEnabled = config.Bind<bool>("Event.Transmute", "EnableEgg", true, "启用 'egg/鸡蛋' -> 煎蛋");
			TransmuteFruitEnabled = config.Bind<bool>("Event.Transmute", "EnableFruit", true, "启用 'fruit/水果' -> 随机水果");
			TransmuteMushroomEnabled = config.Bind<bool>("Event.Transmute", "EnableMushroom", true, "启用 'mushroom/fungus/蘑菇/真菌' -> 蘑菇");
			TransmuteBallEnabled = config.Bind<bool>("Event.Transmute", "EnableBall", true, "启用 'ball/球' -> 篮球");
			DeathEnabled = config.Bind<bool>("Event.Death", "Enabled", false, "启用死亡事件。");
			DeathKeywords = config.Bind<string>("Event.Death", "Keywords", "死亡,去世,毙命,自杀,杀死,骷髅,骨头,尸体,棺材,坟墓,安息,永别,完蛋,嗝屁,牺牲,阵亡,挂了,断气,升天,投胎,终结,末日,死神,坟墓,墓穴,葬送,毁灭,消除,终结", "触发死亡事件的关键字列表,用逗号分隔。");
			ZombifyEnabled = config.Bind<bool>("Event.Zombify", "Enabled", true, "启用僵尸化事件。");
			ZombifyKeywords = config.Bind<string>("Event.Zombify", "Keywords", "僵尸,丧尸,感染,病毒,瘟疫,行尸,咬,脑子,腐烂,变异,不死,末日,生化,尸变,感染者,丧尸化,僵尸化,行尸走肉,活死人,亡灵,丧尸病毒,爆发,食人,血肉", "触发僵尸化事件的关键字列表,用逗号分隔。");
			SleepEnabled = config.Bind<bool>("Event.Sleep", "Enabled", true, "启用睡眠事件。");
			SleepKeywords = config.Bind<string>("Event.Sleep", "Keywords", "睡觉,睡眠,疲惫,疲倦,打盹,小睡,休息,昏迷,昏倒,做梦,床,晚安,睡意,困倦,打瞌睡,昏睡,沉睡,熟睡,打哈欠,眼皮重,想睡,睡一觉,眯一会,躺平,打瞌睡,午睡,打盹儿", "触发睡眠事件的关键字列表,用逗号分隔。");
			DropEnabled = config.Bind<bool>("Event.Drop", "Enabled", true, "启用掉落事件。");
			DropKeywords = config.Bind<string>("Event.Drop", "Keywords", "掉落,丢下,扔掉,失手,滑落,放手,放弃,丢失,手滑,没拿住,掉了,落下了,忘拿了,不见了,失踪,抛弃,丢弃,脱手,撒手,失物,遗失", "触发掉落事件的关键字列表,用逗号分隔。");
			ExplodeEnabled = config.Bind<bool>("Event.Explode", "Enabled", true, "启用爆炸事件。");
			ExplodeKeywords = config.Bind<string>("Event.Explode", "Keywords", "爆炸,引爆,炸弹,炸药,爆破,爆裂,核弹,手榴弹,地雷,自爆,炸裂,boom,爆破,引爆,爆炸物,炸开,炸成灰,炸成碎片", "触发爆炸事件的关键字列表,用逗号分隔。");
			ExplodeRadius = config.Bind<float>("Event.Explode", "Radius", 6f, "爆炸效果和伤害的半径。");
			ExplodeDamage = config.Bind<float>("Event.Explode", "DamagePercent", 0.4f, "施加给玩家的伤害百分比 (0.0 到 1.0)。");
			ExplodeStunDuration = config.Bind<float>("Event.Explode", "StunDuration", 3f, "爆炸后玩家被眩晕/物理击倒的持续时间(以秒为单位)。");
			ExplodeForceLowerBound = config.Bind<float>("Event.Explode", "ForceLowerBound", 2000f, "施加的最低爆炸力值。");
			ExplodeForceHigherBound = config.Bind<float>("Event.Explode", "ForceHigherBound", 3000f, "施加的最高爆炸力值。");
			SlipEnabled = config.Bind<bool>("Event.Slip", "Enabled", true, "启用滑倒事件。");
			SlipKeywords = config.Bind<string>("Event.Slip", "Keywords", "甲沟炎,滑倒,摔倒,绊倒,跌倒,摔跤,失足,溜滑,扑街,摔个狗吃屎,四脚朝天,人仰马翻,失衡,不稳,倾斜,打滑,滑行,绊脚,跌跤", "触发滑倒事件的关键字列表,用逗号分隔。");
			SlipStunDuration = config.Bind<float>("Event.Slip", "StunDuration", 2f, "滑倒后玩家被眩晕/物理击倒的持续时间(以秒为单位)。");
			BananaBombEnabled = config.Bind<bool>("Event.Slip", "BananaBombEnabled", true, "启用罕见的香蕉炸弹彩蛋。");
			BananaBombChance = config.Bind<float>("Event.Slip", "BananaBombChance", 0.05f, "滑倒时触发香蕉炸弹的几率 (0.0 - 1.0)。");
			BananaBombAmount = config.Bind<int>("Event.Slip", "BananaBombAmount", 30, "香蕉炸弹生成的香蕉数量。");
			SacrificeEnabled = config.Bind<bool>("Event.Sacrifice", "Enabled", true, "启用献祭事件。");
			SacrificeKeywords = config.Bind<string>("Event.Sacrifice", "Keywords", "献祭,交易,复活,重生,牺牲,救赎,召唤,归来,复苏,穿越,请神", "触发献祭事件的关键字列表,用逗号分隔。");
			SacrificeCooldown = config.Bind<float>("Event.Sacrifice", "Cooldown", 300f, "献祭事件的冷却时间(秒)。");
			BlindEnabled = config.Bind<bool>("Event.Blind", "Enabled", true, "启用致盲事件。");
			BlindKeywords = config.Bind<string>("Event.Blind", "Keywords", "致盲,闪光,眼睛,眼瞎,视力,看不见,失明,眼花,瞎了", "触发致盲事件的关键字列表,用逗号分隔。");
			BlindDuration = config.Bind<float>("Event.Blind", "Duration", 15f, "玩家致盲的持续时间(秒)。");
		}
	}
	[BepInPlugin("com.github.jie65535.VoiceCurse", "VoiceCurse", "1.1.0")]
	public class Plugin : BaseUnityPlugin
	{
		private Config? _config;

		private VoiceHandler? _voiceHandler;

		private Harmony? _harmony;

		public const string Id = "com.github.jie65535.VoiceCurse";

		private static ManualLogSource Log { get; set; }

		public static string Name => "VoiceCurse";

		public static string Version => "1.1.0";

		private void Awake()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Log.LogInfo((object)("Plugin " + Name + " is loading..."));
			_config = new Config(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("com.github.jie65535.VoiceCurse");
			_harmony.PatchAll();
			Log.LogInfo((object)"Harmony Patches applied.");
			string text = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
			if (string.IsNullOrEmpty(text))
			{
				text = Paths.PluginPath;
			}
			_voiceHandler = new VoiceHandler(Log, _config, text);
			Log.LogInfo((object)("Plugin " + Name + " loaded successfully."));
		}

		private void Update()
		{
			_voiceHandler?.Update();
		}

		private void OnDestroy()
		{
			_voiceHandler?.Dispose();
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
}
namespace VoiceCurse.Voice
{
	public class VoiceHook : MonoBehaviour
	{
		private VoiceHandler? _manager;

		private Recorder? _recorder;

		private bool _hasInjected;

		public void Initialize(VoiceHandler manager, Recorder recorder)
		{
			_manager = manager;
			_recorder = recorder;
			CheckIfReady();
		}

		private void Update()
		{
			if (!_hasInjected)
			{
				CheckIfReady();
			}
		}

		private void CheckIfReady()
		{
			if (!Object.op_Implicit((Object)(object)_recorder) || _manager == null || !_recorder.IsCurrentlyTransmitting)
			{
				return;
			}
			FieldInfo field = typeof(Recorder).GetField("voice", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (!(field == null))
			{
				object? value = field.GetValue(_recorder);
				LocalVoice val = (LocalVoice)((value is LocalVoice) ? value : null);
				if (val != null)
				{
					_manager.OnPhotonVoiceReady(_recorder, val);
					_hasInjected = true;
				}
			}
		}

		private void PhotonVoiceCreated(PhotonVoiceCreatedParams p)
		{
			if (!_hasInjected && !((Object)(object)_recorder == (Object)null))
			{
				_manager?.OnPhotonVoiceReady(_recorder, p.Voice);
				_hasInjected = true;
			}
		}
	}
	public class VoiceProcessor : IProcessor<float>, IDisposable
	{
		[CompilerGenerated]
		private IVoiceRecognizer <recognizer>P;

		[CompilerGenerated]
		private int <inputSampleRate>P;

		private const int TargetSampleRate = 16000;

		public VoiceProcessor(IVoiceRecognizer recognizer, int inputSampleRate)
		{
			<recognizer>P = recognizer;
			<inputSampleRate>P = inputSampleRate;
			base..ctor();
		}

		public float[]? Process(float[]? buf)
		{
			if (buf == null || buf.Length == 0)
			{
				return buf;
			}
			if (Math.Abs(<inputSampleRate>P - 16000) < 100)
			{
				ProcessDirect(buf);
				return buf;
			}
			float num = (float)<inputSampleRate>P / 16000f;
			int num2 = (int)((float)buf.Length / num);
			if (num2 == 0)
			{
				return buf;
			}
			short[] array = new short[num2];
			for (int i = 0; i < num2; i++)
			{
				float num3 = (float)i * num;
				int num4 = (int)num3;
				float num5 = num3 - (float)num4;
				if (num4 >= buf.Length - 1)
				{
					array[i] = FloatToShort(buf[^1]);
					continue;
				}
				float num6 = buf[num4];
				float num7 = buf[num4 + 1];
				float sample = num6 + (num7 - num6) * num5;
				array[i] = FloatToShort(sample);
			}
			<recognizer>P.FeedAudio(array, array.Length);
			return buf;
		}

		private void ProcessDirect(float[] buf)
		{
			short[] array = new short[buf.Length];
			for (int i = 0; i < buf.Length; i++)
			{
				array[i] = FloatToShort(buf[i]);
			}
			<recognizer>P.FeedAudio(array, array.Length);
		}

		private static short FloatToShort(float sample)
		{
			float num = ((sample > 1f) ? 1f : ((!(sample < -1f)) ? sample : (-1f)));
			sample = num;
			return (short)(sample * 32767f);
		}

		public void Dispose()
		{
		}
	}
	public class VoiceRecognizer : IVoiceRecognizer, IDisposable
	{
		private readonly VoskRecognizer _recognizer;

		private readonly ConcurrentQueue<short[]> _audioQueue = new ConcurrentQueue<short[]>();

		private Thread? _workerThread;

		private volatile bool _isRunning;

		private const int MaxQueueSize = 50;

		public event Action<string>? OnPhraseRecognized;

		public event Action<string>? OnPartialResult;

		public VoiceRecognizer(Model model, float sampleRate)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			try
			{
				_recognizer = new VoskRecognizer(model, sampleRate);
				_recognizer.SetMaxAlternatives(0);
				_recognizer.SetWords(true);
				Debug.Log((object)$"[VoiceCurse] Initialized VoskRecognizer with Rate: {sampleRate} Hz");
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("Failed to create VoskRecognizer: " + ex.Message));
				throw;
			}
		}

		public void Start()
		{
			if (!_isRunning)
			{
				_isRunning = true;
				_workerThread = new Thread(ProcessAudioLoop)
				{
					IsBackground = true,
					Name = "VoiceCurse Worker"
				};
				_workerThread.Start();
			}
		}

		public void Stop()
		{
			_isRunning = false;
			Thread workerThread = _workerThread;
			if (workerThread != null && workerThread.IsAlive)
			{
				_workerThread.Join(500);
			}
		}

		public void FeedAudio(short[] pcmData, int length)
		{
			if (!_isRunning)
			{
				return;
			}
			if (_audioQueue.Count >= 50)
			{
				short[] result;
				while (_audioQueue.TryDequeue(out result))
				{
				}
			}
			_audioQueue.Enqueue(pcmData);
		}

		private void ProcessAudioLoop()
		{
			while (_isRunning)
			{
				if (_audioQueue.TryDequeue(out short[] result))
				{
					try
					{
						if (_recognizer.AcceptWaveform(result, result.Length))
						{
							string json = _recognizer.Result();
							ExtractAndFire(json, isPartial: false);
						}
						else
						{
							string json2 = _recognizer.PartialResult();
							ExtractAndFire(json2, isPartial: true);
						}
					}
					catch (Exception ex)
					{
						Debug.LogError((object)("[VoiceCurse] Vosk Error: " + ex.Message));
					}
				}
				else
				{
					Thread.Sleep(10);
				}
			}
		}

		private void ExtractAndFire(string json, bool isPartial)
		{
			if (string.IsNullOrEmpty(json))
			{
				return;
			}
			string text = (isPartial ? "\"partial\"" : "\"text\"");
			int num = json.IndexOf(text + " :", StringComparison.Ordinal);
			if (num == -1)
			{
				num = json.IndexOf(text + ":", StringComparison.Ordinal);
			}
			if (num == -1)
			{
				return;
			}
			int num2 = json.IndexOf("\"", num + text.Length + 1, StringComparison.Ordinal) + 1;
			int num3 = json.LastIndexOf("\"", StringComparison.Ordinal);
			if (num3 <= num2)
			{
				return;
			}
			string text2 = json.Substring(num2, num3 - num2);
			if (!string.IsNullOrWhiteSpace(text2))
			{
				if (isPartial)
				{
					this.OnPartialResult?.Invoke(text2);
				}
				else
				{
					this.OnPhraseRecognized?.Invoke(text2);
				}
			}
		}

		public void Dispose()
		{
			Stop();
			_recognizer.Dispose();
		}
	}
}
namespace VoiceCurse.Interfaces
{
	public interface IVoiceEvent
	{
		bool TryExecute(string spokenWord, string fullSentence);

		void PlayEffects(Vector3 position);

		void PlayEffects(Character origin, Vector3 position, string detail);
	}
	public interface IVoiceRecognizer : IDisposable
	{
		event Action<string> OnPhraseRecognized;

		event Action<string> OnPartialResult;

		void FeedAudio(short[] pcmData, int length);

		void Start();

		void Stop();
	}
}
namespace VoiceCurse.Handlers
{
	public class EventHandler
	{
		public static readonly Dictionary<string, IVoiceEvent> Events = new Dictionary<string, IVoiceEvent>();

		private readonly Dictionary<string, int> _previousWordCounts = new Dictionary<string, int>();

		public EventHandler(Config config)
		{
			Events.Clear();
			RegisterEvents(config);
		}

		private static void RegisterEvents(Config config)
		{
			IEnumerable<Type> enumerable = from t in Assembly.GetExecutingAssembly().GetTypes()
				where typeof(VoiceEventBase).IsAssignableFrom(t) && !t.IsAbstract && t.IsClass
				select t;
			foreach (Type item in enumerable)
			{
				try
				{
					if (Activator.CreateInstance(item, config) is IVoiceEvent value)
					{
						string text = item.Name.Replace("Event", "");
						Events[text] = value;
						if (config.EnableDebugLogs.Value)
						{
							Debug.Log((object)("[VoiceCurse] Registered event: " + text));
						}
					}
				}
				catch (Exception ex)
				{
					Debug.LogError((object)("[VoiceCurse] Failed to register event " + item.Name + ": " + ex.Message));
				}
			}
		}

		public void HandleSpeech(string text, bool isFinal)
		{
			if (string.IsNullOrWhiteSpace(text))
			{
				return;
			}
			string text2 = text.ToLowerInvariant();
			string[] array = text2.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
			Dictionary<string, int> dictionary = new Dictionary<string, int>();
			string[] array2 = array;
			string key;
			int value;
			foreach (string text3 in array2)
			{
				dictionary.TryAdd(text3, 0);
				key = text3;
				value = dictionary[key]++;
			}
			foreach (KeyValuePair<string, int> item in dictionary)
			{
				item.Deconstruct(out key, out value);
				string text4 = key;
				int num = value;
				int num2 = 0;
				if (_previousWordCounts.TryGetValue(text4, out var value2))
				{
					num2 = value2;
				}
				int num3 = num - num2;
				if (num3 <= 0)
				{
					continue;
				}
				for (int j = 0; j < num3; j++)
				{
					foreach (IVoiceEvent value3 in Events.Values)
					{
						value3.TryExecute(text4, text2);
					}
				}
			}
			_previousWordCounts.Clear();
			foreach (KeyValuePair<string, int> item2 in dictionary)
			{
				_previousWordCounts[item2.Key] = item2.Value;
			}
			if (isFinal)
			{
				_previousWordCounts.Clear();
			}
		}
	}
	public class NetworkHandler : IOnEventCallback
	{
		private const byte VoiceCurseEventCode = 187;

		private static MonoBehaviour? _connectionLog;

		private static MethodInfo? _addMessageMethod;

		public static void SendCurseEvent(string spokenWord, string matchedKeyword, string eventName, string? detail, string? payload, Vector3 position)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//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)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			object[] array = new object[7]
			{
				PhotonNetwork.LocalPlayer.ActorNumber,
				spokenWord,
				matchedKeyword,
				eventName,
				detail ?? string.Empty,
				position,
				payload ?? string.Empty
			};
			RaiseEventOptions val = new RaiseEventOptions
			{
				Receivers = (ReceiverGroup)1
			};
			SendOptions val2 = default(SendOptions);
			((SendOptions)(ref val2)).Reliability = true;
			SendOptions val3 = val2;
			PhotonNetwork.RaiseEvent((byte)187, (object)array, val, val3);
		}

		public void OnEvent(EventData photonEvent)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: 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_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			if (photonEvent.Code != 187)
			{
				return;
			}
			object[] array = (object[])photonEvent.CustomData;
			int num = (int)array[0];
			string fullWord = (string)array[1];
			string keyword = (string)array[2];
			string text = (string)array[3];
			string text2 = (string)array[4];
			Vector3 position = (Vector3)array[5];
			string text3 = ((array.Length > 6) ? ((string)array[6]) : string.Empty);
			string playerName = "Unknown";
			Color color = Color.white;
			Player player = PhotonNetwork.CurrentRoom.GetPlayer(num, false);
			if (player != null)
			{
				playerName = player.NickName;
			}
			Character val = FindCharacterByActorNumber(num);
			if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.refs?.customization))
			{
				color = val.refs.customization.PlayerColor;
			}
			DisplayNotification(playerName, color, fullWord, keyword, text, text2);
			if (EventHandler.Events.TryGetValue(text, out IVoiceEvent value))
			{
				if (Object.op_Implicit((Object)(object)val))
				{
					string detail = ((!string.IsNullOrEmpty(text3)) ? text3 : text2);
					value.PlayEffects(val, position, detail);
				}
				else
				{
					value.PlayEffects(position);
				}
			}
		}

		private static Character? FindCharacterByActorNumber(int actorNumber)
		{
			return ((IEnumerable<Character>)Character.AllCharacters).FirstOrDefault((Func<Character, bool>)((Character c) => ((MonoBehaviourPun)c).photonView.OwnerActorNr == actorNumber));
		}

		private static void DisplayNotification(string playerName, Color color, string fullWord, string keyword, string eventName, string detail)
		{
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)_connectionLog))
			{
				Object obj = Object.FindFirstObjectByType(Type.GetType("PlayerConnectionLog, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"));
				_connectionLog = (MonoBehaviour?)(((object)((obj is MonoBehaviour) ? obj : null)) ?? ((object)((IEnumerable<MonoBehaviour>)Object.FindObjectsByType<MonoBehaviour>((FindObjectsSortMode)0)).FirstOrDefault((Func<MonoBehaviour, bool>)((MonoBehaviour m) => ((object)m).GetType().Name == "PlayerConnectionLog"))));
				_addMessageMethod = null;
			}
			if (!Object.op_Implicit((Object)(object)_connectionLog))
			{
				return;
			}
			if (_addMessageMethod == null)
			{
				_addMessageMethod = ((object)_connectionLog).GetType().GetMethod("AddMessage", BindingFlags.Instance | BindingFlags.NonPublic);
			}
			if (_addMessageMethod == null)
			{
				return;
			}
			string text = "#" + ColorUtility.ToHtmlStringRGB(color);
			string text2 = fullWord;
			int num = fullWord.IndexOf(keyword, StringComparison.OrdinalIgnoreCase);
			if (num >= 0)
			{
				string text3 = fullWord.Substring(0, num);
				string text4 = fullWord.Substring(num, keyword.Length);
				int num2 = num + keyword.Length;
				string text5 = fullWord.Substring(num2, fullWord.Length - num2);
				text2 = text3 + "<color=#8B0000>" + text4 + "</color>" + text5;
			}
			string text6 = "<color=" + text + ">" + playerName + " 说了 \"" + text2 + "\" 触发了 </color><color=#FFA500>" + eventName + "</color><color=#FAFA33>" + (string.IsNullOrEmpty(detail) ? "" : (" (" + detail + ")")) + "</color>";
			try
			{
				_addMessageMethod.Invoke(_connectionLog, new object[1] { text6 });
			}
			catch
			{
				_connectionLog = null;
			}
		}
	}
	public class VoiceHandler : IDisposable
	{
		private readonly ManualLogSource _log;

		private readonly Config _config;

		private IVoiceRecognizer? _recognizer;

		private EventHandler? _eventHandler;

		private NetworkHandler? _networker;

		private Model? _voskModel;

		private VoiceHook? _activeHook;

		private readonly ConcurrentQueue<Action> _mainThreadActions = new ConcurrentQueue<Action>();

		private volatile string _lastPartialText = "";

		[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
		private static extern bool SetDllDirectory(string lpPathName);

		public VoiceHandler(ManualLogSource logger, Config config, string pluginDir)
		{
			_log = logger;
			_config = config;
			Initialize(pluginDir);
		}

		private void Initialize(string pluginDir)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			_log.LogInfo((object)"Initializing VoiceCurse Manager...");
			if (Directory.Exists(pluginDir))
			{
				SetDllDirectory(pluginDir);
			}
			_eventHandler = new EventHandler(_config);
			_networker = new NetworkHandler();
			PhotonNetwork.AddCallbackTarget((object)_networker);
			string text = Path.Combine(pluginDir, "model-zh-cn");
			if (Directory.Exists(text))
			{
				try
				{
					_voskModel = new Model(text);
					_log.LogInfo((object)"Vosk Model loaded successfully.");
					return;
				}
				catch (Exception ex)
				{
					_log.LogError((object)("Failed to load Vosk Model: " + ex.Message));
					return;
				}
			}
			_log.LogError((object)("Vosk model not found at: " + text));
		}

		public void Update()
		{
			Action result;
			while (_mainThreadActions.TryDequeue(out result))
			{
				result();
			}
			if (!Object.op_Implicit((Object)(object)_activeHook) && Object.op_Implicit((Object)(object)Character.localCharacter))
			{
				TryHookIntoPhotonVoice();
			}
		}

		private void TryHookIntoPhotonVoice()
		{
			PhotonVoiceView component = ((Component)Character.localCharacter).GetComponent<PhotonVoiceView>();
			if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.RecorderInUse))
			{
				Recorder recorderInUse = component.RecorderInUse;
				VoiceHook voiceHook = ((Component)recorderInUse).gameObject.AddComponent<VoiceHook>();
				voiceHook.Initialize(this, recorderInUse);
				_activeHook = voiceHook;
				_log.LogInfo((object)("[VoiceCurse] Hooked into Recorder on: " + ((Object)((Component)recorderInUse).gameObject).name));
			}
		}

		public void OnPhotonVoiceReady(Recorder recorder, LocalVoice voice)
		{
			//IL_0007: 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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			int num = 48000;
			VoiceInfo info = voice.Info;
			if (((VoiceInfo)(ref info)).SamplingRate > 0)
			{
				info = voice.Info;
				num = ((VoiceInfo)(ref info)).SamplingRate;
			}
			_log.LogInfo((object)$"[VoiceCurse] Photon Input Rate: {num} Hz. Initializing Vosk at 16000 Hz.");
			SetupVoiceRecognition();
			if (_recognizer is VoiceRecognizer && voice is LocalVoiceAudio<float> val)
			{
				((LocalVoiceFramed<float>)(object)val).AddPostProcessor(new IProcessor<float>[1]
				{
					new VoiceProcessor(_recognizer, num)
				});
				_log.LogInfo((object)$"[VoiceCurse] Audio Processor attached. Resampling {num} -> 16000 Hz.");
			}
			else
			{
				_log.LogWarning((object)("[VoiceCurse] Could not attach processor. Voice type: " + ((object)voice).GetType().Name));
			}
		}

		private void SetupVoiceRecognition()
		{
			if (_recognizer != null || _voskModel == null)
			{
				return;
			}
			try
			{
				_recognizer = new VoiceRecognizer(_voskModel, 16000f);
				_recognizer.OnPhraseRecognized += delegate(string text)
				{
					string text2 = text;
					_lastPartialText = "";
					_mainThreadActions.Enqueue(delegate
					{
						_log.LogInfo((object)("[Recognized]: " + text2));
						_eventHandler?.HandleSpeech(text2, isFinal: true);
					});
				};
				_recognizer.OnPartialResult += delegate(string text)
				{
					if (!string.IsNullOrWhiteSpace(text) && text.Length >= 2 && !(_lastPartialText == text))
					{
						_lastPartialText = text;
						string captured = text;
						_mainThreadActions.Enqueue(delegate
						{
							_log.LogInfo((object)("[Partial]: " + captured));
							_eventHandler?.HandleSpeech(captured, isFinal: false);
						});
					}
				};
				_recognizer.Start();
				_log.LogInfo((object)"[VoiceCurse] Vosk Recognizer started.");
			}
			catch (Exception ex)
			{
				_log.LogError((object)("Failed to start Vosk Recognizer: " + ex.Message));
			}
		}

		public void Dispose()
		{
			if (_networker != null)
			{
				PhotonNetwork.RemoveCallbackTarget((object)_networker);
			}
			_recognizer?.Stop();
			_recognizer?.Dispose();
			Model? voskModel = _voskModel;
			if (voskModel != null)
			{
				voskModel.Dispose();
			}
			_log.LogInfo((object)"VoiceCurse Manager disposed.");
		}
	}
}
namespace VoiceCurse.Events
{
	public class AfflictionEvent : VoiceEventBase
	{
		private readonly Dictionary<string, STATUSTYPE> _wordToType;

		public AfflictionEvent(Config config)
			: base(config)
		{
			_wordToType = new Dictionary<string, STATUSTYPE>();
			LoadKeywordsForType(config.AfflictionKeywordsInjury.Value, (STATUSTYPE)0);
			LoadKeywordsForType(config.AfflictionKeywordsHunger.Value, (STATUSTYPE)1);
			LoadKeywordsForType(config.AfflictionKeywordsCold.Value, (STATUSTYPE)2);
			LoadKeywordsForType(config.AfflictionKeywordsHot.Value, (STATUSTYPE)8);
			LoadKeywordsForType(config.AfflictionKeywordsPoison.Value, (STATUSTYPE)3);
			LoadKeywordsForType(config.AfflictionKeywordsSpores.Value, (STATUSTYPE)10);
		}

		private void LoadKeywordsForType(string configLine, STATUSTYPE type)
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			IEnumerable<string> enumerable = from w in configLine.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries)
				select w.Trim().ToLowerInvariant() into w
				where !string.IsNullOrWhiteSpace(w)
				select w;
			foreach (string item in enumerable)
			{
				_wordToType[item] = type;
			}
		}

		protected override IEnumerable<string> GetKeywords()
		{
			if (!Config.AfflictionEnabled.Value)
			{
				return Enumerable.Empty<string>();
			}
			return _wordToType.Keys;
		}

		protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Expected I4, but got Unknown
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Invalid comparison between Unknown and I4
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Invalid comparison between Unknown and I4
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			if (!Config.AfflictionEnabled.Value)
			{
				return false;
			}
			if (player.refs?.afflictions == null)
			{
				return false;
			}
			if (player.data.dead || player.data.fullyPassedOut)
			{
				return false;
			}
			if (!_wordToType.TryGetValue(matchedKeyword, out var value))
			{
				return false;
			}
			base.ExecutionDetail = (int)value switch
			{
				0 => "受伤", 
				1 => "饥饿", 
				2 => "寒冷", 
				8 => "灼烧", 
				3 => "中毒", 
				10 => "孢子", 
				_ => ((object)(STATUSTYPE)(ref value)).ToString(), 
			};
			bool value2 = Config.AfflictionTemperatureSwapEnabled.Value;
			bool flag = value2;
			if (flag)
			{
				bool flag2 = (((int)value == 2 || (int)value == 8) ? true : false);
				flag = flag2;
			}
			if (flag)
			{
				HandleTemperatureExchange(player, value);
			}
			float num = Random.Range(Config.AfflictionMinPercent.Value, Config.AfflictionMaxPercent.Value);
			if (Config.EnableDebugLogs.Value)
			{
				Debug.Log((object)$"[VoiceCurse] Affliction Specifics: {value} ({num:P0})");
			}
			player.refs.afflictions.AddStatus(value, num, false, true);
			return true;
		}

		private void HandleTemperatureExchange(Character player, STATUSTYPE incomingType)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			STATUSTYPE val = (STATUSTYPE)(((int)incomingType == 8) ? 2 : 8);
			float currentStatus = player.refs.afflictions.GetCurrentStatus(val);
			if (!(currentStatus <= 0.01f))
			{
				if (Config.EnableDebugLogs.Value)
				{
					Debug.Log((object)$"[VoiceCurse] Swapping {val} ({currentStatus:P0}) to {incomingType}");
				}
				player.refs.afflictions.SubtractStatus(val, currentStatus, false, false);
				player.refs.afflictions.AddStatus(incomingType, currentStatus, false, true);
			}
		}
	}
	public class BlindEvent : VoiceEventBase
	{
		[CompilerGenerated]
		private sealed class <BlindnessRoutine>d__6 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public Character player;

			public BlindEvent <>4__this;

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

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

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

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

			private bool MoveNext()
			{
				int num = <>1__state;
				BlindEvent blindEvent = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (Time.time < blindEvent._blindEndTime && Object.op_Implicit((Object)(object)player) && !player.data.dead)
				{
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				if (Object.op_Implicit((Object)(object)player))
				{
					ToggleBlindness(player, enable: false);
				}
				blindEvent._blindRoutine = null;
				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();
			}
		}

		private readonly HashSet<string> _keywords = VoiceEventBase.ParseKeywords(config.BlindKeywords.Value);

		private float _blindEndTime;

		private Coroutine? _blindRoutine;

		public BlindEvent(Config config)
			: base(config)
		{
		}

		protected override IEnumerable<string> GetKeywords()
		{
			if (!Config.BlindEnabled.Value)
			{
				return Enumerable.Empty<string>();
			}
			return _keywords;
		}

		protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword)
		{
			if (!Config.BlindEnabled.Value)
			{
				return false;
			}
			if (player.data.dead)
			{
				return false;
			}
			float value = Config.BlindDuration.Value;
			_blindEndTime = Time.time + value;
			if (_blindRoutine == null)
			{
				ToggleBlindness(player, enable: true);
				_blindRoutine = ((MonoBehaviour)player).StartCoroutine(BlindnessRoutine(player));
			}
			player.AddIllegalStatus("BLIND", value);
			return true;
		}

		[IteratorStateMachine(typeof(<BlindnessRoutine>d__6))]
		private IEnumerator BlindnessRoutine(Character player)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <BlindnessRoutine>d__6(0)
			{
				<>4__this = this,
				player = player
			};
		}

		private static void ToggleBlindness(Character player, bool enable)
		{
			if (Object.op_Implicit((Object)(object)player) && player.refs != null && Object.op_Implicit((Object)(object)player.refs.customization) && Object.op_Implicit((Object)(object)player.refs.customization.refs))
			{
				Renderer blindRenderer = player.refs.customization.refs.blindRenderer;
				if (Object.op_Implicit((Object)(object)blindRenderer))
				{
					((Component)blindRenderer).gameObject.SetActive(enable);
				}
			}
		}
	}
	public class DeathEvent : VoiceEventBase
	{
		private readonly HashSet<string> _deathKeywords = VoiceEventBase.ParseKeywords(config.DeathKeywords.Value);

		public DeathEvent(Config config)
			: base(config)
		{
		}

		protected override IEnumerable<string> GetKeywords()
		{
			if (!Config.DeathEnabled.Value)
			{
				return Enumerable.Empty<string>();
			}
			return _deathKeywords;
		}

		protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword)
		{
			if (!Config.DeathEnabled.Value)
			{
				return false;
			}
			if (player.data.dead)
			{
				return false;
			}
			player.DieInstantly();
			return true;
		}
	}
	public class DropEvent : VoiceEventBase
	{
		private readonly HashSet<string> _keywords = VoiceEventBase.ParseKeywords(config.DropKeywords.Value);

		public DropEvent(Config config)
			: base(config)
		{
		}

		protected override IEnumerable<string> GetKeywords()
		{
			if (!Config.DropEnabled.Value)
			{
				return Enumerable.Empty<string>();
			}
			return _keywords;
		}

		protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword)
		{
			if (Config.DropEnabled.Value)
			{
				return !player.data.dead;
			}
			return false;
		}

		public override void PlayEffects(Character origin, Vector3 position)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: 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_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			if (!PhotonNetwork.IsMasterClient || !Object.op_Implicit((Object)(object)origin) || origin.data.dead)
			{
				return;
			}
			ScatterBackpackContents(origin);
			Transform transform = ((Component)origin.GetBodypart((BodypartType)0)).transform;
			Vector3 val = transform.forward;
			if (Vector3.Dot(val, Vector3.up) < 0f)
			{
				val = -val;
			}
			Vector3 val2 = origin.Center + val * 0.6f + Vector3.up * 0.5f;
			for (byte b = 0; b < 4; b++)
			{
				if (!origin.player.GetItemSlot(b).IsEmpty())
				{
					origin.refs.items.photonView.RPC("DropItemFromSlotRPC", (RpcTarget)0, new object[2] { b, val2 });
					val2 += Vector3.up * 0.3f;
				}
			}
			origin.refs.items.photonView.RPC("EquipSlotRpc", (RpcTarget)0, new object[2] { -1, -1 });
		}

		private static void ScatterBackpackContents(Character player)
		{
			//IL_0027: 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_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			ItemSlot itemSlot = player.player.GetItemSlot((byte)3);
			BackpackData val = default(BackpackData);
			if (itemSlot.IsEmpty() || !itemSlot.data.TryGetDataEntry<BackpackData>((DataEntryKey)7, ref val))
			{
				return;
			}
			Vector3 center = player.Center;
			ItemSlot[] itemSlots = val.itemSlots;
			PhotonView val5 = default(PhotonView);
			foreach (ItemSlot val2 in itemSlots)
			{
				if (val2.IsEmpty())
				{
					continue;
				}
				string prefabName = val2.GetPrefabName();
				if (!string.IsNullOrEmpty(prefabName))
				{
					Vector3 val3 = center + Random.insideUnitSphere * 0.5f;
					val3.y = center.y + 0.5f;
					GameObject val4 = PhotonNetwork.Instantiate("0_Items/" + prefabName, val3, Quaternion.identity, (byte)0, (object[])null);
					if (val4.TryGetComponent<PhotonView>(ref val5))
					{
						val5.RPC("SetItemInstanceDataRPC", (RpcTarget)0, new object[1] { val2.data });
						val5.RPC("SetKinematicRPC", (RpcTarget)0, new object[3]
						{
							false,
							val3,
							Quaternion.identity
						});
					}
					val2.EmptyOut();
				}
			}
		}
	}
	public class ExplodeEvent : VoiceEventBase
	{
		private readonly HashSet<string> _keywords = VoiceEventBase.ParseKeywords(config.ExplodeKeywords.Value);

		private static GameObject? _cachedExplosionPrefab;

		public ExplodeEvent(Config config)
			: base(config)
		{
		}

		protected override IEnumerable<string> GetKeywords()
		{
			if (!Config.ExplodeEnabled.Value)
			{
				return Enumerable.Empty<string>();
			}
			return _keywords;
		}

		protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword)
		{
			if (!Config.ExplodeEnabled.Value)
			{
				return false;
			}
			return !player.data.dead;
		}

		public override void PlayEffects(Vector3 position)
		{
			//IL_0022: 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_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: 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_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)_cachedExplosionPrefab))
			{
				FindExplosionPrefab();
			}
			if (Object.op_Implicit((Object)(object)_cachedExplosionPrefab))
			{
				Object.Instantiate<GameObject>(_cachedExplosionPrefab, position, Quaternion.identity);
			}
			Character localCharacter = Character.localCharacter;
			if (!Object.op_Implicit((Object)(object)localCharacter) || localCharacter.data.dead)
			{
				return;
			}
			float num = Vector3.Distance(localCharacter.Center, position);
			if (num <= Config.ExplodeRadius.Value)
			{
				if (Object.op_Implicit((Object)(object)localCharacter.refs.afflictions))
				{
					localCharacter.refs.afflictions.AddStatus((STATUSTYPE)0, Config.ExplodeDamage.Value, false, true);
				}
				localCharacter.Fall(Config.ExplodeStunDuration.Value, 0f);
				Vector3 val = localCharacter.Center - position;
				Vector3 val2 = ((Vector3)(ref val)).normalized;
				val2 += Vector3.up * 0.6f;
				((Vector3)(ref val2)).Normalize();
				float num2 = Random.Range(Config.ExplodeForceLowerBound.Value, Config.ExplodeForceHigherBound.Value);
				localCharacter.AddForce(val2 * num2, 1f, 1f);
			}
		}

		private static void FindExplosionPrefab()
		{
			Dynamite val = Resources.FindObjectsOfTypeAll<Dynamite>().FirstOrDefault();
			if (Object.op_Implicit((Object)(object)val))
			{
				_cachedExplosionPrefab = val.explosionPrefab;
			}
		}
	}
	public class LaunchEvent : VoiceEventBase
	{
		private readonly HashSet<string> _keywords = VoiceEventBase.ParseKeywords(config.LaunchKeywords.Value);

		private static GameObject? _cachedLaunchSFX;

		public LaunchEvent(Config config)
			: base(config)
		{
		}

		protected override IEnumerable<string> GetKeywords()
		{
			if (!Config.LaunchEnabled.Value)
			{
				return Enumerable.Empty<string>();
			}
			return _keywords;
		}

		protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword)
		{
			//IL_0062: 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)
			//IL_0068: 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)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: 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_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			if (!Config.LaunchEnabled.Value)
			{
				return false;
			}
			if (player.data.dead || player.data.fullyPassedOut)
			{
				return false;
			}
			if (_cachedLaunchSFX == null)
			{
				FindLaunchSFX();
			}
			player.Fall(Config.LaunchStunDuration.Value, 0f);
			Vector3 normalized = ((Vector3)(ref player.data.lookDirection_Flat)).normalized;
			Vector3 val = Vector3.Cross(Vector3.up, normalized);
			string executionDetail;
			Vector3 val2;
			if (fullSentence.Contains("left") || fullSentence.Contains("左"))
			{
				executionDetail = "左";
				val2 = -val + Vector3.up * 0.2f;
			}
			else if (fullSentence.Contains("right") || fullSentence.Contains("右"))
			{
				executionDetail = "右";
				val2 = val + Vector3.up * 0.2f;
			}
			else if (fullSentence.Contains("backward") || fullSentence.Contains("backwards") || fullSentence.Contains("back") || fullSentence.Contains("后"))
			{
				executionDetail = "后";
				val2 = -normalized + Vector3.up * 0.2f;
			}
			else if (fullSentence.Contains("forward") || fullSentence.Contains("forwards") || fullSentence.Contains("前"))
			{
				executionDetail = "前";
				val2 = normalized + Vector3.up * 0.2f;
			}
			else if (fullSentence.Contains("up") || fullSentence.Contains("上") || fullSentence.Contains("飞"))
			{
				executionDetail = "上";
				val2 = Vector3.up;
			}
			else
			{
				executionDetail = "随机";
				val2 = GetRandomUpwardDirection();
			}
			base.ExecutionDetail = executionDetail;
			((Vector3)(ref val2)).Normalize();
			float num = Random.Range(Config.LaunchForceLowerBound.Value, Config.LaunchForceHigherBound.Value);
			Vector3 val3 = val2 * num;
			player.AddForce(val3, 1f, 1f);
			return true;
		}

		private static Vector3 GetRandomUpwardDirection()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: 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_0031: Unknown result type (might be due to invalid IL or missing references)
			Vector3 onUnitSphere = Random.onUnitSphere;
			onUnitSphere.y = Mathf.Abs(onUnitSphere.y);
			if (onUnitSphere.y < 0.5f)
			{
				onUnitSphere.y = 0.5f;
			}
			return onUnitSphere;
		}

		public override void PlayEffects(Vector3 position)
		{
			//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)
			if (!Object.op_Implicit((Object)(object)_cachedLaunchSFX))
			{
				FindLaunchSFX();
			}
			if (Object.op_Implicit((Object)(object)_cachedLaunchSFX))
			{
				GameObject val = Object.Instantiate<GameObject>(_cachedLaunchSFX, position, Quaternion.identity);
				val.SetActive(true);
				Object.Destroy((Object)(object)val, 5f);
			}
		}

		private static void FindLaunchSFX()
		{
			ScoutCannon val = Resources.FindObjectsOfTypeAll<ScoutCannon>().FirstOrDefault();
			if (val != null)
			{
				_cachedLaunchSFX = val.fireSFX;
			}
		}
	}
	public class SacrificeEvent : VoiceEventBase
	{
		private readonly HashSet<string> _sacrificeKeywords = VoiceEventBase.ParseKeywords(config.SacrificeKeywords.Value);

		private float _lastSacrificeTime = -999f;

		public SacrificeEvent(Config config)
			: base(config)
		{
		}

		protected override IEnumerable<string> GetKeywords()
		{
			if (!Config.SacrificeEnabled.Value)
			{
				return Enumerable.Empty<string>();
			}
			return _sacrificeKeywords;
		}

		protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: 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)
			if (!Config.SacrificeEnabled.Value)
			{
				return false;
			}
			if (player.data.dead)
			{
				return false;
			}
			if (Time.time < _lastSacrificeTime + Config.SacrificeCooldown.Value)
			{
				Debug.Log((object)"[VoiceCurse] Cooldown active, cannot sacrifice now.");
				return false;
			}
			Vector3 deathPos;
			Character closestDeadPlayer = DeathTracker.GetClosestDeadPlayer(player.Center, out deathPos);
			if (!Object.op_Implicit((Object)(object)closestDeadPlayer))
			{
				return false;
			}
			_lastSacrificeTime = Time.time;
			Vector3 val = deathPos + Vector3.up * 1f;
			base.ExecutionDetail = "复活 " + closestDeadPlayer.characterName;
			closestDeadPlayer.view.RPC("RPCA_ReviveAtPosition", (RpcTarget)0, new object[2] { val, true });
			DeathTracker.RemoveDeath(closestDeadPlayer);
			player.DieInstantly();
			return true;
		}
	}
	[HarmonyPatch(typeof(Character))]
	public static class DeathTracker
	{
		private static readonly Dictionary<int, Vector3> DeathLocations = new Dictionary<int, Vector3>();

		[HarmonyPatch("RPCA_Die")]
		[HarmonyPrefix]
		private static void OnDiePrefix(Character __instance)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)__instance))
			{
				DeathLocations[((MonoBehaviourPun)__instance).photonView.ViewID] = __instance.Center;
			}
		}

		[HarmonyPatch("RPCA_Revive")]
		[HarmonyPostfix]
		private static void OnRevivePostfix(Character __instance)
		{
			RemoveDeath(__instance);
		}

		[HarmonyPatch("RPCA_ReviveAtPosition")]
		[HarmonyPostfix]
		private static void OnReviveAtPosPostfix(Character __instance)
		{
			RemoveDeath(__instance);
		}

		public static void RemoveDeath(Character c)
		{
			if (Object.op_Implicit((Object)(object)c) && Object.op_Implicit((Object)(object)((MonoBehaviourPun)c).photonView))
			{
				DeathLocations.Remove(((MonoBehaviourPun)c).photonView.ViewID);
			}
		}

		public static Character? GetClosestDeadPlayer(Vector3 origin, out Vector3 deathPos)
		{
			//IL_0009: 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_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			Character result = null;
			float num = float.MaxValue;
			deathPos = Vector3.zero;
			foreach (Character item in Character.AllCharacters.Where((Character c) => c.data.dead))
			{
				Vector3 val;
				if (DeathLocations.TryGetValue(((MonoBehaviourPun)item).photonView.ViewID, out var value))
				{
					val = value;
				}
				else
				{
					if (!Object.op_Implicit((Object)(object)item.Ghost))
					{
						continue;
					}
					val = ((Component)item.Ghost).transform.position;
				}
				float num2 = Vector3.Distance(origin, val);
				if (num2 < num)
				{
					num = num2;
					result = item;
					deathPos = val;
				}
			}
			return result;
		}
	}
	public class SleepEvent : VoiceEventBase
	{
		private readonly HashSet<string> _sleepKeywords = VoiceEventBase.ParseKeywords(config.SleepKeywords.Value);

		public SleepEvent(Config config)
			: base(config)
		{
		}

		protected override IEnumerable<string> GetKeywords()
		{
			if (!Config.SleepEnabled.Value)
			{
				return Enumerable.Empty<string>();
			}
			return _sleepKeywords;
		}

		protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword)
		{
			if (!Config.SleepEnabled.Value)
			{
				return false;
			}
			if (player.data.passedOut || player.data.dead)
			{
				return false;
			}
			player.PassOutInstantly();
			return true;
		}
	}
	public class SlipEvent : VoiceEventBase
	{
		private readonly HashSet<string> _keywords = VoiceEventBase.ParseKeywords(config.SlipKeywords.Value);

		private static AudioClip? _cachedTripSound;

		private Item? _cachedBananaItem;

		private static readonly Regex NameCleaner = new Regex("\\s*\\((\\d+|Clone)\\)", RegexOptions.Compiled);

		public SlipEvent(Config config)
			: base(config)
		{
		}

		protected override IEnumerable<string> GetKeywords()
		{
			if (!Config.SlipEnabled.Value)
			{
				return Enumerable.Empty<string>();
			}
			return _keywords;
		}

		protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword)
		{
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			if (!Config.SlipEnabled.Value)
			{
				return false;
			}
			if (player.data.dead || player.data.fullyPassedOut)
			{
				return false;
			}
			if (Config.BananaBombEnabled.Value && Random.value <= Config.BananaBombChance.Value)
			{
				base.ExecutionDetail = "BananaBomb";
			}
			player.Fall(Config.SlipStunDuration.Value, 0f);
			Vector3 lookDirection_Flat = player.data.lookDirection_Flat;
			ApplyForceToPart(player, (BodypartType)16, (lookDirection_Flat + Vector3.up) * 200f);
			ApplyForceToPart(player, (BodypartType)13, (lookDirection_Flat + Vector3.up) * 200f);
			ApplyForceToPart(player, (BodypartType)0, Vector3.up * 1500f);
			ApplyForceToPart(player, (BodypartType)4, lookDirection_Flat * -300f);
			return true;
		}

		private static void ApplyForceToPart(Character player, BodypartType partType, Vector3 force)
		{
			//IL_0001: 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)
			Rigidbody bodypartRig = player.GetBodypartRig(partType);
			if (Object.op_Implicit((Object)(object)bodypartRig))
			{
				bodypartRig.AddForce(force, (ForceMode)1);
			}
		}

		public override void PlayEffects(Character origin, Vector3 position, string detail)
		{
			//IL_0002: 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)
			base.PlayEffects(origin, position, detail);
			if (detail == "BananaBomb")
			{
				SpawnBananaBomb(position);
			}
		}

		public override void PlayEffects(Vector3 position)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			AudioClip tripSound = GetTripSound();
			if (Object.op_Implicit((Object)(object)tripSound))
			{
				AudioSource.PlayClipAtPoint(tripSound, position);
			}
		}

		private void SpawnBananaBomb(Vector3 origin)
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: 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_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			if (!PhotonNetwork.IsMasterClient)
			{
				return;
			}
			Item bananaItem = GetBananaItem();
			if (!Object.op_Implicit((Object)(object)bananaItem))
			{
				if (Config.EnableDebugLogs.Value)
				{
					Debug.LogWarning((object)"[VoiceCurse] Could not find 'Berrynana Peel Yellow' for Banana Bomb.");
				}
				return;
			}
			string text = NameCleaner.Replace(((Object)bananaItem).name, "").Trim();
			string text2 = "0_Items/" + text;
			int value = Config.BananaBombAmount.Value;
			PhotonView val3 = default(PhotonView);
			Rigidbody val4 = default(Rigidbody);
			for (int i = 0; i < value; i++)
			{
				Vector3 val = origin + Random.insideUnitSphere * 3f;
				val.y = origin.y + 1.5f;
				GameObject val2 = PhotonNetwork.Instantiate(text2, val, Quaternion.identity, (byte)0, (object[])null);
				if (Object.op_Implicit((Object)(object)val2) && val2.TryGetComponent<PhotonView>(ref val3))
				{
					val3.RPC("SetKinematicRPC", (RpcTarget)0, new object[3]
					{
						false,
						val,
						Quaternion.identity
					});
					Vector3 randomUpwardDirection = GetRandomUpwardDirection();
					float num = Random.Range(25f, 200f);
					if (val2.TryGetComponent<Rigidbody>(ref val4))
					{
						val4.isKinematic = false;
						val4.AddForce(randomUpwardDirection * num, (ForceMode)1);
					}
				}
			}
		}

		private static Vector3 GetRandomUpwardDirection()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: 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_0033: Unknown result type (might be due to invalid IL or missing references)
			Vector3 onUnitSphere = Random.onUnitSphere;
			onUnitSphere.y = Mathf.Abs(onUnitSphere.y);
			if (onUnitSphere.y < 0.2f)
			{
				onUnitSphere.y = 0.5f;
			}
			return ((Vector3)(ref onUnitSphere)).normalized;
		}

		private Item? GetBananaItem()
		{
			if (Object.op_Implicit((Object)(object)_cachedBananaItem))
			{
				return _cachedBananaItem;
			}
			_cachedBananaItem = ((IEnumerable<Item>)Resources.FindObjectsOfTypeAll<Item>()).FirstOrDefault((Func<Item, bool>)((Item i) => ((Object)i).name.Contains("Berrynana Peel Yellow")));
			return _cachedBananaItem;
		}

		private static AudioClip? GetTripSound()
		{
			if (!Object.op_Implicit((Object)(object)_cachedTripSound))
			{
				_cachedTripSound = ((IEnumerable<AudioClip>)Resources.FindObjectsOfTypeAll<AudioClip>()).FirstOrDefault((Func<AudioClip, bool>)((AudioClip c) => ((Object)c).name == "Au_Slip1"));
			}
			return _cachedTripSound;
		}
	}
	[Serializable]
	public class TransmutePayload
	{
		public string? ruleName;

		public bool isDeath;

		public int spawnCount;

		public Vector3 deathPosition;
	}
	public class TransmuteEvent : VoiceEventBase
	{
		private readonly List<(string Name, string[] Triggers, string[] Targets, Func<bool> IsEnabled)> _definitions;

		private readonly Dictionary<string, (string Name, string[] Targets, Func<bool> IsEnabled)> _transmuteLookup = new Dictionary<string, (string, string[], Func<bool>)>();

		private readonly Dictionary<string, Item?> _itemCache = new Dictionary<string, Item>();

		private static readonly Regex NameCleaner = new Regex("\\s*\\((\\d+|Clone)\\)", RegexOptions.Compiled);

		public TransmuteEvent(Config config)
		{
			Config config2 = config;
			base..ctor(config2);
			_definitions = new List<(string, string[], string[], Func<bool>)>(9)
			{
				("奶", new string[4] { "milk", "calcium", "奶", "钙" }, new string[1] { "Fortified Milk" }, () => config2.TransmuteMilkEnabled.Value),
				("仙人掌", new string[3] { "cactus", "cacti", "仙人掌" }, new string[1] { "Cactus" }, () => config2.TransmuteCactusEnabled.Value),
				("椰子", new string[2] { "coconut", "椰子" }, new string[1] { "Coconut" }, () => config2.TransmuteCoconutEnabled.Value),
				("苹果/浆果", new string[5] { "apple", "berry", "berries", "苹果", "浆果" }, new string[3] { "Red Crispberry", "Yellow Crispberry", "Green Crispberry" }, () => config2.TransmuteAppleEnabled.Value),
				("香蕉", new string[2] { "banana", "香蕉" }, new string[1] { "Berrynana Peel Yellow" }, () => config2.TransmuteBananaEnabled.Value),
				("鸡蛋", new string[2] { "egg", "鸡蛋" }, new string[1] { "Egg" }, () => config2.TransmuteEggEnabled.Value),
				("水果", new string[2] { "fruit", "水果" }, new string[10] { "Red Crispberry", "Yellow Crispberry", "Green Crispberry", "Kingberry Purple", "Kingberry Yellow", "Kingberry Green", "Berrynana Brown", "Berrynana Yellow", "Berrynana Pink", "Berrynana Blue" }, () => config2.TransmuteFruitEnabled.Value),
				("蘑菇", new string[7] { "fungus", "mushroom", "fungi", "funghi", "shroom", "蘑菇", "真菌" }, new string[1] { "Mushroom Normie" }, () => config2.TransmuteMushroomEnabled.Value),
				("球", new string[2] { "ball", "球" }, new string[1] { "Basketball" }, () => config2.TransmuteBallEnabled.Value)
			};
			foreach (var definition in _definitions)
			{
				string[] item = definition.Triggers;
				foreach (string key in item)
				{
					_transmuteLookup[key] = (definition.Name, definition.Targets, definition.IsEnabled);
				}
			}
		}

		protected override IEnumerable<string> GetKeywords()
		{
			if (!Config.TransmuteEnabled.Value)
			{
				return Array.Empty<string>();
			}
			return _definitions.Where<(string, string[], string[], Func<bool>)>(((string Name, string[] Triggers, string[] Targets, Func<bool> IsEnabled) d) => d.IsEnabled()).SelectMany<(string, string[], string[], Func<bool>), string>(((string Name, string[] Triggers, string[] Targets, Func<bool> IsEnabled) d) => d.Triggers);
		}

		protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword)
		{
			//IL_00e3: 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)
			string fullSentence2 = fullSentence;
			if (!Config.TransmuteEnabled.Value)
			{
				return false;
			}
			if (player.data.dead)
			{
				return false;
			}
			string[] array = null;
			string text = null;
			if (_transmuteLookup.TryGetValue(matchedKeyword, out (string, string[], Func<bool>) value) && value.Item3())
			{
				(text, array, _) = value;
			}
			if (array == null)
			{
				string text2 = _transmuteLookup.Keys.FirstOrDefault((string k) => fullSentence2.Contains(k) && _transmuteLookup[k].IsEnabled());
				if (text2 != null)
				{
					(text, array, _) = _transmuteLookup[text2];
				}
			}
			if (array == null || array.Length == 0)
			{
				return false;
			}
			bool value2 = Config.TransmuteDeathEnabled.Value;
			TransmutePayload transmutePayload = new TransmutePayload
			{
				ruleName = text,
				isDeath = value2,
				spawnCount = 0,
				deathPosition = player.Center
			};
			if (value2)
			{
				int spawnCount = ClearInventoryForDeath(player);
				player.DieInstantly();
				transmutePayload.spawnCount = spawnCount;
			}
			base.ExecutionDetail = text;
			base.ExecutionPayload = JsonUtility.ToJson((object)transmutePayload);
			return true;
		}

		public override void PlayEffects(Character origin, Vector3 position, string detail)
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: 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)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			if (!PhotonNetwork.IsMasterClient || !Object.op_Implicit((Object)(object)origin) || string.IsNullOrEmpty(detail))
			{
				return;
			}
			TransmutePayload payload;
			try
			{
				payload = JsonUtility.FromJson<TransmutePayload>(detail);
			}
			catch
			{
				return;
			}
			if (payload == null || string.IsNullOrEmpty(payload.ruleName))
			{
				return;
			}
			(string, string[], string[], Func<bool>) tuple = _definitions.FirstOrDefault<(string, string[], string[], Func<bool>)>(((string Name, string[] Triggers, string[] Targets, Func<bool> IsEnabled) d) => d.Name == payload.ruleName);
			if (tuple.Item3 == null || tuple.Item3.Length == 0)
			{
				return;
			}
			string[] item = tuple.Item3;
			if (payload.isDeath)
			{
				Vector3 origin2 = ((payload.deathPosition != Vector3.zero) ? payload.deathPosition : origin.Center);
				SpawnTransmutedItems(origin2, payload.spawnCount, item);
				return;
			}
			TransmuteInventoryAlive(origin, item);
			float num = Random.Range(Config.AfflictionMinPercent.Value, Config.AfflictionMaxPercent.Value);
			if (Object.op_Implicit((Object)(object)origin.refs.afflictions))
			{
				origin.refs.afflictions.AddStatus((STATUSTYPE)0, num, false, true);
			}
		}

		private static int ClearInventoryForDeath(Character player)
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			int num = 1;
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(0f, -5000f, 0f);
			for (byte b = 0; b < 3; b++)
			{
				ItemSlot itemSlot = player.player.GetItemSlot(b);
				if (itemSlot != null && !itemSlot.IsEmpty())
				{
					num++;
					player.refs.items.photonView.RPC("DropItemFromSlotRPC", (RpcTarget)0, new object[2] { b, val });
				}
			}
			ItemSlot itemSlot2 = player.player.GetItemSlot((byte)3);
			if (itemSlot2 != null && !itemSlot2.IsEmpty())
			{
				BackpackData val2 = default(BackpackData);
				if (itemSlot2.data.TryGetDataEntry<BackpackData>((DataEntryKey)7, ref val2))
				{
					num += val2.FilledSlotCount();
				}
				num++;
				player.refs.items.photonView.RPC("DropItemFromSlotRPC", (RpcTarget)0, new object[2]
				{
					(byte)3,
					val
				});
			}
			if (Object.op_Implicit((Object)(object)player.refs.afflictions))
			{
				player.refs.afflictions.UpdateWeight();
			}
			return num;
		}

		private void TransmuteInventoryAlive(Character player, string[] possibleTargets)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(0f, -5000f, 0f);
			Vector3 center = player.Center;
			int num = 0;
			for (byte b = 0; b < 3; b++)
			{
				ItemSlot itemSlot = player.player.GetItemSlot(b);
				if (itemSlot != null && !itemSlot.IsEmpty())
				{
					player.refs.items.photonView.RPC("DropItemFromSlotRPC", (RpcTarget)0, new object[2] { b, val });
					num++;
				}
			}
			ItemSlot itemSlot2 = player.player.GetItemSlot((byte)3);
			if (itemSlot2 != null && !itemSlot2.IsEmpty())
			{
				num++;
				BackpackData val2 = default(BackpackData);
				if (itemSlot2.data.TryGetDataEntry<BackpackData>((DataEntryKey)7, ref val2))
				{
					num += val2.FilledSlotCount();
				}
				player.refs.items.photonView.RPC("DropItemFromSlotRPC", (RpcTarget)0, new object[2]
				{
					(byte)3,
					val
				});
			}
			SpawnTransmutedItems(center, num, possibleTargets);
			if (Object.op_Implicit((Object)(object)player.refs.afflictions))
			{
				player.refs.afflictions.UpdateWeight();
			}
		}

		private void SpawnTransmutedItems(Vector3 origin, int count, string[] targets)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < count; i++)
			{
				SpawnItem(origin, targets, autoPickup: false, null);
			}
		}

		private void SpawnAndPickupItem(Character player, string[] targets, Vector3 origin)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			SpawnItem(origin, targets, autoPickup: true, player);
		}

		private void SpawnItem(Vector3 origin, string[] targets, bool autoPickup, Character? picker)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			string searchName = targets[Random.Range(0, targets.Length)];
			Item orFindItem = GetOrFindItem(searchName);
			if (!Object.op_Implicit((Object)(object)orFindItem))
			{
				return;
			}
			Vector3 val = origin + Random.insideUnitSphere * 0.5f;
			val.y = origin.y + 0.5f;
			string text = NameCleaner.Replace(((Object)orFindItem).name, "").Trim();
			string text2 = "0_Items/" + text;
			GameObject val2 = PhotonNetwork.Instantiate(text2, val, Quaternion.identity, (byte)0, (object[])null);
			PhotonView val3 = default(PhotonView);
			if (!Object.op_Implicit((Object)(object)val2) || !val2.TryGetComponent<PhotonView>(ref val3))
			{
				return;
			}
			val3.RPC("SetKinematicRPC", (RpcTarget)0, new object[3]
			{
				false,
				val,
				Quaternion.identity
			});
			Item val4 = default(Item);
			if (autoPickup && Object.op_Implicit((Object)(object)picker) && val2.TryGetComponent<Item>(ref val4))
			{
				if (picker.refs != null && (Object)(object)picker.refs.items != (Object)null)
				{
					picker.refs.items.lastEquippedSlotTime = 0f;
				}
				val4.Interact(picker);
			}
		}

		private Item? GetOrFindItem(string searchName)
		{
			string searchName2 = searchName;
			if (_itemCache.TryGetValue(searchName2, out Item value))
			{
				if (Object.op_Implicit((Object)(object)value))
				{
					return value;
				}
				_itemCache.Remove(searchName2);
			}
			Item val = ((IEnumerable<Item>)Resources.FindObjectsOfTypeAll<Item>()).FirstOrDefault((Func<Item, bool>)((Item i) => ((Object)i).name.Contains(searchName2) || (i.UIData != null && i.UIData.itemName.Contains(searchName2))));
			_itemCache[searchName2] = val;
			if (!Object.op_Implicit((Object)(object)val) && Config.EnableDebugLogs.Value)
			{
				Debug.LogWarning((object)("[VoiceCurse] Could not find item matching '" + searchName2 + "'"));
			}
			return val;
		}
	}
	public abstract class VoiceEventBase : IVoiceEvent
	{
		protected readonly Config Config;

		private float _lastExecutionTime;

		private float Cooldown => Config.GlobalCooldown.Value;

		protected string? ExecutionDetail { get; set; }

		protected string? ExecutionPayload { get; set; }

		protected VoiceEventBase(Config config)
		{
			Config = config;
			_lastExecutionTime = -999f;
			base..ctor();
		}

		protected abstract IEnumerable<string> GetKeywords();

		protected abstract bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword);

		protected static HashSet<string> ParseKeywords(string configLine)
		{
			return (from k in configLine.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries)
				select k.Trim().ToLowerInvariant() into k
				where !string.IsNullOrWhiteSpace(k)
				select k).ToHashSet();
		}

		public bool TryExecute(string spokenWord, string fullSentence)
		{
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			string spokenWord2 = spokenWord;
			string fullSentence2 = fullSentence;
			if (Time.time < _lastExecutionTime + Cooldown)
			{
				return false;
			}
			string text = GetKeywords().FirstOrDefault((string keyword) => spokenWord2.Contains(keyword) || (fullSentence2.Contains(keyword) && keyword.EndsWith(" " + spokenWord2, StringComparison.OrdinalIgnoreCase)));
			if (text == null)
			{
				return false;
			}
			Character localCharacter = Character.localCharacter;
			if (!Object.op_Implicit((Object)(object)localCharacter) || !((Component)localCharacter).gameObject.activeInHierarchy)
			{
				return false;
			}
			ExecutionDetail = null;
			ExecutionPayload = null;
			bool flag = false;
			try
			{
				flag = OnExecute(localCharacter, spokenWord2, fullSentence2, text);
			}
			catch (Exception ex)
			{
				if (Config.EnableDebugLogs.Value)
				{
					Debug.LogWarning((object)("[VoiceCurse] Failed to execute " + GetType().Name + ": " + ex.Message));
				}
			}
			if (!flag)
			{
				return false;
			}
			_lastExecutionTime = Time.time;
			if (Config.EnableDebugLogs.Value)
			{
				Debug.Log((object)("[VoiceCurse] " + GetType().Name + " executed locally. Broadcasting event..."));
			}
			string eventName = GetType().Name.Replace("Event", "");
			string spokenWord3 = fullSentence2;
			int num = fullSentence2.LastIndexOf(text, StringComparison.OrdinalIgnoreCase);
			if (num != -1)
			{
				int num2 = num;
				int i = num + text.Length;
				while (num2 > 0 && fullSentence2[num2 - 1] != ' ')
				{
					num2--;
				}
				for (; i < fullSentence2.Length && fullSentence2[i] != ' '; i++)
				{
				}
				spokenWord3 = fullSentence2.Substring(num2, i - num2);
			}
			NetworkHandler.SendCurseEvent(spokenWord3, text, eventName, ExecutionDetail, ExecutionPayload, localCharacter.Center);
			return true;
		}

		public virtual void PlayEffects(Character origin, Vector3 position, string detail)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			PlayEffects(origin, position);
		}

		public virtual void PlayEffects(Character origin, Vector3 position)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			PlayEffects(position);
		}

		public virtual void PlayEffects(Vector3 position)
		{
		}
	}
	public class ZombifyEvent : VoiceEventBase
	{
		private readonly HashSet<string> _zombifyKeywords = VoiceEventBase.ParseKeywords(config.ZombifyKeywords.Value);

		public ZombifyEvent(Config config)
			: base(config)
		{
		}

		protected override IEnumerable<string> GetKeywords()
		{
			if (!Config.ZombifyEnabled.Value)
			{
				return Enumerable.Empty<string>();
			}
			return _zombifyKeywords;
		}

		protected override bool OnExecute(Character player, string spokenWord, string fullSentence, string matchedKeyword)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			if (!Config.ZombifyEnabled.Value)
			{
				return false;
			}
			if (player.data.dead || player.data.zombified)
			{
				return false;
			}
			((MonoBehaviourPun)player).photonView.RPC("RPCA_Zombify", (RpcTarget)0, new object[1] { player.Center });
			return true;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}

plugins/Vosk.dll

Decompiled a month ago
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace Vosk;

public class Model : IDisposable
{
	private HandleRef handle;

	internal Model(IntPtr cPtr)
	{
		handle = new HandleRef(this, cPtr);
	}

	public Model(string model_path)
		: this(VoskPINVOKE.new_Model(model_path))
	{
	}

	internal static HandleRef getCPtr(Model obj)
	{
		return obj?.handle ?? new HandleRef(null, IntPtr.Zero);
	}

	~Model()
	{
		Dispose(disposing: false);
	}

	public void Dispose()
	{
		Dispose(disposing: true);
		GC.SuppressFinalize(this);
	}

	protected virtual void Dispose(bool disposing)
	{
		lock (this)
		{
			if (handle.Handle != IntPtr.Zero)
			{
				VoskPINVOKE.delete_Model(handle);
				handle = new HandleRef(null, IntPtr.Zero);
			}
		}
	}

	public int FindWord(string word)
	{
		return VoskPINVOKE.Model_vosk_model_find_word(handle, word);
	}
}
public class SpkModel : IDisposable
{
	private HandleRef handle;

	internal SpkModel(IntPtr cPtr)
	{
		handle = new HandleRef(this, cPtr);
	}

	public SpkModel(string model_path)
		: this(VoskPINVOKE.new_SpkModel(model_path))
	{
	}

	internal static HandleRef getCPtr(SpkModel obj)
	{
		return obj?.handle ?? new HandleRef(null, IntPtr.Zero);
	}

	~SpkModel()
	{
		Dispose(disposing: false);
	}

	public void Dispose()
	{
		Dispose(disposing: true);
		GC.SuppressFinalize(this);
	}

	protected virtual void Dispose(bool disposing)
	{
		lock (this)
		{
			if (handle.Handle != IntPtr.Zero)
			{
				VoskPINVOKE.delete_SpkModel(handle);
				handle = new HandleRef(null, IntPtr.Zero);
			}
		}
	}
}
public class Vosk
{
	public static void SetLogLevel(int level)
	{
		VoskPINVOKE.SetLogLevel(level);
	}

	public static void GpuInit()
	{
		VoskPINVOKE.GpuInit();
	}

	public static void GpuThreadInit()
	{
		VoskPINVOKE.GpuThreadInit();
	}
}
internal class VoskPINVOKE
{
	static VoskPINVOKE()
	{
	}

	[DllImport("libvosk", EntryPoint = "vosk_model_new")]
	public static extern IntPtr new_Model(string jarg1);

	[DllImport("libvosk", EntryPoint = "vosk_model_free")]
	public static extern void delete_Model(HandleRef jarg1);

	[DllImport("libvosk", EntryPoint = "vosk_model_find_word")]
	public static extern int Model_vosk_model_find_word(HandleRef jarg1, string jarg2);

	[DllImport("libvosk", EntryPoint = "vosk_spk_model_new")]
	public static extern IntPtr new_SpkModel(string jarg1);

	[DllImport("libvosk", EntryPoint = "vosk_spk_model_free")]
	public static extern void delete_SpkModel(HandleRef jarg1);

	[DllImport("libvosk", EntryPoint = "vosk_recognizer_new")]
	public static extern IntPtr new_VoskRecognizer(HandleRef jarg1, float jarg2);

	[DllImport("libvosk", EntryPoint = "vosk_recognizer_new_spk")]
	public static extern IntPtr new_VoskRecognizerSpk(HandleRef jarg1, float jarg2, HandleRef jarg3);

	[DllImport("libvosk", EntryPoint = "vosk_recognizer_new_grm")]
	public static extern IntPtr new_VoskRecognizerGrm(HandleRef jarg1, float jarg2, string jarg3);

	[DllImport("libvosk", EntryPoint = "vosk_recognizer_free")]
	public static extern void delete_VoskRecognizer(HandleRef jarg1);

	[DllImport("libvosk", EntryPoint = "vosk_recognizer_set_max_alternatives")]
	public static extern void VoskRecognizer_SetMaxAlternatives(HandleRef jarg1, int jarg2);

	[DllImport("libvosk", EntryPoint = "vosk_recognizer_set_words")]
	public static extern void VoskRecognizer_SetWords(HandleRef jarg1, int jarg2);

	[DllImport("libvosk", EntryPoint = "vosk_recognizer_set_partial_words")]
	public static extern void VoskRecognizer_SetPartialWords(HandleRef jarg1, int jarg2);

	[DllImport("libvosk", EntryPoint = "vosk_recognizer_set_spk_model")]
	public static extern void VoskRecognizer_SetSpkModel(HandleRef jarg1, HandleRef jarg2);

	[DllImport("libvosk", EntryPoint = "vosk_recognizer_accept_waveform")]
	public static extern bool VoskRecognizer_AcceptWaveform(HandleRef jarg1, [In][MarshalAs(UnmanagedType.LPArray)] byte[] jarg2, int jarg3);

	[DllImport("libvosk", EntryPoint = "vosk_recognizer_accept_waveform_s")]
	public static extern bool VoskRecognizer_AcceptWaveformShort(HandleRef jarg1, [In][MarshalAs(UnmanagedType.LPArray)] short[] jarg2, int jarg3);

	[DllImport("libvosk", EntryPoint = "vosk_recognizer_accept_waveform_f")]
	public static extern bool VoskRecognizer_AcceptWaveformFloat(HandleRef jarg1, [In][MarshalAs(UnmanagedType.LPArray)] float[] jarg2, int jarg3);

	[DllImport("libvosk", EntryPoint = "vosk_recognizer_result")]
	public static extern IntPtr VoskRecognizer_Result(HandleRef jarg1);

	[DllImport("libvosk", EntryPoint = "vosk_recognizer_partial_result")]
	public static extern IntPtr VoskRecognizer_PartialResult(HandleRef jarg1);

	[DllImport("libvosk", EntryPoint = "vosk_recognizer_final_result")]
	public static extern IntPtr VoskRecognizer_FinalResult(HandleRef jarg1);

	[DllImport("libvosk", EntryPoint = "vosk_recognizer_reset")]
	public static extern void VoskRecognizer_Reset(HandleRef jarg1);

	[DllImport("libvosk", EntryPoint = "vosk_set_log_level")]
	public static extern void SetLogLevel(int jarg1);

	[DllImport("libvosk", EntryPoint = "vosk_gpu_init")]
	public static extern void GpuInit();

	[DllImport("libvosk", EntryPoint = "vosk_gpu_thread_init")]
	public static extern void GpuThreadInit();
}
public class VoskRecognizer : IDisposable
{
	private HandleRef handle;

	internal VoskRecognizer(IntPtr cPtr)
	{
		handle = new HandleRef(this, cPtr);
	}

	public VoskRecognizer(Model model, float sample_rate)
		: this(VoskPINVOKE.new_VoskRecognizer(Model.getCPtr(model), sample_rate))
	{
	}

	public VoskRecognizer(Model model, float sample_rate, SpkModel spk_model)
		: this(VoskPINVOKE.new_VoskRecognizerSpk(Model.getCPtr(model), sample_rate, SpkModel.getCPtr(spk_model)))
	{
	}

	public VoskRecognizer(Model model, float sample_rate, string grammar)
		: this(VoskPINVOKE.new_VoskRecognizerGrm(Model.getCPtr(model), sample_rate, grammar))
	{
	}

	internal static HandleRef getCPtr(VoskRecognizer obj)
	{
		return obj?.handle ?? new HandleRef(null, IntPtr.Zero);
	}

	~VoskRecognizer()
	{
		Dispose(disposing: false);
	}

	public void Dispose()
	{
		Dispose(disposing: true);
		GC.SuppressFinalize(this);
	}

	protected virtual void Dispose(bool disposing)
	{
		lock (this)
		{
			if (handle.Handle != IntPtr.Zero)
			{
				VoskPINVOKE.delete_VoskRecognizer(handle);
				handle = new HandleRef(null, IntPtr.Zero);
			}
		}
	}

	public void SetMaxAlternatives(int max_alternatives)
	{
		VoskPINVOKE.VoskRecognizer_SetMaxAlternatives(handle, max_alternatives);
	}

	public void SetWords(bool words)
	{
		VoskPINVOKE.VoskRecognizer_SetWords(handle, words ? 1 : 0);
	}

	public void SetPartialWords(bool partial_words)
	{
		VoskPINVOKE.VoskRecognizer_SetPartialWords(handle, partial_words ? 1 : 0);
	}

	public void SetSpkModel(SpkModel spk_model)
	{
		VoskPINVOKE.VoskRecognizer_SetSpkModel(handle, SpkModel.getCPtr(spk_model));
	}

	public bool AcceptWaveform(byte[] data, int len)
	{
		return VoskPINVOKE.VoskRecognizer_AcceptWaveform(handle, data, len);
	}

	public bool AcceptWaveform(short[] sdata, int len)
	{
		return VoskPINVOKE.VoskRecognizer_AcceptWaveformShort(handle, sdata, len);
	}

	public bool AcceptWaveform(float[] fdata, int len)
	{
		return VoskPINVOKE.VoskRecognizer_AcceptWaveformFloat(handle, fdata, len);
	}

	private static string PtrToStringUTF8(IntPtr ptr)
	{
		int i;
		for (i = 0; Marshal.ReadByte(ptr, i) != 0; i++)
		{
		}
		byte[] array = new byte[i];
		Marshal.Copy(ptr, array, 0, i);
		return Encoding.UTF8.GetString(array);
	}

	public string Result()
	{
		return PtrToStringUTF8(VoskPINVOKE.VoskRecognizer_Result(handle));
	}

	public string PartialResult()
	{
		return PtrToStringUTF8(VoskPINVOKE.VoskRecognizer_PartialResult(handle));
	}

	public string FinalResult()
	{
		return PtrToStringUTF8(VoskPINVOKE.VoskRecognizer_FinalResult(handle));
	}

	public void Reset()
	{
		VoskPINVOKE.VoskRecognizer_Reset(handle);
	}
}