using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using Microsoft.CodeAnalysis; [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("UnifiedStorage.Core")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+5d7be5f6efeb56f9a845ddaab6e91dfa01032b38")] [assembly: AssemblyProduct("UnifiedStorage.Core")] [assembly: AssemblyTitle("UnifiedStorage.Core")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } [CompilerGenerated] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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 UnifiedStorage.Core { public static class AggregationService { public static IReadOnlyList Aggregate(IReadOnlyList sourceStacks, Func? resolveMaxStackSize = null) { Func resolveMaxStackSize2 = resolveMaxStackSize; return (from item in (from s in sourceStacks where s.Amount > 0 group s by s.Key).Select(delegate(IGrouping @group) { int num = ((resolveMaxStackSize2 != null) ? resolveMaxStackSize2(@group.Key.PrefabName) : @group.Max((SourceStack s) => s.StackSize)); if (num <= 0) { num = 1; } return new AggregatedItem { Key = @group.Key, DisplayName = (@group.Select((SourceStack s) => s.DisplayName).FirstOrDefault() ?? @group.Key.PrefabName), TotalAmount = @group.Sum((SourceStack s) => s.Amount), SourceCount = @group.Select((SourceStack s) => s.SourceId).Distinct().Count(), StackSize = num }; }) orderby item.DisplayName, item.TotalAmount descending select item).ToList(); } public static int CalculateVirtualSlots(IReadOnlyList items) { return items.Sum((AggregatedItem i) => (i.StackSize <= 0) ? 1 : ((int)Math.Ceiling((double)i.TotalAmount / (double)i.StackSize))); } } public static class ChunkedTransfer { public static int ClampMeasuredMove(int requestedAmount, int beforeAmount, int afterAmount) { if (requestedAmount <= 0) { return 0; } int num = afterAmount - beforeAmount; if (num <= 0) { return 0; } return Math.Min(requestedAmount, num); } public static int Move(int requestedAmount, int maxChunkSize, Func moveChunk) { if (moveChunk == null) { throw new ArgumentNullException("moveChunk"); } if (requestedAmount <= 0 || maxChunkSize <= 0) { return 0; } int num = requestedAmount; int num2 = 0; while (num > 0) { int num3 = Math.Min(maxChunkSize, num); int num4 = moveChunk(num3); if (num4 <= 0) { break; } if (num4 > num3) { num4 = num3; } num2 += num4; num -= num4; if (num4 < num3) { break; } } return num2; } } public sealed class ContainerSlot { public string SourceId { get; set; } = string.Empty; public int FreeSpace { get; set; } public float Distance { get; set; } } public static class DepositPlanner { public static DepositPlan Plan(IReadOnlyList containers, int requestedAmount) { DepositPlan depositPlan = new DepositPlan { RequestedAmount = requestedAmount }; int num = Math.Max(0, requestedAmount); if (num <= 0 || containers.Count == 0) { return depositPlan; } int num2 = num; foreach (ContainerSlot item in (from c in containers where c.FreeSpace > 0 orderby c.Distance select c).ThenBy((ContainerSlot c) => c.SourceId, StringComparer.Ordinal)) { if (num2 <= 0) { break; } int num3 = Math.Min(item.FreeSpace, num2); if (num3 > 0) { depositPlan.Deposits.Add(new PlannedDeposit { SourceId = item.SourceId, Amount = num3 }); num2 -= num3; } } depositPlan.PlannedAmount = num - num2; return depositPlan; } } public readonly struct ItemKey : IEquatable { public string PrefabName { get; } public int Quality { get; } public int Variant { get; } public ItemKey(string prefabName, int quality, int variant) { PrefabName = prefabName ?? string.Empty; Quality = quality; Variant = variant; } public bool Equals(ItemKey other) { if (string.Equals(PrefabName, other.PrefabName, StringComparison.Ordinal) && Quality == other.Quality) { return Variant == other.Variant; } return false; } public override bool Equals(object? obj) { if (obj is ItemKey other) { return Equals(other); } return false; } public override int GetHashCode() { return ((17 * 23 + (PrefabName?.GetHashCode() ?? 0)) * 23 + Quality.GetHashCode()) * 23 + Variant.GetHashCode(); } } public sealed class AggregatedItem { public ItemKey Key { get; set; } public string DisplayName { get; set; } = string.Empty; public int TotalAmount { get; set; } public int SourceCount { get; set; } public int StackSize { get; set; } } public sealed class SearchResult { public IReadOnlyList Items { get; set; } = Array.Empty(); } public sealed class SourceStack { public ItemKey Key { get; set; } public string DisplayName { get; set; } = string.Empty; public int Amount { get; set; } public int StackSize { get; set; } public float Distance { get; set; } public string SourceId { get; set; } = string.Empty; } public sealed class PlannedTake { public string SourceId { get; set; } = string.Empty; public int Amount { get; set; } } public sealed class WithdrawPlan { public List Takes { get; set; } = new List(); public int RequestedAmount { get; set; } public int PlannedAmount { get; set; } } public sealed class PlannedDeposit { public string SourceId { get; set; } = string.Empty; public int Amount { get; set; } } public sealed class DepositPlan { public List Deposits { get; set; } = new List(); public int RequestedAmount { get; set; } public int PlannedAmount { get; set; } } public static class SearchService { public static SearchResult Filter(IReadOnlyList items, string query) { if (items.Count == 0) { return new SearchResult(); } if (string.IsNullOrWhiteSpace(query)) { return new SearchResult { Items = items }; } string trimmed = query.Trim(); List items2 = items.Where((AggregatedItem item) => item.DisplayName.IndexOf(trimmed, StringComparison.OrdinalIgnoreCase) >= 0).ToList(); return new SearchResult { Items = items2 }; } } public static class WithdrawPlanner { public static WithdrawPlan Plan(IReadOnlyList sourceStacks, ItemKey key, int requestedAmount, int maxReceivable) { int val = Math.Max(0, requestedAmount); int num = Math.Max(0, Math.Min(val, maxReceivable)); int num2 = num; WithdrawPlan withdrawPlan = new WithdrawPlan { RequestedAmount = requestedAmount }; if (num2 <= 0) { return withdrawPlan; } foreach (SourceStack item in (from s in sourceStacks where s.Key.Equals(key) && s.Amount > 0 orderby s.Distance select s).ThenBy((SourceStack s) => s.SourceId, StringComparer.Ordinal)) { if (num2 == 0) { break; } int num3 = Math.Min(item.Amount, num2); if (num3 > 0) { withdrawPlan.Takes.Add(new PlannedTake { SourceId = item.SourceId, Amount = num3 }); num2 -= num3; } } withdrawPlan.PlannedAmount = num - num2; return withdrawPlan; } } }