Decompiled source of Helmet v1.0.0

BepInEx/plugins/Helmet/Helmet.dll

Decompiled 4 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using CSync.Extensions;
using CSync.Lib;
using GameNetcodeStuff;
using HarmonyLib;
using Helmet.Behaviour;
using Helmet.Misc;
using Helmet.Misc.Util;
using Helmet.NetcodePatcher;
using Helmet.Patches;
using LethalLib.Modules;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[module: NetcodePatchedAssembly]
internal class <Module>
{
	static <Module>()
	{
	}
}
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Helmet
{
	[BepInPlugin("com.github.WhiteSpike.Helmet", "Helmet", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		internal static readonly Harmony harmony = new Harmony("com.github.WhiteSpike.Helmet");

		internal static readonly ManualLogSource mls = Logger.CreateLogSource("Helmet");

		internal static GameObject helmetModel;

		internal static GameObject helmet;

		internal static GameObject networkPrefab;

		internal static AudioClip breakSFX;

		internal static AudioClip damageSFX;

		public static PluginConfig Config;

		private void Awake()
		{
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			Config = new PluginConfig(((BaseUnityPlugin)this).Config);
			IEnumerable<Type> enumerable;
			try
			{
				enumerable = Assembly.GetExecutingAssembly().GetTypes();
			}
			catch (ReflectionTypeLoadException ex)
			{
				enumerable = ex.Types.Where((Type t) => t != null);
			}
			foreach (Type item in enumerable)
			{
				MethodInfo[] methods = item.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic);
				MethodInfo[] array = methods;
				foreach (MethodInfo methodInfo in array)
				{
					object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false);
					if (customAttributes.Length != 0)
					{
						methodInfo.Invoke(null, null);
					}
				}
			}
			string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "whitespike.helmet");
			AssetBundle val = AssetBundle.LoadFromFile(text);
			string text2 = "Assets/Helmet/";
			helmetModel = val.LoadAsset<GameObject>(text2 + "HelmetModel.prefab");
			breakSFX = val.LoadAsset<AudioClip>(text2 + "breakWood.mp3");
			damageSFX = val.LoadAsset<AudioClip>(text2 + "bonk.mp3");
			Item val2 = ScriptableObject.CreateInstance<Item>();
			((Object)val2).name = "HelmetItemProperties";
			val2.allowDroppingAheadOfPlayer = SyncedEntry<bool>.op_Implicit(Config.DROP_AHEAD_PLAYER);
			val2.canBeGrabbedBeforeGameStart = SyncedEntry<bool>.op_Implicit(Config.GRABBED_BEFORE_START);
			val2.canBeInspected = false;
			val2.creditsWorth = SyncedEntry<int>.op_Implicit(Config.PRICE);
			val2.restingRotation = new Vector3(0f, 0f, 0f);
			val2.rotationOffset = new Vector3(90f, 90f, 0f);
			val2.positionOffset = new Vector3(-0.25f, 0f, 0f);
			val2.weight = 1f + (float)SyncedEntry<int>.op_Implicit(Config.WEIGHT) / 100f;
			val2.twoHanded = false;
			val2.itemIcon = val.LoadAsset<Sprite>(text2 + "Icon.png");
			val2.spawnPrefab = val.LoadAsset<GameObject>(text2 + "Helmet.prefab");
			val2.highestSalePercentage = SyncedEntry<int>.op_Implicit(Config.HIGHEST_SALE_PERCENTAGE);
			val2.itemName = "Helmet";
			val2.itemSpawnsOnGround = true;
			val2.isConductiveMetal = SyncedEntry<bool>.op_Implicit(Config.CONDUCTIVE);
			val2.requiresBattery = false;
			val2.batteryUsage = 0f;
			val2.syncInteractLRFunction = false;
			val2.syncGrabFunction = false;
			val2.syncUseFunction = false;
			val2.syncDiscardFunction = false;
			HelmetBehaviour helmetBehaviour = val2.spawnPrefab.AddComponent<HelmetBehaviour>();
			((GrabbableObject)helmetBehaviour).itemProperties = val2;
			((GrabbableObject)helmetBehaviour).grabbable = true;
			((GrabbableObject)helmetBehaviour).grabbableToEnemies = true;
			NetworkPrefabs.RegisterNetworkPrefab(val2.spawnPrefab);
			helmet = val2.spawnPrefab;
			TerminalNode val3 = SetupInfoNode();
			Items.RegisterShopItem(val2, (TerminalNode)null, (TerminalNode)null, val3, val2.creditsWorth);
			networkPrefab = NetworkPrefabs.CreateNetworkPrefab("Helmet Manager");
			networkPrefab.AddComponent<HelmetManager>();
			PatchMainVersion();
			mls.LogInfo((object)"Helmet 1.0.0 has been loaded successfully.");
		}

		internal static TerminalNode SetupInfoNode()
		{
			TerminalNode val = ScriptableObject.CreateInstance<TerminalNode>();
			val.displayText = val.displayText + GetDisplayInfo() + "\n";
			val.clearPreviousText = true;
			return val;
		}

		public static string GetDisplayInfo()
		{
			return $"Blocks all incoming damage, has {Config.HITS_BLOCKED.Value} durability.\n\n";
		}

		internal static void PatchMainVersion()
		{
			PatchVitalComponents();
		}

		private static void PatchVitalComponents()
		{
			harmony.PatchAll(typeof(StartOfRoundPatcher));
			harmony.PatchAll(typeof(PlayerControllerBPatcher));
			harmony.PatchAll(typeof(GameNetworkManagerPatcher));
			mls.LogInfo((object)"Game managers have been patched");
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "Helmet";

		public const string PLUGIN_NAME = "DivingKit";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace Helmet.Patches
{
	[HarmonyPatch(typeof(GameNetworkManager))]
	internal static class GameNetworkManagerPatcher
	{
		[HarmonyPatch("Disconnect")]
		[HarmonyPrefix]
		private static void DisconnectPrefix(GameNetworkManager __instance)
		{
			//IL_0033: 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)
			if (__instance.isHostingGame && HelmetManager.Instance.wearingHelmet)
			{
				GameObject val = Object.Instantiate<GameObject>(Plugin.helmet, ((Component)__instance.localPlayerController).transform.position, Quaternion.identity);
				val.GetComponent<NetworkObject>().Spawn(false);
			}
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB))]
	internal static class PlayerControllerBPatcher
	{
		[HarmonyPrefix]
		[HarmonyPatch("DamagePlayer")]
		private static bool DamagePlayerPrefix(ref PlayerControllerB __instance, ref int damageNumber)
		{
			if (!((NetworkBehaviour)__instance).IsOwner || __instance.isPlayerDead || !__instance.AllowPlayerDeath())
			{
				return true;
			}
			if (HelmetManager.Instance.wearingHelmet)
			{
				HelmetBehaviour.ExecuteHelmetDamageMitigation(ref __instance, ref damageNumber);
			}
			return damageNumber != 0;
		}
	}
	[HarmonyPatch(typeof(StartOfRound))]
	internal static class StartOfRoundPatcher
	{
		[HarmonyPrefix]
		[HarmonyPatch("Awake")]
		private static void InitLguStore(StartOfRound __instance)
		{
			Plugin.mls.LogDebug((object)"Initiating components...");
			if (((NetworkBehaviour)__instance).NetworkManager.IsHost || ((NetworkBehaviour)__instance).NetworkManager.IsServer)
			{
				GameObject val = Object.Instantiate<GameObject>(Plugin.networkPrefab);
				((Object)val).hideFlags = (HideFlags)61;
				val.GetComponent<NetworkObject>().Spawn(false);
				Plugin.mls.LogDebug((object)"Spawned behaviour...");
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("OnPlayerDC")]
		private static void OnPlayerDCPostfix(StartOfRound __instance, int playerObjectNumber, ulong clientId)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			if (((NetworkBehaviour)__instance).IsServer && HelmetManager.Instance.clientWearingHelmet.TryGetValue(clientId, out var value) && value)
			{
				GameObject val = Object.Instantiate<GameObject>(Plugin.helmet, ((Component)__instance.allPlayerScripts[playerObjectNumber]).transform.position, Quaternion.identity);
				val.GetComponent<NetworkObject>().Spawn(false);
				HelmetManager.Instance.DestroyHelmetClientRpc(clientId);
			}
		}
	}
}
namespace Helmet.Misc
{
	[DataContract]
	public class PluginConfig : SyncedConfig2<PluginConfig>
	{
		[field: SyncedEntryField]
		public SyncedEntry<bool> SCAN_NODE { get; set; }

		[field: SyncedEntryField]
		public SyncedEntry<int> PRICE { get; set; }

		[field: SyncedEntryField]
		public SyncedEntry<int> WEIGHT { get; set; }

		[field: SyncedEntryField]
		public SyncedEntry<bool> DROP_AHEAD_PLAYER { get; set; }

		[field: SyncedEntryField]
		public SyncedEntry<bool> GRABBED_BEFORE_START { get; set; }

		[field: SyncedEntryField]
		public SyncedEntry<bool> CONDUCTIVE { get; set; }

		[field: SyncedEntryField]
		public SyncedEntry<int> HIGHEST_SALE_PERCENTAGE { get; set; }

		[field: SyncedEntryField]
		public SyncedEntry<int> DAMAGE_REDUCTION { get; set; }

		[field: SyncedEntryField]
		public SyncedEntry<string> DAMAGE_MITIGATION_MODE { get; set; }

		[field: SyncedEntryField]
		public SyncedEntry<int> HITS_BLOCKED { get; set; }

		public PluginConfig(ConfigFile cfg)
			: base("com.github.WhiteSpike.Helmet")
		{
			string text = "Helmet";
			PRICE = SyncedBindingExtensions.BindSyncedEntry<int>(cfg, text, "Helmet price", 300, "Price for Helmet.");
			WEIGHT = SyncedBindingExtensions.BindSyncedEntry<int>(cfg, text, "Item weight", 10, "Weight (in lbs)");
			SCAN_NODE = SyncedBindingExtensions.BindSyncedEntry<bool>(cfg, text, Constants.HELMET_SCAN_NODE_KEY, true, "Shows a scan node on the item when scanning");
			DROP_AHEAD_PLAYER = SyncedBindingExtensions.BindSyncedEntry<bool>(cfg, text, "Drop ahead of player when dropping", false, "If on, the item will drop infront of the player. Otherwise, drops underneath them and slightly infront.");
			CONDUCTIVE = SyncedBindingExtensions.BindSyncedEntry<bool>(cfg, text, "Conductive", true, "Wether it attracts lightning to the item or not. (Or other mechanics that rely on item being conductive)");
			GRABBED_BEFORE_START = SyncedBindingExtensions.BindSyncedEntry<bool>(cfg, text, "Grabbable before game start", false, "Allows wether the item can be grabbed before hand or not");
			HIGHEST_SALE_PERCENTAGE = SyncedBindingExtensions.BindSyncedEntry<int>(cfg, text, "Highest Sale Percentage", 50, "Maximum percentage of sale allowed when this item is selected for a sale.");
			HITS_BLOCKED = SyncedBindingExtensions.BindSyncedEntry<int>(cfg, text, "Amount of hits blocked by Helmet", 3, (ConfigDescription)null);
			DAMAGE_REDUCTION = SyncedBindingExtensions.BindSyncedEntry<int>(cfg, text, "Damage reduction (%) when wearing a Helmet", 20, (ConfigDescription)null);
			DAMAGE_MITIGATION_MODE = SyncedBindingExtensions.BindSyncedEntry<string>(cfg, text, "Damage mitigation mode selected when wearing a Helmet", "TotalPerHit", "Accepted Values: TotalPerHit (full immunity and helmet takes hits on durability), PartialTilLowHealth (partial immunity and helmet breaks when low health)");
			ConfigManager.Register<PluginConfig>((SyncedConfig2<PluginConfig>)this);
		}
	}
	internal static class Metadata
	{
		public const string GUID = "com.github.WhiteSpike.Helmet";

		public const string NAME = "Helmet";

		public const string VERSION = "1.0.0";
	}
}
namespace Helmet.Misc.Util
{
	internal static class Constants
	{
		internal const string ITEM_SCAN_NODE_KEY_FORMAT = "Enable scan node of {0}";

		internal const bool ITEM_SCAN_NODE_DEFAULT = true;

		internal const string ITEM_SCAN_NODE_DESCRIPTION = "Shows a scan node on the item when scanning";

		internal const string HELMET_PRICE_KEY = "Helmet price";

		internal const int HELMET_PRICE_DEFAULT = 300;

		internal const string HELMET_PRICE_DESCRIPTION = "Price for Helmet.";

		internal const string HELMET_WEIGHT_KEY = "Item weight";

		internal const int HELMET_WEIGHT_DEFAULT = 10;

		internal const string HELMET_WEIGHT_DESCRIPTION = "Weight (in lbs)";

		internal const string HELMET_CONDUCTIVE_KEY = "Conductive";

		internal const bool HELMET_CONDUCTIVE_DEFAULT = true;

		internal const string HELMET_CONDUCTIVE_DESCRIPTION = "Wether it attracts lightning to the item or not. (Or other mechanics that rely on item being conductive)";

		internal const string HELMET_DROP_AHEAD_PLAYER_KEY = "Drop ahead of player when dropping";

		internal const bool HELMET_DROP_AHEAD_PLAYER_DEFAULT = false;

		internal const string HELMET_DROP_AHEAD_PLAYER_DESCRIPTION = "If on, the item will drop infront of the player. Otherwise, drops underneath them and slightly infront.";

		internal const string HELMET_GRABBED_BEFORE_START_KEY = "Grabbable before game start";

		internal const bool HELMET_GRABBED_BEFORE_START_DEFAULT = false;

		internal const string HELMET_GRABBED_BEFORE_START_DESCRIPTION = "Allows wether the item can be grabbed before hand or not";

		internal const string HELMET_HIGHEST_SALE_PERCENTAGE_KEY = "Highest Sale Percentage";

		internal const int HELMET_HIGHEST_SALE_PERCENTAGE_DEFAULT = 50;

		internal const string HELMET_HIGHEST_SALE_PERCENTAGE_DESCRIPTION = "Maximum percentage of sale allowed when this item is selected for a sale.";

		internal const string HELMET_AMOUNT_OF_HITS_KEY = "Amount of hits blocked by Helmet";

		internal const int HELMET_AMOUNT_OF_HITS_DEFAULT = 3;

		internal const string HELMET_AMOUNT_OF_HITS_DESCRIPTION = "Only valid when TotalPerHit damage mitigation mode is selected.";

		internal const string HELMET_DAMAGE_REDUCTION_KEY = "Damage reduction (%) when wearing a Helmet";

		internal const int HELMET_DAMAGE_REDUCTION_DEFAULT = 20;

		internal const string HELMET_DAMAGE_REDUCTION_DESCRIPTION = "Only valid when PartialTilLowHealth damage mitigation mode is selected.";

		internal const string HELMET_DAMAGE_MITIGATION_MODE_KEY = "Damage mitigation mode selected when wearing a Helmet";

		internal const string HELMET_DAMAGE_MITIGATION_MODE_DEFAULT = "TotalPerHit";

		internal const string HELMET_DAMAGE_MITIGATION_MODE_DESCRIPTION = "Accepted Values: TotalPerHit (full immunity and helmet takes hits on durability), PartialTilLowHealth (partial immunity and helmet breaks when low health)";

		internal static readonly string HELMET_SCAN_NODE_KEY = string.Format("Enable scan node of {0}", "Helmet");
	}
}
namespace Helmet.Behaviour
{
	internal class HelmetBehaviour : GrabbableObject
	{
		internal enum DamageMitigationMode
		{
			TotalPerHit,
			PartialTilLowHealth
		}

		internal const string ITEM_NAME = "Helmet";

		protected bool KeepScanNode => SyncedEntry<bool>.op_Implicit(Plugin.Config.SCAN_NODE);

		public override void Start()
		{
			((GrabbableObject)this).Start();
			if (!KeepScanNode)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject.GetComponentInChildren<ScanNodeProperties>());
			}
		}

		public override void ItemActivate(bool used, bool buttonDown = true)
		{
			//IL_008c: 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)
			((GrabbableObject)this).ItemActivate(used, buttonDown);
			if (buttonDown && !HelmetManager.Instance.wearingHelmet)
			{
				HelmetManager.Instance.wearingHelmet = true;
				HelmetManager.Instance.helmetHits = Plugin.Config.HITS_BLOCKED.Value;
				if (((NetworkBehaviour)this).IsHost)
				{
					HelmetManager.Instance.SpawnAndMoveHelmetClientRpc(new NetworkObjectReference(((Component)base.playerHeldBy).GetComponent<NetworkObject>()), base.playerHeldBy.playerSteamId);
				}
				else
				{
					HelmetManager.Instance.ReqSpawnAndMoveHelmetServerRpc(new NetworkObjectReference(((Component)base.playerHeldBy).GetComponent<NetworkObject>()), base.playerHeldBy.playerSteamId);
				}
				base.playerHeldBy.DespawnHeldObject();
			}
		}

		internal static void ExecuteHelmetDamageMitigation(ref PlayerControllerB player, ref int damageNumber)
		{
			DamageMitigationMode damageMitigationMode = DamageMitigationMode.TotalPerHit;
			Enum.TryParse(typeof(DamageMitigationMode), Plugin.Config.DAMAGE_MITIGATION_MODE.Value, out object result);
			if (result == null)
			{
				Plugin.mls.LogError((object)("An error occured parsing the damage mitigation mode (" + Plugin.Config.DAMAGE_MITIGATION_MODE.Value + "), defaulting to TotalPerHit"));
			}
			else
			{
				damageMitigationMode = (DamageMitigationMode)result;
			}
			switch (damageMitigationMode)
			{
			case DamageMitigationMode.TotalPerHit:
				ExecuteHelmetCompleteMitigation(ref player, ref damageNumber);
				break;
			case DamageMitigationMode.PartialTilLowHealth:
				ExecuteHelmetPartialMitigation(ref player, ref damageNumber);
				break;
			}
		}

		internal static void ExecuteHelmetCompleteMitigation(ref PlayerControllerB player, ref int damageNumber)
		{
			Plugin.mls.LogDebug((object)("Player " + player.playerUsername + " is wearing a helmet, executing helmet logic..."));
			HelmetManager.Instance.helmetHits--;
			if (HelmetManager.Instance.helmetHits <= 0)
			{
				Plugin.mls.LogDebug((object)"Helmet has ran out of durability, breaking the helmet...");
				BreakHelmet(ref player);
			}
			else
			{
				Plugin.mls.LogDebug((object)$"Helmet still has some durability ({HelmetManager.Instance.helmetHits}), decreasing it...");
				HitHelmet(ref player);
			}
			damageNumber = 0;
		}

		internal static void ExecuteHelmetPartialMitigation(ref PlayerControllerB player, ref int damageNumber)
		{
			int health = player.health;
			int num = health - Mathf.CeilToInt((float)damageNumber * Mathf.Clamp((100f - (float)SyncedEntry<int>.op_Implicit(Plugin.Config.DAMAGE_REDUCTION)) / 100f, 0f, (float)damageNumber));
			if (num > 0)
			{
				HitHelmet(ref player);
				damageNumber = Mathf.CeilToInt((float)damageNumber * ((100f - (float)SyncedEntry<int>.op_Implicit(Plugin.Config.DAMAGE_REDUCTION)) / 100f));
			}
			else
			{
				BreakHelmet(ref player);
				damageNumber = 0;
			}
		}

		internal static void HitHelmet(ref PlayerControllerB player)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			if (((NetworkBehaviour)player).IsHost || ((NetworkBehaviour)player).IsServer)
			{
				HelmetManager.Instance.PlayAudioOnPlayerClientRpc(new NetworkBehaviourReference((NetworkBehaviour)(object)player), breakHelmet: false);
			}
			else
			{
				HelmetManager.Instance.ReqPlayAudioOnPlayerServerRpc(new NetworkBehaviourReference((NetworkBehaviour)(object)player), breakHelmet: false);
			}
		}

		internal static void BreakHelmet(ref PlayerControllerB player)
		{
			//IL_007c: 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)
			HelmetManager.Instance.wearingHelmet = false;
			if (((NetworkBehaviour)player).IsHost || ((NetworkBehaviour)player).IsServer)
			{
				HelmetManager.Instance.DestroyHelmetClientRpc(player.playerClientId);
			}
			else
			{
				HelmetManager.Instance.ReqDestroyHelmetServerRpc(player.playerClientId);
			}
			if (((NetworkBehaviour)player).IsHost || ((NetworkBehaviour)player).IsServer)
			{
				HelmetManager.Instance.PlayAudioOnPlayerClientRpc(new NetworkBehaviourReference((NetworkBehaviour)(object)player), breakHelmet: true);
			}
			else
			{
				HelmetManager.Instance.ReqPlayAudioOnPlayerServerRpc(new NetworkBehaviourReference((NetworkBehaviour)(object)player), breakHelmet: true);
			}
		}

		protected override void __initializeVariables()
		{
			((GrabbableObject)this).__initializeVariables();
		}

		protected internal override string __getTypeName()
		{
			return "HelmetBehaviour";
		}
	}
	internal class HelmetManager : NetworkBehaviour
	{
		internal Dictionary<ulong, bool> clientWearingHelmet = new Dictionary<ulong, bool>();

		internal bool wearingHelmet;

		internal int helmetHits;

		internal static HelmetManager Instance;

		private void Start()
		{
			Instance = this;
		}

		public void DestroyHelmet(ulong id)
		{
			if (StartOfRound.Instance.allPlayerObjects.Length <= (int)id)
			{
				Plugin.mls.LogError((object)$"ID: {id} can not be used to index allPlayerObjects! (Length: {StartOfRound.Instance.allPlayerObjects.Length})");
				return;
			}
			GameObject val = StartOfRound.Instance.allPlayerObjects[(uint)id];
			if ((Object)(object)val == (Object)null)
			{
				Plugin.mls.LogError((object)"Player is with helmet is null!");
			}
			else
			{
				if (((NetworkBehaviour)val.GetComponent<PlayerControllerB>()).IsOwner)
				{
					return;
				}
				Transform val2 = val.transform.GetChild(0).GetChild(3).GetChild(0)
					.GetChild(0)
					.GetChild(0)
					.GetChild(0)
					.GetChild(2)
					.Find("HelmetModel(Clone)");
				if ((Object)(object)val2 == (Object)null)
				{
					Plugin.mls.LogError((object)"Unable to find 'HelmetModel(Clone) on player!");
					return;
				}
				Object.Destroy((Object)(object)((Component)val2).gameObject);
				if (((NetworkBehaviour)this).IsServer)
				{
					PlayerControllerB component = val.GetComponent<PlayerControllerB>();
					clientWearingHelmet[component.actualClientId] = true;
				}
			}
		}

		[ClientRpc]
		public void DestroyHelmetClientRpc(ulong id)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Invalid comparison between Unknown and I4
			//IL_005f: 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_0071: 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)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
				{
					ClientRpcParams val = default(ClientRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(1416534108u, val, (RpcDelivery)0);
					BytePacker.WriteValueBitPacked(val2, id);
					((NetworkBehaviour)this).__endSendClientRpc(ref val2, 1416534108u, val, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost))
				{
					DestroyHelmet(id);
				}
			}
		}

		[ServerRpc(RequireOwnership = false)]
		public void ReqDestroyHelmetServerRpc(ulong id)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Invalid comparison between Unknown and I4
			//IL_005f: 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_0071: 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)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
				{
					ServerRpcParams val = default(ServerRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(2465058859u, val, (RpcDelivery)0);
					BytePacker.WriteValueBitPacked(val2, id);
					((NetworkBehaviour)this).__endSendServerRpc(ref val2, 2465058859u, val, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost))
				{
					Plugin.mls.LogInfo((object)$"Instructing clients to destroy helmet of player : {id}");
					DestroyHelmetClientRpc(id);
				}
			}
		}

		[ClientRpc]
		internal void SpawnAndMoveHelmetClientRpc(NetworkObjectReference netRef, ulong id)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Invalid comparison between Unknown and I4
			//IL_005f: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: 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_018c: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val = default(ClientRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(3419834455u, val, (RpcDelivery)0);
				((FastBufferWriter)(ref val2)).WriteValueSafe<NetworkObjectReference>(ref netRef, default(ForNetworkSerializable));
				BytePacker.WriteValueBitPacked(val2, id);
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 3419834455u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage != 2 || (!networkManager.IsClient && !networkManager.IsHost))
			{
				return;
			}
			NetworkObject val3 = default(NetworkObject);
			((NetworkObjectReference)(ref netRef)).TryGet(ref val3, (NetworkManager)null);
			if ((Object)(object)val3 == (Object)null || val3.IsOwner)
			{
				if ((Object)(object)val3 == (Object)null)
				{
					Plugin.mls.LogError((object)"Failed to resolve network object ref in SpawnAndMoveHelmetClientRpc!");
				}
				else
				{
					Plugin.mls.LogInfo((object)"This client owns the helmet, skipping cosmetic instantiation.");
				}
				return;
			}
			Transform child = ((Component)val3).transform.GetChild(0).GetChild(3).GetChild(0)
				.GetChild(0)
				.GetChild(0)
				.GetChild(0)
				.GetChild(2);
			GameObject val4 = Object.Instantiate<GameObject>(Plugin.helmetModel, child);
			val4.transform.localPosition = new Vector3(0.01f, 0.1f, 0.08f);
			Plugin.mls.LogInfo((object)$"Successfully spawned helmet cosmetic for player: {id}");
			if (((NetworkBehaviour)this).IsServer)
			{
				PlayerControllerB component = ((Component)val3).GetComponent<PlayerControllerB>();
				clientWearingHelmet[component.actualClientId] = true;
			}
		}

		[ServerRpc(RequireOwnership = false)]
		internal void ReqSpawnAndMoveHelmetServerRpc(NetworkObjectReference netRef, ulong id)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Invalid comparison between Unknown and I4
			//IL_005f: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: 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_016b: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
			{
				ServerRpcParams val = default(ServerRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(2324765119u, val, (RpcDelivery)0);
				((FastBufferWriter)(ref val2)).WriteValueSafe<NetworkObjectReference>(ref netRef, default(ForNetworkSerializable));
				BytePacker.WriteValueBitPacked(val2, id);
				((NetworkBehaviour)this).__endSendServerRpc(ref val2, 2324765119u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage != 1 || (!networkManager.IsServer && !networkManager.IsHost))
			{
				return;
			}
			Plugin.mls.LogInfo((object)$"Instructing clients to spawn helmet on player : {id}");
			NetworkObject val3 = default(NetworkObject);
			((NetworkObjectReference)(ref netRef)).TryGet(ref val3, (NetworkManager)null);
			if ((Object)(object)val3 == (Object)null || val3.IsOwner)
			{
				if ((Object)(object)val3 == (Object)null)
				{
					Plugin.mls.LogError((object)"Failed to resolve network object ref in SpawnAndMoveHelmetClientRpc!");
				}
				else
				{
					Plugin.mls.LogInfo((object)"This client owns the helmet, skipping cosmetic instantiation.");
				}
			}
			else
			{
				PlayerControllerB component = ((Component)val3).GetComponent<PlayerControllerB>();
				clientWearingHelmet[component.actualClientId] = true;
				SpawnAndMoveHelmetClientRpc(netRef, id);
			}
		}

		[ClientRpc]
		internal void PlayAudioOnPlayerClientRpc(NetworkBehaviourReference netRef, bool breakHelmet)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Invalid comparison between Unknown and I4
			//IL_005f: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val = default(ClientRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(1166131989u, val, (RpcDelivery)0);
				((FastBufferWriter)(ref val2)).WriteValueSafe<NetworkBehaviourReference>(ref netRef, default(ForNetworkSerializable));
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref breakHelmet, default(ForPrimitives));
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 1166131989u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage != 2 || (!networkManager.IsClient && !networkManager.IsHost))
			{
				return;
			}
			PlayerControllerB val3 = default(PlayerControllerB);
			((NetworkBehaviourReference)(ref netRef)).TryGet<PlayerControllerB>(ref val3, (NetworkManager)null);
			if ((Object)(object)val3 == (Object)null)
			{
				Plugin.mls.LogError((object)"Unable to resolve network behaviour reference in PlayAudioOnPlayerClientRpc!");
				return;
			}
			((Component)val3).GetComponentInChildren<AudioSource>().PlayOneShot(breakHelmet ? Plugin.breakSFX : Plugin.damageSFX);
			if (breakHelmet && ((NetworkBehaviour)this).IsServer)
			{
				clientWearingHelmet[val3.actualClientId] = false;
			}
		}

		[ServerRpc(RequireOwnership = false)]
		internal void ReqPlayAudioOnPlayerServerRpc(NetworkBehaviourReference netRef, bool breakHelmet)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Invalid comparison between Unknown and I4
			//IL_005f: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
				{
					ServerRpcParams val = default(ServerRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(4183433902u, val, (RpcDelivery)0);
					((FastBufferWriter)(ref val2)).WriteValueSafe<NetworkBehaviourReference>(ref netRef, default(ForNetworkSerializable));
					((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref breakHelmet, default(ForPrimitives));
					((NetworkBehaviour)this).__endSendServerRpc(ref val2, 4183433902u, val, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost))
				{
					PlayAudioOnPlayerClientRpc(netRef, breakHelmet);
				}
			}
		}

		protected override void __initializeVariables()
		{
			((NetworkBehaviour)this).__initializeVariables();
		}

		[RuntimeInitializeOnLoadMethod]
		internal static void InitializeRPCS_HelmetManager()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Expected O, but got Unknown
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Expected O, but got Unknown
			NetworkManager.__rpc_func_table.Add(1416534108u, new RpcReceiveHandler(__rpc_handler_1416534108));
			NetworkManager.__rpc_func_table.Add(2465058859u, new RpcReceiveHandler(__rpc_handler_2465058859));
			NetworkManager.__rpc_func_table.Add(3419834455u, new RpcReceiveHandler(__rpc_handler_3419834455));
			NetworkManager.__rpc_func_table.Add(2324765119u, new RpcReceiveHandler(__rpc_handler_2324765119));
			NetworkManager.__rpc_func_table.Add(1166131989u, new RpcReceiveHandler(__rpc_handler_1166131989));
			NetworkManager.__rpc_func_table.Add(4183433902u, new RpcReceiveHandler(__rpc_handler_4183433902));
		}

		private static void __rpc_handler_1416534108(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				ulong id = default(ulong);
				ByteUnpacker.ReadValueBitPacked(reader, ref id);
				target.__rpc_exec_stage = (__RpcExecStage)2;
				((HelmetManager)(object)target).DestroyHelmetClientRpc(id);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_2465058859(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				ulong id = default(ulong);
				ByteUnpacker.ReadValueBitPacked(reader, ref id);
				target.__rpc_exec_stage = (__RpcExecStage)1;
				((HelmetManager)(object)target).ReqDestroyHelmetServerRpc(id);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_3419834455(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_002f: 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_003e: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				NetworkObjectReference netRef = default(NetworkObjectReference);
				((FastBufferReader)(ref reader)).ReadValueSafe<NetworkObjectReference>(ref netRef, default(ForNetworkSerializable));
				ulong id = default(ulong);
				ByteUnpacker.ReadValueBitPacked(reader, ref id);
				target.__rpc_exec_stage = (__RpcExecStage)2;
				((HelmetManager)(object)target).SpawnAndMoveHelmetClientRpc(netRef, id);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_2324765119(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_002f: 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_003e: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				NetworkObjectReference netRef = default(NetworkObjectReference);
				((FastBufferReader)(ref reader)).ReadValueSafe<NetworkObjectReference>(ref netRef, default(ForNetworkSerializable));
				ulong id = default(ulong);
				ByteUnpacker.ReadValueBitPacked(reader, ref id);
				target.__rpc_exec_stage = (__RpcExecStage)1;
				((HelmetManager)(object)target).ReqSpawnAndMoveHelmetServerRpc(netRef, id);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_1166131989(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_002f: 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_004a: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				NetworkBehaviourReference netRef = default(NetworkBehaviourReference);
				((FastBufferReader)(ref reader)).ReadValueSafe<NetworkBehaviourReference>(ref netRef, default(ForNetworkSerializable));
				bool breakHelmet = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref breakHelmet, default(ForPrimitives));
				target.__rpc_exec_stage = (__RpcExecStage)2;
				((HelmetManager)(object)target).PlayAudioOnPlayerClientRpc(netRef, breakHelmet);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_4183433902(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_002f: 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_004a: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				NetworkBehaviourReference netRef = default(NetworkBehaviourReference);
				((FastBufferReader)(ref reader)).ReadValueSafe<NetworkBehaviourReference>(ref netRef, default(ForNetworkSerializable));
				bool breakHelmet = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref breakHelmet, default(ForPrimitives));
				target.__rpc_exec_stage = (__RpcExecStage)1;
				((HelmetManager)(object)target).ReqPlayAudioOnPlayerServerRpc(netRef, breakHelmet);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		protected internal override string __getTypeName()
		{
			return "HelmetManager";
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}
namespace Helmet.NetcodePatcher
{
	[AttributeUsage(AttributeTargets.Module)]
	internal class NetcodePatchedAssemblyAttribute : Attribute
	{
	}
}