Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of RailroadsAutomation v0.3.2
plugins/RailroadsAutomation/RailroadsAutomation.dll
Decompiled 2 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyVersion("0.0.0.0")] namespace RailroadsAutomation; [Serializable] public sealed class Pier { public V Foot; public V Origin; public double Step; public double Radius; public int Blocks; public int Stone; [JsonIgnore] public V Top => Foot + new V(0.0, Step * (double)Blocks, 0.0); } internal static class BridgeRules { internal static bool Elevated(double deck, double ground, double water, double threshold) { if (!(ground < water - 0.5)) { return deck - ground > threshold; } return true; } internal static double Guide(double reference, double ground, double water, double bed, double threshold) { if (!Elevated(reference - bed, ground, water, threshold)) { return ground + bed; } return reference; } internal static V Nearest(V point, V[] path) { double num = double.PositiveInfinity; V result = path[0]; for (int i = 1; i < path.Length; i++) { V v = path[i] - path[i - 1]; double num2 = v.x * v.x + v.z * v.z; double num3 = ((num2 < 1E-10) ? 0.0 : Math.Max(0.0, Math.Min(1.0, ((point.x - path[i - 1].x) * v.x + (point.z - path[i - 1].z) * v.z) / num2))); V v2 = path[i - 1] + v * num3; double num4 = (point.x - v2.x) * (point.x - v2.x) + (point.z - v2.z) * (point.z - v2.z); if (num4 < num) { num = num4; result = v2; } } return result; } internal static List<Pier> Plan(V[] path, Func<V, double> ground, double water, double bed, double threshold, double maximum, double blockHeight, V offset, double radius, int stone) { List<Pier> list = new List<Pier>(); double num = 0.0; for (int i = 1; i < path.Length; i++) { num += (path[i] - path[i - 1]).Length; } int num2 = Math.Max(1, (int)Math.Ceiling(num / 8.0)); for (int j = 0; j < num2; j++) { double num3 = num * ((double)j + 0.5) / (double)num2; V v = path[0]; for (int k = 1; k < path.Length; k++) { double length = (path[k] - path[k - 1]).Length; if (num3 <= length || k == path.Length - 1) { v = path[k - 1] + (path[k] - path[k - 1]) * ((length < 1E-10) ? 0.0 : Math.Min(1.0, num3 / length)); break; } num3 -= length; } double num4 = ground(v); double num5 = v.y - bed; if (!Elevated(num5, num4, water, threshold)) { continue; } double num6 = num4; double[] array = new double[3] { 0.0 - radius, 0.0, radius }; foreach (double a in array) { double[] array2 = new double[3] { 0.0 - radius, 0.0, radius }; foreach (double c in array2) { num6 = Math.Min(num6, ground(v + new V(a, 0.0, c))); } } double num7 = num5 - num6; if (num7 > maximum + 0.001) { throw new InvalidOperationException(L.Key("raa_bridge_depth")); } int num8 = Math.Max(1, (int)Math.Ceiling((num7 + 0.15) / blockHeight)); V v2 = new V(v.x, num5 - (double)num8 * blockHeight, v.z); list.Add(new Pier { Foot = v2, Origin = v2 + offset, Blocks = num8, Step = blockHeight, Radius = radius, Stone = stone }); } return list; } internal static int StoneCost(IList<Pier> piers) { int num = 0; if (piers != null) { foreach (Pier pier in piers) { num = checked(num + pier.Blocks * pier.Stone); } } return num; } internal static bool Valid(Pier p) { if (p != null && p.Foot.Finite && p.Origin.Finite && p.Step >= 0.5 && p.Step <= 4.0 && p.Radius >= 0.1 && p.Radius <= 3.0 && p.Blocks >= 1 && p.Blocks <= 256 && p.Step * (double)p.Blocks <= 132.0 && p.Stone >= 1 && p.Stone <= 1000) { return (p.Origin - p.Foot).Length <= 10.0; } return false; } internal static V[] Clearance(IList<Pier> piers) { List<V> list = new List<V>(); if (piers != null) { foreach (Pier pier in piers) { int num = (int)Math.Ceiling(pier.Step * (double)pier.Blocks / 0.5); for (int i = 0; i <= num; i++) { list.Add(pier.Foot + (pier.Top - pier.Foot) * ((double)i / (double)num)); } } } return list.ToArray(); } } internal static class BridgeWorks { internal const string Prefab = "stone_pillar"; private static readonly int Part = StringExtensionMethods.GetStableHashCode("local.raa.pier"); private static double height; private static double radius; private static V offset; private static int stone; internal static bool IsPier(ZDO zdo) { if (zdo.GetPrefab() == StringExtensionMethods.GetStableHashCode("stone_pillar") && zdo.GetInt(Part, -1) >= 0) { return !string.IsNullOrEmpty(zdo.GetString(Keys.JobTag, "")); } return false; } internal static void Ready() { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_0263: 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_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: 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_00f1: 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_0186: 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_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) GameObject prefab = ZNetScene.instance.GetPrefab("stone_pillar"); if (Object.op_Implicit((Object)(object)prefab) && Object.op_Implicit((Object)(object)prefab.GetComponent<ZNetView>()) && Object.op_Implicit((Object)(object)prefab.GetComponent<WearNTear>()) && Object.op_Implicit((Object)(object)prefab.GetComponent<Piece>())) { Vector3 val = prefab.transform.localScale - Vector3.one; if (!(((Vector3)(ref val)).sqrMagnitude > 0.0001f)) { bool flag = false; Bounds val2 = default(Bounds); Collider[] componentsInChildren = prefab.GetComponentsInChildren<Collider>(); Bounds bounds = default(Bounds); foreach (Collider val3 in componentsInChildren) { if (val3.isTrigger) { continue; } BoxCollider val4 = (BoxCollider)(object)((val3 is BoxCollider) ? val3 : null); MeshCollider val5 = (MeshCollider)(object)((val3 is MeshCollider) ? val3 : null); if (Object.op_Implicit((Object)(object)val4)) { ((Bounds)(ref bounds))..ctor(val4.center, val4.size); } else { if (!Object.op_Implicit((Object)(object)val5) || !Object.op_Implicit((Object)(object)val5.sharedMesh)) { throw new InvalidOperationException(L.Key("raa_bridge_prefab")); } bounds = val5.sharedMesh.bounds; } Matrix4x4 val6 = prefab.transform.worldToLocalMatrix * ((Component)val3).transform.localToWorldMatrix; int[] array = new int[2] { -1, 1 }; foreach (int num in array) { int[] array2 = new int[2] { -1, 1 }; foreach (int num2 in array2) { int[] array3 = new int[2] { -1, 1 }; foreach (int num3 in array3) { Vector3 val7 = ((Matrix4x4)(ref val6)).MultiplyPoint3x4(((Bounds)(ref bounds)).center + Vector3.Scale(((Bounds)(ref bounds)).extents, new Vector3((float)num, (float)num2, (float)num3))); if (!flag) { ((Bounds)(ref val2))..ctor(val7, Vector3.zero); flag = true; } else { ((Bounds)(ref val2)).Encapsulate(val7); } } } } } height = ((Bounds)(ref val2)).size.y; radius = Math.Max(((Bounds)(ref val2)).extents.x, ((Bounds)(ref val2)).extents.z); offset = new V(0f - ((Bounds)(ref val2)).center.x, 0f - ((Bounds)(ref val2)).min.y, 0f - ((Bounds)(ref val2)).center.z); Requirement[] array4 = prefab.GetComponent<Piece>().m_resources.Where((Requirement r) => Object.op_Implicit((Object)(object)r.m_resItem) && r.m_amount > 0).ToArray(); if (!flag || array4.Length != 1 || ((Object)((Component)array4[0].m_resItem).gameObject).name != "Stone" || height < 0.5 || height > 4.0 || radius < 0.1 || radius > 3.0) { throw new InvalidOperationException(L.Key("raa_bridge_prefab")); } stone = array4[0].m_amount; return; } } throw new InvalidOperationException(L.Key("raa_bridge_prefab")); } internal static void Plan(List<Segment> route, Ground ground) { if (!Plugin.Bridges.Value) { return; } Ready(); foreach (Segment item in route) { item.Piers = BridgeRules.Plan(RailBridge.Points(item).ToArray(), ground.Height, ZoneSystem.instance.m_waterLevel, RailBridge.BedOffset, Plugin.BridgeThreshold.Value, Plugin.MaxPierHeight.Value, height, offset, radius, stone); } } internal static void Validate(Segment step, Ground ground) { if (step.Piers == null) { return; } if (step.Piers.Count > 0 && !Plugin.Bridges.Value) { throw new InvalidOperationException(L.Key("raa_bridge_changed")); } foreach (Pier pier in step.Piers) { if (!BridgeRules.Valid(pier)) { throw new InvalidOperationException(L.Key("raa_bridge_prefab")); } double[] array = new double[3] { 0.0 - pier.Radius, 0.0, pier.Radius }; foreach (double a in array) { double[] array2 = new double[3] { 0.0 - pier.Radius, 0.0, pier.Radius }; foreach (double c in array2) { double num = ground.Height(pier.Foot + new V(a, 0.0, c)); if (num < pier.Foot.y - 0.05 || num > pier.Top.y - 0.1) { throw new InvalidOperationException(L.Key("raa_bridge_changed")); } } } } } internal static void Create(Segment step, Job job, long creator) { //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0190: 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_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) if (step.Piers == null || step.Piers.Count == 0) { return; } GameObject prefab = ZNetScene.instance.GetPrefab("stone_pillar"); if (!Object.op_Implicit((Object)(object)prefab)) { throw new InvalidOperationException(L.Key("raa_bridge_prefab")); } ZNetView component = prefab.GetComponent<ZNetView>(); WearNTear component2 = prefab.GetComponent<WearNTear>(); ZDO[] source = RailBridge.All.Where((ZDO z) => z.GetPrefab() == StringExtensionMethods.GetStableHashCode("stone_pillar") && z.GetString(Keys.JobTag, "") == job.Id && z.GetInt(Keys.Index, -1) == job.Index).ToArray(); for (int num = 0; num < step.Piers.Count; num++) { for (int num2 = 0; num2 < step.Piers[num].Blocks; num2++) { int part = num * 256 + num2; V v = step.Piers[num].Origin + new V(0.0, step.Piers[num].Step * (double)num2, 0.0); ZDO[] array = source.Where((ZDO z) => z.GetInt(Part, -1) == part).ToArray(); if (array.Length > 1 || (array.Length == 1 && ((RailBridge.V3(array[0].GetPosition()) - v).Length > 0.02 || (double)Quaternion.Angle(array[0].GetRotation(), Quaternion.identity) > 0.1))) { throw new InvalidOperationException(L.Key("raa_bridge_identity")); } if (array.Length != 1) { ZDO obj = ZDOMan.instance.CreateNewZDO(RailBridge.U(v), StringExtensionMethods.GetStableHashCode("stone_pillar")); obj.Persistent = true; obj.Type = component.m_type; obj.Distant = component.m_distant; obj.SetPrefab(StringExtensionMethods.GetStableHashCode("stone_pillar")); obj.SetRotation(Quaternion.identity); obj.Set(ZDOVars.s_creator, creator); obj.Set(Keys.JobTag, job.Id); obj.Set(Keys.Index, job.Index, false); obj.Set(Part, part, false); obj.Set(ZDOVars.s_health, component2.m_health); obj.Set(ZDOVars.s_support, 1000f); } } } } } internal sealed class Ground { internal sealed class Region { internal Vector3 Center; internal Heightmap Loaded; internal ZDO Zdo; internal byte[] Before; internal TerrainData Data; internal HMBuildData Base; internal double[] Current; internal byte[] Protection; internal bool Changed; } private readonly Dictionary<Vector2s, Region> regions = new Dictionary<Vector2s, Region>(); private readonly Dictionary<Vector2s, List<ZDO>> compilers; private readonly List<Tuple<Vector3, float>> legacy = new List<Tuple<Vector3, float>>(); private readonly TrackCorridor existingRails; private readonly List<StructureBox> stations = new List<StructureBox>(); internal readonly Heightmap Template; internal readonly int Width; internal readonly int Pitch; internal readonly float Scale; internal Ground() { //IL_01d6: Unknown result type (might be due to invalid IL or missing references) existingRails = new TrackCorridor(RailBridge.Tracks.SelectMany(delegate(ZDO z) { GameObject prefab2 = ZNetScene.instance.GetPrefab(z.GetPrefab()); return (!Object.op_Implicit((Object)(object)prefab2)) ? Enumerable.Empty<V[]>() : RailBridge.WorldLines(prefab2, z); }), (double)Plugin.BedHalfWidth.Value + 0.5); Template = ZoneSystem.instance.m_zonePrefab.GetComponentInChildren<Heightmap>(); Width = Template.m_width; Scale = Template.m_scale; Pitch = Width + 1; if (Math.Abs((float)Width * Scale - ZoneSystem.instance.m_zoneSize) > 0.01f) { throw new InvalidOperationException(L.Key("raa_earthworks_001")); } int hash = StringExtensionMethods.GetStableHashCode(((Object)Template.m_terrainCompilerPrefab).name); compilers = (from z in RailBridge.All where z.GetPrefab() == hash group z by ZoneSystem.GetZone(z.GetPosition())).ToDictionary((IGrouping<Vector2s, ZDO> g) => g.Key, (IGrouping<Vector2s, ZDO> g) => g.ToList()); foreach (ZDO item in RailBridge.All) { GameObject prefab = ZNetScene.instance.GetPrefab(item.GetPrefab()); TerrainModifier val = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponent<TerrainModifier>() : null); if (Object.op_Implicit((Object)(object)val)) { legacy.Add(Tuple.Create<Vector3, float>(item.GetPosition(), val.GetRadius())); } if (Object.op_Implicit((Object)(object)prefab) && RailBridge.IsStation(prefab)) { stations.AddRange(RailBridge.StationBoxes(prefab, item)); } } } internal Region Get(Vector2s zone) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_0327: Unknown result type (might be due to invalid IL or missing references) if (regions.TryGetValue(zone, out var r)) { return r; } r = new Region { Center = ZoneSystem.GetZonePos(zone) }; if (compilers.TryGetValue(zone, out var value)) { if (value.Count != 1) { throw new InvalidOperationException(L.Key("raa_earthworks_002")); } r.Zdo = value[0]; } Region region = r; ZDO zdo = r.Zdo; region.Before = ((zdo != null) ? zdo.GetByteArray(ZDOVars.s_TCData, (byte[])null) : null); r.Data = TerrainData.Read((r.Before == null) ? null : Utils.Decompress(r.Before), Pitch * Pitch); r.Loaded = Heightmap.FindHeightmap(r.Center); if (Object.op_Implicit((Object)(object)r.Loaded) && Vector3.Distance(((Component)r.Loaded).transform.position, r.Center) > 0.01f) { r.Loaded = null; } if (!Object.op_Implicit((Object)(object)r.Loaded) && legacy.Any((Tuple<Vector3, float> m) => (double)Math.Abs(m.Item1.x - r.Center.x) <= (double)((float)Width * Scale) * 0.5 + (double)m.Item2 && (double)Math.Abs(m.Item1.z - r.Center.z) <= (double)((float)Width * Scale) * 0.5 + (double)m.Item2)) { throw new InvalidOperationException(L.Key("raa_earthworks_003")); } TerrainComp val = (Object.op_Implicit((Object)(object)r.Loaded) ? TerrainComp.FindTerrainCompiler(r.Center) : null); if (Object.op_Implicit((Object)(object)val)) { Earthworks.ReloadCompiler.Invoke(val, null); } if (Object.op_Implicit((Object)(object)r.Loaded)) { r.Loaded.Regenerate(); } r.Base = HeightmapBuilder.instance.RequestTerrainSync(r.Center, Width, Scale, false, WorldGenerator.instance); r.Current = new double[Pitch * Pitch]; r.Protection = new byte[Pitch * Pitch]; for (int num = 0; num < Pitch; num++) { for (int num2 = 0; num2 < Pitch; num2++) { int num3 = num * Pitch + num2; r.Current[num3] = r.Center.y + (Object.op_Implicit((Object)(object)r.Loaded) ? r.Loaded.GetHeight(num2, num) : (r.Base.m_baseHeights[num3] + Math.Max(-8f, Math.Min(8f, r.Data.Level[num3] + r.Data.Smooth[num3])))); } } regions[zone] = r; return r; } internal double Height(V point) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) Region region = Get(ZoneSystem.GetZone(RailBridge.U(point))); double num = (point.x - (double)region.Center.x) / (double)Scale + (double)Width * 0.5; double num2 = (point.z - (double)region.Center.z) / (double)Scale + (double)Width * 0.5; int num3 = Math.Max(0, Math.Min(Width - 1, (int)Math.Floor(num))); int num4 = Math.Max(0, Math.Min(Width - 1, (int)Math.Floor(num2))); double num5 = Math.Max(0.0, Math.Min(1.0, num - (double)num3)); double num6 = Math.Max(0.0, Math.Min(1.0, num2 - (double)num4)); return (Vertex(region, num3, num4) * (1.0 - num5) + Vertex(region, num3 + 1, num4) * num5) * (1.0 - num6) + (Vertex(region, num3, num4 + 1) * (1.0 - num5) + Vertex(region, num3 + 1, num4 + 1) * num5) * num6; } internal double Vertex(Region r, int x, int z) { return r.Current[z * Pitch + x]; } internal double Cost(V[] path) { if (Evaluate(path, path, write: false, requireKnown: false, out var _, out var cost) != null) { return double.PositiveInfinity; } return cost; } internal void Validate(V[] path, V[] profile) { List<Region> result; double cost; string text = Evaluate(path, profile, write: false, requireKnown: false, out result, out cost); if (text != null) { throw new InvalidOperationException(text); } } internal List<Region> Grade(V[] path, V[] profile) { List<Region> result; double cost; string text = Evaluate(path, profile, write: true, requireKnown: true, out result, out cost); if (text != null) { throw new InvalidOperationException(text); } return result; } private string Evaluate(V[] path, V[] profile, bool write, bool requireKnown, out List<Region> result, out double cost) { //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_0734: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_0720: Unknown result type (might be due to invalid IL or missing references) //IL_010b: 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_00f3: Unknown result type (might be due to invalid IL or missing references) result = new List<Region>(); cost = 0.0; int num = 0; double num2 = Plugin.BedHalfWidth.Value; double num3 = Plugin.ShoulderWidth.Value; double num4 = num2 + num3; V p = path.Aggregate((V a, V b) => new V(Math.Min(a.x, b.x), 0.0, Math.Min(a.z, b.z))) - new V(num4, 0.0, num4); V p2 = path.Aggregate((V a, V b) => new V(Math.Max(a.x, b.x), 0.0, Math.Max(a.z, b.z))) + new V(num4, 0.0, num4); Vector2s zone = ZoneSystem.GetZone(RailBridge.U(p)); Vector2s zone2 = ZoneSystem.GetZone(RailBridge.U(p2)); Vector2s val = default(Vector2s); for (int num5 = zone.y; num5 <= zone2.y; num5++) { for (int num6 = zone.x; num6 <= zone2.x; num6++) { ((Vector2s)(ref val))..ctor(num6, num5); if (requireKnown && !RailBridge.Generated(ZoneSystem.GetZonePos(val))) { return L.Key("raa_earthworks_004"); } Region region = Get(val); if (write && region.Zdo != null && region.Zdo.GetOwner() != 0L && !region.Zdo.IsOwner()) { return L.Key("raa_earthworks_005"); } int num7 = Math.Max(0, (int)Math.Ceiling((p.x - (double)region.Center.x) / (double)Scale + (double)Width * 0.5)); int num8 = Math.Min(Width, (int)Math.Floor((p2.x - (double)region.Center.x) / (double)Scale + (double)Width * 0.5)); int num9 = Math.Max(0, (int)Math.Ceiling((p.z - (double)region.Center.z) / (double)Scale + (double)Width * 0.5)); int num10 = Math.Min(Width, (int)Math.Floor((p2.z - (double)region.Center.z) / (double)Scale + (double)Width * 0.5)); for (int num11 = num9; num11 <= num10; num11++) { for (int num12 = num7; num12 <= num8; num12++) { V p3 = new V((double)region.Center.x + ((double)num12 - (double)Width * 0.5) * (double)Scale, 0.0, (double)region.Center.z + ((double)num11 - (double)Width * 0.5) * (double)Scale); if (!Grading.Project(p3, path, out var distance, out var height) || distance > num4) { continue; } int num13 = num11 * Pitch + num12; if (region.Protection[num13] == 0) { region.Protection[num13] = (byte)((!existingRails.ProtectsGround(p3) && !stations.Any((StructureBox box) => box.ProtectsGround(p3))) ? 1u : 2u); } if (region.Protection[num13] == 2) { continue; } double num14 = Vertex(region, num12, num11); Grading.Project(p3, profile, out var _, out height, extendEnds: true); double num15 = height - RailBridge.BedOffset; if (Plugin.Bridges.Value) { V point = BridgeRules.Nearest(p3, path); double num16 = Height(point); double num17 = ZoneSystem.instance.m_waterLevel; if (num16 < num17 - 0.5 && point.y < num17 + 0.8) { return L.Key("raa_bridge_water"); } if (BridgeRules.Elevated(point.y - RailBridge.BedOffset, num16, num17, Plugin.BridgeThreshold.Value)) { if (point.y - RailBridge.BedOffset - num16 > (double)Plugin.MaxPierHeight.Value) { return L.Key("raa_bridge_depth"); } if (num14 <= num15) { continue; } } } if (num14 < (double)ZoneSystem.instance.m_waterLevel - 0.5) { continue; } double target; double delta; switch (Grading.Evaluate(num14, num15, distance, num2, num3, region.Data.Level[num13], region.Data.Smooth[num13], Plugin.MaxEarthwork.Value, out target, out delta)) { case Grading.Limit.TooMuch: return L.Key("raa_earthworks_006") + Math.Round(p3.x) + ", " + Math.Round(p3.z) + L.Key("raa_earthworks_007") + Math.Round(Math.Abs(target - num14), 1) + L.Key("raa_earthworks_008") + Plugin.MaxEarthwork.Value + L.Key("raa_earthworks_009"); case Grading.Limit.NativeLimit: return L.Key("raa_earthworks_010") + Math.Round(p3.x) + ", " + Math.Round(p3.z) + L.Key("raa_earthworks_011"); case Grading.Limit.Outside: continue; } cost += (target - num14) * (target - num14); num++; if (write) { delta = Math.Max(-8.0, Math.Min(8.0, delta)); if (Math.Abs(target - num14) > 0.005) { region.Data.Level[num13] = (float)delta; region.Data.Smooth[num13] = 0f; region.Data.Modified[num13] = true; region.Changed = true; } if (distance <= num2 && (!region.Data.Painted[num13] || region.Data.Colors[num13][0] != 1f || region.Data.Colors[num13][1] != 0f || region.Data.Colors[num13][2] != 0f || region.Data.Colors[num13][3] != 1f)) { region.Data.Painted[num13] = true; region.Data.Colors[num13] = new float[4] { 1f, 0f, 0f, 1f }; region.Changed = true; } } } } if (region.Changed) { result.Add(region); } } } cost /= Math.Max(1, num); return null; } internal void Apply(List<Region> changes, V center) { //IL_0085: 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_0116: Unknown result type (might be due to invalid IL or missing references) //IL_014f: 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) foreach (Region change in changes) { if (change.Zdo != null && !Same(change.Before, change.Zdo.GetByteArray(ZDOVars.s_TCData, (byte[])null))) { throw new InvalidOperationException(L.Key("raa_earthworks_012")); } } foreach (Region change2 in changes) { TerrainComp val = (Object.op_Implicit((Object)(object)change2.Loaded) ? TerrainComp.FindTerrainCompiler(change2.Center) : null); if (change2.Zdo == null) { if (Object.op_Implicit((Object)(object)change2.Loaded)) { val = change2.Loaded.GetAndCreateTerrainCompiler(); change2.Zdo = ((Component)val).GetComponent<ZNetView>().GetZDO(); } else { GameObject terrainCompilerPrefab = Template.m_terrainCompilerPrefab; ZNetView component = terrainCompilerPrefab.GetComponent<ZNetView>(); change2.Zdo = ZDOMan.instance.CreateNewZDO(change2.Center, StringExtensionMethods.GetStableHashCode(((Object)terrainCompilerPrefab).name)); change2.Zdo.Persistent = true; change2.Zdo.Type = component.m_type; change2.Zdo.Distant = component.m_distant; change2.Zdo.SetPrefab(StringExtensionMethods.GetStableHashCode(((Object)terrainCompilerPrefab).name)); change2.Zdo.SetRotation(Quaternion.identity); } } if (change2.Zdo.GetOwner() == 0L) { change2.Zdo.SetOwner(ZNet.GetUID()); } if (!change2.Zdo.IsOwner()) { throw new InvalidOperationException(L.Key("raa_earthworks_013")); } change2.Data.Operations++; change2.Data.X = (float)center.x; change2.Data.Y = (float)center.y; change2.Data.Z = (float)center.z; change2.Data.Radius = 35f; change2.Zdo.Set(ZDOVars.s_TCData, Utils.Compress(change2.Data.Write())); if (Object.op_Implicit((Object)(object)val)) { Earthworks.ReloadCompiler.Invoke(val, null); } if (Object.op_Implicit((Object)(object)change2.Loaded)) { change2.Loaded.Regenerate(); } if (Object.op_Implicit((Object)(object)ClutterSystem.instance)) { ClutterSystem.instance.ResetGrass(change2.Center, (float)Width * Scale * 0.5f); } } } private static bool Same(byte[] a, byte[] b) { if (a != null) { if (b != null) { return a.SequenceEqual(b); } return false; } return b == null; } } internal static class Earthworks { private sealed class ClearAction { internal ZDO Zdo; internal Action Apply; } internal static readonly MethodInfo ReloadCompiler = AccessTools.Method(typeof(TerrainComp), "CheckLoad", (Type[])null, (Type[])null); private static readonly MethodInfo RockReload = AccessTools.Method(typeof(MineRock5), "CheckForUpdate", (Type[])null, (Type[])null); private static readonly MethodInfo OldRockReload = AccessTools.Method(typeof(MineRock), "UpdateVisability", (Type[])null, (Type[])null); internal static List<Segment> Plan(Goal start, List<Goal> goals) { //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.FollowTerrain.Value) { List<Segment> list = RoutePlanner.Plan(start.Position, start.Direction, goals, RailBridge.Primitives, Plugin.SearchNodes.Value, Plugin.MaxSegments.Value); ValidateRails(list); Ground ground = new Ground(); if (Plugin.Bridges.Value) { for (int i = 0; i < list.Count; i++) { ground.Validate(RailBridge.Points(list[i]).ToArray(), Profile(list, i)); } } BridgeWorks.Plan(list, ground); return list; } Ground ground2 = new Ground(); List<Goal> list2 = TerrainSearch.Goals(start, goals, ground2.Height, ZoneSystem.instance.m_waterLevel, RailBridge.BedOffset, Plugin.Bridges.Value, Plugin.BridgeThreshold.Value); Stopwatch watch = Stopwatch.StartNew(); SearchStats stats = new SearchStats(); Func<Segment, double> terrainCost = delegate(Segment step) { if (watch.Elapsed.TotalSeconds > 8.0) { throw new InvalidOperationException(L.Key("raa_earthworks_014") + stats.Goal + " / " + stats.Goals + L.Key("raa_earthworks_015") + stats.Evaluated + L.Key("raa_earthworks_016") + stats.Rejected + L.Key("raa_earthworks_017")); } return TerrainSearch.Penalty(ground2.Cost(RailBridge.Points(step).ToArray()), step.Length); }; List<Segment> list3; try { list3 = RoutePlanner.Plan(start.Position, start.Direction, list2, RailBridge.Primitives, Plugin.SearchNodes.Value, Plugin.MaxSegments.Value, terrainCost, stats); } finally { ManualLogSource log = Plugin.Log; if (log != null) { object[] obj = new object[20] { "Terrain search: A=", null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null }; Vector3 val = RailBridge.U(start.Position); obj[1] = ((Vector3)(ref val)).ToString("F3"); obj[2] = ", heading="; val = RailBridge.U(start.Direction); obj[3] = ((Vector3)(ref val)).ToString("F3"); obj[4] = ", goals="; obj[5] = string.Join("; ", list2.Select(delegate(Goal g) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) object[] array = new object[5]; Vector3 val2 = RailBridge.U(g.Position); array[0] = ((Vector3)(ref val2)).ToString("F3"); array[1] = " tolerance="; array[2] = g.Tolerance; array[3] = " match="; array[4] = g.MatchDirection.ToString(); return string.Concat(array); }).ToArray()); obj[6] = ", leg="; obj[7] = stats.Goal; obj[8] = "/"; obj[9] = stats.Goals; obj[10] = ", popped="; obj[11] = stats.Popped; obj[12] = ", expanded="; obj[13] = stats.Expanded; obj[14] = ", terrain checks="; obj[15] = stats.Evaluated; obj[16] = ", rejected="; obj[17] = stats.Rejected; obj[18] = ", ms="; obj[19] = watch.ElapsedMilliseconds; log.LogInfo((object)string.Concat(obj)); } } ValidateRails(list3); if (Plugin.AutoGrade.Value || Plugin.Bridges.Value) { for (int num = 0; num < list3.Count; num++) { try { ground2.Validate(RailBridge.Points(list3[num]).ToArray(), Profile(list3, num)); } catch (Exception ex) { throw new InvalidOperationException(L.Key("raa_earthworks_018") + (num + 1) + ": " + ex.Message); } } } BridgeWorks.Plan(list3, ground2); return list3; } internal static V[] Profile(IList<Segment> route, int index) { List<V> list = new List<V>(); for (int i = Math.Max(0, index - 1); i <= Math.Min(route.Count - 1, index + 1); i++) { IEnumerable<V> enumerable = RailBridge.Points(route[i]); list.AddRange((list.Count == 0) ? enumerable : enumerable.Skip(1)); } return list.ToArray(); } private static void ValidateRails(List<Segment> route) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < route.Count; i++) { ZDO val = RailBridge.Existing(route[i], null, -1); HashSet<ZDOID> hashSet = new HashSet<ZDOID>(); if (val != null) { hashSet.Add(val.m_uid); } string text = RailsConflict(route[i], hashSet); if (text != null) { throw new InvalidOperationException(L.Key("raa_earthworks_019") + (i + 1) + ": " + text + L.Key("raa_earthworks_020")); } } } private static string RailsConflict(Segment step, HashSet<ZDOID> own) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) List<Tuple<ZDO, V[]>> rails = new List<Tuple<ZDO, V[]>>(); foreach (ZDO track in RailBridge.Tracks) { V v = RailBridge.V3(track.GetPosition()); V v2 = (step.Start + step.End) * 0.5; double num = step.Length * 0.5 + 100.0; if (Math.Abs(v.x - v2.x) > num || Math.Abs(v.z - v2.z) > num) { continue; } GameObject prefab = ZNetScene.instance.GetPrefab(track.GetPrefab()); if (!Object.op_Implicit((Object)(object)prefab)) { continue; } foreach (V[] item2 in RailBridge.WorldLines(prefab, track)) { rails.Add(Tuple.Create<ZDO, V[]>(track, item2)); } } HashSet<int> ignored = new HashSet<int>(from i in Enumerable.Range(0, rails.Count) where own.Contains(rails[i].Item1.m_uid) select i); int num2 = new TrackCorridor(rails.Select((Tuple<ZDO, V[]> r) => r.Item2), (double)Plugin.BedHalfWidth.Value + 0.5).Conflict(RailBridge.Points(step).ToArray(), ignored); if (num2 >= 0) { ZDO item = rails[num2].Item1; Vector3 position = item.GetPosition(); GameObject prefab2 = ZNetScene.instance.GetPrefab(item.GetPrefab()); return L.Key("raa_earthworks_021") + ((Object)prefab2).name + L.Key("raa_earthworks_022") + Math.Round(position.x) + ", " + Math.Round(position.z) + L.Key("raa_earthworks_023"); } return null; } internal static string Prepare(Segment step, HashSet<ZDOID> own, V[] profile) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: 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_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_098b: Unknown result type (might be due to invalid IL or missing references) //IL_031c: Unknown result type (might be due to invalid IL or missing references) //IL_0322: Invalid comparison between Unknown and I4 //IL_04fe: Unknown result type (might be due to invalid IL or missing references) //IL_051b: Unknown result type (might be due to invalid IL or missing references) //IL_0867: Unknown result type (might be due to invalid IL or missing references) //IL_0884: Unknown result type (might be due to invalid IL or missing references) V[] path = RailBridge.Sample(step, 0.5); V[] array = path; for (int i = 0; i < array.Length; i++) { if (!RailBridge.Generated(RailBridge.U(array[i]))) { return L.Key("raa_earthworks_024"); } } V[] pierPath = BridgeRules.Clearance(step.Piers); double pierRadius = ((step.Piers == null || step.Piers.Count == 0) ? 0.0 : (step.Piers.Max((Pier pier) => pier.Radius) + 0.15)); if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return L.Key("raa_earthworks_025"); } array = path; for (int i = 0; i < array.Length; i++) { if (!PrivateArea.CheckAccess(RailBridge.U(array[i]), 0f, false, false)) { return L.Key("raa_earthworks_026"); } } array = pierPath; for (int i = 0; i < array.Length; i++) { if (!PrivateArea.CheckAccess(RailBridge.U(array[i]), 0f, false, false)) { return L.Key("raa_earthworks_026"); } } string text = RailsConflict(step, own); if (text != null) { return text; } List<ClearAction> list = new List<ClearAction>(); double width = Plugin.BedHalfWidth.Value + Plugin.ShoulderWidth.Value; ZDO[] array2 = RailBridge.All.ToArray(); foreach (ZDO zdo in array2) { if (own.Contains(zdo.m_uid) || Registry.IsMarker(zdo.GetPrefab())) { continue; } Vector3 position = zdo.GetPosition(); double num = step.Length * 0.5 + 100.0; V v = (step.Start + step.End) * 0.5; if (Math.Abs((double)position.x - v.x) > num || Math.Abs((double)position.z - v.z) > num) { continue; } GameObject prefab = ZNetScene.instance.GetPrefab(zdo.GetPrefab()); if (!Object.op_Implicit((Object)(object)prefab)) { continue; } bool flag = Object.op_Implicit((Object)(object)prefab.GetComponent<MineRock5>()); bool flag2 = Object.op_Implicit((Object)(object)prefab.GetComponent<MineRock>()); Destructible component = prefab.GetComponent<Destructible>(); bool num2 = Object.op_Implicit((Object)(object)prefab.GetComponent<TreeBase>()) || Object.op_Implicit((Object)(object)prefab.GetComponent<TreeLog>()) || (Object.op_Implicit((Object)(object)component) && (int)component.m_destructibleType == 2); ObstacleFeatures obstacleFeatures = ObstacleFeatures.None; if (num2) { obstacleFeatures |= ObstacleFeatures.Tree; } if (flag2 || flag) { obstacleFeatures |= ObstacleFeatures.Rock; } if (Object.op_Implicit((Object)(object)component)) { obstacleFeatures |= ObstacleFeatures.Destructible; } if (Object.op_Implicit((Object)(object)prefab.GetComponent<Pickable>())) { obstacleFeatures |= ObstacleFeatures.Pickable; } if (Object.op_Implicit((Object)(object)prefab.GetComponentInChildren<Piece>(true))) { obstacleFeatures |= ObstacleFeatures.Piece; } if (Object.op_Implicit((Object)(object)prefab.GetComponentInChildren<Container>(true))) { obstacleFeatures |= ObstacleFeatures.Container; } if (Object.op_Implicit((Object)(object)prefab.GetComponentInChildren<Character>(true))) { obstacleFeatures |= ObstacleFeatures.Character; } if (Object.op_Implicit((Object)(object)prefab.GetComponent<TeleportWorld>())) { obstacleFeatures |= ObstacleFeatures.Portal; } ObstacleKind obstacleKind = ObstaclePolicy.Classify(((Object)prefab).name, obstacleFeatures); if (obstacleKind == ObstacleKind.Ignore) { continue; } bool flag3 = obstacleKind != ObstacleKind.Natural; if (RailBridge.IsTrack(prefab) && obstacleKind != ObstacleKind.Container && (obstacleFeatures & ObstacleFeatures.Portal) == 0) { if (prefab.GetComponentsInChildren<Collider>().Any((Collider c) => !c.isTrigger && Contact(prefab, zdo, c, pierPath, pierRadius, 0.0, 0.0))) { return L.Key("raa_bridge_blocked"); } continue; } if (RailBridge.IsStation(prefab) && obstacleKind != ObstacleKind.Container && (obstacleFeatures & ObstacleFeatures.Portal) == 0) { StructureBox[] array3 = RailBridge.StationBoxes(prefab, zdo).ToArray(); if (array3.Length == 0) { return L.Key("raa_earthworks_027"); } if (array3.Any((StructureBox box) => path.Any((V point) => box.Touches(point, 1.125, 0.4, 5.5)))) { return L.Key("raa_earthworks_028") + Math.Round(position.x) + ", " + Math.Round(position.z) + L.Key("raa_earthworks_029"); } if (array3.Any((StructureBox box) => pierPath.Any((V point) => box.Touches(point, pierRadius, 0.0, 0.0)))) { return L.Key("raa_bridge_blocked"); } continue; } Collider[] colliders = ((flag2 && Object.op_Implicit((Object)(object)prefab.GetComponent<MineRock>().m_areaRoot)) ? prefab.GetComponent<MineRock>().m_areaRoot.GetComponentsInChildren<Collider>() : prefab.GetComponentsInChildren<Collider>()); float num3 = (flag ? prefab.GetComponent<MineRock5>().m_health : 0f); float[] health = (flag ? RockHealth(zdo, colliders.Length, num3 + (float)Game.m_worldLevel * num3 * Game.instance.m_worldLevelMineHPMultiplier) : null); List<int> hits = new List<int>(); for (int num4 = 0; num4 < colliders.Length; num4++) { if (!colliders[num4].isTrigger && (!flag || !(health[num4] <= 0f)) && (!flag2 || !(zdo.GetFloat(StringExtensionMethods.GetStableHashCode("Health" + num4), 1f) <= 0f)) && ((BridgeWorks.IsPier(zdo) ? Contact(prefab, zdo, colliders[num4], path, 1.125, 5.0, RailBridge.BedOffset - 0.05) : Contact(prefab, zdo, colliders[num4], path, width, flag3 ? 12 : 5)) || Contact(prefab, zdo, colliders[num4], pierPath, pierRadius, 0.0, 0.0))) { hits.Add(num4); } } if (hits.Count != 0) { if (flag3) { return string.Concat(L.Key("raa_earthworks_030"), obstacleKind switch { ObstacleKind.Building => L.Key("raa_earthworks_032"), ObstacleKind.Container => L.Key("raa_earthworks_031"), _ => L.Key("raa_earthworks_033"), }, " «", ((Object)prefab).name, L.Key("raa_earthworks_034"), Math.Round(position.x), ", ", Math.Round(position.z), "."); } if (!Plugin.AutoClear.Value) { return L.Key("raa_earthworks_035"); } if (zdo.GetOwner() != 0L && !zdo.IsOwner()) { return L.Key("raa_earthworks_036"); } ZDO target = zdo; list.Add(new ClearAction { Zdo = target, Apply = delegate { Clear(target, prefab, colliders.Length, hits, health); } }); } } Ground ground = new Ground(); List<Ground.Region> list2 = null; BridgeWorks.Validate(step, ground); if (Plugin.AutoGrade.Value) { list2 = ground.Grade(RailBridge.Points(step).ToArray(), profile); } else { array = path; float num5 = default(float); for (int i = 0; i < array.Length; i++) { V p = array[i]; if (Heightmap.GetHeight(RailBridge.U(p), ref num5) && p.y < (double)num5 + 0.1) { return L.Key("raa_earthworks_037"); } } } if (list.Count > 0) { foreach (ClearAction item in list.Take(24)) { if (item.Zdo.GetOwner() == 0L) { item.Zdo.SetOwner(ZNet.GetUID()); } item.Apply(); } return L.Key("raa_earthworks_038") + Math.Min(24, list.Count) + L.Key("raa_earthworks_039") + list.Count + L.Key("raa_earthworks_040"); } if (list2 != null) { ground.Apply(list2, (step.Start + step.End) * 0.5); } return null; } private static float[] RockHealth(ZDO zdo, int count, float initial) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown float[] array = Enumerable.Repeat(initial, count).ToArray(); string text = zdo.GetString(ZDOVars.s_health, ""); if (string.IsNullOrEmpty(text)) { return array; } ZPackage val = new ZPackage(Convert.FromBase64String(text)); if (val.ReadInt() != count) { throw new InvalidOperationException(L.Key("raa_earthworks_041")); } for (int i = 0; i < count; i++) { array[i] = val.ReadSingle(); } return array; } private static void Clear(ZDO zdo, GameObject prefab, int count, List<int> hits, float[] health) { //IL_0035: 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_0082: Expected O, but got Unknown if (!zdo.IsOwner()) { throw new InvalidOperationException(L.Key("raa_earthworks_042")); } GameObject val = ZNetScene.instance.FindInstance(zdo.m_uid); if (health != null) { foreach (int hit in hits) { health[hit] = 0f; } ZPackage val2 = new ZPackage(); val2.Write(count); foreach (float num in health) { val2.Write(num); } zdo.Set(ZDOVars.s_health, Convert.ToBase64String(val2.GetArray())); if (Object.op_Implicit((Object)(object)val)) { RockReload.Invoke(val.GetComponent<MineRock5>(), null); } if (health.Any((float h) => h > 0f)) { return; } } else if (Object.op_Implicit((Object)(object)prefab.GetComponent<MineRock>())) { foreach (int hit2 in hits) { zdo.Set(StringExtensionMethods.GetStableHashCode("Health" + hit2), 0f); } if (Object.op_Implicit((Object)(object)val)) { OldRockReload.Invoke(val.GetComponent<MineRock>(), null); } if (Enumerable.Range(0, count).Any((int num2) => zdo.GetFloat(StringExtensionMethods.GetStableHashCode("Health" + num2), 1f) > 0f) || !prefab.GetComponent<MineRock>().m_removeWhenDestroyed) { return; } } if (Object.op_Implicit((Object)(object)val)) { ZNetScene.instance.Destroy(val); } else { ZDOMan.instance.DestroyZDO(zdo); } } private static bool Contact(GameObject prefab, ZDO zdo, Collider collider, V[] path, double width, double clearance, double below = double.NaN) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0124: 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_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_022e: 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_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_02b5: Unknown result type (might be due to invalid IL or missing references) //IL_02c3: 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_02d7: Unknown result type (might be due to invalid IL or missing references) //IL_02ec: Unknown result type (might be due to invalid IL or missing references) //IL_02f3: Unknown result type (might be due to invalid IL or missing references) BoxCollider val = (BoxCollider)(object)((collider is BoxCollider) ? collider : null); CapsuleCollider val2 = (CapsuleCollider)(object)((collider is CapsuleCollider) ? collider : null); SphereCollider val3 = (SphereCollider)(object)((collider is SphereCollider) ? collider : null); MeshCollider val4 = (MeshCollider)(object)((collider is MeshCollider) ? collider : null); Bounds bounds = default(Bounds); if (Object.op_Implicit((Object)(object)val)) { ((Bounds)(ref bounds))..ctor(val.center, val.size); } else if (Object.op_Implicit((Object)(object)val2)) { Vector3 val5 = Vector3.one * (val2.radius * 2f); ((Vector3)(ref val5))[val2.direction] = Math.Max(val2.height, val2.radius * 2f); ((Bounds)(ref bounds))..ctor(val2.center, val5); } else if (Object.op_Implicit((Object)(object)val3)) { ((Bounds)(ref bounds))..ctor(val3.center, Vector3.one * val3.radius * 2f); } else { if (!Object.op_Implicit((Object)(object)val4) || !Object.op_Implicit((Object)(object)val4.sharedMesh)) { return false; } bounds = val4.sharedMesh.bounds; } float num = zdo.GetFloat(ZDOVars.s_scaleScalarHash, 1f); Vector3 vec = zdo.GetVec3(ZDOVars.s_scaleHash, Vector3.one * num); Matrix4x4 val6 = Matrix4x4.TRS(zdo.GetPosition(), zdo.GetRotation(), vec) * prefab.transform.worldToLocalMatrix * ((Component)collider).transform.localToWorldMatrix; Vector3 val7 = ((Matrix4x4)(ref val6)).MultiplyPoint3x4(((Bounds)(ref bounds)).center); Vector3 val8 = ((Matrix4x4)(ref val6)).MultiplyVector(new Vector3(((Bounds)(ref bounds)).extents.x, 0f, 0f)); Vector3 val9 = ((Matrix4x4)(ref val6)).MultiplyVector(new Vector3(0f, ((Bounds)(ref bounds)).extents.y, 0f)); Vector3 val10 = ((Matrix4x4)(ref val6)).MultiplyVector(new Vector3(0f, 0f, ((Bounds)(ref bounds)).extents.z)); Vector3 val11 = default(Vector3); ((Vector3)(ref val11))..ctor(Math.Abs(val8.x) + Math.Abs(val9.x) + Math.Abs(val10.x), Math.Abs(val8.y) + Math.Abs(val9.y) + Math.Abs(val10.y), Math.Abs(val8.z) + Math.Abs(val9.z) + Math.Abs(val10.z)); double num2 = (double.IsNaN(below) ? (RailBridge.BedOffset + ((clearance > 5.0) ? 8.0 : 0.4)) : below); for (int i = 0; i < path.Length; i++) { V v = path[i]; if (Math.Abs(v.x - (double)val7.x) <= (double)val11.x + width && Math.Abs(v.z - (double)val7.z) <= (double)val11.z + width && (double)(val7.y - val11.y) <= v.y + clearance && (double)(val7.y + val11.y) >= v.y - num2) { return true; } } return false; } } internal static class Keys { internal static readonly int State = StringExtensionMethods.GetStableHashCode("local.raa.state.v1"); internal static readonly int Name = StringExtensionMethods.GetStableHashCode("local.raa.line"); internal static readonly int JobTag = StringExtensionMethods.GetStableHashCode("local.raa.job"); internal static readonly int Index = StringExtensionMethods.GetStableHashCode("local.raa.segment"); internal static readonly int Error = StringExtensionMethods.GetStableHashCode("local.raa.error"); } internal static class Engine { internal static OrderBook ReadBook(ZDO site) { return OrderBook.Read(site.GetString(Keys.State, ""), site.GetString(Keys.Name, "Линия1")); } internal static Job Read(ZDO site) { return ReadBook(site).Current; } private static void SaveBook(ZDO site, OrderBook book) { if (!site.IsOwner()) { throw new InvalidOperationException(L.Key("raa_engine_001")); } string text = book.Write(); site.Set(Keys.State, text); site.Set(Keys.Name, book.Selected); } internal static void Save(ZDO site, Job job) { OrderBook orderBook = ReadBook(site); orderBook.Put(job); SaveBook(site, orderBook); } internal static string[] Lines(ZDO site) { long owner = site.GetLong(ZDOVars.s_creator, 0L); return ReadBook(site).Jobs.Select((Job j) => j.Line).Concat(from z in RailBridge.All where (z.GetPrefab() == Registry.StartHash || z.GetPrefab() == Registry.EndHash) && z.GetLong(ZDOVars.s_creator, 0L) == owner select z.GetString(Keys.Name, "Линия1")).Distinct<string>(StringComparer.OrdinalIgnoreCase) .OrderBy<string, string>((string s) => s, StringComparer.OrdinalIgnoreCase) .ToArray(); } internal static void Command(ZDO site, string command, string line) { //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) OrderBook orderBook = ReadBook(site); Job current = orderBook.Current; if (command == "line") { orderBook.Select(line); SaveBook(site, orderBook); return; } if (!string.Equals(JobRules.Line(line), orderBook.Selected, StringComparison.OrdinalIgnoreCase)) { throw new InvalidOperationException(L.Key("raa_engine_002")); } if (command == "pause") { current.Active = false; current.Status = L.Key("raa_engine_003"); Save(site, current); return; } if (current.Pending != null) { throw new InvalidOperationException(L.Key("raa_engine_004")); } switch (command) { case "remove_markers": RemoveMarkers(site, current); break; case "plan": { if (current.Active) { throw new InvalidOperationException(L.Key("raa_engine_005")); } string name = current.Line; long owner = site.GetLong(ZDOVars.s_creator, 0L); List<ZDO> source = RailBridge.All.Where((ZDO z) => Registry.IsMarker(z.GetPrefab()) && z.GetLong(ZDOVars.s_creator, 0L) == owner).ToList(); List<ZDO> list = source.Where((ZDO z) => z.GetPrefab() == Registry.StartHash && string.Equals(z.GetString(Keys.Name, "Линия1"), name, StringComparison.OrdinalIgnoreCase)).ToList(); List<ZDO> list2 = source.Where((ZDO z) => z.GetPrefab() == Registry.EndHash && string.Equals(z.GetString(Keys.Name, "Линия1"), name, StringComparison.OrdinalIgnoreCase)).ToList(); if (list.Count != 1 || list2.Count != 1) { throw new InvalidOperationException(L.Key("raa_engine_006") + name + L.Key("raa_engine_007")); } Goal a = RailBridge.Anchor(list[0], start: true); Goal item = RailBridge.Anchor(list2[0], start: false); ZDO[] ways = source.Where((ZDO z) => z.GetPrefab() == Registry.WayHash).ToArray(); bool automatic; int[] array = WaypointRules.Select(name, ways.Select((ZDO z) => z.GetString(Keys.Name, "Линия1:1")).ToArray(), ways.Select((ZDO z) => RailBridge.V3(z.GetPosition())).ToArray(), RailBridge.V3(list[0].GetPosition()), RailBridge.V3(list2[0].GetPosition()), out automatic, Lines(site)); List<Goal> list3 = (from i in array select new Goal { Position = RailBridge.Anchor(ways[i], start: false).Position, Tolerance = 1.25 } into g where !RailAnchors.AlreadyPassed(g.Position, a) select g).ToList(); string text = L.Key("raa_engine_008") + list3.Count + " / " + array.Length + (automatic ? L.Key("raa_engine_009") : L.Key("raa_engine_010")); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)L.Render("Planning line «" + name + "»: " + text, "English")); } list3.Add(item); List<Segment> list4 = ((list3.Count == 1 && (list3[0].Position - a.Position).Length <= list3[0].Tolerance) ? new List<Segment>() : Earthworks.Plan(a, list3)); current = new Job { Line = name, Segments = list4, PlanRevision = 4 }; current.Estimate = (from c in list4.SelectMany(RailBridge.Costs) group c by c.Prefab into g select new Cost { Prefab = g.Key, Amount = g.Sum((Cost c) => c.Amount) }).ToList(); current.Status = ((list4.Count == 0) ? L.Key("raa_engine_011") : (L.Key("raa_engine_012") + list4.Count + L.Key("raa_engine_013") + Math.Round(list4.Sum((Segment s) => s.Length)) + L.Key("raa_engine_014") + text + ((a.ExistingLength > 0.0) ? (L.Key("raa_engine_015") + Math.Round(a.ExistingLength) + L.Key("raa_engine_016")) : "") + L.Key("raa_engine_017"))); current.Write(); Save(site, current); break; } case "start": if (current.Segments.Count == 0 || current.Index >= current.Segments.Count) { throw new InvalidOperationException(L.Key("raa_engine_018")); } if (current.PlanRevision < 4) { throw new InvalidOperationException(L.Key("raa_engine_019")); } current.Active = true; current.Status = L.Key("raa_engine_020"); current.Next = 0.0; Save(site, current); break; default: throw new InvalidOperationException(L.Key("raa_engine_021")); } } private static void RemoveMarkers(ZDO site, Job job) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) long owner = site.GetLong(ZDOVars.s_creator, 0L); string[] knownLines = Lines(site); ZDO[] array = RailBridge.All.Where((ZDO z) => z.IsValid() && MarkerRules.Matches(z.GetPrefab(), Registry.StartHash, Registry.EndHash, z.GetLong(ZDOVars.s_creator, 0L), owner, z.GetString(Keys.Name, (z.GetPrefab() == Registry.WayHash) ? "Линия1:1" : "Линия1"), job.Line, Registry.WayHash, knownLines)).ToArray(); ZDO[] array2 = array; foreach (ZDO val in array2) { if (!PrivateArea.CheckAccess(val.GetPosition(), 0f, false, false)) { throw new InvalidOperationException(L.Key("raa_engine_022")); } if (val.GetOwner() != 0L && !val.IsOwner()) { throw new InvalidOperationException(L.Key("raa_engine_023")); } } MarkerRules.PauseAndInvalidate(job, array.Count((ZDO z) => z.GetPrefab() == Registry.StartHash), array.Count((ZDO z) => z.GetPrefab() == Registry.EndHash), array.Count((ZDO z) => z.GetPrefab() == Registry.WayHash)); string status = job.Status; job.Status = L.Key("raa_engine_024"); Save(site, job); array2 = array; foreach (ZDO val2 in array2) { if (val2.GetOwner() == 0L) { val2.SetOwner(ZNet.GetUID()); } GameObject val3 = ZNetScene.instance.FindInstance(val2.m_uid); if (Object.op_Implicit((Object)(object)val3)) { ZNetScene.instance.Destroy(val3); } else { ZDOMan.instance.DestroyZDO(val2); } } job.Status = status; Save(site, job); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)L.Render("Removed " + array.Length + " route markers of line «" + job.Line + "»; rails and stock retained.", "English")); } } internal static void Tick(ZDO site, double now) { if (!site.IsOwner()) { return; } OrderBook orderBook; try { orderBook = ReadBook(site); } catch (Exception ex) { site.Set(Keys.Error, ex.Message); return; } Job job = orderBook.Jobs.FirstOrDefault((Job j) => j.Pending != null); if (job != null) { TickOrder(site, job, now); return; } foreach (Job item in orderBook.Jobs.Where((Job j) => j.Active)) { TickOrder(site, item, now); if (ReadBook(site).Jobs.Any((Job j) => j.Pending != null)) { break; } } } private static void TickOrder(ZDO site, Job job, double now) { //IL_0189: Unknown result type (might be due to invalid IL or missing references) if (job.Pending == null && job.Active && job.PlanRevision < 4) { job.Active = false; job.Status = L.Key("raa_engine_025"); Save(site, job); } else { if (job.Pending == null && (!job.Active || job.Index >= job.Segments.Count || job.Next > now)) { return; } if (!RailBridge.Busy(site)) { try { if (job.Pending != null) { Recover(site, job, now); } else { Segment segment = job.Segments[job.Index]; bool flag = RailBridge.Existing(segment, job.Id, job.Index) != null; HashSet<ZDOID> hashSet = new HashSet<ZDOID>(from z in RailBridge.All where z.GetString(Keys.JobTag, "") == job.Id select z.m_uid); ZDO val = RailBridge.Existing(segment, job.Id, job.Index); if (val != null) { hashSet.Add(val.m_uid); } string text = RailBridge.TextInventory(site); List<Cost> costs = (flag ? new List<Cost>() : RailBridge.Costs(segment)); string text2 = (flag ? text : RailBridge.Debit(text, costs)); string text3 = Earthworks.Prepare(segment, hashSet, Earthworks.Profile(job.Segments, job.Index)); if (text3 != null) { Status(site, job, text3); } else if (flag) { Complete(site, job, now, L.Key("raa_engine_027")); } else { job.Pending = new Pending { Index = job.Index, Before = text, After = text2, Costs = costs }; Save(site, job); RailBridge.StoreInventory(site, text2); BridgeWorks.Create(segment, job, site.GetLong(ZDOVars.s_creator, 0L)); RailBridge.Create(segment, job, site.GetLong(ZDOVars.s_creator, 0L), costs); Complete(site, job, now, L.Key("raa_engine_028")); } } return; } catch (Exception ex) { Status(site, job, ex.GetBaseException().Message); return; } } Status(site, job, L.Key("raa_engine_026")); } } private static void Recover(ZDO site, Job job, double now) { Pending pending = job.Pending; Segment step = job.Segments[job.Index]; bool exists = RailBridge.Existing(step, job.Id, job.Index) != null; switch (JobRules.Recover(RailBridge.TextInventory(site), pending, exists)) { case Recovery.Blocked: job.Active = false; job.Status = L.Key("raa_engine_029"); Save(site, job); return; case Recovery.Retry: job.Pending = null; job.Status = L.Key("raa_engine_030"); Save(site, job); return; case Recovery.Debit: RailBridge.StoreInventory(site, pending.After); break; case Recovery.Create: { HashSet<ZDOID> own = new HashSet<ZDOID>(from z in RailBridge.All where z.GetString(Keys.JobTag, "") == job.Id select z.m_uid); string text = Earthworks.Prepare(step, own, Earthworks.Profile(job.Segments, job.Index)); if (text != null) { Status(site, job, text); return; } BridgeWorks.Create(step, job, site.GetLong(ZDOVars.s_creator, 0L)); RailBridge.Create(step, job, site.GetLong(ZDOVars.s_creator, 0L), pending.Costs); break; } } Complete(site, job, now, L.Key("raa_engine_031")); } private static void Complete(ZDO site, Job job, double now, string status) { double length = job.Segments[job.Index].Length; job.Index++; job.Pending = null; job.Next = now + Math.Max(1.0, length * (double)Plugin.SecondsPerMeter.Value); job.Status = ((job.Index == job.Segments.Count) ? L.Key("raa_engine_032") : status); if (job.Index == job.Segments.Count) { job.Active = false; } Save(site, job); } private static void Status(ZDO site, Job job, string status) { //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) if (job.Status == status) { return; } job.Status = status; Save(site, job); if (job.Index < job.Segments.Count) { Segment segment = job.Segments[job.Index]; ManualLogSource log = Plugin.Log; if (log != null) { object[] obj = new object[12] { "Line «", job.Line, "», section ", job.Index, " ", segment.Prefab, ", start=", null, null, null, null, null }; Vector3 val = RailBridge.U(segment.Start); obj[7] = ((Vector3)(ref val)).ToString("F3"); obj[8] = ", end="; val = RailBridge.U(segment.End); obj[9] = ((Vector3)(ref val)).ToString("F3"); obj[10] = ": "; obj[11] = status; log.LogInfo((object)L.Render(string.Concat(obj), "English")); } } } } [Serializable] public sealed class Cost { public string Prefab; public int Amount; } [Serializable] public sealed class Pending { public int Index; public string Before; public string After; public List<Cost> Costs; } [Serializable] public sealed class Job { public const int CurrentPlanRevision = 4; public int Format = 1; public int Index; public int PlanRevision; public string Id = Guid.NewGuid().ToString("N"); public string Line = "Линия1"; public string Status = L.Key("raa_job_001"); public bool Active; public double Next; public List<Segment> Segments = new List<Segment>(); public List<Cost> Estimate = new List<Cost>(); public Pending Pending; public static Job Read(string json) { if (string.IsNullOrEmpty(json)) { return new Job(); } if (json.Length > 131072) { throw new InvalidOperationException(L.Key("raa_job_002")); } Job job = JsonConvert.DeserializeObject<Job>(json); if (job == null || job.Format != 1 || job.PlanRevision < 0 || job.PlanRevision > 4 || string.IsNullOrEmpty(job.Id) || job.Segments == null || job.Segments.Count > 512 || job.Index < 0 || job.Index > job.Segments.Count || (job.Pending != null && job.Pending.Index != job.Index)) { throw new InvalidOperationException(L.Key("raa_job_003")); } if (job.Estimate == null || double.IsNaN(job.Next) || double.IsInfinity(job.Next) || (job.Pending != null && (job.Index >= job.Segments.Count || job.Pending.Before == null || job.Pending.After == null || job.Pending.Costs == null))) { throw new InvalidOperationException(L.Key("raa_job_004")); } foreach (Segment segment in job.Segments) { if (segment == null || segment.Prefab == null || !segment.Origin.Finite || !segment.Start.Finite || !segment.End.Finite || !segment.Direction.Finite || segment.Length <= 0.0 || segment.Length > 200.0 || double.IsNaN(segment.Length) || double.IsNaN(segment.Yaw) || double.IsInfinity(segment.Yaw)) { throw new InvalidOperationException(L.Key("raa_job_005")); } } foreach (Segment segment2 in job.Segments) { if (segment2.Piers != null && (segment2.Piers.Count > 64 || segment2.Piers.Exists((Pier p) => !BridgeRules.Valid(p)))) { throw new InvalidOperationException(L.Key("raa_bridge_saved")); } } foreach (Cost item in job.Estimate) { Validate(item); } if (job.Pending != null) { foreach (Cost cost in job.Pending.Costs) { Validate(cost); } } return job; } private static void Validate(Cost c) { if (c == null || string.IsNullOrEmpty(c.Prefab) || c.Amount < 0 || c.Amount > 1000000) { throw new InvalidOperationException(L.Key("raa_job_006")); } } public string Write() { string text = JsonConvert.SerializeObject((object)this, (Formatting)0); if (text.Length > 131072) { throw new InvalidOperationException(L.Key("raa_job_007")); } return text; } } public enum Recovery { Retry, Create, Debit, Commit, Blocked } public static class JobRules { public static Recovery Recover(string inventory, Pending pending, bool exists) { if (pending == null) { return Recovery.Retry; } if (inventory == pending.After) { if (!exists) { return Recovery.Create; } return Recovery.Commit; } if (inventory == pending.Before) { if (!exists) { return Recovery.Retry; } return Recovery.Debit; } return Recovery.Blocked; } public static string Line(string input) { input = (input ?? "").Trim(); if (input.Length == 0 || input.Length > 40 || input.IndexOfAny(new char[4] { '\n', '\r', '<', '>' }) >= 0) { throw new InvalidOperationException(L.Key("raa_job_008")); } return input; } } internal static class L { private const char Open = '\ue000'; private const char Close = '\ue001'; private static readonly Dictionary<string, string> English = Read("English"); private static readonly Dictionary<string, string> Russian = Read("Russian"); private static readonly Dictionary<string, string> Legacy = LegacyMap(); internal static Func<string> Language = () => "English"; internal static string Selected { get { if (!(Language() == "Russian")) { return "English"; } return "Russian"; } } internal static string Json(string language) { using Stream stream = typeof(L).Assembly.GetManifestResourceStream("RailroadsAutomation." + language + ".json"); using StreamReader streamReader = new StreamReader(stream ?? throw new InvalidDataException("Missing localization: " + language)); return streamReader.ReadToEnd(); } private static Dictionary<string, string> Read(string language) { return JsonConvert.DeserializeObject<Dictionary<string, string>>(Json(language)); } private static Dictionary<string, string> LegacyMap() { Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.Ordinal); foreach (KeyValuePair<string, string> item in Russian) { if (!dictionary.ContainsKey(item.Value)) { dictionary.Add(item.Value, item.Key); } } return dictionary; } internal static string Key(string key) { return "\ue000" + key + "\ue001"; } internal static string Native(string message) { if (message.Length > 2 && message[0] == '\ue000' && message[message.Length - 1] == '\ue001') { return "$" + message.Substring(1, message.Length - 2); } return Render(message); } internal static string Render(string message) { return Render(message, Selected); } internal static string Render(string message, string language) { if (string.IsNullOrEmpty(message)) { return message ?? ""; } Dictionary<string, string> dictionary = ((language == "Russian") ? Russian : English); if (message.IndexOf('\ue000') < 0) { if (Legacy.TryGetValue(message, out var value)) { return dictionary[value]; } return message; } StringBuilder stringBuilder = new StringBuilder(); int num = 0; while (num < message.Length) { int num2 = message.IndexOf('\ue000', num); if (num2 < 0) { stringBuilder.Append(message, num, message.Length - num); break; } stringBuilder.Append(message, num, num2 - num); int num3 = message.IndexOf('\ue001', num2 + 1); if (num3 < 0) { stringBuilder.Append(message, num2, message.Length - num2); break; } string text = message.Substring(num2 + 1, num3 - num2 - 1); if (!dictionary.TryGetValue(text, out var value2) && !English.TryGetValue(text, out value2)) { value2 = "[" + text + "]"; } stringBuilder.Append(value2); num = num3 + 1; } return stringBuilder.ToString(); } } internal static class MarkerRules { internal static bool Matches(int prefab, int start, int end, long creator, long owner, string markerLine, string selected, int waypoint = -1, string[] knownLines = null) { if (creator == owner) { if ((prefab != start && prefab != end) || !string.Equals(markerLine, selected, StringComparison.OrdinalIgnoreCase)) { if (prefab == waypoint) { return WaypointRules.Belongs(markerLine, selected, knownLines); } return false; } return true; } return false; } internal static void PauseAndInvalidate(Job job, int starts, int ends, int ways = 0) { if (job.Pending != null) { throw new InvalidOperationException(L.Key("raa_markerrules_001")); } if (starts < 0 || ends < 0 || ways < 0) { throw new InvalidOperationException(L.Key("raa_markerrules_002")); } job.Active = false; job.PlanRevision = 0; job.Status = ((starts + ends + ways == 0) ? L.Key("raa_markerrules_003") : (L.Key("raa_markerrules_004") + job.Line + L.Key("raa_markerrules_005") + starts + L.Key("raa_markerrules_006") + ends + L.Key("raa_markerrules_008") + ways + L.Key("raa_markerrules_007"))); } } [Flags] public enum ObstacleFeatures { None = 0, Tree = 1, Rock = 2, Destructible = 4, Pickable = 8, Piece = 0x10, Container = 0x20, Character = 0x40, Portal = 0x80 } public enum ObstacleKind { Ignore, Natural, Building, Container, Unknown } public static class ObstaclePolicy { public static ObstacleKind Classify(string name, ObstacleFeatures f) { if ((f & ObstacleFeatures.Character) != ObstacleFeatures.None) { return ObstacleKind.Ignore; } if ((f & ObstacleFeatures.Container) != ObstacleFeatures.None) { return ObstacleKind.Container; } if ((f & ObstacleFeatures.Portal) != ObstacleFeatures.None) { return ObstacleKind.Building; } string text = new string((name ?? "").ToLowerInvariant().Where(char.IsLetterOrDigit).ToArray()); bool flag = (f & (ObstacleFeatures.Destructible | ObstacleFeatures.Pickable)) != 0; bool flag2 = text == "bcawildchilipepper" || text == "bcawildtomato"; bool flag3 = text == "pickableshrimptraprtd"; bool flag4 = flag && (flag2 || flag3 || new string[14] { "shrub", "firtreesmall", "bush01", "bush02", "raspberrybush", "blueberrybush", "cloudberrybush", "sapling", "pickablestone", "pickablebranch", "pickableflint", "pickablemushroom", "pickablethistle", "pickabledandelion" }.Any(text.StartsWith)); if ((f & (ObstacleFeatures.Tree | ObstacleFeatures.Rock)) != 0 || flag4) { return ObstacleKind.Natural; } if ((f & ObstacleFeatures.Piece) != ObstacleFeatures.None) { return ObstacleKind.Building; } if (flag && !text.Contains("runestone") && !text.Contains("dungeon") && new string[13] { "stub", "stump", "bush", "beech", "firtree", "pinetree", "oak", "rock", "stone", "branch", "thistle", "dandelion", "mushroom" }.Any(text.Contains)) { return ObstacleKind.Natural; } if ((f & ObstacleFeatures.Destructible) == 0) { return ObstacleKind.Ignore; } return ObstacleKind.Unknown; } } [Serializable] public sealed class OrderBook { public int Format = 2; public string Selected = "Линия1"; public List<Job> Jobs = new List<Job>(); public Job Current => Jobs.First((Job j) => Same(j.Line, Selected)); private static bool Same(string a, string b) { return string.Equals(a, b, StringComparison.OrdinalIgnoreCase); } public static OrderBook Read(string json, string fallback) { if ((json ?? "").Length > 524288) { throw new InvalidOperationException(L.Key("raa_orderbook_001")); } OrderBook orderBook; if (string.IsNullOrEmpty(json) || (int?)JObject.Parse(json)["Format"] == 1) { Job job = Job.Read(json); orderBook = new OrderBook(); job.Line = JobRules.Line((job.Segments.Count > 0 || job.Pending != null) ? job.Line : fallback); orderBook.Selected = job.Line; orderBook.Jobs.Add(job); } else { orderBook = JsonConvert.DeserializeObject<OrderBook>(json); } if (orderBook == null || orderBook.Format != 2 || orderBook.Jobs == null || orderBook.Jobs.Count == 0 || orderBook.Jobs.Count > 32) { throw new InvalidOperationException(L.Key("raa_orderbook_002")); } orderBook.Selected = JobRules.Line(orderBook.Selected); HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); foreach (Job job2 in orderBook.Jobs) { if (job2 == null) { throw new InvalidOperationException(L.Key("raa_orderbook_003")); } job2.Line = JobRules.Line(job2.Line); Job.Read(job2.Write()); if (!hashSet.Add(job2.Line)) { throw new InvalidOperationException(L.Key("raa_orderbook_004")); } } if (!hashSet.Contains(orderBook.Selected)) { throw new InvalidOperationException(L.Key("raa_orderbook_005")); } if (orderBook.Jobs.Count((Job j) => j.Pending != null) > 1) { throw new InvalidOperationException(L.Key("raa_orderbook_006")); } return orderBook; } public void Select(string line) { line = JobRules.Line(line); Job job = Jobs.FirstOrDefault((Job j) => Same(j.Line, line)); if (job == null) { if (Jobs.Count >= 32) { throw new InvalidOperationException(L.Key("raa_orderbook_007")); } job = new Job { Line = line }; Jobs.Add(job); } Selected = job.Line; } public void Put(Job job) { int num = Jobs.FindIndex((Job j) => Same(j.Line, job.Line)); if (num < 0) { throw new InvalidOperationException(L.Key("raa_orderbook_008")); } Jobs[num] = job; } public string Write() { string text = JsonConvert.SerializeObject((object)new { Format, Selected, Jobs }, (Formatting)0); if (text.Length > 524288) { throw new InvalidOperationException(L.Key("raa_orderbook_009")); } return text; } } [BepInPlugin("local.railroads.automation", "Railroads Automation", "0.3.2")] [BepInDependency("vladasz.railroads", "0.2.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { [HarmonyPatch(typeof(Container), "Interact")] private static class OpenSite { private static bool Prefix(Container __instance, Humanoid character, bool hold, bool alt, ref bool __result) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) Site component = ((Component)__instance).GetComponent<Site>(); if (!Object.op_Implicit((Object)(object)component) || alt) { return true; } __result = true; if (hold || (Object)(object)character != (Object)(object)Player.m_localPlayer) { return false; } if (!ZNet.instance.IsServer()) { ((Character)Player.m_localPlayer).Message((MessageType)2, L.Render(L.Key("raa_plugin_001")), 0, (Sprite)null, false); return false; } if (!((Component)__instance).GetComponent<Piece>().IsCreator() || !PrivateArea.CheckAccess(((Component)__instance).transform.position, 0f, true, false)) { return false; } Window.Show(component); return false; } } [HarmonyPatch(typeof(Container), "GetHoverText")] private static class SiteHover { private static void Postfix(Container __instance, ref string __result) { if (Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<Site>())) { __result = Localization.instance.Localize(L.Render(L.Key("raa_plugin_002"))); } } } [HarmonyPatch(typeof(Player), "TakeInput")] private static class InputBlock { private static void Postfix(ref bool __result) { if (Window.Open) { __result = false; } } } [HarmonyPatch(typeof(Menu), "IsVisible")] private static class MenuVisible { private static void Postfix(ref bool __result) { if (Window.Open) { __result = true; } } } [HarmonyPatch(typeof(Menu), "Update")] private static class MenuBlock { private static bool Prefix() { if (!Window.Open) { return !Window.Suppress; } return false; } } [HarmonyPatch(typeof(InventoryGui), "Update")] private static class InventoryBlock { private static bool Prefix() { if (!Window.Open) { return !Window.Suppress; } return false; } } [HarmonyPatch(typeof(GameCamera), "UpdateMouseCapture")] private static class CursorCapture { private static bool Prefix() { if (!Window.Open) { return true; } ZCursor.LockState = (CursorLockMode)0; ZCursor.Show(); return false; } } internal static ConfigEntry<int> SearchNodes; internal static ConfigEntry<int> MaxSegments; internal static ConfigEntry<float> SecondsPerMeter; internal static ConfigEntry<bool> IgnoreSupport; internal static ConfigEntry<bool> AutoClear; internal static ConfigEntry<bool> AutoGrade; internal static ConfigEntry<bool> FollowTerrain; internal static ConfigEntry<float> BedHalfWidth; internal static ConfigEntry<float> MaxEarthwork; internal static ConfigEntry<float> ShoulderWidth; internal static ConfigEntry<bool> Bridges; internal static ConfigEntry<float> BridgeThreshold; internal static ConfigEntry<float> MaxPierHeight; private Harmony harmony; private ZDOMan world; private float next; private float errorAt; internal static ManualLogSource Log; private void Awake() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Expected O, but got Unknown //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Expected O, but got Unknown //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Expected O, but got Unknown //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Expected O, but got Unknown //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Expected O, but got Unknown //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Expected O, but got Unknown //IL_02ae: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Expected O, but got Unknown //IL_02eb: Unknown result type (might be due to invalid IL or missing references) //IL_02f5: Expected O, but got Unknown //IL_031b: Unknown result type (might be due to invalid IL or missing references) //IL_0325: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; L.Language = () => (Localization.instance == null) ? "English" : Localization.instance.GetSelectedLanguage(); CustomLocalization val = new CustomLocalization(((BaseUnityPlugin)this).Info.Metadata); val.AddJsonFile("English", L.Json("English")); val.AddJsonFile("Russian", L.Json("Russian")); LocalizationManager.Instance.AddLocalization(val); SearchNodes = ((BaseUnityPlugin)this).Config.Bind<int>("Construction", "Search Nodes", 12000, new ConfigDescription("Bounded planner search per waypoint.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1000, 30000), Array.Empty<object>())); MaxSegments = ((BaseUnityPlugin)this).Config.Bind<int>("Construction", "Maximum Segments", 256, new ConfigDescription("Split longer railways into several orders.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(8, 512), Array.Empty<object>())); SecondsPerMeter = ((BaseUnityPlugin)this).Config.Bind<float>("Construction", "Seconds Per Meter", 0.5f, new ConfigDescription("Construction time, while the world is running.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 60f), Array.Empty<object>())); IgnoreSupport = ((BaseUnityPlugin)this).Config.Bind<bool>("Construction", "Support Automated Tracks", true, "Prevent structural collapse only for tracks created by this add-on. Damage/removal unchanged. Disabling may collapse bridges."); AutoClear = ((BaseUnityPlugin)this).Config.Bind<bool>("Earthworks", "Auto Clear", true, "Clear natural trees, stumps, bushes and intersecting rock parts. No harvesting rewards. Buildings/containers stop construction."); AutoGrade = ((BaseUnityPlugin)this).Config.Bind<bool>("Earthworks", "Auto Grade", true, "Prepare a graded bed below each track section; retain native terrain save data and water bottoms."); FollowTerrain = ((BaseUnityPlugin)this).Config.Bind<bool>("Earthworks", "Follow Terrain", true, "New route calculations follow land elevations using native slope sections. Recalculate old plans to use this."); BedHalfWidth = ((BaseUnityPlugin)this).Config.Bind<float>("Earthworks", "Bed Half Width", 2f, new ConfigDescription("Track bed half-width in metres, before shoulders.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1.5f, 4f), Array.Empty<object>())); ShoulderWidth = ((BaseUnityPlugin)this).Config.Bind<float>("Earthworks", "Shoulder Width", 3f, new ConfigDescription("Smooth transition from the bed to surrounding terrain in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 6f), Array.Empty<object>())); MaxEarthwork = ((BaseUnityPlugin)this).Config.Bind<float>("Earthworks", "Maximum Cut Or Fill", 4f, new ConfigDescription("Maximum local cut/fill per vertex. Native cumulative +/-8m limit is also retained.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 7f), Array.Empty<object>())); Bridges = ((BaseUnityPlugin)this).Config.Bind<bool>("Bridges", "Automatic Bridges", true, "Keep a crossing above water/deep depressions and build stone piers. Recalculate plans after changing bridge settings."); BridgeThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("Bridges", "Minimum Gap", 2f, new ConfigDescription("Use piers instead of filling a depression deeper than this many metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 7f), Array.Empty<object>())); MaxPierHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Bridges", "Maximum Pier Height", 80f, new ConfigDescription("Maximum height from the seabed/ground to the track bed. Stone is charged for every native pillar block.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(4f, 128f), Array.Empty<object>())); try { RailBridge.Bind(); PrefabManager.OnVanillaPrefabsAvailable += Registry.Register; Support.Bind(); harmony = new Harmony("local.railroads.automation"); harmony.PatchAll(typeof(Plugin).Assembly); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Railroads Automation 0.3.2: stone bridges and RtDOcean scenery clearance; English and Russian localization ready."); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)L.Render(ex.ToString(), "English")); ((Behaviour)this).enabled = false; } } private void Update() { Window.Tick(); if (ZDOMan.instance != world) { world = ZDOMan.instance; RailBridge.Reset(); Window.Hide(); } if (!Object.op_Implicit((Object)(object)ZNet.instance) || !Object.op_Implicit((Object)(object)ZNetScene.instance) || !Object.op_Implicit((Object)(object)ZoneSystem.instance) || WorldGenerator.instance == null || world == null || Time.unscaledTime < next) { return; } next = Time.unscaledTime + 1f; try { RailBridge.Ready(); if (!ZNet.instance.IsServer()) { return; } double timeSeconds = ZNet.instance.GetTimeSeconds(); ZDO[] array = RailBridge.All.Where((ZDO z) => z.GetPrefab() == Registry.CampHash).ToArray(); foreach (ZDO val in array) { if (val.GetOwner() == 0L && !RailBridge.Busy(val)) { val.SetOwner(ZNet.GetUID()); } if (val.IsOwner()) { Engine.Tick(val, timeSeconds); } } } catch (Exception ex) { if (Time.unscaledTime >= errorAt) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Construction paused: " + ex.GetBaseException().Message)); errorAt = Time.unscaledTime + 15f; } } } private void OnDestroy() { Window.Dispose(); PrefabManager.OnVanillaPrefabsAvailable -= Registry.Register; Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } } internal static class Support { [HarmonyPatch(typeof(WearNTear), "UpdateSupport")] private static class Set { private static bool Prefix(WearNTear __instance) { if (!Protected(__instance)) { return true; } float num = maximum(__instance); value.Invoke(__instance) = num; ZNetView component = ((Component)__instance).GetComponent<ZNetView>(); if (component.IsOwner()) { component.GetZDO().Set(ZDOVars.s_support, num); } return false; } } [HarmonyPatch(typeof(WearNTear), "HaveSupport")] private static class Have { private static void Postfix(WearNTear __instance, ref bool __result) { if (Protected(__instance)) { __result = true; } } } [HarmonyPatch(typeof(WearNTear), "GetSupport")] private static class Get { private static void Postfix(WearNTear __instance, ref float __result) { if (Protected(__instance)) { __result = maximum(__instance); } } } private static FieldRef<WearNTear, float> value; private static Func<WearNTear, float> maximum; internal static void Bind() { value = AccessTools.FieldRefAccess<WearNTear, float>("m_support"); maximum = AccessTools.MethodDelegate<Func<WearNTear, float>>(AccessTools.Method(typeof(WearNTear), "GetMaxSupport", (Type[])null, (Type[])null), (object)null, true); } private static bool Protected(WearNTear wear) { ZNetView component = ((Component)wear).GetComponent<ZNetView>(); if (Plugin.IgnoreSupport.Value && Object.op_Implicit((Object)(object)component) && component.IsValid()) { return !string.IsNullOrEmpty(component.GetZDO().GetString(Keys.JobTag, "")); } return false; } } internal static class RailAnchors { private sealed class End { internal int Line; internal int Side; internal V Point; internal V Outward; } private static End Endpoint(V[][] lines, int index, int side) { V[] array = lines[index]; int num = ((side != 0) ? (array.Length - 1) : 0); return new End { Line = index, Side = side, Point = array[num], Outward = (array[num] - array[(side == 0) ? 1 : (num - 1)]).Unit }; } private static List<End> Connections(End current, V[][] lines) { List<End> list = new List<End>(); for (int i = 0; i < lines.Length; i++) { if (i == current.Line) { continue; } for (int j = 0; j < 2; j++) { End end = Endpoint(lines, i, j); if ((end.Point - current.Point).Length <= 0.3 && V.Dot(end.Outward, current.Outward) < -0.5) { list.Add(end); } } } return list; } internal static Goal Select(V requested, V heading, V[][] lines, bool[] allowed, bool start) { if (lines.Length != allowed.Length || lines.Any((V[] p) => p.Length < 2)) { throw new InvalidOperationException(L.Key("raa_railanchors_001")); } End end = null; double num = 3.0; for (int num2 = 0; num2 < lines.Length; num2++) { if (!allowed[num2]) { continue; } for (int num3 = 0; num3 < 2; num3++) { End end2 = Endpoint(lines, num2, num3); double length = (end2.Point - requested).Length; if (!(length >= num) && (!start || !(V.Dot(end2.Outward, heading) <= 0.2)) && (start || Connections(end2, lines).Count <= 0)) { end = end2; num = length; } } } if (end == null) { foreach (V[] path in lines) { if (Distance(requested, path) < 1.25) { throw new InvalidOperationException(L.Key("raa_railanchors_002") + (start ? L.Key("raa_railanchors_003") : L.Key("raa_railanchors_004")) + L.Key("raa_railanchors_005")); } } return new Goal { Position = requested, Direction = heading, Tolerance = 1.25 }; } List<V[]> list = new List<V[]>(); double num5 = 0.0; HashSet<string> hashSet = new HashSet<string>(); if (start) { while (true) { if (!hashSet.Add(end.Line + ":" + end.Side)) { throw new InvalidOperationException(L.Key("raa_railanchors_006")); } List<End> list2 = Connections(end, lines); if (list2.Count == 0) { break; } if (list2.Count != 1) { throw new InvalidOperationException(L.Key("raa_railanchors_007")); } End end3 = list2[0]; V[] array = ((end3.Side == 0) ? lines[end3.Line] : lines[end3.Line].Reverse().ToArray()); for (int num6 = 1; num6 < array.Length; num6++) { num5 += (array[num6] - array[num6 - 1]).Length; } if (num5 > 512.0 || list.Count >= 256) { throw new InvalidOperationException(L.Key("raa_railanchors_008")); } list.Add(array); end = Endpoint(lines, end3.Line, 1 - end3.Side); } } return new Goal { Position = end.Point, Direction = (start ? end.Outward : (-end.Outward)), MatchDirection = !start, Tolerance = 0.24, ExistingLength = num5, Passed = list.ToArray() }; } private static double Distance(V point, V[] path) { double num = double.PositiveInfinity; for (int i = 0; i + 1 < path.Length; i++) { V v = path[i + 1] - path[i]; double num2 = V.Dot(v, v); double num3 = ((num2 < 1E-12) ? 0.0 : Math.Max(0.0, Math.Min(1.0, V.Dot(point - path[i], v) / num2))); num = Math.Min(num, (point - path[i] - v * num3).Length); } return num; } internal static bool AlreadyPassed(V point, Goal start) { if (start.Passed != null) { return start.Passed.Any((V[] p) => Distance(point, p) <= 1.25); } return false; } } internal static class RailBridge { internal static readonly string[] Allowed = new string[17] { "bf_track_straight_32", "bf_track_straight_16", "bf_track_straight_8", "bf_track_straight_4", "bf_track_straight", "bf_track_straight_1", "bf_track_curve_r8_22", "bf_track_curve_r8_45", "bf_track_curve_r8_90", "bf_track_curve_r16_22", "bf_track_curve_r16_45", "bf_track_slope_gentle", "bf_track_slope_steep", "bf_track_slope_bottom_gentle", "bf_track_slope_top_gentle", "bf_track_slope_bottom_steep", "bf_track_slope_top_steep" }; private static Type railTrack; private static Type station; private static PropertyInfo lines; private static MethodInfo tracks; private static MethodInfo containerLoad; private static MethodInfo isGenerated; private static FieldInfo objects; private static readonly Dictionary<string, V[]> shapes = new Dictionary<string, V[]>(); internal static readonly List<Primitive> Primitives = new List<Primitive>(); internal static IEnumerable<ZDO> All { get { if (ZDOMan.instance != null) { return ((Dictionary<ZDOID, ZDO>)objects.GetValue(ZDOMan.instance)).Values; } return Enumerable.Empty<ZDO>(); } } internal static List<ZDO> Tracks => (List<ZDO>)tracks.Invoke(null, null); internal static double BedOffset => shapes["bf_track_straight"][0].y; internal static V V3(Vector3 p) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) return new V(p.x, p.y, p.z); } internal static Vector3 U(V p) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) return new Vector3((float)p.x, (float)p.y, (float)p.z); } internal static void Bind() { Assembly assembly = ((object)Chainloader.PluginInfos["vladasz.railroads"].Instance).GetType().Assembly; railTrack = assembly.GetType("Blackforge.RailTrack", throwOnError: true); station = assembly.GetType("Blackforge.Station", throwOnError: true); lines = railTrack.GetProperty("Lines"); tracks = assembly.GetType("Blackforge.Scan", throwOnError: true).GetProperty("Tracks").GetGetMethod(); objects = AccessTools.Field(typeof(ZDOMan), "m_objectsByID"); containerLoad = AccessTools.Method(typeof(Container), "Load", Type.EmptyTypes, (Type[])null); isGenerated = AccessTools.Method(typeof(ZoneSystem), "IsZoneGenerated", (Type[])null, (Type[])null); if (lines == null || tracks == null || objects == null || containerLoad == null || isGenerated == null) { throw new MissingMemberException(L.Key("raa_railbridge_001")); } } internal static void Ready() { if (Primitives.Count > 0) { return; } try { string[] allowed = Allowed; foreach (string text in allowed) { GameObject prefab = ZNetScene.instance.GetPrefab(text); if ((Object)(object)prefab == (Object)null) { throw new InvalidOperationException(L.Key("raa_railbridge_002") + text); } Component component = prefab.GetComponent(railTrack); List<Vector3[]> list = (List<Vector3[]>)lines.GetValue(component, null); if (list.Count != 1 || list[0].Length < 2) { throw new InvalidOperationException(L.Key("raa_railbridge_003") + text); } V[] array = list[0].Select(V3).ToArray(); shapes[text] = array; double num = 0.0; for (int j = 1; j < array.Length; j++) { num += (array[j] - array[j - 1]).Length; } Primitives.Add(new Primitive { Prefab = text, Points = array, Length = num }); Primitives.Add(new Primitive { Prefab = text, Points = array.Reverse().ToArray(), Length = num }); } } catch { Reset(); throw; } } internal static void Reset() { Primitives.Clear(); shapes.Clear(); } internal static List<Cost> Costs(Segment segment) { List<Cost> list = TrackCosts(segment); int num = BridgeRules.StoneCost(segment.Piers); if (num > 0) { list.Add(new Cost { Prefab = "Stone", Amount = num }); } return (from c in list group c by c.Prefab into g select new Cost { Prefab = g.Key, Amount = g.Sum((Cost c) => c.Amount) }).ToList(); } internal static List<Cost> TrackCosts(Segment segment) { if (!shapes.ContainsKey(segment.Prefab)) { throw new InvalidOperationException(L.Key("raa_railbridge_004")); } return (from r in ZNetScene.instance.GetPrefab(segment.Prefab).GetComponent<Piece>().m_resources where Object.op_Implicit((Object)(object)r.m_resItem) && r.m_amount > 0 select new Cost { Prefab = ((Object)((Component)r.m_resItem).gameObject).name, Amount = r.m_amount }).ToList(); } internal static string TextInventory(ZDO site) { byte[] byteArray = site.GetByteArray(ZDOVars.s_items, (byte[])null); if (byteArray != null) { return Convert.ToBase64String(byteArray); } return ""; } internal static Inventory Inventory(string text) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown Inventory val = new Inventory("Railroads Automation", (Sprite)null, 8, 8); if (tex