using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Spherewright.Bridge.Core.Snapshots; using Spherewright.Contracts.Errors; using Spherewright.Contracts.Factory; using Spherewright.Contracts.Logistics; using Spherewright.Contracts.Players; using Spherewright.Contracts.Progression; using Spherewright.Contracts.Protocol; using Spherewright.Contracts.Resources; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyCompany("Spherewright.Bridge.Core")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.3.3.0")] [assembly: AssemblyInformationalVersion("0.3.3+f0cd11105957ae63cb4b45fd5756b0a42508857f")] [assembly: AssemblyProduct("Spherewright.Bridge.Core")] [assembly: AssemblyTitle("Spherewright.Bridge.Core")] [assembly: AssemblyVersion("0.3.3.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Spherewright.Bridge.Core.Snapshots { public static class OpaqueToken { public static string Create(int byteCount = 32) { if (byteCount < 32) { throw new ArgumentOutOfRangeException("byteCount", "Opaque tokens must contain at least 256 bits of entropy."); } byte[] array = new byte[byteCount]; using (RandomNumberGenerator randomNumberGenerator = RandomNumberGenerator.Create()) { randomNumberGenerator.GetBytes(array); } return Convert.ToBase64String(array).TrimEnd(new char[1] { '=' }).Replace('+', '-') .Replace('/', '_'); } } public enum SnapshotCursorStatus { Success, Missing, Stale, Expired } public sealed class SnapshotPage { public string SnapshotId { get; } public DateTimeOffset ExpiresAtUtc { get; } public IReadOnlyList Items { get; } public string? NextCursor { get; } public SnapshotPage(string snapshotId, DateTimeOffset expiresAtUtc, IReadOnlyList items, string? nextCursor) { SnapshotId = snapshotId; ExpiresAtUtc = expiresAtUtc; Items = items; NextCursor = nextCursor; } } public sealed class SnapshotPageStore { private sealed class SnapshotRecord { public string Id { get; } public string SessionId { get; } public int PlanetId { get; } public string FilterHash { get; } public int PageSize { get; } public DateTimeOffset ExpiresAtUtc { get; } public IReadOnlyList Items { get; } public Dictionary CursorsByOffset { get; } = new Dictionary(); public SnapshotRecord(string id, string sessionId, int planetId, string filterHash, int pageSize, DateTimeOffset expiresAtUtc, IReadOnlyList items) { Id = id; SessionId = sessionId; PlanetId = planetId; FilterHash = filterHash; PageSize = pageSize; ExpiresAtUtc = expiresAtUtc; Items = items; } } private sealed class CursorRecord { public string SnapshotId { get; } public int Offset { get; } public CursorRecord(string snapshotId, int offset) { SnapshotId = snapshotId; Offset = offset; } } private readonly object _gate = new object(); private readonly Dictionary _snapshots = new Dictionary(StringComparer.Ordinal); private readonly Dictionary _cursors = new Dictionary(StringComparer.Ordinal); private readonly TimeSpan _lifetime; private readonly int _capacity; private readonly Func _utcNow; public SnapshotPageStore(TimeSpan lifetime, int capacity, Func? utcNow = null) { if (lifetime <= TimeSpan.Zero) { throw new ArgumentOutOfRangeException("lifetime"); } if (capacity <= 0) { throw new ArgumentOutOfRangeException("capacity"); } _lifetime = lifetime; _capacity = capacity; _utcNow = utcNow ?? ((Func)(() => DateTimeOffset.UtcNow)); } public bool TryCreate(string sessionId, int planetId, string filterHash, IReadOnlyList items, int pageSize, out SnapshotPage? page) { ValidateBinding(sessionId, planetId, filterHash, pageSize); if (items == null) { throw new ArgumentNullException("items"); } lock (_gate) { RemoveExpiredUnsafe(); if (_snapshots.Count >= _capacity) { page = null; return false; } DateTimeOffset dateTimeOffset = _utcNow(); SnapshotRecord snapshotRecord = new SnapshotRecord(OpaqueToken.Create(), sessionId, planetId, filterHash, pageSize, dateTimeOffset.Add(_lifetime), items.ToArray()); _snapshots.Add(snapshotRecord.Id, snapshotRecord); page = CreatePageUnsafe(snapshotRecord, 0); return true; } } public SnapshotCursorStatus TryGetPage(string? cursor, string sessionId, int planetId, string filterHash, int pageSize, out SnapshotPage? page) { ValidateBinding(sessionId, planetId, filterHash, pageSize); page = null; if (string.IsNullOrWhiteSpace(cursor)) { return SnapshotCursorStatus.Missing; } lock (_gate) { if (!_cursors.TryGetValue(cursor, out CursorRecord value) || !_snapshots.TryGetValue(value.SnapshotId, out SnapshotRecord value2)) { return SnapshotCursorStatus.Missing; } if (value2.ExpiresAtUtc <= _utcNow()) { RemoveSnapshotUnsafe(value2.Id); return SnapshotCursorStatus.Expired; } if (!string.Equals(value2.SessionId, sessionId, StringComparison.Ordinal) || value2.PlanetId != planetId || !string.Equals(value2.FilterHash, filterHash, StringComparison.Ordinal) || value2.PageSize != pageSize) { return SnapshotCursorStatus.Stale; } page = CreatePageUnsafe(value2, value.Offset); return SnapshotCursorStatus.Success; } } public void Clear() { lock (_gate) { _cursors.Clear(); _snapshots.Clear(); } } private SnapshotPage CreatePageUnsafe(SnapshotRecord snapshot, int offset) { int num = Math.Min(snapshot.PageSize, Math.Max(0, snapshot.Items.Count - offset)); T[] array = new T[num]; for (int i = 0; i < num; i++) { array[i] = snapshot.Items[offset + i]; } int num2 = offset + num; string text = null; if (num2 < snapshot.Items.Count) { text = (snapshot.CursorsByOffset.TryGetValue(num2, out string value) ? value : OpaqueToken.Create()); snapshot.CursorsByOffset[num2] = text; _cursors[text] = new CursorRecord(snapshot.Id, num2); } return new SnapshotPage(snapshot.Id, snapshot.ExpiresAtUtc, array, text); } private void RemoveExpiredUnsafe() { DateTimeOffset now = _utcNow(); string[] array = (from pair in _snapshots where pair.Value.ExpiresAtUtc <= now select pair.Key).ToArray(); foreach (string snapshotId in array) { RemoveSnapshotUnsafe(snapshotId); } } private void RemoveSnapshotUnsafe(string snapshotId) { if (!_snapshots.TryGetValue(snapshotId, out SnapshotRecord value)) { return; } _snapshots.Remove(snapshotId); foreach (string value2 in value.CursorsByOffset.Values) { _cursors.Remove(value2); } } private static void ValidateBinding(string sessionId, int planetId, string filterHash, int pageSize) { if (string.IsNullOrWhiteSpace(sessionId)) { throw new ArgumentException("A snapshot session ID is required.", "sessionId"); } if (planetId <= 0) { throw new ArgumentOutOfRangeException("planetId"); } if (string.IsNullOrWhiteSpace(filterHash)) { throw new ArgumentException("A snapshot filter hash is required.", "filterHash"); } if (pageSize <= 0) { throw new ArgumentOutOfRangeException("pageSize"); } } } } namespace Spherewright.Bridge.Core.Safety { public static class BeltConnectionProof { public static bool OutputMatches(int expectedObjectId, bool actualIsOutput, int actualObjectId) { if (expectedObjectId > 0) { if (actualIsOutput) { return actualObjectId == expectedObjectId; } return false; } return actualObjectId == 0; } } public static class BuildConnectionSlots { public static IReadOnlyList SelectAvailable(int slotCount, IEnumerable occupiedSlots) { if (slotCount < 0) { throw new ArgumentOutOfRangeException("slotCount"); } if (occupiedSlots == null) { throw new ArgumentNullException("occupiedSlots"); } HashSet hashSet = new HashSet(occupiedSlots.Where((int slot) => slot >= 0 && slot < slotCount)); List list = new List(Math.Max(0, slotCount - hashSet.Count)); for (int num = 0; num < slotCount; num++) { if (!hashSet.Contains(num)) { list.Add(num); } } return list; } public static IReadOnlyList SelectVerificationCandidates(int preparedSlot, int connectionSlotCount) { if (connectionSlotCount < 0) { throw new ArgumentOutOfRangeException("connectionSlotCount"); } if (preparedSlot >= 0) { if (preparedSlot >= connectionSlotCount) { return Array.Empty(); } return new int[1] { preparedSlot }; } return Enumerable.Range(0, connectionSlotCount).ToArray(); } } public readonly struct BuildEntityCandidate { public int EntityId { get; } public float SquaredDistance { get; } public BuildEntityCandidate(int entityId, float squaredDistance) { EntityId = entityId; SquaredDistance = squaredDistance; } } public readonly struct DirectedBuildEntityCandidate { public int EntityId { get; } public int InputObjectId { get; } public int OutputObjectId { get; } public float SquaredDistance { get; } public DirectedBuildEntityCandidate(int entityId, int inputObjectId, int outputObjectId, float squaredDistance) { EntityId = entityId; InputObjectId = inputObjectId; OutputObjectId = outputObjectId; SquaredDistance = squaredDistance; } } public static class BuildEntityAttribution { public static int SelectNearestNewCandidate(IEnumerable candidates, IReadOnlyCollection preexistingEntityIds, IReadOnlyCollection alreadySelectedEntityIds, float maximumSquaredDistance) { if (candidates == null) { throw new ArgumentNullException("candidates"); } if (preexistingEntityIds == null) { throw new ArgumentNullException("preexistingEntityIds"); } if (alreadySelectedEntityIds == null) { throw new ArgumentNullException("alreadySelectedEntityIds"); } if (maximumSquaredDistance <= 0f || float.IsNaN(maximumSquaredDistance) || float.IsInfinity(maximumSquaredDistance)) { throw new ArgumentOutOfRangeException("maximumSquaredDistance"); } int result = 0; float num = maximumSquaredDistance; foreach (BuildEntityCandidate candidate in candidates) { if (candidate.EntityId > 0 && !(candidate.SquaredDistance < 0f) && !float.IsNaN(candidate.SquaredDistance) && !float.IsInfinity(candidate.SquaredDistance) && !preexistingEntityIds.Contains(candidate.EntityId) && !alreadySelectedEntityIds.Contains(candidate.EntityId) && candidate.SquaredDistance < num) { num = candidate.SquaredDistance; result = candidate.EntityId; } } return result; } public static bool TrySelectUniqueDirectedPath(IReadOnlyList> candidatesByStep, IReadOnlyCollection excludedEntityIds, int sourceObjectId, int destinationObjectId, float maximumSquaredDistance, out IReadOnlyList selectedEntityIds) { if (candidatesByStep == null) { throw new ArgumentNullException("candidatesByStep"); } if (excludedEntityIds == null) { throw new ArgumentNullException("excludedEntityIds"); } if (maximumSquaredDistance <= 0f || float.IsNaN(maximumSquaredDistance) || float.IsInfinity(maximumSquaredDistance)) { throw new ArgumentOutOfRangeException("maximumSquaredDistance"); } selectedEntityIds = Array.Empty(); if (candidatesByStep.Count == 0 || candidatesByStep.Any((IReadOnlyList step) => step == null)) { return false; } int[] current = new int[candidatesByStep.Count]; int[] unique = null; int solutionCount = 0; Search(0, sourceObjectId); if (solutionCount != 1 || unique == null) { return false; } selectedEntityIds = unique; return true; void Search(int stepIndex, int expectedInputObjectId) { if (solutionCount <= 1) { if (stepIndex != candidatesByStep.Count) { foreach (DirectedBuildEntityCandidate item in candidatesByStep[stepIndex]) { if (item.EntityId > 0 && !(item.SquaredDistance < 0f) && !(item.SquaredDistance >= maximumSquaredDistance) && !float.IsNaN(item.SquaredDistance) && !float.IsInfinity(item.SquaredDistance) && !excludedEntityIds.Contains(item.EntityId) && !current.Take(stepIndex).Contains(item.EntityId) && (expectedInputObjectId <= 0 || item.InputObjectId == expectedInputObjectId)) { if (stepIndex + 1 < candidatesByStep.Count) { if (item.OutputObjectId <= 0) { continue; } } else if (destinationObjectId > 0 && item.OutputObjectId != destinationObjectId) { continue; } current[stepIndex] = item.EntityId; Search(stepIndex + 1, item.EntityId); current[stepIndex] = 0; } } return; } if (destinationObjectId <= 0 || candidatesByStep.Count <= 0 || candidatesByStep[candidatesByStep.Count - 1].Any((DirectedBuildEntityCandidate candidate) => candidate.EntityId == current[current.Length - 1] && candidate.OutputObjectId == destinationObjectId)) { solutionCount++; unique = current.ToArray(); } } } } } public static class CanonicalStateHash { public const int Version = 1; public static string Player(PlayerStateSnapshot snapshot) { StringBuilder stringBuilder = new StringBuilder(); Append(stringBuilder, "player-v1", snapshot.SessionId, snapshot.PlanetId, snapshot.IsAlive, snapshot.IsOnPlanet, snapshot.MovementState, F(snapshot.Position.X), F(snapshot.Position.Y), F(snapshot.Position.Z), F(snapshot.CoreEnergy), F(snapshot.CoreEnergyCapacity), snapshot.InventorySlotCount, snapshot.InventoryOccupiedSlotCount, F(snapshot.ReactorEnergy), snapshot.ReactorItemId, snapshot.ReactorItemInc, snapshot.AutoReplenishFuel, snapshot.FuelStorageSlotCount, snapshot.FuelStorageOccupiedSlotCount); foreach (PlayerInventoryItem item in snapshot.Inventory.OrderBy((PlayerInventoryItem item) => item.ItemId)) { Append(stringBuilder, "inventory", item.ItemId, item.Count, item.Inc, item.SlotCount); } foreach (PlayerInventoryItem item2 in snapshot.FuelStorage.OrderBy((PlayerInventoryItem item) => item.ItemId)) { Append(stringBuilder, "fuel", item2.ItemId, item2.Count, item2.Inc, item2.SlotCount); } if (snapshot.InHandItem != null) { Append(stringBuilder, "hand", snapshot.InHandItem.ItemId, snapshot.InHandItem.Count, snapshot.InHandItem.Inc, snapshot.InHandItem.SlotCount); } foreach (HandcraftTaskSnapshot item3 in snapshot.HandcraftQueue.OrderBy((HandcraftTaskSnapshot task) => task.QueueIndex)) { Append(stringBuilder, "forge", item3.QueueIndex, item3.RecipeId, item3.RemainingCraftCount, item3.Progress, item3.ProgressRequired, item3.ParentTaskIndex, item3.IngredientsReserved); foreach (PlayerItemAmount item4 in item3.Inputs.OrderBy((PlayerItemAmount item) => item.ItemId)) { Append(stringBuilder, "forge-in", item4.ItemId, item4.Count, item4.BufferedCount); } foreach (PlayerItemAmount item5 in item3.Outputs.OrderBy((PlayerItemAmount item) => item.ItemId)) { Append(stringBuilder, "forge-out", item5.ItemId, item5.Count, item5.BufferedCount); } } Append(stringBuilder, "drones", snapshot.ConstructionDrones.Enabled, snapshot.ConstructionDrones.ConstructionEnabled, snapshot.ConstructionDrones.Total, snapshot.ConstructionDrones.Alive, snapshot.ConstructionDrones.Idle, snapshot.ConstructionDrones.PendingBuildTargets, snapshot.ConstructionDrones.PendingRepairTargets); return Hash(stringBuilder); } public static string PlayerAction(PlayerStateSnapshot snapshot) { StringBuilder stringBuilder = new StringBuilder(); Append(stringBuilder, "player-action-v1", snapshot.SessionId, snapshot.PlanetId, snapshot.IsAlive, snapshot.IsOnPlanet, snapshot.MovementState, Q(snapshot.Position.X), Q(snapshot.Position.Y), Q(snapshot.Position.Z), snapshot.CoreEnergy > 0.0, snapshot.CoreEnergyCapacity > 0.0, snapshot.InventorySlotCount, snapshot.InventoryOccupiedSlotCount, snapshot.ReactorEnergy > 0.0, snapshot.ReactorItemId, snapshot.ReactorItemInc, snapshot.AutoReplenishFuel, snapshot.FuelStorageSlotCount, snapshot.FuelStorageOccupiedSlotCount); foreach (PlayerInventoryItem item in snapshot.Inventory.OrderBy((PlayerInventoryItem item) => item.ItemId)) { Append(stringBuilder, "inventory", item.ItemId, item.Count, item.Inc, item.SlotCount); } foreach (PlayerInventoryItem item2 in snapshot.FuelStorage.OrderBy((PlayerInventoryItem item) => item.ItemId)) { Append(stringBuilder, "fuel", item2.ItemId, item2.Count, item2.Inc, item2.SlotCount); } if (snapshot.InHandItem != null) { Append(stringBuilder, "hand", snapshot.InHandItem.ItemId, snapshot.InHandItem.Count, snapshot.InHandItem.Inc, snapshot.InHandItem.SlotCount); } foreach (HandcraftTaskSnapshot item3 in snapshot.HandcraftQueue.OrderBy((HandcraftTaskSnapshot task) => task.QueueIndex)) { Append(stringBuilder, "forge", item3.QueueIndex, item3.RecipeId, item3.RemainingCraftCount, item3.Progress, item3.ProgressRequired, item3.ParentTaskIndex, item3.IngredientsReserved); } Append(stringBuilder, "drones", snapshot.ConstructionDrones.Enabled, snapshot.ConstructionDrones.ConstructionEnabled, snapshot.ConstructionDrones.Total, snapshot.ConstructionDrones.Alive, snapshot.ConstructionDrones.Idle, snapshot.ConstructionDrones.PendingBuildTargets, snapshot.ConstructionDrones.PendingRepairTargets); return Hash(stringBuilder); } public static string Resource(ResourceNodeSnapshot snapshot) { StringBuilder stringBuilder = new StringBuilder(); Append(stringBuilder, "resource-v1", snapshot.SessionId, snapshot.PlanetId, snapshot.Kind, snapshot.NodeId, snapshot.ResourceType, snapshot.ProtoId, snapshot.RemainingAmount, snapshot.GroupIndex, snapshot.MinerCount, F(snapshot.Position.X), F(snapshot.Position.Y), F(snapshot.Position.Z)); foreach (ResourceYieldSnapshot item in snapshot.Yields.OrderBy((ResourceYieldSnapshot item) => item.ItemId)) { Append(stringBuilder, "yield", item.ItemId, item.Count, F(item.Chance)); } return Hash(stringBuilder); } public static string Progression(ProgressionStateSnapshot snapshot) { StringBuilder stringBuilder = new StringBuilder(); Append(stringBuilder, "progression-v1", snapshot.SessionId, snapshot.PlanetId, snapshot.CurrentTechId); foreach (int item in snapshot.TechQueue) { Append(stringBuilder, "queue", item); } foreach (TechStateSnapshot item2 in snapshot.Technologies.OrderBy((TechStateSnapshot tech) => tech.TechId)) { Append(stringBuilder, "tech", item2.TechId, item2.Unlocked, item2.CurrentLevel, item2.MaximumLevel, item2.HashUploaded, item2.HashRequired, item2.IsLabTech, item2.IsQueued); } return Hash(stringBuilder); } public static string Factory(FactoryEntitySnapshot snapshot) { StringBuilder stringBuilder = new StringBuilder(); Append(stringBuilder, "factory-v1", snapshot.SessionId, snapshot.PlanetId, snapshot.ObjectId, snapshot.ObjectKind, snapshot.ItemId, snapshot.ComponentKind, F(snapshot.Position.X), F(snapshot.Position.Y), F(snapshot.Position.Z), snapshot.RecipeId, snapshot.IsWorking, snapshot.Progress, snapshot.ProgressRequired, snapshot.PowerNetworkId, snapshot.PickTargetObjectId, snapshot.InsertTargetObjectId, snapshot.FilterItemId, snapshot.InserterStage, snapshot.InserterStackCount, snapshot.RequiredBuildItemCount, snapshot.ConstructionProgress.HasValue ? F(snapshot.ConstructionProgress.Value) : string.Empty); foreach (FactoryConnectionSnapshot item in snapshot.Connections.OrderBy((FactoryConnectionSnapshot connection) => connection.Slot)) { Append(stringBuilder, "connection", item.Slot, item.IsOutput, item.OtherObjectId, item.OtherSlot); } foreach (FactoryBufferSnapshot item2 in snapshot.Buffers.OrderBy((FactoryBufferSnapshot buffer) => buffer.Role, StringComparer.Ordinal).ThenBy((FactoryBufferSnapshot buffer) => buffer.ItemId)) { Append(stringBuilder, "buffer", item2.Role, item2.ItemId, item2.Count, item2.Inc); } foreach (int item3 in snapshot.ResourceNodeIds.OrderBy((int id) => id)) { Append(stringBuilder, "node", item3); } return Hash(stringBuilder); } public static string FactoryEndpoint(FactoryEntitySnapshot snapshot) { StringBuilder stringBuilder = new StringBuilder(); Append(stringBuilder, "factory-endpoint-v1", snapshot.SessionId, snapshot.PlanetId, snapshot.ObjectId, snapshot.ObjectKind, snapshot.ItemId, snapshot.ComponentKind, F(snapshot.Position.X), F(snapshot.Position.Y), F(snapshot.Position.Z), F(snapshot.Rotation.X), F(snapshot.Rotation.Y), F(snapshot.Rotation.Z), F(snapshot.Rotation.W)); foreach (FactoryConnectionSnapshot item in snapshot.Connections.OrderBy((FactoryConnectionSnapshot connection) => connection.Slot)) { Append(stringBuilder, "connection", item.Slot, item.IsOutput, item.OtherObjectId, item.OtherSlot); } return Hash(stringBuilder); } public static string FactoryConfiguration(FactoryEntitySnapshot snapshot) { StringBuilder stringBuilder = new StringBuilder(); Append(stringBuilder, "factory-configuration-v1", snapshot.SessionId, snapshot.PlanetId, snapshot.ObjectId, snapshot.ObjectKind, snapshot.ItemId, snapshot.ComponentKind, F(snapshot.Position.X), F(snapshot.Position.Y), F(snapshot.Position.Z), F(snapshot.Rotation.X), F(snapshot.Rotation.Y), F(snapshot.Rotation.Z), F(snapshot.Rotation.W), snapshot.RecipeId, snapshot.PickTargetObjectId, snapshot.InsertTargetObjectId, snapshot.FilterItemId, snapshot.InserterStackCount); foreach (FactoryConnectionSnapshot item in snapshot.Connections.OrderBy((FactoryConnectionSnapshot connection) => connection.Slot)) { Append(stringBuilder, "connection", item.Slot, item.IsOutput, item.OtherObjectId, item.OtherSlot); } foreach (FactoryBufferSnapshot item2 in snapshot.Buffers.OrderBy((FactoryBufferSnapshot buffer) => buffer.Role, StringComparer.Ordinal).ThenBy((FactoryBufferSnapshot buffer) => buffer.ItemId)) { Append(stringBuilder, "buffer", item2.Role, item2.ItemId, item2.Count, item2.Inc); } return Hash(stringBuilder); } public static string ProgressionSelection(ProgressionStateSnapshot snapshot) { StringBuilder stringBuilder = new StringBuilder(); Append(stringBuilder, "progression-selection-v1", snapshot.SessionId, snapshot.PlanetId, snapshot.CurrentTechId); foreach (int item in snapshot.TechQueue) { Append(stringBuilder, "queue", item); } foreach (TechStateSnapshot item2 in snapshot.Technologies.OrderBy((TechStateSnapshot tech) => tech.TechId)) { Append(stringBuilder, "tech", item2.TechId, item2.Unlocked, item2.CurrentLevel, item2.MaximumLevel, item2.HashRequired, item2.IsLabTech, item2.IsQueued); foreach (int item3 in item2.PrerequisiteTechIds.OrderBy((int id) => id)) { Append(stringBuilder, "prerequisite", item2.TechId, item3); } } return Hash(stringBuilder); } public static string LogisticsStation(LogisticsStationSnapshot snapshot) { StringBuilder stringBuilder = new StringBuilder(); AppendLogisticsStationConfiguration(stringBuilder, snapshot, "logistics-station-v1"); Append(stringBuilder, "live", snapshot.PowerServeRatio, snapshot.Energy, snapshot.RequestedChargeEnergyPerTick, snapshot.RequestedChargePowerWatts, snapshot.WarperCount, snapshot.IdleDroneCount, snapshot.WorkingDroneCount, snapshot.IdleVesselCount, snapshot.WorkingVesselCount); foreach (LogisticsStationStorageSlotSnapshot item in snapshot.StorageSlots.OrderBy((LogisticsStationStorageSlotSnapshot slot) => slot.Index)) { Append(stringBuilder, "storage-live", item.Index, item.Count, item.Inc, item.LocalOrder, item.RemoteOrder, item.TotalOrdered, item.LocalSupplyCount, item.LocalDemandCount, item.RemoteSupplyCount, item.RemoteDemandCount); } foreach (int item2 in snapshot.NeededItemIds.OrderBy((int itemId) => itemId)) { Append(stringBuilder, "need", item2); } foreach (LogisticsStationBeltSlotSnapshot item3 in snapshot.BeltSlots.OrderBy((LogisticsStationBeltSlotSnapshot slot) => slot.Index)) { Append(stringBuilder, "belt-live", item3.Index, item3.Counter); } return Hash(stringBuilder); } public static string LogisticsStationConfiguration(LogisticsStationSnapshot snapshot) { StringBuilder stringBuilder = new StringBuilder(); AppendLogisticsStationConfiguration(stringBuilder, snapshot, "logistics-station-config-v1"); return Hash(stringBuilder); } public static string LogisticsStationFleet(LogisticsStationSnapshot snapshot) { StringBuilder stringBuilder = new StringBuilder(); Append(stringBuilder, "logistics-station-fleet-v1", snapshot.SessionId, snapshot.PlanetId, snapshot.EntityId, snapshot.StationId, snapshot.GalacticStationId, snapshot.BuildingItemId, F(snapshot.Position.X), F(snapshot.Position.Y), F(snapshot.Position.Z), snapshot.IsInterstellar, snapshot.IsCollector, snapshot.IsVeinCollector, snapshot.DroneCapacity, snapshot.VesselCapacity, snapshot.IdleDroneCount, snapshot.WorkingDroneCount, snapshot.IdleVesselCount, snapshot.WorkingVesselCount, snapshot.DroneAutoReplenish, snapshot.VesselAutoReplenish); return Hash(stringBuilder); } private static void AppendLogisticsStationConfiguration(StringBuilder value, LogisticsStationSnapshot snapshot, string domain) { Append(value, domain, snapshot.SessionId, snapshot.PlanetId, snapshot.EntityId, snapshot.StationId, snapshot.GalacticStationId, snapshot.BuildingItemId, F(snapshot.Position.X), F(snapshot.Position.Y), F(snapshot.Position.Z), snapshot.IsInterstellar, snapshot.IsCollector, snapshot.IsVeinCollector, snapshot.PowerNetworkId, snapshot.EnergyCapacity, snapshot.MaximumChargeEnergyPerTick, snapshot.MaximumChargePowerWatts, snapshot.WarperCapacity, F(snapshot.DroneTripRangeRaw), F(snapshot.VesselTripRangeRaw), snapshot.IncludeOrbitCollectors, F(snapshot.WarpEnableDistanceRaw), snapshot.WarpersRequired, snapshot.DroneDeliverySetting, snapshot.VesselDeliverySetting, snapshot.PilerCount, snapshot.DroneAutoReplenish, snapshot.VesselAutoReplenish, snapshot.RemoteGroupMask, snapshot.RemoteRoutePriority); foreach (LogisticsStationStorageSlotSnapshot item in snapshot.StorageSlots.OrderBy((LogisticsStationStorageSlotSnapshot slot) => slot.Index)) { Append(value, "storage-config", item.Index, item.ItemId, item.MaximumCount, item.LocalLogic, item.RemoteLogic, item.KeepMode, F(item.KeepIncRatio)); } foreach (LogisticsStationBeltSlotSnapshot item2 in snapshot.BeltSlots.OrderBy((LogisticsStationBeltSlotSnapshot slot) => slot.Index)) { Append(value, "belt-slot", item2.Index, item2.Direction, item2.BeltComponentId, item2.BeltEntityId, item2.StorageIndex); } } public static string Combine(string actionKind, params object?[] fields) { StringBuilder stringBuilder = new StringBuilder(); Append(stringBuilder, "action-v1", actionKind); Append(stringBuilder, fields); return Hash(stringBuilder); } private static string F(float value) { return value.ToString("R", CultureInfo.InvariantCulture); } private static string F(double value) { return value.ToString("R", CultureInfo.InvariantCulture); } private static string Q(float value) { return value.ToString("0.00", CultureInfo.InvariantCulture); } private static void Append(StringBuilder builder, params object?[] fields) { foreach (object obj in fields) { string text = ((obj == null) ? string.Empty : ((!(obj is IFormattable formattable)) ? (obj.ToString() ?? string.Empty) : formattable.ToString(null, CultureInfo.InvariantCulture))); string text2 = text; builder.Append(text2.Length.ToString(CultureInfo.InvariantCulture)); builder.Append(':'); builder.Append(text2); builder.Append('|'); } } private static string Hash(StringBuilder canonical) { using SHA256 sHA = SHA256.Create(); byte[] array = sHA.ComputeHash(Encoding.UTF8.GetBytes(canonical.ToString())); StringBuilder stringBuilder = new StringBuilder(array.Length * 2); byte[] array2 = array; foreach (byte b in array2) { stringBuilder.Append(b.ToString("x2", CultureInfo.InvariantCulture)); } return "sha256:" + stringBuilder; } } public static class GameplayModePolicy { public static bool AllowsNormalActions(bool descriptorAvailable, bool isPeaceful, bool isSandboxMode, bool sandboxToolsEnabled, float resourceMultiplier) { return descriptorAvailable && isPeaceful; } } public sealed class IdempotencyCache { private sealed class Entry { public string Fingerprint { get; } public T Result { get; } public DateTimeOffset ExpiresAtUtc { get; } public Entry(string fingerprint, T result, DateTimeOffset expiresAtUtc) { Fingerprint = fingerprint; Result = result; ExpiresAtUtc = expiresAtUtc; } } private readonly object _gate = new object(); private readonly Dictionary> _entriesByScope = new Dictionary>(StringComparer.Ordinal); private readonly int _capacityPerScope; private readonly TimeSpan _retention; private readonly Func _utcNow; public IdempotencyCache(int capacity) : this(capacity, TimeSpan.FromMinutes(30.0), (Func?)null) { } public IdempotencyCache(int capacity, TimeSpan retention, Func? utcNow = null) { if (capacity <= 0) { throw new ArgumentOutOfRangeException("capacity"); } if (retention <= TimeSpan.Zero) { throw new ArgumentOutOfRangeException("retention"); } _capacityPerScope = capacity; _retention = retention; _utcNow = utcNow ?? ((Func)(() => DateTimeOffset.UtcNow)); } public bool TryGet(string key, string fingerprint, out T? result, out bool conflict) { return TryGetCore(string.Empty, key, fingerprint, out result, out conflict); } public bool TryGet(string scope, string key, string fingerprint, out T? result, out bool conflict) { if (string.IsNullOrWhiteSpace(scope)) { throw new ArgumentException("An idempotency scope is required.", "scope"); } return TryGetCore(scope, key, fingerprint, out result, out conflict); } public bool TryAdd(string key, string fingerprint, T result) { return TryAddCore(string.Empty, key, fingerprint, result); } public bool TryAdd(string scope, string key, string fingerprint, T result) { if (string.IsNullOrWhiteSpace(scope)) { throw new ArgumentException("An idempotency scope is required.", "scope"); } return TryAddCore(scope, key, fingerprint, result); } public bool HasCapacity() { return HasCapacityCore(string.Empty); } public bool HasCapacity(string scope) { if (string.IsNullOrWhiteSpace(scope)) { throw new ArgumentException("An idempotency scope is required.", "scope"); } return HasCapacityCore(scope); } private bool TryGetCore(string scope, string key, string fingerprint, out T? result, out bool conflict) { result = default(T); conflict = false; if (string.IsNullOrWhiteSpace(key) || string.IsNullOrWhiteSpace(fingerprint)) { throw new ArgumentException("Idempotency key and fingerprint are required."); } lock (_gate) { DateTimeOffset now = _utcNow(); RemoveExpiredUnsafe(now); if (!_entriesByScope.TryGetValue(scope, out Dictionary value)) { return false; } if (!value.TryGetValue(key, out var value2)) { return false; } if (!string.Equals(value2.Fingerprint, fingerprint, StringComparison.Ordinal)) { conflict = true; return false; } result = value2.Result; return true; } } private bool TryAddCore(string scope, string key, string fingerprint, T result) { if (string.IsNullOrWhiteSpace(key) || string.IsNullOrWhiteSpace(fingerprint)) { throw new ArgumentException("Idempotency key and fingerprint are required."); } lock (_gate) { DateTimeOffset now = _utcNow(); RemoveExpiredUnsafe(now); if (!_entriesByScope.TryGetValue(scope, out Dictionary value)) { value = new Dictionary(StringComparer.Ordinal); _entriesByScope.Add(scope, value); } if (value.ContainsKey(key)) { return false; } if (value.Count >= _capacityPerScope) { return false; } value.Add(key, new Entry(fingerprint, result, now.Add(_retention))); return true; } } private bool HasCapacityCore(string scope) { lock (_gate) { RemoveExpiredUnsafe(_utcNow()); Dictionary value; return !_entriesByScope.TryGetValue(scope, out value) || value.Count < _capacityPerScope; } } private void RemoveExpiredUnsafe(DateTimeOffset now) { string[] array = _entriesByScope.Keys.ToArray(); foreach (string key in array) { Dictionary dictionary = _entriesByScope[key]; string[] array2 = (from pair in dictionary where pair.Value.ExpiresAtUtc <= now select pair.Key).ToArray(); foreach (string key2 in array2) { dictionary.Remove(key2); } if (dictionary.Count == 0) { _entriesByScope.Remove(key); } } } } public readonly struct FlightPathPoint { public double X { get; } public double Y { get; } public double Z { get; } public FlightPathPoint(double x, double y, double z) { X = x; Y = y; Z = z; } } public readonly struct FlightPathDetour { public int ObstacleBodyId { get; } public FlightPathPoint AimPoint { get; } public double AlongRouteDistance { get; } public double DirectClearance { get; } public double RequiredClearance { get; } public double DetourRadius { get; } public FlightPathDetour(int obstacleBodyId, FlightPathPoint aimPoint, double alongRouteDistance, double directClearance, double requiredClearance, double detourRadius) { ObstacleBodyId = obstacleBodyId; AimPoint = aimPoint; AlongRouteDistance = alongRouteDistance; DirectClearance = directClearance; RequiredClearance = requiredClearance; DetourRadius = detourRadius; } } public static class InterplanetaryFlightPathAvoidance { public const double MinimumSafetyMargin = 1000.0; public const double RelativeSafetyMargin = 0.75; public const double DetourRadiusFactor = 1.5; private const double MinimumRouteLength = 1.0; private const double MinimumVectorLengthSquared = 1E-12; private const double SegmentSafetyFactor = 1.05; private const int MaximumDetourExpansionAttempts = 8; public static bool TryCreateDetour(FlightPathPoint currentPosition, FlightPathPoint destinationPosition, int obstacleBodyId, FlightPathPoint obstacleCenter, double obstacleRadius, out FlightPathDetour detour) { ValidateFinite(currentPosition, "currentPosition"); ValidateFinite(destinationPosition, "destinationPosition"); detour = default(FlightPathDetour); if (obstacleBodyId <= 0 || !IsFinite(obstacleRadius) || obstacleRadius <= 0.0 || !IsFinite(obstacleCenter)) { return false; } FlightPathPoint flightPathPoint = Subtract(destinationPosition, currentPosition); double num = LengthSquared(flightPathPoint); if (num < 1.0) { return false; } double num2 = Dot(Subtract(obstacleCenter, currentPosition), flightPathPoint) / num; if (num2 <= 0.0 || num2 >= 1.0) { return false; } FlightPathPoint value = Subtract(Add(currentPosition, Scale(flightPathPoint, num2)), obstacleCenter); double num3 = Length(value); double num4 = obstacleRadius + Math.Max(1000.0, obstacleRadius * 0.75); if (num3 >= num4) { return false; } double num5 = Math.Sqrt(num); FlightPathPoint direction = Scale(flightPathPoint, 1.0 / num5); FlightPathPoint normalized; FlightPathPoint value2 = (TryNormalize(value, out normalized) ? normalized : SelectStablePerpendicular(direction)); double num6 = num4 * 1.5; double num7 = num4 * 1.05; FlightPathPoint flightPathPoint2 = Add(obstacleCenter, Scale(value2, num6)); for (int i = 0; i < 8; i++) { double num8 = DistanceToSegment(obstacleCenter, currentPosition, flightPathPoint2); double num9 = DistanceToSegment(obstacleCenter, flightPathPoint2, destinationPosition); if (num8 >= num7 && num9 >= num7) { detour = new FlightPathDetour(obstacleBodyId, flightPathPoint2, num2 * num5, num3, num4, num6); return true; } num6 *= 1.25; flightPathPoint2 = Add(obstacleCenter, Scale(value2, num6)); } return false; } public static bool IsPreferred(FlightPathDetour candidate, FlightPathDetour? current) { if (!current.HasValue) { return true; } int num = candidate.AlongRouteDistance.CompareTo(current.Value.AlongRouteDistance); if (num == 0) { return candidate.ObstacleBodyId < current.Value.ObstacleBodyId; } return num < 0; } private static FlightPathPoint SelectStablePerpendicular(FlightPathPoint direction) { FlightPathPoint right = ((Math.Abs(direction.X) <= Math.Abs(direction.Y) && Math.Abs(direction.X) <= Math.Abs(direction.Z)) ? new FlightPathPoint(1.0, 0.0, 0.0) : ((Math.Abs(direction.Y) <= Math.Abs(direction.Z)) ? new FlightPathPoint(0.0, 1.0, 0.0) : new FlightPathPoint(0.0, 0.0, 1.0))); if (!TryNormalize(Cross(direction, right), out var normalized)) { return new FlightPathPoint(0.0, 1.0, 0.0); } return normalized; } private static double DistanceToSegment(FlightPathPoint point, FlightPathPoint segmentStart, FlightPathPoint segmentEnd) { FlightPathPoint flightPathPoint = Subtract(segmentEnd, segmentStart); double num = LengthSquared(flightPathPoint); if (num < 1E-12) { return Length(Subtract(point, segmentStart)); } double val = Dot(Subtract(point, segmentStart), flightPathPoint) / num; val = Math.Max(0.0, Math.Min(1.0, val)); FlightPathPoint right = Add(segmentStart, Scale(flightPathPoint, val)); return Length(Subtract(point, right)); } private static bool TryNormalize(FlightPathPoint value, out FlightPathPoint normalized) { double num = LengthSquared(value); if (num < 1E-12) { normalized = default(FlightPathPoint); return false; } normalized = Scale(value, 1.0 / Math.Sqrt(num)); return true; } private static FlightPathPoint Add(FlightPathPoint left, FlightPathPoint right) { return new FlightPathPoint(left.X + right.X, left.Y + right.Y, left.Z + right.Z); } private static FlightPathPoint Subtract(FlightPathPoint left, FlightPathPoint right) { return new FlightPathPoint(left.X - right.X, left.Y - right.Y, left.Z - right.Z); } private static FlightPathPoint Scale(FlightPathPoint value, double scale) { return new FlightPathPoint(value.X * scale, value.Y * scale, value.Z * scale); } private static FlightPathPoint Cross(FlightPathPoint left, FlightPathPoint right) { return new FlightPathPoint(left.Y * right.Z - left.Z * right.Y, left.Z * right.X - left.X * right.Z, left.X * right.Y - left.Y * right.X); } private static double Dot(FlightPathPoint left, FlightPathPoint right) { return left.X * right.X + left.Y * right.Y + left.Z * right.Z; } private static double Length(FlightPathPoint value) { return Math.Sqrt(LengthSquared(value)); } private static double LengthSquared(FlightPathPoint value) { return Dot(value, value); } private static void ValidateFinite(FlightPathPoint value, string parameterName) { if (!IsFinite(value)) { throw new ArgumentOutOfRangeException(parameterName); } } private static bool IsFinite(FlightPathPoint value) { if (IsFinite(value.X) && IsFinite(value.Y)) { return IsFinite(value.Z); } return false; } private static bool IsFinite(double value) { if (!double.IsNaN(value)) { return !double.IsInfinity(value); } return false; } } public sealed class LandingShoreCandidateScore { public int Index { get; set; } public double SurfaceDistance { get; set; } public double TerrainClearance { get; set; } } public static class LandingShoreSelection { public static bool IsEligible(LandingShoreCandidateScore candidate, double minimumDistance, double maximumDistance, double minimumTerrainClearance) { if (candidate == null) { throw new ArgumentNullException("candidate"); } if (IsFinite(candidate.SurfaceDistance) && IsFinite(candidate.TerrainClearance) && candidate.SurfaceDistance >= minimumDistance && candidate.SurfaceDistance <= maximumDistance) { return candidate.TerrainClearance >= minimumTerrainClearance; } return false; } public static bool IsPreferred(LandingShoreCandidateScore candidate, LandingShoreCandidateScore? current) { if (candidate == null) { throw new ArgumentNullException("candidate"); } if (current == null) { return true; } int num = candidate.SurfaceDistance.CompareTo(current.SurfaceDistance); if (num != 0) { return num < 0; } int num2 = candidate.TerrainClearance.CompareTo(current.TerrainClearance); if (num2 == 0) { return candidate.Index < current.Index; } return num2 > 0; } private static bool IsFinite(double value) { if (!double.IsNaN(value)) { return !double.IsInfinity(value); } return false; } } public sealed class MovementFailureRecoveryAdvice { public string FailureKind { get; set; } = string.Empty; public long StalledGameTicks { get; set; } public double RemainingDistance { get; set; } public bool DoNotRetrySameTarget { get; set; } public string RecommendedRecovery { get; set; } = string.Empty; public double RecommendedShortMoveDistanceMeters { get; set; } public double OrthogonalProbeDistanceMeters { get; set; } public int MaximumOrthogonalProbeAttempts { get; set; } } public static class MovementFailureRecoveryAdvisor { public const double SingleObstacleMoveDistanceMeters = 5.0; public const double OrthogonalProbeDistanceMeters = 4.0; public const int MaximumOrthogonalProbeAttempts = 4; public const string RecoverySummary = "Fresh-read the player and nearby geometry. If one obstacle is identifiable, prepare and commit one local-tangent target about 5 m away from it. Otherwise try at most four orthogonal local-tangent targets about 4 m away, each direction once. Poll every returned actionId to terminal; after success fresh-read Walk, low speed, and sufficient energy."; public static MovementFailureRecoveryAdvice ForStall(MovementProgressObservation observation) { return Create(observation.Status switch { MovementProgressStatus.PositionStalled => "position_stalled", MovementProgressStatus.RouteStalled => "route_stalled", _ => throw new ArgumentException("A progressing observation has no movement-failure recovery advice.", "observation"), }, observation.StalledGameTicks, observation.RemainingDistance); } public static MovementFailureRecoveryAdvice ForBoundedTimeout(long elapsedGameTicks, double remainingDistance) { return Create("bounded_timeout", elapsedGameTicks, remainingDistance); } private static MovementFailureRecoveryAdvice Create(string failureKind, long stalledGameTicks, double remainingDistance) { return new MovementFailureRecoveryAdvice { FailureKind = failureKind, StalledGameTicks = stalledGameTicks, RemainingDistance = remainingDistance, DoNotRetrySameTarget = true, RecommendedRecovery = "Fresh-read the player and nearby geometry. If one obstacle is identifiable, prepare and commit one local-tangent target about 5 m away from it. Otherwise try at most four orthogonal local-tangent targets about 4 m away, each direction once. Poll every returned actionId to terminal; after success fresh-read Walk, low speed, and sufficient energy.", RecommendedShortMoveDistanceMeters = 5.0, OrthogonalProbeDistanceMeters = 4.0, MaximumOrthogonalProbeAttempts = 4 }; } } public enum MovementProgressStatus { Progressing, PositionStalled, RouteStalled } public readonly struct MovementProgressObservation { public MovementProgressStatus Status { get; } public long StalledGameTicks { get; } public double RemainingDistance { get; } public MovementProgressObservation(MovementProgressStatus status, long stalledGameTicks, double remainingDistance) { Status = status; StalledGameTicks = stalledGameTicks; RemainingDistance = remainingDistance; } } public sealed class MovementProgressWatchdog { public const long DefaultPositionStallTicks = 180L; public const long DefaultRouteStallTicks = 600L; public const double DefaultMinimumDisplacement = 0.75; public const double DefaultMinimumTargetProgress = 1.0; private readonly long _positionStallTicks; private readonly long _routeStallTicks; private readonly double _minimumDisplacementSquared; private readonly double _minimumTargetProgress; private double _checkpointX; private double _checkpointY; private double _checkpointZ; private long _lastDisplacementGameTick; private double _bestRemainingDistance; private long _lastTargetProgressGameTick; public MovementProgressWatchdog(long startedAtGameTick, double initialX, double initialY, double initialZ, double initialRemainingDistance, long positionStallTicks = 180L, long routeStallTicks = 600L, double minimumDisplacement = 0.75, double minimumTargetProgress = 1.0) { if (startedAtGameTick < 0) { throw new ArgumentOutOfRangeException("startedAtGameTick"); } if (positionStallTicks <= 0) { throw new ArgumentOutOfRangeException("positionStallTicks"); } if (routeStallTicks < positionStallTicks) { throw new ArgumentOutOfRangeException("routeStallTicks"); } ValidateFinite(initialX, "initialX"); ValidateFinite(initialY, "initialY"); ValidateFinite(initialZ, "initialZ"); ValidateNonNegativeFinite(initialRemainingDistance, "initialRemainingDistance"); ValidatePositiveFinite(minimumDisplacement, "minimumDisplacement"); ValidatePositiveFinite(minimumTargetProgress, "minimumTargetProgress"); _positionStallTicks = positionStallTicks; _routeStallTicks = routeStallTicks; _minimumDisplacementSquared = minimumDisplacement * minimumDisplacement; _minimumTargetProgress = minimumTargetProgress; _checkpointX = initialX; _checkpointY = initialY; _checkpointZ = initialZ; _lastDisplacementGameTick = startedAtGameTick; _bestRemainingDistance = initialRemainingDistance; _lastTargetProgressGameTick = startedAtGameTick; } public MovementProgressObservation Observe(long gameTick, double x, double y, double z, double remainingDistance) { if (gameTick < _lastDisplacementGameTick || gameTick < _lastTargetProgressGameTick) { throw new ArgumentOutOfRangeException("gameTick"); } ValidateFinite(x, "x"); ValidateFinite(y, "y"); ValidateFinite(z, "z"); ValidateNonNegativeFinite(remainingDistance, "remainingDistance"); double num = x - _checkpointX; double num2 = y - _checkpointY; double num3 = z - _checkpointZ; if (num * num + num2 * num2 + num3 * num3 >= _minimumDisplacementSquared) { _checkpointX = x; _checkpointY = y; _checkpointZ = z; _lastDisplacementGameTick = gameTick; } if (remainingDistance <= _bestRemainingDistance - _minimumTargetProgress) { _bestRemainingDistance = remainingDistance; _lastTargetProgressGameTick = gameTick; } long num4 = gameTick - _lastDisplacementGameTick; if (num4 >= _positionStallTicks) { return new MovementProgressObservation(MovementProgressStatus.PositionStalled, num4, remainingDistance); } long num5 = gameTick - _lastTargetProgressGameTick; if (num5 < _routeStallTicks) { return new MovementProgressObservation(MovementProgressStatus.Progressing, 0L, remainingDistance); } return new MovementProgressObservation(MovementProgressStatus.RouteStalled, num5, remainingDistance); } public void ResetWindow(long gameTick, double x, double y, double z, double remainingDistance) { if (gameTick < _lastDisplacementGameTick || gameTick < _lastTargetProgressGameTick) { throw new ArgumentOutOfRangeException("gameTick"); } ValidateFinite(x, "x"); ValidateFinite(y, "y"); ValidateFinite(z, "z"); ValidateNonNegativeFinite(remainingDistance, "remainingDistance"); _checkpointX = x; _checkpointY = y; _checkpointZ = z; _lastDisplacementGameTick = gameTick; _bestRemainingDistance = remainingDistance; _lastTargetProgressGameTick = gameTick; } private static void ValidateFinite(double value, string parameterName) { if (double.IsNaN(value) || double.IsInfinity(value)) { throw new ArgumentOutOfRangeException(parameterName); } } private static void ValidateNonNegativeFinite(double value, string parameterName) { ValidateFinite(value, parameterName); if (value < 0.0) { throw new ArgumentOutOfRangeException(parameterName); } } private static void ValidatePositiveFinite(double value, string parameterName) { ValidateFinite(value, parameterName); if (value <= 0.0) { throw new ArgumentOutOfRangeException(parameterName); } } } public static class OwnedWorldProvenancePolicy { public static bool MatchesProtectedSaveIdentity(string? ticketOwnedSaveName, string? loadedSaveName) { if (!string.IsNullOrWhiteSpace(ticketOwnedSaveName)) { return string.Equals(ticketOwnedSaveName, loadedSaveName, StringComparison.Ordinal); } return false; } } public enum OwnedWorldResumeSourceKind { None, LastExit, OwnedPrimary } public static class OwnedWorldResumeSourceSelector { public static OwnedWorldResumeSourceKind Select(bool quarantineRecovery, long minimumGameTick, DateTimeOffset ticketIssuedAtUtc, DateTimeOffset? lastExitWrittenAtUtc, long? lastExitGameTick, DateTimeOffset? ownedPrimaryWrittenAtUtc, long? ownedPrimaryGameTick, TimeSpan timestampTolerance) { if (minimumGameTick < 0) { throw new ArgumentOutOfRangeException("minimumGameTick"); } if (timestampTolerance < TimeSpan.Zero) { throw new ArgumentOutOfRangeException("timestampTolerance"); } DateTimeOffset dateTimeOffset = ticketIssuedAtUtc - timestampTolerance; DateTimeOffset? dateTimeOffset2; DateTimeOffset dateTimeOffset3; if (quarantineRecovery) { dateTimeOffset2 = lastExitWrittenAtUtc; dateTimeOffset3 = dateTimeOffset; if (!dateTimeOffset2.HasValue || !(dateTimeOffset2.GetValueOrDefault() >= dateTimeOffset3) || !(lastExitGameTick >= minimumGameTick)) { return OwnedWorldResumeSourceKind.None; } return OwnedWorldResumeSourceKind.LastExit; } dateTimeOffset2 = ownedPrimaryWrittenAtUtc; dateTimeOffset3 = dateTimeOffset; if (!dateTimeOffset2.HasValue || !(dateTimeOffset2.GetValueOrDefault() >= dateTimeOffset3) || !(ownedPrimaryGameTick >= minimumGameTick)) { return OwnedWorldResumeSourceKind.None; } return OwnedWorldResumeSourceKind.OwnedPrimary; } } public sealed class PreparedPlan { public string Token { get; } public DateTimeOffset ExpiresAtUtc { get; } public string Fingerprint { get; } public T Payload { get; } internal PreparedPlan(string token, DateTimeOffset expiresAtUtc, string fingerprint, T payload) { Token = token; ExpiresAtUtc = expiresAtUtc; Fingerprint = fingerprint; Payload = payload; } } public sealed class PreparedPlanStore { private readonly object _gate = new object(); private readonly Dictionary> _plans = new Dictionary>(StringComparer.Ordinal); private readonly TimeSpan _lifetime; private readonly int _capacity; private readonly Func _utcNow; public PreparedPlanStore(TimeSpan lifetime, int capacity, Func? utcNow = null) { if (lifetime <= TimeSpan.Zero) { throw new ArgumentOutOfRangeException("lifetime"); } if (capacity <= 0) { throw new ArgumentOutOfRangeException("capacity"); } _lifetime = lifetime; _capacity = capacity; _utcNow = utcNow ?? ((Func)(() => DateTimeOffset.UtcNow)); } public PreparedPlan Add(string fingerprint, T payload) { if (string.IsNullOrWhiteSpace(fingerprint)) { throw new ArgumentException("A plan fingerprint is required.", "fingerprint"); } lock (_gate) { RemoveExpiredUnsafe(); if (_plans.Count >= _capacity) { throw new InvalidOperationException("Prepared-plan capacity has been reached."); } PreparedPlan preparedPlan = new PreparedPlan(OpaqueToken.Create(), _utcNow().Add(_lifetime), fingerprint, payload); _plans.Add(preparedPlan.Token, preparedPlan); return preparedPlan; } } public bool TryTake(string token, out PreparedPlan? plan, out bool expired) { plan = null; expired = false; if (string.IsNullOrWhiteSpace(token)) { return false; } lock (_gate) { if (!_plans.TryGetValue(token, out PreparedPlan value)) { return false; } _plans.Remove(token); if (value.ExpiresAtUtc <= _utcNow()) { expired = true; return false; } plan = value; return true; } } public bool TryGet(string token, out PreparedPlan? plan, out bool expired) { plan = null; expired = false; if (string.IsNullOrWhiteSpace(token)) { return false; } lock (_gate) { if (!_plans.TryGetValue(token, out PreparedPlan value)) { return false; } if (value.ExpiresAtUtc <= _utcNow()) { _plans.Remove(token); expired = true; return false; } plan = value; return true; } } public bool Remove(string token) { if (string.IsNullOrWhiteSpace(token)) { return false; } lock (_gate) { return _plans.Remove(token); } } private void RemoveExpiredUnsafe() { DateTimeOffset now = _utcNow(); string[] array = (from pair in _plans where pair.Value.ExpiresAtUtc <= now select pair.Key).ToArray(); foreach (string key in array) { _plans.Remove(key); } } } public sealed class ResourceCoverageCandidateScore { public int Index { get; set; } public int CoveredNodeCount { get; set; } public double DistanceToBoundNode { get; set; } public double Yaw { get; set; } } public static class ResourceCoverageSelection { public static int SelectBestIndex(IReadOnlyList candidates) { if (candidates == null || candidates.Count == 0) { return -1; } return (from candidate in candidates orderby candidate.CoveredNodeCount descending, candidate.DistanceToBoundNode, candidate.Yaw, candidate.Index select candidate).First().Index; } } public static class SorterFilterPolicy { public static bool IsSafeAssignmentWindow(int filterItemId, int pickTargetObjectId, int insertTargetObjectId, int heldItemId, int heldItemCount, int heldStackCount, int heldItemInc) { if (filterItemId >= 0 && pickTargetObjectId != 0 && insertTargetObjectId != 0 && heldItemId == 0 && heldItemCount == 0 && heldStackCount == 0) { return heldItemInc == 0; } return false; } } public static class SpherewrightSaveNameFactory { public const string NewWorldPrefix = "Spherewright_New_"; public const string ImportedWorldPrefix = "Spherewright_Imported_"; public static string CreateNewWorldName(DateTimeOffset createdAtUtc, Guid uniqueness) { return Create("Spherewright_New_", createdAtUtc, uniqueness); } public static string CreateImportedWorldName(DateTimeOffset createdAtUtc, Guid uniqueness) { return Create("Spherewright_Imported_", createdAtUtc, uniqueness); } private static string Create(string prefix, DateTimeOffset createdAtUtc, Guid uniqueness) { return $"{prefix}{createdAtUtc.UtcDateTime:yyyyMMdd_HHmmss}_{uniqueness:N}"; } } public static class UserSaveImportConfirmationPolicy { public static bool IsCommitDeclared(bool userConfirmedInConversation, bool acknowledgeOriginalSaveRemainsUnchanged, bool acknowledgeJournalStartsAtImport) { return userConfirmedInConversation && acknowledgeOriginalSaveRemainsUnchanged && acknowledgeJournalStartsAtImport; } } public static class UserSaveImportSafetyPolicy { public static bool IsEnabled(bool allowWrites, bool allowUserSaveImport) { return allowWrites && allowUserSaveImport; } public static bool MatchesPreparedCandidate(string? expectedSessionId, string? currentSessionId, long expectedRevision, long currentRevision, object? expectedGameData, object? currentGameData) { if (!string.IsNullOrWhiteSpace(expectedSessionId) && string.Equals(expectedSessionId, currentSessionId, StringComparison.Ordinal) && expectedRevision == currentRevision && expectedGameData != null) { return expectedGameData == currentGameData; } return false; } public static bool HasVerifiedCopyHeader(bool saveReturnedTrue, long expectedGameTick, long? headerGameTick) { if (saveReturnedTrue && expectedGameTick >= 0) { return headerGameTick == expectedGameTick; } return false; } } } namespace Spherewright.Bridge.Core.Routing { public static class ProtocolValidator { public static BridgeError? ValidateHeader(BridgeEnvelopeHeader? header, string expectedMessageType) { if (header == null) { return Invalid("The bridge envelope is missing."); } if (header.ProtocolVersion != 1) { return BridgeError.Create("INVALID_REQUEST", $"Protocol version {header.ProtocolVersion} is not supported.", false, $"Use protocol version {1}."); } if (!string.Equals(header.MessageType, expectedMessageType, StringComparison.Ordinal)) { return Invalid("Expected message type '" + expectedMessageType + "'."); } if (!Guid.TryParse(header.RequestId, out var _)) { return Invalid("requestId must be a UUID."); } return null; } private static BridgeError Invalid(string message) { return BridgeError.Create("INVALID_REQUEST", message, false, "Create a new request that matches the Spherewright bridge schema."); } } } namespace Spherewright.Bridge.Core.Progression { public static class RuntimeDependencyGraphBuilder { public static RuntimeDependencyGraph Build(int targetItemId, string targetItemName, IReadOnlyList recipes) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Expected O, but got Unknown //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Expected O, but got Unknown RuntimeDependencyGraph val = new RuntimeDependencyGraph { TargetItemId = targetItemId, TargetItemName = (targetItemName ?? string.Empty) }; if (targetItemId <= 0) { return val; } Dictionary> dictionary = new Dictionary>(); foreach (RecipeCatalogEntry recipe in recipes) { foreach (CatalogItemAmount output in recipe.Outputs) { if (!dictionary.TryGetValue(output.ItemId, out var value)) { value = new List(); dictionary.Add(output.ItemId, value); } value.Add(recipe); } } Stack stack = new Stack(); HashSet hashSet = new HashSet(); HashSet hashSet2 = new HashSet(); stack.Push(targetItemId); while (stack.Count > 0) { int num = stack.Pop(); if (!hashSet.Add(num) || !dictionary.TryGetValue(num, out var value2)) { continue; } foreach (RecipeCatalogEntry item in value2.OrderBy((RecipeCatalogEntry entry) => entry.RecipeId)) { if (!hashSet2.Add(item.RecipeId)) { continue; } foreach (CatalogItemAmount input in item.Inputs) { val.Edges.Add(new RuntimeDependencyEdge { FromKind = "item", FromId = input.ItemId, ToKind = "recipe", ToId = item.RecipeId }); stack.Push(input.ItemId); } foreach (CatalogItemAmount output2 in item.Outputs) { val.Edges.Add(new RuntimeDependencyEdge { FromKind = "recipe", FromId = item.RecipeId, ToKind = "item", ToId = output2.ItemId }); } } } val.ItemIds = (from id in (from id in val.Edges.SelectMany((RuntimeDependencyEdge edge) => new int[2] { (edge.FromKind == "item") ? edge.FromId : 0, (edge.ToKind == "item") ? edge.ToId : 0 }) where id > 0 select id).Append(targetItemId).Distinct() orderby id select id).ToList(); val.RecipeIds = hashSet2.OrderBy((int id) => id).ToList(); val.Edges = val.Edges.OrderBy((RuntimeDependencyEdge edge) => edge.FromKind, StringComparer.Ordinal).ThenBy((RuntimeDependencyEdge edge) => edge.FromId).ThenBy((RuntimeDependencyEdge edge) => edge.ToKind, StringComparer.Ordinal) .ThenBy((RuntimeDependencyEdge edge) => edge.ToId) .ToList(); return val; } } } namespace Spherewright.Bridge.Core.Logistics { public static class LogisticsStationChargePolicy { public const long EnergyPerTickStep = 50000L; public const long PowerWattsStep = 3000000L; public static bool TryNormalizeUiPower(long prefabWorkEnergyPerTick, long requestedPowerWatts, out long requestedEnergyPerTick, out long minimumEnergyPerTick, out long maximumEnergyPerTick) { requestedEnergyPerTick = 0L; minimumEnergyPerTick = 0L; maximumEnergyPerTick = 0L; if (prefabWorkEnergyPerTick <= 0 || prefabWorkEnergyPerTick > 30744573456182586L || requestedPowerWatts <= 0 || requestedPowerWatts % 3000000 != 0L) { return false; } minimumEnergyPerTick = prefabWorkEnergyPerTick / 2 / 50000 * 50000; maximumEnergyPerTick = prefabWorkEnergyPerTick * 5 / 50000 * 50000; requestedEnergyPerTick = requestedPowerWatts / 60; if (minimumEnergyPerTick > 0 && maximumEnergyPerTick >= minimumEnergyPerTick && requestedEnergyPerTick >= minimumEnergyPerTick) { return requestedEnergyPerTick <= maximumEnergyPerTick; } return false; } } public static class LogisticsStationFleetTransferPolicy { public static bool TryValidate(bool isInterstellar, bool isCollector, bool isVeinCollector, string direction, int itemId, int count, int playerItemCount, int playerItemInc, int idleDroneCount, int workingDroneCount, int droneCapacity, int idleVesselCount, int workingVesselCount, int vesselCapacity, bool playerCanAcceptWithdrawal, out string rejection) { rejection = string.Empty; if (isCollector || isVeinCollector) { rejection = "Orbital and vein collectors do not expose an ordinary player fleet slot."; return false; } if (direction != "player-to-station" && direction != "station-to-player") { rejection = "Fleet transfer direction must be player-to-station or station-to-player."; return false; } if (count <= 0 || count > 100) { rejection = "Fleet transfer count must be from 1 through 100."; return false; } bool flag = itemId == 5001; bool flag2 = itemId == 5002; if (!flag && !flag2) { rejection = "Only logistics drones (5001) or logistics vessels (5002) belong in station fleet slots."; return false; } if (flag2 && !isInterstellar) { rejection = "A planetary logistics station has no logistics-vessel slot."; return false; } int num = (flag ? idleDroneCount : idleVesselCount); int num2 = (flag ? workingDroneCount : workingVesselCount); int num3 = (flag ? droneCapacity : vesselCapacity); if (num < 0 || num2 < 0 || num3 <= 0 || num + num2 > num3) { rejection = "The station fleet counters or current-version prefab capacity are inconsistent."; return false; } if (direction == "player-to-station") { if (playerItemCount < count) { rejection = "The player package contains fewer than the requested fleet items."; return false; } if (playerItemInc != 0) { rejection = "Proliferated fleet items are rejected because the normal station UI discards their proliferator points."; return false; } if (num + num2 + count > num3) { rejection = "The requested items exceed the station fleet capacity after working craft are included."; return false; } return true; } if (num < count) { rejection = "Only idle station craft can be withdrawn, and fewer than the requested count are idle."; return false; } if (!playerCanAcceptWithdrawal) { rejection = "The player package cannot accept the exact requested withdrawal."; return false; } return true; } } public static class LogisticsStationIdentityPolicy { public static bool MatchesLocalPlanet(bool isInterstellar, int stationPlanetId, int factoryPlanetId) { if (factoryPlanetId <= 0) { return false; } if (isInterstellar) { return stationPlanetId == factoryPlanetId; } if (stationPlanetId != 0) { return stationPlanetId == factoryPlanetId; } return true; } } } namespace Spherewright.Bridge.Core.Journals { public sealed class GameplayFirstOccurrenceDetector { private readonly HashSet _manualItemIds; private readonly HashSet _productionLineItemIds; private readonly HashSet _researchIds; public GameplayFirstOccurrenceDetector(IEnumerable? knownManualItemIds = null, IEnumerable? knownProductionLineItemIds = null, IEnumerable? knownResearchIds = null) { _manualItemIds = new HashSet(knownManualItemIds ?? Enumerable.Empty()); _productionLineItemIds = new HashSet(knownProductionLineItemIds ?? Enumerable.Empty()); _researchIds = new HashSet(knownResearchIds ?? Enumerable.Empty()); } public IReadOnlyList ObserveManualCounts(IReadOnlyDictionary cumulativeCounts) { return ObserveItemCounts(cumulativeCounts, _manualItemIds, "manual_item_first"); } public IReadOnlyList ObserveProductionLineCounts(IReadOnlyDictionary producedThisTick) { return ObserveItemCounts(producedThisTick, _productionLineItemIds, "production_line_item_first"); } public bool TryObserveResearchSelection(int techId) { if (techId > 0) { return _researchIds.Add(techId); } return false; } private static IReadOnlyList ObserveItemCounts(IReadOnlyDictionary counts, HashSet knownIds, string kind) { List list = new List(); foreach (KeyValuePair item in counts.OrderBy((KeyValuePair pair) => pair.Key)) { if (item.Key > 0 && item.Value > 0 && knownIds.Add(item.Key)) { list.Add(new GameplayItemFirstOccurrence(item.Key, item.Value, kind)); } } return list; } } public sealed class GameplayItemFirstOccurrence { public int ItemId { get; } public long ObservedCount { get; } public string Kind { get; } public GameplayItemFirstOccurrence(int itemId, long observedCount, string kind) { ItemId = itemId; ObservedCount = observedCount; Kind = kind; } } } namespace Spherewright.Bridge.Core.Framing { public sealed class FrameCodec { private static readonly UTF8Encoding StrictUtf8 = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true); private readonly int _maxFrameBytes; public FrameCodec(int maxFrameBytes) { if (maxFrameBytes <= 0) { throw new ArgumentOutOfRangeException("maxFrameBytes"); } _maxFrameBytes = maxFrameBytes; } public async Task ReadFrameAsync(Stream stream, CancellationToken cancellationToken) { if (stream == null) { throw new ArgumentNullException("stream"); } byte[] header = new byte[4]; int num = await stream.ReadAsync(header, 0, header.Length, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (num == 0) { return null; } await ReadRemainderAsync(stream, header, num, header.Length, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); int num2 = header[0] | (header[1] << 8) | (header[2] << 16) | (header[3] << 24); if (num2 < 0) { throw new FrameProtocolException("Frame length must not be negative."); } if (num2 > _maxFrameBytes) { throw new FrameProtocolException($"Frame length {num2} exceeds the configured maximum {_maxFrameBytes}."); } byte[] payload = new byte[num2]; if (num2 > 0) { await ReadRemainderAsync(stream, payload, 0, num2, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } return payload; } public async Task WriteFrameAsync(Stream stream, byte[] payload, CancellationToken cancellationToken) { if (stream == null) { throw new ArgumentNullException("stream"); } if (payload == null) { throw new ArgumentNullException("payload"); } if (payload.Length > _maxFrameBytes) { throw new FrameProtocolException($"Frame length {payload.Length} exceeds the configured maximum {_maxFrameBytes}."); } int num = payload.Length; byte[] array = new byte[4] { (byte)num, (byte)(num >> 8), (byte)(num >> 16), (byte)(num >> 24) }; await stream.WriteAsync(array, 0, array.Length, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (payload.Length != 0) { await stream.WriteAsync(payload, 0, payload.Length, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } await stream.FlushAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } public static string DecodeUtf8(byte[] payload) { if (payload == null) { throw new ArgumentNullException("payload"); } try { return StrictUtf8.GetString(payload); } catch (DecoderFallbackException innerException) { throw new FrameProtocolException("Frame payload is not valid UTF-8.", innerException); } } public static byte[] EncodeUtf8(string text) { if (text == null) { throw new ArgumentNullException("text"); } return StrictUtf8.GetBytes(text); } private static async Task ReadRemainderAsync(Stream stream, byte[] buffer, int offset, int expectedCount, CancellationToken cancellationToken) { int num; for (int readTotal = offset; readTotal < expectedCount; readTotal += num) { num = await stream.ReadAsync(buffer, readTotal, expectedCount - readTotal, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (num == 0) { throw new EndOfStreamException("Connection ended before the complete frame was received."); } } } } public sealed class FrameProtocolException : Exception { public FrameProtocolException(string message) : base(message) { } public FrameProtocolException(string message, Exception innerException) : base(message, innerException) { } } } namespace Spherewright.Bridge.Core.Authentication { public sealed class HandshakeAuthenticator { private readonly string _bridgeInstanceId; private readonly byte[] _authTokenBytes; public HandshakeAuthenticator(string bridgeInstanceId, string authToken) { if (string.IsNullOrWhiteSpace(bridgeInstanceId)) { throw new ArgumentException("Bridge instance ID is required.", "bridgeInstanceId"); } if (string.IsNullOrWhiteSpace(authToken)) { throw new ArgumentException("Authentication token is required.", "authToken"); } _bridgeInstanceId = bridgeInstanceId; _authTokenBytes = Encoding.UTF8.GetBytes(authToken); } public BridgeError? Authenticate(HandshakeRequest? request) { if (request == null || !string.Equals(request.BridgeInstanceId, _bridgeInstanceId, StringComparison.Ordinal) || !FixedTimeEquals(_authTokenBytes, Encoding.UTF8.GetBytes(request.AuthToken ?? string.Empty))) { return BridgeError.Create("AUTH_FAILED", "Bridge authentication failed.", false, "Rediscover the active Spherewright bridge descriptor and reconnect."); } if (string.IsNullOrWhiteSpace(request.ClientName) || string.IsNullOrWhiteSpace(request.ClientVersion)) { return BridgeError.Create("INVALID_REQUEST", "Handshake client name and version are required.", false, "Send a complete handshake request."); } return null; } private static bool FixedTimeEquals(byte[] expected, byte[] actual) { int num = expected.Length ^ actual.Length; int num2 = Math.Max(expected.Length, actual.Length); for (int i = 0; i < num2; i++) { byte b = (byte)((i < expected.Length) ? expected[i] : 0); byte b2 = (byte)((i < actual.Length) ? actual[i] : 0); num |= b ^ b2; } return num == 0; } } } namespace Spherewright.Bridge.Core.Abstractions { public sealed class BoundedMainThreadDispatcher : IDisposable { private interface IWorkItem { void Execute(); void Cancel(); } private sealed class WorkItem : IWorkItem { private readonly Func _operation; private readonly TaskCompletionSource _completion = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); public Task Task => _completion.Task; public WorkItem(Func operation) { _operation = operation; } public void Execute() { try { _completion.TrySetResult(_operation()); } catch (Exception exception) { _completion.TrySetException(exception); } } public void Cancel() { _completion.TrySetCanceled(); } } private readonly object _gate = new object(); private readonly Queue _queue = new Queue(); private readonly int _capacity; private bool _disposed; public int Count { get { lock (_gate) { return _queue.Count; } } } public BoundedMainThreadDispatcher(int capacity) { if (capacity <= 0) { throw new ArgumentOutOfRangeException("capacity"); } _capacity = capacity; } public bool TryEnqueue(Func operation, out Task completion) { if (operation == null) { throw new ArgumentNullException("operation"); } WorkItem workItem = new WorkItem(operation); lock (_gate) { if (_disposed || _queue.Count >= _capacity) { completion = workItem.Task; workItem.Cancel(); return false; } _queue.Enqueue(workItem); completion = workItem.Task; return true; } } public int Pump(int maxItems, TimeSpan budget) { if (maxItems <= 0) { throw new ArgumentOutOfRangeException("maxItems"); } if (budget <= TimeSpan.Zero) { throw new ArgumentOutOfRangeException("budget"); } Stopwatch stopwatch = Stopwatch.StartNew(); int i; for (i = 0; i < maxItems; i++) { if (!(stopwatch.Elapsed < budget)) { break; } IWorkItem workItem; lock (_gate) { workItem = ((_queue.Count > 0) ? _queue.Dequeue() : null); } if (workItem == null) { break; } workItem.Execute(); } return i; } public void Dispose() { IWorkItem[] array; lock (_gate) { if (_disposed) { return; } _disposed = true; array = _queue.ToArray(); _queue.Clear(); } IWorkItem[] array2 = array; for (int i = 0; i < array2.Length; i++) { array2[i].Cancel(); } } } }