Decompiled source of ModConfigEnforcer v4.0.4

ModConfigEnforcer.dll

Decompiled 2 months ago
using System;
using System.Collections;
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 BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Steamworks;
using UnityEngine;
using ZstdNet;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ModConfigEnforcer")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ModConfigEnforcer")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("7e7b5c74-ddfd-4667-980a-04c189e07c67")]
[assembly: AssemblyFileVersion("4.0.4")]
[assembly: TargetFramework(".NETFramework,Version=v4.6.1", FrameworkDisplayName = ".NET Framework 4.6.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("4.0.4.0")]
[module: UnverifiableCode]
namespace ModConfigEnforcer;

public interface IConfigVariable
{
	bool ValueChanged { get; set; }

	string GetName();

	bool LocalOnly();

	object GetValue();

	void SetValue(object o);

	Type GetValueType();

	void Serialize(ZPackage zpg);

	bool Deserialize(ZPackage zpg);

	void Cleanup();
}
public class AutomatedConfigWrapper<T> : IConfigVariable
{
	private ConfigEntry<T> _ConfigFileEntry;

	private FieldInfo _TypedValueFI;

	private T _LastValidValue;

	public bool ValueChanged { get; set; }

	public AutomatedConfigWrapper(ConfigEntry<T> configEntry)
	{
		_ConfigFileEntry = configEntry;
		_ConfigFileEntry.SettingChanged += SettingChanged;
		_TypedValueFI = ((object)configEntry).GetType().GetField("_typedValue", BindingFlags.Instance | BindingFlags.NonPublic);
	}

	private void SettingChanged(object sender, EventArgs e)
	{
		ref T reference = ref _LastValidValue;
		T val = default(T);
		if (val == null)
		{
			val = reference;
			reference = ref val;
		}
		if (!reference.Equals(_ConfigFileEntry.Value))
		{
			if (!ConfigManager.ShouldUseLocalConfig)
			{
				SetValue(_LastValidValue);
			}
			else
			{
				_LastValidValue = (T)GetValue();
			}
		}
	}

	public string GetName()
	{
		return ((ConfigEntryBase)_ConfigFileEntry).Definition.Key;
	}

	public bool LocalOnly()
	{
		return false;
	}

	public Type GetValueType()
	{
		return typeof(T);
	}

	public object GetValue()
	{
		return ConfigManager.ShouldUseLocalConfig ? _ConfigFileEntry.Value : _LastValidValue;
	}

	public void SetValue(object o)
	{
		_LastValidValue = (T)o;
		if (ConfigManager.ShouldUseLocalConfig)
		{
			ValueChanged = !_ConfigFileEntry.Value.Equals(_LastValidValue);
			_ConfigFileEntry.Value = _LastValidValue;
		}
		else
		{
			_TypedValueFI.SetValue(_ConfigFileEntry, o);
		}
	}

	public void Serialize(ZPackage zpg)
	{
		object value = GetValue();
		zpg.FillZPackage(GetValueType().IsEnum ? ((object)(int)value) : value);
		ValueChanged = false;
	}

	public bool Deserialize(ZPackage zpg)
	{
		return false;
	}

	public void Cleanup()
	{
	}
}
public class ConfigVariable<T> : IConfigVariable
{
	private ConfigEntry<T> _ConfigFileEntry;

	private T _LocalValue;

	private bool _LocalOnly;

	public string Key => ((ConfigEntryBase)_ConfigFileEntry).Definition.Key;

	public T Value
	{
		get
		{
			if (!_LocalOnly)
			{
				if (!ConfigManager.ShouldUseLocalConfig)
				{
					return _LocalValue;
				}
				return _ConfigFileEntry.Value;
			}
			return _ConfigFileEntry.Value;
		}
	}

	public bool ValueChanged { get; set; }

	public ConfigVariable(ConfigFile config, string section, string key, T defaultValue, string description, bool localOnly)
	{
		_ConfigFileEntry = config.Bind<T>(section, key, defaultValue, description);
		_LocalValue = _ConfigFileEntry.Value;
		_LocalOnly = localOnly;
	}

	public ConfigVariable(ConfigFile config, string section, string key, T defaultValue, ConfigDescription description, bool localOnly)
	{
		_ConfigFileEntry = config.Bind<T>(section, key, defaultValue, description);
		_LocalValue = _ConfigFileEntry.Value;
		_LocalOnly = localOnly;
	}

	public ConfigVariable(ConfigEntry<T> configFileEntry)
	{
		_ConfigFileEntry = configFileEntry;
		_LocalValue = _ConfigFileEntry.Value;
		_LocalOnly = false;
	}

	public string GetName()
	{
		return Key;
	}

	public bool LocalOnly()
	{
		return _LocalOnly;
	}

	public Type GetValueType()
	{
		return typeof(T);
	}

	public object GetValue()
	{
		return Value;
	}

	public void SetValue(object o)
	{
		T val = (T)o;
		if (ConfigManager.ShouldUseLocalConfig)
		{
			ValueChanged = !_ConfigFileEntry.Value.Equals(val);
			_ConfigFileEntry.Value = val;
		}
		else
		{
			_LocalValue = val;
		}
	}

	public void Serialize(ZPackage zpg)
	{
		object value = GetValue();
		zpg.FillZPackage(GetValueType().IsEnum ? ((object)(int)value) : value);
		ValueChanged = false;
	}

	public bool Deserialize(ZPackage zpg)
	{
		return false;
	}

	public void Cleanup()
	{
	}
}
public class ClientVariable<T> : IConfigVariable
{
	private T _Value;

	private string _Name;

	public T Value => _Value;

	public bool ValueChanged
	{
		get
		{
			return false;
		}
		set
		{
		}
	}

	public ClientVariable(string name, T value)
	{
		_Name = name;
		_Value = value;
	}

	public string GetName()
	{
		return _Name;
	}

	public object GetValue()
	{
		return Value;
	}

	public Type GetValueType()
	{
		return typeof(T);
	}

	public void SetValue(object o)
	{
		_Value = (T)o;
	}

	public bool LocalOnly()
	{
		return true;
	}

	public void Serialize(ZPackage zpg)
	{
	}

	public bool Deserialize(ZPackage zpg)
	{
		return false;
	}

	public void Cleanup()
	{
	}
}
public class FileWatcherVariable : IConfigVariable
{
	private ConfigManager.ModConfig _Mod;

	private string _Name;

	private bool _LocalOnly;

	private ZPackage _FileContents;

	private string WatchedFilePath;

	private string RelativePath;

	private FileSystemWatcher FSW;

	private Action<string, ZPackage> FileContentsChanged;

	public bool ValueChanged { get; set; }

	private int GetLengthOfPathCommonality(string path1, string path2)
	{
		path1 = Path.GetFullPath(path1).ToLower();
		path2 = Path.GetFullPath(path2).ToLower();
		int result = -1;
		int num = Mathf.Min(path1.Length, path2.Length);
		for (int i = 0; i < num; i++)
		{
			if (path1[i] != path2[i])
			{
				if (path1[i] == Path.DirectorySeparatorChar || path1[i] == Path.AltDirectorySeparatorChar)
				{
					if (path2[i] != Path.DirectorySeparatorChar && path2[i] != Path.AltDirectorySeparatorChar)
					{
						break;
					}
					result = i + 1;
				}
				else if (path2[i] == Path.DirectorySeparatorChar || path2[i] == Path.AltDirectorySeparatorChar)
				{
					break;
				}
			}
			else if (path1[i] == Path.DirectorySeparatorChar || path1[i] == Path.AltDirectorySeparatorChar)
			{
				result = i + 1;
			}
		}
		return result;
	}

	public FileWatcherVariable(ConfigManager.ModConfig mod, string filepath, bool localOnly, Action<string, ZPackage> handler)
	{
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0106: Expected O, but got Unknown
		//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: Expected O, but got Unknown
		_Mod = mod;
		WatchedFilePath = filepath;
		int lengthOfPathCommonality = GetLengthOfPathCommonality(WatchedFilePath, Assembly.GetCallingAssembly().Location);
		if (lengthOfPathCommonality == -1)
		{
			RelativePath = WatchedFilePath;
		}
		else
		{
			RelativePath = WatchedFilePath.Substring(lengthOfPathCommonality);
		}
		Plugin.Log.LogInfo((object)("Watching " + WatchedFilePath + " with RelativePath " + RelativePath));
		FSW = new FileSystemWatcher(Path.GetDirectoryName(WatchedFilePath));
		FSW.Filter = Path.GetFileName(filepath);
		FSW.NotifyFilter = NotifyFilters.Size | NotifyFilters.LastWrite;
		FSW.IncludeSubdirectories = false;
		_Name = "FileWatcher_" + FSW.Filter;
		_LocalOnly = localOnly;
		if (File.Exists(WatchedFilePath))
		{
			_FileContents = new ZPackage(File.ReadAllBytes(WatchedFilePath));
		}
		else
		{
			_FileContents = new ZPackage();
		}
		FileContentsChanged = handler;
		FSW.Changed += FSW_Changed;
		FSW.EnableRaisingEvents = true;
	}

	private void FSW_Changed(object sender, FileSystemEventArgs e)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Expected O, but got Unknown
		if (_LocalOnly || ConfigManager.ShouldUseLocalConfig)
		{
			_FileContents = new ZPackage(File.ReadAllBytes(WatchedFilePath));
			FileContentsChanged?.Invoke(RelativePath, _FileContents);
			if (!_LocalOnly && Object.op_Implicit((Object)(object)ZNet.instance) && Plugin.IsAdmin(Player.m_localPlayer))
			{
				ConfigManager.SendConfigToClient(_Mod.Name, changesOnly: true, 0L);
			}
		}
	}

	public string GetName()
	{
		return _Name;
	}

	public bool LocalOnly()
	{
		return _LocalOnly;
	}

	public object GetValue()
	{
		return _FileContents;
	}

	public Type GetValueType()
	{
		return typeof(ZPackage);
	}

	public void SetValue(object o)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Expected O, but got Unknown
		ValueChanged = true;
		ZPackage val = (ZPackage)((o is ZPackage) ? o : null);
		_FileContents = new ZPackage(val.GetArray());
		FileContentsChanged?.Invoke(RelativePath, _FileContents);
	}

	public void Serialize(ZPackage zpg)
	{
		zpg.Write(_FileContents);
	}

	public bool Deserialize(ZPackage zpg)
	{
		return false;
	}

	public void Cleanup()
	{
		FSW.Dispose();
	}
}
public static class ConfigManager
{
	private class PackageTrackerInfo
	{
		private ZPackage[] Packages;

		public int Received { get; private set; }

		public int Total
		{
			get
			{
				ZPackage[] packages = Packages;
				if (packages == null)
				{
					return 0;
				}
				return packages.Length;
			}
		}

		public bool Add(ZPackage zpg)
		{
			int num = zpg.ReadInt();
			int num2 = zpg.ReadInt();
			Plugin.Log.LogDebug((object)("Client received package " + num + " of " + num2));
			if (Packages == null)
			{
				Packages = (ZPackage[])(object)new ZPackage[num2];
			}
			if (Packages[num - 1] == null)
			{
				Packages[num - 1] = zpg;
				return ++Received == num2;
			}
			return false;
		}

		public ZPackage GetPackage()
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			if (Received != Total)
			{
				return null;
			}
			using MemoryStream memoryStream = new MemoryStream();
			for (int i = 0; i < Packages.Length; i++)
			{
				byte[] array = Packages[i].ReadByteArray();
				memoryStream.Write(array, 0, array.Length);
				Packages[i] = null;
			}
			Packages = null;
			memoryStream.Flush();
			return new ZPackage(memoryStream.ToArray());
		}
	}

	public class ModConfig
	{
		public string Name;

		public ConfigFile Config;

		public List<IConfigVariable> Variables = new List<IConfigVariable>();

		public Action ServerConfigReceived;

		public Action ConfigReloaded;

		public string GetRegistrationType()
		{
			bool flag = false;
			bool flag2 = false;
			foreach (IConfigVariable variable in Variables)
			{
				if (variable.GetType() == typeof(ConfigVariable<>))
				{
					flag = true;
				}
				else if (variable.GetType() == typeof(AutomatedConfigWrapper<>))
				{
					flag2 = true;
				}
			}
			if (flag && flag2)
			{
				return "manual and automated discovery";
			}
			if (flag)
			{
				return "manual";
			}
			return "automated discovery";
		}

		public void SortVariables()
		{
			Variables.Sort((IConfigVariable a, IConfigVariable b) => string.Compare(a.GetName(), b.GetName()));
		}

		public ZPackage Serialize(bool changesOnly = false)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			ZPackage val = null;
			bool flag = false;
			for (int i = 0; i < Variables.Count; i++)
			{
				if (!Variables[i].LocalOnly() && (!changesOnly || Variables[i].ValueChanged))
				{
					if (!flag)
					{
						val = new ZPackage();
						flag = true;
						val.Write(Name);
					}
					val.Write(i);
					Variables[i].Serialize(val);
				}
			}
			return val;
		}

		public void Deserialize(ZPackage zpg)
		{
			while (zpg.m_reader.PeekChar() > -1)
			{
				int num = zpg.ReadInt();
				if (num < 0 || num >= Variables.Count)
				{
					Plugin.Log.LogError((object)("Invalid variable index " + num + " read from package, aborting deserialization for mod " + Name));
					break;
				}
				try
				{
					zpg.ReadVariable(Variables[num]);
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)("Exception deserializing variable " + Variables[num].GetName() + " @ " + num + " for mod " + Name + ": " + ex.Message));
					break;
				}
			}
		}

		public void Cleanup()
		{
			foreach (IConfigVariable variable in Variables)
			{
				variable.Cleanup();
			}
		}
	}

	private static Dictionary<ulong, PackageTrackerInfo> PackageTracking = new Dictionary<ulong, PackageTrackerInfo>();

	private const string ConfigRPCName = "ClientReceiveConfigData";

	private static ulong LastPackageID;

	public static bool ShouldUseLocalConfig = true;

	private static readonly List<string> Mods = new List<string>();

	private static readonly Dictionary<string, ModConfig> ModConfigs = new Dictionary<string, ModConfig>();

	private static readonly Dictionary<string, IConfigVariable> AutomatedConfigsLocked = new Dictionary<string, IConfigVariable>();

	public static event Action<string> UnknownModConfigReceived;

	public static bool IsConfigLocked(string name)
	{
		return AutomatedConfigsLocked.ContainsKey(name);
	}

	public static void RegisterRPC(ZRpc zrpc)
	{
		zrpc.Register<ZPackage>("ClientReceiveConfigData", (Action<ZRpc, ZPackage>)ClientReceiveConfigData);
	}

	internal static List<ModConfig> GetRegisteredModConfigs()
	{
		return ModConfigs.Values.ToList();
	}

	internal static ModConfig GetRegisteredModConfig(string name, bool ignoreCase)
	{
		if (!ignoreCase)
		{
			if (ModConfigs.TryGetValue(name, out var value))
			{
				return value;
			}
			return null;
		}
		return ModConfigs.Values.FirstOrDefault((ModConfig mc) => string.Compare(mc.Name, name, ignoreCase: true) == 0);
	}

	public static void RegisterMod(string modName, ConfigFile configFile, Action scrd = null, Action cr = null)
	{
		if (ModConfigs.TryGetValue(modName, out var value))
		{
			value.Variables.Clear();
			return;
		}
		Mods.Add(modName);
		ModConfigs[modName] = new ModConfig
		{
			Name = modName,
			Config = configFile,
			ServerConfigReceived = scrd,
			ConfigReloaded = cr
		};
		configFile.ConfigReloaded += ConfigFile_ConfigReloaded;
	}

	private static void ConfigFile_ConfigReloaded(object sender, EventArgs e)
	{
		if (Object.op_Implicit((Object)(object)ZNet.instance) && !ZNet.instance.IsDedicated() && !ZNet.instance.IsServer())
		{
			return;
		}
		List<ModConfig> list = new List<ModConfig>();
		foreach (ModConfig item in ModConfigs.Values.Where((ModConfig mc) => mc.Config == sender))
		{
			list.Add(item);
			item.ConfigReloaded?.Invoke();
		}
		if (list.Count > 0)
		{
			SendConfigsToClients(list, changesOnly: true);
		}
	}

	public static ConfigVariable<T> RegisterModConfigVariable<T>(string modName, string varName, T defaultValue, string configSection, string configDescription, bool localOnly)
	{
		if (!ModConfigs.TryGetValue(modName, out var value))
		{
			return null;
		}
		ConfigVariable<T> configVariable = new ConfigVariable<T>(value.Config, configSection, varName, defaultValue, configDescription, localOnly);
		value.Variables.Add(configVariable);
		return configVariable;
	}

	public static ConfigVariable<T> RegisterModConfigVariable<T>(string modName, string varName, T defaultValue, string configSection, ConfigDescription configDescription, bool localOnly)
	{
		if (!ModConfigs.TryGetValue(modName, out var value))
		{
			return null;
		}
		ConfigVariable<T> configVariable = new ConfigVariable<T>(value.Config, configSection, varName, defaultValue, configDescription, localOnly);
		value.Variables.Add(configVariable);
		return configVariable;
	}

	public static void RegisterAutomatedModConfigVariable<T>(string modName, ConfigEntry<T> entry)
	{
		if (entry != null && ModConfigs.TryGetValue(modName, out var value))
		{
			AutomatedConfigWrapper<T> automatedConfigWrapper = new AutomatedConfigWrapper<T>(entry);
			AutomatedConfigsLocked.Add(automatedConfigWrapper.GetName(), automatedConfigWrapper);
			value.Variables.Add(automatedConfigWrapper);
		}
	}

	public static ClientVariable<T> RegisterClientVariable<T>(string modName, string varName, T value)
	{
		ClientVariable<T> clientVariable = new ClientVariable<T>(varName, value);
		if (RegisterModConfigVariable(modName, clientVariable))
		{
			return clientVariable;
		}
		return null;
	}

	public static bool RegisterModConfigVariable(string modName, IConfigVariable cv)
	{
		if (!ModConfigs.TryGetValue(modName, out var value))
		{
			return false;
		}
		value.Variables.Add(cv);
		return true;
	}

	public static FileWatcherVariable RegisterModFileWatcher(string modName, string filePath, bool localOnly, Action<string, ZPackage> handler)
	{
		if (!ModConfigs.TryGetValue(modName, out var value))
		{
			return null;
		}
		FileWatcherVariable fileWatcherVariable = new FileWatcherVariable(value, filePath, localOnly, handler);
		value.Variables.Add(fileWatcherVariable);
		return fileWatcherVariable;
	}

	public static void SortModVariables(string modName)
	{
		if (ModConfigs.TryGetValue(modName, out var value))
		{
			value.SortVariables();
		}
	}

	private static void ReadVariable(this ZPackage zp, IConfigVariable cv)
	{
		//IL_0231: Unknown result type (might be due to invalid IL or missing references)
		//IL_026c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0290: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b9: Expected O, but got Unknown
		Type valueType = cv.GetValueType();
		if (valueType == typeof(int))
		{
			cv.SetValue(zp.ReadInt());
		}
		else if (valueType == typeof(uint))
		{
			cv.SetValue(zp.ReadUInt());
		}
		else if (valueType == typeof(bool))
		{
			cv.SetValue(zp.ReadBool());
		}
		else if (valueType == typeof(byte))
		{
			cv.SetValue(zp.ReadByte());
		}
		else if (valueType == typeof(byte[]))
		{
			cv.SetValue(zp.ReadByteArray());
		}
		else if (valueType == typeof(char))
		{
			cv.SetValue(zp.ReadChar());
		}
		else if (valueType == typeof(sbyte))
		{
			cv.SetValue(zp.ReadSByte());
		}
		else if (valueType == typeof(long))
		{
			cv.SetValue(zp.ReadLong());
		}
		else if (valueType == typeof(ulong))
		{
			cv.SetValue(zp.ReadULong());
		}
		else if (valueType == typeof(float))
		{
			cv.SetValue(zp.ReadSingle());
		}
		else if (valueType == typeof(double))
		{
			cv.SetValue(zp.ReadDouble());
		}
		else if (valueType == typeof(string))
		{
			cv.SetValue(zp.ReadString());
		}
		else if (valueType == typeof(ZPackage))
		{
			cv.SetValue(zp.ReadPackage());
		}
		else if (valueType == typeof(List<string>))
		{
			int num = zp.ReadInt();
			List<string> list = new List<string>(num);
			for (int i = 0; i < num; i++)
			{
				list.Add(zp.ReadString());
			}
			cv.SetValue(list);
		}
		else if (valueType == typeof(Vector3))
		{
			cv.SetValue((object)new Vector3(zp.ReadSingle(), zp.ReadSingle(), zp.ReadSingle()));
		}
		else if (valueType == typeof(Quaternion))
		{
			cv.SetValue((object)new Quaternion(zp.ReadSingle(), zp.ReadSingle(), zp.ReadSingle(), zp.ReadSingle()));
		}
		else if (valueType == typeof(ZDOID))
		{
			cv.SetValue(zp.ReadZDOID());
		}
		else if (valueType == typeof(HitData))
		{
			HitData val = new HitData();
			val.Deserialize(ref zp);
			cv.SetValue(val);
		}
		else if (valueType.IsEnum)
		{
			cv.SetValue(zp.ReadInt());
		}
		else if (!cv.Deserialize(zp))
		{
			Plugin.Log.LogError((object)("Unable to deserialize data for " + cv.ToString()));
		}
	}

	public static void FillZPackage(this ZPackage zp, params object[] ps)
	{
		ZRpc.Serialize(ps, ref zp);
	}

	private static ZPackage SerializeMod(string modname, bool changesOnly)
	{
		if (!ModConfigs.TryGetValue(modname, out var value))
		{
			return null;
		}
		return value.Serialize(changesOnly);
	}

	public static ZPackage[] CompressPackage(ZPackage data)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Expected O, but got Unknown
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: Expected O, but got Unknown
		byte[] array = new Compressor().Wrap(data.GetArray());
		int num = array.Length / 450000 + 1;
		ZPackage[] array2 = (ZPackage[])(object)new ZPackage[num];
		int num2 = array.Length / num;
		LastPackageID++;
		byte[] array3;
		ZPackage val;
		for (int i = 0; i < num - 1; i++)
		{
			array3 = new byte[num2];
			Array.Copy(array, i * num2, array3, 0, array3.Length);
			val = new ZPackage();
			val.Write(LastPackageID);
			val.Write(i + 1);
			val.Write(num);
			val.Write(array3);
			array2[i] = val;
		}
		int num3 = (num - 1) * num2;
		array3 = new byte[array.Length - num3];
		Array.Copy(array, num3, array3, 0, array3.Length);
		val = new ZPackage();
		val.Write(LastPackageID);
		val.Write(num);
		val.Write(num);
		val.Write(array3);
		array2[^1] = val;
		return array2;
	}

	public static void SendConfigToClient(string modname, bool changesOnly, long peerID = 0L)
	{
		if (!ZNet.instance.IsDedicated() && !ZNet.instance.IsServer())
		{
			return;
		}
		ZPackage val = SerializeMod(modname, changesOnly);
		if (val != null)
		{
			ZPackage[] array = CompressPackage(val);
			for (int i = 0; i < array.Length; i++)
			{
				ZNet.instance.m_routedRpc.InvokeRoutedRPC(peerID, "ClientReceiveConfigData", new object[1] { array[i] });
			}
		}
	}

	private static void SendConfigsToClients(List<ModConfig> list, bool changesOnly)
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Expected O, but got Unknown
		if (!Object.op_Implicit((Object)(object)ZNet.instance) || (!ZNet.instance.IsDedicated() && !ZNet.instance.IsServer()))
		{
			return;
		}
		ZPackage val = new ZPackage();
		foreach (ModConfig item in list)
		{
			ZPackage val2 = item.Serialize(changesOnly);
			if (val2 != null)
			{
				val.Write(val2);
			}
		}
		if (val.Size() > 0)
		{
			ZPackage[] array = CompressPackage(val);
			for (int i = 0; i < array.Length; i++)
			{
				ZNet.instance.m_routedRpc.InvokeRoutedRPC(ZNetView.Everybody, "ClientReceiveConfigData", new object[1] { array[i] });
			}
		}
	}

	public static void SendConfigsToClient(ZRpc rpc)
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Expected O, but got Unknown
		if (!Object.op_Implicit((Object)(object)ZNet.instance) || (!ZNet.instance.IsDedicated() && !ZNet.instance.IsServer()))
		{
			return;
		}
		ZPackage val = new ZPackage();
		foreach (string mod in Mods)
		{
			ZPackage val2 = SerializeMod(mod, changesOnly: false);
			if (val2 != null)
			{
				val.Write(val2);
			}
		}
		if (val.Size() > 0)
		{
			ZPackage[] data = CompressPackage(val);
			Plugin.instance.SendDataToZRpc(rpc, "ClientReceiveConfigData", data);
		}
	}

	private static void ClientReceiveConfigData(ZRpc rpc, ZPackage data)
	{
		if (ZNet.instance.IsDedicated() || ZNet.instance.IsServer())
		{
			Plugin.Log.LogWarning((object)"Server should not be sent config values!");
			return;
		}
		ulong key = data.ReadULong();
		if (!PackageTracking.TryGetValue(key, out var value))
		{
			Plugin.Log.LogDebug((object)("Client received new packageID " + key));
			value = new PackageTrackerInfo();
			PackageTracking[key] = value;
		}
		if (value.Add(data))
		{
			SetConfigValues(value.GetPackage());
		}
	}

	private static void SetConfigValues(ZPackage data)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Expected O, but got Unknown
		ShouldUseLocalConfig = false;
		Dictionary<string, ModConfig> dictionary = new Dictionary<string, ModConfig>();
		ZPackage val = new ZPackage(new Decompressor().Unwrap(data.GetArray(), int.MaxValue).ToArray());
		try
		{
			ZPackage val2 = val.ReadPackage();
			while (val2 != null)
			{
				string text = val2.ReadString();
				if (!string.IsNullOrWhiteSpace(text))
				{
					if (!ModConfigs.TryGetValue(text, out var value))
					{
						ConfigManager.UnknownModConfigReceived?.Invoke(text);
						if (!ModConfigs.TryGetValue(text, out value))
						{
							Plugin.Log.LogError((object)("Could not find registered mod " + text));
							continue;
						}
						Plugin.Log.LogInfo((object)("Client received data for previously unregistered mod config " + text));
					}
					value.Deserialize(val2);
					dictionary[text] = value;
					Plugin.Log.LogDebug((object)("Client updated with settings for mod " + text));
				}
				val2 = ((val.m_reader.PeekChar() == -1) ? null : val.ReadPackage());
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("Exception on client SetConfigValues: " + ex.Message));
		}
		foreach (ModConfig value2 in dictionary.Values)
		{
			value2.ServerConfigReceived?.Invoke();
		}
	}

	public static void ClearModConfigs()
	{
		Mods.Clear();
		foreach (ModConfig value in ModConfigs.Values)
		{
			value.Cleanup();
		}
		ModConfigs.Clear();
		AutomatedConfigsLocked.Clear();
	}
}
internal sealed class Patches
{
	[HarmonyPatch(typeof(ZNet))]
	public static class ZNetPatches
	{
		[HarmonyPrefix]
		[HarmonyPatch("Awake")]
		public static void AwakePrefix(ZNet __instance)
		{
			ConfigManager.ShouldUseLocalConfig = true;
		}

		[HarmonyPrefix]
		[HarmonyPriority(int.MaxValue)]
		[HarmonyPatch("OnNewConnection")]
		public static void OnNewConnectionPrefix(ZNet __instance, ZNetPeer peer)
		{
			ConfigManager.ShouldUseLocalConfig = true;
			if (!__instance.IsDedicated() && !__instance.IsServer())
			{
				ConfigManager.RegisterRPC(peer.m_rpc);
			}
		}

		[HarmonyPrefix]
		[HarmonyPriority(int.MaxValue)]
		[HarmonyPatch("RPC_ServerHandshake")]
		public static void RPC_ServerHandshakePrefix(ZNet __instance, ZRpc rpc)
		{
			if (__instance.IsDedicated() || __instance.IsServer())
			{
				ConfigManager.SendConfigsToClient(rpc);
			}
		}
	}

	[HarmonyPatch(typeof(ConfigEntryBase))]
	public static class BepinexConfigEntryBasePatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("OnSettingChanged")]
		public static bool OnSettingChangedPrefix(object __instance)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			if (!ConfigManager.IsConfigLocked(((ConfigEntryBase)__instance).Definition.Key))
			{
				return true;
			}
			return ConfigManager.ShouldUseLocalConfig;
		}
	}

	[HarmonyPatch(typeof(Terminal))]
	public static class TerminalPatches
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static ConsoleEvent <>9__0_0;

			internal void <InitTerminalPostfix>b__0_0(ConsoleEventArgs args)
			{
				bool flag = !Object.op_Implicit((Object)(object)ZNet.instance) || ZNet.instance.IsDedicated() || ZNet.instance.IsServer();
				if (!flag)
				{
					flag = Object.op_Implicit((Object)(object)Player.m_localPlayer) && ZNet.instance.ListContainsId(ZNet.instance.m_adminList, ZNet.instance.GetPeer(((ZDOID)(ref ((Character)Player.m_localPlayer).m_nview.GetZDO().m_uid)).UserID).m_rpc.GetSocket().GetHostName());
				}
				for (int i = 0; i < args.Args.Length; i++)
				{
					args.Args[i] = args[i].ToLower();
				}
				if (args.Length == 2)
				{
					if (args[1] == "list")
					{
						foreach (ConfigManager.ModConfig registeredModConfig2 in ConfigManager.GetRegisteredModConfigs())
						{
							args.Context.AddString(".. " + registeredModConfig2.Name + " (" + registeredModConfig2.GetRegistrationType() + ")");
						}
						return;
					}
					if (args[1] == "reload")
					{
						if (flag)
						{
							args.Context.AddString(".. missing mod registration name");
						}
						else
						{
							args.Context.AddString("<color=orange>mce reload</color> is not available on clients in multiplayer.");
						}
					}
					else
					{
						args.Context.AddString(".. unknown command option '" + args[1] + "'");
					}
				}
				else if (args.Length > 2)
				{
					if (args[1] == "reload" && !flag)
					{
						args.Context.AddString("<color=orange>mce reload</color> is not available on clients in multiplayer.");
					}
					else if (args[1] == "list" || args[1] == "reload")
					{
						string text = "";
						for (int j = 2; j < args.Length; j++)
						{
							text += ((j > 2) ? (" " + args[j]) : args[j]);
						}
						ConfigManager.ModConfig registeredModConfig = ConfigManager.GetRegisteredModConfig(text, ignoreCase: true);
						if (registeredModConfig == null)
						{
							args.Context.AddString(".. mod named '" + text + "' not found!");
							return;
						}
						if (args[1] == "list")
						{
							foreach (IConfigVariable variable in registeredModConfig.Variables)
							{
								string name = variable.GetType().Name;
								name = name.Remove(name.IndexOf('`'));
								args.Context.AddString(".. " + variable.GetName() + " :" + (variable.LocalOnly() ? " localOnly " : " ") + name + " : " + variable.GetValue());
							}
							return;
						}
						args.Context.AddString(".. reloading config for " + text);
						registeredModConfig.Config.Reload();
					}
					else
					{
						args.Context.AddString(".. unknown command option '" + args[1] + "'");
					}
				}
				else
				{
					args.Context.AddString("<color=orange>mce</color> command supports the following options :");
					args.Context.AddString("<color=yellow>list</color> - displays a list of each mod registered with MCE and their registration method");
					args.Context.AddString("<color=yellow>list <mod registration name></color> - displays a list of all config options registered for the mod");
					if (flag)
					{
						args.Context.AddString("<color=yellow>reload <mod registration name></color> - reloads the config options from file for the mod (on servers, this will also send config updates to all clients)");
					}
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("InitTerminal")]
		public static void InitTerminalPostfix(Terminal __instance)
		{
			//IL_0032: 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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			object obj = <>c.<>9__0_0;
			if (obj == null)
			{
				ConsoleEvent val = delegate(ConsoleEventArgs args)
				{
					bool flag = !Object.op_Implicit((Object)(object)ZNet.instance) || ZNet.instance.IsDedicated() || ZNet.instance.IsServer();
					if (!flag)
					{
						flag = Object.op_Implicit((Object)(object)Player.m_localPlayer) && ZNet.instance.ListContainsId(ZNet.instance.m_adminList, ZNet.instance.GetPeer(((ZDOID)(ref ((Character)Player.m_localPlayer).m_nview.GetZDO().m_uid)).UserID).m_rpc.GetSocket().GetHostName());
					}
					for (int i = 0; i < args.Args.Length; i++)
					{
						args.Args[i] = args[i].ToLower();
					}
					if (args.Length == 2)
					{
						if (args[1] == "list")
						{
							foreach (ConfigManager.ModConfig registeredModConfig2 in ConfigManager.GetRegisteredModConfigs())
							{
								args.Context.AddString(".. " + registeredModConfig2.Name + " (" + registeredModConfig2.GetRegistrationType() + ")");
							}
							return;
						}
						if (args[1] == "reload")
						{
							if (flag)
							{
								args.Context.AddString(".. missing mod registration name");
							}
							else
							{
								args.Context.AddString("<color=orange>mce reload</color> is not available on clients in multiplayer.");
							}
						}
						else
						{
							args.Context.AddString(".. unknown command option '" + args[1] + "'");
						}
					}
					else if (args.Length > 2)
					{
						if (args[1] == "reload" && !flag)
						{
							args.Context.AddString("<color=orange>mce reload</color> is not available on clients in multiplayer.");
						}
						else if (args[1] == "list" || args[1] == "reload")
						{
							string text = "";
							for (int j = 2; j < args.Length; j++)
							{
								text += ((j > 2) ? (" " + args[j]) : args[j]);
							}
							ConfigManager.ModConfig registeredModConfig = ConfigManager.GetRegisteredModConfig(text, ignoreCase: true);
							if (registeredModConfig == null)
							{
								args.Context.AddString(".. mod named '" + text + "' not found!");
							}
							else
							{
								if (args[1] == "list")
								{
									foreach (IConfigVariable variable in registeredModConfig.Variables)
									{
										string name = variable.GetType().Name;
										name = name.Remove(name.IndexOf('`'));
										args.Context.AddString(".. " + variable.GetName() + " :" + (variable.LocalOnly() ? " localOnly " : " ") + name + " : " + variable.GetValue());
									}
									return;
								}
								args.Context.AddString(".. reloading config for " + text);
								registeredModConfig.Config.Reload();
							}
						}
						else
						{
							args.Context.AddString(".. unknown command option '" + args[1] + "'");
						}
					}
					else
					{
						args.Context.AddString("<color=orange>mce</color> command supports the following options :");
						args.Context.AddString("<color=yellow>list</color> - displays a list of each mod registered with MCE and their registration method");
						args.Context.AddString("<color=yellow>list <mod registration name></color> - displays a list of all config options registered for the mod");
						if (flag)
						{
							args.Context.AddString("<color=yellow>reload <mod registration name></color> - reloads the config options from file for the mod (on servers, this will also send config updates to all clients)");
						}
					}
				};
				<>c.<>9__0_0 = val;
				obj = (object)val;
			}
			new ConsoleCommand("mce", "shows info for Mod Config Enforcer", (ConsoleEvent)obj, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
		}
	}

	public static class ZSteamSocketPatches
	{
		public static bool RegisterGlobalCallbacksPrefix()
		{
			if (ZSteamSocket.m_statusChanged == null)
			{
				GCHandle gCHandle = GCHandle.Alloc(30000f, GCHandleType.Pinned);
				GCHandle gCHandle2 = GCHandle.Alloc(1, GCHandleType.Pinned);
				GCHandle gCHandle3 = GCHandle.Alloc(0, GCHandleType.Pinned);
				try
				{
					ZSteamSocket.m_statusChanged = Callback<SteamNetConnectionStatusChangedCallback_t>.Create((DispatchDelegate<SteamNetConnectionStatusChangedCallback_t>)ZSteamSocket.OnStatusChanged);
					SteamNetworkingUtils.SetConfigValue((ESteamNetworkingConfigValue)25, (ESteamNetworkingConfigScope)1, IntPtr.Zero, (ESteamNetworkingConfigDataType)3, gCHandle.AddrOfPinnedObject());
					SteamNetworkingUtils.SetConfigValue((ESteamNetworkingConfigValue)23, (ESteamNetworkingConfigScope)1, IntPtr.Zero, (ESteamNetworkingConfigDataType)1, gCHandle2.AddrOfPinnedObject());
					SteamNetworkingUtils.SetConfigValue((ESteamNetworkingConfigValue)12, (ESteamNetworkingConfigScope)1, IntPtr.Zero, (ESteamNetworkingConfigDataType)1, gCHandle3.AddrOfPinnedObject());
				}
				catch
				{
				}
				try
				{
					ZSteamSocket.m_statusChanged = Callback<SteamNetConnectionStatusChangedCallback_t>.CreateGameServer((DispatchDelegate<SteamNetConnectionStatusChangedCallback_t>)ZSteamSocket.OnStatusChanged);
					SteamGameServerNetworkingUtils.SetConfigValue((ESteamNetworkingConfigValue)25, (ESteamNetworkingConfigScope)1, IntPtr.Zero, (ESteamNetworkingConfigDataType)3, gCHandle.AddrOfPinnedObject());
					SteamGameServerNetworkingUtils.SetConfigValue((ESteamNetworkingConfigValue)23, (ESteamNetworkingConfigScope)1, IntPtr.Zero, (ESteamNetworkingConfigDataType)1, gCHandle2.AddrOfPinnedObject());
					SteamGameServerNetworkingUtils.SetConfigValue((ESteamNetworkingConfigValue)12, (ESteamNetworkingConfigScope)1, IntPtr.Zero, (ESteamNetworkingConfigDataType)1, gCHandle3.AddrOfPinnedObject());
				}
				catch
				{
				}
				gCHandle.Free();
				gCHandle2.Free();
				gCHandle3.Free();
			}
			return false;
		}
	}
}
[BepInPlugin("pfhoenix.modconfigenforcer", "Mod Config Enforcer", "4.0.4")]
public class Plugin : BaseUnityPlugin
{
	[CompilerGenerated]
	private sealed class <SendDataViaZRpc>d__7 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public ZRpc peer;

		public string rpc;

		public ZPackage[] zpgs;

		private int <i>5__2;

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

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

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

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

		private bool MoveNext()
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<i>5__2 = 0;
				break;
			case 1:
				<>1__state = -1;
				<i>5__2++;
				break;
			}
			if (<i>5__2 < zpgs.Length)
			{
				peer.GetSocket().Flush();
				peer.Invoke(rpc, new object[1] { zpgs[<i>5__2] });
				<>2__current = (object)new WaitForSecondsRealtime(1f);
				<>1__state = 1;
				return true;
			}
			return false;
		}

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

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

	public const string Version = "4.0.4";

	private Harmony _Harmony;

	public static ManualLogSource Log;

	public static Plugin instance;

	public static ConfigVariable<bool> OptimizeNetworking;

	private void Awake()
	{
		instance = this;
		Log = ((BaseUnityPlugin)this).Logger;
		Assembly assembly = ((object)this).GetType().Assembly;
		string[] array = new string[2] { "libzstd", "ZstdNet" };
		foreach (string text in array)
		{
			Stream manifestResourceStream = assembly.GetManifestResourceStream(assembly.GetName().Name + "." + text + ".dll");
			if (manifestResourceStream == null)
			{
				Log.LogError((object)("Failed to load " + text + ".dll from resource stream!"));
				continue;
			}
			string pluginPath = Paths.PluginPath;
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			string path = pluginPath + directorySeparatorChar + text + ".dll";
			if (!File.Exists(path))
			{
				using FileStream destination = new FileStream(path, FileMode.OpenOrCreate);
				manifestResourceStream.CopyTo(destination);
			}
		}
		ConfigManager.RegisterMod("_MCE_", ((BaseUnityPlugin)this).Config);
		OptimizeNetworking = ConfigManager.RegisterModConfigVariable("_MCE_", "Optimize Networking", defaultValue: true, "Networking", "Optimize Valheim's networking subsystem", localOnly: true);
		_Harmony = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null);
		if (!OptimizeNetworking.Value)
		{
			return;
		}
		Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
		foreach (Assembly assembly2 in assemblies)
		{
			if (assembly2.FullName.StartsWith("assembly_valheim"))
			{
				Type type = assembly2.GetType("ZSteamSocket");
				if (type != null)
				{
					MethodInfo method = type.GetMethod("RegisterGlobalCallbacks", BindingFlags.Static | BindingFlags.NonPublic);
					MethodInfo method2 = typeof(Patches.ZSteamSocketPatches).GetMethod("RegisterGlobalCallbacksPrefix", BindingFlags.Static | BindingFlags.Public);
					_Harmony.CreateProcessor((MethodBase)method).AddPrefix(method2).Patch();
				}
				break;
			}
		}
	}

	private void Start()
	{
		MethodInfo method = typeof(ConfigManager).GetMethod("RegisterAutomatedModConfigVariable", BindingFlags.Static | BindingFlags.Public);
		foreach (PluginInfo value in Chainloader.PluginInfos.Values)
		{
			if ((Object)(object)value.Instance == (Object)(object)this || !Object.op_Implicit((Object)(object)value.Instance) || !((Behaviour)value.Instance).isActiveAndEnabled)
			{
				continue;
			}
			Type type = ((object)value.Instance).GetType();
			FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			object obj = null;
			FieldInfo[] array = fields;
			foreach (FieldInfo fieldInfo in array)
			{
				if (string.Compare(fieldInfo.Name, "AutomatedConfigDiscovery", ignoreCase: true) == 0)
				{
					obj = fieldInfo.GetValue(value.Instance);
					break;
				}
			}
			if (obj == null)
			{
				continue;
			}
			Log.LogDebug((object)("... searching for configuration for " + value.Metadata.Name + " version " + value.Metadata.Version?.ToString() + " ..."));
			type = obj.GetType();
			Action scrd = null;
			MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			MethodInfo[] array2 = methods;
			foreach (MethodInfo methodInfo in array2)
			{
				if (string.Compare(methodInfo.Name, "ServerConfigReceived", ignoreCase: true) == 0)
				{
					scrd = (Action)Delegate.CreateDelegate(typeof(Action), obj, methodInfo);
					break;
				}
				if (string.Compare(methodInfo.Name, "ConfigReloaded", ignoreCase: true) == 0)
				{
					_ = (Action)Delegate.CreateDelegate(typeof(Action), obj, methodInfo);
					break;
				}
			}
			string text = null;
			FieldInfo[] fields2 = type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			int num = 0;
			array = fields2;
			foreach (FieldInfo fieldInfo2 in array)
			{
				if (fieldInfo2.FieldType.IsSubclassOf(typeof(ConfigEntryBase)) && !fieldInfo2.IsNotSerialized)
				{
					if (text == null)
					{
						text = value.Metadata.Name;
						ConfigManager.RegisterMod(text, value.Instance.Config, scrd);
					}
					method.MakeGenericMethod(fieldInfo2.FieldType.GetGenericArguments()[0]).Invoke(null, new object[2]
					{
						text,
						fieldInfo2.GetValue(obj)
					});
					Log.LogDebug((object)("... bound " + fieldInfo2.Name));
					num++;
				}
				else
				{
					if (!(fieldInfo2.FieldType == typeof(string)) || !fieldInfo2.Name.StartsWith("File_"))
					{
						continue;
					}
					fieldInfo2.Name.Substring(5);
					MethodInfo methodInfo2 = methods.FirstOrDefault((MethodInfo m) => string.Compare(m.Name, "FileChanged", ignoreCase: true) == 0);
					if (methodInfo2 != null)
					{
						if (text == null)
						{
							text = value.Metadata.Name;
							ConfigManager.RegisterMod(text, value.Instance.Config, scrd);
						}
						ConfigManager.RegisterModFileWatcher(text, (string)fieldInfo2.GetValue(obj), fieldInfo2.IsNotSerialized, (Action<string, ZPackage>)Delegate.CreateDelegate(typeof(Action<string, ZPackage>), obj, methodInfo2));
						Log.LogDebug((object)("... bound " + fieldInfo2.Name));
						num++;
					}
				}
			}
			if (num == 0)
			{
				Log.LogWarning((object)"... no configuration found to enforce!");
			}
			else
			{
				ConfigManager.SortModVariables(text);
			}
		}
	}

	[IteratorStateMachine(typeof(<SendDataViaZRpc>d__7))]
	private IEnumerator SendDataViaZRpc(ZRpc peer, string rpc, ZPackage[] zpgs)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <SendDataViaZRpc>d__7(0)
		{
			peer = peer,
			rpc = rpc,
			zpgs = zpgs
		};
	}

	public void SendDataToZRpc(ZRpc peer, string rpc, ZPackage[] data)
	{
		((MonoBehaviour)this).StartCoroutine(SendDataViaZRpc(peer, rpc, data));
	}

	public static bool IsAdmin(Player player)
	{
		if (!Object.op_Implicit((Object)(object)ZNet.instance))
		{
			return true;
		}
		if (!Object.op_Implicit((Object)(object)player))
		{
			return false;
		}
		if (ZNet.instance.m_adminList == null)
		{
			return false;
		}
		return ZNet.instance.ListContainsId(ZNet.instance.m_adminList, ZNet.instance.GetPeer(((ZDOID)(ref ((Character)player).m_nview.GetZDO().m_uid)).UserID).m_rpc.GetSocket().GetHostName());
	}

	private void OnDestroy()
	{
		ConfigManager.ClearModConfigs();
		if (_Harmony != null)
		{
			_Harmony.UnpatchSelf();
		}
	}
}