Decompiled source of Gunworks v0.1.0

plugins/Gunworks/Gunworks.dll

Decompiled 15 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.UI;

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Gunworks
{
	internal sealed class Ammo
	{
		public const string GiveRpc = "gw_give";

		private readonly IModHost host;

		private readonly float scale;

		private Recipe recipe;

		public AmmoSpec Spec { get; }

		public GameObject Item { get; private set; }

		public string ItemName => Spec.Name;

		public Ammo(IModHost host, AmmoSpec spec, float scale)
		{
			this.host = host;
			this.scale = scale;
			Spec = spec;
		}

		public GameObject Ensure(IEnumerable<GameObject> vanilla, Transform holder, Dictionary<string, Material> materials)
		{
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: 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_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: 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_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Expected O, but got Unknown
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Item != (Object)null)
			{
				return Item;
			}
			GameObject val = vanilla.FirstOrDefault((Func<GameObject, bool>)((GameObject go) => (Object)(object)go != (Object)null && ((Object)go).name == Spec.Look));
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			GameObject val2 = Object.Instantiate<GameObject>(val, holder, false);
			((Object)val2).name = Spec.Prefab;
			LODGroup[] componentsInChildren = val2.GetComponentsInChildren<LODGroup>(true);
			for (int num = 0; num < componentsInChildren.Length; num++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[num]);
			}
			Renderer[] componentsInChildren2 = val2.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val3 in componentsInChildren2)
			{
				Object.DestroyImmediate((Object)(((Object)(object)((Component)val3).gameObject == (Object)(object)val2) ? ((object)val3) : ((object)((Component)val3).gameObject)));
			}
			Collider[] componentsInChildren3 = val2.GetComponentsInChildren<Collider>(true);
			for (int num = 0; num < componentsInChildren3.Length; num++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren3[num]);
			}
			Model model = Files.Mesh(host, Spec.Model);
			GameObject val4 = new GameObject("look")
			{
				layer = val2.layer
			};
			val4.transform.SetParent(val2.transform, false);
			val4.transform.localScale = Vector3.one * scale;
			val4.AddComponent<MeshFilter>().sharedMesh = model.mesh;
			((Renderer)val4.AddComponent<MeshRenderer>()).sharedMaterials = model.slots.Select((string slot) => materials[slot]).ToArray();
			BoxCollider obj = val2.AddComponent<BoxCollider>();
			Bounds bounds = model.mesh.bounds;
			obj.center = ((Bounds)(ref bounds)).center * scale;
			bounds = model.mesh.bounds;
			obj.size = ((Bounds)(ref bounds)).size * scale;
			ItemDrop component = val2.GetComponent<ItemDrop>();
			SharedData val5 = (SharedData)AccessTools.Method(typeof(object), "MemberwiseClone", (Type[])null, (Type[])null).Invoke(component.m_itemData.m_shared, null);
			val5.m_name = Spec.Name;
			val5.m_description = Spec.Description;
			val5.m_itemType = (ItemType)1;
			val5.m_weight = Spec.Weight;
			val5.m_maxStackSize = Spec.MaxStack;
			val5.m_teleportable = true;
			val5.m_icons = (Sprite[])(object)new Sprite[1] { Files.Icon(host, Spec.Icon) };
			component.m_itemData.m_shared = val5;
			component.m_itemData.m_stack = 1;
			Item = val2;
			Renew(val5);
			return val2;
		}

		private void Renew(SharedData shared)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			foreach (ItemData item in from i in ((Humanoid)localPlayer).GetInventory().GetAllItems()
				where i.m_shared.m_name == shared.m_name
				select i)
			{
				item.m_shared = shared;
				item.m_dropPrefab = Item;
			}
		}

		public void Register(ObjectDB db, CraftingStation station)
		{
			if ((Object)(object)Item == (Object)null)
			{
				return;
			}
			if (!db.m_items.Contains(Item))
			{
				db.m_items.RemoveAll((GameObject go) => (Object)(object)go != (Object)null && ((Object)go).name == ((Object)Item).name);
				db.m_items.Add(Item);
				db.UpdateRegisters();
			}
			if ((Object)(object)recipe == (Object)null)
			{
				recipe = ScriptableObject.CreateInstance<Recipe>();
				((Object)recipe).name = "Recipe_" + Spec.Prefab;
				recipe.m_item = Item.GetComponent<ItemDrop>();
				recipe.m_amount = 1;
			}
			recipe.m_craftingStation = station;
			recipe.m_resources = Guns.Costs(host, db, Spec.Cost(), Spec.Name, recover: false);
			if (!db.m_recipes.Contains(recipe))
			{
				db.m_recipes.Add(recipe);
			}
		}

		public void Unload()
		{
			ObjectDB instance = ObjectDB.instance;
			if ((Object)(object)instance != (Object)null)
			{
				if ((Object)(object)Item != (Object)null && instance.m_items.Remove(Item))
				{
					instance.UpdateRegisters();
				}
				if ((Object)(object)recipe != (Object)null)
				{
					instance.m_recipes.Remove(recipe);
				}
			}
			Item = null;
			recipe = null;
		}

		public static void RegisterGive()
		{
			if (ZRoutedRpc.instance != null)
			{
				Guns.UnregisterRpc("gw_give");
				ZRoutedRpc.instance.Register<string, int>("gw_give", (Action<long, string, int>)OnGive);
			}
		}

		private static void OnGive(long sender, string prefab, int count)
		{
			Player localPlayer = Player.m_localPlayer;
			GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(prefab) : null);
			if (!((Object)(object)localPlayer == (Object)null) && !((Object)(object)val == (Object)null))
			{
				bool flag = ((Humanoid)localPlayer).GetInventory().AddItem(val, count);
				string name = val.GetComponent<ItemDrop>().m_itemData.m_shared.m_name;
				((Character)localPlayer).Message((MessageType)2, flag ? $"{count} {name}" : ("No room for " + name), 0, (Sprite)null, false);
				Guns.Log.LogInfo((object)string.Format("gunworks gave {0} {1}, {2}", count, prefab, flag ? "in the inventory" : "no room"));
			}
		}
	}
	public sealed class GunBuilder
	{
		private readonly Dictionary<string, Material> materials;

		private readonly GameObject smelter;

		public Transform Swivel;

		public Transform Barrel;

		public Transform Muzzle;

		public Transform Seat;

		public Transform Grips;

		public Light Flash;

		public Light Glow;

		public ParticleSystem Steam;

		public IModHost Host { get; }

		public MountedGun Gun { get; }

		public Transform Root { get; }

		internal GunBuilder(IModHost host, MountedGun gun, Transform root, Dictionary<string, Material> materials, GameObject smelter)
		{
			Host = host;
			Gun = gun;
			Root = root;
			this.materials = materials;
			this.smelter = smelter;
		}

		public Transform Part(Transform parent, string model, Vector3 at, Quaternion rotation)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: 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_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			Model model2 = Files.Mesh(Host, model);
			GameObject val = new GameObject(model)
			{
				layer = ((Component)parent).gameObject.layer
			};
			val.transform.SetParent(parent, false);
			val.transform.localPosition = at;
			val.transform.localRotation = rotation;
			val.transform.localScale = Vector3.one * Gun.Scale;
			val.AddComponent<MeshFilter>().sharedMesh = model2.mesh;
			((Renderer)val.AddComponent<MeshRenderer>()).sharedMaterials = model2.slots.Select((string slot) => materials[slot]).ToArray();
			return val.transform;
		}

		public Transform Inner(Transform parent, string model, Vector3 at, Quaternion rotation)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			Transform obj = Part(parent, model, at, rotation);
			obj.localScale = Vector3.one;
			return obj;
		}

		public Transform Point(Transform parent, string name, Vector3 at)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent(parent, false);
			val.transform.localPosition = at;
			return val.transform;
		}

		public GameObject Solid(Transform parent, Vector3 center, Vector3 size, Quaternion rotation)
		{
			//IL_0006: 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_0013: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = Box(parent, "collider", center, size);
			obj.transform.localRotation = rotation;
			obj.AddComponent<Inert>();
			return obj;
		}

		public void Handle(Transform parent, Vector3 center, Vector3 size)
		{
			//IL_0006: 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)
			Box(parent, "handle", center, size).AddComponent<Handle>();
		}

		public void GripsAt(Transform parent, Vector3 center, Vector3 size)
		{
			//IL_0006: 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)
			GameObject val = Box(parent, "grips", center, size);
			val.AddComponent<Grips>();
			Grips = val.transform;
		}

		public void SlotAt(Transform parent, Vector3 center, Vector3 size)
		{
			//IL_0006: 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)
			Box(parent, "slot", center, size).AddComponent<Slot>();
		}

		public Light Lamp(Transform at, Color color, float range, float intensity)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			Light obj = ((Component)at).gameObject.AddComponent<Light>();
			obj.type = (LightType)2;
			obj.color = color;
			obj.range = range;
			obj.intensity = intensity;
			obj.shadows = (LightShadows)0;
			((Behaviour)obj).enabled = false;
			return obj;
		}

		public ParticleSystem SteamAt(Transform at)
		{
			//IL_008a: 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_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: 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)
			ParticleSystem val = (((Object)(object)smelter != (Object)null) ? ((IEnumerable<ParticleSystem>)smelter.GetComponentsInChildren<ParticleSystem>(true)).FirstOrDefault((Func<ParticleSystem, bool>)((ParticleSystem p) => ((Object)p).name.ToLowerInvariant().Contains("smoke"))) : null);
			if ((Object)(object)val == (Object)null)
			{
				Host.Log.LogWarning((object)("the smoke of the smelter was not found, " + Gun.Name + " has no steam"));
				return null;
			}
			GameObject obj = Object.Instantiate<GameObject>(((Component)val).gameObject, at, false);
			obj.transform.localPosition = Vector3.zero;
			obj.transform.localRotation = Quaternion.identity;
			obj.SetActive(true);
			ParticleSystem component = obj.GetComponent<ParticleSystem>();
			MainModule main = component.main;
			((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(new Color(0.95f, 0.95f, 0.95f, 0.7f));
			((MainModule)(ref main)).loop = true;
			((MainModule)(ref main)).playOnAwake = true;
			EmissionModule emission = component.emission;
			((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(0f);
			return component;
		}

		public AudioClip Sound(string name)
		{
			return Files.Sound(Host, name);
		}

		public AudioSource Speaker(AudioClip clip, float maxDistance)
		{
			return Guns.Speaker(((Component)Root).gameObject, clip, maxDistance);
		}

		public Transform FromPrefab(GameObject model)
		{
			GameObject copy = Object.Instantiate<GameObject>(model, Root, false);
			((Object)copy).name = ((Object)model).name;
			Swivel = Find("swivel") ?? Swivel;
			Barrel = Find("barrel") ?? Barrel;
			Muzzle = Find("muzzle") ?? Muzzle;
			Seat = Find("seat") ?? Seat;
			Transform val = Find("grips");
			Transform val2 = Find("slot");
			Transform val3 = Find("handle");
			Collider[] componentsInChildren = copy.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Transform transform = ((Component)componentsInChildren[i]).transform;
				if ((Object)(object)transform == (Object)(object)val)
				{
					((Component)transform).gameObject.AddComponent<Grips>();
					Grips = transform;
				}
				else if ((Object)(object)transform == (Object)(object)val2)
				{
					((Component)transform).gameObject.AddComponent<Slot>();
				}
				else if ((Object)(object)transform == (Object)(object)val3)
				{
					((Component)transform).gameObject.AddComponent<Handle>();
				}
				else
				{
					((Component)transform).gameObject.AddComponent<Inert>();
				}
			}
			return copy.transform;
			Transform Find(string name)
			{
				return ((IEnumerable<Transform>)copy.GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name.ToLowerInvariant() == name));
			}
		}

		private static GameObject Box(Transform parent, string name, Vector3 center, Vector3 size)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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_003d: Expected O, but got Unknown
			GameObject val = new GameObject(name)
			{
				layer = ((Component)parent).gameObject.layer
			};
			val.transform.SetParent(parent, false);
			val.transform.localPosition = center;
			val.AddComponent<BoxCollider>().size = size;
			return val;
		}
	}
	public sealed class SyncedConfig
	{
		private abstract class Entry
		{
			public abstract void Write(ZPackage pkg);

			public abstract void Read(ZPackage pkg);

			public abstract string Show();
		}

		private sealed class Entry<T> : Entry
		{
			public ConfigEntry<T> local;

			public T server;

			public SyncedConfig owner;

			public Func<T, T> clamp;

			public T Value => clamp(owner.fromServer ? server : local.Value);

			public override void Write(ZPackage pkg)
			{
				object obj = Value;
				if (!(obj is float num))
				{
					if (obj is bool flag)
					{
						pkg.Write(flag);
					}
					else
					{
						pkg.Write((string)obj);
					}
				}
				else
				{
					pkg.Write(num);
				}
			}

			public override void Read(ZPackage pkg)
			{
				object obj = ((typeof(T) == typeof(float)) ? ((object)pkg.ReadSingle()) : ((typeof(T) == typeof(bool)) ? ((object)pkg.ReadBool()) : pkg.ReadString()));
				server = (T)obj;
			}

			public override string Show()
			{
				return $"{((ConfigEntryBase)local).Definition.Key} {Value}";
			}
		}

		private static readonly List<SyncedConfig> all = new List<SyncedConfig>();

		private readonly IModHost host;

		private readonly ConfigFile file;

		private readonly string ask;

		private readonly string answer;

		private readonly List<Entry> entries = new List<Entry>();

		private bool fromServer;

		public event Action Received;

		public SyncedConfig(IModHost host, string fileName, string keys)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			this.host = host;
			file = new ConfigFile(Path.Combine(Paths.ConfigPath, fileName), true);
			ask = keys + "_settings_ask";
			answer = keys + "_settings";
			all.Add(this);
		}

		public void Start()
		{
			if (ZRoutedRpc.instance != null && (Object)(object)ZNet.instance != (Object)null)
			{
				Register(ZRoutedRpc.instance);
			}
		}

		public Func<float> Float(string section, string key, float value, string description, float min, float max)
		{
			return Add(section, key, value, description, (float v) => Mathf.Clamp(v, min, max));
		}

		public Func<bool> Bool(string section, string key, bool value, string description)
		{
			return Add(section, key, value, description, (bool v) => v);
		}

		public Func<string> Text(string section, string key, string value, string description)
		{
			return Add(section, key, value, description, (string v) => v);
		}

		private Func<T> Add<T>(string section, string key, T value, string description, Func<T, T> clamp)
		{
			Entry<T> entry = new Entry<T>
			{
				local = file.Bind<T>(section, key, value, description),
				owner = this,
				clamp = clamp
			};
			entries.Add(entry);
			return () => entry.Value;
		}

		internal static void RegisterAll(ZRoutedRpc rpc)
		{
			foreach (SyncedConfig item in all)
			{
				item.Register(rpc);
			}
		}

		internal static void UnregisterAll()
		{
			foreach (SyncedConfig item in all)
			{
				Guns.UnregisterRpc(item.ask, item.answer);
			}
			all.Clear();
		}

		private void Register(ZRoutedRpc rpc)
		{
			Guns.UnregisterRpc(ask, answer);
			rpc.Register(ask, (Action<long>)OnAsk);
			rpc.Register<ZPackage>(answer, (Action<long, ZPackage>)OnAnswer);
			fromServer = false;
			if (!ZNet.instance.IsServer())
			{
				rpc.InvokeRoutedRPC(rpc.GetServerPeerID(), ask, Array.Empty<object>());
			}
		}

		private void OnAsk(long sender)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			if (!ZNet.instance.IsServer())
			{
				return;
			}
			ZPackage val = new ZPackage();
			foreach (Entry entry in entries)
			{
				entry.Write(val);
			}
			ZRoutedRpc.instance.InvokeRoutedRPC(sender, answer, new object[1] { val });
		}

		private void OnAnswer(long sender, ZPackage pkg)
		{
			foreach (Entry entry in entries)
			{
				entry.Read(pkg);
			}
			fromServer = true;
			host.Log.LogInfo((object)(host.Name + " settings from the server: " + string.Join(", ", entries.ConvertAll((Entry e) => e.Show()))));
			this.Received?.Invoke();
		}
	}
	internal static class Damage
	{
		private const int AnyTier = 100;

		public static bool Hits(Player gunner, Collider collider)
		{
			Character componentInParent = ((Component)collider).GetComponentInParent<Character>();
			if ((Object)(object)componentInParent == (Object)null)
			{
				return true;
			}
			if ((Object)(object)componentInParent == (Object)(object)gunner || componentInParent.IsDead())
			{
				return false;
			}
			if (!BaseAI.IsEnemy((Character)(object)gunner, componentInParent) && (!((Object)(object)componentInParent.GetBaseAI() != (Object)null) || !componentInParent.GetBaseAI().IsAggravatable()))
			{
				return ((Character)gunner).IsPVPEnabled();
			}
			return true;
		}

		public static void Strike(Player gunner, Collider collider, Vector3 point, Vector3 dir, RoundSpec spec)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_0026: 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_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_0093: Unknown result type (might be due to invalid IL or missing references)
			IDestructible componentInParent = ((Component)collider).GetComponentInParent<IDestructible>();
			if (componentInParent == null)
			{
				if ((Object)(object)((Component)collider).GetComponent<Heightmap>() != (Object)null && Random.value < spec.DentChance)
				{
					Guns.Dent(point, gunner);
				}
			}
			else if (Breaks(gunner, collider))
			{
				HitData val = new HitData();
				if (componentInParent is Character)
				{
					val.m_damage.m_pierce = spec.Damage();
				}
				else
				{
					val.m_damage.m_damage = spec.Damage();
					val.m_toolTier = 100;
					val.m_itemWorldLevel = (byte)Game.m_worldLevel;
				}
				val.m_point = point;
				val.m_dir = dir;
				val.m_pushForce = spec.PushForce;
				val.m_ranged = true;
				val.m_dodgeable = false;
				val.m_blockable = true;
				val.m_hitCollider = collider;
				val.SetAttacker((Character)(object)gunner);
				componentInParent.Damage(val);
			}
		}

		private static bool Breaks(Player gunner, Collider collider)
		{
			Piece componentInParent = ((Component)collider).GetComponentInParent<Piece>();
			if ((Object)(object)componentInParent == (Object)null || Guns.BreakAllBuildings() || ((Character)gunner).IsPVPEnabled())
			{
				return true;
			}
			long creator = componentInParent.GetCreator();
			if (creator != 0L)
			{
				return creator == gunner.GetPlayerID();
			}
			return true;
		}
	}
	public class Feed : MonoBehaviour
	{
		private ZNetView m_nview;

		private FeedSpec m_spec;

		private Ammo m_ammo;

		private string m_roundsKey;

		private string m_loadRpc;

		public FeedSpec Spec => m_spec;

		public int Loaded
		{
			get
			{
				if (m_spec == null || !m_nview.IsValid())
				{
					return 0;
				}
				return m_nview.GetZDO().GetInt(m_roundsKey, 0);
			}
		}

		private void Awake()
		{
			m_nview = ((Component)this).GetComponentInParent<ZNetView>();
			Guns.Entry entry = Guns.Find(((Component)this).GetComponent<Gun>()?.m_prefab);
			if (!((Object)(object)m_nview == (Object)null) && m_nview.GetZDO() != null && entry != null)
			{
				m_spec = entry.gun.Feed;
				m_ammo = entry.ammo;
				m_roundsKey = entry.gun.Keys + "_rounds";
				m_loadRpc = entry.gun.Keys + "_load";
				m_nview.Register<int>(m_loadRpc, (Action<long, int>)OnLoad);
			}
		}

		public bool Holds(ItemData item)
		{
			if ((Object)(object)m_ammo?.Item != (Object)null)
			{
				return item.m_shared.m_name == m_ammo.ItemName;
			}
			return false;
		}

		public bool Load(Humanoid user, Gun gun)
		{
			if (m_spec == null || !m_nview.IsValid() || (Object)(object)m_ammo?.Item == (Object)null)
			{
				return false;
			}
			Inventory inventory = user.GetInventory();
			if (inventory.CountItems(m_ammo.ItemName, -1, true) == 0)
			{
				((Character)user).Message((MessageType)2, "You have no " + m_ammo.ItemName, 0, (Sprite)null, false);
				return false;
			}
			if (Loaded + m_spec.RoundsPerItem > m_spec.Most)
			{
				((Character)user).Message((MessageType)2, $"The gun holds {m_spec.Most} rounds", 0, (Sprite)null, false);
				return false;
			}
			inventory.RemoveItem(m_ammo.ItemName, 1, -1, true);
			m_nview.InvokeRPC(m_loadRpc, new object[1] { m_spec.RoundsPerItem });
			m_nview.InvokeRPC(ZNetView.Everybody, gun.LoadShowRpc, Array.Empty<object>());
			((Character)user).Message((MessageType)2, $"A {m_spec.Noun} of {m_spec.RoundsPerItem} rounds is in", 0, (Sprite)null, false);
			return true;
		}

		public void Spend(int rounds)
		{
			if (m_spec != null && rounds > 0)
			{
				ZDO zDO = m_nview.GetZDO();
				zDO.Set(m_roundsKey, Mathf.Max(0, zDO.GetInt(m_roundsKey, 0) - rounds));
			}
		}

		private void OnLoad(long sender, int rounds)
		{
			if (m_nview.IsOwner())
			{
				ZDO zDO = m_nview.GetZDO();
				zDO.Set(m_roundsKey, Mathf.Min(m_spec.Most, zDO.GetInt(m_roundsKey, 0) + rounds));
			}
		}
	}
	public sealed class Model
	{
		public Mesh mesh;

		public string[] slots;

		public List<Box> boxes;
	}
	public sealed class Box
	{
		public Vector3 center;

		public Vector3 size;

		public Quaternion rotation;
	}
	public static class Files
	{
		private static readonly Dictionary<string, Model> models = new Dictionary<string, Model>();

		private static readonly Dictionary<string, AssetBundle> bundles = new Dictionary<string, AssetBundle>();

		public static Model Mesh(IModHost host, string name)
		{
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: 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_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: 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_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: 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_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Expected O, but got Unknown
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			string key = host.Name + "/" + name;
			if (models.TryGetValue(key, out var value))
			{
				return value;
			}
			using BinaryReader binaryReader = new BinaryReader(new MemoryStream(host.ReadAsset("meshes/" + name + ".bfm")));
			if (Encoding.ASCII.GetString(binaryReader.ReadBytes(4)) != "BFM5")
			{
				throw new InvalidDataException(name + " is not a mesh file");
			}
			int num = binaryReader.ReadInt32();
			List<Vector3> list = new List<Vector3>();
			List<Vector3> list2 = new List<Vector3>();
			List<Vector2> list3 = new List<Vector2>();
			List<int[]> list4 = new List<int[]>();
			string[] array = new string[num];
			for (int i = 0; i < num; i++)
			{
				array[i] = Encoding.UTF8.GetString(binaryReader.ReadBytes(binaryReader.ReadInt32()));
				int count = list.Count;
				int num2 = binaryReader.ReadInt32();
				for (int j = 0; j < num2; j++)
				{
					list.Add(Vector(binaryReader));
					list2.Add(Vector(binaryReader));
					list3.Add(new Vector2(binaryReader.ReadSingle(), binaryReader.ReadSingle()));
				}
				int[] array2 = new int[binaryReader.ReadInt32()];
				for (int k = 0; k < array2.Length; k++)
				{
					array2[k] = count + binaryReader.ReadInt32();
				}
				list4.Add(array2);
			}
			List<Box> list5 = new List<Box>();
			int num3 = binaryReader.ReadInt32();
			for (int l = 0; l < num3; l++)
			{
				Vector3 center = Vector(binaryReader);
				Vector3 size = Vector(binaryReader);
				Vector3 val = Vector(binaryReader);
				Vector3 val2 = Vector(binaryReader);
				list5.Add(new Box
				{
					center = center,
					size = size,
					rotation = Quaternion.LookRotation(val, val2)
				});
			}
			Mesh val3 = new Mesh
			{
				name = "gw_" + name
			};
			if (list.Count > 65535)
			{
				val3.indexFormat = (IndexFormat)1;
			}
			val3.SetVertices(list);
			val3.SetNormals(list2);
			val3.SetUVs(0, list3);
			val3.SetColors(Enumerable.Repeat<Color>(Color.white, list.Count).ToList());
			val3.subMeshCount = num;
			for (int m = 0; m < num; m++)
			{
				val3.SetTriangles(list4[m], m);
			}
			val3.RecalculateBounds();
			val3.RecalculateTangents();
			value = new Model
			{
				mesh = val3,
				slots = array,
				boxes = list5
			};
			models[key] = value;
			return value;
		}

		private static Vector3 Vector(BinaryReader reader)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
		}

		public static Sprite Icon(IModHost host, string name)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			//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)
			Texture2D val = new Texture2D(2, 2);
			ImageConversion.LoadImage(val, host.ReadAsset("icons/" + name + ".png"));
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
		}

		public static AudioClip Sound(IModHost host, string name)
		{
			byte[] array = host.ReadAsset("sounds/" + name + ".wav");
			if (Encoding.ASCII.GetString(array, 0, 4) != "RIFF" || Encoding.ASCII.GetString(array, 8, 4) != "WAVE")
			{
				throw new FormatException(name + ".wav is not a WAV file");
			}
			int num = 1;
			int num2 = 44100;
			int num3;
			for (int i = 12; i + 8 <= array.Length; i += 8 + num3 + (num3 & 1))
			{
				string text = Encoding.ASCII.GetString(array, i, 4);
				num3 = BitConverter.ToInt32(array, i + 4);
				if (text == "fmt ")
				{
					num = BitConverter.ToInt16(array, i + 10);
					num2 = BitConverter.ToInt32(array, i + 12);
					if (BitConverter.ToInt16(array, i + 22) != 16)
					{
						throw new FormatException(name + ".wav is not 16 bit");
					}
				}
				else if (text == "data")
				{
					int num4 = Math.Min(num3, array.Length - i - 8) / 2;
					float[] array2 = new float[num4];
					for (int j = 0; j < num4; j++)
					{
						array2[j] = (float)BitConverter.ToInt16(array, i + 8 + j * 2) / 32768f;
					}
					AudioClip obj = AudioClip.Create(host.Name + " " + name, num4 / num, num, num2, false);
					obj.SetData(array2, 0);
					return obj;
				}
			}
			throw new FormatException(name + ".wav has no data");
		}

		public static GameObject Bundle(IModHost host, string file, string asset)
		{
			string key = host.Name + "/" + file;
			if (!bundles.TryGetValue(key, out var value))
			{
				value = AssetBundle.LoadFromMemory(host.ReadAsset(file));
				if ((Object)(object)value == (Object)null)
				{
					throw new InvalidDataException(file + " is not an asset bundle of this Unity version");
				}
				bundles[key] = value;
			}
			GameObject val = value.LoadAsset<GameObject>(asset);
			if ((Object)(object)val == (Object)null)
			{
				throw new InvalidDataException(file + " has no prefab " + asset + ", it has " + string.Join(", ", value.GetAllAssetNames()));
			}
			return val;
		}

		public static void Clear()
		{
			models.Clear();
			foreach (AssetBundle value in bundles.Values)
			{
				value.Unload(true);
			}
			bundles.Clear();
		}
	}
	internal sealed class Flight
	{
		private sealed class Round
		{
			public LineRenderer line;

			public LineRenderer core;

			public Light light;

			public Vector3 at;

			public Vector3 velocity;

			public float flown;

			public Player gunner;

			public bool active;
		}

		private const int MostRounds = 48;

		private readonly Transform gun;

		private readonly RoundSpec spec;

		private readonly float range;

		private readonly Material tracer;

		private readonly Material core;

		private readonly List<Round> rounds = new List<Round>();

		public Flight(Transform gun, RoundSpec spec, float range, Material tracer, Material core)
		{
			this.gun = gun;
			this.spec = spec;
			this.range = range;
			this.tracer = tracer;
			this.core = core;
		}

		public void Launch(Vector3 from, Vector3 dir, Player gunner)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			Round round = Free();
			if (round != null)
			{
				round.at = from;
				round.velocity = ((Vector3)(ref dir)).normalized * spec.Speed;
				round.flown = 0f;
				round.gunner = gunner;
				round.active = true;
				Show(round, on: true);
				Draw(round);
			}
		}

		public void Fly(float dt)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: 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_009f: 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_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			foreach (Round item in rounds.Where((Round r) => r.active))
			{
				Vector3 val = item.velocity * dt;
				item.velocity += Vector3.down * spec.Gravity * dt;
				if (Cast(item, val, out var found))
				{
					item.at = ((RaycastHit)(ref found)).point;
					Land(item, found);
					continue;
				}
				item.at += val;
				item.flown += ((Vector3)(ref val)).magnitude;
				if (item.flown >= range)
				{
					Stop(item);
				}
				else
				{
					Draw(item);
				}
			}
		}

		private bool Cast(Round round, Vector3 step, out RaycastHit found)
		{
			//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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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_00f9: 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_00da: Unknown result type (might be due to invalid IL or missing references)
			float magnitude = ((Vector3)(ref step)).magnitude;
			object obj;
			if (!((Object)(object)round.gunner != (Object)null))
			{
				Player localPlayer = Player.m_localPlayer;
				obj = ((localPlayer != null) ? ((Component)localPlayer).transform : null);
			}
			else
			{
				obj = ((Component)round.gunner).transform;
			}
			Transform val = (Transform)obj;
			foreach (RaycastHit item in from h in Physics.RaycastAll(round.at, step / magnitude, magnitude, Gun.Mask)
				orderby ((RaycastHit)(ref h)).distance
				select h)
			{
				RaycastHit current = item;
				if (!((Component)((RaycastHit)(ref current)).collider).transform.IsChildOf(gun) && (!((Object)(object)val != (Object)null) || !((Component)((RaycastHit)(ref current)).collider).transform.IsChildOf(val)) && (!((Object)(object)round.gunner != (Object)null) || Damage.Hits(round.gunner, ((RaycastHit)(ref current)).collider)))
				{
					found = current;
					return true;
				}
			}
			found = default(RaycastHit);
			return false;
		}

		private void Land(Round round, RaycastHit hit)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_0051: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)round.gunner != (Object)null)
			{
				Damage.Strike(round.gunner, ((RaycastHit)(ref hit)).collider, ((RaycastHit)(ref hit)).point, ((Vector3)(ref round.velocity)).normalized, spec);
			}
			EffectList hitEffects = Guns.HitEffects;
			if (hitEffects != null)
			{
				hitEffects.Create(((RaycastHit)(ref hit)).point, Quaternion.LookRotation(((RaycastHit)(ref hit)).normal), (Transform)null, 1f, -1, default(ZDOID));
			}
			Stop(round);
		}

		private void Draw(Round round)
		{
			//IL_0015: 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_001f: 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_0051: 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)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: 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_0088: 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_0097: 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)
			if (!((Object)(object)round.line == (Object)null))
			{
				Vector3 val = -((Vector3)(ref round.velocity)).normalized;
				float num = Mathf.Min(round.flown, spec.TracerLength);
				round.line.SetPosition(0, round.at);
				round.line.SetPosition(1, round.at + val * num);
				round.core.SetPosition(0, round.at);
				round.core.SetPosition(1, round.at + val * num * 0.45f);
				((Component)round.light).transform.position = round.at;
			}
		}

		private static void Stop(Round round)
		{
			round.active = false;
			Show(round, on: false);
		}

		private static void Show(Round round, bool on)
		{
			if ((Object)(object)round.line != (Object)null)
			{
				((Renderer)round.line).enabled = on;
				((Renderer)round.core).enabled = on;
				((Behaviour)round.light).enabled = on;
			}
		}

		private Round Free()
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Expected O, but got Unknown
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Expected O, but got Unknown
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			Round round = rounds.FirstOrDefault((Round r) => !r.active);
			if (round != null)
			{
				return round;
			}
			if (rounds.Count >= 48)
			{
				return null;
			}
			if ((Object)(object)tracer == (Object)null)
			{
				round = new Round();
				rounds.Add(round);
				return round;
			}
			GameObject val = new GameObject("round");
			val.transform.SetParent(gun, false);
			LineRenderer line = Streak(val, tracer, spec.TracerWidth);
			GameObject val2 = new GameObject("core");
			val2.transform.SetParent(val.transform, false);
			LineRenderer val3 = Streak(val2, core ?? tracer, spec.CoreWidth);
			Light val4 = val.AddComponent<Light>();
			val4.type = (LightType)2;
			val4.color = new Color(1f, 0.5f, 0.15f);
			val4.range = 5f;
			val4.intensity = 3f;
			val4.shadows = (LightShadows)0;
			((Behaviour)val4).enabled = false;
			round = new Round
			{
				line = line,
				core = val3,
				light = val4
			};
			rounds.Add(round);
			return round;
		}

		private static LineRenderer Streak(GameObject go, Material material, float width)
		{
			//IL_002e: 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)
			LineRenderer obj = go.AddComponent<LineRenderer>();
			obj.useWorldSpace = true;
			obj.positionCount = 2;
			obj.startWidth = width;
			obj.endWidth = 0f;
			((Renderer)obj).material = material;
			obj.startColor = Color.white;
			obj.endColor = new Color(1f, 1f, 1f, 0f);
			obj.numCapVertices = 2;
			((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)obj).receiveShadows = false;
			((Renderer)obj).enabled = false;
			return obj;
		}
	}
	public class Gun : MonoBehaviour, IDoodadController
	{
		[HarmonyPatch(typeof(Player), "SetControls")]
		private static class TriggerFromAttack
		{
			private static void Prefix(Player __instance, ref bool attack, ref bool attackHold, ref bool secondaryAttack, ref bool secondaryAttackHold)
			{
				if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && __instance.GetDoodadController() is Gun gun)
				{
					gun.SetTrigger((attack | attackHold) || gun.FireHeld);
					attack = false;
					attackHold = false;
					secondaryAttack = false;
					secondaryAttackHold = false;
				}
			}
		}

		public static readonly int Mask = LayerMask.GetMask(new string[13]
		{
			"Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "terrain", "character", "character_net", "character_ghost", "hitbox",
			"character_noenv", "vehicle", "tree"
		});

		public string m_prefab;

		public Transform m_swivel;

		public Transform m_barrel;

		public Transform m_muzzle;

		public Transform m_seat;

		public Transform m_grips;

		public Light m_flash;

		public Light m_glow;

		public ParticleSystem m_steam;

		public AudioSource[] m_voices;

		public AudioSource m_tail;

		private MountedGun m_spec;

		private Guns.Entry m_entry;

		private string m_userKey;

		private string m_yawKey;

		private string m_pitchKey;

		private string m_heatKey;

		private string m_heatTimeKey;

		private string m_jamKey;

		private string m_firingKey;

		private string m_takeRpc;

		private string m_grantRpc;

		private string m_releaseRpc;

		private string m_stateRpc;

		private string m_loadShowRpc;

		private ZNetView m_nview;

		private Rigidbody m_body;

		private Feed m_feed;

		private IGunExtra[] m_extras;

		private bool m_manned;

		private bool m_trigger;

		private Vector3 m_look;

		private Vector3 m_target;

		private float m_yaw;

		private float m_pitch;

		private float m_shotTimer;

		private int m_spent;

		private float m_heat;

		private double m_heatTime;

		private double m_jamUntil;

		private float m_nextSend;

		private bool m_wasFiring;

		private float m_flashOff;

		private int m_voice;

		private float m_burnMessage;

		private float m_loadWait;

		private Hud m_hud;

		private int m_rounds;

		private int m_lastSeen;

		private Flight m_flight;

		public static Gun Manned { get; private set; }

		public MountedGun Spec => m_spec;

		public bool Busy => m_extras.Any((IGunExtra e) => e.Busy);

		public string LoadShowRpc => m_loadShowRpc;

		private static double Now
		{
			get
			{
				if (!((Object)(object)ZNet.instance != (Object)null))
				{
					return Time.time;
				}
				return ZNet.instance.GetTimeSeconds();
			}
		}

		public float Heat
		{
			get
			{
				if (!m_manned)
				{
					return HeatNow(m_nview.GetZDO().GetFloat(m_heatKey, 0f), Seconds(m_heatTimeKey));
				}
				return HeatNow(m_heat, m_heatTime);
			}
		}

		public float JamLeft => (float)((m_manned ? m_jamUntil : Seconds(m_jamKey)) - Now);

		public bool Infinite => m_spec.Fire.InfiniteAmmo();

		public int Rounds
		{
			get
			{
				if (!Infinite)
				{
					if (!m_manned)
					{
						return Loaded;
					}
					return m_rounds;
				}
				return int.MaxValue;
			}
		}

		private int Loaded
		{
			get
			{
				if (!((Object)(object)m_feed != (Object)null))
				{
					return 0;
				}
				return m_feed.Loaded;
			}
		}

		public long User
		{
			get
			{
				if (!m_nview.IsValid())
				{
					return 0L;
				}
				return m_nview.GetZDO().GetLong(m_userKey, 0L);
			}
		}

		private float Interval => 60f / m_spec.Fire.RoundsPerMinute();

		internal bool FireHeld
		{
			get
			{
				if ((Object)(object)m_hud != (Object)null)
				{
					return m_hud.FireHeld;
				}
				return false;
			}
		}

		private void Awake()
		{
			m_nview = ((Component)this).GetComponent<ZNetView>();
			m_body = ((Component)this).GetComponent<Rigidbody>();
			m_feed = ((Component)this).GetComponentInChildren<Feed>(true);
			m_extras = ((Component)this).GetComponents<IGunExtra>();
			m_entry = Guns.Find(m_prefab);
			if ((Object)(object)m_nview == (Object)null || m_nview.GetZDO() == null || m_entry == null)
			{
				((Behaviour)this).enabled = false;
				return;
			}
			m_spec = m_entry.gun;
			string keys = m_spec.Keys;
			m_userKey = keys + "_user";
			m_yawKey = keys + "_yaw";
			m_pitchKey = keys + "_pitch";
			m_heatKey = keys + "_heat";
			m_heatTimeKey = keys + "_heat_time";
			m_jamKey = keys + "_jam";
			m_firingKey = keys + "_firing";
			m_takeRpc = keys + "_take";
			m_grantRpc = keys + "_grant";
			m_releaseRpc = keys + "_release";
			m_stateRpc = keys + "_state";
			m_loadShowRpc = keys + "_load_show";
			m_flight = new Flight(((Component)this).transform, m_spec.Round, m_spec.Fire.Range, m_entry.tracer, m_entry.core);
			m_nview.Register<long>(m_takeRpc, (Action<long, long>)OnTake);
			m_nview.Register<bool>(m_grantRpc, (Action<long, bool>)OnGrant);
			m_nview.Register<long>(m_releaseRpc, (Action<long, long>)OnRelease);
			m_nview.Register<ZPackage>(m_stateRpc, (Action<long, ZPackage>)OnState);
			m_nview.Register(m_loadShowRpc, (Action<long>)OnLoadShow);
		}

		private void OnLoadShow(long sender)
		{
			IGunExtra[] extras = m_extras;
			for (int i = 0; i < extras.Length; i++)
			{
				extras[i].OnLoadShow();
			}
		}

		public void LoadFrom(Humanoid user)
		{
			m_feed?.Load(user, this);
		}

		private void OnDestroy()
		{
			if (m_manned && (Object)(object)Player.m_localPlayer != (Object)null)
			{
				Player.m_localPlayer.StopDoodadControl();
				((Character)Player.m_localPlayer).AttachStop();
			}
			Leave();
		}

		private float HeatNow(float heat, double since)
		{
			HeatSpec heat2 = m_spec.Heat;
			if (heat2 == null)
			{
				return 0f;
			}
			float num = (float)(Now - since) - heat2.CoolAfter;
			return Mathf.Max(0f, heat - Mathf.Max(0f, num) * heat2.CoolPerSecond);
		}

		private double Seconds(string key)
		{
			return (double)m_nview.GetZDO().GetLong(key, 0L) / 1000.0;
		}

		public void Take(Humanoid character)
		{
			Player val = (Player)(object)((character is Player) ? character : null);
			if (!((Object)(object)val == (Object)null) && m_nview.IsValid())
			{
				if (m_manned)
				{
					val.StopDoodadControl();
					return;
				}
				m_nview.InvokeRPC(m_takeRpc, new object[1] { val.GetPlayerID() });
			}
		}

		private void OnTake(long sender, long playerID)
		{
			if (m_nview.IsOwner())
			{
				long user = User;
				bool flag = user == 0L || user == playerID || (Object)(object)Player.GetPlayer(user) == (Object)null;
				if (flag)
				{
					m_nview.GetZDO().Set(m_userKey, playerID);
				}
				m_nview.InvokeRPC(sender, m_grantRpc, new object[1] { flag });
			}
		}

		private void OnGrant(long sender, bool granted)
		{
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null))
			{
				if (!granted)
				{
					((Character)localPlayer).Message((MessageType)2, "$msg_inuse", 0, (Sprite)null, false);
					return;
				}
				ZDO zDO = m_nview.GetZDO();
				m_heat = zDO.GetFloat(m_heatKey, 0f);
				m_heatTime = Seconds(m_heatTimeKey);
				m_jamUntil = Seconds(m_jamKey);
				m_rounds = Loaded;
				m_lastSeen = m_rounds;
				m_yaw = zDO.GetFloat(m_yawKey, 0f);
				m_pitch = zDO.GetFloat(m_pitchKey, 0f);
				m_spent = 0;
				m_manned = true;
				Manned = this;
				localPlayer.StartDoodadControl((IDoodadController)(object)this);
				((Character)localPlayer).AttachStart(m_seat, ((Component)this).gameObject, true, false, false, "crouching", new Vector3(0f, 0.1f, -0.3f), (Transform)null);
				m_hud = Hud.Show(this);
				Guns.Log.LogInfo((object)$"{m_spec.Name} taken, {Rounds} rounds, heat {Heat:0}");
			}
		}

		private void OnRelease(long sender, long playerID)
		{
			if (m_nview.IsOwner() && User == playerID)
			{
				m_nview.GetZDO().Set(m_userKey, 0L);
				m_nview.GetZDO().Set(m_firingKey, false);
			}
		}

		public void OnUseStop(Player player)
		{
			if (m_manned)
			{
				Send(force: true, firing: false);
				if (m_nview.IsValid())
				{
					m_nview.InvokeRPC(m_releaseRpc, new object[1] { player.GetPlayerID() });
				}
				((Character)player).AttachStop();
				Leave();
			}
		}

		private void Leave()
		{
			if (m_manned)
			{
				AudioSource tail = m_tail;
				if (tail != null)
				{
					tail.Play();
				}
			}
			m_manned = false;
			m_trigger = false;
			if ((Object)(object)Manned == (Object)(object)this)
			{
				Manned = null;
			}
			if ((Object)(object)m_hud != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)m_hud).gameObject);
				m_hud = null;
			}
		}

		public void ApplyControlls(Vector3 moveDir, Vector3 lookDir, bool run, bool autoRun, bool block)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			m_look = lookDir;
		}

		public Component GetControlledComponent()
		{
			return (Component)(object)m_barrel;
		}

		public Vector3 GetPosition()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return m_grips.position;
		}

		public bool IsValid()
		{
			if ((Object)(object)this != (Object)null && (Object)(object)m_nview != (Object)null)
			{
				return m_nview.IsValid();
			}
			return false;
		}

		public void SetTrigger(bool down)
		{
			m_trigger = down;
		}

		private void Update()
		{
			//IL_0189: 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)
			if (!m_nview.IsValid())
			{
				return;
			}
			if (m_manned)
			{
				int loaded = Loaded;
				if (loaded > m_lastSeen)
				{
					m_rounds += loaded - m_lastSeen;
				}
				m_lastSeen = loaded;
				Aim();
				Fire(Time.deltaTime);
				Send(force: false, m_wasFiring);
			}
			else
			{
				ZDO zDO = m_nview.GetZDO();
				float num = m_spec.Traverse.Speed * 2f * Time.deltaTime;
				m_yaw = Mathf.MoveTowardsAngle(m_yaw, zDO.GetFloat(m_yawKey, 0f), num);
				m_pitch = Mathf.MoveTowardsAngle(m_pitch, zDO.GetFloat(m_pitchKey, 0f), num);
				Echo(zDO.GetBool(m_firingKey, false), Time.deltaTime);
			}
			m_flight.Fly(Time.deltaTime);
			bool loaded2 = Loaded > 0 || (m_manned && m_rounds > 0);
			IGunExtra[] extras = m_extras;
			for (int i = 0; i < extras.Length; i++)
			{
				extras[i].Tick(loaded2);
			}
			if ((Object)(object)m_swivel != (Object)null)
			{
				m_swivel.localRotation = Quaternion.Euler(0f, m_yaw, 0f);
			}
			m_barrel.localRotation = Quaternion.Euler(0f - m_pitch, m_yaw, 0f);
			ShowHeat(Heat);
		}

		private Vector3 Target()
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: 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_0046: 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_0058: 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_0070: 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_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			float range = m_spec.Fire.Range;
			Transform val = (((Object)(object)GameCamera.instance != (Object)null) ? ((Component)GameCamera.instance).transform : null);
			if ((Object)(object)val == (Object)null)
			{
				return m_muzzle.position + ((m_look == Vector3.zero) ? m_muzzle.forward : ((Vector3)(ref m_look)).normalized) * range;
			}
			Player localPlayer = Player.m_localPlayer;
			foreach (RaycastHit item in from h in Physics.RaycastAll(val.position, val.forward, range, Mask)
				orderby ((RaycastHit)(ref h)).distance
				select h)
			{
				RaycastHit current = item;
				if (!((Component)((RaycastHit)(ref current)).collider).transform.IsChildOf(((Component)this).transform) && (!((Object)(object)localPlayer != (Object)null) || !((Component)((RaycastHit)(ref current)).collider).transform.IsChildOf(((Component)localPlayer).transform)))
				{
					return ((RaycastHit)(ref current)).point;
				}
			}
			return val.position + val.forward * range;
		}

		private void Aim()
		{
			//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_002b: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			m_target = Target();
			Vector3 val = (((Object)(object)GameCamera.instance != (Object)null) ? ((Component)GameCamera.instance).transform.forward : m_look);
			if (!(val == Vector3.zero))
			{
				TraverseSpec traverse = m_spec.Traverse;
				Vector3 val2 = ((Component)this).transform.InverseTransformDirection(((Vector3)(ref val)).normalized);
				float num = Mathf.Atan2(val2.x, val2.z) * 57.29578f;
				if (traverse.Side < 180f)
				{
					num = Mathf.Clamp(num, 0f - traverse.Side, traverse.Side);
				}
				float num2 = Mathf.Clamp(Mathf.Asin(Mathf.Clamp(val2.y, -1f, 1f)) * 57.29578f, 0f - traverse.Down, traverse.Up);
				m_yaw = Mathf.Repeat(Mathf.MoveTowardsAngle(m_yaw, num, traverse.Speed * Time.deltaTime) + 180f, 360f) - 180f;
				m_pitch = Mathf.MoveTowards(m_pitch, num2, traverse.Speed * Time.deltaTime);
			}
		}

		private void Fire(float dt)
		{
			bool flag = JamLeft > 0f;
			bool busy = Busy;
			bool num = m_trigger && Rounds > 0 && !flag && !busy;
			Player localPlayer = Player.m_localPlayer;
			if (m_trigger && !flag && !busy && Rounds == 0 && (Object)(object)localPlayer != (Object)null && Time.time > m_loadWait && m_spec.Feed != null)
			{
				m_loadWait = Time.time + 2f;
				((Character)localPlayer).Message((MessageType)2, m_spec.Feed.EmptyHint, 0, (Sprite)null, false);
			}
			if (!num)
			{
				m_shotTimer = 0f;
				if (m_wasFiring)
				{
					AudioSource tail = m_tail;
					if (tail != null)
					{
						tail.Play();
					}
					m_wasFiring = false;
				}
			}
			else
			{
				if (!m_wasFiring)
				{
					m_wasFiring = true;
					m_shotTimer = Interval;
				}
				m_shotTimer += dt;
				while (m_shotTimer >= Interval && Rounds > 0 && JamLeft <= 0f)
				{
					m_shotTimer -= Interval;
					Shot(localPlayer);
				}
			}
		}

		private void Shot(Player player)
		{
			//IL_006f: 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_0094: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00b3: 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_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: 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_00fc: 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_010f: Unknown result type (might be due to invalid IL or missing references)
			if (!Infinite)
			{
				m_rounds--;
				m_spent++;
			}
			float num = (m_heat = HeatNow(m_heat, m_heatTime) + 1f);
			m_heatTime = Now;
			FireSpec fire = m_spec.Fire;
			Vector3 val;
			float num2;
			if ((Object)(object)m_body != (Object)null)
			{
				val = m_body.linearVelocity;
				if (((Vector3)(ref val)).magnitude > 0.3f)
				{
					num2 = fire.MovingSpread;
					goto IL_0092;
				}
			}
			num2 = fire.Spread;
			goto IL_0092;
			IL_0092:
			float num3 = num2;
			val = m_target - m_muzzle.position;
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			Vector3 val2 = ((Vector3.Angle(normalized, m_muzzle.forward) < 3f) ? normalized : m_muzzle.forward);
			Vector3 dir = Quaternion.Euler(Random.Range(0f - num3, num3), Random.Range(0f - num3, num3), 0f) * val2;
			m_flight.Launch(m_muzzle.position, dir, player);
			Flash();
			HeatSpec heat = m_spec.Heat;
			if (heat == null)
			{
				return;
			}
			if (num >= heat.BurnFrom)
			{
				Burn(player, num, heat);
			}
			if (num >= heat.JamAt)
			{
				m_jamUntil = Now + (double)heat.JamSeconds;
				if (player != null)
				{
					((Character)player).Message((MessageType)2, $"The gun jammed from the heat, {heat.JamSeconds:0} s", 0, (Sprite)null, false);
				}
				Guns.Log.LogInfo((object)$"{m_spec.Name} jammed at heat {num:0}");
			}
		}

		private void Burn(Player player, float heat, HeatSpec spec)
		{
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			float num = 0.02f + 0.13f * Mathf.Clamp01((heat - spec.BurnFrom) / (spec.JamAt - spec.BurnFrom));
			if (!(Random.value > num))
			{
				SEMan sEMan = ((Character)player).GetSEMan();
				StatusEffect statusEffect = sEMan.GetStatusEffect(SEMan.s_statusEffectBurning);
				SE_Burning val = (SE_Burning)(((object)((statusEffect is SE_Burning) ? statusEffect : null)) ?? ((object)/*isinst with value type is only supported in some contexts*/));
				if ((Object)(object)val != (Object)null && !val.AddFireDamage(4f))
				{
					sEMan.RemoveStatusEffect((StatusEffect)(object)val, false);
				}
				if (Time.time > m_burnMessage)
				{
					m_burnMessage = Time.time + 3f;
					((Character)player).Message((MessageType)2, "The gun is too hot, it burns your hands", 0, (Sprite)null, false);
				}
			}
		}

		private void Send(bool force, bool firing)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			if (force || !(Time.time < m_nextSend))
			{
				m_nextSend = Time.time + 0.1f;
				ZPackage val = new ZPackage();
				val.Write(m_yaw);
				val.Write(m_pitch);
				val.Write(m_spent);
				val.Write(m_heat);
				val.Write(m_heatTime);
				val.Write(m_jamUntil);
				val.Write(firing);
				m_nview.InvokeRPC(m_stateRpc, new object[1] { val });
				m_spent = 0;
			}
		}

		private void OnState(long sender, ZPackage pkg)
		{
			if (m_nview.IsOwner())
			{
				ZDO zDO = m_nview.GetZDO();
				zDO.Set(m_yawKey, pkg.ReadSingle());
				zDO.Set(m_pitchKey, pkg.ReadSingle());
				int rounds = pkg.ReadInt();
				m_feed?.Spend(rounds);
				zDO.Set(m_heatKey, pkg.ReadSingle());
				zDO.Set(m_heatTimeKey, (long)(pkg.ReadDouble() * 1000.0));
				zDO.Set(m_jamKey, (long)(pkg.ReadDouble() * 1000.0));
				zDO.Set(m_firingKey, pkg.ReadBool());
			}
		}

		private void Echo(bool firing, float dt)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: 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_009d: 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_00af: Unknown result type (might be due to invalid IL or missing references)
			if (!firing)
			{
				if (m_wasFiring)
				{
					AudioSource tail = m_tail;
					if (tail != null)
					{
						tail.Play();
					}
					m_wasFiring = false;
				}
				return;
			}
			if (!m_wasFiring)
			{
				m_wasFiring = true;
				m_shotTimer = Interval;
			}
			m_shotTimer += dt;
			float spread = m_spec.Fire.Spread;
			while (m_shotTimer >= Interval)
			{
				m_shotTimer -= Interval;
				Vector3 dir = Quaternion.Euler(Random.Range(0f - spread, spread), Random.Range(0f - spread, spread), 0f) * m_muzzle.forward;
				m_flight.Launch(m_muzzle.position, dir, null);
				Flash();
			}
		}

		private void Flash()
		{
			if ((Object)(object)m_flash != (Object)null)
			{
				((Behaviour)m_flash).enabled = true;
				m_flashOff = Time.time + 0.035f;
			}
			if (m_voices != null && m_voices.Length != 0)
			{
				AudioSource obj = m_voices[m_voice++ % m_voices.Length];
				obj.pitch = Random.Range(0.93f, 1.04f);
				obj.Play();
			}
		}

		private void ShowHeat(float heat)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)m_flash != (Object)null && ((Behaviour)m_flash).enabled && Time.time > m_flashOff)
			{
				((Behaviour)m_flash).enabled = false;
			}
			HeatSpec heat2 = m_spec.Heat;
			if (heat2 != null)
			{
				if ((Object)(object)m_steam != (Object)null)
				{
					EmissionModule emission = m_steam.emission;
					((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit((heat < heat2.SteamFrom) ? 0f : ((heat < heat2.BurnFrom) ? Mathf.Lerp(1f, 6f, (heat - heat2.SteamFrom) / (heat2.BurnFrom - heat2.SteamFrom)) : Mathf.Lerp(15f, 40f, (heat - heat2.BurnFrom) / (heat2.JamAt - heat2.BurnFrom))));
				}
				if ((Object)(object)m_glow != (Object)null)
				{
					float num = Mathf.Clamp01((heat - heat2.GlowFrom) / (heat2.JamAt - heat2.GlowFrom));
					((Behaviour)m_glow).enabled = num > 0f;
					m_glow.intensity = num * 2.5f;
				}
			}
		}
	}
	public static class Guns
	{
		internal sealed class Entry
		{
			public IModHost host;

			public MountedGun gun;

			public GameObject prefab;

			public Ammo ammo;

			public Dictionary<string, Material> looks;

			public Material tracer;

			public Material core;
		}

		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		private static class RegisterPrefabs
		{
			private static void Prefix(ZNetScene __instance)
			{
				FindHitEffects(__instance);
				foreach (Entry entry in entries)
				{
					if (Ensure(entry, __instance.m_prefabs))
					{
						entry.host.AddPrefabs(__instance, Prefabs(entry));
					}
					else
					{
						entry.host.Log.LogError((object)("the vanilla materials were not found, " + entry.gun.Name + " is off"));
					}
				}
			}
		}

		[HarmonyPatch(typeof(ObjectDB), "Awake")]
		private static class OnHammer
		{
			private static void Postfix(ObjectDB __instance)
			{
				AddToHammer(__instance);
			}
		}

		[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
		private static class OnCopiedHammer
		{
			private static void Postfix(ObjectDB __instance)
			{
				AddToHammer(__instance);
			}
		}

		[HarmonyPatch(typeof(Game), "Start")]
		private static class OnGame
		{
			private static void Postfix()
			{
				Ammo.RegisterGive();
				SyncedConfig.RegisterAll(ZRoutedRpc.instance);
			}
		}

		private static readonly List<Entry> entries = new List<Entry>();

		private static GameObject holder;

		private static GameObject dent;

		internal static ManualLogSource Log;

		internal static EffectList HitEffects;

		public static Func<bool> BreakAllBuildings = () => false;

		public static string Version { get; private set; }

		public static void Start(IModHost host, Harmony harmony, string version)
		{
			Log = host.Log;
			Version = version;
			harmony.PatchAll(typeof(Guns).Assembly);
			SyncedConfig syncedConfig = new SyncedConfig(host, "vladasz.gunworks.cfg", "gw");
			BreakAllBuildings = syncedConfig.Bool("Damage", "BreakAllBuildings", value: false, "true: rounds and shells break every building. false: only the buildings of the gunner, and of everyone when the gunner has PvP on.");
			syncedConfig.Received += Refresh;
			syncedConfig.Start();
			Ammo.RegisterGive();
			Log.LogInfo((object)("gunworks " + version + " ready"));
		}

		public static void Register(IModHost host, MountedGun gun)
		{
			if (entries.Any((Entry e) => e.gun.Prefab == gun.Prefab))
			{
				host.Log.LogError((object)("a gun " + gun.Prefab + " is registered already, " + gun.Name + " is left out"));
				return;
			}
			Entry entry = new Entry
			{
				host = host,
				gun = gun
			};
			entries.Add(entry);
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				FindHitEffects(ZNetScene.instance);
			}
			if ((Object)(object)ZNetScene.instance != (Object)null && Ensure(entry, ZNetScene.instance.m_prefabs))
			{
				host.AddPrefabs(ZNetScene.instance, Prefabs(entry));
			}
			if ((Object)(object)ObjectDB.instance != (Object)null)
			{
				AddToHammer(ObjectDB.instance);
			}
		}

		public static void Stop()
		{
			if ((Object)(object)Gun.Manned != (Object)null && (Object)(object)Player.m_localPlayer != (Object)null)
			{
				Player.m_localPlayer.StopDoodadControl();
			}
			PieceTable val = Hammer(ObjectDB.instance);
			Player localPlayer = Player.m_localPlayer;
			foreach (Entry entry in entries)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)entry.prefab != (Object)null)
				{
					val.m_pieces.Remove(entry.prefab);
				}
				if ((Object)(object)localPlayer != (Object)null && (Object)(object)localPlayer.m_placementGhost != (Object)null && ((Object)localPlayer.m_placementGhost).name.StartsWith(entry.gun.Prefab))
				{
					localPlayer.SetupPlacementGhost();
				}
				entry.ammo?.Unload();
			}
			entries.Clear();
			SyncedConfig.UnregisterAll();
			UnregisterRpc("gw_give");
			if ((Object)(object)holder != (Object)null)
			{
				Object.Destroy((Object)(object)holder);
				holder = null;
			}
			TerrainOp val2 = (((Object)(object)dent != (Object)null) ? dent.GetComponent<TerrainOp>() : null);
			if ((Object)(object)val2 != (Object)null && (Object)(object)ObjectDB.instance != (Object)null && ObjectDB.instance.m_terrainOps.Remove(val2))
			{
				ObjectDB.instance.UpdateRegisters();
			}
			dent = null;
			HitEffects = null;
			Files.Clear();
		}

		internal static Entry Find(string prefab)
		{
			return entries.FirstOrDefault((Entry e) => e.gun.Prefab == prefab);
		}

		public static void UnregisterRpc(params string[] names)
		{
			if (ZRoutedRpc.instance != null)
			{
				foreach (string text in names)
				{
					ZRoutedRpc.instance.m_functions.Remove(StringExtensionMethods.GetStableHashCode(text));
				}
			}
		}

		private static IEnumerable<GameObject> Prefabs(Entry entry)
		{
			return ((IEnumerable<GameObject>)(object)new GameObject[2]
			{
				entry.prefab,
				entry.ammo?.Item
			}).Where((GameObject go) => (Object)(object)go != (Object)null);
		}

		private static void Refresh()
		{
			if ((Object)(object)ObjectDB.instance != (Object)null)
			{
				AddToHammer(ObjectDB.instance);
			}
		}

		private static bool Ensure(Entry entry, IEnumerable<GameObject> vanilla)
		{
			//IL_00d9: 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)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Expected O, but got Unknown
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Expected O, but got Unknown
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)entry.prefab != (Object)null)
			{
				return true;
			}
			Dictionary<string, GameObject> dictionary = (from go in vanilla
				where (Object)(object)go != (Object)null
				group go by ((Object)go).name).ToDictionary((IGrouping<string, GameObject> g) => g.Key, (IGrouping<string, GameObject> g) => g.First());
			Dictionary<string, Material> dictionary2 = Looks.Vanilla(dictionary);
			if (dictionary2 == null)
			{
				return false;
			}
			foreach (KeyValuePair<string, Color> tint in entry.gun.Tints)
			{
				dictionary2[tint.Key] = new Material(dictionary2["iron"])
				{
					name = entry.gun.Prefab + " " + tint.Key,
					color = tint.Value
				};
			}
			entry.looks = dictionary2;
			if ((Object)(object)holder == (Object)null)
			{
				holder = new GameObject("GunworksPrefabs");
				holder.SetActive(false);
				Object.DontDestroyOnLoad((Object)(object)holder);
			}
			if (entry.gun.Feed?.Item != null)
			{
				entry.ammo = new Ammo(entry.host, entry.gun.Feed.Item, entry.gun.Scale);
				entry.ammo.Ensure(dictionary.Values, holder.transform, dictionary2);
			}
			entry.tracer = Looks.Tracer(entry.gun.Round.Glow);
			entry.core = Looks.Tracer(entry.gun.Round.Core);
			dictionary.TryGetValue("Cart", out var value);
			dictionary.TryGetValue("forge", out var value2);
			dictionary.TryGetValue("smelter", out var value3);
			entry.prefab = Prefab.Build(entry, holder.transform, value, value2, value3);
			entry.host.Log.LogInfo((object)(entry.gun.Name + " built: " + entry.gun.Prefab + ", cart sound " + (((Object)(object)value != (Object)null) ? "found" : "missing")));
			return true;
		}

		private static void FindHitEffects(ZNetScene scene)
		{
			if (HitEffects == null)
			{
				HitEffects = Looks.BoltHits(scene.m_prefabs.Where((GameObject go) => (Object)(object)go != (Object)null));
			}
		}

		private static PieceTable Hammer(ObjectDB db)
		{
			GameObject val = (((Object)(object)db != (Object)null) ? db.GetItemPrefab("Hammer") : null);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return val.GetComponent<ItemDrop>()?.m_itemData.m_shared.m_buildPieces;
		}

		private static void AddToHammer(ObjectDB db)
		{
			PieceTable val = Hammer(db);
			if ((Object)(object)val == (Object)null || entries.Count == 0)
			{
				return;
			}
			EnsureDent(db);
			foreach (Entry entry in entries)
			{
				if (!Ensure(entry, val.m_pieces))
				{
					entry.host.Log.LogError((object)("the vanilla materials were not found, " + entry.gun.Name + " is not buildable"));
					continue;
				}
				Piece component = entry.prefab.GetComponent<Piece>();
				component.m_craftingStation = Station(val, entry.gun.Station);
				if (entry.ammo != null && (Object)(object)entry.ammo.Item == (Object)null && (Object)(object)entry.ammo.Ensure(db.m_items, holder.transform, entry.looks) != (Object)null && (Object)(object)ZNetScene.instance != (Object)null)
				{
					entry.host.AddPrefabs(ZNetScene.instance, (IEnumerable<GameObject>)(object)new GameObject[1] { entry.ammo.Item });
				}
				entry.ammo?.Register(db, Station(val, entry.ammo.Spec.Station));
				component.m_resources = Costs(entry.host, db, entry.gun.Cost(), entry.gun.Name, recover: true);
				if (!val.m_pieces.Contains(entry.prefab))
				{
					val.m_pieces.Add(entry.prefab);
				}
				entry.host.Log.LogInfo((object)(entry.gun.Name + " on the hammer, station " + (((Object)(object)component.m_craftingStation != (Object)null) ? ((Object)component.m_craftingStation).name : "none")));
			}
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer != (Object)null))
			{
				return;
			}
			try
			{
				localPlayer.UpdateKnownRecipesList();
				localPlayer.UpdateAvailablePiecesList();
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("the game could not look for new pieces, the guns show after the next change of the inventory: " + ex.Message));
			}
		}

		private static CraftingStation Station(PieceTable table, string name)
		{
			return table.m_pieces.Select((GameObject p) => p.GetComponent<CraftingStation>()).FirstOrDefault((Func<CraftingStation, bool>)((CraftingStation s) => (Object)(object)s != (Object)null && ((Object)s).name == name));
		}

		internal static Requirement[] Costs(IModHost host, ObjectDB db, string cost, string what, bool recover)
		{
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: 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_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Expected O, but got Unknown
			List<Requirement> list = new List<Requirement>();
			string[] array = cost.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
			foreach (string text in array)
			{
				string[] array2 = text.Split(':');
				object obj;
				if (array2.Length != 2)
				{
					obj = null;
				}
				else
				{
					GameObject itemPrefab = db.GetItemPrefab(array2[0].Trim());
					obj = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null);
				}
				ItemDrop val = (ItemDrop)obj;
				if ((Object)(object)val == (Object)null || !int.TryParse(array2[1].Trim(), out var result) || result <= 0)
				{
					host.Log.LogWarning((object)("the cost part " + text + " of " + what + " is not a known item:amount, it is left out"));
				}
				else
				{
					list.Add(new Requirement
					{
						m_resItem = val,
						m_amount = result,
						m_recover = recover
					});
				}
			}
			return list.ToArray();
		}

		private static void EnsureDent(ObjectDB db)
		{
			if ((Object)(object)dent == (Object)null && (Object)(object)holder != (Object)null)
			{
				GameObject itemPrefab = db.GetItemPrefab("PickaxeIron");
				GameObject val = ((itemPrefab == null) ? null : itemPrefab.GetComponent<ItemDrop>()?.m_itemData.m_shared.m_spawnOnHitTerrain);
				if ((Object)(object)val == (Object)null)
				{
					Log.LogWarning((object)"the dig of the iron pickaxe was not found, the rounds make no dents");
					return;
				}
				dent = Object.Instantiate<GameObject>(val, holder.transform, false);
				((Object)dent).name = "gw_dent";
				TerrainOp[] componentsInChildren = dent.GetComponentsInChildren<TerrainOp>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					Settings settings = componentsInChildren[i].m_settings;
					settings.m_raiseDelta *= 0.25f;
					settings.m_raisePower *= 0.25f;
					settings.m_raiseRadius *= 0.5f;
					settings.m_smoothRadius *= 0.5f;
					settings.m_levelRadius *= 0.5f;
					settings.m_paintRadius *= 0.5f;
				}
			}
			TerrainOp val2 = (((Object)(object)dent != (Object)null) ? dent.GetComponent<TerrainOp>() : null);
			if ((Object)(object)val2 != (Object)null && !db.m_terrainOps.Contains(val2))
			{
				db.m_terrainOps.Add(val2);
				db.UpdateRegisters();
			}
		}

		internal static void Dent(Vector3 point, Player player)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)dent != (Object)null)
			{
				Attack.SpawnOnHitTerrain(point, dent, (Character)(object)player, 0f, (ItemData)null, (ItemData)null, false);
			}
		}

		internal static AudioSource Speaker(GameObject root, AudioClip clip, float maxDistance)
		{
			AudioSource obj = root.AddComponent<AudioSource>();
			obj.clip = clip;
			obj.playOnAwake = false;
			obj.spatialBlend = 1f;
			obj.rolloffMode = (AudioRolloffMode)1;
			obj.minDistance = 4f;
			obj.maxDistance = maxDistance;
			obj.volume = 0.9f;
			obj.outputAudioMixerGroup = Looks.Mixer;
			return obj;
		}
	}
	public interface IModHost
	{
		string Name { get; }

		ManualLogSource Log { get; }

		byte[] ReadAsset(string relative);

		void AddPrefabs(ZNetScene scene, IEnumerable<GameObject> prefabs);
	}
	public sealed class FolderHost : IModHost
	{
		private readonly string folder;

		public string Name { get; }

		public ManualLogSource Log { get; }

		public FolderHost(string name, ManualLogSource log, string folder)
		{
			Name = name;
			Log = log;
			this.folder = folder;
		}

		public byte[] ReadAsset(string relative)
		{
			string path = Path.Combine(folder, relative.Replace('/', Path.DirectorySeparatorChar));
			if (!File.Exists(path))
			{
				path = Path.Combine(folder, Path.GetFileName(path));
			}
			if (!File.Exists(path))
			{
				throw new FileNotFoundException(Name + " has no " + relative + " next to its dll, install the whole mod folder");
			}
			return File.ReadAllBytes(path);
		}

		public void AddPrefabs(ZNetScene scene, IEnumerable<GameObject> prefabs)
		{
			bool flag = (Object)(object)ZNetScene.instance == (Object)(object)scene;
			foreach (GameObject prefab in prefabs)
			{
				scene.m_prefabs.RemoveAll((GameObject p) => (Object)(object)p != (Object)null && ((Object)p).name == ((Object)prefab).name);
				scene.m_prefabs.Add(prefab);
				if (flag)
				{
					scene.m_namedPrefabs[StringExtensionMethods.GetStableHashCode(((Object)prefab).name)] = prefab;
				}
			}
		}
	}
	public class Hud : MonoBehaviour
	{
		private const float BarWidth = 320f;

		private static readonly Color Cool = new Color(0.75f, 0.75f, 0.75f, 0.9f);

		private static readonly Color Hot = new Color(1f, 0.55f, 0.1f, 0.95f);

		private static readonly Color Red = new Color(0.95f, 0.15f, 0.1f, 1f);

		private static bool touched;

		private Gun m_gun;

		private RectTransform m_back;

		private RectTransform m_fill;

		private Image m_fillImage;

		private TMP_Text m_text;

		private GameObject m_fire;

		private GameObject m_leave;

		public bool FireHeld { get; private set; }

		public static Hud Show(Gun gun)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("GunworksHud");
			Canvas obj = val.AddComponent<Canvas>();
			obj.renderMode = (RenderMode)0;
			obj.sortingOrder = 40;
			CanvasScaler obj2 = val.AddComponent<CanvasScaler>();
			obj2.uiScaleMode = (ScaleMode)1;
			obj2.referenceResolution = new Vector2(1920f, 1080f);
			val.AddComponent<GraphicRaycaster>();
			Hud hud = val.AddComponent<Hud>();
			hud.m_gun = gun;
			hud.Build(val.transform);
			return hud;
		}

		private void Build(Transform root)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ae: 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_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			HeatSpec heat = m_gun.Spec.Heat;
			m_back = Box(root, "heat", new Vector2(0.5f, 0.5f), new Vector2(0f, -90f), new Vector2(326f, 18f), new Color(0f, 0f, 0f, 0.6f));
			m_fill = Box((Transform)(object)m_back, "fill", new Vector2(0f, 0.5f), new Vector2(3f, 0f), new Vector2(0f, 12f), Cool);
			m_fill.pivot = new Vector2(0f, 0.5f);
			m_fillImage = ((Component)m_fill).GetComponent<Image>();
			if (heat != null)
			{
				Box((Transform)(object)m_back, "burn mark", new Vector2(0f, 0.5f), new Vector2(3f + 320f * heat.BurnFrom / heat.JamAt, 0f), new Vector2(2f, 18f), new Color(1f, 1f, 1f, 0.7f));
			}
			else
			{
				((Behaviour)((Component)m_back).GetComponent<Image>()).enabled = false;
				((Component)m_fill).gameObject.SetActive(false);
			}
			m_text = Text((Transform)(object)m_back, "rounds", new Vector2(0f, 22f), 24f);
			Text((Transform)(object)m_back, "help", new Vector2(0f, -24f), 18f).text = Localization.instance.Localize("[<color=yellow>$KEY_Attack</color>] Fire   [<color=yellow>$KEY_Use</color>] Let go");
			RectTransform val = Box(root, "fire", new Vector2(1f, 0f), new Vector2(-150f, 150f), new Vector2(190f, 190f), new Color(0.55f, 0.08f, 0.05f, 0.55f));
			m_fire = ((Component)val).gameObject;
			Text((Transform)(object)val, "label", Vector2.zero, 40f).text = "FIRE";
			EventTrigger trigger = ((Component)val).gameObject.AddComponent<EventTrigger>();
			On(trigger, (EventTriggerType)2, delegate
			{
				FireHeld = true;
			});
			On(trigger, (EventTriggerType)3, delegate
			{
				FireHeld = false;
			});
			On(trigger, (EventTriggerType)1, delegate
			{
				FireHeld = false;
			});
			RectTransform val2 = Box(root, "leave", new Vector2(1f, 0f), new Vector2(-370f, 110f), new Vector2(170f, 90f), new Color(0f, 0f, 0f, 0.55f));
			m_leave = ((Component)val2).gameObject;
			Text((Transform)(object)val2, "label", Vector2.zero, 30f).text = "LEAVE";
			On(((Component)val2).gameObject.AddComponent<EventTrigger>(), (EventTriggerType)4, delegate
			{
				Player localPlayer = Player.m_localPlayer;
				if (localPlayer != null)
				{
					localPlayer.StopDoodadControl();
				}
			});
			Buttons();
		}

		private void Buttons()
		{
			touched |= Input.touchCount > 0;
			if (m_fire.activeSelf != touched)
			{
				m_fire.SetActive(touched);
				m_leave.SetActive(touched);
			}
		}

		private void Update()
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: 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)
			if (!((Object)(object)m_gun == (Object)null))
			{
				Buttons();
				HeatSpec heat = m_gun.Spec.Heat;
				if (heat != null)
				{
					float heat2 = m_gun.Heat;
					m_fill.sizeDelta = new Vector2(320f * Mathf.Clamp01(heat2 / heat.JamAt), 12f);
					((Graphic)m_fillImage).color = ((heat2 < heat.BurnFrom) ? Color.Lerp(Cool, Hot, heat2 / heat.BurnFrom) : Color.Lerp(Hot, Red, (heat2 - heat.BurnFrom) / (heat.JamAt - heat.BurnFrom)));
				}
				float jamLeft = m_gun.JamLeft;
				m_text.text = ((jamLeft > 0f) ? $"Jammed, {Mathf.CeilToInt(jamLeft)} s" : (m_gun.Infinite ? "Infinite rounds" : $"{m_gun.Rounds} rounds"));
			}
		}

		private static RectTransform Box(Transform parent, string name, Vector2 anchor, Vector2 position, Vector2 size, Color color)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: 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_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_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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(parent, false);
			RectTransform val2 = (RectTransform)val.transform;
			val2.anchorMin = anchor;
			val2.anchorMax = anchor;
			val2.anchoredPosition = position;
			val2.sizeDelta = size;
			((Graphic)val.AddComponent<Image>()).color = color;
			return val2;
		}

		private static TMP_Text Text(Transform parent, string name, Vector2 position, float size)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: 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_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: 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)
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val.SetActive(false);
			val.transform.SetParent(parent, false);
			RectTransform val2 = (RectTransform)val.transform;
			val2.anchoredPosition = position;
			val2.sizeDelta = new Vector2(400f, 50f);
			TextMeshProUGUI val3 = val.AddComponent<TextMeshProUGUI>();
			((TMP_Text)val3).alignment = (TextAlignmentOptions)514;
			((TMP_Text)val3).fontSize = size;
			((Graphic)val3).raycastTarget = false;
			TMP_Text val4 = (((Object)(object)MessageHud.instance != (Object)null) ? MessageHud.instance.m_messageText : null);
			if ((Object)(object)val4 != (Object)null)
			{
				((TMP_Text)val3).font = val4.font;
			}
			val.SetActive(true);
			return (TMP_Text)(object)val3;
		}

		private static void On(EventTrigger trigger, EventTriggerType type, Action action)
		{
			//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_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			Entry val = new Entry
			{
				eventID = type
			};
			((UnityEvent<BaseEventData>)(object)val.callback).AddListener((UnityAction<BaseEventData>)delegate
			{
				action();
			});
			trigger.triggers.Add(val);
		}
	}
	public static class Looks
	{
		public const string Wood = "wood";

		public const string Iron = "iron";

		private static readonly (string slot, string prefab, string material)[] Sources = new(string, string, string)[2]
		{
			("wood", "wood_beam", "woodwall"),
			("iron", "woodiron_beam", "Ironbeam_mat")
		};

		internal static AudioMixerGroup Mixer;

		internal static Dictionary<string, Material> Vanilla(Dictionary<string, GameObject> byName)
		{
			Dictionary<string, Material> dictionary = new Dictionary<string, Material>();
			(string, string, string)[] sources = Sources;
			for (int i = 0; i < sources.Length; i++)
			{
				(string, string, string) tuple = sources[i];
				string item = tuple.Item1;
				string item2 = tuple.Item2;
				string material = tuple.Item3;
				GameObject value;
				Material val = (byName.TryGetValue(item2, out value) ? value.GetComponentsInChildren<Renderer>(true).SelectMany((Renderer r) => r.sharedMaterials).FirstOrDefault((Func<Material, bool>)((Material m) => (Object)(object)m != (Object)null && ((Object)m).name == material)) : null);
				if ((Object)(object)val == (Object)null)
				{
					return null;
				}
				dictionary[item] = Moveable(val, item);
			}
			if ((Object)(object)Mixer == (Object)null && byName.TryGetValue("Cart", out var value2))
			{
				Vagon componentInChildren = value2.GetComponentInChildren<Vagon>(true);
				object mixer;
				if (componentInChildren == null)
				{
					mixer = null;
				}
				else
				{
					ZSFX? obj = ((IEnumerable<ZSFX>)componentInChildren.m_wheelLoops).FirstOrDefault((Func<ZSFX, bool>)((ZSFX z) => (Object)(object)z != (Object)null));
					if (obj == null)
					{
						mixer = null;
					}
					else
					{
						AudioSource component = ((Component)obj).GetComponent<AudioSource>();
						mixer = ((component != null) ? component.outputAudioMixerGroup : null);
					}
				}
				Mixer = (AudioMixerGroup)mixer;
			}
			return dictionary;
		}

		private static Material Moveable(Material source, string slot)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			Material val = new Material(source)
			{
				name = "gunworks " + slot
			};
			(string, float)[] array = new(string, float)[5]
			{
				("_MoveableObject", 1f),
				("_TriplanarLocalPos", 1f),
				("_ValueNoise", 0f),
				("_ValueNoiseVertex", 0f),
				("_RippleDistance", 0f)
			};
			for (int i = 0; i < array.Length; i++)
			{
				var (text, num) = array[i];
				if (val.HasProperty(text))
				{
					val.SetFloat(text, num);
				}
			}
			return val;
		}

		internal static EffectList BoltHits(IEnumerable<GameObject> vanilla)
		{
			Projectile[] source = (from go in vanilla
				select go.GetComponent<Projectile>() into p
				where (Object)(object)p != (Object)null && p.m_hitEffects != null && p.m_hitEffects.m_effectPrefabs.Length != 0
				select p).ToArray();
			Projectile val = ((IEnumerable<Projectile>)source).FirstOrDefault((Func<Projectile, bool>)((Projectile p) => ((Object)p).name.Contains("bolt") || ((Object)p).name.Contains("arbalest"))) ?? ((IEnumerable<Projectile>)source).FirstOrDefault((Func<Projectile, bool>)((Projectile p) => ((Object)p).name.Contains("arrow")));
			Guns.Log.LogInfo((object)("gunworks hit effects from " + (((Object)(object)val != (Object)null) ? ((Object)val).name : "nothing")));
			return val?.m_hitEffects;
		}

		internal static Material Tracer(Color color)
		{
			//IL_0034: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			Shader val = Shader.Find("Legacy Shaders/Particles/Additive") ?? Shader.Find("Sprites/Default");
			if ((Object)(object)val == (Object)null)
			{
				Guns.Log.LogWarning((object)"no shader for the tracers was found, the rounds show no tracers");
				return null;
			}
			return new Material(val)
			{
				name = "gunworks tracer",
				color = color
			};
		}
	}
	public class Grips : MonoBehaviour, Hoverable, Interactable
	{
		private Gun m_gun;

		private void Awake()
		{
			m_gun = ((Component)this).GetComponentInParent<Gun>();
		}

		public string GetHoverName()
		{
			if (!((Object)(object)m_gun != (Object)null) || m_gun.Spec == null)
			{
				return "";
			}
			return m_gun.Spec.Name;
		}

		public string GetHoverText()
		{
			if ((Object)(object)m_gun == (Object)null || m_gun.Spec == null)
			{
				return "";
			}
			string text = (((Object)(object)Gun.Manned == (Object)(object)m_gun) ? "Let go" : "Shoot");
			string text2 = (m_gun.Infinite ? "" : $", {m_gun.Rounds} rounds");
			return Localization.instance.Localize(m_gun.Spec.Name + text2 + "\n[<color=yellow><b>$KEY_Use</b></color>] " + text);
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			if (hold || (Object)(object)m_gun == (Object)null)
			{
				return false;
			}
			m_gun.Take(user);
			return true;
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			return false;
		}

		public float GetHoverOffset()
		{
			return 0f;
		}
	}
	public class Handle : MonoBehaviour, Hoverable, Interactable
	{
		private Vagon m_vagon;

		private void Awake()
		{
			m_vagon = ((Component)this).GetComponentInParent<Vagon>();
		}

		public string GetHoverName()
		{
			if (!((Object)(object)m_vagon != (Object)null))
			{
				return "";
			}
			return m_vagon.m_name;
		}

		public string GetHoverText()
		{
			if ((Object)(object)m_vagon == (Object)null)
			{
				return "";
			}
			string text = (((Object)(object)Player.m_localPlayer != (Object)null && m_vagon.IsAttached((Character)(object)Player.m_localPlayer)) ? "Let go" : "Pull");
			return Localization.instance.Localize(m_vagon.m_name + "\n[<color=yellow><b>$KEY_Use</b></color>] " + text);
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			if ((Object)(object)m_vagon != (Object)null)
			{
				return m_vagon.Interact(user, hold, alt);
			}
			return false;
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			return false;
		}

		public float GetHoverOffset()
		{
			return 0f;
		}
	}
	public class Inert : MonoBehaviour, Hoverable, Interactable
	{
		public string GetHoverName()
		{
			return "";
		}

		public string GetHoverText()
		{
			return "";
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			return false;
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			return false;
		}

		public float GetHoverOffset()
		{
			return 0f;
		}
	}
	public class Slot : MonoBehaviour, Hoverable, Interactable
	{
		private Gun m_gun;

		private Feed m_feed;