Decompiled source of IndustrialGoldSafe v1.0.1

plugins/IndustrialGoldSafe/IndustrialGoldSafe.dll

Decompiled 4 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using IndustrialGoldSafe.Core;
using LethalLib.Modules;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.LowLevel;
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("IndustrialGoldSafe")]
[assembly: AssemblyDescription("Host-authoritative indoor gold safes with a shared timing challenge.")]
[assembly: AssemblyCompany("Serenta")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace IndustrialGoldSafe.Runtime
{
	internal static class DecoderItems
	{
		private sealed class Claim
		{
			internal NetworkObject Item;

			internal NetworkManager Manager;

			internal ulong Installer;
		}

		private sealed class ObservedMount
		{
			internal ulong LevelNonce;

			internal ulong ItemId;

			internal NetworkObject Item;
		}

		private static AssetBundle bundle;

		private static GameObject mountedArt;

		private static Material material;

		internal static GameObject Prefab;

		internal static Item Definition;

		private static readonly Dictionary<ulong, Claim> claims = new Dictionary<ulong, Claim>();

		private static readonly Dictionary<ulong, NetworkObject> consumedLocally = new Dictionary<ulong, NetworkObject>();

		private static readonly Dictionary<ulong, ObservedMount> observedMounts = new Dictionary<ulong, ObservedMount>();

		internal static void Initialize(string pluginDirectory)
		{
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_038e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0395: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0403: Expected O, but got Unknown
			//IL_0343: Unknown result type (might be due to invalid IL or missing references)
			//IL_0352: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Prefab != (Object)null)
			{
				return;
			}
			string text = Path.Combine(pluginDirectory, "industrialgolddecoder_assets");
			bundle = AssetBundle.LoadFromFile(text);
			if ((Object)(object)bundle == (Object)null)
			{
				throw new FileNotFoundException("Missing industrialgolddecoder_assets next to IndustrialGoldSafe.dll.", text);
			}
			mountedArt = bundle.LoadAsset<GameObject>("assets/decodergenerated/industrialdecoderart.prefab");
			GameObject val = bundle.LoadAsset<GameObject>("assets/decodergenerated/industrialdecoderheldart.prefab");
			if ((Object)(object)mountedArt == (Object)null || (Object)(object)val == (Object)null)
			{
				throw new InvalidDataException("Decoder art prefabs are missing from the asset bundle.");
			}
			material = BuildMaterial();
			Prefab = NetworkPrefabs.CreateNetworkPrefab("IndustrialGoldSafe.NetworkDecoder.v1");
			int num = LayerMask.NameToLayer("Props");
			Prefab.layer = ((num >= 0) ? num : 6);
			Prefab.tag = "PhysicsProp";
			GameObject val2 = Object.Instantiate<GameObject>(val, Prefab.transform);
			((Object)val2).name = "DecoderArt";
			val2.transform.localPosition = Vector3.zero;
			val2.transform.localRotation = Quaternion.identity;
			val2.transform.localScale = Vector3.one;
			ApplyMaterial(val2);
			BoxCollider val3 = Prefab.AddComponent<BoxCollider>();
			Bounds val4 = ModelBounds(val2, Prefab.transform);
			val3.center = ((Bounds)(ref val4)).center;
			val3.size = ((Bounds)(ref val4)).size + new Vector3(0.02f, 0.02f, 0.02f);
			Rigidbody val5 = Prefab.AddComponent<Rigidbody>();
			val5.isKinematic = true;
			val5.useGravity = false;
			Item val6 = ScriptableObject.CreateInstance<Item>();
			((Object)val6).name = "IndustrialGoldSafe.SafeDecoder.Item.v1";
			val6.itemId = 1768616049;
			val6.itemName = "Safe decoder";
			val6.spawnPositionTypes = new List<ItemGroup>();
			val6.twoHanded = false;
			val6.twoHandedAnimation = false;
			val6.canBeGrabbedBeforeGameStart = true;
			val6.disallowUtilitySlot = true;
			val6.weight = 1.0380952f;
			val6.isConductiveMetal = true;
			val6.isScrap = false;
			val6.itemSpawnsOnGround = true;
			val6.requiresBattery = false;
			val6.saveItemVariable = false;
			val6.spawnPrefab = Prefab;
			val6.allowDroppingAheadOfPlayer = true;
			val6.toolTips = new string[1] { "Install on safe : [E]" };
			val6.grabAnim = (val6.useAnim = (val6.pocketAnim = (val6.throwAnim = "")));
			val6.meshVariants = Array.Empty<Mesh>();
			val6.materialVariants = Array.Empty<Material>();
			val6.clinkAudios = Array.Empty<AudioClip>();
			val6.positionOffset = new Vector3(0.02f, 0.03f, -0.05f);
			val6.rotationOffset = new Vector3(0f, 0f, 0f);
			val6.verticalOffset = Mathf.Max(0.02f, 0f - ((Bounds)(ref val4)).min.y);
			val6.itemIcon = bundle.LoadAsset<Sprite>("assets/decodergenerated/decoder_icon.png");
			if ((Object)(object)val6.itemIcon == (Object)null)
			{
				Texture2D val7 = bundle.LoadAsset<Texture2D>("assets/decodergenerated/decoder_icon.png");
				if ((Object)(object)val7 != (Object)null)
				{
					val6.itemIcon = Sprite.Create(val7, new Rect(0f, 0f, (float)((Texture)val7).width, (float)((Texture)val7).height), new Vector2(0.5f, 0.5f), 100f);
				}
			}
			if ((Object)(object)val6.itemIcon == (Object)null)
			{
				throw new InvalidDataException("Decoder inventory icon is missing.");
			}
			Definition = val6;
			ScanNodeProperties val8 = SafeScanning.Add(Prefab, ((Bounds)(ref val4)).center, ((Bounds)(ref val4)).size + new Vector3(0.02f, 0.02f, 0.02f), "Safe decoder", "Single-use safe decoder");
			PhysicsProp val9 = Prefab.AddComponent<PhysicsProp>();
			((GrabbableObject)val9).itemProperties = val6;
			((GrabbableObject)val9).grabbable = true;
			((GrabbableObject)val9).grabbableToEnemies = false;
			((GrabbableObject)val9).isInFactory = true;
			((GrabbableObject)val9).insertedBattery = new Battery(false, 1f);
			((GrabbableObject)val9).propBody = val5;
			((GrabbableObject)val9).propColliders = (Collider[])(object)new Collider[2]
			{
				(Collider)val3,
				(Collider)((Component)val8).GetComponent<BoxCollider>()
			};
			((GrabbableObject)val9).mainObjectRenderer = val2.GetComponentInChildren<MeshRenderer>(true);
			NetworkObject component = Prefab.GetComponent<NetworkObject>();
			component.DontDestroyWithOwner = true;
			component.AutoObjectParentSync = false;
			Items.RegisterItem(val6);
			SafePlugin.Log.LogInfo((object)"Safe decoder registered as a one-handed, battery-free 4 lb utility item with native scanning; only safe drops create it.");
		}

		internal static bool IsHeldDecoder(PlayerControllerB player, out ulong id)
		{
			id = ulong.MaxValue;
			if ((Object)(object)player == (Object)null || (Object)(object)Definition == (Object)null || (Object)(object)player.currentlyHeldObjectServer == (Object)null)
			{
				return false;
			}
			GrabbableObject currentlyHeldObjectServer = player.currentlyHeldObjectServer;
			NetworkObject networkObject = ((NetworkBehaviour)currentlyHeldObjectServer).NetworkObject;
			int currentItemSlot = player.currentItemSlot;
			if (((object)currentlyHeldObjectServer).GetType() != typeof(PhysicsProp) || (Object)(object)currentlyHeldObjectServer.itemProperties != (Object)(object)Definition || !currentlyHeldObjectServer.isHeld || currentlyHeldObjectServer.isPocketed || (Object)(object)currentlyHeldObjectServer.playerHeldBy != (Object)(object)player || currentlyHeldObjectServer.deactivated || !currentlyHeldObjectServer.grabbable || (Object)(object)networkObject == (Object)null || !networkObject.IsSpawned || player.ItemSlots == null || currentItemSlot < 0 || currentItemSlot >= player.ItemSlots.Length || (Object)(object)player.ItemSlots[currentItemSlot] != (Object)(object)currentlyHeldObjectServer)
			{
				return false;
			}
			id = networkObject.NetworkObjectId;
			return true;
		}

		internal static bool ValidateAndMount(ulong sender, ulong safeId, ulong itemId)
		{
			//IL_00ca: 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)
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || !singleton.IsServer || !singleton.IsListening || singleton.ShutdownInProgress || singleton.SpawnManager == null || !singleton.ConnectedClients.ContainsKey(sender) || !SafeView.Find(safeId, out var result) || !singleton.SpawnManager.SpawnedObjects.TryGetValue(itemId, out var value) || (Object)(object)value == (Object)null || !value.IsSpawned || (Object)(object)value.NetworkManager != (Object)(object)singleton || claims.ContainsKey(itemId))
			{
				return false;
			}
			PlayerControllerB val = FindPlayer(sender);
			if ((Object)(object)val == (Object)null || !val.isPlayerControlled || val.isPlayerDead || !val.isInsideFactory || ((NetworkBehaviour)val).OwnerClientId != sender || value.OwnerClientId != sender || Vector3.Distance(((Component)val).transform.position, ((Component)result).transform.position) > SafePlugin.Settings.Distance.Value || !IsHeldDecoder(val, out var id) || id != itemId || (Object)(object)((NetworkBehaviour)val.currentlyHeldObjectServer).NetworkObject != (Object)(object)value)
			{
				return false;
			}
			GrabbableObject currentlyHeldObjectServer = val.currentlyHeldObjectServer;
			claims.Add(itemId, new Claim
			{
				Item = value,
				Manager = singleton,
				Installer = sender
			});
			currentlyHeldObjectServer.grabbable = false;
			currentlyHeldObjectServer.grabbableToEnemies = false;
			currentlyHeldObjectServer.deactivated = true;
			currentlyHeldObjectServer.isBeingUsed = false;
			currentlyHeldObjectServer.EnableItemMeshes(false);
			SafeScanning.Hide(currentlyHeldObjectServer);
			SafePlugin.Log.LogInfo((object)$"Decoder #{itemId} installed on safe #{safeId} by client {sender}.");
			return true;
		}

		internal static void ObserveMount(SafeSnapshot state)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			if (state == null || state.Mode != SafeMode.Decoding || state.DecoderObjectId == ulong.MaxValue)
			{
				return;
			}
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || !singleton.IsListening || singleton.ShutdownInProgress || singleton.SpawnManager == null)
			{
				return;
			}
			NetworkTime serverTime = singleton.ServerTime;
			if (((NetworkTime)(ref serverTime)).Time > state.DecodeDeadline)
			{
				return;
			}
			NetworkObject value2;
			if (observedMounts.TryGetValue(state.SafeId, out var value) && value.LevelNonce == state.LevelNonce)
			{
				value2 = value.Item;
				if (value.ItemId != state.DecoderObjectId || (Object)(object)value2 == (Object)null || !value2.IsSpawned)
				{
					return;
				}
			}
			else
			{
				if (!singleton.SpawnManager.SpawnedObjects.TryGetValue(state.DecoderObjectId, out value2) || (Object)(object)value2 == (Object)null)
				{
					return;
				}
				PhysicsProp component = ((Component)value2).GetComponent<PhysicsProp>();
				if ((Object)(object)component == (Object)null || (Object)(object)((GrabbableObject)component).itemProperties != (Object)(object)Definition)
				{
					return;
				}
				observedMounts[state.SafeId] = new ObservedMount
				{
					LevelNonce = state.LevelNonce,
					ItemId = state.DecoderObjectId,
					Item = value2
				};
			}
			PhysicsProp component2 = ((Component)value2).GetComponent<PhysicsProp>();
			if ((Object)(object)component2 == (Object)null || (Object)(object)((GrabbableObject)component2).itemProperties != (Object)(object)Definition)
			{
				return;
			}
			((GrabbableObject)component2).grabbable = false;
			((GrabbableObject)component2).grabbableToEnemies = false;
			((GrabbableObject)component2).deactivated = true;
			((GrabbableObject)component2).EnableItemMeshes(false);
			SafeScanning.Hide((GrabbableObject)(object)component2);
			if (state.DecoderInstallerClientId != singleton.LocalClientId || (consumedLocally.TryGetValue(state.DecoderObjectId, out var value3) && value3 == value2))
			{
				return;
			}
			PlayerControllerB val = FindPlayer(state.DecoderInstallerClientId);
			if ((Object)(object)val == (Object)null || !((NetworkBehaviour)val).IsOwner || val.ItemSlots == null)
			{
				return;
			}
			for (int i = 0; i < val.ItemSlots.Length; i++)
			{
				if ((object)val.ItemSlots[i] != component2)
				{
					continue;
				}
				bool flag = val.currentItemSlot == i;
				if (!flag || !val.isHoldingObject || (object)val.currentlyHeldObjectServer == component2)
				{
					bool num = flag && val.isHoldingObject;
					float carryWeight = val.carryWeight;
					val.DestroyItemInSlotAndSync(i);
					if (!num)
					{
						val.carryWeight = Mathf.Clamp(carryWeight - Mathf.Max(0f, Definition.weight - 1f), 1f, 10f);
					}
					StartOfRound instance = StartOfRound.Instance;
					if (instance != null)
					{
						instance.SendChangedWeightEvent();
					}
					consumedLocally[state.DecoderObjectId] = value2;
				}
				break;
			}
		}

		internal static void Tick()
		{
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || !singleton.IsServer || !singleton.IsListening || singleton.ShutdownInProgress)
			{
				return;
			}
			foreach (KeyValuePair<ulong, Claim> item2 in new List<KeyValuePair<ulong, Claim>>(claims))
			{
				Claim value = item2.Value;
				NetworkObject item = value.Item;
				if (value.Manager != singleton)
				{
					claims.Remove(item2.Key);
					continue;
				}
				if ((Object)(object)item == (Object)null || !item.IsSpawned)
				{
					if (SafeNetworking.ReleaseConsumedDecoder(item2.Key))
					{
						claims.Remove(item2.Key);
					}
					continue;
				}
				GrabbableObject component = ((Component)item).GetComponent<GrabbableObject>();
				bool flag = !singleton.ConnectedClients.ContainsKey(value.Installer);
				bool flag2 = (Object)(object)component != (Object)null && !component.isHeld && !component.heldByPlayerOnServer && !HasInventoryReference(component);
				if (!flag && !flag2)
				{
					continue;
				}
				if (flag)
				{
					RemoveDisconnectedReferences(component);
				}
				try
				{
					item.Despawn(true);
					if (SafeNetworking.ReleaseConsumedDecoder(item2.Key))
					{
						claims.Remove(item2.Key);
					}
				}
				catch (Exception ex)
				{
					SafePlugin.Log.LogWarning((object)("Decoder consumption cleanup deferred: " + ex.Message));
				}
			}
		}

		internal static void Spawn(Transform safe, bool testPlacement = false)
		{
			//IL_0068: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			RoundManager instance = RoundManager.Instance;
			if ((Object)(object)singleton == (Object)null || !singleton.IsServer || (Object)(object)instance == (Object)null || (Object)(object)Prefab == (Object)null || (Object)(object)safe == (Object)null)
			{
				return;
			}
			GameObject val = null;
			try
			{
				Vector3 val2 = safe.TransformPoint(testPlacement ? new Vector3(0f, 0.5f, 1.25f) : new Vector3(0.72f, 0.5f, 1.05f));
				RaycastHit val3 = default(RaycastHit);
				if ((Object)(object)StartOfRound.Instance != (Object)null && Physics.Raycast(val2 + Vector3.up, Vector3.down, ref val3, 3f, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1))
				{
					val2.y = ((RaycastHit)(ref val3)).point.y + 0.5f;
				}
				val = Object.Instantiate<GameObject>(Prefab, val2, Quaternion.identity, instance.spawnedScrapContainer);
				PhysicsProp component = val.GetComponent<PhysicsProp>();
				((GrabbableObject)component).isInFactory = true;
				((GrabbableObject)component).isInElevator = (((GrabbableObject)component).isInShipRoom = false);
				((GrabbableObject)component).fallTime = 0f;
				val.SetActive(true);
				NetworkObject component2 = val.GetComponent<NetworkObject>();
				component2.Spawn(false);
				SafePlugin.Log.LogInfo((object)$"Extra safe decoder #{component2.NetworkObjectId} spawned independently of the gold reward batch.");
			}
			catch (Exception ex)
			{
				if ((Object)(object)val != (Object)null)
				{
					NetworkObject component3 = val.GetComponent<NetworkObject>();
					if ((Object)(object)component3 == (Object)null || !component3.IsSpawned)
					{
						Object.Destroy((Object)(object)val);
					}
				}
				SafePlugin.Log.LogError((object)("Extra safe decoder spawn failed: " + ex));
			}
		}

		internal static GameObject CreateMountedArt(Transform hinge)
		{
			//IL_0036: 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_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)mountedArt == (Object)null || (Object)(object)hinge == (Object)null)
			{
				return null;
			}
			GameObject val = Object.Instantiate<GameObject>(mountedArt, hinge);
			((Object)val).name = "MountedDecoder";
			val.transform.localPosition = -hinge.localPosition;
			val.transform.localRotation = Quaternion.identity;
			val.transform.localScale = Vector3.one;
			ApplyMaterial(val);
			Collider[] componentsInChildren = val.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].enabled = false;
			}
			return val;
		}

		internal static void ClearWorld()
		{
			claims.Clear();
			consumedLocally.Clear();
			observedMounts.Clear();
		}

		internal static void Shutdown()
		{
			ClearWorld();
			if ((Object)(object)bundle != (Object)null)
			{
				bundle.Unload(false);
			}
			bundle = null;
		}

		private static PlayerControllerB FindPlayer(ulong client)
		{
			PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
			if ((Object)(object)val != (Object)null && val.actualClientId == client && ((NetworkBehaviour)val).OwnerClientId == client)
			{
				return val;
			}
			PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts;
			if (array != null)
			{
				PlayerControllerB[] array2 = array;
				foreach (PlayerControllerB val2 in array2)
				{
					if ((Object)(object)val2 != (Object)null && val2.isPlayerControlled && val2.actualClientId == client && ((NetworkBehaviour)val2).OwnerClientId == client)
					{
						return val2;
					}
				}
			}
			return null;
		}

		private static bool HasInventoryReference(GrabbableObject prop)
		{
			PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts;
			if (array == null)
			{
				return false;
			}
			PlayerControllerB[] array2 = array;
			foreach (PlayerControllerB val in array2)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				if (val.currentlyHeldObjectServer == prop || val.ItemOnlySlot == prop)
				{
					return true;
				}
				if (val.ItemSlots == null)
				{
					continue;
				}
				GrabbableObject[] itemSlots = val.ItemSlots;
				for (int j = 0; j < itemSlots.Length; j++)
				{
					if (itemSlots[j] == prop)
					{
						return true;
					}
				}
			}
			return false;
		}

		private static void RemoveDisconnectedReferences(GrabbableObject prop)
		{
			if ((Object)(object)prop == (Object)null)
			{
				return;
			}
			PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts;
			if (array == null)
			{
				return;
			}
			PlayerControllerB[] array2 = array;
			foreach (PlayerControllerB val in array2)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				bool flag = false;
				if (val.ItemSlots != null)
				{
					for (int j = 0; j < val.ItemSlots.Length; j++)
					{
						if (val.ItemSlots[j] == prop)
						{
							val.ItemSlots[j] = null;
							flag = true;
						}
					}
				}
				if (val.ItemOnlySlot == prop)
				{
					val.ItemOnlySlot = null;
					flag = true;
				}
				if (val.currentlyHeldObjectServer == prop)
				{
					val.currentlyHeldObjectServer = null;
					val.isHoldingObject = (val.twoHanded = (val.twoHandedAnimation = (val.activatingItem = false)));
				}
				if (flag)
				{
					val.carryWeight = Mathf.Clamp(val.carryWeight - Mathf.Max(0f, Definition.weight - 1f), 1f, 10f);
				}
			}
		}

		private static Material BuildMaterial()
		{
			//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_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: 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)
			//IL_0137: 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)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Expected O, but got Unknown
			//IL_017b: Expected O, but got Unknown
			Shader val = Shader.Find("HDRP/Lit");
			if ((Object)(object)val == (Object)null)
			{
				Material[] array = Resources.FindObjectsOfTypeAll<Material>();
				foreach (Material val2 in array)
				{
					if ((Object)(object)val2 != (Object)null && (Object)(object)val2.shader != (Object)null && ((Object)val2.shader).name == "HDRP/Lit")
					{
						val = val2.shader;
						break;
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				throw new InvalidOperationException("Game HDRP/Lit shader was not found for the decoder.");
			}
			Material val3 = new Material(val)
			{
				name = "IndustrialGoldSafe.Decoder.HDRP"
			};
			Texture2D val4 = bundle.LoadAsset<Texture2D>("assets/decodersource/decoder_basecolor_512.png");
			Texture2D val5 = bundle.LoadAsset<Texture2D>("assets/decodergenerated/decoder_maskmap_512.png");
			if ((Object)(object)val4 == (Object)null || (Object)(object)val5 == (Object)null)
			{
				throw new InvalidDataException("Decoder base-color or HDRP mask texture is missing.");
			}
			val3.SetTexture("_BaseColorMap", (Texture)(object)val4);
			val3.SetTexture("_MaskMap", (Texture)(object)val5);
			val3.SetColor("_BaseColor", Color.white);
			val3.SetFloat("_Metallic", 1f);
			val3.SetFloat("_Smoothness", 1f);
			val3.SetFloat("_SmoothnessRemapMin", 0f);
			val3.SetFloat("_SmoothnessRemapMax", 1f);
			val3.SetFloat("_SurfaceType", 0f);
			val3.SetFloat("_MaterialID", 1f);
			val3.SetFloat("_NormalMapSpace", 0f);
			if (!HDMaterial.ValidateMaterial(val3))
			{
				throw new InvalidOperationException("HDRP could not validate the decoder material.");
			}
			return val3;
		}

		private static void ApplyMaterial(GameObject model)
		{
			Renderer[] componentsInChildren = model.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer obj in componentsInChildren)
			{
				obj.sharedMaterial = material;
				obj.renderingLayerMask = 1u;
				obj.shadowCastingMode = (ShadowCastingMode)1;
				obj.receiveShadows = true;
				obj.lightProbeUsage = (LightProbeUsage)1;
				obj.reflectionProbeUsage = (ReflectionProbeUsage)1;
			}
		}

		private static Bounds ModelBounds(GameObject model, Transform root)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: 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)
			//IL_00e2: 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_0058: 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_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_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_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: 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_00b1: 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)
			Bounds result = default(Bounds);
			((Bounds)(ref result))..ctor(Vector3.zero, Vector3.one * 0.01f);
			bool flag = false;
			MeshFilter[] componentsInChildren = model.GetComponentsInChildren<MeshFilter>(true);
			foreach (MeshFilter val in componentsInChildren)
			{
				if ((Object)(object)val.sharedMesh == (Object)null)
				{
					continue;
				}
				Bounds bounds = val.sharedMesh.bounds;
				for (int j = 0; j < 8; j++)
				{
					Vector3 val2 = ((Bounds)(ref bounds)).center + Vector3.Scale(((Bounds)(ref bounds)).extents, new Vector3((float)(((j & 1) != 0) ? 1 : (-1)), (float)(((j & 2) != 0) ? 1 : (-1)), (float)(((j & 4) != 0) ? 1 : (-1))));
					val2 = root.InverseTransformPoint(((Component)val).transform.TransformPoint(val2));
					if (!flag)
					{
						((Bounds)(ref result))..ctor(val2, Vector3.zero);
						flag = true;
					}
					else
					{
						((Bounds)(ref result)).Encapsulate(val2);
					}
				}
			}
			return result;
		}
	}
	internal static class GoldRewards
	{
		internal static int? ReadCurrentValue(ulong id)
		{
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton != (Object)null && singleton.SpawnManager != null && singleton.SpawnManager.SpawnedObjects.TryGetValue(id, out var value) && (Object)(object)value != (Object)null)
			{
				GrabbableObject component = ((Component)value).GetComponent<GrabbableObject>();
				if ((Object)(object)component != (Object)null)
				{
					return component.scrapValue;
				}
			}
			return null;
		}

		internal static void ApplyValue(ulong id, int value)
		{
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton != (Object)null && singleton.SpawnManager != null && singleton.SpawnManager.SpawnedObjects.TryGetValue(id, out var value2) && (Object)(object)value2 != (Object)null)
			{
				GrabbableObject component = ((Component)value2).GetComponent<GrabbableObject>();
				if (component != null)
				{
					component.SetScrapValue(value);
				}
			}
		}

		internal static void AddStatistics(int delta)
		{
			if ((Object)(object)RoundManager.Instance != (Object)null)
			{
				RoundManager instance = RoundManager.Instance;
				instance.totalScrapValueInLevel += (float)delta;
			}
		}

		internal static void Spawn(Transform safe, SafeSettings settings, SafeRewardPlan plan)
		{
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			RoundManager instance = RoundManager.Instance;
			if ((Object)(object)singleton == (Object)null || !singleton.IsServer || (Object)(object)instance == (Object)null)
			{
				return;
			}
			if (plan == null)
			{
				throw new ArgumentNullException("plan");
			}
			HashSet<string> exclude = new HashSet<string>(from s in (settings.ExcludedGold.Value ?? "").Split(',')
				select s.Trim(), StringComparer.OrdinalIgnoreCase);
			ItemData[] array = (GoldScrapPlugin.allGoldGrabbableObjects ?? Array.Empty<ItemData>()).Where((ItemData i) => (Object)(object)i != (Object)null && i.isScrap && !i.isStoreItem && (Object)(object)i.itemProperties != (Object)null && (Object)(object)i.itemProperties.spawnPrefab != (Object)null && !exclude.Contains(i.folderName)).ToArray();
			if (array.Length == 0)
			{
				SafePlugin.Log.LogError((object)"Safe opened but gold reward pool is empty. Check ExcludedGoldIDs and GoldScrapLite.");
				return;
			}
			Random random = plan.CreateRewardRandom();
			int count = plan.Count;
			int num = 0;
			float num2 = 0f;
			Vector3 val3 = default(Vector3);
			RaycastHit val5 = default(RaycastHit);
			for (int num3 = 0; num3 < count; num3++)
			{
				GameObject val = null;
				try
				{
					ItemData val2 = array[random.Next(array.Length)];
					Item itemProperties = val2.itemProperties;
					((Vector3)(ref val3))..ctor((float)(num3 % 3 - 1) * 0.5f, 0.5f, 1.2f + (float)(num3 / 3) * 0.5f);
					Vector3 val4 = safe.TransformPoint(val3);
					if (Physics.Raycast(val4 + Vector3.up, Vector3.down, ref val5, 3f, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1))
					{
						val4.y = ((RaycastHit)(ref val5)).point.y + 0.5f;
					}
					val = Object.Instantiate<GameObject>(itemProperties.spawnPrefab, val4, Quaternion.Euler(itemProperties.restingRotation), instance.spawnedScrapContainer);
					GrabbableObject component = val.GetComponent<GrabbableObject>();
					NetworkObject component2 = val.GetComponent<NetworkObject>();
					if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null)
					{
						throw new InvalidOperationException("Gold prefab lacks GrabbableObject / NetworkObject: " + val2.folderName);
					}
					component.isInFactory = true;
					component.isInShipRoom = false;
					component.isInElevator = false;
					component.fallTime = 0f;
					int num4 = Math.Max(0, Math.Min(itemProperties.minValue, itemProperties.maxValue));
					int num5 = Math.Max(num4, Math.Max(itemProperties.minValue, itemProperties.maxValue));
					double num6 = ((num5 == num4) ? num4 : random.Next(num4, num5));
					int num7 = (int)Math.Min(2147483647.0, Math.Max(0.0, num6 * (double)instance.scrapValueMultiplier * (double)settings.ValueMultiplier.Value));
					component.SetScrapValue(num7);
					component2.Spawn(false);
					SafeNetworking.RecordReward(component2.NetworkObjectId, num7);
					SafeNetworking.RecordStatisticsAdded(component2.NetworkObjectId, num7);
					num++;
					num2 += (float)num7;
					SafePlugin.Log.LogInfo((object)$"Safe reward #{component2.NetworkObjectId}: {val2.folderName}, ${num7}.");
				}
				catch (Exception arg)
				{
					if ((Object)(object)val != (Object)null)
					{
						NetworkObject component3 = val.GetComponent<NetworkObject>();
						if ((Object)(object)component3 == (Object)null || !component3.IsSpawned)
						{
							Object.Destroy((Object)(object)val);
						}
					}
					SafePlugin.Log.LogError((object)$"Safe reward {num3 + 1}/{count} failed: {arg}");
				}
			}
			SafePlugin.Log.LogInfo((object)$"Safe rewards delivered: {num}/{count}, pool {array.Length}, total ${num2}.");
		}
	}
	internal enum SafeSound
	{
		Start,
		Press,
		Step,
		Fail,
		Jam,
		Open,
		DecoderLoop
	}
	internal static class SafeAudio
	{
		private const int SampleRate = 24000;

		internal const float CompletionGapSeconds = 0.15f;

		private static readonly AudioClip[] Clips = (AudioClip[])(object)new AudioClip[7];

		private static readonly List<AudioSource> WorldSources = new List<AudioSource>();

		private static readonly List<AudioSource> DecoderLoops = new List<AudioSource>();

		private static AudioSource localSource;

		private static float volume = 0.6f;

		internal static float Volume
		{
			get
			{
				return volume;
			}
			set
			{
				volume = ((float.IsNaN(value) || float.IsInfinity(value)) ? 0.6f : Mathf.Clamp01(value));
			}
		}

		internal static void Local(SafeSound sound, float level = 1f)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			float num = Gain(level);
			if (!(num <= 0f))
			{
				if ((Object)(object)localSource == (Object)null)
				{
					GameObject val = new GameObject("IndustrialGoldSafe.LocalAudio")
					{
						hideFlags = (HideFlags)61
					};
					Object.DontDestroyOnLoad((Object)val);
					localSource = val.AddComponent<AudioSource>();
					Configure(localSource);
					localSource.spatialBlend = 0f;
					localSource.bypassReverbZones = true;
				}
				localSource.PlayOneShot(GetClip(sound), num);
			}
		}

		internal static void World(SafeSound sound, Vector3 position, float level = 1f)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			WorldDelayed(sound, position, 0f, level);
		}

		internal static void WorldCompletion(Vector3 position)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			World(SafeSound.Step, position);
			WorldDelayed(SafeSound.Open, position, 0.15f);
		}

		internal static void WorldDelayed(SafeSound sound, Vector3 position, float delaySeconds, float level = 1f)
		{
			//IL_00ad: 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_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Expected O, but got Unknown
			float num = Gain(level);
			if (num <= 0f)
			{
				return;
			}
			float num2 = ((float.IsNaN(delaySeconds) || float.IsInfinity(delaySeconds)) ? 0f : Mathf.Clamp(delaySeconds, 0f, 5f));
			for (int num3 = WorldSources.Count - 1; num3 >= 0; num3--)
			{
				if ((Object)(object)WorldSources[num3] == (Object)null)
				{
					WorldSources.RemoveAt(num3);
				}
			}
			if (WorldSources.Count >= 12)
			{
				Object.Destroy((Object)(object)((Component)WorldSources[0]).gameObject);
				WorldSources.RemoveAt(0);
			}
			AudioClip clip = GetClip(sound);
			GameObject val = new GameObject("IndustrialGoldSafe.WorldAudio")
			{
				hideFlags = (HideFlags)61
			};
			val.transform.position = position;
			AudioSource val2 = val.AddComponent<AudioSource>();
			Configure(val2);
			val2.spatialBlend = 1f;
			val2.rolloffMode = (AudioRolloffMode)1;
			val2.minDistance = 1.5f;
			val2.maxDistance = 16f;
			val2.spread = 20f;
			val2.volume = num;
			val2.clip = clip;
			WorldSources.Add(val2);
			if (num2 > 0f)
			{
				val2.PlayDelayed(num2);
			}
			else
			{
				val2.Play();
			}
			Object.Destroy((Object)val, num2 + clip.length + 0.1f);
		}

		internal static AudioSource StartDecoderLoop(Transform parent, double elapsedSeconds = 0.0)
		{
			//IL_0063: 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)
			if ((Object)(object)parent == (Object)null)
			{
				return null;
			}
			for (int num = DecoderLoops.Count - 1; num >= 0; num--)
			{
				if ((Object)(object)DecoderLoops[num] == (Object)null)
				{
					DecoderLoops.RemoveAt(num);
				}
			}
			if (DecoderLoops.Count >= 12)
			{
				StopLoop(DecoderLoops[0]);
			}
			GameObject val = new GameObject("IndustrialGoldSafe.DecoderLoop");
			val.transform.SetParent(parent, false);
			AudioSource val2 = val.AddComponent<AudioSource>();
			Configure(val2);
			val2.spatialBlend = 1f;
			val2.rolloffMode = (AudioRolloffMode)1;
			val2.minDistance = 1.5f;
			val2.maxDistance = 16f;
			val2.spread = 20f;
			val2.loop = true;
			val2.clip = GetClip(SafeSound.DecoderLoop);
			val2.volume = Gain(1f);
			if (!double.IsNaN(elapsedSeconds) && !double.IsInfinity(elapsedSeconds) && elapsedSeconds > 0.0 && val2.clip.length > 0f)
			{
				val2.time = (float)(elapsedSeconds % (double)val2.clip.length);
			}
			DecoderLoops.Add(val2);
			val2.Play();
			return val2;
		}

		internal static void RefreshDecoderLoop(AudioSource source)
		{
			if ((Object)(object)source != (Object)null)
			{
				source.volume = Gain(1f);
			}
		}

		internal static void StopLoop(AudioSource source)
		{
			if (!((Object)(object)source == (Object)null))
			{
				DecoderLoops.Remove(source);
				source.Stop();
				source.loop = false;
				Object.Destroy((Object)(object)((Component)source).gameObject);
			}
		}

		private static void Configure(AudioSource source)
		{
			source.playOnAwake = false;
			source.loop = false;
			source.dopplerLevel = 0f;
			source.pitch = 1f;
			source.volume = 1f;
			source.priority = 128;
		}

		private static float Gain(float level)
		{
			if (!float.IsNaN(level) && !float.IsInfinity(level))
			{
				return Volume * Mathf.Clamp01(level);
			}
			return 0f;
		}

		internal static AudioClip GetClip(SafeSound sound)
		{
			int num = (int)sound;
			if (num < 0 || num >= Clips.Length)
			{
				throw new ArgumentOutOfRangeException("sound");
			}
			if ((Object)(object)Clips[num] != (Object)null)
			{
				return Clips[num];
			}
			double num2;
			switch (sound)
			{
			case SafeSound.Step:
			case SafeSound.Jam:
			case SafeSound.Open:
			case SafeSound.DecoderLoop:
			{
				string resource = sound switch
				{
					SafeSound.DecoderLoop => "IndustrialGoldSafe.Audio.DecoderLoop.wav", 
					SafeSound.Jam => "IndustrialGoldSafe.Audio.Jam.wav", 
					SafeSound.Step => "IndustrialGoldSafe.Audio.Success.wav", 
					_ => "IndustrialGoldSafe.Audio.Open.wav", 
				};
				Clips[num] = LoadRecordedClip(resource, sound);
				return Clips[num];
			}
			default:
				num2 = sound switch
				{
					SafeSound.Jam => 0.46, 
					SafeSound.Fail => 0.27, 
					SafeSound.Start => 0.22, 
					SafeSound.Step => 0.16, 
					_ => 0.76, 
				};
				break;
			case SafeSound.Press:
				num2 = 0.075;
				break;
			}
			double num3 = num2;
			float[] array = new float[(int)Math.Ceiling(num3 * 24000.0)];
			uint num4 = (uint)(833049489 + num * 1630357685);
			double num5 = 0.0;
			for (int i = 0; i < array.Length; i++)
			{
				num4 ^= num4 << 13;
				num4 ^= num4 >> 17;
				num4 ^= num4 << 5;
				double num6 = (double)(num4 & 0xFFFFFF) / 8388607.5 - 1.0;
				num5 += (num6 - num5) * 0.18;
				double num7 = (double)i / 24000.0;
				double num8;
				switch (sound)
				{
				case SafeSound.Start:
					num8 = Tick(num7, 0.0, 0.09, 520.0, 0.23, num5) + Tick(num7, 0.085, 0.11, 740.0, 0.18, num5);
					break;
				case SafeSound.Press:
					num8 = Tick(num7, 0.0, 0.067, 920.0, 0.21, num5);
					break;
				case SafeSound.Step:
					num8 = Tick(num7, 0.0, 0.07, 1080.0, 0.24, num5) + Tick(num7, 0.055, 0.09, 680.0, 0.13, num5);
					break;
				case SafeSound.Fail:
					num8 = Tick(num7, 0.0, 0.14, 185.0, 0.31, num5) + Tick(num7, 0.065, 0.16, 260.0, 0.17, num5);
					num8 += Scrape(num7, 0.045, 0.16, 0.11, num5);
					break;
				case SafeSound.Jam:
					num8 = Tick(num7, 0.0, 0.16, 140.0, 0.35, num5) + Tick(num7, 0.075, 0.18, 225.0, 0.26, num5) + Tick(num7, 0.18, 0.23, 170.0, 0.2, num5) + Scrape(num7, 0.08, 0.27, 0.12, num5);
					break;
				default:
					num8 = Tick(num7, 0.0, 0.09, 650.0, 0.24, num5) + Tick(num7, 0.065, 0.12, 420.0, 0.22, num5) + Scrape(num7, 0.13, 0.39, 0.2, num5) + Tick(num7, 0.54, 0.18, 115.0, 0.28, num5);
					break;
				}
				double val = Math.Min(1.0, num7 / 0.0015) * Math.Min(1.0, (num3 - num7) / 0.012);
				array[i] = (float)Math.Max(-0.55, Math.Min(0.55, num8 * Math.Max(0.0, val)));
			}
			AudioClip val2 = AudioClip.Create("IndustrialGoldSafe." + sound, array.Length, 1, 24000, false);
			((Object)val2).hideFlags = (HideFlags)61;
			if (!val2.SetData(array, 0))
			{
				Object.Destroy((Object)(object)val2);
				throw new InvalidOperationException("Could not upload the generated safe sound.");
			}
			Clips[num] = val2;
			return val2;
		}

		private static AudioClip LoadRecordedClip(string resource, SafeSound sound)
		{
			using Stream stream = typeof(SafeAudio).Assembly.GetManifestResourceStream(resource);
			if (stream == null)
			{
				throw new InvalidOperationException("Missing embedded safe recording: " + resource);
			}
			using BinaryReader binaryReader = new BinaryReader(stream);
			if (stream.Length < 44 || stream.Length > 1048576 || binaryReader.ReadUInt32() != 1179011410 || binaryReader.ReadUInt32() != stream.Length - 8 || binaryReader.ReadUInt32() != 1163280727)
			{
				throw new InvalidDataException("Invalid safe recording RIFF/WAVE header: " + resource);
			}
			bool flag = false;
			byte[] array = null;
			while (stream.Position + 8 <= stream.Length)
			{
				uint num = binaryReader.ReadUInt32();
				uint num2 = binaryReader.ReadUInt32();
				long num3 = stream.Position + num2;
				if (num3 > stream.Length || num3 + (num2 & 1) > stream.Length)
				{
					throw new InvalidDataException("Truncated safe recording chunk: " + resource);
				}
				switch (num)
				{
				case 544501094u:
					if (flag || num2 != 16 || binaryReader.ReadUInt16() != 1 || binaryReader.ReadUInt16() != 1 || binaryReader.ReadUInt32() != 48000 || binaryReader.ReadUInt32() != 96000 || binaryReader.ReadUInt16() != 2 || binaryReader.ReadUInt16() != 16)
					{
						throw new InvalidDataException("Safe recordings must be mono 48 kHz PCM16: " + resource);
					}
					flag = true;
					break;
				case 1635017060u:
					if (!flag || array != null || num2 == 0 || num2 % 2 != 0)
					{
						throw new InvalidDataException("Invalid safe recording sample data: " + resource);
					}
					array = binaryReader.ReadBytes((int)num2);
					if (array.Length != num2)
					{
						throw new InvalidDataException("Incomplete safe recording: " + resource);
					}
					break;
				}
				stream.Position = num3 + (num2 & 1);
			}
			if (!flag || array == null || stream.Position != stream.Length)
			{
				throw new InvalidDataException("Incomplete safe recording structure: " + resource);
			}
			float[] array2 = new float[array.Length / 2];
			for (int i = 0; i < array2.Length; i++)
			{
				array2[i] = (float)(short)(array[i * 2] | (array[i * 2 + 1] << 8)) / 32768f;
			}
			AudioClip val = AudioClip.Create("IndustrialGoldSafe." + sound, array2.Length, 1, 48000, false);
			((Object)val).hideFlags = (HideFlags)61;
			if (!val.SetData(array2, 0))
			{
				Object.Destroy((Object)(object)val);
				throw new InvalidOperationException("Could not upload the safe recording: " + resource);
			}
			return val;
		}

		private static double Tick(double time, double start, double duration, double frequency, double gain, double noise)
		{
			double num = time - start;
			if (num < 0.0 || num >= duration)
			{
				return 0.0;
			}
			double num2 = Math.Min(1.0, num / 0.0015) * Math.Exp((0.0 - num) / (duration * 0.22)) * Math.Min(1.0, (duration - num) / 0.008);
			double num3 = num * frequency * Math.PI * 2.0;
			return gain * num2 * (0.56 * noise + 0.3 * Math.Sin(num3) + 0.14 * Math.Sin(num3 * 1.61));
		}

		private static double Scrape(double time, double start, double duration, double gain, double noise)
		{
			double num = time - start;
			if (num < 0.0 || num >= duration)
			{
				return 0.0;
			}
			double num2 = Math.Sin(num / duration * Math.PI);
			return gain * noise * num2 * (0.72 + 0.28 * Math.Sin(num * 63.0));
		}

		internal static void Shutdown()
		{
			if ((Object)(object)localSource != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)localSource).gameObject);
			}
			localSource = null;
			foreach (AudioSource worldSource in WorldSources)
			{
				if ((Object)(object)worldSource != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)worldSource).gameObject);
				}
			}
			WorldSources.Clear();
			foreach (AudioSource item in new List<AudioSource>(DecoderLoops))
			{
				StopLoop(item);
			}
			DecoderLoops.Clear();
			for (int i = 0; i < Clips.Length; i++)
			{
				if ((Object)(object)Clips[i] != (Object)null)
				{
					Object.Destroy((Object)(object)Clips[i]);
				}
				Clips[i] = null;
			}
		}
	}
	internal static class SafeDialRaster
	{
		internal const int LogicalWidth = 128;

		internal const int LogicalHeight = 144;

		internal const int PixelDensity = 2;

		internal const int Width = 256;

		internal const int Height = 288;

		private static readonly Color32[] Pixels;

		private static readonly Color32[] OutlinedPixels;

		private static readonly Color32 Outline;

		private static readonly double[] Radii;

		private static readonly double[] Phases;

		private static readonly Color32 Track;

		private static readonly Color32 Target;

		private static readonly Color32 Pointer;

		private static readonly Color32 Timer;

		private static readonly Color32 Success;

		private static readonly Color32 Failure;

		private static readonly string[] Glyphs;

		private const string Alphabet = "SPACEMILOKDN[].";

		static SafeDialRaster()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: 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_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_00ad: 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_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			Pixels = (Color32[])(object)new Color32[73728];
			OutlinedPixels = (Color32[])(object)new Color32[73728];
			Outline = new Color32((byte)0, (byte)0, (byte)0, (byte)245);
			Radii = new double[73728];
			Phases = new double[73728];
			Track = new Color32((byte)185, (byte)109, (byte)45, (byte)130);
			Target = new Color32((byte)246, (byte)158, (byte)58, (byte)230);
			Pointer = new Color32((byte)232, (byte)228, (byte)205, (byte)230);
			Timer = new Color32((byte)182, (byte)154, (byte)106, (byte)126);
			Success = new Color32((byte)156, (byte)193, (byte)113, (byte)230);
			Failure = new Color32((byte)221, (byte)99, (byte)63, (byte)230);
			Glyphs = new string[15]
			{
				"01111100001000001110000010000111110", "11110100011000111110100001000010000", "01110100011000111111100011000110001", "01111100001000010000100001000001111", "11111100001000011110100001000011111", "10001110111010110101100011000110001", "11111001000010000100001000010011111", "10000100001000010000100001000011111", "01110100011000110001100011000101110", "10001100101010011000101001001010001",
				"11110100011000110001100011000111110", "10001110011100110101100111001110001", "01110010000100001000010000100001110", "01110000100001000010000100001001110", "00000000000000000000000000010000100"
			};
			for (int i = 0; i < 288; i++)
			{
				for (int j = 0; j < 256; j++)
				{
					int num = i * 256 + j;
					double num2 = ((double)j + 0.5) / 2.0 - 64.0;
					double num3 = ((double)i + 0.5) / 2.0 - 60.0;
					Radii[num] = Math.Sqrt(num2 * num2 + num3 * num3);
					Phases[num] = QteMath.WrapPhase(Math.Atan2(num2, 0.0 - num3) / (Math.PI * 2.0));
				}
			}
		}

		internal static Texture2D CreateTexture()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: 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)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			return new Texture2D(256, 288, (TextureFormat)4, false, true)
			{
				name = "IndustrialGoldSafe.TransparentDial",
				filterMode = (FilterMode)0,
				wrapMode = (TextureWrapMode)1,
				hideFlags = (HideFlags)61
			};
		}

		internal static void Paint(Texture2D texture, SafeSnapshot state, double serverTime, bool pending)
		{
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: 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_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0297: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0409: Unknown result type (might be due to invalid IL or missing references)
			//IL_040b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0380: Unknown result type (might be due to invalid IL or missing references)
			//IL_0382: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f1: Unknown result type (might be due to invalid IL or missing references)
			double num = QteMath.Pointer(serverTime, state) * Math.PI * 2.0;
			double num2 = 64.0 + 45.0 * Math.Sin(num);
			double num3 = 60.0 - 45.0 * Math.Cos(num);
			bool flag = serverTime < state.StepStartTime;
			string text = ((state.Mode == SafeMode.Open) ? "OPEN" : ((state.Mode == SafeMode.Jammed) ? "LOCKED" : ((state.Mode == SafeMode.Closed) ? "MISS" : ((flag || pending) ? "..." : "[SPACE]"))));
			Color32 val = ((state.Mode == SafeMode.Open) ? Success : ((state.Mode == SafeMode.Jammed || state.Mode == SafeMode.Closed) ? Failure : Pointer));
			double num4 = (double)(128 - (text.Length * 6 - 1)) / 2.0;
			double num5 = 57.0;
			double num6 = Math.Max(0.001, state.Deadline - state.StepStartTime);
			double num7 = (flag ? 1.0 : Math.Max(0.0, Math.Min(1.0, (state.Deadline - serverTime) / num6)));
			int num8 = Math.Max(0, Math.Min(30, state.Step));
			double num9 = ((num8 > 14) ? 1 : 3);
			double num10 = Math.Min(5.0, (100.0 - (double)Math.Max(0, num8 - 1) * num9) / (double)Math.Max(1, num8));
			double num11 = (double)num8 * num10 + (double)Math.Max(0, num8 - 1) * num9;
			double num12 = (128.0 - num11) / 2.0;
			for (int i = 0; i < 288; i++)
			{
				for (int j = 0; j < 256; j++)
				{
					int num13 = i * 256 + j;
					double num14 = ((double)j + 0.5) / 2.0;
					double num15 = ((double)i + 0.5) / 2.0;
					double num16 = Radii[num13];
					double num17 = Phases[num13];
					Color32 val2 = default(Color32);
					if (Math.Abs(num16 - 45.0) < 0.6)
					{
						val2 = Track;
					}
					if (!pending && Math.Abs(num16 - 45.0) < 2.1 && QteMath.CircleDistance(num17, state.TargetCenter) <= state.TargetWidth / 2.0)
					{
						val2 = Target;
					}
					if (Math.Abs(num16 - 53.0) < 0.5 && num17 < num7)
					{
						val2 = Timer;
					}
					if (Math.Abs(num14 - num2) < 1.65 && Math.Abs(num15 - num3) < 1.65)
					{
						val2 = Pointer;
					}
					int num18 = (int)Math.Floor((double)j / 2.0 - num4);
					int num19 = i / 2 - (int)num5;
					int num20 = ((num18 >= 0) ? (num18 / 6) : (-1));
					int num21 = num18 % 6;
					if (num20 >= 0 && num20 < text.Length && num21 >= 0 && num21 < 5 && num19 >= 0 && num19 < 7)
					{
						int num22 = "SPACEMILOKDN[].".IndexOf(text[num20]);
						if (num22 >= 0 && Glyphs[num22][num19 * 5 + num21] == '1')
						{
							val2 = val;
						}
					}
					if (num8 > 0 && num15 >= 125.0 && num15 < 127.0)
					{
						double num23 = (double)j / 2.0 - num12;
						int num24 = ((num23 >= 0.0) ? ((int)Math.Floor(num23 / (num10 + num9))) : (-1));
						if (num24 >= 0 && num24 < num8 && num23 % (num10 + num9) < num10)
						{
							val2 = Target;
						}
					}
					Pixels[(287 - i) * 256 + j] = val2;
				}
			}
			AddOutline();
			texture.SetPixels32(OutlinedPixels);
			texture.Apply(false, false);
		}

		private static bool HasMark(int x, int y)
		{
			if (x >= 0 && x < 256 && y >= 0 && y < 288)
			{
				return Pixels[y * 256 + x].a != 0;
			}
			return false;
		}

		private static void AddOutline()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//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_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)
			for (int i = 0; i < 288; i++)
			{
				for (int j = 0; j < 256; j++)
				{
					int num = i * 256 + j;
					Color32 val = Pixels[num];
					if (val.a == 0)
					{
						bool flag = false;
						for (int k = -1; k <= 1; k++)
						{
							if (flag)
							{
								break;
							}
							for (int l = -1; l <= 1; l++)
							{
								if (HasMark(j + l, i + k))
								{
									flag = true;
									break;
								}
							}
						}
						if (flag)
						{
							val = Outline;
						}
					}
					OutlinedPixels[num] = val;
				}
			}
		}
	}
	public static class SafeNetworking
	{
		private const string HelloName = "Serenta.IndustrialGoldSafe.Hello.4";

		private const string CommandName = "Serenta.IndustrialGoldSafe.Command.4";

		private const string EventName = "Serenta.IndustrialGoldSafe.Event.4";

		private const byte Protocol = 4;

		private const long MaximumStatisticsTotal = 8796093018112L;

		private static readonly ManualLogSource Log = Logger.CreateLogSource("IndustrialGoldSafe.Network");

		private static SafeNetworkOptions options = new SafeNetworkOptions();

		private static Func<ulong, int?> currentRewardValue;

		private static Func<ulong, ulong, ulong, bool> mountDecoder;

		private static bool claimingDecoder;

		private static NetworkManager manager;

		private static CustomMessagingManager messages;

		private static SafeAuthority authority;

		private static ulong generation;

		private static ulong localNonce;

		private static ulong serverNonce;

		private static ulong levelNonce;

		private static bool acknowledged;

		private static float nextHello;

		private static float nextWarning;

		private static readonly Dictionary<ulong, ulong> peers = new Dictionary<ulong, ulong>();

		private static readonly HashSet<ulong> pendingHello = new HashSet<ulong>();

		private static readonly Dictionary<ulong, double> nextStart = new Dictionary<ulong, double>();

		private static readonly Dictionary<ulong, SafeSnapshot> states = new Dictionary<ulong, SafeSnapshot>();

		private static readonly Dictionary<ulong, int> rewards = new Dictionary<ulong, int>();

		private static readonly Dictionary<ulong, NetworkObject> rewardObjects = new Dictionary<ulong, NetworkObject>();

		private static readonly Dictionary<ulong, int> pendingRewards = new Dictionary<ulong, int>();

		private static readonly Dictionary<ulong, NetworkObject> pendingObjects = new Dictionary<ulong, NetworkObject>();

		private static readonly Dictionary<ulong, float> pendingExpires = new Dictionary<ulong, float>();

		private static readonly Dictionary<ulong, NetworkObject> appliedRewards = new Dictionary<ulong, NetworkObject>();

		private static readonly Dictionary<ulong, NetworkObject> statisticsRecorded = new Dictionary<ulong, NetworkObject>();

		private static long statisticsTotal;

		private static long statisticsApplied;

		private static bool initialStatisticsReady;

		private static Action<ulong> disconnect;

		private static Action<bool> stopped;

		public static event Action<ulong> OnOpened;

		public static event Action<ulong, int> OnRewardValue;

		public static event Action<int> OnStatisticsDelta;

		public static void Initialize(SafeNetworkOptions settings, Func<ulong, int?> readCurrentRewardValue = null, Func<ulong, ulong, ulong, bool> validateAndMountDecoder = null)
		{
			options = (settings ?? throw new ArgumentNullException("settings")).ValidatedCopy();
			currentRewardValue = readCurrentRewardValue;
			mountDecoder = validateAndMountDecoder;
		}

		public static bool TryGetState(ulong id, out SafeSnapshot state)
		{
			if (authority != null && (Object)(object)manager != (Object)null && manager.IsServer)
			{
				return authority.TryGetState(id, out state);
			}
			if (states.TryGetValue(id, out var value))
			{
				state = value.Copy();
				return true;
			}
			state = null;
			return false;
		}

		public static bool RegisterHostSafe(ulong id, int requiredSteps = 0)
		{
			bool registered = false;
			Guard(delegate
			{
				if (EnsureBound() && manager.IsServer && ObjectExists(id) && authority.Register(id, requiredSteps))
				{
					registered = true;
					Publish(id, mayOpen: false);
				}
			});
			return registered;
		}

		public static void ResetLevel()
		{
			Guard(delegate
			{
				if (!EnsureBound() || !manager.IsServer)
				{
					return;
				}
				if (levelNonce == ulong.MaxValue)
				{
					throw new InvalidOperationException("Level epochs exhausted.");
				}
				authority.Reset(++levelNonce);
				states.Clear();
				nextStart.Clear();
				statisticsRecorded.Clear();
				statisticsTotal = (statisticsApplied = 0L);
				initialStatisticsReady = false;
				PruneRewards();
				foreach (ulong item in new List<ulong>(peers.Keys))
				{
					pendingHello.Add(item);
					try
					{
						SendAck(item);
					}
					catch (Exception ex)
					{
						Warn(ex);
					}
				}
			});
		}

		public static void RequestStart(ulong id)
		{
			Request(0, id);
		}

		public static void RequestHit(ulong id)
		{
			Request(1, id);
		}

		public static void RequestHit(ulong id, ulong attempt, int step, double inputTime)
		{
			Guard(delegate
			{
				if (EnsureBound() && (manager.IsServer || acknowledged) && QteMath.IsFinite(inputTime) && TryGetState(id, out var state) && state.Mode == SafeMode.Active && state.OperatorClientId == manager.LocalClientId && state.AttemptToken == attempt && state.Step == step)
				{
					SendRequest(1, id, attempt, step, inputTime);
				}
			});
		}

		public static void Cancel(ulong id)
		{
			Request(2, id);
		}

		public static void RequestDecoder(ulong id, ulong decoderObjectId)
		{
			Guard(delegate
			{
				//IL_005e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0063: Unknown result type (might be due to invalid IL or missing references)
				if (EnsureBound() && (manager.IsServer || acknowledged) && decoderObjectId != ulong.MaxValue && TryGetState(id, out var state) && (state.Mode == SafeMode.Closed || state.Mode == SafeMode.Jammed))
				{
					ulong id2 = id;
					ulong attempt = decoderObjectId;
					int revision = state.Revision;
					NetworkTime serverTime = manager.ServerTime;
					SendRequest(3, id2, attempt, revision, ((NetworkTime)(ref serverTime)).Time);
				}
			});
		}

		public static bool ReleaseConsumedDecoder(ulong decoderObjectId)
		{
			bool released = false;
			Guard(delegate
			{
				if (EnsureBound() && manager.IsServer && !((Object)(object)CurrentObject(decoderObjectId) != (Object)null))
				{
					released = authority.ReleaseConsumedDecoder(decoderObjectId);
				}
			});
			return released;
		}

		public static void ResetInitialStatisticsReady()
		{
			Guard(delegate
			{
				if (EnsureBound())
				{
					initialStatisticsReady = false;
					statisticsApplied = 0L;
					if (!manager.IsServer)
					{
						localNonce = NewNonce();
						acknowledged = false;
						nextHello = 0f;
					}
				}
			});
		}

		public static void MarkInitialStatisticsReady()
		{
			Guard(delegate
			{
				if (EnsureBound())
				{
					initialStatisticsReady = true;
					statisticsApplied = 0L;
					FlushStatistics();
					if (manager.IsServer)
					{
						BroadcastStatistics();
					}
				}
			});
		}

		public static void RecordStatisticsAdded(ulong objectId, int value)
		{
			Guard(delegate
			{
				if (EnsureBound() && manager.IsServer && value >= 0 && ObjectExists(objectId))
				{
					NetworkObject val = CurrentObject(objectId);
					if (!statisticsRecorded.TryGetValue(objectId, out var value2) || value2 != val)
					{
						long num = checked(statisticsTotal + value);
						if (num > 8796093018112L)
						{
							throw new InvalidOperationException("Safe reward statistics exceed the protocol limit.");
						}
						statisticsRecorded[objectId] = val;
						statisticsTotal = num;
						FlushStatistics();
						if (initialStatisticsReady)
						{
							BroadcastStatistics();
						}
					}
				}
			});
		}

		private static void Request(byte kind, ulong id)
		{
			Guard(delegate
			{
				//IL_0063: 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)
				if (EnsureBound() && (manager.IsServer || acknowledged))
				{
					ulong num = 0uL;
					int num2 = 0;
					if (TryGetState(id, out var state))
					{
						num = state.AttemptToken;
						num2 = ((kind == 0) ? state.Revision : state.Step);
						byte kind2 = kind;
						ulong id2 = id;
						ulong attempt = num;
						int step = num2;
						NetworkTime serverTime = manager.ServerTime;
						SendRequest(kind2, id2, attempt, step, ((NetworkTime)(ref serverTime)).Time);
					}
				}
			});
		}

		private unsafe static void SendRequest(byte kind, ulong id, ulong attempt, int step, double inputTime)
		{
			//IL_0035: 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)
			//IL_004d: 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_0062: 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_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: 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_00aa: 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)
			//IL_00bc: 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_00ce: 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_00e6: Unknown result type (might be due to invalid IL or missing references)
			if (manager.IsServer)
			{
				Execute(kind, manager.LocalClientId, id, attempt, step, inputTime);
				return;
			}
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(64, (Allocator)2, -1);
			try
			{
				byte b = 4;
				((FastBufferWriter)(ref val)).WriteValueSafe<byte>(ref b, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<byte>(ref kind, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref localNonce, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref serverNonce, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref levelNonce, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref id, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref attempt, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref step, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<double>(ref inputTime, default(ForPrimitives));
				messages.SendNamedMessage("Serenta.IndustrialGoldSafe.Command.4", 0uL, val, (NetworkDelivery)3);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		public static void RecordReward(ulong id, int value)
		{
			Guard(delegate
			{
				if (EnsureBound() && manager.IsServer && value >= 0 && ObjectExists(id))
				{
					PruneRewards();
					if (!rewards.ContainsKey(id))
					{
						rewards.Add(id, value);
						rewardObjects[id] = CurrentObject(id);
						QueueReward(id, value);
						FlushRewards();
						foreach (ulong item in new List<ulong>(peers.Keys))
						{
							try
							{
								SendReward(item, id, value);
							}
							catch (Exception ex)
							{
								pendingHello.Add(item);
								Warn(ex);
							}
						}
					}
				}
			});
		}

		public unsafe static void Tick()
		{
			Guard(delegate
			{
				//IL_0021: 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_0211: Unknown result type (might be due to invalid IL or missing references)
				//IL_0217: Unknown result type (might be due to invalid IL or missing references)
				//IL_0227: Unknown result type (might be due to invalid IL or missing references)
				//IL_022d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0240: Unknown result type (might be due to invalid IL or missing references)
				if (EnsureBound())
				{
					PruneRewards();
					if (manager.IsServer)
					{
						NetworkTime serverTime = manager.ServerTime;
						double time = ((NetworkTime)(ref serverTime)).Time;
						SafeSnapshot[] array = authority.Snapshot();
						foreach (SafeSnapshot safeSnapshot in array)
						{
							if (authority.Tick(safeSnapshot.SafeId, time, Eligible(safeSnapshot.OperatorClientId, safeSnapshot.SafeId)))
							{
								Publish(safeSnapshot.SafeId, safeSnapshot.Mode != SafeMode.Open);
							}
						}
						foreach (ulong item in new List<ulong>(pendingHello))
						{
							if (!Connected(item) || !peers.ContainsKey(item))
							{
								pendingHello.Remove(item);
							}
							else
							{
								try
								{
									SendAck(item);
									array = authority.Snapshot();
									foreach (SafeSnapshot s in array)
									{
										SendState(item, s);
									}
									foreach (KeyValuePair<ulong, int> item2 in new List<KeyValuePair<ulong, int>>(rewards))
									{
										if (ObjectExists(item2.Key))
										{
											int? num = ((currentRewardValue != null) ? currentRewardValue(item2.Key) : ReadLiveReward(item2.Key));
											if (num.HasValue && num.Value >= 0)
											{
												SendReward(item, item2.Key, num.Value);
											}
										}
									}
									if (initialStatisticsReady)
									{
										SendStatistics(item);
									}
									pendingHello.Remove(item);
								}
								catch (Exception ex)
								{
									Warn(ex);
								}
							}
						}
					}
					else if (!acknowledged && Time.realtimeSinceStartup >= nextHello)
					{
						nextHello = Time.realtimeSinceStartup + 2f;
						FastBufferWriter val = default(FastBufferWriter);
						((FastBufferWriter)(ref val))..ctor(9, (Allocator)2, -1);
						try
						{
							byte b = 4;
							((FastBufferWriter)(ref val)).WriteValueSafe<byte>(ref b, default(ForPrimitives));
							((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref localNonce, default(ForPrimitives));
							messages.SendNamedMessage("Serenta.IndustrialGoldSafe.Hello.4", 0uL, val, (NetworkDelivery)3);
						}
						finally
						{
							((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
						}
					}
					FlushRewards();
					FlushStatistics();
				}
			});
		}

		private static bool EnsureBound()
		{
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Expected O, but got Unknown
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Expected O, but got Unknown
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Expected O, but got Unknown
			NetworkManager current = NetworkManager.Singleton;
			if ((Object)(object)current == (Object)null || !current.IsListening || (!current.IsServer && !current.IsConnectedClient) || current.CustomMessagingManager == null)
			{
				if ((Object)(object)manager != (Object)null)
				{
					Shutdown();
				}
				return false;
			}
			if (current == manager && messages == current.CustomMessagingManager)
			{
				return true;
			}
			Shutdown();
			manager = current;
			messages = current.CustomMessagingManager;
			localNonce = NewNonce();
			serverNonce = (current.IsServer ? NewNonce() : 0);
			levelNonce = (ulong)(current.IsServer ? 1 : 0);
			authority = (current.IsServer ? new SafeAuthority(options, levelNonce, (int)serverNonce) : null);
			ulong captured = generation;
			try
			{
				messages.RegisterNamedMessageHandler("Serenta.IndustrialGoldSafe.Hello.4", (HandleNamedMessageDelegate)delegate(ulong sender, FastBufferReader reader)
				{
					//IL_000e: Unknown result type (might be due to invalid IL or missing references)
					//IL_000f: Unknown result type (might be due to invalid IL or missing references)
					if (IsCurrent(current, captured))
					{
						Guard(delegate
						{
							//IL_0007: Unknown result type (might be due to invalid IL or missing references)
							ReceiveHello(sender, reader);
						});
					}
				});
				messages.RegisterNamedMessageHandler("Serenta.IndustrialGoldSafe.Command.4", (HandleNamedMessageDelegate)delegate(ulong sender, FastBufferReader reader)
				{
					//IL_000e: Unknown result type (might be due to invalid IL or missing references)
					//IL_000f: Unknown result type (might be due to invalid IL or missing references)
					if (IsCurrent(current, captured))
					{
						Guard(delegate
						{
							//IL_0007: Unknown result type (might be due to invalid IL or missing references)
							ReceiveCommand(sender, reader);
						});
					}
				});
				messages.RegisterNamedMessageHandler("Serenta.IndustrialGoldSafe.Event.4", (HandleNamedMessageDelegate)delegate(ulong sender, FastBufferReader reader)
				{
					//IL_000e: Unknown result type (might be due to invalid IL or missing references)
					//IL_000f: Unknown result type (might be due to invalid IL or missing references)
					if (IsCurrent(current, captured))
					{
						Guard(delegate
						{
							//IL_0007: Unknown result type (might be due to invalid IL or missing references)
							ReceiveEvent(sender, reader);
						});
					}
				});
				disconnect = delegate(ulong id)
				{
					if (IsCurrent(current, captured))
					{
						peers.Remove(id);
						pendingHello.Remove(id);
						nextStart.Remove(id);
						if (id == current.LocalClientId || (!current.IsServer && id == 0L))
						{
							Shutdown();
						}
					}
				};
				stopped = delegate
				{
					if (manager == current && generation == captured)
					{
						Shutdown();
					}
				};
				current.OnClientDisconnectCallback += disconnect;
				current.OnServerStopped += stopped;
				current.OnClientStopped += stopped;
				Log.LogInfo((object)("Safe messaging bound; authority=" + current.IsServer));
			}
			catch
			{
				Shutdown();
				throw;
			}
			return true;
		}

		public static void Shutdown()
		{
			generation++;
			if (messages != null)
			{
				string[] array = new string[3] { "Serenta.IndustrialGoldSafe.Hello.4", "Serenta.IndustrialGoldSafe.Command.4", "Serenta.IndustrialGoldSafe.Event.4" };
				foreach (string text in array)
				{
					try
					{
						messages.UnregisterNamedMessageHandler(text);
					}
					catch (Exception ex)
					{
						Warn(ex);
					}
				}
			}
			if ((Object)(object)manager != (Object)null)
			{
				if (disconnect != null)
				{
					manager.OnClientDisconnectCallback -= disconnect;
				}
				if (stopped != null)
				{
					manager.OnServerStopped -= stopped;
					manager.OnClientStopped -= stopped;
				}
			}
			manager = null;
			messages = null;
			authority = null;
			disconnect = null;
			stopped = null;
			peers.Clear();
			pendingHello.Clear();
			nextStart.Clear();
			states.Clear();
			rewards.Clear();
			rewardObjects.Clear();
			pendingRewards.Clear();
			pendingObjects.Clear();
			pendingExpires.Clear();
			appliedRewards.Clear();
			statisticsRecorded.Clear();
			statisticsTotal = (statisticsApplied = 0L);
			initialStatisticsReady = false;
			localNonce = (serverNonce = (levelNonce = 0uL));
			acknowledged = false;
			nextHello = 0f;
		}

		private static bool IsCurrent(NetworkManager source, ulong captured)
		{
			if (manager == source && generation == captured)
			{
				return source.IsListening;
			}
			return false;
		}

		private static ulong NewNonce()
		{
			ulong num = BitConverter.ToUInt64(Guid.NewGuid().ToByteArray(), 0);
			if (num != 0L)
			{
				return num;
			}
			return 1uL;
		}

		private static bool Connected(ulong id)
		{
			if ((Object)(object)manager == (Object)null)
			{
				return false;
			}
			foreach (ulong connectedClientsId in manager.ConnectedClientsIds)
			{
				if (connectedClientsId == id)
				{
					return true;
				}
			}
			return false;
		}

		private static bool ObjectExists(ulong id)
		{
			if ((Object)(object)manager != (Object)null && manager.SpawnManager != null && manager.SpawnManager.SpawnedObjects.TryGetValue(id, out var value) && (Object)(object)value != (Object)null)
			{
				return value.IsSpawned;
			}
			return false;
		}

		private static NetworkObject CurrentObject(ulong id)
		{
			if (!ObjectExists(id))
			{
				return null;
			}
			return manager.SpawnManager.SpawnedObjects[id];
		}

		private static bool Eligible(ulong client, ulong id)
		{
			//IL_0084: 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_0099: Unknown result type (might be due to invalid IL or missing references)
			if (!Connected(client) || !ObjectExists(id) || (Object)(object)StartOfRound.Instance == (Object)null || StartOfRound.Instance.allPlayerScripts == null)
			{
				return false;
			}
			NetworkObject val = manager.SpawnManager.SpawnedObjects[id];
			PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts;
			foreach (PlayerControllerB val2 in allPlayerScripts)
			{
				if ((Object)(object)val2 != (Object)null && val2.actualClientId == client && val2.isPlayerControlled && !val2.isPlayerDead && val2.isInsideFactory)
				{
					Vector3 val3 = ((Component)val2).transform.position - ((Component)val).transform.position;
					return (double)((Vector3)(ref val3)).sqrMagnitude <= options.InteractionDistance * options.InteractionDistance;
				}
			}
			return false;
		}

		private static int? ReadLiveReward(ulong id)
		{
			if (!ObjectExists(id))
			{
				return null;
			}
			GrabbableObject component = ((Component)manager.SpawnManager.SpawnedObjects[id]).GetComponent<GrabbableObject>();
			if (!((Object)(object)component != (Object)null))
			{
				return null;
			}
			return component.scrapValue;
		}

		private static void ReceiveHello(ulong sender, FastBufferReader reader)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			if (manager.IsServer && sender != manager.LocalClientId && Connected(sender) && ((FastBufferReader)(ref reader)).Length == 9 && ((FastBufferReader)(ref reader)).TryBeginRead(9))
			{
				byte b = default(byte);
				((FastBufferReader)(ref reader)).ReadValueSafe<byte>(ref b, default(ForPrimitives));
				ulong num = default(ulong);
				((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref num, default(ForPrimitives));
				if (b == 4 && num != 0L)
				{
					peers[sender] = num;
					pendingHello.Add(sender);
				}
			}
		}

		private static void ReceiveCommand(ulong sender, FastBufferReader reader)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: 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_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: 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_00a5: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			if (manager.IsServer && Connected(sender) && peers.TryGetValue(sender, out var value) && ((FastBufferReader)(ref reader)).Length == 54 && ((FastBufferReader)(ref reader)).TryBeginRead(54))
			{
				byte b = default(byte);
				((FastBufferReader)(ref reader)).ReadValueSafe<byte>(ref b, default(ForPrimitives));
				byte b2 = default(byte);
				((FastBufferReader)(ref reader)).ReadValueSafe<byte>(ref b2, default(ForPrimitives));
				ulong num = default(ulong);
				((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref num, default(ForPrimitives));
				ulong num2 = default(ulong);
				((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref num2, default(ForPrimitives));
				ulong num3 = default(ulong);
				((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref num3, default(ForPrimitives));
				ulong id = default(ulong);
				((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref id, default(ForPrimitives));
				ulong token = default(ulong);
				((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref token, default(ForPrimitives));
				int step = default(int);
				((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref step, default(ForPrimitives));
				double time = default(double);
				((FastBufferReader)(ref reader)).ReadValueSafe<double>(ref time, default(ForPrimitives));
				if (b == 4 && b2 <= 3 && num == value && num2 == serverNonce && num3 == levelNonce)
				{
					Execute(b2, sender, id, token, step, time);
				}
			}
		}

		private static void Execute(byte kind, ulong sender, ulong id, ulong token, int step, double time)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			if (claimingDecoder || !authority.TryGetState(id, out var state))
			{
				return;
			}
			NetworkTime serverTime = manager.ServerTime;
			double time2 = ((NetworkTime)(ref serverTime)).Time;
			bool flag = false;
			switch (kind)
			{
			case 0:
			{
				if (state.Mode != SafeMode.Closed || token != state.AttemptToken || step != state.Revision || (nextStart.TryGetValue(sender, out var value) && time2 < value))
				{
					return;
				}
				nextStart[sender] = time2 + 0.25;
				flag = authority.Start(id, sender, time2, Eligible(sender, id));
				break;
			}
			case 1:
				flag = authority.Hit(id, sender, token, step, time, time2, Eligible(sender, id));
				break;
			case 2:
				flag = authority.Cancel(id, sender, token, step);
				break;
			case 3:
				if (!QteMath.IsFinite(time2) || !Eligible(sender, id) || mountDecoder == null || !authority.CanStartDecoder(id, token, step))
				{
					return;
				}
				claimingDecoder = true;
				try
				{
					if (!mountDecoder(sender, id, token))
					{
						return;
					}
					flag = authority.StartDecoder(id, sender, token, step, time2);
					if (!flag)
					{
						throw new InvalidOperationException("A validated decoder claim could not commit.");
					}
				}
				finally
				{
					claimingDecoder = false;
				}
				break;
			}
			if (flag)
			{
				Publish(id, state.Mode != SafeMode.Open);
			}
		}

		private static void Publish(ulong id, bool mayOpen)
		{
			if (!authority.TryGetState(id, out var state))
			{
				return;
			}
			states[id] = state;
			foreach (ulong item in new List<ulong>(peers.Keys))
			{
				try
				{
					SendState(item, state);
				}
				catch (Exception ex)
				{
					pendingHello.Add(item);
					Warn(ex);
				}
			}
			if (!mayOpen || state.Mode != SafeMode.Open || SafeNetworking.OnOpened == null)
			{
				return;
			}
			Delegate[] invocationList = SafeNetworking.OnOpened.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				Action<ulong> action = (Action<ulong>)invocationList[i];
				try
				{
					action(id);
				}
				catch (Exception ex2)
				{
					Warn(ex2);
				}
			}
		}

		private static void Header(FastBufferWriter writer, byte kind, ulong peer)
		{
			//IL_0008: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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)
			byte b = 4;
			((FastBufferWriter)(ref writer)).WriteValueSafe<byte>(ref b, default(ForPrimitives));
			((FastBufferWriter)(ref writer)).WriteValueSafe<byte>(ref kind, default(ForPrimitives));
			ulong num = peers[peer];
			((FastBufferWriter)(ref writer)).WriteValueSafe<ulong>(ref num, default(ForPrimitives));
			((FastBufferWriter)(ref writer)).WriteValueSafe<ulong>(ref serverNonce, default(ForPrimitives));
			((FastBufferWriter)(ref writer)).WriteValueSafe<ulong>(ref levelNonce, default(ForPrimitives));
		}

		private unsafe static void SendAck(ulong peer)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if (!Connected(peer) || !peers.ContainsKey(peer))
			{
				return;
			}
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(26, (Allocator)2, -1);
			try
			{
				Header(val, 0, peer);
				messages.SendNamedMessage("Serenta.IndustrialGoldSafe.Event.4", peer, val, (NetworkDelivery)3);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private unsafe static void SendState(ulong peer, SafeSnapshot s)
		{
			//IL_0024: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: 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_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: 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_00bd: 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_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: 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_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: 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)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: 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_01c5: 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_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			if (!Connected(peer) || !peers.ContainsKey(peer))
			{
				return;
			}
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(176, (Allocator)2, -1);
			try
			{
				Header(val, 1, peer);
				((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref s.SafeId, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref s.Revision, default(ForPrimitives));
				byte mode = (byte)s.Mode;
				((FastBufferWriter)(ref val)).WriteValueSafe<byte>(ref mode, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref s.OperatorClientId, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref s.AttemptToken, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref s.Step, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref s.Failures, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref s.RequiredSteps, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<double>(ref s.JamChancePerFailure, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<double>(ref s.StepStartTime, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<double>(ref s.Deadline, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<double>(ref s.TargetCenter, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<double>(ref s.PeriodSeconds, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<double>(ref s.TargetWidth, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<double>(ref s.PhaseAtStart, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<double>(ref s.EdgeToleranceSeconds, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<double>(ref s.NextPeriodSeconds, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref s.DecoderObjectId, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref s.DecoderInstallerClientId, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<double>(ref s.DecodeStartedAt, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<double>(ref s.DecodeDeadline, default(ForPrimitives));
				messages.SendNamedMessage("Serenta.IndustrialGoldSafe.Event.4", peer, val, (NetworkDelivery)3);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private unsafe static void SendReward(ulong peer, ulong id, int value)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//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_0041: 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)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			if (!Connected(peer) || !peers.ContainsKey(peer))
			{
				return;
			}
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(38, (Allocator)2, -1);
			try
			{
				Header(val, 2, peer);
				((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref id, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref value, default(ForPrimitives));
				messages.SendNamedMessage("Serenta.IndustrialGoldSafe.Event.4", peer, val, (NetworkDelivery)3);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private unsafe static void SendStatistics(ulong peer)
		{
			//IL_0028: 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_003f: 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)
			if (!initialStatisticsReady || !Connected(peer) || !peers.ContainsKey(peer))
			{
				return;
			}
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(34, (Allocator)2, -1);
			try
			{
				Header(val, 3, peer);
				((FastBufferWriter)(ref val)).WriteValueSafe<long>(ref statisticsTotal, default(ForPrimitives));
				messages.SendNamedMessage("Serenta.IndustrialGoldSafe.Event.4", peer, val, (NetworkDelivery)3);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private static void BroadcastStatistics()
		{
			foreach (ulong item in new List<ulong>(peers.Keys))
			{
				try
				{
					SendStatistics(item);
				}
				catch (Exception ex)
				{
					pendingHello.Add(item);
					Warn(ex);
				}
			}
		}

		private static void ReceiveEvent(ulong sender, FastBufferReader reader)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: 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_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0303: Unknown result type (might be due to invalid IL or missing references)
			//IL_0309: Unknown result type (might be due to invalid IL or missing references)
			//IL_031b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0321: Unknown result type (might be due to invalid IL or missing references)
			//IL_0333: Unknown result type (might be due to invalid IL or missing references)
			//IL_0339: Unknown result type (might be due to invalid IL or missing references)
			//IL_034b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0351: Unknown result type (might be due to invalid IL or missing references)
			//IL_0363: Unknown result type (might be due to invalid IL or missing references)
			//IL_0369: Unknown result ty