Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of HylandHelper v0.3.1
HylandHelper.BridgeMod.dll
Decompiled 2 weeks 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.Globalization; using System.IO; using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using HylandHelper.BridgeContracts; using HylandHelper.BridgeMod; using MelonLoader; using MelonLoader.Utils; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: InternalsVisibleTo("HylandHelper.BridgeMod.Tests")] [assembly: MelonInfo(typeof(HylandHelperBridgeMod), "Hyland Helper Bridge", "0.3.1", "MadJag Studios", null)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("MadJag Studios")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright © 2026 MadJag Studios")] [assembly: AssemblyDescription("Hyland Helper bridge for Schedule I")] [assembly: AssemblyFileVersion("0.3.1.0")] [assembly: AssemblyInformationalVersion("0.3.1")] [assembly: AssemblyProduct("Hyland Helper")] [assembly: AssemblyTitle("HylandHelper.BridgeMod")] [assembly: AssemblyVersion("0.3.1.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } public static class GeneratedLayoutManifest { public const int SchemaVersion = 1; public const string GameVersion = "0.4.6f13"; public const string DumpSha256 = "e8c3c5af34e43a0ce12ef2c742ec7b040e0e94a218bcd292c189943a53144bf1"; public const string LayoutRevision = "g1-7b34d3b8a094343742351e1a89e697fdc49dc979117c30e416311233be3b4a90"; public const string CatalogRevision = "c1-3ac35145ecefb9411a19fb5ace0c65dd5300ceccf5bc4273edd0222500b4f24b"; } namespace HylandHelper.BridgeContracts { public static class BridgeContract { public const string SchemaVersion = "1.0.0"; } public enum BridgeEnvelopeType { Heartbeat, Snapshot, Capabilities, SessionEvent, Ingest } public enum BridgeCapabilityStatus { Present, Partial, Unavailable, Degraded } public sealed class BridgeEnvelope { [JsonPropertyName("envelopeType")] public string EnvelopeType { get; set; } = "heartbeat"; [JsonPropertyName("schemaVersion")] public string SchemaVersion { get; set; } = "1.0.0"; [JsonPropertyName("modVersion")] public string ModVersion { get; set; } = ""; [JsonPropertyName("gameVersion")] public string GameVersion { get; set; } = ""; [JsonPropertyName("melonLoaderVersion")] public string MelonLoaderVersion { get; set; } = ""; [JsonPropertyName("saveFingerprint")] public BridgeSaveFingerprint SaveFingerprint { get; set; } = new BridgeSaveFingerprint(); [JsonPropertyName("sequence")] public long Sequence { get; set; } [JsonPropertyName("sentAt")] public string SentAt { get; set; } = ""; [JsonPropertyName("capabilities")] public BridgeCapabilities Capabilities { get; set; } = new BridgeCapabilities(); [JsonPropertyName("snapshot")] public BridgeSnapshot? Snapshot { get; set; } [JsonPropertyName("session")] public BridgeSessionEvent? Session { get; set; } } public sealed class BridgeSaveFingerprint { [JsonPropertyName("slotId")] public string SlotId { get; set; } = ""; [JsonPropertyName("steamIdHash")] public string? SteamIdHash { get; set; } [JsonPropertyName("fingerprint")] public string Fingerprint { get; set; } = ""; } public sealed class BridgeCapabilities { [JsonPropertyName("slices")] public Dictionary<string, BridgeCapabilitySlice> Slices { get; set; } = new Dictionary<string, BridgeCapabilitySlice>(); [JsonPropertyName("features")] public Dictionary<string, BridgeFeatureCapability>? Features { get; set; } } public sealed class BridgeFeatureCapability { [JsonPropertyName("supported")] public bool Supported { get; set; } [JsonPropertyName("protocolVersion")] public int ProtocolVersion { get; set; } } public sealed class BridgeCapabilitySlice { [JsonPropertyName("status")] public string Status { get; set; } = "unavailable"; [JsonPropertyName("source")] public string Source { get; set; } = "notSupported"; [JsonPropertyName("reason")] public string? Reason { get; set; } [JsonPropertyName("gameDataType")] public string? GameDataType { get; set; } [JsonPropertyName("gameDataVersion")] public int? GameDataVersion { get; set; } } public sealed class BridgeSnapshot { [JsonPropertyName("capturedAt")] public string CapturedAt { get; set; } = ""; [JsonPropertyName("status")] public string Status { get; set; } = "partial"; [JsonPropertyName("slices")] public List<string> Slices { get; set; } = new List<string>(); [JsonPropertyName("money")] public BridgeMoneySnapshot? Money { get; set; } [JsonPropertyName("rank")] public BridgeRankSnapshot? Rank { get; set; } [JsonPropertyName("time")] public BridgeTimeSnapshot? Time { get; set; } [JsonPropertyName("inventory")] public BridgeInventorySnapshot? Inventory { get; set; } [JsonPropertyName("properties")] public BridgePropertiesSnapshot? Properties { get; set; } [JsonPropertyName("products")] public BridgeProductsSnapshot? Products { get; set; } [JsonPropertyName("layout")] public BridgeLayoutSnapshot? Layout { get; set; } [JsonPropertyName("warnings")] public List<string> Warnings { get; set; } = new List<string>(); } public sealed class BridgeMoneySnapshot { [JsonPropertyName("onlineBalance")] public decimal OnlineBalance { get; set; } [JsonPropertyName("networth")] public decimal Networth { get; set; } [JsonPropertyName("lifetimeEarnings")] public decimal LifetimeEarnings { get; set; } [JsonPropertyName("cashOnHandTotal")] public decimal CashOnHandTotal { get; set; } [JsonPropertyName("appProfileCash")] public decimal AppProfileCash { get; set; } [JsonPropertyName("appProfileCashSource")] public string AppProfileCashSource { get; set; } = "cashOnHandTotal"; [JsonPropertyName("cashAggregation")] public BridgeCashAggregation? CashAggregation { get; set; } } public sealed class BridgeCashAggregation { [JsonPropertyName("includesPlayerInventory")] public bool IncludesPlayerInventory { get; set; } [JsonPropertyName("includesStorage")] public bool IncludesStorage { get; set; } [JsonPropertyName("missingContainers")] public List<string> MissingContainers { get; set; } = new List<string>(); } public sealed class BridgeRankSnapshot { [JsonPropertyName("rank")] public string? Rank { get; set; } [JsonPropertyName("tier")] public int? Tier { get; set; } [JsonPropertyName("xp")] public decimal? Xp { get; set; } [JsonPropertyName("totalXp")] public decimal? TotalXp { get; set; } [JsonPropertyName("unlockedRegions")] public List<string> UnlockedRegions { get; set; } = new List<string>(); } public sealed class BridgeTimeSnapshot { [JsonPropertyName("timeOfDay")] public decimal? TimeOfDay { get; set; } [JsonPropertyName("elapsedDays")] public int? ElapsedDays { get; set; } [JsonPropertyName("playtimeSeconds")] public decimal? PlaytimeSeconds { get; set; } } public sealed class BridgeInventorySnapshot { [JsonPropertyName("totalStacks")] public int TotalStacks { get; set; } [JsonPropertyName("totalQuantity")] public decimal TotalQuantity { get; set; } [JsonPropertyName("cashOnHandTotal")] public decimal CashOnHandTotal { get; set; } [JsonPropertyName("sources")] public List<BridgeInventorySourceSummary> Sources { get; set; } = new List<BridgeInventorySourceSummary>(); [JsonPropertyName("items")] public List<BridgeInventoryItemStack> Items { get; set; } = new List<BridgeInventoryItemStack>(); [JsonPropertyName("truncated")] public bool Truncated { get; set; } } public sealed class BridgeInventorySourceSummary { [JsonPropertyName("source")] public string Source { get; set; } = ""; [JsonPropertyName("container")] public string? Container { get; set; } [JsonPropertyName("itemStacks")] public int ItemStacks { get; set; } [JsonPropertyName("cashOnHand")] public decimal CashOnHand { get; set; } } public sealed class BridgeInventoryItemStack { [JsonPropertyName("id")] public string Id { get; set; } = ""; [JsonPropertyName("quantity")] public decimal Quantity { get; set; } [JsonPropertyName("source")] public string Source { get; set; } = ""; [JsonPropertyName("container")] public string? Container { get; set; } [JsonPropertyName("dataType")] public string? DataType { get; set; } [JsonPropertyName("quality")] public string? Quality { get; set; } [JsonPropertyName("packagingId")] public string? PackagingId { get; set; } } public sealed class BridgePropertiesSnapshot { [JsonPropertyName("ownedCount")] public int OwnedCount { get; set; } [JsonPropertyName("totalCount")] public int TotalCount { get; set; } [JsonPropertyName("properties")] public List<BridgePropertySummary> Properties { get; set; } = new List<BridgePropertySummary>(); } public sealed class BridgePropertySummary { [JsonPropertyName("code")] public string Code { get; set; } = ""; [JsonPropertyName("kind")] public string Kind { get; set; } = ""; [JsonPropertyName("isOwned")] public bool IsOwned { get; set; } [JsonPropertyName("objectCount")] public int ObjectCount { get; set; } [JsonPropertyName("employeeCount")] public int EmployeeCount { get; set; } [JsonPropertyName("launderingOperationCount")] public int LaunderingOperationCount { get; set; } } public sealed class BridgeLayoutSnapshot { [JsonPropertyName("manifest")] public BridgeLayoutManifest? Manifest { get; set; } [JsonPropertyName("properties")] public List<BridgeLayoutProperty> Properties { get; set; } = new List<BridgeLayoutProperty>(); [JsonPropertyName("truncated")] public bool Truncated { get; set; } } public sealed class BridgeLayoutManifest { [JsonPropertyName("schemaVersion")] public int SchemaVersion { get; set; } [JsonPropertyName("gameVersion")] public string GameVersion { get; set; } = ""; [JsonPropertyName("dumpSha256")] public string DumpSha256 { get; set; } = ""; [JsonPropertyName("layoutRevision")] public string LayoutRevision { get; set; } = ""; } public sealed class BridgeLayoutProperty { [JsonPropertyName("propertyCode")] public string PropertyCode { get; set; } = ""; [JsonPropertyName("objects")] public List<BridgeLayoutObject> Objects { get; set; } = new List<BridgeLayoutObject>(); [JsonPropertyName("truncated")] public bool Truncated { get; set; } [JsonPropertyName("skippedObjectCount")] public int SkippedObjectCount { get; set; } } public sealed class BridgeLayoutObject { [JsonPropertyName("itemId")] public string? ItemId { get; set; } [JsonPropertyName("objectGuid")] public string? ObjectGuid { get; set; } [JsonPropertyName("gridGuid")] public string? GridGuid { get; set; } [JsonPropertyName("x")] public int? X { get; set; } [JsonPropertyName("y")] public int? Y { get; set; } [JsonPropertyName("rotation")] public int? Rotation { get; set; } [JsonPropertyName("hostTileOwnerGuid")] public string? HostTileOwnerGuid { get; set; } [JsonPropertyName("footprint")] public List<BridgeLayoutFootprintTile>? Footprint { get; set; } [JsonPropertyName("dataType")] public string DataType { get; set; } = ""; } public sealed class BridgeLayoutFootprintTile { [JsonPropertyName("tileIndex")] public int TileIndex { get; set; } [JsonPropertyName("x")] public int X { get; set; } [JsonPropertyName("y")] public int Y { get; set; } } public sealed class BridgeProductsSnapshot { [JsonPropertyName("discoveredCount")] public int DiscoveredCount { get; set; } [JsonPropertyName("discoveredProducts")] public List<string> DiscoveredProducts { get; set; } = new List<string>(); [JsonPropertyName("listedProducts")] public List<string> ListedProducts { get; set; } = new List<string>(); [JsonPropertyName("activeMixOperation")] public BridgeActiveMixOperation? ActiveMixOperation { get; set; } [JsonPropertyName("isMixComplete")] public bool? IsMixComplete { get; set; } [JsonPropertyName("recipeCount")] public int RecipeCount { get; set; } [JsonPropertyName("recipes")] public List<BridgeMixRecipeSummary> Recipes { get; set; } = new List<BridgeMixRecipeSummary>(); [JsonPropertyName("truncated")] public bool Truncated { get; set; } } public sealed class BridgeActiveMixOperation { [JsonPropertyName("productId")] public string? ProductId { get; set; } [JsonPropertyName("ingredientId")] public string? IngredientId { get; set; } } public sealed class BridgeMixRecipeSummary { [JsonPropertyName("product")] public string Product { get; set; } = ""; [JsonPropertyName("mixer")] public string Mixer { get; set; } = ""; [JsonPropertyName("output")] public string Output { get; set; } = ""; } public sealed class BridgeSessionEvent { [JsonPropertyName("eventType")] public string EventType { get; set; } = "heartbeat"; [JsonPropertyName("reason")] public string? Reason { get; set; } } public sealed class BridgePendingMix { [JsonPropertyName("mixId")] public string? MixId { get; set; } [JsonPropertyName("productId")] public string ProductId { get; set; } = ""; [JsonPropertyName("ingredientIds")] public List<string> IngredientIds { get; set; } = new List<string>(); [JsonPropertyName("name")] public string? Name { get; set; } [JsonPropertyName("capturedAt")] public string CapturedAt { get; set; } = ""; [JsonPropertyName("source")] public string Source { get; set; } = "inGameTile"; [JsonPropertyName("steps")] public List<BridgePendingMixStep>? Steps { get; set; } } public sealed class BridgePendingMixStep { [JsonPropertyName("ingredientId")] public string IngredientId { get; set; } = ""; [JsonPropertyName("outputProductId")] public string? OutputProductId { get; set; } [JsonPropertyName("outputEffects")] public List<string>? OutputEffects { get; set; } } public enum BridgeLayoutCaptureOutcome { Captured, CapturedPartial, NothingBuilt, NoSupportedObjects, TargetNotFound, TargetUnowned, TargetUnreadable, SaveUnavailable } public enum BridgeLayoutObjectKind { Unsupported, Grid, Dependent } public sealed class BridgeLayoutCaptureResult { public BridgeLayoutCaptureOutcome Outcome { get; } public string Reason { get; } public BridgeLayoutProperty? Property { get; } public int SkippedObjectCount => Property?.SkippedObjectCount ?? 0; public bool Succeeded { get { BridgeLayoutCaptureOutcome outcome = Outcome; if ((uint)outcome <= 1u) { return true; } return false; } } public BridgeLayoutCaptureResult(BridgeLayoutCaptureOutcome outcome, string reason, BridgeLayoutProperty? property = null) { Outcome = outcome; Reason = reason; Property = property; } } public static class BridgeLayoutSaveCapture { private sealed record LayoutSource(string DirectoryName, string[] DataTypes); private const int MaxLayoutObjectsPerProperty = 5000; private const int MaxContractStringLength = 128; private const long MaxSaveJsonBytes = 1048576L; public static bool TryReadOwnedProperty(string saveDirectory, string propertyCode, out BridgeLayoutProperty? property) { BridgeLayoutCaptureResult bridgeLayoutCaptureResult = ReadOwnedProperty(saveDirectory, propertyCode); property = (bridgeLayoutCaptureResult.Succeeded ? bridgeLayoutCaptureResult.Property : null); return bridgeLayoutCaptureResult.Succeeded; } public static BridgeLayoutCaptureResult ReadOwnedProperty(string saveDirectory, string propertyCode) { if (string.IsNullOrWhiteSpace(saveDirectory) || string.IsNullOrWhiteSpace(propertyCode) || propertyCode.Length > 128 || !Directory.Exists(saveDirectory) || !TryReadSaveGameVersion(saveDirectory, out string gameVersion)) { return Result(BridgeLayoutCaptureOutcome.SaveUnavailable, "save_unavailable"); } string text = NormalizePropertyIdentity(propertyCode); if (string.IsNullOrWhiteSpace(text)) { return Result(BridgeLayoutCaptureOutcome.TargetNotFound, "target_not_found"); } BridgeLayoutCaptureResult bridgeLayoutCaptureResult = null; LayoutSource[] array = new LayoutSource[2] { new LayoutSource("Properties", new string[2] { "PropertyData", "ManorData" }), new LayoutSource("Businesses", new string[1] { "BusinessData" }) }; foreach (LayoutSource layoutSource in array) { string path = Path.Combine(saveDirectory, layoutSource.DirectoryName); if (!Directory.Exists(path)) { continue; } IEnumerable<string> enumerable; try { enumerable = Directory.EnumerateFiles(path, "*.json").OrderBy<string, string>((string result) => result, StringComparer.Ordinal).ToArray(); } catch (IOException) { return Result(BridgeLayoutCaptureOutcome.SaveUnavailable, "save_unavailable"); } catch (UnauthorizedAccessException) { return Result(BridgeLayoutCaptureOutcome.SaveUnavailable, "save_unavailable"); } foreach (string item in enumerable) { string a = NormalizePropertyIdentity(Path.GetFileNameWithoutExtension(item)); JsonDocument jsonDocument; try { jsonDocument = ReadDocument(item); } catch (IOException) { if (string.Equals(a, text, StringComparison.Ordinal)) { return Result(BridgeLayoutCaptureOutcome.TargetUnreadable, "target_unreadable"); } continue; } catch (UnauthorizedAccessException) { if (string.Equals(a, text, StringComparison.Ordinal)) { return Result(BridgeLayoutCaptureOutcome.TargetUnreadable, "target_unreadable"); } continue; } catch (JsonException) { if (string.Equals(a, text, StringComparison.Ordinal)) { return Result(BridgeLayoutCaptureOutcome.TargetUnreadable, "target_unreadable"); } continue; } using (jsonDocument) { JsonElement rootElement = jsonDocument.RootElement; if (rootElement.ValueKind != JsonValueKind.Object) { if (string.Equals(a, text, StringComparison.Ordinal)) { return Result(BridgeLayoutCaptureOutcome.TargetUnreadable, "target_unreadable"); } continue; } string text2 = GetString(rootElement, "DataType"); if (!layoutSource.DataTypes.Contains<string>(text2 ?? "", StringComparer.Ordinal)) { if (string.Equals(a, text, StringComparison.Ordinal)) { return Result(BridgeLayoutCaptureOutcome.TargetUnreadable, "target_unreadable"); } continue; } string text3 = GetString(rootElement, "PropertyCode"); if (string.IsNullOrWhiteSpace(text3)) { text3 = Path.GetFileNameWithoutExtension(item); } if (string.Equals(NormalizePropertyIdentity(text3), text, StringComparison.Ordinal)) { if (bridgeLayoutCaptureResult != null) { return Result(BridgeLayoutCaptureOutcome.TargetUnreadable, "target_unreadable"); } if (!IsVersionCompatible(rootElement, gameVersion)) { return Result(BridgeLayoutCaptureOutcome.TargetUnreadable, "target_unreadable"); } if (GetBool(rootElement, "IsOwned") != true) { return Result(BridgeLayoutCaptureOutcome.TargetUnowned, "target_unowned"); } bridgeLayoutCaptureResult = ReadMatchedProperty(rootElement, text3); } } } } return bridgeLayoutCaptureResult ?? Result(BridgeLayoutCaptureOutcome.TargetNotFound, "target_not_found"); } public static bool TryParseLayoutObject(JsonElement item, out BridgeLayoutObject layoutObject, out bool mountedChildInvalid) { mountedChildInvalid = false; string text = ((item.ValueKind == JsonValueKind.Object) ? (GetString(item, "DataType") ?? "") : ""); layoutObject = new BridgeLayoutObject { DataType = ((text.Length > 128) ? text.Substring(0, 128) : text) }; if (item.ValueKind != JsonValueKind.Object || !item.TryGetProperty("BaseData", out var value) || value.ValueKind != JsonValueKind.String) { return false; } try { using JsonDocument jsonDocument = JsonDocument.Parse(value.GetString() ?? "{}"); JsonElement rootElement = jsonDocument.RootElement; layoutObject.ObjectGuid = BoundedIdentifier(GetString(rootElement, "GUID")); layoutObject.GridGuid = BoundedIdentifier(GetString(rootElement, "GridGUID")); layoutObject.Rotation = GetIntegralInt(rootElement, "Rotation"); if (rootElement.TryGetProperty("OriginCoordinate", out var value2) && value2.ValueKind == JsonValueKind.Object) { layoutObject.X = GetIntegralInt(value2, "x"); layoutObject.Y = GetIntegralInt(value2, "y"); } if (rootElement.TryGetProperty("ItemString", out var value3) && value3.ValueKind == JsonValueKind.String) { using JsonDocument jsonDocument2 = JsonDocument.Parse(value3.GetString() ?? "{}"); layoutObject.ItemId = BoundedIdentifier(GetString(jsonDocument2.RootElement, "ID")); } if (IsMountedChild(layoutObject.DataType)) { if (!TryReadProceduralFootprint(rootElement, out string hostTileOwnerGuid, out List<BridgeLayoutFootprintTile> footprint)) { mountedChildInvalid = true; } else { layoutObject.HostTileOwnerGuid = hostTileOwnerGuid; layoutObject.Footprint = footprint; } } } catch (Exception) { } if (IsMountedChild(layoutObject.DataType)) { layoutObject.GridGuid = null; layoutObject.X = null; layoutObject.Y = null; if (mountedChildInvalid) { layoutObject.HostTileOwnerGuid = null; layoutObject.Footprint = null; } } return true; } public static BridgeLayoutObjectKind ClassifyLayoutObject(BridgeLayoutObject? layoutObject) { if (layoutObject == null) { return BridgeLayoutObjectKind.Unsupported; } if (IsMountedChild(layoutObject.DataType)) { if (!string.IsNullOrWhiteSpace(layoutObject.ItemId) && IsNonEmptyGuid(layoutObject.ObjectGuid) && layoutObject.Rotation.HasValue && IsNonEmptyGuid(layoutObject.HostTileOwnerGuid)) { List<BridgeLayoutFootprintTile> footprint = layoutObject.Footprint; if (footprint != null && footprint.Count > 0 && layoutObject.Footprint.All((BridgeLayoutFootprintTile tile) => tile != null && tile.TileIndex >= 0) && layoutObject.Footprint.Select((BridgeLayoutFootprintTile tile) => tile.TileIndex).Distinct().Count() == layoutObject.Footprint.Count) { return BridgeLayoutObjectKind.Dependent; } } return BridgeLayoutObjectKind.Unsupported; } if (string.IsNullOrWhiteSpace(layoutObject.ItemId) || !IsNonEmptyGuid(layoutObject.ObjectGuid) || !IsNonEmptyGuid(layoutObject.GridGuid) || !layoutObject.X.HasValue || !layoutObject.Y.HasValue || !layoutObject.Rotation.HasValue) { return BridgeLayoutObjectKind.Unsupported; } return BridgeLayoutObjectKind.Grid; } private static BridgeLayoutCaptureResult ReadMatchedProperty(JsonElement root, string code) { if (string.IsNullOrWhiteSpace(code) || code.Length > 128 || !root.TryGetProperty("Objects", out var value) || value.ValueKind != JsonValueKind.Array) { return Result(BridgeLayoutCaptureOutcome.TargetUnreadable, "target_unreadable"); } BridgeLayoutProperty bridgeLayoutProperty = new BridgeLayoutProperty { PropertyCode = code }; int num = 0; foreach (JsonElement item in value.EnumerateArray()) { num++; if (num > 5000) { return Result(BridgeLayoutCaptureOutcome.TargetUnreadable, "scope_limit_exceeded"); } if (!TryParseLayoutObject(item, out BridgeLayoutObject layoutObject, out bool mountedChildInvalid) || mountedChildInvalid || ClassifyLayoutObject(layoutObject) == BridgeLayoutObjectKind.Unsupported) { bridgeLayoutProperty.SkippedObjectCount++; } else { bridgeLayoutProperty.Objects.Add(layoutObject); } } bridgeLayoutProperty.Truncated = bridgeLayoutProperty.SkippedObjectCount > 0; if (num == 0) { return Result(BridgeLayoutCaptureOutcome.NothingBuilt, "nothing_built", bridgeLayoutProperty); } if (bridgeLayoutProperty.Objects.Count == 0) { return Result(BridgeLayoutCaptureOutcome.NoSupportedObjects, "no_supported_objects", bridgeLayoutProperty); } if (!bridgeLayoutProperty.Truncated) { return Result(BridgeLayoutCaptureOutcome.Captured, "captured", bridgeLayoutProperty); } return Result(BridgeLayoutCaptureOutcome.CapturedPartial, "partial_skipped", bridgeLayoutProperty); } private static bool TryReadSaveGameVersion(string directory, out string? gameVersion) { gameVersion = null; string[] array = new string[2] { "Metadata.json", "Game.json" }; foreach (string path in array) { try { using JsonDocument jsonDocument = ReadDocument(Path.Combine(directory, path)); string text = GetString(jsonDocument.RootElement, "GameVersion"); if (!string.IsNullOrWhiteSpace(text)) { gameVersion = text; return true; } } catch (IOException) { } catch (UnauthorizedAccessException) { } catch (JsonException) { } } return false; } private static JsonDocument ReadDocument(string path) { FileInfo fileInfo = new FileInfo(path); if (!fileInfo.Exists || fileInfo.Length > 1048576) { throw new IOException("save_json_unavailable"); } using FileStream utf8Json = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete); return JsonDocument.Parse(utf8Json); } private static bool IsVersionCompatible(JsonElement root, string gameVersion) { string text = GetString(root, "GameVersion"); if (!string.IsNullOrWhiteSpace(text)) { return string.Equals(text, gameVersion, StringComparison.Ordinal); } return true; } private static bool IsMountedChild(string dataType) { return string.Equals(dataType, "ProceduralGridItemData", StringComparison.Ordinal); } private static bool TryReadProceduralFootprint(JsonElement baseRoot, out string? hostTileOwnerGuid, out List<BridgeLayoutFootprintTile>? footprint) { hostTileOwnerGuid = null; footprint = null; if (!baseRoot.TryGetProperty("FootprintMatches", out var value) || value.ValueKind != JsonValueKind.Array) { return false; } List<BridgeLayoutFootprintTile> list = new List<BridgeLayoutFootprintTile>(); foreach (JsonElement item in value.EnumerateArray()) { if (item.ValueKind != JsonValueKind.Object || !item.TryGetProperty("FootprintCoordinate", out var value2) || value2.ValueKind != JsonValueKind.Object) { return false; } string text = BoundedIdentifier(GetString(item, "TileOwnerGUID")); int? integralInt = GetIntegralInt(item, "TileIndex"); int? integralInt2 = GetIntegralInt(value2, "x"); int? integralInt3 = GetIntegralInt(value2, "y"); if (!IsNonEmptyGuid(text) || !integralInt.HasValue || integralInt < 0 || !integralInt2.HasValue || !integralInt3.HasValue || (hostTileOwnerGuid != null && !string.Equals(hostTileOwnerGuid, text, StringComparison.OrdinalIgnoreCase))) { return false; } hostTileOwnerGuid = text; list.Add(new BridgeLayoutFootprintTile { TileIndex = integralInt.Value, X = integralInt2.Value, Y = integralInt3.Value }); } if (hostTileOwnerGuid == null || list.Count == 0 || list.Select((BridgeLayoutFootprintTile tile) => tile.TileIndex).Distinct().Count() != list.Count) { return false; } footprint = list; return true; } private static string? BoundedIdentifier(string? value) { if (value == null || value.Length > 128) { return null; } return value; } private static bool IsNonEmptyGuid(string? value) { if (Guid.TryParse(value, out var result)) { return result != Guid.Empty; } return false; } private static string? GetString(JsonElement root, string name) { if (!root.TryGetProperty(name, out var value) || value.ValueKind != JsonValueKind.String) { return null; } return value.GetString(); } private static bool? GetBool(JsonElement root, string name) { if (!root.TryGetProperty(name, out var value) || (value.ValueKind != JsonValueKind.True && value.ValueKind != JsonValueKind.False)) { return null; } return value.GetBoolean(); } private static int? GetIntegralInt(JsonElement root, string name) { if (!root.TryGetProperty(name, out var value) || !value.TryGetDecimal(out var value2)) { return null; } if (value2 != decimal.Truncate(value2) || value2 < -2147483648m || value2 > 2147483647m) { return null; } return (int)value2; } private static string NormalizePropertyIdentity(string? value) { if (!string.IsNullOrWhiteSpace(value)) { return new string(value.Where(char.IsLetterOrDigit).Select(char.ToLowerInvariant).ToArray()); } return ""; } private static BridgeLayoutCaptureResult Result(BridgeLayoutCaptureOutcome outcome, string reason, BridgeLayoutProperty? property = null) { return new BridgeLayoutCaptureResult(outcome, reason, property); } } public static class PendingMixLimits { public const int MaxChainSteps = 64; public const int MaxEffectsPerStep = 12; public const int MaxStringLength = 64; public static string OverLimitReason(int stepCount) { return $"Save/Track unavailable: this mix has {stepCount} steps; the shared limit is {64}."; } } public static class PhoneRecipeLimits { public const int MaxRecipes = 50; public const int MaxChainSteps = 64; public const int MaxEffects = 8; public const int MaxStringLength = 64; public const int MaxBodyBytes = 73728; public const int StaleGraceHours = 24; } public sealed class BridgePhoneRecipe { [JsonPropertyName("recipeId")] public string RecipeId { get; set; } = ""; [JsonPropertyName("name")] public string Name { get; set; } = ""; [JsonPropertyName("productId")] public string ProductId { get; set; } = ""; [JsonPropertyName("ingredientIds")] public List<string> IngredientIds { get; set; } = new List<string>(); [JsonPropertyName("effects")] public List<string>? Effects { get; set; } [JsonPropertyName("effectsAvailable")] public bool EffectsAvailable { get; set; } [JsonPropertyName("sellPrice")] public double SellPrice { get; set; } [JsonPropertyName("profit")] public double Profit { get; set; } [JsonPropertyName("profitMargin")] public double ProfitMargin { get; set; } [JsonPropertyName("profileMode")] public string ProfileMode { get; set; } = "standard"; [JsonPropertyName("source")] public string Source { get; set; } = "app-saved"; [JsonPropertyName("publishedAt")] public string PublishedAt { get; set; } = ""; [JsonPropertyName("expiresAt")] public string ExpiresAt { get; set; } = ""; } public sealed class BridgePhoneRecipeSnapshot { [JsonPropertyName("schemaVersion")] public int SchemaVersion { get; set; } = 1; [JsonPropertyName("snapshotId")] public string SnapshotId { get; set; } = ""; [JsonPropertyName("publishedAt")] public string PublishedAt { get; set; } = ""; [JsonPropertyName("expiresAt")] public string ExpiresAt { get; set; } = ""; [JsonPropertyName("omittedCount")] public int OmittedCount { get; set; } [JsonPropertyName("recipes")] public List<BridgePhoneRecipe> Recipes { get; set; } = new List<BridgePhoneRecipe>(); } public sealed class BridgeExchangeRequest { [JsonPropertyName("envelope")] public BridgeEnvelope Envelope { get; set; } = new BridgeEnvelope(); [JsonPropertyName("downlink")] public BridgeExchangeRequestDownlink Downlink { get; set; } = new BridgeExchangeRequestDownlink(); } public sealed class BridgeExchangeRequestDownlink { [JsonPropertyName("phoneRecipes")] [JsonIgnore(Condition = JsonIgnoreCondition.Never)] public string? PhoneRecipes { get; set; } [JsonPropertyName("advisorDispatches")] [JsonIgnore(Condition = JsonIgnoreCondition.Never)] public string? AdvisorDispatches { get; set; } } public sealed class BridgeExchangeResponse { [JsonPropertyName("ingest")] public BridgeIngestAcknowledgement Ingest { get; set; } = new BridgeIngestAcknowledgement(); [JsonPropertyName("downlink")] public BridgeExchangeResponseDownlink Downlink { get; set; } = new BridgeExchangeResponseDownlink(); [JsonPropertyName("pollHintSeconds")] public int? PollHintSeconds { get; set; } } public sealed class BridgeIngestAcknowledgement { [JsonPropertyName("stored")] public bool Stored { get; set; } [JsonPropertyName("stale")] public bool Stale { get; set; } [JsonPropertyName("sequence")] public long Sequence { get; set; } [JsonPropertyName("currentSequence")] public long? CurrentSequence { get; set; } [JsonPropertyName("receivedAt")] public string? ReceivedAt { get; set; } [JsonPropertyName("gameVersionChanged")] public bool? GameVersionChanged { get; set; } } public sealed class BridgeExchangeResponseDownlink { [JsonPropertyName("phoneRecipes")] public BridgePhoneRecipeExchangeSlice PhoneRecipes { get; set; } = new BridgePhoneRecipeExchangeSlice(); [JsonPropertyName("advisorDispatches")] public BridgeAdvisorDispatchExchangeSlice AdvisorDispatches { get; set; } = new BridgeAdvisorDispatchExchangeSlice(); } public sealed class BridgePhoneRecipeExchangeSlice { [JsonPropertyName("state")] public string State { get; set; } = "unsupported"; [JsonPropertyName("revision")] public string? Revision { get; set; } [JsonPropertyName("payload")] public BridgePhoneRecipeSnapshot? Payload { get; set; } [JsonPropertyName("retryAfterSeconds")] public int? RetryAfterSeconds { get; set; } } public sealed class BridgeAdvisorDispatchExchangeSlice { [JsonPropertyName("state")] public string State { get; set; } = "unsupported"; [JsonPropertyName("revision")] public string? Revision { get; set; } [JsonPropertyName("payload")] public BridgeAdvisorDispatchPayload? Payload { get; set; } [JsonPropertyName("retryAfterSeconds")] public int? RetryAfterSeconds { get; set; } } public sealed class BridgeAdvisorDispatchPayload { [JsonPropertyName("scopeGeneration")] public string ScopeGeneration { get; set; } = ""; [JsonPropertyName("capturedAt")] public string CapturedAt { get; set; } = ""; [JsonPropertyName("dispatches")] public List<BridgeAdvisorDispatchRecord> Dispatches { get; set; } = new List<BridgeAdvisorDispatchRecord>(); } public sealed class BridgeAdvisorDispatchRecord { [JsonPropertyName("id")] public string Id { get; set; } = ""; [JsonPropertyName("createdAt")] public string CreatedAt { get; set; } = ""; [JsonPropertyName("headline")] public string Headline { get; set; } = ""; [JsonPropertyName("body")] public string Body { get; set; } = ""; [JsonPropertyName("personaId")] public string PersonaId { get; set; } = ""; [JsonPropertyName("voiceVersion")] public string VoiceVersion { get; set; } = ""; [JsonPropertyName("triggerId")] public string TriggerId { get; set; } = ""; } public sealed class BridgeExchangeError { [JsonPropertyName("error")] public BridgeStructuredError Error { get; set; } = new BridgeStructuredError(); } public sealed class BridgeStructuredError { [JsonPropertyName("code")] public string Code { get; set; } = ""; [JsonPropertyName("message")] public string Message { get; set; } = ""; [JsonPropertyName("retriable")] public bool Retriable { get; set; } [JsonPropertyName("requiresRepair")] public string? RequiresRepair { get; set; } [JsonPropertyName("retryAfterSeconds")] public int? RetryAfterSeconds { get; set; } } public sealed class BridgeTileChallenge { [JsonPropertyName("version")] public int Version { get; set; } [JsonPropertyName("challenge")] public string Challenge { get; set; } = ""; [JsonPropertyName("tileBuild")] public string TileBuild { get; set; } = ""; [JsonPropertyName("protocolVersion")] public int ProtocolVersion { get; set; } } public static class GameDatasetIds { private static readonly Dictionary<string, string> CanonicalAliases = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) { ["ogkush"] = "og_kush", ["sourdiesel"] = "sour_diesel", ["greencrack"] = "green_crack", ["granddaddypurple"] = "granddaddy_purple", ["shroom"] = "shrooms", ["energydrink"] = "energy_drink", ["motoroil"] = "motor_oil", ["megabean"] = "mega_bean", ["flumedicine"] = "flu_medicine", ["horsesemen"] = "horse_semen", ["viagor"] = "viagra" }; private static readonly Dictionary<string, string> FriendlyLabels = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) { ["og_kush"] = "OG Kush", ["sour_diesel"] = "Sour Diesel", ["green_crack"] = "Green Crack", ["granddaddy_purple"] = "Granddaddy Purple", ["shrooms"] = "Shrooms", ["meth"] = "Meth", ["cocaine"] = "Cocaine", ["flu_medicine"] = "Flu Medicine", ["energy_drink"] = "Energy Drink", ["motor_oil"] = "Motor Oil", ["mega_bean"] = "Mega Bean", ["horse_semen"] = "Horse Semen", ["viagra"] = "Viagor" }; private static readonly HashSet<string> BaseProducts = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "og_kush", "sour_diesel", "green_crack", "granddaddy_purple", "meth", "cocaine", "shrooms" }; public static string Canonicalize(string value) { if (string.IsNullOrWhiteSpace(value)) { return value; } string text = value.Trim(); if (!CanonicalAliases.TryGetValue(text, out string value2)) { return text; } return value2; } public static bool IsBaseProduct(string value) { return BaseProducts.Contains(Canonicalize(value)); } public static string FriendlyName(string value) { string text = Canonicalize(value); if (FriendlyLabels.TryGetValue(text, out string value2)) { return value2; } string[] array = text.Replace('_', ' ').Split(' ', StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { if (array[i].Length != 0) { array[i] = char.ToUpperInvariant(array[i][0]) + array[i].Substring(1); } } return string.Join(" ", array); } } } namespace HylandHelper.BridgeMod { internal enum AdvisorDispatchCacheState { Empty, Fresh, Expired } internal sealed class AdvisorDispatchCacheRead { public AdvisorDispatchCacheState State { get; init; } public string? ScopeGeneration { get; init; } public string? Revision { get; init; } public DateTimeOffset? CapturedAt { get; init; } public List<BridgeAdvisorDispatchRecord> Dispatches { get; init; } = new List<BridgeAdvisorDispatchRecord>(); } internal sealed record AdvisorDispatchCacheCheckpoint(bool Exists, byte[]? Bytes); internal sealed class AdvisorDispatchCache { private sealed class AdvisorDispatchCacheDocument { [JsonPropertyName("version")] public int Version { get; set; } [JsonPropertyName("saveFingerprint")] public string SaveFingerprint { get; set; } = ""; [JsonPropertyName("scopeGeneration")] public string ScopeGeneration { get; set; } = ""; [JsonPropertyName("revision")] public string Revision { get; set; } = ""; [JsonPropertyName("capturedAt")] public string CapturedAt { get; set; } = ""; [JsonPropertyName("dispatches")] public List<BridgeAdvisorDispatchRecord> Dispatches { get; set; } = new List<BridgeAdvisorDispatchRecord>(); } public static readonly TimeSpan DispatchTtl = TimeSpan.FromDays(7.0); private const int MaxCacheBytes = 65536; private const int MaxDispatches = 20; private static readonly JsonSerializerOptions JsonOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true, WriteIndented = true }; private readonly string _path; private readonly Action<string, string> _replaceFile; private readonly Action<string> _deleteFile; public static string DefaultPath => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "AppData", "LocalLow", "TVGS", "Schedule I", "HylandHelper", "advisor-dispatches-cache.json"); public AdvisorDispatchCache(string path, Action<string, string>? replaceFile = null, Action<string>? deleteFile = null) { _path = path; _replaceFile = replaceFile ?? ((Action<string, string>)delegate(string source, string destination) { File.Move(source, destination, overwrite: true); }); _deleteFile = deleteFile ?? new Action<string>(File.Delete); } public bool Write(BridgeAdvisorDispatchPayload payload, string revision, DateTimeOffset now, string saveFingerprint) { if (!SaveGenerationIdentity.IsV2Fingerprint(saveFingerprint) || !CanWrite(payload, revision, now, out var capturedAt)) { return false; } AdvisorDispatchCacheDocument value = new AdvisorDispatchCacheDocument { Version = 2, SaveFingerprint = saveFingerprint, ScopeGeneration = payload.ScopeGeneration, Revision = revision, CapturedAt = capturedAt.ToString("O"), Dispatches = payload.Dispatches }; return WriteRawAtomic(JsonSerializer.SerializeToUtf8Bytes(value, JsonOptions)); } internal static bool CanWrite(BridgeAdvisorDispatchPayload payload, string revision, DateTimeOffset now) { DateTimeOffset capturedAt; return CanWrite(payload, revision, now, out capturedAt); } private static bool CanWrite(BridgeAdvisorDispatchPayload payload, string revision, DateTimeOffset now, out DateTimeOffset capturedAt) { if (!IsSafePayload(payload, revision, out capturedAt)) { return false; } DateTimeOffset result; return payload.Dispatches.All((BridgeAdvisorDispatchRecord record) => DateTimeOffset.TryParse(record.CreatedAt, out result) && now < result + DispatchTtl); } public AdvisorDispatchCacheRead Read(DateTimeOffset now, string saveFingerprint) { try { if (!SaveGenerationIdentity.IsV2Fingerprint(saveFingerprint) || !TryReadDocument(out AdvisorDispatchCacheDocument document) || !string.Equals(document.SaveFingerprint, saveFingerprint, StringComparison.Ordinal)) { return Empty(); } BridgeAdvisorDispatchPayload bridgeAdvisorDispatchPayload = new BridgeAdvisorDispatchPayload { ScopeGeneration = document.ScopeGeneration, CapturedAt = document.CapturedAt, Dispatches = (document.Dispatches ?? new List<BridgeAdvisorDispatchRecord>()) }; if (!IsSafePayload(bridgeAdvisorDispatchPayload, document.Revision, out var capturedAt)) { return Empty(); } DateTimeOffset result; List<BridgeAdvisorDispatchRecord> list = bridgeAdvisorDispatchPayload.Dispatches.Where((BridgeAdvisorDispatchRecord record) => DateTimeOffset.TryParse(record.CreatedAt, out result) && now < result + DispatchTtl).ToList(); return new AdvisorDispatchCacheRead { State = ((bridgeAdvisorDispatchPayload.Dispatches.Count <= 0 || list.Count != 0) ? AdvisorDispatchCacheState.Fresh : AdvisorDispatchCacheState.Expired), ScopeGeneration = bridgeAdvisorDispatchPayload.ScopeGeneration, Revision = document.Revision, CapturedAt = capturedAt, Dispatches = list }; } catch { return Empty(); } } public bool Clear() { try { if (File.Exists(_path)) { _deleteFile(_path); } return !File.Exists(_path); } catch { return false; } } public bool ClearForScope(string saveFingerprint) { try { if (!SaveGenerationIdentity.IsV2Fingerprint(saveFingerprint)) { return false; } if (!File.Exists(_path)) { return true; } if (!TryReadDocument(out AdvisorDispatchCacheDocument document) || !string.Equals(document.SaveFingerprint, saveFingerprint, StringComparison.Ordinal)) { return true; } return Clear(); } catch { return false; } } internal bool TryCapture(out AdvisorDispatchCacheCheckpoint checkpoint) { checkpoint = new AdvisorDispatchCacheCheckpoint(Exists: false, null); try { if (!File.Exists(_path)) { return true; } if (!IsBoundedFile()) { return false; } checkpoint = new AdvisorDispatchCacheCheckpoint(Exists: true, File.ReadAllBytes(_path)); return true; } catch { return false; } } internal bool Restore(AdvisorDispatchCacheCheckpoint checkpoint) { if (!checkpoint.Exists || checkpoint.Bytes == null) { return Clear(); } return WriteRawAtomic(checkpoint.Bytes); } private static AdvisorDispatchCacheRead Empty() { return new AdvisorDispatchCacheRead { State = AdvisorDispatchCacheState.Empty }; } private static bool IsSafePayload(BridgeAdvisorDispatchPayload? payload, string? revision, out DateTimeOffset capturedAt) { capturedAt = default(DateTimeOffset); if (payload == null || !Bounded(payload.ScopeGeneration, 128) || !Bounded(revision, 128) || !DateTimeOffset.TryParse(payload.CapturedAt, out capturedAt) || payload.Dispatches == null || payload.Dispatches.Count > 20) { return false; } HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal); foreach (BridgeAdvisorDispatchRecord dispatch in payload.Dispatches) { if (dispatch == null || !Bounded(dispatch.Id, 64) || !hashSet.Add(dispatch.Id) || !DateTimeOffset.TryParse(dispatch.CreatedAt, out var result) || result > capturedAt || capturedAt - result > DispatchTtl || !Bounded(dispatch.Headline, 60) || !Bounded(dispatch.Body, 512) || !Bounded(dispatch.PersonaId, 64) || !Bounded(dispatch.VoiceVersion, 64) || !Bounded(dispatch.TriggerId, 64)) { return false; } } return true; } private bool WriteRawAtomic(byte[] bytes) { if (bytes.Length == 0 || bytes.Length > 65536) { return false; } if (ExistingBytesEqual(bytes)) { return true; } string text = null; try { string directoryName = Path.GetDirectoryName(_path); if (!string.IsNullOrWhiteSpace(directoryName)) { Directory.CreateDirectory(directoryName); } text = $"{_path}.{Guid.NewGuid():N}.tmp"; using (FileStream fileStream = new FileStream(text, FileMode.CreateNew, FileAccess.Write, FileShare.None)) { fileStream.Write(bytes, 0, bytes.Length); fileStream.Flush(flushToDisk: true); } _replaceFile(text, _path); text = null; return true; } catch { return false; } finally { if (text != null) { try { File.Delete(text); } catch { } } } } private bool ExistingBytesEqual(byte[] desired) { try { FileInfo fileInfo = new FileInfo(_path); return fileInfo.Exists && fileInfo.Length == desired.Length && File.ReadAllBytes(_path).SequenceEqual(desired); } catch { return false; } } private bool IsBoundedFile() { if (!File.Exists(_path)) { return false; } long length = new FileInfo(_path).Length; if (length > 0) { return length <= 65536; } return false; } private bool TryReadDocument(out AdvisorDispatchCacheDocument document) { document = null; if (!IsBoundedFile()) { return false; } byte[] array = File.ReadAllBytes(_path); using JsonDocument jsonDocument = JsonDocument.Parse(array); if (!HasExactProperties(jsonDocument.RootElement, "version", "saveFingerprint", "scopeGeneration", "revision", "capturedAt", "dispatches")) { return false; } AdvisorDispatchCacheDocument advisorDispatchCacheDocument = JsonSerializer.Deserialize<AdvisorDispatchCacheDocument>(array, JsonOptions); if (advisorDispatchCacheDocument == null || advisorDispatchCacheDocument.Version != 2 || !SaveGenerationIdentity.IsV2Fingerprint(advisorDispatchCacheDocument.SaveFingerprint)) { return false; } document = advisorDispatchCacheDocument; return true; } private static bool HasExactProperties(JsonElement element, params string[] expected) { if (element.ValueKind != JsonValueKind.Object) { return false; } HashSet<string> hashSet = new HashSet<string>(expected, StringComparer.Ordinal); foreach (JsonProperty item in element.EnumerateObject()) { if (!hashSet.Remove(item.Name)) { return false; } } return hashSet.Count == 0; } private static bool Bounded(string? value, int maxLength) { if (!string.IsNullOrWhiteSpace(value)) { return value.Length <= maxLength; } return false; } } internal sealed class BridgeAuthSeamWriter { private readonly string _path; public static string DefaultSeamPath => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "AppData", "LocalLow", "TVGS", "Schedule I", "HylandHelper", "bridge-auth.json"); public BridgeAuthSeamWriter(string? path = null) { _path = path ?? DefaultSeamPath; } public void WritePaired(string bridgeToken) { Write(JsonSerializer.Serialize(new { protectedBridgeToken = BridgeTokenProtection.Protect(bridgeToken), paired = true })); } public void WriteUnpaired() { Write(JsonSerializer.Serialize(new { paired = false })); } private void Write(string json) { string directoryName = Path.GetDirectoryName(_path); if (!string.IsNullOrEmpty(directoryName)) { Directory.CreateDirectory(directoryName); } BridgeStatusWriter.WriteAtomic(_path, json); } } internal interface IBridgeCadenceAuthority { bool TryAdmitAdaptiveFull(DateTimeOffset now); bool TryAdmitNonAdaptiveStart(DateTimeOffset now); bool TryAdmitHeartbeat(DateTimeOffset now, out bool adaptive); void NotifyStarted(BridgeEnvelopePlan plan, bool adaptive, DateTimeOffset now); void NotifyCompleted(BridgeEnvelopePlan plan, DateTimeOffset now); } internal sealed class BridgeCadenceController : IBridgeCadenceAuthority { internal static readonly TimeSpan FloorInterval = TimeSpan.FromSeconds(3.0); internal static readonly TimeSpan BurstInterval = TimeSpan.FromSeconds(3.0); internal static readonly TimeSpan BurstMaxDuration = TimeSpan.FromSeconds(30.0); internal static readonly TimeSpan ActiveVisibleInterval = TimeSpan.FromSeconds(7.0); internal static readonly TimeSpan HintLease = TimeSpan.FromSeconds(60.0); internal static readonly TimeSpan RuntimeObservationFloor = TimeSpan.FromSeconds(10.0); internal const int MaxAdaptiveStartsPerWindow = 20; private readonly TimeSpan _idle; private readonly bool _enabled; private DateTimeOffset _lastStart = DateTimeOffset.MinValue; private DateTimeOffset _lastCompleted = DateTimeOffset.MinValue; private DateTimeOffset _burst = DateTimeOffset.MinValue; private DateTimeOffset _lease = DateTimeOffset.MinValue; private DateTimeOffset _lastOverlayFull = DateTimeOffset.MinValue; private bool _visible; private bool _immediate; private readonly Queue<DateTimeOffset> _adaptive = new Queue<DateTimeOffset>(); private string? _facts; private DateTimeOffset? _armed; internal bool HasPendingImmediate => _immediate; internal BridgeCadenceController(TimeSpan idleInterval, bool accelerationEnabled) { _idle = idleInterval; _enabled = accelerationEnabled; } internal void ObserveScreen(bool visible, bool openedTransition, DateTimeOffset now) { if (_enabled) { _visible = visible; if (openedTransition) { _immediate = true; _burst = now; } } } internal void NotifyHint(int? hint, bool acceptedFreshDelivery, DateTimeOffset now) { if (_enabled && acceptedFreshDelivery && hint.HasValue) { int valueOrDefault = hint.GetValueOrDefault(); if (valueOrDefault >= 1 && valueOrDefault <= 60) { _lease = now + HintLease; } } } public bool TryAdmitAdaptiveFull(DateTimeOffset now) { return Admit(now, adaptive: true); } public bool TryAdmitNonAdaptiveStart(DateTimeOffset now) { return Admit(now, adaptive: false); } public bool TryAdmitHeartbeat(DateTimeOffset now, out bool adaptive) { adaptive = false; if (!_enabled) { return now >= _lastCompleted + _idle; } if (_immediate && Admit(now, adaptive: true)) { adaptive = true; return true; } TimeSpan timeSpan = Interval(now); adaptive = timeSpan < _idle; DateTimeOffset dateTimeOffset = (adaptive ? (_lastStart + timeSpan) : (_lastCompleted + _idle)); if (now >= dateTimeOffset) { return Admit(now, adaptive); } return false; } private TimeSpan Interval(DateTimeOffset now) { if (!_visible || !(now - _burst < BurstMaxDuration)) { if (!_visible && !(now < _lease)) { return _idle; } return ActiveVisibleInterval; } return BurstInterval; } private bool Admit(DateTimeOffset now, bool adaptive) { if (!_enabled) { return true; } if (now - _lastStart < FloorInterval) { return false; } while (_adaptive.Count > 0 && now - _adaptive.Peek() >= TimeSpan.FromMinutes(1.0)) { _adaptive.Dequeue(); } if (adaptive) { return _adaptive.Count < 20; } return true; } public void NotifyStarted(BridgeEnvelopePlan plan, bool adaptive, DateTimeOffset now) { if (plan.Kind == BridgeEnvelopeKind.FullSnapshot) { _armed = null; _lastOverlayFull = now; } if (_enabled) { _lastStart = now; if (adaptive) { _adaptive.Enqueue(now); } _immediate = false; } } public void NotifyCompleted(BridgeEnvelopePlan plan, DateTimeOffset now) { _lastCompleted = now; } internal void OnOverlayAccepted(LiveOverlayReadResult result, DateTimeOffset now) { if (result.Status != LiveOverlayReadStatus.Accepted || result.Document == null) { return; } string text = JsonSerializer.Serialize(result.Document.Facts, new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }); bool flag = text != _facts; _facts = text; if (result.Rotation || flag) { DateTimeOffset valueOrDefault = _armed.GetValueOrDefault(); if (!_armed.HasValue) { valueOrDefault = now; _armed = valueOrDefault; } } } internal bool ShouldRequestRuntimeObservationFull(DateTimeOffset now) { if (!_armed.HasValue || now - _lastOverlayFull < RuntimeObservationFloor) { return false; } _armed = null; return true; } internal void Reset() { _lastStart = (_lastCompleted = (_burst = (_lease = DateTimeOffset.MinValue))); _visible = (_immediate = false); _adaptive.Clear(); _armed = null; _facts = null; } } internal static class AcceptedFreshDelivery { internal static bool Evaluate(BridgeIngestAcknowledgement acknowledgement, BridgeDownlinkApplyOutcome outcome, string? requestKnownRevision, string? responseRevision) { bool flag = acknowledgement.Stored && !acknowledgement.Stale; if (flag) { bool flag2 = (uint)outcome <= 1u; flag = flag2; } if (flag && !string.IsNullOrWhiteSpace(requestKnownRevision) && !string.IsNullOrWhiteSpace(responseRevision)) { return responseRevision != requestKnownRevision; } return false; } } internal sealed class BridgeClient : IDisposable { public const int DefaultMaxExchangeRequestBytes = 1048576; public const int DefaultMaxExchangeResponseBytes = 262144; private static readonly JsonSerializerOptions JsonOptions = new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, PropertyNameCaseInsensitive = true }; private readonly HttpClient _httpClient; private readonly Uri _baseUri; private readonly MelonBridgeLogger _logger; private readonly int _maxExchangeRequestBytes; private readonly int _maxExchangeResponseBytes; public BridgeClient(string baseUrl, MelonBridgeLogger logger) : this(baseUrl, logger, null) { } internal BridgeClient(string baseUrl, MelonBridgeLogger logger, HttpMessageHandler? handler, int maxExchangeRequestBytes = 1048576, int maxExchangeResponseBytes = 262144) { if (maxExchangeRequestBytes <= 0 || maxExchangeResponseBytes <= 0) { throw new ArgumentOutOfRangeException("maxExchangeRequestBytes"); } _baseUri = new Uri(baseUrl.TrimEnd('/') + "/", UriKind.Absolute); _logger = logger; _maxExchangeRequestBytes = maxExchangeRequestBytes; _maxExchangeResponseBytes = maxExchangeResponseBytes; _httpClient = ((handler == null) ? new HttpClient() : new HttpClient(handler)); _httpClient.Timeout = TimeSpan.FromSeconds(15.0); } public async Task<BridgeExchangeResponse> ExchangeAsync(string bridgeToken, BridgeExchangeRequest exchange, CancellationToken cancellationToken) { string text = JsonSerializer.Serialize(exchange, JsonOptions); if (Encoding.UTF8.GetByteCount(text) > _maxExchangeRequestBytes) { throw new BridgePayloadException("Bridge exchange request exceeded the local byte limit."); } using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, new Uri(_baseUri, "api/bridge/exchange")) { Content = new StringContent(text, Encoding.UTF8, "application/json") }; request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", bridgeToken); using HttpResponseMessage response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); TimeSpan? retryAfter = ReadRetryAfter(response); byte[] array = await ReadBoundedBodyAsync(response, _maxExchangeResponseBytes, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (!response.IsSuccessStatusCode) { throw CreateExchangeException(response.StatusCode, array, retryAfter); } try { return JsonSerializer.Deserialize<BridgeExchangeResponse>(array, JsonOptions) ?? throw new BridgePayloadException("Bridge exchange response was empty."); } catch (JsonException innerException) { throw new BridgePayloadException("Bridge exchange response was malformed.", innerException); } } public async Task<PendingMixPostResponse?> SendPendingMixAsync(string bridgeToken, BridgePendingMix mix, CancellationToken cancellationToken) { try { return await PostJsonAsync<PendingMixPostResponse>("api/bridge/mixes", mix, bridgeToken, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } catch (BridgeClientException ex) when (ex.IsUnauthorized) { throw; } catch (OperationCanceledException exception) when (!cancellationToken.IsCancellationRequested) { _logger.WarningThrottled("Pending mix POST quiet-failed.", exception); return null; } catch (Exception ex2) when (!(ex2 is OperationCanceledException)) { _logger.WarningThrottled("Pending mix POST quiet-failed.", ex2); return null; } } public async Task<PairingSession> StartPairingAsync(BridgeSaveFingerprint saveFingerprint, CancellationToken cancellationToken) { PairingStartResponse pairingStartResponse = await PostJsonAsync<PairingStartResponse>("api/bridge/pairing/start", new { saveFingerprint }, null, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (string.IsNullOrWhiteSpace(pairingStartResponse.PairingId) || string.IsNullOrWhiteSpace(pairingStartResponse.Code) || string.IsNullOrWhiteSpace(pairingStartResponse.ModSecret)) { throw new InvalidOperationException("Pairing start response was incomplete."); } return new PairingSession(pairingStartResponse.PairingId, pairingStartResponse.Code, pairingStartResponse.ModSecret); } public async Task<PairingStatusResponse> PollPairingStatusAsync(PairingSession session, CancellationToken cancellationToken) { string path = "api/bridge/pairing/" + Uri.EscapeDataString(session.PairingId) + "/status"; PairingStatusResponse pairingStatusResponse = await PostJsonAsync<PairingStatusResponse>(path, new { modSecret = session.ModSecret }, null, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (!string.IsNullOrWhiteSpace(pairingStatusResponse.BridgeToken)) { pairingStatusResponse.VerifiedScope = pairingStatusResponse.Scope?.ToPairingScope(session.PairingId) ?? throw new InvalidOperationException("Claimed pairing response omitted its verified scope."); } return pairingStatusResponse; } public Task SendHeartbeatAsync(string bridgeToken, BridgeEnvelope heartbeat, CancellationToken cancellationToken) { return PostJsonAsync<object>("api/bridge/ingest", heartbeat, bridgeToken, cancellationToken); } public async Task<LatestStateResponse?> GetLatestAsync(string bridgeToken, PairingScope scope, CancellationToken cancellationToken) { string relativeUri = $"api/bridge/latest?pairingId={Uri.EscapeDataString(scope.PairingId)}&deviceId={Uri.EscapeDataString(scope.DeviceId)}&profileId={Uri.EscapeDataString(scope.ProfileId)}"; try { using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, new Uri(_baseUri, relativeUri)); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", bridgeToken); using HttpResponseMessage response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (response.StatusCode == HttpStatusCode.Unauthorized) { throw new BridgeClientException(HttpStatusCode.Unauthorized, "Latest poll was unauthorized."); } if (!response.IsSuccessStatusCode) { _logger.WarningThrottled($"Latest poll returned {response.StatusCode}."); return null; } return JsonSerializer.Deserialize<LatestStateResponse>(await ReadBoundedBodyAsync(response, _maxExchangeResponseBytes, cancellationToken).ConfigureAwait(continueOnCapturedContext: false), JsonOptions); } catch (BridgeClientException ex) when (ex.IsUnauthorized) { throw; } catch (Exception ex2) when (!(ex2 is OperationCanceledException)) { _logger.WarningThrottled("Latest poll quiet-failed.", ex2); return null; } } public async Task<PhoneRecipePollResult?> GetPhoneRecipeAvailabilityAsync(string bridgeToken, CancellationToken cancellationToken) { _ = 1; try { using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, new Uri(_baseUri, "api/bridge/recipes/availability")); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", bridgeToken); using HttpResponseMessage response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (response.StatusCode == HttpStatusCode.Unauthorized) { throw new BridgeClientException(HttpStatusCode.Unauthorized, "Phone recipe poll was unauthorized."); } if (response.StatusCode == HttpStatusCode.NotFound) { return new PhoneRecipePollResult(null, NotPublished: true); } if (!response.IsSuccessStatusCode) { _logger.WarningThrottled($"Phone recipe poll returned {response.StatusCode}."); return null; } BridgePhoneRecipeSnapshot bridgePhoneRecipeSnapshot = JsonSerializer.Deserialize<BridgePhoneRecipeSnapshot>(await ReadBoundedBodyAsync(response, _maxExchangeResponseBytes, cancellationToken).ConfigureAwait(continueOnCapturedContext: false), JsonOptions); return (bridgePhoneRecipeSnapshot == null) ? null : new PhoneRecipePollResult(bridgePhoneRecipeSnapshot, NotPublished: false); } catch (BridgeClientException ex) when (ex.IsUnauthorized) { throw; } catch (Exception ex2) when (!(ex2 is OperationCanceledException)) { _logger.WarningThrottled("Phone recipe poll quiet-failed.", ex2); return null; } } public void Dispose() { _httpClient.Dispose(); } private async Task<T> PostJsonAsync<T>(string path, object body, string? bearerToken, CancellationToken cancellationToken) { string content = JsonSerializer.Serialize(body, JsonOptions); using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, new Uri(_baseUri, path)) { Content = new StringContent(content, Encoding.UTF8, "application/json") }; if (!string.IsNullOrWhiteSpace(bearerToken)) { request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", bearerToken); } using HttpResponseMessage response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (!response.IsSuccessStatusCode) { throw new BridgeClientException(response.StatusCode, $"{path} returned HTTP {response.StatusCode}."); } if (typeof(T) == typeof(object)) { return (T)new object(); } return JsonSerializer.Deserialize<T>(await ReadBoundedBodyAsync(response, _maxExchangeResponseBytes, cancellationToken).ConfigureAwait(continueOnCapturedContext: false), JsonOptions) ?? throw new InvalidOperationException(path + " returned an empty response."); } private static BridgeClientException CreateExchangeException(HttpStatusCode statusCode, byte[] body, TimeSpan? retryAfter) { BridgeStructuredError bridgeStructuredError = null; try { BridgeExchangeError bridgeExchangeError = JsonSerializer.Deserialize<BridgeExchangeError>(body, JsonOptions); if (bridgeExchangeError?.Error != null && IsSafeErrorCode(bridgeExchangeError.Error.Code)) { bridgeStructuredError = bridgeExchangeError.Error; } } catch (JsonException) { } string text = bridgeStructuredError?.Code; string requiresRepair = (IsBounded(bridgeStructuredError?.RequiresRepair, 64) ? bridgeStructuredError.RequiresRepair : null); int? num = bridgeStructuredError?.RetryAfterSeconds; TimeSpan? obj; if (num.HasValue) { int valueOrDefault = num.GetValueOrDefault(); if (valueOrDefault >= 0 && valueOrDefault <= 86400) { obj = TimeSpan.FromSeconds(bridgeStructuredError.RetryAfterSeconds.Value); goto IL_00cd; } } obj = null; goto IL_00cd; IL_00cd: TimeSpan? timeSpan = obj; string value = ((text == null) ? "HTTP_ERROR" : text); return new BridgeClientException(statusCode, $"Bridge exchange failed with HTTP {statusCode} ({value}).", text, bridgeStructuredError?.Retriable ?? false, requiresRepair, retryAfter ?? timeSpan); } private static bool IsSafeErrorCode(string? code) { switch (code) { case "SAVE_SCOPE_MISMATCH": case "BRIDGE_TOKEN_INVALID": case "PAIRING_SCOPE_MISMATCH": case "ENTITLEMENT_PROOF_REQUIRED": case "RATE_LIMITED": return true; default: return false; } } private static bool IsBounded(string? value, int maxLength) { if (!string.IsNullOrWhiteSpace(value)) { return value.Length <= maxLength; } return false; } private static TimeSpan? ReadRetryAfter(HttpResponseMessage response) { RetryConditionHeaderValue retryAfter = response.Headers.RetryAfter; TimeSpan? timeSpan = retryAfter?.Delta; if (timeSpan.HasValue) { return timeSpan.GetValueOrDefault(); } DateTimeOffset? dateTimeOffset = retryAfter?.Date; if (dateTimeOffset.HasValue) { DateTimeOffset valueOrDefault = dateTimeOffset.GetValueOrDefault(); TimeSpan timeSpan2 = valueOrDefault - DateTimeOffset.UtcNow; return (timeSpan2 > TimeSpan.Zero) ? timeSpan2 : TimeSpan.Zero; } return null; } private static async Task<byte[]> ReadBoundedBodyAsync(HttpResponseMessage response, int maxBytes, CancellationToken cancellationToken) { long? contentLength = response.Content.Headers.ContentLength; if (contentLength.HasValue && contentLength.GetValueOrDefault() > 0 && response.Content.Headers.ContentLength > maxBytes) { throw new BridgePayloadException("Bridge response exceeded the local byte limit."); } byte[] result; await using (Stream source = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) { using MemoryStream destination = new MemoryStream(); byte[] buffer = new byte[Math.Min(8192, maxBytes + 1)]; while (true) { int num = await source.ReadAsync(buffer.AsMemory(0, buffer.Length), cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (num == 0) { break; } if (destination.Length + num > maxBytes) { throw new BridgePayloadException("Bridge response exceeded the local byte limit."); } destination.Write(buffer, 0, num); } result = destination.ToArray(); } return result; } } internal sealed class BridgeClientException : Exception { public HttpStatusCode StatusCode { get; } public string? Code { get; } public bool Retriable { get; } public string? RequiresRepair { get; } public TimeSpan? RetryAfter { get; } public bool IsUnauthorized => StatusCode == HttpStatusCode.Unauthorized; public bool IsUnsupported => StatusCode == HttpStatusCode.NotFound; public bool IsTransient { get { if (!Retriable && StatusCode != HttpStatusCode.TooManyRequests) { return StatusCode >= HttpStatusCode.InternalServerError; } return true; } } public BridgeClientException(HttpStatusCode statusCode, string message, string? code = null, bool retriable = false, string? requiresRepair = null, TimeSpan? retryAfter = null) : base(message) { StatusCode = statusCode; Code = code; Retriable = retriable; RequiresRepair = requiresRepair; RetryAfter = retryAfter; } } internal sealed class BridgePayloadException : Exception { public BridgePayloadException(string message) : base(message) { } public BridgePayloadException(string message, Exception innerException) : base(message, innerException) { } } internal sealed record PhoneRecipePollResult(BridgePhoneRecipeSnapshot? Snapshot, bool NotPublished); internal sealed record PairingSession(string PairingId, string Code, string ModSecret); internal sealed class PairingStartResponse { [JsonPropertyName("pairingId")] public string? PairingId { get; set; } [JsonPropertyName("code")] public string? Code { get; set; } [JsonPropertyName("modSecret")] public string? ModSecret { get; set; } } internal sealed class PairingStatusResponse { [JsonPropertyName("status")] public string Status { get; set; } = ""; [JsonPropertyName("bridgeToken")] public string? BridgeToken { get; set; } [JsonPropertyName("scope")] public PairingScopeResponse? Scope { get; set; } [JsonIgnore] public PairingScope? VerifiedScope { get; set; } } internal sealed class PairingScopeResponse { [JsonPropertyName("deviceId")] public string DeviceId { get; set; } = ""; [JsonPropertyName("profileId")] public string ProfileId { get; set; } = ""; [JsonPropertyName("saveFingerprint")] public BridgeSaveFingerprint? SaveFingerprint { get; set; } public PairingScope ToPairingScope(string pairingId) { PairingScope obj = new PairingScope { PairingId = pairingId, DeviceId = DeviceId, ProfileId = ProfileId, SaveFingerprint = (SaveFingerprint ?? new BridgeSaveFingerprint()) }; if (!obj.IsValid()) { throw new InvalidOperationException("Claimed pairing response contained an invalid verified scope."); } return obj; } } internal sealed class LatestStateResponse { [JsonPropertyName("sequence")] public long? Sequence { get; set; } } internal sealed class PendingMixPostResponse { [JsonPropertyName("accepted")] public bool Accepted { get; set; } [JsonPropertyName("deduped")] public bool Deduped { get; set; } [JsonPropertyName("mixId")] public string? MixId { get; set; } } internal sealed class BridgeCommandReader { private const long MaxCommandBytes = 8192L; private readonly MelonBridgeLogger _logger; private readonly string _path; private static readonly Regex IsoTimestampPattern = new Regex("^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{1,9})?(?:Z|[+-]\\d{2}:\\d{2})$", RegexOptions.CultureInvariant); private static readonly JsonSerializerOptions JsonOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; public BridgeCommandReader(MelonBridgeLogger logger) { _logger = logger; _path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "AppData", "LocalLow", "TVGS", "Schedule I", "HylandHelper", "bridge-command.json"); } public BridgeCommand? TakeCommand() { try { if (!File.Exists(_path)) { return null; } BridgeCommand command = null; try { if (new FileInfo(_path).Length <= 8192) { if (!TryParseCommand(File.ReadAllText(_path), out command)) { command = null; } } else { _logger.WarningThrottled("Bridge command file exceeded the safety limit; discarding."); } } catch (Exception exception) { _logger.WarningThrottled("Bridge command file was unreadable; discarding.", exception); } try { File.Delete(_path); } catch { } return command; } catch (Exception exception2) { _logger.WarningThrottled("Bridge command check failed.", exception2); return null; } } public bool TakeUnlink() { try { if (!File.Exists(_path)) { return false; } string a = null; BridgeCommand command = null; try { if (new FileInfo(_path).Length <= 8192 && TryParseCommand(File.ReadAllText(_path), out command)) { a = command?.Command; } } catch (Exception exception) { _logger.WarningThrottled("Bridge command file was unreadable; discarding.", exception); } if (IsSupported(command) && string.Equals(a, "saveMix", StringComparison.OrdinalIgnoreCase)) { return false; } try { File.Delete(_path); } catch { } return string.Equals(a, "unlink", StringComparison.OrdinalIgnoreCase); } catch (Exception exception2) { _logger.WarningThrottled("Bridge unlink command check failed.", exception2); return false; } } private static bool IsSupported(BridgeCommand? command) { if (command == null || string.IsNullOrWhiteSpace(command.Command)) { return false; } if (string.Equals(command.Command, "unlink", StringComparison.OrdinalIgnoreCase)) { return true; } if (!SaveGenerationIdentity.IsV2Fingerprint(command.SaveFingerprint)) { return false; } if (string.Equals(command.Command, "syncNow", StringComparison.OrdinalIgnoreCase)) { if (command.Version == 1 && IsSafeSyncRequestId(command.RequestId) && IsUtcIsoTimestamp(command.RequestedAt)) { return command.Mix == null; } return false; } if (!string.Equals(command.Command, "saveMix", StringComparison.OrdinalIgnoreCase) || !IsSafeRequestId(command.RequestId) || command.Mix == null) { return false; } BridgePendingMix mix = command.Mix; if (!IsBoundedString(mix.ProductId) || mix.IngredientIds == null || mix.IngredientIds.Count == 0 || mix.IngredientIds.Count > 64 || mix.IngredientIds.Exists((string id) => !IsBoundedString(id)) || (mix.Name != null && mix.Name.Length > 64) || !IsIsoTimestamp(mix.CapturedAt) || !string.Equals(mix.Source, "inGameTile", StringComparison.Ordinal) || mix.Steps == null || mix.Steps.Count != mix.IngredientIds.Count) { return false; } for (int num = 0; num < mix.Steps.Count; num++) { BridgePendingMixStep bridgePendingMixStep = mix.Steps[num]; if (bridgePendingMixStep == null || !IsBoundedString(bridgePendingMixStep.IngredientId) || !string.Equals(bridgePendingMixStep.IngredientId, mix.IngredientIds[num], StringComparison.OrdinalIgnoreCase) || !IsBoundedString(bridgePendingMixStep.OutputProductId) || bridgePendingMixStep.OutputEffects == null || bridgePendingMixStep.OutputEffects.Count > 12 || bridgePendingMixStep.OutputEffects.Exists((string effect) => !IsBoundedString(effect))) { return false; } } return true; } private static bool TryParseCommand(string json, out BridgeCommand? command) { command = null; using JsonDocument jsonDocument = JsonDocument.Parse(json); JsonElement rootElement = jsonDocument.RootElement; if (rootElement.ValueKind != JsonValueKind.Object || !rootElement.TryGetProperty("command", out var value) || value.ValueKind != JsonValueKind.String) { return false; } string[] array = value.GetString()?.ToLowerInvariant() switch { "unlink" => new string[1] { "command" }, "syncnow" => new string[5] { "command", "version", "saveFingerprint", "requestId", "requestedAt" }, "savemix" => new string[4] { "command", "saveFingerprint", "requestId", "mix" }, _ => Array.Empty<string>(), }; if (array.Length == 0 || !HasExactFields(rootElement, (IReadOnlyCollection<string>)(object)array)) { return false; } command = JsonSerializer.Deserialize<BridgeCommand>(json, JsonOptions); return IsSupported(command); } private static bool HasExactFields(JsonElement root, IReadOnlyCollection<string> expected) { HashSet<string> hashSet = new HashSet<string>(expected, StringComparer.Ordinal); foreach (JsonProperty item in root.EnumerateObject()) { if (!hashSet.Remove(item.Name)) { return false; } } return hashSet.Count == 0; } private static bool IsSafeRequestId(string? requestId) { if (string.IsNullOrWhiteSpace(requestId) || requestId.Length > 64) { return false; } foreach (char c in requestId) { if (!char.IsLetterOrDigit(c) && c != '-' && c != '_') { return false; } } return true; } private static bool IsSafeSyncRequestId(string? requestId) { if (requestId == null || requestId.Length != 32) { return false; } for (int i = 0; i < requestId.Length; i++) { if (!char.IsLetterOrDigit(requestId[i])) { return false; } } return true; } private static bool IsBoundedString(string? value) { if (!string.IsNullOrWhiteSpace(value)) { return value.Length <= 64; } return false; } private static bool IsIsoTimestamp(string? value) { DateTimeOffset result; if (!string.IsNullOrWhiteSpace(value) && value.Length >= 20 && value.Length <= 40 && IsoTimestampPattern.IsMatch(value)) { return DateTimeOffset.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out result); } return false; } private static bool IsUtcIsoTimestamp(string? value) { if (IsIsoTimestamp(value)) { return value.EndsWith("Z", StringComparison.Ordinal); } return false; } } internal sealed class BridgeCommand { [JsonPropertyName("command")] public string? Command { get; set; } [JsonPropertyName("version")] public int? Version { get; set; } [JsonPropertyName("saveFingerprint")] public string? SaveFingerprint { get; set; } [JsonPropertyName("requestId")] public string? RequestId { get; set; } [JsonPropertyName("requestedAt")] public string? RequestedAt { get; set; } [JsonPropertyName("mix")] public BridgePendingMix? Mix { get; set; } } internal sealed class BridgeCommandResultWriter { private readonly MelonBridgeLogger _logger; private readonly string _directory; public BridgeCommandResultWriter(MelonBridgeLogger logger) { _logger = logger; _directory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "AppData", "LocalLow", "TVGS", "Schedule I", "HylandHelper"); try { Directory.CreateDirectory(_directory); } catch { } } public void Write(string requestId, string status, string saveFingerprint) { if (!IsSafeRequestId(requestId) || string.IsNullOrWhiteSpace(status) || !SaveGenerationIdentity.IsV2Fingerprint(saveFingerprint)) { return; } string text = Path.Combine(_directory, "bridge-command-result-" + requestId + ".json"); string text2 = $"{text}.{Guid.NewGuid():N}.tmp"; try { Directory.CreateDirectory(_directory); File.WriteAllText(text2, JsonSerializer.Serialize(new { version = 1, requestId = requestId, status = status, saveFingerprint = saveFingerprint })); File.Move(text2, text, overwrite: true); } catch (Exception exception) { try { if (File.Exists(text2)) { File.Delete(text2); } } catch { } _logger.WarningThrottled("Bridge command result write failed.", exception); } } private static bool IsSafeRequestId(string requestId) { if (string.IsNullOrWhiteSpace(requestId) || requestId.Length > 64) { return false; } foreach (char c in requestId) { if (!char.IsLetterOrDigit(c) && c != '-' && c != '_') { return false; } } return true; } } internal static class BridgeConstants { public const string BackendBaseUrl = "https://hyland-helper-backend.vercel.app"; public const string ModVersion = "0.3.1"; public const string TargetGameVersion = "0.4.6f13"; public const string TargetMelonLoaderVersion = "0.7.3"; public static readonly TimeSpan PairingPollInterval = TimeSpan.FromSeconds(5.0); public static readonly TimeSpan SnapshotInterval = TimeSpan.FromSeconds(30.0); public static readonly TimeSpan LatestPollInterval = TimeSpan.FromSeconds(30.0); public static readonly TimeSpan PhoneRecipePollInterval = TimeSpan.FromSeconds(30.0); public static readonly TimeSpan RetryBackoff = TimeSpan.FromSeconds(10.0); } internal enum BridgeDownlinkApplyOutcome { Applied, Cleared, Unchanged, NotPublished, TemporarilyUnavailable, Unsupported, NotConsented, EntitlementUnavailable, Malformed, PersistenceFailed } internal sealed class BridgeDownlinkCoordinator { private readonly PhoneRecipeCache _phoneRecipes; private readonly BridgeSettingsStore _settingsStore; private readonly BridgeLocalSettings _settings; private readonly Func<DateTimeOffset> _utcNow; private readonly AdvisorDispatchCache? _advisorDispatches; public bool PhoneRecipesRequireLegacyPoll { get; private set; } public bool AdvisorDispatchesSupported { get; private set; } = true; public BridgeDownlinkCoordinator(PhoneRecipeCache phoneRecipes, BridgeSettingsStore settingsStore, BridgeLocalSettings settings, Func<DateTimeOffset> utcNow, AdvisorDispatchCache? advisorDispatches = null) { _phoneRecipes = phoneRecipes; _settingsStore = settingsStore; _settings = settings; _utcNow = utcNow; _advisorDispatches = advisorDispatches; } public void PopulateKnownRevisions(BridgeExchangeRequestDownlink downlink) { downlink.PhoneRecipes = _settings.PhoneRecipesRevision; downlink.AdvisorDispatches = _settings.AdvisorDispatchesRevision; } public BridgeDownlinkApplyOutcome ApplyPhoneRecipes(BridgePhoneRecipeExchangeSlice? slice, string saveFingerprint) { if (!SaveGenerationIdentity.IsV2Fingerprint(saveFingerprint) || slice == null || string.IsNullOrWhiteSpace(slice.State)) { return BridgeDownlinkApplyOutcome.Malformed; } switch (slice.State) { case "changed": if (!ValidRevision(slice.Revision) || slice.Payload == null) { return BridgeDownlinkApplyOutcome.Malformed; } PhoneRecipesRequireLegacyPoll = false; return ReplacePhoneRecipes(slice.Payload, slice.Revision, saveFingerprint); case "unchanged": if (!ValidRevision(slice.Revision) || !string.Equals(slice.Revision, _settings.PhoneRecipesRevision, StringComparison.Ordinal)) { return BridgeDownlinkApplyOutcome.Malformed; } PhoneRecipesRequireLegacyPoll = false; return BridgeDownlinkApplyOutcome.Unchanged; case "cleared": if (!ValidRevision(slice.Revision)) { return BridgeDownlinkApplyOutcome.Malformed; } PhoneRecipesRequireLegacyPoll = false; return ClearPhoneRecipes(slice.Revision, saveFingerprint); case "notPublished": if (slice.Revision != null || slice.Payload != null) { return BridgeDownlinkApplyOutcome.Malformed; } PhoneRecipesRequireLegacyPoll = false; return BridgeDownlinkApplyOutcome.NotPublished; case "temporarilyUnavailable": if (slice.Payload != null || (slice.Revision != null && !ValidRevision(slice.Revision)) || !ValidRetryAfter(slice.RetryAfterSeconds)) { return BridgeDownlinkApplyOutcome.Malformed; } PhoneRecipesRequireLegacyPoll = false; _phoneRecipes.MarkOffline(_utcNow(), saveFingerprint); return BridgeDownlinkApplyOutcome.TemporarilyUnavailable; case "unsupported": if (slice.Payload != null || (slice.Revision != null && !ValidRevision(slice.Revision)) || slice.RetryAfterSeconds.HasValue) { return BridgeDownlinkApplyOutcome.Malformed; } PhoneRecipesRequireLegacyPoll = true; return BridgeDownlinkApplyOutcome.Unsupported; default: return BridgeDownlinkApplyOutcome.Malformed; } } public BridgeDownlinkApplyOutcome ApplyAdvisorDispatches(BridgeAdvisorDispatchExchangeSlice? slice, string saveFingerprint) { if (!SaveGenerationIdentity.IsV2Fingerprint(saveFingerprint) || _advisorDispatches == null || slice == null || string.IsNullOrWhiteSpace(slice.State)) { return BridgeDownlinkApplyOutcome.Malformed; } switch (slice.State) { case "changed": if (!ValidRevision(slice.Revision) || slice.Payload == null) { return BridgeDownlinkApplyOutcome.Malformed; } AdvisorDispatchesSupported = true; return ReplaceAdvisorDispatches(slice.Payload, slice.Revision, saveFingerprint); case "unchanged": if (!ValidRevision(slice.Revision) || !string.Equals(slice.Revision, _settings.AdvisorDispatchesRevision, StringComparison.Ordinal)) { return BridgeDownlinkApplyOutcome.Malformed; } AdvisorDispatchesSupported = true; return BridgeDownlinkApplyOutcome.Unchanged; case "cleared": if (!ValidRevision(slice.Revision)) { return BridgeDownlinkApplyOutcome.Malformed; } AdvisorDispatchesSupported = true; return ClearAdvisorDispatches(slice.Revision, saveFingerprint); case "notConsented": if (slice.Payload != null || (slice.Revision != null && !ValidRevision(slice.Revision))) { return BridgeDownlinkApplyOutcome.Malformed; } AdvisorDispatchesSupported = true; return BridgeDownlinkApplyOutcome.NotConsented; case "entitlementUnavailable": if (slice.Payload != null || (slice.Revision != null && !ValidRevision(slice.Revision))) { return BridgeDownlinkApplyOutcome.Malformed; } AdvisorDispatchesSupported = true; return BridgeDownlinkApplyOutcome.EntitlementUnavailable; case "temporarilyUnavailable": if (slice.Payload != null || (slice.Revision != null && !ValidRevision(slice.Revision)) || !ValidRetryAfter(slice.RetryAfterSeconds)) { return BridgeDownlinkApplyOutcome.Malformed; } AdvisorDispatchesSupported = true; return BridgeDownlinkApplyOutcome.TemporarilyUnavailable; case "unsupported": if (slice.Payload != null || (slice.Revision != null && !ValidRevision(slice.Revision)) || slice.RetryAfterSeconds.HasValue) { return BridgeDownlinkApplyOutcome.Malformed; } AdvisorDispatchesSupported = false; return BridgeDownlinkApplyOutcome.Unsupported; default: return BridgeDownlinkApplyOutcome.Malformed; } } public void ClearTokenScopedState() { _phoneRecipes.Clear(); _advisorDispatches?.Clear(); PhoneRecipesRequireLegacyPoll = false; AdvisorDispatchesSupported = true; } private BridgeDownlinkApplyOutcome ReplacePhoneRecipes(BridgePhoneRecipeSnapshot snapshot, string revision, string saveFingerprint) { if (!_phoneRecipes.TryCapture(out PhoneRecipeCacheCheckpoint checkpoint)) { return BridgeDownlinkApplyOutcome.PersistenceFailed; } if (!_phoneRecipes.Write(snapshot, _utcNow(), saveFingerprint)) { return BridgeDownlinkApplyOutcome.PersistenceFailed; } return PersistPhoneRevision(revision, checkpoint, BridgeDownlinkApplyOutcome.Applied); } private BridgeDownlinkApplyOutcome ClearPhoneRecipes(string revision, string saveFingerprint) { if (!_phoneRecipes.TryCapture(out PhoneRecipeCacheCheckpoint checkpoint)) { return BridgeDownlinkApplyOutcome.PersistenceFailed; } if (!_phoneRecipes.ClearForScope(saveFingerprint)) { return BridgeDownlinkApplyOutcome.PersistenceFailed; } return PersistPhoneRevision(revision, checkpoint, BridgeDownlinkApplyOutcome.Cleared); } private BridgeDownlinkApplyOutcome PersistPhoneRevision(string revision, PhoneRecipeCacheCheckpoint checkpoint, BridgeDownlinkApplyOutcome success) { string phoneRecipesRevision = _settings.PhoneRecipesRevision; _settings.PhoneRecipesRevision = revision; if (_settingsStore.Save(_settings)) { return success; } _settings.PhoneRecipesRevision = phoneRecipesRevision; _phoneRecipes.Restore(checkpoint); return BridgeDownlinkApplyOutcome.PersistenceFailed; } private BridgeDownlinkApplyOutcome ReplaceAdvisorDispatches(BridgeAdvisorDispatchPayload payload, string revision, string saveFingerprint) { if (!AdvisorDispatchCache.CanWrite(payload, revision, _utcNow())) { return BridgeDownlinkApplyOutcome.Malformed; } if (_advisorDispatches == null || !_advisorDispatches.TryCapture(out AdvisorDispatchCacheCheckpoint checkpoint)) { return BridgeDownlinkApplyOutcome.PersistenceFailed; } if (!_advisorDispatches.Write(payload, revision, _utcNow(), saveFingerprint)) { return BridgeDownlinkApplyOutcome.PersistenceFailed; } return PersistAdvisorRevision(revision, checkpoint, BridgeDownlinkApplyOutcome.Applied); } private BridgeDownlinkApplyOutcome ClearAdvisorDispatches(string revision, string saveFingerprint) { if (_advisorDispatches == null || !_advisorDispatches.TryCapture(out AdvisorDispatchCacheCheckpoint checkpoint)) { return BridgeDownlinkApplyOutcome.PersistenceFailed; } if (!_advisorDispatches.ClearForScope(saveFingerprint)) { return BridgeDownlinkApplyOutcome.PersistenceFailed; } return PersistAdvisorRevision(revision, checkpoint, BridgeDownlinkApplyOutcome.Cleared); } private BridgeDownlinkApplyOutcome PersistAdvisorRevision(string revision, AdvisorDispatchCacheCheckpoint checkpoint, BridgeDownlinkApplyOutcome success) { string advisorDispatchesRevision = _settings.AdvisorDispatchesRevision; _settings.AdvisorDispatchesRevision = revision; if (_settingsStore.Save(_settings)) { return success; } _settings.AdvisorDispatchesRevision = advisorDispatchesRevision; _advisorDispatches.Restore(checkpoint); return BridgeDownlinkApplyOutcome.PersistenceFailed; } private static bool ValidRevision(string? revision) { return PairingScope.IsBounded(revision, 128); } private static bool ValidRetryAfter(int? retryAfterSeconds) { if (retryAfterSeconds.HasValue) { if (retryAfterSeconds.HasValue) { int valueOrDefault = retryAfterSeconds.GetValueOrDefault(); if (valueOrDefault >= 0) { return valueOrDefault <= 86400; } } return false; } return true; } } internal enum BridgeExchangeMode { Negotiating, Exchange, Legacy, Repair } internal sealed record BridgeAcknowledgementResult(long SequenceFloor, bool RequiresFullResynchronization); internal sealed class BridgeExchangeState { private DateTimeOffset _retryAt = DateTimeOffset.MinValue; private int _attempt; public BridgeExchangeMode Mode { get; private set; } public bool CanSendHeartbeat => Mode == BridgeExchangeMode.Exchange; public bool CanAttemptExchange(DateTimeOffset now) { BridgeExchangeMode mode = Mode; if ((uint)mode <= 1u) { return now >= _retryAt; } return false; } public BridgeAcknowledgementResult ApplySuccess(BridgeIngestAcknowledgement acknowledgement, long localSequence, DateTimeOffset now) { Mode = BridgeExchangeMode.Exchange; _attempt = 0; _retryAt = DateTimeOffset.MinValue; return new BridgeAcknowledgementResult(Math.Max(localSequence, Math.Max(acknowledgement.Sequence, acknowledgement.CurrentSequence.GetValueOrDefault())), acknowledgement.Stale || !acknowledgement.Stored); } public BridgeRetryDecision ApplyFailure(Exception exception, BridgeRetryPolicy policy, DateTimeOffset now) { BridgeRetryDecision bridgeRetryDecision = policy.Decide(exception, _attempt, now); switch (bridgeRetryDecision.Action) { case BridgeRetryAction.StickyLegacy: Mode = BridgeExchangeMode.Legacy; _retryAt = DateTimeOffset.MaxValue; break; case BridgeRetryAction.Repair: Mode = BridgeExchangeMode.Repair; _retryAt = DateTimeOffset.MaxValue; break; case BridgeRetryAction.Retry: case BridgeRetryAction.Resynchronize: _retryAt = now + (bridgeRetryDecision.Delay ?? BridgeRetryPolicy.MinDelay); _attempt++; break; } return bridgeRetryDecision; } public void EnterRepair() { Mode = BridgeExchangeMode.Repair; _retryAt = DateTimeOffset.MaxValue; } public void Reset() { Mode = BridgeExchangeMode.Negotiating; _retryAt = DateTimeOffset.MinValue; _attempt = 0; } } public static class BridgeFeatureAdvertisement { public const string PhoneRecipeAvailability = "phoneRecipeAvailability"; public const int PhoneRecipeProtocolVersion = 1; public const string BridgeExchange = "bridgeExchange"; public const string AdvisorDispatches = "advisorDispatches"; public const int ExchangeProtocolVersion = 1; public const int AdvisorDispatchProtocolVersion = 1; public static Dictionary<string, BridgeFeatureCapability> Current(bool exchangeOperational = false, bool advisorOperational = false) { Dictionary<string, BridgeFeatureCapability> dictionary = new Dictionary<string, BridgeFeatureCapability> { ["phoneRecipeAvailability"] = new BridgeFeatureCapability { Supported = true, ProtocolVersion = 1 } }; if (exchangeOperational) { dictionary["bridgeExchange"] = new BridgeFeatureCapability { Supported = true, ProtocolVersion = 1 }; } if (exchangeOperational && advisorOperational) { dictionary["advisorDispatches"] = new BridgeFeatureCapability { Supported = true, ProtocolVersion = 1 }; } return dictionary; } } internal sealed class BridgeOperationalCapabilityState { private bool _exchangeOperational; private bool _advisorOperational; public bool Update(BridgeExchangeMode mode, bool tileReady, bool advisorAvailable = true) { bool flag = mode == BridgeExchangeMode.Exchange; bool flag2 = flag && tileReady && advisorAvailable; if (flag == _exchangeOperational && flag2 == _advisorOperational) { return false; } _exchangeOperational = flag; _advisorOperational = flag2; return true; } public Dictionary<string, BridgeFeatureCapability> Current() { return BridgeFeatureAdvertisement.Current(_exchangeOperational, _advisorOperational); } } public sealed class HylandHelperBridgeMod : MelonMod { private readonly OverlayState _overlay = new OverlayState(); private CancellationTokenSource? _cts; private BridgeRunner? _runner; public override void OnInitializeMelon() { try { _cts = new CancellationTokenSource(); MelonBridgeLogger logger = new MelonBridgeLogger(((MelonBase)this).LoggerInstance); BridgeOperationalCapabilityState bridgeOperationalCapabilityState = new BridgeOperationalCapabilityState(); GameAdapter gameAdapter = new GameAdapter(logger, bridgeOperationalCapabilityState.Current); BridgeSettingsStore settingsStore = BridgeSettingsStore.Create(logger); BridgeClient bridgeClient = new BridgeClient("https://hyland-helper-backend.vercel.app", logger); _runner = new BridgeRunner(gameAdapter, bridgeClient, settingsStore, _overlay, logger, bridgeOperationalCapabilityState); _runner.RunAsync(_cts.Token); _overlay.SetStatus("Starting bridge..."); } catch (Exception ex) { ((MelonBase)this).LoggerInstance.Warning("Hyland Helper Bridge disabled during init: " + ex.Message); _overlay.SetStatus("Bridge disabled during init."); } } public override void OnDeinitializeMelon() { try { _cts?.Cancel(); _runner?.Dispose(); _cts?.Dispose(); } catch { } } public override void OnGUI() { try { OverlaySnapshot overlaySnapshot = _overlay.Snapshot(); if (overlaySnapshot.Status == null || (!overlaySnapshot.Status.Contains("synced") && !overlaySnapshot.Status.Contains("Paired"))) { OverlayRenderer.Draw(_overlay); } } catch { } } } internal sealed class BridgePreferencesStore { public const int SchemaVersionCurrent = 1; public const int MaxPreferencesBytes = 4096; private readonly string _path; internal static string DefaultPath => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "AppData", "LocalLow", "TVGS", "Schedule I", "HylandHelper", "bridge-preferences.json"); internal BridgePreferencesStore(string? path = null) { _path = path ?? DefaultPath; } internal bool ReadLiveOverlayEnabled() { return ReadEnabledFlag("liveOverlayEnabled"); } internal bool ReadAdaptiveCadenceEnabled() { return ReadEnabledFlag("adaptiveCadenceEnabled"); } private bool ReadEnabledFlag(string property) { try { FileInfo fileInfo = new FileInfo(_path); if (!fileInfo.Exists || fileInfo.Length <= 0 || fileInfo.Length > 4096) { return true; } byte[] array = File.ReadAllBytes(_path); if (array.Length == 0 || array.Length > 4096) { return true; } using JsonDocument jsonDocument = JsonDocument.Parse(array); JsonElement rootElement = jsonDocument.RootElement; if (rootElement.ValueKind != JsonValueKind.Object) { return true; } if (!rootElement.TryGetProperty(property, out var value)) { return true; } return value.ValueKind != JsonValueKind.False; } catch { return true; } } internal bool Save(bool liveOverlayEnabled) { try { string directoryName = Path.GetDirectoryName(_path); if (!string.IsNullOrEmpty(directoryName)) { Directory.CreateDirectory(directoryName); } string s = "{\"schemaVersion\":" + 1 + ",\"liveOverlayEnabled\":" + (liveOverlayEnabled ? "true" : "false") + "}"; string text = $"{_path}.{Guid.NewGuid():N}.tmp"; try { File.WriteAllBytes(text, Encoding.UTF8.GetBytes(s)); File.Move(text, _path, overwrite: true); } finally { try { if (File.Exists(text)) { File.Delete(text); } } catch { } } return true; } catch { return false; } } } internal enum BridgeRetryAction { Continue, Retry, Repair, StickyLegacy, Resynchronize, Stop } internal sealed record BridgeRetryDecision(BridgeRetryAction Action, TimeSpan? Delay = null); internal sealed class BridgeRetryPolicy { public static readonly TimeSpan MinDelay = TimeSpan.FromSeconds(2.0); public static readonly TimeSpan MaxDelay = TimeSpan.FromMinutes(2.0); private readonly Func<double> _nextJitter; public BridgeRetryPolicy(Func<double>? nextJitter = null) { _nextJitter = nextJitter ?? new Func<double>(Random.Shared.NextDouble); } public BridgeRetryDecision Decide(Exception exception, int attempt, DateTimeOffset now) { if ((exception is HttpRequestException || exception is TaskCanceledException) ? true : false) { return Retry(attempt, null); } if (exception is BridgePayloadException) { return Retry(attempt, null); } if (!(exception is BridgeClientException { StatusCode: var statusCode } ex)) { return new BridgeRetryDecision(BridgeRetryAction.Stop); } switch (statusCode) { case HttpStatusCode.Unauthorized: retur
HylandHelper.PhoneTile.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Buffers.Binary; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using HylandHelper.BridgeContracts; using HylandHelper.BridgeMod; using HylandHelper.PhoneTile; using HylandHelper.PhoneTile.Layouts; using HylandHelper.PhoneTile.Layouts.Engine; using Il2CppFishNet; using Il2CppFishNet.Object; using Il2CppInterop.Runtime; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppScheduleOne.Building; using Il2CppScheduleOne.DevUtilities; using Il2CppScheduleOne.EntityFramework; using Il2CppScheduleOne.ItemFramework; using Il2CppScheduleOne.Persistence; using Il2CppScheduleOne.Property; using Il2CppScheduleOne.Tiles; using Il2CppScheduleOne.UI; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using MelonLoader; using Microsoft.CodeAnalysis; using S1API.Building; using S1API.Console; using S1API.GameTime; using S1API.Items; using S1API.Items.Storable; using S1API.Leveling; using S1API.Lifecycle; using S1API.Money; using S1API.PhoneApp; using S1API.Property; using S1API.UI; using S1API.Utils; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(PhoneTileMod), "Hyland Helper Phone Tile", "0.3.1", "MadJag Studios", null)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("MadJag Studios")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright © 2026 MadJag Studios")] [assembly: AssemblyDescription("Hyland Helper in-game phone tile for Schedule I")] [assembly: AssemblyFileVersion("0.3.1.0")] [assembly: AssemblyInformationalVersion("0.3.1")] [assembly: AssemblyProduct("Hyland Helper")] [assembly: AssemblyTitle("HylandHelper.PhoneTile")] [assembly: AssemblyVersion("0.3.1.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } public sealed class GeneratedLayoutApplyObjectDefinition { public string LayoutObjectId { get; set; } = ""; public string GameItemId { get; set; } = ""; public string PlacementClass { get; set; } = "grid"; public int Width { get; set; } public int Height { get; set; } public bool CanRotate { get; set; } public bool BlocksPlacement { get; set; } } public static class GeneratedLayoutApplyCatalog { public const string CatalogRevision = "c1-3ac35145ecefb9411a19fb5ace0c65dd5300ceccf5bc4273edd0222500b4f24b"; public static readonly GeneratedLayoutApplyObjectDefinition[] PhysicalObjects = new GeneratedLayoutApplyObjectDefinition[41] { new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "pot", GameItemId = "airpot", Width = 2, Height = 2, CanRotate = false, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "suspension_rack", GameItemId = "suspensionrack", Width = 2, Height = 2, CanRotate = false, BlocksPlacement = false }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "full_spectrum_grow_light", GameItemId = "fullspectrumgrowlight", PlacementClass = "dependent", Width = 2, Height = 2, CanRotate = false, BlocksPlacement = false }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "led_grow_light", GameItemId = "ledgrowlight", PlacementClass = "dependent", Width = 2, Height = 2, CanRotate = false, BlocksPlacement = false }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "halogen_grow_light", GameItemId = "halogengrowlight", PlacementClass = "dependent", Width = 2, Height = 2, CanRotate = false, BlocksPlacement = false }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "mushroom_bed", GameItemId = "mushroombed", Width = 2, Height = 2, CanRotate = false, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "spore_spawn_station", GameItemId = "mushroomspawnstation", Width = 4, Height = 2, CanRotate = true, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "drying_rack", GameItemId = "dryingrack", Width = 3, Height = 2, CanRotate = true, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "chemistry_station", GameItemId = "chemistrystation", Width = 4, Height = 2, CanRotate = true, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "lab_oven", GameItemId = "laboven", Width = 4, Height = 2, CanRotate = true, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "mixing_station", GameItemId = "mixingstation", Width = 4, Height = 2, CanRotate = true, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "mixing_station_mk2", GameItemId = "mixingstationmk2", Width = 4, Height = 2, CanRotate = true, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "cauldron", GameItemId = "cauldron", Width = 4, Height = 4, CanRotate = true, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "brick_press", GameItemId = "brickpress", Width = 2, Height = 2, CanRotate = false, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "ac_unit", GameItemId = "acunit", Width = 2, Height = 2, CanRotate = false, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "pot_sprinkler", GameItemId = "potsprinkler", Width = 2, Height = 1, CanRotate = true, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "big_sprinkler", GameItemId = "bigsprinkler", Width = 2, Height = 2, CanRotate = false, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "soil_pourer", GameItemId = "soilpourer", Width = 2, Height = 1, CanRotate = true, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "plastic_pot", GameItemId = "plasticpot", Width = 2, Height = 2, CanRotate = false, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "moisture_preserving_pot", GameItemId = "moisturepreservingpot", Width = 2, Height = 2, CanRotate = false, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "grow_tent", GameItemId = "growtent", Width = 2, Height = 2, CanRotate = false, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "floor_lamp", GameItemId = "floorlamp", Width = 1, Height = 1, CanRotate = false, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "garbage_throne", GameItemId = "garbagethrone", Width = 4, Height = 3, CanRotate = true, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "plastic_table", GameItemId = "plastictable", Width = 4, Height = 2, CanRotate = true, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "trash_can", GameItemId = "trashcan", Width = 2, Height = 2, CanRotate = false, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "toilet", GameItemId = "toilet", Width = 2, Height = 2, CanRotate = false, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "supply_shelf", GameItemId = "smallstoragerack", Width = 2, Height = 1, CanRotate = true, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "medium_storage_rack", GameItemId = "mediumstoragerack", Width = 3, Height = 1, CanRotate = true, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "large_storage_rack", GameItemId = "largestoragerack", Width = 4, Height = 1, CanRotate = true, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "locker", GameItemId = "locker", Width = 3, Height = 1, CanRotate = true, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "bed", GameItemId = "bed", Width = 3, Height = 5, CanRotate = true, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "small_storage_closet", GameItemId = "smallstoragecloset", Width = 2, Height = 1, CanRotate = true, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "medium_storage_closet", GameItemId = "mediumstoragecloset", Width = 3, Height = 1, CanRotate = true, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "large_storage_closet", GameItemId = "largestoragecloset", Width = 4, Height = 1, CanRotate = true, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "huge_storage_closet", GameItemId = "hugestoragecloset", Width = 4, Height = 2, CanRotate = true, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "display_cabinet", GameItemId = "displaycabinet", Width = 3, Height = 2, CanRotate = true, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "filing_cabinet", GameItemId = "filingcabinet", Width = 2, Height = 2, CanRotate = false, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "safe", GameItemId = "safe", Width = 2, Height = 2, CanRotate = false, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "packing_station", GameItemId = "packagingstation", Width = 4, Height = 2, CanRotate = true, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "packing_station_mk2", GameItemId = "packagingstationmk2", Width = 4, Height = 2, CanRotate = true, BlocksPlacement = true }, new GeneratedLayoutApplyObjectDefinition { LayoutObjectId = "laundering_station", GameItemId = "launderingstation", Width = 4, Height = 2, CanRotate = true, BlocksPlacement = true } }; } public sealed class GeneratedLayoutApplyCell { public int NativeX { get; set; } public int NativeY { get; set; } public int Row2 { get; set; } public int Col2 { get; set; } } public sealed class GeneratedLayoutApplyRotation { public int NativeDegrees { get; set; } public string LayoutRotation { get; set; } = ""; } public sealed class GeneratedLayoutApplyGrid { public string GridGuid { get; set; } = ""; public string PropertyId { get; set; } = ""; public int FloorIndex { get; set; } public int RowOrigin2 { get; set; } public int ColOrigin2 { get; set; } public int RowFromX { get; set; } public int RowFromY { get; set; } public int ColFromX { get; set; } public int ColFromY { get; set; } public GeneratedLayoutApplyRotation[] RotationByNativeDegrees { get; set; } = new GeneratedLayoutApplyRotation[0]; public GeneratedLayoutApplyCell[] PlaceableCells { get; set; } = new GeneratedLayoutApplyCell[0]; public GeneratedLayoutApplyCell[] BlockedCells { get; set; } = new GeneratedLayoutApplyCell[0]; } public sealed class GeneratedLayoutApplyFloor { public int FloorIndex { get; set; } public GeneratedLayoutApplyGrid[] Grids { get; set; } = new GeneratedLayoutApplyGrid[0]; } public sealed class GeneratedLayoutApplyProperty { public string PropertyCode { get; set; } = ""; public string PropertyId { get; set; } = ""; public GeneratedLayoutApplyFloor[] Floors { get; set; } = new GeneratedLayoutApplyFloor[0]; } public static class GeneratedLayoutApplyProperties { public const string LayoutRevision = "g1-7b34d3b8a094343742351e1a89e697fdc49dc979117c30e416311233be3b4a90"; public static readonly GeneratedLayoutApplyProperty[] Properties = new GeneratedLayoutApplyProperty[8] { new GeneratedLayoutApplyProperty { PropertyCode = "barn", PropertyId = "barn", Floors = new GeneratedLayoutApplyFloor[2] { new GeneratedLayoutApplyFloor { FloorIndex = 0, Grids = new GeneratedLayoutApplyGrid[1] { new GeneratedLayoutApplyGrid { GridGuid = "fa2d9b23-eb58-43ae-8f8b-7c37a132a46e", PropertyId = "barn", FloorIndex = 0, RowOrigin2 = 58, ColOrigin2 = 0, RowFromX = 0, RowFromY = -1, ColFromX = 1, ColFromY = 0, RotationByNativeDegrees = new GeneratedLayoutApplyRotation[4] { new GeneratedLayoutApplyRotation { NativeDegrees = 0, LayoutRotation = "west" }, new GeneratedLayoutApplyRotation { NativeDegrees = 90, LayoutRotation = "north" }, new GeneratedLayoutApplyRotation { NativeDegrees = 180, LayoutRotation = "east" }, new GeneratedLayoutApplyRotation { NativeDegrees = 270, LayoutRotation = "south" } }, PlaceableCells = new GeneratedLayoutApplyCell[1055] { new GeneratedLayoutApplyCell { NativeX = 1, NativeY = 29, Row2 = 0, Col2 = 2 }, new GeneratedLayoutApplyCell { NativeX = 2, NativeY = 29, Row2 = 0, Col2 = 4 }, new GeneratedLayoutApplyCell { NativeX = 3, NativeY = 29, Row2 = 0, Col2 = 6 }, new GeneratedLayoutApplyCell { NativeX = 4, NativeY = 29, Row2 = 0, Col2 = 8 }, new GeneratedLayoutApplyCell { NativeX = 5, NativeY = 29, Row2 = 0, Col2 = 10 }, new GeneratedLayoutApplyCell { NativeX = 6, NativeY = 29, Row2 = 0, Col2 = 12 }, new GeneratedLayoutApplyCell { NativeX = 7, NativeY = 29, Row2 = 0, Col2 = 14 }, new GeneratedLayoutApplyCell { NativeX = 8, NativeY = 29, Row2 = 0, Col2 = 16 }, new GeneratedLayoutApplyCell { NativeX = 10, NativeY = 29, Row2 = 0, Col2 = 20 }, new GeneratedLayoutApplyCell { NativeX = 11, NativeY = 29, Row2 = 0, Col2 = 22 }, new GeneratedLayoutApplyCell { NativeX = 12, NativeY = 29, Row2 = 0, Col2 = 24 }, new GeneratedLayoutApplyCell { NativeX = 13, NativeY = 29, Row2 = 0, Col2 = 26 }, new GeneratedLayoutApplyCell { NativeX = 14, NativeY = 29, Row2 = 0, Col2 = 28 }, new GeneratedLayoutApplyCell { NativeX = 15, NativeY = 29, Row2 = 0, Col2 = 30 }, new GeneratedLayoutApplyCell { NativeX = 16, NativeY = 29, Row2 = 0, Col2 = 32 }, new GeneratedLayoutApplyCell { NativeX = 17, NativeY = 29, Row2 = 0, Col2 = 34 }, new GeneratedLayoutApplyCell { NativeX = 19, NativeY = 29, Row2 = 0, Col2 = 38 }, new GeneratedLayoutApplyCell { NativeX = 20, NativeY = 29, Row2 = 0, Col2 = 40 }, new GeneratedLayoutApplyCell { NativeX = 21, NativeY = 29, Row2 = 0, Col2 = 42 }, new GeneratedLayoutApplyCell { NativeX = 22, NativeY = 29, Row2 = 0, Col2 = 44 }, new GeneratedLayoutApplyCell { NativeX = 23, NativeY = 29, Row2 = 0, Col2 = 46 }, new GeneratedLayoutApplyCell { NativeX = 24, NativeY = 29, Row2 = 0, Col2 = 48 }, new GeneratedLayoutApplyCell { NativeX = 25, NativeY = 29, Row2 = 0, Col2 = 50 }, new GeneratedLayoutApplyCell { NativeX = 26, NativeY = 29, Row2 = 0, Col2 = 52 }, new GeneratedLayoutApplyCell { NativeX = 28, NativeY = 29, Row2 = 0, Col2 = 56 }, new GeneratedLayoutApplyCell { NativeX = 29, NativeY = 29, Row2 = 0, Col2 = 58 }, new GeneratedLayoutApplyCell { NativeX = 30, NativeY = 29, Row2 = 0, Col2 = 60 }, new GeneratedLayoutApplyCell { NativeX = 31, NativeY = 29, Row2 = 0, Col2 = 62 }, new GeneratedLayoutApplyCell { NativeX = 32, NativeY = 29, Row2 = 0, Col2 = 64 }, new GeneratedLayoutApplyCell { NativeX = 33, NativeY = 29, Row2 = 0, Col2 = 66 }, new GeneratedLayoutApplyCell { NativeX = 34, NativeY = 29, Row2 = 0, Col2 = 68 }, new GeneratedLayoutApplyCell { NativeX = 35, NativeY = 29, Row2 = 0, Col2 = 70 }, new GeneratedLayoutApplyCell { NativeX = 0, NativeY = 28, Row2 = 2, Col2 = 0 }, new GeneratedLayoutApplyCell { NativeX = 1, NativeY = 28, Row2 = 2, Col2 = 2 }, new GeneratedLayoutApplyCell { NativeX = 2, NativeY = 28, Row2 = 2, Col2 = 4 }, new GeneratedLayoutApplyCell { NativeX = 3, NativeY = 28, Row2 = 2, Col2 = 6 }, new GeneratedLayoutApplyCell { NativeX = 4, NativeY = 28, Row2 = 2, Col2 = 8 }, new GeneratedLayoutApplyCell { NativeX = 5, NativeY = 28, Row2 = 2, Col2 = 10 }, new GeneratedLayoutApplyCell { NativeX = 6, NativeY = 28, Row2 = 2, Col2 = 12 }, new GeneratedLayoutApplyCell { NativeX = 7, NativeY = 28, Row2 = 2, Col2 = 14 }, new GeneratedLayoutApplyCell { NativeX = 8, NativeY = 28, Row2 = 2, Col2 = 16 }, new GeneratedLayoutApplyCell { NativeX = 9, NativeY = 28, Row2 = 2, Col2 = 18 }, new GeneratedLayoutApplyCell { NativeX = 10, NativeY = 28, Row2 = 2, Col2 = 20 }, new GeneratedLayoutApplyCell { NativeX = 11, NativeY = 28, Row2 = 2, Col2 = 22 }, new GeneratedLayoutApplyCell { NativeX = 12, NativeY = 28, Row2 = 2, Col2 = 24 }, new GeneratedLayoutApplyCell { NativeX = 13, NativeY = 28, Row2 = 2, Col2 = 26 }, new GeneratedLayoutApplyCell { NativeX = 14, NativeY = 28, Row2 = 2, Col2 = 28 }, new GeneratedLayoutApplyCell { NativeX = 15, NativeY = 28, Row2 = 2, Col2 = 30 }, new GeneratedLayoutApplyCell { NativeX = 16, NativeY = 28, Row2 = 2, Col2 = 32 }, new GeneratedLayoutApplyCell { NativeX = 17, NativeY = 28, Row2 = 2, Col2 = 34 }, new GeneratedLayoutApplyCell { NativeX = 18, NativeY = 28, Row2 = 2, Col2 = 36 }, new GeneratedLayoutApplyCell { NativeX = 19, NativeY = 28, Row2 = 2, Col2 = 38 }, new GeneratedLayoutApplyCell { NativeX = 20, NativeY = 28, Row2 = 2, Col2 = 40 }, new GeneratedLayoutApplyCell { NativeX = 21, NativeY = 28, Row2 = 2, Col2 = 42 }, new GeneratedLayoutApplyCell { NativeX = 22, NativeY = 28, Row2 = 2, Col2 = 44 }, new GeneratedLayoutApplyCell { NativeX = 23, NativeY = 28, Row2 = 2, Col2 = 46 }, new GeneratedLayoutApplyCell { NativeX = 24, NativeY = 28, Row2 = 2, Col2 = 48 }, new GeneratedLayoutApplyCell { NativeX = 25, NativeY = 28, Row2 = 2, Col2 = 50 }, new GeneratedLayoutApplyCell { NativeX = 26, NativeY = 28, Row2 = 2, Col2 = 52 }, new GeneratedLayoutApplyCell { NativeX = 27, NativeY = 28, Row2 = 2, Col2 = 54 }, new GeneratedLayoutApplyCell { NativeX = 28, NativeY = 28, Row2 = 2, Col2 = 56 }, new GeneratedLayoutApplyCell { NativeX = 29, NativeY = 28, Row2 = 2, Col2 = 58 }, new GeneratedLayoutApplyCell { NativeX = 30, NativeY = 28, Row2 = 2, Col2 = 60 }, new GeneratedLayoutApplyCell { NativeX = 31, NativeY = 28, Row2 = 2, Col2 = 62 }, new GeneratedLayoutApplyCell { NativeX = 32, NativeY = 28, Row2 = 2, Col2 = 64 }, new GeneratedLayoutApplyCell { NativeX = 33, NativeY = 28, Row2 = 2, Col2 = 66 }, new GeneratedLayoutApplyCell { NativeX = 34, NativeY = 28, Row2 = 2, Col2 = 68 }, new GeneratedLayoutApplyCell { NativeX = 35, NativeY = 28, Row2 = 2, Col2 = 70 }, new GeneratedLayoutApplyCell { NativeX = 36, NativeY = 28, Row2 = 2, Col2 = 72 }, new GeneratedLayoutApplyCell { NativeX = 0, NativeY = 27, Row2 = 4, Col2 = 0 }, new GeneratedLayoutApplyCell { NativeX = 1, NativeY = 27, Row2 = 4, Col2 = 2 }, new GeneratedLayoutApplyCell { NativeX = 2, NativeY = 27, Row2 = 4, Col2 = 4 }, new GeneratedLayoutApplyCell { NativeX = 3, NativeY = 27, Row2 = 4, Col2 = 6 }, new GeneratedLayoutApplyCell { NativeX = 4, NativeY = 27, Row2 = 4, Col2 = 8 }, new GeneratedLayoutApplyCell { NativeX = 5, NativeY = 27, Row2 = 4, Col2 = 10 }, new GeneratedLayoutApplyCell { NativeX = 6, NativeY = 27, Row2 = 4, Col2 = 12 }, new GeneratedLayoutApplyCell { NativeX = 7, NativeY = 27, Row2 = 4, Col2 = 14 }, new GeneratedLayoutApplyCell { NativeX = 8, NativeY = 27, Row2 = 4, Col2 = 16 }, new GeneratedLayoutApplyCell { NativeX = 9, NativeY = 27, Row2 = 4, Col2 = 18 }, new GeneratedLayoutApplyCell { NativeX = 10, NativeY = 27, Row2 = 4, Col2 = 20 }, new GeneratedLayoutApplyCell { NativeX = 11, NativeY = 27, Row2 = 4, Col2 = 22 }, new GeneratedLayoutApplyCell { NativeX = 12, NativeY = 27, Row2 = 4, Col2 = 24 }, new GeneratedLayoutApplyCell { NativeX = 13, NativeY = 27, Row2 = 4, Col2 = 26 }, new GeneratedLayoutApplyCell { NativeX = 14, NativeY = 27, Row2 = 4, Col2 = 28 }, new GeneratedLayoutApplyCell { NativeX = 15, NativeY = 27, Row2 = 4, Col2 = 30 }, new GeneratedLayoutApplyCell { NativeX = 16, NativeY = 27, Row2 = 4, Col2 = 32 }, new GeneratedLayoutApplyCell { NativeX = 17, NativeY = 27, Row2 = 4, Col2 = 34 }, new GeneratedLayoutApplyCell { NativeX = 18, NativeY = 27, Row2 = 4, Col2 = 36 }, new GeneratedLayoutApplyCell { NativeX = 19, NativeY = 27, Row2 = 4, Col2 = 38 }, new GeneratedLayoutApplyCell { NativeX = 20, NativeY = 27, Row2 = 4, Col2 = 40 }, new GeneratedLayoutApplyCell { NativeX = 21, NativeY = 27, Row2 = 4, Col2 = 42 }, new GeneratedLayoutApplyCell { NativeX = 22, NativeY = 27, Row2 = 4, Col2 = 44 }, new GeneratedLayoutApplyCell { NativeX = 23, NativeY = 27, Row2 = 4, Col2 = 46 }, new GeneratedLayoutApplyCell { NativeX = 24, NativeY = 27, Row2 = 4, Col2 = 48 }, new GeneratedLayoutApplyCell { NativeX = 25, NativeY = 27, Row2 = 4, Col2 = 50 }, new GeneratedLayoutApplyCell { NativeX = 26, NativeY = 27, Row2 = 4, Col2 = 52 }, new GeneratedLayoutApplyCell { NativeX = 27, NativeY = 27, Row2 = 4, Col2 = 54 }, new GeneratedLayoutApplyCell { NativeX = 28, NativeY = 27, Row2 = 4, Col2 = 56 }, new GeneratedLayoutApplyCell { NativeX = 29, NativeY = 27, Row2 = 4, Col2 = 58 }, new GeneratedLayoutApplyCell { NativeX = 30, NativeY = 27, Row2 = 4, Col2 = 60 }, new GeneratedLayoutApplyCell { NativeX = 31, NativeY = 27, Row2 = 4, Col2 = 62 }, new GeneratedLayoutApplyCell { NativeX = 32, NativeY = 27, Row2 = 4, Col2 = 64 }, new GeneratedLayoutApplyCell { NativeX = 33, NativeY = 27, Row2 = 4, Col2 = 66 }, new GeneratedLayoutApplyCell { NativeX = 34, NativeY = 27, Row2 = 4, Col2 = 68 }, new GeneratedLayoutApplyCell { NativeX = 35, NativeY = 27, Row2 = 4, Col2 = 70 }, new GeneratedLayoutApplyCell { NativeX = 36, NativeY = 27, Row2 = 4, Col2 = 72 }, new GeneratedLayoutApplyCell { NativeX = 0, NativeY = 26, Row2 = 6, Col2 = 0 }, new GeneratedLayoutApplyCell { NativeX = 1, NativeY = 26, Row2 = 6, Col2 = 2 }, new GeneratedLayoutApplyCell { NativeX = 2, NativeY = 26, Row2 = 6, Col2 = 4 }, new GeneratedLayoutApplyCell { NativeX = 3, NativeY = 26, Row2 = 6, Col2 = 6 }, new GeneratedLayoutApplyCell { NativeX = 4, NativeY = 26, Row2 = 6, Col2 = 8 }, new GeneratedLayoutApplyCell { NativeX = 5, NativeY = 26, Row2 = 6, Col2 = 10 }, new GeneratedLayoutApplyCell { NativeX = 6, NativeY = 26, Row2 = 6, Col2 = 12 }, new GeneratedLayoutApplyCell { NativeX = 7, NativeY = 26, Row2 = 6, Col2 = 14 }, new GeneratedLayoutApplyCell { NativeX = 8, NativeY = 26, Row2 = 6, Col2 = 16 }, new GeneratedLayoutApplyCell { NativeX = 9, NativeY = 26, Row2 = 6, Col2 = 18 }, new GeneratedLayoutApplyCell { NativeX = 10, NativeY = 26, Row2 = 6, Col2 = 20 }, new GeneratedLayoutApplyCell { NativeX = 11, NativeY = 26, Row2 = 6, Col2 = 22 }, new GeneratedLayoutApplyCell { NativeX = 12, NativeY = 26, Row2 = 6, Col2 = 24 }, new GeneratedLayoutApplyCell { NativeX = 13, NativeY = 26, Row2 = 6, Col2 = 26 }, new GeneratedLayoutApplyCell { NativeX = 14, NativeY = 26, Row2 = 6, Col2 = 28 }, new GeneratedLayoutApplyCell { NativeX = 15, NativeY = 26, Row2 = 6, Col2 = 30 }, new GeneratedLayoutApplyCell { NativeX = 16, NativeY = 26, Row2 = 6, Col2 = 32 }, new GeneratedLayoutApplyCell { NativeX = 17, NativeY = 26, Row2 = 6, Col2 = 34 }, new GeneratedLayoutApplyCell { NativeX = 18, NativeY = 26, Row2 = 6, Col2 = 36 }, new GeneratedLayoutApplyCell { NativeX = 19, NativeY = 26, Row2 = 6, Col2 = 38 }, new GeneratedLayoutApplyCell { NativeX = 20, NativeY = 26, Row2 = 6, Col2 = 40 }, new GeneratedLayoutApplyCell { NativeX = 21, NativeY = 26, Row2 = 6, Col2 = 42 }, new GeneratedLayoutApplyCell { NativeX = 22, NativeY = 26, Row2 = 6, Col2 = 44 }, new GeneratedLayoutApplyCell { NativeX = 23, NativeY = 26, Row2 = 6, Col2 = 46 }, new GeneratedLayoutApplyCell { NativeX = 24, NativeY = 26, Row2 = 6, Col2 = 48 }, new GeneratedLayoutApplyCell { NativeX = 25, NativeY = 26, Row2 = 6, Col2 = 50 }, new GeneratedLayoutApplyCell { NativeX = 26, NativeY = 26, Row2 = 6, Col2 = 52 }, new GeneratedLayoutApplyCell { NativeX = 27, NativeY = 26, Row2 = 6, Col2 = 54 }, new GeneratedLayoutApplyCell { NativeX = 28, NativeY = 26, Row2 = 6, Col2 = 56 }, new GeneratedLayoutApplyCell { NativeX = 29, NativeY = 26, Row2 = 6, Col2 = 58 }, new GeneratedLayoutApplyCell { NativeX = 30, NativeY = 26, Row2 = 6, Col2 = 60 }, new GeneratedLayoutApplyCell { NativeX = 31, NativeY = 26, Row2 = 6, Col2 = 62 }, new GeneratedLayoutApplyCell { NativeX = 32, NativeY = 26, Row2 = 6, Col2 = 64 }, new GeneratedLayoutApplyCell { NativeX = 33, NativeY = 26, Row2 = 6, Col2 = 66 }, new GeneratedLayoutApplyCell { NativeX = 34, NativeY = 26, Row2 = 6, Col2 = 68 }, new GeneratedLayoutApplyCell { NativeX = 35, NativeY = 26, Row2 = 6, Col2 = 70 }, new GeneratedLayoutApplyCell { NativeX = 36, NativeY = 26, Row2 = 6, Col2 = 72 }, new GeneratedLayoutApplyCell { NativeX = 0, NativeY = 25, Row2 = 8, Col2 = 0 }, new GeneratedLayoutApplyCell { NativeX = 1, NativeY = 25, Row2 = 8, Col2 = 2 }, new GeneratedLayoutApplyCell { NativeX = 2, NativeY = 25, Row2 = 8, Col2 = 4 }, new GeneratedLayoutApplyCell { NativeX = 3, NativeY = 25, Row2 = 8, Col2 = 6 }, new GeneratedLayoutApplyCell { NativeX = 4, NativeY = 25, Row2 = 8, Col2 = 8 }, new GeneratedLayoutApplyCell { NativeX = 5, NativeY = 25, Row2 = 8, Col2 = 10 }, new GeneratedLayoutApplyCell { NativeX = 6, NativeY = 25, Row2 = 8, Col2 = 12 }, new GeneratedLayoutApplyCell { NativeX = 7, NativeY = 25, Row2 = 8, Col2 = 14 }, new GeneratedLayoutApplyCell { NativeX = 8, NativeY = 25, Row2 = 8, Col2 = 16 }, new GeneratedLayoutApplyCell { NativeX = 9, NativeY = 25, Row2 = 8, Col2 = 18 }, new GeneratedLayoutApplyCell { NativeX = 10, NativeY = 25, Row2 = 8, Col2 = 20 }, new GeneratedLayoutApplyCell { NativeX = 11, NativeY = 25, Row2 = 8, Col2 = 22 }, new GeneratedLayoutApplyCell { NativeX = 12, NativeY = 25, Row2 = 8, Col2 = 24 }, new GeneratedLayoutApplyCell { NativeX = 13, NativeY = 25, Row2 = 8, Col2 = 26 }, new GeneratedLayoutApplyCell { NativeX = 14, NativeY = 25, Row2 = 8, Col2 = 28 }, new GeneratedLayoutApplyCell { NativeX = 15, NativeY = 25, Row2 = 8, Col2 = 30 }, new GeneratedLayoutApplyCell { NativeX = 16, NativeY = 25, Row2 = 8, Col2 = 32 }, new GeneratedLayoutApplyCell { NativeX = 17, NativeY = 25, Row2 = 8, Col2 = 34 }, new GeneratedLayoutApplyCell { NativeX = 18, NativeY = 25, Row2 = 8, Col2 = 36 }, new GeneratedLayoutApplyCell { NativeX = 19, NativeY = 25, Row2 = 8, Col2 = 38 }, new GeneratedLayoutApplyCell { NativeX = 20, NativeY = 25, Row2 = 8, Col2 = 40 }, new GeneratedLayoutApplyCell { NativeX = 21, NativeY = 25, Row2 = 8, Col2 = 42 }, new GeneratedLayoutApplyCell { NativeX = 22, NativeY = 25, Row2 = 8, Col2 = 44 }, new GeneratedLayoutApplyCell { NativeX = 23, NativeY = 25, Row2 = 8, Col2 = 46 }, new GeneratedLayoutApplyCell { NativeX = 24, NativeY = 25, Row2 = 8, Col2 = 48 }, new GeneratedLayoutApplyCell { NativeX = 25, NativeY = 25, Row2 = 8, Col2 = 50 }, new GeneratedLayoutApplyCell { NativeX = 26, NativeY = 25, Row2 = 8, Col2 = 52 }, new GeneratedLayoutApplyCell { NativeX = 27, NativeY = 25, Row2 = 8, Col2 = 54 }, new GeneratedLayoutApplyCell { NativeX = 28, NativeY = 25, Row2 = 8, Col2 = 56 }, new GeneratedLayoutApplyCell { NativeX = 29, NativeY = 25, Row2 = 8, Col2 = 58 }, new GeneratedLayoutApplyCell { NativeX = 30, NativeY = 25, Row2 = 8, Col2 = 60 }, new GeneratedLayoutApplyCell { NativeX = 31, NativeY = 25, Row2 = 8, Col2 = 62 }, new GeneratedLayoutApplyCell { NativeX = 32, NativeY = 25, Row2 = 8, Col2 = 64 }, new GeneratedLayoutApplyCell { NativeX = 33, NativeY = 25, Row2 = 8, Col2 = 66 }, new GeneratedLayoutApplyCell { NativeX = 34, NativeY = 25, Row2 = 8, Col2 = 68 }, new GeneratedLayoutApplyCell { NativeX = 35, NativeY = 25, Row2 = 8, Col2 = 70 }, new GeneratedLayoutApplyCell { NativeX = 36, NativeY = 25, Row2 = 8, Col2 = 72 }, new GeneratedLayoutApplyCell { NativeX = 0, NativeY = 24, Row2 = 10, Col2 = 0 }, new GeneratedLayoutApplyCell { NativeX = 1, NativeY = 24, Row2 = 10, Col2 = 2 }, new GeneratedLayoutApplyCell { NativeX = 2, NativeY = 24, Row2 = 10, Col2 = 4 }, new GeneratedLayoutApplyCell { NativeX = 3, NativeY = 24, Row2 = 10, Col2 = 6 }, new GeneratedLayoutApplyCell { NativeX = 4, NativeY = 24, Row2 = 10, Col2 = 8 }, new GeneratedLayoutApplyCell { NativeX = 5, NativeY = 24, Row2 = 10, Col2 = 10 }, new GeneratedLayoutApplyCell { NativeX = 6, NativeY = 24, Row2 = 10, Col2 = 12 }, new GeneratedLayoutApplyCell { NativeX = 7, NativeY = 24, Row2 = 10, Col2 = 14 }, new GeneratedLayoutApplyCell { NativeX = 8, NativeY = 24, Row2 = 10, Col2 = 16 }, new GeneratedLayoutApplyCell { NativeX = 9, NativeY = 24, Row2 = 10, Col2 = 18 }, new GeneratedLayoutApplyCell { NativeX = 10, NativeY = 24, Row2 = 10, Col2 = 20 }, new GeneratedLayoutApplyCell { NativeX = 11, NativeY = 24, Row2 = 10, Col2 = 22 }, new GeneratedLayoutApplyCell { NativeX = 12, NativeY = 24, Row2 = 10, Col2 = 24 }, new GeneratedLayoutApplyCell { NativeX = 13, NativeY = 24, Row2 = 10, Col2 = 26 }, new GeneratedLayoutApplyCell { NativeX = 14, NativeY = 24, Row2 = 10, Col2 = 28 }, new GeneratedLayoutApplyCell { NativeX = 15, NativeY = 24, Row2 = 10, Col2 = 30 }, new GeneratedLayoutApplyCell { NativeX = 16, NativeY = 24, Row2 = 10, Col2 = 32 }, new GeneratedLayoutApplyCell { NativeX = 17, NativeY = 24, Row2 = 10, Col2 = 34 }, new GeneratedLayoutApplyCell { NativeX = 18, NativeY = 24, Row2 = 10, Col2 = 36 }, new GeneratedLayoutApplyCell { NativeX = 19, NativeY = 24, Row2 = 10, Col2 = 38 }, new GeneratedLayoutApplyCell { NativeX = 20, NativeY = 24, Row2 = 10, Col2 = 40 }, new GeneratedLayoutApplyCell { NativeX = 21, NativeY = 24, Row2 = 10, Col2 = 42 }, new GeneratedLayoutApplyCell { NativeX = 22, NativeY = 24, Row2 = 10, Col2 = 44 }, new GeneratedLayoutApplyCell { NativeX = 23, NativeY = 24, Row2 = 10, Col2 = 46 }, new GeneratedLayoutApplyCell { NativeX = 24, NativeY = 24, Row2 = 10, Col2 = 48 }, new GeneratedLayoutApplyCell { NativeX = 25, NativeY = 24, Row2 = 10, Col2 = 50 }, new GeneratedLayoutApplyCell { NativeX = 26, NativeY = 24, Row2 = 10, Col2 = 52 }, new GeneratedLayoutApplyCell { NativeX = 27, NativeY = 24, Row2 = 10, Col2 = 54 }, new GeneratedLayoutApplyCell { NativeX = 28, NativeY = 24, Row2 = 10, Col2 = 56 }, new GeneratedLayoutApplyCell { NativeX = 29, NativeY = 24, Row2 = 10, Col2 = 58 }, new GeneratedLayoutApplyCell { NativeX = 30, NativeY = 24, Row2 = 10, Col2 = 60 }, new GeneratedLayoutApplyCell { NativeX = 31, NativeY = 24, Row2 = 10, Col2 = 62 }, new GeneratedLayoutApplyCell { NativeX = 32, NativeY = 24, Row2 = 10, Col2 = 64 }, new GeneratedLayoutApplyCell { NativeX = 33, NativeY = 24, Row2 = 10, Col2 = 66 }, new GeneratedLayoutApplyCell { NativeX = 34, NativeY = 24, Row2 = 10, Col2 = 68 }, new GeneratedLayoutApplyCell { NativeX = 35, NativeY = 24, Row2 = 10, Col2 = 70 }, new GeneratedLayoutApplyCell { NativeX = 36, NativeY = 24, Row2 = 10, Col2 = 72 }, new GeneratedLayoutApplyCell { NativeX = 0, NativeY = 23, Row2 = 12, Col2 = 0 }, new GeneratedLayoutApplyCell { NativeX = 1, NativeY = 23, Row2 = 12, Col2 = 2 }, new GeneratedLayoutApplyCell { NativeX = 2, NativeY = 23, Row2 = 12, Col2 = 4 }, new GeneratedLayoutApplyCell { NativeX = 3, NativeY = 23, Row2 = 12, Col2 = 6 }, new GeneratedLayoutApplyCell { NativeX = 4, NativeY = 23, Row2 = 12, Col2 = 8 }, new GeneratedLayoutApplyCell { NativeX = 5, NativeY = 23, Row2 = 12, Col2 = 10 }, new GeneratedLayoutApplyCell { NativeX = 6, NativeY = 23, Row2 = 12, Col2 = 12 }, new GeneratedLayoutApplyCell { NativeX = 7, NativeY = 23, Row2 = 12, Col2 = 14 }, new GeneratedLayoutApplyCell { NativeX = 8, NativeY = 23, Row2 = 12, Col2 = 16 }, new GeneratedLayoutApplyCell { NativeX = 9, NativeY = 23, Row2 = 12, Col2 = 18 }, new GeneratedLayoutApplyCell { NativeX = 10, NativeY = 23, Row2 = 12, Col2 = 20 }, new GeneratedLayoutApplyCell { NativeX = 11, NativeY = 23, Row2 = 12, Col2 = 22 }, new GeneratedLayoutApplyCell { NativeX = 12, NativeY = 23, Row2 = 12, Col2 = 24 }, new GeneratedLayoutApplyCell { NativeX = 13, NativeY = 23, Row2 = 12, Col2 = 26 }, new GeneratedLayoutApplyCell { NativeX = 14, NativeY = 23, Row2 = 12, Col2 = 28 }, new GeneratedLayoutApplyCell { NativeX = 15, NativeY = 23, Row2 = 12, Col2 = 30 }, new GeneratedLayoutApplyCell { NativeX = 16, NativeY = 23, Row2 = 12, Col2 = 32 }, new GeneratedLayoutApplyCell { NativeX = 17, NativeY = 23, Row2 = 12, Col2 = 34 }, new GeneratedLayoutApplyCell { NativeX = 18, NativeY = 23, Row2 = 12, Col2 = 36 }, new GeneratedLayoutApplyCell { NativeX = 19, NativeY = 23, Row2 = 12, Col2 = 38 }, new GeneratedLayoutApplyCell { NativeX = 20, NativeY = 23, Row2 = 12, Col2 = 40 }, new GeneratedLayoutApplyCell { NativeX = 21, NativeY = 23, Row2 = 12, Col2 = 42 }, new GeneratedLayoutApplyCell { NativeX = 22, NativeY = 23, Row2 = 12, Col2 = 44 }, new GeneratedLayoutApplyCell { NativeX = 23, NativeY = 23, Row2 = 12, Col2 = 46 }, new GeneratedLayoutApplyCell { NativeX = 24, NativeY = 23, Row2 = 12, Col2 = 48 }, new GeneratedLayoutApplyCell { NativeX = 25, NativeY = 23, Row2 = 12, Col2 = 50 }, new GeneratedLayoutApplyCell { NativeX = 26, NativeY = 23, Row2 = 12, Col2 = 52 }, new GeneratedLayoutApplyCell { NativeX = 27, NativeY = 23, Row2 = 12, Col2 = 54 }, new GeneratedLayoutApplyCell { NativeX = 28, NativeY = 23, Row2 = 12, Col2 = 56 }, new GeneratedLayoutApplyCell { NativeX = 29, NativeY = 23, Row2 = 12, Col2 = 58 }, new GeneratedLayoutApplyCell { NativeX = 30, NativeY = 23, Row2 = 12, Col2 = 60 }, new GeneratedLayoutApplyCell { NativeX = 31, NativeY = 23, Row2 = 12, Col2 = 62 }, new GeneratedLayoutApplyCell { NativeX = 32, NativeY = 23, Row2 = 12, Col2 = 64 }, new GeneratedLayoutApplyCell { NativeX = 33, NativeY = 23, Row2 = 12, Col2 = 66 }, new GeneratedLayoutApplyCell { NativeX = 34, NativeY = 23, Row2 = 12, Col2 = 68 }, new GeneratedLayoutApplyCell { NativeX = 35, NativeY = 23, Row2 = 12, Col2 = 70 }, new GeneratedLayoutApplyCell { NativeX = 36, NativeY = 23, Row2 = 12, Col2 = 72 }, new GeneratedLayoutApplyCell { NativeX = 0, NativeY = 22, Row2 = 14, Col2 = 0 }, new GeneratedLayoutApplyCell { NativeX = 1, NativeY = 22, Row2 = 14, Col2 = 2 }, new GeneratedLayoutApplyCell { NativeX = 2, NativeY = 22, Row2 = 14, Col2 = 4 }, new GeneratedLayoutApplyCell { NativeX = 3, NativeY = 22, Row2 = 14, Col2 = 6 }, new GeneratedLayoutApplyCell { NativeX = 4, NativeY = 22, Row2 = 14, Col2 = 8 }, new GeneratedLayoutApplyCell { NativeX = 5, NativeY = 22, Row2 = 14, Col2 = 10 }, new GeneratedLayoutApplyCell { NativeX = 6, NativeY = 22, Row2 = 14, Col2 = 12 }, new GeneratedLayoutApplyCell { NativeX = 7, NativeY = 22, Row2 = 14, Col2 = 14 }, new GeneratedLayoutApplyCell { NativeX = 8, NativeY = 22, Row2 = 14, Col2 = 16 }, new GeneratedLayoutApplyCell { NativeX = 9, NativeY = 22, Row2 = 14, Col2 = 18 }, new GeneratedLayoutApplyCell { NativeX = 10, NativeY = 22, Row2 = 14, Col2 = 20 }, new GeneratedLayoutApplyCell { NativeX = 11, NativeY = 22, Row2 = 14, Col2 = 22 }, new GeneratedLayoutApplyCell { NativeX = 12, NativeY = 22, Row2 = 14, Col2 = 24 }, new GeneratedLayoutApplyCell { NativeX = 13, NativeY = 22, Row2 = 14, Col2 = 26 }, new GeneratedLayoutApplyCell { NativeX = 14, NativeY = 22, Row2 = 14, Col2 = 28 }, new GeneratedLayoutApplyCell { NativeX = 15, NativeY = 22, Row2 = 14, Col2 = 30 }, new GeneratedLayoutApplyCell { NativeX = 16, NativeY = 22, Row2 = 14, Col2 = 32 }, new GeneratedLayoutApplyCell { NativeX = 17, NativeY = 22, Row2 = 14, Col2 = 34 }, new GeneratedLayoutApplyCell { NativeX = 18, NativeY = 22, Row2 = 14, Col2 = 36 }, new GeneratedLayoutApplyCell { NativeX = 19, NativeY = 22, Row2 = 14, Col2 = 38 }, new GeneratedLayoutApplyCell { NativeX = 20, NativeY = 22, Row2 = 14, Col2 = 40 }, new GeneratedLayoutApplyCell { NativeX = 21, NativeY = 22, Row2 = 14, Col2 = 42 }, new GeneratedLayoutApplyCell { NativeX = 22, NativeY = 22, Row2 = 14, Col2 = 44 }, new GeneratedLayoutApplyCell { NativeX = 23, NativeY = 22, Row2 = 14, Col2 = 46 }, new GeneratedLayoutApplyCell { NativeX = 24, NativeY = 22, Row2 = 14, Col2 = 48 }, new GeneratedLayoutApplyCell { NativeX = 25, NativeY = 22, Row2 = 14, Col2 = 50 }, new GeneratedLayoutApplyCell { NativeX = 26, NativeY = 22, Row2 = 14, Col2 = 52 }, new GeneratedLayoutApplyCell { NativeX = 27, NativeY = 22, Row2 = 14, Col2 = 54 }, new GeneratedLayoutApplyCell { NativeX = 28, NativeY = 22, Row2 = 14, Col2 = 56 }, new GeneratedLayoutApplyCell { NativeX = 29, NativeY = 22, Row2 = 14, Col2 = 58 }, new GeneratedLayoutApplyCell { NativeX = 30, NativeY = 22, Row2 = 14, Col2 = 60 }, new GeneratedLayoutApplyCell { NativeX = 31, NativeY = 22, Row2 = 14, Col2 = 62 }, new GeneratedLayoutApplyCell { NativeX = 32, NativeY = 22, Row2 = 14, Col2 = 64 }, new GeneratedLayoutApplyCell { NativeX = 33, NativeY = 22, Row2 = 14, Col2 = 66 }, new GeneratedLayoutApplyCell { NativeX = 34, NativeY = 22, Row2 = 14, Col2 = 68 }, new GeneratedLayoutApplyCell { NativeX = 35, NativeY = 22, Row2 = 14, Col2 = 70 }, new GeneratedLayoutApplyCell { NativeX = 36, NativeY = 22, Row2 = 14, Col2 = 72 }, new GeneratedLayoutApplyCell { NativeX = 0, NativeY = 21, Row2 = 16, Col2 = 0 }, new GeneratedLayoutApplyCell { NativeX = 1, NativeY = 21, Row2 = 16, Col2 = 2 }, new GeneratedLayoutApplyCell { NativeX = 2, NativeY = 21, Row2 = 16, Col2 = 4 }, new GeneratedLayoutApplyCell { NativeX = 3, NativeY = 21, Row2 = 16, Col2 = 6 }, new GeneratedLayoutApplyCell { NativeX = 4, NativeY = 21, Row2 = 16, Col2 = 8 }, new GeneratedLayoutApplyCell { NativeX = 5, NativeY = 21, Row2 = 16, Col2 = 10 }, new GeneratedLayoutApplyCell { NativeX = 6, NativeY = 21, Row2 = 16, Col2 = 12 }, new GeneratedLayoutApplyCell { NativeX = 7, NativeY = 21, Row2 = 16, Col2 = 14 }, new GeneratedLayoutApplyCell { NativeX = 8, NativeY = 21, Row2 = 16, Col2 = 16 }, new GeneratedLayoutApplyCell { NativeX = 9, NativeY = 21, Row2 = 16, Col2 = 18 }, new GeneratedLayoutApplyCell { NativeX = 10, NativeY = 21, Row2 = 16, Col2 = 20 }, new GeneratedLayoutApplyCell { NativeX = 11, NativeY = 21, Row2 = 16, Col2 = 22 }, new GeneratedLayoutApplyCell { NativeX = 12, NativeY = 21, Row2 = 16, Col2 = 24 }, new GeneratedLayoutApplyCell { NativeX = 13, NativeY = 21, Row2 = 16, Col2 = 26 }, new GeneratedLayoutApplyCell { NativeX = 14, NativeY = 21, Row2 = 16, Col2 = 28 }, new GeneratedLayoutApplyCell { NativeX = 15, NativeY = 21, Row2 = 16, Col2 = 30 }, new GeneratedLayoutApplyCell { NativeX = 16, NativeY = 21, Row2 = 16, Col2 = 32 }, new GeneratedLayoutApplyCell { NativeX = 17, NativeY = 21, Row2 = 16, Col2 = 34 }, new GeneratedLayoutApplyCell { NativeX = 18, NativeY = 21, Row2 = 16, Col2 = 36 }, new GeneratedLayoutApplyCell { NativeX = 19, NativeY = 21, Row2 = 16, Col2 = 38 }, new GeneratedLayoutApplyCell { NativeX = 20, NativeY = 21, Row2 = 16, Col2 = 40 }, new GeneratedLayoutApplyCell { NativeX = 21, NativeY = 21, Row2 = 16, Col2 = 42 }, new GeneratedLayoutApplyCell { NativeX = 22, NativeY = 21, Row2 = 16, Col2 = 44 }, new GeneratedLayoutApplyCell { NativeX = 23, NativeY = 21, Row2 = 16, Col2 = 46 }, new GeneratedLayoutApplyCell { NativeX = 24, NativeY = 21, Row2 = 16, Col2 = 48 }, new GeneratedLayoutApplyCell { NativeX = 25, NativeY = 21, Row2 = 16, Col2 = 50 }, new GeneratedLayoutApplyCell { NativeX = 26, NativeY = 21, Row2 = 16, Col2 = 52 }, new GeneratedLayoutApplyCell { NativeX = 27, NativeY = 21, Row2 = 16, Col2 = 54 }, new GeneratedLayoutApplyCell { NativeX = 28, NativeY = 21, Row2 = 16, Col2 = 56 }, new GeneratedLayoutApplyCell { NativeX = 29, NativeY = 21, Row2 = 16, Col2 = 58 }, new GeneratedLayoutApplyCell { NativeX = 30, NativeY = 21, Row2 = 16, Col2 = 60 }, new GeneratedLayoutApplyCell { NativeX = 31, NativeY = 21, Row2 = 16, Col2 = 62 }, new GeneratedLayoutApplyCell { NativeX = 32, NativeY = 21, Row2 = 16, Col2 = 64 }, new GeneratedLayoutApplyCell { NativeX = 33, NativeY = 21, Row2 = 16, Col2 = 66 }, new GeneratedLayoutApplyCell { NativeX = 34, NativeY = 21, Row2 = 16, Col2 = 68 }, new GeneratedLayoutApplyCell { NativeX = 35, NativeY = 21, Row2 = 16, Col2 = 70 }, new GeneratedLayoutApplyCell { NativeX = 36, NativeY = 21, Row2 = 16, Col2 = 72 }, new GeneratedLayoutApplyCell { NativeX = 1, NativeY = 20, Row2 = 18, Col2 = 2 }, new GeneratedLayoutApplyCell { NativeX = 2, NativeY = 20, Row2 = 18, Col2 = 4 }, new GeneratedLayoutApplyCell { NativeX = 3, NativeY = 20, Row2 = 18, Col2 = 6 }, new GeneratedLayoutApplyCell { NativeX = 4, NativeY = 20, Row2 = 18, Col2 = 8 }, new GeneratedLayoutApplyCell { NativeX = 5, NativeY = 20, Row2 = 18, Col2 = 10 }, new GeneratedLayoutApplyCell { NativeX = 6, NativeY = 20, Row2 = 18, Col2 = 12 }, new GeneratedLayoutApplyCell { NativeX = 7, NativeY = 20, Row2 = 18, Col2 = 14 }, new GeneratedLayoutApplyCell { NativeX = 8, NativeY = 20, Row2 = 18, Col2 = 16 }, new GeneratedLayoutApplyCell { NativeX = 10, NativeY = 20, Row2 = 18, Col2 = 20 }, new GeneratedLayoutApplyCell { NativeX = 11, NativeY = 20, Row2 = 18, Col2 = 22 }, new GeneratedLayoutApplyCell { NativeX = 12, NativeY = 20, Row2 = 18, Col2 = 24 }, new GeneratedLayoutApplyCell { NativeX = 13, NativeY = 20, Row2 = 18, Col2 = 26 }, new GeneratedLayoutApplyCell { NativeX = 14, NativeY = 20, Row2 = 18, Col2 = 28 }, new GeneratedLayoutApplyCell { NativeX = 15, NativeY = 20, Row2 = 18, Col2 = 30 }, new GeneratedLayoutApplyCell { NativeX = 16, NativeY = 20, Row2 = 18, Col2 = 32 }, new GeneratedLayoutApplyCell { NativeX = 17, NativeY = 20, Row2 = 18, Col2 = 34 }, new GeneratedLayoutApplyCell { NativeX = 19, NativeY = 20, Row2 = 18, Col2 = 38 }, new GeneratedLayoutApplyCell { NativeX = 20, NativeY = 20, Row2 = 18, Col2 = 40 }, new GeneratedLayoutApplyCell { NativeX = 21, NativeY = 20, Row2 = 18, Col2 = 42 }, new GeneratedLayoutApplyCell { NativeX = 22, NativeY = 20, Row2 = 18, Col2 = 44 }, new GeneratedLayoutApplyCell { NativeX = 23, NativeY = 20, Row2 = 18, Col2 = 46 }, new GeneratedLayoutApplyCell { NativeX = 24, NativeY = 20, Row2 = 18, Col2 = 48 }, new GeneratedLayoutApplyCell { NativeX = 25, NativeY = 20, Row2 = 18, Col2 = 50 }, new GeneratedLayoutApplyCell { NativeX = 26, NativeY = 20, Row2 = 18, Col2 = 52 }, new GeneratedLayoutApplyCell { NativeX = 28, NativeY = 20, Row2 = 18, Col2 = 56 }, new GeneratedLayoutApplyCell { NativeX = 29, NativeY = 20, Row2 = 18, Col2 = 58 }, new GeneratedLayoutApplyCell { NativeX = 30, NativeY = 20, Row2 = 18, Col2 = 60 }, new GeneratedLayoutApplyCell { NativeX = 31, NativeY = 20, Row2 = 18, Col2 = 62 }, new GeneratedLayoutApplyCell { NativeX = 32, NativeY = 20, Row2 = 18, Col2 = 64 }, new GeneratedLayoutApplyCell { NativeX = 0, NativeY = 19, Row2 = 20, Col2 = 0 }, new GeneratedLayoutApplyCell { NativeX = 1, NativeY = 19, Row2 = 20, Col2 = 2 }, new GeneratedLayoutApplyCell { NativeX = 2, NativeY = 19, Row2 = 20, Col2 = 4 }, new GeneratedLayoutApplyCell { NativeX = 3, NativeY = 19, Row2 = 20, Col2 = 6 }, new GeneratedLayoutApplyCell { NativeX = 4, NativeY = 19, Row2 = 20, Col2 = 8 }, new GeneratedLayoutApplyCell { NativeX = 5, NativeY = 19, Row2 = 20, Col2 = 10 }, new GeneratedLayoutApplyCell { NativeX = 6, NativeY = 19, Row2 = 20, Col2 = 12 }, new GeneratedLayoutApplyCell { NativeX = 7, NativeY = 19, Row2 = 20, Col2 = 14 }, new GeneratedLayoutApplyCell { NativeX = 8, NativeY = 19, Row2 = 20, Col2 = 16 }, new GeneratedLayoutApplyCell { NativeX = 9, NativeY = 19, Row2 = 20, Col2 = 18 }, new GeneratedLayoutApplyCell { NativeX = 10, NativeY = 19, Row2 = 20, Col2 = 20 }, new GeneratedLayoutApplyCell { NativeX = 11, NativeY = 19, Row2 = 20, Col2 = 22 }, new GeneratedLayoutApplyCell { NativeX = 12, NativeY = 19, Row2 = 20, Col2 = 24 }, new GeneratedLayoutApplyCell { NativeX = 13, NativeY = 19, Row2 = 20, Col2 = 26 }, new GeneratedLayoutApplyCell { NativeX = 14, NativeY = 19, Row2 = 20, Col2 = 28 }, new GeneratedLayoutApplyCell { NativeX = 15, NativeY = 19, Row2 = 20, Col2 = 30 }, new GeneratedLayoutApplyCell { NativeX = 16, NativeY = 19, Row2 = 20, Col2 = 32 }, new GeneratedLayoutApplyCell { NativeX = 17, NativeY = 19, Row2 = 20, Col2 = 34 }, new GeneratedLayoutApplyCell { NativeX = 18, NativeY = 19, Row2 = 20, Col2 = 36 }, new GeneratedLayoutApplyCell { NativeX = 19, NativeY = 19, Row2 = 20, Col2 = 38 }, new GeneratedLayoutApplyCell { NativeX = 20, NativeY = 19, Row2 = 20, Col2 = 40 }, new GeneratedLayoutApplyCell { NativeX = 21, NativeY = 19, Row2 = 20, Col2 = 42 }, new GeneratedLayoutApplyCell { NativeX = 22, NativeY = 19, Row2 = 20, Col2 = 44 }, new GeneratedLayoutApplyCell { NativeX = 23, NativeY = 19, Row2 = 20, Col2 = 46 }, new GeneratedLayoutApplyCell { NativeX = 24, NativeY = 19, Row2 = 20, Col2 = 48 }, new GeneratedLayoutApplyCell { NativeX = 25, NativeY = 19, Row2 = 20, Col2 = 50 }, new GeneratedLayoutApplyCell { NativeX = 26, NativeY = 19, Row2 = 20, Col2 = 52 }, new GeneratedLayoutApplyCell { NativeX = 27, NativeY = 19, Row2 = 20, Col2 = 54 }, new GeneratedLayoutApplyCell { NativeX = 28, NativeY = 19, Row2 = 20, Col2 = 56 }, new GeneratedLayoutApplyCell { NativeX = 29, NativeY = 19, Row2 = 20, Col2 = 58 }, new GeneratedLayoutApplyCell { NativeX = 30, NativeY = 19, Row2 = 20, Col2 = 60 }, new GeneratedLayoutApplyCell { NativeX = 31, NativeY = 19, Row2 = 20, Col2 = 62 }, new GeneratedLayoutApplyCell { NativeX = 32, NativeY = 19, Row2 = 20, Col2 = 64 }, new GeneratedLayoutApplyCell { NativeX = 0, NativeY = 18, Row2 = 22, Col2 = 0 }, new GeneratedLayoutApplyCell { NativeX = 1, NativeY = 18, Row2 = 22, Col2 = 2 }, new GeneratedLayoutApplyCell { NativeX = 2, NativeY = 18, Row2 = 22, Col2 = 4 }, new GeneratedLayoutApplyCell { NativeX = 3, NativeY = 18, Row2 = 22, Col2 = 6 }, new GeneratedLayoutApplyCell { NativeX = 4, NativeY = 18, Row2 = 22, Col2 = 8 }, new GeneratedLayoutApplyCell { NativeX = 5, NativeY = 18, Row2 = 22, Col2 = 10 }, new GeneratedLayoutApplyCell { NativeX = 6, NativeY = 18, Row2 = 22, Col2 = 12 }, new GeneratedLayoutApplyCell { NativeX = 7, NativeY = 18, Row2 = 22, Col2 = 14 }, new GeneratedLayoutApplyCell { NativeX = 8, NativeY = 18, Row2 = 22, Col2 = 16 }, new GeneratedLayoutApplyCell { NativeX = 9, NativeY = 18, Row2 = 22, Col2 = 18 }, new GeneratedLayoutApplyCell { NativeX = 10, NativeY = 18, Row2 = 22, Col2 = 20 }, new GeneratedLayoutApplyCell { NativeX = 11, NativeY = 18, Row2 = 22, Col2 = 22 }, new GeneratedLayoutApplyCell { NativeX = 12, NativeY = 18, Row2 = 22, Col2 = 24 }, new GeneratedLayoutApplyCell { NativeX = 13, NativeY = 18, Row2 = 22, Col2 = 26 }, new GeneratedLayoutApplyCell { NativeX = 14, NativeY = 18, Row2 = 22, Col2 = 28 }, new GeneratedLayoutApplyCell { NativeX = 15, NativeY = 18, Row2 = 22, Col2 = 30 }, new GeneratedLayoutApplyCell { NativeX = 16, NativeY = 18, Row2 = 22, Col2 = 32 }, new GeneratedLayoutApplyCell { NativeX = 17, NativeY = 18, Row2 = 22, Col2 = 34 }, new GeneratedLayoutApplyCell { NativeX = 18, NativeY = 18, Row2 = 22, Col2 = 36 }, new GeneratedLayoutApplyCell { NativeX = 19, NativeY = 18, Row2 = 22, Col2 = 38 }, new GeneratedLayoutApplyCell { NativeX = 20, NativeY = 18, Row2 = 22, Col2 = 40 }, new GeneratedLayoutApplyCell { NativeX = 21, NativeY = 18, Row2 = 22, Col2 = 42 }, new GeneratedLayoutApplyCell { NativeX = 22, NativeY = 18, Row2 = 22, Col2 = 44 }, new GeneratedLayoutApplyCell { NativeX = 23, NativeY = 18, Row2 = 22, Col2 = 46 }, new GeneratedLayoutApplyCell { NativeX = 24, NativeY = 18, Row2 = 22, Col2 = 48 }, new GeneratedLayoutApplyCell { NativeX = 25, NativeY = 18, Row2 = 22, Col2 = 50 }, new GeneratedLayoutApplyCell { NativeX = 26, NativeY = 18, Row2 = 22, Col2 = 52 }, new GeneratedLayoutApplyCell { NativeX = 27, NativeY = 18, Row2 = 22, Col2 = 54 }, new GeneratedLayoutApplyCell { NativeX = 28, NativeY = 18, Row2 = 22, Col2 = 56 }, new GeneratedLayoutApplyCell { NativeX = 29, NativeY = 18, Row2 = 22, Col2 = 58 }, new GeneratedLayoutApplyCell { NativeX = 30, NativeY = 18, Row2 = 22, Col2 = 60 }, new GeneratedLayoutApplyCell { NativeX = 31, NativeY = 18, Row2 = 22, Col2 = 62 }, new GeneratedLayoutApplyCell { NativeX = 32, NativeY = 18, Row2 = 22, Col2 = 64 }, new GeneratedLayoutApplyCell { NativeX = 0, NativeY = 17, Row2 = 24, Col2 = 0 }, new GeneratedLayoutApplyCell { NativeX = 1, NativeY = 17, Row2 = 24, Col2 = 2 }, new GeneratedLayoutApplyCell { NativeX = 2, NativeY = 17, Row2 = 24, Col2 = 4 }, new GeneratedLayoutApplyCell { NativeX = 3, NativeY = 17, Row2 = 24, Col2 = 6 }, new GeneratedLayoutApplyCell { NativeX = 4, NativeY = 17, Row2 = 24, Col2 = 8 }, new GeneratedLayoutApplyCell { NativeX = 5, NativeY = 17, Row2 = 24, Col2 = 10 }, new GeneratedLayoutApplyCell { NativeX = 6, NativeY = 17, Row2 = 24, Col2 = 12 }, new GeneratedLayoutApplyCell { NativeX = 7, NativeY = 17, Row2 = 24, Col2 = 14 }, new GeneratedLayoutApplyCell { NativeX = 8, NativeY = 17, Row2 = 24, Col2 = 16 }, new GeneratedLayoutApplyCell { NativeX = 9, NativeY = 17, Row2 = 24, Col2 = 18 }, new GeneratedLayoutApplyCell { NativeX = 10, NativeY = 17, Row2 = 24, Col2 = 20 }, new GeneratedLayoutApplyCell { NativeX = 11, NativeY = 17, Row2 = 24, Col2 = 22 }, new GeneratedLayoutApplyCell { NativeX = 12, NativeY = 17, Row2 = 24, Col2 = 24 }, new GeneratedLayoutApplyCell { NativeX = 13, NativeY = 17, Row2 = 24, Col2 = 26 }, new GeneratedLayoutApplyCell { NativeX = 14, NativeY = 17, Row2 = 24, Col2 = 28 }, new GeneratedLayoutApplyCell { NativeX = 15, NativeY = 17, Row2 = 24, Col2 = 30 }, new GeneratedLayoutApplyCell { NativeX = 16, NativeY = 17, Row2 = 24, Col2 = 32 }, new GeneratedLayoutApplyCell { NativeX = 17, NativeY = 17, Row2 = 24, Col2 = 34 }, new GeneratedLayoutApplyCell { NativeX = 18, NativeY = 17, Row2 = 24, Col2 = 36 }, new GeneratedLayoutApplyCell { NativeX = 19, NativeY = 17, Row2 = 24, Col2 = 38 }, new GeneratedLayoutApplyCell { NativeX = 20, NativeY = 17, Row2 = 24, Col2 = 40 }, new GeneratedLayoutApplyCell { NativeX = 21, NativeY = 17, Row2 = 24, Col2 = 42 }, new GeneratedLayoutApplyCell { NativeX = 22, NativeY = 17, Row2 = 24, Col2 = 44 }, new GeneratedLayoutApplyCell { NativeX = 23, NativeY = 17, Row2 = 24, Col2 = 46 }, new GeneratedLayoutApplyCell { NativeX = 24, NativeY = 17, Row2 = 24, Col2 = 48 }, new GeneratedLayoutApplyCell { NativeX = 25, NativeY = 17, Row2 = 24, Col2 = 50 }, new GeneratedLayoutApplyCell { NativeX = 26, NativeY = 17, Row2 = 24, Col2 = 52 }, new GeneratedLayoutApplyCell { NativeX = 27, NativeY = 17, Row2 = 24, Col2 = 54 }, new GeneratedLayoutApplyCell { NativeX = 28, NativeY = 17, Row2 = 24, Col2 = 56 }, new GeneratedLayoutApplyCell { NativeX = 29, NativeY = 17, Row2 = 24, Col2 = 58 }, new GeneratedLayoutApplyCell { NativeX = 30, NativeY = 17, Row2 = 24, Col2 = 60 }, new GeneratedLayoutApplyCell { NativeX = 31, NativeY = 17, Row2 = 24, Col2 = 62 }, new GeneratedLayoutApplyCell { NativeX = 32, NativeY = 17, Row2 = 24, Col2 = 64 }, new GeneratedLayoutApplyCell { NativeX = 0, NativeY = 16, Row2 = 26, Col2 = 0 }, new GeneratedLayoutApplyCell { NativeX = 1, NativeY = 16, Row2 = 26, Col2 = 2 }, new GeneratedLayoutApplyCell { NativeX = 2, NativeY = 16, Row2 = 26, Col2 = 4 }, new GeneratedLayoutApplyCell { NativeX = 3, NativeY = 16, Row2 = 26, Col2 = 6 }, new GeneratedLayoutApplyCell { NativeX = 4, NativeY = 16, Row2 = 26, Col2 = 8 }, new GeneratedLayoutApplyCell { NativeX = 5, NativeY = 16, Row2 = 26, Col2 = 10 }, new GeneratedLayoutApplyCell { NativeX = 6, NativeY = 16, Row2 = 26, Col2 = 12 }, new GeneratedLayoutApplyCell { NativeX = 7, NativeY = 16, Row2 = 26, Col2 = 14 }, new GeneratedLayoutApplyCell { NativeX = 8, NativeY = 16, Row2 = 26, Col2 = 16 }, new GeneratedLayoutApplyCell { NativeX = 9, NativeY = 16, Row2 = 26, Col2 = 18 }, new GeneratedLayoutApplyCell { NativeX = 10, NativeY = 16, Row2 = 26, Col2 = 20 }, new GeneratedLayoutApplyCell { NativeX = 11, NativeY = 16, Row2 = 26, Col2 = 22 }, new GeneratedLayoutApplyCell { NativeX = 12, NativeY = 16, Row2 = 26, Col2 = 24 }, new GeneratedLayoutApplyCell { NativeX = 13, NativeY = 16, Row2 = 26, Col2 = 26 }, new GeneratedLayoutApplyCell { NativeX = 14, NativeY = 16, Row2 = 26, Col2 = 28 }, new GeneratedLayoutApplyCell { NativeX = 15, NativeY = 16, Row2 = 26, Col2 = 30 }, new GeneratedLayoutApplyCell { NativeX = 16, NativeY = 16, Row2 = 26, Col2 = 32 }, new GeneratedLayoutApplyCell { NativeX = 17, NativeY = 16, Row2 = 26, Col2 = 34 }, new GeneratedLayoutApplyCell { NativeX = 18, NativeY = 16, Row2 = 26, Col2 = 36 }, new GeneratedLayoutApplyCell { NativeX = 19, NativeY = 16, Row2 = 26, Col2 = 38 }, new GeneratedLayoutApplyCell { NativeX = 20, NativeY = 16, Row2 = 26, Col2 = 40 }, new GeneratedLayoutApplyCell { NativeX = 21, NativeY = 16, Row2 = 26, Col2 = 42 }, new GeneratedLayoutApplyCell { NativeX = 22, NativeY = 16, Row2 = 26, Col2 = 44 }, new GeneratedLayoutApplyCell { NativeX = 23, NativeY = 16, Row2 = 26, Col2 = 46 }, new GeneratedLayoutApplyCell { NativeX = 24, NativeY = 16, Row2 = 26, Col2 = 48 }, new GeneratedLayoutApplyCell { NativeX = 25, NativeY = 16, Row2 = 26, Col2 = 50 }, new GeneratedLayoutApplyCell { NativeX = 26, NativeY = 16, Row2 = 26, Col2 = 52 }, new GeneratedLayoutApplyCell { NativeX = 27, NativeY = 16, Row2 = 26, Col2 = 54 }, new GeneratedLayoutApplyCell { NativeX = 28, NativeY = 16, Row2 = 26, Col2 = 56 }, new GeneratedLayoutApplyCell { NativeX = 29, NativeY = 16, Row2 = 26, Col2 = 58 }, new GeneratedLayoutApplyCell { NativeX = 30, NativeY = 16, Row2 = 26, Col2 = 60 }, new GeneratedLayoutApplyCell { NativeX = 31, NativeY = 16, Row2 = 26, Col2 = 62 }, new GeneratedLayoutApplyCell { NativeX = 32, NativeY = 16, Row2 = 26, Col2 = 64 }, new GeneratedLayoutApplyCell { NativeX = 0, NativeY = 15, Row2 = 28, Col2 = 0 }, new GeneratedLayoutApplyCell { NativeX = 1, NativeY = 15, Row2 = 28, Col2 = 2 }, new GeneratedLayoutApplyCell { NativeX = 2, NativeY = 15, Row2 = 28, Col2 = 4 }, new GeneratedLayoutApplyCell { NativeX = 3, NativeY = 15, Row2 = 28, Col2 = 6 }, new GeneratedLayoutApplyCell { NativeX = 4, NativeY = 15, Row2 = 28, Col2 = 8 }, new GeneratedLayoutApplyCell { NativeX = 5, NativeY = 15, Row2 = 28, Col2 = 10 }, new GeneratedLayoutApplyCell { NativeX = 6, NativeY = 15, Row2 = 28, Col2 = 12 }, new GeneratedLayoutApplyCell { NativeX = 7, NativeY = 15, Row2 = 28, Col2 = 14 }, new GeneratedLayoutApplyCell { NativeX = 8, NativeY = 15, Row2 = 28, Col2 = 16 }, new GeneratedLayoutApplyCell { NativeX = 9, NativeY = 15, Row2 = 28, Col2 = 18 }, new GeneratedLayoutApplyCell { NativeX = 10, NativeY = 15, Row2 = 28, Col2 = 20 }, new GeneratedLayoutApplyCell { NativeX = 11, NativeY = 15, Row2 = 28, Col2 = 22 }, new GeneratedLayoutApplyCell { NativeX = 12, NativeY = 15, Row2 = 28, Col2 = 24 }, new GeneratedLayoutApplyCell { NativeX = 13, NativeY = 15, Row2 = 28, Col2 = 26 }, new GeneratedLayoutApplyCell { NativeX = 14, NativeY = 15, Row2 = 28, Col2 = 28 }, new GeneratedLayoutApplyCell { NativeX = 15, NativeY = 15, Row2 = 28, Col2 = 30 }, new GeneratedLayoutApplyCell { NativeX = 16, NativeY = 15, Row2 = 28, Col2 = 32 }, new GeneratedLayoutApplyCell { NativeX = 17, NativeY = 15, Row2 = 28, Col2 = 34 }, new GeneratedLayoutApplyCell { NativeX = 18, NativeY = 15, Row2 = 28, Col2 = 36 }, new GeneratedLayoutApplyCell { NativeX = 19, NativeY = 15, Row2 = 28, Col2 = 38 }, new GeneratedLayoutApplyCell { NativeX = 20, NativeY = 15, Row2 = 28, Col2 = 40 }, new GeneratedLayoutApplyCell { NativeX = 21, NativeY = 15, Row2 = 28, Col2 = 42 }, new GeneratedLayoutApplyCell { NativeX = 22, NativeY = 15, Row2 = 28, Col2 = 44 }, new GeneratedLayoutApplyCell { NativeX = 23, NativeY = 15, Row2 = 28, Col2 = 46 }, new GeneratedLayoutApplyCell { NativeX = 24, NativeY = 15, Row2 = 28, Col2 = 48 }, new GeneratedLayoutApplyCell { NativeX = 25, NativeY = 15, Row2 = 28, Col2 = 50 }, new GeneratedLayoutApplyCell { NativeX = 26, NativeY = 15, Row2 = 28, Col2 = 52 }, new GeneratedLayoutApplyCell { NativeX = 27, NativeY = 15, Row2 = 28, Col2 = 54 }, new GeneratedLayoutApplyCell { NativeX = 28, NativeY = 15, Row2 = 28, Col2 = 56 }, new GeneratedLayoutApplyCell { NativeX = 29, NativeY = 15, Row2 = 28, Col2 = 58 }, new GeneratedLayoutApplyCell { NativeX = 30, NativeY = 15, Row2 = 28, Col2 = 60 }, new GeneratedLayoutApplyCell { NativeX = 31, NativeY = 15, Row2 = 28, Col2 = 62 }, new GeneratedLayoutApplyCell { NativeX = 32, NativeY = 15, Row2 = 28, Col2 = 64 }, new GeneratedLayoutApplyCell { NativeX = 0, NativeY = 14, Row2 = 30, Col2 = 0 }, new GeneratedLayoutApplyCell { NativeX = 1, NativeY = 14, Row2 = 30, Col2 = 2 }, new GeneratedLayoutApplyCell { NativeX = 2, NativeY = 14, Row2 = 30, Col2 = 4 }, new GeneratedLayoutApplyCell { NativeX = 3, NativeY = 14, Row2 = 30, Col2 = 6 }, new GeneratedLayoutApplyCell { NativeX = 4, NativeY = 14, Row2 = 30, Col2 = 8 }, new GeneratedLayoutApplyCell { NativeX = 5, NativeY = 14, Row2 = 30, Col2 = 10 }, new GeneratedLayoutApplyCell { NativeX = 6, NativeY = 14, Row2 = 30, Col2 = 12 }, new GeneratedLayoutApplyCell { NativeX = 7, NativeY = 14, Row2 = 30, Col2 = 14 }, new GeneratedLayoutApplyCell { NativeX = 8, NativeY = 14, Row2 = 30, Col2 = 16 }, new GeneratedLayoutApplyCell { NativeX = 9, NativeY = 14, Row2 = 30, Col2 = 18 }, new GeneratedLayoutApplyCell { NativeX = 10, NativeY = 14, Row2 = 30, Col2 = 20 }, new GeneratedLayoutApplyCell { NativeX = 11, NativeY = 14, Row2 = 30, Col2 = 22 }, new GeneratedLayoutApplyCell { NativeX = 12, NativeY = 14, Row2 = 30, Col2 = 24 }, new GeneratedLayoutApplyCell { NativeX = 13, NativeY = 14, Row2 = 30, Col2 = 26 }, new GeneratedLayoutApplyCell { NativeX = 14, NativeY = 14, Row2 = 30, Col2 = 28 }, new GeneratedLayoutApplyCell { NativeX = 15, NativeY = 14, Row2 = 30, Col2 = 30 }, new GeneratedLayoutApplyCell { NativeX = 16, NativeY = 14, Row2 = 30, Col2 = 32 }, new GeneratedLayoutApplyCell { NativeX = 17, NativeY = 14, Row2 = 30, Col2 = 34 }, new GeneratedLayoutApplyCell { NativeX = 18, NativeY = 14, Row2 = 30, Col2 = 36 }, new GeneratedLayoutApplyCell { NativeX = 19, NativeY = 14, Row2 = 30, Col2 = 38 }, new GeneratedLayoutApplyCell { NativeX = 20, NativeY = 14, Row2 = 30, Col2 = 40 }, new GeneratedLayoutApplyCell { NativeX = 21, NativeY = 14, Row2 = 30, Col2 = 42 }, new GeneratedLayoutApplyCell { NativeX = 22, NativeY = 14, Row2 = 30, Col2 = 44 }, new GeneratedLayoutApplyCell { NativeX = 23, NativeY = 14, Row2 = 30, Col2 = 46 }, new GeneratedLayoutApplyCell { NativeX = 24, NativeY = 14, Row2 = 30, Col2 = 48 }, new GeneratedLayoutApplyCell { NativeX = 25, NativeY = 14, Row2 = 30, Col2 = 50 }, new GeneratedLayoutApplyCell { NativeX = 26, NativeY = 14, Row2 = 30, Col2 = 52 }, new GeneratedLayoutApplyCell { NativeX = 27, NativeY = 14, Row2 = 30, Col2 = 54 }, new GeneratedLayoutApplyCell { NativeX = 28, NativeY = 14, Row2 = 30, Col2 = 56 }, new GeneratedLayoutApplyCell { NativeX = 29, NativeY = 14, Row2 = 30, Col2 = 58 }, new GeneratedLayoutApplyCell { NativeX = 30, NativeY = 14, Row2 = 30, Col2 = 60 }, new GeneratedLayoutApplyCell { NativeX = 31, NativeY = 14, Row2 = 30, Col2 = 62 }, new GeneratedLayoutApplyCell { NativeX = 32, NativeY = 14, Row2 = 30, Col2 = 64 }, new GeneratedLayoutApplyCell { NativeX = 0, NativeY = 13, Row2 = 32, Col2 = 0 }, new GeneratedLayoutApplyCell { NativeX = 1, NativeY = 13, Row2 = 32, Col2 = 2 }, new GeneratedLayoutApplyCell { NativeX = 2, NativeY = 13, Row2 = 32, Col2 = 4 }, new GeneratedLayoutApplyCell { NativeX = 3, NativeY = 13, Row2 = 32, Col2 = 6 }, new GeneratedLayoutApplyCell { NativeX = 4, NativeY = 13, Row2 = 32, Col2 = 8 }, new GeneratedLayoutApplyCell { NativeX = 5, NativeY = 13, Row2 = 32, Col2 = 10 }, new GeneratedLayoutApplyCell { NativeX = 6, NativeY = 13, Row2 = 32, Col2 = 12 }, new GeneratedLayoutApplyCell { NativeX = 7, NativeY = 13, Row2 = 32, Col2 = 14 }, new GeneratedLayoutApplyCell { NativeX = 8, NativeY = 13, Row2 = 32, Col2 = 16 }, new GeneratedLayoutApplyCell { NativeX = 9, NativeY = 13, Row2 = 32, Col2 = 18 }, new GeneratedLayoutApplyCell { NativeX = 10, NativeY = 13, Row2 = 32, Col2 = 20 }, new GeneratedLayoutApplyCell { NativeX = 11, NativeY = 13, Row2 = 32, Col2 = 22 }, new GeneratedLayoutApplyCell { NativeX = 12, NativeY = 13, Row2 = 32, Col2 = 24 }, new GeneratedLayoutApplyCell { NativeX = 13, NativeY = 13, Row2 = 32, Col2 = 26 }, new GeneratedLayoutApplyCell { NativeX = 14, NativeY = 13, Row2 = 32, Col2 = 28 }, new GeneratedLayoutApplyCell { NativeX = 15, NativeY = 13, Row2 = 32, Col2 = 30 }, new GeneratedLayoutApplyCell { NativeX = 16, NativeY = 13, Row2 = 32, Col2 = 32 }, new GeneratedLayoutApplyCell { NativeX = 17, NativeY = 13, Row2 = 32, Col2 = 34 }, new GeneratedLayoutApplyCell { NativeX = 18, NativeY = 13, Row2 = 32, Col2 = 36 }, new GeneratedLayoutApplyCell { NativeX = 19, NativeY = 13, Row2 = 32, Col2 = 38 }, new GeneratedLayoutApplyCell { NativeX = 20, NativeY = 13, Row2 = 32, Col2 = 40 }, new GeneratedLayoutApplyCell { NativeX = 21, NativeY = 13, Row2 = 32, Col2 = 42 }, new GeneratedLayoutApplyCell { NativeX = 22, NativeY = 13, Row2 = 32, Col2 = 44 }, new GeneratedLayoutApplyCell { NativeX = 23, NativeY = 13, Row2 = 32, Col2 = 46 }, new GeneratedLayoutApplyCell { NativeX = 24, NativeY = 13, Row2 = 32, Col2 = 48 }, new GeneratedLayoutApplyCell { NativeX = 25, NativeY = 13, Row2 = 32, Col2 = 50 }, new GeneratedLayoutApplyCell { NativeX = 26, NativeY = 13, Row2 = 32, Col2 = 52 }, new GeneratedLayoutApplyCell { NativeX = 27, NativeY = 13, Row2 = 32, Col2 = 54 }, new GeneratedLayoutApplyCell { NativeX = 28, NativeY = 13, Row2 = 32, Col2 = 56 }, new GeneratedLayoutApplyCell { NativeX = 29, NativeY = 13, Row2 = 32, Col2 = 58 }, new GeneratedLayoutApplyCell { NativeX = 30, NativeY = 13, Row2 = 32, Col2 = 60 }, new GeneratedLayoutApplyCell { NativeX = 31, NativeY = 13, Row2 = 32, Col2 = 62 }, new GeneratedLayoutApplyCell { NativeX = 32, NativeY = 13, Row2 = 32, Col2 = 64 }, new GeneratedLayoutApplyCell { NativeX = 0, NativeY = 12, Row2 = 34, Col2 = 0 }, new GeneratedLayoutApplyCell { NativeX = 1, NativeY = 12, Row2 = 34, Col2 = 2 }, new GeneratedLayoutApplyCell { NativeX = 2, NativeY = 12, Row2 = 34, Col2 = 4 }, new GeneratedLayoutApplyCell { NativeX = 3, NativeY = 12, Row2 = 34, Col2 = 6 }, new GeneratedLayoutApplyCell { NativeX = 4, NativeY = 12, Row2 = 34, Col2 = 8 }, new GeneratedLayoutApplyCell { NativeX = 5, NativeY = 12, Row2 = 34, Col2 = 10 }, new GeneratedLayoutApplyCell { NativeX = 6, NativeY = 12, Row2 = 34, Col2 = 12 }, new GeneratedLayoutApplyCell { NativeX = 7, NativeY = 12, Row2 = 34, Col2 = 14 }, new GeneratedLayoutApplyCell { NativeX = 8, NativeY = 12, Row2 = 34, Col2 = 16 }, new GeneratedLayoutApplyCell { NativeX = 9, NativeY = 12, Row2 = 34, Col2 = 18 }, new GeneratedLayoutApplyCell { NativeX = 10, NativeY = 12, Row2 = 34, Col2 = 20 }, new GeneratedLayoutApplyCell { NativeX = 11, NativeY = 12, Row2 = 34, Col2 = 22 }, new GeneratedLayoutApplyCell { NativeX = 12, NativeY = 12, Row2 = 34, Col2 = 24 }, new GeneratedLayoutApplyCell { NativeX = 13, NativeY = 12, Row2 = 34, Col2 = 26 }, new GeneratedLayoutApplyCell { NativeX = 14, NativeY = 12, Row2 = 34, Col2 = 28 }, new GeneratedLayoutApplyCell { NativeX = 15, NativeY = 12, Row2 = 34, Col2 = 30 }, new GeneratedLayoutApplyCell { NativeX = 16, NativeY = 12, Row2 = 34, Col2 = 32 }, new GeneratedLayoutApplyCell { NativeX = 17, NativeY = 12, Row2 = 34, Col2 = 34 }, new GeneratedLayoutApplyCell { NativeX = 18, NativeY = 12, Row2 = 34, Col2 = 36 }, new GeneratedLayoutApplyCell { NativeX = 19, NativeY = 12, Row2 = 34, Col2 = 38 }, new GeneratedLayoutApplyCell { NativeX = 20, NativeY = 12, Row2 = 34, Col2 = 40 }, new Gen