Decompiled source of ValheimRailway v0.7.5

plugins/ValheimRailway/ValheimRailway.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using ValheimRailway.Building;
using ValheimRailway.Rails;
using ValheimRailway.Trains;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: AssemblyCompany("ValheimRailway")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.7.5.0")]
[assembly: AssemblyInformationalVersion("0.7.5")]
[assembly: AssemblyProduct("ValheimRailway")]
[assembly: AssemblyTitle("ValheimRailway")]
[assembly: AssemblyVersion("0.7.5.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ValheimRailway
{
	[HarmonyPatch]
	internal static class PersistentZdoReferences
	{
		internal const string IdentityKey = "VR_PersistentId";

		private const string ReferenceSuffix = "_persistentId";

		private const string MigrationFile = "railway-reference-migration.tsv";

		private const long UnknownFormerUser = 1L;

		private static readonly Dictionary<string, ZDOID> Identities = new Dictionary<string, ZDOID>(StringComparer.Ordinal);

		private static readonly Dictionary<string, string> LegacyIdentities = new Dictionary<string, string>(StringComparer.Ordinal);

		private static ZDOMan? _manager;

		private static bool _migrationLoaded;

		private static bool _initializing;

		private static bool _worldLoaded;

		internal unsafe static ZDOID Get(ZDO source, string key)
		{
			//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_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: 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_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: 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)
			Initialize();
			ZDOID zDOID = source.GetZDOID(key);
			string value = source.GetString(key + "_persistentId", "");
			if (value.Length == 0)
			{
				if (((ZDOID)(ref zDOID)).IsNone())
				{
					return ZDOID.None;
				}
				if (!LegacyIdentities.TryGetValue(((object)(*(ZDOID*)(&zDOID))/*cast due to .constrained prefix*/).ToString(), out value))
				{
					if (((ZDOID)(ref zDOID)).UserID == 1)
					{
						return ZDOID.None;
					}
					ZDOMan instance = ZDOMan.instance;
					ZDO val = ((instance != null) ? instance.GetZDO(zDOID) : null);
					if (val == null)
					{
						return zDOID;
					}
					value = EnsureIdentity(val);
				}
				if (value.Length > 0 && CanWrite(source))
				{
					source.Set(key + "_persistentId", value);
				}
			}
			if (value.Length == 0)
			{
				return zDOID;
			}
			ZDOID val2 = Resolve(value);
			if (!((ZDOID)(ref val2)).IsNone())
			{
				if (val2 != zDOID && CanWrite(source))
				{
					source.Set(key, val2);
				}
				return val2;
			}
			if (!((ZDOID)(ref zDOID)).IsNone())
			{
				ZDOMan instance2 = ZDOMan.instance;
				if (((instance2 != null) ? instance2.GetZDO(zDOID) : null) == null)
				{
					ZDOMan instance3 = ZDOMan.instance;
					if (instance3 != null)
					{
						instance3.RequestZDO(zDOID);
					}
					return zDOID;
				}
			}
			return ZDOID.None;
		}

		internal static void Set(ZDO source, string key, ZDOID targetId)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			Initialize();
			EnsureIdentity(source);
			if (((ZDOID)(ref targetId)).IsNone())
			{
				Remove(source, key);
				return;
			}
			ZDOMan instance = ZDOMan.instance;
			ZDO val = ((instance != null) ? instance.GetZDO(targetId) : null);
			string text = ((val != null) ? EnsureIdentity(val) : "");
			if (text.Length == 0 && source.GetZDOID(key) == targetId)
			{
				text = source.GetString(key + "_persistentId", "");
			}
			source.Set(key, targetId);
			if (text.Length > 0)
			{
				source.Set(key + "_persistentId", text);
			}
			else
			{
				source.RemoveString(StringExtensionMethods.GetStableHashCode(key + "_persistentId"));
			}
		}

		internal static void Remove(ZDO source, string key)
		{
			source.RemoveZDOID(key);
			source.RemoveString(StringExtensionMethods.GetStableHashCode(key + "_persistentId"));
		}

		private static bool CanWrite(ZDO zdo)
		{
			if (!zdo.IsOwner())
			{
				if ((Object)(object)ZNet.instance != (Object)null)
				{
					return ZNet.instance.IsServer();
				}
				return false;
			}
			return true;
		}

		internal static string EnsureAuthoritativeIdentity(ZDO zdo)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || ZDOMan.instance == null || zdo == null || ZDOMan.instance.GetZDO(zdo.m_uid) != zdo)
			{
				return string.Empty;
			}
			if (_manager != ZDOMan.instance)
			{
				Reset();
			}
			_manager = ZDOMan.instance;
			return EnsureIdentity(zdo);
		}

		private static string EnsureIdentity(ZDO zdo)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			string text = zdo.GetString("VR_PersistentId", "");
			if (text.Length == 0 && CanWrite(zdo))
			{
				text = Guid.NewGuid().ToString("N");
				zdo.Set("VR_PersistentId", text);
			}
			if (text.Length > 0)
			{
				Identities[text] = zdo.m_uid;
			}
			return text;
		}

		private static ZDOID Resolve(string identity)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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)
			if (Identities.TryGetValue(identity, out var value))
			{
				ZDOMan instance = ZDOMan.instance;
				ZDO val = ((instance != null) ? instance.GetZDO(value) : null);
				if (val != null && val.GetString("VR_PersistentId", "") == identity)
				{
					return value;
				}
				Identities.Remove(identity);
			}
			IndexIdentities();
			if (!Identities.TryGetValue(identity, out value))
			{
				return ZDOID.None;
			}
			return value;
		}

		private static void IndexIdentities()
		{
			//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_002d: Unknown result type (might be due to invalid IL or missing references)
			if (ZDOMan.instance == null)
			{
				return;
			}
			foreach (ZDOID item in ZDOExtraData.GetAllZDOIDsWithHash((Type)5, StringExtensionMethods.GetStableHashCode("VR_PersistentId")))
			{
				ZDO zDO = ZDOMan.instance.GetZDO(item);
				if (zDO != null)
				{
					EnsureIdentity(zDO);
				}
			}
		}

		private static void Initialize()
		{
			if (_initializing || ZDOMan.instance == null)
			{
				return;
			}
			if (_manager != ZDOMan.instance)
			{
				Reset();
			}
			_manager = ZDOMan.instance;
			if (!_worldLoaded || _migrationLoaded || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
			{
				return;
			}
			_initializing = true;
			try
			{
				_migrationLoaded = true;
				IndexIdentities();
				LoadMigration();
				NormalizeReferences();
			}
			finally
			{
				_initializing = false;
			}
		}

		private static void LoadMigration()
		{
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			string path = Path.Combine(Path.GetDirectoryName(typeof(Plugin).Assembly.Location), "railway-reference-migration.tsv");
			if (!File.Exists(path))
			{
				return;
			}
			try
			{
				string[] array = File.ReadAllLines(path);
				string value = "worldId=" + ZNet.instance.GetWorldUID() + ";";
				if (array.Length == 0 || !array[0].Contains(value))
				{
					return;
				}
				Dictionary<string, ZDO> dictionary = new Dictionary<string, ZDO>(StringComparer.Ordinal);
				foreach (ZDOID item in ZDOExtraData.GetAllZDOIDsWithHash((Type)5, StringExtensionMethods.GetStableHashCode("architect_label")))
				{
					ZDO zDO = ZDOMan.instance.GetZDO(item);
					if (zDO != null)
					{
						string key = zDO.GetString("architect_group", "") + "\t" + zDO.GetString("architect_label", "");
						if (dictionary.ContainsKey(key))
						{
							dictionary[key] = null;
						}
						else
						{
							dictionary.Add(key, zDO);
						}
					}
				}
				string[] array2 = array;
				foreach (string text in array2)
				{
					if (!text.StartsWith("#", StringComparison.Ordinal))
					{
						string[] array3 = text.Split(new char[1] { '\t' });
						if (array3.Length == 4 && !(array3[0] != ZNet.instance.GetWorldName()) && dictionary.TryGetValue(array3[2] + "\t" + array3[3], out var value2) && value2 != null)
						{
							LegacyIdentities[array3[1]] = EnsureIdentity(value2);
						}
					}
				}
				RailwayLog.Info($"Prepared {LegacyIdentities.Count} exact legacy railway identity migrations.");
			}
			catch (Exception ex)
			{
				RailwayLog.Error("Could not read railway reference migration: " + ex.Message);
			}
		}

		[HarmonyPatch(typeof(ZDOMan), "PrepareSave")]
		[HarmonyPrefix]
		private static void BeforeSave()
		{
			MarkWorldReady();
			if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
			{
				NormalizeReferences();
			}
		}

		[HarmonyPatch(typeof(ZNet), "OnWorldSaveLoaded")]
		[HarmonyPostfix]
		private static void AfterWorldLoaded()
		{
			MarkWorldReady();
		}

		private static void MarkWorldReady()
		{
			if (ZDOMan.instance != null)
			{
				if (_manager != ZDOMan.instance)
				{
					Reset();
				}
				_manager = ZDOMan.instance;
				_worldLoaded = true;
				Initialize();
			}
		}

		private static void NormalizeReferences()
		{
			//IL_0088: 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_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			HashSet<ZDOID> hashSet = new HashSet<ZDOID>();
			List<string> list = new List<string> { "VR_ParentCar", "VR_RailSegment", "VR_Follower0" };
			for (int i = 0; i < 128; i++)
			{
				list.Add("VR_MountedChild" + i);
			}
			foreach (string item in list)
			{
				foreach (ZDOID item2 in ZDOExtraData.GetAllZDOIDsWithHash((Type)4, StringExtensionMethods.GetStableHashCode(item + "_u")))
				{
					hashSet.Add(item2);
				}
			}
			foreach (ZDOID item3 in hashSet)
			{
				ZDO zDO = ZDOMan.instance.GetZDO(item3);
				if (zDO == null)
				{
					continue;
				}
				EnsureIdentity(zDO);
				foreach (string item4 in list)
				{
					Get(zDO, item4);
				}
				ZDOMan.instance.ForceSendZDO(item3);
			}
		}

		[HarmonyPatch(typeof(ZDOMan), "ResetBeforeLoad")]
		[HarmonyPrefix]
		private static void Reset()
		{
			Identities.Clear();
			LegacyIdentities.Clear();
			_manager = null;
			_migrationLoaded = false;
			_initializing = false;
			_worldLoaded = false;
		}
	}
	[BepInPlugin("com.valheimrailway.prototype", "Valheim Railway", "0.7.5")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		private Harmony? _harmony;

		private RailwayAssets? _assets;

		private void Awake()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			RailwayLog.Initialize(((BaseUnityPlugin)this).Logger);
			_harmony = new Harmony("com.valheimrailway.prototype");
			_harmony.PatchAll(typeof(Plugin).Assembly);
			_assets = new RailwayAssets();
			_assets.LoadAndRegister();
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new RailwayConsoleCommand());
			RailwayLog.Info("Loaded Valheim Railway 0.7.5");
		}

		private void OnDestroy()
		{
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
			_assets?.Dispose();
			_assets = null;
		}
	}
	internal static class PluginInfo
	{
		public const string Guid = "com.valheimrailway.prototype";

		public const string Name = "Valheim Railway";

		public const string Version = "0.7.5";

		public const string JotunnGuid = "com.jotunn.jotunn";
	}
	internal sealed class RailwayAssets : IDisposable
	{
		private enum RailwayIconKind
		{
			TrackStraight,
			TrackCurve,
			TrackFlexible,
			TrackIncline15,
			TrackIncline30,
			TrackStation,
			Support,
			Platform,
			Cart,
			Floor,
			Wall,
			Roof,
			ControlStand,
			WindowWall,
			Door,
			Seat,
			InteriorLamp,
			ExteriorLamp,
			WindowWallTall,
			WindowWallPanoramic,
			TrackEntry,
			TrackExit,
			TrackGrade,
			Ladder,
			DestinationDisplay,
			RailSwitch,
			BoardingLadder
		}

		private const string BundleResource = "valheimrailwayassets";

		private const string AssetRoot = "Assets/ValheimRailway/Generated/Prefabs/";

		private AssetBundle? _bundle;

		public void LoadAndRegister()
		{
			_bundle = LoadEmbeddedBundle();
			if ((Object)(object)_bundle == (Object)null)
			{
				throw new InvalidOperationException("Embedded asset bundle 'valheimrailwayassets' could not be loaded.");
			}
			RegisterTrack("VR_TrackStraight", "Rail - Straight", "A four-metre railway segment with solid trestle beams; no ground support required.");
			RegisterTrack("VR_TrackCurve45", "Rail - Curve 45°", "A broad forty-five-degree curve with solid trestle beams; no ground support required.", isStationStop: false, isFlexible: false, RailwayIconKind.TrackCurve);
			RegisterTrack("VR_TrackFlexible", "Rail - Flexible Closure", "Closes a small remaining route gap by adjusting its length and angle after placement.", isStationStop: false, isFlexible: true, RailwayIconKind.TrackFlexible);
			RegisterTrack("VR_TrackIncline15", "Rail - Incline 15°", "A smooth gentle incline for elevated railways and roller-coaster layouts.", isStationStop: false, isFlexible: false, RailwayIconKind.TrackIncline15);
			RegisterTrack("VR_TrackIncline30", "Rail - Incline 30°", "A smooth steep incline for compact roller-coaster climbs and drops.", isStationStop: false, isFlexible: false, RailwayIconKind.TrackIncline30);
			RegisterTrack("VR_TrackStationStop", "Rail - Station Stop", "Stops arriving trains. Press E at its sign to call the nearest parked train on connected, loaded track.", isStationStop: true, isFlexible: false, RailwayIconKind.TrackStation);
			RegisterSupport();
			int[] array = new int[2] { 15, 30 };
			for (int i = 0; i < array.Length; i++)
			{
				int num = array[i];
				RegisterTrack("VR_TrackTransition" + num + "Entry", $"Rail - Flat to {num}°", $"An eight-metre smooth transition from level track to the new constant {num}° grade.", isStationStop: false, isFlexible: false, RailwayIconKind.TrackEntry);
				RegisterTrack("VR_TrackGrade" + num, $"Rail - Constant Grade {num}°", $"A four-metre straight {num}° slope for the new entry/exit transition family. Old inclines are unchanged.", isStationStop: false, isFlexible: false, RailwayIconKind.TrackGrade);
				RegisterTrack("VR_TrackTransition" + num + "Exit", $"Rail - {num}° to Flat", $"An eight-metre smooth transition from the new {num}° grade to level track. Reverse the sequence for a descent.", isStationStop: false, isFlexible: false, RailwayIconKind.TrackExit);
			}
			RegisterRailVehicle("VR_RailPlatform", "Rail Platform", "A large low-speed buildable railway platform. Place it close to a completed rail.", RailwayIconKind.Platform);
			RegisterRailVehicle("VR_RailCart", "Rail Cart", "A compact buildable cart for trains and roller-coaster layouts.", RailwayIconKind.Cart);
			RegisterTrainBuildingPart("VR_TrainFloor2x2", "Train Floor - Flat 2x2", "A flat two-metre floor tile made for modular carriage interiors.", RailwayIconKind.Floor);
			RegisterTrainBuildingPart("VR_TrainWall2x2", "Train Wall - Flat 2x2", "A flat two-metre wall panel that snaps to the carriage building grid.", RailwayIconKind.Wall);
			RegisterTrainBuildingPart("VR_TrainRoof2x2", "Train Roof - Flat 2x2", "A flat two-metre roof panel for modular carriage compartments.", RailwayIconKind.Roof);
			RegisterTrainBuildingPart("VR_CarriageWindowWall", "Train Wall - Window 2x2", "A flat two-metre carriage wall with a wide window.", RailwayIconKind.WindowWall);
			RegisterTrainBuildingPart("VR_CarriageWindowWall2x4", "Train Wall - Tall Window 2x4", "A two-metre-wide, four-metre-tall carriage wall with one continuous window. Counts as one mounted piece.", RailwayIconKind.WindowWallTall);
			RegisterTrainBuildingPart("VR_CarriageWindowWall4x4", "Train Wall - Panoramic Window 4x4", "A four-metre-wide, four-metre-tall carriage wall with one continuous panoramic window. Counts as one mounted piece.", RailwayIconKind.WindowWallPanoramic);
			RegisterTrainDoor();
			RegisterTrainSeat();
			RegisterTrainLamp("VR_InteriorLamp", "Train Lamp - Interior", "A warm, compact carriage light. Press E to turn it on or off.", exterior: false, RailwayIconKind.InteriorLamp);
			RegisterTrainLamp("VR_ExteriorLamp", "Train Lamp - Exterior", "A cool, brighter outside carriage light. Press E to turn it on or off.", exterior: true, RailwayIconKind.ExteriorLamp);
			RegisterControlStand();
			RegisterRailSwitch();
			RegisterTrainBuildingPart("VR_TrainLadder", "Train Stairs - 2m Rise", "A compact walk-up ladder with a continuous collision slope. Rises two metres over a two-metre run; snap it between floors.", RailwayIconKind.Ladder);
			RegisterTrainBuildingPart("VR_TrainBoardingLadder", "Train Boarding Ladder - Vertical 2m", "A boat-style ladder that hangs from the deck edge. Snap its top bracket to the train, with the brackets pointing inward. Press E to board a clear deck.", RailwayIconKind.BoardingLadder);
			RegisterDestinationDisplay();
			RailwayLog.Info("Registered rails, inclines, station stop, compact cart, 6x6 platform, flat carriage panels, 2x2, 2x4 and 4x4 window walls, working door, seat, train lamps, control stand, junction switch, and legacy support.");
		}

		public void Dispose()
		{
			AssetBundle bundle = _bundle;
			_bundle = null;
			if ((Object)(object)bundle != (Object)null)
			{
				bundle.Unload(false);
			}
		}

		private void RegisterTrack(string prefabName, string displayName, string description, bool isStationStop = false, bool isFlexible = false, RailwayIconKind iconKind = RailwayIconKind.TrackStraight)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			GameObject val = LoadPrefab(prefabName);
			PreparePiece(val, (UsageTagFlags)2048);
			TagSnapPoint(val, "snap_start");
			TagSnapPoint(val, "snap_end");
			GetOrAdd<RailSegment>(val);
			if (isStationStop)
			{
				GetOrAdd<RailStop>(val);
				ConfigureStationCallHitbox(val);
			}
			if (isFlexible)
			{
				GetOrAdd<FlexibleRail>(val);
			}
			PieceConfig val2 = CreatePieceConfig(displayName, description, iconKind);
			AddPieceOrThrow(new CustomPiece(val, false, val2));
		}

		private static void ConfigureStationCallHitbox(GameObject prefab)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: 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 val = FindRequiredChild(prefab, "visual_station_stop_board");
			Transform val2 = prefab.transform.Find("station_call_hitbox");
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = new GameObject("station_call_hitbox").transform;
				val2.SetParent(prefab.transform, false);
			}
			((Component)val2).gameObject.layer = prefab.layer;
			val2.localPosition = val.localPosition;
			val2.localRotation = val.localRotation;
			val2.localScale = Vector3.one;
			BoxCollider orAdd = GetOrAdd<BoxCollider>(((Component)val2).gameObject);
			orAdd.center = Vector3.zero;
			orAdd.size = new Vector3(0.8f, 0.56f, 0.2f);
			((Collider)orAdd).isTrigger = false;
		}

		private void RegisterSupport()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			GameObject obj = LoadPrefab("VR_TrackSupport");
			PreparePiece(obj, (UsageTagFlags)68);
			TagSnapPoint(obj, "snap_top");
			PieceConfig val = CreatePieceConfig("Rail Support (Legacy)", "Legacy solid-beam support retained for existing saves; new tracks include their own trestles.", RailwayIconKind.Support);
			val.Enabled = false;
			AddPieceOrThrow(new CustomPiece(obj, false, val));
		}

		private void RegisterRailVehicle(string prefabName, string displayName, string description, RailwayIconKind iconKind)
		{
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Expected O, but got Unknown
			GameObject obj = LoadPrefab(prefabName);
			PreparePiece(obj, (UsageTagFlags)12);
			TagSnapPoint(obj, "coupler_front");
			TagSnapPoint(obj, "coupler_rear");
			TagSnapPoint(obj, "snap_accessory_front");
			TagSnapPoint(obj, "snap_accessory_rear");
			TagSnapPoint(obj, "snap_accessory_left");
			TagSnapPoint(obj, "snap_accessory_right");
			TagSnapPointsWithPrefix(obj, "snap_grid_");
			TrainCar orAdd = GetOrAdd<TrainCar>(obj);
			Transform constructionOrigin = obj.transform.Find("build_origin");
			orAdd.ConfigureConstructionOrigin(constructionOrigin);
			GetOrAdd<RailPlatform>(obj);
			Rigidbody orAdd2 = GetOrAdd<Rigidbody>(obj);
			orAdd2.isKinematic = true;
			orAdd2.useGravity = false;
			orAdd2.interpolation = (RigidbodyInterpolation)1;
			orAdd2.collisionDetectionMode = (CollisionDetectionMode)3;
			GetOrAdd<TrainConsist>(obj);
			ZSyncTransform orAdd3 = GetOrAdd<ZSyncTransform>(obj);
			orAdd3.m_syncPosition = true;
			orAdd3.m_syncRotation = true;
			orAdd3.m_syncScale = false;
			orAdd3.m_syncBodyVelocity = false;
			orAdd3.m_characterParentSync = false;
			PieceConfig val = CreatePieceConfig(displayName, description, iconKind);
			AddPieceOrThrow(new CustomPiece(obj, false, val));
		}

		private void RegisterControlStand()
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			GameObject obj = LoadPrefab("VR_TrainControlStand");
			PreparePiece(obj, (UsageTagFlags)2048);
			TagSnapPoint(obj, "snap_base");
			GetOrAdd<TrainControlStand>(obj);
			PieceConfig val = CreatePieceConfig("Train Control Stand", "Onboard controls: E forward, Shift+E reverse, Alt+E speed, and Ctrl+E stop.", RailwayIconKind.ControlStand);
			AddPieceOrThrow(new CustomPiece(obj, false, val));
		}

		private void RegisterRailSwitch()
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			GameObject val = LoadPrefab("VR_RailSwitch");
			PreparePiece(val, (UsageTagFlags)2048);
			TagSnapPoint(val, "snap_junction");
			FindRequiredChild(val, "interaction_point");
			GetOrAdd<RailSwitch>(val).Configure(FindRequiredChild(val, "lever_pivot"), FindRequiredChild(val, "route_a_indicator"), FindRequiredChild(val, "route_b_indicator"));
			PieceConfig val2 = CreatePieceConfig("Rail Junction Switch", "Snap the junction marker onto a track end. Use the side lever to select Route A or B.", RailwayIconKind.RailSwitch);
			AddPieceOrThrow(new CustomPiece(val, false, val2));
		}

		private void RegisterDestinationDisplay()
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			GameObject obj = LoadPrefab("VR_TrainDestinationDisplay");
			PreparePiece(obj, (UsageTagFlags)2048);
			TagSnapPointsWithPrefix(obj, "snap_");
			GetOrAdd<TrainDestinationDisplay>(obj);
			PieceConfig val = CreatePieceConfig("Train Station Display - 2x2", "Mount on a train to show its named automatic-call destination and travel status. Manual driving has no selected destination.", RailwayIconKind.DestinationDisplay);
			AddPieceOrThrow(new CustomPiece(obj, false, val));
		}

		private void RegisterTrainDoor()
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			GameObject obj = LoadPrefab("VR_TrainDoor");
			PreparePiece(obj, (UsageTagFlags)262148);
			TagSnapPointsWithPrefix(obj, "snap_");
			Transform doorLeaf = FindRequiredChild(obj, "door_leaf");
			FindRequiredChild(obj, "interaction_anchor");
			GetOrAdd<TrainDoor>(obj).Configure(doorLeaf);
			PieceConfig val = CreatePieceConfig("Train Door 2x2", "A full-height carriage door. Press E to open or close it.", RailwayIconKind.Door);
			AddPieceOrThrow(new CustomPiece(obj, false, val));
		}

		private void RegisterTrainSeat()
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Expected O, but got Unknown
			GameObject obj = LoadPrefab("VR_TrainSeat");
			PreparePiece(obj, (UsageTagFlags)128);
			TagSnapPointsWithPrefix(obj, "snap_");
			Transform attachPoint = FindRequiredChild(obj, "seat_anchor");
			FindRequiredChild(obj, "interaction_anchor");
			Chair orAdd = GetOrAdd<Chair>(obj);
			orAdd.m_name = "Train Seat";
			orAdd.m_useDistance = 2f;
			orAdd.m_attachPoint = attachPoint;
			orAdd.m_detachOffset = new Vector3(0f, 0.5f, 0.65f);
			orAdd.m_attachAnimation = "attach_chair";
			orAdd.m_inShip = false;
			PieceConfig val = CreatePieceConfig("Train Seat", "A compact, functional passenger seat for a carriage.", RailwayIconKind.Seat);
			AddPieceOrThrow(new CustomPiece(obj, false, val));
		}

		private void RegisterTrainLamp(string prefabName, string displayName, string description, bool exterior, RailwayIconKind iconKind)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			GameObject obj = LoadPrefab(prefabName);
			PreparePiece(obj, (UsageTagFlags)256);
			TagSnapPointsWithPrefix(obj, "snap_");
			Transform lightAnchor = FindRequiredChild(obj, "light_anchor");
			FindRequiredChild(obj, "interaction_anchor");
			GetOrAdd<TrainLamp>(obj).Configure(exterior, lightAnchor);
			PieceConfig val = CreatePieceConfig(displayName, description, iconKind);
			AddPieceOrThrow(new CustomPiece(obj, false, val));
		}

		private void RegisterTrainBuildingPart(string prefabName, string displayName, string description, RailwayIconKind iconKind)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Expected O, but got Unknown
			GameObject val = LoadPrefab(prefabName);
			PreparePiece(val, (UsageTagFlags)(4 | (iconKind switch
			{
				RailwayIconKind.Floor => 8, 
				RailwayIconKind.Ladder => 8, 
				RailwayIconKind.BoardingLadder => 8, 
				RailwayIconKind.Wall => 16, 
				RailwayIconKind.WindowWall => 16, 
				RailwayIconKind.WindowWallTall => 16, 
				RailwayIconKind.WindowWallPanoramic => 16, 
				RailwayIconKind.Roof => 32, 
				_ => throw new ArgumentOutOfRangeException("iconKind", iconKind, "Unknown carriage panel role."), 
			})));
			if (iconKind == RailwayIconKind.Ladder || iconKind == RailwayIconKind.BoardingLadder)
			{
				GetOrAdd<TrainLadder>(val);
			}
			if (iconKind == RailwayIconKind.BoardingLadder)
			{
				GetOrAdd<TrainBoardingLadder>(val);
			}
			TagSnapPointsWithPrefix(val, "snap_");
			PieceConfig val2 = CreatePieceConfig(displayName, description, iconKind);
			AddPieceOrThrow(new CustomPiece(val, false, val2));
		}

		private GameObject LoadPrefab(string prefabName)
		{
			string text = "Assets/ValheimRailway/Generated/Prefabs/" + prefabName + ".prefab";
			GameObject obj = _bundle.LoadAsset<GameObject>(text);
			if ((Object)(object)obj == (Object)null)
			{
				throw new InvalidOperationException("AssetBundle is missing required prefab '" + text + "'.");
			}
			return obj;
		}

		private static AssetBundle LoadEmbeddedBundle()
		{
			using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("valheimrailwayassets") ?? throw new InvalidOperationException("Embedded asset bundle 'valheimrailwayassets' was not found.");
			using MemoryStream memoryStream = new MemoryStream();
			stream.CopyTo(memoryStream);
			return AssetBundle.LoadFromMemory(memoryStream.ToArray()) ?? throw new InvalidOperationException("Embedded asset bundle 'valheimrailwayassets' could not be loaded.");
		}

		private static void PreparePiece(GameObject prefab, UsageTagFlags usage = (UsageTagFlags)2048)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			int num = LayerMask.NameToLayer("piece");
			if (num >= 0)
			{
				prefab.layer = num;
				Collider[] componentsInChildren = prefab.GetComponentsInChildren<Collider>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					((Component)componentsInChildren[i]).gameObject.layer = num;
				}
			}
			ZNetView orAdd = GetOrAdd<ZNetView>(prefab);
			orAdd.m_persistent = true;
			orAdd.m_distant = false;
			orAdd.m_type = (ObjectType)2;
			Piece orAdd2 = GetOrAdd<Piece>(prefab);
			orAdd2.m_canBeRemoved = true;
			orAdd2.m_canRotate = true;
			orAdd2.m_noClipping = true;
			orAdd2.m_groundOnly = false;
			orAdd2.m_usage = (UsageTagFlags)(0x800 | usage);
			WearNTear orAdd3 = GetOrAdd<WearNTear>(prefab);
			orAdd3.m_noRoofWear = false;
			orAdd3.m_noSupportWear = false;
			orAdd3.m_ashDamageImmune = true;
			orAdd3.m_supports = true;
			orAdd3.m_staticPosition = false;
			orAdd3.m_burnable = false;
			GetOrAdd<RailwayProtectedPiece>(prefab);
		}

		private static PieceConfig CreatePieceConfig(string displayName, string description, RailwayIconKind iconKind = RailwayIconKind.TrackStraight)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: 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_0013: 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_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			PieceConfig val = new PieceConfig
			{
				Name = displayName,
				Description = description,
				PieceTable = "Hammer",
				Category = "Misc",
				Enabled = true,
				Icon = CreatePrototypeIcon(displayName, iconKind)
			};
			val.AddRequirement("Wood", 1, true);
			return val;
		}

		private static Sprite CreatePrototypeIcon(string name, RailwayIconKind iconKind)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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_002c: Expected O, but got Unknown
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0408: Unknown result type (might be due to invalid IL or missing references)
			//IL_0417: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			//IL_0334: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false)
			{
				name = name + "_IconTexture",
				filterMode = (FilterMode)0,
				hideFlags = (HideFlags)61
			};
			Color[] pixels = (Color[])(object)new Color[4096];
			Color color = ((iconKind <= RailwayIconKind.TrackStation) ? new Color(0.1f, 0.08f, 0.06f, 1f) : new Color(0.055f, 0.07f, 0.09f, 1f));
			Fill(pixels, color);
			DrawRect(pixels, 64, 1, 1, 62, 62, new Color(0.58f, 0.64f, 0.69f, 1f), fill: false, 2);
			switch (iconKind)
			{
			case RailwayIconKind.TrackCurve:
				DrawCurveTrackIcon(pixels, 64);
				break;
			case RailwayIconKind.TrackFlexible:
				DrawFlexibleTrackIcon(pixels, 64);
				break;
			case RailwayIconKind.TrackIncline15:
				DrawInclineTrackIcon(pixels, 64, steep: false);
				break;
			case RailwayIconKind.TrackIncline30:
				DrawInclineTrackIcon(pixels, 64, steep: true);
				break;
			case RailwayIconKind.TrackStation:
				DrawStationTrackIcon(pixels, 64);
				break;
			case RailwayIconKind.RailSwitch:
				DrawRailSwitchIcon(pixels, 64);
				break;
			case RailwayIconKind.TrackEntry:
			case RailwayIconKind.TrackExit:
			case RailwayIconKind.TrackGrade:
				DrawTransitionIcon(pixels, 64, iconKind);
				break;
			case RailwayIconKind.Ladder:
			{
				DrawLine(pixels, 64, 15, 10, 30, 54, new Color(0.75f, 0.48f, 0.2f), 4);
				DrawLine(pixels, 64, 34, 10, 49, 54, new Color(0.75f, 0.48f, 0.2f), 4);
				for (int k = 0; k < 5; k++)
				{
					DrawLine(pixels, 64, 18 + k * 3, 17 + k * 8, 37 + k * 3, 17 + k * 8, new Color(0.9f, 0.72f, 0.4f), 3);
				}
				break;
			}
			case RailwayIconKind.DestinationDisplay:
			{
				DrawRect(pixels, 64, 10, 10, 54, 54, new Color(0.64f, 0.39f, 0.15f), fill: true);
				DrawRect(pixels, 64, 14, 15, 50, 49, new Color(0.015f, 0.04f, 0.05f), fill: true);
				for (int j = 0; j < 3; j++)
				{
					DrawLine(pixels, 64, 19, 24 + j * 8, 45, 24 + j * 8, new Color(0.4f, 0.95f, 0.73f), 2);
				}
				break;
			}
			case RailwayIconKind.BoardingLadder:
			{
				DrawLine(pixels, 64, 20, 8, 20, 56, new Color(0.75f, 0.48f, 0.2f), 4);
				DrawLine(pixels, 64, 43, 8, 43, 56, new Color(0.75f, 0.48f, 0.2f), 4);
				for (int i = 0; i < 6; i++)
				{
					DrawLine(pixels, 64, 21, 12 + i * 7, 42, 12 + i * 7, new Color(0.9f, 0.72f, 0.4f), 3);
				}
				DrawLine(pixels, 64, 14, 51, 50, 51, new Color(0.32f, 0.42f, 0.45f), 4);
				break;
			}
			case RailwayIconKind.Support:
				DrawSupportIcon(pixels, 64);
				break;
			case RailwayIconKind.Platform:
				DrawPlatformIcon(pixels, 64, compact: false);
				break;
			case RailwayIconKind.Cart:
				DrawPlatformIcon(pixels, 64, compact: true);
				break;
			case RailwayIconKind.Floor:
				DrawFloorIcon(pixels, 64);
				break;
			case RailwayIconKind.Wall:
				DrawWallIcon(pixels, 64);
				break;
			case RailwayIconKind.Roof:
				DrawRoofIcon(pixels, 64);
				break;
			case RailwayIconKind.ControlStand:
				DrawControlStandIcon(pixels, 64);
				break;
			case RailwayIconKind.WindowWall:
				DrawWindowWallIcon(pixels, 64);
				break;
			case RailwayIconKind.WindowWallTall:
				DrawContinuousWindowWallIcon(pixels, 64, panoramic: false);
				break;
			case RailwayIconKind.WindowWallPanoramic:
				DrawContinuousWindowWallIcon(pixels, 64, panoramic: true);
				break;
			case RailwayIconKind.Door:
				DrawDoorIcon(pixels, 64);
				break;
			case RailwayIconKind.Seat:
				DrawSeatIcon(pixels, 64);
				break;
			case RailwayIconKind.InteriorLamp:
				DrawLampIcon(pixels, 64, exterior: false);
				break;
			case RailwayIconKind.ExteriorLamp:
				DrawLampIcon(pixels, 64, exterior: true);
				break;
			default:
				DrawTrackIcon(pixels, 64);
				break;
			}
			val.SetPixels(pixels);
			val.Apply(false, true);
			Sprite obj = Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 64f);
			((Object)obj).name = name + "_Icon";
			((Object)obj).hideFlags = (HideFlags)61;
			return obj;
		}

		private static void DrawRailSwitchIcon(Color[] pixels, int size)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: 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_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			Color color = default(Color);
			((Color)(ref color))..ctor(0.72f, 0.77f, 0.8f);
			Color color2 = default(Color);
			((Color)(ref color2))..ctor(0.36f, 0.72f, 1f);
			Color color3 = default(Color);
			((Color)(ref color3))..ctor(1f, 0.68f, 0.2f);
			DrawLine(pixels, size, 24, 9, 24, 29, color, 4);
			DrawLine(pixels, size, 24, 29, 11, 51, color2, 4);
			DrawLine(pixels, size, 24, 29, 38, 51, color3, 4);
			DrawLine(pixels, size, 8, 45, 11, 53, color2, 3);
			DrawLine(pixels, size, 11, 53, 18, 50, color2, 3);
			DrawLine(pixels, size, 31, 50, 38, 53, color3, 3);
			DrawLine(pixels, size, 38, 53, 41, 45, color3, 3);
			DrawRect(pixels, size, 43, 10, 57, 15, new Color(0.57f, 0.34f, 0.16f), fill: true);
			DrawLine(pixels, size, 50, 15, 45, 34, color, 4);
			DrawCircle(pixels, size, 45, 35, 4, color3);
		}

		private static void DrawTrackIcon(Color[] pixels, int size)
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			Color color = default(Color);
			((Color)(ref color))..ctor(0.7f, 0.74f, 0.78f, 1f);
			Color color2 = default(Color);
			((Color)(ref color2))..ctor(0.42f, 0.25f, 0.12f, 1f);
			for (int i = 12; i <= 51; i++)
			{
				if (i % 9 <= 2)
				{
					DrawRect(pixels, size, 10, i, 53, i + 2, color2, fill: true);
				}
			}
			DrawRect(pixels, size, 19, 7, 23, 56, color, fill: true);
			DrawRect(pixels, size, 40, 7, 44, 56, color, fill: true);
		}

		private static void DrawTransitionIcon(Color[] pixels, int size, RailwayIconKind kind)
		{
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			Color color = default(Color);
			((Color)(ref color))..ctor(0.75f, 0.81f, 0.85f);
			for (int i = 1; i <= 40; i++)
			{
				float num = (float)(i - 1) / 40f;
				float num2 = (float)i / 40f;
				float num3 = kind switch
				{
					RailwayIconKind.TrackExit => 2f * num - num * num, 
					RailwayIconKind.TrackEntry => num * num, 
					_ => num, 
				};
				float num4 = kind switch
				{
					RailwayIconKind.TrackExit => 2f * num2 - num2 * num2, 
					RailwayIconKind.TrackEntry => num2 * num2, 
					_ => num2, 
				};
				DrawLine(pixels, size, 12 + i - 1, 17 + Mathf.RoundToInt(28f * num3), 12 + i, 17 + Mathf.RoundToInt(28f * num4), color, 3);
				if (i % 8 == 0)
				{
					DrawLine(pixels, size, 12 + i, 11, 12 + i, 16 + Mathf.RoundToInt(28f * num4), new Color(0.42f, 0.29f, 0.18f), 2);
				}
			}
		}

		private static void DrawCurveTrackIcon(Color[] pixels, int size)
		{
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			Color color = default(Color);
			((Color)(ref color))..ctor(0.72f, 0.77f, 0.82f, 1f);
			Color color2 = default(Color);
			((Color)(ref color2))..ctor(0.52f, 0.3f, 0.13f, 1f);
			for (int i = 5; i <= 85; i += 8)
			{
				float num = (float)i * ((float)Math.PI / 180f);
				int x = 7 + Mathf.RoundToInt(Mathf.Cos(num) * 25f);
				int y = 7 + Mathf.RoundToInt(Mathf.Sin(num) * 25f);
				int x2 = 7 + Mathf.RoundToInt(Mathf.Cos(num) * 40f);
				int y2 = 7 + Mathf.RoundToInt(Mathf.Sin(num) * 40f);
				DrawLine(pixels, size, x, y, x2, y2, color2, 3);
			}
			DrawArc(pixels, size, 7, 7, 27, 3f, 88f, color, 4);
			DrawArc(pixels, size, 7, 7, 38, 3f, 88f, color, 4);
		}

		private static void DrawFlexibleTrackIcon(Color[] pixels, int size)
		{
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			Color color = default(Color);
			((Color)(ref color))..ctor(0.92f, 0.61f, 0.23f, 1f);
			Color color2 = default(Color);
			((Color)(ref color2))..ctor(0.48f, 0.29f, 0.14f, 1f);
			Vector2Int val = default(Vector2Int);
			((Vector2Int)(ref val))..ctor(20, 6);
			Vector2Int val2 = default(Vector2Int);
			((Vector2Int)(ref val2))..ctor(34, 6);
			Vector2Int val3 = default(Vector2Int);
			Vector2Int val4 = default(Vector2Int);
			for (int i = 1; i <= 24; i++)
			{
				float num = (float)i / 24f;
				int num2 = Mathf.RoundToInt(27f + Mathf.Sin(num * (float)Math.PI * 2f) * 9f);
				int num3 = Mathf.RoundToInt(6f + num * 51f);
				((Vector2Int)(ref val3))..ctor(num2 - 7, num3);
				((Vector2Int)(ref val4))..ctor(num2 + 7, num3);
				DrawLine(pixels, size, ((Vector2Int)(ref val)).x, ((Vector2Int)(ref val)).y, ((Vector2Int)(ref val3)).x, ((Vector2Int)(ref val3)).y, color, 3);
				DrawLine(pixels, size, ((Vector2Int)(ref val2)).x, ((Vector2Int)(ref val2)).y, ((Vector2Int)(ref val4)).x, ((Vector2Int)(ref val4)).y, color, 3);
				if (i % 4 == 0)
				{
					DrawLine(pixels, size, ((Vector2Int)(ref val3)).x - 2, num3, ((Vector2Int)(ref val4)).x + 2, num3, color2, 3);
				}
				val = val3;
				val2 = val4;
			}
		}

		private static void DrawInclineTrackIcon(Color[] pixels, int size, bool steep)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			Color color = (steep ? new Color(0.95f, 0.48f, 0.22f, 1f) : new Color(0.88f, 0.76f, 0.3f, 1f));
			Color color2 = default(Color);
			((Color)(ref color2))..ctor(0.45f, 0.28f, 0.14f, 1f);
			int num = 13;
			int num2 = (steep ? 52 : 37);
			DrawLine(pixels, size, 6, num, 57, num2, color, 4);
			DrawLine(pixels, size, 6, num + 7, 57, num2 + 7, color, 3);
			for (int i = 12; i <= 52; i += 10)
			{
				float num3 = (float)(i - 6) / 51f;
				int num4 = Mathf.RoundToInt(Mathf.Lerp((float)num, (float)num2, num3));
				DrawLine(pixels, size, i, num4 + 5, i, 7, color2, 3);
			}
			DrawLine(pixels, size, 5, 7, 58, 7, color2, 3);
		}

		private static void DrawStationTrackIcon(Color[] pixels, int size)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			DrawTrackIcon(pixels, size);
			Color color = default(Color);
			((Color)(ref color))..ctor(0.35f, 0.43f, 0.5f, 1f);
			Color color2 = default(Color);
			((Color)(ref color2))..ctor(1f, 0.28f, 0.18f, 1f);
			DrawRect(pixels, size, 48, 8, 57, 55, color, fill: true);
			DrawRect(pixels, size, 49, 27, 60, 35, color2, fill: true);
			DrawLine(pixels, size, 53, 27, 53, 14, color2, 3);
		}

		private static void DrawSupportIcon(Color[] pixels, int size)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			Color color = default(Color);
			((Color)(ref color))..ctor(0.63f, 0.39f, 0.18f, 1f);
			Color color2 = default(Color);
			((Color)(ref color2))..ctor(0.8f, 0.58f, 0.29f, 1f);
			DrawRect(pixels, size, 7, 47, 57, 53, color, fill: true);
			DrawLine(pixels, size, 13, 46, 25, 9, color, 5);
			DrawLine(pixels, size, 51, 46, 39, 9, color, 5);
			DrawLine(pixels, size, 20, 30, 44, 30, color2, 4);
			DrawLine(pixels, size, 20, 30, 42, 12, color2, 3);
			DrawLine(pixels, size, 44, 30, 22, 12, color2, 3);
		}

		private static void DrawPlatformIcon(Color[] pixels, int size, bool compact)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			Color color = (compact ? new Color(0.72f, 0.38f, 0.16f, 1f) : new Color(0.5f, 0.31f, 0.16f, 1f));
			Color color2 = default(Color);
			((Color)(ref color2))..ctor(0.78f, 0.8f, 0.8f, 1f);
			Color color3 = default(Color);
			((Color)(ref color3))..ctor(0.12f, 0.14f, 0.16f, 1f);
			int num = (compact ? 14 : 6);
			int num2 = (compact ? 50 : 58);
			int num3 = (compact ? 22 : 15);
			int num4 = (compact ? 44 : 49);
			DrawRect(pixels, size, num, num3, num2, num4, color2, fill: true);
			DrawRect(pixels, size, num + 4, num3 + 4, num2 - 4, num4 - 4, color, fill: true);
			DrawLine(pixels, size, (num + num2) / 2, num3 + 4, (num + num2) / 2, num4 - 4, color2, 2);
			DrawLine(pixels, size, num + 4, (num3 + num4) / 2, num2 - 4, (num3 + num4) / 2, color2, 2);
			DrawCircle(pixels, size, num + 7, num3 - 3, 4, color3);
			DrawCircle(pixels, size, num2 - 7, num3 - 3, 4, color3);
			DrawCircle(pixels, size, num + 7, num4 + 3, 4, color3);
			DrawCircle(pixels, size, num2 - 7, num4 + 3, 4, color3);
		}

		private static void DrawFloorIcon(Color[] pixels, int size)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: 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)
			Color color = default(Color);
			((Color)(ref color))..ctor(0.62f, 0.38f, 0.18f, 1f);
			Color color2 = default(Color);
			((Color)(ref color2))..ctor(0.85f, 0.63f, 0.31f, 1f);
			DrawRect(pixels, size, 8, 8, 55, 55, color, fill: true);
			DrawRect(pixels, size, 8, 8, 55, 55, color2, fill: false, 4);
			for (int i = 18; i <= 48; i += 10)
			{
				DrawLine(pixels, size, i, 11, i, 52, color2, 2);
			}
		}

		private static void DrawWallIcon(Color[] pixels, int size)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			Color color = default(Color);
			((Color)(ref color))..ctor(0.57f, 0.3f, 0.15f, 1f);
			Color color2 = default(Color);
			((Color)(ref color2))..ctor(0.83f, 0.57f, 0.29f, 1f);
			DrawRect(pixels, size, 9, 7, 54, 56, color, fill: true);
			DrawRect(pixels, size, 9, 7, 54, 56, color2, fill: false, 4);
			for (int i = 18; i <= 45; i += 9)
			{
				DrawLine(pixels, size, 13, i, 50, i, color2, 2);
			}
			DrawLine(pixels, size, 13, 10, 50, 53, color2, 3);
		}

		private static void DrawRoofIcon(Color[] pixels, int size)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			Color color = default(Color);
			((Color)(ref color))..ctor(0.32f, 0.48f, 0.6f, 1f);
			Color color2 = default(Color);
			((Color)(ref color2))..ctor(0.72f, 0.82f, 0.87f, 1f);
			for (int i = 0; i <= 22; i++)
			{
				DrawLine(pixels, size, 7 + i, 12 + i, 56 - i, 12 + i, color, 2);
			}
			DrawLine(pixels, size, 7, 12, 31, 55, color2, 4);
			DrawLine(pixels, size, 56, 12, 31, 55, color2, 4);
			DrawLine(pixels, size, 7, 12, 56, 12, color2, 3);
		}

		private static void DrawControlStandIcon(Color[] pixels, int size)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: 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_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			Color color = default(Color);
			((Color)(ref color))..ctor(0.54f, 0.62f, 0.68f, 1f);
			Color color2 = default(Color);
			((Color)(ref color2))..ctor(0.2f, 0.27f, 0.31f, 1f);
			Color color3 = default(Color);
			((Color)(ref color3))..ctor(0.91f, 0.24f, 0.17f, 1f);
			DrawRect(pixels, size, 16, 8, 48, 35, color, fill: true);
			DrawRect(pixels, size, 20, 12, 44, 31, color2, fill: true);
			DrawLine(pixels, size, 19, 8, 12, 52, color, 5);
			DrawLine(pixels, size, 45, 8, 52, 52, color, 5);
			DrawLine(pixels, size, 32, 28, 39, 46, color, 4);
			DrawCircle(pixels, size, 41, 49, 5, color3);
			DrawCircle(pixels, size, 27, 22, 3, new Color(0.25f, 0.92f, 0.46f, 1f));
		}

		private static void DrawWindowWallIcon(Color[] pixels, int size)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			Color color = default(Color);
			((Color)(ref color))..ctor(0.7f, 0.4f, 0.18f, 1f);
			Color color2 = default(Color);
			((Color)(ref color2))..ctor(0.2f, 0.6f, 0.82f, 1f);
			Color color3 = default(Color);
			((Color)(ref color3))..ctor(0.69f, 0.9f, 1f, 1f);
			DrawRect(pixels, size, 8, 10, 55, 53, color, fill: false, 5);
			DrawRect(pixels, size, 14, 16, 49, 46, color2, fill: true);
			DrawRect(pixels, size, 29, 14, 34, 49, color, fill: true);
			DrawRect(pixels, size, 12, 29, 51, 34, color, fill: true);
			DrawLine(pixels, size, 17, 43, 28, 35, color3, 2);
			DrawLine(pixels, size, 36, 26, 46, 18, color3, 2);
		}

		private static void DrawContinuousWindowWallIcon(Color[] pixels, int size, bool panoramic)
		{
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			Color color = default(Color);
			((Color)(ref color))..ctor(0.7f, 0.4f, 0.18f, 1f);
			Color color2 = default(Color);
			((Color)(ref color2))..ctor(0.89f, 0.66f, 0.36f, 1f);
			Color color3 = default(Color);
			((Color)(ref color3))..ctor(0.18f, 0.54f, 0.72f, 1f);
			Color color4 = default(Color);
			((Color)(ref color4))..ctor(0.69f, 0.9f, 1f, 1f);
			int num = (panoramic ? 8 : 20);
			int num2 = (panoramic ? 55 : 43);
			DrawRect(pixels, size, num, 8, num2, 55, color, fill: true);
			DrawRect(pixels, size, num + 3, 13, num2 - 3, 52, color3, fill: true);
			DrawLine(pixels, size, num, 55, num2, 55, color2, 1);
			DrawLine(pixels, size, num + 5, 43, num2 - 5, 33, color4, 2);
			DrawLine(pixels, size, num + 5, 36, num2 - 5, 26, color4, 1);
			DrawLine(pixels, size, num - 3, 31, num - 1, 31, color2, 1);
			DrawLine(pixels, size, num2 + 1, 31, num2 + 3, 31, color2, 1);
			if (panoramic)
			{
				DrawLine(pixels, size, 31, 5, 31, 7, color2, 1);
				DrawLine(pixels, size, 31, 56, 31, 58, color2, 1);
			}
		}

		private static void DrawDoorIcon(Color[] pixels, int size)
		{
			//IL_0075: 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_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			Color color = default(Color);
			((Color)(ref color))..ctor(0.82f, 0.55f, 0.27f, 1f);
			Color color2 = default(Color);
			((Color)(ref color2))..ctor(0.49f, 0.18f, 0.12f, 1f);
			Color color3 = default(Color);
			((Color)(ref color3))..ctor(0.67f, 0.28f, 0.17f, 1f);
			Color color4 = default(Color);
			((Color)(ref color4))..ctor(1f, 0.82f, 0.24f, 1f);
			DrawRect(pixels, size, 16, 7, 48, 56, color, fill: true);
			DrawRect(pixels, size, 21, 11, 44, 53, color2, fill: true);
			DrawRect(pixels, size, 25, 16, 40, 31, color3, fill: false, 2);
			DrawRect(pixels, size, 25, 36, 40, 49, color3, fill: false, 2);
			DrawCircle(pixels, size, 39, 34, 3, color4);
		}

		private static void DrawSeatIcon(Color[] pixels, int size)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			Color color = default(Color);
			((Color)(ref color))..ctor(0.73f, 0.76f, 0.78f, 1f);
			Color color2 = default(Color);
			((Color)(ref color2))..ctor(0.2f, 0.68f, 0.43f, 1f);
			Color color3 = default(Color);
			((Color)(ref color3))..ctor(0.47f, 0.92f, 0.65f, 1f);
			DrawRect(pixels, size, 14, 25, 25, 53, color2, fill: true);
			DrawRect(pixels, size, 20, 21, 48, 32, color2, fill: true);
			DrawRect(pixels, size, 17, 28, 20, 49, color3, fill: true);
			DrawLine(pixels, size, 25, 23, 18, 8, color, 4);
			DrawLine(pixels, size, 45, 23, 49, 8, color, 4);
			DrawLine(pixels, size, 15, 23, 10, 10, color, 3);
		}

		private static void DrawLampIcon(Color[] pixels, int size, bool exterior)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: 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_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			Color color = default(Color);
			((Color)(ref color))..ctor(0.68f, 0.73f, 0.78f, 1f);
			Color color2 = (exterior ? new Color(0.42f, 0.78f, 1f, 1f) : new Color(1f, 0.68f, 0.19f, 1f));
			Color color3 = (exterior ? new Color(0.84f, 0.95f, 1f, 1f) : new Color(1f, 0.94f, 0.58f, 1f));
			if (exterior)
			{
				DrawRect(pixels, size, 10, 13, 16, 51, color, fill: true);
				DrawLine(pixels, size, 14, 44, 31, 38, color, 4);
				DrawRect(pixels, size, 27, 31, 43, 42, color, fill: true);
				DrawCircle(pixels, size, 37, 30, 8, color3);
				DrawLine(pixels, size, 34, 19, 27, 7, color2, 3);
				DrawLine(pixels, size, 40, 19, 47, 7, color2, 3);
				DrawLine(pixels, size, 46, 25, 57, 20, color2, 3);
			}
			else
			{
				DrawRect(pixels, size, 30, 44, 34, 56, color, fill: true);
				DrawLine(pixels, size, 22, 39, 42, 39, color, 4);
				DrawLine(pixels, size, 22, 39, 27, 31, color, 4);
				DrawLine(pixels, size, 42, 39, 37, 31, color, 4);
				DrawCircle(pixels, size, 32, 27, 8, color3);
				DrawLine(pixels, size, 19, 26, 8, 22, color2, 3);
				DrawLine(pixels, size, 45, 26, 56, 22, color2, 3);
				DrawLine(pixels, size, 23, 17, 16, 8, color2, 3);
				DrawLine(pixels, size, 41, 17, 48, 8, color2, 3);
			}
		}

		private static void DrawArc(Color[] pixels, int size, int centreX, int centreY, int radius, float startDegrees, float endDegrees, Color color, int thickness)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			int x = centreX + Mathf.RoundToInt(Mathf.Cos(startDegrees * ((float)Math.PI / 180f)) * (float)radius);
			int y = centreY + Mathf.RoundToInt(Mathf.Sin(startDegrees * ((float)Math.PI / 180f)) * (float)radius);
			for (float num = startDegrees + 2f; num <= endDegrees + 0.01f; num += 2f)
			{
				float num2 = num * ((float)Math.PI / 180f);
				int num3 = centreX + Mathf.RoundToInt(Mathf.Cos(num2) * (float)radius);
				int num4 = centreY + Mathf.RoundToInt(Mathf.Sin(num2) * (float)radius);
				DrawLine(pixels, size, x, y, num3, num4, color, thickness);
				x = num3;
				y = num4;
			}
		}

		private static void Fill(Color[] pixels, Color color)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < pixels.Length; i++)
			{
				pixels[i] = color;
			}
		}

		private static void DrawRect(Color[] pixels, int size, int x0, int y0, int x1, int y1, Color color, bool fill, int thickness = 1)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			for (int i = y0; i <= y1; i++)
			{
				for (int j = x0; j <= x1; j++)
				{
					if (fill || j < x0 + thickness || j > x1 - thickness || i < y0 + thickness || i > y1 - thickness)
					{
						SetPixel(pixels, size, j, i, color);
					}
				}
			}
		}

		private static void DrawLine(Color[] pixels, int size, int x0, int y0, int x1, int y1, Color color, int thickness)
		{
			//IL_001f: 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)
			int num = Math.Max(Math.Abs(x1 - x0), Math.Abs(y1 - y0));
			if (num == 0)
			{
				SetPixel(pixels, size, x0, y0, color);
				return;
			}
			for (int i = 0; i <= num; i++)
			{
				float num2 = (float)i / (float)num;
				int num3 = Mathf.RoundToInt(Mathf.Lerp((float)x0, (float)x1, num2));
				int num4 = Mathf.RoundToInt(Mathf.Lerp((float)y0, (float)y1, num2));
				int num5 = Math.Max(0, thickness / 2);
				for (int j = -num5; j <= num5; j++)
				{
					for (int k = -num5; k <= num5; k++)
					{
						SetPixel(pixels, size, num3 + k, num4 + j, color);
					}
				}
			}
		}

		private static void DrawCircle(Color[] pixels, int size, int centreX, int centreY, int radius, Color color)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			int num = radius * radius;
			for (int i = -radius; i <= radius; i++)
			{
				for (int j = -radius; j <= radius; j++)
				{
					if (j * j + i * i <= num)
					{
						SetPixel(pixels, size, centreX + j, centreY + i, color);
					}
				}
			}
		}

		private static void SetPixel(Color[] pixels, int size, int x, int y, Color color)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if (x >= 0 && x < size && y >= 0 && y < size)
			{
				pixels[y * size + x] = color;
			}
		}

		private static Transform FindRequiredChild(GameObject prefab, string childName)
		{
			Transform obj = prefab.transform.Find(childName);
			if ((Object)(object)obj == (Object)null)
			{
				throw new InvalidOperationException(((Object)prefab).name + " is missing required child '" + childName + "'.");
			}
			return obj;
		}

		private static void TagSnapPoint(GameObject prefab, string childName)
		{
			Transform obj = prefab.transform.Find(childName);
			if ((Object)(object)obj == (Object)null)
			{
				throw new InvalidOperationException(((Object)prefab).name + " is missing required snap point '" + childName + "'.");
			}
			((Component)obj).gameObject.tag = "snappoint";
		}

		private static void TagSnapPointsWithPrefix(GameObject prefab, string childNamePrefix)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			foreach (Transform item in prefab.transform)
			{
				Transform val = item;
				if (((Object)val).name.StartsWith(childNamePrefix, StringComparison.Ordinal))
				{
					((Component)val).gameObject.tag = "snappoint";
				}
			}
		}

		private static T GetOrAdd<T>(GameObject gameObject) where T : Component
		{
			return gameObject.GetComponent<T>() ?? gameObject.AddComponent<T>();
		}

		private static void AddPieceOrThrow(CustomPiece piece)
		{
			if (!PieceManager.Instance.AddPiece(piece))
			{
				GameObject piecePrefab = piece.PiecePrefab;
				throw new InvalidOperationException("Jotunn rejected custom piece '" + (((piecePrefab != null) ? ((Object)piecePrefab).name : null) ?? "<unknown>") + "'.");
			}
		}
	}
	internal sealed class RailwayConsoleCommand : ConsoleCommand
	{
		private const string CommandName = "vr_train";

		private const float DefaultDepartureThrottle = 0.25f;

		public override string Name => "vr_train";

		public override string Help => "Controls the nearest train: vr_train <status|snap|go [-2..2]|speed -2..2|forward [0..2]|reverse [0..2]|stop|couple|help> (1=100%, 2=200%)";

		public override List<string> CommandOptionList()
		{
			return new List<string>
			{
				"status", "snap", "go", "start", "speed", "forward", "reverse", "stop", "brake", "couple",
				"help"
			};
		}

		public override void Run(string[] args)
		{
			Execute(args, null);
		}

		public override void Run(string[] args, Terminal context)
		{
			Execute(args, context);
		}

		private static void Execute(string[] args, Terminal? context)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_039e: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				Reply(context, "vr_train requires a local player.", warning: true);
				return;
			}
			TrainConsist trainConsist = TrainRegistry.FindNearest(((Component)localPlayer).transform.position);
			if ((Object)(object)trainConsist == (Object)null)
			{
				Reply(context, "No active rail platform was found.", warning: true);
				return;
			}
			int num = ((args.Length != 0 && string.Equals(args[0], "vr_train", StringComparison.OrdinalIgnoreCase)) ? 1 : 0);
			string text = ((args.Length > num) ? args[num].ToLowerInvariant() : "status");
			switch (text)
			{
			case "snap":
				Reply(context, trainConsist.SnapToNearestTrack(6f) ? "Nearest platform snapped to track." : "No track was close enough.");
				break;
			case "start":
			case "go":
			{
				if (!trainConsist.HasTrack)
				{
					Reply(context, "Platform is not attached to a rail; use vr_train snap first.", warning: true);
					break;
				}
				float throttle3 = 0.25f;
				int num4 = num + 1;
				if (args.Length > num4 && !TryReadSignedThrottle(args[num4], out throttle3))
				{
					Reply(context, "Usage: vr_train go [-2..2] (1=100%, 2=200%)", warning: true);
					break;
				}
				trainConsist.SetThrottle(throttle3);
				Reply(context, $"Train departing at throttle {throttle3:0.00}.");
				break;
			}
			case "speed":
			{
				if (!trainConsist.HasTrack)
				{
					Reply(context, "Platform is not attached to a rail; use vr_train snap first.", warning: true);
					break;
				}
				int num3 = num + 1;
				if (args.Length <= num3 || !TryReadSignedThrottle(args[num3], out var throttle2))
				{
					Reply(context, "Usage: vr_train speed <-2..2> (1=100%, 2=200%)", warning: true);
					break;
				}
				trainConsist.SetThrottle(throttle2);
				Reply(context, $"Train throttle set to {throttle2:0.00}.");
				break;
			}
			case "forward":
			case "reverse":
			{
				if (!trainConsist.HasTrack)
				{
					Reply(context, "Platform is not attached to a rail; use vr_train snap first.", warning: true);
					break;
				}
				float magnitude = 0.25f;
				int num2 = num + 1;
				if (args.Length > num2 && !TryReadMagnitude(args[num2], out magnitude))
				{
					Reply(context, "Usage: vr_train " + text + " [0..2] (1=100%, 2=200%)", warning: true);
					break;
				}
				float throttle = ((text == "reverse") ? (0f - magnitude) : magnitude);
				trainConsist.SetThrottle(throttle);
				Reply(context, $"Train departing {text} at throttle {magnitude:0.00}.");
				break;
			}
			case "stop":
			case "brake":
				trainConsist.EmergencyStop();
				Reply(context, "Train stopped.");
				break;
			case "couple":
			{
				TrainConsist trainConsist2 = TrainRegistry.FindNearest(((Component)trainConsist).transform.position, trainConsist);
				if ((Object)(object)trainConsist2 == (Object)null)
				{
					Reply(context, "No second active platform was found.", warning: true);
					break;
				}
				if (trainConsist.TryCouple(trainConsist2, out string reason))
				{
					Reply(context, reason);
					break;
				}
				string text2 = reason;
				if (trainConsist2.TryCouple(trainConsist, out reason))
				{
					Reply(context, reason);
				}
				else
				{
					Reply(context, "Coupling failed in either direction. Nearest-first: " + text2 + " Opposite order: " + reason, warning: true);
				}
				break;
			}
			case "help":
				Reply(context, "vr_train status | snap | go [-2..2] | speed <-2..2> | forward [0..2] | reverse [0..2] | stop | couple. 1=100%, 1.5=150%, 2=200% ultra-fast. Negative throttle moves backward without turning the train. Station-stop rails brake in either direction; command a direction to depart again.");
				break;
			case "status":
				Reply(context, $"Nearest platform: track={trainConsist.HasTrack}, speed={trainConsist.Speed:0.00} m/s, " + $"requested={trainConsist.RequestedThrottle * 100f:0}% (200% maximum), " + $"mounted pieces={trainConsist.LeaderCar.MountedPieceCount}/{128}.");
				break;
			default:
				Reply(context, "Unknown train command '" + text + "'. Use vr_train help.", warning: true);
				break;
			}
		}

		private static bool TryReadSignedThrottle(string value, out float throttle)
		{
			return TrainSpeed.TryParseThrottle(value, out throttle);
		}

		private static bool TryReadThrottle(string value, out float throttle)
		{
			return TryReadSignedThrottle(value, out throttle);
		}

		private static bool TryReadMagnitude(string value, out float magnitude)
		{
			if (!TryReadSignedThrottle(value, out magnitude))
			{
				return false;
			}
			return magnitude >= 0f;
		}

		private static void Reply(Terminal? context, string message, bool warning = false)
		{
			if (warning)
			{
				RailwayLog.Warning(message);
			}
			else
			{
				RailwayLog.Info(message);
			}
			if (context != null)
			{
				context.AddString(message);
			}
		}
	}
	internal static class RailwayLog
	{
		private static ManualLogSource? _source;

		public static void Initialize(ManualLogSource source)
		{
			_source = source;
		}

		public static void Info(object message)
		{
			ManualLogSource? source = _source;
			if (source != null)
			{
				source.LogInfo(message);
			}
		}

		public static void Warning(object message)
		{
			ManualLogSource? source = _source;
			if (source != null)
			{
				source.LogWarning(message);
			}
		}

		public static void Error(object message)
		{
			ManualLogSource? source = _source;
			if (source != null)
			{
				source.LogError(message);
			}
		}
	}
}
namespace ValheimRailway.Trains
{
	[HarmonyPatch(typeof(ZNet), "Awake")]
	internal static class MountedChildAbsenceProtocol
	{
		private readonly struct MountTuple : IEquatable<MountTuple>
		{
			private ZDOID ParentId { get; }

			private ZDOID ChildId { get; }

			internal MountTuple(ZDOID parentId, ZDOID childId)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				ParentId = parentId;
				ChildId = childId;
			}

			public bool Equals(MountTuple other)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				if (ParentId == other.ParentId)
				{
					return ChildId == other.ChildId;
				}
				return false;
			}

			public override bool Equals(object? obj)
			{
				if (obj is MountTuple other)
				{
					return Equals(other);
				}
				return false;
			}

			public override int GetHashCode()
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				return (((object)ParentId/*cast due to .constrained prefix*/).GetHashCode() * 397) ^ ((object)ChildId/*cast due to .constrained prefix*/).GetHashCode();
			}
		}

		private const string RequestRpc = "ValheimRailway_MountedChildAbsentRequest_v1";

		private const string ResponseRpc = "ValheimRailway_MountedChildAbsentResponse_v1";

		private const float RequestRetryInterval = 1f;

		private const float AuthorizationLifetime = 10f;

		private static readonly Dictionary<MountTuple, float> LastRequestAt = new Dictionary<MountTuple, float>();

		private static readonly Dictionary<MountTuple, float> Authorizations = new Dictionary<MountTuple, float>();

		private static ZRoutedRpc? _registeredRpc;

		[HarmonyPostfix]
		private static void RegisterForWorld()
		{
			EnsureRegistered();
		}

		internal static void RequestConfirmation(ZDOID parentId, ZDOID childId)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			if (!((ZDOID)(ref parentId)).IsNone() && !((ZDOID)(ref childId)).IsNone() && !((Object)(object)ZNet.instance == (Object)null) && !ZNet.instance.IsServer() && EnsureRegistered())
			{
				MountTuple key = new MountTuple(parentId, childId);
				float realtimeSinceStartup = Time.realtimeSinceStartup;
				if (!LastRequestAt.TryGetValue(key, out var value) || !(realtimeSinceStartup - value < 1f))
				{
					LastRequestAt[key] = realtimeSinceStartup;
					ZRoutedRpc.instance.InvokeRoutedRPC("ValheimRailway_MountedChildAbsentRequest_v1", new object[2] { parentId, childId });
				}
			}
		}

		internal static bool ConsumeConfirmation(ZDOID parentId, ZDOID childId)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			if (((ZDOID)(ref parentId)).IsNone() || ((ZDOID)(ref childId)).IsNone() || (Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsServer() || !EnsureRegistered())
			{
				return false;
			}
			MountTuple key = new MountTuple(parentId, childId);
			if (!Authorizations.TryGetValue(key, out var value))
			{
				return false;
			}
			Authorizations.Remove(key);
			LastRequestAt.Remove(key);
			return Time.realtimeSinceStartup <= value;
		}

		internal static void Forget(ZDOID parentId, ZDOID childId)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			MountTuple key = new MountTuple(parentId, childId);
			LastRequestAt.Remove(key);
			Authorizations.Remove(key);
		}

		private static bool EnsureRegistered()
		{
			ZRoutedRpc instance = ZRoutedRpc.instance;
			if (instance == null)
			{
				return false;
			}
			if (_registeredRpc == instance)
			{
				return true;
			}
			LastRequestAt.Clear();
			Authorizations.Clear();
			instance.Register<ZDOID, ZDOID>("ValheimRailway_MountedChildAbsentRequest_v1", (Action<long, ZDOID, ZDOID>)HandleRequest);
			instance.Register<ZDOID, ZDOID>("ValheimRailway_MountedChildAbsentResponse_v1", (Action<long, ZDOID, ZDOID>)HandleResponse);
			_registeredRpc = instance;
			return true;
		}

		private static void HandleRequest(long sender, ZDOID parentId, ZDOID childId)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: 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)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			ZNet instance = ZNet.instance;
			ZDOMan instance2 = ZDOMan.instance;
			ZRoutedRpc instance3 = ZRoutedRpc.instance;
			if (!((Object)(object)instance == (Object)null) && instance2 != null && instance3 != null && instance.IsServer() && !((ZDOID)(ref parentId)).IsNone() && !((ZDOID)(ref childId)).IsNone() && !(parentId == childId) && instance.GetPeer(sender) != null)
			{
				ZDO zDO = instance2.GetZDO(parentId);
				if (zDO != null && zDO.GetOwner() == sender && TrainCar.HasPersistedMountedChild(zDO, childId) && instance2.GetZDO(childId) == null)
				{
					instance3.InvokeRoutedRPC(sender, "ValheimRailway_MountedChildAbsentResponse_v1", new object[2] { parentId, childId });
				}
			}
		}

		private static void HandleResponse(long sender, ZDOID parentId, ZDOID childId)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: 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)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			ZNet instance = ZNet.instance;
			ZDOMan instance2 = ZDOMan.instance;
			if (!((Object)(object)instance == (Object)null) && instance2 != null && !instance.IsServer() && !((ZDOID)(ref parentId)).IsNone() && !((ZDOID)(ref childId)).IsNone())
			{
				ZNetPeer serverPeer = instance.GetServerPeer();
				ZDO zDO = instance2.GetZDO(parentId);
				if (serverPeer != null && serverPeer.m_uid == sender && zDO != null && zDO.IsOwner() && TrainCar.HasPersistedMountedChild(zDO, childId) && instance2.GetZDO(childId) == null)
				{
					Authorizations[new MountTuple(parentId, childId)] = Time.realtimeSinceStartup + 10f;
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class RailMotionPatches
	{
		private static readonly FieldRef<Character, float> GroundForceTimer = AccessTools.FieldRefAccess<Character, float>("m_groundForceTimer");

		private static readonly FieldRef<Character, Rigidbody> LastGroundBody = AccessTools.FieldRefAccess<Character, Rigidbody>("m_lastGroundBody");

		private static readonly FieldRef<Character, Rigidbody> CharacterBody = AccessTools.FieldRefAccess<Character, Rigidbody>("m_body");

		private static readonly FieldRef<Character, CapsuleCollider> CharacterCollider = AccessTools.FieldRefAccess<Character, CapsuleCollider>("m_collider");

		private static readonly FieldRef<Character, bool> CharacterSlipping = AccessTools.FieldRefAccess<Character, bool>("m_slipping");

		private static Player? _rider;

		private static RailPlatform? _anchorPlatform;

		private static Vector3 _idleLocalAnchor;

		private static bool _hasIdleAnchor;

		private static readonly RaycastHit[] AdjacentGroundHits = (RaycastHit[])(object)new RaycastHit[16];

		private static Player? _frictionRider;

		private static PhysicsMaterial? _riderMaterial;

		private static float _originalStaticFriction;

		private static float _originalDynamicFriction;

		private static PhysicsMaterialCombine _originalFrictionCombine;

		private static Player? _airRider;

		private static RailPlatform? _airPlatform;

		private static Vector3 _previousCarrierVelocity;

		private static Vector3 _airCarrierVelocity;

		private static Vector3 _airVelocityDelta;

		private static Vector3 _previousRiderPosition;

		private static float _lastSupportTime;

		private static bool _airFrameActive;

		private static Vector3 _previousGroundCarrierPosition;

		private static Quaternion _previousGroundCarrierRotation;

		private static Vector3 _groundClampCorrection;

		private static Rigidbody? _continuousBody;

		private static CollisionDetectionMode _originalCollisionMode;

		[HarmonyPatch(typeof(Character), "UpdateBodyFriction")]
		[HarmonyPrefix]
		private static void RestoreVanillaFrictionBeforeUpdate(Character __instance)
		{
			if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				Player val = (Player)(object)((__instance is Player) ? __instance : null);
				if (val != null && ((Object)(object)_airPlatform == (Object)null || !((Character)val).IsOwner() || ((Character)val).IsAttached() || ((Character)val).IsDead() || ((Character)val).IsSwimming() || ((Character)val).IsDebugFlying()))
				{
					RestoreContinuousCollision();
				}
			}
			if ((Object)(object)__instance == (Object)(object)_frictionRider)
			{
				RestoreRiderFriction();
			}
		}

		[HarmonyPatch(typeof(Character), "OnDestroy")]
		[HarmonyPrefix]
		private static void ReleaseRiderBeforeDestroy(Character __instance)
		{
			if ((Object)(object)__instance == (Object)(object)_frictionRider)
			{
				RestoreRiderFriction();
			}
			if ((Object)(object)__instance == (Object)(object)_rider)
			{
				ClearAnchor();
			}
			if ((Object)(object)__instance == (Object)(object)_airRider)
			{
				ClearAirSupport();
			}
			if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				RestoreContinuousCollision();
			}
		}

		[HarmonyPatch(typeof(Character), "UpdateWalking")]
		[HarmonyPrefix]
		private static void PrepareAirborneRailMotion(Character __instance, float dt)
		{
			//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_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if (val == null)
			{
				return;
			}
			_airFrameActive = false;
			_groundClampCorrection = Vector3.zero;
			if (!((Character)val).IsOwner() || ((Character)val).IsAttached() || ((Character)val).IsDead() || ((Character)val).IsDebugFlying() || ((Character)val).IsSwimming() || GroundForceTimer.Invoke((Character)(object)val) > 0f)
			{
				ClearAirSupport();
				RestoreContinuousCollision();
			}
			else
			{
				if (((Character)val).IsOnGround())
				{
					return;
				}
				Rigidbody val2 = CharacterBody.Invoke((Character)(object)val);
				if (!((Object)(object)val2 == (Object)null) && !val2.isKinematic && !((Object)(object)_airRider != (Object)(object)val) && !((Object)(object)_airPlatform == (Object)null) && !(Time.fixedTime - _lastSupportTime > 4f))
				{
					Vector3 val3 = val2.position - _previousRiderPosition;
					if (!(((Vector3)(ref val3)).sqrMagnitude > 9f) && HasAirborneSupportBelow(_airPlatform, val, val2.position) && _airPlatform.TryGetGroundVelocity(val2.position, out var velocity) && RailRiderMotionPolicy.CanFollowCarrierChange(_previousCarrierVelocity, velocity, dt))
					{
						_airCarrierVelocity = _previousCarrierVelocity;
						_airVelocityDelta = velocity - _previousCarrierVelocity;
						_previousCarrierVelocity = velocity;
						_previousRiderPosition = val2.position;
						_airFrameActive = true;
						UseContinuousCollision(val2);
						return;
					}
				}
				ClearAirSupport();
				RestoreContinuousCollision();
			}
		}

		[HarmonyPatch(typeof(Character), "UpdateWalking")]
		[HarmonyPostfix]
		private static void FinishAirborneRailMotion(Character __instance)
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if (val != null)
			{
				Rigidbody val2 = CharacterBody.Invoke((Character)(object)val);
				if ((Object)(object)val2 != (Object)null && !val2.isKinematic && ((Character)val).IsOwner() && !((Character)val).IsAttached() && ((Character)val).IsOnGround() && !CharacterSlipping.Invoke((Character)(object)val) && GroundForceTimer.Invoke((Character)(object)val) <= 0f && ((Vector3)(ref _groundClampCorrection)).sqrMagnitude > 0f)
				{
					val2.AddForce(_groundClampCorrection, (ForceMode)2);
				}
				_groundClampCorrection = Vector3.zero;
				if (_airFrameActive && (Object)(object)val2 != (Object)null && !val2.isKinematic && ((Character)val).IsOwner() && !((Character)val).IsAttached())
				{
					val2.linearVelocity += _airVelocityDelta;
				}
				_airFrameActive = false;
			}
		}

		[HarmonyPatch(typeof(Character), "ApplyGroundForce")]
		[HarmonyPostfix]
		private static void StabilizeRailwayRider(Character __instance, ref Vector3 vel, Vector3 targetVel)
		{
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_0282: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_029e: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0310: Unknown result type (might be due to invalid IL or missing references)
			//IL_032b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0330: Unknown result type (might be due to invalid IL or missing references)
			//IL_0335: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_034b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0351: Unknown result type (might be due to invalid IL or missing references)
			//IL_0356: Unknown result type (might be due to invalid IL or missing references)
			//IL_035b: Unknown result type (might be due to invalid IL or missing references)
			//IL_035d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0364: Unknown result type (might be due to invalid IL or missing references)
			//IL_0369: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if (val == null)
			{
				return;
			}
			if (_airFrameActive && !((Character)val).IsOnGround())
			{
				vel.x += _airCarrierVelocity.x;
				vel.z += _airCarrierVelocity.z;
				ClearAnchor();
				RestoreRiderFriction();
				return;
			}
			if (!((Character)val).IsOwner() || !((Character)val).IsOnGround() || ((Character)val).IsAttached() || ((Character)val).IsDead() || ((Character)val).IsDebugFlying() || ((Character)val).IsSwimming() || GroundForceTimer.Invoke((Character)(object)val) > 0f)
			{
				ClearAnchor();
				RestoreRiderFriction();
				if (((Character)val).IsOnGround() || ((Character)val).IsAttached() || ((Character)val).IsDebugFlying() || ((Character)val).IsDead() || ((Character)val).IsSwimming() || !((Character)val).IsOwner())
				{
					ClearAirSupport();
				}
				return;
			}
			RailPlatform railPlatform = RailPlatform.ResolveGroundPlatform(((Character)val).GetLastGroundCollider());
			Rigidbody val2 = CharacterBody.Invoke((Character)(object)val);
			if ((Object)(object)railPlatform == (Object)null || (Object)(object)val2 == (Object)null)
			{
				ClearAnchor();
				ClearAirSupport();
				RestoreRiderFriction();
				return;
			}
			if (!StillStandingOnPlatform(railPlatform, val, val2.position, out var supportNormal, out var supportGap))
			{
				ClearAnchor();
				ClearAirSupport();
				RestoreRiderFriction();
				return;
			}
			if (!railPlatform.TryGetGroundVelocity(val2.position, out var velocity))
			{
				ClearAnchor();
				ClearAirSupport();
				RestoreRiderFriction();
				return;
			}
			railPlatform.GetPhysicsPose(out var position, out var rotation);
			Vector3 previousCarrierVelocity = _previousCarrierVelocity;
			int num;
			if ((Object)(object)_airRider == (Object)(object)val && (Object)(object)_airPlatform == (Object)(object)railPlatform && Time.fixedTime - _lastSupportTime > 0f && Time.fixedTime - _lastSupportTime <= Time.fixedDeltaTime * 1.5f)
			{
				Vector3 val3 = position - _previousGroundCarrierPosition;
				if (((Vector3)(ref val3)).sqrMagnitude <= 0.5625f)
				{
					num = ((Quaternion.Angle(rotation, _previousGroundCarrierRotation) <= 15f) ? 1 : 0);
					goto IL_01e5;
				}
			}
			num = 0;
			goto IL_01e5;
			IL_01e5:
			_previousGroundCarrierPosition = position;
			_previousGroundCarrierRotation = rotation;
			_airRider = val;
			_airPlatform = railPlatform;
			_previousCarrierVelocity = velocity;
			_previousRiderPosition = val2.position;
			_lastSupportTime = Time.fixedTime;
			UseContinuousCollision(val2);
			Rigidbody val4 = LastGroundBody.Invoke((Character)(object)val);
			if ((Object)(object)val4 != (Object)null)
			{
				Vector3 pointVelocity = val4.GetPointVelocity(((Component)val).transform.position);
				pointVelocity.y = 0f;
				vel -= pointVelocity;
			}
			vel.y = ((supportNormal.y > 0.25f) ? ((0f - (supportNormal.x * vel.x + supportNormal.z * vel.z)) / supportNormal.y) : targetVel.y);
			vel += velocity;
			vel += GetIdleCorrection(val, railPlatform, val2.position, targetVel, supportNormal);
			float num2 = Mathf.Max(0f, supportGap) * supportNormal.y;
			float num3 = Mathf.Max(0.04f, Time.fixedDeltaTime * 2f);
			vel -= supportNormal * Mathf.Clamp(0.25f + num2 / num3, 0.25f, 2.5f);
			if (num != 0 && !CharacterSlipping.Invoke((Character)(object)val))
			{
				_groundClampCorrection = RailRiderMotionPolicy.GroundedCarrierClampCorrection(vel - val2.linearVelocity, previousCarrierVelocity, velocity, Time.fixedDeltaTime);
			}
			UseRailwayRelativeFriction(val);
		}

		private static void UseRailwayRelativeFriction(Player player)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			Capsul