Decompiled source of balrond runerails v1.0.5

plugins/BalrondRuneRails.dll

Decompiled 2 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BalrondCargoSystems;
using BepInEx;
using HarmonyLib;
using LitJson2;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("BalrondCargoSystems")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("BalrondCargoSystems")]
[assembly: AssemblyCopyright("Copyright ©  2022")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("cde312a0-cf19-4264-8616-e1c74774beed")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
public enum BalrondLiftGateState
{
	Closed,
	Opening,
	Open,
	Closing
}
public class BalrondLiftGate : MonoBehaviour, Hoverable, Interactable
{
	private const string RpcToggle = "RPC_BalrondLiftGate_Toggle";

	private const string RpcSetOpen = "RPC_BalrondLiftGate_SetOpen";

	private const string ZdoState = "BalrondLiftGate_State";

	private const string ZdoAnimStart = "BalrondLiftGate_AnimStart";

	private const string ZdoInitialized = "BalrondLiftGate_Initialized";

	[Header("Gate")]
	public string m_name = "Lift Gate";

	public bool m_enabled = true;

	public bool m_defaultOpen = false;

	[Header("Gate Animation")]
	public Transform m_gatePivot;

	public Vector3 m_gateAxis = Vector3.right;

	public float m_openAngle = 85f;

	public float m_openDirection = 1f;

	public float m_animationSeconds = 2f;

	[Header("Gears - One Side")]
	public Transform m_gearStatic;

	public Transform m_gearBridge;

	public Vector3 m_gearAxis = Vector3.right;

	public float m_gearDegreesPerGateDegree = 4f;

	[Header("Animation Audio")]
	public GameObject m_animationActiveObject;

	[Header("Effects")]
	public EffectList m_openStartEffects = new EffectList();

	public EffectList m_closeStartEffects = new EffectList();

	[Header("Debug")]
	public bool m_debugLogs = false;

	private ZNetView _nview;

	private Quaternion _closedLocalRotation;

	private bool _closedRotationCached;

	private void Awake()
	{
		_nview = ((Component)this).GetComponent<ZNetView>();
		CacheClosedRotation();
		if ((Object)(object)_nview != (Object)null && _nview.IsValid())
		{
			_nview.Register("RPC_BalrondLiftGate_Toggle", (Action<long>)RPC_Toggle);
			_nview.Register<bool>("RPC_BalrondLiftGate_SetOpen", (Action<long, bool>)RPC_SetOpen);
			ZDO zDO = _nview.GetZDO();
			if (zDO != null && !zDO.GetBool("BalrondLiftGate_Initialized", false))
			{
				ClaimOwnershipIfNeeded();
				BalrondLiftGateState balrondLiftGateState = (m_defaultOpen ? BalrondLiftGateState.Open : BalrondLiftGateState.Closed);
				zDO.Set("BalrondLiftGate_State", (int)balrondLiftGateState);
				zDO.Set("BalrondLiftGate_AnimStart", GetNetworkTime());
				zDO.Set("BalrondLiftGate_Initialized", true);
			}
		}
		BalrondLiftGateState state = GetState();
		ApplyVisual(GetVisualProgress(state));
		UpdateAnimationActiveObject(state);
	}

	private void Update()
	{
		UpdateAnimationAndState();
	}

	public string GetHoverName()
	{
		return m_name;
	}

	public string GetHoverText()
	{
		string text = m_name + " State: " + GetStateText(GetState());
		text = text + "\n[<color=yellow><b>$KEY_Use</b></color>] " + (IsOpenOrOpening() ? "Close" : "Open");
		BCSSignalLiftGateReceiver component = ((Component)this).GetComponent<BCSSignalLiftGateReceiver>();
		if ((Object)(object)component != (Object)null)
		{
			text += component.GetExtraHoverText();
		}
		return (Localization.instance != null) ? Localization.instance.Localize(text) : text;
	}

	public bool Interact(Humanoid user, bool hold, bool alt)
	{
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		if (hold || !m_enabled)
		{
			return false;
		}
		Player val = (Player)(object)((user is Player) ? user : null);
		if ((Object)(object)val == (Object)null)
		{
			return false;
		}
		if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false))
		{
			return true;
		}
		BCSSignalLiftGateReceiver component = ((Component)this).GetComponent<BCSSignalLiftGateReceiver>();
		if ((Object)(object)component != (Object)null)
		{
			if (IsShiftHeld())
			{
				component.RequestSetSignalNameFromUser();
				return true;
			}
			if (IsAltHeld())
			{
				component.ToggleEventStateFromUser();
				return true;
			}
		}
		if ((Object)(object)_nview == (Object)null || !_nview.IsValid())
		{
			return false;
		}
		_nview.InvokeRPC("RPC_BalrondLiftGate_Toggle", Array.Empty<object>());
		return true;
	}

	private static bool IsShiftHeld()
	{
		return Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303);
	}

	private static bool IsAltHeld()
	{
		return Input.GetKey((KeyCode)308) || Input.GetKey((KeyCode)307);
	}

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

	public void RequestOpen()
	{
		RequestSetOpen(open: true);
	}

	public void RequestClose()
	{
		RequestSetOpen(open: false);
	}

	public void RequestSetOpen(bool open)
	{
		if (!((Object)(object)_nview == (Object)null) && _nview.IsValid())
		{
			_nview.InvokeRPC("RPC_BalrondLiftGate_SetOpen", new object[1] { open });
		}
	}

	public bool IsOpen()
	{
		return GetState() == BalrondLiftGateState.Open;
	}

	public bool IsClosed()
	{
		return GetState() == BalrondLiftGateState.Closed;
	}

	public bool IsAnimating()
	{
		BalrondLiftGateState state = GetState();
		return state == BalrondLiftGateState.Opening || state == BalrondLiftGateState.Closing;
	}

	public bool IsOpenOrOpening()
	{
		BalrondLiftGateState state = GetState();
		return state == BalrondLiftGateState.Open || state == BalrondLiftGateState.Opening;
	}

	public BalrondLiftGateState GetState()
	{
		ZDO zdo = GetZdo();
		if (zdo == null)
		{
			return m_defaultOpen ? BalrondLiftGateState.Open : BalrondLiftGateState.Closed;
		}
		return zdo.GetInt("BalrondLiftGate_State", m_defaultOpen ? 2 : 0) switch
		{
			1 => BalrondLiftGateState.Opening, 
			2 => BalrondLiftGateState.Open, 
			3 => BalrondLiftGateState.Closing, 
			_ => BalrondLiftGateState.Closed, 
		};
	}

	private void RPC_Toggle(long sender)
	{
		if (m_enabled && !IsAnimating())
		{
			SetTargetOpenOwned(!IsOpenOrOpening());
		}
	}

	private void RPC_SetOpen(long sender, bool open)
	{
		if (m_enabled)
		{
			SetTargetOpenOwned(open);
		}
	}

	private void SetTargetOpenOwned(bool open)
	{
		if ((Object)(object)_nview == (Object)null || !_nview.IsValid())
		{
			return;
		}
		ClaimOwnershipIfNeeded();
		BalrondLiftGateState state = GetState();
		if (state == BalrondLiftGateState.Opening || state == BalrondLiftGateState.Closing)
		{
			return;
		}
		if (open)
		{
			if (state != BalrondLiftGateState.Open)
			{
				SetStateOwned(BalrondLiftGateState.Opening);
				CreateEffects(m_openStartEffects);
			}
		}
		else if (state != 0)
		{
			SetStateOwned(BalrondLiftGateState.Closing);
			CreateEffects(m_closeStartEffects);
		}
	}

	private void SetStateOwned(BalrondLiftGateState state)
	{
		ZDO zdo = GetZdo();
		if (zdo != null)
		{
			ClaimOwnershipIfNeeded();
			zdo.Set("BalrondLiftGate_State", (int)state);
			zdo.Set("BalrondLiftGate_AnimStart", GetNetworkTime());
		}
	}

	private void SetStateNoRestartOwned(BalrondLiftGateState state)
	{
		ZDO zdo = GetZdo();
		if (zdo != null)
		{
			ClaimOwnershipIfNeeded();
			zdo.Set("BalrondLiftGate_State", (int)state);
		}
	}

	private void UpdateAnimationAndState()
	{
		if (!m_enabled)
		{
			return;
		}
		CacheClosedRotation();
		BalrondLiftGateState state = GetState();
		float num = Mathf.Max(0.01f, SanitizeFloat(m_animationSeconds, 2f));
		float animStartTime = GetAnimStartTime();
		float networkTime = GetNetworkTime();
		float num2 = Mathf.Clamp01((networkTime - animStartTime) / num);
		float progress = 0f;
		switch (state)
		{
		case BalrondLiftGateState.Closed:
			progress = 0f;
			break;
		case BalrondLiftGateState.Open:
			progress = 1f;
			break;
		case BalrondLiftGateState.Opening:
			progress = num2;
			if (num2 >= 1f && IsOwner())
			{
				SetStateNoRestartOwned(BalrondLiftGateState.Open);
			}
			break;
		case BalrondLiftGateState.Closing:
			progress = 1f - num2;
			if (num2 >= 1f && IsOwner())
			{
				SetStateNoRestartOwned(BalrondLiftGateState.Closed);
			}
			break;
		}
		ApplyVisual(progress);
		UpdateAnimationActiveObject(state);
	}

	private void ApplyVisual(float progress)
	{
		//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_0079: 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_0087: 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_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		float num = Mathf.Clamp01(progress);
		float num2 = Mathf.Sign(SanitizeFloat(m_openDirection, 1f));
		if (Mathf.Abs(num2) <= 0.001f)
		{
			num2 = 1f;
		}
		float num3 = num * Mathf.Max(0f, SanitizeFloat(m_openAngle, 85f)) * num2;
		if ((Object)(object)m_gatePivot != (Object)null)
		{
			Vector3 safeAxis = GetSafeAxis(m_gateAxis, Vector3.right);
			m_gatePivot.localRotation = _closedLocalRotation * Quaternion.AngleAxis(num3, safeAxis);
		}
		float num4 = Mathf.Abs(num3) * Mathf.Max(0f, SanitizeFloat(m_gearDegreesPerGateDegree, 4f));
		ApplyGear(m_gearStatic, 0f - num4);
		ApplyGear(m_gearBridge, num4);
	}

	private Transform GetGearRotationPivot(Transform gearRoot)
	{
		if ((Object)(object)gearRoot == (Object)null)
		{
			return null;
		}
		if (((Object)gearRoot).name == "gear-pivot")
		{
			return gearRoot;
		}
		Transform val = gearRoot.Find("gear-pivot");
		if ((Object)(object)val != (Object)null)
		{
			return val;
		}
		Transform[] componentsInChildren = ((Component)gearRoot).GetComponentsInChildren<Transform>(true);
		foreach (Transform val2 in componentsInChildren)
		{
			if ((Object)(object)val2 != (Object)null && ((Object)val2).name == "gear-pivot")
			{
				return val2;
			}
		}
		return gearRoot;
	}

	private void ApplyGear(Transform gearRoot, float angle)
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: 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)
		Transform gearRotationPivot = GetGearRotationPivot(gearRoot);
		if (!((Object)(object)gearRotationPivot == (Object)null))
		{
			Vector3 safeAxis = GetSafeAxis(m_gearAxis, Vector3.right);
			gearRotationPivot.localRotation = Quaternion.AngleAxis(angle, safeAxis);
		}
	}

	private void CacheClosedRotation()
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		if (!_closedRotationCached && !((Object)(object)m_gatePivot == (Object)null))
		{
			_closedLocalRotation = m_gatePivot.localRotation;
			_closedRotationCached = true;
		}
	}

	private float GetVisualProgress(BalrondLiftGateState state)
	{
		if (state == BalrondLiftGateState.Open || state == BalrondLiftGateState.Opening)
		{
			return 1f;
		}
		return 0f;
	}

	private void UpdateAnimationActiveObject(BalrondLiftGateState state)
	{
		bool flag = state == BalrondLiftGateState.Opening || state == BalrondLiftGateState.Closing;
		if ((Object)(object)m_animationActiveObject == (Object)null)
		{
			return;
		}
		if (m_animationActiveObject.activeSelf != flag)
		{
			m_animationActiveObject.SetActive(flag);
		}
		AudioSource[] componentsInChildren = m_animationActiveObject.GetComponentsInChildren<AudioSource>(true);
		foreach (AudioSource val in componentsInChildren)
		{
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			val.loop = true;
			if (flag)
			{
				if (!val.isPlaying)
				{
					val.Play();
				}
				continue;
			}
			if (val.isPlaying)
			{
				val.Stop();
			}
			val.time = 0f;
		}
	}

	private void CreateEffects(EffectList effects)
	{
		//IL_0027: 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)
		if (effects != null && effects.m_effectPrefabs != null && effects.m_effectPrefabs.Length != 0)
		{
			effects.Create(((Component)this).transform.position, ((Component)this).transform.rotation, (Transform)null, 1f, -1);
		}
	}

	private float GetAnimStartTime()
	{
		ZDO zdo = GetZdo();
		if (zdo == null)
		{
			return GetNetworkTime();
		}
		return zdo.GetFloat("BalrondLiftGate_AnimStart", GetNetworkTime());
	}

	private string GetStateText(BalrondLiftGateState state)
	{
		return state switch
		{
			BalrondLiftGateState.Open => "Open", 
			BalrondLiftGateState.Opening => "Opening", 
			BalrondLiftGateState.Closing => "Closing", 
			_ => "Closed", 
		};
	}

	private ZDO GetZdo()
	{
		if ((Object)(object)_nview == (Object)null || !_nview.IsValid())
		{
			return null;
		}
		return _nview.GetZDO();
	}

	private bool IsOwner()
	{
		return (Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.IsOwner();
	}

	private void ClaimOwnershipIfNeeded()
	{
		if ((Object)(object)_nview != (Object)null && _nview.IsValid() && !_nview.IsOwner())
		{
			_nview.ClaimOwnership();
		}
	}

	private static Vector3 GetSafeAxis(Vector3 axis, Vector3 fallback)
	{
		//IL_0023: 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_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		if (((Vector3)(ref axis)).sqrMagnitude <= 0.0001f)
		{
			return ((Vector3)(ref fallback)).normalized;
		}
		return ((Vector3)(ref axis)).normalized;
	}

	private static float SanitizeFloat(float value, float fallback)
	{
		if (float.IsNaN(value) || float.IsInfinity(value))
		{
			return fallback;
		}
		return value;
	}

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

	private void Log(string msg)
	{
		if (m_debugLogs)
		{
			Debug.Log((object)("[BalrondLiftGate][" + ((Object)((Component)this).gameObject).name + "] " + msg));
		}
	}
}
namespace BalrondCargoSystems
{
	public class BalrondTranslator
	{
		public static Dictionary<string, Dictionary<string, string>> translations = new Dictionary<string, Dictionary<string, string>>();

		public static Dictionary<string, string> getLanguage(string language)
		{
			if (string.IsNullOrEmpty(language))
			{
				return null;
			}
			if (translations.TryGetValue(language, out var value))
			{
				return value;
			}
			return null;
		}
	}
	public static class BCSPrefabFind
	{
		public static T GetOrAdd<T>(GameObject prefab) where T : Component
		{
			T component = prefab.GetComponent<T>();
			return ((Object)(object)component != (Object)null) ? component : prefab.AddComponent<T>();
		}

		public static void DestroyIfExists(Object obj)
		{
			if (obj != (Object)null)
			{
				Object.DestroyImmediate(obj);
			}
		}

		public static Transform FindTransformDeep(GameObject prefab, string childName)
		{
			if ((Object)(object)prefab == (Object)null || string.IsNullOrEmpty(childName))
			{
				return null;
			}
			Transform[] componentsInChildren = prefab.GetComponentsInChildren<Transform>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if ((Object)(object)componentsInChildren[i] != (Object)null && ((Object)componentsInChildren[i]).name == childName)
				{
					return componentsInChildren[i];
				}
			}
			return null;
		}

		public static GameObject FindGameObjectDeep(GameObject prefab, string childName)
		{
			Transform val = FindTransformDeep(prefab, childName);
			return ((Object)(object)val != (Object)null) ? ((Component)val).gameObject : null;
		}

		public static void WarnIfMissing(Object obj, GameObject prefab, string name)
		{
			if (obj == (Object)null && (Object)(object)prefab != (Object)null)
			{
				Debug.LogWarning((object)("[BCS] Missing " + name + " on " + ((Object)prefab).name));
			}
		}
	}
	[DisallowMultipleComponent]
	public class BuilderWorkstation : MonoBehaviour
	{
		public string[] m_supportedBuildStations = new string[6] { "$piece_workbench", "$piece_forge", "$piece_stonecutter", "$piece_artisanstation", "$tag_heavyworkbench_bal", "$tag_ironworks_bal" };

		public bool Supports(string stationName)
		{
			if (string.IsNullOrEmpty(stationName))
			{
				return false;
			}
			for (int i = 0; i < m_supportedBuildStations.Length; i++)
			{
				if (m_supportedBuildStations[i] == stationName)
				{
					return true;
				}
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(CraftingStation), "HaveBuildStationInRange")]
	public static class BuilderWorkstation_HaveBuildStationInRange_Patch
	{
		private static void Postfix(string name, Vector3 point, ref CraftingStation __result)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)__result != (Object)null))
			{
				__result = BuilderWorkstationUtility.HaveBuildStationInRange(name, point);
			}
		}
	}
	[HarmonyPatch(typeof(CraftingStation), "FindClosestStationInRange")]
	public static class BuilderWorkstation_FindClosestStationInRange_Patch
	{
		private static void Postfix(string name, Vector3 point, float range, ref CraftingStation __result)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)__result != (Object)null))
			{
				__result = BuilderWorkstationUtility.FindClosestStationInRange(name, point, range);
			}
		}
	}
	[HarmonyPatch(typeof(CraftingStation), "FindStationsInRange")]
	public static class BuilderWorkstation_FindStationsInRange_Patch
	{
		private static void Postfix(string name, Vector3 point, float range, List<CraftingStation> stations)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			BuilderWorkstationUtility.FindStationsInRange(name, point, range, stations);
		}
	}
	public static class BuilderWorkstationUtility
	{
		public static CraftingStation HaveBuildStationInRange(string requiredStationName, Vector3 point)
		{
			//IL_003e: 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_0049: 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_0063: Unknown result type (might be due to invalid IL or missing references)
			CraftingStation val = null;
			float num = 999999f;
			foreach (CraftingStation allStation in CraftingStation.m_allStations)
			{
				if (IsValidSupportedStation(allStation, requiredStationName))
				{
					float stationBuildRange = allStation.GetStationBuildRange();
					Vector3 val2 = point;
					val2.y = ((Component)allStation).transform.position.y;
					float num2 = Vector3.Distance(((Component)allStation).transform.position, val2);
					if (!(num2 >= stationBuildRange) && ((Object)(object)val == (Object)null || num2 < num))
					{
						val = allStation;
						num = num2;
					}
				}
			}
			return val;
		}

		public static CraftingStation FindClosestStationInRange(string requiredStationName, Vector3 point, float range)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			CraftingStation val = null;
			float num = 999999f;
			foreach (CraftingStation allStation in CraftingStation.m_allStations)
			{
				if (IsValidSupportedStation(allStation, requiredStationName))
				{
					float num2 = Vector3.Distance(((Component)allStation).transform.position, point);
					if (!(num2 >= range) && ((Object)(object)val == (Object)null || num2 < num))
					{
						val = allStation;
						num = num2;
					}
				}
			}
			return val;
		}

		public static void FindStationsInRange(string requiredStationName, Vector3 point, float range, List<CraftingStation> stations)
		{
			//IL_003a: 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)
			if (stations == null)
			{
				return;
			}
			foreach (CraftingStation allStation in CraftingStation.m_allStations)
			{
				if (IsValidSupportedStation(allStation, requiredStationName) && !(Vector3.Distance(((Component)allStation).transform.position, point) >= range) && !stations.Contains(allStation))
				{
					stations.Add(allStation);
				}
			}
		}

		private static bool IsValidSupportedStation(CraftingStation station, string requiredStationName)
		{
			if ((Object)(object)station == (Object)null || string.IsNullOrEmpty(requiredStationName))
			{
				return false;
			}
			BuilderWorkstation component = ((Component)station).GetComponent<BuilderWorkstation>();
			if ((Object)(object)component == (Object)null)
			{
				return false;
			}
			return component.Supports(requiredStationName);
		}
	}
	internal class BuildPieceList
	{
		public static string[] buildPieces = new string[40]
		{
			"pressenceSignalEmitter_bal", "railtrackSignalEmitter_bal", "railSignalLiftGate_bal", "railSignalDoor_bal", "railtrackStop_bal", "railtrackLampReciver_bal", "railtrackControl_bal", "railtrackSignalStopReceiver_bal", "railtrackContainer_bal", "railtrackUnload_bal",
			"railtrackSpeed_bal", "railtrack_bal", "railtrack1m_bal", "railtrack4m_bal", "railtrack8m_bal", "railtrackRamp_bal", "railtrackRamp26short_bal", "railtrackRamp45_bal", "railtrackRamp45short_bal", "railtrackRamp64_bal",
			"railtrackCross_bal", "railtrackSwitchLeft_bal", "railtrackSwitchMid_bal", "railtrackSwitchRight_bal", "railtrackTurnRight15_bal", "railtrackTurnRight30_bal", "railtrackTurnRight45_bal", "railtrackTurnLeft15_bal", "railtrackTurnLeft30_bal", "railtrackTurnLeft45_bal",
			"railtrackJump4m_bal", "railtrackJump6m_bal", "railtrackJump8m_bal", "railtrackDrop8m_bal", "railtrackDrawbridge10m_bal", "RailPowerWagon_bal", "RailCargoWagon_bal", "RailTableWagon_bal", "RailPersonelWagon_bal", "piece_buildstation_bal"
		};
	}
	public static class BCSContainerInitUtility
	{
		public static bool EnsureInitialized(Container container, ZNetView rootOverride)
		{
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Expected O, but got Unknown
			if ((Object)(object)container == (Object)null)
			{
				return false;
			}
			if ((Object)(object)rootOverride != (Object)null)
			{
				container.m_rootObjectOverride = rootOverride;
			}
			ZNetView val = (((Object)(object)container.m_rootObjectOverride != (Object)null) ? ((Component)container.m_rootObjectOverride).GetComponent<ZNetView>() : ((Component)container).GetComponent<ZNetView>());
			if ((Object)(object)val == (Object)null || !val.IsValid() || val.GetZDO() == null)
			{
				return false;
			}
			container.m_nview = val;
			if ((Object)(object)container.m_piece == (Object)null)
			{
				container.m_piece = (((Object)(object)container.m_rootObjectOverride != (Object)null) ? ((Component)container.m_rootObjectOverride).GetComponent<Piece>() : ((Component)container).GetComponent<Piece>());
			}
			if (container.m_inventory == null)
			{
				container.m_inventory = new Inventory(container.m_name, container.m_bkg, container.m_width, container.m_height);
				Inventory inventory = container.m_inventory;
				inventory.m_onChanged = (Action)Delegate.Combine(inventory.m_onChanged, new Action(container.OnContainerChanged));
			}
			container.Load();
			container.UpdateUseVisual();
			return container.m_inventory != null;
		}

		public static bool EnsureInitialized(Container container)
		{
			return EnsureInitialized(container, null);
		}
	}
	public class BCSCargoCartAppearanceSelector : MonoBehaviour, Hoverable, Interactable
	{
		private const string RpcSetVariant = "RPC_SetCargoAppearanceVariant";

		private const string ZdoVariant = "BCS_CargoAppearanceVariant";

		public string m_name = "Cargo Wagon Appearance";

		[Header("States")]
		public string m_statesRootName = "container_states";

		[Header("Debug")]
		public bool m_debugLogs = false;

		private ZNetView _nview;

		private Transform _statesRoot;

		private readonly List<GameObject> _states = new List<GameObject>();

		private int _lastAppliedVariant = -999;

		private void Awake()
		{
			_nview = ((Component)this).GetComponent<ZNetView>();
			if ((Object)(object)_nview == (Object)null || !_nview.IsValid())
			{
				((Behaviour)this).enabled = false;
				return;
			}
			_nview.Register<int>("RPC_SetCargoAppearanceVariant", (Action<long, int>)RPC_SetVariant);
			CacheStates();
			ApplyCurrentVariant();
		}

		private void Start()
		{
			CacheStates();
			ApplyCurrentVariant();
		}

		private void Update()
		{
			int variantIndex = GetVariantIndex();
			if (variantIndex != _lastAppliedVariant)
			{
				ApplyVariant(variantIndex);
			}
		}

		private void CacheStates()
		{
			_states.Clear();
			_statesRoot = null;
			Transform val = ((Component)this).transform.Find(m_statesRootName);
			if ((Object)(object)val == (Object)null)
			{
				val = FindTransformDeep(((Component)this).transform, m_statesRootName);
			}
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)this).transform.Find("states");
			}
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)this).transform.Find("States");
			}
			_statesRoot = val;
			if ((Object)(object)_statesRoot == (Object)null)
			{
				Log("CacheStates: states root missing");
				return;
			}
			for (int i = 0; i < _statesRoot.childCount; i++)
			{
				Transform child = _statesRoot.GetChild(i);
				if ((Object)(object)child != (Object)null)
				{
					_states.Add(((Component)child).gameObject);
				}
			}
			Log("CacheStates count=" + _states.Count);
		}

		public string GetHoverName()
		{
			return m_name;
		}

		public string GetHoverText()
		{
			StringBuilder stringBuilder = new StringBuilder(128);
			stringBuilder.Append(m_name);
			stringBuilder.Append("\n[<color=yellow><b>$KEY_Use</b></color>] Variant: ");
			stringBuilder.Append(GetVariantName(GetVariantIndex()));
			return (Localization.instance != null) ? Localization.instance.Localize(stringBuilder.ToString()) : stringBuilder.ToString();
		}

		public bool Interact(Humanoid human, bool hold, bool alt)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (hold)
			{
				return false;
			}
			Player val = (Player)(object)((human is Player) ? human : null);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false))
			{
				return true;
			}
			SetVariant(GetNextVariantIndex());
			((Character)val).Message((MessageType)2, "Cargo variant: " + GetVariantName(GetNextPreviewVariantIndex()), 0, (Sprite)null);
			return true;
		}

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

		private void SetVariant(int index)
		{
			if (!((Object)(object)_nview == (Object)null) && _nview.IsValid())
			{
				if (!_nview.HasOwner())
				{
					_nview.ClaimOwnership();
				}
				_nview.InvokeRPC("RPC_SetCargoAppearanceVariant", new object[1] { ClampVariantIndex(index) });
			}
		}

		private void RPC_SetVariant(long sender, int value)
		{
			if (!((Object)(object)_nview == (Object)null) && _nview.IsValid() && _nview.IsOwner())
			{
				int num = ClampVariantIndex(value);
				_nview.GetZDO().Set("BCS_CargoAppearanceVariant", num);
				ApplyVariant(num);
			}
		}

		private void ApplyCurrentVariant()
		{
			ApplyVariant(GetVariantIndex());
		}

		private void ApplyVariant(int index)
		{
			if (_states.Count == 0)
			{
				CacheStates();
			}
			int num = (_lastAppliedVariant = ClampVariantIndex(index));
			for (int i = 0; i < _states.Count; i++)
			{
				GameObject val = _states[i];
				if ((Object)(object)val != (Object)null)
				{
					val.SetActive(i == num);
				}
			}
		}

		public int GetVariantIndex()
		{
			if ((Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.GetZDO() != null)
			{
				return ClampVariantIndex(_nview.GetZDO().GetInt("BCS_CargoAppearanceVariant", 0));
			}
			return 0;
		}

		private int GetNextVariantIndex()
		{
			return GetNextVariantIndex(GetVariantIndex());
		}

		private int GetNextPreviewVariantIndex()
		{
			return GetNextVariantIndex(GetVariantIndex());
		}

		private int GetNextVariantIndex(int current)
		{
			if (_states.Count == 0)
			{
				CacheStates();
			}
			if (_states.Count <= 0)
			{
				return 0;
			}
			return (ClampVariantIndex(current) + 1) % _states.Count;
		}

		private int ClampVariantIndex(int value)
		{
			if (_states.Count == 0)
			{
				CacheStates();
			}
			if (_states.Count <= 0)
			{
				return 0;
			}
			return Mathf.Clamp(value, 0, _states.Count - 1);
		}

		private string GetVariantName(int index)
		{
			if (_states.Count == 0)
			{
				CacheStates();
			}
			int num = ClampVariantIndex(index);
			if (num < 0 || num >= _states.Count || (Object)(object)_states[num] == (Object)null)
			{
				return "<none>";
			}
			return ((Object)_states[num]).name;
		}

		private static Transform FindTransformDeep(Transform root, string childName)
		{
			if ((Object)(object)root == (Object)null || string.IsNullOrEmpty(childName))
			{
				return null;
			}
			Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if ((Object)(object)componentsInChildren[i] != (Object)null && ((Object)componentsInChildren[i]).name == childName)
				{
					return componentsInChildren[i];
				}
			}
			return null;
		}

		private void Log(string msg)
		{
			if (m_debugLogs)
			{
				Debug.Log((object)("[BCSCargoCartAppearanceSelector][" + ((Object)((Component)this).gameObject).name + "] " + msg));
			}
		}
	}
	public class BCSCartCraftingStation : MonoBehaviour
	{
		[Header("Cart Crafting Station")]
		public bool m_useCartZNetView = true;

		public bool m_disableRoofRequirement = true;

		public bool m_disableFireRequirement = true;
	}
	public static class BCSCartPrefabConfigurator
	{
		public static void Configure(GameObject prefab)
		{
			if ((Object)(object)prefab == (Object)null)
			{
				Debug.LogWarning((object)"[BCS] ConfigureTrainCart: prefab == null");
				return;
			}
			BCSCartRoot orAdd = BCSPrefabFind.GetOrAdd<BCSCartRoot>(prefab);
			BCSPrefabFind.GetOrAdd<BCSCartRailPlacementSnap>(prefab);
			Smelter val = prefab.GetComponent<Smelter>();
			if ((Object)(object)val == (Object)null)
			{
				val = prefab.GetComponentInChildren<Smelter>(true);
			}
			StationExtension val2 = prefab.GetComponent<StationExtension>();
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = prefab.GetComponentInChildren<StationExtension>(true);
			}
			Fermenter val3 = prefab.GetComponent<Fermenter>();
			if ((Object)(object)val3 == (Object)null)
			{
				val3 = prefab.GetComponentInChildren<Fermenter>(true);
			}
			ZNetView component = prefab.GetComponent<ZNetView>();
			if ((Object)(object)val == (Object)null)
			{
				Debug.LogWarning((object)("[BCS] ConfigureTrainCart: Smelter missing on " + ((Object)prefab).name));
				CleanupVanillaReferenceComponents(prefab);
				return;
			}
			ConfigureCartBase(orAdd, val, val2);
			ConfigureCartWheels(orAdd, val);
			ConfigureCartSensorCollider(prefab);
			if ((Object)(object)val3 != (Object)null)
			{
				orAdd.m_haltingStartEffects = val3.m_tapEffects;
			}
			switch (((Object)prefab).name)
			{
			case "RailPowerWagon_bal":
				ConfigurePoweredCart(prefab, orAdd, val, val3);
				break;
			case "RailCargoWagon_bal":
				ConfigureCargoCart(prefab, orAdd, val, component);
				break;
			case "RailTableWagon_bal":
				ConfigureUtilityWorkbenchCart(prefab, orAdd, val, component);
				break;
			case "RailPersonelWagon_bal":
				ConfigurePassengerCart(prefab, orAdd);
				break;
			default:
				Debug.LogWarning((object)("[BCS] ConfigureTrainCart: unknown cart prefab: " + ((Object)prefab).name));
				break;
			}
			CleanupVanillaReferenceComponents(prefab);
		}

		private static void ConfigureCartBase(BCSCartRoot cart, Smelter smelter, StationExtension stationExtension)
		{
			cart.m_backCouplerPoint = (((Object)(object)smelter.m_addOreSwitch != (Object)null) ? ((Component)smelter.m_addOreSwitch).transform : null);
			cart.m_backCouplerSwitch = smelter.m_addOreSwitch;
			cart.m_frontCouplerPoint = (((Object)(object)smelter.m_addWoodSwitch != (Object)null) ? ((Component)smelter.m_addWoodSwitch).transform : null);
			cart.m_frontCouplerSwitch = smelter.m_addWoodSwitch;
			cart.m_frontPosePoint = smelter.m_outputPoint;
			cart.m_backPosePoint = smelter.m_roofCheckPoint;
			cart.m_isMovingObject = smelter.m_haveFuelObject;
			cart.m_isHaltingObject = smelter.m_noOreObject;
			cart.m_moveStartEffects = smelter.m_oreAddedEffects;
			cart.m_moveStopEffects = smelter.m_fuelAddedEffects;
			cart.m_jumpLaunchRiderEffects = smelter.m_produceEffects;
			cart.m_jumpLandRiderEffects = smelter.m_produceEffects;
			cart.m_connectionPrefab = (((Object)(object)stationExtension != (Object)null) ? stationExtension.m_connectionPrefab : null);
			cart.m_allowRuntimeAdditions = true;
		}

		private static void ConfigureCartWheels(BCSCartRoot cart, Smelter smelter)
		{
			if ((Object)(object)cart == (Object)null || (Object)(object)smelter == (Object)null || smelter.m_animators == null || smelter.m_animators.Length < 2)
			{
				Debug.LogWarning((object)"[BCS] ConfigureCartWheels: missing wheel animators");
				return;
			}
			GameObject val = (((Object)(object)smelter.m_animators[0] != (Object)null) ? ((Component)smelter.m_animators[0]).gameObject : null);
			GameObject val2 = (((Object)(object)smelter.m_animators[1] != (Object)null) ? ((Component)smelter.m_animators[1]).gameObject : null);
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
			{
				Debug.LogWarning((object)"[BCS] ConfigureCartWheels: wheel object missing");
				return;
			}
			BCSPrefabFind.DestroyIfExists((Object)(object)val.GetComponent<Animator>());
			BCSPrefabFind.DestroyIfExists((Object)(object)val2.GetComponent<Animator>());
			cart.m_wheelAnimators = (Transform[])(object)new Transform[2] { val.transform, val2.transform };
		}

		private static void ConfigurePoweredCart(GameObject prefab, BCSCartRoot cart, Smelter smelter, Fermenter fermenter)
		{
			cart.m_cartType = BCSCartType.Powered;
			cart.m_engineSwitch = smelter.m_emptyOreSwitch;
			cart.m_seatObject = smelter.m_haveOreObject;
			cart.m_chair = (((Object)(object)smelter.m_haveOreObject != (Object)null) ? smelter.m_haveOreObject.GetComponent<Chair>() : null);
			cart.m_containerObject = smelter.m_disabledObject;
			cart.m_container = (((Object)(object)smelter.m_disabledObject != (Object)null) ? smelter.m_disabledObject.GetComponent<Container>() : null);
			cart.m_powerEnabledObject = smelter.m_enabledObject;
			cart.m_powerDisabledObject = smelter.m_disabledObject;
			BCSTrainRuntime orAdd = BCSPrefabFind.GetOrAdd<BCSTrainRuntime>(prefab);
			ConfigurePoweredRuntime(orAdd, cart);
			BCSCartRunDamage orAdd2 = BCSPrefabFind.GetOrAdd<BCSCartRunDamage>(prefab);
			ConfigureRunDamage(prefab, cart, orAdd, orAdd2);
			BCSPowerCartControls orAdd3 = BCSPrefabFind.GetOrAdd<BCSPowerCartControls>(prefab);
			ConfigurePowerCartControls(orAdd3, cart, orAdd, fermenter);
			ConfigureMovingChair(cart.m_chair, 2f);
		}

		private static void ConfigurePoweredRuntime(BCSTrainRuntime runtime, BCSCartRoot cart)
		{
			runtime.m_engineRoot = cart;
			runtime.m_baseSpeed = 8f;
			runtime.m_currentSpeed = 8f;
			runtime.m_minSpeed = 4f;
			runtime.m_maxSpeed = 16f;
			runtime.m_speedChangeRate = 2f;
			runtime.m_useStraightRunAcceleration = true;
			runtime.m_straightRunRequiredMeters = 4f;
			runtime.m_straightRunBonusPerMeter = 0.35f;
			runtime.m_maxStraightRunBonus = 4f;
			runtime.m_straightRunResetRate = 8f;
			runtime.m_straightDirectionDotThreshold = 0.985f;
			runtime.m_useSlopeSpeed = true;
			runtime.m_slopeSampleDistance = 0.25f;
			runtime.m_uphillSlowdownFactor = 1.2f;
			runtime.m_downhillBoostFactor = 1f;
			runtime.m_maxUphillNormalized = 0.3f;
			runtime.m_maxDownhillNormalized = 0.3f;
			runtime.m_minSpeedMultiplierUphill = 0.8f;
			runtime.m_maxSpeedMultiplierDownhill = 1.5f;
			runtime.m_useSlopeMomentum = true;
			runtime.m_slopeMomentumBuildRate = 1.35f;
			runtime.m_slopeMomentumDecayRate = 0.55f;
			runtime.m_maxSlopeMomentum = 1.5f;
			runtime.m_slopeMomentumSpeedInfluence = 1f;
			runtime.m_slopeMomentumDeadzone = 0.01f;
			runtime.m_useSoftStopBraking = true;
			runtime.m_softStopBrakeStartDistance = 1.25f;
			runtime.m_softStopMinApproachSpeed = 0.2f;
			runtime.m_softStopBrakeExponent = 1.5f;
		}

		private static void ConfigureRunDamage(GameObject prefab, BCSCartRoot cart, BCSTrainRuntime runtime, BCSCartRunDamage runDamage)
		{
			runDamage.m_cart = cart;
			runDamage.m_runtime = runtime;
			Transform val = prefab.transform.Find("RunHitDamage");
			runDamage.m_runDamageObject = (((Object)(object)val != (Object)null) ? ((Component)val).gameObject : null);
			runDamage.m_runDamageObjectName = "RunHitDamage";
			runDamage.m_attachToLeadingCoupler = true;
			runDamage.m_speedThreshold = 6f;
			runDamage.m_fullDamageSpeed = 16f;
			runDamage.m_minDamageMultiplierAtThreshold = 0.75f;
			runDamage.m_maxDamageMultiplierAtFullSpeed = 2f;
			runDamage.m_extraDamageMultiplierPerAttachedCart = 0.25f;
			runDamage.m_maxAttachedCartDamageBonus = 1f;
			runDamage.m_minForceMultiplierAtThreshold = 1f;
			runDamage.m_maxForceMultiplierAtFullSpeed = 3f;
			runDamage.m_extraForceMultiplierPerAttachedCart = 0.35f;
			runDamage.m_maxAttachedCartForceBonus = 1.5f;
			if ((Object)(object)runDamage.m_runDamageObject == (Object)null)
			{
				Debug.LogWarning((object)("[BCS] ConfigurePoweredCart: RunHitDamage object missing on " + ((Object)prefab).name));
			}
		}

		private static void ConfigurePowerCartControls(BCSPowerCartControls controls, BCSCartRoot cart, BCSTrainRuntime runtime, Fermenter fermenter)
		{
			//IL_0015: 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)
			controls.m_cart = cart;
			controls.m_runtime = runtime;
			controls.m_modifierSwitch = (KeyCode)304;
			controls.m_modifierCamera = (KeyCode)308;
			controls.m_switchSearchRadius = 5f;
			if ((Object)(object)fermenter != (Object)null)
			{
				controls.m_switchToggleEffects = fermenter.m_spawnEffects;
			}
		}

		private static void ConfigureCargoCart(GameObject prefab, BCSCartRoot cart, Smelter smelter, ZNetView rootNview)
		{
			cart.m_cartType = BCSCartType.Cargo;
			cart.m_engineSwitch = null;
			cart.m_powerEnabledObject = null;
			cart.m_powerDisabledObject = null;
			cart.m_seatObject = null;
			cart.m_chair = null;
			cart.m_containerObject = smelter.m_enabledObject;
			cart.m_container = (((Object)(object)smelter.m_enabledObject != (Object)null) ? smelter.m_enabledObject.GetComponent<Container>() : null);
			if ((Object)(object)cart.m_container != (Object)null && (Object)(object)rootNview != (Object)null)
			{
				cart.m_container.m_rootObjectOverride = rootNview;
			}
			BCSCargoCartAppearanceSelector orAdd = BCSPrefabFind.GetOrAdd<BCSCargoCartAppearanceSelector>(prefab);
			orAdd.m_name = "Cargo Wagon Appearance";
			orAdd.m_statesRootName = "container_states";
			RemoveNonPoweredRuntime(prefab);
		}

		private static void ConfigureUtilityWorkbenchCart(GameObject prefab, BCSCartRoot cart, Smelter smelter, ZNetView rootNview)
		{
			cart.m_cartType = BCSCartType.Utility;
			cart.m_engineSwitch = null;
			cart.m_powerEnabledObject = null;
			cart.m_powerDisabledObject = null;
			cart.m_seatObject = null;
			cart.m_chair = null;
			cart.m_containerObject = smelter.m_enabledObject;
			cart.m_container = (((Object)(object)smelter.m_enabledObject != (Object)null) ? smelter.m_enabledObject.GetComponent<Container>() : null);
			if ((Object)(object)cart.m_container != (Object)null && (Object)(object)rootNview != (Object)null)
			{
				cart.m_container.m_rootObjectOverride = rootNview;
			}
			CraftingStation componentInChildren = prefab.GetComponentInChildren<CraftingStation>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				BCSCartCraftingStation bCSCartCraftingStation = ((Component)componentInChildren).GetComponent<BCSCartCraftingStation>();
				if ((Object)(object)bCSCartCraftingStation == (Object)null)
				{
					bCSCartCraftingStation = ((Component)componentInChildren).gameObject.AddComponent<BCSCartCraftingStation>();
				}
				bCSCartCraftingStation.m_useCartZNetView = true;
				bCSCartCraftingStation.m_disableRoofRequirement = true;
				bCSCartCraftingStation.m_disableFireRequirement = true;
				componentInChildren.m_craftRequireRoof = false;
				componentInChildren.m_craftRequireFire = false;
			}
			else
			{
				Debug.LogWarning((object)("[BCS] ConfigureUtilityWorkbenchCart: CraftingStation missing on " + ((Object)prefab).name));
			}
			RemoveNonPoweredRuntime(prefab);
		}

		private static void ConfigurePassengerCart(GameObject prefab, BCSCartRoot cart)
		{
			cart.m_cartType = BCSCartType.Passenger;
			cart.m_engineSwitch = null;
			cart.m_powerEnabledObject = null;
			cart.m_powerDisabledObject = null;
			cart.m_containerObject = null;
			cart.m_container = null;
			Chair[] componentsInChildren = prefab.GetComponentsInChildren<Chair>(true);
			cart.m_chair = ((componentsInChildren != null && componentsInChildren.Length != 0) ? componentsInChildren[0] : null);
			cart.m_seatObject = (((Object)(object)cart.m_chair != (Object)null) ? ((Component)cart.m_chair).gameObject : null);
			if (componentsInChildren != null)
			{
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					ConfigureMovingChair(componentsInChildren[i], 2f);
				}
			}
			RemoveNonPoweredRuntime(prefab);
			if (componentsInChildren == null || componentsInChildren.Length == 0)
			{
				Debug.LogWarning((object)("[BCS] ConfigurePassengerCart: no Chair components found on " + ((Object)prefab).name));
			}
		}

		private static void ConfigureMovingChair(Chair chair, float useDistance)
		{
			if (!((Object)(object)chair == (Object)null))
			{
				if ((Object)(object)chair.m_attachPoint == (Object)null)
				{
					chair.m_attachPoint = ((Component)chair).transform;
				}
				chair.m_inShip = true;
				chair.m_attachAnimation = "emote_sit";
				chair.m_useDistance = useDistance;
			}
		}

		private static void RemoveNonPoweredRuntime(GameObject prefab)
		{
			BCSPrefabFind.DestroyIfExists((Object)(object)prefab.GetComponent<BCSTrainRuntime>());
			BCSPrefabFind.DestroyIfExists((Object)(object)prefab.GetComponent<BCSPowerCartControls>());
			BCSPrefabFind.DestroyIfExists((Object)(object)prefab.GetComponent<BCSCartRunDamage>());
		}

		private static void ConfigureCartSensorCollider(GameObject prefab)
		{
			Transform val = prefab.transform.Find("CartSensorCollider");
			if ((Object)(object)val == (Object)null)
			{
				Debug.LogWarning((object)("[BCS] ConfigureCartSensorCollider: CartSensorCollider missing on " + ((Object)prefab).name));
				return;
			}
			GameObject gameObject = ((Component)val).gameObject;
			int num = LayerMask.NameToLayer("character_noenv");
			if (num >= 0)
			{
				gameObject.layer = num;
			}
			else
			{
				Debug.LogWarning((object)("[BCS] ConfigureCartSensorCollider: layer character_noenv missing on " + ((Object)prefab).name));
			}
			Collider component = gameObject.GetComponent<Collider>();
			if ((Object)(object)component == (Object)null)
			{
				Debug.LogWarning((object)("[BCS] ConfigureCartSensorCollider: Collider missing on " + ((Object)prefab).name));
				return;
			}
			component.isTrigger = true;
			DisableInPlacementGhost component2 = gameObject.GetComponent<DisableInPlacementGhost>();
			if ((Object)(object)component2 != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)component2);
			}
		}

		private static void CleanupVanillaReferenceComponents(GameObject prefab)
		{
			if (!((Object)(object)prefab == (Object)null))
			{
				DestroyComponentsInChildren<StationExtension>(prefab);
				DestroyComponentsInChildren<Smelter>(prefab);
				DestroyComponentsInChildren<Fermenter>(prefab);
			}
		}

		private static void DestroyComponentsInChildren<T>(GameObject prefab) where T : Component
		{
			if ((Object)(object)prefab == (Object)null)
			{
				return;
			}
			T[] componentsInChildren = prefab.GetComponentsInChildren<T>(true);
			if (componentsInChildren == null)
			{
				return;
			}
			for (int num = componentsInChildren.Length - 1; num >= 0; num--)
			{
				T val = componentsInChildren[num];
				if (!((Object)(object)val == (Object)null))
				{
					Object.DestroyImmediate((Object)(object)val);
				}
			}
		}
	}
	public class BCSDrawbridgeRail : MonoBehaviour
	{
		private const string RpcToggleDrawbridge = "RPC_ToggleDrawbridge";

		private readonly List<BCSCartRoot> _cartScanScratch = new List<BCSCartRoot>(64);

		private ZNetView _nview;

		private BCSRailPiece _rail;

		[Header("Drawbridge")]
		public bool m_enabled = true;

		public float m_stopMargin = 1f;

		public float m_animationSeconds = 3f;

		public float m_raisedAngle = 75f;

		public float m_extraStopOffset = 1.5f;

		[Header("Bridge Leaves")]
		public Transform m_leftPivotC;

		public Transform m_rightPivotD;

		[Header("Gears")]
		public Transform m_gearCStatic;

		public Transform m_gearCBridge;

		public Transform m_gearDStatic;

		public Transform m_gearDBridge;

		public float m_gearDegreesPerBridgeDegree = 4f;

		[Header("Rotation Axis")]
		public Vector3 m_leftLeafAxis = Vector3.right;

		public Vector3 m_rightLeafAxis = Vector3.right;

		public Vector3 m_gearAxis = Vector3.right;

		[Header("Animation Audio")]
		public GameObject m_animationActiveObject;

		[Header("Effects")]
		public EffectList m_openStartEffects = new EffectList();

		public EffectList m_closeStartEffects = new EffectList();

		[Header("Debug")]
		public bool m_debugLogs = false;

		private void Awake()
		{
			_nview = ((Component)this).GetComponent<ZNetView>();
			_rail = ((Component)this).GetComponent<BCSRailPiece>();
			if ((Object)(object)_nview != (Object)null)
			{
				_nview.Register("RPC_ToggleDrawbridge", (Action<long>)RPC_ToggleDrawbridge);
			}
			UpdateAnimationActiveObject(GetState());
		}

		private void Update()
		{
			UpdateAnimationAndState();
		}

		public bool IsDrawbridgeRail()
		{
			return m_enabled && (Object)(object)_rail != (Object)null && _rail.m_pieceType == BCSRailPieceType.Drawbridge;
		}

		public bool IsPassableForTrain()
		{
			return GetState() == BCSDrawbridgeState.Lowered;
		}

		public bool IsBlockedForTrain()
		{
			return !IsPassableForTrain();
		}

		public bool IsAnimating()
		{
			BCSDrawbridgeState state = GetState();
			return state == BCSDrawbridgeState.Raising || state == BCSDrawbridgeState.Lowering;
		}

		public BCSDrawbridgeState GetState()
		{
			ZDO zdo = GetZdo();
			if (zdo == null)
			{
				return BCSDrawbridgeState.Lowered;
			}
			return zdo.GetInt("hl_rail_drawbridge_state", 0) switch
			{
				1 => BCSDrawbridgeState.Raising, 
				2 => BCSDrawbridgeState.Raised, 
				3 => BCSDrawbridgeState.Lowering, 
				_ => BCSDrawbridgeState.Lowered, 
			};
		}

		public string GetHoverText()
		{
			string text = "Drawbridge Rail";
			BCSDrawbridgeState state = GetState();
			text += "\n[<color=yellow><b>$KEY_Use</b></color>] Toggle bridge";
			text = text + "\nState: " + GetStateText(state);
			if (IsBridgeSpanOccupied())
			{
				text += "\n<color=red>Train is on bridge</color>";
			}
			else if (IsAnimating())
			{
				text += "\n<color=orange>Bridge is moving</color>";
			}
			return (Localization.instance != null) ? Localization.instance.Localize(text) : text;
		}

		public bool TryInteract(Player player)
		{
			if ((Object)(object)player == (Object)null || !IsDrawbridgeRail())
			{
				return false;
			}
			if ((Object)(object)_nview == (Object)null || !_nview.IsValid())
			{
				return false;
			}
			if (IsBridgeSpanOccupied())
			{
				((Character)player).Message((MessageType)2, "Train is on bridge", 0, (Sprite)null);
				return true;
			}
			if (IsAnimating())
			{
				((Character)player).Message((MessageType)2, "Bridge is moving", 0, (Sprite)null);
				return true;
			}
			_nview.InvokeRPC("RPC_ToggleDrawbridge", Array.Empty<object>());
			return true;
		}

		public bool TryGetStopDistance(bool travelReversed, out float stopDistance)
		{
			stopDistance = 0f;
			if (!IsDrawbridgeRail())
			{
				return false;
			}
			if (IsPassableForTrain())
			{
				return false;
			}
			float length = _rail.GetLength();
			if (length <= 0.001f)
			{
				return false;
			}
			float safeStopMargin = GetSafeStopMargin(length);
			float num = Mathf.Max(0f, BCSCommonUtility.SanitizeFloat(m_extraStopOffset, 1.5f));
			float num2 = Mathf.Clamp(safeStopMargin - num, 0.05f, length - 0.05f);
			float num3 = Mathf.Clamp(length - safeStopMargin + num, 0.05f, length - 0.05f);
			stopDistance = (travelReversed ? num3 : num2);
			return true;
		}

		public bool IsDistanceOnBridgeSpan(float distance)
		{
			if ((Object)(object)_rail == (Object)null)
			{
				return false;
			}
			float length = _rail.GetLength();
			if (length <= 0.001f)
			{
				return false;
			}
			float safeStopMargin = GetSafeStopMargin(length);
			float num = BCSCommonUtility.SanitizeFloat(distance, 0f);
			return num > safeStopMargin && num < length - safeStopMargin;
		}

		public bool IsBridgeSpanOccupied()
		{
			if ((Object)(object)_rail == (Object)null)
			{
				return false;
			}
			string railId = _rail.GetRailId();
			if (string.IsNullOrEmpty(railId))
			{
				return false;
			}
			BCSCartRegistry.FillAll(_cartScanScratch);
			for (int i = 0; i < _cartScanScratch.Count; i++)
			{
				BCSCartRoot bCSCartRoot = _cartScanScratch[i];
				if (!((Object)(object)bCSCartRoot == (Object)null) && !(bCSCartRoot.GetCurrentRailId() != railId) && IsDistanceOnBridgeSpan(bCSCartRoot.GetDistanceOnRail()))
				{
					return true;
				}
			}
			return false;
		}

		private void RPC_ToggleDrawbridge(long sender)
		{
			if (!IsDrawbridgeRail())
			{
				return;
			}
			if (IsBridgeSpanOccupied())
			{
				Log("Toggle rejected: train is on bridge");
				return;
			}
			if (IsAnimating())
			{
				Log("Toggle rejected: bridge is already moving");
				return;
			}
			ClaimOwnershipIfNeeded();
			switch (GetState())
			{
			case BCSDrawbridgeState.Lowered:
				SetStateOwned(BCSDrawbridgeState.Raising);
				CreateEffects(m_openStartEffects);
				Log("Drawbridge raising");
				break;
			case BCSDrawbridgeState.Raised:
				SetStateOwned(BCSDrawbridgeState.Lowering);
				CreateEffects(m_closeStartEffects);
				Log("Drawbridge lowering");
				break;
			}
		}

		private void SetStateOwned(BCSDrawbridgeState state)
		{
			ZDO zdo = GetZdo();
			if (zdo != null)
			{
				ClaimOwnershipIfNeeded();
				zdo.Set("hl_rail_drawbridge_state", (int)state);
				zdo.Set("hl_rail_drawbridge_anim_start_time", BCSCommonUtility.GetNetworkTimeSecondsFloat());
			}
		}

		private void SetStateNoRestartOwned(BCSDrawbridgeState state)
		{
			ZDO zdo = GetZdo();
			if (zdo != null)
			{
				ClaimOwnershipIfNeeded();
				zdo.Set("hl_rail_drawbridge_state", (int)state);
			}
		}

		private void UpdateAnimationAndState()
		{
			if (!IsDrawbridgeRail())
			{
				return;
			}
			BCSDrawbridgeState state = GetState();
			float num = Mathf.Max(0.01f, BCSCommonUtility.SanitizeFloat(m_animationSeconds, 3f));
			float animStartTime = GetAnimStartTime();
			float networkTimeSecondsFloat = BCSCommonUtility.GetNetworkTimeSecondsFloat();
			float num2 = Mathf.Clamp01((networkTimeSecondsFloat - animStartTime) / num);
			float progress = 0f;
			switch (state)
			{
			case BCSDrawbridgeState.Lowered:
				progress = 0f;
				break;
			case BCSDrawbridgeState.Raised:
				progress = 1f;
				break;
			case BCSDrawbridgeState.Raising:
				progress = num2;
				if (num2 >= 1f && IsOwner())
				{
					SetStateNoRestartOwned(BCSDrawbridgeState.Raised);
				}
				break;
			case BCSDrawbridgeState.Lowering:
				progress = 1f - num2;
				if (num2 >= 1f && IsOwner())
				{
					SetStateNoRestartOwned(BCSDrawbridgeState.Lowered);
				}
				break;
			}
			UpdateAnimationActiveObject(state);
			ApplyVisual(progress);
		}

		private void ApplyVisual(float progress)
		{
			//IL_002e: 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_003d: 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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: 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)
			float num = Mathf.Clamp01(progress);
			float num2 = num * BCSCommonUtility.SanitizeFloat(m_raisedAngle, 75f);
			if ((Object)(object)m_leftPivotC != (Object)null)
			{
				Vector3 safeAxis = GetSafeAxis(m_leftLeafAxis, Vector3.right);
				m_leftPivotC.localRotation = Quaternion.AngleAxis(num2, safeAxis);
			}
			if ((Object)(object)m_rightPivotD != (Object)null)
			{
				Vector3 safeAxis2 = GetSafeAxis(m_rightLeafAxis, Vector3.right);
				m_rightPivotD.localRotation = Quaternion.AngleAxis(0f - num2, safeAxis2);
			}
			float num3 = num2 * BCSCommonUtility.SanitizeFloat(m_gearDegreesPerBridgeDegree, 4f);
			ApplyGear(m_gearCStatic, 0f - num3);
			ApplyGear(m_gearCBridge, num3);
			ApplyGear(m_gearDStatic, num3);
			ApplyGear(m_gearDBridge, 0f - num3);
		}

		private void UpdateAnimationActiveObject(BCSDrawbridgeState state)
		{
			bool flag = state == BCSDrawbridgeState.Raising || state == BCSDrawbridgeState.Lowering;
			if ((Object)(object)m_animationActiveObject == (Object)null)
			{
				return;
			}
			if (m_animationActiveObject.activeSelf != flag)
			{
				m_animationActiveObject.SetActive(flag);
			}
			AudioSource[] componentsInChildren = m_animationActiveObject.GetComponentsInChildren<AudioSource>(true);
			foreach (AudioSource val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				val.loop = true;
				if (flag)
				{
					if (!val.isPlaying)
					{
						val.Play();
					}
					continue;
				}
				if (val.isPlaying)
				{
					val.Stop();
				}
				val.time = 0f;
			}
		}

		private Transform GetGearRotationPivot(Transform gearRoot)
		{
			if ((Object)(object)gearRoot == (Object)null)
			{
				return null;
			}
			if (((Object)gearRoot).name == "gear-pivot")
			{
				return gearRoot;
			}
			Transform val = gearRoot.Find("gear-pivot");
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			Transform[] componentsInChildren = ((Component)gearRoot).GetComponentsInChildren<Transform>(true);
			foreach (Transform val2 in componentsInChildren)
			{
				if ((Object)(object)val2 != (Object)null && ((Object)val2).name == "gear-pivot")
				{
					return val2;
				}
			}
			return gearRoot;
		}

		private void CreateEffects(EffectList effects)
		{
			//IL_0027: 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)
			if (effects != null && effects.m_effectPrefabs != null && effects.m_effectPrefabs.Length != 0)
			{
				effects.Create(((Component)this).transform.position, ((Component)this).transform.rotation, (Transform)null, 1f, -1);
			}
		}

		private void ApplyGear(Transform gearRoot, float angle)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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_002c: Unknown result type (might be due to invalid IL or missing references)
			Transform gearRotationPivot = GetGearRotationPivot(gearRoot);
			if (!((Object)(object)gearRotationPivot == (Object)null))
			{
				Vector3 safeAxis = GetSafeAxis(m_gearAxis, Vector3.right);
				gearRotationPivot.localRotation = Quaternion.AngleAxis(angle, safeAxis);
			}
		}

		private float GetSafeStopMargin(float length)
		{
			float num = Mathf.Max(0.001f, BCSCommonUtility.SanitizeFloat(length, 0f));
			return Mathf.Clamp(BCSCommonUtility.SanitizeFloat(m_stopMargin, 1f), 0.05f, Mathf.Max(0.05f, num * 0.45f));
		}

		private Vector3 GetSafeAxis(Vector3 axis, Vector3 fallback)
		{
			//IL_0023: 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_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			if (((Vector3)(ref axis)).sqrMagnitude <= 0.0001f)
			{
				return ((Vector3)(ref fallback)).normalized;
			}
			return ((Vector3)(ref axis)).normalized;
		}

		private float GetAnimStartTime()
		{
			ZDO zdo = GetZdo();
			if (zdo == null)
			{
				return BCSCommonUtility.GetNetworkTimeSecondsFloat();
			}
			return zdo.GetFloat("hl_rail_drawbridge_anim_start_time", BCSCommonUtility.GetNetworkTimeSecondsFloat());
		}

		private string GetStateText(BCSDrawbridgeState state)
		{
			return state switch
			{
				BCSDrawbridgeState.Lowered => "Lowered / passable", 
				BCSDrawbridgeState.Raising => "Raising / blocked", 
				BCSDrawbridgeState.Raised => "Raised / blocked", 
				_ => "Lowering / blocked", 
			};
		}

		private ZDO GetZdo()
		{
			if ((Object)(object)_nview == (Object)null || !_nview.IsValid())
			{
				return null;
			}
			return _nview.GetZDO();
		}

		private bool IsOwner()
		{
			return (Object)(object)_nview != (Object)null && _nview.IsValid() && _nview.IsOwner();
		}

		private void ClaimOwnershipIfNeeded()
		{
			if ((Object)(object)_nview != (Object)null && _nview.IsValid() && !_nview.IsOwner())
			{
				_nview.ClaimOwnership();
			}
		}

		public bool TryGetStopDistanceFromCurrentDistance(float currentDistance, out float stopDistance)
		{
			stopDistance = 0f;
			if (!IsDrawbridgeRail())
			{
				return false;
			}
			if (IsPassableForTrain())
			{
				return false;
			}
			float length = _rail.GetLength();
			if (length <= 0.001f)
			{
				return false;
			}
			float safeStopMargin = GetSafeStopMargin(length);
			float num = Mathf.Max(0f, BCSCommonUtility.SanitizeFloat(m_extraStopOffset, 1.5f));
			float num2 = Mathf.Clamp(safeStopMargin - num, 0.05f, length - 0.05f);
			float num3 = Mathf.Clamp(length - safeStopMargin + num, 0.05f, length - 0.05f);
			float num4 = Mathf.Clamp(BCSCommonUtility.SanitizeFloat(currentDistance, 0f), 0f, length);
			bool flag = num4 > length * 0.5f;
			stopDistance = (flag ? num3 : num2);
			return true;
		}

		private void Log(string msg)
		{
			if (m_debugLogs)
			{
				Debug.Log((object)("[BCSDrawbridgeRail][" + ((Object)((Component)this).gameObject).name + "] " + msg));
			}
		}
	}
	public static class BCSPrefabConfigurator
	{
		public static void ConfigureTrainCart(GameObject prefab)
		{
			BCSCartPrefabConfigurator.Configure(prefab);
		}

		public static void ConfigureRail(GameObject prefab)
		{
			BCSRailPrefabConfigurator.Configure(prefab);
		}

		public static void ConfigureSignalPiece(GameObject prefab)
		{
			BCSSignalPrefabConfigurator.Configure(prefab);
		}
	}
	public class DatabaseAddMethods
	{
		public void AddItems(List<GameObject> items)
		{
			foreach (GameObject item in items)
			{
				AddItem(item);
			}
		}

		public void AddRecipes(List<Recipe> recipes)
		{
			foreach (Recipe recipe in recipes)
			{
				AddRecipe(recipe);
			}
		}

		public void AddStatuseffects(List<StatusEffect> statusEffects)
		{
			foreach (StatusEffect statusEffect in statusEffects)
			{
				AddStatus(statusEffect);
			}
		}

		private bool IsObjectDBValid()
		{
			return (Object)(object)ObjectDB.instance != (Object)null && ObjectDB.instance.m_items.Count != 0 && ObjectDB.instance.m_recipes.Count != 0 && (Object)(object)ObjectDB.instance.GetItemPrefab("Amber") != (Object)null;
		}

		private void AddStatus(StatusEffect status)
		{
			if (!IsObjectDBValid())
			{
				return;
			}
			if ((Object)(object)status != (Object)null)
			{
				if ((Object)(object)ObjectDB.instance.GetStatusEffect(status.m_nameHash) == (Object)null)
				{
					ObjectDB.instance.m_StatusEffects.Add(status);
				}
				else
				{
					Debug.Log((object)(Launch.projectName + ":  " + ((Object)status).name + " - Status already in the game"));
				}
			}
			else
			{
				Debug.LogError((object)(Launch.projectName + ":  " + ((Object)status).name + " - Status not found"));
			}
		}

		private void AddRecipe(Recipe recipe)
		{
			if (!IsObjectDBValid())
			{
				return;
			}
			if ((Object)(object)recipe != (Object)null)
			{
				if ((Object)(object)ObjectDB.instance.m_recipes.Find((Recipe x) => ((Object)x).name == ((Object)recipe).name) == (Object)null)
				{
					if ((Object)(object)recipe.m_item != (Object)null)
					{
						ObjectDB.instance.m_recipes.Add(recipe);
					}
				}
				else
				{
					Debug.Log((object)(Launch.projectName + ":  " + ((Object)recipe).name + " - Recipe with this name already in the Game"));
				}
			}
			else
			{
				Debug.LogError((object)(Launch.projectName + ":  " + ((Object)recipe).name + " - Recipe not found"));
			}
		}

		private void AddItem(GameObject newPrefab)
		{
			if (!IsObjectDBValid())
			{
				return;
			}
			ItemDrop component = newPrefab.GetComponent<ItemDrop>();
			if ((Object)(object)component != (Object)null)
			{
				if ((Object)(object)ObjectDB.instance.GetItemPrefab(((Object)newPrefab).name) == (Object)null)
				{
					ObjectDB.instance.m_items.Add(newPrefab);
					Dictionary<int, GameObject> dictionary = (Dictionary<int, GameObject>)typeof(ObjectDB).GetField("m_itemByHash", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(ObjectDB.instance);
					dictionary[((Object)newPrefab).name.GetHashCode()] = newPrefab;
				}
				else
				{
					Debug.LogWarning((object)(Launch.projectName + ": " + ((Object)newPrefab).name + " - ItemDrop already exist"));
				}
			}
			else
			{
				Debug.LogError((object)(Launch.projectName + ": " + ((Object)newPrefab).name + " - ItemDrop not found on prefab"));
			}
		}
	}
	public class ModResourceLoader
	{
		public AssetBundle assetBundle;

		public List<GameObject> buildPrefabs = new List<GameObject>();

		public List<GameObject> plantPrefabs = new List<GameObject>();

		public List<GameObject> itemPrefabs = new List<GameObject>();

		public List<GameObject> monsterPrefabs = new List<GameObject>();

		public List<GameObject> vegetationPrefabs = new List<GameObject>();

		public List<GameObject> clutterPrefabs = new List<GameObject>();

		public List<GameObject> locationPrefabs = new List<GameObject>();

		public List<GameObject> roomPrefabs = new List<GameObject>();

		public List<GameObject> vfxPrefabs = new List<GameObject>();

		public List<Texture2D> texturePrefabs = new List<Texture2D>();

		public List<Recipe> recipes = new List<Recipe>();

		public List<StatusEffect> statusEffects = new List<StatusEffect>();

		public StatusEffect newBarleyStatus = null;

		public ShaderReplacment shaderReplacment = new ShaderReplacment();

		public Sprite newLogo = null;

		public GameObject railwaytable = null;

		public GameObject unchargedStone = null;

		public void loadAssets()
		{
			assetBundle = GetAssetBundleFromResources("balrondcargosystem");
			string basePath = "Assets/Custom/BalrondCargoSystems/";
			loadPieces(basePath);
			loadItems(basePath);
			loadOther(basePath);
		}

		public void AddPrefabsToZnetScene(ZNetScene zNetScene)
		{
			zNetScene.m_prefabs.AddRange(vegetationPrefabs);
			foreach (GameObject gm in itemPrefabs)
			{
				GameObject val = zNetScene.m_prefabs.Find((GameObject x) => ((Object)x).name == ((Object)gm).name);
				if ((Object)(object)val == (Object)null)
				{
					zNetScene.m_prefabs.Add(gm);
				}
				else
				{
					Debug.LogWarning((object)("Object exists: " + ((Object)gm).name));
				}
			}
			foreach (GameObject gm2 in buildPrefabs)
			{
				GameObject val2 = zNetScene.m_prefabs.Find((GameObject x) => ((Object)x).name == ((Object)gm2).name);
				if ((Object)(object)val2 == (Object)null)
				{
					zNetScene.m_prefabs.Add(gm2);
				}
				else
				{
					Debug.LogWarning((object)("Object exists: " + ((Object)gm2).name));
				}
			}
			foreach (GameObject gm3 in vfxPrefabs)
			{
				GameObject val3 = zNetScene.m_prefabs.Find((GameObject x) => ((Object)x).name == ((Object)gm3).name);
				if ((Object)(object)val3 == (Object)null)
				{
					zNetScene.m_prefabs.Add(gm3);
				}
				else
				{
					Debug.LogWarning((object)("Object exists: " + ((Object)gm3).name));
				}
			}
			zNetScene.m_prefabs.RemoveAll((GameObject x) => (Object)(object)x == (Object)null);
			setupRails(zNetScene);
			setupTraincarts(zNetScene);
			setupSignalPieces(zNetScene);
			addPlantstoCultivator(zNetScene);
			setupBuildPiecesList(zNetScene);
		}

		private void setupTraincarts(ZNetScene zNetScene)
		{
			string[] array = new string[4] { "RailCargoWagon_bal", "RailPowerWagon_bal", "RailTableWagon_bal", "RailPersonelWagon_bal" };
			string[] array2 = array;
			foreach (string name in array2)
			{
				GameObject val = buildPrefabs.Find((GameObject x) => (Object)(object)x != (Object)null && ((Object)x).name == name);
				if ((Object)(object)val == (Object)null)
				{
					Debug.LogWarning((object)("[BCS] setupTraincarts: prefab not found: " + name));
				}
				else
				{
					setupTraincart(zNetScene, val);
				}
			}
		}

		private void setupTraincart(ZNetScene zNetScene, GameObject prefab)
		{
			BCSPrefabConfigurator.ConfigureTrainCart(prefab);
		}

		private void setupSignalPieces(ZNetScene zNetScene)
		{
			string[] array = new string[6] { "pressenceSignalEmitter_bal", "railtrackSignalEmitter_bal", "railtrackLampReciver_bal", "railtrackSpeakerReciver_bal", "railSignalDoor_bal", "railSignalLiftGate_bal" };
			string[] array2 = array;
			foreach (string name in array2)
			{
				GameObject val = buildPrefabs.Find((GameObject x) => (Object)(object)x != (Object)null && ((Object)x).name == name);
				if ((Object)(object)val == (Object)null)
				{
					Debug.LogWarning((object)("[BCS] setupSignalPieces: prefab not found: " + name));
				}
				else
				{
					setupSignalPiece(zNetScene, val);
				}
			}
		}

		private void setupSignalPiece(ZNetScene zNetScene, GameObject prefab)
		{
			BCSPrefabConfigurator.ConfigureSignalPiece(prefab);
		}

		private void setupRails(ZNetScene zNetScene)
		{
			string[] array = new string[29]
			{
				"railtrackControl_bal", "railtrackSignalStopReceiver_bal", "railtrackContainer_bal", "railtrackUnload_bal", "railtrackSpeed_bal", "railtrack_bal", "railtrack1m_bal", "railtrack4m_bal", "railtrack8m_bal", "railtrackRamp_bal",
				"railtrackRamp26short_bal", "railtrackRamp45_bal", "railtrackRamp45short_bal", "railtrackRamp64_bal", "railtrackCross_bal", "railtrackSwitchLeft_bal", "railtrackSwitchMid_bal", "railtrackSwitchRight_bal", "railtrackTurnRight15_bal", "railtrackTurnRight30_bal",
				"railtrackTurnRight45_bal", "railtrackTurnLeft15_bal", "railtrackTurnLeft30_bal", "railtrackTurnLeft45_bal", "railtrackJump4m_bal", "railtrackJump6m_bal", "railtrackJump8m_bal", "railtrackDrop8m_bal", "railtrackDrawbridge10m_bal"
			};
			string[] array2 = array;
			foreach (string name in array2)
			{
				GameObject val = buildPrefabs.Find((GameObject x) => (Object)(object)x != (Object)null && ((Object)x).name == name);
				if ((Object)(object)val == (Object)null)
				{
					Debug.LogWarning((object)("[BCS] setupRails: prefab not found: " + name));
				}
				else
				{
					setupRail(zNetScene, val);
				}
			}
		}

		private void setupRail(ZNetScene zNetScene, GameObject prefab)
		{
			BCSPrefabConfigurator.ConfigureRail(prefab);
		}

		private void setupBuildPiecesList(ZNetScene zNetScene)
		{
			string[] array = new string[4] { "Hammer", "HammerIron", "HammerDverger", "HammerBlackmetal" };
			GameObject val = zNetScene.m_prefabs.Find((GameObject x) => ((Object)x).name == "Hammer");
			PieceTable buildPieces = val.GetComponent<ItemDrop>().m_itemData.m_shared.m_buildPieces;
			string[] array2 = array;
			foreach (string name in array2)
			{
				addBuildpiecesToOtherHammer(name, buildPieces, zNetScene);
			}
			List<GameObject> pieces = buildPieces.m_pieces;
			foreach (GameObject buildPrefab in buildPrefabs)
			{
				setupRavenGuide(buildPrefab, zNetScene.m_prefabs);
				AddToBuildList(buildPrefab, pieces);
			}
		}

		private void addBuildpiecesToOtherHammer(string name, PieceTable pieceTable, ZNetScene zNetScene)
		{
			GameObject val = zNetScene.m_prefabs.Find((GameObject x) => ((Object)x).name == name);
			if (!((Object)(object)val == (Object)null))
			{
				val.GetComponent<ItemDrop>().m_itemData.m_shared.m_buildPieces = pieceTable;
			}
		}

		public void setupRavenGuide(GameObject gameObject, List<GameObject> gameObjects)
		{
			GameObject val = null;
			Transform val2 = gameObject.transform.Find("GuidePoint");
			if ((Object)(object)val2 == (Object)null)
			{
				return;
			}
			GameObject val3 = gameObjects.Find((GameObject x) => ((Object)x).name == "piece_workbench");
			if ((Object)(object)val3 != (Object)null)
			{
				GameObject gameObject2 = ((Component)val3.transform.Find("GuidePoint")).gameObject;
				if ((Object)(object)gameObject2 != (Object)null)
				{
					GuidePoint component = gameObject2.GetComponent<GuidePoint>();
					if ((Object)(object)component != (Object)null)
					{
						val = component.m_ravenPrefab;
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				Debug.LogWarning((object)"Ravens not found");
			}
			else
			{
				((Component)val2).GetComponent<GuidePoint>().m_ravenPrefab = val;
			}
		}

		public void setupBuildPiecesListDB()
		{
			GameObject val = ObjectDB.instance.m_items.Find((GameObject x) => ((Object)x).name == "Hammer");
			List<GameObject> pieces = val.GetComponent<ItemDrop>().m_itemData.m_shared.m_buildPieces.m_pieces;
			foreach (GameObject buildPrefab in buildPrefabs)
			{
				AddToBuildList(buildPrefab, pieces);
			}
		}

		private void AddToBuildList(GameObject prefab, List<GameObject> buildPieces)
		{
			if ((Object)(object)buildPieces.Find((GameObject x) => ((Object)x).name == ((Object)prefab).name) == (Object)null)
			{
				buildPieces.Add(prefab);
			}
		}

		private void addPlantstoCultivator(ZNetScene zNetScene)
		{
			GameObject val = zNetScene.m_prefabs.Find((GameObject x) => ((Object)x).name == "Cultivator");
			PieceTable buildPieces = val.GetComponent<ItemDrop>().m_itemData.m_shared.m_buildPieces;
			List<GameObject> pieces = buildPieces.m_pieces;
			foreach (GameObject plantPrefab in plantPrefabs)
			{
				pieces.Add(plantPrefab);
			}
		}

		private void loadItems(string basePath)
		{
			string mainPath = basePath + "Items/";
			string[] nameList = new string[9] { "WagonBundlePower_bal", "WagonBundleCargo_bal", "WagonBundleTable_bal", "WagonBundlePersonel_bal", "WagonPartsBundle_bal", "RailPartsBundle_bal", "RailwayHammer_bal", "BuilderWorkstationBundle_bal", "UncharedThunderstone_bal" };
			addNewPrefabToCollection(nameList, mainPath, itemPrefabs, "item");
		}

		private void addNewPrefabToCollection(string[] nameList, string mainPath, List<GameObject> prefabList, string typeName)
		{
			foreach (string text in nameList)
			{
				GameObject val = assetBundle.LoadAsset<GameObject>(mainPath + text + ".prefab");
				if ((Object)(object)val == (Object)null)
				{
					Debug.LogWarning((object)("Could not find " + typeName + " with name: " + text));
					continue;
				}
				if (((Object)val).name == "UncharedThunderstone_bal")
				{
					unchargedStone = val;
				}
				if (Object.op_Implicit((Object)(object)val.GetComponent<ZNetView>()) || typeName == "clutter")
				{
					ShaderReplacment.Replace(val);
					prefabList.Add(val);
				}
				else
				{
					Debug.LogWarning((object)("Prefab with name has no ZNetView could not been removed: " + text));
				}
			}
		}

		private AssetBundle GetAssetBundleFromResources(string filename)
		{
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			string name = executingAssembly.GetManifestResourceNames().Single((string str) => str.EndsWith(filename));
			using Stream stream = executingAssembly.GetManifestResourceStream(name);
			return AssetBundle.LoadFromStream(stream);
		}

		private void loadPlants(string basePath)
		{
			string text = basePath + "Plants/";
			string[] array = new string[0];
			string[] array2 = array;
			foreach (string text2 in array2)
			{
				GameObject val = assetBundle.LoadAsset<GameObject>(text + text2 + ".prefab");
				if ((Object)(object)val == (Object)null)
				{
					Debug.LogWarning((object)("Could not find plant with name: " + text2));
					continue;
				}
				ShaderReplacment.Replace(val);
				plantPrefabs.Add(val);
			}
		}

		private void loadPieces(string basePath)
		{
			string text = basePath + "Pieces/";
			string[] buildPieces = BuildPieceList.buildPieces;
			string[] array = buildPieces;
			foreach (string text2 in array)
			{
				GameObject val = assetBundle.LoadAsset<GameObject>(text + text2 + ".prefab");
				if ((Object)(object)val == (Object)null)
				{
					Debug.LogWarning((object)("Could not find piece with name: " + text2));
					continue;
				}
				ShaderReplacment.Replace(val);
				if (((Object)val).name == "RailTableWagon_bal")
				{
					railwaytable = val;
				}
				buildPrefabs.Add(val);
			}
		}

		private void loadVegetation(string basePath)
		{
			string text = basePath + "Vegetation/";
			string[] array = new string[0];
			string[] array2 = array;
			foreach (string text2 in array2)
			{
				GameObject val = assetBundle.LoadAsset<GameObject>(text + text2 + ".prefab");
				if ((Object)(object)val == (Object)null)
				{
					Debug.LogWarning((object)("Could not find vegegation with name: " + text2));
					continue;
				}
				ShaderReplacment.Replace(val);
				vegetationPrefabs.Add(val);
			}
		}

		private void loadOther(string basePath)
		{
			string text = basePath + "Other/";
			string[] array = new string[3] { "sfx_stop_cart_bal", "vfx_cartconnector_bal", "_railhammerPieceTable_bal" };
			string[] array2 = array;
			foreach (string text2 in array2)
			{
				GameObject val = assetBundle.LoadAsset<GameObject>(text + text2 + ".prefab");
				if ((Object)(object)val == (Object)null)
				{
					Debug.LogWarning((object)("Could not find object with name: " + text2));
					continue;
				}
				ShaderReplacment.Replace(val);
				vfxPrefabs.Add(val);
			}
		}

		private void prepareOtherEffects(string mainPath)
		{
			string[] array = new string[0];
			string[] array2 = array;
			foreach (string text in array2)
			{
				StatusEffect val = (StatusEffect)(object)assetBundle.LoadAsset<SE_Stats>(mainPath + "Status/" + text + ".asset");
				if ((Object)(object)val == (Object)null)
				{
					Debug.LogWarning((object)("Status not found: " + text));
				}
				else
				{
					statusEffects.Add(val);
				}
			}
		}
	}
	public class ShaderReplacment
	{
		public static List<GameObject> prefabsToReplaceShader = new List<GameObject>();

		public static List<Material> materialsInPrefabs = new List<Material>();

		public string[] shaderlist = new string[49]
		{
			"Custom/AlphaParticle", "Custom/Blob", "Custom/Bonemass", "Custom/Clouds", "Custom/Creature", "Custom/Decal", "Custom/Distortion", "Custom/Flow", "Custom/FlowOpaque", "Custom/Grass",
			"Custom/GuiScroll", "Custom/Heightmap", "Custom/icon", "Custom/InteriorSide", "Custom/LitGui", "Custom/LitParticles", "Custom/mapshader", "Custom/ParticleDecal", "Custom/Piece", "Custom/Player",
			"Custom/Rug", "Custom/ShadowBlob", "Custom/SkyboxProcedural", "Custom/SkyObject", "Custom/StaticRock", "Custom/Tar", "Custom/Trilinearmap", "Custom/UI/BGBlur", "Custom/Vegetation", "Custom/Water",
			"Custom/WaterBottom", "Custom/WaterMask", "Custom/Yggdrasil", "Custom/Yggdrasil/root", "Hidden/BlitCopyHDRTonemap", "Hidden/Dof/DepthOfFieldHdr", "Hidden/Dof/DX11Dof", "Hidden/Internal-Loading", "Hidden/Internal-UIRDefaultWorld", "Hidden/SimpleClear",
			"Hidden/SunShaftsComposite", "Lux Lit Particles/ Bumped", "Lux Lit Particles/ Tess Bumped", "Particles/Standard Surface2", "Particles/Standard Unlit2", "Standard TwoSided", "ToonDeferredShading2017", "Unlit/DepthWrite", "Unlit/Lighting"
		};

		public static List<Shader> shaders = new List<Shader>();

		private static readonly HashSet<Shader> CachedShaders = new HashSet<Shader>();

		public static bool debug = true;

		public static Shader findShader(string name)
		{
			Shader[] array = Resources.FindObjectsOfTypeAll<Shader>();
			if (array.Length == 0)
			{
				Debug.LogWarning((object)"SHADER LIST IS EMPTY!");
				return null;
			}
			if (debug)
			{
			}
			return shaders.Find((Shader x) => ((Object)x).name == name);
		}

		public static Shader GetShaderByName(string name)
		{
			return shaders.Find((Shader x) => ((Object)x).name == name.Trim());
		}

		public static void debugShaderList(List<Shader> shadersRes)
		{
			foreach (Shader shadersRe in shadersRes)
			{
				Debug.LogWarning((object)("SHADER NAME IS: " + ((Object)shadersRe).name));
			}
			debug = false;
		}

		public static void Replace(GameObject gameObject)
		{
			prefabsToReplaceShader.Add(gameObject);
			GetMaterialsInPrefab(gameObject);
		}

		public static void GetMaterialsInPrefab(GameObject gameObject)
		{
			Renderer[] componentsInChildren = gameObject.GetComponentsInChildren<Renderer>(true);
			Renderer[] array = componentsInChildren;
			foreach (Renderer val in array)
			{
				Material[] sharedMaterials = val.sharedMaterials;
				if (sharedMaterials == null || sharedMaterials.Length == 0)
				{
					continue;
				}
				Material[] array2 = sharedMaterials;
				foreach (Material val2 in array2)
				{
					if ((Object)(object)val2 != (Object)null)
					{
						materialsInPrefabs.Add(val2);
					}
				}
			}
		}

		public static void getMeShaders()
		{
			AssetBundle[] array = Resources.FindObjectsOfTypeAll<AssetBundle>();
			AssetBundle[] array2 = array;
			foreach (AssetBundle val in array2)
			{
				IEnumerable<Shader> enumerable3;
				try
				{
					IEnumerable<Shader> enumerable2;
					if (!val.isStreamedSceneAssetBundle || !Object.op_Implicit((Object)(object)val))
					{
						IEnumerable<Shader> enumerable = val.LoadAllAssets<Shader>();
						enumerable2 = enumerable;
					}
					else
					{
						enumerable2 = from shader in ((IEnumerable<string>)val.GetAllAssetNames()).Select((Func<string, Shader>)val.LoadAsset<Shader>)
							where (Object)(object)shader != (Object)null
							select shader;
					}
					enumerable3 = enumerable2;
				}
				catch (Exception)
				{
					continue;
				}
				if (enumerable3 == null)
				{
					continue;
				}
				foreach (Shader item in enumerable3)
				{
					CachedShaders.Add(item);
				}
			}
		}

		public static void runMaterialFix()
		{
			getMeShaders();
			shaders.AddRange(CachedShaders);
			foreach (Material materialsInPrefab in materialsInPrefabs)
			{
				Shader shader = materialsInPrefab.shader;
				if (!((Object)(object)shader == (Object)null))
				{
					string name = ((Object)shader).name;
					if (!(name == "Standard") && name.Contains("Balrond"))
					{
						setProperValue(materialsInPrefab, name);
					}
				}
			}
		}

		private static void setProperValue(Material material, string shaderName)
		{
			string name = shaderName.Replace("Balrond", "Custom");
			name = checkNaming(name);
			Shader shaderByName = GetShaderByName(name);
			if ((Object)(object)shaderByName == (Object)null)
			{
				Debug.LogWarning((object)("Shader not found " + name));
			}
			else
			{
				material.shader = shaderByName;
			}
		}

		private static string checkNaming(string name)
		{
			string result = name;
			if (name.Contains("Bumped"))
			{
				result = name.Replace("Custom", "Lux Lit Particles");
			}
			if (name.Contains("Tess Bumped"))
			{
				result = name.Replace("Custom", "Lux Lit Particles");
			}
			if (name.Contains("Standard Surface"))
			{
				result = name.Replace("Custom", "Particles");
				result = result.Replace("Standard Surface2", "Standard Surface");
			}
			if (name.Contains("Standard Unlit"))
			{
				result = name.Replace("Custom", "Particles");
				result = result.Replace("Standard Unlit", "Standard Unlit2");
				result = result.Replace("Standard Unlit22", "Standard Unlit2");
			}
			return result;
		}
	}
	public class JsonLoader
	{
		public string defaultPath = string.Empty;

		public void loadJson()
		{
			LoadTranslations();
			justDefaultPath();
		}

		public void justDefaultPath()
		{
			string configPath = Paths.ConfigPath;
			string text = Path.Combine(configPath, "BalrondRuneRails-translation/");
			defaultPath = text;
		}

		public void createDefaultPath()
		{
			string configPath = Paths.ConfigPath;
			string text = Path.Combine(configPath, "BalrondRuneRails-translation/");
			if (!Directory.Exists(text))
			{
				CreateFolder(text);
			}
			else
			{
				Debug.Log((object)("BalrondRuneRails: Folder already exists: " + text));
			}
			defaultPath = text;
		}

		private string[] jsonFilePath(string folderName, string extension)
		{
			string configPath = Paths.ConfigPath;
			string text = Path.Combine(configPath, "BalrondRuneRails-translation/");
			if (!Directory.Exists(text))
			{
				CreateFolder(text);
			}
			else
			{
				Debug.Log((object)("BalrondRuneRails: Folder already exists: " + text));
			}
			string[] files = Directory.GetFiles(text, extension);
			Debug.Log((object)("BalrondRuneRails:" + folderName + " Json Files Found: " + files.Length));
			return files;
		}

		private static void CreateFolder(string path)
		{
			try
			{
				Directory.CreateDirectory(path);
				Debug.Log((object)"BalrondRuneRails: Folder created successfully.");
			}
			catch (Exception ex)
			{
				Debug.Log((object)("BalrondRuneRails: Error creating folder: " + ex.Message));
			}
		}

		private void LoadTranslations()
		{
			int num = 0;
			string[] array = jsonFilePath("Translation", "*.json");
			foreach (string text in array)
			{
				string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text);
				string json = File.ReadAllText(text);
				JsonData jsonData = JsonMapper.ToObject(json);
				Dictionary<string, string> dictionary = new Dictionary<string, string>();
				foreach (string key in jsonData.Keys)
				{
					dictionary[key] = jsonData[key].ToString();
				}
				if (dictionary != null)
				{
					BalrondTranslator.translations.Add(fileNameWithoutExtension, dictionary);
					Debug.Log((object)("BalrondRuneRails: Json Files Language: " + fileNameWithoutExtension));
					num++;
				}
				else
				{
					Debug.LogError((object)("BalrondRuneRails: Loading FAILED file: " + text));
				}
			}
			Debug.Log((object)("BalrondRuneRails: Translation JsonFiles Loaded: " + num));
		}
	}
	[BepInPlugin("balrond.astafaraios.BalrondRuneRails", "BalrondRuneRails", "1.0.5")]
	public class Launch : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(CraftingStation), "Start")]
		public static class BCSCartCraftingStation_Start_Patch
		{
			private static void Postfix(CraftingStation __instance)
			{
				if ((Object)(object)__instance == (Object)null)
				{
					return;
				}
				BCSCartCraftingStation component = ((Component)__instance).GetComponent<BCSCartCraftingStation>();
				if ((Object)(object)component == (Object)null)
				{
					return;
				}
				if (component.m_disableRoofRequirement)
				{
					__instance.m_craftRequireRoof = false;
				}
				if (component.m_disableFireRequirement)
				{
					__instance.m_craftRequireFire = false;
				}
				if (!component.m_useCartZNetView)
				{
					return;
				}
				BCSCartRoot componentInParent = ((Component)__instance).GetComponentInParent<BCSCartRoot>();
				if ((Object)(object)componentInParent == (Object)null)
				{
					Debug.LogWarning((object)("[BCS] Cart CraftingStation has no BCSCartRoot parent: " + ((Object)__instance).name));
					return;
				}
				ZNetView netView = componentInParent.GetNetView();
				if ((Object)(object)netView == (Object)null)
				{
					Debug.LogWarning((object)("[BCS] Cart CraftingStation parent cart has no ZNetView: " + ((Object)__instance).name));
					return;
				}
				__instance.m_nview = netView;
				if (!CraftingStation.m_allStations.Contains(__instance))
				{
					CraftingStation.m_allStations.Add(__instance);
				}
			}
		}

		[HarmonyPatch]
		public static class BCSPowerCartCameraPatches
		{
			private static Vector3 _cameraVelocity;

			private static Quaternion _lastRotation = Quaternion.identity;

			private static bool _initialized;

			[HarmonyPrefix]
			[HarmonyPatch(typeof(GameCamera), "UpdateCamera")]
			private static bool GameCamera_UpdateCamera_Prefix(GameCamera __instance, float dt)
			{
				//IL_00f9: 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_010c: 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_0127: Unknown result type (might be due to invalid IL or missing references)
				//IL_012a: Unknown result type (might be due to invalid IL or missing references)
				//IL_012f: Unknown result type (might be due to invalid IL or missing references)
				//IL_013a: Unknown result type (might be due to invalid IL or missing references)
				//IL_00be: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)__instance == (Object)null)
				{
					Reset();
					return true;
				}
				BCSPowerCartControls localDrivingCameraLockControl = BCSPowerCartControls.GetLocalDrivingCameraLockControl();
				if ((Object)(object)localDrivingCameraLockControl == (Object)null)
				{
					Reset();
					return true;
				}
				if (!localDrivingCameraLockControl.TryGetDriverViewCameraPose(out var position, out var rotation))
				{
					Reset();
					return true;
				}
				float num = Mathf.Max(0.01f, BCSCommonUtility.SanitizeFloat(localDrivingCameraLockControl.m_driverViewSmoothTime, 0.12f));
				float num2 = ((dt > 0f) ? dt : Time.unscaledDeltaTime);
				if (num2 <= 0f)
				{
					num2 = Time.unscaledDeltaTime;
				}
				if (!_initialized)
				{
					_initialized = true;
					_cameraVelocity = Vector3.zero;
					_lastRotation = rotation;
					((Component)__instance).transform.position = position;
					((Component)__instance).transform.rotation = rotation;
					return false;
				}
				((Component)__instance).transform.position = Vector3.SmoothDamp(((Component)__instance).transform.position, position, ref _cameraVelocity, num, 999f, num2);
				float num3 = Mathf.Clamp01(num2 / num);
				_lastRotation = Quaternion.Slerp(_lastRotation, rotation, num3);
				((Component)__instance).transform.rotation = _lastRotation;
				return false;
			}

			private static void Reset()
			{
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				_initialized = false;
				_cameraVelocity = Vector3.zero;
				_lastRotation = Quaternion.identity;
			}
		}

		[HarmonyPatch(typeof(AudioMan), "Awake")]
		private static class AudioMan_Awake_Patch
		{
			private static void Postfix(AudioMan __instance)
			{
				List<List<GameObject>> list = new List<List<GameObject>> { modResourceLoader.itemPrefabs, modResourceLoader.buildPrefabs, modResourceLoader.monsterPrefabs, modResourceLoader.vfxPrefabs, modResourceLoader.vegetationPrefabs };
				foreach (List<GameObject> item in list)
				{
					foreach (GameObject item2 in item)
					{
						AudioSource[] componentsInChildren = item2.GetComponentsInChildren<AudioSource>(true);
						foreach (AudioSource val in componentsInChildren)
						{
							val.outputAudioMixerGroup = __instance.m_masterMixer.outputAudioMixerGroup;
						}
					}
				}
			}
		}

		[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
		public static class Object_CopyOtherDB_Path
		{
			public static void Postfix()
			{
				if (IsObjectDBValid())
				{
					modResourceLoader.setupBuildPiecesListDB();
					modResourceLoader.recipes = recipeFactory.createRecipes(ObjectDB.instance.m_items, modResourceLoader.itemPrefabs, modResourceLoader.railwaytable);
					databaseAddMethods.AddItems(modResourceLoader.itemPrefabs);
					databaseAddMethods.AddStatuseffects(modResourceLoader.statusEffects);
					databaseAddMethods.AddRecipes(modResourceLoader.recipes);
				}
			}
		}

		[HarmonyPatch(typeof(ObjectDB), "Awake")]
		public static class ObjectDB_Awake_Path
		{
			public static void Postfix()
			{
				if (IsObjectDBValid())
				{
					modResourceLoader.setupBuildPiecesListDB();
					modResourceLoader.recipes = recipeFactory.createRecipes(ObjectDB.instance.m_items, modResourceLoader.itemPrefabs, modResourceLoader.railwaytable);
					databaseAddMethods.AddItems(modResourceLoader.itemPrefabs);
					databaseAddMethods.AddStatuseffects(modResourceLoader.statusEffects);
					databaseAddMethods.AddRecipes(modResourceLoader.recipes);
					ObjectDB.instance.m_recipes.Sort(SortByScore);
				}
			}

			private static int SortByScore(Recipe p1, Recipe p2)
			{
				if ((Object)(object)p1.m_item == (Object)null)
				{
					return 0;
				}
				if ((Object)(object)p2.m_item == (Object)null)
				{
					return 1;
				}
				return ((Object)p1.m_item).name.CompareTo(((Object)p2.m_item).name);
			}
		}

		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		public static class ZNetScene_Awake_Path
		{
			public static void Prefix(ZNetScene __instance)
			{
				if ((Object)(object)__instance == (Object)null)
				{
					Debug.LogWarning((object)(projectName + ": No ZnetScene found"));
					return;
				}
				modResourceLoader.AddPrefabsToZnetScene(__instance);
				if (!hasSpawned)
				{
					buildPieceBuilder.SetupBuildPieces(__instance.m_prefabs);
					hasSpawned = true;
					if (!((Object)(object)ZNet.instance != (Object)null) || !ZNet.instance.IsDedicated())
					{
						ShaderReplacment.runMaterialFix();
					}
				}
			}
		}

		[HarmonyPatch(typeof(Door), "Interact")]
		public static class BCSSignalDoorReceiver_Interact_Patch
		{
			private static bool Prefix(Door __instance, Humanoid character, bool hold, bool alt, ref bool __result)
			{
				if ((Object)(object)__instance == (Object)null || hold)
				{
					return true;
				}
				BCSSignalDoorReceiver component = ((Component)__instance).GetComponent<BCSSignalDoorReceiver>();
				if ((Object)(object)component == (Object)null)
				{
					return true;
				}
				if (IsShiftHeld())
				{
					component.RequestSetSignalNameFromUser();
					__result = true;
					return false;
				}
				if (IsAltHeld())
				{
					component.ToggleEventStateFromUser();
					__result = true;
					return false;
				}
				return true;
			}

			private static bool IsShiftHeld()
			{
				return Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303);
			}

			private static bool IsAltHeld()
			{
				return Input.GetKey((KeyCode)308) || Input.GetKey((KeyCode)307);
			}
		}

		[HarmonyPatch(typeof(Door), "GetHoverText")]
		public static class BCSSignalDoorReceiver_Hover_Patch
		{
			private static void Postfix(Door __instance, ref string __result)
			{
				if (!((Object)(object)__instance == (Object)null))
				{
					BCSSignalDoorReceiver component = ((Component)__instance).GetComponent<BCSSignalDoorReceiver>();
					if (!((Object)(object)component == (Object)null))
					{
						__result += ((Localization.instance != null) ? Localization.instance.Localize(component.GetExtraHoverText()) : component.GetExtraHoverText());
					}
				}
			}
		}

		[HarmonyPatch(typeof(Container), "Interact")]
		public static class BCS_Container_Interact_Patch
		{
			private static bool Prefix(Container __instance, Humanoid character, bool hold, bool alt, ref bool __result)
			{
				if ((Object)(object)__instance == (Object)null || hold || (Object)(object)character == (Object)null)
				{
					return true;
				}
				BCSCartRoot componentInParent = ((Component)__instance).GetComponentInParent<BCSCartRoot>();
				if ((Object)(object)componentInParent != (Object)null)
				{
					BCSContainerInitUtility.EnsureInitialized(__instance, componentInParent.GetNetView());
					return true;
				}
				BCSRailContainerTransfer componentInParent2 = ((Component)__instance).GetComponentInParent<BCSRailContainerTransfer>();
				if ((Object)(object)componentInParent2 == (Object)null)
				{
					return true;
				}
				BCSContainerInitUtility.EnsureInitialized(__instance);
				if (!componentInParent2.OwnsContainer(__instance))
				{
					return true;
				}
				if (componentInParent2.IsTransferRunning())
				{
					__instance.UpdateUseVisual();
					Player val = (Player)(object)((character is Player) ? character : null);
					if ((Object)(object)val != (Object)null)
					{
						((Character)val).Message((MessageType)2, "Container transfer in progress", 0, (Sprite)null);
					}
					__result = true;
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(Container), "GetHoverText")]
		public static class BCS_Container_InitHover_Patch
		{
			private static void Prefix(Container __instance)
			{
				if ((Object)(object)__instance == (Object)null)
				{
					return;
				}
				BCSCartRoot componentInParent = ((Component)__instance).GetComponentInParent<BCSCartRoot>();
				if ((Object)(object)componentInParent != (Object)null)
				{
					BCSContainerInitUtility.EnsureInitialized(__instance, componentInParent.GetNetView());
					return;
				}
				BCSRailContainerTransfer componentInParent2 = ((Component)__instance).GetComponentInParent<BCSRailContainerTransfer>();
				if ((Object)(object)componentInParent2 != (Object)null)
				{
					BCSContainerInitUtility.EnsureInitialized(__instance);
					__instance.UpdateUseVisual();
				}
			}

			private static void Postfix(Container __instance, ref string __result)
			{
				if ((Object)(object)__instance == (Object)null)
				{
					return;
				}
				BCSRailContainerTransfer componentInParent = ((Component)__instance).GetComponentInParent<BCSRailContainerTransfer>();
				if (!((Object)(object)componentInParent == (Object)null) && componentInParent.OwnsContainer(__instance))
				{
					string hoverStatusText = componentInParent.GetHoverStatusText();
					if (!string.IsNullOrEmpty(hoverStatusText))
					{
						__result = __result + "\n" + hoverStatusText;
					}
				}
			}
		}

		private readonly Harmony harmony = new Harmony("balrond.astafaraios.BalrondRuneRails");

		public const string PluginGUID = "balrond.astafaraios.BalrondRuneRails";

		public const string PluginName = "BalrondRuneRails";

		public const string PluginVersion = "1.0.5";

		public static ModResourceLoader modResourceLoader = new ModResourceLoader();

		public static DatabaseAddMethods databaseAddMethods = new DatabaseAddMethods();

		public static BuildPieceBuilder buildPieceBuilder = new BuildPieceBuilder();

		public static string projectName = "BalrondRuneRails";

		public static GameObject RootObject;

		public static GameObject PrefabContainer;

		public static bool hasSpawned = false;

		public static JsonLoader jsonLoader = new JsonLoader();

		public static RecipeFactory recipeFactory = new RecipeFactory();

		public static Vector2 sizeDelta;

		public static bool addedWidth = false;

		private void Awake()
		{
			jsonLoader.loadJson();
			createPrefabContainer();
			modResourceLoader.loadAssets();
			debugvariabelcall();
			harmony.PatchAll();
		}

		public void createPrefabContainer()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			RootObject = new GameObject("_ValheimReforgedRoot");
			Object.DontDestroyOnLoad((Object)(object)RootObject);
			PrefabContainer = new GameObject("Prefabs");
			PrefabContainer.transform.parent = RootObject.transform;
			PrefabContainer.SetActive(false);
		}

		public static void debugvariabelcall()
		{
			Debug.LogWarning((object)"BalrondRuneRails DISPLAY ZDO KEYS KASHED NAMES:");
			Debug.LogWarning((object)"BalrondRuneRails Track:");
			Debug.Log((object)("Name: " + "hl_rail_id".ToString() + " Encoded: " + StringExtensionMethods.GetStableHashCode("hl_rail_id".ToString())));
			Debug.Log((object)("Name: " + "hl_rail_type".ToString() + " Encoded: " + StringExtensionMethods.GetStableHashCode("hl_rail_type".ToString())));
			Debug.Log((object)("Name: " + "hl_is_platform".ToString() + " Encoded: " + StringExtensionMethods.GetStableHashCode("hl_is_platform".ToString())));
			Debug.Log((object)("Name: " + "hl_neighbor_a".ToString() + " Encoded: " + StringExtensionMethods.GetStableHashCode("hl_neighbor_a".ToString())));
			Debug.Log((object)("Name: " + "hl_neighbor_b".ToString() + " Encoded: " + StringExtensionMethods.GetStableHashCode("hl_neighbor_b".ToString())));
			Debug.Log((object)("Name: " + "hl_neighbor_c".ToString() + " Encoded: " + StringExtensionMethods.GetStableHashCode("hl_neighbor_c".ToString())));
			Debug.Log((object)("Name: " + "hl_neighbor_d".ToString() + " Encoded: " + StringExtensionMethods.GetStableHashCode("hl_neighbor_d".ToString())));
			Debug.Log((object)("Name: " + "hl_rail_forced_stop".ToString() + " Encoded: " + StringExtensionMethods.GetStableHashCode("hl_rail_forced_stop".ToString())));
			Debug.Log((object)("Name: " + "hl_rail_switch_direction".ToString() + " Encoded: " + StringExtensionMethods.GetStableHashCode("hl_rail_switch_direction".ToString())));
			Debug.Log((object)("Name: " + "hl_halting".ToString() + " Encoded: " + StringExtensionMethods.GetStableHashCode("hl_halting".ToString())));
			Debug.Log((object)("Name: " + "hl_rail_stop_mode".ToString() + " Encoded: " + StringExtensionMethods.GetStableHashCode("hl_rail_type".ToString())));
			Debug.Log((object)("Name: " + "hl_stop_timer_seconds".ToString() + " Encoded: " + StringExtensionMethods.GetStableHashCode("hl_rail_type".ToString())));
			Debug.Log((object)("Name: " + "hl_stop_timer_end_time".ToString() + " Encoded: " + StringExtensionMethods.GetStableHashCode("hl_rail_type".ToString())));
			Debug.LogWarning((object)"BalrondRuneRails Cart:");
			Debug.Log((object)("Name: " + "hl_cart_id".ToString() + " Encoded: " + StringExtensionMethods.GetStableHashCode("hl_cart_id".ToString())));
			Debug.Log((object)("Name: " + "hl_cart_type".ToString() + " Encoded: " + StringExtensionMethods.GetStableHashCode("hl_cart_type".ToString())));
			Debug.Log((object)("Name: " + "hl_front_cart_id".ToString() + " Encoded: " + StringExtensionMethods.GetStableHashCode("hl_front_cart_id".ToString())));
			Debug.Log((object)("Name: " + "hl_back_cart_id".ToString() + " Encoded: " + StringExtensionMethods.GetStableHashCode("hl_back_cart_id".ToString())));
			Debug.Log((object)("Name: " + "hl_current_rail_id".ToString() + " Encoded: " + StringExtensionMethods.GetStableHashCode("hl_current_rail_id".ToString())));
			Debug.Log((object)("Name: " + "hl_distance_on_rail".ToString() + " Encoded: " + StringExtensionMeth