using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using JetBrains.Annotations; using Microsoft.CodeAnalysis; using ServerSync; using Splatform; using TMPro; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.UI; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Core.ObjectPool; using YamlDotNet.Core.Tokens; using YamlDotNet.Helpers; using YamlDotNet.Serialization; using YamlDotNet.Serialization.BufferedDeserialization; using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators; using YamlDotNet.Serialization.Callbacks; using YamlDotNet.Serialization.Converters; using YamlDotNet.Serialization.EventEmitters; using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.NodeDeserializers; using YamlDotNet.Serialization.NodeTypeResolvers; using YamlDotNet.Serialization.ObjectFactories; using YamlDotNet.Serialization.ObjectGraphTraversalStrategies; using YamlDotNet.Serialization.ObjectGraphVisitors; using YamlDotNet.Serialization.Schemas; using YamlDotNet.Serialization.TypeInspectors; using YamlDotNet.Serialization.TypeResolvers; using YamlDotNet.Serialization.Utilities; using YamlDotNet.Serialization.ValueDeserializers; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("ZoneSavior")] [assembly: AssemblyDescription("Dedicated-server zone archiving, zone bundle restore, zone UI, and per-zone WearNTear limits for Valheim.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("sighsorry")] [assembly: AssemblyProduct("ZoneSavior")] [assembly: AssemblyCopyright("Copyright 2026 sighsorry")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("B276E8F6-7F9F-4A0F-8E7D-757383FF7CB1")] [assembly: AssemblyFileVersion("1.0.1")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [CompilerGenerated] internal sealed class <>z__ReadOnlySingleElementList : IEnumerable, ICollection, IList, IEnumerable, IReadOnlyCollection, IReadOnlyList, ICollection, IList { private sealed class Enumerator : IDisposable, IEnumerator, IEnumerator { object IEnumerator.Current => _item; T IEnumerator.Current => _item; public Enumerator(T item) { _item = item; } bool IEnumerator.MoveNext() { if (!_moveNextCalled) { return _moveNextCalled = true; } return false; } void IEnumerator.Reset() { _moveNextCalled = false; } void IDisposable.Dispose() { } } int ICollection.Count => 1; bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; object IList.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } set { throw new NotSupportedException(); } } bool IList.IsFixedSize => true; bool IList.IsReadOnly => true; int IReadOnlyCollection.Count => 1; T IReadOnlyList.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } } int ICollection.Count => 1; bool ICollection.IsReadOnly => true; T IList.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } set { throw new NotSupportedException(); } } public <>z__ReadOnlySingleElementList(T item) { _item = item; } IEnumerator IEnumerable.GetEnumerator() { return new Enumerator(_item); } void ICollection.CopyTo(Array array, int index) { array.SetValue(_item, index); } int IList.Add(object value) { throw new NotSupportedException(); } void IList.Clear() { throw new NotSupportedException(); } bool IList.Contains(object value) { return EqualityComparer.Default.Equals(_item, (T)value); } int IList.IndexOf(object value) { if (!EqualityComparer.Default.Equals(_item, (T)value)) { return -1; } return 0; } void IList.Insert(int index, object value) { throw new NotSupportedException(); } void IList.Remove(object value) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } IEnumerator IEnumerable.GetEnumerator() { return new Enumerator(_item); } void ICollection.Add(T item) { throw new NotSupportedException(); } void ICollection.Clear() { throw new NotSupportedException(); } bool ICollection.Contains(T item) { return EqualityComparer.Default.Equals(_item, item); } void ICollection.CopyTo(T[] array, int arrayIndex) { array[arrayIndex] = _item; } bool ICollection.Remove(T item) { throw new NotSupportedException(); } int IList.IndexOf(T item) { if (!EqualityComparer.Default.Equals(_item, item)) { return -1; } return 0; } void IList.Insert(int index, T item) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } } namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [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; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class ExtensionMarkerAttribute : Attribute { private readonly string k__BackingField; public string Name => k__BackingField; public ExtensionMarkerAttribute(string name) { k__BackingField = name; } } } namespace ZoneSavior { internal static class AutoArchiveCommands { [CompilerGenerated] private static class <>O { public static ConsoleEvent <0>__HandleCommand; public static Action <1>__RPC_HandleRequest; public static Action <2>__RPC_HandleResult; public static Func <3>__IsDigit; } [CompilerGenerated] private sealed class <>c__DisplayClass24_0 { public ZoneBundleCommandResult result; internal void b__0(ZoneBundleCommandResult value) { result = value; } } [CompilerGenerated] private sealed class d__24 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string tag; public Action onComplete; private <>c__DisplayClass24_0 <>8__1; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__24(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__1 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass24_0(); <>8__1.result = ZoneBundleCommandResult.Fail("Archive restore failed before it started."); <>2__current = ZoneBundleCommands.RestoreTagToOriginalZonesAsync(tag, delegate(ZoneBundleCommandResult value) { <>8__1.result = value; }); <>1__state = 1; return true; case 1: <>1__state = -1; onComplete(<>8__1.result.Success ? AutoArchiveCommandResult.Ok(new <>z__ReadOnlySingleElementList(<>8__1.result.Message)) : AutoArchiveCommandResult.Fail(<>8__1.result.Message)); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private const string ScanCommand = "zs_archive_scan"; private const string StatusCommand = "zs_archive_status"; private const string PlayerCommand = "zs_archive_player"; private const string ListCommand = "zs_archive_list"; private const string MarkSeenCommand = "zs_archive_mark_seen"; private const string IgnorePlayerCommand = "zs_archive_ignore_player"; private const string RestoreCommand = "zs_archive_restore"; private const string ScheduleCommand = "zs_archive_schedule"; private const string DebugZoneCommand = "zs_archive_debug_zone"; private const string RequestRpcName = "sighsorry.ZoneSavior_AutoArchiveCommandRequest"; private const string ResultRpcName = "sighsorry.ZoneSavior_AutoArchiveCommandResult"; private static readonly Regex ZoneSpecPattern = new Regex("^\\s*\\(\\s*(-?\\d+)\\s*,\\s*(-?\\d+)\\s*\\)\\s*$", RegexOptions.Compiled); private static ManualLogSource _logger = null; private static bool _initialized; private static readonly ZoneRpcRegistrar RpcRegistrar = new ZoneRpcRegistrar(); public static void Initialize(ManualLogSource logger) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Expected O, but got Unknown //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Expected O, but got Unknown //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Expected O, but got Unknown //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Expected O, but got Unknown //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Expected O, but got Unknown //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Expected O, but got Unknown if (!_initialized) { _initialized = true; _logger = logger; object obj = <>O.<0>__HandleCommand; if (obj == null) { ConsoleEvent val = HandleCommand; <>O.<0>__HandleCommand = val; obj = (object)val; } new ConsoleCommand("zs_archive_scan", "[dry|save|reset] - Runs an auto archive scan.", (ConsoleEvent)obj, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj2 = <>O.<0>__HandleCommand; if (obj2 == null) { ConsoleEvent val2 = HandleCommand; <>O.<0>__HandleCommand = val2; obj2 = (object)val2; } new ConsoleCommand("zs_archive_status", "- Prints auto archive activity status.", (ConsoleEvent)obj2, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj3 = <>O.<0>__HandleCommand; if (obj3 == null) { ConsoleEvent val3 = HandleCommand; <>O.<0>__HandleCommand = val3; obj3 = (object)val3; } new ConsoleCommand("zs_archive_player", "steamID [dry|save|reset] - Runs an auto archive scan filtered to one Steam owner.", (ConsoleEvent)obj3, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj4 = <>O.<0>__HandleCommand; if (obj4 == null) { ConsoleEvent val4 = HandleCommand; <>O.<0>__HandleCommand = val4; obj4 = (object)val4; } new ConsoleCommand("zs_archive_list", "- Lists recent auto archive runs.", (ConsoleEvent)obj4, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj5 = <>O.<0>__HandleCommand; if (obj5 == null) { ConsoleEvent val5 = HandleCommand; <>O.<0>__HandleCommand = val5; obj5 = (object)val5; } new ConsoleCommand("zs_archive_mark_seen", "playerID - Marks a playerID as seen now.", (ConsoleEvent)obj5, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj6 = <>O.<0>__HandleCommand; if (obj6 == null) { ConsoleEvent val6 = HandleCommand; <>O.<0>__HandleCommand = val6; obj6 = (object)val6; } new ConsoleCommand("zs_archive_ignore_player", "playerID [on|off] - Protects or unprotects a playerID from auto archive.", (ConsoleEvent)obj6, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj7 = <>O.<0>__HandleCommand; if (obj7 == null) { ConsoleEvent val7 = HandleCommand; <>O.<0>__HandleCommand = val7; obj7 = (object)val7; } new ConsoleCommand("zs_archive_restore", "tag - Restores an archived tag to its original zones.", (ConsoleEvent)obj7, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj8 = <>O.<0>__HandleCommand; if (obj8 == null) { ConsoleEvent val8 = HandleCommand; <>O.<0>__HandleCommand = val8; obj8 = (object)val8; } new ConsoleCommand("zs_archive_schedule", "[status|now|clear|last yyyy-MM-dd HH:mm|next yyyy-MM-dd HH:mm] - Shows or adjusts the automatic archive scan schedule anchor. Local server time is used unless the date includes Z or an offset.", (ConsoleEvent)obj8, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj9 = <>O.<0>__HandleCommand; if (obj9 == null) { ConsoleEvent val9 = HandleCommand; <>O.<0>__HandleCommand = val9; obj9 = (object)val9; } new ConsoleCommand("zs_archive_debug_zone", "(x,z) - Writes a YAML report explaining auto archive eligibility for one zone.", (ConsoleEvent)obj9, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); RegisterRpcs(); } } internal static void RegisterRpcs() { RpcRegistrar.EnsureRegistered(delegate(ZRoutedRpc routedRpc) { routedRpc.Register("sighsorry.ZoneSavior_AutoArchiveCommandRequest", (Action)RPC_HandleRequest); routedRpc.Register("sighsorry.ZoneSavior_AutoArchiveCommandResult", (Action)RPC_HandleResult); }); } private static void HandleCommand(ConsoleEventArgs args) { EnsureCommandReady(); DispatchRequest(new AutoArchiveCommandRequest { Command = ((args.Args.Length != 0) ? args.Args[0] : ""), Args = args.Args.ToList() }, args.Context); } private static void DispatchRequest(AutoArchiveCommandRequest request, Terminal? context) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown Terminal context2 = context; if (ZNet.instance.IsServer()) { StartRequest(request, delegate(AutoArchiveCommandResult result) { ShowResult(result, context2); }); return; } RegisterRpcs(); ZPackage val = new ZPackage(); val.Write(ZoneBundleSerialization.Serialize(request)); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), "sighsorry.ZoneSavior_AutoArchiveCommandRequest", new object[1] { val }); Terminal obj = context2; if (obj != null) { obj.AddString(request.Command + " request sent to server."); } } private static void RPC_HandleRequest(long sender, ZPackage package) { if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } try { if (!IsAuthorizedSender(sender)) { SendResult(sender, AutoArchiveCommandResult.Fail("Admin only.")); return; } StartRequest(ZoneBundleSerialization.Deserialize(package.ReadString()), delegate(AutoArchiveCommandResult result) { SendResult(sender, result); }); } catch (Exception ex) { _logger.LogError((object)$"Auto archive command RPC failed: {ex}"); SendResult(sender, AutoArchiveCommandResult.Fail(ex.Message)); } } private static void SendResult(long target, AutoArchiveCommandResult result) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown if (ZRoutedRpc.instance != null) { ZPackage val = new ZPackage(); val.Write(ZoneBundleSerialization.Serialize(result)); ZRoutedRpc.instance.InvokeRoutedRPC(target, "sighsorry.ZoneSavior_AutoArchiveCommandResult", new object[1] { val }); } } private static void RPC_HandleResult(long sender, ZPackage package) { if (!((Object)(object)ZNet.instance != (Object)null) || !ZNet.instance.IsServer()) { ShowResult(ZoneBundleSerialization.Deserialize(package.ReadString()), (Terminal?)(object)Console.instance); } } private static void StartRequest(AutoArchiveCommandRequest request, Action onComplete) { if ((Object)(object)ZoneSaviorPlugin.Instance != (Object)null && TryGetRestoreTag(request, out string tag, out AutoArchiveCommandResult validationResult)) { if (validationResult != null) { onComplete(validationResult); } else { ((MonoBehaviour)ZoneSaviorPlugin.Instance).StartCoroutine(ExecuteRestoreAsync(tag, onComplete)); } } else { onComplete(ExecuteRequest(request)); } } private static bool TryGetRestoreTag(AutoArchiveCommandRequest request, out string tag, out AutoArchiveCommandResult? validationResult) { tag = ""; validationResult = null; string text = request.Command; string[] array = request.Args?.ToArray() ?? Array.Empty(); if (string.IsNullOrWhiteSpace(text) && array.Length != 0) { text = array[0]; } if (!string.Equals(text, "zs_archive_restore", StringComparison.OrdinalIgnoreCase)) { return false; } if (array.Length < 2) { validationResult = AutoArchiveCommandResult.Fail("Syntax: zs_archive_restore tag"); return true; } tag = array[1]; return true; } [IteratorStateMachine(typeof(d__24))] private static IEnumerator ExecuteRestoreAsync(string tag, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__24(0) { tag = tag, onComplete = onComplete }; } private static AutoArchiveCommandResult ExecuteRequest(AutoArchiveCommandRequest request) { List messages = new List(); try { string text = request.Command; string[] array = request.Args?.ToArray() ?? Array.Empty(); if (string.IsNullOrWhiteSpace(text) && array.Length != 0) { text = array[0]; } switch (text) { case "zs_archive_scan": ExecuteScan(array, messages); break; case "zs_archive_status": ExecuteStatus(messages); break; case "zs_archive_player": ExecutePlayer(array, messages); break; case "zs_archive_list": ExecuteList(messages); break; case "zs_archive_mark_seen": ExecuteMarkSeen(array, messages); break; case "zs_archive_ignore_player": ExecuteIgnorePlayer(array, messages); break; case "zs_archive_restore": ExecuteRestore(array, messages); break; case "zs_archive_schedule": ExecuteSchedule(array, messages); break; case "zs_archive_debug_zone": ExecuteDebugZone(array, messages); break; default: throw new InvalidOperationException("Unsupported auto archive command '" + text + "'."); } return AutoArchiveCommandResult.Ok(messages); } catch (Exception ex) { _logger.LogError((object)$"Auto archive command '{request.Command}' failed: {ex}"); return AutoArchiveCommandResult.Fail(ex.Message); } } private static void ExecuteScan(string[] args, List messages) { ParseMode(args.Skip(1), out var dryRun, out var reset); if (!AutoArchiveService.QueueManualScan(dryRun, reset)) { messages.Add("Auto archive scan could not be started. World may not be ready or another scan is running."); } else { messages.Add("Auto archive scan started."); } } private static void ExecuteStatus(List messages) { AutoArchiveState state = AutoArchiveStore.State; int num = state.Players.Sum((PlayerActivityRecord player) => player.PlayerIds.Count); string arg = (AutoArchiveConfig.Enabled ? $"enabled, interval: {AutoArchiveConfig.ScanIntervalMinutes} minute(s), next auto scan: {FormatDate(GetNextAutoScanUtc(state.LastAutoScanUtc))}" : "disabled (Scan Interval Minutes = 0)"); messages.Add($"Auto archive automatic scan: {arg}, dry run: {AutoArchiveConfig.DryRun}, reset after save: {AutoArchiveConfig.ResetAfterSave}."); messages.Add($"Players: {state.Players.Count} platform record(s), {num} playerID(s), ignored: {state.IgnoredPlayerIds.Count}."); messages.Add($"Runs: {state.Runs.Count}, last scan: {FormatDate(state.LastScanUtc)}, last auto scan: {FormatDate(state.LastAutoScanUtc)}."); messages.Add("Activity file: " + AutoArchiveStore.FilePath); } private static void ExecutePlayer(string[] args, List messages) { if (args.Length < 2) { throw new InvalidOperationException("Syntax: zs_archive_player steamID [dry|save|reset]"); } string targetLabel; List targetPlayerIds = ResolveTargetPlayerIds(args[1], out targetLabel); ParseMode(args.Skip(2), out var dryRun, out var reset); if (!AutoArchiveService.QueueManualScan(dryRun, reset, targetPlayerIds)) { messages.Add("Auto archive player scan could not be started. World may not be ready or another scan is running."); } else { messages.Add("Auto archive scan started for " + targetLabel + "."); } } private static void ExecuteList(List messages) { List list = AutoArchiveStore.State.Runs.OrderByDescending((ArchiveRunRecord run) => run.CreatedUtc).Take(10).ToList(); if (list.Count == 0) { messages.Add("No auto archive runs recorded."); return; } foreach (ArchiveRunRecord item in list) { messages.Add($"{item.RunId}: dry={item.DryRun}, reset={item.ResetAfterSave}, candidates={item.CandidateZones}, processed={item.ProcessedZones}, clusters={item.Clusters.Count}"); foreach (ArchiveClusterRecord item2 in item.Clusters.Take(5)) { string text = (string.IsNullOrWhiteSpace(item2.Tag) ? "-" : item2.Tag); messages.Add($" {item2.Status} {text}: zones={item2.Zones.Count}, pieces={item2.PieceCount}, reason={item2.Reason}"); } } } private static void ExecuteMarkSeen(string[] args, List messages) { if (args.Length < 2 || !long.TryParse(args[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { throw new InvalidOperationException("Syntax: zs_archive_mark_seen playerID"); } AutoArchiveStore.RecordManualPlayerSeen(result, DateTime.UtcNow); AutoArchiveStore.Flush(force: true); messages.Add($"Marked playerID {result} as seen now."); } private static void ExecuteIgnorePlayer(string[] args, List messages) { if (args.Length < 2 || !long.TryParse(args[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { throw new InvalidOperationException("Syntax: zs_archive_ignore_player playerID [on|off]"); } bool flag = args.Length < 3 || !string.Equals(args[2], "off", StringComparison.OrdinalIgnoreCase); AutoArchiveStore.SetIgnored(result, flag); AutoArchiveStore.Flush(force: true); messages.Add(flag ? $"playerID {result} is now protected from auto archive." : $"playerID {result} is no longer ignored."); } private static void ExecuteRestore(string[] args, List messages) { if (args.Length < 2) { throw new InvalidOperationException("Syntax: zs_archive_restore tag"); } ZoneBundleCommandResult zoneBundleCommandResult = ZoneBundleCommands.RestoreTagToOriginalZones(args[1]); messages.Add(zoneBundleCommandResult.Message); } private static void ExecuteSchedule(string[] args, List messages) { if (args.Length < 2 || string.Equals(args[1], "status", StringComparison.OrdinalIgnoreCase)) { messages.Add(BuildScheduleMessage()); return; } string a = args[1]; if (string.Equals(a, "now", StringComparison.OrdinalIgnoreCase)) { AutoArchiveStore.SetLastAutoScanUtc(DateTime.UtcNow); AutoArchiveStore.Flush(force: true); messages.Add(BuildScheduleMessage()); return; } if (string.Equals(a, "clear", StringComparison.OrdinalIgnoreCase)) { AutoArchiveStore.SetLastAutoScanUtc(DateTime.MinValue); AutoArchiveStore.Flush(force: true); messages.Add(BuildScheduleMessage()); return; } if (args.Length < 3) { throw new InvalidOperationException("Syntax: zs_archive_schedule [status|now|clear|last yyyy-MM-dd HH:mm|next yyyy-MM-dd HH:mm]"); } DateTime dateTime = ParseScheduleDate(args.Skip(2)); if (string.Equals(a, "last", StringComparison.OrdinalIgnoreCase)) { AutoArchiveStore.SetLastAutoScanUtc(dateTime); AutoArchiveStore.Flush(force: true); messages.Add(BuildScheduleMessage()); return; } if (string.Equals(a, "next", StringComparison.OrdinalIgnoreCase)) { if (!AutoArchiveConfig.Enabled) { throw new InvalidOperationException("Automatic auto archive scans are disabled because Scan Interval Minutes is 0."); } AutoArchiveStore.SetLastAutoScanUtc(dateTime - TimeSpan.FromMinutes(AutoArchiveConfig.ScanIntervalMinutes)); AutoArchiveStore.Flush(force: true); messages.Add(BuildScheduleMessage()); return; } throw new InvalidOperationException("Syntax: zs_archive_schedule [status|now|clear|last yyyy-MM-dd HH:mm|next yyyy-MM-dd HH:mm]"); } private static void ExecuteDebugZone(string[] args, List messages) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) Vector2i val = ParseZoneSpec(args.Skip(1)); AutoArchiveZoneDebugReport autoArchiveZoneDebugReport = BuildZoneDebugReport(val); string text = WriteZoneDebugReport(autoArchiveZoneDebugReport); messages.Add($"Archive debug zone ({val.x},{val.y}): zdo={autoArchiveZoneDebugReport.Summary.TotalZdos}, candidatePieces={autoArchiveZoneDebugReport.Summary.AutoArchiveCandidatePieces}, creators={autoArchiveZoneDebugReport.Summary.CandidateCreators}, wouldCandidate={autoArchiveZoneDebugReport.Summary.WouldBeCandidateZone}."); messages.Add("Reason: " + autoArchiveZoneDebugReport.Summary.Reason); messages.Add("Wrote YAML: " + text); } private static string BuildScheduleMessage() { DateTime lastAutoScanUtc = AutoArchiveStore.State.LastAutoScanUtc; if (!AutoArchiveConfig.Enabled) { return "Auto archive schedule: disabled (Scan Interval Minutes = 0), last auto scan=" + FormatDate(lastAutoScanUtc) + "."; } return $"Auto archive schedule: interval={AutoArchiveConfig.ScanIntervalMinutes} minute(s), last auto scan={FormatDate(lastAutoScanUtc)}, next auto scan={FormatDate(GetNextAutoScanUtc(lastAutoScanUtc))}."; } private static AutoArchiveZoneDebugReport BuildZoneDebugReport(Vector2i zone) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) if (ZDOMan.instance == null || (Object)(object)ZNetScene.instance == (Object)null || (Object)(object)ZoneSystem.instance == (Object)null) { throw new InvalidOperationException("World ZDO systems are not ready."); } List list = new List(); ZDOMan.instance.FindObjects(zone, list); DateTime utcNow = DateTime.UtcNow; AutoArchiveZoneDebugReport autoArchiveZoneDebugReport = new AutoArchiveZoneDebugReport(); ZNet instance = ZNet.instance; autoArchiveZoneDebugReport.World = ((instance != null) ? instance.GetWorldName() : null) ?? "unknown"; autoArchiveZoneDebugReport.CreatedAt = ZoneSaviorTimestamp.Format(utcNow); autoArchiveZoneDebugReport.Zone = new ZoneBundleZone { X = zone.x, Z = zone.y }; autoArchiveZoneDebugReport.Settings = new AutoArchiveZoneDebugSettings { DryRun = AutoArchiveConfig.DryRun, ResetAfterSave = AutoArchiveConfig.ResetAfterSave, InactiveDays = AutoArchiveConfig.InactiveDays, UnknownOwnerGraceDays = AutoArchiveConfig.UnknownOwnerGraceDays, MinimumPiecesPerCluster = AutoArchiveConfig.MinimumPiecesPerCluster, SmallClusterAction = AutoArchiveConfig.SmallClusterAction.ToString(), MaxZonesPerRun = AutoArchiveConfig.MaxZonesPerRun }; AutoArchiveZoneDebugReport autoArchiveZoneDebugReport2 = autoArchiveZoneDebugReport; HashSet hashSet = new HashSet(); foreach (ZDO item in list) { if (item != null && item.IsValid() && hashSet.Add(item.m_uid)) { AutoArchiveZoneDebugObject autoArchiveZoneDebugObject = BuildZoneDebugObject(zone, item); autoArchiveZoneDebugReport2.Objects.Add(autoArchiveZoneDebugObject); AddExclusionCounts(autoArchiveZoneDebugReport2.ExclusionCounts, autoArchiveZoneDebugObject.ExclusionReasons); } } List list2 = (from playerId in (from entry in autoArchiveZoneDebugReport2.Objects where entry.AutoArchiveCandidatePiece select entry.CreatorPlayerId into playerId where playerId != 0 select playerId).Distinct() orderby playerId select playerId).ToList(); autoArchiveZoneDebugReport2.Creators = list2.Select((long playerId) => BuildCreatorDebug(playerId, utcNow)).ToList(); bool flag = autoArchiveZoneDebugReport2.Creators.Count > 0 && autoArchiveZoneDebugReport2.Creators.All((AutoArchiveZoneDebugCreator creator) => creator.Eligible); autoArchiveZoneDebugReport2.Summary = new AutoArchiveZoneDebugSummary { TotalZdos = autoArchiveZoneDebugReport2.Objects.Count, InRequestedZone = autoArchiveZoneDebugReport2.Objects.Count((AutoArchiveZoneDebugObject entry) => entry.InRequestedZone), WearNTear = autoArchiveZoneDebugReport2.Objects.Count((AutoArchiveZoneDebugObject entry) => entry.HasWearNTear), PlayerBuildRecipe = autoArchiveZoneDebugReport2.Objects.Count((AutoArchiveZoneDebugObject entry) => entry.HasBuildRecipe), AutoArchiveCandidatePieces = autoArchiveZoneDebugReport2.Objects.Count((AutoArchiveZoneDebugObject entry) => entry.AutoArchiveCandidatePiece), CandidateCreators = list2.Count, ObjectDbReady = ((Object)(object)ObjectDB.instance != (Object)null), WouldBeCandidateZone = (autoArchiveZoneDebugReport2.Objects.Any((AutoArchiveZoneDebugObject entry) => entry.AutoArchiveCandidatePiece) && flag) }; autoArchiveZoneDebugReport2.Summary.Reason = BuildDebugSummaryReason(autoArchiveZoneDebugReport2, flag); return autoArchiveZoneDebugReport2; } private static AutoArchiveZoneDebugObject BuildZoneDebugObject(Vector2i requestedZone, ZDO zdo) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) Vector3 position = zdo.GetPosition(); Vector2i zone = ZoneSystem.GetZone(position); GameObject prefab = ZNetScene.instance.GetPrefab(zdo.GetPrefab()); bool flag = (Object)(object)prefab != (Object)null && Object.op_Implicit((Object)(object)prefab); bool flag2 = flag && (Object)(object)prefab.GetComponent() != (Object)null; bool flag3 = flag && (Object)(object)prefab.GetComponent() != (Object)null; bool hasPiece = flag && (Object)(object)prefab.GetComponent() != (Object)null; bool flag4 = flag && ZoneBlueprintCommands.HasBuildRecipe(prefab); bool flag5 = zone.x == requestedZone.x && zone.y == requestedZone.y; long @long = zdo.GetLong(ZDOVars.s_creator, 0L); List list = new List(); if (!flag5) { list.Add("outside_requested_zone"); } if (!flag) { list.Add("prefab_missing"); } if (flag && !flag2) { list.Add("no_znetview"); } if (!flag3) { list.Add("not_wearntear"); } if (@long == 0L) { list.Add("creatorless_or_missing_creator"); } if (flag3 && !flag4) { list.Add("no_player_build_recipe_or_resource_cost"); } bool flag6 = flag5 && @long != 0 && flag3 && flag4; if (flag6) { list.Clear(); } AutoArchiveZoneDebugObject autoArchiveZoneDebugObject = new AutoArchiveZoneDebugObject(); autoArchiveZoneDebugObject.ZdoId = ((object)(ZDOID)(ref zdo.m_uid)).ToString(); autoArchiveZoneDebugObject.PrefabHash = zdo.GetPrefab(); autoArchiveZoneDebugObject.Prefab = (flag ? Utils.GetPrefabName(prefab) : ""); autoArchiveZoneDebugObject.Position = new float[3] { Round(position.x), Round(position.y), Round(position.z) }; autoArchiveZoneDebugObject.ObjectZone = new ZoneBundleZone { X = zone.x, Z = zone.y }; autoArchiveZoneDebugObject.CreatorPlayerId = @long; autoArchiveZoneDebugObject.CreatorName = zdo.GetString(ZDOVars.s_creatorName, ""); autoArchiveZoneDebugObject.HasPrefab = flag; autoArchiveZoneDebugObject.HasZNetView = flag2; autoArchiveZoneDebugObject.HasWearNTear = flag3; autoArchiveZoneDebugObject.HasPiece = hasPiece; autoArchiveZoneDebugObject.HasBuildRecipe = flag4; autoArchiveZoneDebugObject.InRequestedZone = flag5; autoArchiveZoneDebugObject.AutoArchiveCandidatePiece = flag6; autoArchiveZoneDebugObject.ExclusionReasons = list; return autoArchiveZoneDebugObject; } private static AutoArchiveZoneDebugCreator BuildCreatorDebug(long playerId, DateTime utcNow) { AutoArchiveCreatorEligibility autoArchiveCreatorEligibility = AutoArchiveStore.EvaluateCreatorArchiveEligibility(playerId, utcNow, AutoArchiveConfig.InactiveDays, AutoArchiveConfig.UnknownOwnerGraceDays, recordUnknownPlayer: false); return new AutoArchiveZoneDebugCreator { PlayerId = autoArchiveCreatorEligibility.PlayerId, PlatformId = autoArchiveCreatorEligibility.PlatformId, Names = autoArchiveCreatorEligibility.Names, RecordedInActivity = autoArchiveCreatorEligibility.RecordedInActivity, UnknownActivityRecord = autoArchiveCreatorEligibility.UnknownActivityRecord, Ignored = autoArchiveCreatorEligibility.Ignored, Protected = autoArchiveCreatorEligibility.Protected, Eligible = autoArchiveCreatorEligibility.Eligible, Reason = autoArchiveCreatorEligibility.Reason }; } private static string BuildDebugSummaryReason(AutoArchiveZoneDebugReport report, bool allCreatorsEligible) { if (report.Summary.AutoArchiveCandidatePieces == 0) { return "No WearNTear with a non-zero creator and a registered player build recipe was found in this zone."; } if (!allCreatorsEligible) { string text = string.Join("; ", from creator in report.Creators where !creator.Eligible select creator.Reason); return "At least one candidate creator is not archive-eligible: " + text; } if (report.Summary.AutoArchiveCandidatePieces < AutoArchiveConfig.MinimumPiecesPerCluster) { return $"Zone has candidate pieces, but this single-zone piece count is below Minimum Pieces Per Cluster ({report.Summary.AutoArchiveCandidatePieces}/{AutoArchiveConfig.MinimumPiecesPerCluster}). Cluster adjacency may still change the final action."; } return "This zone would be an auto archive candidate before cluster adjacency and max-zones-per-run checks."; } private static string WriteZoneDebugReport(AutoArchiveZoneDebugReport report) { string text = Path.Combine(ZoneSaviorPlugin.DataStorageFullPath, "Diagnostics"); Directory.CreateDirectory(text); string path = string.Format("archive_debug_zone_{0}_{1}_{2}.yml", report.Zone.X, report.Zone.Z, DateTime.UtcNow.ToString("yyyyMMdd_HHmmss", CultureInfo.InvariantCulture)); string text2 = Path.Combine(text, path); File.WriteAllText(text2, ZoneBundleSerialization.Serialize(report)); return text2; } private static Vector2i ParseZoneSpec(IEnumerable values) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) string input = string.Join(" ", values).Trim(); Match match = ZoneSpecPattern.Match(input); if (!match.Success || !int.TryParse(match.Groups[1].Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) || !int.TryParse(match.Groups[2].Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2)) { throw new InvalidOperationException("Syntax: zs_archive_debug_zone (x,z)"); } return new Vector2i(result, result2); } private static void AddExclusionCounts(Dictionary counts, IEnumerable reasons) { foreach (string reason in reasons) { counts.TryGetValue(reason, out var value); counts[reason] = value + 1; } } private static float Round(float value) { return Mathf.Round(value * 1000f) / 1000f; } private static void ParseMode(IEnumerable args, out bool? dryRun, out bool? reset) { dryRun = null; reset = null; foreach (string arg in args) { if (string.Equals(arg, "dry", StringComparison.OrdinalIgnoreCase) || string.Equals(arg, "dry-run", StringComparison.OrdinalIgnoreCase)) { dryRun = true; reset = false; continue; } if (string.Equals(arg, "save", StringComparison.OrdinalIgnoreCase)) { dryRun = false; reset = false; continue; } if (string.Equals(arg, "reset", StringComparison.OrdinalIgnoreCase)) { dryRun = false; reset = true; continue; } throw new InvalidOperationException("Unknown archive mode '" + arg + "'. Use dry, save, or reset."); } } private static List ResolveTargetPlayerIds(string target, out string targetLabel) { if (AutoArchiveStore.TryGetPlayerIdsBySteamId(target, out List playerIds, out string normalizedSteamId)) { targetLabel = "steamID " + normalizedSteamId + " (playerID " + string.Join(", ", playerIds) + ")"; return playerIds; } if (IsLikelySteamId(target)) { throw new InvalidOperationException("No known playerID is linked to SteamID " + target + ". The player must have joined while ZoneSavior activity tracking was active."); } throw new InvalidOperationException("Syntax: zs_archive_player steamID [dry|save|reset]"); } private static bool IsLikelySteamId(string target) { if (string.IsNullOrWhiteSpace(target)) { return false; } string text = target.Trim(); if (text.StartsWith("steam:", StringComparison.OrdinalIgnoreCase)) { text = text.Substring("steam:".Length); } return new string(text.Where(char.IsDigit).ToArray()).Length >= 15; } private static void EnsureCommandReady() { if ((Object)(object)ZNet.instance == (Object)null) { throw new InvalidOperationException("World is not ready."); } if (!ZNet.instance.IsServer() && ZRoutedRpc.instance == null) { throw new InvalidOperationException("Server RPC is not ready."); } if (!ZNet.instance.IsServer() || (ZNet.instance.IsServer() && (Object)(object)Player.m_localPlayer == (Object)null) || ZNet.instance.LocalPlayerIsAdminOrHost()) { return; } throw new InvalidOperationException("Admin only."); } private static bool IsAuthorizedSender(long sender) { ZNetPeer peer = ZNet.instance.GetPeer(sender); object obj; if (peer == null) { obj = null; } else { ZRpc rpc = peer.m_rpc; if (rpc == null) { obj = null; } else { ISocket socket = rpc.m_socket; obj = ((socket != null) ? socket.GetHostName() : null); } } if (obj == null) { obj = ""; } string text = (string)obj; if (text.Length > 0) { return ZNet.instance.IsAdmin(text); } return false; } private static void ShowResult(AutoArchiveCommandResult result, Terminal? terminal) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) MessageType val = (MessageType)(result.Success ? 1 : 2); foreach (string item in (result.Messages.Count > 0) ? result.Messages : new List(1) { result.Success ? "Done." : "Command failed." }) { _logger.LogInfo((object)item); if (terminal != null) { terminal.AddString(item); } if ((Object)(object)Player.m_localPlayer != (Object)null) { ((Character)Player.m_localPlayer).Message(val, item, 0, (Sprite)null); } } } private static string FormatDate(DateTime value) { if (!(value == DateTime.MinValue)) { return ZoneSaviorTimestamp.Format(value); } return "-"; } private static DateTime GetNextAutoScanUtc(DateTime lastAutoScanUtc) { if (AutoArchiveConfig.Enabled && !(lastAutoScanUtc == DateTime.MinValue)) { return DateTime.SpecifyKind(lastAutoScanUtc, DateTimeKind.Utc) + TimeSpan.FromMinutes(AutoArchiveConfig.ScanIntervalMinutes); } return DateTime.MinValue; } private static DateTime ParseScheduleDate(IEnumerable values) { string text = string.Join(" ", values).Trim(); if (string.IsNullOrWhiteSpace(text)) { throw new InvalidOperationException("Missing schedule date."); } DateTimeStyles styles = ((text.EndsWith("Z", StringComparison.OrdinalIgnoreCase) || HasTimezoneOffset(text)) ? (DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal) : (DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeLocal)); if (!DateTime.TryParse(text, CultureInfo.InvariantCulture, styles, out var result) && !DateTime.TryParse(text, CultureInfo.CurrentCulture, styles, out result)) { throw new InvalidOperationException("Invalid schedule date '" + text + "'. Use local server time like 2026-05-02 15:00, or UTC like 2026-05-02T06:00:00Z."); } return DateTime.SpecifyKind(result, DateTimeKind.Utc); } private static bool HasTimezoneOffset(string value) { string text = value.Trim(); if (text.Length < 6) { return false; } int num = text.Length - 6; char c = text[num]; if ((c == '+' || c == '-') && char.IsDigit(text[num + 1]) && char.IsDigit(text[num + 2]) && text[num + 3] == ':' && char.IsDigit(text[num + 4])) { return char.IsDigit(text[num + 5]); } return false; } } internal sealed class AutoArchiveCommandRequest { public string Command { get; set; } = ""; public List Args { get; set; } = new List(); } internal sealed class AutoArchiveCommandResult { public bool Success { get; set; } public List Messages { get; set; } = new List(); public static AutoArchiveCommandResult Ok(IEnumerable messages) { return new AutoArchiveCommandResult { Success = true, Messages = messages.ToList() }; } public static AutoArchiveCommandResult Fail(string message) { return new AutoArchiveCommandResult { Success = false, Messages = new List(1) { message } }; } } internal enum AutoArchiveSmallClusterAction { Skip, SaveAnyway, ResetWithoutSave } internal sealed class AutoArchiveState { public int Version { get; set; } = 1; [YamlIgnore] public DateTime LastScanUtc { get; set; } = DateTime.MinValue; public string LastScanAt { get { return ZoneSaviorTimestamp.Format(LastScanUtc); } set { LastScanUtc = ZoneSaviorTimestamp.ParseUtc(value); } } [YamlIgnore] public DateTime LastAutoScanUtc { get; set; } = DateTime.MinValue; public string LastAutoScanAt { get { return ZoneSaviorTimestamp.Format(LastAutoScanUtc); } set { LastAutoScanUtc = ZoneSaviorTimestamp.ParseUtc(value); } } public List Players { get; set; } = new List(); public List Runs { get; set; } = new List(); public List IgnoredPlayerIds { get; set; } = new List(); } internal sealed class PlayerActivityRecord { public string PlatformId { get; set; } = ""; public List PlayerIds { get; set; } = new List(); public List Names { get; set; } = new List(); [YamlIgnore] public DateTime FirstSeenUtc { get; set; } = DateTime.MinValue; public string FirstSeenAt { get { return ZoneSaviorTimestamp.Format(FirstSeenUtc); } set { FirstSeenUtc = ZoneSaviorTimestamp.ParseUtc(value); } } [YamlIgnore] public DateTime LastSeenUtc { get; set; } = DateTime.MinValue; public string LastSeenAt { get { return ZoneSaviorTimestamp.Format(LastSeenUtc); } set { LastSeenUtc = ZoneSaviorTimestamp.ParseUtc(value); } } } internal sealed class ArchiveRunRecord { public string RunId { get; set; } = ""; [YamlIgnore] public DateTime CreatedUtc { get; set; } = DateTime.MinValue; public string CreatedAt { get { return ZoneSaviorTimestamp.Format(CreatedUtc); } set { CreatedUtc = ZoneSaviorTimestamp.ParseUtc(value); } } public bool Manual { get; set; } public bool DryRun { get; set; } public bool ResetAfterSave { get; set; } public List TargetPlayerIds { get; set; } = new List(); public int ScannedZdos { get; set; } public int StructureZdos { get; set; } public int CandidateZones { get; set; } public int ProcessedZones { get; set; } public List Clusters { get; set; } = new List(); public List Messages { get; set; } = new List(); } internal sealed class ArchiveClusterRecord { public string Tag { get; set; } = ""; public string Status { get; set; } = ""; public string Reason { get; set; } = ""; public int PieceCount { get; set; } public int TerrainLoaded { get; set; } public int TerrainCaptured { get; set; } public List Creators { get; set; } = new List(); public List Zones { get; set; } = new List(); } internal sealed class AutoArchiveScanOptions { public bool Manual { get; set; } public bool DryRun { get; set; } public bool ResetAfterSave { get; set; } public List TargetPlayerIds { get; set; } = new List(); } internal sealed class AutoArchiveCreatorEligibility { public long PlayerId { get; set; } public string PlatformId { get; set; } = ""; public List Names { get; set; } = new List(); public bool RecordedInActivity { get; set; } public bool UnknownActivityRecord { get; set; } public bool Ignored { get; set; } public bool Protected { get; set; } public bool Eligible { get; set; } public string Reason { get; set; } = ""; } internal sealed class ZoneBundleArchiveResult { public bool Success { get; set; } public string Message { get; set; } = ""; public string Tag { get; set; } = ""; public string ManifestPath { get; set; } = ""; public int ZoneCount { get; set; } public int EntryCount { get; set; } public int MonsterCount { get; set; } public int TerrainLoaded { get; set; } public int TerrainCaptured { get; set; } } internal sealed class ZoneBundleResetResult { public bool Success { get; set; } public string Message { get; set; } = ""; public int ZoneCount { get; set; } public int RemovedCount { get; set; } public int RemainingWearNTearCount { get; set; } } internal sealed class AutoArchiveZoneDebugReport { public int Version { get; set; } = 1; public string World { get; set; } = ""; public string CreatedAt { get; set; } = ""; public ZoneBundleZone Zone { get; set; } = new ZoneBundleZone(); public AutoArchiveZoneDebugSettings Settings { get; set; } = new AutoArchiveZoneDebugSettings(); public AutoArchiveZoneDebugSummary Summary { get; set; } = new AutoArchiveZoneDebugSummary(); public List Creators { get; set; } = new List(); public Dictionary ExclusionCounts { get; set; } = new Dictionary(); public List Objects { get; set; } = new List(); } internal sealed class AutoArchiveZoneDebugSettings { public bool DryRun { get; set; } public bool ResetAfterSave { get; set; } public int InactiveDays { get; set; } public int UnknownOwnerGraceDays { get; set; } public int MinimumPiecesPerCluster { get; set; } public string SmallClusterAction { get; set; } = ""; public int MaxZonesPerRun { get; set; } } internal sealed class AutoArchiveZoneDebugSummary { public int TotalZdos { get; set; } public int InRequestedZone { get; set; } public int WearNTear { get; set; } public int PlayerBuildRecipe { get; set; } public int AutoArchiveCandidatePieces { get; set; } public int CandidateCreators { get; set; } public bool ObjectDbReady { get; set; } public bool WouldBeCandidateZone { get; set; } public string Reason { get; set; } = ""; } internal sealed class AutoArchiveZoneDebugCreator { public long PlayerId { get; set; } public string PlatformId { get; set; } = ""; public List Names { get; set; } = new List(); public bool RecordedInActivity { get; set; } public bool UnknownActivityRecord { get; set; } public bool Ignored { get; set; } public bool Protected { get; set; } public bool Eligible { get; set; } public string Reason { get; set; } = ""; } internal sealed class AutoArchiveZoneDebugObject { public string ZdoId { get; set; } = ""; public int PrefabHash { get; set; } public string Prefab { get; set; } = ""; public float[] Position { get; set; } = new float[3]; public ZoneBundleZone ObjectZone { get; set; } = new ZoneBundleZone(); public long CreatorPlayerId { get; set; } public string CreatorName { get; set; } = ""; public bool HasPrefab { get; set; } public bool HasZNetView { get; set; } public bool HasWearNTear { get; set; } public bool HasPiece { get; set; } public bool HasBuildRecipe { get; set; } public bool InRequestedZone { get; set; } public bool AutoArchiveCandidatePiece { get; set; } public List ExclusionReasons { get; set; } = new List(); } internal static class AutoArchiveScanner { private sealed class AutoArchiveZoneInfo { public Vector2i Zone { get; } public int PieceCount { get; set; } public HashSet Creators { get; } = new HashSet(); public Dictionary CreatorPieceCounts { get; } = new Dictionary(); public AutoArchiveZoneInfo(Vector2i zone) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) Zone = zone; } public void AddCreator(long creator) { PieceCount++; Creators.Add(creator); CreatorPieceCounts.TryGetValue(creator, out var value); CreatorPieceCounts[creator] = value + 1; } } [CompilerGenerated] private sealed class <>c__DisplayClass3_0 { public ZoneBundleArchiveResult saveResult; internal void b__4(ZoneBundleArchiveResult result) { saveResult = result; } } [CompilerGenerated] private sealed class <>c__DisplayClass3_1 { public ZoneBundleResetResult resetResult; internal void b__5(ZoneBundleResetResult result) { resetResult = result; } } [CompilerGenerated] private sealed class d__3 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public AutoArchiveScanOptions options; public Action onComplete; private <>c__DisplayClass3_0 <>8__1; private <>c__DisplayClass3_1 <>8__2; private DateTime 5__2; private ArchiveRunRecord 5__3; private Dictionary 5__4; private Dictionary 5__5; private int 5__6; private int 5__7; private IEnumerator> <>7__wrap7; private List 5__9; private ArchiveClusterRecord 5__10; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__3(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 2) <= 5u) { try { } finally { <>m__Finally1(); } } <>8__1 = null; <>8__2 = null; 5__3 = null; 5__4 = null; 5__5 = null; <>7__wrap7 = null; 5__9 = null; 5__10 = null; <>1__state = -2; } private bool MoveNext() { try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__2 = DateTime.UtcNow; 5__3 = new ArchiveRunRecord { RunId = 5__2.ToString("yyyyMMdd_HHmmss", CultureInfo.InvariantCulture), CreatedUtc = 5__2, Manual = options.Manual, DryRun = options.DryRun, ResetAfterSave = options.ResetAfterSave, TargetPlayerIds = options.TargetPlayerIds.ToList() }; if (!IsWorldReady()) { 5__3.Messages.Add("World is not ready."); onComplete(5__3); return false; } PlayerActivityTracker.TrackOnlinePlayers(5__2); 5__4 = new Dictionary(); <>2__current = ScanZdosBySector(5__2, 5__4, 5__3); <>1__state = 1; return true; case 1: { <>1__state = -1; 5__5 = BuildCandidateZones(5__4, 5__2, options.TargetPlayerIds, 5__3); 5__3.CandidateZones = 5__5.Count; List> source = BuildClusters(5__5); 5__6 = 0; 5__7 = 0; <>7__wrap7 = (from cluster in source orderby cluster.Min((Vector2i zone) => zone.x), cluster.Min((Vector2i zone) => zone.y) select cluster).GetEnumerator(); <>1__state = -3; break; } case 2: <>1__state = -3; break; case 3: <>1__state = -3; if (<>8__1.saveResult == null) { 5__10.Status = "failed"; 5__10.Reason = "save failed: archive coroutine did not return a result"; 5__3.Clusters.Add(5__10); _logger.LogError((object)("Auto archive save failed for tag '" + 5__10.Tag + "': archive coroutine did not return a result.")); <>2__current = null; <>1__state = 4; return true; } 5__10.TerrainLoaded = <>8__1.saveResult.TerrainLoaded; 5__10.TerrainCaptured = <>8__1.saveResult.TerrainCaptured; if (!<>8__1.saveResult.Success) { 5__10.Status = "failed"; 5__10.Reason = <>8__1.saveResult.Message; 5__3.Clusters.Add(5__10); break; } 5__10.Status = "saved"; 5__10.Reason = <>8__1.saveResult.Message; if (options.ResetAfterSave) { if (!AutoArchiveConfig.RequireLoadedTerrainForReset || <>8__1.saveResult.TerrainCaptured >= 5__9.Count) { <>8__2 = new <>c__DisplayClass3_1(); <>8__2.resetResult = null; <>2__current = ZoneBundleCommands.ResetGeneratedZonesAsync(5__9, delegate(ZoneBundleResetResult result) { <>8__2.resetResult = result; }); <>1__state = 5; return true; } 5__10.Status = "saved-reset-skipped"; 5__10.Reason = $"saved, but reset skipped because usable terrain contacts were captured for {<>8__1.saveResult.TerrainCaptured}/{5__9.Count} zones"; } goto IL_08c2; case 4: <>1__state = -3; break; case 5: <>1__state = -3; if (<>8__2.resetResult == null) { 5__10.Status = "saved-reset-failed"; 5__10.Reason = "reset failed: reset coroutine did not return a result"; 5__3.Clusters.Add(5__10); _logger.LogError((object)("Auto archive reset failed for tag '" + 5__10.Tag + "': reset coroutine did not return a result.")); <>2__current = null; <>1__state = 6; return true; } 5__10.Status = (<>8__2.resetResult.Success ? "reset" : "saved-reset-failed"); 5__10.Reason = <>8__2.resetResult.Message; <>8__2 = null; goto IL_08c2; case 6: <>1__state = -3; break; case 7: { <>1__state = -3; <>8__1 = null; 5__10 = null; 5__9 = null; break; } IL_08c2: 5__3.Clusters.Add(5__10); 5__6 += 5__9.Count; <>2__current = null; <>1__state = 7; return true; } while (<>7__wrap7.MoveNext()) { 5__9 = <>7__wrap7.Current; <>8__1 = new <>c__DisplayClass3_0(); 5__7++; 5__10 = BuildClusterRecord(5__9, 5__5); bool flag = 5__10.PieceCount < AutoArchiveConfig.MinimumPiecesPerCluster; if (flag && AutoArchiveConfig.SmallClusterAction == AutoArchiveSmallClusterAction.Skip) { 5__10.Status = "skipped"; 5__10.Reason = $"piece count {5__10.PieceCount} is below minimum {AutoArchiveConfig.MinimumPiecesPerCluster}"; 5__3.Clusters.Add(5__10); continue; } if (5__6 + 5__9.Count > AutoArchiveConfig.MaxZonesPerRun) { 5__10.Status = "skipped"; 5__10.Reason = $"max zones per run would be exceeded ({5__6 + 5__9.Count}/{AutoArchiveConfig.MaxZonesPerRun})"; 5__3.Clusters.Add(5__10); continue; } if (!AllCreatorsEligible(5__10.Creators, 5__2, out string reason)) { 5__10.Status = "skipped"; 5__10.Reason = reason; 5__3.Clusters.Add(5__10); continue; } if (flag && AutoArchiveConfig.SmallClusterAction == AutoArchiveSmallClusterAction.ResetWithoutSave) { if (!options.ResetAfterSave) { 5__10.Status = "skipped"; 5__10.Reason = $"piece count {5__10.PieceCount} is below minimum {AutoArchiveConfig.MinimumPiecesPerCluster}; reset mode is not enabled"; 5__3.Clusters.Add(5__10); continue; } if (options.DryRun) { 5__10.Status = "dry-run-reset-without-save"; 5__10.Reason = $"small inactive cluster would be reset without saving ({5__10.PieceCount}/{AutoArchiveConfig.MinimumPiecesPerCluster} pieces)"; 5__3.Clusters.Add(5__10); 5__6 += 5__9.Count; continue; } ZoneBundleResetResult zoneBundleResetResult = ZoneBundleCommands.ResetGeneratedZones(5__9); 5__10.Status = (zoneBundleResetResult.Success ? "reset-without-save" : "reset-without-save-failed"); 5__10.Reason = zoneBundleResetResult.Message; 5__3.Clusters.Add(5__10); 5__6 += 5__9.Count; <>2__current = null; <>1__state = 2; return true; } 5__10.Tag = ZoneBundleCommands.MakeUniqueAutoArchiveTag(BuildTag(5__7, 5__9, 5__5)); if (options.DryRun) { 5__10.Status = "dry-run"; 5__10.Reason = "candidate only; dry run is enabled"; 5__3.Clusters.Add(5__10); 5__6 += 5__9.Count; continue; } <>8__1.saveResult = null; <>2__current = ZoneBundleCommands.SaveZonesAsync(5__9, 5__10.Tag, delegate(ZoneBundleArchiveResult result) { <>8__1.saveResult = result; }); <>1__state = 3; return true; } <>m__Finally1(); <>7__wrap7 = null; 5__3.ProcessedZones = 5__6; onComplete(5__3); return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>7__wrap7 != null) { <>7__wrap7.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__5 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public DateTime utcNow; public Dictionary zoneInfos; public ArchiveRunRecord run; private int 5__2; private int 5__3; private List[] 5__4; private int 5__5; private List 5__6; private int 5__7; private List>.Enumerator <>7__wrap7; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__5(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 2) { try { } finally { <>m__Finally1(); } } 5__4 = null; 5__6 = null; <>7__wrap7 = default(List>.Enumerator); <>1__state = -2; } private bool MoveNext() { try { List> list; switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__2 = Math.Max(1, AutoArchiveConfig.ScannerBatchSize); 5__3 = 0; 5__4 = ZDOMan.instance.m_objectsBySector; 5__5 = 0; goto IL_0138; case 1: <>1__state = -1; goto IL_00fb; case 2: { <>1__state = -3; goto IL_022d; } IL_0138: if (5__4 != null && 5__5 < 5__4.Length) { 5__6 = 5__4[5__5]; if (5__6 != null && 5__6.Count != 0) { 5__7 = 0; goto IL_010b; } goto IL_0128; } list = ZDOMan.instance.m_objectsByOutsideSector?.Values.ToList() ?? new List>(); <>7__wrap7 = list.GetEnumerator(); <>1__state = -3; goto IL_025a; IL_00fb: 5__7++; goto IL_010b; IL_0128: 5__5++; goto IL_0138; IL_025a: do { if (<>7__wrap7.MoveNext()) { 5__6 = <>7__wrap7.Current; continue; } <>m__Finally1(); <>7__wrap7 = default(List>.Enumerator); return false; } while (5__6 == null || 5__6.Count == 0); 5__5 = 0; goto IL_023d; IL_010b: if (5__7 < 5__6.Count) { ProcessScanZdo(5__6[5__7], utcNow, zoneInfos, run); 5__3++; if (5__3 >= 5__2) { 5__3 = 0; <>2__current = null; <>1__state = 1; return true; } goto IL_00fb; } 5__6 = null; goto IL_0128; IL_022d: 5__5++; goto IL_023d; IL_023d: if (5__5 < 5__6.Count) { ProcessScanZdo(5__6[5__5], utcNow, zoneInfos, run); 5__3++; if (5__3 >= 5__2) { 5__3 = 0; <>2__current = null; <>1__state = 2; return true; } goto IL_022d; } 5__6 = null; goto IL_025a; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>7__wrap7).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static readonly Vector2i[] NeighborOffsets = (Vector2i[])(object)new Vector2i[8] { new Vector2i(-1, -1), new Vector2i(0, -1), new Vector2i(1, -1), new Vector2i(-1, 0), new Vector2i(1, 0), new Vector2i(-1, 1), new Vector2i(0, 1), new Vector2i(1, 1) }; private static ManualLogSource _logger = null; public static void Initialize(ManualLogSource logger) { _logger = logger; } [IteratorStateMachine(typeof(d__3))] public static IEnumerator Run(AutoArchiveScanOptions options, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__3(0) { options = options, onComplete = onComplete }; } private static bool TryReadPlayerStructure(ZDO zdo, DateTime utcNow, out Vector2i zone, out long creator) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) zone = default(Vector2i); creator = 0L; if (zdo == null || !zdo.IsValid()) { return false; } creator = zdo.GetLong(ZDOVars.s_creator, 0L); if (creator == 0L) { return false; } GameObject prefab = ZNetScene.instance.GetPrefab(zdo.GetPrefab()); if ((Object)(object)prefab == (Object)null || !Object.op_Implicit((Object)(object)prefab) || (Object)(object)prefab.GetComponent() == (Object)null || !ZoneBlueprintCommands.HasBuildRecipe(prefab)) { return false; } string @string = zdo.GetString(ZDOVars.s_creatorName, ""); AutoArchiveStore.RecordUnknownPlayer(creator, utcNow, @string); zone = ZoneSystem.GetZone(zdo.GetPosition()); return true; } [IteratorStateMachine(typeof(d__5))] private static IEnumerator ScanZdosBySector(DateTime utcNow, Dictionary zoneInfos, ArchiveRunRecord run) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__5(0) { utcNow = utcNow, zoneInfos = zoneInfos, run = run }; } private static void ProcessScanZdo(ZDO zdo, DateTime utcNow, Dictionary zoneInfos, ArchiveRunRecord run) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) run.ScannedZdos++; if (TryReadPlayerStructure(zdo, utcNow, out var zone, out var creator)) { run.StructureZdos++; if (!zoneInfos.TryGetValue(zone, out AutoArchiveZoneInfo value)) { value = (zoneInfos[zone] = new AutoArchiveZoneInfo(zone)); } value.AddCreator(creator); } } private static Dictionary BuildCandidateZones(Dictionary zoneInfos, DateTime utcNow, IReadOnlyCollection targetPlayerIds, ArchiveRunRecord run) { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) Dictionary dictionary = new Dictionary(); foreach (AutoArchiveZoneInfo value in zoneInfos.Values) { if (targetPlayerIds.Count <= 0 || value.Creators.Any(((IEnumerable)targetPlayerIds).Contains)) { if (!AllCreatorsEligible(value.Creators, utcNow, out string reason)) { run.Messages.Add($"Skipped zone ({value.Zone.x},{value.Zone.y}): {reason}"); } else { dictionary[value.Zone] = value; } } } return dictionary; } private static List> BuildClusters(Dictionary candidates) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) List> list = new List>(); HashSet hashSet = candidates.Keys.ToHashSet(); Vector2i item2 = default(Vector2i); while (hashSet.Count > 0) { Vector2i item = hashSet.First(); hashSet.Remove(item); List list2 = new List(); Queue queue = new Queue(); queue.Enqueue(item); while (queue.Count > 0) { Vector2i val = queue.Dequeue(); list2.Add(val); Vector2i[] neighborOffsets = NeighborOffsets; foreach (Vector2i val2 in neighborOffsets) { ((Vector2i)(ref item2))..ctor(val.x + val2.x, val.y + val2.y); if (hashSet.Contains(item2)) { hashSet.Remove(item2); queue.Enqueue(item2); } } } list.Add(list2); } return list; } private static ArchiveClusterRecord BuildClusterRecord(List cluster, Dictionary candidates) { //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) ArchiveClusterRecord archiveClusterRecord = new ArchiveClusterRecord { Zones = (from zone in cluster orderby zone.y, zone.x select new ZoneBundleZone { X = zone.x, Z = zone.y }).ToList() }; HashSet hashSet = new HashSet(); foreach (Vector2i item in cluster) { AutoArchiveZoneInfo autoArchiveZoneInfo = candidates[item]; archiveClusterRecord.PieceCount += autoArchiveZoneInfo.PieceCount; foreach (long creator in autoArchiveZoneInfo.Creators) { hashSet.Add(creator); } } archiveClusterRecord.Creators = hashSet.OrderBy((long id) => id).ToList(); return archiveClusterRecord; } private static bool AllCreatorsEligible(IEnumerable creators, DateTime utcNow, out string reason) { foreach (long creator in creators) { if (!AutoArchiveStore.IsCreatorArchiveEligible(creator, utcNow, AutoArchiveConfig.InactiveDays, AutoArchiveConfig.UnknownOwnerGraceDays, out reason)) { return false; } } reason = ""; return true; } private static string BuildTag(int index, List cluster, Dictionary candidates) { string arg = BuildOwnerSegment(BuildCreatorPieceCounts(cluster, candidates)); return $"auto_{arg}_c{index:D3}"; } private static Dictionary BuildCreatorPieceCounts(List cluster, Dictionary candidates) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) Dictionary dictionary = new Dictionary(); foreach (Vector2i item in cluster) { foreach (KeyValuePair creatorPieceCount in candidates[item].CreatorPieceCounts) { dictionary.TryGetValue(creatorPieceCount.Key, out var value); dictionary[creatorPieceCount.Key] = value + creatorPieceCount.Value; } } return dictionary; } private static string BuildOwnerSegment(IReadOnlyDictionary creatorPieceCounts) { IReadOnlyDictionary creatorPieceCounts2 = creatorPieceCounts; List list = (from creator in creatorPieceCounts2.Keys.Where((long creator) => creator != 0).Distinct() orderby creator select creator).ToList(); if (list.Count == 0) { return "unknown"; } int value; string text = BuildOwnerToken((from owner in list orderby creatorPieceCounts2.TryGetValue(owner, out value) ? value : 0 descending, owner select owner).First()); if (list.Count == 1) { return text; } return $"{text}_plus{list.Count - 1}_{BuildOwnerHash(list)}"; } private static string BuildOwnerToken(long playerId) { string text = ResolvePlayerName(playerId); string text2 = ResolveSteamId(playerId); if (!string.Equals(text2, "unknown", StringComparison.Ordinal)) { return text + "_s" + text2; } return text; } private static string ResolvePlayerName(long playerId) { if (!AutoArchiveStore.TryGetPlayerRecord(playerId, out PlayerActivityRecord record)) { return "unknown"; } return SanitizeTagToken(record.Names.LastOrDefault((string candidate) => !string.IsNullOrWhiteSpace(candidate) && !string.Equals(candidate, "unknown", StringComparison.OrdinalIgnoreCase) && !string.Equals(candidate, "manual", StringComparison.OrdinalIgnoreCase)) ?? "unknown"); } private static string ResolveSteamId(long playerId) { if (!AutoArchiveStore.TryGetPlayerRecord(playerId, out PlayerActivityRecord record) || string.IsNullOrWhiteSpace(record.PlatformId) || !record.PlatformId.StartsWith("steam:", StringComparison.OrdinalIgnoreCase)) { return "unknown"; } string source = record.PlatformId.Substring("steam:".Length); string text = new string(source.Where(char.IsDigit).ToArray()); if (text.Length >= 15) { return text; } string text2 = new string(source.Where((char character) => char.IsLetterOrDigit(character) || character == '-' || character == '_').ToArray()); if (!string.IsNullOrWhiteSpace(text2)) { return text2; } return "unknown"; } private static string BuildOwnerHash(IEnumerable ownerIds) { uint num = 2166136261u; foreach (long ownerId in ownerIds) { byte[] bytes = BitConverter.GetBytes(ownerId); foreach (byte b in bytes) { num ^= b; num *= 16777619; } } return num.ToString("x8", CultureInfo.InvariantCulture); } private static string SanitizeTagToken(string value) { if (string.IsNullOrWhiteSpace(value)) { return "unknown"; } char[] invalidChars = Path.GetInvalidFileNameChars(); string text = new string(value.Select(delegate(char character) { if (invalidChars.Contains(character)) { return '_'; } if (char.IsWhiteSpace(character)) { return '_'; } return (!char.IsLetterOrDigit(character) && character != '-' && character != '_') ? '_' : character; }).ToArray()); text = text.Trim(new char[1] { '_' }); while (text.Contains("__")) { text = text.Replace("__", "_"); } if (text.Length > 32) { text = text.Substring(0, 32).Trim(new char[1] { '_' }); } if (!string.IsNullOrWhiteSpace(text)) { return text; } return "unknown"; } private static bool IsWorldReady() { if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer() && ZDOMan.instance != null && (Object)(object)ZNetScene.instance != (Object)null) { return (Object)(object)ZoneSystem.instance != (Object)null; } return false; } private static string FormatDate(DateTime value) { if (!(value == DateTime.MinValue)) { return value.ToString("O", CultureInfo.InvariantCulture); } return "-"; } } internal static class AutoArchiveService { [CompilerGenerated] private sealed class <>c__DisplayClass13_0 { public ArchiveRunRecord completed; internal void b__0(ArchiveRunRecord run) { completed = run; } } [CompilerGenerated] private sealed class d__13 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public AutoArchiveScanOptions options; private <>c__DisplayClass13_0 <>8__1; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__13(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__1 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass13_0(); <>8__1.completed = null; <>2__current = AutoArchiveScanner.Run(options, delegate(ArchiveRunRecord run) { <>8__1.completed = run; }); <>1__state = 1; return true; case 1: <>1__state = -1; if (<>8__1.completed != null) { AutoArchiveStore.RecordRun(<>8__1.completed); AutoArchiveStore.Flush(force: true); _logger.LogInfo((object)$"Auto archive scan finished: {<>8__1.completed.CandidateZones} candidate zone(s), {<>8__1.completed.ProcessedZones} processed zone(s), {<>8__1.completed.Clusters.Count} cluster record(s)."); } _scanRunning = false; _scanCoroutine = null; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static readonly TimeSpan TrackInterval = TimeSpan.FromMinutes(10.0); private static readonly TimeSpan FlushInterval = TimeSpan.FromMinutes(5.0); private static ManualLogSource _logger = null; private static bool _initialized; private static bool _scanRunning; private static DateTime _lastTrackUtc = DateTime.MinValue; private static DateTime _lastFlushUtc = DateTime.MinValue; private static Coroutine? _scanCoroutine; public static void Initialize(ManualLogSource logger) { if (!_initialized) { _initialized = true; _logger = logger; PlayerActivityTracker.Initialize(logger); AutoArchiveScanner.Initialize(logger); } } public static void Update() { if (!IsServerReady()) { return; } DateTime utcNow = DateTime.UtcNow; if (utcNow - _lastTrackUtc >= TrackInterval) { _lastTrackUtc = utcNow; PlayerActivityTracker.TrackOnlinePlayers(utcNow); } if (utcNow - _lastFlushUtc >= FlushInterval) { _lastFlushUtc = utcNow; AutoArchiveStore.Flush(); } if (AutoArchiveConfig.Enabled && !_scanRunning) { TimeSpan timeSpan = TimeSpan.FromMinutes(AutoArchiveConfig.ScanIntervalMinutes); DateTime dateTime = DateTime.SpecifyKind(AutoArchiveStore.State.LastAutoScanUtc, DateTimeKind.Utc); if (!(dateTime != DateTime.MinValue) || !(utcNow - dateTime < timeSpan)) { QueueScan(new AutoArchiveScanOptions { Manual = false, DryRun = AutoArchiveConfig.DryRun, ResetAfterSave = AutoArchiveConfig.ResetAfterSave }); } } } public static bool QueueManualScan(bool? dryRunOverride = null, bool? resetAfterSaveOverride = null, IEnumerable? targetPlayerIds = null) { if (!IsServerReady() || _scanRunning) { return false; } QueueScan(new AutoArchiveScanOptions { Manual = true, DryRun = (dryRunOverride ?? AutoArchiveConfig.DryRun), ResetAfterSave = (resetAfterSaveOverride ?? AutoArchiveConfig.ResetAfterSave), TargetPlayerIds = ((targetPlayerIds == null) ? new List() : new List(targetPlayerIds)) }); return true; } public static void Shutdown() { if (_scanCoroutine != null && (Object)(object)ZoneSaviorPlugin.Instance != (Object)null) { ((MonoBehaviour)ZoneSaviorPlugin.Instance).StopCoroutine(_scanCoroutine); _scanCoroutine = null; } _scanRunning = false; } private static void QueueScan(AutoArchiveScanOptions options) { _scanRunning = true; _logger.LogInfo((object)$"Starting auto archive scan (manual: {options.Manual}, dry run: {options.DryRun}, reset: {options.ResetAfterSave}, targets: {options.TargetPlayerIds.Count})."); _scanCoroutine = ((MonoBehaviour)ZoneSaviorPlugin.Instance).StartCoroutine(RunScan(options)); } [IteratorStateMachine(typeof(d__13))] private static IEnumerator RunScan(AutoArchiveScanOptions options) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__13(0) { options = options }; } private static bool IsServerReady() { if ((Object)(object)ZoneSaviorPlugin.Instance != (Object)null && (Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer() && ZDOMan.instance != null && (Object)(object)ZNetScene.instance != (Object)null) { return (Object)(object)ZoneSystem.instance != (Object)null; } return false; } } internal static class AutoArchiveStore { private const string UnknownPlatformPrefix = "unknown:"; private const string ManualPlatformPrefix = "manual:"; private const int MaxRunHistory = 50; private static readonly ISerializer Serializer = new SerializerBuilder().WithNamingConvention(UnderscoredNamingConvention.Instance).Build(); private static readonly IDeserializer Deserializer = new DeserializerBuilder().IgnoreUnmatchedProperties().WithNamingConvention(UnderscoredNamingConvention.Instance).Build(); private static readonly object Sync = new object(); private static ManualLogSource _logger = null; private static bool _initialized; private static bool _dirty; private static DateTime _lastFlushUtc = DateTime.MinValue; private static readonly Dictionary PlayersByPlatform = new Dictionary(StringComparer.Ordinal); private static readonly Dictionary PlayersById = new Dictionary(); public static string FilePath => Path.Combine(ZoneSaviorPlugin.DataStorageFullPath, "activity.yml"); public static AutoArchiveState State { get; private set; } = new AutoArchiveState(); public static void Initialize(ManualLogSource logger) { if (!_initialized) { _initialized = true; _logger = logger; Load(); } } public static void Load() { lock (Sync) { if (!File.Exists(FilePath)) { State = new AutoArchiveState(); RebuildIndexes(); _dirty = true; Flush(force: true); return; } try { string input = File.ReadAllText(FilePath); State = Deserializer.Deserialize(input) ?? new AutoArchiveState(); AutoArchiveState state = State; if (state.Players == null) { List list2 = (state.Players = new List()); } state = State; if (state.Runs == null) { List list4 = (state.Runs = new List()); } state = State; if (state.IgnoredPlayerIds == null) { List list6 = (state.IgnoredPlayerIds = new List()); } RebuildIndexes(); _dirty = false; } catch (Exception arg) { _logger.LogError((object)$"Failed to load auto archive activity file, using a blank state: {arg}"); State = new AutoArchiveState(); RebuildIndexes(); _dirty = true; } } } public static void Flush(bool force = false) { lock (Sync) { if (_dirty || force) { DateTime utcNow = DateTime.UtcNow; if (force || !(utcNow - _lastFlushUtc < TimeSpan.FromSeconds(60.0))) { Directory.CreateDirectory(Path.GetDirectoryName(FilePath)); File.WriteAllText(FilePath, Serializer.Serialize(State)); _lastFlushUtc = utcNow; _dirty = false; } } } } public static void RecordPlayerSeen(string platformId, long playerId, string name, DateTime utcNow) { if (string.IsNullOrWhiteSpace(platformId)) { platformId = ((playerId != 0L) ? UnknownPlatformId(playerId) : "unknown"); } lock (Sync) { PlayerActivityRecord value; PlayerActivityRecord playerActivityRecord = (PlayersByPlatform.TryGetValue(platformId, out value) ? value : null); if (playerActivityRecord == null) { playerActivityRecord = new PlayerActivityRecord { PlatformId = platformId, FirstSeenUtc = utcNow }; State.Players.Add(playerActivityRecord); IndexPlayer(playerActivityRecord); } if (playerActivityRecord.FirstSeenUtc == DateTime.MinValue) { playerActivityRecord.FirstSeenUtc = utcNow; } playerActivityRecord.LastSeenUtc = utcNow; AddDistinct(playerActivityRecord.Names, name); if (playerId != 0L) { AddDistinct(playerActivityRecord.PlayerIds, playerId); PlayersById[playerId] = playerActivityRecord; MergePlayerIdRecords(playerActivityRecord, playerId); } _dirty = true; } } public static void RecordManualPlayerSeen(long playerId, DateTime utcNow) { lock (Sync) { PlayerActivityRecord value; PlayerActivityRecord playerActivityRecord = (PlayersById.TryGetValue(playerId, out value) ? value : new PlayerActivityRecord { PlatformId = ManualPlatformId(playerId), FirstSeenUtc = utcNow, PlayerIds = new List(1) { playerId } }); if (!State.Players.Contains(playerActivityRecord)) { State.Players.Add(playerActivityRecord); } if (IsUnknown(playerActivityRecord)) { playerActivityRecord.PlatformId = ManualPlatformId(playerId); } if (playerActivityRecord.FirstSeenUtc == DateTime.MinValue) { playerActivityRecord.FirstSeenUtc = utcNow; } playerActivityRecord.LastSeenUtc = utcNow; AddDistinct(playerActivityRecord.Names, "manual"); RebuildPlayerIndexes(); _dirty = true; } } public static void RecordUnknownPlayer(long playerId, DateTime utcNow, string observedName = "") { if (playerId == 0L) { return; } lock (Sync) { if (PlayersById.TryGetValue(playerId, out PlayerActivityRecord value)) { if (AddObservedName(value, observedName)) { _dirty = true; } } else { GetOrCreateUnknownPlayer(playerId, utcNow, observedName); _dirty = true; } } } public static bool TryGetPlayerRecord(long playerId, out PlayerActivityRecord record) { lock (Sync) { record = (PlayersById.TryGetValue(playerId, out PlayerActivityRecord value) ? value : null); return record != null; } } public static bool TryGetPlayerIdsBySteamId(string steamId, out List playerIds, out string normalizedSteamId) { normalizedSteamId = NormalizeSteamId(steamId); playerIds = new List(); if (string.IsNullOrWhiteSpace(normalizedSteamId)) { return false; } lock (Sync) { foreach (PlayerActivityRecord player in State.Players) { if (!TryNormalizeSteamPlatformId(player.PlatformId, out string steamId2) || !string.Equals(steamId2, normalizedSteamId, StringComparison.Ordinal)) { continue; } foreach (long item in player.PlayerIds.Where((long id) => id != 0)) { AddDistinct(playerIds, item); } } } return playerIds.Count > 0; } public static bool IsIgnored(long playerId) { lock (Sync) { return State.IgnoredPlayerIds.Contains(playerId); } } public static void SetIgnored(long playerId, bool ignored) { lock (Sync) { if (ignored) { AddDistinct(State.IgnoredPlayerIds, playerId); } else { State.IgnoredPlayerIds.Remove(playerId); } _dirty = true; } } public static AutoArchiveCreatorEligibility EvaluateCreatorArchiveEligibility(long playerId, DateTime utcNow, int inactiveDays, int unknownGraceDays, bool recordUnknownPlayer, string observedName = "") { AutoArchiveCreatorEligibility autoArchiveCreatorEligibility = new AutoArchiveCreatorEligibility { PlayerId = playerId, Ignored = (playerId != 0L && IsIgnored(playerId)) }; if (playerId == 0L) { autoArchiveCreatorEligibility.Reason = "creatorless"; return autoArchiveCreatorEligibility; } if (ZoneLimitConfiguration.IsArchiveProtected(playerId, out string reason)) { autoArchiveCreatorEligibility.Protected = true; autoArchiveCreatorEligibility.Reason = reason; return autoArchiveCreatorEligibility; } if (autoArchiveCreatorEligibility.Ignored) { autoArchiveCreatorEligibility.Reason = $"player {playerId} is ignored"; return autoArchiveCreatorEligibility; } if (!TryGetPlayerRecord(playerId, out PlayerActivityRecord record)) { autoArchiveCreatorEligibility.PlatformId = UnknownPlatformId(playerId); autoArchiveCreatorEligibility.Names = (string.IsNullOrWhiteSpace(observedName) ? new List(1) { "not_recorded_in_activity" } : new List(1) { observedName.Trim() }); autoArchiveCreatorEligibility.UnknownActivityRecord = true; if (recordUnknownPlayer) { RecordUnknownPlayer(playerId, utcNow, observedName); autoArchiveCreatorEligibility.Reason = $"player {playerId} was first discovered by scanner"; } else { autoArchiveCreatorEligibility.Reason = $"player {playerId} is not recorded in activity"; } return autoArchiveCreatorEligibility; } autoArchiveCreatorEligibility.RecordedInActivity = true; autoArchiveCreatorEligibility.PlatformId = record.PlatformId; autoArchiveCreatorEligibility.Names = record.Names?.ToList() ?? new List(); bool flag2 = (autoArchiveCreatorEligibility.UnknownActivityRecord = IsUnknown(record)); DateTime dateTime = (flag2 ? record.FirstSeenUtc : record.LastSeenUtc); int num = (flag2 ? unknownGraceDays : inactiveDays); if (dateTime == DateTime.MinValue) { autoArchiveCreatorEligibility.Reason = $"player {playerId} has no usable activity timestamp"; return autoArchiveCreatorEligibility; } TimeSpan timeSpan = utcNow - DateTime.SpecifyKind(dateTime, DateTimeKind.Utc); if (timeSpan.TotalDays < (double)num) { autoArchiveCreatorEligibility.Reason = (flag2 ? $"unknown player {playerId} first seen {timeSpan.TotalDays:F1}/{num} days ago" : $"player {playerId} last seen {timeSpan.TotalDays:F1}/{num} days ago"); return autoArchiveCreatorEligibility; } autoArchiveCreatorEligibility.Eligible = true; autoArchiveCreatorEligibility.Reason = (flag2 ? $"unknown player {playerId} grace expired" : $"player {playerId} inactive for {timeSpan.TotalDays:F1} days"); return autoArchiveCreatorEligibility; } public static bool IsCreatorArchiveEligible(long playerId, DateTime utcNow, int inactiveDays, int unknownGraceDays, out string reason) { AutoArchiveCreatorEligibility autoArchiveCreatorEligibility = EvaluateCreatorArchiveEligibility(playerId, utcNow, inactiveDays, unknownGraceDays, recordUnknownPlayer: true); reason = autoArchiveCreatorEligibility.Reason; return autoArchiveCreatorEligibility.Eligible; } public static void RecordRun(ArchiveRunRecord run) { lock (Sync) { State.LastScanUtc = run.CreatedUtc; if (!run.Manual) { State.LastAutoScanUtc = run.CreatedUtc; } State.Runs.Add(run); if (State.Runs.Count > 50) { State.Runs.RemoveRange(0, State.Runs.Count - 50); } _dirty = true; } } public static void SetLastAutoScanUtc(DateTime value) { lock (Sync) { State.LastAutoScanUtc = ((value == DateTime.MinValue) ? DateTime.MinValue : DateTime.SpecifyKind(value.ToUniversalTime(), DateTimeKind.Utc)); _dirty = true; } } private static PlayerActivityRecord GetOrCreateUnknownPlayer(long playerId, DateTime utcNow, string observedName = "") { string text = UnknownPlatformId(playerId); if (PlayersByPlatform.TryGetValue(text, out PlayerActivityRecord value)) { AddObservedName(value, observedName); return value; } List list = new List(); AddObservedName(list, observedName); if (list.Count == 0) { list.Add("unknown"); } value = new PlayerActivityRecord { PlatformId = text, FirstSeenUtc = utcNow, LastSeenUtc = DateTime.MinValue, PlayerIds = new List(1) { playerId }, Names = list }; State.Players.Add(value); IndexPlayer(value); return value; } private static bool AddObservedName(PlayerActivityRecord record, string observedName) { return AddObservedName(record.Names, observedName); } private static bool AddObservedName(List names, string observedName) { if (string.IsNullOrWhiteSpace(observedName) || string.Equals(observedName, "unknown", StringComparison.OrdinalIgnoreCase)) { return false; } string item = observedName.Trim(); if (names.Contains(item)) { return false; } names.Add(item); return true; } private static void MergePlayerIdRecords(PlayerActivityRecord target, long playerId) { PlayerActivityRecord target2 = target; foreach (PlayerActivityRecord item in State.Players.Where((PlayerActivityRecord player) => player != target2 && player.PlayerIds.Contains(playerId)).ToList()) { foreach (long playerId2 in item.PlayerIds) { AddDistinct(target2.PlayerIds, playerId2); } foreach (string name in item.Names) { AddDistinct(target2.Names, name); } if (target2.FirstSeenUtc == DateTime.MinValue || item.FirstSeenUtc < target2.FirstSeenUtc) { target2.FirstSeenUtc = item.FirstSeenUtc; } State.Players.Remove(item); } RebuildPlayerIndexes(); } private static void RebuildIndexes() { RebuildPlayerIndexes(); } private static void RebuildPlayerIndexes() { PlayersByPlatform.Clear(); PlayersById.Clear(); foreach (PlayerActivityRecord player in State.Players) { IndexPlayer(player); } } private static void IndexPlayer(PlayerActivityRecord record) { if (!string.IsNullOrWhiteSpace(record.PlatformId)) { PlayersByPlatform[record.PlatformId] = record; } foreach (long playerId in record.PlayerIds) { if (playerId != 0L) { PlayersById[playerId] = record; } } } private static string UnknownPlatformId(long playerId) { return "unknown:" + playerId; } private static string ManualPlatformId(long playerId) { return "manual:" + playerId; } private static bool IsUnknown(PlayerActivityRecord record) { return record.PlatformId.StartsWith("unknown:", StringComparison.Ordinal); } private static bool IsManual(PlayerActivityRecord record) { return record.PlatformId.StartsWith("manual:", StringComparison.Ordinal); } private static bool TryNormalizeSteamPlatformId(string platformId, out string steamId) { steamId = ""; if (string.IsNullOrWhiteSpace(platformId) || !platformId.StartsWith("steam:", StringComparison.OrdinalIgnoreCase)) { return false; } steamId = NormalizeSteamId(platformId.Substring("steam:".Length)); return !string.IsNullOrWhiteSpace(steamId); } private static string NormalizeSteamId(string value) { if (string.IsNullOrWhiteSpace(value)) { return ""; } string text = value.Trim(); if (text.StartsWith("steam:", StringComparison.OrdinalIgnoreCase)) { text = text.Substring("steam:".Length); } string text2 = new string(text.Where(char.IsDigit).ToArray()); if (text2.Length < 15) { return ""; } return text2; } private static void AddDistinct(List values, T value) { if (value != null && !values.Contains(value)) { values.Add(value); } } } internal sealed class BuildCounterHud : MonoBehaviour { private const float FadeDuration = 0.15f; private static BuildCounterHud? _instance; private CanvasGroup? _canvasGroup; private TextMeshProUGUI? _text; private float _hideAt = float.MinValue; public static void ShowCount(int count, int limit) { if (!((Object)(object)Hud.instance == (Object)null)) { EnsureInstance(); _instance?.Show($"{count}/{limit}"); } } private static void EnsureInstance() { if ((Object)(object)Hud.instance == (Object)null) { return; } if ((Object)(object)_instance != (Object)null && Object.op_Implicit((Object)(object)_instance)) { _instance.EnsureElements(); return; } _instance = ((Component)Hud.instance).GetComponent(); if ((Object)(object)_instance == (Object)null) { _instance = ((Component)Hud.instance).gameObject.AddComponent(); } _instance.EnsureElements(); } private void Update() { if ((Object)(object)_canvasGroup == (Object)null) { return; } if (Time.unscaledTime <= _hideAt) { _canvasGroup.alpha = 1f; return; } _canvasGroup.alpha = Mathf.MoveTowards(_canvasGroup.alpha, 0f, Time.unscaledDeltaTime / 0.15f); if (_canvasGroup.alpha <= 0f && (Object)(object)_text != (Object)null) { ((TMP_Text)_text).text = string.Empty; } } private void Show(string value) { EnsureElements(); if (!((Object)(object)_text == (Object)null) && !((Object)(object)_canvasGroup == (Object)null)) { ((TMP_Text)_text).text = value; _canvasGroup.alpha = 1f; _hideAt = Time.unscaledTime + ClientConfig.CounterVisibleSeconds; } } private void EnsureElements() { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_text != (Object)null) || !((Object)(object)_canvasGroup != (Object)null)) { TMP_Text val = Hud.instance?.m_buildSelection; if (!((Object)(object)val == (Object)null)) { GameObject val2 = new GameObject("ZoneSaviorCounter", new Type[4] { typeof(RectTransform), typeof(CanvasRenderer), typeof(CanvasGroup), typeof(TextMeshProUGUI) }); val2.transform.SetParent(((Component)Hud.instance).transform, false); RectTransform val3 = (RectTransform)val2.transform; val3.anchorMin = new Vector2(0.5f, 1f); val3.anchorMax = new Vector2(0.5f, 1f); val3.pivot = new Vector2(0.5f, 1f); val3.anchoredPosition = new Vector2(0f, -18f); val3.sizeDelta = new Vector2(280f, 34f); _canvasGroup = val2.GetComponent(); _canvasGroup.alpha = 0f; _text = val2.GetComponent(); ((TMP_Text)_text).font = val.font; ((TMP_Text)_text).fontSharedMaterial = val.fontSharedMaterial; ((TMP_Text)_text).fontSize = val.fontSize; ((Graphic)_text).color = ((Graphic)val).color; ((TMP_Text)_text).alignment = (TextAlignmentOptions)514; ((TMP_Text)_text).textWrappingMode = (TextWrappingModes)0; ((TMP_Text)_text).overflowMode = (TextOverflowModes)0; ((Graphic)_text).raycastTarget = false; ((TMP_Text)_text).text = string.Empty; } } } } internal static class ZoneSaviorTimestamp { public static string Now() { return Format(DateTime.UtcNow); } public static string Format(DateTime utc) { if (utc == DateTime.MinValue) { return ""; } return new DateTimeOffset(DateTime.SpecifyKind(utc, DateTimeKind.Utc)).ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss zzz", CultureInfo.InvariantCulture); } public static DateTime ParseUtc(string value) { if (string.IsNullOrWhiteSpace(value)) { return DateTime.MinValue; } if (DateTimeOffset.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces, out var result) || DateTimeOffset.TryParse(value, CultureInfo.CurrentCulture, DateTimeStyles.AllowWhiteSpaces, out result)) { return DateTime.SpecifyKind(result.UtcDateTime, DateTimeKind.Utc); } if (DateTime.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeLocal, out var result2) || DateTime.TryParse(value, CultureInfo.CurrentCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeLocal, out result2)) { return DateTime.SpecifyKind(result2, DateTimeKind.Utc); } return DateTime.MinValue; } public static bool IsExpired(string timestamp, DateTime utcNow) { DateTime dateTime = ParseUtc(timestamp); if (dateTime != DateTime.MinValue) { return dateTime <= DateTime.SpecifyKind(utcNow, DateTimeKind.Utc); } return false; } } internal static class PlayerActivityTracker { private static ManualLogSource _logger; public static void Initialize(ManualLogSource logger) { _logger = logger; } public static void TrackOnlinePlayers(DateTime utcNow) { if (!IsServerReady()) { return; } try { TrackRemotePeers(utcNow); TrackLocalPlayer(utcNow); } catch (Exception ex) { _logger.LogWarning((object)("Failed to update player activity: " + ex.Message)); } } private static void TrackRemotePeers(DateTime utcNow) { foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (TryGetPeerActivity(peer, out string platformId, out long playerId, out string name)) { AutoArchiveStore.RecordPlayerSeen(platformId, playerId, name, utcNow); } } } internal static bool TryGetPeerActivity(ZNetPeer peer, out string platformId, out long playerId, out string name) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) platformId = ""; playerId = 0L; name = ""; if (peer == null || !peer.IsReady()) { return false; } platformId = BuildPlatformId(peer); playerId = TryReadPlayerId(peer.m_characterID); name = peer.m_playerName; return true; } private static void TrackLocalPlayer(DateTime utcNow) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { long playerID = localPlayer.GetPlayerID(); string playerName = localPlayer.GetPlayerName(); AutoArchiveStore.RecordPlayerSeen(ZonePlayerIdentity.ResolveLocalPlatformId(playerID), playerID, playerName, utcNow); } } private static long TryReadPlayerId(ZDOID characterId) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (((ZDOID)(ref characterId)).IsNone() || ZDOMan.instance == null) { return 0L; } ZDO zDO = ZDOMan.instance.GetZDO(characterId); if (zDO == null) { return 0L; } return zDO.GetLong(ZDOVars.s_playerID, 0L); } private static string BuildPlatformId(ZNetPeer peer) { return ZonePlayerIdentity.ResolvePeerPlatformId(peer, 0L); } private static bool IsServerReady() { if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer() && ZDOMan.instance != null) { return (Object)(object)ZoneSystem.instance != (Object)null; } return false; } } internal static class ZoneBoundaryOverlay { private const int SegmentsPerEdge = 16; private const float LineHeightOffset = 0.12f; private static bool _visible; private static GameObject? _lineRoot; private static LineRenderer? _line; private static Material? _lineMaterial; private static TextMeshProUGUI? _hudText; private static CanvasGroup? _hudGroup; private static Vector2i _lastZone = new Vector2i(int.MinValue, int.MinValue); private static float _nextRefreshTime; public static void Update() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) if (IsToggleHotkeyDown()) { _visible = !_visible; _lastZone = new Vector2i(int.MinValue, int.MinValue); SetVisible(_visible); } if (!_visible) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead() || (Object)(object)ZoneSystem.instance == (Object)null) { SetVisible(visible: false); return; } EnsureHud(); EnsureLine(); Vector2i zone = ZoneSystem.GetZone(((Component)localPlayer).transform.position); UpdateHud(zone); if (zone.x != _lastZone.x || zone.y != _lastZone.y || Time.time >= _nextRefreshTime) { DrawBoundary(zone); _lastZone = zone; _nextRefreshTime = Time.time + 0.5f; } } public static void Shutdown() { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) _visible = false; if ((Object)(object)_lineRoot != (Object)null) { Object.Destroy((Object)(object)_lineRoot); } if ((Object)(object)_hudText != (Object)null) { Object.Destroy((Object)(object)((Component)_hudText).gameObject); } _lineRoot = null; _line = null; _lineMaterial = null; _hudText = null; _hudGroup = null; _lastZone = new Vector2i(int.MinValue, int.MinValue); } private static bool IsToggleHotkeyDown() { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (ShouldBlockInput()) { return false; } KeyboardShortcut zoneUiToggleHotkey = ClientConfig.ZoneUiToggleHotkey; if ((int)((KeyboardShortcut)(ref zoneUiToggleHotkey)).MainKey == 0 || !Input.GetKeyDown(((KeyboardShortcut)(ref zoneUiToggleHotkey)).MainKey)) { return false; } return ((KeyboardShortcut)(ref zoneUiToggleHotkey)).Modifiers.All(IsModifierHeld); } private static bool ShouldBlockInput() { if (!Console.IsVisible() && !TextInput.IsVisible()) { return Menu.IsVisible(); } return true; } private static bool IsModifierHeld(KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected I4, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) if ((int)key != 0) { switch (key - 303) { case 0: case 1: return Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303); case 2: case 3: return Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305); case 4: case 5: return Input.GetKey((KeyCode)308) || Input.GetKey((KeyCode)307); default: return Input.GetKey(key); } } return true; } private static void SetVisible(bool visible) { if ((Object)(object)_line != (Object)null) { ((Renderer)_line).enabled = visible; } if ((Object)(object)_hudGroup != (Object)null) { _hudGroup.alpha = (visible ? 1f : 0f); } } private static void EnsureLine() { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_005c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_line != (Object)null) { ((Renderer)_line).enabled = _visible; return; } if ((Object)(object)_lineMaterial == (Object)null) { Shader val = Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Color"); if ((Object)(object)val != (Object)null) { _lineMaterial = new Material(val); _lineMaterial.color = Color.white; } } _lineRoot = new GameObject("ZoneSaviorZoneBoundary"); Object.DontDestroyOnLoad((Object)(object)_lineRoot); _line = _lineRoot.AddComponent(); _line.useWorldSpace = true; _line.startWidth = 0.18f; _line.endWidth = 0.18f; _line.numCornerVertices = 2; _line.numCapVertices = 2; ((Renderer)_line).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)_line).receiveShadows = false; ((Renderer)_line).material = _lineMaterial; _line.startColor = new Color(0.2f, 0.85f, 1f, 0.95f); _line.endColor = new Color(0.2f, 0.85f, 1f, 0.95f); ((Renderer)_line).enabled = _visible; } private static void EnsureHud() { //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_hudText != (Object)null && (Object)(object)_hudGroup != (Object)null) { _hudGroup.alpha = (_visible ? 1f : 0f); } else { if ((Object)(object)Hud.instance == (Object)null) { return; } TextMeshProUGUI val = FindHudTextTemplate(); if (!((Object)(object)((val != null) ? ((TMP_Text)val).font : null) == (Object)null)) { _hudText = Object.Instantiate(val, ((Component)Hud.instance).transform, false); ((Object)((Component)_hudText).gameObject).name = "ZoneSaviorZoneHud"; ((Component)_hudText).gameObject.SetActive(true); ((TMP_Text)_hudText).transform.SetAsLastSibling(); ((TMP_Text)_hudText).font = ((TMP_Text)val).font; if ((Object)(object)((TMP_Text)val).fontSharedMaterial != (Object)null) { ((TMP_Text)_hudText).fontSharedMaterial = ((TMP_Text)val).fontSharedMaterial; } ((Graphic)_hudText).color = new Color(0.2f, 0.85f, 1f, 1f); ((TMP_Text)_hudText).alignment = (TextAlignmentOptions)514; ((TMP_Text)_hudText).enableAutoSizing = false; ((TMP_Text)_hudText).fontSize = 20f; ((TMP_Text)_hudText).textWrappingMode = (TextWrappingModes)0; ((TMP_Text)_hudText).overflowMode = (TextOverflowModes)0; ((Graphic)_hudText).raycastTarget = false; RectTransform val2 = (RectTransform)((TMP_Text)_hudText).transform; val2.anchorMin = new Vector2(0.5f, 1f); val2.anchorMax = new Vector2(0.5f, 1f); val2.pivot = new Vector2(0.5f, 1f); val2.anchoredPosition = new Vector2(0f, -96f); val2.sizeDelta = new Vector2(260f, 42f); _hudGroup = ((Component)_hudText).GetComponent(); if ((Object)(object)_hudGroup == (Object)null) { _hudGroup = ((Component)_hudText).gameObject.AddComponent(); } _hudGroup.alpha = (_visible ? 1f : 0f); } } } private static TextMeshProUGUI? FindHudTextTemplate() { TMP_Text obj = Hud.instance?.m_buildSelection; TextMeshProUGUI val = (TextMeshProUGUI)(object)((obj is TextMeshProUGUI) ? obj : null); if ((Object)(object)((val != null) ? ((TMP_Text)val).font : null) != (Object)null) { return val; } Hud instance = Hud.instance; if (instance == null) { return null; } return ((IEnumerable)((Component)instance).GetComponentsInChildren(true)).FirstOrDefault((Func)((TextMeshProUGUI text) => (Object)(object)text != (Object)null && (Object)(object)((TMP_Text)text).font != (Object)null)); } private static void UpdateHud(Vector2i zone) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_hudText == (Object)null)) { ((TMP_Text)_hudText).text = $"Zone {zone.x}, {zone.y}"; } } private static void DrawBoundary(Vector2i zone) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_line == (Object)null)) { float num = (((Object)(object)ZoneSystem.instance != (Object)null) ? ZoneSystem.instance.m_zoneSize : 64f) * 0.5f; Vector3 zonePos = ZoneSystem.GetZonePos(zone); int num2 = 65; _line.positionCount = num2; int index = 0; AddEdge(ref index, zonePos.x - num, zonePos.z - num, zonePos.x + num, zonePos.z - num); AddEdge(ref index, zonePos.x + num, zonePos.z - num, zonePos.x + num, zonePos.z + num); AddEdge(ref index, zonePos.x + num, zonePos.z + num, zonePos.x - num, zonePos.z + num); AddEdge(ref index, zonePos.x - num, zonePos.z + num, zonePos.x - num, zonePos.z - num); Vector3 position = _line.GetPosition(0); _line.SetPosition(num2 - 1, position); } } private static void AddEdge(ref int index, float startX, float startZ, float endX, float endZ) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_line == (Object)null)) { for (int i = 0; i < 16; i++) { float num = (float)i / 16f; float num2 = Mathf.Lerp(startX, endX, num); float num3 = Mathf.Lerp(startZ, endZ, num); float num4 = ZoneToolAim.SampleGroundY(num2, num3, 0f) + 0.12f; _line.SetPosition(index++, new Vector3(num2, num4, num3)); } } } } internal static class ZoneBundleCommands { private enum SaveEntryKind { Static, Monster } private readonly struct ZoneLoadStats { public int Removed { get; } public int Created { get; } public bool TerrainApplied { get; } public ZoneLoadStats(int removed, int created, bool terrainApplied) { Removed = removed; Created = created; TerrainApplied = terrainApplied; } } private sealed class CaptureBundleResult { public bool Success { get; private set; } public string ErrorMessage { get; private set; } = ""; public ZoneBundleFile? Bundle { get; private set; } public int EntryCount { get; private set; } public int MonsterCount { get; private set; } public ZoneBundleTerrainCaptureState TerrainState { get; private set; } private CaptureBundleResult() { } public static CaptureBundleResult Completed(ZoneBundleFile bundle, int entryCount, int monsterCount, ZoneBundleTerrainCaptureState terrainState) { return new CaptureBundleResult { Success = true, Bundle = bundle, EntryCount = entryCount, MonsterCount = monsterCount, TerrainState = terrainState }; } public static CaptureBundleResult Failed(string errorMessage) { return new CaptureBundleResult { Success = false, ErrorMessage = errorMessage }; } } private readonly struct LoadWorkItem { public Vector2i TargetZone { get; } public ZoneBundleFile Bundle { get; } public LoadWorkItem(Vector2i targetZone, ZoneBundleFile bundle) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) TargetZone = targetZone; Bundle = bundle; } } [CompilerGenerated] private static class <>O { public static ConsoleEvent <0>__HandleSaveZoneCommand; public static ConsoleEvent <1>__HandleLoadZoneCommand; public static ConsoleEvent <2>__HandleLoadArchiveCommand; public static Action <3>__RPC_HandleRequest; public static Action <4>__RPC_HandleResult; public static Func <5>__CloneCreatorPlayer; } [CompilerGenerated] private sealed class <>c__DisplayClass30_0 { public ZoneBundleArchiveResult archiveResult; internal void b__0(ZoneBundleArchiveResult result) { archiveResult = result; } } [CompilerGenerated] private sealed class <>c__DisplayClass31_0 { public ZoneBundleCommandResult result; internal void b__0(ZoneBundleCommandResult value) { result = value; } internal void b__1(ZoneBundleCommandResult value) { result = value; } } [CompilerGenerated] private sealed class <>c__DisplayClass38_0 { public ZoneBundleTerrain.TerrainSourceAnchor sourceAnchor; internal void b__6(ZoneBundleTerrain.TerrainSourceAnchor anchor) { sourceAnchor = anchor; } } [CompilerGenerated] private sealed class <>c__DisplayClass38_1 { public CaptureBundleResult capture; internal void b__7(CaptureBundleResult result) { capture = result; } } [CompilerGenerated] private sealed class <>c__DisplayClass49_0 { public string readyError; public TerrainPlacementContext terrainContext; public string contextError; public ZoneLoadStats stats; internal void b__0(string value) { readyError = value; } internal void b__1(TerrainPlacementContext? context, string error) { terrainContext = context; contextError = error; } internal void b__2(ZoneLoadStats value) { stats = value; } } [CompilerGenerated] private sealed class <>c__DisplayClass51_0 { public string readyError; public TerrainPlacementContext terrainContext; public string contextError; internal void b__0(string value) { readyError = value; } internal void b__1(TerrainPlacementContext? context, string error) { terrainContext = context; contextError = error; } } [CompilerGenerated] private sealed class <>c__DisplayClass51_1 { public ZoneLoadStats stats; internal void b__3(ZoneLoadStats value) { stats = value; } } [CompilerGenerated] private sealed class <>c__DisplayClass53_0 { public string readyError; public TerrainPlacementContext terrainContext; public string contextError; internal void b__0(string value) { readyError = value; } internal void b__1(TerrainPlacementContext? context, string error) { terrainContext = context; contextError = error; } } [CompilerGenerated] private sealed class <>c__DisplayClass53_1 { public ZoneLoadStats stats; internal void b__5(ZoneLoadStats value) { stats = value; } } [CompilerGenerated] private sealed class <>c__DisplayClass55_0 { public bool requiresTerrainApply; internal void b__0(bool value) { requiresTerrainApply = value; } } [CompilerGenerated] private sealed class <>c__DisplayClass58_0 { public TerrainPlacementContext context; internal void b__1(TerrainPlacementContext? value) { context = value; } } [CompilerGenerated] private sealed class <>c__DisplayClass63_0 { public bool hasWearNTearEntries; internal void b__0(bool value) { hasWearNTearEntries = value; } } [CompilerGenerated] private sealed class <>c__DisplayClass72_0 { public int removed; public bool terrainApplied; internal void b__0(int value) { removed = value; } internal void b__1(bool result) { terrainApplied = result; } } [CompilerGenerated] private sealed class <>c__DisplayClass74_0 { public string readyError; public TerrainPlacementContext terrainContext; public string contextError; internal void b__0(string value) { readyError = value; } internal void b__1(TerrainPlacementContext? context, string error) { terrainContext = context; contextError = error; } } [CompilerGenerated] private sealed class <>c__DisplayClass74_1 { public ZoneLoadStats stats; internal void b__2(ZoneLoadStats value) { stats = value; } } [CompilerGenerated] private sealed class <>c__DisplayClass77_0 { public int removed; public int remainingWearNTear; public int verificationRemoved; internal void b__2(int value) { removed = value; } internal void b__3(int value) { remainingWearNTear = value; } internal void b__4(int value) { verificationRemoved = value; } internal void b__5(int value) { remainingWearNTear = value; } } [CompilerGenerated] private sealed class d__72 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Vector2i targetZone; private <>c__DisplayClass72_0 <>8__1; public TerrainPlacementContext terrainContext; public ZoneBundleFile bundle; public float yOffset; public Action onComplete; private int 5__2; private int 5__3; private Vector3 5__4; private float 5__5; private List.Enumerator <>7__wrap5; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__72(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 4) { try { } finally { <>m__Finally1(); } } <>8__1 = null; <>7__wrap5 = default(List.Enumerator); <>1__state = -2; } private bool MoveNext() { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_02ba: Unknown result type (might be due to invalid IL or missing references) try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass72_0(); <>8__1.removed = 0; <>2__current = ClearTargetZoneAsync(targetZone, delegate(int value) { <>8__1.removed = value; }); <>1__state = 1; return true; case 1: <>1__state = -1; <>2__current = null; <>1__state = 2; return true; case 2: <>1__state = -1; <>8__1.terrainApplied = false; if (terrainContext != null) { <>2__current = ZoneBundleTerrainApplier.ApplySupportFillAsync(targetZone, bundle.Entries, bundle.TerrainContacts, bundle.TerrainContactsCaptured, terrainContext, delegate(bool result) { <>8__1.terrainApplied = result; }); <>1__state = 3; return true; } goto IL_010b; case 3: <>1__state = -1; goto IL_010b; case 4: { <>1__state = -3; break; } IL_010b: 5__2 = 0; 5__3 = 0; 5__4 = ZoneSystem.GetZonePos(targetZone); 5__5 = terrainContext?.BaseWorldY ?? (bundle.SourceBaseY + yOffset); <>7__wrap5 = bundle.Entries.GetEnumerator(); <>1__state = -3; break; } Vector3 position = default(Vector3); Quaternion rotation = default(Quaternion); Vector3 value2 = default(Vector3); while (<>7__wrap5.MoveNext()) { ZoneBundleEntry current = <>7__wrap5.Current; if (string.Equals(current.Kind, "item", StringComparison.OrdinalIgnoreCase)) { continue; } GameObject prefab = ZNetScene.instance.GetPrefab(current.Prefab); if (!Object.op_Implicit((Object)(object)prefab)) { _logger.LogWarning((object)("Missing prefab '" + current.Prefab + "' while loading zone bundle.")); } else if (!Object.op_Implicit((Object)(object)prefab.GetComponent())) { float num = (UsesRelativeY(bundle) ? (5__5 + current.LocalPos[1]) : (current.LocalPos[1] + yOffset)); ((Vector3)(ref position))..ctor(5__4.x + current.LocalPos[0], num, 5__4.z + current.LocalPos[2]); ((Quaternion)(ref rotation))..ctor(current.Rot[0], current.Rot[1], current.Rot[2], current.Rot[3]); ((Vector3)(ref value2))..ctor(current.Scale[0], current.Scale[1], current.Scale[2]); ZoneBundleZdoData data = (string.IsNullOrEmpty(current.Data) ? new ZoneBundleZdoData() : new ZoneBundleZdoData(current.Data)); SanitizeForLoad(current, prefab, data); ZDO val = ZoneBundleZdoHelper.Init(prefab, position, rotation, value2, data, EmptyParameters); if (val != null) { ZNetScene.instance.CreateObject(val); 5__2++; } 5__3++; if (5__3 >= 1000) { 5__3 = 0; <>2__current = null; <>1__state = 4; return true; } } } <>m__Finally1(); <>7__wrap5 = default(List.Enumerator); onComplete(new ZoneLoadStats(<>8__1.removed, 5__2, <>8__1.terrainApplied)); return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>7__wrap5).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__67 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Vector2i zone; public ZoneBundleTerrain.TerrainSourceAnchor sourceAnchor; public Action onComplete; public string tag; private Vector3 5__2; private bool 5__3; private List 5__4; private Dictionary 5__5; private int 5__6; private int 5__7; private int 5__8; private List.Enumerator <>7__wrap8; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__67(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } 5__4 = null; 5__5 = null; <>7__wrap8 = default(List.Enumerator); <>1__state = -2; } private bool MoveNext() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_044c: Unknown result type (might be due to invalid IL or missing references) //IL_048e: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Unknown result type (might be due to invalid IL or missing references) //IL_02f8: Unknown result type (might be due to invalid IL or missing references) //IL_0307: Unknown result type (might be due to invalid IL or missing references) //IL_0316: Unknown result type (might be due to invalid IL or missing references) //IL_0332: Unknown result type (might be due to invalid IL or missing references) //IL_0341: Unknown result type (might be due to invalid IL or missing references) //IL_0350: Unknown result type (might be due to invalid IL or missing references) bool result; try { switch (<>1__state) { default: result = false; break; case 0: { <>1__state = -1; 5__2 = ZoneSystem.GetZonePos(zone); 5__3 = !float.IsNaN(sourceAnchor.BaseWorldY); 5__4 = new List(); 5__5 = new Dictionary(); List list3 = new List(); try { ZDOMan.instance.FindObjects(zone, list3); } catch (Exception ex3) { onComplete(CaptureBundleResult.Failed(ex3.Message)); result = false; break; } 5__6 = 0; 5__7 = 0; 5__8 = 0; <>7__wrap8 = list3.GetEnumerator(); <>1__state = -3; goto IL_0400; } case 1: <>1__state = -3; goto IL_0400; case 2: { <>1__state = -1; try { bool contactsCaptured; List list = ZoneBundleTerrainApplier.CaptureSupportContacts(zone, sourceAnchor.BaseWorldY, 5__4, out contactsCaptured); ZoneBundleTerrainCaptureState terrainCaptureState = GetTerrainCaptureState(contactsCaptured, list.Count); ZoneBundleFile bundle = new ZoneBundleFile { Tag = tag, SourceZone = ToModel(zone), TerrainMode = ZoneBundleTerrainApplier.SupportFillMode, SourceBaseY = (5__3 ? sourceAnchor.BaseWorldY : 0f), TerrainCaptureState = terrainCaptureState, TerrainContactsCaptured = contactsCaptured, TerrainContacts = list, SourceZoneCreators = BuildSourceZoneCreators(5__5), Entries = 5__4.OrderBy((ZoneBundleEntry entry) => entry.Kind, StringComparer.Ordinal).ThenBy((ZoneBundleEntry entry) => entry.Prefab, StringComparer.Ordinal).ThenBy((ZoneBundleEntry entry) => entry.LocalPos[0]) .ThenBy((ZoneBundleEntry entry) => entry.LocalPos[2]) .ThenBy((ZoneBundleEntry entry) => entry.LocalPos[1]) .ToList() }; onComplete(CaptureBundleResult.Completed(bundle, 5__4.Count, 5__7, terrainCaptureState)); } catch (Exception ex) { onComplete(CaptureBundleResult.Failed(ex.Message)); } result = false; break; } IL_0400: while (true) { if (<>7__wrap8.MoveNext()) { ZDO current = <>7__wrap8.Current; try { if (current != null && current.IsValid() && TryClassify(current, out SaveEntryKind kind, out GameObject prefab)) { bool flag = (Object)(object)prefab.GetComponent() != (Object)null; bool flag2 = kind == SaveEntryKind.Monster; long num = (flag ? current.GetLong(ZDOVars.s_creator, 0L) : 0); string text = (flag ? current.GetString(ZDOVars.s_creatorName, "") : ""); AddCreatorPlayer(5__5, num, text); if ((!flag || ZoneBlueprintCommands.HasBuildRecipe(prefab)) && (ZoneBundleTerrainApplier.IsSupportWearNTear(current, zone, out GameObject _) || flag2)) { ZoneBundleZdoData zoneBundleZdoData = new ZoneBundleZdoData(current); string text2 = ((kind == SaveEntryKind.Monster) ? "monster-v1" : ((!flag) ? "" : "wearntear-v1")); string sanitize = text2; SanitizeForSave(kind, zoneBundleZdoData, sanitize); Vector3 position = current.m_position; Quaternion rotation = current.GetRotation(); Vector3 val = ReadScale(current, prefab); List list2 = 5__4; ZoneBundleEntry zoneBundleEntry = new ZoneBundleEntry(); text2 = ((kind != SaveEntryKind.Monster) ? $"s_{++5__6:D4}" : $"m_{++5__7:D4}"); zoneBundleEntry.SaveId = text2; string kind2 = ((kind != SaveEntryKind.Monster) ? "static" : "monster"); zoneBundleEntry.Kind = kind2; zoneBundleEntry.Prefab = Utils.GetPrefabName(prefab); zoneBundleEntry.LocalPos = new float[3] { Round(position.x - 5__2.x), Round(5__3 ? (position.y - sourceAnchor.BaseWorldY) : position.y), Round(position.z - 5__2.z) }; zoneBundleEntry.Rot = new float[4] { Round(rotation.x), Round(rotation.y), Round(rotation.z), Round(rotation.w) }; zoneBundleEntry.Scale = new float[3] { Round(val.x), Round(val.y), Round(val.z) }; zoneBundleEntry.CreatorPlayerId = num; zoneBundleEntry.CreatorName = NormalizeCreatorString(text); zoneBundleEntry.Data = zoneBundleZdoData.GetBase64(EmptyParameters); zoneBundleEntry.Sanitize = sanitize; list2.Add(zoneBundleEntry); goto IL_03bd; } } } catch (Exception ex2) { onComplete(CaptureBundleResult.Failed(ex2.Message)); result = false; goto IL_0418; } continue; } <>m__Finally1(); <>7__wrap8 = default(List.Enumerator); <>2__current = null; <>1__state = 2; result = true; break; IL_0418: <>m__Finally1(); break; IL_03bd: 5__8++; if (5__8 >= 1000) { 5__8 = 0; <>2__current = null; <>1__state = 1; result = true; break; } } break; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>7__wrap8).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__79 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Vector2i targetZone; public Action onComplete; private int 5__2; private int 5__3; private List.Enumerator <>7__wrap3; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__79(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <>7__wrap3 = default(List.Enumerator); <>1__state = -2; } private bool MoveNext() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) try { switch (<>1__state) { default: return false; case 0: { <>1__state = -1; List list = new List(); ZDOMan.instance.FindObjects(targetZone, list); 5__2 = 0; 5__3 = 0; <>7__wrap3 = list.ToList().GetEnumerator(); <>1__state = -3; break; } case 1: <>1__state = -3; break; } while (<>7__wrap3.MoveNext()) { ZDO current = <>7__wrap3.Current; if (current != null && current.IsValid()) { GameObject prefab = ZNetScene.instance.GetPrefab(current.GetPrefab()); if (Object.op_Implicit((Object)(object)prefab) && ShouldDeleteForOverwrite(prefab, current)) { ZoneBundleZdoHelper.Destroy(current); 5__2++; } } 5__3++; if (5__3 >= 1000) { ZoneBundleZdoHelper.FlushDestroyed(); 5__3 = 0; <>2__current = null; <>1__state = 1; return true; } } <>m__Finally1(); <>7__wrap3 = default(List.Enumerator); ZoneBundleZdoHelper.FlushDestroyed(); onComplete(5__2); return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>7__wrap3).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__84 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public HashSet zones; public HashSet protectedCharacterIds; public Action onComplete; private HashSet 5__2; private List 5__3; private int 5__4; private int 5__5; private HashSet.Enumerator <>7__wrap5; private List.Enumerator <>7__wrap6; private ZDO 5__8; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__84(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if ((uint)(num - -4) <= 1u || num == 1) { try { if (num == -4 || num == 1) { try { } finally { <>m__Finally2(); } } } finally { <>m__Finally1(); } } 5__2 = null; 5__3 = null; <>7__wrap5 = default(HashSet.Enumerator); <>7__wrap6 = default(List.Enumerator); 5__8 = null; <>1__state = -2; } private bool MoveNext() { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) try { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -4; goto IL_00fb; } <>1__state = -1; 5__2 = new HashSet(); 5__3 = new List(); 5__4 = 0; 5__5 = 0; <>7__wrap5 = zones.GetEnumerator(); <>1__state = -3; goto IL_01c2; IL_01c2: if (<>7__wrap5.MoveNext()) { Vector2i current = <>7__wrap5.Current; 5__3.Clear(); ZDOMan.instance.FindObjects(current, 5__3); <>7__wrap6 = 5__3.GetEnumerator(); <>1__state = -4; goto IL_01a0; } <>m__Finally1(); <>7__wrap5 = default(HashSet.Enumerator); onComplete(5__4); return false; IL_01a0: if (<>7__wrap6.MoveNext()) { 5__8 = <>7__wrap6.Current; 5__5++; if (5__5 >= 1000) { 5__5 = 0; <>2__current = null; <>1__state = 1; return true; } goto IL_00fb; } <>m__Finally2(); <>7__wrap6 = default(List.Enumerator); goto IL_01c2; IL_00fb: if (5__8 != null && 5__8.IsValid() && 5__2.Add(5__8.m_uid) && IsResettableZoneObject(5__8, zones, protectedCharacterIds) && 5__8.GetLong(ZDOVars.s_creator, 0L) != 0L) { GameObject prefab = ZNetScene.instance.GetPrefab(5__8.GetPrefab()); if (Object.op_Implicit((Object)(object)prefab) && (Object)(object)prefab.GetComponent() != (Object)null) { 5__4++; } 5__8 = null; } goto IL_01a0; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>7__wrap5).Dispose(); } private void <>m__Finally2() { <>1__state = -3; ((IDisposable)<>7__wrap6).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__58 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public IEnumerable work; public Action onComplete; public bool exactSource; private <>c__DisplayClass58_0 <>8__1; public float yOffset; private List 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__58(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__1 = null; 5__2 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass58_0(); 5__2 = work.ToList(); <>8__1.context = null; try { if (5__2.Count == 0) { onComplete(null, ""); return false; } if (exactSource) { <>8__1.context = CreateTerrainPlacementContext(5__2, exactSource); } } catch (Exception ex) { onComplete(null, ex.Message); return false; } if (!exactSource) { <>2__current = ZoneBundleTerrainApplier.CreateSupportFillPlacementContextAsync(5__2.Select((LoadWorkItem item) => new TerrainSupportTarget { Zone = item.TargetZone, SourceBaseY = item.Bundle.SourceBaseY, Entries = item.Bundle.Entries, ContactsCaptured = item.Bundle.TerrainContactsCaptured, Contacts = item.Bundle.TerrainContacts }), delegate(TerrainPlacementContext? value) { <>8__1.context = value; }); <>1__state = 1; return true; } break; case 1: <>1__state = -1; break; } try { ApplyYOffset(<>8__1.context, yOffset); ValidateTerrainPlacementContext(5__2, <>8__1.context); onComplete(<>8__1.context, ""); } catch (Exception ex2) { onComplete(null, ex2.Message); } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__112 : IEnumerable, IEnumerable, IEnumerator, IDisposable, IEnumerator { private int <>1__state; private Vector2i <>2__current; private int <>l__initialThreadId; private ZoneBundleRange range; public ZoneBundleRange <>3__range; private int 5__2; private int 5__3; Vector2i IEnumerator.Current { [DebuggerHidden] get { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return <>2__current; } } [DebuggerHidden] public d__112(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; 5__3++; goto IL_0074; } <>1__state = -1; 5__2 = range.MinZ; goto IL_0097; IL_0074: if (5__3 <= range.MaxX) { <>2__current = new Vector2i(5__3, 5__2); <>1__state = 1; return true; } 5__2++; goto IL_0097; IL_0097: if (5__2 <= range.MaxZ) { 5__3 = range.MinX; goto IL_0074; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { d__112 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__112(0); } d__.range = <>3__range; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } [CompilerGenerated] private sealed class d__31 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public ZoneBundleCommandRequest request; public Action onComplete; private <>c__DisplayClass31_0 <>8__1; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__31(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__1 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass31_0(); <>8__1.result = ZoneBundleCommandResult.Fail("Load failed before it started."); if (request.Operation == "zs_loadzone") { <>2__current = LoadZoneRequestAsync(request, delegate(ZoneBundleCommandResult value) { <>8__1.result = value; }); <>1__state = 1; return true; } if (request.Operation == "zs_loadarchive") { <>2__current = LoadArchiveManifestAsync(request, delegate(ZoneBundleCommandResult value) { <>8__1.result = value; }); <>1__state = 2; return true; } <>8__1.result = ExecuteRequest(request); break; case 1: <>1__state = -1; break; case 2: <>1__state = -1; break; } onComplete(<>8__1.result); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__30 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public ZoneBundleCommandRequest request; private <>c__DisplayClass30_0 <>8__1; public Action onComplete; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__30(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__1 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass30_0(); <>8__1.archiveResult = null; <>2__current = SaveZonesAsync(EnumerateZones(request.SourceRange), request.Tag, delegate(ZoneBundleArchiveResult result) { <>8__1.archiveResult = result; }); <>1__state = 1; return true; case 1: <>1__state = -1; if (<>8__1.archiveResult == null) { onComplete(ZoneBundleCommandResult.Fail("Save failed: archive coroutine did not return a result.")); return false; } onComplete(<>8__1.archiveResult.Success ? ZoneBundleCommandResult.Ok(<>8__1.archiveResult.Message) : ZoneBundleCommandResult.Fail(<>8__1.archiveResult.Message)); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__64 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public ZoneBundleFile bundle; public Action onComplete; private int 5__2; private List.Enumerator <>7__wrap2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__64(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <>7__wrap2 = default(List.Enumerator); <>1__state = -2; } private bool MoveNext() { bool result; try { switch (<>1__state) { default: result = false; goto end_IL_0000; case 0: <>1__state = -1; 5__2 = 0; <>7__wrap2 = bundle.Entries.GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; break; } while (true) { if (<>7__wrap2.MoveNext()) { ZoneBundleEntry current = <>7__wrap2.Current; if (!string.Equals(current.Kind, "item", StringComparison.OrdinalIgnoreCase)) { GameObject prefab = ZNetScene.instance.GetPrefab(current.Prefab); if (Object.op_Implicit((Object)(object)prefab) && (Object)(object)prefab.GetComponent() != (Object)null) { onComplete(obj: true); result = false; <>m__Finally1(); break; } } 5__2++; if (5__2 >= 1000) { 5__2 = 0; <>2__current = null; <>1__state = 1; result = true; break; } continue; } <>m__Finally1(); <>7__wrap2 = default(List.Enumerator); onComplete(obj: false); result = false; break; } end_IL_0000:; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>7__wrap2).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__53 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public ZoneBundleCommandRequest request; public Action onComplete; private <>c__DisplayClass53_0 <>8__1; private <>c__DisplayClass53_1 <>8__2; private Vector2i 5__2; private List 5__3; private int 5__4; private int 5__5; private int 5__6; private int 5__7; private int 5__8; private List.Enumerator <>7__wrap8; private List.Enumerator <>7__wrap9; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__53(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { switch (<>1__state) { case -3: case 1: try { } finally { <>m__Finally1(); } break; case -4: case 4: try { } finally { <>m__Finally2(); } break; } <>8__1 = null; <>8__2 = null; 5__3 = null; <>7__wrap8 = default(List.Enumerator); <>7__wrap9 = default(List.Enumerator); <>1__state = -2; } private bool MoveNext() { //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_043f: Unknown result type (might be due to invalid IL or missing references) bool result; try { ZoneBundleManifest zoneBundleManifest; switch (<>1__state) { default: result = false; goto end_IL_0000; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass53_0(); try { zoneBundleManifest = ZoneBundleSerialization.LoadManifest(GetManifestPath(request.Tag)); if (zoneBundleManifest.Bundles.Count != 0) { List source = zoneBundleManifest.Bundles.Select((ZoneBundleManifestEntry entry) => ToVector2i(entry.Zone)).ToList(); 5__2 = ToVector2i(request.TargetZone); int num = source.Min((Vector2i zone) => zone.x); int num2 = source.Min((Vector2i zone) => zone.y); 5__4 = 5__2.x - num; 5__5 = 5__2.y - num2; goto IL_017e; } onComplete(ZoneBundleCommandResult.Fail("Manifest for tag '" + request.Tag + "' contains no zone bundles.")); result = false; } catch (Exception ex) { _logger.LogError((object)$"Zone bundle async archive load failed: {ex}"); onComplete(ZoneBundleCommandResult.Fail(ex.Message)); result = false; } goto end_IL_0000; case 1: <>1__state = -3; goto IL_0265; case 2: <>1__state = -1; if (!string.IsNullOrWhiteSpace(<>8__1.readyError)) { _logger.LogError((object)("Zone bundle async archive load failed: " + <>8__1.readyError)); onComplete(ZoneBundleCommandResult.Fail(<>8__1.readyError)); result = false; } else { <>8__1.terrainContext = null; <>8__1.contextError = ""; <>2__current = CreateAndValidateTerrainPlacementContextAsync(5__3, exactSource: false, request.YOffset, delegate(TerrainPlacementContext? context, string error) { <>8__1.terrainContext = context; <>8__1.contextError = error; }); <>1__state = 3; result = true; } goto end_IL_0000; case 3: <>1__state = -1; if (string.IsNullOrWhiteSpace(<>8__1.contextError)) { 5__6 = 0; 5__7 = 0; 5__8 = 0; <>7__wrap9 = 5__3.GetEnumerator(); <>1__state = -4; break; } _logger.LogError((object)("Zone bundle async archive load failed: " + <>8__1.contextError)); onComplete(ZoneBundleCommandResult.Fail(<>8__1.contextError)); result = false; goto end_IL_0000; case 4: { <>1__state = -4; 5__6 += <>8__2.stats.Removed; 5__7 += <>8__2.stats.Created; if (<>8__2.stats.TerrainApplied) { 5__8++; } <>8__2 = null; break; } IL_017e: 5__3 = new List(); <>7__wrap8 = zoneBundleManifest.Bundles.GetEnumerator(); <>1__state = -3; goto IL_0265; IL_0265: if (<>7__wrap8.MoveNext()) { ZoneBundleManifestEntry current = <>7__wrap8.Current; Vector2i val = ToVector2i(current.Zone); if (!TryLoadBundleFile(Path.Combine(GetTagDirectory(request.Tag), current.File), out ZoneBundleFile bundle, out string reason)) { _logger.LogError((object)("Zone bundle async archive load failed: " + reason)); onComplete(ZoneBundleCommandResult.Fail(reason)); result = false; <>m__Finally1(); } else { 5__3.Add(new LoadWorkItem(new Vector2i(val.x + 5__4, val.y + 5__5), bundle)); <>2__current = null; <>1__state = 1; result = true; } } else { <>m__Finally1(); <>7__wrap8 = default(List.Enumerator); <>8__1.readyError = ""; <>2__current = ValidateLoadReadyAsync(5__3, delegate(string value) { <>8__1.readyError = value; }); <>1__state = 2; result = true; } goto end_IL_0000; } if (<>7__wrap9.MoveNext()) { LoadWorkItem current2 = <>7__wrap9.Current; <>8__2 = new <>c__DisplayClass53_1(); <>8__2.stats = default(ZoneLoadStats); <>2__current = ApplyBundleToZoneAsync(current2.TargetZone, current2.Bundle, <>8__1.terrainContext, request.YOffset, delegate(ZoneLoadStats value) { <>8__2.stats = value; }); <>1__state = 4; result = true; } else { <>m__Finally2(); <>7__wrap9 = default(List.Enumerator); onComplete(ZoneBundleCommandResult.Ok($"Loaded archive '{request.Tag}' as {5__3.Count} manifest zone(s) to target start ({5__2.x},{5__2.y}) " + $"(removed: {5__6}, created: {5__7}, terrain: {5__8}/{5__3.Count}, mode: SupportFill, yOffset: {Round(request.YOffset)}).")); result = false; } end_IL_0000:; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>7__wrap8).Dispose(); } private void <>m__Finally2() { <>1__state = -1; ((IDisposable)<>7__wrap9).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__49 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public ZoneBundleCommandRequest request; public Action onComplete; private <>c__DisplayClass49_0 <>8__1; private Vector2i 5__2; private Vector2i 5__3; private ZoneBundleFile 5__4; private List 5__5; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__49(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__1 = null; 5__4 = null; 5__5 = null; <>1__state = -2; } private bool MoveNext() { //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: { <>1__state = -1; <>8__1 = new <>c__DisplayClass49_0(); try { 5__2 = ToSingleSourceZone(request.SourceRange); 5__3 = ToVector2i(request.TargetZone); } catch (Exception ex) { _logger.LogError((object)$"Zone bundle async load failed: {ex}"); onComplete(ZoneBundleCommandResult.Fail(ex.Message)); return false; } string bundlePathFromManifest; try { bundlePathFromManifest = GetBundlePathFromManifest(request.Tag, 5__2); } catch (Exception ex2) { _logger.LogError((object)$"Zone bundle async load failed: {ex2}"); onComplete(ZoneBundleCommandResult.Fail(ex2.Message)); return false; } if (!TryLoadBundleFile(bundlePathFromManifest, out 5__4, out string reason)) { _logger.LogError((object)("Zone bundle async load failed: " + reason)); onComplete(ZoneBundleCommandResult.Fail(reason)); return false; } <>2__current = null; <>1__state = 1; return true; } case 1: <>1__state = -1; 5__5 = new List(1) { new LoadWorkItem(5__3, 5__4) }; <>8__1.readyError = ""; <>2__current = ValidateLoadReadyAsync(5__5, delegate(string value) { <>8__1.readyError = value; }); <>1__state = 2; return true; case 2: <>1__state = -1; if (!string.IsNullOrWhiteSpace(<>8__1.readyError)) { _logger.LogError((object)("Zone bundle async load failed: " + <>8__1.readyError)); onComplete(ZoneBundleCommandResult.Fail(<>8__1.readyError)); return false; } <>8__1.terrainContext = null; <>8__1.contextError = ""; <>2__current = CreateAndValidateTerrainPlacementContextAsync(5__5, exactSource: false, request.YOffset, delegate(TerrainPlacementContext? context, string error) { <>8__1.terrainContext = context; <>8__1.contextError = error; }); <>1__state = 3; return true; case 3: <>1__state = -1; if (!string.IsNullOrWhiteSpace(<>8__1.contextError)) { _logger.LogError((object)("Zone bundle async load failed: " + <>8__1.contextError)); onComplete(ZoneBundleCommandResult.Fail(<>8__1.contextError)); return false; } <>8__1.stats = default(ZoneLoadStats); <>2__current = ApplyBundleToZoneAsync(5__3, 5__4, <>8__1.terrainContext, request.YOffset, delegate(ZoneLoadStats value) { <>8__1.stats = value; }); <>1__state = 4; return true; case 4: <>1__state = -1; onComplete(ZoneBundleCommandResult.Ok($"Loaded {request.Tag} source zone ({5__2.x},{5__2.y}) into target zone ({5__3.x},{5__3.y}) " + string.Format("(removed: {0}, created: {1}, terrain: {2}, mode: SupportFill, yOffset: {3}).", <>8__1.stats.Removed, <>8__1.stats.Created, <>8__1.stats.TerrainApplied ? "yes" : "no", Round(request.YOffset)))); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__51 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public ZoneBundleCommandRequest request; public Action onComplete; private <>c__DisplayClass51_0 <>8__1; private <>c__DisplayClass51_1 <>8__2; private Vector2i 5__2; private List 5__3; private Dictionary 5__4; private int 5__5; private int 5__6; private int 5__7; private int 5__8; private int 5__9; private IEnumerator <>7__wrap9; private List.Enumerator <>7__wrap10; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__51(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { switch (<>1__state) { case -3: case 1: try { } finally { <>m__Finally1(); } break; case -4: case 4: try { } finally { <>m__Finally2(); } break; } <>8__1 = null; <>8__2 = null; 5__3 = null; 5__4 = null; <>7__wrap9 = null; <>7__wrap10 = default(List.Enumerator); <>1__state = -2; } private bool MoveNext() { //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0436: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) bool result; try { switch (<>1__state) { default: result = false; goto end_IL_0000; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass51_0(); try { ZoneBundleManifest zoneBundleManifest = ZoneBundleSerialization.LoadManifest(GetManifestPath(request.Tag)); 5__4 = zoneBundleManifest.Bundles.ToDictionary((ZoneBundleManifestEntry entry) => ToVector2i(entry.Zone)); 5__2 = ToVector2i(request.TargetZone); 5__5 = 5__2.x - request.SourceRange.MinX; 5__6 = 5__2.y - request.SourceRange.MinZ; } catch (Exception ex) { _logger.LogError((object)$"Zone bundle async range load failed: {ex}"); onComplete(ZoneBundleCommandResult.Fail(ex.Message)); result = false; goto end_IL_0000; } 5__3 = new List(); <>7__wrap9 = EnumerateZones(request.SourceRange).GetEnumerator(); <>1__state = -3; goto IL_0261; case 1: <>1__state = -3; goto IL_0261; case 2: <>1__state = -1; if (!string.IsNullOrWhiteSpace(<>8__1.readyError)) { _logger.LogError((object)("Zone bundle async range load failed: " + <>8__1.readyError)); onComplete(ZoneBundleCommandResult.Fail(<>8__1.readyError)); result = false; } else { <>8__1.terrainContext = null; <>8__1.contextError = ""; <>2__current = CreateAndValidateTerrainPlacementContextAsync(5__3, exactSource: false, request.YOffset, delegate(TerrainPlacementContext? context, string error) { <>8__1.terrainContext = context; <>8__1.contextError = error; }); <>1__state = 3; result = true; } goto end_IL_0000; case 3: <>1__state = -1; if (string.IsNullOrWhiteSpace(<>8__1.contextError)) { 5__7 = 0; 5__8 = 0; 5__9 = 0; <>7__wrap10 = 5__3.GetEnumerator(); <>1__state = -4; break; } _logger.LogError((object)("Zone bundle async range load failed: " + <>8__1.contextError)); onComplete(ZoneBundleCommandResult.Fail(<>8__1.contextError)); result = false; goto end_IL_0000; case 4: { <>1__state = -4; 5__7 += <>8__2.stats.Removed; 5__8 += <>8__2.stats.Created; if (<>8__2.stats.TerrainApplied) { 5__9++; } <>8__2 = null; break; } IL_0279: <>m__Finally1(); goto end_IL_0000; IL_0261: if (<>7__wrap9.MoveNext()) { Vector2i current = <>7__wrap9.Current; if (!5__4.TryGetValue(current, out ZoneBundleManifestEntry value2)) { string text = $"Manifest for tag '{request.Tag}' does not contain source zone ({current.x},{current.y})."; _logger.LogError((object)("Zone bundle async range load failed: " + text)); onComplete(ZoneBundleCommandResult.Fail(text)); result = false; goto IL_0279; } if (!TryLoadBundleFile(Path.Combine(GetTagDirectory(request.Tag), value2.File), out ZoneBundleFile bundle, out string reason)) { _logger.LogError((object)("Zone bundle async range load failed: " + reason)); onComplete(ZoneBundleCommandResult.Fail(reason)); result = false; goto IL_0279; } 5__3.Add(new LoadWorkItem(new Vector2i(current.x + 5__5, current.y + 5__6), bundle)); <>2__current = null; <>1__state = 1; result = true; } else { <>m__Finally1(); <>7__wrap9 = null; <>8__1.readyError = ""; <>2__current = ValidateLoadReadyAsync(5__3, delegate(string value) { <>8__1.readyError = value; }); <>1__state = 2; result = true; } goto end_IL_0000; } if (<>7__wrap10.MoveNext()) { LoadWorkItem current2 = <>7__wrap10.Current; <>8__2 = new <>c__DisplayClass51_1(); <>8__2.stats = default(ZoneLoadStats); <>2__current = ApplyBundleToZoneAsync(current2.TargetZone, current2.Bundle, <>8__1.terrainContext, request.YOffset, delegate(ZoneLoadStats value) { <>8__2.stats = value; }); <>1__state = 4; result = true; } else { <>m__Finally2(); <>7__wrap10 = default(List.Enumerator); onComplete(ZoneBundleCommandResult.Ok($"Batch loaded {5__3.Count} zone bundle(s) for tag '{request.Tag}' to target start ({5__2.x},{5__2.y}) " + $"(removed: {5__7}, created: {5__8}, terrain: {5__9}/{5__3.Count}, mode: SupportFill, yOffset: {Round(request.YOffset)}).")); result = false; } end_IL_0000:; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>7__wrap9 != null) { <>7__wrap9.Dispose(); } } private void <>m__Finally2() { <>1__state = -1; ((IDisposable)<>7__wrap10).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__35 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public ZoneBundleCommandRequest request; public Action onComplete; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__35(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (IsSingleRange(request.SourceRange)) { <>2__current = LoadSingleZoneAsync(request, onComplete); <>1__state = 1; return true; } <>2__current = LoadZoneRangeAsync(request, onComplete); <>1__state = 2; return true; case 1: <>1__state = -1; break; case 2: <>1__state = -1; break; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__89 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; private int 5__2; private List.Enumerator <>7__wrap2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__89(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <>7__wrap2 = default(List.Enumerator); <>1__state = -2; } private bool MoveNext() { try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__2 = 0; <>7__wrap2 = GetLoadedHeightmapSnapshot().GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; break; } while (<>7__wrap2.MoveNext()) { if (RecalculateHeightmap(<>7__wrap2.Current)) { 5__2++; if (5__2 >= 8) { 5__2 = 0; <>2__current = null; <>1__state = 1; return true; } } } <>m__Finally1(); <>7__wrap2 = default(List.Enumerator); return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>7__wrap2).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__63 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public ZoneBundleFile bundle; public Action onComplete; private <>c__DisplayClass63_0 <>8__1; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__63(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__1 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass63_0(); if (!IsSupportFillBundle(bundle)) { onComplete(obj: false); return false; } if (HasSavedTerrainContacts(bundle)) { onComplete(obj: true); return false; } <>8__1.hasWearNTearEntries = false; <>2__current = HasWearNTearEntriesAsync(bundle, delegate(bool value) { <>8__1.hasWearNTearEntries = value; }); <>1__state = 1; return true; case 1: <>1__state = -1; onComplete(<>8__1.hasWearNTearEntries); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__77 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public IEnumerable sourceZones; public Action onComplete; private <>c__DisplayClass77_0 <>8__1; private List 5__2; private HashSet 5__3; private HashSet 5__4; private int 5__5; private List.Enumerator <>7__wrap5; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__77(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 2) { try { } finally { <>m__Finally1(); } } <>8__1 = null; 5__2 = null; 5__3 = null; 5__4 = null; <>7__wrap5 = default(List.Enumerator); <>1__state = -2; } private bool MoveNext() { //IL_0163: Unknown result type (might be due to invalid IL or missing references) try { ClutterSystem instance2; switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass77_0(); 5__2 = (from zone in sourceZones.Distinct() orderby zone.y, zone.x select zone).ToList(); if (5__2.Count == 0) { onComplete(new ZoneBundleResetResult { Success = false, Message = "No zones to reset." }); return false; } 5__3 = GetOnlineCharacterIds(); 5__4 = 5__2.ToHashSet(); <>8__1.removed = 0; <>2__current = ResetZoneObjectsAsync(5__4, 5__3, delegate(int value) { <>8__1.removed = value; }); <>1__state = 1; return true; case 1: <>1__state = -1; 5__5 = 0; <>7__wrap5 = 5__2.GetEnumerator(); <>1__state = -3; goto IL_01aa; case 2: <>1__state = -3; goto IL_01aa; case 3: <>1__state = -1; if (<>8__1.remainingWearNTear > 0) { <>2__current = ResetZoneObjectsAsync(5__4, 5__3, delegate(int value) { <>8__1.verificationRemoved = value; }); <>1__state = 4; return true; } goto IL_02cb; case 4: <>1__state = -1; <>8__1.removed += <>8__1.verificationRemoved; <>2__current = CountRemainingCreatorWearNTearAsync(5__4, 5__3, delegate(int value) { <>8__1.remainingWearNTear = value; }); <>1__state = 5; return true; case 5: <>1__state = -1; goto IL_02cb; case 6: { <>1__state = -1; Minimap instance = Minimap.instance; if (instance != null) { instance.UpdateLocationPins(1000f); } string text = $"Reset {5__2.Count} generated zone(s), removed {<>8__1.removed} ZDO(s)."; if (<>8__1.verificationRemoved > 0) { text += $" Verification pass removed {<>8__1.verificationRemoved} ZDO(s)."; _logger.LogWarning((object)text); } if (<>8__1.remainingWearNTear > 0) { text += $" {<>8__1.remainingWearNTear} creator WearNTear ZDO(s) still remain after reset."; _logger.LogWarning((object)text); } onComplete(new ZoneBundleResetResult { Success = (<>8__1.remainingWearNTear == 0), ZoneCount = 5__2.Count, RemovedCount = <>8__1.removed, RemainingWearNTearCount = <>8__1.remainingWearNTear, Message = text }); return false; } IL_02cb: instance2 = ClutterSystem.instance; if (instance2 != null) { instance2.ClearAll(); } <>2__current = RecalculateLoadedTerrainAsync(); <>1__state = 6; return true; IL_01aa: while (<>7__wrap5.MoveNext()) { ResetZoneSystemState(<>7__wrap5.Current); 5__5++; if (5__5 >= 8) { 5__5 = 0; <>2__current = null; <>1__state = 2; return true; } } <>m__Finally1(); <>7__wrap5 = default(List.Enumerator); <>8__1.verificationRemoved = 0; <>8__1.remainingWearNTear = 0; <>2__current = CountRemainingCreatorWearNTearAsync(5__4, 5__3, delegate(int value) { <>8__1.remainingWearNTear = value; }); <>1__state = 3; return true; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>7__wrap5).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__82 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public HashSet zones; public HashSet protectedCharacterIds; public Action onComplete; private HashSet 5__2; private List 5__3; private int 5__4; private int 5__5; private HashSet.Enumerator <>7__wrap5; private List.Enumerator <>7__wrap6; private ZDO 5__8; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__82(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if ((uint)(num - -4) <= 1u || num == 1) { try { if (num == -4 || num == 1) { try { } finally { <>m__Finally2(); } } } finally { <>m__Finally1(); } } 5__2 = null; 5__3 = null; <>7__wrap5 = default(HashSet.Enumerator); <>7__wrap6 = default(List.Enumerator); 5__8 = null; <>1__state = -2; } private bool MoveNext() { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) try { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -4; goto IL_00fe; } <>1__state = -1; 5__2 = new HashSet(); 5__3 = new List(); 5__4 = 0; 5__5 = 0; <>7__wrap5 = zones.GetEnumerator(); <>1__state = -3; goto IL_01a5; IL_01a5: if (<>7__wrap5.MoveNext()) { Vector2i current = <>7__wrap5.Current; 5__3.Clear(); ZDOMan.instance.FindObjects(current, 5__3); <>7__wrap6 = 5__3.GetEnumerator(); <>1__state = -4; goto IL_0183; } <>m__Finally1(); <>7__wrap5 = default(HashSet.Enumerator); ZoneBundleZdoHelper.FlushDestroyed(); onComplete(5__4); return false; IL_0183: if (<>7__wrap6.MoveNext()) { 5__8 = <>7__wrap6.Current; 5__5++; if (5__5 >= 1000) { ZoneBundleZdoHelper.FlushDestroyed(); 5__5 = 0; <>2__current = null; <>1__state = 1; return true; } goto IL_00fe; } <>m__Finally2(); <>7__wrap6 = default(List.Enumerator); goto IL_01a5; IL_00fe: if (5__8 != null && 5__8.IsValid() && 5__2.Add(5__8.m_uid) && zones.Contains(ZoneSystem.GetZone(5__8.GetPosition()))) { if (IsResettableZoneObject(5__8, zones, protectedCharacterIds)) { ZoneBundleZdoHelper.Destroy(5__8); 5__4++; } 5__8 = null; } goto IL_0183; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>7__wrap5).Dispose(); } private void <>m__Finally2() { <>1__state = -3; ((IDisposable)<>7__wrap6).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__74 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string tag; public Action onComplete; private <>c__DisplayClass74_0 <>8__1; private <>c__DisplayClass74_1 <>8__2; private List 5__2; private int 5__3; private int 5__4; private int 5__5; private List.Enumerator <>7__wrap5; private List.Enumerator <>7__wrap6; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__74(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { switch (<>1__state) { case -3: case 1: try { } finally { <>m__Finally1(); } break; case -4: case 4: try { } finally { <>m__Finally2(); } break; } <>8__1 = null; <>8__2 = null; 5__2 = null; <>7__wrap5 = default(List.Enumerator); <>7__wrap6 = default(List.Enumerator); <>1__state = -2; } private bool MoveNext() { //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0317: Unknown result type (might be due to invalid IL or missing references) bool result; try { switch (<>1__state) { default: result = false; goto end_IL_0000; case 0: { <>1__state = -1; <>8__1 = new <>c__DisplayClass74_0(); ZoneBundleManifest zoneBundleManifest; try { zoneBundleManifest = ZoneBundleSerialization.LoadManifest(GetManifestPath(tag)); } catch (Exception ex) { _logger.LogError((object)$"Zone bundle async archive restore failed: {ex}"); onComplete(ZoneBundleCommandResult.Fail(ex.Message)); result = false; goto end_IL_0000; } 5__2 = new List(); <>7__wrap5 = zoneBundleManifest.Bundles.GetEnumerator(); <>1__state = -3; goto IL_0143; } case 1: <>1__state = -3; goto IL_0143; case 2: <>1__state = -1; if (!string.IsNullOrWhiteSpace(<>8__1.readyError)) { _logger.LogError((object)("Zone bundle async archive restore failed: " + <>8__1.readyError)); onComplete(ZoneBundleCommandResult.Fail(<>8__1.readyError)); result = false; } else { <>8__1.terrainContext = null; <>8__1.contextError = ""; <>2__current = CreateAndValidateTerrainPlacementContextAsync(5__2, exactSource: true, 0f, delegate(TerrainPlacementContext? context, string error) { <>8__1.terrainContext = context; <>8__1.contextError = error; }); <>1__state = 3; result = true; } goto end_IL_0000; case 3: <>1__state = -1; if (string.IsNullOrWhiteSpace(<>8__1.contextError)) { 5__3 = 0; 5__4 = 0; 5__5 = 0; <>7__wrap6 = 5__2.GetEnumerator(); <>1__state = -4; break; } _logger.LogError((object)("Zone bundle async archive restore failed: " + <>8__1.contextError)); onComplete(ZoneBundleCommandResult.Fail(<>8__1.contextError)); result = false; goto end_IL_0000; case 4: { <>1__state = -4; 5__3 += <>8__2.stats.Removed; 5__4 += <>8__2.stats.Created; if (<>8__2.stats.TerrainApplied) { 5__5++; } <>8__2 = null; break; } IL_0143: if (<>7__wrap5.MoveNext()) { ZoneBundleManifestEntry current = <>7__wrap5.Current; Vector2i targetZone = ToVector2i(current.Zone); if (!TryLoadBundleFile(Path.Combine(GetTagDirectory(tag), current.File), out ZoneBundleFile bundle, out string reason)) { _logger.LogError((object)("Zone bundle async archive restore failed: " + reason)); onComplete(ZoneBundleCommandResult.Fail(reason)); result = false; <>m__Finally1(); } else { 5__2.Add(new LoadWorkItem(targetZone, bundle)); <>2__current = null; <>1__state = 1; result = true; } } else { <>m__Finally1(); <>7__wrap5 = default(List.Enumerator); <>8__1.readyError = ""; <>2__current = ValidateLoadReadyAsync(5__2, delegate(string value) { <>8__1.readyError = value; }); <>1__state = 2; result = true; } goto end_IL_0000; } if (<>7__wrap6.MoveNext()) { LoadWorkItem current2 = <>7__wrap6.Current; <>8__2 = new <>c__DisplayClass74_1(); <>8__2.stats = default(ZoneLoadStats); <>2__current = ApplyBundleToZoneAsync(current2.TargetZone, current2.Bundle, <>8__1.terrainContext, 0f, delegate(ZoneLoadStats value) { <>8__2.stats = value; }); <>1__state = 4; result = true; } else { <>m__Finally2(); <>7__wrap6 = default(List.Enumerator); onComplete(ZoneBundleCommandResult.Ok($"Restored {5__2.Count} archived zone bundle(s) for tag '{tag}' " + $"(removed: {5__3}, created: {5__4}, terrain: {5__5}/{5__2.Count}).")); result = false; } end_IL_0000:; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>7__wrap5).Dispose(); } private void <>m__Finally2() { <>1__state = -1; ((IDisposable)<>7__wrap6).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__38 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public IEnumerable sourceZones; public Action onComplete; public string tag; private <>c__DisplayClass38_0 <>8__1; private <>c__DisplayClass38_1 <>8__2; private List 5__2; private string 5__3; private ZoneBundleManifest 5__4; private int 5__5; private int 5__6; private int 5__7; private int 5__8; private int 5__9; private List.Enumerator <>7__wrap9; private Vector2i 5__11; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__38(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 2) <= 1u) { try { } finally { <>m__Finally1(); } } <>8__1 = null; <>8__2 = null; 5__2 = null; 5__3 = null; 5__4 = null; <>7__wrap9 = default(List.Enumerator); <>1__state = -2; } private bool MoveNext() { //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Unknown result type (might be due to invalid IL or missing references) //IL_0470: Unknown result type (might be due to invalid IL or missing references) bool result2; try { switch (<>1__state) { default: result2 = false; goto end_IL_0000; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass38_0(); 5__2 = (from zone in sourceZones.Distinct() orderby zone.y, zone.x select zone).ToList(); if (5__2.Count == 0) { onComplete(new ZoneBundleArchiveResult { Success = false, Tag = tag, Message = "No zones to save." }); result2 = false; } else { ZoneBundleRange sourceRange = CreateRange(5__2.Min((Vector2i zone) => zone.x), 5__2.Min((Vector2i zone) => zone.y), 5__2.Max((Vector2i zone) => zone.x), 5__2.Max((Vector2i zone) => zone.y)); 5__3 = GetManifestPath(tag); 5__4 = new ZoneBundleManifest { Tag = tag, World = GetWorldName(), SavedAt = ZoneSaviorTimestamp.Now(), SourceRange = sourceRange }; <>8__1.sourceAnchor = new ZoneBundleTerrain.TerrainSourceAnchor(float.NaN); <>2__current = ZoneBundleTerrainApplier.ComputeSupportAnchorAsync(5__2, delegate(ZoneBundleTerrain.TerrainSourceAnchor anchor) { <>8__1.sourceAnchor = anchor; }); <>1__state = 1; result2 = true; } goto end_IL_0000; case 1: <>1__state = -1; 5__5 = 0; 5__6 = 0; 5__7 = 0; 5__8 = 0; 5__9 = 0; <>7__wrap9 = 5__2.GetEnumerator(); <>1__state = -3; goto IL_055d; case 2: <>1__state = -3; if (<>8__2.capture == null || !<>8__2.capture.Success || <>8__2.capture.Bundle == null) { onComplete(new ZoneBundleArchiveResult { Success = false, Tag = tag, ManifestPath = 5__3, ZoneCount = 5__4.Bundles.Count, EntryCount = 5__5, MonsterCount = 5__6, TerrainLoaded = 5__7, TerrainCaptured = 5__8, Message = "save failed: " + (<>8__2.capture?.ErrorMessage ?? "capture coroutine did not return a result") }); result2 = false; break; } try { ZoneBundleFile bundle = <>8__2.capture.Bundle; int entryCount = <>8__2.capture.EntryCount; int monsterCount = <>8__2.capture.MonsterCount; ZoneBundleTerrainCaptureState terrainState = <>8__2.capture.TerrainState; 5__5 += entryCount; 5__6 += monsterCount; if (terrainState != 0) { 5__7++; } if (terrainState == ZoneBundleTerrainCaptureState.Contacts) { 5__8++; } string bundlePath = GetBundlePath(tag, ++5__9); ZoneBundleSerialization.SaveBundle(bundlePath, bundle); 5__4.Bundles.Add(new ZoneBundleManifestEntry { Zone = ToModel(5__11), File = Path.GetFileName(bundlePath), SourceZoneCreators = CloneSourceZoneCreators(bundle.SourceZoneCreators) }); } catch (Exception ex) { onComplete(new ZoneBundleArchiveResult { Success = false, Tag = tag, ManifestPath = 5__3, ZoneCount = 5__4.Bundles.Count, EntryCount = 5__5, MonsterCount = 5__6, TerrainLoaded = 5__7, TerrainCaptured = 5__8, Message = "save failed: " + ex.Message }); result2 = false; break; } <>2__current = null; <>1__state = 3; result2 = true; goto end_IL_0000; case 3: { <>1__state = -3; <>8__2 = null; goto IL_055d; } IL_055d: if (<>7__wrap9.MoveNext()) { 5__11 = <>7__wrap9.Current; <>8__2 = new <>c__DisplayClass38_1(); <>8__2.capture = null; <>2__current = CaptureBundleAsync(5__11, tag, <>8__1.sourceAnchor, delegate(CaptureBundleResult result) { <>8__2.capture = result; }); <>1__state = 2; result2 = true; } else { <>m__Finally1(); <>7__wrap9 = default(List.Enumerator); try { UpdateManifestSourceZoneCreators(5__4); ZoneBundleSerialization.SaveManifest(5__3, 5__4); } catch (Exception ex2) { onComplete(new ZoneBundleArchiveResult { Success = false, Tag = tag, ManifestPath = 5__3, ZoneCount = 5__4.Bundles.Count, EntryCount = 5__5, MonsterCount = 5__6, TerrainLoaded = 5__7, TerrainCaptured = 5__8, Message = "manifest save failed: " + ex2.Message }); result2 = false; goto end_IL_0000; } onComplete(new ZoneBundleArchiveResult { Success = true, Tag = tag, ManifestPath = 5__3, ZoneCount = 5__4.Bundles.Count, EntryCount = 5__5, MonsterCount = 5__6, TerrainLoaded = 5__7, TerrainCaptured = 5__8, Message = $"Saved {5__4.Bundles.Count} zone bundle(s) for tag '{tag}' to '{Path.GetDirectoryName(5__3)}' " + $"(entries: {5__5}, monsters: {5__6}, terrain contacts: {5__8}/{5__4.Bundles.Count}, terrain loaded: {5__7}/{5__4.Bundles.Count}, mode: SupportFill)." }); result2 = false; } goto end_IL_0000; } <>m__Finally1(); end_IL_0000:; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result2; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>7__wrap9).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__55 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public IEnumerable work; public Action onComplete; private <>c__DisplayClass55_0 <>8__1; private List.Enumerator <>7__wrap1; private LoadWorkItem 5__3; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__55(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 1) <= 1u) { try { } finally { <>m__Finally1(); } } <>8__1 = null; <>7__wrap1 = default(List.Enumerator); 5__3 = default(LoadWorkItem); <>1__state = -2; } private bool MoveNext() { //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) bool result; try { switch (<>1__state) { default: result = false; goto end_IL_0000; case 0: <>1__state = -1; <>7__wrap1 = work.ToList().GetEnumerator(); <>1__state = -3; goto IL_0169; case 1: <>1__state = -3; if (<>8__1.requiresTerrainApply && !ZoneBundleTerrainApplier.CanApply(5__3.TargetZone)) { onComplete($"Target zone ({5__3.TargetZone.x},{5__3.TargetZone.y}) is not loaded for terrain overwrite. Move closer and try again."); result = false; break; } <>2__current = null; <>1__state = 2; result = true; goto end_IL_0000; case 2: { <>1__state = -3; <>8__1 = null; 5__3 = default(LoadWorkItem); goto IL_0169; } IL_0169: if (<>7__wrap1.MoveNext()) { 5__3 = <>7__wrap1.Current; <>8__1 = new <>c__DisplayClass55_0(); try { EnsureSupportFillBundle(5__3.Bundle); } catch (Exception ex) { onComplete(ex.Message); result = false; break; } <>8__1.requiresTerrainApply = false; <>2__current = RequiresTerrainApplyAsync(5__3.Bundle, delegate(bool value) { <>8__1.requiresTerrainApply = value; }); <>1__state = 1; result = true; } else { <>m__Finally1(); <>7__wrap1 = default(List.Enumerator); onComplete(""); result = false; } goto end_IL_0000; } <>m__Finally1(); end_IL_0000:; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>7__wrap1).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private const string SaveOperation = "zs_savezone"; private const string LoadOperation = "zs_loadzone"; private const string LoadArchiveOperation = "zs_loadarchive"; private const string RequestRpcName = "sighsorry.ZoneSavior_ZoneBundleRequest"; private const string ResultRpcName = "sighsorry.ZoneSavior_ZoneBundleResult"; private const string WearNTearSanitize = "wearntear-v1"; private const string MonsterSanitize = "monster-v1"; private const string TamedMonsterSanitize = "tamed-monster-v1"; private const int CaptureBatchSize = 1000; private const int ResetBatchSize = 1000; private const int TerrainRecalcBatchSize = 8; private static readonly Regex CommandPattern = new Regex("^\\s*(\\([^)]+\\))\\s+([^\\s]+)(?:\\s+to\\s+(\\([^)]+\\)))?\\s*$", RegexOptions.IgnoreCase | RegexOptions.Compiled); private static readonly Regex LoadArchivePattern = new Regex("^\\s*([^\\s]+)(?:\\s+to\\s+(\\([^)]+\\)))?\\s*$", RegexOptions.IgnoreCase | RegexOptions.Compiled); private static readonly Regex YOffsetEqualsOptionPattern = new Regex("(?:^|\\s)(?:offset|yoffset|y-offset)\\s*=\\s*([+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+))", RegexOptions.IgnoreCase | RegexOptions.Compiled); private static readonly Regex YOffsetFlagOptionPattern = new Regex("(?:^|\\s)--(?:offset|yoffset|y-offset)\\s+([+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+))", RegexOptions.IgnoreCase | RegexOptions.Compiled); private static readonly Regex RangePattern = new Regex("^\\(\\s*([^,]+)\\s*,\\s*([^)]+)\\s*\\)$", RegexOptions.Compiled); private static readonly Dictionary EmptyParameters = new Dictionary(); private static ManualLogSource _logger = null; private static bool _initialized; private static readonly ZoneRpcRegistrar RpcRegistrar = new ZoneRpcRegistrar(); public static void Initialize(ManualLogSource logger) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown if (!_initialized) { _initialized = true; _logger = logger; object obj = <>O.<0>__HandleSaveZoneCommand; if (obj == null) { ConsoleEvent val = HandleSaveZoneCommand; <>O.<0>__HandleSaveZoneCommand = val; obj = (object)val; } new ConsoleCommand("zs_savezone", "(x~x,z~z) tag - Saves SupportFill zone bundles.", (ConsoleEvent)obj, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj2 = <>O.<1>__HandleLoadZoneCommand; if (obj2 == null) { ConsoleEvent val2 = HandleLoadZoneCommand; <>O.<1>__HandleLoadZoneCommand = val2; obj2 = (object)val2; } new ConsoleCommand("zs_loadzone", "(x,z) or (x~x,z~z) tag [to (x,z)] [offset=Y] - Loads saved source zone bundles.", (ConsoleEvent)obj2, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj3 = <>O.<2>__HandleLoadArchiveCommand; if (obj3 == null) { ConsoleEvent val3 = HandleLoadArchiveCommand; <>O.<2>__HandleLoadArchiveCommand = val3; obj3 = (object)val3; } new ConsoleCommand("zs_loadarchive", "tag [to (x,z)] [offset=Y] - Loads all zones listed in a saved manifest, preserving non-rectangular shape.", (ConsoleEvent)obj3, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); RegisterRpcs(); } } internal static void RegisterRpcs() { RpcRegistrar.EnsureRegistered(delegate(ZRoutedRpc routedRpc) { routedRpc.Register("sighsorry.ZoneSavior_ZoneBundleRequest", (Action)RPC_HandleRequest); routedRpc.Register("sighsorry.ZoneSavior_ZoneBundleResult", (Action)RPC_HandleResult); }); } private static void HandleSaveZoneCommand(ConsoleEventArgs args) { EnsureCommandAllowed(); DispatchRequest(ParseRequest(args.ArgsAll, "zs_savezone", requireSingleZone: false, requireTarget: false), args.Context); } private static void HandleLoadZoneCommand(ConsoleEventArgs args) { EnsureCommandAllowed(); DispatchRequest(ParseRequest(args.ArgsAll, "zs_loadzone", requireSingleZone: false, requireTarget: true), args.Context); } private static void HandleLoadArchiveCommand(ConsoleEventArgs args) { EnsureCommandAllowed(); DispatchRequest(ParseArchiveRequest(args.ArgsAll), args.Context); } private static void DispatchRequest(ZoneBundleCommandRequest request, Terminal context) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown Terminal context2 = context; if (ZNet.instance.IsServer()) { StartRequest(request, delegate(ZoneBundleCommandResult result) { ShowResult(result, context2); }); return; } RegisterRpcs(); ZPackage val = new ZPackage(); val.Write(ZoneBundleSerialization.Serialize(request)); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), "sighsorry.ZoneSavior_ZoneBundleRequest", new object[1] { val }); context2.AddString(request.Operation + " request sent to server."); } private static void RPC_HandleRequest(long sender, ZPackage package) { if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer()) { return; } try { if (!IsAuthorizedSender(sender)) { SendResult(sender, ZoneBundleCommandResult.Fail("Admin only.")); return; } StartRequest(ZoneBundleSerialization.Deserialize(package.ReadString()), delegate(ZoneBundleCommandResult result) { SendResult(sender, result); }); } catch (Exception ex) { _logger.LogError((object)$"Zone bundle RPC failed: {ex}"); SendResult(sender, ZoneBundleCommandResult.Fail(ex.Message)); } } private static void SendResult(long target, ZoneBundleCommandResult result) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(ZoneBundleSerialization.Serialize(result)); ZRoutedRpc.instance.InvokeRoutedRPC(target, "sighsorry.ZoneSavior_ZoneBundleResult", new object[1] { val }); } private static void RPC_HandleResult(long sender, ZPackage package) { if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer()) { ShowResult(ZoneBundleSerialization.Deserialize(package.ReadString()), (Terminal?)(object)Console.instance); } } private static void StartRequest(ZoneBundleCommandRequest request, Action onComplete) { if (request.Operation == "zs_savezone" && (Object)(object)ZoneSaviorPlugin.Instance != (Object)null) { ((MonoBehaviour)ZoneSaviorPlugin.Instance).StartCoroutine(ExecuteSaveRequestAsync(request, onComplete)); } else if ((request.Operation == "zs_loadzone" || request.Operation == "zs_loadarchive") && (Object)(object)ZoneSaviorPlugin.Instance != (Object)null) { ((MonoBehaviour)ZoneSaviorPlugin.Instance).StartCoroutine(ExecuteLoadRequestAsync(request, onComplete)); } else { onComplete(ExecuteRequest(request)); } } [IteratorStateMachine(typeof(d__30))] private static IEnumerator ExecuteSaveRequestAsync(ZoneBundleCommandRequest request, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__30(0) { request = request, onComplete = onComplete }; } [IteratorStateMachine(typeof(d__31))] private static IEnumerator ExecuteLoadRequestAsync(ZoneBundleCommandRequest request, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__31(0) { request = request, onComplete = onComplete }; } private static ZoneBundleCommandResult ExecuteRequest(ZoneBundleCommandRequest request) { try { return request.Operation switch { "zs_savezone" => SaveRange(request), "zs_loadzone" => LoadZoneRequest(request), "zs_loadarchive" => LoadArchiveManifest(request), _ => ZoneBundleCommandResult.Fail("Unsupported operation '" + request.Operation + "'."), }; } catch (Exception ex) { _logger.LogError((object)$"Zone bundle command '{request.Operation}' failed: {ex}"); return ZoneBundleCommandResult.Fail(ex.Message); } } private static ZoneBundleCommandResult SaveRange(ZoneBundleCommandRequest request) { ZoneBundleArchiveResult zoneBundleArchiveResult = SaveZones(EnumerateZones(request.SourceRange), request.Tag); if (!zoneBundleArchiveResult.Success) { return ZoneBundleCommandResult.Fail(zoneBundleArchiveResult.Message); } return ZoneBundleCommandResult.Ok(zoneBundleArchiveResult.Message); } private static ZoneBundleCommandResult LoadZoneRequest(ZoneBundleCommandRequest request) { if (!IsSingleRange(request.SourceRange)) { return LoadZoneRange(request); } return LoadSingleZone(request); } [IteratorStateMachine(typeof(d__35))] private static IEnumerator LoadZoneRequestAsync(ZoneBundleCommandRequest request, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__35(0) { request = request, onComplete = onComplete }; } private static bool IsSingleRange(ZoneBundleRange range) { if (range.MinX == range.MaxX) { return range.MinZ == range.MaxZ; } return false; } internal static ZoneBundleArchiveResult SaveZones(IEnumerable sourceZones, string tag) { //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) List list = (from zone in sourceZones.Distinct() orderby zone.y, zone.x select zone).ToList(); if (list.Count == 0) { return new ZoneBundleArchiveResult { Success = false, Tag = tag, Message = "No zones to save." }; } ZoneBundleRange sourceRange = CreateRange(list.Min((Vector2i zone) => zone.x), list.Min((Vector2i zone) => zone.y), list.Max((Vector2i zone) => zone.x), list.Max((Vector2i zone) => zone.y)); string manifestPath = GetManifestPath(tag); ZoneBundleManifest zoneBundleManifest = new ZoneBundleManifest { Tag = tag, World = GetWorldName(), SavedAt = ZoneSaviorTimestamp.Now(), SourceRange = sourceRange }; ZoneBundleTerrain.TerrainSourceAnchor sourceAnchor = ZoneBundleTerrainApplier.ComputeSupportAnchor(list); int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; int num5 = 0; foreach (Vector2i item in list) { int entries; int monsters; ZoneBundleTerrainCaptureState terrainState; ZoneBundleFile zoneBundleFile = CaptureBundle(item, tag, sourceAnchor, out entries, out monsters, out terrainState); num += entries; num2 += monsters; if (terrainState != 0) { num3++; } if (terrainState == ZoneBundleTerrainCaptureState.Contacts) { num4++; } string bundlePath = GetBundlePath(tag, ++num5); ZoneBundleSerialization.SaveBundle(bundlePath, zoneBundleFile); zoneBundleManifest.Bundles.Add(new ZoneBundleManifestEntry { Zone = ToModel(item), File = Path.GetFileName(bundlePath), SourceZoneCreators = CloneSourceZoneCreators(zoneBundleFile.SourceZoneCreators) }); } UpdateManifestSourceZoneCreators(zoneBundleManifest); ZoneBundleSerialization.SaveManifest(manifestPath, zoneBundleManifest); ZoneBundleArchiveResult zoneBundleArchiveResult = new ZoneBundleArchiveResult(); zoneBundleArchiveResult.Success = true; zoneBundleArchiveResult.Tag = tag; zoneBundleArchiveResult.ManifestPath = manifestPath; zoneBundleArchiveResult.ZoneCount = zoneBundleManifest.Bundles.Count; zoneBundleArchiveResult.EntryCount = num; zoneBundleArchiveResult.MonsterCount = num2; zoneBundleArchiveResult.TerrainLoaded = num3; zoneBundleArchiveResult.TerrainCaptured = num4; zoneBundleArchiveResult.Message = $"Saved {zoneBundleManifest.Bundles.Count} zone bundle(s) for tag '{tag}' to '{Path.GetDirectoryName(manifestPath)}' " + $"(entries: {num}, monsters: {num2}, terrain contacts: {num4}/{zoneBundleManifest.Bundles.Count}, terrain loaded: {num3}/{zoneBundleManifest.Bundles.Count}, mode: SupportFill)."; return zoneBundleArchiveResult; } [IteratorStateMachine(typeof(d__38))] internal static IEnumerator SaveZonesAsync(IEnumerable sourceZones, string tag, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__38(0) { sourceZones = sourceZones, tag = tag, onComplete = onComplete }; } private static void UpdateManifestSourceZoneCreators(ZoneBundleManifest manifest) { Dictionary dictionary = new Dictionary(); foreach (ZoneBundleCreatorPlayer item in manifest.Bundles.SelectMany((ZoneBundleManifestEntry entry) => entry.SourceZoneCreators)) { if (item.PlayerId != 0L && !dictionary.ContainsKey(item.PlayerId)) { dictionary[item.PlayerId] = CloneCreatorPlayer(item); } } manifest.SourceZoneCreators = dictionary.Values.OrderBy((ZoneBundleCreatorPlayer player) => player.PlayerId).ToList(); } private static void AddCreatorPlayer(Dictionary creatorNames, long playerId, string observedName) { if (playerId != 0L) { string value = NormalizeCreatorString(observedName) ?? ""; if (!creatorNames.TryGetValue(playerId, out string value2) || string.IsNullOrWhiteSpace(value2)) { creatorNames[playerId] = value; } } } private static List BuildSourceZoneCreators(IReadOnlyDictionary creatorNames) { IReadOnlyDictionary creatorNames2 = creatorNames; string value; return (from playerId in creatorNames2.Keys where playerId != 0 orderby playerId select BuildCreatorPlayer(playerId, creatorNames2.TryGetValue(playerId, out value) ? value : "")).ToList(); } private static ZoneBundleCreatorPlayer BuildCreatorPlayer(long playerId, string observedName) { return new ZoneBundleCreatorPlayer { PlayerId = playerId, Name = ResolveCreatorName(playerId, observedName), PlatformId = ResolveCreatorPlatformId(playerId) }; } private static List CloneSourceZoneCreators(IEnumerable players) { return (from player in players where player.PlayerId != 0 orderby player.PlayerId select player).Select(CloneCreatorPlayer).ToList(); } private static ZoneBundleCreatorPlayer CloneCreatorPlayer(ZoneBundleCreatorPlayer player) { return new ZoneBundleCreatorPlayer { PlayerId = player.PlayerId, Name = NormalizeCreatorString(player.Name ?? ""), PlatformId = NormalizeCreatorString(player.PlatformId ?? "") }; } private static string? ResolveCreatorName(long playerId, string observedName) { string text = NormalizeCreatorString(observedName); if (text != null) { return text; } if (!AutoArchiveStore.TryGetPlayerRecord(playerId, out PlayerActivityRecord record)) { return null; } return NormalizeCreatorString(record.Names.LastOrDefault((string candidate) => !string.IsNullOrWhiteSpace(candidate) && !string.Equals(candidate, "unknown", StringComparison.OrdinalIgnoreCase) && !string.Equals(candidate, "manual", StringComparison.OrdinalIgnoreCase)) ?? ""); } private static string? ResolveCreatorPlatformId(long playerId) { if (!AutoArchiveStore.TryGetPlayerRecord(playerId, out PlayerActivityRecord record)) { return null; } string text = NormalizeCreatorString(record.PlatformId); if (text == null || text.StartsWith("unknown:", StringComparison.OrdinalIgnoreCase) || text.StartsWith("manual:", StringComparison.OrdinalIgnoreCase)) { return null; } return text; } private static string? NormalizeCreatorString(string value) { string text = value.Trim(); if (!string.IsNullOrWhiteSpace(text)) { return text; } return null; } private static ZoneBundleCommandResult LoadSingleZone(ZoneBundleCommandRequest request) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) Vector2i val = ToSingleSourceZone(request.SourceRange); Vector2i val2 = ToVector2i(request.TargetZone); ZoneBundleFile bundle = ZoneBundleSerialization.LoadBundle(GetBundlePathFromManifest(request.Tag, val)); List work = new List(1) { new LoadWorkItem(val2, bundle) }; ValidateLoadReady(work); TerrainPlacementContext terrainContext = CreateAndValidateTerrainPlacementContext(work, exactSource: false, request.YOffset); ZoneLoadStats zoneLoadStats = ApplyBundleToZone(val2, bundle, terrainContext, request.YOffset); return ZoneBundleCommandResult.Ok($"Loaded {request.Tag} source zone ({val.x},{val.y}) into target zone ({val2.x},{val2.y}) " + string.Format("(removed: {0}, created: {1}, terrain: {2}, mode: SupportFill, yOffset: {3}).", zoneLoadStats.Removed, zoneLoadStats.Created, zoneLoadStats.TerrainApplied ? "yes" : "no", Round(request.YOffset))); } [IteratorStateMachine(typeof(d__49))] private static IEnumerator LoadSingleZoneAsync(ZoneBundleCommandRequest request, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__49(0) { request = request, onComplete = onComplete }; } private static ZoneBundleCommandResult LoadZoneRange(ZoneBundleCommandRequest request) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) Dictionary dictionary = ZoneBundleSerialization.LoadManifest(GetManifestPath(request.Tag)).Bundles.ToDictionary((ZoneBundleManifestEntry entry) => ToVector2i(entry.Zone)); Vector2i val = ToVector2i(request.TargetZone); int num = val.x - request.SourceRange.MinX; int num2 = val.y - request.SourceRange.MinZ; List list = new List(); foreach (Vector2i item in EnumerateZones(request.SourceRange)) { if (!dictionary.TryGetValue(item, out var value)) { throw new FileNotFoundException($"Manifest for tag '{request.Tag}' does not contain source zone ({item.x},{item.y})."); } ZoneBundleFile bundle = ZoneBundleSerialization.LoadBundle(Path.Combine(GetTagDirectory(request.Tag), value.File)); list.Add(new LoadWorkItem(new Vector2i(item.x + num, item.y + num2), bundle)); } ValidateLoadReady(list); TerrainPlacementContext terrainContext = CreateAndValidateTerrainPlacementContext(list, exactSource: false, request.YOffset); int num3 = 0; int num4 = 0; int num5 = 0; foreach (LoadWorkItem item2 in list) { ZoneLoadStats zoneLoadStats = ApplyBundleToZone(item2.TargetZone, item2.Bundle, terrainContext, request.YOffset); num3 += zoneLoadStats.Removed; num4 += zoneLoadStats.Created; if (zoneLoadStats.TerrainApplied) { num5++; } } return ZoneBundleCommandResult.Ok($"Batch loaded {list.Count} zone bundle(s) for tag '{request.Tag}' to target start ({val.x},{val.y}) " + $"(removed: {num3}, created: {num4}, terrain: {num5}/{list.Count}, mode: SupportFill, yOffset: {Round(request.YOffset)})."); } [IteratorStateMachine(typeof(d__51))] private static IEnumerator LoadZoneRangeAsync(ZoneBundleCommandRequest request, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__51(0) { request = request, onComplete = onComplete }; } private static ZoneBundleCommandResult LoadArchiveManifest(ZoneBundleCommandRequest request) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) ZoneBundleManifest zoneBundleManifest = ZoneBundleSerialization.LoadManifest(GetManifestPath(request.Tag)); if (zoneBundleManifest.Bundles.Count == 0) { return ZoneBundleCommandResult.Fail("Manifest for tag '" + request.Tag + "' contains no zone bundles."); } List source = zoneBundleManifest.Bundles.Select((ZoneBundleManifestEntry entry) => ToVector2i(entry.Zone)).ToList(); Vector2i val = ToVector2i(request.TargetZone); int num = source.Min((Vector2i zone) => zone.x); int num2 = source.Min((Vector2i zone) => zone.y); int num3 = val.x - num; int num4 = val.y - num2; List list = new List(); foreach (ZoneBundleManifestEntry bundle2 in zoneBundleManifest.Bundles) { Vector2i val2 = ToVector2i(bundle2.Zone); ZoneBundleFile bundle = ZoneBundleSerialization.LoadBundle(Path.Combine(GetTagDirectory(request.Tag), bundle2.File)); list.Add(new LoadWorkItem(new Vector2i(val2.x + num3, val2.y + num4), bundle)); } ValidateLoadReady(list); TerrainPlacementContext terrainContext = CreateAndValidateTerrainPlacementContext(list, exactSource: false, request.YOffset); int num5 = 0; int num6 = 0; int num7 = 0; foreach (LoadWorkItem item in list) { ZoneLoadStats zoneLoadStats = ApplyBundleToZone(item.TargetZone, item.Bundle, terrainContext, request.YOffset); num5 += zoneLoadStats.Removed; num6 += zoneLoadStats.Created; if (zoneLoadStats.TerrainApplied) { num7++; } } return ZoneBundleCommandResult.Ok($"Loaded archive '{request.Tag}' as {list.Count} manifest zone(s) to target start ({val.x},{val.y}) " + $"(removed: {num5}, created: {num6}, terrain: {num7}/{list.Count}, mode: SupportFill, yOffset: {Round(request.YOffset)})."); } [IteratorStateMachine(typeof(d__53))] private static IEnumerator LoadArchiveManifestAsync(ZoneBundleCommandRequest request, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__53(0) { request = request, onComplete = onComplete }; } private static void ValidateLoadReady(IEnumerable work) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) foreach (LoadWorkItem item in work) { EnsureSupportFillBundle(item.Bundle); if (RequiresTerrainApply(item.Bundle) && !ZoneBundleTerrainApplier.CanApply(item.TargetZone)) { throw new InvalidOperationException($"Target zone ({item.TargetZone.x},{item.TargetZone.y}) is not loaded for terrain overwrite. Move closer and try again."); } } } [IteratorStateMachine(typeof(d__55))] private static IEnumerator ValidateLoadReadyAsync(IEnumerable work, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__55(0) { work = work, onComplete = onComplete }; } private static TerrainPlacementContext? CreateTerrainPlacementContext(IEnumerable work, bool exactSource) { List list = work.ToList(); if (list.Count == 0) { return null; } if (exactSource) { return ZoneBundleTerrainApplier.CreateExactContext(list.Min((LoadWorkItem item) => item.Bundle.SourceBaseY), list.Select((LoadWorkItem item) => item.TargetZone)); } return ZoneBundleTerrainApplier.CreateSupportFillPlacementContext(list.Select((LoadWorkItem item) => new TerrainSupportTarget { Zone = item.TargetZone, SourceBaseY = item.Bundle.SourceBaseY, Entries = item.Bundle.Entries, ContactsCaptured = item.Bundle.TerrainContactsCaptured, Contacts = item.Bundle.TerrainContacts })); } private static TerrainPlacementContext? CreateAndValidateTerrainPlacementContext(IEnumerable work, bool exactSource, float yOffset) { List work2 = work.ToList(); TerrainPlacementContext terrainPlacementContext = CreateTerrainPlacementContext(work2, exactSource); ApplyYOffset(terrainPlacementContext, yOffset); ValidateTerrainPlacementContext(work2, terrainPlacementContext); return terrainPlacementContext; } [IteratorStateMachine(typeof(d__58))] private static IEnumerator CreateAndValidateTerrainPlacementContextAsync(IEnumerable work, bool exactSource, float yOffset, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__58(0) { work = work, exactSource = exactSource, yOffset = yOffset, onComplete = onComplete }; } private static void ValidateTerrainPlacementContext(IReadOnlyCollection work, TerrainPlacementContext? terrainContext) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) if (!work.Any((LoadWorkItem item) => RequiresTerrainApply(item.Bundle))) { return; } if (terrainContext == null) { throw new InvalidOperationException("Zone bundle terrain support placement could not be resolved. Load aborted before overwriting target zones."); } bool flag = false; foreach (LoadWorkItem item in work) { if (RequiresTerrainApply(item.Bundle) && ZoneBundleTerrainApplier.HasApplicableSupportFill(item.TargetZone, item.Bundle.Entries, item.Bundle.TerrainContacts, item.Bundle.TerrainContactsCaptured, terrainContext)) { flag = true; break; } } if (flag) { return; } throw new InvalidOperationException("Zone bundle terrain support placement produced no usable terrain support points. Load aborted before overwriting target zones."); } private static bool IsSupportFillBundle(ZoneBundleFile bundle) { return string.Equals(bundle.TerrainMode, ZoneBundleTerrainApplier.SupportFillMode, StringComparison.Ordinal); } private static bool UsesRelativeY(ZoneBundleFile bundle) { return IsSupportFillBundle(bundle); } private static bool RequiresTerrainApply(ZoneBundleFile bundle) { if (!IsSupportFillBundle(bundle)) { return false; } if (!HasSavedTerrainContacts(bundle)) { return HasWearNTearEntries(bundle); } return true; } [IteratorStateMachine(typeof(d__63))] private static IEnumerator RequiresTerrainApplyAsync(ZoneBundleFile bundle, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__63(0) { bundle = bundle, onComplete = onComplete }; } [IteratorStateMachine(typeof(d__64))] private static IEnumerator HasWearNTearEntriesAsync(ZoneBundleFile bundle, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__64(0) { bundle = bundle, onComplete = onComplete }; } private static void EnsureSupportFillBundle(ZoneBundleFile bundle) { if (IsSupportFillBundle(bundle)) { return; } string text = (string.IsNullOrWhiteSpace(bundle.TerrainMode) ? "unknown" : bundle.TerrainMode); throw new InvalidOperationException("Unsupported zone bundle terrain mode '" + text + "'. Re-save the zone with the current SupportFill format."); } private static ZoneBundleFile CaptureBundle(Vector2i zone, string tag, ZoneBundleTerrain.TerrainSourceAnchor sourceAnchor, out int entries, out int monsters, out ZoneBundleTerrainCaptureState terrainState) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_0324: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_028a: Unknown result type (might be due to invalid IL or missing references) Vector3 zonePos = ZoneSystem.GetZonePos(zone); bool flag = !float.IsNaN(sourceAnchor.BaseWorldY); List list = new List(); Dictionary creatorNames = new Dictionary(); List list2 = new List(); ZDOMan.instance.FindObjects(zone, list2); int num = 0; int num2 = 0; foreach (ZDO item in list2) { if (item != null && item.IsValid() && TryClassify(item, out SaveEntryKind kind, out GameObject prefab)) { bool flag2 = (Object)(object)prefab.GetComponent() != (Object)null; bool flag3 = kind == SaveEntryKind.Monster; long num3 = (flag2 ? item.GetLong(ZDOVars.s_creator, 0L) : 0); string text = (flag2 ? item.GetString(ZDOVars.s_creatorName, "") : ""); AddCreatorPlayer(creatorNames, num3, text); if ((!flag2 || ZoneBlueprintCommands.HasBuildRecipe(prefab)) && (ZoneBundleTerrainApplier.IsSupportWearNTear(item, zone, out GameObject _) || flag3)) { ZoneBundleZdoData zoneBundleZdoData = new ZoneBundleZdoData(item); string text2 = ((kind == SaveEntryKind.Monster) ? "monster-v1" : ((!flag2) ? "" : "wearntear-v1")); string sanitize = text2; SanitizeForSave(kind, zoneBundleZdoData, sanitize); Vector3 position = item.m_position; Quaternion rotation = item.GetRotation(); Vector3 val = ReadScale(item, prefab); List list3 = list; ZoneBundleEntry zoneBundleEntry = new ZoneBundleEntry(); text2 = ((kind != SaveEntryKind.Monster) ? $"s_{++num:D4}" : $"m_{++num2:D4}"); zoneBundleEntry.SaveId = text2; string kind2 = ((kind != SaveEntryKind.Monster) ? "static" : "monster"); zoneBundleEntry.Kind = kind2; zoneBundleEntry.Prefab = Utils.GetPrefabName(prefab); zoneBundleEntry.LocalPos = new float[3] { Round(position.x - zonePos.x), Round(flag ? (position.y - sourceAnchor.BaseWorldY) : position.y), Round(position.z - zonePos.z) }; zoneBundleEntry.Rot = new float[4] { Round(rotation.x), Round(rotation.y), Round(rotation.z), Round(rotation.w) }; zoneBundleEntry.Scale = new float[3] { Round(val.x), Round(val.y), Round(val.z) }; zoneBundleEntry.CreatorPlayerId = num3; zoneBundleEntry.CreatorName = NormalizeCreatorString(text); zoneBundleEntry.Data = zoneBundleZdoData.GetBase64(EmptyParameters); zoneBundleEntry.Sanitize = sanitize; list3.Add(zoneBundleEntry); } } } bool contactsCaptured; List list4 = ZoneBundleTerrainApplier.CaptureSupportContacts(zone, sourceAnchor.BaseWorldY, list, out contactsCaptured); terrainState = GetTerrainCaptureState(contactsCaptured, list4.Count); ZoneBundleFile result = new ZoneBundleFile { Tag = tag, SourceZone = ToModel(zone), TerrainMode = ZoneBundleTerrainApplier.SupportFillMode, SourceBaseY = (flag ? sourceAnchor.BaseWorldY : 0f), TerrainCaptureState = terrainState, TerrainContactsCaptured = contactsCaptured, TerrainContacts = list4, SourceZoneCreators = BuildSourceZoneCreators(creatorNames), Entries = list.OrderBy((ZoneBundleEntry entry) => entry.Kind, StringComparer.Ordinal).ThenBy((ZoneBundleEntry entry) => entry.Prefab, StringComparer.Ordinal).ThenBy((ZoneBundleEntry entry) => entry.LocalPos[0]) .ThenBy((ZoneBundleEntry entry) => entry.LocalPos[2]) .ThenBy((ZoneBundleEntry entry) => entry.LocalPos[1]) .ToList() }; entries = list.Count; monsters = num2; return result; } [IteratorStateMachine(typeof(d__67))] private static IEnumerator CaptureBundleAsync(Vector2i zone, string tag, ZoneBundleTerrain.TerrainSourceAnchor sourceAnchor, Action onComplete) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__67(0) { zone = zone, tag = tag, sourceAnchor = sourceAnchor, onComplete = onComplete }; } private static ZoneBundleTerrainCaptureState GetTerrainCaptureState(bool contactsCaptured, int contactCount) { if (!contactsCaptured) { return ZoneBundleTerrainCaptureState.NotLoaded; } if (contactCount <= 0) { return ZoneBundleTerrainCaptureState.LoadedNoContacts; } return ZoneBundleTerrainCaptureState.Contacts; } private static bool HasSavedTerrainContacts(ZoneBundleFile bundle) { if (bundle.TerrainContactsCaptured) { return bundle.TerrainContacts.Count > 0; } return false; } private static bool HasWearNTearEntries(ZoneBundleFile bundle) { foreach (ZoneBundleEntry entry in bundle.Entries) { if (!string.Equals(entry.Kind, "item", StringComparison.OrdinalIgnoreCase)) { GameObject prefab = ZNetScene.instance.GetPrefab(entry.Prefab); if (Object.op_Implicit((Object)(object)prefab) && (Object)(object)prefab.GetComponent() != (Object)null) { return true; } } } return false; } private static ZoneLoadStats ApplyBundleToZone(Vector2i targetZone, ZoneBundleFile bundle, TerrainPlacementContext? terrainContext, float yOffset) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) int removed = ClearTargetZone(targetZone); bool terrainApplied = false; if (terrainContext != null) { terrainApplied = ZoneBundleTerrainApplier.ApplySupportFill(targetZone, bundle.Entries, bundle.TerrainContacts, bundle.TerrainContactsCaptured, terrainContext); } int num = 0; Vector3 zonePos = ZoneSystem.GetZonePos(targetZone); float num2 = terrainContext?.BaseWorldY ?? (bundle.SourceBaseY + yOffset); Vector3 position = default(Vector3); Quaternion rotation = default(Quaternion); Vector3 value = default(Vector3); foreach (ZoneBundleEntry entry in bundle.Entries) { if (string.Equals(entry.Kind, "item", StringComparison.OrdinalIgnoreCase)) { continue; } GameObject prefab = ZNetScene.instance.GetPrefab(entry.Prefab); if (!Object.op_Implicit((Object)(object)prefab)) { _logger.LogWarning((object)("Missing prefab '" + entry.Prefab + "' while loading zone bundle.")); } else if (!Object.op_Implicit((Object)(object)prefab.GetComponent())) { float num3 = (UsesRelativeY(bundle) ? (num2 + entry.LocalPos[1]) : (entry.LocalPos[1] + yOffset)); ((Vector3)(ref position))..ctor(zonePos.x + entry.LocalPos[0], num3, zonePos.z + entry.LocalPos[2]); ((Quaternion)(ref rotation))..ctor(entry.Rot[0], entry.Rot[1], entry.Rot[2], entry.Rot[3]); ((Vector3)(ref value))..ctor(entry.Scale[0], entry.Scale[1], entry.Scale[2]); ZoneBundleZdoData data = (string.IsNullOrEmpty(entry.Data) ? new ZoneBundleZdoData() : new ZoneBundleZdoData(entry.Data)); SanitizeForLoad(entry, prefab, data); ZDO val = ZoneBundleZdoHelper.Init(prefab, position, rotation, value, data, EmptyParameters); if (val != null) { ZNetScene.instance.CreateObject(val); num++; } } } return new ZoneLoadStats(removed, num, terrainApplied); } [IteratorStateMachine(typeof(d__72))] private static IEnumerator ApplyBundleToZoneAsync(Vector2i targetZone, ZoneBundleFile bundle, TerrainPlacementContext? terrainContext, float yOffset, Action onComplete) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__72(0) { targetZone = targetZone, bundle = bundle, terrainContext = terrainContext, yOffset = yOffset, onComplete = onComplete }; } internal static ZoneBundleCommandResult RestoreTagToOriginalZones(string tag) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) ZoneBundleManifest zoneBundleManifest = ZoneBundleSerialization.LoadManifest(GetManifestPath(tag)); List list = new List(); foreach (ZoneBundleManifestEntry bundle2 in zoneBundleManifest.Bundles) { Vector2i targetZone = ToVector2i(bundle2.Zone); ZoneBundleFile bundle = ZoneBundleSerialization.LoadBundle(Path.Combine(GetTagDirectory(tag), bundle2.File)); list.Add(new LoadWorkItem(targetZone, bundle)); } ValidateLoadReady(list); TerrainPlacementContext terrainContext = CreateAndValidateTerrainPlacementContext(list, exactSource: true, 0f); int num = 0; int num2 = 0; int num3 = 0; foreach (LoadWorkItem item in list) { ZoneLoadStats zoneLoadStats = ApplyBundleToZone(item.TargetZone, item.Bundle, terrainContext, 0f); num += zoneLoadStats.Removed; num2 += zoneLoadStats.Created; if (zoneLoadStats.TerrainApplied) { num3++; } } return ZoneBundleCommandResult.Ok($"Restored {list.Count} archived zone bundle(s) for tag '{tag}' " + $"(removed: {num}, created: {num2}, terrain: {num3}/{list.Count})."); } [IteratorStateMachine(typeof(d__74))] internal static IEnumerator RestoreTagToOriginalZonesAsync(string tag, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__74(0) { tag = tag, onComplete = onComplete }; } internal static string MakeUniqueAutoArchiveTag(string preferredTag) { if (!ArchiveTagExists(preferredTag)) { return preferredTag; } for (int i = 2; i <= 999; i++) { string text = $"{preferredTag}_n{i:D3}"; if (!ArchiveTagExists(text)) { return text; } } throw new InvalidOperationException("Could not find a free archive tag for '" + preferredTag + "'."); } internal static ZoneBundleResetResult ResetGeneratedZones(IEnumerable sourceZones) { //IL_0095: Unknown result type (might be due to invalid IL or missing references) List list = (from zone in sourceZones.Distinct() orderby zone.y, zone.x select zone).ToList(); if (list.Count == 0) { return new ZoneBundleResetResult { Success = false, Message = "No zones to reset." }; } HashSet onlineCharacterIds = GetOnlineCharacterIds(); HashSet zones = list.ToHashSet(); int num = ResetZoneObjects(zones, onlineCharacterIds); foreach (Vector2i item in list) { ResetZoneSystemState(item); } int num2 = 0; int num3 = CountRemainingCreatorWearNTear(zones, onlineCharacterIds); if (num3 > 0) { num2 = ResetZoneObjects(zones, onlineCharacterIds); num += num2; num3 = CountRemainingCreatorWearNTear(zones, onlineCharacterIds); } ClutterSystem instance = ClutterSystem.instance; if (instance != null) { instance.ClearAll(); } RecalculateLoadedTerrain(); Minimap instance2 = Minimap.instance; if (instance2 != null) { instance2.UpdateLocationPins(1000f); } string text = $"Reset {list.Count} generated zone(s), removed {num} ZDO(s)."; if (num2 > 0) { text += $" Verification pass removed {num2} ZDO(s)."; _logger.LogWarning((object)text); } if (num3 > 0) { text += $" {num3} creator WearNTear ZDO(s) still remain after reset."; _logger.LogWarning((object)text); } return new ZoneBundleResetResult { Success = (num3 == 0), ZoneCount = list.Count, RemovedCount = num, RemainingWearNTearCount = num3, Message = text }; } [IteratorStateMachine(typeof(d__77))] internal static IEnumerator ResetGeneratedZonesAsync(IEnumerable sourceZones, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__77(0) { sourceZones = sourceZones, onComplete = onComplete }; } private static int ClearTargetZone(Vector2i targetZone) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) List list = new List(); ZDOMan.instance.FindObjects(targetZone, list); int num = 0; foreach (ZDO item in list.ToList()) { if (item != null && item.IsValid()) { GameObject prefab = ZNetScene.instance.GetPrefab(item.GetPrefab()); if (Object.op_Implicit((Object)(object)prefab) && ShouldDeleteForOverwrite(prefab, item)) { ZoneBundleZdoHelper.Destroy(item); num++; } } } ZoneBundleZdoHelper.FlushDestroyed(); return num; } [IteratorStateMachine(typeof(d__79))] private static IEnumerator ClearTargetZoneAsync(Vector2i targetZone, Action onComplete) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__79(0) { targetZone = targetZone, onComplete = onComplete }; } private static void ResetZoneSystemState(Vector2i zone) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) if (ZoneSystem.instance.m_locationInstances.TryGetValue(zone, out var value)) { value.m_placed = false; value.m_position = new Vector3(value.m_position.x, WorldGenerator.instance.GetHeight(value.m_position.x, value.m_position.z), value.m_position.z); ZoneSystem.instance.m_locationInstances[zone] = value; } ZoneSystem.instance.m_generatedZones.Remove(zone); if (ZoneSystem.instance.m_zones.TryGetValue(zone, out var value2)) { Object.Destroy((Object)(object)value2.m_root); ZoneSystem.instance.m_zones.Remove(zone); } } private static int ResetZoneObjects(HashSet zones, HashSet protectedCharacterIds) { List resetZoneObjects = GetResetZoneObjects(zones); int num = 0; foreach (ZDO item in resetZoneObjects) { if (IsResettableZoneObject(item, zones, protectedCharacterIds)) { ZoneBundleZdoHelper.Destroy(item); num++; } } ZoneBundleZdoHelper.FlushDestroyed(); return num; } [IteratorStateMachine(typeof(d__82))] private static IEnumerator ResetZoneObjectsAsync(HashSet zones, HashSet protectedCharacterIds, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__82(0) { zones = zones, protectedCharacterIds = protectedCharacterIds, onComplete = onComplete }; } private static int CountRemainingCreatorWearNTear(HashSet zones, HashSet protectedCharacterIds) { List resetZoneObjects = GetResetZoneObjects(zones); int num = 0; foreach (ZDO item in resetZoneObjects) { if (IsResettableZoneObject(item, zones, protectedCharacterIds) && item.GetLong(ZDOVars.s_creator, 0L) != 0L) { GameObject prefab = ZNetScene.instance.GetPrefab(item.GetPrefab()); if (Object.op_Implicit((Object)(object)prefab) && (Object)(object)prefab.GetComponent() != (Object)null) { num++; } } } return num; } [IteratorStateMachine(typeof(d__84))] private static IEnumerator CountRemainingCreatorWearNTearAsync(HashSet zones, HashSet protectedCharacterIds, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__84(0) { zones = zones, protectedCharacterIds = protectedCharacterIds, onComplete = onComplete }; } private static List GetResetZoneObjects(HashSet zones) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) List list = new List(); HashSet hashSet = new HashSet(); List list2 = new List(); foreach (Vector2i zone in zones) { list2.Clear(); ZDOMan.instance.FindObjects(zone, list2); foreach (ZDO item in list2) { if (item != null && item.IsValid() && hashSet.Add(item.m_uid) && zones.Contains(ZoneSystem.GetZone(item.GetPosition()))) { list.Add(item); } } } return list; } private static bool IsResettableZoneObject(ZDO zdo, HashSet zones, HashSet protectedCharacterIds) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (zdo != null && zdo.IsValid() && !protectedCharacterIds.Contains(zdo.m_uid)) { return zones.Contains(ZoneSystem.GetZone(zdo.GetPosition())); } return false; } private static HashSet GetOnlineCharacterIds() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) HashSet hashSet = new HashSet(); if ((Object)(object)ZNet.instance == (Object)null) { return hashSet; } if (!((ZDOID)(ref ZNet.instance.m_characterID)).IsNone()) { hashSet.Add(ZNet.instance.m_characterID); } foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (peer != null && peer.IsReady() && !((ZDOID)(ref peer.m_characterID)).IsNone()) { hashSet.Add(peer.m_characterID); } } return hashSet; } private static void RecalculateLoadedTerrain() { foreach (Heightmap item in GetLoadedHeightmapSnapshot()) { RecalculateHeightmap(item); } } [IteratorStateMachine(typeof(d__89))] private static IEnumerator RecalculateLoadedTerrainAsync() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__89(0); } private static List GetLoadedHeightmapSnapshot() { return Heightmap.s_heightmaps.Where((Heightmap heightmap) => Object.op_Implicit((Object)(object)heightmap)).ToList(); } private static bool RecalculateHeightmap(Heightmap heightmap) { if (!Object.op_Implicit((Object)(object)heightmap)) { return false; } try { heightmap.m_buildData = null; heightmap.Poke(true); return true; } catch (Exception ex) { _logger.LogWarning((object)("Failed to recalculate loaded terrain heightmap: " + ex.Message)); return false; } } private static bool TryClassify(ZDO zdo, out SaveEntryKind kind, out GameObject prefab) { prefab = ZNetScene.instance.GetPrefab(zdo.GetPrefab()); kind = SaveEntryKind.Static; if (!Object.op_Implicit((Object)(object)prefab)) { return false; } if (!Object.op_Implicit((Object)(object)prefab.GetComponent()) || Object.op_Implicit((Object)(object)prefab.GetComponent()) || Object.op_Implicit((Object)(object)prefab.GetComponent()) || Object.op_Implicit((Object)(object)prefab.GetComponent()) || Object.op_Implicit((Object)(object)prefab.GetComponent()) || Object.op_Implicit((Object)(object)prefab.GetComponent()) || Object.op_Implicit((Object)(object)prefab.GetComponent()) || Object.op_Implicit((Object)(object)prefab.GetComponent()) || Object.op_Implicit((Object)(object)prefab.GetComponent()) || Object.op_Implicit((Object)(object)prefab.GetComponent())) { return false; } Character component = prefab.GetComponent(); if (Object.op_Implicit((Object)(object)component)) { if (!Object.op_Implicit((Object)(object)prefab.GetComponent()) || component.IsBoss() || zdo.GetBool(ZDOVars.s_eventCreature, false) || !IsTamedMonster(zdo, prefab)) { return false; } kind = SaveEntryKind.Monster; } return true; } private static bool ShouldDeleteForOverwrite(GameObject prefab, ZDO zdo) { if (Object.op_Implicit((Object)(object)prefab.GetComponent())) { return true; } SaveEntryKind kind; GameObject prefab2; return TryClassify(zdo, out kind, out prefab2); } private static bool IsTamedMonster(ZDO zdo, GameObject prefab) { if ((Object)(object)prefab.GetComponent() != (Object)null) { return zdo.GetBool(ZDOVars.s_tamed, false); } return false; } private static void SanitizeForSave(SaveEntryKind kind, ZoneBundleZdoData data, string sanitize) { //IL_0001: 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) data.OriginalId = ZDOID.None; data.TargetConnectionId = ZDOID.None; data.ConnectionHash = 0; data.ConnectionType = (ConnectionType)0; if (string.Equals(sanitize, "wearntear-v1", StringComparison.Ordinal)) { RemoveWearNTearVolatileKeys(data); } else if (kind == SaveEntryKind.Monster) { RemoveMonsterVolatileKeys(data); } } private static void SanitizeForLoad(ZoneBundleEntry entry, GameObject prefab, ZoneBundleZdoData data) { //IL_0001: 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) data.OriginalId = ZDOID.None; data.TargetConnectionId = ZDOID.None; data.ConnectionHash = 0; data.ConnectionType = (ConnectionType)0; if (string.Equals(entry.Sanitize, "wearntear-v1", StringComparison.Ordinal) || (string.IsNullOrEmpty(entry.Sanitize) && Object.op_Implicit((Object)(object)prefab.GetComponent()))) { RemoveWearNTearVolatileKeys(data); } else if (string.Equals(entry.Sanitize, "monster-v1", StringComparison.Ordinal) || string.Equals(entry.Sanitize, "tamed-monster-v1", StringComparison.Ordinal)) { RemoveMonsterVolatileKeys(data); } } private static void RemoveWearNTearVolatileKeys(ZoneBundleZdoData data) { RemoveCommonEntityVolatileKeys(data); RemoveKey(data, ZDOVars.s_support); RemoveKey(data, ZDOVars.s_inUse); RemoveKey(data, ZDOVars.s_user); KeyValuePair s_zdoidUser = ZDOVars.s_zdoidUser; RemoveKey(data, s_zdoidUser.Key); s_zdoidUser = ZDOVars.s_zdoidUser; RemoveKey(data, s_zdoidUser.Value); } private static void RemoveMonsterVolatileKeys(ZoneBundleZdoData data) { RemoveCommonEntityVolatileKeys(data); RemoveKey(data, ZDOVars.s_alert); RemoveKey(data, ZDOVars.s_aggravated); RemoveKey(data, ZDOVars.s_follow); RemoveKey(data, ZDOVars.s_haveTargetHash); RemoveKey(data, ZDOVars.s_huntPlayer); RemoveKey(data, ZDOVars.s_patrol); RemoveKey(data, ZDOVars.s_patrolPoint); RemoveKey(data, ZDOVars.s_spawnPoint); RemoveKey(data, ZDOVars.s_targets); RemoveKey(data, ZDOVars.s_shownAlertMessage); RemoveKey(data, ZDOVars.s_sleeping); RemoveKey(data, ZDOVars.s_worldTimeHash); RemoveKey(data, ZDOVars.s_spawnTime); RemoveKey(data, ZDOVars.s_spawn_time__DontUse); RemoveKey(data, ZDOVars.s_SpawnTime__DontUse); RemoveKey(data, ZDOVars.s_tameLastFeeding); RemoveKey(data, ZDOVars.s_tameTimeLeft); RemoveKey(data, ZDOVars.s_lovePoints); RemoveKey(data, ZDOVars.s_pregnant); RemoveKey(data, ZDOVars.s_seAttrib); RemoveKey(data, ZDOVars.s_lastAttack); RemoveKey(data, ZDOVars.s_noise); RemoveKey(data, ZDOVars.s_tiltrot); KeyValuePair s_toRemoveTarget = ZDOVars.s_toRemoveTarget; RemoveKey(data, s_toRemoveTarget.Key); s_toRemoveTarget = ZDOVars.s_toRemoveTarget; RemoveKey(data, s_toRemoveTarget.Value); s_toRemoveTarget = ZDOVars.s_toRemoveSpawnID; RemoveKey(data, s_toRemoveTarget.Key); s_toRemoveTarget = ZDOVars.s_toRemoveSpawnID; RemoveKey(data, s_toRemoveTarget.Value); } private static void RemoveCommonEntityVolatileKeys(ZoneBundleZdoData data) { RemoveKey(data, ZDOVars.s_bodyAVelHash); RemoveKey(data, ZDOVars.s_bodyVelHash); RemoveKey(data, ZDOVars.s_bodyVelocity); RemoveKey(data, ZDOVars.s_velHash); RemoveKey(data, ZDOVars.s_initVel); RemoveKey(data, ZDOVars.s_forward); RemoveKey(data, ZDOVars.s_landed); RemoveKey(data, ZDOVars.s_inWater); RemoveKey(data, ZDOVars.s_hitDir); RemoveKey(data, ZDOVars.s_hitPoint); RemoveKey(data, ZDOVars.s_stamina); RemoveKey(data, ZDOVars.s_eitr); RemoveKey(data, ZDOVars.s_adrenaline); RemoveKey(data, ZDOVars.s_dodgeinv); RemoveKey(data, ZDOVars.s_startTime); RemoveKey(data, ZDOVars.s_lastTime); RemoveKey(data, ZDOVars.s_aliveTime); RemoveKey(data, ZDOVars.s_accTime); RemoveKey(data, ZDOVars.s_worldTimeHash); } private static void RemoveKey(ZoneBundleZdoData data, int hash) { data.Strings?.Remove(hash); data.Floats?.Remove(hash); data.Ints?.Remove(hash); data.Bools?.Remove(hash); data.Hashes?.Remove(hash); data.Longs?.Remove(hash); data.Vecs?.Remove(hash); data.Quats?.Remove(hash); data.ByteArrays?.Remove(hash); } private static Vector3 ReadScale(ZDO zdo, GameObject prefab) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) return zdo.GetVec3(ZDOVars.s_scaleHash, prefab.transform.localScale); } private static ZoneBundleCommandRequest ParseArchiveRequest(string argsAll) { //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) float yOffset = ExtractYOffsetOption(ref argsAll); Match match = LoadArchivePattern.Match(argsAll); if (!match.Success) { throw new InvalidOperationException("Syntax: zs_loadarchive tag [to (x,z)] [offset=Y]"); } return new ZoneBundleCommandRequest { Operation = "zs_loadarchive", Tag = match.Groups[1].Value, TargetZone = (match.Groups[2].Success ? ToModel(ParseSingleZone(match.Groups[2].Value)) : ToModel(GetCurrentPlayerZone())), YOffset = yOffset }; } private static ZoneBundleCommandRequest ParseRequest(string argsAll, string operation, bool requireSingleZone, bool requireTarget) { //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) float yOffset = ExtractYOffsetOption(ref argsAll); Match match = CommandPattern.Match(argsAll); if (!match.Success) { string message = ((operation == "zs_savezone") ? "Syntax: zs_savezone (x~x,z~z) tag" : ((!(operation == "zs_loadzone")) ? "Syntax: zs_loadarchive tag [to (x,z)] [offset=Y]" : "Syntax: zs_loadzone (x,z) tag [to (x,z)] [offset=Y] or zs_loadzone (x~x,z~z) tag [to (x,z)] [offset=Y]")); throw new InvalidOperationException(message); } ZoneBundleCommandRequest zoneBundleCommandRequest = new ZoneBundleCommandRequest { Operation = operation, SourceRange = ParseZoneRange(match.Groups[1].Value, requireSingleZone), Tag = match.Groups[2].Value, YOffset = yOffset }; if (match.Groups[3].Success) { zoneBundleCommandRequest.TargetZone = ToModel(ParseSingleZone(match.Groups[3].Value)); } else if (requireTarget) { zoneBundleCommandRequest.TargetZone = ToModel(GetCurrentPlayerZone()); } return zoneBundleCommandRequest; } private static ZoneBundleRange ParseZoneRange(string spec, bool requireSingleZone) { Match match = RangePattern.Match(spec); if (!match.Success) { throw new InvalidOperationException("Invalid zone spec '" + spec + "'."); } var (num, num2) = ParseAxis(match.Groups[1].Value); var (num3, num4) = ParseAxis(match.Groups[2].Value); if (requireSingleZone && (num != num2 || num3 != num4)) { throw new InvalidOperationException("This command requires a single source zone."); } return CreateRange(num, num3, num2, num4); } private static Vector2i ParseSingleZone(string spec) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) ZoneBundleRange zoneBundleRange = ParseZoneRange(spec, requireSingleZone: true); return new Vector2i(zoneBundleRange.MinX, zoneBundleRange.MinZ); } private static (int Min, int Max) ParseAxis(string axis) { string[] array = axis.Trim().Split(new char[1] { '~' }); if (array.Length == 1) { int num = ParseInt(array[0]); return (num, num); } if (array.Length != 2) { throw new InvalidOperationException("Invalid axis range '" + axis + "'."); } int num2 = ParseInt(array[0]); int num3 = ParseInt(array[1]); if (num2 > num3) { return (num3, num2); } return (num2, num3); } private static float ExtractYOffsetOption(ref string argsAll) { Match match = YOffsetEqualsOptionPattern.Match(argsAll); if (!match.Success) { match = YOffsetFlagOptionPattern.Match(argsAll); } if (!match.Success) { return 0f; } float result = ParseFloat(match.Groups[1].Value); argsAll = YOffsetEqualsOptionPattern.Replace(argsAll, " "); argsAll = YOffsetFlagOptionPattern.Replace(argsAll, " ").Trim(); return result; } private static void ApplyYOffset(TerrainPlacementContext? context, float yOffset) { if (context != null && !(Mathf.Abs(yOffset) <= 0.0001f)) { context.BaseWorldY += yOffset; } } private static int ParseInt(string value) { if (!int.TryParse(value.Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { throw new InvalidOperationException("Invalid integer '" + value + "'."); } return result; } private static float ParseFloat(string value) { if (!float.TryParse(value.Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { throw new InvalidOperationException("Invalid number '" + value + "'."); } return result; } private static ZoneBundleRange CreateRange(int minX, int minZ, int maxX, int maxZ) { return new ZoneBundleRange { MinX = Math.Min(minX, maxX), MaxX = Math.Max(minX, maxX), MinZ = Math.Min(minZ, maxZ), MaxZ = Math.Max(minZ, maxZ) }; } [IteratorStateMachine(typeof(d__112))] private static IEnumerable EnumerateZones(ZoneBundleRange range) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__112(-2) { <>3__range = range }; } private static Vector2i GetCurrentPlayerZone() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer)) { throw new InvalidOperationException("No local player available. Use to (x,z) from a dedicated server console."); } return ZoneSystem.GetZone(((Component)localPlayer).transform.position); } private static void EnsureCommandAllowed() { if (!Object.op_Implicit((Object)(object)ZNet.instance) || !Object.op_Implicit((Object)(object)ZNetScene.instance) || !Object.op_Implicit((Object)(object)ZoneSystem.instance) || ZDOMan.instance == null) { throw new InvalidOperationException("World is not ready."); } if (!ZNet.instance.IsServer()) { if (ZRoutedRpc.instance == null) { throw new InvalidOperationException("Server RPC is not ready."); } } else if ((!ZNet.instance.IsServer() || !((Object)(object)Player.m_localPlayer == (Object)null)) && !ZNet.instance.LocalPlayerIsAdminOrHost()) { throw new InvalidOperationException("Admin only."); } } private static bool IsAuthorizedSender(long sender) { ZNetPeer peer = ZNet.instance.GetPeer(sender); object obj; if (peer == null) { obj = null; } else { ZRpc rpc = peer.m_rpc; if (rpc == null) { obj = null; } else { ISocket socket = rpc.m_socket; obj = ((socket != null) ? socket.GetHostName() : null); } } if (obj == null) { obj = ""; } string text = (string)obj; if (text.Length > 0) { return ZNet.instance.IsAdmin(text); } return false; } private static void ShowResult(ZoneBundleCommandResult result, Terminal? terminal = null) { _logger.LogInfo((object)result.Message); if ((Object)(object)terminal != (Object)null) { terminal.AddString(result.Message); } else if ((Object)(object)Console.instance != (Object)null) { ((Terminal)Console.instance).AddString(result.Message); } if ((Object)(object)Player.m_localPlayer != (Object)null) { ((Character)Player.m_localPlayer).Message((MessageType)(result.Success ? 1 : 2), result.Message, 0, (Sprite)null); } } private static string GetManifestPath(string tag) { return Path.Combine(GetTagDirectory(tag), "manifest.yml"); } private static bool ArchiveTagExists(string tag) { if (!Directory.Exists(GetTagDirectory(tag))) { return File.Exists(GetManifestPath(tag)); } return true; } private static string GetBundlePath(string tag, int index) { return Path.Combine(GetTagDirectory(tag), $"bundle{index:D3}.zonebundle.yml"); } private static string GetBundlePathFromManifest(string tag, Vector2i zone) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) ZoneBundleManifestEntry zoneBundleManifestEntry = ZoneBundleSerialization.LoadManifest(GetManifestPath(tag)).Bundles.FirstOrDefault(delegate(ZoneBundleManifestEntry candidate) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) Vector2i val = ToVector2i(candidate.Zone); return val.x == zone.x && val.y == zone.y; }); if (zoneBundleManifestEntry == null) { throw new FileNotFoundException($"Manifest for tag '{tag}' does not contain source zone ({zone.x},{zone.y})."); } return Path.Combine(GetTagDirectory(tag), zoneBundleManifestEntry.File); } private static bool TryLoadBundleFile(string path, out ZoneBundleFile bundle, out string reason) { bundle = null; reason = ""; try { bundle = ZoneBundleSerialization.LoadBundle(path); return true; } catch (Exception ex) { reason = ex.Message; return false; } } private static string GetTagDirectory(string tag) { return Path.Combine(ZoneSaviorPlugin.ZoneBundleStorageFullPath, SanitizePathSegment(tag)); } private static string GetWorldName() { return ZNet.instance.GetWorldName(); } internal static string GetCurrentWorldName() { return GetWorldName(); } private static string SanitizePathSegment(string value) { char[] invalidChars = Path.GetInvalidFileNameChars(); string text = new string(value.Select((char character) => (!invalidChars.Contains(character)) ? character : '_').ToArray()).Trim(); if (text.Length == 0) { throw new InvalidOperationException("Tag or world name resolves to an empty path segment."); } return text; } private static ZoneBundleZone ToModel(Vector2i zone) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) return new ZoneBundleZone { X = zone.x, Z = zone.y }; } private static Vector2i ToVector2i(ZoneBundleZone zone) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) return new Vector2i(zone.X, zone.Z); } private static Vector2i ToSingleSourceZone(ZoneBundleRange range) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) return new Vector2i(range.MinX, range.MinZ); } private static float Round(float value) { return Mathf.Round(value * 1000f) / 1000f; } } internal sealed class ZoneBundleManifest { public int Version { get; set; } = 1; public string Tag { get; set; } = ""; public string World { get; set; } = ""; public string SavedAt { get; set; } = ""; public ZoneBundleRange SourceRange { get; set; } = new ZoneBundleRange(); public List SourceZoneCreators { get; set; } = new List(); public List Bundles { get; set; } = new List(); public List Connections { get; set; } = new List(); } internal sealed class ZoneBundleManifestEntry { public ZoneBundleZone Zone { get; set; } = new ZoneBundleZone(); public string File { get; set; } = ""; public List SourceZoneCreators { get; set; } = new List(); } internal sealed class ZoneBundleCreatorPlayer { public long PlayerId { get; set; } public string? Name { get; set; } public string? PlatformId { get; set; } } internal sealed class ZoneBundleConnection { public string SaveId { get; set; } = ""; public string Type { get; set; } = ""; public string TargetSaveId { get; set; } = ""; } internal sealed class ZoneBundleFile { public int Version { get; set; } = 1; public string Tag { get; set; } = ""; public ZoneBundleZone SourceZone { get; set; } = new ZoneBundleZone(); public string TerrainMode { get; set; } = ""; public float SourceBaseY { get; set; } public ZoneBundleTerrainCaptureState TerrainCaptureState { get; set; } public bool TerrainContactsCaptured { get; set; } public List TerrainContacts { get; set; } = new List(); public List SourceZoneCreators { get; set; } = new List(); public List Entries { get; set; } = new List(); } internal enum ZoneBundleTerrainCaptureState { NotLoaded, LoadedNoContacts, Contacts } internal sealed class ZoneBundleTerrainContact { public float LocalX { get; set; } public float LocalZ { get; set; } public float RelativeY { get; set; } } internal sealed class ZoneBundleEntry { public string SaveId { get; set; } = ""; public string Kind { get; set; } = ""; public string Prefab { get; set; } = ""; public float[] LocalPos { get; set; } = new float[3]; public float[] Rot { get; set; } = new float[4]; public float[] Scale { get; set; } = new float[3]; public long CreatorPlayerId { get; set; } public string? CreatorName { get; set; } public string Data { get; set; } = ""; public string Sanitize { get; set; } = ""; } internal sealed class ZoneBundleRange { public int MinX { get; set; } public int MaxX { get; set; } public int MinZ { get; set; } public int MaxZ { get; set; } } internal sealed class ZoneBundleZone { public int X { get; set; } public int Z { get; set; } } internal sealed class ZoneBundleCommandRequest { public string Operation { get; set; } = ""; public ZoneBundleRange SourceRange { get; set; } = new ZoneBundleRange(); public string Tag { get; set; } = ""; public ZoneBundleZone? TargetZone { get; set; } public float YOffset { get; set; } } internal sealed class ZoneBundleCommandResult { public bool Success { get; set; } public string Message { get; set; } = ""; public static ZoneBundleCommandResult Ok(string message) { return new ZoneBundleCommandResult { Success = true, Message = message }; } public static ZoneBundleCommandResult Fail(string message) { return new ZoneBundleCommandResult { Success = false, Message = message }; } } internal sealed class TerrainSupportTarget { public Vector2i Zone { get; set; } public float SourceBaseY { get; set; } public List Entries { get; set; } = new List(); public bool ContactsCaptured { get; set; } public List Contacts { get; set; } = new List(); } internal sealed class TerrainPlacementContext { public float BaseWorldY { get; set; } public float MinX { get; set; } public float MaxX { get; set; } public float MinZ { get; set; } public float MaxZ { get; set; } public float BlendWidth { get; set; } = 16f; public float SupportWidth { get; set; } = 64f; public Dictionary SupportRelativeHeights { get; } = new Dictionary(); } internal static class ZoneBundleSerialization { private static readonly ISerializer Serializer = new SerializerBuilder().DisableAliases().ConfigureDefaultValuesHandling(DefaultValuesHandling.OmitNull).WithNamingConvention(CamelCaseNamingConvention.Instance) .WithTypeConverter(new FlowFloatArrayYamlConverter()) .Build(); private static readonly IDeserializer Deserializer = new DeserializerBuilder().IgnoreUnmatchedProperties().WithNamingConvention(CamelCaseNamingConvention.Instance).WithTypeConverter(new FlowFloatArrayYamlConverter()) .Build(); public static string Serialize(T value) { return Serializer.Serialize(value); } public static T Deserialize(string yaml) { return Deserializer.Deserialize(yaml) ?? throw new InvalidDataException("Failed to deserialize " + typeof(T).Name + "."); } public static void SaveManifest(string path, ZoneBundleManifest manifest) { Directory.CreateDirectory(Path.GetDirectoryName(path)); File.WriteAllText(path, Serialize(manifest), Encoding.UTF8); } public static ZoneBundleManifest LoadManifest(string path) { return Deserialize(File.ReadAllText(path, Encoding.UTF8)); } public static void SaveBundle(string path, ZoneBundleFile bundle) { Directory.CreateDirectory(Path.GetDirectoryName(path)); File.WriteAllText(path, Serialize(bundle), Encoding.UTF8); } public static ZoneBundleFile LoadBundle(string path) { return Deserialize(File.ReadAllText(path, Encoding.UTF8)); } } internal sealed class FlowFloatArrayYamlConverter : IYamlTypeConverter { public bool Accepts(Type type) { return type == typeof(float[]); } public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer) { parser.Consume(); List list = new List(); SequenceEnd @event; while (!parser.TryConsume(out @event)) { YamlDotNet.Core.Events.Scalar scalar = parser.Consume(); if (!float.TryParse(scalar.Value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { Mark start = scalar.Start; Mark end = scalar.End; throw new YamlException(in start, in end, "Invalid float value '" + scalar.Value + "'."); } list.Add(result); } return list.ToArray(); } public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer) { float[] obj = (value as float[]) ?? Array.Empty(); emitter.Emit(new SequenceStart(AnchorName.Empty, TagName.Empty, isImplicit: true, SequenceStyle.Flow)); float[] array = obj; foreach (float num in array) { emitter.Emit(new YamlDotNet.Core.Events.Scalar(AnchorName.Empty, TagName.Empty, num.ToString("0.###", CultureInfo.InvariantCulture), ScalarStyle.Plain, isPlainImplicit: true, isQuotedImplicit: true)); } emitter.Emit(new SequenceEnd()); } } internal static class ZoneBundleTerrain { private abstract class TerrainSupportStrategy { public abstract string Name { get; } public abstract List CollectPlacementSamples(TerrainSupportTarget target); public abstract List CollectApplySamples(Vector2i zone, IEnumerable entries, IReadOnlyCollection contacts); public abstract float ResolveBaseWorldY(List footprintSamples); public virtual bool IsPlacementTargetUsable(TerrainSupportSample sample, float baseWorldY) { return true; } public virtual bool IsApplyTargetUsable(TerrainSupportSample sample, float targetHeight) { return true; } } private sealed class SavedContactTerrainStrategy : TerrainSupportStrategy { public override string Name => "saved-contact"; public override List CollectPlacementSamples(TerrainSupportTarget target) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return CollectSavedContactSamples(target.Zone, target.Contacts); } public override List CollectApplySamples(Vector2i zone, IEnumerable entries, IReadOnlyCollection contacts) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return CollectSavedContactSamples(zone, contacts); } public override float ResolveBaseWorldY(List footprintSamples) { return ResolveSupportFillBaseWorldY(footprintSamples); } } private sealed class ColliderFallbackTerrainStrategy : TerrainSupportStrategy { public override string Name => "collider-fallback"; public override List CollectPlacementSamples(TerrainSupportTarget target) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return CollectSupportSamples(target.Zone, target.Entries, target.SourceBaseY); } public override List CollectApplySamples(Vector2i zone, IEnumerable entries, IReadOnlyCollection contacts) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return CollectSupportSamples(zone, entries); } public override float ResolveBaseWorldY(List footprintSamples) { return ResolveFallbackSupportBaseWorldY(footprintSamples); } public override bool IsPlacementTargetUsable(TerrainSupportSample sample, float baseWorldY) { return IsReasonableFallbackSupportTarget(sample, baseWorldY); } public override bool IsApplyTargetUsable(TerrainSupportSample sample, float targetHeight) { return IsReasonableFallbackTarget(sample.WorldX, sample.WorldZ, targetHeight); } } private readonly struct PlacementSupportSampleSet { public TerrainSupportStrategy Strategy { get; } public List Samples { get; } public PlacementSupportSampleSet(TerrainSupportStrategy strategy, List samples) { Strategy = strategy; Samples = samples; } } private sealed class TerrainSupportApplicationPlan { public Dictionary SupportHeights { get; } public List SupportCells { get; } public bool HasSupport => SupportHeights.Count > 0; public TerrainSupportApplicationPlan(Dictionary supportHeights, List supportCells) { SupportHeights = supportHeights; SupportCells = supportCells; } } private readonly struct TerrainSupportSample { public float WorldX { get; } public float WorldZ { get; } public float RelativeY { get; } public TerrainSupportSample(float worldX, float worldZ, float relativeY) { WorldX = worldX; WorldZ = worldZ; RelativeY = relativeY; } } private readonly struct TerrainSupportCell { public int X { get; } public int Z { get; } public float Height { get; } public TerrainSupportCell(int x, int z, float height) { X = x; Z = z; Height = height; } } private sealed class TerrainSupportCellIndex { private readonly Dictionary> _cellsByBucket = new Dictionary>(); private readonly float _bucketSize; private readonly int _searchRadius; public TerrainSupportCellIndex(IEnumerable cells, float featherWidth) { _bucketSize = Mathf.Max(1f, featherWidth); _searchRadius = Mathf.Max(0, Mathf.CeilToInt(featherWidth / _bucketSize)); foreach (TerrainSupportCell cell in cells) { long key = PackCell(ToBucket(cell.X), ToBucket(cell.Z)); if (!_cellsByBucket.TryGetValue(key, out List value)) { value = new List(); _cellsByBucket[key] = value; } value.Add(cell); } } public bool TryGetNearest(Vector3 node, float maxDistanceSqr, out TerrainSupportCell nearest, out float bestDistanceSqr) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) nearest = default(TerrainSupportCell); bestDistanceSqr = float.PositiveInfinity; if (_cellsByBucket.Count == 0) { return false; } int num = ToBucket(node.x); int num2 = ToBucket(node.z); for (int i = num2 - _searchRadius; i <= num2 + _searchRadius; i++) { for (int j = num - _searchRadius; j <= num + _searchRadius; j++) { if (!_cellsByBucket.TryGetValue(PackCell(j, i), out List value)) { continue; } foreach (TerrainSupportCell item in value) { float num3 = node.x - (float)item.X; float num4 = node.z - (float)item.Z; float num5 = num3 * num3 + num4 * num4; if (!(num5 >= bestDistanceSqr) && !(num5 > maxDistanceSqr)) { bestDistanceSqr = num5; nearest = item; } } } } return !float.IsPositiveInfinity(bestDistanceSqr); } private int ToBucket(float value) { return Mathf.FloorToInt(value / _bucketSize); } } internal readonly struct TerrainSourceAnchor { public float BaseWorldY { get; } public TerrainSourceAnchor(float baseWorldY) { BaseWorldY = baseWorldY; } } [CompilerGenerated] private sealed class <>c__DisplayClass17_0 { public List samples; internal void b__0(List value) { samples = value; } } [CompilerGenerated] private sealed class <>c__DisplayClass23_0 { public bool changed; internal void b__0(bool result) { changed = result; } } [CompilerGenerated] private sealed class <>c__DisplayClass34_0 { public bool zoneChanged; internal void b__7(bool result) { zoneChanged = result; } } [CompilerGenerated] private sealed class d__54 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Heightmap heightmap; public List supportCells; public TerrainSupportApplyOptions applyOptions; public Dictionary supportHeights; public Action onComplete; private int 5__2; private float[] 5__3; private Color[] 5__4; private TerrainSupportCellIndex 5__5; private bool 5__6; private int 5__7; private int 5__8; private int 5__9; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__54(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__3 = null; 5__4 = null; 5__5 = null; <>1__state = -2; } private bool MoveNext() { //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_0296: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; goto IL_01f0; } <>1__state = -1; 5__2 = heightmap.m_width + 1; 5__3 = new float[5__2 * 5__2]; 5__4 = (Color[])(object)new Color[5__2 * 5__2]; 5__5 = new TerrainSupportCellIndex(supportCells, applyOptions.FeatherWidth); 5__6 = false; 5__7 = 0; 5__8 = 0; goto IL_0225; IL_0225: if (5__8 < 5__2) { 5__9 = 0; goto IL_0202; } if (!5__6) { onComplete(obj: false); return false; } PersistSupportFillTerrain(heightmap.GetAndCreateTerrainCompiler(), 5__2, 5__3, 5__4, applyOptions); heightmap.Poke(false); ClutterSystem instance = ClutterSystem.instance; if (instance != null) { instance.ResetGrass(((Component)heightmap).transform.position, 48f); } onComplete(obj: true); return false; IL_01f0: 5__9++; goto IL_0202; IL_0202: if (5__9 < 5__2) { int num2 = 5__8 * 5__2 + 5__9; Vector3 val = VertexToWorld(heightmap, 5__9, 5__8); float worldHeight = GetWorldHeight(heightmap, 5__9, 5__8); float height; float num3 = (TryGetTerrainBaseHeight(val.x, val.z, out height) ? height : worldHeight); float num4 = num3; 5__4[num2] = GetPaint(heightmap, 5__9, 5__8); float height2; if (supportHeights.TryGetValue(PackCell(Mathf.RoundToInt(val.x), Mathf.RoundToInt(val.z)), out var value)) { num4 = applyOptions.ClampTerrainDelta(value, num3); } else if (TryGetFeatheredSupportHeight(val, num3, 5__5, applyOptions.FeatherWidth, out height2)) { num4 = applyOptions.ClampTerrainDelta(height2, num3); } 5__3[num2] = num4; if (Mathf.Abs(worldHeight - num4) > 0.01f) { 5__6 = true; } 5__7++; if (5__7 >= 1024) { 5__7 = 0; <>2__current = null; <>1__state = 1; return true; } goto IL_01f0; } 5__8++; goto IL_0225; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__23 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public IEnumerable contacts; public bool contactsCaptured; public Vector2i zone; public IEnumerable entries; public TerrainPlacementContext context; public Action onComplete; private <>c__DisplayClass23_0 <>8__1; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__23(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__1 = null; <>1__state = -2; } private bool MoveNext() { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: { <>1__state = -1; <>8__1 = new <>c__DisplayClass23_0(); List list = contacts.ToList(); bool hasContacts = contactsCaptured && list.Count > 0; TerrainSupportApplyOptions applyOptions = TerrainSupportApplyOptions.ZoneBundle(); if (!TryGetHeightmap(zone, out Heightmap heightmap)) { throw new InvalidOperationException($"Target zone ({zone.x},{zone.y}) is not loaded for support terrain placement."); } TerrainSupportApplicationPlan terrainSupportApplicationPlan = BuildSupportPlan(zone, entries, list, hasContacts, context, heightmap, applyOptions); if (!terrainSupportApplicationPlan.HasSupport) { onComplete(obj: false); return false; } <>8__1.changed = false; <>2__current = ApplySupportCellsToHeightmapAsync(heightmap, terrainSupportApplicationPlan.SupportHeights, terrainSupportApplicationPlan.SupportCells, applyOptions, delegate(bool result) { <>8__1.changed = result; }); <>1__state = 1; return true; } case 1: <>1__state = -1; onComplete(<>8__1.changed); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__34 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public IEnumerable supportContacts; public Action onComplete; private <>c__DisplayClass34_0 <>8__1; private List 5__2; private Dictionary 5__3; private bool 5__4; private List.Enumerator <>7__wrap4; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__34(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 1) <= 1u) { try { } finally { <>m__Finally1(); } } <>8__1 = null; 5__2 = null; 5__3 = null; <>7__wrap4 = default(List.Enumerator); <>1__state = -2; } private bool MoveNext() { //IL_016e: Unknown result type (might be due to invalid IL or missing references) bool result2; try { switch (<>1__state) { default: result2 = false; goto end_IL_0000; case 0: <>1__state = -1; 5__2 = (from contact in supportContacts select new TerrainSupportCell(Mathf.RoundToInt(contact.x), Mathf.RoundToInt(contact.z), contact.y - 0.05f) into cell group cell by PackCell(cell.X, cell.Z) into @group select @group.OrderBy((TerrainSupportCell cell) => cell.Height).First()).ToList(); if (5__2.Count != 0) { 5__3 = 5__2.ToDictionary((TerrainSupportCell cell) => PackCell(cell.X, cell.Z), (TerrainSupportCell cell) => cell.Height); List list = 5__2.Select((TerrainSupportCell cell) => ZoneSystem.GetZone(new Vector3((float)cell.X, 0f, (float)cell.Z))).Distinct().ToList(); 5__4 = false; <>7__wrap4 = list.GetEnumerator(); <>1__state = -3; break; } onComplete(obj: false); result2 = false; goto end_IL_0000; case 1: <>1__state = -3; 5__4 |= <>8__1.zoneChanged; <>2__current = null; <>1__state = 2; result2 = true; goto end_IL_0000; case 2: <>1__state = -3; <>8__1 = null; break; } if (<>7__wrap4.MoveNext()) { Vector2i current = <>7__wrap4.Current; <>8__1 = new <>c__DisplayClass34_0(); if (!TryGetHeightmap(current, out Heightmap heightmap)) { onComplete(obj: false); result2 = false; <>m__Finally1(); } else { <>8__1.zoneChanged = false; <>2__current = ApplySupportCellsToHeightmapAsync(heightmap, 5__3, 5__2, TerrainSupportApplyOptions.Blueprint(), delegate(bool result) { <>8__1.zoneChanged = result; }); <>1__state = 1; result2 = true; } } else { <>m__Finally1(); <>7__wrap4 = default(List.Enumerator); onComplete(5__4); result2 = false; } end_IL_0000:; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result2; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>7__wrap4).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__76 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Vector2i zone; public float baseWorldY; public IEnumerable entries; public Action> onComplete; private List 5__2; private Vector3 5__3; private bool 5__4; private int 5__5; private IEnumerator <>7__wrap5; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__76(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } 5__2 = null; <>7__wrap5 = null; <>1__state = -2; } private bool MoveNext() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__2 = new List(); 5__3 = ZoneSystem.GetZonePos(zone); 5__4 = !float.IsNaN(baseWorldY); 5__5 = 0; <>7__wrap5 = entries.GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; break; } Vector3 val = default(Vector3); Quaternion rotation = default(Quaternion); Vector3 scale = default(Vector3); while (<>7__wrap5.MoveNext()) { ZoneBundleEntry current = <>7__wrap5.Current; GameObject prefab = ZNetScene.instance.GetPrefab(current.Prefab); if (Object.op_Implicit((Object)(object)prefab) && (Object)(object)prefab.GetComponent() != (Object)null) { float num = (5__4 ? (baseWorldY + current.LocalPos[1]) : current.LocalPos[1]); ((Vector3)(ref val))..ctor(5__3.x + current.LocalPos[0], num, 5__3.z + current.LocalPos[2]); ((Quaternion)(ref rotation))..ctor(current.Rot[0], current.Rot[1], current.Rot[2], current.Rot[3]); ((Vector3)(ref scale))..ctor(current.Scale[0], current.Scale[1], current.Scale[2]); List list = new List(); AddWearNTearSupportSamples(prefab, val, rotation, scale, 5__4 ? baseWorldY : 0f, list); float num2 = (5__4 ? (val.y - baseWorldY) : current.LocalPos[1]) - 8f; foreach (TerrainSupportSample item in list) { if (item.RelativeY >= num2) { 5__2.Add(item); } } } 5__5++; if (5__5 >= 128) { 5__5 = 0; <>2__current = null; <>1__state = 1; return true; } } <>m__Finally1(); <>7__wrap5 = null; onComplete(5__2); return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>7__wrap5 != null) { <>7__wrap5.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__15 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public IEnumerable zones; public Action onComplete; private float 5__2; private float 5__3; private IEnumerator <>7__wrap3; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__15(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 1) <= 1u) { try { } finally { <>m__Finally1(); } } <>7__wrap3 = null; <>1__state = -2; } private bool MoveNext() { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__2 = float.PositiveInfinity; 5__3 = float.PositiveInfinity; <>7__wrap3 = zones.GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; break; case 2: <>1__state = -3; break; } if (<>7__wrap3.MoveNext()) { Vector2i current = <>7__wrap3.Current; if (ZDOMan.instance == null || (Object)(object)ZNetScene.instance == (Object)null) { <>2__current = null; <>1__state = 1; return true; } List list = new List(); ZDOMan.instance.FindObjects(current, list); foreach (ZDO item in list) { if (TryReadSupportWearNTear(item, current, ZoneBundleConfig.WearNTearSaveMode, out GameObject prefab) && TryGetWearNTearWorldBounds(prefab, item.GetPosition(), item.GetRotation(), ReadScale(item, prefab), out var bounds) && IsReasonableFallbackBoundsMinimum(item.GetPosition().y, ((Bounds)(ref bounds)).min.y)) { 5__2 = Mathf.Min(5__2, ((Bounds)(ref bounds)).min.y); } } foreach (ZDO item2 in list) { if (TryReadTamedMonster(item2, current, out GameObject _)) { 5__3 = Mathf.Min(5__3, item2.GetPosition().y); } } <>2__current = null; <>1__state = 2; return true; } <>m__Finally1(); <>7__wrap3 = null; TerrainSourceAnchor obj = ((!float.IsPositiveInfinity(5__2)) ? new TerrainSourceAnchor(5__2) : (float.IsPositiveInfinity(5__3) ? new TerrainSourceAnchor(float.NaN) : new TerrainSourceAnchor(5__3))); onComplete(obj); return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>7__wrap3 != null) { <>7__wrap3.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__17 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public IEnumerable targets; private <>c__DisplayClass17_0 <>8__1; public Action onComplete; private List 5__2; private List.Enumerator <>7__wrap2; private TerrainSupportStrategy 5__4; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__17(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 1) <= 1u) { try { } finally { <>m__Finally1(); } } <>8__1 = null; 5__2 = null; <>7__wrap2 = default(List.Enumerator); 5__4 = null; <>1__state = -2; } private bool MoveNext() { //IL_0097: Unknown result type (might be due to invalid IL or missing references) try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__2 = new List(); <>7__wrap2 = targets.ToList().GetEnumerator(); <>1__state = -3; goto IL_014e; case 1: <>1__state = -3; goto IL_00f2; case 2: { <>1__state = -3; <>8__1 = null; 5__4 = null; goto IL_014e; } IL_014e: if (<>7__wrap2.MoveNext()) { TerrainSupportTarget current = <>7__wrap2.Current; <>8__1 = new <>c__DisplayClass17_0(); 5__4 = SelectPlacementStrategy(current); <>8__1.samples = new List(); if (5__4 == ColliderFallbackStrategy) { <>2__current = CollectSupportSamplesAsync(current.Zone, current.Entries, current.SourceBaseY, delegate(List value) { <>8__1.samples = value; }); <>1__state = 1; return true; } <>8__1.samples = 5__4.CollectPlacementSamples(current); goto IL_00f2; } <>m__Finally1(); <>7__wrap2 = default(List.Enumerator); onComplete(BuildSupportFillPlacementContext(5__2)); return false; IL_00f2: if (<>8__1.samples.Count > 0) { 5__2.Add(new PlacementSupportSampleSet(5__4, <>8__1.samples)); } <>2__current = null; <>1__state = 2; return true; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>7__wrap2).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__88 : IEnumerable, IEnumerable, IEnumerator, IDisposable, IEnumerator { private int <>1__state; private Vector3 <>2__current; private int <>l__initialThreadId; private Bounds bounds; public Bounds <>3__bounds; private Vector3 5__2; private Vector3 5__3; Vector3 IEnumerator.Current { [DebuggerHidden] get { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return <>2__current; } } [DebuggerHidden] public d__88(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__2 = ((Bounds)(ref bounds)).min; 5__3 = ((Bounds)(ref bounds)).max; <>2__current = new Vector3(5__2.x, 5__2.y, 5__2.z); <>1__state = 1; return true; case 1: <>1__state = -1; <>2__current = new Vector3(5__2.x, 5__2.y, 5__3.z); <>1__state = 2; return true; case 2: <>1__state = -1; <>2__current = new Vector3(5__2.x, 5__3.y, 5__2.z); <>1__state = 3; return true; case 3: <>1__state = -1; <>2__current = new Vector3(5__2.x, 5__3.y, 5__3.z); <>1__state = 4; return true; case 4: <>1__state = -1; <>2__current = new Vector3(5__3.x, 5__2.y, 5__2.z); <>1__state = 5; return true; case 5: <>1__state = -1; <>2__current = new Vector3(5__3.x, 5__2.y, 5__3.z); <>1__state = 6; return true; case 6: <>1__state = -1; <>2__current = new Vector3(5__3.x, 5__3.y, 5__2.z); <>1__state = 7; return true; case 7: <>1__state = -1; <>2__current = new Vector3(5__3.x, 5__3.y, 5__3.z); <>1__state = 8; return true; case 8: <>1__state = -1; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) d__88 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__88(0); } d__.bounds = <>3__bounds; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } internal const string SupportFillMode = "support-fill-v1"; private const float HalfZoneSize = 32f; private const float SearchRadius = 48f; private const float SupportFillSampleStep = 1f; private const float SupportFillClearance = 0.05f; private const float FallbackSupportPlaneQuantization = 0.25f; private const float FallbackColliderSampleStep = 0.5f; private const float FallbackMaxColliderDepthBelowOrigin = 8f; private const float FallbackMaxTerrainDelta = 16f; private const int TerrainContextEntryBatchSize = 128; private const int TerrainApplyNodeBatchSize = 1024; private static readonly int SupportFillBaseLayerHash = StringExtensionMethods.GetStableHashCode("sighsorry.ZoneSavior.terrain_base_v1"); private static readonly TerrainSupportStrategy SavedContactStrategy = new SavedContactTerrainStrategy(); private static readonly TerrainSupportStrategy ColliderFallbackStrategy = new ColliderFallbackTerrainStrategy(); public static TerrainSourceAnchor ComputeSupportAnchor(IEnumerable zones) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) float num = float.PositiveInfinity; float num2 = float.PositiveInfinity; foreach (Vector2i zone in zones) { if (ZDOMan.instance == null || (Object)(object)ZNetScene.instance == (Object)null) { continue; } List list = new List(); ZDOMan.instance.FindObjects(zone, list); foreach (ZDO item in list) { if (TryReadSupportWearNTear(item, zone, ZoneBundleConfig.WearNTearSaveMode, out GameObject prefab) && TryGetWearNTearWorldBounds(prefab, item.GetPosition(), item.GetRotation(), ReadScale(item, prefab), out var bounds) && IsReasonableFallbackBoundsMinimum(item.GetPosition().y, ((Bounds)(ref bounds)).min.y)) { num = Mathf.Min(num, ((Bounds)(ref bounds)).min.y); } } foreach (ZDO item2 in list) { if (TryReadTamedMonster(item2, zone, out GameObject _)) { num2 = Mathf.Min(num2, item2.GetPosition().y); } } } if (!float.IsPositiveInfinity(num)) { return new TerrainSourceAnchor(num); } if (!float.IsPositiveInfinity(num2)) { return new TerrainSourceAnchor(num2); } return new TerrainSourceAnchor(float.NaN); } [IteratorStateMachine(typeof(d__15))] public static IEnumerator ComputeSupportAnchorAsync(IEnumerable zones, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__15(0) { zones = zones, onComplete = onComplete }; } public static TerrainPlacementContext? CreateSupportFillPlacementContext(IEnumerable targets) { return BuildSupportFillPlacementContext((from set in targets.ToList().Select(delegate(TerrainSupportTarget target) { TerrainSupportStrategy terrainSupportStrategy = SelectPlacementStrategy(target); return new PlacementSupportSampleSet(terrainSupportStrategy, terrainSupportStrategy.CollectPlacementSamples(target)); }) where set.Samples.Count > 0 select set).ToList()); } [IteratorStateMachine(typeof(d__17))] public static IEnumerator CreateSupportFillPlacementContextAsync(IEnumerable targets, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__17(0) { targets = targets, onComplete = onComplete }; } private static TerrainPlacementContext? BuildSupportFillPlacementContext(List sampleSets) { List list = sampleSets.SelectMany((PlacementSupportSampleSet set) => set.Samples).ToList(); if (list.Count == 0) { return null; } List list2 = CollapseToLowestSupportSamples(list); bool flag = sampleSets.Any((PlacementSupportSampleSet set) => set.Strategy == SavedContactStrategy); float baseWorldY = (flag ? SavedContactStrategy : ColliderFallbackStrategy).ResolveBaseWorldY(list2); TerrainPlacementContext terrainPlacementContext = new TerrainPlacementContext { BaseWorldY = baseWorldY, MinX = list.Min((TerrainSupportSample sample) => sample.WorldX), MaxX = list.Max((TerrainSupportSample sample) => sample.WorldX), MinZ = list.Min((TerrainSupportSample sample) => sample.WorldZ), MaxZ = list.Max((TerrainSupportSample sample) => sample.WorldZ), BlendWidth = 0f, SupportWidth = 0f }; foreach (TerrainSupportSample item in list2) { if (flag || ColliderFallbackStrategy.IsPlacementTargetUsable(item, baseWorldY)) { int x = Mathf.RoundToInt(item.WorldX); int z = Mathf.RoundToInt(item.WorldZ); terrainPlacementContext.SupportRelativeHeights[PackCell(x, z)] = item.RelativeY; } } return terrainPlacementContext; } public static TerrainPlacementContext CreateExactContext(float sourceBaseY, IEnumerable zones) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) List list = zones.Distinct().ToList(); float num = float.PositiveInfinity; float num2 = float.PositiveInfinity; float num3 = float.NegativeInfinity; float num4 = float.NegativeInfinity; foreach (Vector2i item in list) { Vector3 zonePos = ZoneSystem.GetZonePos(item); num = Mathf.Min(num, zonePos.x - 32f); num3 = Mathf.Max(num3, zonePos.x + 32f); num2 = Mathf.Min(num2, zonePos.z - 32f); num4 = Mathf.Max(num4, zonePos.z + 32f); } return new TerrainPlacementContext { BaseWorldY = sourceBaseY, MinX = num, MaxX = num3, MinZ = num2, MaxZ = num4, BlendWidth = 0f, SupportWidth = 0f }; } public static List CaptureSupportContacts(Vector2i zone, float sourceBaseY, IEnumerable entries, out bool contactsCaptured) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) contactsCaptured = false; List result = new List(); if (float.IsNaN(sourceBaseY) || !TryGetHeightmap(zone, out Heightmap _)) { return result; } contactsCaptured = true; List contacts = ZoneTerrainContactSampler.CaptureWorldContacts(ZoneTerrainContactSampler.FromZoneEntries(zone, sourceBaseY, entries), ZoneBundleConfig.SupportFillContactTolerance); return ZoneTerrainContactSampler.ToZoneBundleContacts(zone, sourceBaseY, contacts); } public static bool ApplySupportFill(Vector2i zone, IEnumerable entries, IEnumerable contacts, bool contactsCaptured, TerrainPlacementContext context) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) List list = contacts.ToList(); bool hasContacts = contactsCaptured && list.Count > 0; TerrainSupportApplyOptions applyOptions = TerrainSupportApplyOptions.ZoneBundle(); if (!TryGetHeightmap(zone, out Heightmap heightmap)) { throw new InvalidOperationException($"Target zone ({zone.x},{zone.y}) is not loaded for support terrain placement."); } TerrainSupportApplicationPlan terrainSupportApplicationPlan = BuildSupportPlan(zone, entries, list, hasContacts, context, heightmap, applyOptions); if (terrainSupportApplicationPlan.HasSupport) { return ApplySupportCellsToHeightmap(heightmap, terrainSupportApplicationPlan.SupportHeights, terrainSupportApplicationPlan.SupportCells, applyOptions); } return false; } public static bool HasApplicableSupportFill(Vector2i zone, IEnumerable entries, IEnumerable contacts, bool contactsCaptured, TerrainPlacementContext context) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) List list = contacts.ToList(); bool hasContacts = contactsCaptured && list.Count > 0; TerrainSupportApplyOptions applyOptions = TerrainSupportApplyOptions.ZoneBundle(); if (!TryGetHeightmap(zone, out Heightmap heightmap)) { throw new InvalidOperationException($"Target zone ({zone.x},{zone.y}) is not loaded for support terrain placement."); } return BuildSupportPlan(zone, entries, list, hasContacts, context, heightmap, applyOptions).HasSupport; } [IteratorStateMachine(typeof(d__23))] public static IEnumerator ApplySupportFillAsync(Vector2i zone, IEnumerable entries, IEnumerable contacts, bool contactsCaptured, TerrainPlacementContext context, Action onComplete) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__23(0) { zone = zone, entries = entries, contacts = contacts, contactsCaptured = contactsCaptured, context = context, onComplete = onComplete }; } public static bool IsSupportWearNTear(ZDO zdo, Vector2i zone, out GameObject prefab) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return TryReadSupportWearNTear(zdo, zone, ZoneBundleConfig.WearNTearSaveMode, out prefab); } public static bool CanApply(Vector2i zone) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) Heightmap heightmap; if (IsZoneLoaded(zone)) { return TryGetHeightmap(zone, out heightmap); } return false; } private static TerrainSupportApplicationPlan BuildSupportPlan(Vector2i zone, IEnumerable entries, IReadOnlyCollection contacts, bool hasContacts, TerrainPlacementContext context, Heightmap heightmap, TerrainSupportApplyOptions applyOptions) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) Dictionary supportHeights = new Dictionary(); if (context.SupportRelativeHeights.Count > 0) { AddContextSupportHeights(context, heightmap, applyOptions.FeatherWidth, supportHeights); } else { TerrainSupportStrategy terrainSupportStrategy = SelectApplyStrategy(hasContacts); foreach (TerrainSupportSample item in terrainSupportStrategy.CollectApplySamples(zone, entries, contacts)) { float targetHeight = context.BaseWorldY + item.RelativeY - 0.05f; if (terrainSupportStrategy.IsApplyTargetUsable(item, targetHeight)) { AddSupportHeight(Mathf.RoundToInt(item.WorldX), Mathf.RoundToInt(item.WorldZ), targetHeight, supportHeights); } } } return new TerrainSupportApplicationPlan(supportHeights, ToSupportCells(supportHeights)); } private static void AddContextSupportHeights(TerrainPlacementContext context, Heightmap heightmap, float featherWidth, Dictionary supportHeights) { GetHeightmapWorldBounds(heightmap, featherWidth + 1f, out var minX, out var maxX, out var minZ, out var maxZ); foreach (KeyValuePair supportRelativeHeight in context.SupportRelativeHeights) { UnpackCell(supportRelativeHeight.Key, out var x, out var z); if (!((float)x < minX) && !((float)x > maxX) && !((float)z < minZ) && !((float)z > maxZ)) { float targetHeight = context.BaseWorldY + supportRelativeHeight.Value - 0.05f; AddSupportHeight(x, z, targetHeight, supportHeights); } } } private static List ToSupportCells(Dictionary supportHeights) { List list = new List(); foreach (KeyValuePair supportHeight in supportHeights) { UnpackCell(supportHeight.Key, out var x, out var z); list.Add(new TerrainSupportCell(x, z, supportHeight.Value)); } return list; } private static void AddSupportHeight(int x, int z, float targetHeight, Dictionary supportHeights) { long key = PackCell(x, z); if (!supportHeights.TryGetValue(key, out var value) || targetHeight < value) { supportHeights[key] = targetHeight; } } private static void GetHeightmapWorldBounds(Heightmap heightmap, float padding, out float minX, out float maxX, out float minZ, out float maxZ) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)heightmap).transform.position; float num = (float)heightmap.m_width * heightmap.m_scale * 0.5f; minX = position.x - num - padding; maxX = position.x + num + padding; minZ = position.z - num - padding; maxZ = position.z + num + padding; } public static bool TryGetWearNTearBounds(GameObject prefab, Vector3 position, Quaternion rotation, Vector3 scale, out Bounds bounds) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) return TryGetWearNTearWorldBounds(prefab, position, rotation, scale, out bounds); } public static bool TryGetTerrainHeight(float x, float z, out float height) { return TryGetCurrentTerrainHeight(x, z, out height); } public static bool ApplyWorldSupportContacts(IEnumerable supportContacts) { //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) List list = (from contact in supportContacts select new TerrainSupportCell(Mathf.RoundToInt(contact.x), Mathf.RoundToInt(contact.z), contact.y - 0.05f) into cell group cell by PackCell(cell.X, cell.Z) into @group select @group.OrderBy((TerrainSupportCell cell) => cell.Height).First()).ToList(); if (list.Count == 0) { return false; } Dictionary supportHeights = list.ToDictionary((TerrainSupportCell cell) => PackCell(cell.X, cell.Z), (TerrainSupportCell cell) => cell.Height); List list2 = list.Select((TerrainSupportCell cell) => ZoneSystem.GetZone(new Vector3((float)cell.X, 0f, (float)cell.Z))).Distinct().ToList(); bool flag = false; foreach (Vector2i item in list2) { if (!TryGetHeightmap(item, out Heightmap heightmap)) { throw new InvalidOperationException($"Target terrain zone ({item.x},{item.y}) is not loaded for blueprint support placement."); } flag |= ApplySupportCellsToHeightmap(heightmap, supportHeights, list, TerrainSupportApplyOptions.Blueprint()); } return flag; } [IteratorStateMachine(typeof(d__34))] public static IEnumerator ApplyWorldSupportContactsAsync(IEnumerable supportContacts, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__34(0) { supportContacts = supportContacts, onComplete = onComplete }; } public static void ApplyBaseLayer(Heightmap heightmap) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) TerrainComp val = TerrainComp.FindTerrainCompiler(((Component)heightmap).transform.position); if (!IsCompilerReady(val)) { return; } byte[] byteArray = val.m_nview.GetZDO().GetByteArray(SupportFillBaseLayerHash, (byte[])null); if (byteArray == null || byteArray.Length == 0 || !TryDeserializeBaseLayer(byteArray, heightmap, out int width, out float[] worldHeights, out Color[] paints) || width != heightmap.m_width + 1 || worldHeights.Length != heightmap.m_heights.Count || (paints.Length != 0 && paints.Length != worldHeights.Length)) { return; } float y = ((Component)heightmap).transform.position.y; for (int i = 0; i < worldHeights.Length; i++) { heightmap.m_heights[i] = worldHeights[i] - y; } if (paints.Length != worldHeights.Length) { return; } for (int j = 0; j < width; j++) { for (int k = 0; k < width; k++) { heightmap.m_paintMask.SetPixel(k, j, paints[j * width + k]); } } } internal static void ResetSupportFillBaseLayer(IEnumerable? heightNodes, IEnumerable? paintNodes, Vector3 position, float radius) { //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) Dictionary> dictionary = CollectTerrainNodeIndices(heightNodes); Dictionary> dictionary2 = CollectTerrainNodeIndices(paintNodes); if (dictionary.Count == 0 && dictionary2.Count == 0) { return; } HashSet hashSet = dictionary.Keys.Concat(dictionary2.Keys).ToHashSet(); int num = 0; foreach (TerrainComp item in hashSet) { if (!TryLoadSupportFillBaseLayer(item, out int width, out float[] worldHeights, out Color[] paints)) { continue; } bool flag = false; if (dictionary.TryGetValue(item, out var value)) { foreach (int item2 in value) { if (IsValidPayloadIndex(item2, width, worldHeights.Length)) { IndexToXZ(item2, width, out var x, out var z); Vector3 val = VertexToWorld(item.m_hmap, x, z); if (TryGetTerrainBaseHeight(val.x, val.z, out var height) && Mathf.Abs(worldHeights[item2] - height) > 0.01f) { worldHeights[item2] = height; flag = true; } } } } bool num2 = paints.Length == width * width; Color[] array = (num2 ? TryGetBasePaints(item.m_hmap, width) : null); if (num2 && array != null && dictionary2.TryGetValue(item, out var value2)) { foreach (int item3 in value2) { if (IsValidPayloadIndex(item3, width, paints.Length) && item3 < array.Length) { Color val2 = array[item3]; if (!Approximately(paints[item3], val2)) { paints[item3] = val2; flag = true; } } } } if (flag) { if (IsSupportFillBaseLayerNative(item.m_hmap, width, worldHeights, paints, array)) { item.m_nview.GetZDO().Set(SupportFillBaseLayerHash, Array.Empty()); } else { item.m_nview.GetZDO().Set(SupportFillBaseLayerHash, SerializeBaseLayer(item.m_hmap, width, worldHeights, paints)); } PersistCompiler(item); num++; } } if (num > 0) { ClutterSystem instance = ClutterSystem.instance; if (instance != null) { instance.ResetGrass(position, radius); } } } private static bool TryLoadSupportFillBaseLayer(TerrainComp compiler, out int width, out float[] worldHeights, out Color[] paints) { width = 0; worldHeights = Array.Empty(); paints = Array.Empty(); if (!IsCompilerReady(compiler)) { return false; } byte[] byteArray = compiler.m_nview.GetZDO().GetByteArray(SupportFillBaseLayerHash, (byte[])null); if (byteArray != null && byteArray.Length != 0 && TryDeserializeBaseLayer(byteArray, compiler.m_hmap, out width, out worldHeights, out paints) && width == compiler.m_hmap.m_width + 1 && worldHeights.Length == width * width) { if (paints.Length != 0) { return paints.Length == worldHeights.Length; } return true; } return false; } private static Dictionary> CollectTerrainNodeIndices(IEnumerable? nodes) { Dictionary> dictionary = new Dictionary>(); if (nodes == null) { return dictionary; } foreach (object node in nodes) { if (TryReadTerrainNode(node, out TerrainComp compiler, out int index)) { if (!dictionary.TryGetValue(compiler, out var value)) { value = (dictionary[compiler] = new HashSet()); } value.Add(index); } } return dictionary; } private static bool TryReadTerrainNode(object? node, out TerrainComp compiler, out int index) { compiler = null; index = -1; if (node == null) { return false; } Type type = node.GetType(); FieldInfo fieldInfo = AccessTools.Field(type, "Compiler"); FieldInfo fieldInfo2 = AccessTools.Field(type, "Index"); object? obj = fieldInfo?.GetValue(node); TerrainComp val = (TerrainComp)((obj is TerrainComp) ? obj : null); object obj2 = fieldInfo2?.GetValue(node); if ((Object)(object)val == (Object)null || !(obj2 is int num)) { return false; } compiler = val; index = num; return true; } private static bool IsValidPayloadIndex(int index, int width, int length) { if (width > 0 && index >= 0 && index < length) { return index < width * width; } return false; } private static void IndexToXZ(int index, int width, out int x, out int z) { z = index / width; x = index - z * width; } private static Color[]? TryGetBasePaints(Heightmap heightmap, int width) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) if (HeightmapBuilder.instance == null || WorldGenerator.instance == null) { return null; } try { HMBuildData val = HeightmapBuilder.instance.RequestTerrainSync(((Component)heightmap).transform.position, heightmap.m_width, heightmap.m_scale, heightmap.IsDistantLod, WorldGenerator.instance); return (val.m_baseMask != null && val.m_baseMask.Length == width * width) ? val.m_baseMask : null; } catch { return null; } } private static bool IsSupportFillBaseLayerNative(Heightmap heightmap, int width, float[] worldHeights, Color[] paints, Color[]? basePaints) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) bool flag = paints.Length == width * width; if (flag && (basePaints == null || basePaints.Length != paints.Length)) { return false; } for (int i = 0; i < worldHeights.Length; i++) { IndexToXZ(i, width, out var x, out var z); Vector3 val = VertexToWorld(heightmap, x, z); if (!TryGetTerrainBaseHeight(val.x, val.z, out var height) || Mathf.Abs(worldHeights[i] - height) > 0.01f || (flag && !Approximately(paints[i], basePaints[i]))) { return false; } } return true; } private static bool Approximately(Color a, Color b) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) if (Mathf.Abs(a.r - b.r) < 0.001f && Mathf.Abs(a.g - b.g) < 0.001f && Mathf.Abs(a.b - b.b) < 0.001f) { return Mathf.Abs(a.a - b.a) < 0.001f; } return false; } private static List CollapseToLowestSupportSamples(IEnumerable samples) { Dictionary dictionary = new Dictionary(); foreach (TerrainSupportSample sample in samples) { int num = Mathf.RoundToInt(sample.WorldX); int num2 = Mathf.RoundToInt(sample.WorldZ); long key = PackCell(num, num2); if (!dictionary.TryGetValue(key, out var value) || sample.RelativeY < value.RelativeY) { dictionary[key] = new TerrainSupportSample(num, num2, sample.RelativeY); } } return dictionary.Values.ToList(); } private static float ResolveSupportFillBaseWorldY(List samples) { if (samples.Count == 0) { return 0f; } List list = new List(); TerrainSupportSample terrainSupportSample = samples.OrderBy((TerrainSupportSample sample) => sample.RelativeY).First(); float result = 0f - terrainSupportSample.RelativeY; foreach (TerrainSupportSample sample in samples) { if (TryGetTerrainBaseHeight(sample.WorldX, sample.WorldZ, out var height)) { float num = height - sample.RelativeY; list.Add(num); if (Mathf.Approximately(sample.WorldX, terrainSupportSample.WorldX) && Mathf.Approximately(sample.WorldZ, terrainSupportSample.WorldZ) && Mathf.Approximately(sample.RelativeY, terrainSupportSample.RelativeY)) { result = num; } } } if (list.Count == 0) { return result; } return GetMedianOffset(list); } private static float ResolveFallbackSupportBaseWorldY(List samples) { if (samples.Count == 0) { return 0f; } Dictionary> dictionary = new Dictionary>(); foreach (TerrainSupportSample sample in samples) { int key = Mathf.RoundToInt(sample.RelativeY / 0.25f); if (!dictionary.TryGetValue(key, out var value)) { value = (dictionary[key] = new List()); } value.Add(sample); } KeyValuePair> keyValuePair = (from item in dictionary orderby item.Value.Count descending, item.Key select item).First(); float medianOffset = GetMedianOffset(keyValuePair.Value.Select((TerrainSupportSample sample) => sample.RelativeY).ToList()); List list2 = new List(); foreach (TerrainSupportSample item in keyValuePair.Value) { if (TryGetTerrainBaseHeight(item.WorldX, item.WorldZ, out var height)) { list2.Add(height); } } if (list2.Count != 0) { return GetMedianOffset(list2) - medianOffset; } return 0f - medianOffset; } private static bool IsReasonableFallbackSupportTarget(TerrainSupportSample sample, float baseWorldY) { return IsReasonableFallbackTarget(sample.WorldX, sample.WorldZ, baseWorldY + sample.RelativeY - 0.05f); } private static bool IsReasonableFallbackTarget(float worldX, float worldZ, float targetHeight) { if (TryGetTerrainBaseHeight(worldX, worldZ, out var height)) { return Mathf.Abs(targetHeight - height) <= 16f; } return true; } private static bool IsReasonableFallbackBoundsMinimum(float originY, float boundsMinY) { return boundsMinY >= originY - 8f; } private static float GetMedianOffset(List offsets) { offsets.Sort(); int num = offsets.Count / 2; if (offsets.Count % 2 != 1) { return (offsets[num - 1] + offsets[num]) * 0.5f; } return offsets[num]; } private static bool TryGetFeatheredSupportHeight(Vector3 node, float baseHeight, TerrainSupportCellIndex supportIndex, float featherWidth, out float height) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) height = baseHeight; if (featherWidth <= 0f) { return false; } float maxDistanceSqr = featherWidth * featherWidth; if (!supportIndex.TryGetNearest(node, maxDistanceSqr, out var nearest, out var bestDistanceSqr)) { return false; } float num = Mathf.Sqrt(bestDistanceSqr); float num2 = 1f - Mathf.Clamp01(num / featherWidth); num2 = num2 * num2 * (3f - 2f * num2); height = Mathf.Lerp(baseHeight, nearest.Height, num2); return true; } private static bool ApplySupportCellsToHeightmap(Heightmap heightmap, Dictionary supportHeights, List supportCells, TerrainSupportApplyOptions applyOptions) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) int num = heightmap.m_width + 1; float[] array = new float[num * num]; Color[] array2 = (Color[])(object)new Color[num * num]; TerrainSupportCellIndex supportIndex = new TerrainSupportCellIndex(supportCells, applyOptions.FeatherWidth); bool flag = false; for (int i = 0; i < num; i++) { for (int j = 0; j < num; j++) { int num2 = i * num + j; Vector3 val = VertexToWorld(heightmap, j, i); float worldHeight = GetWorldHeight(heightmap, j, i); float height; float num3 = (TryGetTerrainBaseHeight(val.x, val.z, out height) ? height : worldHeight); float num4 = num3; array2[num2] = GetPaint(heightmap, j, i); float height2; if (supportHeights.TryGetValue(PackCell(Mathf.RoundToInt(val.x), Mathf.RoundToInt(val.z)), out var value)) { num4 = applyOptions.ClampTerrainDelta(value, num3); } else if (TryGetFeatheredSupportHeight(val, num3, supportIndex, applyOptions.FeatherWidth, out height2)) { num4 = applyOptions.ClampTerrainDelta(height2, num3); } array[num2] = num4; if (Mathf.Abs(worldHeight - num4) > 0.01f) { flag = true; } } } if (!flag) { return false; } PersistSupportFillTerrain(heightmap.GetAndCreateTerrainCompiler(), num, array, array2, applyOptions); heightmap.Poke(false); ClutterSystem instance = ClutterSystem.instance; if (instance != null) { instance.ResetGrass(((Component)heightmap).transform.position, 48f); } return true; } [IteratorStateMachine(typeof(d__54))] private static IEnumerator ApplySupportCellsToHeightmapAsync(Heightmap heightmap, Dictionary supportHeights, List supportCells, TerrainSupportApplyOptions applyOptions, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__54(0) { heightmap = heightmap, supportHeights = supportHeights, supportCells = supportCells, applyOptions = applyOptions, onComplete = onComplete }; } private static byte[] SerializeBaseLayer(Heightmap heightmap, int width, float[] worldHeights, Color[] paints) { Color[] paints2 = (ShouldSerializePaints(heightmap, width, paints) ? paints : Array.Empty()); return SerializeSparseBaseLayer(heightmap, width, worldHeights, paints2); } private static byte[] SerializeSparseBaseLayer(Heightmap heightmap, int width, float[] worldHeights, Color[] paints) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Expected O, but got Unknown //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) List list = new List(); List list2 = new List(); for (int i = 0; i < worldHeights.Length; i++) { IndexToXZ(i, width, out var x, out var z); Vector3 val = VertexToWorld(heightmap, x, z); float height; float num = (TryGetTerrainBaseHeight(val.x, val.z, out height) ? height : GetWorldHeight(heightmap, x, z)); if (!(Mathf.Abs(worldHeights[i] - num) <= 0.01f)) { list.Add(i); list2.Add(worldHeights[i]); } } List list3 = new List(); List list4 = new List(); if (paints.Length == worldHeights.Length) { Color[] array = TryGetBasePaints(heightmap, width); for (int j = 0; j < paints.Length; j++) { Color b = ((array != null && array.Length == paints.Length) ? array[j] : GetPaint(heightmap, j % width, j / width)); if (!Approximately(paints[j], b)) { list3.Add(j); list4.Add(paints[j]); } } } ZPackage val2 = new ZPackage(); val2.Write(3); val2.Write(width); val2.Write(worldHeights.Length); val2.Write(list.Count); for (int k = 0; k < list.Count; k++) { val2.Write(list[k]); val2.Write(list2[k]); } val2.Write(list3.Count); for (int l = 0; l < list3.Count; l++) { val2.Write(list3[l]); WriteColor(val2, list4[l]); } return Utils.Compress(val2.GetArray()); } private static bool ShouldSerializePaints(Heightmap heightmap, int width, Color[] paints) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) if (paints.Length != width * width) { return false; } Color[] array = TryGetBasePaints(heightmap, width); if (array == null || array.Length != paints.Length) { return true; } for (int i = 0; i < paints.Length; i++) { if (!Approximately(paints[i], array[i])) { return true; } } return false; } private static bool TryDeserializeBaseLayer(byte[] payload, Heightmap heightmap, out int width, out float[] worldHeights, out Color[] paints) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown width = 0; worldHeights = Array.Empty(); paints = Array.Empty(); try { ZPackage val = new ZPackage(Utils.Decompress(payload)); if (val.ReadInt() != 3) { return false; } width = val.ReadInt(); int heightCount = val.ReadInt(); return TryDeserializeSparseBaseLayer(val, heightmap, width, heightCount, out worldHeights, out paints); } catch { return false; } } private static bool TryDeserializeSparseBaseLayer(ZPackage package, Heightmap heightmap, int width, int heightCount, out float[] worldHeights, out Color[] paints) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) worldHeights = new float[heightCount]; paints = Array.Empty(); if ((Object)(object)heightmap == (Object)null || width <= 0 || width != heightmap.m_width + 1 || heightCount != width * width) { return false; } for (int i = 0; i < worldHeights.Length; i++) { IndexToXZ(i, width, out var x, out var z); Vector3 val = VertexToWorld(heightmap, x, z); worldHeights[i] = (TryGetTerrainBaseHeight(val.x, val.z, out var height) ? height : GetWorldHeight(heightmap, x, z)); } int num = package.ReadInt(); for (int j = 0; j < num; j++) { int num2 = package.ReadInt(); float num3 = package.ReadSingle(); if (num2 < 0 || num2 >= worldHeights.Length) { return false; } worldHeights[num2] = num3; } int num4 = package.ReadInt(); if (num4 <= 0) { return true; } paints = TryGetBasePaints(heightmap, width) ?? BuildCurrentPaintLayer(heightmap, width); if (paints.Length != worldHeights.Length) { return false; } for (int k = 0; k < num4; k++) { int num5 = package.ReadInt(); Color val2 = ReadColor(package); if (num5 < 0 || num5 >= paints.Length) { return false; } paints[num5] = val2; } return true; } private static Color[] BuildCurrentPaintLayer(Heightmap heightmap, int width) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) Color[] array = (Color[])(object)new Color[width * width]; for (int i = 0; i < width; i++) { for (int j = 0; j < width; j++) { array[i * width + j] = GetPaint(heightmap, j, i); } } return array; } private static void PersistSupportFillTerrain(TerrainComp compiler, int width, float[] worldHeights, Color[] paints, TerrainSupportApplyOptions applyOptions) { if (applyOptions.UseVanillaTerrainDelta) { PersistSupportFillVanillaDelta(compiler, width, worldHeights, applyOptions.MaxTerrainDelta); } else { PersistSupportFillBaseLayer(compiler, width, worldHeights, paints); } } private static void PersistSupportFillVanillaDelta(TerrainComp compiler, int width, float[] worldHeights, float maxTerrainDelta) { //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) if (!IsCompilerReady(compiler)) { throw new InvalidOperationException("Target terrain compiler is not network ready."); } int num = width * width; if (worldHeights.Length != num || compiler.m_modifiedHeight.Length != num || compiler.m_levelDelta.Length != num || compiler.m_smoothDelta.Length != num) { throw new InvalidOperationException("Target terrain compiler size does not match the heightmap."); } if (!compiler.m_nview.IsOwner()) { compiler.m_nview.ClaimOwnership(); } float num2 = ((maxTerrainDelta > 0f) ? maxTerrainDelta : 8f); for (int i = 0; i < num; i++) { IndexToXZ(i, width, out var x, out var z); Vector3 val = VertexToWorld(compiler.m_hmap, x, z); float height; float num3 = (TryGetTerrainBaseHeight(val.x, val.z, out height) ? height : GetWorldHeight(compiler.m_hmap, x, z)); float num4 = Mathf.Clamp(worldHeights[i] - num3, 0f - num2, num2); compiler.m_smoothDelta[i] = 0f; compiler.m_levelDelta[i] = num4; compiler.m_modifiedHeight[i] = Mathf.Abs(num4) > 0.01f; } compiler.m_nview.GetZDO().Set(SupportFillBaseLayerHash, Array.Empty()); PersistCompiler(compiler); } private static void PersistSupportFillBaseLayer(TerrainComp compiler, int width, float[] worldHeights, Color[] paints) { if (!IsCompilerReady(compiler)) { throw new InvalidOperationException("Target terrain compiler is not network ready."); } if (!compiler.m_nview.IsOwner()) { compiler.m_nview.ClaimOwnership(); } Array.Clear(compiler.m_modifiedHeight, 0, compiler.m_modifiedHeight.Length); Array.Clear(compiler.m_levelDelta, 0, compiler.m_levelDelta.Length); Array.Clear(compiler.m_smoothDelta, 0, compiler.m_smoothDelta.Length); Array.Clear(compiler.m_modifiedPaint, 0, compiler.m_modifiedPaint.Length); Array.Clear(compiler.m_paintMask, 0, compiler.m_paintMask.Length); compiler.m_nview.GetZDO().Set(SupportFillBaseLayerHash, SerializeBaseLayer(compiler.m_hmap, width, worldHeights, paints)); PersistCompiler(compiler); } private static void PersistCompiler(TerrainComp compiler) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)compiler.m_nview != (Object)null && compiler.m_nview.IsValid() && !compiler.m_nview.IsOwner()) { compiler.m_nview.ClaimOwnership(); } compiler.m_operations++; compiler.m_lastOpPoint = Vector3.zero; compiler.m_lastOpRadius = 0f; compiler.Save(); compiler.m_hmap.Poke(false); } private static float GetWorldHeight(Heightmap heightmap, int x, int z) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) return heightmap.GetHeight(x, z) + ((Component)heightmap).transform.position.y; } private static bool TryGetTerrainBaseHeight(float x, float z, out float height) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (WorldGenerator.instance != null) { height = WorldGenerator.instance.GetHeight(x, z); return true; } if (Heightmap.GetHeight(new Vector3(x, 0f, z), ref height)) { return true; } height = 0f; return false; } private static bool TryGetCurrentTerrainHeight(float x, float z, out float height) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) return Heightmap.GetHeight(new Vector3(x, 0f, z), ref height); } private static Color GetPaint(Heightmap heightmap, int x, int z) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.Clamp(x, 0, heightmap.m_width); int num2 = Mathf.Clamp(z, 0, heightmap.m_width); return heightmap.GetPaintMask(num, num2); } private static bool TryGetHeightmap(Vector2i zone, out Heightmap heightmap) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) heightmap = null; if (!IsZoneLoaded(zone)) { return false; } heightmap = Heightmap.FindHeightmap(ZoneSystem.GetZonePos(zone)); return (Object)(object)heightmap != (Object)null; } private static bool IsZoneLoaded(Vector2i zone) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZoneSystem.instance != (Object)null) { return ZoneSystem.instance.IsZoneLoaded(zone); } return false; } private static bool IsCompilerReady(TerrainComp compiler) { if ((Object)(object)compiler == (Object)null || (Object)(object)compiler.m_hmap == (Object)null) { return false; } ZNetView component = ((Component)compiler).GetComponent(); if ((Object)(object)component != (Object)null) { return component.IsValid(); } return false; } private static TerrainSupportStrategy SelectPlacementStrategy(TerrainSupportTarget target) { if (!target.ContactsCaptured || target.Contacts.Count <= 0) { return ColliderFallbackStrategy; } return SavedContactStrategy; } private static TerrainSupportStrategy SelectApplyStrategy(bool hasContacts) { if (!hasContacts) { return ColliderFallbackStrategy; } return SavedContactStrategy; } private static List CollectSavedContactSamples(Vector2i zone, IEnumerable contacts) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) Vector3 zoneCenter = ZoneSystem.GetZonePos(zone); return contacts.Select((ZoneBundleTerrainContact contact) => new TerrainSupportSample(zoneCenter.x + contact.LocalX, zoneCenter.z + contact.LocalZ, contact.RelativeY)).ToList(); } private static List CollectSupportSamples(Vector2i zone, IEnumerable entries, float baseWorldY = 0f) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) List list = new List(); Vector3 zonePos = ZoneSystem.GetZonePos(zone); bool flag = !float.IsNaN(baseWorldY); Vector3 val = default(Vector3); Quaternion rotation = default(Quaternion); Vector3 scale = default(Vector3); foreach (ZoneBundleEntry entry in entries) { GameObject prefab = ZNetScene.instance.GetPrefab(entry.Prefab); if (!Object.op_Implicit((Object)(object)prefab) || (Object)(object)prefab.GetComponent() == (Object)null) { continue; } float num = (flag ? (baseWorldY + entry.LocalPos[1]) : entry.LocalPos[1]); ((Vector3)(ref val))..ctor(zonePos.x + entry.LocalPos[0], num, zonePos.z + entry.LocalPos[2]); ((Quaternion)(ref rotation))..ctor(entry.Rot[0], entry.Rot[1], entry.Rot[2], entry.Rot[3]); ((Vector3)(ref scale))..ctor(entry.Scale[0], entry.Scale[1], entry.Scale[2]); List list2 = new List(); AddWearNTearSupportSamples(prefab, val, rotation, scale, flag ? baseWorldY : 0f, list2); float num2 = (flag ? (val.y - baseWorldY) : entry.LocalPos[1]) - 8f; foreach (TerrainSupportSample item in list2) { if (item.RelativeY >= num2) { list.Add(item); } } } return list; } [IteratorStateMachine(typeof(d__76))] private static IEnumerator CollectSupportSamplesAsync(Vector2i zone, IEnumerable entries, float baseWorldY, Action> onComplete) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__76(0) { zone = zone, entries = entries, baseWorldY = baseWorldY, onComplete = onComplete }; } private static void AddWearNTearSupportSamples(GameObject prefab, Vector3 position, Quaternion rotation, Vector3 scale, float baseWorldY, List samples) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) Collider[] componentsInChildren = prefab.GetComponentsInChildren(); Matrix4x4 val = Matrix4x4.TRS(position, rotation, scale); int count = samples.Count; Collider[] array = componentsInChildren; foreach (Collider val2 in array) { if (!((Object)(object)val2 == (Object)null) && val2.enabled && !val2.isTrigger && TryGetColliderLocalBounds(val2, out var bounds)) { Matrix4x4 val3 = prefab.transform.worldToLocalMatrix * ((Component)val2).transform.localToWorldMatrix; Matrix4x4 colliderToWorld = val * val3; MeshCollider val4 = (MeshCollider)(object)((val2 is MeshCollider) ? val2 : null); if (val4 == null || val4.sharedMesh == null || !AddMeshColliderSupportSamples(val4.sharedMesh, colliderToWorld, baseWorldY, samples)) { AddColliderBottomSamples(bounds, colliderToWorld, baseWorldY, samples); } } } if (samples.Count == count && TryGetWearNTearWorldBounds(prefab, position, rotation, scale, out var bounds2)) { AddBoundsSamples(bounds2, samples, baseWorldY); } } private static void AddColliderBottomSamples(Bounds bounds, Matrix4x4 colliderToWorld, float baseWorldY, List samples) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) int fallbackSampleSteps = GetFallbackSampleSteps(((Bounds)(ref bounds)).size.x); int fallbackSampleSteps2 = GetFallbackSampleSteps(((Bounds)(ref bounds)).size.z); Vector3 val = default(Vector3); for (int i = 0; i <= fallbackSampleSteps; i++) { float num = ((fallbackSampleSteps == 0) ? 0.5f : ((float)i / (float)fallbackSampleSteps)); for (int j = 0; j <= fallbackSampleSteps2; j++) { float num2 = ((fallbackSampleSteps2 == 0) ? 0.5f : ((float)j / (float)fallbackSampleSteps2)); ((Vector3)(ref val))..ctor(Mathf.Lerp(((Bounds)(ref bounds)).min.x, ((Bounds)(ref bounds)).max.x, num), ((Bounds)(ref bounds)).min.y, Mathf.Lerp(((Bounds)(ref bounds)).min.z, ((Bounds)(ref bounds)).max.z, num2)); Vector3 val2 = ((Matrix4x4)(ref colliderToWorld)).MultiplyPoint3x4(val); samples.Add(new TerrainSupportSample(val2.x, val2.z, val2.y - baseWorldY)); } } } private static bool AddMeshColliderSupportSamples(Mesh mesh, Matrix4x4 colliderToWorld, float baseWorldY, List samples) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) Vector3[] vertices = mesh.vertices; int[] triangles = mesh.triangles; int count = samples.Count; for (int i = 0; i + 2 < triangles.Length; i += 3) { Vector3 a = ((Matrix4x4)(ref colliderToWorld)).MultiplyPoint3x4(vertices[triangles[i]]); Vector3 b = ((Matrix4x4)(ref colliderToWorld)).MultiplyPoint3x4(vertices[triangles[i + 1]]); Vector3 c = ((Matrix4x4)(ref colliderToWorld)).MultiplyPoint3x4(vertices[triangles[i + 2]]); AddTriangleSupportSamples(a, b, c, baseWorldY, samples); } return samples.Count > count; } private static void AddTriangleSupportSamples(Vector3 a, Vector3 b, Vector3 c, float baseWorldY, List samples) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Floor(Mathf.Min(a.x, Mathf.Min(b.x, c.x))); float num2 = Mathf.Ceil(Mathf.Max(a.x, Mathf.Max(b.x, c.x))); float num3 = Mathf.Floor(Mathf.Min(a.z, Mathf.Min(b.z, c.z))); float num4 = Mathf.Ceil(Mathf.Max(a.z, Mathf.Max(b.z, c.z))); float num5 = (b.z - c.z) * (a.x - c.x) + (c.x - b.x) * (a.z - c.z); if (Mathf.Abs(num5) < 0.0001f) { return; } for (float num6 = num; num6 <= num2; num6 += 0.5f) { for (float num7 = num3; num7 <= num4; num7 += 0.5f) { if (TryGetTriangleYAtXZ(a, b, c, num5, num6, num7, out var y)) { samples.Add(new TerrainSupportSample(num6, num7, y - baseWorldY)); } } } } private static bool TryGetTriangleYAtXZ(Vector3 a, Vector3 b, Vector3 c, float denominator, float x, float z, out float y) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) y = 0f; float num = ((b.z - c.z) * (x - c.x) + (c.x - b.x) * (z - c.z)) / denominator; float num2 = ((c.z - a.z) * (x - c.x) + (a.x - c.x) * (z - c.z)) / denominator; float num3 = 1f - num - num2; if (num < -0.001f || num2 < -0.001f || num3 < -0.001f) { return false; } y = num * a.y + num2 * b.y + num3 * c.y; return true; } private static int GetFallbackSampleSteps(float size) { return Mathf.Clamp(Mathf.CeilToInt(Mathf.Abs(size) / 0.5f), 1, 64); } private static void AddBoundsSamples(Bounds bounds, List samples, float baseWorldY) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.FloorToInt(((Bounds)(ref bounds)).min.x); int num2 = Mathf.CeilToInt(((Bounds)(ref bounds)).max.x); int num3 = Mathf.FloorToInt(((Bounds)(ref bounds)).min.z); int num4 = Mathf.CeilToInt(((Bounds)(ref bounds)).max.z); if (num == num2) { num2++; } if (num3 == num4) { num4++; } float relativeY = (float.IsNaN(baseWorldY) ? ((Bounds)(ref bounds)).min.y : (((Bounds)(ref bounds)).min.y - baseWorldY)); for (float num5 = num; num5 <= (float)num2; num5 += 1f) { for (float num6 = num3; num6 <= (float)num4; num6 += 1f) { samples.Add(new TerrainSupportSample(num5, num6, relativeY)); } } } private static bool TryReadSupportWearNTear(ZDO zdo, Vector2i zone, ZoneBundleWearNTearSaveMode saveMode, out GameObject prefab) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) prefab = null; if (zdo == null || !zdo.IsValid() || ZoneSystem.GetZone(zdo.GetPosition()) != zone) { return false; } if (saveMode == ZoneBundleWearNTearSaveMode.CreatorOnly && zdo.GetLong(ZDOVars.s_creator, 0L) == 0L) { return false; } prefab = ZNetScene.instance.GetPrefab(zdo.GetPrefab()); if (Object.op_Implicit((Object)(object)prefab)) { return (Object)(object)prefab.GetComponent() != (Object)null; } return false; } private static bool TryReadTamedMonster(ZDO zdo, Vector2i zone, out GameObject prefab) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) prefab = null; if (zdo == null || !zdo.IsValid() || ZoneSystem.GetZone(zdo.GetPosition()) != zone || !zdo.GetBool(ZDOVars.s_tamed, false)) { return false; } prefab = ZNetScene.instance.GetPrefab(zdo.GetPrefab()); if (Object.op_Implicit((Object)(object)prefab) && (Object)(object)prefab.GetComponent() != (Object)null) { return (Object)(object)prefab.GetComponent() != (Object)null; } return false; } private static bool TryGetWearNTearWorldBounds(GameObject prefab, Vector3 position, Quaternion rotation, Vector3 scale, out Bounds bounds) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) bounds = default(Bounds); Collider[] componentsInChildren = prefab.GetComponentsInChildren(); Matrix4x4 val = Matrix4x4.TRS(position, rotation, scale); bool flag = false; Collider[] array = componentsInChildren; foreach (Collider val2 in array) { if ((Object)(object)val2 == (Object)null || !val2.enabled || val2.isTrigger || !TryGetColliderLocalBounds(val2, out var bounds2)) { continue; } Matrix4x4 val3 = prefab.transform.worldToLocalMatrix * ((Component)val2).transform.localToWorldMatrix; foreach (Vector3 boundsCorner in GetBoundsCorners(bounds2)) { Vector3 val4 = ((Matrix4x4)(ref val)).MultiplyPoint3x4(((Matrix4x4)(ref val3)).MultiplyPoint3x4(boundsCorner)); if (flag) { ((Bounds)(ref bounds)).Encapsulate(val4); continue; } bounds = new Bounds(val4, Vector3.zero); flag = true; } } return flag; } private static bool TryGetColliderLocalBounds(Collider collider, out Bounds bounds) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) BoxCollider val = (BoxCollider)(object)((collider is BoxCollider) ? collider : null); if (val == null) { SphereCollider val2 = (SphereCollider)(object)((collider is SphereCollider) ? collider : null); if (val2 == null) { CapsuleCollider val3 = (CapsuleCollider)(object)((collider is CapsuleCollider) ? collider : null); if (val3 == null) { MeshCollider val4 = (MeshCollider)(object)((collider is MeshCollider) ? collider : null); if (val4 != null && (Object)(object)val4.sharedMesh != (Object)null) { bounds = val4.sharedMesh.bounds; return true; } Bounds bounds2 = collider.bounds; bounds = new Bounds(((Component)collider).transform.InverseTransformPoint(((Bounds)(ref bounds2)).center), ((Bounds)(ref bounds2)).size); return true; } Vector3 val5 = Vector3.one * (val3.radius * 2f); ((Vector3)(ref val5))[val3.direction] = Mathf.Max(val3.height, val3.radius * 2f); bounds = new Bounds(val3.center, val5); return true; } bounds = new Bounds(val2.center, Vector3.one * (val2.radius * 2f)); return true; } bounds = new Bounds(val.center, val.size); return true; } [IteratorStateMachine(typeof(d__88))] private static IEnumerable GetBoundsCorners(Bounds bounds) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__88(-2) { <>3__bounds = bounds }; } private static Vector3 ReadScale(ZDO zdo, GameObject prefab) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) return zdo.GetVec3(ZDOVars.s_scaleHash, prefab.transform.localScale); } private static float Round(float value) { return Mathf.Round(value * 1000f) / 1000f; } private static long PackCell(int x, int z) { return ((long)x << 32) ^ (uint)z; } private static void UnpackCell(long key, out int x, out int z) { x = (int)(key >> 32); z = (int)key; } private static Vector3 VertexToWorld(Heightmap heightmap, int x, int z) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)heightmap).transform.position; position.x += (float)(x - heightmap.m_width / 2) * heightmap.m_scale; position.z += (float)(z - heightmap.m_width / 2) * heightmap.m_scale; return position; } private static void WriteColor(ZPackage package, Color color) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) package.Write(color.r); package.Write(color.g); package.Write(color.b); package.Write(color.a); } private static Color ReadColor(ZPackage package) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) return new Color(package.ReadSingle(), package.ReadSingle(), package.ReadSingle(), package.ReadSingle()); } } internal readonly struct TerrainSupportApplyOptions { public float FeatherWidth { get; } public float MaxTerrainDelta { get; } public bool UseVanillaTerrainDelta { get; } private TerrainSupportApplyOptions(float featherWidth, float maxTerrainDelta, bool useVanillaTerrainDelta) { FeatherWidth = featherWidth; MaxTerrainDelta = maxTerrainDelta; UseVanillaTerrainDelta = useVanillaTerrainDelta; } public static TerrainSupportApplyOptions ZoneBundle() { return new TerrainSupportApplyOptions(ZoneBundleConfig.SupportFillFeatherWidth, 8f, useVanillaTerrainDelta: true); } public static TerrainSupportApplyOptions Blueprint() { return new TerrainSupportApplyOptions(BlueprintConfig.TerrainSupportFeatherWidth, 0f, useVanillaTerrainDelta: false); } public float ClampTerrainDelta(float desired, float nativeHeight) { if (!(MaxTerrainDelta <= 0f)) { return Mathf.Clamp(desired, nativeHeight - MaxTerrainDelta, nativeHeight + MaxTerrainDelta); } return desired; } } internal enum ZoneBundleWearNTearSaveMode { CreatorOnly, IncludeCreatorless } [HarmonyPatch(typeof(Heightmap), "ApplyModifiers")] internal static class ZoneBundleTerrainBaseLayerPatch { private static void Prefix(Heightmap __instance) { ZoneBundleTerrain.ApplyBaseLayer(__instance); } } internal static class ZoneBundleTerrainApplier { public static string SupportFillMode => "support-fill-v1"; public static ZoneBundleTerrain.TerrainSourceAnchor ComputeSupportAnchor(IEnumerable zones) { return ZoneBundleTerrain.ComputeSupportAnchor(zones); } public static IEnumerator ComputeSupportAnchorAsync(IEnumerable zones, Action onComplete) { return ZoneBundleTerrain.ComputeSupportAnchorAsync(zones, onComplete); } public static TerrainPlacementContext CreateExactContext(float sourceBaseY, IEnumerable zones) { return ZoneBundleTerrain.CreateExactContext(sourceBaseY, zones); } public static TerrainPlacementContext? CreateSupportFillPlacementContext(IEnumerable targets) { return ZoneBundleTerrain.CreateSupportFillPlacementContext(targets); } public static IEnumerator CreateSupportFillPlacementContextAsync(IEnumerable targets, Action onComplete) { return ZoneBundleTerrain.CreateSupportFillPlacementContextAsync(targets, onComplete); } public static List CaptureSupportContacts(Vector2i zone, float sourceBaseY, IEnumerable entries, out bool contactsCaptured) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return ZoneBundleTerrain.CaptureSupportContacts(zone, sourceBaseY, entries, out contactsCaptured); } public static bool IsSupportWearNTear(ZDO zdo, Vector2i zone, out GameObject prefab) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return ZoneBundleTerrain.IsSupportWearNTear(zdo, zone, out prefab); } public static bool CanApply(Vector2i zone) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return ZoneBundleTerrain.CanApply(zone); } public static bool ApplySupportFill(Vector2i zone, IEnumerable entries, IEnumerable contacts, bool contactsCaptured, TerrainPlacementContext context) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return ZoneBundleTerrain.ApplySupportFill(zone, entries, contacts, contactsCaptured, context); } public static bool HasApplicableSupportFill(Vector2i zone, IEnumerable entries, IEnumerable contacts, bool contactsCaptured, TerrainPlacementContext context) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return ZoneBundleTerrain.HasApplicableSupportFill(zone, entries, contacts, contactsCaptured, context); } public static IEnumerator ApplySupportFillAsync(Vector2i zone, IEnumerable entries, IEnumerable contacts, bool contactsCaptured, TerrainPlacementContext context, Action onComplete) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return ZoneBundleTerrain.ApplySupportFillAsync(zone, entries, contacts, contactsCaptured, context, onComplete); } } internal sealed class ZoneBundleZdoData { private const string Prefix = "zs-zdo-v1:"; private const int Version = 1; public Dictionary Strings { get; private set; } = new Dictionary(); public Dictionary Floats { get; private set; } = new Dictionary(); public Dictionary Ints { get; private set; } = new Dictionary(); public Dictionary Bools { get; private set; } = new Dictionary(); public Dictionary Hashes { get; private set; } = new Dictionary(); public Dictionary Longs { get; private set; } = new Dictionary(); public Dictionary Vecs { get; private set; } = new Dictionary(); public Dictionary Quats { get; private set; } = new Dictionary(); public Dictionary ByteArrays { get; private set; } = new Dictionary(); public ZDOID OriginalId { get; set; } = ZDOID.None; public ZDOID TargetConnectionId { get; set; } = ZDOID.None; public int ConnectionHash { get; set; } public ConnectionType ConnectionType { get; set; } public bool Persistent { get; private set; } public bool Distant { get; private set; } public ObjectType ObjectType { get; private set; } public ZoneBundleZdoData() { }//IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) public ZoneBundleZdoData(ZDO zdo) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) Load(zdo); } public ZoneBundleZdoData(string payload) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) Load(payload); } public string GetBase64(Dictionary _) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected I4, but got Unknown ZPackage package = new ZPackage(); package.Write(1); package.Write(Persistent); package.Write(Distant); package.Write((int)ObjectType); WriteDictionary(package, Strings, (Action)package.Write); WriteDictionary(package, Floats, (Action)package.Write); WriteDictionary(package, Ints, (Action)package.Write); WriteDictionary(package, Longs, (Action)package.Write); WriteDictionary(package, Vecs, (Action)package.Write); WriteDictionary(package, Quats, (Action)package.Write); WriteDictionary(package, ByteArrays, delegate(byte[] bytes) { package.Write(bytes ?? Array.Empty()); }); return "zs-zdo-v1:" + package.GetBase64(); } public void ApplyTo(ZDO zdo) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) zdo.Persistent = Persistent; zdo.Distant = Distant; zdo.Type = ObjectType; foreach (KeyValuePair @string in Strings) { zdo.Set(@string.Key, @string.Value); } foreach (KeyValuePair @float in Floats) { zdo.Set(@float.Key, @float.Value); } foreach (KeyValuePair @int in Ints) { zdo.Set(@int.Key, @int.Value, false); } foreach (KeyValuePair @bool in Bools) { zdo.Set(@bool.Key, @bool.Value); } foreach (KeyValuePair hash in Hashes) { zdo.Set(hash.Key, hash.Value, false); } foreach (KeyValuePair @long in Longs) { zdo.Set(@long.Key, @long.Value); } foreach (KeyValuePair vec in Vecs) { zdo.Set(vec.Key, vec.Value); } foreach (KeyValuePair quat in Quats) { zdo.Set(quat.Key, quat.Value); } foreach (KeyValuePair byteArray in ByteArrays) { zdo.Set(byteArray.Key, byteArray.Value.ToArray()); } } private void Load(ZDO zdo) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_012e: 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_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) OriginalId = zdo.m_uid; Persistent = zdo.Persistent; Distant = zdo.Distant; ObjectType = zdo.Type; Strings = ZDOExtraData.GetStrings(zdo.m_uid).ToDictionary((KeyValuePair item) => item.Key, (KeyValuePair item) => item.Value); Floats = ZDOExtraData.GetFloats(zdo.m_uid).ToDictionary((KeyValuePair item) => item.Key, (KeyValuePair item) => item.Value); Ints = ZDOExtraData.GetInts(zdo.m_uid).ToDictionary((KeyValuePair item) => item.Key, (KeyValuePair item) => item.Value); Longs = ZDOExtraData.GetLongs(zdo.m_uid).ToDictionary((KeyValuePair item) => item.Key, (KeyValuePair item) => item.Value); Vecs = ZDOExtraData.GetVec3s(zdo.m_uid).ToDictionary((KeyValuePair item) => item.Key, (KeyValuePair item) => item.Value); Quats = ZDOExtraData.GetQuaternions(zdo.m_uid).ToDictionary((KeyValuePair item) => item.Key, (KeyValuePair item) => item.Value); ByteArrays = ZDOExtraData.GetByteArrays(zdo.m_uid).ToDictionary((KeyValuePair item) => item.Key, (KeyValuePair item) => item.Value.ToArray()); } private void Load(string payload) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown if (!payload.StartsWith("zs-zdo-v1:", StringComparison.Ordinal)) { throw new InvalidDataException("Unsupported zone bundle ZDO data format. Re-save this bundle with the current ZoneSavior version."); } ZPackage package = new ZPackage(payload.Substring("zs-zdo-v1:".Length)); int num = package.ReadInt(); if (num != 1) { throw new InvalidDataException($"Unsupported ZoneSavior ZDO data version {num}."); } Persistent = package.ReadBool(); Distant = package.ReadBool(); ObjectType = (ObjectType)(byte)package.ReadInt(); Strings = ReadDictionary(package, () => package.ReadString()); Floats = ReadDictionary(package, () => package.ReadSingle()); Ints = ReadDictionary(package, () => package.ReadInt()); Longs = ReadDictionary(package, () => package.ReadLong()); Vecs = ReadDictionary(package, () => package.ReadVector3()); Quats = ReadDictionary(package, () => package.ReadQuaternion()); ByteArrays = ReadDictionary(package, () => package.ReadByteArray().ToArray()); } private static void WriteDictionary(ZPackage package, Dictionary values, Action writeValue) { package.Write(values.Count); foreach (KeyValuePair item in values.OrderBy, int>((KeyValuePair item) => item.Key)) { package.Write(item.Key); writeValue(item.Value); } } private static Dictionary ReadDictionary(ZPackage package, Func readValue) { int num = package.ReadInt(); Dictionary dictionary = new Dictionary(num); for (int i = 0; i < num; i++) { int key = package.ReadInt(); dictionary[key] = readValue(); } return dictionary; } } internal static class ZoneBundleZdoHelper { public static ZDO? Init(GameObject prefab, Vector3 position, Quaternion rotation, Vector3? scale, ZoneBundleZdoData data, Dictionary _) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) if (ZDOMan.instance == null || !Object.op_Implicit((Object)(object)prefab)) { return null; } int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)prefab).name); ZDO val = ZDOMan.instance.CreateNewZDO(position, stableHashCode); val.SetPrefab(stableHashCode); val.SetRotation(rotation); ZNetView component = prefab.GetComponent(); if ((Object)(object)component != (Object)null) { val.Persistent = component.m_persistent; val.Distant = component.m_distant; val.Type = component.m_type; } data.ApplyTo(val); if (scale.HasValue) { val.Set(ZDOVars.s_scaleHash, scale.Value); } return val; } public static void Destroy(ZDO zdo) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) if (zdo == null || ZDOMan.instance == null) { return; } ZDOID uid = zdo.m_uid; if (!CanDestroyZdo(uid)) { return; } zdo.SetOwner(ZDOMan.GetSessionID()); ZDOID connectionZDOID = zdo.GetConnectionZDOID((ConnectionType)3); if (connectionZDOID != ZDOID.None && ZDOMan.instance.m_objectsByID.TryGetValue(connectionZDOID, out var value) && value != zdo) { Destroy(value); } ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance != (Object)null) { ZNetView val = instance.FindInstance(zdo); if ((Object)(object)val != (Object)null) { instance.Destroy(((Component)val).gameObject); } } ZDO zDO = ZDOMan.instance.GetZDO(uid); if (zDO != null && zDO.IsValid()) { zDO.SetOwner(ZDOMan.GetSessionID()); ZDOMan.instance.DestroyZDO(zDO); ZDOMan.instance.HandleDestroyedZDO(uid); } } public static void FlushDestroyed() { ZDOMan instance = ZDOMan.instance; if (instance != null) { instance.SendDestroyed(); } } private static bool CanDestroyZdo(ZDOID id) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.m_localPlayer != (Object)null && ((Character)Player.m_localPlayer).GetZDOID() == id) { return false; } if (!((Object)(object)ZNet.instance == (Object)null)) { return !ZNet.instance.m_peers.Any((ZNetPeer peer) => peer != null && peer.m_characterID == id); } return true; } } internal static class ZoneLimitConfiguration { private static readonly IDeserializer Deserializer = new DeserializerBuilder().IgnoreUnmatchedProperties().WithNamingConvention(UnderscoredNamingConvention.Instance).Build(); private static readonly List Rules = new List(); private static readonly HashSet ProtectedPlayerIds = new HashSet(); private static readonly HashSet ProtectedSteamIds = new HashSet(StringComparer.Ordinal); private static readonly HashSet ProtectedPlayerNames = new HashSet(StringComparer.OrdinalIgnoreCase); private static ManualLogSource? _logger; private static CustomSyncedValue? _syncedYaml; public static IReadOnlyList ActiveRules => Rules; public static bool Enabled => GeneralConfig.ZoneWearNTearLimitEnabled; public static void Initialize(ConfigSync configSync, ManualLogSource logger) { _logger = logger; _syncedYaml = new CustomSyncedValue(configSync, "zone_rules_yaml", ""); _syncedYaml.ValueChanged += OnSyncedYamlChanged; configSync.SourceOfTruthChanged += OnSourceOfTruthChanged; EnsureFileExists(); ReloadFromDisk(); } public static void ReloadFromDisk() { if (_syncedYaml == null) { return; } EnsureFileExists(); if (!ZoneSaviorPlugin.ConfigSync.IsSourceOfTruth) { if (!string.IsNullOrWhiteSpace(_syncedYaml.Value)) { ApplyYaml(_syncedYaml.Value, "server sync"); } return; } string text = File.ReadAllText(ZoneSaviorPlugin.ZoneRuleFileFullPath); if (!TryParseYaml(text, out List _, out ZoneArchiveProtection _, out string error)) { ManualLogSource? logger = _logger; if (logger != null) { logger.LogError((object)("Zone rule YAML is invalid, keeping previous rules: " + error)); } } else { _syncedYaml.AssignLocalValue(text); if (string.IsNullOrWhiteSpace(_syncedYaml.Value)) { ApplyConfiguration(new List(), default(ZoneArchiveProtection)); } } } public static bool TryGetLimit(Vector2i zone, out int limit) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if (TryGetRule(zone, out var rule)) { limit = rule.Limit; return true; } limit = 0; return false; } public static bool TryGetRule(Vector2i zone, out ZoneLimitRule rule) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (!Enabled) { rule = default(ZoneLimitRule); return false; } foreach (ZoneLimitRule rule2 in Rules) { if (rule2.Contains(zone)) { rule = rule2; return true; } } rule = default(ZoneLimitRule); return false; } public static bool IsArchiveProtected(long playerId, out string reason) { reason = ""; if (playerId == 0L) { return false; } if (ProtectedPlayerIds.Contains(playerId)) { reason = $"player {playerId} is protected by zones.yml player_ids"; return true; } if (!AutoArchiveStore.TryGetPlayerRecord(playerId, out PlayerActivityRecord record)) { return false; } if (TryNormalizeSteamPlatformId(record.PlatformId, out string steamId) && ProtectedSteamIds.Contains(steamId)) { reason = $"player {playerId} is protected by zones.yml steam_ids"; return true; } foreach (string name in record.Names) { if (!string.IsNullOrWhiteSpace(name) && ProtectedPlayerNames.Contains(name.Trim())) { reason = $"player {playerId} is protected by zones.yml player_names ({name.Trim()})"; return true; } } return false; } private static void EnsureFileExists() { if (!File.Exists(ZoneSaviorPlugin.ZoneRuleFileFullPath)) { Directory.CreateDirectory(Path.GetDirectoryName(ZoneSaviorPlugin.ZoneRuleFileFullPath)); File.WriteAllText(ZoneSaviorPlugin.ZoneRuleFileFullPath, BuildDefaultYaml()); } } private static void OnSyncedYamlChanged() { if (_syncedYaml != null) { ApplyYaml(_syncedYaml.Value, ZoneSaviorPlugin.ConfigSync.IsSourceOfTruth ? "local file" : "server sync"); } } private static void OnSourceOfTruthChanged(bool isSourceOfTruth) { if (isSourceOfTruth) { ReloadFromDisk(); } else if (_syncedYaml != null) { ApplyYaml(_syncedYaml.Value, "server sync"); } } private static void ApplyYaml(string yaml, string source) { if (!TryParseYaml(yaml, out List rules, out ZoneArchiveProtection protection, out string error)) { ManualLogSource? logger = _logger; if (logger != null) { logger.LogError((object)("Failed to parse zone rule YAML from " + source + ": " + error)); } return; } ApplyConfiguration(rules, protection); ManualLogSource? logger2 = _logger; if (logger2 != null) { logger2.LogInfo((object)$"Loaded {Rules.Count} zone limit rule(s) from {source}."); } } private static void ApplyConfiguration(List parsedRules, ZoneArchiveProtection parsedProtection) { Rules.Clear(); Rules.AddRange(parsedRules); ProtectedPlayerIds.Clear(); foreach (long playerId in parsedProtection.PlayerIds) { if (playerId != 0L) { ProtectedPlayerIds.Add(playerId); } } ProtectedSteamIds.Clear(); foreach (string steamId in parsedProtection.SteamIds) { string text = NormalizeSteamId(steamId); if (!string.IsNullOrWhiteSpace(text)) { ProtectedSteamIds.Add(text); } } ProtectedPlayerNames.Clear(); foreach (string playerName in parsedProtection.PlayerNames) { if (!string.IsNullOrWhiteSpace(playerName)) { ProtectedPlayerNames.Add(playerName.Trim()); } } ZonePieceCounter.RebuildCounts(); } private static bool TryParseYaml(string yaml, out List rules, out ZoneArchiveProtection protection, out string error) { rules = new List(); protection = default(ZoneArchiveProtection); error = ""; if (string.IsNullOrWhiteSpace(yaml)) { return true; } ZoneLimitFile zoneLimitFile; try { zoneLimitFile = Deserializer.Deserialize(yaml); } catch (Exception ex) { error = ex.Message; return false; } if (zoneLimitFile == null) { return true; } if (!ZoneArchiveProtection.TryCreateFromFile(zoneLimitFile.ArchiveProtection, out protection, out string error2)) { error = "archive_protection." + error2; return false; } bool defaultValue = zoneLimitFile.Defaults?.CountCreatorless ?? false; ZoneLimitFile zoneLimitFile2 = zoneLimitFile; if (zoneLimitFile2.Rules == null) { List list2 = (zoneLimitFile2.Rules = new List()); } for (int i = 0; i < zoneLimitFile.Rules.Count; i++) { ZoneLimitRuleFile zoneLimitRuleFile = zoneLimitFile.Rules[i]; if (zoneLimitRuleFile == null) { error = $"rules[{i}] is null."; return false; } if (!TryNormalizeRange(zoneLimitRuleFile.X, out int min, out int max, out string error3)) { error = $"rules[{i}].x {error3}"; return false; } if (!TryNormalizeRange(zoneLimitRuleFile.Z, out int min2, out int max2, out string error4)) { error = $"rules[{i}].z {error4}"; return false; } if (zoneLimitRuleFile.Limit < 0) { error = $"rules[{i}].limit must be zero or greater."; return false; } bool valueOrDefault = zoneLimitRuleFile.CountCreatorless.GetValueOrDefault(defaultValue); rules.Add(new ZoneLimitRule(min, max, min2, max2, zoneLimitRuleFile.Limit, valueOrDefault, zoneLimitRuleFile.Name ?? $"rule_{i + 1}")); } return true; } private static string NormalizeSteamId(string value) { if (string.IsNullOrWhiteSpace(value)) { return ""; } string text = value.Trim(); if (text.Length != 17 || !text.All(char.IsDigit)) { return ""; } return text; } private static bool TryNormalizeSteamPlatformId(string platformId, out string steamId) { steamId = ""; if (string.IsNullOrWhiteSpace(platformId) || !platformId.StartsWith("steam:", StringComparison.OrdinalIgnoreCase)) { return false; } steamId = NormalizeSteamId(platformId.Substring("steam:".Length)); return !string.IsNullOrWhiteSpace(steamId); } private static bool TryNormalizeRange(IReadOnlyList? range, out int min, out int max, out string error) { min = 0; max = 0; error = ""; if (range == null || range.Count != 2) { error = "must contain exactly two integers like [-1, 3]."; return false; } min = Math.Min(range[0], range[1]); max = Math.Max(range[0], range[1]); return true; } private static string BuildDefaultYaml() { return "# ZoneSavior zone rules\n# Rules are evaluated from top to bottom.\n# The first matching rule wins.\n# If a zone does not match any rule, it is unlimited.\nversion: 1\narchive_protection:\n steam_ids:\n - \"76561198000000000\"\n - \"76561198000000001\"\n player_ids:\n - 123456789\n player_names:\n - \"GreatViking\"\n - \"Xcxcx\"\ndefaults:\n count_creatorless: false\nrules:\n - name: center_keep\n x: [-1, 1]\n z: [-1, 1]\n limit: 40\n count_creatorless: true\n - name: outer_ring\n x: [-3, 3]\n z: [-3, 3]\n limit: 80\n"; } } internal sealed class ZoneLimitFile { public int Version { get; set; } = 1; public ZoneLimitDefaultsFile? Defaults { get; set; } public ZoneArchiveProtectionFile? ArchiveProtection { get; set; } public List Rules { get; set; } = new List(); } internal sealed class ZoneArchiveProtectionFile { public List SteamIds { get; set; } = new List(); public List PlayerIds { get; set; } = new List(); public List PlayerNames { get; set; } = new List(); } internal sealed class ZoneLimitDefaultsFile { public bool CountCreatorless { get; set; } } internal sealed class ZoneLimitRuleFile { public string? Name { get; set; } public List? X { get; set; } public List? Z { get; set; } public int Limit { get; set; } public bool? CountCreatorless { get; set; } } internal readonly struct ZoneLimitRule { public int MinX { get; } public int MaxX { get; } public int MinZ { get; } public int MaxZ { get; } public int Limit { get; } public bool CountCreatorless { get; } public string Name { get; } public ZoneLimitRule(int minX, int maxX, int minZ, int maxZ, int limit, bool countCreatorless, string name) { MinX = minX; MaxX = maxX; MinZ = minZ; MaxZ = maxZ; Limit = limit; CountCreatorless = countCreatorless; Name = name; } public bool Contains(Vector2i zone) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) if (zone.x >= MinX && zone.x <= MaxX && zone.y >= MinZ) { return zone.y <= MaxZ; } return false; } } internal readonly struct ZoneArchiveProtection { private readonly IReadOnlyList? _steamIds; private readonly IReadOnlyList? _playerIds; private readonly IReadOnlyList? _playerNames; public IReadOnlyList SteamIds => _steamIds ?? Array.Empty(); public IReadOnlyList PlayerIds => _playerIds ?? Array.Empty(); public IReadOnlyList PlayerNames => _playerNames ?? Array.Empty(); private ZoneArchiveProtection(List steamIds, List playerIds, List playerNames) { _steamIds = steamIds; _playerIds = playerIds; _playerNames = playerNames; } public static bool TryCreateFromFile(ZoneArchiveProtectionFile? file, out ZoneArchiveProtection protection, out string error) { protection = default(ZoneArchiveProtection); error = ""; for (int i = 0; i < (file?.SteamIds?.Count).GetValueOrDefault(); i++) { string text = file.SteamIds[i]; if (string.IsNullOrWhiteSpace(text) || text.Trim().Length != 17 || !text.Trim().All(char.IsDigit)) { error = $"steam_ids[{i}] must be a quoted 17-digit SteamID64 like \"76561198000000000\". The steam: prefix is not supported here."; return false; } } protection = new ZoneArchiveProtection(file?.SteamIds ?? new List(), file?.PlayerIds ?? new List(), file?.PlayerNames ?? new List()); return true; } } internal static class ZonePieceCounter { private sealed class StructureEntry { public GameObject GameObject { get; } public Vector2i Zone { get; private set; } public bool PlayerPlaced { get; private set; } public bool Counted { get; private set; } public StructureEntry(GameObject gameObject) { GameObject = gameObject; } public void Update(StructureState state) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) Zone = state.Zone; PlayerPlaced = state.PlayerPlaced; Counted = state.Counted; } } private readonly struct StructureState { public Vector2i Zone { get; } public bool PlayerPlaced { get; } public bool Counted { get; } public StructureState(Vector2i zone, bool playerPlaced, bool counted) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) Zone = zone; PlayerPlaced = playerPlaced; Counted = counted; } } private const string BlueprintPieceMarkerKey = "sighsorry.Homestead.blueprint_piece"; private static readonly int ZoneBlueprintPlacedHash = StringExtensionMethods.GetStableHashCode("sighsorry.Homestead.blueprint_piece"); private static readonly Dictionary KnownStructures = new Dictionary(); private static readonly Dictionary ZoneCounts = new Dictionary(); private static ManualLogSource? _logger; public static void Initialize(ManualLogSource logger) { _logger = logger; Clear(); } public static void Clear() { KnownStructures.Clear(); ZoneCounts.Clear(); } public static void RebuildCounts() { //IL_007d: Unknown result type (might be due to invalid IL or missing references) ZoneCounts.Clear(); if (!ZoneLimitConfiguration.Enabled) { KnownStructures.Clear(); return; } List list = new List(); foreach (KeyValuePair knownStructure in KnownStructures) { if (!TryBuildStructureState(knownStructure.Value.GameObject, out var state)) { list.Add(knownStructure.Key); continue; } knownStructure.Value.Update(state); if (knownStructure.Value.Counted) { AdjustZoneCount(knownStructure.Value.Zone, 1); } } foreach (int item in list) { KnownStructures.Remove(item); } } public static bool CanAddWearNTears(IEnumerable positions, out string reason) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) if (!ZoneLimitConfiguration.Enabled) { reason = ""; return true; } Dictionary dictionary = new Dictionary(); foreach (Vector3 position in positions) { Vector2i zone = ZoneSystem.GetZone(position); dictionary[zone] = ((!dictionary.TryGetValue(zone, out var value)) ? 1 : (value + 1)); } foreach (KeyValuePair item in dictionary) { if (ZoneLimitConfiguration.TryGetRule(item.Key, out var rule)) { int num = GetCount(item.Key) + item.Value; if (num > rule.Limit) { reason = $"WearNTear zone limit would be exceeded at ({item.Key.x},{item.Key.y}): {num}/{rule.Limit}."; return false; } } } reason = ""; return true; } public static void Refresh(Piece piece) { if (!ZoneLimitConfiguration.Enabled) { Clear(); } else if (!((Object)(object)piece == (Object)null)) { Refresh(((Component)piece).gameObject); } } public static void Refresh(WearNTear wearNTear) { if (!ZoneLimitConfiguration.Enabled) { Clear(); } else if (!((Object)(object)wearNTear == (Object)null)) { Refresh(((Component)wearNTear).gameObject); } } public static void Remove(Component component) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) if (!ZoneLimitConfiguration.Enabled) { Clear(); } else { if ((Object)(object)component == (Object)null) { return; } int instanceID = ((Object)component.gameObject).GetInstanceID(); if (KnownStructures.TryGetValue(instanceID, out StructureEntry value)) { KnownStructures.Remove(instanceID); if (value.Counted) { AdjustZoneCount(value.Zone, -1); } } } } public static void HandlePlacement(Piece piece) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) if (!ZoneLimitConfiguration.Enabled) { Clear(); } else { if ((Object)(object)piece == (Object)null) { return; } Refresh(piece); if (TryGetStructureEntry(((Component)piece).gameObject, out StructureEntry entry) && ZoneLimitConfiguration.TryGetRule(entry.Zone, out var rule)) { int count = GetCount(entry.Zone); bool flag = count > rule.Limit; if (flag) { RejectPlacement(piece, count, rule.Limit); } if (piece.IsCreator()) { BuildCounterHud.ShowCount(flag ? Mathf.Max(0, count - 1) : count, rule.Limit); } } } } private static void Refresh(GameObject gameObject) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) if (!TryBuildStructureState(gameObject, out var state)) { UnregisterStructure(gameObject); return; } int instanceID = ((Object)gameObject).GetInstanceID(); if (KnownStructures.TryGetValue(instanceID, out StructureEntry value)) { if (value.Counted) { AdjustZoneCount(value.Zone, -1); } value.Update(state); } else { value = new StructureEntry(gameObject); value.Update(state); KnownStructures[instanceID] = value; } if (value.Counted) { AdjustZoneCount(value.Zone, 1); } } private static void UnregisterStructure(GameObject gameObject) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) int instanceID = ((Object)gameObject).GetInstanceID(); if (KnownStructures.TryGetValue(instanceID, out StructureEntry value)) { KnownStructures.Remove(instanceID); if (value.Counted) { AdjustZoneCount(value.Zone, -1); } } } private static bool TryGetStructureEntry(GameObject gameObject, out StructureEntry entry) { return KnownStructures.TryGetValue(((Object)gameObject).GetInstanceID(), out entry); } private static bool TryBuildStructureState(GameObject gameObject, out StructureState state) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) state = default(StructureState); if (!Object.op_Implicit((Object)(object)gameObject)) { return false; } if ((Object)(object)gameObject.GetComponent() == (Object)null) { return false; } Piece component = gameObject.GetComponent(); ZNetView component2 = gameObject.GetComponent(); ZDO val = ((component2 != null) ? component2.GetZDO() : null); if ((Object)(object)component2 == (Object)null || !component2.IsValid() || val == null) { return false; } Vector2i zone = ZoneSystem.GetZone(gameObject.transform.position); bool playerPlaced = IsPlayerPlaced(component, component2); bool forceCount = IsKnownBlueprintPiece(val); bool counted = ShouldCount(zone, playerPlaced, forceCount); state = new StructureState(zone, playerPlaced, counted); return true; } private static bool IsPlayerPlaced(Piece? piece, ZNetView nview) { if ((Object)(object)piece != (Object)null) { return piece.IsPlacedByPlayer(); } ZDO zDO = nview.GetZDO(); if (zDO == null) { return true; } return zDO.GetLong(ZDOVars.s_creator, 0L) != 0; } private static bool ShouldCount(Vector2i zone, bool playerPlaced, bool forceCount) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if (!ZoneLimitConfiguration.TryGetRule(zone, out var rule)) { return false; } if (!(playerPlaced || forceCount)) { return rule.CountCreatorless; } return true; } private static bool IsKnownBlueprintPiece(ZDO zdo) { return zdo.GetBool(ZoneBlueprintPlacedHash, false); } private static int GetCount(Vector2i zone) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (!ZoneCounts.TryGetValue(zone, out var value)) { return 0; } return value; } private static void AdjustZoneCount(Vector2i zone, int delta) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) int num = GetCount(zone) + delta; if (num <= 0) { ZoneCounts.Remove(zone); } else { ZoneCounts[zone] = num; } } private static void RejectPlacement(Piece piece, int zoneCount, int limit) { string text = $"WearNTear zone limit reached ({zoneCount}/{limit})"; if (piece.IsCreator() && (Object)(object)Player.m_localPlayer != (Object)null) { ((Character)Player.m_localPlayer).Message((MessageType)2, text, 0, (Sprite)null); } WearNTear component = ((Component)piece).GetComponent(); if ((Object)(object)component != (Object)null) { component.Remove(false); return; } ZNetView component2 = ((Component)piece).GetComponent(); if ((Object)(object)component2 == (Object)null || !component2.IsValid() || !component2.IsOwner()) { ManualLogSource? logger = _logger; if (logger != null) { logger.LogWarning((object)("Unable to reject " + ((Object)piece).name + " cleanly because the local client does not own it and it has no WearNTear component.")); } } else { piece.DropResources((HitData)null); if ((Object)(object)ZNetScene.instance != (Object)null) { ZNetScene.instance.Destroy(((Component)piece).gameObject); } else { Object.Destroy((Object)(object)((Component)piece).gameObject); } } } } [HarmonyPatch(typeof(ZNetScene), "Awake")] internal static class ZonePieceCounterScenePatch { private static void Postfix() { ZonePieceCounter.Clear(); } } [HarmonyPatch(typeof(Piece), "Awake")] internal static class ZonePieceCounterPieceAwakePatch { private static void Postfix(Piece __instance) { ZonePieceCounter.Refresh(__instance); } } [HarmonyPatch(typeof(Piece), "SetCreator")] internal static class ZonePieceCounterPieceCreatorPatch { private static void Postfix(Piece __instance) { ZonePieceCounter.Refresh(__instance); } } [HarmonyPatch(typeof(Piece), "OnPlaced")] internal static class ZonePieceCounterPiecePlacedPatch { private static void Postfix(Piece __instance) { ZonePieceCounter.HandlePlacement(__instance); } } [HarmonyPatch(typeof(Piece), "OnDestroy")] internal static class ZonePieceCounterPieceDestroyPatch { private static void Prefix(Piece __instance) { ZonePieceCounter.Remove((Component)(object)__instance); } } [HarmonyPatch(typeof(WearNTear), "Awake")] internal static class ZonePieceCounterWearNTearAwakePatch { private static void Postfix(WearNTear __instance) { ZonePieceCounter.Refresh(__instance); } } [HarmonyPatch(typeof(WearNTear), "OnDestroy")] internal static class ZonePieceCounterWearNTearDestroyPatch { private static void Prefix(WearNTear __instance) { ZonePieceCounter.Remove((Component)(object)__instance); } } internal static class ZonePlayerIdentity { public static string ResolvePlatformId(Player? player, long sender, long playerId) { if ((Object)(object)player != (Object)null) { return ResolveLocalPlatformId(playerId); } ZNet instance = ZNet.instance; ZNetPeer val = ((instance != null) ? instance.GetPeer(sender) : null); if (val != null) { return ResolvePeerPlatformId(val, playerId); } if ((Object)(object)Player.m_localPlayer != (Object)null && Player.m_localPlayer.GetPlayerID() == playerId) { return ResolveLocalPlatformId(playerId); } return FallbackPlatformId(playerId); } public static string ResolvePeerPlatformId(ZNetPeer peer, long playerId) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (peer == null) { return FallbackPlatformId(playerId); } ISocket socket = peer.m_socket; string text = ((socket != null) ? socket.GetHostName() : null) ?? ""; if (!string.IsNullOrWhiteSpace(text)) { return NormalizePlatformId(((int)ZNet.m_onlineBackend == 0) ? ("steam:" + text) : text); } return $"session:{peer.m_uid}"; } public static string ResolveLocalPlatformId(long playerId) { string value = ""; try { UserInfo localUser = UserInfo.GetLocalUser(); value = ((localUser != null) ? ((object)(PlatformUserID)(ref localUser.UserId)).ToString() : null) ?? ""; } catch { } value = NormalizePlatformId(value); if (!string.IsNullOrWhiteSpace(value)) { return value; } return FallbackPlatformId(playerId); } public static string FallbackPlatformId(long playerId) { if (playerId == 0L) { return ""; } return $"local:{playerId}"; } public static string NormalizePlatformId(string value) { string text = (value ?? "").Trim(); if (string.IsNullOrWhiteSpace(text)) { return ""; } if (text.StartsWith("Steam_", StringComparison.OrdinalIgnoreCase)) { return "steam:" + text.Substring("Steam_".Length); } if (text.StartsWith("steam:", StringComparison.OrdinalIgnoreCase)) { return "steam:" + text.Substring("steam:".Length).Trim(); } return text; } } internal sealed class ZoneRpcRegistrar { private ZRoutedRpc? _registeredRoutedRpc; public bool EnsureRegistered(Action register) { ZRoutedRpc instance = ZRoutedRpc.instance; if (instance == null || _registeredRoutedRpc == instance) { return false; } register(instance); _registeredRoutedRpc = instance; return true; } public void Reset() { _registeredRoutedRpc = null; } } internal static class BlueprintConfig { public static float TerrainSupportFeatherWidth => ZoneBundleConfig.SupportFillFeatherWidth; } internal sealed class ZoneBlueprintTerrainContact { public float LocalX { get; set; } public float LocalY { get; set; } public float LocalZ { get; set; } } internal static class ZoneBlueprintCommands { private static readonly Dictionary BuildRecipeCache = new Dictionary(StringComparer.Ordinal); private static int _buildRecipeCacheObjectDbCount = -1; internal static bool HasBuildRecipe(GameObject? prefab) { if (!Object.op_Implicit((Object)(object)prefab)) { return false; } Piece component = prefab.GetComponent(); if ((Object)(object)component == (Object)null || component.m_resources == null) { return false; } if (HasResourceCost(component)) { return IsRegisteredPlayerBuildPiece(prefab); } return false; } private static bool HasResourceCost(Piece piece) { return piece.m_resources.Any((Requirement requirement) => Object.op_Implicit((Object)(object)requirement.m_resItem) && requirement.m_amount > 0); } private static bool IsRegisteredPlayerBuildPiece(GameObject prefab) { string prefabName = Utils.GetPrefabName(prefab); if (string.IsNullOrWhiteSpace(prefabName)) { return false; } ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance == (Object)null || instance.m_items == null) { return false; } if (_buildRecipeCacheObjectDbCount != instance.m_items.Count) { BuildRecipeCache.Clear(); _buildRecipeCacheObjectDbCount = instance.m_items.Count; } if (BuildRecipeCache.TryGetValue(prefabName, out var value)) { return value; } foreach (GameObject item in instance.m_items) { PieceTable val = (Object.op_Implicit((Object)(object)item) ? item.GetComponent() : null)?.m_itemData.m_shared.m_buildPieces; if (val?.m_pieces != null && val.m_pieces.Any((GameObject piecePrefab) => Object.op_Implicit((Object)(object)piecePrefab) && string.Equals(Utils.GetPrefabName(piecePrefab), prefabName, StringComparison.Ordinal))) { BuildRecipeCache[prefabName] = true; return true; } } BuildRecipeCache[prefabName] = false; return false; } } internal static class GeneralConfig { private static ConfigEntry _serverConfigLocked; private static ConfigEntry _zoneWearNTearLimit; public static bool ZoneWearNTearLimitEnabled => _zoneWearNTearLimit.Value.IsOn(); public static void Bind(ZoneSaviorPlugin plugin) { _serverConfigLocked = plugin.config("01 - General", "Lock Configuration", ZoneSaviorPlugin.Toggle.On, "If on, the server controls synced settings."); ZoneSaviorPlugin.ConfigSync.AddLockingConfigEntry(_serverConfigLocked); _zoneWearNTearLimit = plugin.config("01 - General", "Zone WearNTear Limit", ZoneSaviorPlugin.Toggle.Off, "If on, ZoneSavior enforces per-zone WearNTear limits from BepInEx/config/ZoneSavior/zones.yml. If off, zone rules stay loaded but placement is not rejected by zone count."); _zoneWearNTearLimit.SettingChanged += delegate { ZonePieceCounter.RebuildCounts(); }; } } internal static class ClientConfig { private static ConfigEntry _counterVisibleSeconds; private static ConfigEntry _zoneUiToggleHotkey; public static float CounterVisibleSeconds => Mathf.Max(0.1f, _counterVisibleSeconds.Value); public static KeyboardShortcut ZoneUiToggleHotkey => _zoneUiToggleHotkey.Value; public static void Bind(ZoneSaviorPlugin plugin) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_004e: Unknown result type (might be due to invalid IL or missing references) _counterVisibleSeconds = plugin.config("02 - Client", "Build Counter Visible Seconds", 2.5f, new ConfigDescription("How long the top build counter stays visible after you place a build piece.", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 10f), Array.Empty()), synchronizedSetting: false); _zoneUiToggleHotkey = plugin.config("02 - Client", "Zone UI Toggle Hotkey", new KeyboardShortcut((KeyCode)289, Array.Empty()), "Client-only hotkey that toggles the current zone number HUD and floor boundary line. The Zone UI starts hidden after login.", synchronizedSetting: false); } } internal static class ZoneBundleConfig { private static ConfigEntry _wearNTearSaveMode; private static ConfigEntry _supportFillFeatherWidth; private static ConfigEntry _supportFillContactTolerance; public static ZoneBundleWearNTearSaveMode WearNTearSaveMode => _wearNTearSaveMode.Value; public static float SupportFillFeatherWidth => Mathf.Clamp(_supportFillFeatherWidth.Value, 0f, 64f); public static float SupportFillContactTolerance => Mathf.Clamp(_supportFillContactTolerance.Value, 0.01f, 2f); public static void Bind(ZoneSaviorPlugin plugin) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Expected O, but got Unknown _wearNTearSaveMode = plugin.config("03 - Admin Zone Bundle", "WearNTear Save Mode", ZoneBundleWearNTearSaveMode.CreatorOnly, "Controls which WearNTear objects SupportFill saves. CreatorOnly saves only player-created WearNTear. IncludeCreatorless also saves WearNTear with no creator id."); _supportFillFeatherWidth = plugin.config("03 - Admin Zone Bundle", "Zone Bundle Support Fill Feather Width", 6f, new ConfigDescription("Meters around SupportFill footprints that blend back to native terrain. Set to 0 to only change exact footprint cells.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 64f), Array.Empty())); _supportFillContactTolerance = plugin.config("03 - Admin Zone Bundle", "Support Fill Contact Tolerance", 0.5f, new ConfigDescription("How close terrain must be to a WearNTear bottom at a 1m x/z cell to be saved as a terrain contact.", (AcceptableValueBase)(object)new AcceptableValueRange(0.01f, 2f), Array.Empty())); } } internal static class AutoArchiveConfig { private static ConfigEntry _inactiveDays; private static ConfigEntry _dryRun; private static ConfigEntry _resetAfterSave; private static ConfigEntry _requireLoadedTerrainForReset; private static ConfigEntry _minimumPiecesPerCluster; private static ConfigEntry _smallClusterAction; private static ConfigEntry _maxZonesPerRun; private static ConfigEntry _scanIntervalMinutes; private static ConfigEntry _unknownOwnerGraceDays; private static ConfigEntry _scannerBatchSize; public static bool Enabled => ScanIntervalMinutes > 0; public static int InactiveDays => Mathf.Clamp(_inactiveDays.Value, 0, 3650); public static bool DryRun => _dryRun.Value.IsOn(); public static bool ResetAfterSave => _resetAfterSave.Value.IsOn(); public static bool RequireLoadedTerrainForReset => _requireLoadedTerrainForReset.Value.IsOn(); public static int MinimumPiecesPerCluster => Mathf.Clamp(_minimumPiecesPerCluster.Value, 1, 10000); public static AutoArchiveSmallClusterAction SmallClusterAction => _smallClusterAction.Value; public static int MaxZonesPerRun => Mathf.Clamp(_maxZonesPerRun.Value, 1, 10000); public static int ScanIntervalMinutes => Mathf.Clamp(_scanIntervalMinutes.Value, 0, 525600); public static int UnknownOwnerGraceDays => Mathf.Clamp(_unknownOwnerGraceDays.Value, 0, 3650); public static int ScannerBatchSize => Mathf.Clamp(_scannerBatchSize.Value, 100, 10000); public static void Bind(ZoneSaviorPlugin plugin) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Expected O, but got Unknown //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Expected O, but got Unknown //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Expected O, but got Unknown //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Expected O, but got Unknown _inactiveDays = plugin.config("04 - Admin Auto Archive", "Inactive Days", 30, new ConfigDescription("A creator must be unseen for this many days before their zones can be archived. Set to 0 for testing.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 3650), Array.Empty())); _dryRun = plugin.config("04 - Admin Auto Archive", "Dry Run", ZoneSaviorPlugin.Toggle.On, "If on, auto archive only reports candidate zones and never saves or resets them."); _resetAfterSave = plugin.config("04 - Admin Auto Archive", "Reset After Save", ZoneSaviorPlugin.Toggle.Off, "If on, saved candidate zones are reset after their bundle is written."); _requireLoadedTerrainForReset = plugin.config("04 - Admin Auto Archive", "Require Loaded Terrain For Reset", ZoneSaviorPlugin.Toggle.Off, "If on, reset is skipped unless every zone saved usable terrain contacts. A loaded zone with no contacts is not enough."); _minimumPiecesPerCluster = plugin.config("04 - Admin Auto Archive", "Minimum Pieces Per Cluster", 5, new ConfigDescription("Candidate clusters with fewer player structures are skipped.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 10000), Array.Empty())); _smallClusterAction = plugin.config("04 - Admin Auto Archive", "Small Cluster Action", AutoArchiveSmallClusterAction.ResetWithoutSave, "What to do when an inactive WearNTear cluster has fewer structures than Minimum Pieces Per Cluster. ResetWithoutSave only resets during reset runs, not dry/save runs."); _maxZonesPerRun = plugin.config("04 - Admin Auto Archive", "Max Zones Per Run", 50, new ConfigDescription("Maximum number of zones to save or reset in one automatic run.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 10000), Array.Empty())); _scanIntervalMinutes = plugin.config("04 - Admin Auto Archive", "Scan Interval Minutes", 0, new ConfigDescription("How often the server runs automatic inactive-structure archive scans. Set to 0 to disable automatic scans. Set to 1 for rapid testing.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 525600), Array.Empty())); _unknownOwnerGraceDays = plugin.config("04 - Admin Auto Archive", "Unknown Owner Grace Days", 90, new ConfigDescription("Owners first discovered by the scanner but never seen online are protected for this many days. Set to 0 to archive imported-world owners immediately.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 3650), Array.Empty())); _scannerBatchSize = plugin.config("04 - Admin Auto Archive", "Scanner Batch Size", 1000, new ConfigDescription("How many ZDOs the auto archive scanner inspects before yielding a frame.", (AcceptableValueBase)(object)new AcceptableValueRange(100, 10000), Array.Empty())); } } internal sealed class ConfigurationManagerAttributes { public int? Order; public bool? Browsable; public string? Category; public Action? CustomDrawer; } internal static class ZoneSaviorFeatureBootstrap { public static void Initialize(ManualLogSource logger) { ZoneLimitConfiguration.Initialize(ZoneSaviorPlugin.ConfigSync, logger); ZonePieceCounter.Initialize(logger); ZoneBundleCommands.Initialize(logger); AutoArchiveStore.Initialize(logger); AutoArchiveService.Initialize(logger); AutoArchiveCommands.Initialize(logger); } public static void InitializeCompat(ManualLogSource logger, Harmony harmony) { ZoneWorldEditTerrainCompat.Initialize(logger, harmony); } public static void Update() { ZoneBundleCommands.RegisterRpcs(); AutoArchiveCommands.RegisterRpcs(); ZoneWorldEditTerrainCompat.Update(); AutoArchiveService.Update(); ZoneBoundaryOverlay.Update(); } public static void Shutdown() { ZonePieceCounter.Clear(); ZoneBoundaryOverlay.Shutdown(); AutoArchiveService.Shutdown(); AutoArchiveStore.Flush(force: true); } public static void ReloadZoneRulesFromDisk() { ZoneLimitConfiguration.ReloadFromDisk(); } } [BepInPlugin("sighsorry.ZoneSavior", "ZoneSavior", "1.0.1")] public class ZoneSaviorPlugin : BaseUnityPlugin { public enum Toggle { On = 1, Off = 0 } internal const string ModName = "ZoneSavior"; internal const string ModVersion = "1.0.1"; internal const string Author = "sighsorry"; internal const string ModGUID = "sighsorry.ZoneSavior"; internal const string DataStorageFolder = "ZoneSavior"; internal const string ZoneBundleStorageFolder = "ZoneBundles"; internal const string ActivityFileName = "activity.yml"; private const string ConfigFileName = "sighsorry.ZoneSavior.cfg"; private const string ZoneRuleFileName = "zones.yml"; private const long ReloadDelay = 10000000L; private static readonly string ConfigFileFullPath = Path.Combine(Paths.ConfigPath, "sighsorry.ZoneSavior.cfg"); internal static readonly string DataStorageFullPath = Path.Combine(Paths.ConfigPath, "ZoneSavior"); internal static readonly string ZoneBundleStorageFullPath = Path.Combine(DataStorageFullPath, "ZoneBundles"); internal static readonly string ZoneRuleFileFullPath = Path.Combine(DataStorageFullPath, "zones.yml"); internal static readonly ManualLogSource ZoneSaviorLogger = Logger.CreateLogSource("ZoneSavior"); internal static readonly ConfigSync ConfigSync = new ConfigSync("sighsorry.ZoneSavior") { DisplayName = "ZoneSavior", CurrentVersion = "1.0.1", MinimumRequiredVersion = "1.0.1" }; internal static string ConnectionError = ""; private readonly Harmony _harmony = new Harmony("sighsorry.ZoneSavior"); private readonly object _reloadLock = new object(); private FileSystemWatcher? _configWatcher; private FileSystemWatcher? _zoneRuleWatcher; private DateTime _lastConfigReloadTime; private DateTime _lastZoneRuleReloadTime; internal static ZoneSaviorPlugin Instance { get; private set; } = null; public void Awake() { Instance = this; bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet; ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; BindConfiguration(); EnsureDataDirectories(); ZoneSaviorFeatureBootstrap.Initialize(ZoneSaviorLogger); _harmony.PatchAll(typeof(ZoneSaviorPlugin).Assembly); ZoneSaviorFeatureBootstrap.InitializeCompat(ZoneSaviorLogger, _harmony); SetupWatchers(); SaveWithRespectToConfigSet(); if (saveOnConfigSet) { ((BaseUnityPlugin)this).Config.SaveOnConfigSet = true; } } private void OnDestroy() { SaveWithRespectToConfigSet(); ZoneSaviorFeatureBootstrap.Shutdown(); _configWatcher?.Dispose(); _zoneRuleWatcher?.Dispose(); } private void Update() { ZoneSaviorFeatureBootstrap.Update(); } private void BindConfiguration() { GeneralConfig.Bind(this); ClientConfig.Bind(this); ZoneBundleConfig.Bind(this); AutoArchiveConfig.Bind(this); } private void SetupWatchers() { EnsureDataDirectories(); _configWatcher = new FileSystemWatcher(Paths.ConfigPath, "sighsorry.ZoneSavior.cfg"); _configWatcher.Changed += ReadConfigValues; _configWatcher.Created += ReadConfigValues; _configWatcher.Renamed += ReadConfigValues; _configWatcher.IncludeSubdirectories = false; _configWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; _configWatcher.EnableRaisingEvents = true; _zoneRuleWatcher = new FileSystemWatcher(DataStorageFullPath, "zones.yml"); _zoneRuleWatcher.Changed += ReadZoneRuleValues; _zoneRuleWatcher.Created += ReadZoneRuleValues; _zoneRuleWatcher.Renamed += ReadZoneRuleValues; _zoneRuleWatcher.IncludeSubdirectories = false; _zoneRuleWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; _zoneRuleWatcher.EnableRaisingEvents = true; } private static void EnsureDataDirectories() { Directory.CreateDirectory(DataStorageFullPath); Directory.CreateDirectory(ZoneBundleStorageFullPath); } private void ReadConfigValues(object sender, FileSystemEventArgs e) { if (!CanReload(ref _lastConfigReloadTime)) { return; } lock (_reloadLock) { if (!File.Exists(ConfigFileFullPath)) { ZoneSaviorLogger.LogWarning((object)"Config file does not exist. Skipping reload."); return; } try { ZoneSaviorLogger.LogDebug((object)"Reloading configuration..."); ReloadConfigFromDisk(); ZoneSaviorLogger.LogInfo((object)"Configuration reload complete."); } catch (Exception arg) { ZoneSaviorLogger.LogError((object)$"Error reloading configuration: {arg}"); } } } private void ReadZoneRuleValues(object sender, FileSystemEventArgs e) { if (!CanReload(ref _lastZoneRuleReloadTime)) { return; } lock (_reloadLock) { try { ZoneSaviorFeatureBootstrap.ReloadZoneRulesFromDisk(); } catch (Exception arg) { ZoneSaviorLogger.LogError((object)$"Error reloading zone rule YAML: {arg}"); } } } private static bool CanReload(ref DateTime lastReloadTime) { DateTime now = DateTime.Now; if (now.Ticks - lastReloadTime.Ticks < 10000000) { return false; } lastReloadTime = now; return true; } private void SaveWithRespectToConfigSet(bool reload = false) { bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet; ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; if (reload) { ((BaseUnityPlugin)this).Config.Reload(); } ((BaseUnityPlugin)this).Config.Save(); ((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet; } private void ReloadConfigFromDisk() { bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet; ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; ((BaseUnityPlugin)this).Config.Reload(); ((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet; } internal ConfigEntry config(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown ConfigDescription val = new ConfigDescription(description.Description + (synchronizedSetting ? " [Synced with Server]" : " [Client Only]"), description.AcceptableValues, description.Tags); ConfigEntry val2 = ((BaseUnityPlugin)this).Config.Bind(group, name, value, val); ConfigSync.AddConfigEntry(val2).SynchronizedConfig = synchronizedSetting; return val2; } internal ConfigEntry config(string group, string name, T value, string description, bool synchronizedSetting = true) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty()), synchronizedSetting); } } public static class ToggleExtensions { [SpecialName] public sealed class $59729026E5FF074F3F69AF871D418641 { [SpecialName] public static class $6E098E68D44B10778B775ABA2AEEF21C { } [ExtensionMarker("$6E098E68D44B10778B775ABA2AEEF21C")] public bool IsOn() { throw new NotSupportedException(); } [ExtensionMarker("$6E098E68D44B10778B775ABA2AEEF21C")] public bool IsOff() { throw new NotSupportedException(); } } public static bool IsOn(this ZoneSaviorPlugin.Toggle value) { return value == ZoneSaviorPlugin.Toggle.On; } public static bool IsOff(this ZoneSaviorPlugin.Toggle value) { return value == ZoneSaviorPlugin.Toggle.Off; } } internal static class ZoneTerrainContactSampler { public static List CaptureWorldContacts(IEnumerable sources, float tolerance) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) Dictionary dictionary = new Dictionary(); foreach (TerrainContactSource source in sources) { if (Object.op_Implicit((Object)(object)source.Prefab) && !((Object)(object)source.Prefab.GetComponent() == (Object)null) && ZoneBundleTerrain.TryGetWearNTearBounds(source.Prefab, source.Position, source.Rotation, source.Scale, out var bounds)) { AddLowestBoundsFootprintContacts(bounds, dictionary); } } List list = new List(); foreach (TerrainWorldContact item in from contact in dictionary.Values orderby contact.WorldZ, contact.WorldX select contact) { if (ZoneBundleTerrain.TryGetTerrainHeight(item.WorldX, item.WorldZ, out var height) && !(Mathf.Abs(height - item.WorldY) > tolerance)) { list.Add(item); } } return list; } public static List FromZoneEntries(Vector2i zone, float sourceBaseY, IEnumerable entries) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) List list = new List(); if (float.IsNaN(sourceBaseY) || (Object)(object)ZNetScene.instance == (Object)null) { return list; } Vector3 zonePos = ZoneSystem.GetZonePos(zone); foreach (ZoneBundleEntry entry in entries) { GameObject prefab = ZNetScene.instance.GetPrefab(entry.Prefab); if (Object.op_Implicit((Object)(object)prefab) && !((Object)(object)prefab.GetComponent() == (Object)null)) { list.Add(new TerrainContactSource(prefab, new Vector3(zonePos.x + entry.LocalPos[0], sourceBaseY + entry.LocalPos[1], zonePos.z + entry.LocalPos[2]), new Quaternion(entry.Rot[0], entry.Rot[1], entry.Rot[2], entry.Rot[3]), new Vector3(entry.Scale[0], entry.Scale[1], entry.Scale[2]))); } } return list; } public static List ToZoneBundleContacts(Vector2i zone, float sourceBaseY, IEnumerable contacts) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) Vector3 zoneCenter = ZoneSystem.GetZonePos(zone); return (from contact in contacts select new ZoneBundleTerrainContact { LocalX = Round(contact.WorldX - zoneCenter.x), LocalZ = Round(contact.WorldZ - zoneCenter.z), RelativeY = Round(contact.WorldY - sourceBaseY) } into contact orderby contact.LocalZ, contact.LocalX select contact).ToList(); } public static List ToBlueprintContacts(Vector3 anchor, Quaternion inverseAnchorRotation, IEnumerable contacts) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) return (from contact in contacts.Select(delegate(TerrainWorldContact contact) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) Vector3 val = inverseAnchorRotation * (contact.ToVector3() - anchor); return new ZoneBlueprintTerrainContact { LocalX = Round(val.x), LocalY = Round(val.y), LocalZ = Round(val.z) }; }) orderby contact.LocalZ, contact.LocalX select contact).ToList(); } private static void AddLowestBoundsFootprintContacts(Bounds bounds, Dictionary lowestByCell) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) float y = ((Bounds)(ref bounds)).min.y; int num = Mathf.FloorToInt(((Bounds)(ref bounds)).min.x); int num2 = Mathf.CeilToInt(((Bounds)(ref bounds)).max.x); int num3 = Mathf.FloorToInt(((Bounds)(ref bounds)).min.z); int num4 = Mathf.CeilToInt(((Bounds)(ref bounds)).max.z); for (int i = num; i <= num2; i++) { for (int j = num3; j <= num4; j++) { long key = PackCell(i, j); TerrainWorldContact value = new TerrainWorldContact(i, j, y); if (!lowestByCell.TryGetValue(key, out var value2) || value.WorldY < value2.WorldY) { lowestByCell[key] = value; } } } } private static long PackCell(int x, int z) { return ((long)x << 32) ^ (uint)z; } private static float Round(float value) { return Mathf.Round(value * 1000f) / 1000f; } } internal readonly struct TerrainContactSource { public GameObject Prefab { get; } public Vector3 Position { get; } public Quaternion Rotation { get; } public Vector3 Scale { get; } public TerrainContactSource(GameObject prefab, Vector3 position, Quaternion rotation, Vector3 scale) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) Prefab = prefab; Position = position; Rotation = rotation; Scale = scale; } } internal readonly struct TerrainWorldContact { public float WorldX { get; } public float WorldZ { get; } public float WorldY { get; } public TerrainWorldContact(int cellX, int cellZ, float worldY) { WorldX = cellX; WorldZ = cellZ; WorldY = worldY; } public Vector3 ToVector3() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) return new Vector3(WorldX, WorldY, WorldZ); } } internal static class ZoneToolAim { private const float NativePlacementRayDistance = 50f; public static bool TryGetAimPoint(Player player, float maxToolDistance, out Vector3 point) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) point = default(Vector3); if ((Object)(object)player == (Object)null) { return false; } if (TryGetCameraRay(out var origin, out var direction)) { int num = ((player.m_placeRayMask != 0) ? player.m_placeRayMask : (-5)); float num2 = Mathf.Max(50f, maxToolDistance); RaycastHit val = default(RaycastHit); if (Physics.Raycast(origin, direction, ref val, num2, num, (QueryTriggerInteraction)1)) { point = ((RaycastHit)(ref val)).point; point.y = SampleGroundY(point.x, point.z, point.y); return true; } } return false; } public static float SampleGroundY(float x, float z, float fallbackY) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZoneSystem.instance == (Object)null) { return fallbackY; } Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(x, fallbackY, z); Vector3 val2 = default(Vector3); Biome val3 = default(Biome); BiomeArea val4 = default(BiomeArea); Heightmap val5 = default(Heightmap); ZoneSystem.instance.GetGroundData(ref val, ref val2, ref val3, ref val4, ref val5); return val.y; } private static bool TryGetCameraRay(out Vector3 origin, out Vector3 direction) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)GameCamera.instance != (Object)null) { Transform transform = ((Component)GameCamera.instance).transform; origin = transform.position; direction = transform.forward; return true; } Camera mainCamera = Utils.GetMainCamera(); if ((Object)(object)mainCamera != (Object)null) { Ray val = mainCamera.ScreenPointToRay(new Vector3((float)Screen.width * 0.5f, (float)Screen.height * 0.5f)); origin = ((Ray)(ref val)).origin; direction = ((Ray)(ref val)).direction; return true; } origin = default(Vector3); direction = default(Vector3); return false; } } internal static class ZoneWorldEditTerrainCompat { private const string WorldEditCommandsGuid = "world_edit_commands"; private static ManualLogSource? _logger; private static Harmony? _harmony; private static bool _patched; private static bool _missingLogged; internal static void Initialize(ManualLogSource logger, Harmony harmony) { _logger = logger; _harmony = harmony; TryPatch(); } internal static void Update() { if (!_patched) { TryPatch(); } } private static void TryPatch() { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown if (_patched) { return; } MethodInfo methodInfo = GetWorldEditCommandsType("WorldEditCommands.Terrain")?.GetMethod("ResetTerrain", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (methodInfo == null) { if (!_missingLogged) { ManualLogSource? logger = _logger; if (logger != null) { logger.LogInfo((object)"WorldEditCommands terrain reset compat: WorldEditCommands.Terrain.ResetTerrain not found yet."); } _missingLogged = true; } return; } MethodInfo methodInfo2 = AccessTools.Method(typeof(ZoneWorldEditTerrainCompat), "ResetTerrainPostfix", (Type[])null, (Type[])null); Harmony? harmony = _harmony; if (harmony != null) { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } _patched = true; ManualLogSource? logger2 = _logger; if (logger2 != null) { logger2.LogInfo((object)"WorldEditCommands terrain reset compat: patched terrain reset for ZoneSavior support-fill base layers."); } } private static Type? GetWorldEditCommandsType(string fullName) { if (!Chainloader.PluginInfos.TryGetValue("world_edit_commands", out var value)) { return null; } return (((object)value.Instance)?.GetType().Assembly)?.GetType(fullName, throwOnError: false); } private static void ResetTerrainPostfix(object __0, object __1, Vector3 __2, float __3) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) try { ZoneBundleTerrain.ResetSupportFillBaseLayer(__0 as IEnumerable, __1 as IEnumerable, __2, __3); } catch (Exception arg) { ManualLogSource? logger = _logger; if (logger != null) { logger.LogWarning((object)$"WorldEditCommands terrain reset compat failed: {arg}"); } } } } } namespace ServerSync { [PublicAPI] internal abstract class OwnConfigEntryBase { public object? LocalBaseValue; public bool SynchronizedConfig = true; public abstract ConfigEntryBase BaseConfig { get; } } [PublicAPI] internal class SyncedConfigEntry : OwnConfigEntryBase { public readonly ConfigEntry SourceConfig; public override ConfigEntryBase BaseConfig => (ConfigEntryBase)(object)SourceConfig; public T Value { get { return SourceConfig.Value; } set { SourceConfig.Value = value; } } public SyncedConfigEntry(ConfigEntry sourceConfig) { SourceConfig = sourceConfig; base..ctor(); } public void AssignLocalValue(T value) { if (LocalBaseValue == null) { Value = value; } else { LocalBaseValue = value; } } } internal abstract class CustomSyncedValueBase { public object? LocalBaseValue; public readonly string Identifier; public readonly Type Type; private object? boxedValue; protected bool localIsOwner; public readonly int Priority; public object? BoxedValue { get { return boxedValue; } set { boxedValue = value; this.ValueChanged?.Invoke(); } } public event Action? ValueChanged; protected CustomSyncedValueBase(ConfigSync configSync, string identifier, Type type, int priority) { Priority = priority; Identifier = identifier; Type = type; configSync.AddCustomValue(this); localIsOwner = configSync.IsSourceOfTruth; configSync.SourceOfTruthChanged += delegate(bool truth) { localIsOwner = truth; }; } } [PublicAPI] internal sealed class CustomSyncedValue : CustomSyncedValueBase { public T Value { get { return (T)base.BoxedValue; } set { base.BoxedValue = value; } } public CustomSyncedValue(ConfigSync configSync, string identifier, T value = default(T), int priority = 0) : base(configSync, identifier, typeof(T), priority) { Value = value; } public void AssignLocalValue(T value) { if (localIsOwner) { Value = value; } else { LocalBaseValue = value; } } } internal class ConfigurationManagerAttributes { [UsedImplicitly] public bool? ReadOnly = false; } [PublicAPI] internal class ConfigSync { [HarmonyPatch(typeof(ZRpc), "HandlePackage")] private static class SnatchCurrentlyHandlingRPC { public static ZRpc? currentRpc; [HarmonyPrefix] private static void Prefix(ZRpc __instance) { currentRpc = __instance; } } [HarmonyPatch(typeof(ZNet), "Awake")] internal static class RegisterRPCPatch { [HarmonyPostfix] private static void Postfix(ZNet __instance) { isServer = __instance.IsServer(); foreach (ConfigSync configSync2 in configSyncs) { ZRoutedRpc.instance.Register(configSync2.Name + " ConfigSync", (Action)configSync2.RPC_FromOtherClientConfigSync); if (isServer) { configSync2.InitialSyncDone = true; Debug.Log((object)("Registered '" + configSync2.Name + " ConfigSync' RPC - waiting for incoming connections")); } } if (isServer) { ((MonoBehaviour)__instance).StartCoroutine(WatchAdminListChanges()); } static void SendAdmin(List peers, bool isAdmin) { ZPackage package = ConfigsToPackage(null, null, new PackageEntry[1] { new PackageEntry { section = "Internal", key = "lockexempt", type = typeof(bool), value = isAdmin } }); ConfigSync configSync = configSyncs.First(); if (configSync != null) { ((MonoBehaviour)ZNet.instance).StartCoroutine(configSync.sendZPackage(peers, package)); } } static IEnumerator WatchAdminListChanges() { MethodInfo listContainsId = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null); SyncedList adminList = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance); List CurrentList = new List(adminList.GetList()); while (true) { yield return (object)new WaitForSeconds(30f); if (!adminList.GetList().SequenceEqual(CurrentList)) { CurrentList = new List(adminList.GetList()); List adminPeer = ZNet.instance.GetPeers().Where(delegate(ZNetPeer p) { string hostName = p.m_rpc.GetSocket().GetHostName(); return ((object)listContainsId == null) ? adminList.Contains(hostName) : ((bool)listContainsId.Invoke(ZNet.instance, new object[2] { adminList, hostName })); }).ToList(); List nonAdminPeer = ZNet.instance.GetPeers().Except(adminPeer).ToList(); SendAdmin(nonAdminPeer, isAdmin: false); SendAdmin(adminPeer, isAdmin: true); } } } } } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] private static class RegisterClientRPCPatch { [HarmonyPostfix] private static void Postfix(ZNet __instance, ZNetPeer peer) { if (__instance.IsServer()) { return; } foreach (ConfigSync configSync in configSyncs) { peer.m_rpc.Register(configSync.Name + " ConfigSync", (Action)configSync.RPC_FromServerConfigSync); } } } private class ParsedConfigs { public readonly Dictionary configValues = new Dictionary(); public readonly Dictionary customValues = new Dictionary(); } [HarmonyPatch(typeof(ZNet), "Shutdown")] private class ResetConfigsOnShutdown { [HarmonyPostfix] private static void Postfix() { ProcessingServerUpdate = true; foreach (ConfigSync configSync in configSyncs) { configSync.resetConfigsFromServer(); configSync.IsSourceOfTruth = true; configSync.InitialSyncDone = false; } ProcessingServerUpdate = false; } } [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] private class SendConfigsAfterLogin { private class BufferingSocket : ZPlayFabSocket, ISocket { public volatile bool finished = false; public volatile int versionMatchQueued = -1; public readonly List Package = new List(); public readonly ISocket Original; public BufferingSocket(ISocket original) { Original = original; ((ZPlayFabSocket)this)..ctor(); } public bool IsConnected() { return Original.IsConnected(); } public ZPackage Recv() { return Original.Recv(); } public int GetSendQueueSize() { return Original.GetSendQueueSize(); } public int GetCurrentSendRate() { return Original.GetCurrentSendRate(); } public bool IsHost() { return Original.IsHost(); } public void Dispose() { Original.Dispose(); } public bool GotNewData() { return Original.GotNewData(); } public void Close() { Original.Close(); } public string GetEndPointString() { return Original.GetEndPointString(); } public void GetAndResetStats(out int totalSent, out int totalRecv) { Original.GetAndResetStats(ref totalSent, ref totalRecv); } public void GetConnectionQuality(out float localQuality, out float remoteQuality, out int ping, out float outByteSec, out float inByteSec) { Original.GetConnectionQuality(ref localQuality, ref remoteQuality, ref ping, ref outByteSec, ref inByteSec); } public ISocket Accept() { return Original.Accept(); } public int GetHostPort() { return Original.GetHostPort(); } public bool Flush() { return Original.Flush(); } public string GetHostName() { return Original.GetHostName(); } public void VersionMatch() { if (finished) { Original.VersionMatch(); } else { versionMatchQueued = Package.Count; } } public void Send(ZPackage pkg) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown int pos = pkg.GetPos(); pkg.SetPos(0); int num = pkg.ReadInt(); if ((num == StringExtensionMethods.GetStableHashCode("PeerInfo") || num == StringExtensionMethods.GetStableHashCode("RoutedRPC") || num == StringExtensionMethods.GetStableHashCode("ZDOData")) && !finished) { ZPackage val = new ZPackage(pkg.GetArray()); val.SetPos(pos); Package.Add(val); } else { pkg.SetPos(pos); Original.Send(pkg); } } } [HarmonyPriority(800)] [HarmonyPrefix] private static void Prefix(ref Dictionary? __state, ZNet __instance, ZRpc rpc) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Invalid comparison between Unknown and I4 if (!__instance.IsServer()) { return; } BufferingSocket bufferingSocket = new BufferingSocket(rpc.GetSocket()); AccessTools.DeclaredField(typeof(ZRpc), "m_socket").SetValue(rpc, bufferingSocket); object? obj = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance, new object[1] { rpc }); ZNetPeer val = (ZNetPeer)((obj is ZNetPeer) ? obj : null); if (val != null && (int)ZNet.m_onlineBackend > 0) { FieldInfo fieldInfo = AccessTools.DeclaredField(typeof(ZNetPeer), "m_socket"); object? value = fieldInfo.GetValue(val); ZPlayFabSocket val2 = (ZPlayFabSocket)((value is ZPlayFabSocket) ? value : null); if (val2 != null) { typeof(ZPlayFabSocket).GetField("m_remotePlayerId").SetValue(bufferingSocket, val2.m_remotePlayerId); } fieldInfo.SetValue(val, bufferingSocket); } if (__state == null) { __state = new Dictionary(); } __state[Assembly.GetExecutingAssembly()] = bufferingSocket; } [HarmonyPostfix] private static void Postfix(Dictionary __state, ZNet __instance, ZRpc rpc) { ZRpc rpc2 = rpc; ZNet __instance2 = __instance; Dictionary __state2 = __state; ZNetPeer peer; if (__instance2.IsServer()) { object obj = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance2, new object[1] { rpc2 }); peer = (ZNetPeer)((obj is ZNetPeer) ? obj : null); if (peer == null) { SendBufferedData(); } else { ((MonoBehaviour)__instance2).StartCoroutine(sendAsync()); } } void SendBufferedData() { if (rpc2.GetSocket() is BufferingSocket bufferingSocket) { AccessTools.DeclaredField(typeof(ZRpc), "m_socket").SetValue(rpc2, bufferingSocket.Original); object? obj2 = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance2, new object[1] { rpc2 }); ZNetPeer val = (ZNetPeer)((obj2 is ZNetPeer) ? obj2 : null); if (val != null) { AccessTools.DeclaredField(typeof(ZNetPeer), "m_socket").SetValue(val, bufferingSocket.Original); } } BufferingSocket bufferingSocket2 = __state2[Assembly.GetExecutingAssembly()]; bufferingSocket2.finished = true; for (int i = 0; i < bufferingSocket2.Package.Count; i++) { if (i == bufferingSocket2.versionMatchQueued) { bufferingSocket2.Original.VersionMatch(); } bufferingSocket2.Original.Send(bufferingSocket2.Package[i]); } if (bufferingSocket2.Package.Count == bufferingSocket2.versionMatchQueued) { bufferingSocket2.Original.VersionMatch(); } } IEnumerator sendAsync() { foreach (ConfigSync configSync in configSyncs) { List entries = new List(); if (configSync.CurrentVersion != null) { entries.Add(new PackageEntry { section = "Internal", key = "serverversion", type = typeof(string), value = configSync.CurrentVersion }); } MethodInfo listContainsId = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null); SyncedList adminList = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance); entries.Add(new PackageEntry { section = "Internal", key = "lockexempt", type = typeof(bool), value = (((object)listContainsId == null) ? ((object)adminList.Contains(rpc2.GetSocket().GetHostName())) : listContainsId.Invoke(ZNet.instance, new object[2] { adminList, rpc2.GetSocket().GetHostName() })) }); ZPackage package = ConfigsToPackage(configSync.allConfigs.Select((OwnConfigEntryBase c) => c.BaseConfig), configSync.allCustomValues, entries, partial: false); yield return ((MonoBehaviour)__instance2).StartCoroutine(configSync.sendZPackage(new List { peer }, package)); } SendBufferedData(); } } } private class PackageEntry { public string section = null; public string key = null; public Type type = null; public object? value; } [HarmonyPatch(typeof(ConfigEntryBase), "GetSerializedValue")] private static class PreventSavingServerInfo { [HarmonyPrefix] private static bool Prefix(ConfigEntryBase __instance, ref string __result) { OwnConfigEntryBase ownConfigEntryBase = configData(__instance); if (ownConfigEntryBase == null || isWritableConfig(ownConfigEntryBase)) { return true; } __result = TomlTypeConverter.ConvertToString(ownConfigEntryBase.LocalBaseValue, __instance.SettingType); return false; } } [HarmonyPatch(typeof(ConfigEntryBase), "SetSerializedValue")] private static class PreventConfigRereadChangingValues { [HarmonyPrefix] private static bool Prefix(ConfigEntryBase __instance, string value) { OwnConfigEntryBase ownConfigEntryBase = configData(__instance); if (ownConfigEntryBase == null || ownConfigEntryBase.LocalBaseValue == null) { return true; } try { ownConfigEntryBase.LocalBaseValue = TomlTypeConverter.ConvertToValue(value, __instance.SettingType); } catch (Exception ex) { Debug.LogWarning((object)$"Config value of setting \"{__instance.Definition}\" could not be parsed and will be ignored. Reason: {ex.Message}; Value: {value}"); } return false; } } private class InvalidDeserializationTypeException : Exception { public string expected = null; public string received = null; public string field = ""; } public static bool ProcessingServerUpdate; public readonly string Name; public string? DisplayName; public string? CurrentVersion; public string? MinimumRequiredVersion; public bool ModRequired = false; private bool? forceConfigLocking; private bool isSourceOfTruth = true; private static readonly HashSet configSyncs; private readonly HashSet allConfigs = new HashSet(); private HashSet allCustomValues = new HashSet(); private static bool isServer; private static bool lockExempt; private OwnConfigEntryBase? lockedConfig = null; private const byte PARTIAL_CONFIGS = 1; private const byte FRAGMENTED_CONFIG = 2; private const byte COMPRESSED_CONFIG = 4; private readonly Dictionary> configValueCache = new Dictionary>(); private readonly List> cacheExpirations = new List>(); private static long packageCounter; public bool IsLocked { get { bool? flag = forceConfigLocking; bool num; if (!flag.HasValue) { if (lockedConfig == null) { goto IL_0052; } num = ((IConvertible)lockedConfig.BaseConfig.BoxedValue).ToInt32(CultureInfo.InvariantCulture) != 0; } else { num = flag.GetValueOrDefault(); } if (!num) { goto IL_0052; } int result = ((!lockExempt) ? 1 : 0); goto IL_0053; IL_0053: return (byte)result != 0; IL_0052: result = 0; goto IL_0053; } set { forceConfigLocking = value; } } public bool IsAdmin => lockExempt || isSourceOfTruth; public bool IsSourceOfTruth { get { return isSourceOfTruth; } private set { if (value != isSourceOfTruth) { isSourceOfTruth = value; this.SourceOfTruthChanged?.Invoke(value); } } } public bool InitialSyncDone { get; private set; } = false; public event Action? SourceOfTruthChanged; private event Action? lockedConfigChanged; static ConfigSync() { ProcessingServerUpdate = false; configSyncs = new HashSet(); lockExempt = false; packageCounter = 0L; RuntimeHelpers.RunClassConstructor(typeof(VersionCheck).TypeHandle); } public ConfigSync(string name) { Name = name; configSyncs.Add(this); new VersionCheck(this); } public SyncedConfigEntry AddConfigEntry(ConfigEntry configEntry) { ConfigEntry configEntry2 = configEntry; OwnConfigEntryBase ownConfigEntryBase = configData((ConfigEntryBase)(object)configEntry2); SyncedConfigEntry syncedEntry = ownConfigEntryBase as SyncedConfigEntry; if (syncedEntry == null) { syncedEntry = new SyncedConfigEntry(configEntry2); AccessTools.DeclaredField(typeof(ConfigDescription), "k__BackingField").SetValue(((ConfigEntryBase)configEntry2).Description, new object[1] { new ConfigurationManagerAttributes() }.Concat(((ConfigEntryBase)configEntry2).Description.Tags ?? Array.Empty()).Concat(new SyncedConfigEntry[1] { syncedEntry }).ToArray()); configEntry2.SettingChanged += delegate { if (!ProcessingServerUpdate && syncedEntry.SynchronizedConfig) { Broadcast(ZRoutedRpc.Everybody, (ConfigEntryBase)configEntry2); } }; allConfigs.Add(syncedEntry); } return syncedEntry; } public SyncedConfigEntry AddLockingConfigEntry(ConfigEntry lockingConfig) where T : IConvertible { if (lockedConfig != null) { throw new Exception("Cannot initialize locking ConfigEntry twice"); } lockedConfig = AddConfigEntry(lockingConfig); lockingConfig.SettingChanged += delegate { this.lockedConfigChanged?.Invoke(); }; return (SyncedConfigEntry)lockedConfig; } internal void AddCustomValue(CustomSyncedValueBase customValue) { CustomSyncedValueBase customValue2 = customValue; if (allCustomValues.Select((CustomSyncedValueBase v) => v.Identifier).Concat(new string[1] { "serverversion" }).Contains(customValue2.Identifier)) { throw new Exception("Cannot have multiple settings with the same name or with a reserved name (serverversion)"); } allCustomValues.Add(customValue2); allCustomValues = new HashSet(allCustomValues.OrderByDescending((CustomSyncedValueBase v) => v.Priority)); customValue2.ValueChanged += delegate { if (!ProcessingServerUpdate) { Broadcast(ZRoutedRpc.Everybody, customValue2); } }; } private void RPC_FromServerConfigSync(ZRpc rpc, ZPackage package) { lockedConfigChanged += serverLockedSettingChanged; IsSourceOfTruth = false; if (HandleConfigSyncRPC(0L, package, clientUpdate: false)) { InitialSyncDone = true; } } private void RPC_FromOtherClientConfigSync(long sender, ZPackage package) { HandleConfigSyncRPC(sender, package, clientUpdate: true); } private bool HandleConfigSyncRPC(long sender, ZPackage package, bool clientUpdate) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Expected O, but got Unknown //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Expected O, but got Unknown try { if (isServer && IsLocked) { ZRpc? currentRpc = SnatchCurrentlyHandlingRPC.currentRpc; object obj; if (currentRpc == null) { obj = null; } else { ISocket socket = currentRpc.GetSocket(); obj = ((socket != null) ? socket.GetHostName() : null); } string text = (string)obj; if (text != null) { MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null); SyncedList val = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance); if (!(((object)methodInfo == null) ? val.Contains(text) : ((bool)methodInfo.Invoke(ZNet.instance, new object[2] { val, text })))) { return false; } } } cacheExpirations.RemoveAll(delegate(KeyValuePair kv) { if (kv.Key < DateTimeOffset.Now.Ticks) { configValueCache.Remove(kv.Value); return true; } return false; }); byte b = package.ReadByte(); if ((b & 2u) != 0) { long num = package.ReadLong(); string text2 = sender.ToString() + num; if (!configValueCache.TryGetValue(text2, out SortedDictionary value)) { value = new SortedDictionary(); configValueCache[text2] = value; cacheExpirations.Add(new KeyValuePair(DateTimeOffset.Now.AddSeconds(60.0).Ticks, text2)); } int key = package.ReadInt(); int num2 = package.ReadInt(); value.Add(key, package.ReadByteArray()); if (value.Count < num2) { return false; } configValueCache.Remove(text2); package = new ZPackage(value.Values.SelectMany((byte[] a) => a).ToArray()); b = package.ReadByte(); } ProcessingServerUpdate = true; if ((b & 4u) != 0) { byte[] buffer = package.ReadByteArray(); MemoryStream stream = new MemoryStream(buffer); MemoryStream memoryStream = new MemoryStream(); using (DeflateStream deflateStream = new DeflateStream(stream, CompressionMode.Decompress)) { deflateStream.CopyTo(memoryStream); } package = new ZPackage(memoryStream.ToArray()); b = package.ReadByte(); } if ((b & 1) == 0) { resetConfigsFromServer(); } ParsedConfigs parsedConfigs = ReadConfigsFromPackage(package); ConfigFile val2 = null; bool saveOnConfigSet = false; foreach (KeyValuePair configValue in parsedConfigs.configValues) { if (!isServer && configValue.Key.LocalBaseValue == null) { configValue.Key.LocalBaseValue = configValue.Key.BaseConfig.BoxedValue; } if (val2 == null) { val2 = configValue.Key.BaseConfig.ConfigFile; saveOnConfigSet = val2.SaveOnConfigSet; val2.SaveOnConfigSet = false; } configValue.Key.BaseConfig.BoxedValue = configValue.Value; } if (val2 != null) { val2.SaveOnConfigSet = saveOnConfigSet; val2.Save(); } foreach (KeyValuePair customValue in parsedConfigs.customValues) { if (!isServer) { CustomSyncedValueBase key2 = customValue.Key; if (key2.LocalBaseValue == null) { key2.LocalBaseValue = customValue.Key.BoxedValue; } } customValue.Key.BoxedValue = customValue.Value; } Debug.Log((object)string.Format("Received {0} configs and {1} custom values from {2} for mod {3}", parsedConfigs.configValues.Count, parsedConfigs.customValues.Count, (isServer || clientUpdate) ? $"client {sender}" : "the server", DisplayName ?? Name)); if (!isServer) { serverLockedSettingChanged(); } return true; } finally { ProcessingServerUpdate = false; } } private ParsedConfigs ReadConfigsFromPackage(ZPackage package) { ParsedConfigs parsedConfigs = new ParsedConfigs(); Dictionary dictionary = allConfigs.Where((OwnConfigEntryBase c) => c.SynchronizedConfig).ToDictionary((OwnConfigEntryBase c) => c.BaseConfig.Definition.Section + "_" + c.BaseConfig.Definition.Key, (OwnConfigEntryBase c) => c); Dictionary dictionary2 = allCustomValues.ToDictionary((CustomSyncedValueBase c) => c.Identifier, (CustomSyncedValueBase c) => c); int num = package.ReadInt(); for (int i = 0; i < num; i++) { string text = package.ReadString(); string text2 = package.ReadString(); string text3 = package.ReadString(); Type type = Type.GetType(text3); if (text3 == "" || type != null) { object obj; try { obj = ((text3 == "") ? null : ReadValueWithTypeFromZPackage(package, type)); } catch (InvalidDeserializationTypeException ex) { Debug.LogWarning((object)("Got unexpected struct internal type " + ex.received + " for field " + ex.field + " struct " + text3 + " for " + text2 + " in section " + text + " for mod " + (DisplayName ?? Name) + ", expecting " + ex.expected)); continue; } OwnConfigEntryBase value2; if (text == "Internal") { CustomSyncedValueBase value; if (text2 == "serverversion") { if (obj?.ToString() != CurrentVersion) { Debug.LogWarning((object)("Received server version is not equal: server version = " + (obj?.ToString() ?? "null") + "; local version = " + (CurrentVersion ?? "unknown"))); } } else if (text2 == "lockexempt") { if (obj is bool flag) { lockExempt = flag; } } else if (dictionary2.TryGetValue(text2, out value)) { if ((text3 == "" && (!value.Type.IsValueType || Nullable.GetUnderlyingType(value.Type) != null)) || GetZPackageTypeString(value.Type) == text3) { parsedConfigs.customValues[value] = obj; continue; } Debug.LogWarning((object)("Got unexpected type " + text3 + " for internal value " + text2 + " for mod " + (DisplayName ?? Name) + ", expecting " + value.Type.AssemblyQualifiedName)); } } else if (dictionary.TryGetValue(text + "_" + text2, out value2)) { Type type2 = configType(value2.BaseConfig); if ((text3 == "" && (!type2.IsValueType || Nullable.GetUnderlyingType(type2) != null)) || GetZPackageTypeString(type2) == text3) { parsedConfigs.configValues[value2] = obj; continue; } Debug.LogWarning((object)("Got unexpected type " + text3 + " for " + text2 + " in section " + text + " for mod " + (DisplayName ?? Name) + ", expecting " + type2.AssemblyQualifiedName)); } else { Debug.LogWarning((object)("Received unknown config entry " + text2 + " in section " + text + " for mod " + (DisplayName ?? Name) + ". This may happen if client and server versions of the mod do not match.")); } continue; } Debug.LogWarning((object)("Got invalid type " + text3 + ", abort reading of received configs")); return new ParsedConfigs(); } return parsedConfigs; } private static bool isWritableConfig(OwnConfigEntryBase config) { OwnConfigEntryBase config2 = config; ConfigSync configSync = configSyncs.FirstOrDefault((ConfigSync cs) => cs.allConfigs.Contains(config2)); if (configSync == null) { return true; } return configSync.IsSourceOfTruth || !config2.SynchronizedConfig || config2.LocalBaseValue == null || (!configSync.IsLocked && (config2 != configSync.lockedConfig || lockExempt)); } private void serverLockedSettingChanged() { foreach (OwnConfigEntryBase allConfig in allConfigs) { configAttribute(allConfig.BaseConfig).ReadOnly = !isWritableConfig(allConfig); } } private void resetConfigsFromServer() { ConfigFile val = null; bool saveOnConfigSet = false; foreach (OwnConfigEntryBase item in allConfigs.Where((OwnConfigEntryBase config) => config.LocalBaseValue != null)) { if (val == null) { val = item.BaseConfig.ConfigFile; saveOnConfigSet = val.SaveOnConfigSet; val.SaveOnConfigSet = false; } item.BaseConfig.BoxedValue = item.LocalBaseValue; item.LocalBaseValue = null; } if (val != null) { val.SaveOnConfigSet = saveOnConfigSet; } foreach (CustomSyncedValueBase item2 in allCustomValues.Where((CustomSyncedValueBase config) => config.LocalBaseValue != null)) { item2.BoxedValue = item2.LocalBaseValue; item2.LocalBaseValue = null; } lockedConfigChanged -= serverLockedSettingChanged; serverLockedSettingChanged(); } private IEnumerator distributeConfigToPeers(ZNetPeer peer, ZPackage package) { ZNetPeer peer2 = peer; ZRoutedRpc rpc = ZRoutedRpc.instance; if (rpc == null) { yield break; } byte[] data = package.GetArray(); if (data != null && data.LongLength > 250000) { int fragments = (int)(1 + (data.LongLength - 1) / 250000); long packageIdentifier = ++packageCounter; int fragment = 0; while (fragment < fragments) { foreach (bool item in waitForQueue()) { yield return item; } if (peer2.m_socket.IsConnected()) { ZPackage fragmentedPackage = new ZPackage(); fragmentedPackage.Write((byte)2); fragmentedPackage.Write(packageIdentifier); fragmentedPackage.Write(fragment); fragmentedPackage.Write(fragments); fragmentedPackage.Write(data.Skip(250000 * fragment).Take(250000).ToArray()); SendPackage(fragmentedPackage); if (fragment != fragments - 1) { yield return true; } int num = fragment + 1; fragment = num; continue; } break; } yield break; } foreach (bool item2 in waitForQueue()) { yield return item2; } SendPackage(package); void SendPackage(ZPackage pkg) { string text = Name + " ConfigSync"; if (isServer) { peer2.m_rpc.Invoke(text, new object[1] { pkg }); } else { rpc.InvokeRoutedRPC(peer2.m_server ? 0 : peer2.m_uid, text, new object[1] { pkg }); } } IEnumerable waitForQueue() { float timeout = Time.time + 30f; while (peer2.m_socket.GetSendQueueSize() > 20000) { if (Time.time > timeout) { Debug.Log((object)$"Disconnecting {peer2.m_uid} after 30 seconds config sending timeout"); peer2.m_rpc.Invoke("Error", new object[1] { (object)(ConnectionStatus)5 }); ZNet.instance.Disconnect(peer2); break; } yield return false; } } } private IEnumerator sendZPackage(long target, ZPackage package) { if (!Object.op_Implicit((Object)(object)ZNet.instance)) { return Enumerable.Empty().GetEnumerator(); } List list = (List)AccessTools.DeclaredField(typeof(ZRoutedRpc), "m_peers").GetValue(ZRoutedRpc.instance); if (target != ZRoutedRpc.Everybody) { list = list.Where((ZNetPeer p) => p.m_uid == target).ToList(); } return sendZPackage(list, package); } private IEnumerator sendZPackage(List peers, ZPackage package) { ZPackage package2 = package; if (!Object.op_Implicit((Object)(object)ZNet.instance)) { yield break; } byte[] rawData = package2.GetArray(); if (rawData != null && rawData.LongLength > 10000) { ZPackage compressedPackage = new ZPackage(); compressedPackage.Write((byte)4); MemoryStream output = new MemoryStream(); using (DeflateStream deflateStream = new DeflateStream(output, CompressionLevel.Optimal)) { deflateStream.Write(rawData, 0, rawData.Length); } compressedPackage.Write(output.ToArray()); package2 = compressedPackage; } List> writers = (from peer in peers where peer.IsReady() select peer into p select distributeConfigToPeers(p, package2)).ToList(); writers.RemoveAll((IEnumerator writer) => !writer.MoveNext()); while (writers.Count > 0) { yield return null; writers.RemoveAll((IEnumerator writer) => !writer.MoveNext()); } } private void Broadcast(long target, params ConfigEntryBase[] configs) { if (!IsLocked || isServer) { ZPackage package = ConfigsToPackage(configs); ZNet instance = ZNet.instance; if (instance != null) { ((MonoBehaviour)instance).StartCoroutine(sendZPackage(target, package)); } } } private void Broadcast(long target, params CustomSyncedValueBase[] customValues) { if (!IsLocked || isServer) { ZPackage package = ConfigsToPackage(null, customValues); ZNet instance = ZNet.instance; if (instance != null) { ((MonoBehaviour)instance).StartCoroutine(sendZPackage(target, package)); } } } private static OwnConfigEntryBase? configData(ConfigEntryBase config) { return config.Description.Tags?.OfType().SingleOrDefault(); } public static SyncedConfigEntry? ConfigData(ConfigEntry config) { return ((ConfigEntryBase)config).Description.Tags?.OfType>().SingleOrDefault(); } private static T configAttribute(ConfigEntryBase config) { return config.Description.Tags.OfType().First(); } private static Type configType(ConfigEntryBase config) { return configType(config.SettingType); } private static Type configType(Type type) { return type.IsEnum ? Enum.GetUnderlyingType(type) : type; } private static ZPackage ConfigsToPackage(IEnumerable? configs = null, IEnumerable? customValues = null, IEnumerable? packageEntries = null, bool partial = true) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown List list = configs?.Where((ConfigEntryBase config) => configData(config).SynchronizedConfig).ToList() ?? new List(); List list2 = customValues?.ToList() ?? new List(); ZPackage val = new ZPackage(); val.Write((byte)(partial ? 1 : 0)); val.Write(list.Count + list2.Count + (packageEntries?.Count() ?? 0)); foreach (PackageEntry item in packageEntries ?? Array.Empty()) { AddEntryToPackage(val, item); } foreach (CustomSyncedValueBase item2 in list2) { AddEntryToPackage(val, new PackageEntry { section = "Internal", key = item2.Identifier, type = item2.Type, value = item2.BoxedValue }); } foreach (ConfigEntryBase item3 in list) { AddEntryToPackage(val, new PackageEntry { section = item3.Definition.Section, key = item3.Definition.Key, type = configType(item3), value = item3.BoxedValue }); } return val; } private static void AddEntryToPackage(ZPackage package, PackageEntry entry) { package.Write(entry.section); package.Write(entry.key); package.Write((entry.value == null) ? "" : GetZPackageTypeString(entry.type)); AddValueToZPackage(package, entry.value); } private static string GetZPackageTypeString(Type type) { return type.AssemblyQualifiedName; } private static void AddValueToZPackage(ZPackage package, object? value) { Type type = value?.GetType(); if (value is Enum) { value = ((IConvertible)value).ToType(Enum.GetUnderlyingType(value.GetType()), CultureInfo.InvariantCulture); } else { if (value is ICollection collection) { package.Write(collection.Count); { foreach (object item in collection) { AddValueToZPackage(package, item); } return; } } if ((object)type != null && type.IsValueType && !type.IsPrimitive) { FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); package.Write(fields.Length); FieldInfo[] array = fields; foreach (FieldInfo fieldInfo in array) { package.Write(GetZPackageTypeString(fieldInfo.FieldType)); AddValueToZPackage(package, fieldInfo.GetValue(value)); } return; } } ZRpc.Serialize(new object[1] { value }, ref package); } private static object ReadValueWithTypeFromZPackage(ZPackage package, Type type) { if ((object)type != null && type.IsValueType && !type.IsPrimitive && !type.IsEnum) { FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); int num = package.ReadInt(); if (num != fields.Length) { throw new InvalidDeserializationTypeException { received = $"(field count: {num})", expected = $"(field count: {fields.Length})" }; } object uninitializedObject = FormatterServices.GetUninitializedObject(type); FieldInfo[] array = fields; foreach (FieldInfo fieldInfo in array) { string text = package.ReadString(); if (text != GetZPackageTypeString(fieldInfo.FieldType)) { throw new InvalidDeserializationTypeException { received = text, expected = GetZPackageTypeString(fieldInfo.FieldType), field = fieldInfo.Name }; } fieldInfo.SetValue(uninitializedObject, ReadValueWithTypeFromZPackage(package, fieldInfo.FieldType)); } return uninitializedObject; } if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<, >)) { int num2 = package.ReadInt(); IDictionary dictionary = (IDictionary)Activator.CreateInstance(type); Type type2 = typeof(KeyValuePair<, >).MakeGenericType(type.GenericTypeArguments); FieldInfo field = type2.GetField("key", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo field2 = type2.GetField("value", BindingFlags.Instance | BindingFlags.NonPublic); for (int j = 0; j < num2; j++) { object obj = ReadValueWithTypeFromZPackage(package, type2); dictionary.Add(field.GetValue(obj), field2.GetValue(obj)); } return dictionary; } if (type != typeof(List) && type.IsGenericType) { Type type3 = typeof(ICollection<>).MakeGenericType(type.GenericTypeArguments[0]); if ((object)type3 != null && type3.IsAssignableFrom(type)) { int num3 = package.ReadInt(); object obj2 = Activator.CreateInstance(type); MethodInfo method = type3.GetMethod("Add"); for (int k = 0; k < num3; k++) { method.Invoke(obj2, new object[1] { ReadValueWithTypeFromZPackage(package, type.GenericTypeArguments[0]) }); } return obj2; } } ParameterInfo parameterInfo = (ParameterInfo)FormatterServices.GetUninitializedObject(typeof(ParameterInfo)); AccessTools.DeclaredField(typeof(ParameterInfo), "ClassImpl").SetValue(parameterInfo, type); List source = new List(); ZRpc.Deserialize(new ParameterInfo[2] { null, parameterInfo }, package, ref source); return source.First(); } } [PublicAPI] [HarmonyPatch] internal class VersionCheck { private static readonly HashSet versionChecks; private static readonly Dictionary notProcessedNames; public string Name; private string? displayName; private string? currentVersion; private string? minimumRequiredVersion; public bool ModRequired = true; private string? ReceivedCurrentVersion; private string? ReceivedMinimumRequiredVersion; private readonly List ValidatedClients = new List(); private ConfigSync? ConfigSync; public string DisplayName { get { return displayName ?? Name; } set { displayName = value; } } public string CurrentVersion { get { return currentVersion ?? "0.0.0"; } set { currentVersion = value; } } public string MinimumRequiredVersion { get { return minimumRequiredVersion ?? (ModRequired ? CurrentVersion : "0.0.0"); } set { minimumRequiredVersion = value; } } private static void PatchServerSync() { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown Patches patchInfo = PatchProcessor.GetPatchInfo((MethodBase)AccessTools.DeclaredMethod(typeof(ZNet), "Awake", (Type[])null, (Type[])null)); if (patchInfo != null && patchInfo.Postfixes.Count((Patch p) => p.PatchMethod.DeclaringType == typeof(ConfigSync.RegisterRPCPatch)) > 0) { return; } Harmony val = new Harmony("org.bepinex.helpers.ServerSync"); foreach (Type item in from t in typeof(ConfigSync).GetNestedTypes(BindingFlags.NonPublic).Concat(new Type[1] { typeof(VersionCheck) }) where t.IsClass select t) { val.PatchAll(item); } } static VersionCheck() { versionChecks = new HashSet(); notProcessedNames = new Dictionary(); typeof(ThreadingHelper).GetMethod("StartSyncInvoke").Invoke(ThreadingHelper.Instance, new object[1] { new Action(PatchServerSync) }); } public VersionCheck(string name) { Name = name; ModRequired = true; versionChecks.Add(this); } public VersionCheck(ConfigSync configSync) { ConfigSync = configSync; Name = ConfigSync.Name; versionChecks.Add(this); } public void Initialize() { ReceivedCurrentVersion = null; ReceivedMinimumRequiredVersion = null; if (ConfigSync != null) { Name = ConfigSync.Name; DisplayName = ConfigSync.DisplayName; CurrentVersion = ConfigSync.CurrentVersion; MinimumRequiredVersion = ConfigSync.MinimumRequiredVersion; ModRequired = ConfigSync.ModRequired; } } private bool IsVersionOk() { if (ReceivedMinimumRequiredVersion == null || ReceivedCurrentVersion == null) { return !ModRequired; } bool flag = new System.Version(CurrentVersion) >= new System.Version(ReceivedMinimumRequiredVersion); bool flag2 = new System.Version(ReceivedCurrentVersion) >= new System.Version(MinimumRequiredVersion); return flag && flag2; } private string ErrorClient() { if (ReceivedMinimumRequiredVersion == null) { return DisplayName + " is not installed on the server."; } return (new System.Version(CurrentVersion) >= new System.Version(ReceivedMinimumRequiredVersion)) ? (DisplayName + " may not be higher than version " + ReceivedCurrentVersion + ". You have version " + CurrentVersion + ".") : (DisplayName + " needs to be at least version " + ReceivedMinimumRequiredVersion + ". You have version " + CurrentVersion + "."); } private string ErrorServer(ZRpc rpc) { return "Disconnect: The client (" + rpc.GetSocket().GetHostName() + ") doesn't have the correct " + DisplayName + " version " + MinimumRequiredVersion; } private string Error(ZRpc? rpc = null) { return (rpc == null) ? ErrorClient() : ErrorServer(rpc); } private static VersionCheck[] GetFailedClient() { return versionChecks.Where((VersionCheck check) => !check.IsVersionOk()).ToArray(); } private static VersionCheck[] GetFailedServer(ZRpc rpc) { ZRpc rpc2 = rpc; return versionChecks.Where((VersionCheck check) => check.ModRequired && !check.ValidatedClients.Contains(rpc2)).ToArray(); } private static void Logout() { Game.instance.Logout(true, true); AccessTools.DeclaredField(typeof(ZNet), "m_connectionStatus").SetValue(null, (object)(ConnectionStatus)3); } private static void DisconnectClient(ZRpc rpc) { rpc.Invoke("Error", new object[1] { 3 }); } private static void CheckVersion(ZRpc rpc, ZPackage pkg) { CheckVersion(rpc, pkg, null); } private static void CheckVersion(ZRpc rpc, ZPackage pkg, Action? original) { string text = pkg.ReadString(); string text2 = pkg.ReadString(); string text3 = pkg.ReadString(); bool flag = false; foreach (VersionCheck versionCheck in versionChecks) { if (!(text != versionCheck.Name)) { Debug.Log((object)("Received " + versionCheck.DisplayName + " version " + text3 + " and minimum version " + text2 + " from the " + (ZNet.instance.IsServer() ? "client" : "server") + ".")); versionCheck.ReceivedMinimumRequiredVersion = text2; versionCheck.ReceivedCurrentVersion = text3; if (ZNet.instance.IsServer() && versionCheck.IsVersionOk()) { versionCheck.ValidatedClients.Add(rpc); } flag = true; } } if (flag) { return; } pkg.SetPos(0); if (original != null) { original(rpc, pkg); if (pkg.GetPos() == 0) { notProcessedNames.Add(text, text3); } } } [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] [HarmonyPrefix] private static bool RPC_PeerInfo(ZRpc rpc, ZNet __instance) { VersionCheck[] array = (__instance.IsServer() ? GetFailedServer(rpc) : GetFailedClient()); if (array.Length == 0) { return true; } VersionCheck[] array2 = array; foreach (VersionCheck versionCheck in array2) { Debug.LogWarning((object)versionCheck.Error(rpc)); } if (__instance.IsServer()) { DisconnectClient(rpc); } else { Logout(); } return false; } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] [HarmonyPrefix] private static void RegisterAndCheckVersion(ZNetPeer peer, ZNet __instance) { //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Expected O, but got Unknown notProcessedNames.Clear(); IDictionary dictionary = (IDictionary)typeof(ZRpc).GetField("m_functions", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(peer.m_rpc); if (dictionary.Contains(StringExtensionMethods.GetStableHashCode("ServerSync VersionCheck"))) { object obj = dictionary[StringExtensionMethods.GetStableHashCode("ServerSync VersionCheck")]; Action action = (Action)obj.GetType().GetField("m_action", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(obj); peer.m_rpc.Register("ServerSync VersionCheck", (Action)delegate(ZRpc rpc, ZPackage pkg) { CheckVersion(rpc, pkg, action); }); } else { peer.m_rpc.Register("ServerSync VersionCheck", (Action)CheckVersion); } foreach (VersionCheck versionCheck in versionChecks) { versionCheck.Initialize(); if (versionCheck.ModRequired || __instance.IsServer()) { Debug.Log((object)("Sending " + versionCheck.DisplayName + " version " + versionCheck.CurrentVersion + " and minimum version " + versionCheck.MinimumRequiredVersion + " to the " + (__instance.IsServer() ? "client" : "server") + ".")); ZPackage val = new ZPackage(); val.Write(versionCheck.Name); val.Write(versionCheck.MinimumRequiredVersion); val.Write(versionCheck.CurrentVersion); peer.m_rpc.Invoke("ServerSync VersionCheck", new object[1] { val }); } } } [HarmonyPatch(typeof(ZNet), "Disconnect")] [HarmonyPrefix] private static void RemoveDisconnected(ZNetPeer peer, ZNet __instance) { if (!__instance.IsServer()) { return; } foreach (VersionCheck versionCheck in versionChecks) { versionCheck.ValidatedClients.Remove(peer.m_rpc); } } [HarmonyPatch(typeof(FejdStartup), "ShowConnectError")] [HarmonyPostfix] private static void ShowConnectionError(FejdStartup __instance) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) if (!__instance.m_connectionFailedPanel.activeSelf || (int)ZNet.GetConnectionStatus() != 3) { return; } bool flag = false; VersionCheck[] failedClient = GetFailedClient(); if (failedClient.Length != 0) { string text = string.Join("\n", failedClient.Select((VersionCheck check) => check.Error())); TMP_Text connectionFailedError = __instance.m_connectionFailedError; connectionFailedError.text = connectionFailedError.text + "\n" + text; flag = true; } foreach (KeyValuePair item in notProcessedNames.OrderBy, string>((KeyValuePair kv) => kv.Key)) { if (!__instance.m_connectionFailedError.text.Contains(item.Key)) { TMP_Text connectionFailedError2 = __instance.m_connectionFailedError; connectionFailedError2.text = connectionFailedError2.text + "\nServer expects you to have " + item.Key + " (Version: " + item.Value + ") installed."; flag = true; } } if (flag) { RectTransform component = ((Component)__instance.m_connectionFailedPanel.transform.Find("Image")).GetComponent(); Vector2 sizeDelta = component.sizeDelta; sizeDelta.x = 675f; component.sizeDelta = sizeDelta; __instance.m_connectionFailedError.ForceMeshUpdate(false, false); float num = __instance.m_connectionFailedError.renderedHeight + 105f; RectTransform component2 = ((Component)((Component)component).transform.Find("ButtonOk")).GetComponent(); component2.anchoredPosition = new Vector2(component2.anchoredPosition.x, component2.anchoredPosition.y - (num - component.sizeDelta.y) / 2f); sizeDelta = component.sizeDelta; sizeDelta.y = num; component.sizeDelta = sizeDelta; } } } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } } namespace YamlDotNet { internal sealed class CultureInfoAdapter : CultureInfo { private readonly IFormatProvider provider; public CultureInfoAdapter(CultureInfo baseCulture, IFormatProvider provider) : base(baseCulture.Name) { this.provider = provider; } public override object? GetFormat(Type formatType) { return provider.GetFormat(formatType); } } internal static class Polyfills { [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static bool Contains(this string source, char c) { return source.IndexOf(c) != -1; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static bool EndsWith(this string source, char c) { if (source.Length > 0) { return source[source.Length - 1] == c; } return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static bool StartsWith(this string source, char c) { if (source.Length > 0) { return source[0] == c; } return false; } } internal static class PropertyInfoExtensions { public static object? ReadValue(this PropertyInfo property, object target) { return property.GetValue(target, null); } } internal static class ReflectionExtensions { private static readonly Func IsInstance = (PropertyInfo property) => !(property.GetMethod ?? property.SetMethod).IsStatic; private static readonly Func IsInstancePublic = (PropertyInfo property) => IsInstance(property) && (property.GetMethod ?? property.SetMethod).IsPublic; public static Type? BaseType(this Type type) { return type.GetTypeInfo().BaseType; } public static bool IsValueType(this Type type) { return type.GetTypeInfo().IsValueType; } public static bool IsGenericType(this Type type) { return type.GetTypeInfo().IsGenericType; } public static bool IsGenericTypeDefinition(this Type type) { return type.GetTypeInfo().IsGenericTypeDefinition; } public static Type? GetImplementationOfOpenGenericInterface(this Type type, Type openGenericType) { if (!openGenericType.IsGenericType || !openGenericType.IsInterface) { throw new ArgumentException("The type must be a generic type definition and an interface", "openGenericType"); } if (IsGenericDefinitionOfType(type, openGenericType)) { return type; } return type.FindInterfaces((Type t, object context) => IsGenericDefinitionOfType(t, context), openGenericType).FirstOrDefault(); static bool IsGenericDefinitionOfType(Type t, object? context) { if (t.IsGenericType) { return t.GetGenericTypeDefinition() == (Type)context; } return false; } } public static bool IsInterface(this Type type) { return type.GetTypeInfo().IsInterface; } public static bool IsEnum(this Type type) { return type.GetTypeInfo().IsEnum; } public static bool IsRequired(this MemberInfo member) { return member.GetCustomAttributes(inherit: true).Any((object x) => x.GetType().FullName == "System.Runtime.CompilerServices.RequiredMemberAttribute"); } public static bool HasDefaultConstructor(this Type type, bool allowPrivateConstructors) { BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public; if (allowPrivateConstructors) { bindingFlags |= BindingFlags.NonPublic; } if (!type.IsValueType) { return type.GetConstructor(bindingFlags, null, Type.EmptyTypes, null) != null; } return true; } public static bool IsAssignableFrom(this Type type, Type source) { return type.IsAssignableFrom(source.GetTypeInfo()); } public static bool IsAssignableFrom(this Type type, TypeInfo source) { return type.GetTypeInfo().IsAssignableFrom(source); } public static TypeCode GetTypeCode(this Type type) { if (type.IsEnum()) { type = Enum.GetUnderlyingType(type); } if (type == typeof(bool)) { return TypeCode.Boolean; } if (type == typeof(char)) { return TypeCode.Char; } if (type == typeof(sbyte)) { return TypeCode.SByte; } if (type == typeof(byte)) { return TypeCode.Byte; } if (type == typeof(short)) { return TypeCode.Int16; } if (type == typeof(ushort)) { return TypeCode.UInt16; } if (type == typeof(int)) { return TypeCode.Int32; } if (type == typeof(uint)) { return TypeCode.UInt32; } if (type == typeof(long)) { return TypeCode.Int64; } if (type == typeof(ulong)) { return TypeCode.UInt64; } if (type == typeof(float)) { return TypeCode.Single; } if (type == typeof(double)) { return TypeCode.Double; } if (type == typeof(decimal)) { return TypeCode.Decimal; } if (type == typeof(DateTime)) { return TypeCode.DateTime; } if (type == typeof(string)) { return TypeCode.String; } return TypeCode.Object; } public static bool IsDbNull(this object value) { return value?.GetType()?.FullName == "System.DBNull"; } public static Type[] GetGenericArguments(this Type type) { return type.GetTypeInfo().GenericTypeArguments; } public static PropertyInfo? GetPublicProperty(this Type type, string name) { string name2 = name; return type.GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public).FirstOrDefault((PropertyInfo p) => p.Name == name2); } public static FieldInfo? GetPublicStaticField(this Type type, string name) { return type.GetRuntimeField(name); } public static IEnumerable GetProperties(this Type type, bool includeNonPublic) { Func predicate = (includeNonPublic ? IsInstance : IsInstancePublic); if (!type.IsInterface()) { return type.GetRuntimeProperties().Where(predicate); } return new Type[1] { type }.Concat(type.GetInterfaces()).SelectMany((Type i) => i.GetRuntimeProperties().Where(predicate)); } public static IEnumerable GetPublicProperties(this Type type) { return type.GetProperties(includeNonPublic: false); } public static IEnumerable GetPublicFields(this Type type) { return from f in type.GetRuntimeFields() where !f.IsStatic && f.IsPublic select f; } public static IEnumerable GetPublicStaticMethods(this Type type) { return from m in type.GetRuntimeMethods() where m.IsPublic && m.IsStatic select m; } public static MethodInfo GetPrivateStaticMethod(this Type type, string name) { string name2 = name; return type.GetRuntimeMethods().FirstOrDefault((MethodInfo m) => !m.IsPublic && m.IsStatic && m.Name.Equals(name2)) ?? throw new MissingMethodException("Expected to find a method named '" + name2 + "' in '" + type.FullName + "'."); } public static MethodInfo? GetPublicStaticMethod(this Type type, string name, params Type[] parameterTypes) { string name2 = name; Type[] parameterTypes2 = parameterTypes; return type.GetRuntimeMethods().FirstOrDefault(delegate(MethodInfo m) { if (m.IsPublic && m.IsStatic && m.Name.Equals(name2)) { ParameterInfo[] parameters = m.GetParameters(); if (parameters.Length == parameterTypes2.Length) { return parameters.Zip(parameterTypes2, (ParameterInfo pi, Type pt) => pi.ParameterType == pt).All((bool r) => r); } return false; } return false; }); } public static MethodInfo? GetPublicInstanceMethod(this Type type, string name) { string name2 = name; return type.GetRuntimeMethods().FirstOrDefault((MethodInfo m) => m.IsPublic && !m.IsStatic && m.Name.Equals(name2)); } public static MethodInfo? GetGetMethod(this PropertyInfo property, bool nonPublic) { MethodInfo methodInfo = property.GetMethod; if (!nonPublic && !methodInfo.IsPublic) { methodInfo = null; } return methodInfo; } public static MethodInfo? GetSetMethod(this PropertyInfo property) { return property.SetMethod; } public static IEnumerable GetInterfaces(this Type type) { return type.GetTypeInfo().ImplementedInterfaces; } public static bool IsInstanceOf(this Type type, object o) { if (!(o.GetType() == type)) { return o.GetType().GetTypeInfo().IsSubclassOf(type); } return true; } public static Attribute[] GetAllCustomAttributes(this PropertyInfo member) { return Attribute.GetCustomAttributes(member, typeof(TAttribute), inherit: true); } public static bool AcceptsNull(this MemberInfo member) { object[] customAttributes = member.DeclaringType.GetCustomAttributes(inherit: true); object obj = customAttributes.FirstOrDefault((object x) => x.GetType().FullName == "System.Runtime.CompilerServices.NullableContextAttribute"); int num = 0; if (obj != null) { Type type = obj.GetType(); PropertyInfo property = type.GetProperty("Flag"); num = (byte)property.GetValue(obj); } object[] customAttributes2 = member.GetCustomAttributes(inherit: true); object obj2 = customAttributes2.FirstOrDefault((object x) => x.GetType().FullName == "System.Runtime.CompilerServices.NullableAttribute"); PropertyInfo propertyInfo = (obj2?.GetType())?.GetProperty("NullableFlags"); byte[] source = (byte[])propertyInfo.GetValue(obj2); return source.Any((byte x) => x == 2) || num == 2; } } internal static class StandardRegexOptions { public const RegexOptions Compiled = RegexOptions.Compiled; } } namespace YamlDotNet.Serialization { internal abstract class BuilderSkeleton where TBuilder : BuilderSkeleton { internal INamingConvention namingConvention = NullNamingConvention.Instance; internal INamingConvention enumNamingConvention = NullNamingConvention.Instance; internal ITypeResolver typeResolver; internal readonly YamlAttributeOverrides overrides; internal readonly LazyComponentRegistrationList typeConverterFactories; internal readonly LazyComponentRegistrationList typeInspectorFactories; internal bool ignoreFields; internal bool includeNonPublicProperties; internal Settings settings; internal YamlFormatter yamlFormatter = YamlFormatter.Default; protected abstract TBuilder Self { get; } internal BuilderSkeleton(ITypeResolver typeResolver) { overrides = new YamlAttributeOverrides(); typeConverterFactories = new LazyComponentRegistrationList { { typeof(YamlDotNet.Serialization.Converters.GuidConverter), (Nothing _) => new YamlDotNet.Serialization.Converters.GuidConverter(jsonCompatible: false) }, { typeof(SystemTypeConverter), (Nothing _) => new SystemTypeConverter() } }; typeInspectorFactories = new LazyComponentRegistrationList(); this.typeResolver = typeResolver ?? throw new ArgumentNullException("typeResolver"); settings = new Settings(); } public TBuilder IgnoreFields() { ignoreFields = true; return Self; } public TBuilder IncludeNonPublicProperties() { includeNonPublicProperties = true; return Self; } public TBuilder EnablePrivateConstructors() { settings.AllowPrivateConstructors = true; return Self; } public TBuilder WithNamingConvention(INamingConvention namingConvention) { this.namingConvention = namingConvention ?? throw new ArgumentNullException("namingConvention"); return Self; } public TBuilder WithEnumNamingConvention(INamingConvention enumNamingConvention) { this.enumNamingConvention = enumNamingConvention; return Self; } public TBuilder WithTypeResolver(ITypeResolver typeResolver) { this.typeResolver = typeResolver ?? throw new ArgumentNullException("typeResolver"); return Self; } public abstract TBuilder WithTagMapping(TagName tag, Type type); public TBuilder WithAttributeOverride(Expression> propertyAccessor, Attribute attribute) { overrides.Add(propertyAccessor, attribute); return Self; } public TBuilder WithAttributeOverride(Type type, string member, Attribute attribute) { overrides.Add(type, member, attribute); return Self; } public TBuilder WithTypeConverter(IYamlTypeConverter typeConverter) { return WithTypeConverter(typeConverter, delegate(IRegistrationLocationSelectionSyntax w) { w.OnTop(); }); } public TBuilder WithTypeConverter(IYamlTypeConverter typeConverter, Action> where) { IYamlTypeConverter typeConverter2 = typeConverter; if (typeConverter2 == null) { throw new ArgumentNullException("typeConverter"); } if (where == null) { throw new ArgumentNullException("where"); } where(typeConverterFactories.CreateRegistrationLocationSelector(typeConverter2.GetType(), (Nothing _) => typeConverter2)); return Self; } public TBuilder WithTypeConverter(WrapperFactory typeConverterFactory, Action> where) where TYamlTypeConverter : IYamlTypeConverter { WrapperFactory typeConverterFactory2 = typeConverterFactory; if (typeConverterFactory2 == null) { throw new ArgumentNullException("typeConverterFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(typeConverterFactories.CreateTrackingRegistrationLocationSelector(typeof(TYamlTypeConverter), (IYamlTypeConverter wrapped, Nothing _) => typeConverterFactory2(wrapped))); return Self; } public TBuilder WithoutTypeConverter() where TYamlTypeConverter : IYamlTypeConverter { return WithoutTypeConverter(typeof(TYamlTypeConverter)); } public TBuilder WithoutTypeConverter(Type converterType) { if (converterType == null) { throw new ArgumentNullException("converterType"); } typeConverterFactories.Remove(converterType); return Self; } public TBuilder WithTypeInspector(Func typeInspectorFactory) where TTypeInspector : ITypeInspector { return WithTypeInspector(typeInspectorFactory, delegate(IRegistrationLocationSelectionSyntax w) { w.OnTop(); }); } public TBuilder WithTypeInspector(Func typeInspectorFactory, Action> where) where TTypeInspector : ITypeInspector { Func typeInspectorFactory2 = typeInspectorFactory; if (typeInspectorFactory2 == null) { throw new ArgumentNullException("typeInspectorFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(typeInspectorFactories.CreateRegistrationLocationSelector(typeof(TTypeInspector), (ITypeInspector inner) => typeInspectorFactory2(inner))); return Self; } public TBuilder WithTypeInspector(WrapperFactory typeInspectorFactory, Action> where) where TTypeInspector : ITypeInspector { WrapperFactory typeInspectorFactory2 = typeInspectorFactory; if (typeInspectorFactory2 == null) { throw new ArgumentNullException("typeInspectorFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(typeInspectorFactories.CreateTrackingRegistrationLocationSelector(typeof(TTypeInspector), (ITypeInspector wrapped, ITypeInspector inner) => typeInspectorFactory2(wrapped, inner))); return Self; } public TBuilder WithoutTypeInspector() where TTypeInspector : ITypeInspector { return WithoutTypeInspector(typeof(TTypeInspector)); } public TBuilder WithoutTypeInspector(Type inspectorType) { if (inspectorType == null) { throw new ArgumentNullException("inspectorType"); } typeInspectorFactories.Remove(inspectorType); return Self; } public TBuilder WithYamlFormatter(YamlFormatter formatter) { yamlFormatter = formatter ?? throw new ArgumentNullException("formatter"); return Self; } protected IEnumerable BuildTypeConverters() { return typeConverterFactories.BuildComponentList(); } } internal delegate TComponent WrapperFactory(TComponentBase wrapped) where TComponent : TComponentBase; internal delegate TComponent WrapperFactory(TComponentBase wrapped, TArgument argument) where TComponent : TComponentBase; [Flags] internal enum DefaultValuesHandling { Preserve = 0, OmitNull = 1, OmitDefaults = 2, OmitEmptyCollections = 4 } internal sealed class Deserializer : IDeserializer { private readonly IValueDeserializer valueDeserializer; public Deserializer() : this(new DeserializerBuilder().BuildValueDeserializer()) { } private Deserializer(IValueDeserializer valueDeserializer) { this.valueDeserializer = valueDeserializer ?? throw new ArgumentNullException("valueDeserializer"); } public static Deserializer FromValueDeserializer(IValueDeserializer valueDeserializer) { return new Deserializer(valueDeserializer); } public T Deserialize(string input) { using StringReader input2 = new StringReader(input); return Deserialize(input2); } public T Deserialize(TextReader input) { return Deserialize(new Parser(input)); } public T Deserialize(IParser parser) { return (T)Deserialize(parser, typeof(T)); } public object? Deserialize(string input) { return Deserialize(input); } public object? Deserialize(TextReader input) { return Deserialize(input); } public object? Deserialize(IParser parser) { return Deserialize(parser); } public object? Deserialize(string input, Type type) { using StringReader input2 = new StringReader(input); return Deserialize(input2, type); } public object? Deserialize(TextReader input, Type type) { return Deserialize(new Parser(input), type); } public object? Deserialize(IParser parser, Type type) { if (parser == null) { throw new ArgumentNullException("parser"); } if (type == null) { throw new ArgumentNullException("type"); } YamlDotNet.Core.Events.StreamStart @event; bool flag = parser.TryConsume(out @event); YamlDotNet.Core.Events.DocumentStart event2; bool flag2 = parser.TryConsume(out event2); object result = null; if (!parser.Accept(out var _) && !parser.Accept(out var _)) { using SerializerState serializerState = new SerializerState(); result = valueDeserializer.DeserializeValue(parser, type, serializerState, valueDeserializer); serializerState.OnDeserialization(); } if (flag2) { parser.Consume(); } if (flag) { parser.Consume(); } return result; } } internal sealed class DeserializerBuilder : BuilderSkeleton { private Lazy objectFactory; private readonly LazyComponentRegistrationList nodeDeserializerFactories; private readonly LazyComponentRegistrationList nodeTypeResolverFactories; private readonly Dictionary tagMappings; private readonly Dictionary typeMappings; private readonly ITypeConverter typeConverter; private bool ignoreUnmatched; private bool duplicateKeyChecking; private bool attemptUnknownTypeDeserialization; private bool enforceNullability; private bool caseInsensitivePropertyMatching; private bool enforceRequiredProperties; protected override DeserializerBuilder Self => this; public DeserializerBuilder() : base((ITypeResolver)new StaticTypeResolver()) { typeMappings = new Dictionary(); objectFactory = new Lazy(() => new DefaultObjectFactory(typeMappings, settings), isThreadSafe: true); tagMappings = new Dictionary { { FailsafeSchema.Tags.Map, typeof(Dictionary) }, { FailsafeSchema.Tags.Str, typeof(string) }, { JsonSchema.Tags.Bool, typeof(bool) }, { JsonSchema.Tags.Float, typeof(double) }, { JsonSchema.Tags.Int, typeof(int) }, { DefaultSchema.Tags.Timestamp, typeof(DateTime) } }; typeInspectorFactories.Add(typeof(CachedTypeInspector), (ITypeInspector inner) => new CachedTypeInspector(inner)); typeInspectorFactories.Add(typeof(NamingConventionTypeInspector), (ITypeInspector inner) => (!(namingConvention is NullNamingConvention)) ? new NamingConventionTypeInspector(inner, namingConvention) : inner); typeInspectorFactories.Add(typeof(YamlAttributesTypeInspector), (ITypeInspector inner) => new YamlAttributesTypeInspector(inner)); typeInspectorFactories.Add(typeof(YamlAttributeOverridesInspector), (ITypeInspector inner) => (overrides == null) ? inner : new YamlAttributeOverridesInspector(inner, overrides.Clone())); typeInspectorFactories.Add(typeof(ReadableAndWritablePropertiesTypeInspector), (ITypeInspector inner) => new ReadableAndWritablePropertiesTypeInspector(inner)); nodeDeserializerFactories = new LazyComponentRegistrationList { { typeof(YamlConvertibleNodeDeserializer), (Nothing _) => new YamlConvertibleNodeDeserializer(objectFactory.Value) }, { typeof(YamlSerializableNodeDeserializer), (Nothing _) => new YamlSerializableNodeDeserializer(objectFactory.Value) }, { typeof(TypeConverterNodeDeserializer), (Nothing _) => new TypeConverterNodeDeserializer(BuildTypeConverters()) }, { typeof(NullNodeDeserializer), (Nothing _) => new NullNodeDeserializer() }, { typeof(ScalarNodeDeserializer), (Nothing _) => new ScalarNodeDeserializer(attemptUnknownTypeDeserialization, typeConverter, BuildTypeInspector(), yamlFormatter, enumNamingConvention) }, { typeof(ArrayNodeDeserializer), (Nothing _) => new ArrayNodeDeserializer(enumNamingConvention, BuildTypeInspector()) }, { typeof(DictionaryNodeDeserializer), (Nothing _) => new DictionaryNodeDeserializer(objectFactory.Value, duplicateKeyChecking) }, { typeof(CollectionNodeDeserializer), (Nothing _) => new CollectionNodeDeserializer(objectFactory.Value, enumNamingConvention, BuildTypeInspector()) }, { typeof(EnumerableNodeDeserializer), (Nothing _) => new EnumerableNodeDeserializer() }, { typeof(ObjectNodeDeserializer), (Nothing _) => new ObjectNodeDeserializer(objectFactory.Value, BuildTypeInspector(), ignoreUnmatched, duplicateKeyChecking, typeConverter, enumNamingConvention, enforceNullability, caseInsensitivePropertyMatching, enforceRequiredProperties, BuildTypeConverters()) }, { typeof(FsharpListNodeDeserializer), (Nothing _) => new FsharpListNodeDeserializer(BuildTypeInspector(), enumNamingConvention) } }; nodeTypeResolverFactories = new LazyComponentRegistrationList { { typeof(MappingNodeTypeResolver), (Nothing _) => new MappingNodeTypeResolver(typeMappings) }, { typeof(YamlConvertibleTypeResolver), (Nothing _) => new YamlConvertibleTypeResolver() }, { typeof(YamlSerializableTypeResolver), (Nothing _) => new YamlSerializableTypeResolver() }, { typeof(TagNodeTypeResolver), (Nothing _) => new TagNodeTypeResolver(tagMappings) }, { typeof(PreventUnknownTagsNodeTypeResolver), (Nothing _) => new PreventUnknownTagsNodeTypeResolver() }, { typeof(DefaultContainersNodeTypeResolver), (Nothing _) => new DefaultContainersNodeTypeResolver() } }; typeConverter = new ReflectionTypeConverter(); } public ITypeInspector BuildTypeInspector() { ITypeInspector typeInspector = new WritablePropertiesTypeInspector(typeResolver, includeNonPublicProperties); if (!ignoreFields) { typeInspector = new CompositeTypeInspector(new ReadableFieldsTypeInspector(typeResolver), typeInspector); } return typeInspectorFactories.BuildComponentChain(typeInspector); } public DeserializerBuilder WithAttemptingUnquotedStringTypeDeserialization() { attemptUnknownTypeDeserialization = true; return this; } public DeserializerBuilder WithObjectFactory(IObjectFactory objectFactory) { IObjectFactory objectFactory2 = objectFactory; if (objectFactory2 == null) { throw new ArgumentNullException("objectFactory"); } this.objectFactory = new Lazy(() => objectFactory2, isThreadSafe: true); return this; } public DeserializerBuilder WithObjectFactory(Func objectFactory) { if (objectFactory == null) { throw new ArgumentNullException("objectFactory"); } return WithObjectFactory(new LambdaObjectFactory(objectFactory)); } public DeserializerBuilder WithNodeDeserializer(INodeDeserializer nodeDeserializer) { return WithNodeDeserializer(nodeDeserializer, delegate(IRegistrationLocationSelectionSyntax w) { w.OnTop(); }); } public DeserializerBuilder WithNodeDeserializer(INodeDeserializer nodeDeserializer, Action> where) { INodeDeserializer nodeDeserializer2 = nodeDeserializer; if (nodeDeserializer2 == null) { throw new ArgumentNullException("nodeDeserializer"); } if (where == null) { throw new ArgumentNullException("where"); } where(nodeDeserializerFactories.CreateRegistrationLocationSelector(nodeDeserializer2.GetType(), (Nothing _) => nodeDeserializer2)); return this; } public DeserializerBuilder WithNodeDeserializer(WrapperFactory nodeDeserializerFactory, Action> where) where TNodeDeserializer : INodeDeserializer { WrapperFactory nodeDeserializerFactory2 = nodeDeserializerFactory; if (nodeDeserializerFactory2 == null) { throw new ArgumentNullException("nodeDeserializerFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(nodeDeserializerFactories.CreateTrackingRegistrationLocationSelector(typeof(TNodeDeserializer), (INodeDeserializer wrapped, Nothing _) => nodeDeserializerFactory2(wrapped))); return this; } public DeserializerBuilder WithoutNodeDeserializer() where TNodeDeserializer : INodeDeserializer { return WithoutNodeDeserializer(typeof(TNodeDeserializer)); } public DeserializerBuilder WithoutNodeDeserializer(Type nodeDeserializerType) { if (nodeDeserializerType == null) { throw new ArgumentNullException("nodeDeserializerType"); } nodeDeserializerFactories.Remove(nodeDeserializerType); return this; } public DeserializerBuilder WithTypeDiscriminatingNodeDeserializer(Action configureTypeDiscriminatingNodeDeserializerOptions, int maxDepth = -1, int maxLength = -1) { TypeDiscriminatingNodeDeserializerOptions typeDiscriminatingNodeDeserializerOptions = new TypeDiscriminatingNodeDeserializerOptions(); configureTypeDiscriminatingNodeDeserializerOptions(typeDiscriminatingNodeDeserializerOptions); TypeDiscriminatingNodeDeserializer nodeDeserializer = new TypeDiscriminatingNodeDeserializer(nodeDeserializerFactories.BuildComponentList(), typeDiscriminatingNodeDeserializerOptions.discriminators, maxDepth, maxLength); return WithNodeDeserializer(nodeDeserializer, delegate(IRegistrationLocationSelectionSyntax s) { s.Before(); }); } public DeserializerBuilder WithNodeTypeResolver(INodeTypeResolver nodeTypeResolver) { return WithNodeTypeResolver(nodeTypeResolver, delegate(IRegistrationLocationSelectionSyntax w) { w.OnTop(); }); } public DeserializerBuilder WithNodeTypeResolver(INodeTypeResolver nodeTypeResolver, Action> where) { INodeTypeResolver nodeTypeResolver2 = nodeTypeResolver; if (nodeTypeResolver2 == null) { throw new ArgumentNullException("nodeTypeResolver"); } if (where == null) { throw new ArgumentNullException("where"); } where(nodeTypeResolverFactories.CreateRegistrationLocationSelector(nodeTypeResolver2.GetType(), (Nothing _) => nodeTypeResolver2)); return this; } public DeserializerBuilder WithNodeTypeResolver(WrapperFactory nodeTypeResolverFactory, Action> where) where TNodeTypeResolver : INodeTypeResolver { WrapperFactory nodeTypeResolverFactory2 = nodeTypeResolverFactory; if (nodeTypeResolverFactory2 == null) { throw new ArgumentNullException("nodeTypeResolverFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(nodeTypeResolverFactories.CreateTrackingRegistrationLocationSelector(typeof(TNodeTypeResolver), (INodeTypeResolver wrapped, Nothing _) => nodeTypeResolverFactory2(wrapped))); return this; } public DeserializerBuilder WithCaseInsensitivePropertyMatching() { caseInsensitivePropertyMatching = true; return this; } public DeserializerBuilder WithEnforceNullability() { enforceNullability = true; return this; } public DeserializerBuilder WithEnforceRequiredMembers() { enforceRequiredProperties = true; return this; } public DeserializerBuilder WithoutNodeTypeResolver() where TNodeTypeResolver : INodeTypeResolver { return WithoutNodeTypeResolver(typeof(TNodeTypeResolver)); } public DeserializerBuilder WithoutNodeTypeResolver(Type nodeTypeResolverType) { if (nodeTypeResolverType == null) { throw new ArgumentNullException("nodeTypeResolverType"); } nodeTypeResolverFactories.Remove(nodeTypeResolverType); return this; } public override DeserializerBuilder WithTagMapping(TagName tag, Type type) { if (tag.IsEmpty) { throw new ArgumentException("Non-specific tags cannot be maped"); } if (type == null) { throw new ArgumentNullException("type"); } if (tagMappings.TryGetValue(tag, out Type value)) { throw new ArgumentException($"Type already has a registered type '{value.FullName}' for tag '{tag}'", "tag"); } tagMappings.Add(tag, type); return this; } public DeserializerBuilder WithTypeMapping() where TConcrete : TInterface { Type typeFromHandle = typeof(TInterface); Type typeFromHandle2 = typeof(TConcrete); if (!typeFromHandle.IsAssignableFrom(typeFromHandle2)) { throw new InvalidOperationException("The type '" + typeFromHandle2.Name + "' does not implement interface '" + typeFromHandle.Name + "'."); } if (!DictionaryExtensions.TryAdd(typeMappings, typeFromHandle, typeFromHandle2)) { typeMappings[typeFromHandle] = typeFromHandle2; } return this; } public DeserializerBuilder WithoutTagMapping(TagName tag) { if (tag.IsEmpty) { throw new ArgumentException("Non-specific tags cannot be maped"); } if (!tagMappings.Remove(tag)) { throw new KeyNotFoundException($"Tag '{tag}' is not registered"); } return this; } public DeserializerBuilder IgnoreUnmatchedProperties() { ignoreUnmatched = true; return this; } public DeserializerBuilder WithDuplicateKeyChecking() { duplicateKeyChecking = true; return this; } public IDeserializer Build() { if (FsharpHelper.Instance == null) { FsharpHelper.Instance = new DefaultFsharpHelper(); } return Deserializer.FromValueDeserializer(BuildValueDeserializer()); } public IValueDeserializer BuildValueDeserializer() { return new AliasValueDeserializer(new NodeValueDeserializer(nodeDeserializerFactories.BuildComponentList(), nodeTypeResolverFactories.BuildComponentList(), typeConverter, enumNamingConvention, BuildTypeInspector())); } } internal sealed class EmissionPhaseObjectGraphVisitorArgs { private readonly IEnumerable> preProcessingPhaseVisitors; public IObjectGraphVisitor InnerVisitor { get; private set; } public IEventEmitter EventEmitter { get; private set; } public ObjectSerializer NestedObjectSerializer { get; private set; } public IEnumerable TypeConverters { get; private set; } public EmissionPhaseObjectGraphVisitorArgs(IObjectGraphVisitor innerVisitor, IEventEmitter eventEmitter, IEnumerable> preProcessingPhaseVisitors, IEnumerable typeConverters, ObjectSerializer nestedObjectSerializer) { InnerVisitor = innerVisitor ?? throw new ArgumentNullException("innerVisitor"); EventEmitter = eventEmitter ?? throw new ArgumentNullException("eventEmitter"); this.preProcessingPhaseVisitors = preProcessingPhaseVisitors ?? throw new ArgumentNullException("preProcessingPhaseVisitors"); TypeConverters = typeConverters ?? throw new ArgumentNullException("typeConverters"); NestedObjectSerializer = nestedObjectSerializer ?? throw new ArgumentNullException("nestedObjectSerializer"); } public T GetPreProcessingPhaseObjectGraphVisitor() where T : IObjectGraphVisitor { return preProcessingPhaseVisitors.OfType().Single(); } } internal abstract class EventInfo { public IObjectDescriptor Source { get; } protected EventInfo(IObjectDescriptor source) { Source = source ?? throw new ArgumentNullException("source"); } } internal class AliasEventInfo : EventInfo { public AnchorName Alias { get; } public bool NeedsExpansion { get; set; } public AliasEventInfo(IObjectDescriptor source, AnchorName alias) : base(source) { if (alias.IsEmpty) { throw new ArgumentNullException("alias"); } Alias = alias; } } internal class ObjectEventInfo : EventInfo { public AnchorName Anchor { get; set; } public TagName Tag { get; set; } protected ObjectEventInfo(IObjectDescriptor source) : base(source) { } } internal sealed class ScalarEventInfo : ObjectEventInfo { public string RenderedValue { get; set; } public ScalarStyle Style { get; set; } public bool IsPlainImplicit { get; set; } public bool IsQuotedImplicit { get; set; } public ScalarEventInfo(IObjectDescriptor source) : base(source) { Style = source.ScalarStyle; RenderedValue = string.Empty; } } internal sealed class MappingStartEventInfo : ObjectEventInfo { public bool IsImplicit { get; set; } public MappingStyle Style { get; set; } public MappingStartEventInfo(IObjectDescriptor source) : base(source) { } } internal sealed class MappingEndEventInfo : EventInfo { public MappingEndEventInfo(IObjectDescriptor source) : base(source) { } } internal sealed class SequenceStartEventInfo : ObjectEventInfo { public bool IsImplicit { get; set; } public SequenceStyle Style { get; set; } public SequenceStartEventInfo(IObjectDescriptor source) : base(source) { } } internal sealed class SequenceEndEventInfo : EventInfo { public SequenceEndEventInfo(IObjectDescriptor source) : base(source) { } } internal interface IAliasProvider { AnchorName GetAlias(object target); } internal interface IDeserializer { T Deserialize(string input); T Deserialize(TextReader input); T Deserialize(IParser parser); object? Deserialize(string input); object? Deserialize(TextReader input); object? Deserialize(IParser parser); object? Deserialize(string input, Type type); object? Deserialize(TextReader input, Type type); object? Deserialize(IParser parser, Type type); } internal interface IEventEmitter { void Emit(AliasEventInfo eventInfo, IEmitter emitter); void Emit(ScalarEventInfo eventInfo, IEmitter emitter); void Emit(MappingStartEventInfo eventInfo, IEmitter emitter); void Emit(MappingEndEventInfo eventInfo, IEmitter emitter); void Emit(SequenceStartEventInfo eventInfo, IEmitter emitter); void Emit(SequenceEndEventInfo eventInfo, IEmitter emitter); } internal interface INamingConvention { string Apply(string value); string Reverse(string value); } internal interface INodeDeserializer { bool Deserialize(IParser reader, Type expectedType, Func nestedObjectDeserializer, out object? value, ObjectDeserializer rootDeserializer); } internal interface INodeTypeResolver { bool Resolve(NodeEvent? nodeEvent, ref Type currentType); } internal interface IObjectAccessor { void Set(string name, object target, object value); object? Read(string name, object target); } internal interface IObjectDescriptor { object? Value { get; } Type Type { get; } Type StaticType { get; } ScalarStyle ScalarStyle { get; } } internal static class ObjectDescriptorExtensions { public static object NonNullValue(this IObjectDescriptor objectDescriptor) { return objectDescriptor.Value ?? throw new InvalidOperationException("Attempted to use a IObjectDescriptor of type '" + objectDescriptor.Type.FullName + "' whose Value is null at a point whete it is invalid to do so. This may indicate a bug in YamlDotNet."); } } internal interface IObjectFactory { object Create(Type type); object? CreatePrimitive(Type type); bool GetDictionary(IObjectDescriptor descriptor, out IDictionary? dictionary, out Type[]? genericArguments); Type GetValueType(Type type); void ExecuteOnDeserializing(object value); void ExecuteOnDeserialized(object value); void ExecuteOnSerializing(object value); void ExecuteOnSerialized(object value); } internal interface IObjectGraphTraversalStrategy { void Traverse(IObjectDescriptor graph, IObjectGraphVisitor visitor, TContext context, ObjectSerializer serializer); } internal interface IObjectGraphVisitor { bool Enter(IPropertyDescriptor? propertyDescriptor, IObjectDescriptor value, TContext context, ObjectSerializer serializer); bool EnterMapping(IObjectDescriptor key, IObjectDescriptor value, TContext context, ObjectSerializer serializer); bool EnterMapping(IPropertyDescriptor key, IObjectDescriptor value, TContext context, ObjectSerializer serializer); void VisitScalar(IObjectDescriptor scalar, TContext context, ObjectSerializer serializer); void VisitMappingStart(IObjectDescriptor mapping, Type keyType, Type valueType, TContext context, ObjectSerializer serializer); void VisitMappingEnd(IObjectDescriptor mapping, TContext context, ObjectSerializer serializer); void VisitSequenceStart(IObjectDescriptor sequence, Type elementType, TContext context, ObjectSerializer serializer); void VisitSequenceEnd(IObjectDescriptor sequence, TContext context, ObjectSerializer serializer); } internal interface IPropertyDescriptor { string Name { get; } bool AllowNulls { get; } bool CanWrite { get; } Type Type { get; } Type? TypeOverride { get; set; } int Order { get; set; } ScalarStyle ScalarStyle { get; set; } bool Required { get; } Type? ConverterType { get; } T? GetCustomAttribute() where T : Attribute; IObjectDescriptor Read(object target); void Write(object target, object? value); } internal interface IRegistrationLocationSelectionSyntax { void InsteadOf() where TRegistrationType : TBaseRegistrationType; void Before() where TRegistrationType : TBaseRegistrationType; void After() where TRegistrationType : TBaseRegistrationType; void OnTop(); void OnBottom(); } internal interface ITrackingRegistrationLocationSelectionSyntax { void InsteadOf() where TRegistrationType : TBaseRegistrationType; } internal interface ISerializer { string Serialize(object? graph); string Serialize(object? graph, Type type); void Serialize(TextWriter writer, object? graph); void Serialize(TextWriter writer, object? graph, Type type); void Serialize(IEmitter emitter, object? graph); void Serialize(IEmitter emitter, object? graph, Type type); } internal interface ITypeInspector { IEnumerable GetProperties(Type type, object? container); IPropertyDescriptor GetProperty(Type type, object? container, string name, [MaybeNullWhen(true)] bool ignoreUnmatched, bool caseInsensitivePropertyMatching); string GetEnumName(Type enumType, string name); string GetEnumValue(object enumValue); } internal interface ITypeResolver { Type Resolve(Type staticType, object? actualValue); } internal interface IValueDeserializer { object? DeserializeValue(IParser parser, Type expectedType, SerializerState state, IValueDeserializer nestedObjectDeserializer); } internal interface IValuePromise { event Action ValueAvailable; } internal interface IValueSerializer { void SerializeValue(IEmitter emitter, object? value, Type? type); } internal interface IYamlConvertible { void Read(IParser parser, Type expectedType, ObjectDeserializer nestedObjectDeserializer); void Write(IEmitter emitter, ObjectSerializer nestedObjectSerializer); } internal delegate object? ObjectDeserializer(Type type); internal delegate void ObjectSerializer(object? value, Type? type = null); [Obsolete("Please use IYamlConvertible instead")] internal interface IYamlSerializable { void ReadYaml(IParser parser); void WriteYaml(IEmitter emitter); } internal interface IYamlTypeConverter { bool Accepts(Type type); object? ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer); void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer); } internal sealed class LazyComponentRegistrationList : IEnumerable>, IEnumerable { public sealed class LazyComponentRegistration { public readonly Type ComponentType; public readonly Func Factory; public LazyComponentRegistration(Type componentType, Func factory) { ComponentType = componentType; Factory = factory; } } public sealed class TrackingLazyComponentRegistration { public readonly Type ComponentType; public readonly Func Factory; public TrackingLazyComponentRegistration(Type componentType, Func factory) { ComponentType = componentType; Factory = factory; } } private class RegistrationLocationSelector : IRegistrationLocationSelectionSyntax { private readonly LazyComponentRegistrationList registrations; private readonly LazyComponentRegistration newRegistration; public RegistrationLocationSelector(LazyComponentRegistrationList registrations, LazyComponentRegistration newRegistration) { this.registrations = registrations; this.newRegistration = newRegistration; } void IRegistrationLocationSelectionSyntax.InsteadOf() { if (newRegistration.ComponentType != typeof(TRegistrationType)) { registrations.EnsureNoDuplicateRegistrationType(newRegistration.ComponentType); } int index = registrations.EnsureRegistrationExists(); registrations.entries[index] = newRegistration; } void IRegistrationLocationSelectionSyntax.After() { registrations.EnsureNoDuplicateRegistrationType(newRegistration.ComponentType); int num = registrations.EnsureRegistrationExists(); registrations.entries.Insert(num + 1, newRegistration); } void IRegistrationLocationSelectionSyntax.Before() { registrations.EnsureNoDuplicateRegistrationType(newRegistration.ComponentType); int index = registrations.EnsureRegistrationExists(); registrations.entries.Insert(index, newRegistration); } void IRegistrationLocationSelectionSyntax.OnBottom() { registrations.EnsureNoDuplicateRegistrationType(newRegistration.ComponentType); registrations.entries.Add(newRegistration); } void IRegistrationLocationSelectionSyntax.OnTop() { registrations.EnsureNoDuplicateRegistrationType(newRegistration.ComponentType); registrations.entries.Insert(0, newRegistration); } } private class TrackingRegistrationLocationSelector : ITrackingRegistrationLocationSelectionSyntax { private readonly LazyComponentRegistrationList registrations; private readonly TrackingLazyComponentRegistration newRegistration; public TrackingRegistrationLocationSelector(LazyComponentRegistrationList registrations, TrackingLazyComponentRegistration newRegistration) { this.registrations = registrations; this.newRegistration = newRegistration; } void ITrackingRegistrationLocationSelectionSyntax.InsteadOf() { if (newRegistration.ComponentType != typeof(TRegistrationType)) { registrations.EnsureNoDuplicateRegistrationType(newRegistration.ComponentType); } int index = registrations.EnsureRegistrationExists(); Func innerComponentFactory = registrations.entries[index].Factory; registrations.entries[index] = new LazyComponentRegistration(newRegistration.ComponentType, (TArgument arg) => newRegistration.Factory(innerComponentFactory(arg), arg)); } } private readonly List entries = new List(); public int Count => entries.Count; public IEnumerable> InReverseOrder { get { int i = entries.Count - 1; while (i >= 0) { yield return entries[i].Factory; int num = i - 1; i = num; } } } public LazyComponentRegistrationList Clone() { LazyComponentRegistrationList lazyComponentRegistrationList = new LazyComponentRegistrationList(); foreach (LazyComponentRegistration entry in entries) { lazyComponentRegistrationList.entries.Add(entry); } return lazyComponentRegistrationList; } public void Clear() { entries.Clear(); } public void Add(Type componentType, Func factory) { entries.Add(new LazyComponentRegistration(componentType, factory)); } public void Remove(Type componentType) { for (int i = 0; i < entries.Count; i++) { if (entries[i].ComponentType == componentType) { entries.RemoveAt(i); return; } } throw new KeyNotFoundException("A component registration of type '" + componentType.FullName + "' was not found."); } public IRegistrationLocationSelectionSyntax CreateRegistrationLocationSelector(Type componentType, Func factory) { return new RegistrationLocationSelector(this, new LazyComponentRegistration(componentType, factory)); } public ITrackingRegistrationLocationSelectionSyntax CreateTrackingRegistrationLocationSelector(Type componentType, Func factory) { return new TrackingRegistrationLocationSelector(this, new TrackingLazyComponentRegistration(componentType, factory)); } public IEnumerator> GetEnumerator() { return entries.Select((LazyComponentRegistration e) => e.Factory).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } private int IndexOfRegistration(Type registrationType) { for (int i = 0; i < entries.Count; i++) { if (registrationType == entries[i].ComponentType) { return i; } } return -1; } private void EnsureNoDuplicateRegistrationType(Type componentType) { if (IndexOfRegistration(componentType) != -1) { throw new InvalidOperationException("A component of type '" + componentType.FullName + "' has already been registered."); } } private int EnsureRegistrationExists() { int num = IndexOfRegistration(typeof(TRegistrationType)); if (num == -1) { throw new InvalidOperationException("A component of type '" + typeof(TRegistrationType).FullName + "' has not been registered."); } return num; } } internal static class LazyComponentRegistrationListExtensions { public static TComponent BuildComponentChain(this LazyComponentRegistrationList registrations, TComponent innerComponent) { return registrations.InReverseOrder.Aggregate(innerComponent, (TComponent inner, Func factory) => factory(inner)); } public static TComponent BuildComponentChain(this LazyComponentRegistrationList registrations, TComponent innerComponent, Func argumentBuilder) { Func argumentBuilder2 = argumentBuilder; return registrations.InReverseOrder.Aggregate(innerComponent, (TComponent inner, Func factory) => factory(argumentBuilder2(inner))); } public static List BuildComponentList(this LazyComponentRegistrationList registrations) { return registrations.Select((Func factory) => factory(default(Nothing))).ToList(); } public static List BuildComponentList(this LazyComponentRegistrationList registrations, TArgument argument) { TArgument argument2 = argument; return registrations.Select((Func factory) => factory(argument2)).ToList(); } } [StructLayout(LayoutKind.Sequential, Size = 1)] internal struct Nothing { } internal sealed class ObjectDescriptor : IObjectDescriptor { public object? Value { get; private set; } public Type Type { get; private set; } public Type StaticType { get; private set; } public ScalarStyle ScalarStyle { get; private set; } public ObjectDescriptor(object? value, Type type, Type staticType) : this(value, type, staticType, ScalarStyle.Any) { } public ObjectDescriptor(object? value, Type type, Type staticType, ScalarStyle scalarStyle) { Value = value; Type = type ?? throw new ArgumentNullException("type"); StaticType = staticType ?? throw new ArgumentNullException("staticType"); ScalarStyle = scalarStyle; } } internal delegate IObjectGraphTraversalStrategy ObjectGraphTraversalStrategyFactory(ITypeInspector typeInspector, ITypeResolver typeResolver, IEnumerable typeConverters, int maximumRecursion); internal sealed class PropertyDescriptor : IPropertyDescriptor { private readonly IPropertyDescriptor baseDescriptor; public bool AllowNulls => baseDescriptor.AllowNulls; public string Name { get; set; } public bool Required => baseDescriptor.Required; public Type Type => baseDescriptor.Type; public Type? TypeOverride { get { return baseDescriptor.TypeOverride; } set { baseDescriptor.TypeOverride = value; } } public Type? ConverterType => baseDescriptor.ConverterType; public int Order { get; set; } public ScalarStyle ScalarStyle { get { return baseDescriptor.ScalarStyle; } set { baseDescriptor.ScalarStyle = value; } } public bool CanWrite => baseDescriptor.CanWrite; public PropertyDescriptor(IPropertyDescriptor baseDescriptor) { this.baseDescriptor = baseDescriptor; Name = baseDescriptor.Name; } public void Write(object target, object? value) { baseDescriptor.Write(target, value); } public T? GetCustomAttribute() where T : Attribute { return baseDescriptor.GetCustomAttribute(); } public IObjectDescriptor Read(object target) { return baseDescriptor.Read(target); } } internal sealed class Serializer : ISerializer { private readonly IValueSerializer valueSerializer; private readonly EmitterSettings emitterSettings; public Serializer() : this(new SerializerBuilder().BuildValueSerializer(), EmitterSettings.Default) { } private Serializer(IValueSerializer valueSerializer, EmitterSettings emitterSettings) { this.valueSerializer = valueSerializer ?? throw new ArgumentNullException("valueSerializer"); this.emitterSettings = emitterSettings ?? throw new ArgumentNullException("emitterSettings"); } public static Serializer FromValueSerializer(IValueSerializer valueSerializer, EmitterSettings emitterSettings) { return new Serializer(valueSerializer, emitterSettings); } public string Serialize(object? graph) { using StringWriter stringWriter = new StringWriter(); Serialize(stringWriter, graph); return stringWriter.ToString(); } public string Serialize(object? graph, Type type) { using StringWriter stringWriter = new StringWriter(); Serialize(stringWriter, graph, type); return stringWriter.ToString(); } public void Serialize(TextWriter writer, object? graph) { Serialize(new Emitter(writer, emitterSettings), graph); } public void Serialize(TextWriter writer, object? graph, Type type) { Serialize(new Emitter(writer, emitterSettings), graph, type); } public void Serialize(IEmitter emitter, object? graph) { if (emitter == null) { throw new ArgumentNullException("emitter"); } EmitDocument(emitter, graph, null); } public void Serialize(IEmitter emitter, object? graph, Type type) { if (emitter == null) { throw new ArgumentNullException("emitter"); } if (type == null) { throw new ArgumentNullException("type"); } EmitDocument(emitter, graph, type); } private void EmitDocument(IEmitter emitter, object? graph, Type? type) { emitter.Emit(new YamlDotNet.Core.Events.StreamStart()); emitter.Emit(new YamlDotNet.Core.Events.DocumentStart()); valueSerializer.SerializeValue(emitter, graph, type); emitter.Emit(new YamlDotNet.Core.Events.DocumentEnd(isImplicit: true)); emitter.Emit(new YamlDotNet.Core.Events.StreamEnd()); } } internal sealed class SerializerBuilder : BuilderSkeleton { private class ValueSerializer : IValueSerializer { private readonly IObjectGraphTraversalStrategy traversalStrategy; private readonly IEventEmitter eventEmitter; private readonly IEnumerable typeConverters; private readonly LazyComponentRegistrationList, IObjectGraphVisitor> preProcessingPhaseObjectGraphVisitorFactories; private readonly LazyComponentRegistrationList> emissionPhaseObjectGraphVisitorFactories; public ValueSerializer(IObjectGraphTraversalStrategy traversalStrategy, IEventEmitter eventEmitter, IEnumerable typeConverters, LazyComponentRegistrationList, IObjectGraphVisitor> preProcessingPhaseObjectGraphVisitorFactories, LazyComponentRegistrationList> emissionPhaseObjectGraphVisitorFactories) { this.traversalStrategy = traversalStrategy; this.eventEmitter = eventEmitter; this.typeConverters = typeConverters; this.preProcessingPhaseObjectGraphVisitorFactories = preProcessingPhaseObjectGraphVisitorFactories; this.emissionPhaseObjectGraphVisitorFactories = emissionPhaseObjectGraphVisitorFactories; } public void SerializeValue(IEmitter emitter, object? value, Type? type) { IEmitter emitter2 = emitter; Type type2 = type ?? ((value != null) ? value.GetType() : typeof(object)); Type staticType = type ?? typeof(object); ObjectDescriptor graph = new ObjectDescriptor(value, type2, staticType); List> preProcessingPhaseObjectGraphVisitors = preProcessingPhaseObjectGraphVisitorFactories.BuildComponentList(typeConverters); IObjectGraphVisitor visitor = emissionPhaseObjectGraphVisitorFactories.BuildComponentChain>(new EmittingObjectGraphVisitor(eventEmitter), (IObjectGraphVisitor inner) => new EmissionPhaseObjectGraphVisitorArgs(inner, eventEmitter, preProcessingPhaseObjectGraphVisitors, typeConverters, NestedObjectSerializer)); foreach (IObjectGraphVisitor item in preProcessingPhaseObjectGraphVisitors) { traversalStrategy.Traverse(graph, item, default(Nothing), NestedObjectSerializer); } traversalStrategy.Traverse(graph, visitor, emitter2, NestedObjectSerializer); void NestedObjectSerializer(object? v, Type? t) { SerializeValue(emitter2, v, t); } } } private ObjectGraphTraversalStrategyFactory objectGraphTraversalStrategyFactory; private readonly LazyComponentRegistrationList, IObjectGraphVisitor> preProcessingPhaseObjectGraphVisitorFactories; private readonly LazyComponentRegistrationList> emissionPhaseObjectGraphVisitorFactories; private readonly LazyComponentRegistrationList eventEmitterFactories; private readonly Dictionary tagMappings = new Dictionary(); private readonly IObjectFactory objectFactory; private int maximumRecursion = 50; private EmitterSettings emitterSettings = EmitterSettings.Default; private DefaultValuesHandling defaultValuesHandlingConfiguration; private ScalarStyle defaultScalarStyle; private bool quoteNecessaryStrings; private bool quoteYaml1_1Strings; protected override SerializerBuilder Self => this; public SerializerBuilder() : base((ITypeResolver)new DynamicTypeResolver()) { typeInspectorFactories.Add(typeof(CachedTypeInspector), (ITypeInspector inner) => new CachedTypeInspector(inner)); typeInspectorFactories.Add(typeof(NamingConventionTypeInspector), (ITypeInspector inner) => (!(namingConvention is NullNamingConvention)) ? new NamingConventionTypeInspector(inner, namingConvention) : inner); typeInspectorFactories.Add(typeof(YamlAttributesTypeInspector), (ITypeInspector inner) => new YamlAttributesTypeInspector(inner)); typeInspectorFactories.Add(typeof(YamlAttributeOverridesInspector), (ITypeInspector inner) => (overrides == null) ? inner : new YamlAttributeOverridesInspector(inner, overrides.Clone())); preProcessingPhaseObjectGraphVisitorFactories = new LazyComponentRegistrationList, IObjectGraphVisitor> { { typeof(AnchorAssigner), (IEnumerable typeConverters) => new AnchorAssigner(typeConverters) } }; emissionPhaseObjectGraphVisitorFactories = new LazyComponentRegistrationList> { { typeof(CustomSerializationObjectGraphVisitor), (EmissionPhaseObjectGraphVisitorArgs args) => new CustomSerializationObjectGraphVisitor(args.InnerVisitor, args.TypeConverters, args.NestedObjectSerializer) }, { typeof(AnchorAssigningObjectGraphVisitor), (EmissionPhaseObjectGraphVisitorArgs args) => new AnchorAssigningObjectGraphVisitor(args.InnerVisitor, args.EventEmitter, args.GetPreProcessingPhaseObjectGraphVisitor()) }, { typeof(DefaultValuesObjectGraphVisitor), (EmissionPhaseObjectGraphVisitorArgs args) => new DefaultValuesObjectGraphVisitor(defaultValuesHandlingConfiguration, args.InnerVisitor, new DefaultObjectFactory()) }, { typeof(CommentsObjectGraphVisitor), (EmissionPhaseObjectGraphVisitorArgs args) => new CommentsObjectGraphVisitor(args.InnerVisitor) } }; eventEmitterFactories = new LazyComponentRegistrationList { { typeof(TypeAssigningEventEmitter), (IEventEmitter inner) => new TypeAssigningEventEmitter(inner, tagMappings, quoteNecessaryStrings, quoteYaml1_1Strings, defaultScalarStyle, yamlFormatter, enumNamingConvention, BuildTypeInspector()) } }; objectFactory = new DefaultObjectFactory(); objectGraphTraversalStrategyFactory = (ITypeInspector typeInspector, ITypeResolver typeResolver, IEnumerable typeConverters, int maximumRecursion) => new FullObjectGraphTraversalStrategy(typeInspector, typeResolver, maximumRecursion, namingConvention, objectFactory); } public SerializerBuilder WithQuotingNecessaryStrings(bool quoteYaml1_1Strings = false) { quoteNecessaryStrings = true; this.quoteYaml1_1Strings = quoteYaml1_1Strings; return this; } public SerializerBuilder WithDefaultScalarStyle(ScalarStyle style) { defaultScalarStyle = style; return this; } public SerializerBuilder WithMaximumRecursion(int maximumRecursion) { if (maximumRecursion <= 0) { throw new ArgumentOutOfRangeException("maximumRecursion", $"The maximum recursion specified ({maximumRecursion}) is invalid. It should be a positive integer."); } this.maximumRecursion = maximumRecursion; return this; } public SerializerBuilder WithEventEmitter(Func eventEmitterFactory) where TEventEmitter : IEventEmitter { return WithEventEmitter(eventEmitterFactory, delegate(IRegistrationLocationSelectionSyntax w) { w.OnTop(); }); } public SerializerBuilder WithEventEmitter(Func eventEmitterFactory) where TEventEmitter : IEventEmitter { return WithEventEmitter(eventEmitterFactory, delegate(IRegistrationLocationSelectionSyntax w) { w.OnTop(); }); } public SerializerBuilder WithEventEmitter(Func eventEmitterFactory, Action> where) where TEventEmitter : IEventEmitter { Func eventEmitterFactory2 = eventEmitterFactory; return WithEventEmitter((IEventEmitter e, ITypeInspector _) => eventEmitterFactory2(e), where); } public SerializerBuilder WithEventEmitter(Func eventEmitterFactory, Action> where) where TEventEmitter : IEventEmitter { Func eventEmitterFactory2 = eventEmitterFactory; if (eventEmitterFactory2 == null) { throw new ArgumentNullException("eventEmitterFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(eventEmitterFactories.CreateRegistrationLocationSelector(typeof(TEventEmitter), (IEventEmitter inner) => eventEmitterFactory2(inner, BuildTypeInspector()))); return Self; } public SerializerBuilder WithEventEmitter(WrapperFactory eventEmitterFactory, Action> where) where TEventEmitter : IEventEmitter { WrapperFactory eventEmitterFactory2 = eventEmitterFactory; if (eventEmitterFactory2 == null) { throw new ArgumentNullException("eventEmitterFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(eventEmitterFactories.CreateTrackingRegistrationLocationSelector(typeof(TEventEmitter), (IEventEmitter wrapped, IEventEmitter inner) => eventEmitterFactory2(wrapped, inner))); return Self; } public SerializerBuilder WithoutEventEmitter() where TEventEmitter : IEventEmitter { return WithoutEventEmitter(typeof(TEventEmitter)); } public SerializerBuilder WithoutEventEmitter(Type eventEmitterType) { if (eventEmitterType == null) { throw new ArgumentNullException("eventEmitterType"); } eventEmitterFactories.Remove(eventEmitterType); return this; } public override SerializerBuilder WithTagMapping(TagName tag, Type type) { if (tag.IsEmpty) { throw new ArgumentException("Non-specific tags cannot be maped"); } if (type == null) { throw new ArgumentNullException("type"); } if (tagMappings.TryGetValue(type, out var value)) { throw new ArgumentException($"Type already has a registered tag '{value}' for type '{type.FullName}'", "type"); } tagMappings.Add(type, tag); return this; } public SerializerBuilder WithoutTagMapping(Type type) { if (type == null) { throw new ArgumentNullException("type"); } if (!tagMappings.Remove(type)) { throw new KeyNotFoundException("Tag for type '" + type.FullName + "' is not registered"); } return this; } public SerializerBuilder EnsureRoundtrip() { objectGraphTraversalStrategyFactory = (ITypeInspector typeInspector, ITypeResolver typeResolver, IEnumerable typeConverters, int maximumRecursion) => new RoundtripObjectGraphTraversalStrategy(typeConverters, typeInspector, typeResolver, maximumRecursion, namingConvention, settings, objectFactory); WithEventEmitter((IEventEmitter inner) => new TypeAssigningEventEmitter(inner, tagMappings, quoteNecessaryStrings, quoteYaml1_1Strings, defaultScalarStyle, yamlFormatter, enumNamingConvention, BuildTypeInspector()), delegate(IRegistrationLocationSelectionSyntax loc) { loc.InsteadOf(); }); return WithTypeInspector((ITypeInspector inner) => new ReadableAndWritablePropertiesTypeInspector(inner), delegate(IRegistrationLocationSelectionSyntax loc) { loc.OnBottom(); }); } public SerializerBuilder DisableAliases() { preProcessingPhaseObjectGraphVisitorFactories.Remove(typeof(AnchorAssigner)); emissionPhaseObjectGraphVisitorFactories.Remove(typeof(AnchorAssigningObjectGraphVisitor)); return this; } [Obsolete("The default behavior is now to always emit default values, thefore calling this method has no effect. This behavior is now controlled by ConfigureDefaultValuesHandling.", true)] public SerializerBuilder EmitDefaults() { return ConfigureDefaultValuesHandling(DefaultValuesHandling.Preserve); } public SerializerBuilder ConfigureDefaultValuesHandling(DefaultValuesHandling configuration) { defaultValuesHandlingConfiguration = configuration; return this; } public SerializerBuilder JsonCompatible() { emitterSettings = emitterSettings.WithMaxSimpleKeyLength(int.MaxValue).WithoutAnchorName().WithUtf16SurrogatePairs(); return WithTypeConverter(new YamlDotNet.Serialization.Converters.GuidConverter(jsonCompatible: true), delegate(IRegistrationLocationSelectionSyntax w) { w.InsteadOf(); }).WithTypeConverter(new DateTime8601Converter(ScalarStyle.DoubleQuoted)).WithEventEmitter((IEventEmitter inner) => new JsonEventEmitter(inner, yamlFormatter, enumNamingConvention, BuildTypeInspector()), delegate(IRegistrationLocationSelectionSyntax loc) { loc.InsteadOf(); }); } public SerializerBuilder WithNewLine(string newLine) { emitterSettings = emitterSettings.WithNewLine(newLine); return this; } public SerializerBuilder WithPreProcessingPhaseObjectGraphVisitor(TObjectGraphVisitor objectGraphVisitor) where TObjectGraphVisitor : IObjectGraphVisitor { return WithPreProcessingPhaseObjectGraphVisitor(objectGraphVisitor, delegate(IRegistrationLocationSelectionSyntax> w) { w.OnTop(); }); } public SerializerBuilder WithPreProcessingPhaseObjectGraphVisitor(Func, TObjectGraphVisitor> objectGraphVisitorFactory) where TObjectGraphVisitor : IObjectGraphVisitor { return WithPreProcessingPhaseObjectGraphVisitor(objectGraphVisitorFactory, delegate(IRegistrationLocationSelectionSyntax> w) { w.OnTop(); }); } public SerializerBuilder WithPreProcessingPhaseObjectGraphVisitor(TObjectGraphVisitor objectGraphVisitor, Action>> where) where TObjectGraphVisitor : IObjectGraphVisitor { TObjectGraphVisitor objectGraphVisitor2 = objectGraphVisitor; if (objectGraphVisitor2 == null) { throw new ArgumentNullException("objectGraphVisitor"); } if (where == null) { throw new ArgumentNullException("where"); } where(preProcessingPhaseObjectGraphVisitorFactories.CreateRegistrationLocationSelector(typeof(TObjectGraphVisitor), (IEnumerable _) => objectGraphVisitor2)); return this; } public SerializerBuilder WithPreProcessingPhaseObjectGraphVisitor(Func, TObjectGraphVisitor> objectGraphVisitorFactory, Action>> where) where TObjectGraphVisitor : IObjectGraphVisitor { Func, TObjectGraphVisitor> objectGraphVisitorFactory2 = objectGraphVisitorFactory; if (objectGraphVisitorFactory2 == null) { throw new ArgumentNullException("objectGraphVisitorFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(preProcessingPhaseObjectGraphVisitorFactories.CreateRegistrationLocationSelector(typeof(TObjectGraphVisitor), (IEnumerable typeConverters) => objectGraphVisitorFactory2(typeConverters))); return this; } public SerializerBuilder WithPreProcessingPhaseObjectGraphVisitor(WrapperFactory, TObjectGraphVisitor> objectGraphVisitorFactory, Action>> where) where TObjectGraphVisitor : IObjectGraphVisitor { WrapperFactory, TObjectGraphVisitor> objectGraphVisitorFactory2 = objectGraphVisitorFactory; if (objectGraphVisitorFactory2 == null) { throw new ArgumentNullException("objectGraphVisitorFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(preProcessingPhaseObjectGraphVisitorFactories.CreateTrackingRegistrationLocationSelector(typeof(TObjectGraphVisitor), (IObjectGraphVisitor wrapped, IEnumerable _) => objectGraphVisitorFactory2(wrapped))); return this; } public SerializerBuilder WithPreProcessingPhaseObjectGraphVisitor(WrapperFactory, IObjectGraphVisitor, TObjectGraphVisitor> objectGraphVisitorFactory, Action>> where) where TObjectGraphVisitor : IObjectGraphVisitor { WrapperFactory, IObjectGraphVisitor, TObjectGraphVisitor> objectGraphVisitorFactory2 = objectGraphVisitorFactory; if (objectGraphVisitorFactory2 == null) { throw new ArgumentNullException("objectGraphVisitorFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(preProcessingPhaseObjectGraphVisitorFactories.CreateTrackingRegistrationLocationSelector(typeof(TObjectGraphVisitor), (IObjectGraphVisitor wrapped, IEnumerable typeConverters) => objectGraphVisitorFactory2(wrapped, typeConverters))); return this; } public SerializerBuilder WithoutPreProcessingPhaseObjectGraphVisitor() where TObjectGraphVisitor : IObjectGraphVisitor { return WithoutPreProcessingPhaseObjectGraphVisitor(typeof(TObjectGraphVisitor)); } public SerializerBuilder WithoutPreProcessingPhaseObjectGraphVisitor(Type objectGraphVisitorType) { if (objectGraphVisitorType == null) { throw new ArgumentNullException("objectGraphVisitorType"); } preProcessingPhaseObjectGraphVisitorFactories.Remove(objectGraphVisitorType); return this; } public SerializerBuilder WithObjectGraphTraversalStrategyFactory(ObjectGraphTraversalStrategyFactory objectGraphTraversalStrategyFactory) { this.objectGraphTraversalStrategyFactory = objectGraphTraversalStrategyFactory; return this; } public SerializerBuilder WithEmissionPhaseObjectGraphVisitor(Func objectGraphVisitorFactory) where TObjectGraphVisitor : IObjectGraphVisitor { return WithEmissionPhaseObjectGraphVisitor(objectGraphVisitorFactory, delegate(IRegistrationLocationSelectionSyntax> w) { w.OnTop(); }); } public SerializerBuilder WithEmissionPhaseObjectGraphVisitor(Func objectGraphVisitorFactory, Action>> where) where TObjectGraphVisitor : IObjectGraphVisitor { Func objectGraphVisitorFactory2 = objectGraphVisitorFactory; if (objectGraphVisitorFactory2 == null) { throw new ArgumentNullException("objectGraphVisitorFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(emissionPhaseObjectGraphVisitorFactories.CreateRegistrationLocationSelector(typeof(TObjectGraphVisitor), (EmissionPhaseObjectGraphVisitorArgs args) => objectGraphVisitorFactory2(args))); return this; } public SerializerBuilder WithEmissionPhaseObjectGraphVisitor(WrapperFactory, TObjectGraphVisitor> objectGraphVisitorFactory, Action>> where) where TObjectGraphVisitor : IObjectGraphVisitor { WrapperFactory, TObjectGraphVisitor> objectGraphVisitorFactory2 = objectGraphVisitorFactory; if (objectGraphVisitorFactory2 == null) { throw new ArgumentNullException("objectGraphVisitorFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(emissionPhaseObjectGraphVisitorFactories.CreateTrackingRegistrationLocationSelector(typeof(TObjectGraphVisitor), (IObjectGraphVisitor wrapped, EmissionPhaseObjectGraphVisitorArgs args) => objectGraphVisitorFactory2(wrapped, args))); return this; } public SerializerBuilder WithoutEmissionPhaseObjectGraphVisitor() where TObjectGraphVisitor : IObjectGraphVisitor { return WithoutEmissionPhaseObjectGraphVisitor(typeof(TObjectGraphVisitor)); } public SerializerBuilder WithoutEmissionPhaseObjectGraphVisitor(Type objectGraphVisitorType) { if (objectGraphVisitorType == null) { throw new ArgumentNullException("objectGraphVisitorType"); } emissionPhaseObjectGraphVisitorFactories.Remove(objectGraphVisitorType); return this; } public SerializerBuilder WithIndentedSequences() { emitterSettings = emitterSettings.WithIndentedSequences(); return this; } public ISerializer Build() { if (FsharpHelper.Instance == null) { FsharpHelper.Instance = new DefaultFsharpHelper(); } return Serializer.FromValueSerializer(BuildValueSerializer(), emitterSettings); } public IValueSerializer BuildValueSerializer() { IEnumerable typeConverters = BuildTypeConverters(); ITypeInspector typeInspector = BuildTypeInspector(); IObjectGraphTraversalStrategy traversalStrategy = objectGraphTraversalStrategyFactory(typeInspector, typeResolver, typeConverters, maximumRecursion); IEventEmitter eventEmitter = eventEmitterFactories.BuildComponentChain(new WriterEventEmitter()); return new ValueSerializer(traversalStrategy, eventEmitter, typeConverters, preProcessingPhaseObjectGraphVisitorFactories.Clone(), emissionPhaseObjectGraphVisitorFactories.Clone()); } public ITypeInspector BuildTypeInspector() { ITypeInspector typeInspector = new ReadablePropertiesTypeInspector(typeResolver, includeNonPublicProperties); if (!ignoreFields) { typeInspector = new CompositeTypeInspector(new ReadableFieldsTypeInspector(typeResolver), typeInspector); } return typeInspectorFactories.BuildComponentChain(typeInspector); } } internal class Settings { public bool AllowPrivateConstructors { get; set; } } internal abstract class StaticBuilderSkeleton where TBuilder : StaticBuilderSkeleton { internal INamingConvention namingConvention = NullNamingConvention.Instance; internal INamingConvention enumNamingConvention = NullNamingConvention.Instance; internal ITypeResolver typeResolver; internal readonly LazyComponentRegistrationList typeConverterFactories; internal readonly LazyComponentRegistrationList typeInspectorFactories; internal bool includeNonPublicProperties; internal Settings settings; internal YamlFormatter yamlFormatter = YamlFormatter.Default; protected abstract TBuilder Self { get; } internal StaticBuilderSkeleton(ITypeResolver typeResolver) { typeConverterFactories = new LazyComponentRegistrationList { { typeof(YamlDotNet.Serialization.Converters.GuidConverter), (Nothing _) => new YamlDotNet.Serialization.Converters.GuidConverter(jsonCompatible: false) } }; typeInspectorFactories = new LazyComponentRegistrationList(); this.typeResolver = typeResolver ?? throw new ArgumentNullException("typeResolver"); settings = new Settings(); } public TBuilder WithNamingConvention(INamingConvention namingConvention) { this.namingConvention = namingConvention ?? throw new ArgumentNullException("namingConvention"); return Self; } public TBuilder WithEnumNamingConvention(INamingConvention enumNamingConvention) { this.enumNamingConvention = enumNamingConvention ?? throw new ArgumentNullException("enumNamingConvention"); return Self; } public TBuilder WithTypeResolver(ITypeResolver typeResolver) { this.typeResolver = typeResolver ?? throw new ArgumentNullException("typeResolver"); return Self; } public abstract TBuilder WithTagMapping(TagName tag, Type type); public TBuilder WithTypeConverter(IYamlTypeConverter typeConverter) { return WithTypeConverter(typeConverter, delegate(IRegistrationLocationSelectionSyntax w) { w.OnTop(); }); } public TBuilder WithTypeConverter(IYamlTypeConverter typeConverter, Action> where) { IYamlTypeConverter typeConverter2 = typeConverter; if (typeConverter2 == null) { throw new ArgumentNullException("typeConverter"); } if (where == null) { throw new ArgumentNullException("where"); } where(typeConverterFactories.CreateRegistrationLocationSelector(typeConverter2.GetType(), (Nothing _) => typeConverter2)); return Self; } public TBuilder WithTypeConverter(WrapperFactory typeConverterFactory, Action> where) where TYamlTypeConverter : IYamlTypeConverter { WrapperFactory typeConverterFactory2 = typeConverterFactory; if (typeConverterFactory2 == null) { throw new ArgumentNullException("typeConverterFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(typeConverterFactories.CreateTrackingRegistrationLocationSelector(typeof(TYamlTypeConverter), (IYamlTypeConverter wrapped, Nothing _) => typeConverterFactory2(wrapped))); return Self; } public TBuilder WithoutTypeConverter() where TYamlTypeConverter : IYamlTypeConverter { return WithoutTypeConverter(typeof(TYamlTypeConverter)); } public TBuilder WithoutTypeConverter(Type converterType) { if (converterType == null) { throw new ArgumentNullException("converterType"); } typeConverterFactories.Remove(converterType); return Self; } public TBuilder WithTypeInspector(Func typeInspectorFactory) where TTypeInspector : ITypeInspector { return WithTypeInspector(typeInspectorFactory, delegate(IRegistrationLocationSelectionSyntax w) { w.OnTop(); }); } public TBuilder WithTypeInspector(Func typeInspectorFactory, Action> where) where TTypeInspector : ITypeInspector { Func typeInspectorFactory2 = typeInspectorFactory; if (typeInspectorFactory2 == null) { throw new ArgumentNullException("typeInspectorFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(typeInspectorFactories.CreateRegistrationLocationSelector(typeof(TTypeInspector), (ITypeInspector inner) => typeInspectorFactory2(inner))); return Self; } public TBuilder WithTypeInspector(WrapperFactory typeInspectorFactory, Action> where) where TTypeInspector : ITypeInspector { WrapperFactory typeInspectorFactory2 = typeInspectorFactory; if (typeInspectorFactory2 == null) { throw new ArgumentNullException("typeInspectorFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(typeInspectorFactories.CreateTrackingRegistrationLocationSelector(typeof(TTypeInspector), (ITypeInspector wrapped, ITypeInspector inner) => typeInspectorFactory2(wrapped, inner))); return Self; } public TBuilder WithoutTypeInspector() where TTypeInspector : ITypeInspector { return WithoutTypeInspector(typeof(TTypeInspector)); } public TBuilder WithoutTypeInspector(Type inspectorType) { if (inspectorType == null) { throw new ArgumentNullException("inspectorType"); } typeInspectorFactories.Remove(inspectorType); return Self; } public TBuilder WithYamlFormatter(YamlFormatter formatter) { yamlFormatter = formatter ?? throw new ArgumentNullException("formatter"); return Self; } protected IEnumerable BuildTypeConverters() { return typeConverterFactories.BuildComponentList(); } } internal abstract class StaticContext { public virtual bool IsKnownType(Type type) { throw new NotImplementedException(); } public virtual ITypeResolver GetTypeResolver() { throw new NotImplementedException(); } public virtual StaticObjectFactory GetFactory() { throw new NotImplementedException(); } public virtual ITypeInspector GetTypeInspector() { throw new NotImplementedException(); } } internal sealed class StaticDeserializerBuilder : StaticBuilderSkeleton { private readonly StaticContext context; private readonly StaticObjectFactory factory; private readonly LazyComponentRegistrationList nodeDeserializerFactories; private readonly LazyComponentRegistrationList nodeTypeResolverFactories; private readonly Dictionary tagMappings; private readonly ITypeConverter typeConverter; private readonly Dictionary typeMappings; private bool ignoreUnmatched; private bool duplicateKeyChecking; private bool attemptUnknownTypeDeserialization; private bool enforceNullability; private bool caseInsensitivePropertyMatching; protected override StaticDeserializerBuilder Self => this; public StaticDeserializerBuilder(StaticContext context) : base(context.GetTypeResolver()) { this.context = context; factory = context.GetFactory(); typeMappings = new Dictionary(); tagMappings = new Dictionary { { FailsafeSchema.Tags.Map, typeof(Dictionary) }, { FailsafeSchema.Tags.Str, typeof(string) }, { JsonSchema.Tags.Bool, typeof(bool) }, { JsonSchema.Tags.Float, typeof(double) }, { JsonSchema.Tags.Int, typeof(int) }, { DefaultSchema.Tags.Timestamp, typeof(DateTime) } }; typeInspectorFactories.Add(typeof(CachedTypeInspector), (ITypeInspector inner) => new CachedTypeInspector(inner)); typeInspectorFactories.Add(typeof(NamingConventionTypeInspector), (ITypeInspector inner) => (!(namingConvention is NullNamingConvention)) ? new NamingConventionTypeInspector(inner, namingConvention) : inner); typeInspectorFactories.Add(typeof(YamlAttributesTypeInspector), (ITypeInspector inner) => new YamlAttributesTypeInspector(inner)); nodeDeserializerFactories = new LazyComponentRegistrationList { { typeof(YamlConvertibleNodeDeserializer), (Nothing _) => new YamlConvertibleNodeDeserializer(factory) }, { typeof(YamlSerializableNodeDeserializer), (Nothing _) => new YamlSerializableNodeDeserializer(factory) }, { typeof(TypeConverterNodeDeserializer), (Nothing _) => new TypeConverterNodeDeserializer(BuildTypeConverters()) }, { typeof(NullNodeDeserializer), (Nothing _) => new NullNodeDeserializer() }, { typeof(ScalarNodeDeserializer), (Nothing _) => new ScalarNodeDeserializer(attemptUnknownTypeDeserialization, typeConverter, BuildTypeInspector(), yamlFormatter, enumNamingConvention) }, { typeof(StaticArrayNodeDeserializer), (Nothing _) => new StaticArrayNodeDeserializer(factory) }, { typeof(StaticDictionaryNodeDeserializer), (Nothing _) => new StaticDictionaryNodeDeserializer(factory, duplicateKeyChecking) }, { typeof(StaticCollectionNodeDeserializer), (Nothing _) => new StaticCollectionNodeDeserializer(factory) }, { typeof(ObjectNodeDeserializer), (Nothing _) => new ObjectNodeDeserializer(factory, BuildTypeInspector(), ignoreUnmatched, duplicateKeyChecking, typeConverter, enumNamingConvention, enforceNullability, caseInsensitivePropertyMatching, enforceRequiredProperties: false, BuildTypeConverters()) } }; nodeTypeResolverFactories = new LazyComponentRegistrationList { { typeof(MappingNodeTypeResolver), (Nothing _) => new MappingNodeTypeResolver(typeMappings) }, { typeof(YamlConvertibleTypeResolver), (Nothing _) => new YamlConvertibleTypeResolver() }, { typeof(YamlSerializableTypeResolver), (Nothing _) => new YamlSerializableTypeResolver() }, { typeof(TagNodeTypeResolver), (Nothing _) => new TagNodeTypeResolver(tagMappings) }, { typeof(PreventUnknownTagsNodeTypeResolver), (Nothing _) => new PreventUnknownTagsNodeTypeResolver() }, { typeof(DefaultContainersNodeTypeResolver), (Nothing _) => new DefaultContainersNodeTypeResolver() } }; typeConverter = new NullTypeConverter(); } public ITypeInspector BuildTypeInspector() { ITypeInspector typeInspector = context.GetTypeInspector(); return typeInspectorFactories.BuildComponentChain(typeInspector); } public StaticDeserializerBuilder WithAttemptingUnquotedStringTypeDeserialization() { attemptUnknownTypeDeserialization = true; return this; } public StaticDeserializerBuilder WithNodeDeserializer(INodeDeserializer nodeDeserializer) { return WithNodeDeserializer(nodeDeserializer, delegate(IRegistrationLocationSelectionSyntax w) { w.OnTop(); }); } public StaticDeserializerBuilder WithNodeDeserializer(INodeDeserializer nodeDeserializer, Action> where) { INodeDeserializer nodeDeserializer2 = nodeDeserializer; if (nodeDeserializer2 == null) { throw new ArgumentNullException("nodeDeserializer"); } if (where == null) { throw new ArgumentNullException("where"); } where(nodeDeserializerFactories.CreateRegistrationLocationSelector(nodeDeserializer2.GetType(), (Nothing _) => nodeDeserializer2)); return this; } public StaticDeserializerBuilder WithNodeDeserializer(WrapperFactory nodeDeserializerFactory, Action> where) where TNodeDeserializer : INodeDeserializer { WrapperFactory nodeDeserializerFactory2 = nodeDeserializerFactory; if (nodeDeserializerFactory2 == null) { throw new ArgumentNullException("nodeDeserializerFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(nodeDeserializerFactories.CreateTrackingRegistrationLocationSelector(typeof(TNodeDeserializer), (INodeDeserializer wrapped, Nothing _) => nodeDeserializerFactory2(wrapped))); return this; } public StaticDeserializerBuilder WithCaseInsensitivePropertyMatching() { caseInsensitivePropertyMatching = true; return this; } public StaticDeserializerBuilder WithEnforceNullability() { enforceNullability = true; return this; } public StaticDeserializerBuilder WithoutNodeDeserializer() where TNodeDeserializer : INodeDeserializer { return WithoutNodeDeserializer(typeof(TNodeDeserializer)); } public StaticDeserializerBuilder WithoutNodeDeserializer(Type nodeDeserializerType) { if (nodeDeserializerType == null) { throw new ArgumentNullException("nodeDeserializerType"); } nodeDeserializerFactories.Remove(nodeDeserializerType); return this; } public StaticDeserializerBuilder WithTypeDiscriminatingNodeDeserializer(Action configureTypeDiscriminatingNodeDeserializerOptions, int maxDepth = -1, int maxLength = -1) { TypeDiscriminatingNodeDeserializerOptions typeDiscriminatingNodeDeserializerOptions = new TypeDiscriminatingNodeDeserializerOptions(); configureTypeDiscriminatingNodeDeserializerOptions(typeDiscriminatingNodeDeserializerOptions); TypeDiscriminatingNodeDeserializer nodeDeserializer = new TypeDiscriminatingNodeDeserializer(nodeDeserializerFactories.BuildComponentList(), typeDiscriminatingNodeDeserializerOptions.discriminators, maxDepth, maxLength); return WithNodeDeserializer(nodeDeserializer, delegate(IRegistrationLocationSelectionSyntax s) { s.Before(); }); } public StaticDeserializerBuilder WithNodeTypeResolver(INodeTypeResolver nodeTypeResolver) { return WithNodeTypeResolver(nodeTypeResolver, delegate(IRegistrationLocationSelectionSyntax w) { w.OnTop(); }); } public StaticDeserializerBuilder WithNodeTypeResolver(INodeTypeResolver nodeTypeResolver, Action> where) { INodeTypeResolver nodeTypeResolver2 = nodeTypeResolver; if (nodeTypeResolver2 == null) { throw new ArgumentNullException("nodeTypeResolver"); } if (where == null) { throw new ArgumentNullException("where"); } where(nodeTypeResolverFactories.CreateRegistrationLocationSelector(nodeTypeResolver2.GetType(), (Nothing _) => nodeTypeResolver2)); return this; } public StaticDeserializerBuilder WithNodeTypeResolver(WrapperFactory nodeTypeResolverFactory, Action> where) where TNodeTypeResolver : INodeTypeResolver { WrapperFactory nodeTypeResolverFactory2 = nodeTypeResolverFactory; if (nodeTypeResolverFactory2 == null) { throw new ArgumentNullException("nodeTypeResolverFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(nodeTypeResolverFactories.CreateTrackingRegistrationLocationSelector(typeof(TNodeTypeResolver), (INodeTypeResolver wrapped, Nothing _) => nodeTypeResolverFactory2(wrapped))); return this; } public StaticDeserializerBuilder WithoutNodeTypeResolver() where TNodeTypeResolver : INodeTypeResolver { return WithoutNodeTypeResolver(typeof(TNodeTypeResolver)); } public StaticDeserializerBuilder WithoutNodeTypeResolver(Type nodeTypeResolverType) { if (nodeTypeResolverType == null) { throw new ArgumentNullException("nodeTypeResolverType"); } nodeTypeResolverFactories.Remove(nodeTypeResolverType); return this; } public override StaticDeserializerBuilder WithTagMapping(TagName tag, Type type) { if (tag.IsEmpty) { throw new ArgumentException("Non-specific tags cannot be maped"); } if (type == null) { throw new ArgumentNullException("type"); } if (tagMappings.TryGetValue(tag, out Type value)) { throw new ArgumentException($"Type already has a registered type '{value.FullName}' for tag '{tag}'", "tag"); } tagMappings.Add(tag, type); return this; } public StaticDeserializerBuilder WithTypeMapping() where TConcrete : TInterface { Type typeFromHandle = typeof(TInterface); Type typeFromHandle2 = typeof(TConcrete); if (!typeFromHandle.IsAssignableFrom(typeFromHandle2)) { throw new InvalidOperationException("The type '" + typeFromHandle2.Name + "' does not implement interface '" + typeFromHandle.Name + "'."); } typeMappings[typeFromHandle] = typeFromHandle2; return this; } public StaticDeserializerBuilder WithoutTagMapping(TagName tag) { if (tag.IsEmpty) { throw new ArgumentException("Non-specific tags cannot be maped"); } if (!tagMappings.Remove(tag)) { throw new KeyNotFoundException($"Tag '{tag}' is not registered"); } return this; } public StaticDeserializerBuilder IgnoreUnmatchedProperties() { ignoreUnmatched = true; return this; } public StaticDeserializerBuilder WithDuplicateKeyChecking() { duplicateKeyChecking = true; return this; } public IDeserializer Build() { return Deserializer.FromValueDeserializer(BuildValueDeserializer()); } public IValueDeserializer BuildValueDeserializer() { return new AliasValueDeserializer(new NodeValueDeserializer(nodeDeserializerFactories.BuildComponentList(), nodeTypeResolverFactories.BuildComponentList(), typeConverter, enumNamingConvention, BuildTypeInspector())); } } internal sealed class StaticSerializerBuilder : StaticBuilderSkeleton { private class ValueSerializer : IValueSerializer { private readonly IObjectGraphTraversalStrategy traversalStrategy; private readonly IEventEmitter eventEmitter; private readonly IEnumerable typeConverters; private readonly LazyComponentRegistrationList, IObjectGraphVisitor> preProcessingPhaseObjectGraphVisitorFactories; private readonly LazyComponentRegistrationList> emissionPhaseObjectGraphVisitorFactories; public ValueSerializer(IObjectGraphTraversalStrategy traversalStrategy, IEventEmitter eventEmitter, IEnumerable typeConverters, LazyComponentRegistrationList, IObjectGraphVisitor> preProcessingPhaseObjectGraphVisitorFactories, LazyComponentRegistrationList> emissionPhaseObjectGraphVisitorFactories) { this.traversalStrategy = traversalStrategy; this.eventEmitter = eventEmitter; this.typeConverters = typeConverters; this.preProcessingPhaseObjectGraphVisitorFactories = preProcessingPhaseObjectGraphVisitorFactories; this.emissionPhaseObjectGraphVisitorFactories = emissionPhaseObjectGraphVisitorFactories; } public void SerializeValue(IEmitter emitter, object? value, Type? type) { IEmitter emitter2 = emitter; Type type2 = type ?? ((value != null) ? value.GetType() : typeof(object)); Type staticType = type ?? typeof(object); ObjectDescriptor graph = new ObjectDescriptor(value, type2, staticType); List> preProcessingPhaseObjectGraphVisitors = preProcessingPhaseObjectGraphVisitorFactories.BuildComponentList(typeConverters); foreach (IObjectGraphVisitor item in preProcessingPhaseObjectGraphVisitors) { traversalStrategy.Traverse(graph, item, default(Nothing), NestedObjectSerializer); } IObjectGraphVisitor visitor = emissionPhaseObjectGraphVisitorFactories.BuildComponentChain>(new EmittingObjectGraphVisitor(eventEmitter), (IObjectGraphVisitor inner) => new EmissionPhaseObjectGraphVisitorArgs(inner, eventEmitter, preProcessingPhaseObjectGraphVisitors, typeConverters, NestedObjectSerializer)); traversalStrategy.Traverse(graph, visitor, emitter2, NestedObjectSerializer); void NestedObjectSerializer(object? v, Type? t) { SerializeValue(emitter2, v, t); } } } private readonly StaticContext context; private readonly StaticObjectFactory factory; private ObjectGraphTraversalStrategyFactory objectGraphTraversalStrategyFactory; private readonly LazyComponentRegistrationList, IObjectGraphVisitor> preProcessingPhaseObjectGraphVisitorFactories; private readonly LazyComponentRegistrationList> emissionPhaseObjectGraphVisitorFactories; private readonly LazyComponentRegistrationList eventEmitterFactories; private readonly Dictionary tagMappings = new Dictionary(); private int maximumRecursion = 50; private EmitterSettings emitterSettings = EmitterSettings.Default; private DefaultValuesHandling defaultValuesHandlingConfiguration; private bool quoteNecessaryStrings; private bool quoteYaml1_1Strings; private ScalarStyle defaultScalarStyle; protected override StaticSerializerBuilder Self => this; public StaticSerializerBuilder(StaticContext context) : base((ITypeResolver)new DynamicTypeResolver()) { this.context = context; factory = context.GetFactory(); typeInspectorFactories.Add(typeof(CachedTypeInspector), (ITypeInspector inner) => new CachedTypeInspector(inner)); typeInspectorFactories.Add(typeof(NamingConventionTypeInspector), (ITypeInspector inner) => (!(namingConvention is NullNamingConvention)) ? new NamingConventionTypeInspector(inner, namingConvention) : inner); typeInspectorFactories.Add(typeof(YamlAttributesTypeInspector), (ITypeInspector inner) => new YamlAttributesTypeInspector(inner)); preProcessingPhaseObjectGraphVisitorFactories = new LazyComponentRegistrationList, IObjectGraphVisitor> { { typeof(AnchorAssigner), (IEnumerable typeConverters) => new AnchorAssigner(typeConverters) } }; emissionPhaseObjectGraphVisitorFactories = new LazyComponentRegistrationList> { { typeof(CustomSerializationObjectGraphVisitor), (EmissionPhaseObjectGraphVisitorArgs args) => new CustomSerializationObjectGraphVisitor(args.InnerVisitor, args.TypeConverters, args.NestedObjectSerializer) }, { typeof(AnchorAssigningObjectGraphVisitor), (EmissionPhaseObjectGraphVisitorArgs args) => new AnchorAssigningObjectGraphVisitor(args.InnerVisitor, args.EventEmitter, args.GetPreProcessingPhaseObjectGraphVisitor()) }, { typeof(DefaultValuesObjectGraphVisitor), (EmissionPhaseObjectGraphVisitorArgs args) => new DefaultValuesObjectGraphVisitor(defaultValuesHandlingConfiguration, args.InnerVisitor, factory) }, { typeof(CommentsObjectGraphVisitor), (EmissionPhaseObjectGraphVisitorArgs args) => new CommentsObjectGraphVisitor(args.InnerVisitor) } }; eventEmitterFactories = new LazyComponentRegistrationList { { typeof(TypeAssigningEventEmitter), (IEventEmitter inner) => new TypeAssigningEventEmitter(inner, tagMappings, quoteNecessaryStrings, quoteYaml1_1Strings, defaultScalarStyle, yamlFormatter, enumNamingConvention, BuildTypeInspector()) } }; objectGraphTraversalStrategyFactory = (ITypeInspector typeInspector, ITypeResolver typeResolver, IEnumerable typeConverters, int maximumRecursion) => new FullObjectGraphTraversalStrategy(typeInspector, typeResolver, maximumRecursion, namingConvention, factory); } public StaticSerializerBuilder WithQuotingNecessaryStrings(bool quoteYaml1_1Strings = false) { quoteNecessaryStrings = true; this.quoteYaml1_1Strings = quoteYaml1_1Strings; return this; } public StaticSerializerBuilder WithQuotingNecessaryStrings() { quoteNecessaryStrings = true; return this; } public StaticSerializerBuilder WithDefaultScalarStyle(ScalarStyle style) { defaultScalarStyle = style; return this; } public StaticSerializerBuilder WithMaximumRecursion(int maximumRecursion) { if (maximumRecursion <= 0) { throw new ArgumentOutOfRangeException("maximumRecursion", $"The maximum recursion specified ({maximumRecursion}) is invalid. It should be a positive integer."); } this.maximumRecursion = maximumRecursion; return this; } public StaticSerializerBuilder WithEventEmitter(Func eventEmitterFactory) where TEventEmitter : IEventEmitter { return WithEventEmitter(eventEmitterFactory, delegate(IRegistrationLocationSelectionSyntax w) { w.OnTop(); }); } public StaticSerializerBuilder WithEventEmitter(Func eventEmitterFactory) where TEventEmitter : IEventEmitter { return WithEventEmitter(eventEmitterFactory, delegate(IRegistrationLocationSelectionSyntax w) { w.OnTop(); }); } public StaticSerializerBuilder WithEventEmitter(Func eventEmitterFactory, Action> where) where TEventEmitter : IEventEmitter { Func eventEmitterFactory2 = eventEmitterFactory; return WithEventEmitter((IEventEmitter e, ITypeInspector _) => eventEmitterFactory2(e), where); } public StaticSerializerBuilder WithEventEmitter(Func eventEmitterFactory, Action> where) where TEventEmitter : IEventEmitter { Func eventEmitterFactory2 = eventEmitterFactory; if (eventEmitterFactory2 == null) { throw new ArgumentNullException("eventEmitterFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(eventEmitterFactories.CreateRegistrationLocationSelector(typeof(TEventEmitter), (IEventEmitter inner) => eventEmitterFactory2(inner, BuildTypeInspector()))); return Self; } public StaticSerializerBuilder WithEventEmitter(WrapperFactory eventEmitterFactory, Action> where) where TEventEmitter : IEventEmitter { WrapperFactory eventEmitterFactory2 = eventEmitterFactory; if (eventEmitterFactory2 == null) { throw new ArgumentNullException("eventEmitterFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(eventEmitterFactories.CreateTrackingRegistrationLocationSelector(typeof(TEventEmitter), (IEventEmitter wrapped, IEventEmitter inner) => eventEmitterFactory2(wrapped, inner))); return Self; } public StaticSerializerBuilder WithoutEventEmitter() where TEventEmitter : IEventEmitter { return WithoutEventEmitter(typeof(TEventEmitter)); } public StaticSerializerBuilder WithoutEventEmitter(Type eventEmitterType) { if (eventEmitterType == null) { throw new ArgumentNullException("eventEmitterType"); } eventEmitterFactories.Remove(eventEmitterType); return this; } public override StaticSerializerBuilder WithTagMapping(TagName tag, Type type) { if (tag.IsEmpty) { throw new ArgumentException("Non-specific tags cannot be maped"); } if (type == null) { throw new ArgumentNullException("type"); } if (tagMappings.TryGetValue(type, out var value)) { throw new ArgumentException($"Type already has a registered tag '{value}' for type '{type.FullName}'", "type"); } tagMappings.Add(type, tag); return this; } public StaticSerializerBuilder WithoutTagMapping(Type type) { if (type == null) { throw new ArgumentNullException("type"); } if (!tagMappings.Remove(type)) { throw new KeyNotFoundException("Tag for type '" + type.FullName + "' is not registered"); } return this; } public StaticSerializerBuilder EnsureRoundtrip() { objectGraphTraversalStrategyFactory = (ITypeInspector typeInspector, ITypeResolver typeResolver, IEnumerable typeConverters, int maximumRecursion) => new RoundtripObjectGraphTraversalStrategy(typeConverters, typeInspector, typeResolver, maximumRecursion, namingConvention, settings, factory); WithEventEmitter((IEventEmitter inner) => new TypeAssigningEventEmitter(inner, tagMappings, quoteNecessaryStrings, quoteYaml1_1Strings: false, ScalarStyle.Plain, YamlFormatter.Default, enumNamingConvention, BuildTypeInspector()), delegate(IRegistrationLocationSelectionSyntax loc) { loc.InsteadOf(); }); return WithTypeInspector((ITypeInspector inner) => new ReadableAndWritablePropertiesTypeInspector(inner), delegate(IRegistrationLocationSelectionSyntax loc) { loc.OnBottom(); }); } public StaticSerializerBuilder DisableAliases() { preProcessingPhaseObjectGraphVisitorFactories.Remove(typeof(AnchorAssigner)); emissionPhaseObjectGraphVisitorFactories.Remove(typeof(AnchorAssigningObjectGraphVisitor)); return this; } [Obsolete("The default behavior is now to always emit default values, thefore calling this method has no effect. This behavior is now controlled by ConfigureDefaultValuesHandling.", true)] public StaticSerializerBuilder EmitDefaults() { return ConfigureDefaultValuesHandling(DefaultValuesHandling.Preserve); } public StaticSerializerBuilder ConfigureDefaultValuesHandling(DefaultValuesHandling configuration) { defaultValuesHandlingConfiguration = configuration; return this; } public StaticSerializerBuilder JsonCompatible() { emitterSettings = emitterSettings.WithMaxSimpleKeyLength(int.MaxValue).WithoutAnchorName().WithUtf16SurrogatePairs(); return WithTypeConverter(new YamlDotNet.Serialization.Converters.GuidConverter(jsonCompatible: true), delegate(IRegistrationLocationSelectionSyntax w) { w.InsteadOf(); }).WithTypeConverter(new DateTime8601Converter(ScalarStyle.DoubleQuoted)).WithEventEmitter((IEventEmitter inner) => new JsonEventEmitter(inner, yamlFormatter, enumNamingConvention, BuildTypeInspector()), delegate(IRegistrationLocationSelectionSyntax loc) { loc.InsteadOf(); }); } public StaticSerializerBuilder WithNewLine(string newLine) { emitterSettings = emitterSettings.WithNewLine(newLine); return this; } public StaticSerializerBuilder WithPreProcessingPhaseObjectGraphVisitor(TObjectGraphVisitor objectGraphVisitor) where TObjectGraphVisitor : IObjectGraphVisitor { return WithPreProcessingPhaseObjectGraphVisitor(objectGraphVisitor, delegate(IRegistrationLocationSelectionSyntax> w) { w.OnTop(); }); } public StaticSerializerBuilder WithPreProcessingPhaseObjectGraphVisitor(Func, TObjectGraphVisitor> objectGraphVisitorFactory) where TObjectGraphVisitor : IObjectGraphVisitor { return WithPreProcessingPhaseObjectGraphVisitor(objectGraphVisitorFactory, delegate(IRegistrationLocationSelectionSyntax> w) { w.OnTop(); }); } public StaticSerializerBuilder WithPreProcessingPhaseObjectGraphVisitor(TObjectGraphVisitor objectGraphVisitor, Action>> where) where TObjectGraphVisitor : IObjectGraphVisitor { TObjectGraphVisitor objectGraphVisitor2 = objectGraphVisitor; if (objectGraphVisitor2 == null) { throw new ArgumentNullException("objectGraphVisitor"); } if (where == null) { throw new ArgumentNullException("where"); } where(preProcessingPhaseObjectGraphVisitorFactories.CreateRegistrationLocationSelector(typeof(TObjectGraphVisitor), (IEnumerable _) => objectGraphVisitor2)); return this; } public StaticSerializerBuilder WithPreProcessingPhaseObjectGraphVisitor(Func, TObjectGraphVisitor> objectGraphVisitorFactory, Action>> where) where TObjectGraphVisitor : IObjectGraphVisitor { Func, TObjectGraphVisitor> objectGraphVisitorFactory2 = objectGraphVisitorFactory; if (objectGraphVisitorFactory2 == null) { throw new ArgumentNullException("objectGraphVisitorFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(preProcessingPhaseObjectGraphVisitorFactories.CreateRegistrationLocationSelector(typeof(TObjectGraphVisitor), (IEnumerable typeConverters) => objectGraphVisitorFactory2(typeConverters))); return this; } public StaticSerializerBuilder WithPreProcessingPhaseObjectGraphVisitor(WrapperFactory, TObjectGraphVisitor> objectGraphVisitorFactory, Action>> where) where TObjectGraphVisitor : IObjectGraphVisitor { WrapperFactory, TObjectGraphVisitor> objectGraphVisitorFactory2 = objectGraphVisitorFactory; if (objectGraphVisitorFactory2 == null) { throw new ArgumentNullException("objectGraphVisitorFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(preProcessingPhaseObjectGraphVisitorFactories.CreateTrackingRegistrationLocationSelector(typeof(TObjectGraphVisitor), (IObjectGraphVisitor wrapped, IEnumerable _) => objectGraphVisitorFactory2(wrapped))); return this; } public StaticSerializerBuilder WithPreProcessingPhaseObjectGraphVisitor(WrapperFactory, IObjectGraphVisitor, TObjectGraphVisitor> objectGraphVisitorFactory, Action>> where) where TObjectGraphVisitor : IObjectGraphVisitor { WrapperFactory, IObjectGraphVisitor, TObjectGraphVisitor> objectGraphVisitorFactory2 = objectGraphVisitorFactory; if (objectGraphVisitorFactory2 == null) { throw new ArgumentNullException("objectGraphVisitorFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(preProcessingPhaseObjectGraphVisitorFactories.CreateTrackingRegistrationLocationSelector(typeof(TObjectGraphVisitor), (IObjectGraphVisitor wrapped, IEnumerable typeConverters) => objectGraphVisitorFactory2(wrapped, typeConverters))); return this; } public StaticSerializerBuilder WithoutPreProcessingPhaseObjectGraphVisitor() where TObjectGraphVisitor : IObjectGraphVisitor { return WithoutPreProcessingPhaseObjectGraphVisitor(typeof(TObjectGraphVisitor)); } public StaticSerializerBuilder WithoutPreProcessingPhaseObjectGraphVisitor(Type objectGraphVisitorType) { if (objectGraphVisitorType == null) { throw new ArgumentNullException("objectGraphVisitorType"); } preProcessingPhaseObjectGraphVisitorFactories.Remove(objectGraphVisitorType); return this; } public StaticSerializerBuilder WithObjectGraphTraversalStrategyFactory(ObjectGraphTraversalStrategyFactory objectGraphTraversalStrategyFactory) { this.objectGraphTraversalStrategyFactory = objectGraphTraversalStrategyFactory; return this; } public StaticSerializerBuilder WithEmissionPhaseObjectGraphVisitor(Func objectGraphVisitorFactory) where TObjectGraphVisitor : IObjectGraphVisitor { return WithEmissionPhaseObjectGraphVisitor(objectGraphVisitorFactory, delegate(IRegistrationLocationSelectionSyntax> w) { w.OnTop(); }); } public StaticSerializerBuilder WithEmissionPhaseObjectGraphVisitor(Func objectGraphVisitorFactory, Action>> where) where TObjectGraphVisitor : IObjectGraphVisitor { Func objectGraphVisitorFactory2 = objectGraphVisitorFactory; if (objectGraphVisitorFactory2 == null) { throw new ArgumentNullException("objectGraphVisitorFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(emissionPhaseObjectGraphVisitorFactories.CreateRegistrationLocationSelector(typeof(TObjectGraphVisitor), (EmissionPhaseObjectGraphVisitorArgs args) => objectGraphVisitorFactory2(args))); return this; } public StaticSerializerBuilder WithEmissionPhaseObjectGraphVisitor(WrapperFactory, TObjectGraphVisitor> objectGraphVisitorFactory, Action>> where) where TObjectGraphVisitor : IObjectGraphVisitor { WrapperFactory, TObjectGraphVisitor> objectGraphVisitorFactory2 = objectGraphVisitorFactory; if (objectGraphVisitorFactory2 == null) { throw new ArgumentNullException("objectGraphVisitorFactory"); } if (where == null) { throw new ArgumentNullException("where"); } where(emissionPhaseObjectGraphVisitorFactories.CreateTrackingRegistrationLocationSelector(typeof(TObjectGraphVisitor), (IObjectGraphVisitor wrapped, EmissionPhaseObjectGraphVisitorArgs args) => objectGraphVisitorFactory2(wrapped, args))); return this; } public StaticSerializerBuilder WithoutEmissionPhaseObjectGraphVisitor() where TObjectGraphVisitor : IObjectGraphVisitor { return WithoutEmissionPhaseObjectGraphVisitor(typeof(TObjectGraphVisitor)); } public StaticSerializerBuilder WithoutEmissionPhaseObjectGraphVisitor(Type objectGraphVisitorType) { if (objectGraphVisitorType == null) { throw new ArgumentNullException("objectGraphVisitorType"); } emissionPhaseObjectGraphVisitorFactories.Remove(objectGraphVisitorType); return this; } public StaticSerializerBuilder WithIndentedSequences() { emitterSettings = emitterSettings.WithIndentedSequences(); return this; } public ISerializer Build() { return Serializer.FromValueSerializer(BuildValueSerializer(), emitterSettings); } public IValueSerializer BuildValueSerializer() { IEnumerable typeConverters = BuildTypeConverters(); ITypeInspector typeInspector = BuildTypeInspector(); IObjectGraphTraversalStrategy traversalStrategy = objectGraphTraversalStrategyFactory(typeInspector, typeResolver, typeConverters, maximumRecursion); IEventEmitter eventEmitter = eventEmitterFactories.BuildComponentChain(new WriterEventEmitter()); return new ValueSerializer(traversalStrategy, eventEmitter, typeConverters, preProcessingPhaseObjectGraphVisitorFactories.Clone(), emissionPhaseObjectGraphVisitorFactories.Clone()); } public ITypeInspector BuildTypeInspector() { ITypeInspector typeInspector = context.GetTypeInspector(); return typeInspectorFactories.BuildComponentChain(typeInspector); } } internal sealed class StreamFragment : IYamlConvertible { private readonly List events = new List(); public IList Events => events; void IYamlConvertible.Read(IParser parser, Type expectedType, ObjectDeserializer nestedObjectDeserializer) { events.Clear(); int num = 0; do { if (!parser.MoveNext()) { throw new InvalidOperationException("The parser has reached the end before deserialization completed."); } ParsingEvent current = parser.Current; events.Add(current); num += current.NestingIncrease; } while (num > 0); } void IYamlConvertible.Write(IEmitter emitter, ObjectSerializer nestedObjectSerializer) { foreach (ParsingEvent @event in events) { emitter.Emit(@event); } } } internal sealed class TagMappings { private readonly Dictionary mappings; public TagMappings() { mappings = new Dictionary(); } public TagMappings(IDictionary mappings) { this.mappings = new Dictionary(mappings); } public void Add(string tag, Type mapping) { mappings.Add(tag, mapping); } internal Type? GetMapping(string tag) { if (!mappings.TryGetValue(tag, out Type value)) { return null; } return value; } } internal sealed class YamlAttributeOverrides { private readonly struct AttributeKey { public readonly Type AttributeType; public readonly string PropertyName; public AttributeKey(Type attributeType, string propertyName) { AttributeType = attributeType; PropertyName = propertyName; } public override bool Equals(object? obj) { if (obj is AttributeKey attributeKey && AttributeType.Equals(attributeKey.AttributeType)) { return PropertyName.Equals(attributeKey.PropertyName); } return false; } public override int GetHashCode() { return YamlDotNet.Core.HashCode.CombineHashCodes(AttributeType.GetHashCode(), PropertyName.GetHashCode()); } } private sealed class AttributeMapping { public readonly Type RegisteredType; public readonly Attribute Attribute; public AttributeMapping(Type registeredType, Attribute attribute) { RegisteredType = registeredType; Attribute = attribute; } public override bool Equals(object? obj) { if (obj is AttributeMapping attributeMapping && RegisteredType.Equals(attributeMapping.RegisteredType)) { return Attribute.Equals(attributeMapping.Attribute); } return false; } public override int GetHashCode() { return YamlDotNet.Core.HashCode.CombineHashCodes(RegisteredType.GetHashCode(), Attribute.GetHashCode()); } public int Matches(Type matchType) { int num = 0; Type type = matchType; while (type != null) { num++; if (type == RegisteredType) { return num; } type = type.BaseType(); } if (matchType.GetInterfaces().Contains(RegisteredType)) { return num; } return 0; } } private readonly Dictionary> overrides = new Dictionary>(); [return: MaybeNull] public T GetAttribute(Type type, string member) where T : Attribute { if (overrides.TryGetValue(new AttributeKey(typeof(T), member), out List value)) { int num = 0; AttributeMapping attributeMapping = null; foreach (AttributeMapping item in value) { int num2 = item.Matches(type); if (num2 > num) { num = num2; attributeMapping = item; } } if (num > 0) { return (T)attributeMapping.Attribute; } } return null; } public void Add(Type type, string member, Attribute attribute) { AttributeMapping item = new AttributeMapping(type, attribute); AttributeKey key = new AttributeKey(attribute.GetType(), member); if (!overrides.TryGetValue(key, out List value)) { value = new List(); overrides.Add(key, value); } else if (value.Contains(item)) { throw new InvalidOperationException($"Attribute ({attribute}) already set for Type {type.FullName}, Member {member}"); } value.Add(item); } public YamlAttributeOverrides Clone() { YamlAttributeOverrides yamlAttributeOverrides = new YamlAttributeOverrides(); foreach (KeyValuePair> @override in overrides) { foreach (AttributeMapping item in @override.Value) { yamlAttributeOverrides.Add(item.RegisteredType, @override.Key.PropertyName, item.Attribute); } } return yamlAttributeOverrides; } public void Add(Expression> propertyAccessor, Attribute attribute) { PropertyInfo propertyInfo = propertyAccessor.AsProperty(); Add(typeof(TClass), propertyInfo.Name, attribute); } } internal sealed class YamlAttributeOverridesInspector : ReflectionTypeInspector { public sealed class OverridePropertyDescriptor : IPropertyDescriptor { private readonly IPropertyDescriptor baseDescriptor; private readonly YamlAttributeOverrides overrides; private readonly Type classType; public string Name => baseDescriptor.Name; public bool Required => baseDescriptor.Required; public bool AllowNulls => baseDescriptor.AllowNulls; public bool CanWrite => baseDescriptor.CanWrite; public Type Type => baseDescriptor.Type; public Type? TypeOverride { get { return baseDescriptor.TypeOverride; } set { baseDescriptor.TypeOverride = value; } } public Type? ConverterType => GetCustomAttribute()?.ConverterType ?? baseDescriptor.ConverterType; public int Order { get { return baseDescriptor.Order; } set { baseDescriptor.Order = value; } } public ScalarStyle ScalarStyle { get { return baseDescriptor.ScalarStyle; } set { baseDescriptor.ScalarStyle = value; } } public OverridePropertyDescriptor(IPropertyDescriptor baseDescriptor, YamlAttributeOverrides overrides, Type classType) { this.baseDescriptor = baseDescriptor; this.overrides = overrides; this.classType = classType; } public void Write(object target, object? value) { baseDescriptor.Write(target, value); } public T? GetCustomAttribute() where T : Attribute { T attribute = overrides.GetAttribute(classType, Name); return attribute ?? baseDescriptor.GetCustomAttribute(); } public IObjectDescriptor Read(object target) { return baseDescriptor.Read(target); } } private readonly ITypeInspector innerTypeDescriptor; private readonly YamlAttributeOverrides overrides; public YamlAttributeOverridesInspector(ITypeInspector innerTypeDescriptor, YamlAttributeOverrides overrides) { this.innerTypeDescriptor = innerTypeDescriptor; this.overrides = overrides; } public override IEnumerable GetProperties(Type type, object? container) { Type type2 = type; IEnumerable enumerable = innerTypeDescriptor.GetProperties(type2, container); if (overrides != null) { enumerable = enumerable.Select((Func)((IPropertyDescriptor p) => new OverridePropertyDescriptor(p, overrides, type2))); } return enumerable; } } internal sealed class YamlAttributesTypeInspector : TypeInspectorSkeleton { private readonly ITypeInspector innerTypeDescriptor; public YamlAttributesTypeInspector(ITypeInspector innerTypeDescriptor) { this.innerTypeDescriptor = innerTypeDescriptor; } public override string GetEnumName(Type enumType, string name) { return innerTypeDescriptor.GetEnumName(enumType, name); } public override string GetEnumValue(object enumValue) { return innerTypeDescriptor.GetEnumValue(enumValue); } public override IEnumerable GetProperties(Type type, object? container) { return from p in (from p in innerTypeDescriptor.GetProperties(type, container) where p.GetCustomAttribute() == null select p).Select((Func)delegate(IPropertyDescriptor p) { PropertyDescriptor propertyDescriptor = new PropertyDescriptor(p); YamlMemberAttribute customAttribute = p.GetCustomAttribute(); if (customAttribute != null) { if (customAttribute.SerializeAs != null) { propertyDescriptor.TypeOverride = customAttribute.SerializeAs; } propertyDescriptor.Order = customAttribute.Order; propertyDescriptor.ScalarStyle = customAttribute.ScalarStyle; if (customAttribute.Alias != null) { propertyDescriptor.Name = customAttribute.Alias; } } return propertyDescriptor; }) orderby p.Order select p; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)] internal sealed class YamlConverterAttribute : Attribute { public Type ConverterType { get; } public YamlConverterAttribute(Type converterType) { ConverterType = converterType; } } internal class YamlFormatter { public static YamlFormatter Default { get; } = new YamlFormatter(); public NumberFormatInfo NumberFormat { get; set; } = new NumberFormatInfo { CurrencyDecimalSeparator = ".", CurrencyGroupSeparator = "_", CurrencyGroupSizes = new int[1] { 3 }, CurrencySymbol = string.Empty, CurrencyDecimalDigits = 99, NumberDecimalSeparator = ".", NumberGroupSeparator = "_", NumberGroupSizes = new int[1] { 3 }, NumberDecimalDigits = 99, NaNSymbol = ".nan", PositiveInfinitySymbol = ".inf", NegativeInfinitySymbol = "-.inf" }; public virtual Func FormatEnum { get; set; } = delegate(object value, ITypeInspector typeInspector, INamingConvention enumNamingConvention) { string empty = string.Empty; empty = ((value != null) ? typeInspector.GetEnumValue(value) : string.Empty); return enumNamingConvention.Apply(empty); }; public virtual Func PotentiallyQuoteEnums { get; set; } = (object _) => true; public string FormatNumber(object number) { return Convert.ToString(number, NumberFormat); } public string FormatNumber(double number) { return number.ToString("G", NumberFormat); } public string FormatNumber(float number) { return number.ToString("G", NumberFormat); } public string FormatBoolean(object boolean) { if (!boolean.Equals(true)) { return "false"; } return "true"; } public string FormatDateTime(object dateTime) { return ((DateTime)dateTime).ToString("o", CultureInfo.InvariantCulture); } public string FormatTimeSpan(object timeSpan) { return ((TimeSpan)timeSpan).ToString(); } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] internal sealed class YamlIgnoreAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] internal sealed class YamlMemberAttribute : Attribute { private DefaultValuesHandling? defaultValuesHandling; public string? Description { get; set; } public Type? SerializeAs { get; set; } public int Order { get; set; } public string? Alias { get; set; } public bool ApplyNamingConventions { get; set; } public ScalarStyle ScalarStyle { get; set; } public DefaultValuesHandling DefaultValuesHandling { get { return defaultValuesHandling.GetValueOrDefault(); } set { defaultValuesHandling = value; } } public bool IsDefaultValuesHandlingSpecified => defaultValuesHandling.HasValue; public YamlMemberAttribute() { ScalarStyle = ScalarStyle.Any; ApplyNamingConventions = true; } public YamlMemberAttribute(Type serializeAs) : this() { SerializeAs = serializeAs ?? throw new ArgumentNullException("serializeAs"); } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum, Inherited = false, AllowMultiple = true)] internal sealed class YamlSerializableAttribute : Attribute { public YamlSerializableAttribute() { } public YamlSerializableAttribute(Type serializableType) { } } [AttributeUsage(AttributeTargets.Class)] internal sealed class YamlStaticContextAttribute : Attribute { } } namespace YamlDotNet.Serialization.ValueDeserializers { internal sealed class AliasValueDeserializer : IValueDeserializer { private sealed class AliasState : Dictionary, IPostDeserializationCallback { public void OnDeserialization() { foreach (ValuePromise value in base.Values) { if (!value.HasValue) { YamlDotNet.Core.Events.AnchorAlias alias = value.Alias; Mark start = alias.Start; Mark end = alias.End; throw new AnchorNotFoundException(in start, in end, $"Anchor '{alias.Value}' not found"); } } } } private sealed class ValuePromise : IValuePromise { private object? value; public readonly YamlDotNet.Core.Events.AnchorAlias? Alias; public bool HasValue { get; private set; } public object? Value { get { if (!HasValue) { throw new InvalidOperationException("Value not set"); } return value; } set { if (HasValue) { throw new InvalidOperationException("Value already set"); } HasValue = true; this.value = value; this.ValueAvailable?.Invoke(value); } } public event Action? ValueAvailable; public ValuePromise(YamlDotNet.Core.Events.AnchorAlias alias) { Alias = alias; } public ValuePromise(object? value) { HasValue = true; this.value = value; } } private readonly IValueDeserializer innerDeserializer; public AliasValueDeserializer(IValueDeserializer innerDeserializer) { this.innerDeserializer = innerDeserializer ?? throw new ArgumentNullException("innerDeserializer"); } public object? DeserializeValue(IParser parser, Type expectedType, SerializerState state, IValueDeserializer nestedObjectDeserializer) { if (parser.TryConsume(out var @event)) { AliasState aliasState = state.Get(); if (!aliasState.TryGetValue(@event.Value, out ValuePromise value)) { Mark start = @event.Start; Mark end = @event.End; throw new AnchorNotFoundException(in start, in end, $"Alias ${@event.Value} cannot precede anchor declaration"); } if (!value.HasValue) { return value; } return value.Value; } AnchorName anchorName = AnchorName.Empty; if (parser.Accept(out var event2) && !event2.Anchor.IsEmpty) { anchorName = event2.Anchor; AliasState aliasState2 = state.Get(); if (!aliasState2.ContainsKey(anchorName)) { aliasState2[anchorName] = new ValuePromise(new YamlDotNet.Core.Events.AnchorAlias(anchorName)); } } object obj = innerDeserializer.DeserializeValue(parser, expectedType, state, nestedObjectDeserializer); if (!anchorName.IsEmpty) { AliasState aliasState3 = state.Get(); if (!aliasState3.TryGetValue(anchorName, out ValuePromise value2)) { aliasState3.Add(anchorName, new ValuePromise(obj)); } else if (!value2.HasValue) { value2.Value = obj; } else { aliasState3[anchorName] = new ValuePromise(obj); } } return obj; } } internal sealed class NodeValueDeserializer : IValueDeserializer { private readonly IList deserializers; private readonly IList typeResolvers; private readonly ITypeConverter typeConverter; private readonly INamingConvention enumNamingConvention; private readonly ITypeInspector typeInspector; public NodeValueDeserializer(IList deserializers, IList typeResolvers, ITypeConverter typeConverter, INamingConvention enumNamingConvention, ITypeInspector typeInspector) { this.deserializers = deserializers ?? throw new ArgumentNullException("deserializers"); this.typeResolvers = typeResolvers ?? throw new ArgumentNullException("typeResolvers"); this.typeConverter = typeConverter ?? throw new ArgumentNullException("typeConverter"); this.enumNamingConvention = enumNamingConvention ?? throw new ArgumentNullException("enumNamingConvention"); this.typeInspector = typeInspector; } public object? DeserializeValue(IParser parser, Type expectedType, SerializerState state, IValueDeserializer nestedObjectDeserializer) { IParser parser2 = parser; SerializerState state2 = state; IValueDeserializer nestedObjectDeserializer2 = nestedObjectDeserializer; parser2.Accept(out var @event); Type typeFromEvent = GetTypeFromEvent(@event, expectedType); ObjectDeserializer rootDeserializer = (Type x) => DeserializeValue(parser2, x, state2, nestedObjectDeserializer2); Mark start; Mark end; try { foreach (INodeDeserializer deserializer in deserializers) { if (deserializer.Deserialize(parser2, typeFromEvent, (IParser r, Type t) => nestedObjectDeserializer2.DeserializeValue(r, t, state2, nestedObjectDeserializer2), out object value, rootDeserializer)) { return typeConverter.ChangeType(value, expectedType, enumNamingConvention, typeInspector); } } } catch (YamlException) { throw; } catch (Exception innerException) { start = @event?.Start ?? Mark.Empty; end = @event?.End ?? Mark.Empty; throw new YamlException(in start, in end, "Exception during deserialization", innerException); } start = @event?.Start ?? Mark.Empty; end = @event?.End ?? Mark.Empty; throw new YamlException(in start, in end, "No node deserializer was able to deserialize the node into type " + expectedType.AssemblyQualifiedName); } private Type GetTypeFromEvent(NodeEvent? nodeEvent, Type currentType) { foreach (INodeTypeResolver typeResolver in typeResolvers) { if (typeResolver.Resolve(nodeEvent, ref currentType)) { break; } } return currentType; } } } namespace YamlDotNet.Serialization.Utilities { internal interface IPostDeserializationCallback { void OnDeserialization(); } internal interface ITypeConverter { object? ChangeType(object? value, Type expectedType, INamingConvention enumNamingConvention, ITypeInspector typeInspector); } internal class NullTypeConverter : ITypeConverter { public object? ChangeType(object? value, Type expectedType, INamingConvention enumNamingConvention, ITypeInspector typeInspector) { return value; } } internal sealed class ObjectAnchorCollection { private readonly Dictionary objectsByAnchor = new Dictionary(); private readonly Dictionary anchorsByObject = new Dictionary(); public object this[string anchor] { get { if (objectsByAnchor.TryGetValue(anchor, out object value)) { return value; } throw new AnchorNotFoundException("The anchor '" + anchor + "' does not exists"); } } public void Add(string anchor, object @object) { objectsByAnchor.Add(anchor, @object); if (@object != null) { anchorsByObject.Add(@object, anchor); } } public bool TryGetAnchor(object @object, [MaybeNullWhen(false)] out string? anchor) { return anchorsByObject.TryGetValue(@object, out anchor); } } internal class ReflectionTypeConverter : ITypeConverter { public object? ChangeType(object? value, Type expectedType, ITypeInspector typeInspector) { return ChangeType(value, expectedType, NullNamingConvention.Instance, typeInspector); } public object? ChangeType(object? value, Type expectedType, INamingConvention enumNamingConvention, ITypeInspector typeInspector) { return TypeConverter.ChangeType(value, expectedType, enumNamingConvention, typeInspector); } } internal sealed class SerializerState : IDisposable { private readonly Dictionary items = new Dictionary(); public T Get() where T : class, new() { if (!items.TryGetValue(typeof(T), out object value)) { value = new T(); items.Add(typeof(T), value); } return (T)value; } public void OnDeserialization() { foreach (IPostDeserializationCallback item in items.Values.OfType()) { item.OnDeserialization(); } } public void Dispose() { foreach (IDisposable item in items.Values.OfType()) { item.Dispose(); } } } internal static class StringExtensions { private static string ToCamelOrPascalCase(string str, Func firstLetterTransform) { string text = Regex.Replace(str, "([_\\-])(?[a-z])", (Match match) => match.Groups["char"].Value.ToUpperInvariant(), RegexOptions.IgnoreCase); return firstLetterTransform(text[0]) + text.Substring(1); } public static string ToCamelCase(this string str) { return ToCamelOrPascalCase(str, char.ToLowerInvariant); } public static string ToPascalCase(this string str) { return ToCamelOrPascalCase(str, char.ToUpperInvariant); } public static string FromCamelCase(this string str, string separator) { string separator2 = separator; str = char.ToLower(str[0], CultureInfo.InvariantCulture) + str.Substring(1); str = Regex.Replace(str.ToCamelCase(), "(?[A-Z])", (Match match) => separator2 + match.Groups["char"].Value.ToLowerInvariant()); return str; } } internal static class TypeConverter { public static T ChangeType(object? value, INamingConvention enumNamingConvention, ITypeInspector typeInspector) { return (T)ChangeType(value, typeof(T), enumNamingConvention, typeInspector); } public static object? ChangeType(object? value, Type destinationType, INamingConvention enumNamingConvention, ITypeInspector typeInspector) { return ChangeType(value, destinationType, CultureInfo.InvariantCulture, enumNamingConvention, typeInspector); } public static object? ChangeType(object? value, Type destinationType, IFormatProvider provider, INamingConvention enumNamingConvention, ITypeInspector typeInspector) { return ChangeType(value, destinationType, new CultureInfoAdapter(CultureInfo.CurrentCulture, provider), enumNamingConvention, typeInspector); } public static object? ChangeType(object? value, Type destinationType, CultureInfo culture, INamingConvention enumNamingConvention, ITypeInspector typeInspector) { if (value == null || value.IsDbNull()) { if (!destinationType.IsValueType()) { return null; } return Activator.CreateInstance(destinationType); } Type type = value.GetType(); if (destinationType == type || destinationType.IsAssignableFrom(type)) { return value; } if (destinationType.IsGenericType()) { Type genericTypeDefinition = destinationType.GetGenericTypeDefinition(); if (genericTypeDefinition == typeof(Nullable<>) || FsharpHelper.IsOptionType(genericTypeDefinition)) { Type destinationType2 = destinationType.GetGenericArguments()[0]; object obj = ChangeType(value, destinationType2, culture, enumNamingConvention, typeInspector); return Activator.CreateInstance(destinationType, obj); } } if (destinationType.IsEnum()) { object result = value; if (value is string value2) { string name = enumNamingConvention.Reverse(value2); name = typeInspector.GetEnumName(destinationType, name); result = Enum.Parse(destinationType, name, ignoreCase: true); } return result; } if (destinationType == typeof(bool)) { if ("0".Equals(value)) { return false; } if ("1".Equals(value)) { return true; } } System.ComponentModel.TypeConverter converter = TypeDescriptor.GetConverter(type); if (converter != null && converter.CanConvertTo(destinationType)) { return converter.ConvertTo(null, culture, value, destinationType); } System.ComponentModel.TypeConverter converter2 = TypeDescriptor.GetConverter(destinationType); if (converter2 != null && converter2.CanConvertFrom(type)) { return converter2.ConvertFrom(null, culture, value); } Type[] array = new Type[2] { type, destinationType }; foreach (Type type2 in array) { foreach (MethodInfo publicStaticMethod2 in type2.GetPublicStaticMethods()) { if (!publicStaticMethod2.IsSpecialName || (!(publicStaticMethod2.Name == "op_Implicit") && !(publicStaticMethod2.Name == "op_Explicit")) || !destinationType.IsAssignableFrom(publicStaticMethod2.ReturnParameter.ParameterType)) { continue; } ParameterInfo[] parameters = publicStaticMethod2.GetParameters(); if (parameters.Length == 1 && parameters[0].ParameterType.IsAssignableFrom(type)) { try { return publicStaticMethod2.Invoke(null, new object[1] { value }); } catch (TargetInvocationException ex) { throw ex.InnerException; } } } } if (type == typeof(string)) { try { MethodInfo publicStaticMethod = destinationType.GetPublicStaticMethod("Parse", typeof(string), typeof(IFormatProvider)); if (publicStaticMethod != null) { return publicStaticMethod.Invoke(null, new object[2] { value, culture }); } publicStaticMethod = destinationType.GetPublicStaticMethod("Parse", typeof(string)); if (publicStaticMethod != null) { return publicStaticMethod.Invoke(null, new object[1] { value }); } } catch (TargetInvocationException ex2) { throw ex2.InnerException; } } if (destinationType == typeof(TimeSpan)) { return TimeSpan.Parse((string)ChangeType(value, typeof(string), CultureInfo.InvariantCulture, enumNamingConvention, typeInspector), CultureInfo.InvariantCulture); } return Convert.ChangeType(value, destinationType, CultureInfo.InvariantCulture); } public static void RegisterTypeConverter() where TConverter : System.ComponentModel.TypeConverter { if (!TypeDescriptor.GetAttributes(typeof(TConvertible)).OfType().Any((TypeConverterAttribute a) => a.ConverterTypeName == typeof(TConverter).AssemblyQualifiedName)) { TypeDescriptor.AddAttributes(typeof(TConvertible), new TypeConverterAttribute(typeof(TConverter))); } } } internal sealed class TypeConverterCache { private readonly IYamlTypeConverter[] typeConverters; private readonly ConcurrentDictionary cache = new ConcurrentDictionary(); public TypeConverterCache(IEnumerable? typeConverters) : this(typeConverters?.ToArray() ?? Array.Empty()) { } public TypeConverterCache(IYamlTypeConverter[] typeConverters) { this.typeConverters = typeConverters; } public bool TryGetConverterForType(Type type, [NotNullWhen(true)] out IYamlTypeConverter? typeConverter) { (bool, IYamlTypeConverter) orAdd = DictionaryExtensions.GetOrAdd(cache, type, (Type t, IYamlTypeConverter[] tc) => LookupTypeConverter(t, tc), typeConverters); typeConverter = orAdd.Item2; return orAdd.Item1; } public IYamlTypeConverter GetConverterByType(Type converter) { IYamlTypeConverter[] array = typeConverters; foreach (IYamlTypeConverter yamlTypeConverter in array) { if (yamlTypeConverter.GetType() == converter) { return yamlTypeConverter; } } throw new ArgumentException("IYamlTypeConverter of type " + converter.FullName + " not found", "converter"); } private static (bool HasMatch, IYamlTypeConverter? TypeConverter) LookupTypeConverter(Type type, IYamlTypeConverter[] typeConverters) { foreach (IYamlTypeConverter yamlTypeConverter in typeConverters) { if (yamlTypeConverter.Accepts(type)) { return (true, yamlTypeConverter); } } return (false, null); } } } namespace YamlDotNet.Serialization.TypeResolvers { internal sealed class DynamicTypeResolver : ITypeResolver { public Type Resolve(Type staticType, object? actualValue) { if (actualValue == null) { return staticType; } return actualValue.GetType(); } } internal class StaticTypeResolver : ITypeResolver { public virtual Type Resolve(Type staticType, object? actualValue) { if (actualValue != null) { if (actualValue.GetType().IsEnum) { return staticType; } switch (actualValue.GetType().GetTypeCode()) { case TypeCode.Boolean: return typeof(bool); case TypeCode.Char: return typeof(char); case TypeCode.SByte: return typeof(sbyte); case TypeCode.Byte: return typeof(byte); case TypeCode.Int16: return typeof(short); case TypeCode.UInt16: return typeof(ushort); case TypeCode.Int32: return typeof(int); case TypeCode.UInt32: return typeof(uint); case TypeCode.Int64: return typeof(long); case TypeCode.UInt64: return typeof(ulong); case TypeCode.Single: return typeof(float); case TypeCode.Double: return typeof(double); case TypeCode.Decimal: return typeof(decimal); case TypeCode.String: return typeof(string); case TypeCode.DateTime: return typeof(DateTime); } } return staticType; } } } namespace YamlDotNet.Serialization.TypeInspectors { internal class CachedTypeInspector : TypeInspectorSkeleton { private readonly ITypeInspector innerTypeDescriptor; private readonly ConcurrentDictionary> cache = new ConcurrentDictionary>(); private readonly ConcurrentDictionary> enumNameCache = new ConcurrentDictionary>(); private readonly ConcurrentDictionary enumValueCache = new ConcurrentDictionary(); public CachedTypeInspector(ITypeInspector innerTypeDescriptor) { this.innerTypeDescriptor = innerTypeDescriptor ?? throw new ArgumentNullException("innerTypeDescriptor"); } public override string GetEnumName(Type enumType, string name) { ConcurrentDictionary orAdd = enumNameCache.GetOrAdd(enumType, (Type _) => new ConcurrentDictionary()); return DictionaryExtensions.GetOrAdd(orAdd, name, delegate(string n, (Type enumType, ITypeInspector innerTypeDescriptor) context) { var (enumType2, typeInspector) = context; return typeInspector.GetEnumName(enumType2, n); }, (enumType, innerTypeDescriptor)); } public override string GetEnumValue(object enumValue) { return DictionaryExtensions.GetOrAdd(enumValueCache, enumValue, delegate(object _, (object enumValue, ITypeInspector innerTypeDescriptor) context) { var (enumValue2, typeInspector) = context; return typeInspector.GetEnumValue(enumValue2); }, (enumValue, innerTypeDescriptor)); } public override IEnumerable GetProperties(Type type, object? container) { return DictionaryExtensions.GetOrAdd(cache, type, delegate(Type t, (object container, ITypeInspector innerTypeDescriptor) context) { var (container2, typeInspector) = context; return typeInspector.GetProperties(t, container2).ToList(); }, (container, innerTypeDescriptor)); } } internal class CompositeTypeInspector : TypeInspectorSkeleton { private readonly IEnumerable typeInspectors; public CompositeTypeInspector(params ITypeInspector[] typeInspectors) : this((IEnumerable)typeInspectors) { } public CompositeTypeInspector(IEnumerable typeInspectors) { this.typeInspectors = typeInspectors?.ToList() ?? throw new ArgumentNullException("typeInspectors"); } public override string GetEnumName(Type enumType, string name) { foreach (ITypeInspector typeInspector in typeInspectors) { try { return typeInspector.GetEnumName(enumType, name); } catch { } } throw new ArgumentOutOfRangeException("enumType,name", "Name not found on enum type"); } public override string GetEnumValue(object enumValue) { if (enumValue == null) { throw new ArgumentNullException("enumValue"); } foreach (ITypeInspector typeInspector in typeInspectors) { try { return typeInspector.GetEnumValue(enumValue); } catch { } } throw new ArgumentOutOfRangeException("enumValue", $"Value not found for ({enumValue})"); } public override IEnumerable GetProperties(Type type, object? container) { Type type2 = type; object container2 = container; return typeInspectors.SelectMany((ITypeInspector i) => i.GetProperties(type2, container2)); } } internal class NamingConventionTypeInspector : TypeInspectorSkeleton { private readonly ITypeInspector innerTypeDescriptor; private readonly INamingConvention namingConvention; public NamingConventionTypeInspector(ITypeInspector innerTypeDescriptor, INamingConvention namingConvention) { this.innerTypeDescriptor = innerTypeDescriptor ?? throw new ArgumentNullException("innerTypeDescriptor"); this.namingConvention = namingConvention ?? throw new ArgumentNullException("namingConvention"); } public override string GetEnumName(Type enumType, string name) { return innerTypeDescriptor.GetEnumName(enumType, name); } public override string GetEnumValue(object enumValue) { return innerTypeDescriptor.GetEnumValue(enumValue); } public override IEnumerable GetProperties(Type type, object? container) { return innerTypeDescriptor.GetProperties(type, container).Select(delegate(IPropertyDescriptor p) { YamlMemberAttribute customAttribute = p.GetCustomAttribute(); return (customAttribute != null && !customAttribute.ApplyNamingConventions) ? p : new PropertyDescriptor(p) { Name = namingConvention.Apply(p.Name) }; }); } } internal class ReadableAndWritablePropertiesTypeInspector : TypeInspectorSkeleton { private readonly ITypeInspector innerTypeDescriptor; public ReadableAndWritablePropertiesTypeInspector(ITypeInspector innerTypeDescriptor) { this.innerTypeDescriptor = innerTypeDescriptor ?? throw new ArgumentNullException("innerTypeDescriptor"); } public override string GetEnumName(Type enumType, string name) { return innerTypeDescriptor.GetEnumName(enumType, name); } public override string GetEnumValue(object enumValue) { return innerTypeDescriptor.GetEnumValue(enumValue); } public override IEnumerable GetProperties(Type type, object? container) { return from p in innerTypeDescriptor.GetProperties(type, container) where p.CanWrite select p; } } internal class ReadableFieldsTypeInspector : ReflectionTypeInspector { protected class ReflectionFieldDescriptor : IPropertyDescriptor { private readonly FieldInfo fieldInfo; private readonly ITypeResolver typeResolver; public string Name => fieldInfo.Name; public bool Required => fieldInfo.IsRequired(); public Type Type => fieldInfo.FieldType; public Type? ConverterType { get; } public Type? TypeOverride { get; set; } public bool AllowNulls => fieldInfo.AcceptsNull(); public int Order { get; set; } public bool CanWrite => !fieldInfo.IsInitOnly; public ScalarStyle ScalarStyle { get; set; } public ReflectionFieldDescriptor(FieldInfo fieldInfo, ITypeResolver typeResolver) { this.fieldInfo = fieldInfo; this.typeResolver = typeResolver; YamlConverterAttribute customAttribute = fieldInfo.GetCustomAttribute(); if (customAttribute != null) { ConverterType = customAttribute.ConverterType; } ScalarStyle = ScalarStyle.Any; } public void Write(object target, object? value) { fieldInfo.SetValue(target, value); } public T? GetCustomAttribute() where T : Attribute { object[] customAttributes = fieldInfo.GetCustomAttributes(typeof(T), inherit: true); return (T)customAttributes.FirstOrDefault(); } public IObjectDescriptor Read(object target) { object value = fieldInfo.GetValue(target); Type type = TypeOverride ?? typeResolver.Resolve(Type, value); return new ObjectDescriptor(value, type, Type, ScalarStyle); } } private readonly ITypeResolver typeResolver; public ReadableFieldsTypeInspector(ITypeResolver typeResolver) { this.typeResolver = typeResolver ?? throw new ArgumentNullException("typeResolver"); } public override IEnumerable GetProperties(Type type, object? container) { return type.GetPublicFields().Select((Func)((FieldInfo p) => new ReflectionFieldDescriptor(p, typeResolver))); } } internal class ReadablePropertiesTypeInspector : ReflectionTypeInspector { protected class ReflectionPropertyDescriptor : IPropertyDescriptor { private readonly PropertyInfo propertyInfo; private readonly ITypeResolver typeResolver; public string Name => propertyInfo.Name; public bool Required => propertyInfo.IsRequired(); public Type Type => propertyInfo.PropertyType; public Type? TypeOverride { get; set; } public Type? ConverterType { get; set; } public bool AllowNulls => propertyInfo.AcceptsNull(); public int Order { get; set; } public bool CanWrite => propertyInfo.CanWrite; public ScalarStyle ScalarStyle { get; set; } public ReflectionPropertyDescriptor(PropertyInfo propertyInfo, ITypeResolver typeResolver) { this.propertyInfo = propertyInfo ?? throw new ArgumentNullException("propertyInfo"); this.typeResolver = typeResolver ?? throw new ArgumentNullException("typeResolver"); ScalarStyle = ScalarStyle.Any; YamlConverterAttribute customAttribute = propertyInfo.GetCustomAttribute(); if (customAttribute != null) { ConverterType = customAttribute.ConverterType; } } public void Write(object target, object? value) { propertyInfo.SetValue(target, value, null); } public T? GetCustomAttribute() where T : Attribute { Attribute[] allCustomAttributes = propertyInfo.GetAllCustomAttributes(); return (T)allCustomAttributes.FirstOrDefault(); } public IObjectDescriptor Read(object target) { object obj = propertyInfo.ReadValue(target); Type type = TypeOverride ?? typeResolver.Resolve(Type, obj); return new ObjectDescriptor(obj, type, Type, ScalarStyle); } } private readonly ITypeResolver typeResolver; private readonly bool includeNonPublicProperties; public ReadablePropertiesTypeInspector(ITypeResolver typeResolver) : this(typeResolver, includeNonPublicProperties: false) { } public ReadablePropertiesTypeInspector(ITypeResolver typeResolver, bool includeNonPublicProperties) { this.typeResolver = typeResolver ?? throw new ArgumentNullException("typeResolver"); this.includeNonPublicProperties = includeNonPublicProperties; } private static bool IsValidProperty(PropertyInfo property) { if (property.CanRead) { return property.GetGetMethod(nonPublic: true).GetParameters().Length == 0; } return false; } public override IEnumerable GetProperties(Type type, object? container) { return type.GetProperties(includeNonPublicProperties).Where(IsValidProperty).Select((Func)((PropertyInfo p) => new ReflectionPropertyDescriptor(p, typeResolver))); } } internal abstract class ReflectionTypeInspector : TypeInspectorSkeleton { public override string GetEnumName(Type enumType, string name) { return name; } public override string GetEnumValue(object enumValue) { if (enumValue == null) { return string.Empty; } return enumValue.ToString(); } } internal abstract class TypeInspectorSkeleton : ITypeInspector { public abstract string GetEnumName(Type enumType, string name); public abstract string GetEnumValue(object enumValue); public abstract IEnumerable GetProperties(Type type, object? container); public IPropertyDescriptor GetProperty(Type type, object? container, string name, [MaybeNullWhen(true)] bool ignoreUnmatched, bool caseInsensitivePropertyMatching) { string name2 = name; IEnumerable enumerable = ((!caseInsensitivePropertyMatching) ? (from p in GetProperties(type, container) where p.Name == name2 select p) : (from p in GetProperties(type, container) where p.Name.Equals(name2, StringComparison.OrdinalIgnoreCase) select p)); using IEnumerator enumerator = enumerable.GetEnumerator(); if (!enumerator.MoveNext()) { if (ignoreUnmatched) { return null; } throw new SerializationException("Property '" + name2 + "' not found on type '" + type.FullName + "'."); } IPropertyDescriptor current = enumerator.Current; if (enumerator.MoveNext()) { throw new SerializationException("Multiple properties with the name/alias '" + name2 + "' already exists on type '" + type.FullName + "', maybe you're misusing YamlAlias or maybe you are using the wrong naming convention? The matching properties are: " + string.Join(", ", enumerable.Select((IPropertyDescriptor p) => p.Name).ToArray())); } return current; } } internal class WritablePropertiesTypeInspector : ReflectionTypeInspector { protected class ReflectionPropertyDescriptor : IPropertyDescriptor { private readonly PropertyInfo propertyInfo; private readonly ITypeResolver typeResolver; public string Name => propertyInfo.Name; public bool Required => propertyInfo.IsRequired(); public Type Type => propertyInfo.PropertyType; public Type? TypeOverride { get; set; } public Type? ConverterType { get; set; } public bool AllowNulls => propertyInfo.AcceptsNull(); public int Order { get; set; } public bool CanWrite => propertyInfo.CanWrite; public ScalarStyle ScalarStyle { get; set; } public ReflectionPropertyDescriptor(PropertyInfo propertyInfo, ITypeResolver typeResolver) { this.propertyInfo = propertyInfo ?? throw new ArgumentNullException("propertyInfo"); this.typeResolver = typeResolver ?? throw new ArgumentNullException("typeResolver"); ScalarStyle = ScalarStyle.Any; YamlConverterAttribute customAttribute = propertyInfo.GetCustomAttribute(); if (customAttribute != null) { ConverterType = customAttribute.ConverterType; } } public void Write(object target, object? value) { propertyInfo.SetValue(target, value, null); } public T? GetCustomAttribute() where T : Attribute { Attribute[] allCustomAttributes = propertyInfo.GetAllCustomAttributes(); return (T)allCustomAttributes.FirstOrDefault(); } public IObjectDescriptor Read(object target) { object obj = propertyInfo.ReadValue(target); Type type = TypeOverride ?? typeResolver.Resolve(Type, obj); return new ObjectDescriptor(obj, type, Type, ScalarStyle); } } private readonly ITypeResolver typeResolver; private readonly bool includeNonPublicProperties; public WritablePropertiesTypeInspector(ITypeResolver typeResolver) : this(typeResolver, includeNonPublicProperties: false) { } public WritablePropertiesTypeInspector(ITypeResolver typeResolver, bool includeNonPublicProperties) { this.typeResolver = typeResolver ?? throw new ArgumentNullException("typeResolver"); this.includeNonPublicProperties = includeNonPublicProperties; } private static bool IsValidProperty(PropertyInfo property) { if (property.CanWrite) { return property.GetSetMethod(nonPublic: true).GetParameters().Length == 1; } return false; } public override IEnumerable GetProperties(Type type, object? container) { return type.GetProperties(includeNonPublicProperties).Where(IsValidProperty).Select((Func)((PropertyInfo p) => new ReflectionPropertyDescriptor(p, typeResolver))) .ToArray(); } } } namespace YamlDotNet.Serialization.Schemas { internal sealed class FailsafeSchema { public static class Tags { public static readonly TagName Map = new TagName("tag:yaml.org,2002:map"); public static readonly TagName Seq = new TagName("tag:yaml.org,2002:seq"); public static readonly TagName Str = new TagName("tag:yaml.org,2002:str"); } } internal sealed class JsonSchema { public static class Tags { public static readonly TagName Null = new TagName("tag:yaml.org,2002:null"); public static readonly TagName Bool = new TagName("tag:yaml.org,2002:bool"); public static readonly TagName Int = new TagName("tag:yaml.org,2002:int"); public static readonly TagName Float = new TagName("tag:yaml.org,2002:float"); } } internal sealed class CoreSchema { public static class Tags { } } internal sealed class DefaultSchema { public static class Tags { public static readonly TagName Timestamp = new TagName("tag:yaml.org,2002:timestamp"); } } } namespace YamlDotNet.Serialization.ObjectGraphVisitors { internal sealed class AnchorAssigner : PreProcessingPhaseObjectGraphVisitorSkeleton, IAliasProvider { private class AnchorAssignment { public AnchorName Anchor; } private readonly Dictionary assignments = new Dictionary(); private uint nextId; public AnchorAssigner(IEnumerable typeConverters) : base(typeConverters) { } protected override bool Enter(IObjectDescriptor value, ObjectSerializer serializer) { if (value.Value != null && assignments.TryGetValue(value.Value, out AnchorAssignment value2)) { if (value2.Anchor.IsEmpty) { value2.Anchor = new AnchorName("o" + nextId.ToString(CultureInfo.InvariantCulture)); nextId++; } return false; } return true; } protected override bool EnterMapping(IObjectDescriptor key, IObjectDescriptor value, ObjectSerializer serializer) { return true; } protected override bool EnterMapping(IPropertyDescriptor key, IObjectDescriptor value, ObjectSerializer serializer) { return true; } protected override void VisitScalar(IObjectDescriptor scalar, ObjectSerializer serializer) { } protected override void VisitMappingStart(IObjectDescriptor mapping, Type keyType, Type valueType, ObjectSerializer serializer) { VisitObject(mapping); } protected override void VisitMappingEnd(IObjectDescriptor mapping, ObjectSerializer serializer) { } protected override void VisitSequenceStart(IObjectDescriptor sequence, Type elementType, ObjectSerializer serializer) { VisitObject(sequence); } protected override void VisitSequenceEnd(IObjectDescriptor sequence, ObjectSerializer serializer) { } private void VisitObject(IObjectDescriptor value) { if (value.Value != null) { assignments.Add(value.Value, new AnchorAssignment()); } } AnchorName IAliasProvider.GetAlias(object target) { if (target != null && assignments.TryGetValue(target, out AnchorAssignment value)) { return value.Anchor; } return AnchorName.Empty; } } internal sealed class AnchorAssigningObjectGraphVisitor : ChainedObjectGraphVisitor { private readonly IEventEmitter eventEmitter; private readonly IAliasProvider aliasProvider; private readonly HashSet emittedAliases = new HashSet(); public AnchorAssigningObjectGraphVisitor(IObjectGraphVisitor nextVisitor, IEventEmitter eventEmitter, IAliasProvider aliasProvider) : base(nextVisitor) { this.eventEmitter = eventEmitter; this.aliasProvider = aliasProvider; } public override bool Enter(IPropertyDescriptor? propertyDescriptor, IObjectDescriptor value, IEmitter context, ObjectSerializer serializer) { if (value.Value != null) { AnchorName alias = aliasProvider.GetAlias(value.Value); if (!alias.IsEmpty && !emittedAliases.Add(alias)) { AliasEventInfo aliasEventInfo = new AliasEventInfo(value, alias); eventEmitter.Emit(aliasEventInfo, context); return aliasEventInfo.NeedsExpansion; } } return base.Enter(propertyDescriptor, value, context, serializer); } public override void VisitMappingStart(IObjectDescriptor mapping, Type keyType, Type valueType, IEmitter context, ObjectSerializer serializer) { AnchorName alias = aliasProvider.GetAlias(mapping.NonNullValue()); eventEmitter.Emit(new MappingStartEventInfo(mapping) { Anchor = alias }, context); } public override void VisitSequenceStart(IObjectDescriptor sequence, Type elementType, IEmitter context, ObjectSerializer serializer) { AnchorName alias = aliasProvider.GetAlias(sequence.NonNullValue()); eventEmitter.Emit(new SequenceStartEventInfo(sequence) { Anchor = alias }, context); } public override void VisitScalar(IObjectDescriptor scalar, IEmitter context, ObjectSerializer serializer) { ScalarEventInfo scalarEventInfo = new ScalarEventInfo(scalar); if (scalar.Value != null) { scalarEventInfo.Anchor = aliasProvider.GetAlias(scalar.Value); } eventEmitter.Emit(scalarEventInfo, context); } } internal abstract class ChainedObjectGraphVisitor : IObjectGraphVisitor { private readonly IObjectGraphVisitor nextVisitor; protected ChainedObjectGraphVisitor(IObjectGraphVisitor nextVisitor) { this.nextVisitor = nextVisitor; } public virtual bool Enter(IPropertyDescriptor? propertyDescriptor, IObjectDescriptor value, IEmitter context, ObjectSerializer serializer) { return nextVisitor.Enter(propertyDescriptor, value, context, serializer); } public virtual bool EnterMapping(IObjectDescriptor key, IObjectDescriptor value, IEmitter context, ObjectSerializer serializer) { return nextVisitor.EnterMapping(key, value, context, serializer); } public virtual bool EnterMapping(IPropertyDescriptor key, IObjectDescriptor value, IEmitter context, ObjectSerializer serializer) { return nextVisitor.EnterMapping(key, value, context, serializer); } public virtual void VisitScalar(IObjectDescriptor scalar, IEmitter context, ObjectSerializer serializer) { nextVisitor.VisitScalar(scalar, context, serializer); } public virtual void VisitMappingStart(IObjectDescriptor mapping, Type keyType, Type valueType, IEmitter context, ObjectSerializer serializer) { nextVisitor.VisitMappingStart(mapping, keyType, valueType, context, serializer); } public virtual void VisitMappingEnd(IObjectDescriptor mapping, IEmitter context, ObjectSerializer serializer) { nextVisitor.VisitMappingEnd(mapping, context, serializer); } public virtual void VisitSequenceStart(IObjectDescriptor sequence, Type elementType, IEmitter context, ObjectSerializer serializer) { nextVisitor.VisitSequenceStart(sequence, elementType, context, serializer); } public virtual void VisitSequenceEnd(IObjectDescriptor sequence, IEmitter context, ObjectSerializer serializer) { nextVisitor.VisitSequenceEnd(sequence, context, serializer); } } internal sealed class CommentsObjectGraphVisitor : ChainedObjectGraphVisitor { public CommentsObjectGraphVisitor(IObjectGraphVisitor nextVisitor) : base(nextVisitor) { } public override bool EnterMapping(IPropertyDescriptor key, IObjectDescriptor value, IEmitter context, ObjectSerializer serializer) { YamlMemberAttribute customAttribute = key.GetCustomAttribute(); if (customAttribute != null && customAttribute.Description != null) { context.Emit(new YamlDotNet.Core.Events.Comment(customAttribute.Description, isInline: false)); } return base.EnterMapping(key, value, context, serializer); } } internal sealed class CustomSerializationObjectGraphVisitor : ChainedObjectGraphVisitor { private readonly TypeConverterCache typeConverters; private readonly ObjectSerializer nestedObjectSerializer; public CustomSerializationObjectGraphVisitor(IObjectGraphVisitor nextVisitor, IEnumerable typeConverters, ObjectSerializer nestedObjectSerializer) : base(nextVisitor) { this.typeConverters = new TypeConverterCache(typeConverters); this.nestedObjectSerializer = nestedObjectSerializer; } public override bool Enter(IPropertyDescriptor? propertyDescriptor, IObjectDescriptor value, IEmitter context, ObjectSerializer serializer) { if (propertyDescriptor?.ConverterType != null) { IYamlTypeConverter converterByType = typeConverters.GetConverterByType(propertyDescriptor.ConverterType); converterByType.WriteYaml(context, value.Value, value.Type, serializer); return false; } if (typeConverters.TryGetConverterForType(value.Type, out IYamlTypeConverter typeConverter)) { typeConverter.WriteYaml(context, value.Value, value.Type, serializer); return false; } if (value.Value is IYamlConvertible yamlConvertible) { yamlConvertible.Write(context, nestedObjectSerializer); return false; } if (value.Value is IYamlSerializable yamlSerializable) { yamlSerializable.WriteYaml(context); return false; } return base.Enter(propertyDescriptor, value, context, serializer); } } internal sealed class DefaultExclusiveObjectGraphVisitor : ChainedObjectGraphVisitor { public DefaultExclusiveObjectGraphVisitor(IObjectGraphVisitor nextVisitor) : base(nextVisitor) { } private static object? GetDefault(Type type) { if (!type.IsValueType()) { return null; } return Activator.CreateInstance(type); } public override bool EnterMapping(IObjectDescriptor key, IObjectDescriptor value, IEmitter context, ObjectSerializer serializer) { if (!object.Equals(value.Value, GetDefault(value.Type))) { return base.EnterMapping(key, value, context, serializer); } return false; } public override bool EnterMapping(IPropertyDescriptor key, IObjectDescriptor value, IEmitter context, ObjectSerializer serializer) { DefaultValueAttribute customAttribute = key.GetCustomAttribute(); object objB = ((customAttribute != null) ? customAttribute.Value : GetDefault(key.Type)); if (!object.Equals(value.Value, objB)) { return base.EnterMapping(key, value, context, serializer); } return false; } } internal sealed class DefaultValuesObjectGraphVisitor : ChainedObjectGraphVisitor { private readonly DefaultValuesHandling handling; private readonly IObjectFactory factory; public DefaultValuesObjectGraphVisitor(DefaultValuesHandling handling, IObjectGraphVisitor nextVisitor, IObjectFactory factory) : base(nextVisitor) { this.handling = handling; this.factory = factory; } private object? GetDefault(Type type) { return factory.CreatePrimitive(type); } public override bool EnterMapping(IPropertyDescriptor key, IObjectDescriptor value, IEmitter context, ObjectSerializer serializer) { DefaultValuesHandling defaultValuesHandling = handling; YamlMemberAttribute customAttribute = key.GetCustomAttribute(); if (customAttribute != null && customAttribute.IsDefaultValuesHandlingSpecified) { defaultValuesHandling = customAttribute.DefaultValuesHandling; } if ((defaultValuesHandling & DefaultValuesHandling.OmitNull) != 0 && value.Value == null) { return false; } if ((defaultValuesHandling & DefaultValuesHandling.OmitEmptyCollections) != 0 && value.Value is IEnumerable enumerable) { IEnumerator enumerator = enumerable.GetEnumerator(); bool flag = enumerator.MoveNext(); if (enumerator is IDisposable disposable) { disposable.Dispose(); } if (!flag) { return false; } } if ((defaultValuesHandling & DefaultValuesHandling.OmitDefaults) != 0) { object objB = key.GetCustomAttribute()?.Value ?? GetDefault(key.Type); if (object.Equals(value.Value, objB)) { return false; } } return base.EnterMapping(key, value, context, serializer); } } internal sealed class EmittingObjectGraphVisitor : IObjectGraphVisitor { private readonly IEventEmitter eventEmitter; public EmittingObjectGraphVisitor(IEventEmitter eventEmitter) { this.eventEmitter = eventEmitter; } bool IObjectGraphVisitor.Enter(IPropertyDescriptor? propertyDescriptor, IObjectDescriptor value, IEmitter context, ObjectSerializer serializer) { return true; } bool IObjectGraphVisitor.EnterMapping(IObjectDescriptor key, IObjectDescriptor value, IEmitter context, ObjectSerializer serializer) { return true; } bool IObjectGraphVisitor.EnterMapping(IPropertyDescriptor key, IObjectDescriptor value, IEmitter context, ObjectSerializer serializer) { return true; } void IObjectGraphVisitor.VisitScalar(IObjectDescriptor scalar, IEmitter context, ObjectSerializer serializer) { eventEmitter.Emit(new ScalarEventInfo(scalar), context); } void IObjectGraphVisitor.VisitMappingStart(IObjectDescriptor mapping, Type keyType, Type valueType, IEmitter context, ObjectSerializer serializer) { eventEmitter.Emit(new MappingStartEventInfo(mapping), context); } void IObjectGraphVisitor.VisitMappingEnd(IObjectDescriptor mapping, IEmitter context, ObjectSerializer serializer) { eventEmitter.Emit(new MappingEndEventInfo(mapping), context); } void IObjectGraphVisitor.VisitSequenceStart(IObjectDescriptor sequence, Type elementType, IEmitter context, ObjectSerializer serializer) { eventEmitter.Emit(new SequenceStartEventInfo(sequence), context); } void IObjectGraphVisitor.VisitSequenceEnd(IObjectDescriptor sequence, IEmitter context, ObjectSerializer serializer) { eventEmitter.Emit(new SequenceEndEventInfo(sequence), context); } } internal abstract class PreProcessingPhaseObjectGraphVisitorSkeleton : IObjectGraphVisitor { protected readonly IEnumerable typeConverters; private readonly TypeConverterCache typeConverterCache; public PreProcessingPhaseObjectGraphVisitorSkeleton(IEnumerable typeConverters) { typeConverterCache = new TypeConverterCache((IYamlTypeConverter[])(this.typeConverters = typeConverters?.ToArray() ?? Array.Empty())); } bool IObjectGraphVisitor.Enter(IPropertyDescriptor? propertyDescriptor, IObjectDescriptor value, Nothing context, ObjectSerializer serializer) { if (typeConverterCache.TryGetConverterForType(value.Type, out IYamlTypeConverter _)) { return false; } if (value.Value is IYamlConvertible) { return false; } if (value.Value is IYamlSerializable) { return false; } return Enter(value, serializer); } bool IObjectGraphVisitor.EnterMapping(IPropertyDescriptor key, IObjectDescriptor value, Nothing context, ObjectSerializer serializer) { return EnterMapping(key, value, serializer); } bool IObjectGraphVisitor.EnterMapping(IObjectDescriptor key, IObjectDescriptor value, Nothing context, ObjectSerializer serializer) { return EnterMapping(key, value, serializer); } void IObjectGraphVisitor.VisitMappingEnd(IObjectDescriptor mapping, Nothing context, ObjectSerializer serializer) { VisitMappingEnd(mapping, serializer); } void IObjectGraphVisitor.VisitMappingStart(IObjectDescriptor mapping, Type keyType, Type valueType, Nothing context, ObjectSerializer serializer) { VisitMappingStart(mapping, keyType, valueType, serializer); } void IObjectGraphVisitor.VisitScalar(IObjectDescriptor scalar, Nothing context, ObjectSerializer serializer) { VisitScalar(scalar, serializer); } void IObjectGraphVisitor.VisitSequenceEnd(IObjectDescriptor sequence, Nothing context, ObjectSerializer serializer) { VisitSequenceEnd(sequence, serializer); } void IObjectGraphVisitor.VisitSequenceStart(IObjectDescriptor sequence, Type elementType, Nothing context, ObjectSerializer serializer) { VisitSequenceStart(sequence, elementType, serializer); } protected abstract bool Enter(IObjectDescriptor value, ObjectSerializer serializer); protected abstract bool EnterMapping(IPropertyDescriptor key, IObjectDescriptor value, ObjectSerializer serializer); protected abstract bool EnterMapping(IObjectDescriptor key, IObjectDescriptor value, ObjectSerializer serializer); protected abstract void VisitMappingEnd(IObjectDescriptor mapping, ObjectSerializer serializer); protected abstract void VisitMappingStart(IObjectDescriptor mapping, Type keyType, Type valueType, ObjectSerializer serializer); protected abstract void VisitScalar(IObjectDescriptor scalar, ObjectSerializer serializer); protected abstract void VisitSequenceEnd(IObjectDescriptor sequence, ObjectSerializer serializer); protected abstract void VisitSequenceStart(IObjectDescriptor sequence, Type elementType, ObjectSerializer serializer); } } namespace YamlDotNet.Serialization.ObjectGraphTraversalStrategies { internal class FullObjectGraphTraversalStrategy : IObjectGraphTraversalStrategy { protected readonly struct ObjectPathSegment { public readonly object Name; public readonly IObjectDescriptor Value; public ObjectPathSegment(object name, IObjectDescriptor value) { Name = name; Value = value; } } private readonly int maxRecursion; private readonly ITypeInspector typeDescriptor; private readonly ITypeResolver typeResolver; private readonly INamingConvention namingConvention; private readonly IObjectFactory objectFactory; public FullObjectGraphTraversalStrategy(ITypeInspector typeDescriptor, ITypeResolver typeResolver, int maxRecursion, INamingConvention namingConvention, IObjectFactory objectFactory) { if (maxRecursion <= 0) { throw new ArgumentOutOfRangeException("maxRecursion", maxRecursion, "maxRecursion must be greater than 1"); } this.typeDescriptor = typeDescriptor ?? throw new ArgumentNullException("typeDescriptor"); this.typeResolver = typeResolver ?? throw new ArgumentNullException("typeResolver"); this.maxRecursion = maxRecursion; this.namingConvention = namingConvention ?? throw new ArgumentNullException("namingConvention"); this.objectFactory = objectFactory ?? throw new ArgumentNullException("objectFactory"); } void IObjectGraphTraversalStrategy.Traverse(IObjectDescriptor graph, IObjectGraphVisitor visitor, TContext context, ObjectSerializer serializer) { Traverse(null, "", graph, visitor, context, new Stack(maxRecursion), serializer); } protected virtual void Traverse(IPropertyDescriptor? propertyDescriptor, object name, IObjectDescriptor value, IObjectGraphVisitor visitor, TContext context, Stack path, ObjectSerializer serializer) { if (path.Count >= maxRecursion) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("Too much recursion when traversing the object graph."); stringBuilder.AppendLine("The path to reach this recursion was:"); Stack> stack = new Stack>(path.Count); int num = 0; foreach (ObjectPathSegment item in path) { string text = item.Name?.ToString() ?? string.Empty; num = Math.Max(num, text.Length); stack.Push(new KeyValuePair(text, item.Value.Type.FullName)); } foreach (KeyValuePair item2 in stack) { stringBuilder.Append(" -> ").Append(item2.Key.PadRight(num)).Append(" [") .Append(item2.Value) .AppendLine("]"); } throw new MaximumRecursionLevelReachedException(stringBuilder.ToString()); } if (!visitor.Enter(propertyDescriptor, value, context, serializer)) { return; } path.Push(new ObjectPathSegment(name, value)); try { TypeCode typeCode = value.Type.GetTypeCode(); switch (typeCode) { case TypeCode.Boolean: case TypeCode.Char: case TypeCode.SByte: case TypeCode.Byte: case TypeCode.Int16: case TypeCode.UInt16: case TypeCode.Int32: case TypeCode.UInt32: case TypeCode.Int64: case TypeCode.UInt64: case TypeCode.Single: case TypeCode.Double: case TypeCode.Decimal: case TypeCode.DateTime: case TypeCode.String: visitor.VisitScalar(value, context, serializer); return; case TypeCode.Empty: throw new NotSupportedException($"TypeCode.{typeCode} is not supported."); } if (value.IsDbNull()) { visitor.VisitScalar(new ObjectDescriptor(null, typeof(object), typeof(object)), context, serializer); } if (value.Value == null || value.Type == typeof(TimeSpan)) { visitor.VisitScalar(value, context, serializer); return; } Type underlyingType = Nullable.GetUnderlyingType(value.Type); Type type = underlyingType ?? FsharpHelper.GetOptionUnderlyingType(value.Type); object obj = ((type != null) ? FsharpHelper.GetValue(value) : null); if (underlyingType != null) { Traverse(propertyDescriptor, "Value", new ObjectDescriptor(value.Value, underlyingType, value.Type, value.ScalarStyle), visitor, context, path, serializer); } else if (type != null && obj != null) { Traverse(propertyDescriptor, "Value", new ObjectDescriptor(FsharpHelper.GetValue(value), type, value.Type, value.ScalarStyle), visitor, context, path, serializer); } else { TraverseObject(propertyDescriptor, value, visitor, context, path, serializer); } } finally { path.Pop(); } } protected virtual void TraverseObject(IPropertyDescriptor? propertyDescriptor, IObjectDescriptor value, IObjectGraphVisitor visitor, TContext context, Stack path, ObjectSerializer serializer) { IDictionary dictionary; Type[] genericArguments; if (typeof(IDictionary).IsAssignableFrom(value.Type)) { TraverseDictionary(propertyDescriptor, value, visitor, typeof(object), typeof(object), context, path, serializer); } else if (objectFactory.GetDictionary(value, out dictionary, out genericArguments)) { TraverseDictionary(propertyDescriptor, new ObjectDescriptor(dictionary, value.Type, value.StaticType, value.ScalarStyle), visitor, genericArguments[0], genericArguments[1], context, path, serializer); } else if (typeof(IEnumerable).IsAssignableFrom(value.Type)) { TraverseList(propertyDescriptor, value, visitor, context, path, serializer); } else { TraverseProperties(value, visitor, context, path, serializer); } } protected virtual void TraverseDictionary(IPropertyDescriptor? propertyDescriptor, IObjectDescriptor dictionary, IObjectGraphVisitor visitor, Type keyType, Type valueType, TContext context, Stack path, ObjectSerializer serializer) { visitor.VisitMappingStart(dictionary, keyType, valueType, context, serializer); bool flag = dictionary.Type.FullName.Equals("System.Dynamic.ExpandoObject"); foreach (DictionaryEntry? item in (IDictionary)dictionary.NonNullValue()) { DictionaryEntry value = item.Value; object obj = (flag ? namingConvention.Apply(value.Key.ToString()) : value.Key); ObjectDescriptor objectDescriptor = GetObjectDescriptor(obj, keyType); ObjectDescriptor objectDescriptor2 = GetObjectDescriptor(value.Value, valueType); if (visitor.EnterMapping(objectDescriptor, objectDescriptor2, context, serializer)) { Traverse(propertyDescriptor, obj, objectDescriptor, visitor, context, path, serializer); Traverse(propertyDescriptor, obj, objectDescriptor2, visitor, context, path, serializer); } } visitor.VisitMappingEnd(dictionary, context, serializer); } private void TraverseList(IPropertyDescriptor propertyDescriptor, IObjectDescriptor value, IObjectGraphVisitor visitor, TContext context, Stack path, ObjectSerializer serializer) { Type valueType = objectFactory.GetValueType(value.Type); visitor.VisitSequenceStart(value, valueType, context, serializer); int num = 0; foreach (object item in (IEnumerable)value.NonNullValue()) { Traverse(propertyDescriptor, num, GetObjectDescriptor(item, valueType), visitor, context, path, serializer); num++; } visitor.VisitSequenceEnd(value, context, serializer); } protected virtual void TraverseProperties(IObjectDescriptor value, IObjectGraphVisitor visitor, TContext context, Stack path, ObjectSerializer serializer) { if (context.GetType() != typeof(Nothing)) { objectFactory.ExecuteOnSerializing(value.Value); } visitor.VisitMappingStart(value, typeof(string), typeof(object), context, serializer); object obj = value.NonNullValue(); foreach (IPropertyDescriptor property in typeDescriptor.GetProperties(value.Type, obj)) { IObjectDescriptor value2 = property.Read(obj); if (visitor.EnterMapping(property, value2, context, serializer)) { Traverse(null, property.Name, new ObjectDescriptor(property.Name, typeof(string), typeof(string), ScalarStyle.Plain), visitor, context, path, serializer); Traverse(property, property.Name, value2, visitor, context, path, serializer); } } visitor.VisitMappingEnd(value, context, serializer); if (context.GetType() != typeof(Nothing)) { objectFactory.ExecuteOnSerialized(value.Value); } } private ObjectDescriptor GetObjectDescriptor(object? value, Type staticType) { return new ObjectDescriptor(value, typeResolver.Resolve(staticType, value), staticType); } } internal class RoundtripObjectGraphTraversalStrategy : FullObjectGraphTraversalStrategy { private readonly TypeConverterCache converters; private readonly Settings settings; public RoundtripObjectGraphTraversalStrategy(IEnumerable converters, ITypeInspector typeDescriptor, ITypeResolver typeResolver, int maxRecursion, INamingConvention namingConvention, Settings settings, IObjectFactory factory) : base(typeDescriptor, typeResolver, maxRecursion, namingConvention, factory) { this.converters = new TypeConverterCache(converters); this.settings = settings; } protected override void TraverseProperties(IObjectDescriptor value, IObjectGraphVisitor visitor, TContext context, Stack path, ObjectSerializer serializer) { if (!value.Type.HasDefaultConstructor(settings.AllowPrivateConstructors) && !converters.TryGetConverterForType(value.Type, out IYamlTypeConverter _)) { throw new InvalidOperationException($"Type '{value.Type}' cannot be deserialized because it does not have a default constructor or a type converter."); } base.TraverseProperties(value, visitor, context, path, serializer); } } } namespace YamlDotNet.Serialization.ObjectFactories { internal class DefaultObjectFactory : ObjectFactoryBase { private readonly Dictionary> stateMethods = new Dictionary> { { typeof(YamlDotNet.Serialization.Callbacks.OnDeserializedAttribute), new ConcurrentDictionary() }, { typeof(YamlDotNet.Serialization.Callbacks.OnDeserializingAttribute), new ConcurrentDictionary() }, { typeof(YamlDotNet.Serialization.Callbacks.OnSerializedAttribute), new ConcurrentDictionary() }, { typeof(YamlDotNet.Serialization.Callbacks.OnSerializingAttribute), new ConcurrentDictionary() } }; private readonly Dictionary defaultGenericInterfaceImplementations = new Dictionary { { typeof(IEnumerable<>), typeof(List<>) }, { typeof(ICollection<>), typeof(List<>) }, { typeof(IList<>), typeof(List<>) }, { typeof(IDictionary<, >), typeof(Dictionary<, >) } }; private readonly Dictionary defaultNonGenericInterfaceImplementations = new Dictionary { { typeof(IEnumerable), typeof(List) }, { typeof(ICollection), typeof(List) }, { typeof(IList), typeof(List) }, { typeof(IDictionary), typeof(Dictionary) } }; private readonly Settings settings; public DefaultObjectFactory() : this(new Dictionary(), new Settings()) { } public DefaultObjectFactory(IDictionary mappings) : this(mappings, new Settings()) { } public DefaultObjectFactory(IDictionary mappings, Settings settings) { foreach (KeyValuePair mapping in mappings) { if (!mapping.Key.IsAssignableFrom(mapping.Value)) { throw new InvalidOperationException($"Type '{mapping.Value}' does not implement type '{mapping.Key}'."); } defaultNonGenericInterfaceImplementations.Add(mapping.Key, mapping.Value); } this.settings = settings; } public override object Create(Type type) { if (type.IsInterface()) { Type value2; if (type.IsGenericType()) { if (defaultGenericInterfaceImplementations.TryGetValue(type.GetGenericTypeDefinition(), out Type value)) { type = value.MakeGenericType(type.GetGenericArguments()); } } else if (defaultNonGenericInterfaceImplementations.TryGetValue(type, out value2)) { type = value2; } } try { return Activator.CreateInstance(type, settings.AllowPrivateConstructors); } catch (Exception innerException) { string message = "Failed to create an instance of type '" + type.FullName + "'."; throw new InvalidOperationException(message, innerException); } } public override void ExecuteOnDeserialized(object value) { ExecuteState(typeof(YamlDotNet.Serialization.Callbacks.OnDeserializedAttribute), value); } public override void ExecuteOnDeserializing(object value) { ExecuteState(typeof(YamlDotNet.Serialization.Callbacks.OnDeserializingAttribute), value); } public override void ExecuteOnSerialized(object value) { ExecuteState(typeof(YamlDotNet.Serialization.Callbacks.OnSerializedAttribute), value); } public override void ExecuteOnSerializing(object value) { ExecuteState(typeof(YamlDotNet.Serialization.Callbacks.OnSerializingAttribute), value); } private void ExecuteState(Type attributeType, object value) { if (value != null) { Type type = value.GetType(); MethodInfo[] array = GetStateMethods(attributeType, type); MethodInfo[] array2 = array; foreach (MethodInfo methodInfo in array2) { methodInfo.Invoke(value, null); } } } private MethodInfo[] GetStateMethods(Type attributeType, Type valueType) { Type attributeType2 = attributeType; ConcurrentDictionary concurrentDictionary = stateMethods[attributeType2]; return concurrentDictionary.GetOrAdd(valueType, delegate(Type type) { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); return methods.Where((MethodInfo x) => x.GetCustomAttributes(attributeType2, inherit: true).Length != 0).ToArray(); }); } } internal sealed class LambdaObjectFactory : ObjectFactoryBase { private readonly Func factory; public LambdaObjectFactory(Func factory) { this.factory = factory ?? throw new ArgumentNullException("factory"); } public override object Create(Type type) { return factory(type); } } internal abstract class ObjectFactoryBase : IObjectFactory { public abstract object Create(Type type); public virtual object? CreatePrimitive(Type type) { if (!type.IsValueType()) { return null; } return Activator.CreateInstance(type); } public virtual void ExecuteOnDeserialized(object value) { } public virtual void ExecuteOnDeserializing(object value) { } public virtual void ExecuteOnSerialized(object value) { } public virtual void ExecuteOnSerializing(object value) { } public virtual bool GetDictionary(IObjectDescriptor descriptor, out IDictionary? dictionary, out Type[]? genericArguments) { Type implementationOfOpenGenericInterface = descriptor.Type.GetImplementationOfOpenGenericInterface(typeof(IDictionary<, >)); if (implementationOfOpenGenericInterface != null) { genericArguments = implementationOfOpenGenericInterface.GetGenericArguments(); object obj = Activator.CreateInstance(typeof(GenericDictionaryToNonGenericAdapter<, >).MakeGenericType(genericArguments), descriptor.Value); dictionary = obj as IDictionary; return true; } genericArguments = null; dictionary = null; return false; } public virtual Type GetValueType(Type type) { Type implementationOfOpenGenericInterface = type.GetImplementationOfOpenGenericInterface(typeof(IEnumerable<>)); return (implementationOfOpenGenericInterface != null) ? implementationOfOpenGenericInterface.GetGenericArguments()[0] : typeof(object); } } internal abstract class StaticObjectFactory : IObjectFactory { public abstract object Create(Type type); public abstract Array CreateArray(Type type, int count); public abstract bool IsDictionary(Type type); public abstract bool IsArray(Type type); public abstract bool IsList(Type type); public abstract Type GetKeyType(Type type); public abstract Type GetValueType(Type type); public virtual object? CreatePrimitive(Type type) { return Type.GetTypeCode(type) switch { TypeCode.Boolean => false, TypeCode.Byte => (byte)0, TypeCode.Int16 => (short)0, TypeCode.Int32 => 0, TypeCode.Int64 => 0L, TypeCode.SByte => (sbyte)0, TypeCode.UInt16 => (ushort)0, TypeCode.UInt32 => 0u, TypeCode.UInt64 => 0uL, TypeCode.Single => 0f, TypeCode.Double => 0.0, TypeCode.Decimal => 0m, TypeCode.Char => '\0', TypeCode.DateTime => default(DateTime), _ => null, }; } public bool GetDictionary(IObjectDescriptor descriptor, out IDictionary? dictionary, out Type[]? genericArguments) { dictionary = null; genericArguments = null; return false; } public abstract void ExecuteOnDeserializing(object value); public abstract void ExecuteOnDeserialized(object value); public abstract void ExecuteOnSerializing(object value); public abstract void ExecuteOnSerialized(object value); } } namespace YamlDotNet.Serialization.NodeTypeResolvers { internal sealed class DefaultContainersNodeTypeResolver : INodeTypeResolver { bool INodeTypeResolver.Resolve(NodeEvent? nodeEvent, ref Type currentType) { if (currentType == typeof(object)) { if (nodeEvent is SequenceStart) { currentType = typeof(List); return true; } if (nodeEvent is MappingStart) { currentType = typeof(Dictionary); return true; } } return false; } } internal class MappingNodeTypeResolver : INodeTypeResolver { private readonly IDictionary mappings; public MappingNodeTypeResolver(IDictionary mappings) { if (mappings == null) { throw new ArgumentNullException("mappings"); } foreach (KeyValuePair mapping in mappings) { if (!mapping.Key.IsAssignableFrom(mapping.Value)) { throw new InvalidOperationException($"Type '{mapping.Value}' does not implement type '{mapping.Key}'."); } } this.mappings = mappings; } public bool Resolve(NodeEvent? nodeEvent, ref Type currentType) { if (mappings.TryGetValue(currentType, out Type value)) { currentType = value; return true; } return false; } } internal class PreventUnknownTagsNodeTypeResolver : INodeTypeResolver { bool INodeTypeResolver.Resolve(NodeEvent? nodeEvent, ref Type currentType) { if (nodeEvent != null && !nodeEvent.Tag.IsEmpty) { Mark start = nodeEvent.Start; Mark end = nodeEvent.End; throw new YamlException(in start, in end, $"Encountered an unresolved tag '{nodeEvent.Tag}'"); } return false; } } internal sealed class TagNodeTypeResolver : INodeTypeResolver { private readonly IDictionary tagMappings; public TagNodeTypeResolver(IDictionary tagMappings) { this.tagMappings = tagMappings ?? throw new ArgumentNullException("tagMappings"); } bool INodeTypeResolver.Resolve(NodeEvent? nodeEvent, ref Type currentType) { if (nodeEvent != null && !nodeEvent.Tag.IsEmpty && tagMappings.TryGetValue(nodeEvent.Tag, out Type value)) { currentType = value; return true; } return false; } } [Obsolete("The mechanism that this class uses to specify type names is non-standard. Register the tags explicitly instead of using this convention.")] internal sealed class TypeNameInTagNodeTypeResolver : INodeTypeResolver { bool INodeTypeResolver.Resolve(NodeEvent? nodeEvent, ref Type currentType) { if (nodeEvent != null && !nodeEvent.Tag.IsEmpty) { Type type = Type.GetType(nodeEvent.Tag.Value.Substring(1), throwOnError: false); if (type != null) { currentType = type; return true; } } return false; } } internal sealed class YamlConvertibleTypeResolver : INodeTypeResolver { public bool Resolve(NodeEvent? nodeEvent, ref Type currentType) { return typeof(IYamlConvertible).IsAssignableFrom(currentType); } } internal sealed class YamlSerializableTypeResolver : INodeTypeResolver { public bool Resolve(NodeEvent? nodeEvent, ref Type currentType) { return typeof(IYamlSerializable).IsAssignableFrom(currentType); } } } namespace YamlDotNet.Serialization.NodeDeserializers { internal sealed class ArrayNodeDeserializer : INodeDeserializer { private sealed class ArrayList : IList, ICollection, IEnumerable { private object?[] data; public bool IsFixedSize => false; public bool IsReadOnly => false; public object? this[int index] { get { return data[index]; } set { data[index] = value; } } public int Count { get; private set; } public bool IsSynchronized => false; public object SyncRoot => data; public ArrayList() { Clear(); } public int Add(object? value) { if (Count == data.Length) { Array.Resize(ref data, data.Length * 2); } data[Count] = value; return Count++; } public void Clear() { data = new object[10]; Count = 0; } bool IList.Contains(object? value) { throw new NotSupportedException(); } int IList.IndexOf(object? value) { throw new NotSupportedException(); } void IList.Insert(int index, object? value) { throw new NotSupportedException(); } void IList.Remove(object? value) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } public void CopyTo(Array array, int index) { Array.Copy(data, 0, array, index, Count); } public IEnumerator GetEnumerator() { int i = 0; while (i < Count) { yield return data[i]; int num = i + 1; i = num; } } } private readonly INamingConvention enumNamingConvention; private readonly ITypeInspector typeInspector; public ArrayNodeDeserializer(INamingConvention enumNamingConvention, ITypeInspector typeInspector) { this.enumNamingConvention = enumNamingConvention; this.typeInspector = typeInspector; } public bool Deserialize(IParser parser, Type expectedType, Func nestedObjectDeserializer, out object? value, ObjectDeserializer rootDeserializer) { if (!expectedType.IsArray) { value = false; return false; } Type itemType = expectedType.GetElementType(); ArrayList arrayList = new ArrayList(); Array array = null; CollectionNodeDeserializer.DeserializeHelper(itemType, parser, nestedObjectDeserializer, arrayList, canUpdate: true, enumNamingConvention, typeInspector, PromiseResolvedHandler); array = Array.CreateInstance(itemType, arrayList.Count); arrayList.CopyTo(array, 0); value = array; return true; void PromiseResolvedHandler(int index, object? value) { if (array == null) { throw new InvalidOperationException("Destination array is still null"); } array.SetValue(YamlDotNet.Serialization.Utilities.TypeConverter.ChangeType(value, itemType, enumNamingConvention, typeInspector), index); } } } internal abstract class CollectionDeserializer { protected static void DeserializeHelper(Type tItem, IParser parser, Func nestedObjectDeserializer, IList result, bool canUpdate, IObjectFactory objectFactory) { IList result2 = result; parser.Consume(); SequenceEnd @event; while (!parser.TryConsume(out @event)) { ParsingEvent current = parser.Current; object obj = nestedObjectDeserializer(parser, tItem); if (obj is IValuePromise valuePromise) { if (!canUpdate) { Mark start = current?.Start ?? Mark.Empty; Mark end = current?.End ?? Mark.Empty; throw new ForwardAnchorNotSupportedException(in start, in end, "Forward alias references are not allowed because this type does not implement IList<>"); } int index = result2.Add(objectFactory.CreatePrimitive(tItem)); valuePromise.ValueAvailable += delegate(object? v) { result2[index] = v; }; } else { result2.Add(obj); } } } } internal sealed class CollectionNodeDeserializer : INodeDeserializer { private readonly IObjectFactory objectFactory; private readonly INamingConvention enumNamingConvention; private readonly ITypeInspector typeInspector; public CollectionNodeDeserializer(IObjectFactory objectFactory, INamingConvention enumNamingConvention, ITypeInspector typeInspector) { this.objectFactory = objectFactory ?? throw new ArgumentNullException("objectFactory"); this.enumNamingConvention = enumNamingConvention; this.typeInspector = typeInspector; } public bool Deserialize(IParser parser, Type expectedType, Func nestedObjectDeserializer, out object? value, ObjectDeserializer rootDeserializer) { bool canUpdate = true; Type implementationOfOpenGenericInterface = expectedType.GetImplementationOfOpenGenericInterface(typeof(ICollection<>)); Type type; IList list; if (implementationOfOpenGenericInterface != null) { Type[] genericArguments = implementationOfOpenGenericInterface.GetGenericArguments(); type = genericArguments[0]; value = objectFactory.Create(expectedType); list = value as IList; if (list == null) { Type implementationOfOpenGenericInterface2 = expectedType.GetImplementationOfOpenGenericInterface(typeof(IList<>)); canUpdate = implementationOfOpenGenericInterface2 != null; list = (IList)Activator.CreateInstance(typeof(GenericCollectionToNonGenericAdapter<>).MakeGenericType(type), value); } } else { if (!typeof(IList).IsAssignableFrom(expectedType)) { value = null; return false; } type = typeof(object); value = objectFactory.Create(expectedType); list = (IList)value; } DeserializeHelper(type, parser, nestedObjectDeserializer, list, canUpdate, enumNamingConvention, typeInspector); return true; } internal static void DeserializeHelper(Type tItem, IParser parser, Func nestedObjectDeserializer, IList result, bool canUpdate, INamingConvention enumNamingConvention, ITypeInspector typeInspector, Action? promiseResolvedHandler = null) { Action promiseResolvedHandler2 = promiseResolvedHandler; IList result2 = result; Type tItem2 = tItem; INamingConvention enumNamingConvention2 = enumNamingConvention; ITypeInspector typeInspector2 = typeInspector; parser.Consume(); SequenceEnd @event; while (!parser.TryConsume(out @event)) { ParsingEvent current = parser.Current; object obj = nestedObjectDeserializer(parser, tItem2); if (obj is IValuePromise valuePromise) { if (!canUpdate) { Mark start = current?.Start ?? Mark.Empty; Mark end = current?.End ?? Mark.Empty; throw new ForwardAnchorNotSupportedException(in start, in end, "Forward alias references are not allowed because this type does not implement IList<>"); } int index = result2.Add(tItem2.IsValueType() ? Activator.CreateInstance(tItem2) : null); if (promiseResolvedHandler2 != null) { valuePromise.ValueAvailable += delegate(object? v) { promiseResolvedHandler2(index, v); }; } else { valuePromise.ValueAvailable += delegate(object? v) { result2[index] = YamlDotNet.Serialization.Utilities.TypeConverter.ChangeType(v, tItem2, enumNamingConvention2, typeInspector2); }; } } else { result2.Add(YamlDotNet.Serialization.Utilities.TypeConverter.ChangeType(obj, tItem2, enumNamingConvention2, typeInspector2)); } } } } internal abstract class DictionaryDeserializer { private readonly bool duplicateKeyChecking; public DictionaryDeserializer(bool duplicateKeyChecking) { this.duplicateKeyChecking = duplicateKeyChecking; } private void TryAssign(IDictionary result, object key, object value, MappingStart propertyName) { if (duplicateKeyChecking && result.Contains(key)) { Mark start = propertyName.Start; Mark end = propertyName.End; throw new YamlException(in start, in end, $"Encountered duplicate key {key}"); } result[key] = value; } protected virtual void Deserialize(Type tKey, Type tValue, IParser parser, Func nestedObjectDeserializer, IDictionary result, ObjectDeserializer rootDeserializer) { IDictionary result2 = result; MappingStart property = parser.Consume(); MappingEnd @event; while (!parser.TryConsume(out @event)) { object key = nestedObjectDeserializer(parser, tKey); object value = nestedObjectDeserializer(parser, tValue); IValuePromise valuePromise = value as IValuePromise; if (key is IValuePromise valuePromise2) { if (valuePromise == null) { valuePromise2.ValueAvailable += delegate(object? v) { result2[v] = value; }; continue; } bool hasFirstPart = false; valuePromise2.ValueAvailable += delegate(object? v) { if (hasFirstPart) { TryAssign(result2, v, value, property); } else { key = v; hasFirstPart = true; } }; valuePromise.ValueAvailable += delegate(object? v) { if (hasFirstPart) { TryAssign(result2, key, v, property); } else { value = v; hasFirstPart = true; } }; continue; } if (key == null) { throw new ArgumentException("Empty key names are not supported yet.", "tKey"); } if (valuePromise == null) { TryAssign(result2, key, value, property); continue; } valuePromise.ValueAvailable += delegate(object? v) { result2[key] = v; }; } } } internal class DictionaryNodeDeserializer : DictionaryDeserializer, INodeDeserializer { private readonly IObjectFactory objectFactory; public DictionaryNodeDeserializer(IObjectFactory objectFactory, bool duplicateKeyChecking) : base(duplicateKeyChecking) { this.objectFactory = objectFactory ?? throw new ArgumentNullException("objectFactory"); } public bool Deserialize(IParser parser, Type expectedType, Func nestedObjectDeserializer, out object? value, ObjectDeserializer rootDeserializer) { Type implementationOfOpenGenericInterface = expectedType.GetImplementationOfOpenGenericInterface(typeof(IDictionary<, >)); Type type; Type type2; IDictionary dictionary; if (implementationOfOpenGenericInterface != null) { Type[] genericArguments = implementationOfOpenGenericInterface.GetGenericArguments(); type = genericArguments[0]; type2 = genericArguments[1]; value = objectFactory.Create(expectedType); dictionary = value as IDictionary; if (dictionary == null) { dictionary = (IDictionary)Activator.CreateInstance(typeof(GenericDictionaryToNonGenericAdapter<, >).MakeGenericType(type, type2), value); } } else { if (!typeof(IDictionary).IsAssignableFrom(expectedType)) { value = null; return false; } type = typeof(object); type2 = typeof(object); value = objectFactory.Create(expectedType); dictionary = (IDictionary)value; } Deserialize(type, type2, parser, nestedObjectDeserializer, dictionary, rootDeserializer); return true; } } internal sealed class EnumerableNodeDeserializer : INodeDeserializer { public bool Deserialize(IParser parser, Type expectedType, Func nestedObjectDeserializer, out object? value, ObjectDeserializer rootDeserializer) { Type type; if (expectedType == typeof(IEnumerable)) { type = typeof(object); } else { Type implementationOfOpenGenericInterface = expectedType.GetImplementationOfOpenGenericInterface(typeof(IEnumerable<>)); if (implementationOfOpenGenericInterface != expectedType) { value = null; return false; } type = implementationOfOpenGenericInterface.GetGenericArguments()[0]; } Type arg = typeof(List<>).MakeGenericType(type); value = nestedObjectDeserializer(parser, arg); return true; } } internal sealed class FsharpListNodeDeserializer : INodeDeserializer { private readonly ITypeInspector typeInspector; private readonly INamingConvention enumNamingConvention; public FsharpListNodeDeserializer(ITypeInspector typeInspector, INamingConvention enumNamingConvention) { this.typeInspector = typeInspector; this.enumNamingConvention = enumNamingConvention; } public bool Deserialize(IParser parser, Type expectedType, Func nestedObjectDeserializer, out object? value, ObjectDeserializer rootDeserializer) { if (!FsharpHelper.IsFsharpListType(expectedType)) { value = false; return false; } Type type = expectedType.GetGenericArguments()[0]; Type t = expectedType.GetGenericTypeDefinition().MakeGenericType(type); ArrayList arrayList = new ArrayList(); CollectionNodeDeserializer.DeserializeHelper(type, parser, nestedObjectDeserializer, arrayList, canUpdate: true, enumNamingConvention, typeInspector); Array array = Array.CreateInstance(type, arrayList.Count); arrayList.CopyTo(array, 0); object obj = FsharpHelper.CreateFsharpListFromArray(t, type, array); value = obj; return true; } } internal sealed class NullNodeDeserializer : INodeDeserializer { public bool Deserialize(IParser parser, Type expectedType, Func nestedObjectDeserializer, out object? value, ObjectDeserializer rootDeserializer) { value = null; if (parser.Accept(out var @event) && NodeIsNull(@event)) { parser.SkipThisAndNestedEvents(); return true; } return false; } private static bool NodeIsNull(NodeEvent nodeEvent) { if (nodeEvent.Tag == "tag:yaml.org,2002:null") { return true; } if (nodeEvent is YamlDotNet.Core.Events.Scalar scalar && scalar.Style == ScalarStyle.Plain && !scalar.IsKey) { string value = scalar.Value; switch (value) { default: return value == "NULL"; case "": case "~": case "null": case "Null": return true; } } return false; } } internal sealed class ObjectNodeDeserializer : INodeDeserializer { private readonly IObjectFactory objectFactory; private readonly ITypeInspector typeInspector; private readonly bool ignoreUnmatched; private readonly bool duplicateKeyChecking; private readonly ITypeConverter typeConverter; private readonly INamingConvention enumNamingConvention; private readonly bool enforceNullability; private readonly bool caseInsensitivePropertyMatching; private readonly bool enforceRequiredProperties; private readonly TypeConverterCache typeConverters; public ObjectNodeDeserializer(IObjectFactory objectFactory, ITypeInspector typeInspector, bool ignoreUnmatched, bool duplicateKeyChecking, ITypeConverter typeConverter, INamingConvention enumNamingConvention, bool enforceNullability, bool caseInsensitivePropertyMatching, bool enforceRequiredProperties, IEnumerable typeConverters) { this.objectFactory = objectFactory ?? throw new ArgumentNullException("objectFactory"); this.typeInspector = typeInspector ?? throw new ArgumentNullException("typeInspector"); this.ignoreUnmatched = ignoreUnmatched; this.duplicateKeyChecking = duplicateKeyChecking; this.typeConverter = typeConverter ?? throw new ArgumentNullException("typeConverter"); this.enumNamingConvention = enumNamingConvention ?? throw new ArgumentNullException("enumNamingConvention"); this.enforceNullability = enforceNullability; this.caseInsensitivePropertyMatching = caseInsensitivePropertyMatching; this.enforceRequiredProperties = enforceRequiredProperties; this.typeConverters = new TypeConverterCache(typeConverters); } public bool Deserialize(IParser parser, Type expectedType, Func nestedObjectDeserializer, out object? value, ObjectDeserializer rootDeserializer) { if (!parser.TryConsume(out var _)) { value = null; return false; } Type type = Nullable.GetUnderlyingType(expectedType) ?? FsharpHelper.GetOptionUnderlyingType(expectedType) ?? expectedType; value = objectFactory.Create(type); objectFactory.ExecuteOnDeserializing(value); HashSet hashSet = new HashSet(StringComparer.Ordinal); HashSet hashSet2 = new HashSet(StringComparer.Ordinal); Mark start = Mark.Empty; MappingEnd event2; while (!parser.TryConsume(out event2)) { YamlDotNet.Core.Events.Scalar propertyName = parser.Consume(); if (duplicateKeyChecking && !hashSet.Add(propertyName.Value)) { Mark start2 = propertyName.Start; Mark end = propertyName.End; throw new YamlException(in start2, in end, "Encountered duplicate key " + propertyName.Value); } try { IPropertyDescriptor property = typeInspector.GetProperty(type, null, propertyName.Value, ignoreUnmatched, caseInsensitivePropertyMatching); if (property == null) { parser.SkipThisAndNestedEvents(); continue; } hashSet2.Add(property.Name); object obj; if (property.ConverterType != null) { IYamlTypeConverter converterByType = typeConverters.GetConverterByType(property.ConverterType); obj = converterByType.ReadYaml(parser, property.Type, rootDeserializer); } else { obj = nestedObjectDeserializer(parser, property.Type); } if (obj is IValuePromise valuePromise) { object valueRef = value; valuePromise.ValueAvailable += delegate(object? v) { object value3 = typeConverter.ChangeType(v, property.Type, enumNamingConvention, typeInspector); NullCheck(value3, property, propertyName); property.Write(valueRef, value3); }; } else { object value2 = typeConverter.ChangeType(obj, property.Type, enumNamingConvention, typeInspector); NullCheck(value2, property, propertyName); property.Write(value, value2); } goto IL_0267; } catch (SerializationException ex) { Mark start2 = propertyName.Start; Mark end = propertyName.End; throw new YamlException(in start2, in end, ex.Message); } catch (YamlException) { throw; } catch (Exception innerException) { Mark start2 = propertyName.Start; Mark end = propertyName.End; throw new YamlException(in start2, in end, "Exception during deserialization", innerException); } IL_0267: start = propertyName.End; } if (enforceRequiredProperties) { IEnumerable properties = typeInspector.GetProperties(type, value); List list = new List(); foreach (IPropertyDescriptor item in properties) { if (item.Required && !hashSet2.Contains(item.Name)) { list.Add(item.Name); } } if (list.Count > 0) { string text = string.Join(",", list); throw new YamlException(in start, in start, "Missing properties, '" + text + "' in source yaml."); } } objectFactory.ExecuteOnDeserialized(value); return true; } public void NullCheck(object value, IPropertyDescriptor property, YamlDotNet.Core.Events.Scalar propertyName) { if (enforceNullability && value == null && !property.AllowNulls) { Mark start = propertyName.Start; Mark end = propertyName.End; throw new YamlException(in start, in end, "Strict nullability enforcement error.", new NullReferenceException("Yaml value is null when target property requires non null values.")); } } } internal sealed class ScalarNodeDeserializer : INodeDeserializer { private const string BooleanTruePattern = "^(true|y|yes|on)$"; private const string BooleanFalsePattern = "^(false|n|no|off)$"; private readonly bool attemptUnknownTypeDeserialization; private readonly ITypeConverter typeConverter; private readonly ITypeInspector typeInspector; private readonly YamlFormatter formatter; private readonly INamingConvention enumNamingConvention; public ScalarNodeDeserializer(bool attemptUnknownTypeDeserialization, ITypeConverter typeConverter, ITypeInspector typeInspector, YamlFormatter formatter, INamingConvention enumNamingConvention) { this.attemptUnknownTypeDeserialization = attemptUnknownTypeDeserialization; this.typeConverter = typeConverter ?? throw new ArgumentNullException("typeConverter"); this.typeInspector = typeInspector; this.formatter = formatter; this.enumNamingConvention = enumNamingConvention; } public bool Deserialize(IParser parser, Type expectedType, Func nestedObjectDeserializer, out object? value, ObjectDeserializer rootDeserializer) { if (!parser.TryConsume(out var @event)) { value = null; return false; } Type type = Nullable.GetUnderlyingType(expectedType) ?? FsharpHelper.GetOptionUnderlyingType(expectedType) ?? expectedType; if (type.IsEnum()) { string name = enumNamingConvention.Reverse(@event.Value); name = typeInspector.GetEnumName(type, name); value = Enum.Parse(type, name, ignoreCase: true); return true; } TypeCode typeCode = type.GetTypeCode(); switch (typeCode) { case TypeCode.Boolean: value = DeserializeBooleanHelper(@event.Value); break; case TypeCode.SByte: case TypeCode.Byte: case TypeCode.Int16: case TypeCode.UInt16: case TypeCode.Int32: case TypeCode.UInt32: case TypeCode.Int64: case TypeCode.UInt64: value = DeserializeIntegerHelper(typeCode, @event.Value); break; case TypeCode.Single: value = float.Parse(@event.Value, formatter.NumberFormat); break; case TypeCode.Double: value = double.Parse(@event.Value, formatter.NumberFormat); break; case TypeCode.Decimal: value = decimal.Parse(@event.Value, formatter.NumberFormat); break; case TypeCode.String: value = @event.Value; break; case TypeCode.Char: value = @event.Value[0]; break; case TypeCode.DateTime: value = DateTime.Parse(@event.Value, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind); break; default: if (expectedType == typeof(object)) { if (!@event.IsKey && attemptUnknownTypeDeserialization) { value = AttemptUnknownTypeDeserialization(@event); } else { value = @event.Value; } } else { value = typeConverter.ChangeType(@event.Value, expectedType, enumNamingConvention, typeInspector); } break; } return true; } private static bool DeserializeBooleanHelper(string value) { if (Regex.IsMatch(value, "^(true|y|yes|on)$", RegexOptions.IgnoreCase)) { return true; } if (Regex.IsMatch(value, "^(false|n|no|off)$", RegexOptions.IgnoreCase)) { return false; } throw new FormatException("The value \"" + value + "\" is not a valid YAML Boolean"); } private object DeserializeIntegerHelper(TypeCode typeCode, string value) { StringBuilderPool.BuilderWrapper builderWrapper = StringBuilderPool.Rent(); try { StringBuilder builder = builderWrapper.Builder; int i = 0; bool flag = false; ulong num = 0uL; if (value[0] == '-') { i++; flag = true; } else if (value[0] == '+') { i++; } if (value[i] == '0') { int num2; if (i == value.Length - 1) { num2 = 10; num = 0uL; } else { i++; if (value[i] == 'b') { num2 = 2; i++; } else if (value[i] == 'x') { num2 = 16; i++; } else { num2 = 8; } } for (; i < value.Length; i++) { if (value[i] != '_') { builder.Append(value[i]); } } switch (num2) { case 2: case 8: num = Convert.ToUInt64(builder.ToString(), num2); break; case 16: num = ulong.Parse(builder.ToString(), NumberStyles.HexNumber, formatter.NumberFormat); break; } } else { string[] array = value.Substring(i).Split(new char[1] { ':' }); num = 0uL; for (int j = 0; j < array.Length; j++) { num *= 60; num += ulong.Parse(array[j].Replace("_", ""), CultureInfo.InvariantCulture); } } if (!flag) { return CastInteger(num, typeCode); } long number = ((num != 9223372036854775808uL) ? checked(-(long)num) : long.MinValue); return CastInteger(number, typeCode); } finally { ((IDisposable)builderWrapper).Dispose(); } } private static object CastInteger(long number, TypeCode typeCode) { return checked(typeCode switch { TypeCode.Byte => (byte)number, TypeCode.Int16 => (short)number, TypeCode.Int32 => (int)number, TypeCode.Int64 => number, TypeCode.SByte => (sbyte)number, TypeCode.UInt16 => (ushort)number, TypeCode.UInt32 => (uint)number, TypeCode.UInt64 => (ulong)number, _ => number, }); } private static object CastInteger(ulong number, TypeCode typeCode) { return checked(typeCode switch { TypeCode.Byte => (byte)number, TypeCode.Int16 => (short)number, TypeCode.Int32 => (int)number, TypeCode.Int64 => (long)number, TypeCode.SByte => (sbyte)number, TypeCode.UInt16 => (ushort)number, TypeCode.UInt32 => (uint)number, TypeCode.UInt64 => number, _ => number, }); } private object? AttemptUnknownTypeDeserialization(YamlDotNet.Core.Events.Scalar value) { if (value.Style == ScalarStyle.SingleQuoted || value.Style == ScalarStyle.DoubleQuoted || value.Style == ScalarStyle.Folded) { return value.Value; } string v = value.Value; switch (v) { case "null": case "Null": case "NULL": case "~": case "": return null; case "true": case "True": case "TRUE": return true; case "False": case "FALSE": case "false": return false; default: if (Regex.IsMatch(v, "^0x[0-9a-fA-F]+$")) { v = v.Substring(2); if (byte.TryParse(v, NumberStyles.AllowHexSpecifier, formatter.NumberFormat, out var result)) { return result; } if (short.TryParse(v, NumberStyles.AllowHexSpecifier, formatter.NumberFormat, out var result2)) { return result2; } if (int.TryParse(v, NumberStyles.AllowHexSpecifier, formatter.NumberFormat, out var result3)) { return result3; } if (long.TryParse(v, NumberStyles.AllowHexSpecifier, formatter.NumberFormat, out var result4)) { return result4; } if (ulong.TryParse(v, NumberStyles.AllowHexSpecifier, formatter.NumberFormat, out var result5)) { return result5; } return v; } if (Regex.IsMatch(v, "^0o[0-9a-fA-F]+$")) { if (!TryAndSwallow(() => Convert.ToByte(v, 8), out object value2) && !TryAndSwallow(() => Convert.ToInt16(v, 8), out value2) && !TryAndSwallow(() => Convert.ToInt32(v, 8), out value2) && !TryAndSwallow(() => Convert.ToInt64(v, 8), out value2) && !TryAndSwallow(() => Convert.ToUInt64(v, 8), out value2)) { return v; } return value2; } if (Regex.IsMatch(v, "^[-+]?(\\.[0-9]+|[0-9]+(\\.[0-9]*)?)([eE][-+]?[0-9]+)?$")) { if (byte.TryParse(v, NumberStyles.Integer, formatter.NumberFormat, out var result6)) { return result6; } if (short.TryParse(v, NumberStyles.Integer, formatter.NumberFormat, out var result7)) { return result7; } if (int.TryParse(v, NumberStyles.Integer, formatter.NumberFormat, out var result8)) { return result8; } if (long.TryParse(v, NumberStyles.Integer, formatter.NumberFormat, out var result9)) { return result9; } if (ulong.TryParse(v, NumberStyles.Integer, formatter.NumberFormat, out var result10)) { return result10; } if (float.TryParse(v, NumberStyles.Float, formatter.NumberFormat, out var result11)) { return result11; } if (double.TryParse(v, NumberStyles.Float, formatter.NumberFormat, out var result12)) { return result12; } return v; } if (Regex.IsMatch(v, "^[-+]?(\\.inf|\\.Inf|\\.INF)$")) { if (Polyfills.StartsWith(v, '-')) { return float.NegativeInfinity; } return float.PositiveInfinity; } if (Regex.IsMatch(v, "^(\\.nan|\\.NaN|\\.NAN)$")) { return float.NaN; } return v; } } private static bool TryAndSwallow(Func attempt, out object? value) { try { value = attempt(); return true; } catch { value = null; return false; } } } internal sealed class StaticArrayNodeDeserializer : INodeDeserializer { private sealed class ArrayList : IList, ICollection, IEnumerable { private object?[] data; public bool IsFixedSize => false; public bool IsReadOnly => false; public object? this[int index] { get { return data[index]; } set { data[index] = value; } } public int Count { get; private set; } public bool IsSynchronized => false; public object SyncRoot => data; public ArrayList() { Clear(); } public int Add(object? value) { if (Count == data.Length) { Array.Resize(ref data, data.Length * 2); } data[Count] = value; return Count++; } public void Clear() { data = new object[10]; Count = 0; } bool IList.Contains(object? value) { throw new NotSupportedException(); } int IList.IndexOf(object? value) { throw new NotSupportedException(); } void IList.Insert(int index, object? value) { throw new NotSupportedException(); } void IList.Remove(object? value) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } public void CopyTo(Array array, int index) { Array.Copy(data, 0, array, index, Count); } public IEnumerator GetEnumerator() { int i = 0; while (i < Count) { yield return data[i]; int num = i + 1; i = num; } } } private readonly StaticObjectFactory factory; public StaticArrayNodeDeserializer(StaticObjectFactory factory) { this.factory = factory ?? throw new ArgumentNullException("factory"); } public bool Deserialize(IParser parser, Type expectedType, Func nestedObjectDeserializer, out object? value, ObjectDeserializer rootDeserializer) { if (!factory.IsArray(expectedType)) { value = false; return false; } Type valueType = factory.GetValueType(expectedType); ArrayList arrayList = new ArrayList(); StaticCollectionNodeDeserializer.DeserializeHelper(valueType, parser, nestedObjectDeserializer, arrayList, factory); Array array = factory.CreateArray(expectedType, arrayList.Count); arrayList.CopyTo(array, 0); value = array; return true; } } internal sealed class StaticCollectionNodeDeserializer : INodeDeserializer { private readonly StaticObjectFactory factory; public StaticCollectionNodeDeserializer(StaticObjectFactory factory) { this.factory = factory ?? throw new ArgumentNullException("factory"); } public bool Deserialize(IParser parser, Type expectedType, Func nestedObjectDeserializer, out object? value, ObjectDeserializer rootDeserializer) { if (!factory.IsList(expectedType)) { value = null; return false; } DeserializeHelper(result: (IList)(value = factory.Create(expectedType) as IList), tItem: factory.GetValueType(expectedType), parser: parser, nestedObjectDeserializer: nestedObjectDeserializer, factory: factory); return true; } internal static void DeserializeHelper(Type tItem, IParser parser, Func nestedObjectDeserializer, IList result, IObjectFactory factory) { IList result2 = result; parser.Consume(); SequenceEnd @event; while (!parser.TryConsume(out @event)) { ParsingEvent current = parser.Current; object obj = nestedObjectDeserializer(parser, tItem); if (obj is IValuePromise valuePromise) { int index = result2.Add(factory.CreatePrimitive(tItem)); valuePromise.ValueAvailable += delegate(object? v) { result2[index] = v; }; } else { result2.Add(obj); } } } } internal class StaticDictionaryNodeDeserializer : DictionaryDeserializer, INodeDeserializer { private readonly StaticObjectFactory objectFactory; public StaticDictionaryNodeDeserializer(StaticObjectFactory objectFactory, bool duplicateKeyChecking) : base(duplicateKeyChecking) { this.objectFactory = objectFactory ?? throw new ArgumentNullException("objectFactory"); } public bool Deserialize(IParser reader, Type expectedType, Func nestedObjectDeserializer, out object? value, ObjectDeserializer rootDeserializer) { if (objectFactory.IsDictionary(expectedType)) { if (!(objectFactory.Create(expectedType) is IDictionary dictionary)) { value = null; return false; } Type keyType = objectFactory.GetKeyType(expectedType); Type valueType = objectFactory.GetValueType(expectedType); value = dictionary; base.Deserialize(keyType, valueType, reader, nestedObjectDeserializer, dictionary, rootDeserializer); return true; } value = null; return false; } } internal sealed class TypeConverterNodeDeserializer : INodeDeserializer { private readonly TypeConverterCache converters; public TypeConverterNodeDeserializer(IEnumerable converters) { this.converters = new TypeConverterCache(converters); } public bool Deserialize(IParser parser, Type expectedType, Func nestedObjectDeserializer, out object? value, ObjectDeserializer rootDeserializer) { if (!converters.TryGetConverterForType(expectedType, out IYamlTypeConverter typeConverter)) { value = null; return false; } value = typeConverter.ReadYaml(parser, expectedType, rootDeserializer); return true; } } internal sealed class YamlConvertibleNodeDeserializer : INodeDeserializer { private readonly IObjectFactory objectFactory; public YamlConvertibleNodeDeserializer(IObjectFactory objectFactory) { this.objectFactory = objectFactory; } public bool Deserialize(IParser parser, Type expectedType, Func nestedObjectDeserializer, out object? value, ObjectDeserializer rootDeserializer) { Func nestedObjectDeserializer2 = nestedObjectDeserializer; IParser parser2 = parser; if (typeof(IYamlConvertible).IsAssignableFrom(expectedType)) { IYamlConvertible yamlConvertible = (IYamlConvertible)objectFactory.Create(expectedType); yamlConvertible.Read(parser2, expectedType, (Type type) => nestedObjectDeserializer2(parser2, type)); value = yamlConvertible; return true; } value = null; return false; } } internal sealed class YamlSerializableNodeDeserializer : INodeDeserializer { private readonly IObjectFactory objectFactory; public YamlSerializableNodeDeserializer(IObjectFactory objectFactory) { this.objectFactory = objectFactory; } public bool Deserialize(IParser parser, Type expectedType, Func nestedObjectDeserializer, out object? value, ObjectDeserializer rootDeserializer) { if (typeof(IYamlSerializable).IsAssignableFrom(expectedType)) { IYamlSerializable yamlSerializable = (IYamlSerializable)objectFactory.Create(expectedType); yamlSerializable.ReadYaml(parser); value = yamlSerializable; return true; } value = null; return false; } } } namespace YamlDotNet.Serialization.NamingConventions { internal sealed class CamelCaseNamingConvention : INamingConvention { public static readonly INamingConvention Instance = new CamelCaseNamingConvention(); [Obsolete("Use the Instance static field instead of creating new instances")] public CamelCaseNamingConvention() { } public string Apply(string value) { return value.ToCamelCase(); } public string Reverse(string value) { return value.ToPascalCase(); } } internal sealed class HyphenatedNamingConvention : INamingConvention { public static readonly INamingConvention Instance = new HyphenatedNamingConvention(); [Obsolete("Use the Instance static field instead of creating new instances")] public HyphenatedNamingConvention() { } public string Apply(string value) { return value.FromCamelCase("-"); } public string Reverse(string value) { return value.ToPascalCase(); } } internal sealed class LowerCaseNamingConvention : INamingConvention { public static readonly INamingConvention Instance = new LowerCaseNamingConvention(); private LowerCaseNamingConvention() { } public string Apply(string value) { return value.ToCamelCase().ToLower(CultureInfo.InvariantCulture); } public string Reverse(string value) { if (string.IsNullOrEmpty(value)) { return value; } return char.ToUpperInvariant(value[0]) + value.Substring(1); } } internal sealed class NullNamingConvention : INamingConvention { public static readonly INamingConvention Instance = new NullNamingConvention(); [Obsolete("Use the Instance static field instead of creating new instances")] public NullNamingConvention() { } public string Apply(string value) { return value; } public string Reverse(string value) { return value; } } internal sealed class PascalCaseNamingConvention : INamingConvention { public static readonly INamingConvention Instance = new PascalCaseNamingConvention(); [Obsolete("Use the Instance static field instead of creating new instances")] public PascalCaseNamingConvention() { } public string Apply(string value) { return value.ToPascalCase(); } public string Reverse(string value) { return value.ToPascalCase(); } } internal sealed class UnderscoredNamingConvention : INamingConvention { public static readonly INamingConvention Instance = new UnderscoredNamingConvention(); [Obsolete("Use the Instance static field instead of creating new instances")] public UnderscoredNamingConvention() { } public string Apply(string value) { return value.FromCamelCase("_"); } public string Reverse(string value) { return value.ToPascalCase(); } } } namespace YamlDotNet.Serialization.EventEmitters { internal abstract class ChainedEventEmitter : IEventEmitter { protected readonly IEventEmitter nextEmitter; protected ChainedEventEmitter(IEventEmitter nextEmitter) { this.nextEmitter = nextEmitter ?? throw new ArgumentNullException("nextEmitter"); } public virtual void Emit(AliasEventInfo eventInfo, IEmitter emitter) { nextEmitter.Emit(eventInfo, emitter); } public virtual void Emit(ScalarEventInfo eventInfo, IEmitter emitter) { nextEmitter.Emit(eventInfo, emitter); } public virtual void Emit(MappingStartEventInfo eventInfo, IEmitter emitter) { nextEmitter.Emit(eventInfo, emitter); } public virtual void Emit(MappingEndEventInfo eventInfo, IEmitter emitter) { nextEmitter.Emit(eventInfo, emitter); } public virtual void Emit(SequenceStartEventInfo eventInfo, IEmitter emitter) { nextEmitter.Emit(eventInfo, emitter); } public virtual void Emit(SequenceEndEventInfo eventInfo, IEmitter emitter) { nextEmitter.Emit(eventInfo, emitter); } } internal sealed class JsonEventEmitter : ChainedEventEmitter { private readonly YamlFormatter formatter; private readonly INamingConvention enumNamingConvention; private readonly ITypeInspector typeInspector; public JsonEventEmitter(IEventEmitter nextEmitter, YamlFormatter formatter, INamingConvention enumNamingConvention, ITypeInspector typeInspector) : base(nextEmitter) { this.formatter = formatter; this.enumNamingConvention = enumNamingConvention; this.typeInspector = typeInspector; } public override void Emit(AliasEventInfo eventInfo, IEmitter emitter) { eventInfo.NeedsExpansion = true; } public override void Emit(ScalarEventInfo eventInfo, IEmitter emitter) { eventInfo.IsPlainImplicit = true; eventInfo.Style = ScalarStyle.Plain; object value = eventInfo.Source.Value; if (value == null) { eventInfo.RenderedValue = "null"; } else { TypeCode typeCode = eventInfo.Source.Type.GetTypeCode(); switch (typeCode) { case TypeCode.Boolean: eventInfo.RenderedValue = formatter.FormatBoolean(value); break; case TypeCode.SByte: case TypeCode.Byte: case TypeCode.Int16: case TypeCode.UInt16: case TypeCode.Int32: case TypeCode.UInt32: case TypeCode.Int64: case TypeCode.UInt64: if (eventInfo.Source.Type.IsEnum()) { eventInfo.RenderedValue = formatter.FormatEnum(value, typeInspector, enumNamingConvention); eventInfo.Style = ((!formatter.PotentiallyQuoteEnums(value)) ? ScalarStyle.Plain : ScalarStyle.DoubleQuoted); } else { eventInfo.RenderedValue = formatter.FormatNumber(value); } break; case TypeCode.Single: { float f = (float)value; eventInfo.RenderedValue = f.ToString("G", CultureInfo.InvariantCulture); if (float.IsNaN(f) || float.IsInfinity(f)) { eventInfo.Style = ScalarStyle.DoubleQuoted; } break; } case TypeCode.Double: { double d = (double)value; eventInfo.RenderedValue = d.ToString("G", CultureInfo.InvariantCulture); if (double.IsNaN(d) || double.IsInfinity(d)) { eventInfo.Style = ScalarStyle.DoubleQuoted; } break; } case TypeCode.Decimal: eventInfo.RenderedValue = ((decimal)value).ToString(CultureInfo.InvariantCulture); break; case TypeCode.Char: case TypeCode.String: eventInfo.RenderedValue = value.ToString(); eventInfo.Style = ScalarStyle.DoubleQuoted; break; case TypeCode.DateTime: eventInfo.RenderedValue = formatter.FormatDateTime(value); break; case TypeCode.Empty: eventInfo.RenderedValue = "null"; break; default: if (eventInfo.Source.Type == typeof(TimeSpan)) { eventInfo.RenderedValue = formatter.FormatTimeSpan(value); break; } throw new NotSupportedException($"TypeCode.{typeCode} is not supported."); } } base.Emit(eventInfo, emitter); } public override void Emit(MappingStartEventInfo eventInfo, IEmitter emitter) { eventInfo.Style = MappingStyle.Flow; base.Emit(eventInfo, emitter); } public override void Emit(SequenceStartEventInfo eventInfo, IEmitter emitter) { eventInfo.Style = SequenceStyle.Flow; base.Emit(eventInfo, emitter); } } internal sealed class TypeAssigningEventEmitter : ChainedEventEmitter { private readonly IDictionary tagMappings; private readonly bool quoteNecessaryStrings; private readonly Regex? isSpecialStringValue_Regex; private static readonly string SpecialStrings_Pattern = "^(null|Null|NULL|\\~|true|True|TRUE|false|False|FALSE|[-+]?[0-9]+|0o[0-7]+|0x[0-9a-fA-F]+|[-+]?(\\.[0-9]+|[0-9]+(\\.[0-9]*)?)([eE][-+]?[0-9]+)?|[-+]?(\\.inf|\\.Inf|\\.INF)|\\.nan|\\.NaN|\\.NAN|\\s.*)$"; private static readonly string CombinedYaml1_1SpecialStrings_Pattern = "^(null|Null|NULL|\\~|true|True|TRUE|false|False|FALSE|y|Y|yes|Yes|YES|n|N|no|No|NO|on|On|ON|off|Off|OFF|[-+]?0b[0-1_]+|[-+]?0o?[0-7_]+|[-+]?(0|[1-9][0-9_]*)|[-+]?0x[0-9a-fA-F_]+|[-+]?[1-9][0-9_]*(:[0-5]?[0-9])+|[-+]?([0-9][0-9_]*)?\\.[0-9_]*([eE][-+][0-9]+)?|[-+]?[0-9][0-9_]*(:[0-5]?[0-9])+\\.[0-9_]*|[-+]?\\.(inf|Inf|INF)|\\.(nan|NaN|NAN))$"; private readonly ScalarStyle defaultScalarStyle; private readonly YamlFormatter formatter; private readonly INamingConvention enumNamingConvention; private readonly ITypeInspector typeInspector; public TypeAssigningEventEmitter(IEventEmitter nextEmitter, IDictionary tagMappings, bool quoteNecessaryStrings, bool quoteYaml1_1Strings, ScalarStyle defaultScalarStyle, YamlFormatter formatter, INamingConvention enumNamingConvention, ITypeInspector typeInspector) : base(nextEmitter) { this.defaultScalarStyle = defaultScalarStyle; this.formatter = formatter; this.tagMappings = tagMappings; this.quoteNecessaryStrings = quoteNecessaryStrings; isSpecialStringValue_Regex = new Regex(quoteYaml1_1Strings ? CombinedYaml1_1SpecialStrings_Pattern : SpecialStrings_Pattern, RegexOptions.Compiled); this.enumNamingConvention = enumNamingConvention; this.typeInspector = typeInspector; } public override void Emit(ScalarEventInfo eventInfo, IEmitter emitter) { ScalarStyle style = ScalarStyle.Plain; object value = eventInfo.Source.Value; if (value == null) { eventInfo.Tag = JsonSchema.Tags.Null; eventInfo.RenderedValue = ""; } else { TypeCode typeCode = eventInfo.Source.Type.GetTypeCode(); switch (typeCode) { case TypeCode.Boolean: eventInfo.Tag = JsonSchema.Tags.Bool; eventInfo.RenderedValue = formatter.FormatBoolean(value); break; case TypeCode.SByte: case TypeCode.Byte: case TypeCode.Int16: case TypeCode.UInt16: case TypeCode.Int32: case TypeCode.UInt32: case TypeCode.Int64: case TypeCode.UInt64: if (eventInfo.Source.Type.IsEnum) { eventInfo.Tag = FailsafeSchema.Tags.Str; eventInfo.RenderedValue = formatter.FormatEnum(value, typeInspector, enumNamingConvention); style = ((!quoteNecessaryStrings || !IsSpecialStringValue(eventInfo.RenderedValue) || !formatter.PotentiallyQuoteEnums(value)) ? defaultScalarStyle : ScalarStyle.DoubleQuoted); } else { eventInfo.Tag = JsonSchema.Tags.Int; eventInfo.RenderedValue = formatter.FormatNumber(value); } break; case TypeCode.Single: eventInfo.Tag = JsonSchema.Tags.Float; eventInfo.RenderedValue = formatter.FormatNumber((float)value); break; case TypeCode.Double: eventInfo.Tag = JsonSchema.Tags.Float; eventInfo.RenderedValue = formatter.FormatNumber((double)value); break; case TypeCode.Decimal: eventInfo.Tag = JsonSchema.Tags.Float; eventInfo.RenderedValue = formatter.FormatNumber(value); break; case TypeCode.Char: case TypeCode.String: eventInfo.Tag = FailsafeSchema.Tags.Str; eventInfo.RenderedValue = value.ToString(); style = ((!quoteNecessaryStrings || !IsSpecialStringValue(eventInfo.RenderedValue)) ? defaultScalarStyle : ScalarStyle.DoubleQuoted); break; case TypeCode.DateTime: eventInfo.Tag = DefaultSchema.Tags.Timestamp; eventInfo.RenderedValue = formatter.FormatDateTime(value); break; case TypeCode.Empty: eventInfo.Tag = JsonSchema.Tags.Null; eventInfo.RenderedValue = ""; break; default: if (eventInfo.Source.Type == typeof(TimeSpan)) { eventInfo.RenderedValue = formatter.FormatTimeSpan(value); break; } throw new NotSupportedException($"TypeCode.{typeCode} is not supported."); } } eventInfo.IsPlainImplicit = true; if (eventInfo.Style == ScalarStyle.Any) { eventInfo.Style = style; } base.Emit(eventInfo, emitter); } public override void Emit(MappingStartEventInfo eventInfo, IEmitter emitter) { AssignTypeIfNeeded(eventInfo); base.Emit(eventInfo, emitter); } public override void Emit(SequenceStartEventInfo eventInfo, IEmitter emitter) { AssignTypeIfNeeded(eventInfo); base.Emit(eventInfo, emitter); } private void AssignTypeIfNeeded(ObjectEventInfo eventInfo) { if (tagMappings.TryGetValue(eventInfo.Source.Type, out var value)) { eventInfo.Tag = value; } } private bool IsSpecialStringValue(string value) { if (value.Trim() == string.Empty) { return true; } return isSpecialStringValue_Regex?.IsMatch(value) ?? false; } } internal sealed class WriterEventEmitter : IEventEmitter { void IEventEmitter.Emit(AliasEventInfo eventInfo, IEmitter emitter) { emitter.Emit(new YamlDotNet.Core.Events.AnchorAlias(eventInfo.Alias)); } void IEventEmitter.Emit(ScalarEventInfo eventInfo, IEmitter emitter) { emitter.Emit(new YamlDotNet.Core.Events.Scalar(eventInfo.Anchor, eventInfo.Tag, eventInfo.RenderedValue, eventInfo.Style, eventInfo.IsPlainImplicit, eventInfo.IsQuotedImplicit)); } void IEventEmitter.Emit(MappingStartEventInfo eventInfo, IEmitter emitter) { emitter.Emit(new MappingStart(eventInfo.Anchor, eventInfo.Tag, eventInfo.IsImplicit, eventInfo.Style)); } void IEventEmitter.Emit(MappingEndEventInfo eventInfo, IEmitter emitter) { emitter.Emit(new MappingEnd()); } void IEventEmitter.Emit(SequenceStartEventInfo eventInfo, IEmitter emitter) { emitter.Emit(new SequenceStart(eventInfo.Anchor, eventInfo.Tag, eventInfo.IsImplicit, eventInfo.Style)); } void IEventEmitter.Emit(SequenceEndEventInfo eventInfo, IEmitter emitter) { emitter.Emit(new SequenceEnd()); } } } namespace YamlDotNet.Serialization.Converters { internal class DateTime8601Converter : IYamlTypeConverter { private readonly ScalarStyle scalarStyle; public DateTime8601Converter() : this(ScalarStyle.Any) { } public DateTime8601Converter(ScalarStyle scalarStyle) { this.scalarStyle = scalarStyle; } public bool Accepts(Type type) { return type == typeof(DateTime); } public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer) { string value = parser.Consume().Value; DateTime dateTime = DateTime.ParseExact(value, "O", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind); return dateTime; } public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer) { string value2 = ((DateTime)value).ToString("O", CultureInfo.InvariantCulture); emitter.Emit(new YamlDotNet.Core.Events.Scalar(AnchorName.Empty, TagName.Empty, value2, scalarStyle, isPlainImplicit: true, isQuotedImplicit: false)); } } internal class DateTimeConverter : IYamlTypeConverter { private readonly DateTimeKind kind; private readonly IFormatProvider provider; private readonly bool doubleQuotes; private readonly string[] formats; public DateTimeConverter(DateTimeKind kind = DateTimeKind.Utc, IFormatProvider? provider = null, bool doubleQuotes = false, params string[] formats) { this.kind = ((kind == DateTimeKind.Unspecified) ? DateTimeKind.Utc : kind); this.provider = provider ?? CultureInfo.InvariantCulture; this.doubleQuotes = doubleQuotes; this.formats = formats.DefaultIfEmpty("G").ToArray(); } public bool Accepts(Type type) { return type == typeof(DateTime); } public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer) { string value = parser.Consume().Value; DateTimeStyles style = ((kind == DateTimeKind.Local) ? DateTimeStyles.AssumeLocal : DateTimeStyles.AssumeUniversal); DateTime dt = DateTime.ParseExact(value, formats, provider, style); dt = EnsureDateTimeKind(dt, kind); return dt; } public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer) { DateTime dateTime = (DateTime)value; string value2 = ((kind == DateTimeKind.Local) ? dateTime.ToLocalTime() : dateTime.ToUniversalTime()).ToString(formats.First(), provider); emitter.Emit(new YamlDotNet.Core.Events.Scalar(AnchorName.Empty, TagName.Empty, value2, doubleQuotes ? ScalarStyle.DoubleQuoted : ScalarStyle.Any, isPlainImplicit: true, isQuotedImplicit: false)); } private static DateTime EnsureDateTimeKind(DateTime dt, DateTimeKind kind) { if (dt.Kind == DateTimeKind.Local && kind == DateTimeKind.Utc) { return dt.ToUniversalTime(); } if (dt.Kind == DateTimeKind.Utc && kind == DateTimeKind.Local) { return dt.ToLocalTime(); } return dt; } } internal class DateTimeOffsetConverter : IYamlTypeConverter { private readonly IFormatProvider provider; private readonly ScalarStyle style; private readonly DateTimeStyles dateStyle; private readonly string[] formats; public DateTimeOffsetConverter(IFormatProvider? provider = null, ScalarStyle style = ScalarStyle.Any, DateTimeStyles dateStyle = DateTimeStyles.None, params string[] formats) { this.provider = provider ?? CultureInfo.InvariantCulture; this.style = style; this.dateStyle = dateStyle; this.formats = formats.DefaultIfEmpty("O").ToArray(); } public bool Accepts(Type type) { return type == typeof(DateTimeOffset); } public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer) { string value = parser.Consume().Value; DateTimeOffset dateTimeOffset = DateTimeOffset.ParseExact(value, formats, provider, dateStyle); return dateTimeOffset; } public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer) { string value2 = ((DateTimeOffset)value).ToString(formats.First(), provider); emitter.Emit(new YamlDotNet.Core.Events.Scalar(AnchorName.Empty, TagName.Empty, value2, style, isPlainImplicit: true, isQuotedImplicit: false)); } } internal class GuidConverter : IYamlTypeConverter { private readonly bool jsonCompatible; public GuidConverter(bool jsonCompatible) { this.jsonCompatible = jsonCompatible; } public bool Accepts(Type type) { return type == typeof(Guid); } public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer) { string value = parser.Consume().Value; return new Guid(value); } public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer) { Guid guid = (Guid)value; emitter.Emit(new YamlDotNet.Core.Events.Scalar(AnchorName.Empty, TagName.Empty, guid.ToString("D"), jsonCompatible ? ScalarStyle.DoubleQuoted : ScalarStyle.Any, isPlainImplicit: true, isQuotedImplicit: false)); } } internal class SystemTypeConverter : IYamlTypeConverter { public bool Accepts(Type type) { return typeof(Type).IsAssignableFrom(type); } public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer) { string value = parser.Consume().Value; return Type.GetType(value, throwOnError: true); } public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer) { Type type2 = (Type)value; emitter.Emit(new YamlDotNet.Core.Events.Scalar(AnchorName.Empty, TagName.Empty, type2.AssemblyQualifiedName, ScalarStyle.Any, isPlainImplicit: true, isQuotedImplicit: false)); } } } namespace YamlDotNet.Serialization.Callbacks { [AttributeUsage(AttributeTargets.Method)] internal sealed class OnDeserializedAttribute : Attribute { } [AttributeUsage(AttributeTargets.Method)] internal sealed class OnDeserializingAttribute : Attribute { } [AttributeUsage(AttributeTargets.Method)] internal sealed class OnSerializedAttribute : Attribute { } [AttributeUsage(AttributeTargets.Method)] internal sealed class OnSerializingAttribute : Attribute { } } namespace YamlDotNet.Serialization.BufferedDeserialization { internal interface ITypeDiscriminatingNodeDeserializerOptions { void AddTypeDiscriminator(ITypeDiscriminator discriminator); void AddKeyValueTypeDiscriminator(string discriminatorKey, IDictionary valueTypeMapping); void AddUniqueKeyTypeDiscriminator(IDictionary uniqueKeyTypeMapping); } internal class ParserBuffer : IParser { private readonly LinkedList buffer; private LinkedListNode? current; public ParsingEvent? Current => current?.Value; public ParserBuffer(IParser parserToBuffer, int maxDepth, int maxLength) { buffer = new LinkedList(); buffer.AddLast(parserToBuffer.Consume()); int num = 0; do { ParsingEvent parsingEvent = parserToBuffer.Consume(); num += parsingEvent.NestingIncrease; buffer.AddLast(parsingEvent); if (maxDepth > -1 && num > maxDepth) { throw new ArgumentOutOfRangeException("parserToBuffer", "Parser buffer exceeded max depth"); } if (maxLength > -1 && buffer.Count > maxLength) { throw new ArgumentOutOfRangeException("parserToBuffer", "Parser buffer exceeded max length"); } } while (num >= 0); current = buffer.First; } public bool MoveNext() { current = current?.Next; return current != null; } public void Reset() { current = buffer.First; } } internal class TypeDiscriminatingNodeDeserializer : INodeDeserializer { private readonly IList innerDeserializers; private readonly IList typeDiscriminators; private readonly int maxDepthToBuffer; private readonly int maxLengthToBuffer; public TypeDiscriminatingNodeDeserializer(IList innerDeserializers, IList typeDiscriminators, int maxDepthToBuffer, int maxLengthToBuffer) { this.innerDeserializers = innerDeserializers; this.typeDiscriminators = typeDiscriminators; this.maxDepthToBuffer = maxDepthToBuffer; this.maxLengthToBuffer = maxLengthToBuffer; } public bool Deserialize(IParser reader, Type expectedType, Func nestedObjectDeserializer, out object? value, ObjectDeserializer rootDeserializer) { Type expectedType2 = expectedType; if (!reader.Accept(out var _)) { value = null; return false; } IEnumerable enumerable = typeDiscriminators.Where((ITypeDiscriminator t) => t.BaseType.IsAssignableFrom(expectedType2)); if (!enumerable.Any()) { value = null; return false; } Mark start = reader.Current.Start; Type expectedType3 = expectedType2; ParserBuffer parserBuffer; try { parserBuffer = new ParserBuffer(reader, maxDepthToBuffer, maxLengthToBuffer); } catch (Exception innerException) { Mark end = reader.Current.End; throw new YamlException(in start, in end, "Failed to buffer yaml node", innerException); } try { foreach (ITypeDiscriminator item in enumerable) { parserBuffer.Reset(); if (item.TryDiscriminate(parserBuffer, out Type suggestedType)) { expectedType3 = suggestedType; break; } } } catch (Exception innerException2) { Mark end = reader.Current.End; throw new YamlException(in start, in end, "Failed to discriminate type", innerException2); } parserBuffer.Reset(); foreach (INodeDeserializer innerDeserializer in innerDeserializers) { if (innerDeserializer.Deserialize(parserBuffer, expectedType3, nestedObjectDeserializer, out value, rootDeserializer)) { return true; } } value = null; return false; } } internal class TypeDiscriminatingNodeDeserializerOptions : ITypeDiscriminatingNodeDeserializerOptions { internal readonly List discriminators = new List(); public void AddTypeDiscriminator(ITypeDiscriminator discriminator) { discriminators.Add(discriminator); } public void AddKeyValueTypeDiscriminator(string discriminatorKey, IDictionary valueTypeMapping) { discriminators.Add(new KeyValueTypeDiscriminator(typeof(T), discriminatorKey, valueTypeMapping)); } public void AddUniqueKeyTypeDiscriminator(IDictionary uniqueKeyTypeMapping) { discriminators.Add(new UniqueKeyTypeDiscriminator(typeof(T), uniqueKeyTypeMapping)); } } } namespace YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators { internal interface ITypeDiscriminator { Type BaseType { get; } bool TryDiscriminate(IParser buffer, out Type? suggestedType); } internal class KeyValueTypeDiscriminator : ITypeDiscriminator { private readonly string targetKey; private readonly IDictionary typeMapping; public Type BaseType { get; private set; } public KeyValueTypeDiscriminator(Type baseType, string targetKey, IDictionary typeMapping) { foreach (KeyValuePair item in typeMapping) { if (!baseType.IsAssignableFrom(item.Value)) { throw new ArgumentOutOfRangeException("typeMapping", $"{item.Value} is not a assignable to {baseType}"); } } BaseType = baseType; this.targetKey = targetKey; this.typeMapping = typeMapping; } public bool TryDiscriminate(IParser parser, out Type? suggestedType) { if (parser.TryFindMappingEntry((YamlDotNet.Core.Events.Scalar scalar) => targetKey == scalar.Value, out YamlDotNet.Core.Events.Scalar _, out ParsingEvent value) && value is YamlDotNet.Core.Events.Scalar scalar2 && typeMapping.TryGetValue(scalar2.Value, out Type value2)) { suggestedType = value2; return true; } suggestedType = null; return false; } } internal class UniqueKeyTypeDiscriminator : ITypeDiscriminator { private readonly IDictionary typeMapping; public Type BaseType { get; private set; } public UniqueKeyTypeDiscriminator(Type baseType, IDictionary typeMapping) { foreach (KeyValuePair item in typeMapping) { if (!baseType.IsAssignableFrom(item.Value)) { throw new ArgumentOutOfRangeException("typeMapping", $"{item.Value} is not a assignable to {baseType}"); } } BaseType = baseType; this.typeMapping = typeMapping; } public bool TryDiscriminate(IParser parser, out Type? suggestedType) { if (parser.TryFindMappingEntry((YamlDotNet.Core.Events.Scalar scalar) => typeMapping.ContainsKey(scalar.Value), out YamlDotNet.Core.Events.Scalar key, out ParsingEvent _)) { suggestedType = typeMapping[key.Value]; return true; } suggestedType = null; return false; } } } namespace YamlDotNet.RepresentationModel { internal class DocumentLoadingState { private readonly Dictionary anchors = new Dictionary(); private readonly List nodesWithUnresolvedAliases = new List(); public void AddAnchor(YamlNode node) { if (node.Anchor.IsEmpty) { throw new ArgumentException("The specified node does not have an anchor"); } anchors[node.Anchor] = node; } public YamlNode GetNode(AnchorName anchor, Mark start, Mark end) { if (anchors.TryGetValue(anchor, out YamlNode value)) { return value; } throw new AnchorNotFoundException(in start, in end, $"The anchor '{anchor}' does not exists"); } public bool TryGetNode(AnchorName anchor, [NotNullWhen(true)] out YamlNode? node) { return anchors.TryGetValue(anchor, out node); } public void AddNodeWithUnresolvedAliases(YamlNode node) { nodesWithUnresolvedAliases.Add(node); } public void ResolveAliases() { foreach (YamlNode nodesWithUnresolvedAlias in nodesWithUnresolvedAliases) { nodesWithUnresolvedAlias.ResolveAliases(this); } } } internal class EmitterState { public HashSet EmittedAnchors { get; } = new HashSet(); } internal interface IYamlVisitor { void Visit(YamlStream stream); void Visit(YamlDocument document); void Visit(YamlScalarNode scalar); void Visit(YamlSequenceNode sequence); void Visit(YamlMappingNode mapping); } internal class LibYamlEventStream { private readonly IParser parser; public LibYamlEventStream(IParser iParser) { parser = iParser ?? throw new ArgumentNullException("iParser"); } public void WriteTo(TextWriter textWriter) { while (parser.MoveNext()) { ParsingEvent current = parser.Current; if (!(current is YamlDotNet.Core.Events.AnchorAlias anchorAlias)) { if (!(current is YamlDotNet.Core.Events.DocumentEnd documentEnd)) { if (!(current is YamlDotNet.Core.Events.DocumentStart documentStart)) { if (!(current is MappingEnd)) { if (!(current is MappingStart nodeEvent)) { if (!(current is YamlDotNet.Core.Events.Scalar scalar)) { if (!(current is SequenceEnd)) { if (!(current is SequenceStart nodeEvent2)) { if (!(current is YamlDotNet.Core.Events.StreamEnd)) { if (current is YamlDotNet.Core.Events.StreamStart) { textWriter.Write("+STR"); } } else { textWriter.Write("-STR"); } } else { textWriter.Write("+SEQ"); WriteAnchorAndTag(textWriter, nodeEvent2); } } else { textWriter.Write("-SEQ"); } } else { textWriter.Write("=VAL"); WriteAnchorAndTag(textWriter, scalar); switch (scalar.Style) { case ScalarStyle.DoubleQuoted: textWriter.Write(" \""); break; case ScalarStyle.SingleQuoted: textWriter.Write(" '"); break; case ScalarStyle.Folded: textWriter.Write(" >"); break; case ScalarStyle.Literal: textWriter.Write(" |"); break; default: textWriter.Write(" :"); break; } string value = scalar.Value; foreach (char c in value) { switch (c) { case '\b': textWriter.Write("\\b"); break; case '\t': textWriter.Write("\\t"); break; case '\n': textWriter.Write("\\n"); break; case '\r': textWriter.Write("\\r"); break; case '\\': textWriter.Write("\\\\"); break; default: textWriter.Write(c); break; } } } } else { textWriter.Write("+MAP"); WriteAnchorAndTag(textWriter, nodeEvent); } } else { textWriter.Write("-MAP"); } } else { textWriter.Write("+DOC"); if (!documentStart.IsImplicit) { textWriter.Write(" ---"); } } } else { textWriter.Write("-DOC"); if (!documentEnd.IsImplicit) { textWriter.Write(" ..."); } } } else { textWriter.Write("=ALI *"); textWriter.Write(anchorAlias.Value); } textWriter.WriteLine(); } } private static void WriteAnchorAndTag(TextWriter textWriter, NodeEvent nodeEvent) { if (!nodeEvent.Anchor.IsEmpty) { textWriter.Write(" &"); textWriter.Write(nodeEvent.Anchor); } if (!nodeEvent.Tag.IsEmpty) { textWriter.Write(" <"); textWriter.Write(nodeEvent.Tag.Value); textWriter.Write(">"); } } } internal class YamlAliasNode : YamlNode { public override YamlNodeType NodeType => YamlNodeType.Alias; internal YamlAliasNode(AnchorName anchor) { base.Anchor = anchor; } internal override void ResolveAliases(DocumentLoadingState state) { throw new NotSupportedException("Resolving an alias on an alias node does not make sense"); } internal override void Emit(IEmitter emitter, EmitterState state) { throw new NotSupportedException("A YamlAliasNode is an implementation detail and should never be saved."); } public override void Accept(IYamlVisitor visitor) { throw new NotSupportedException("A YamlAliasNode is an implementation detail and should never be visited."); } public override bool Equals(object? obj) { if (obj is YamlAliasNode yamlAliasNode && Equals(yamlAliasNode)) { return object.Equals(base.Anchor, yamlAliasNode.Anchor); } return false; } public override int GetHashCode() { return base.GetHashCode(); } internal override string ToString(RecursionLevel level) { return "*" + base.Anchor; } internal override IEnumerable SafeAllNodes(RecursionLevel level) { yield return this; } } internal class YamlDocument { private class AnchorAssigningVisitor : YamlVisitorBase { private readonly HashSet existingAnchors = new HashSet(); private readonly Dictionary visitedNodes = new Dictionary(); public void AssignAnchors(YamlDocument document) { existingAnchors.Clear(); visitedNodes.Clear(); document.Accept(this); Random random = new Random(); foreach (KeyValuePair visitedNode in visitedNodes) { if (!visitedNode.Value) { continue; } AnchorName anchorName; if (!visitedNode.Key.Anchor.IsEmpty && !existingAnchors.Contains(visitedNode.Key.Anchor)) { anchorName = visitedNode.Key.Anchor; } else { do { anchorName = new AnchorName(random.Next().ToString(CultureInfo.InvariantCulture)); } while (existingAnchors.Contains(anchorName)); } existingAnchors.Add(anchorName); visitedNode.Key.Anchor = anchorName; } } private bool VisitNodeAndFindDuplicates(YamlNode node) { if (visitedNodes.TryGetValue(node, out var value)) { if (!value) { visitedNodes[node] = true; } return !value; } visitedNodes.Add(node, value: false); return false; } public override void Visit(YamlScalarNode scalar) { VisitNodeAndFindDuplicates(scalar); } public override void Visit(YamlMappingNode mapping) { if (!VisitNodeAndFindDuplicates(mapping)) { base.Visit(mapping); } } public override void Visit(YamlSequenceNode sequence) { if (!VisitNodeAndFindDuplicates(sequence)) { base.Visit(sequence); } } } public YamlNode RootNode { get; private set; } public IEnumerable AllNodes => RootNode.AllNodes; public YamlDocument(YamlNode rootNode) { RootNode = rootNode; } public YamlDocument(string rootNode) { RootNode = new YamlScalarNode(rootNode); } internal YamlDocument(IParser parser) { DocumentLoadingState documentLoadingState = new DocumentLoadingState(); parser.Consume(); YamlDotNet.Core.Events.DocumentEnd @event; while (!parser.TryConsume(out @event)) { RootNode = YamlNode.ParseNode(parser, documentLoadingState); if (RootNode is YamlAliasNode) { throw new YamlException("A document cannot contain only an alias"); } } documentLoadingState.ResolveAliases(); if (RootNode == null) { throw new ArgumentException("Atempted to parse an empty document"); } } private void AssignAnchors() { AnchorAssigningVisitor anchorAssigningVisitor = new AnchorAssigningVisitor(); anchorAssigningVisitor.AssignAnchors(this); } internal void Save(IEmitter emitter, bool assignAnchors = true) { if (assignAnchors) { AssignAnchors(); } emitter.Emit(new YamlDotNet.Core.Events.DocumentStart()); RootNode.Save(emitter, new EmitterState()); emitter.Emit(new YamlDotNet.Core.Events.DocumentEnd(isImplicit: false)); } public void Accept(IYamlVisitor visitor) { visitor.Visit(this); } } internal sealed class YamlMappingNode : YamlNode, IEnumerable>, IEnumerable, IYamlConvertible { private readonly OrderedDictionary children = new OrderedDictionary(); public IOrderedDictionary Children => children; public MappingStyle Style { get; set; } public override YamlNodeType NodeType => YamlNodeType.Mapping; internal YamlMappingNode(IParser parser, DocumentLoadingState state) { Load(parser, state); } private void Load(IParser parser, DocumentLoadingState state) { MappingStart mappingStart = parser.Consume(); Load(mappingStart, state); Style = mappingStart.Style; bool flag = false; MappingEnd @event; while (!parser.TryConsume(out @event)) { YamlNode yamlNode = YamlNode.ParseNode(parser, state); YamlNode yamlNode2 = YamlNode.ParseNode(parser, state); if (!children.TryAdd(yamlNode, yamlNode2)) { Mark start = yamlNode.Start; Mark end = yamlNode.End; throw new YamlException(in start, in end, $"Duplicate key {yamlNode}"); } flag = flag || yamlNode is YamlAliasNode || yamlNode2 is YamlAliasNode; } if (flag) { state.AddNodeWithUnresolvedAliases(this); } } public YamlMappingNode() { } public YamlMappingNode(params KeyValuePair[] children) : this((IEnumerable>)children) { } public YamlMappingNode(IEnumerable> children) { foreach (KeyValuePair child in children) { this.children.Add(child); } } public YamlMappingNode(params YamlNode[] children) : this((IEnumerable)children) { } public YamlMappingNode(IEnumerable children) { using IEnumerator enumerator = children.GetEnumerator(); while (enumerator.MoveNext()) { YamlNode current = enumerator.Current; if (!enumerator.MoveNext()) { throw new ArgumentException("When constructing a mapping node with a sequence, the number of elements of the sequence must be even."); } Add(current, enumerator.Current); } } public void Add(YamlNode key, YamlNode value) { children.Add(key, value); } public void Add(string key, YamlNode value) { children.Add(new YamlScalarNode(key), value); } public void Add(YamlNode key, string value) { children.Add(key, new YamlScalarNode(value)); } public void Add(string key, string value) { children.Add(new YamlScalarNode(key), new YamlScalarNode(value)); } internal override void ResolveAliases(DocumentLoadingState state) { Dictionary dictionary = null; Dictionary dictionary2 = null; foreach (KeyValuePair child in children) { if (child.Key is YamlAliasNode) { if (dictionary == null) { dictionary = new Dictionary(); } dictionary.Add(child.Key, state.GetNode(child.Key.Anchor, child.Key.Start, child.Key.End)); } if (child.Value is YamlAliasNode) { if (dictionary2 == null) { dictionary2 = new Dictionary(); } dictionary2.Add(child.Key, state.GetNode(child.Value.Anchor, child.Value.Start, child.Value.End)); } } if (dictionary2 != null) { foreach (KeyValuePair item in dictionary2) { children[item.Key] = item.Value; } } if (dictionary == null) { return; } foreach (KeyValuePair item2 in dictionary) { YamlNode value = children[item2.Key]; children.Remove(item2.Key); children.Add(item2.Value, value); } } internal override void Emit(IEmitter emitter, EmitterState state) { emitter.Emit(new MappingStart(base.Anchor, base.Tag, isImplicit: true, Style)); foreach (KeyValuePair child in children) { child.Key.Save(emitter, state); child.Value.Save(emitter, state); } emitter.Emit(new MappingEnd()); } public override void Accept(IYamlVisitor visitor) { visitor.Visit(this); } public override bool Equals(object? obj) { if (!(obj is YamlMappingNode yamlMappingNode) || !object.Equals(base.Tag, yamlMappingNode.Tag) || children.Count != yamlMappingNode.children.Count) { return false; } foreach (KeyValuePair child in children) { if (!yamlMappingNode.children.TryGetValue(child.Key, out YamlNode value) || !object.Equals(child.Value, value)) { return false; } } return true; } public override int GetHashCode() { int num = base.GetHashCode(); foreach (KeyValuePair child in children) { num = YamlDotNet.Core.HashCode.CombineHashCodes(num, child.Key); num = (child.Value.Anchor.IsEmpty ? YamlDotNet.Core.HashCode.CombineHashCodes(num, child.Value) : YamlDotNet.Core.HashCode.CombineHashCodes(num, child.Value.Anchor)); } return num; } internal override IEnumerable SafeAllNodes(RecursionLevel level) { level.Increment(); yield return this; foreach (KeyValuePair child in children) { foreach (YamlNode item in child.Key.SafeAllNodes(level)) { yield return item; } foreach (YamlNode item2 in child.Value.SafeAllNodes(level)) { yield return item2; } } level.Decrement(); } internal override string ToString(RecursionLevel level) { if (!level.TryIncrement()) { return "WARNING! INFINITE RECURSION!"; } StringBuilderPool.BuilderWrapper builderWrapper = StringBuilderPool.Rent(); try { StringBuilder builder = builderWrapper.Builder; builder.Append("{ "); foreach (KeyValuePair child in children) { if (builder.Length > 2) { builder.Append(", "); } builder.Append("{ ").Append(child.Key.ToString(level)).Append(", ") .Append(child.Value.ToString(level)) .Append(" }"); } builder.Append(" }"); level.Decrement(); return builder.ToString(); } finally { ((IDisposable)builderWrapper).Dispose(); } } public IEnumerator> GetEnumerator() { return children.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } void IYamlConvertible.Read(IParser parser, Type expectedType, ObjectDeserializer nestedObjectDeserializer) { Load(parser, new DocumentLoadingState()); } void IYamlConvertible.Write(IEmitter emitter, ObjectSerializer nestedObjectSerializer) { Emit(emitter, new EmitterState()); } public static YamlMappingNode FromObject(object mapping) { if (mapping == null) { throw new ArgumentNullException("mapping"); } YamlMappingNode yamlMappingNode = new YamlMappingNode(); foreach (PropertyInfo publicProperty in mapping.GetType().GetPublicProperties()) { if (publicProperty.CanRead && publicProperty.GetGetMethod(nonPublic: false).GetParameters().Length == 0) { object value = publicProperty.GetValue(mapping, null); YamlNode yamlNode = value as YamlNode; if (yamlNode == null) { string text = Convert.ToString(value, CultureInfo.InvariantCulture); yamlNode = text ?? string.Empty; } yamlMappingNode.Add(publicProperty.Name, yamlNode); } } return yamlMappingNode; } } internal abstract class YamlNode { private const int MaximumRecursionLevel = 1000; internal const string MaximumRecursionLevelReachedToStringValue = "WARNING! INFINITE RECURSION!"; public AnchorName Anchor { get; set; } public TagName Tag { get; set; } public Mark Start { get; private set; } = Mark.Empty; public Mark End { get; private set; } = Mark.Empty; public IEnumerable AllNodes { get { RecursionLevel level = new RecursionLevel(1000); return SafeAllNodes(level); } } public abstract YamlNodeType NodeType { get; } public YamlNode this[int index] { get { if (!(this is YamlSequenceNode yamlSequenceNode)) { throw new ArgumentException($"Accessed '{NodeType}' with an invalid index: {index}. Only Sequences can be indexed by number."); } return yamlSequenceNode.Children[index]; } } public YamlNode this[YamlNode key] { get { if (!(this is YamlMappingNode yamlMappingNode)) { throw new ArgumentException($"Accessed '{NodeType}' with an invalid index: {key}. Only Mappings can be indexed by key."); } return yamlMappingNode.Children[key]; } } internal void Load(NodeEvent yamlEvent, DocumentLoadingState state) { Tag = yamlEvent.Tag; if (!yamlEvent.Anchor.IsEmpty) { Anchor = yamlEvent.Anchor; state.AddAnchor(this); } Start = yamlEvent.Start; End = yamlEvent.End; } internal static YamlNode ParseNode(IParser parser, DocumentLoadingState state) { if (parser.Accept(out var _)) { return new YamlScalarNode(parser, state); } if (parser.Accept(out var _)) { return new YamlSequenceNode(parser, state); } if (parser.Accept(out var _)) { return new YamlMappingNode(parser, state); } if (parser.TryConsume(out var event4)) { if (!state.TryGetNode(event4.Value, out YamlNode node)) { return new YamlAliasNode(event4.Value); } return node; } throw new ArgumentException("The current event is of an unsupported type.", "parser"); } internal abstract void ResolveAliases(DocumentLoadingState state); internal void Save(IEmitter emitter, EmitterState state) { if (!Anchor.IsEmpty && !state.EmittedAnchors.Add(Anchor)) { emitter.Emit(new YamlDotNet.Core.Events.AnchorAlias(Anchor)); } else { Emit(emitter, state); } } internal abstract void Emit(IEmitter emitter, EmitterState state); public abstract void Accept(IYamlVisitor visitor); public override string ToString() { RecursionLevel recursionLevel = new RecursionLevel(1000); return ToString(recursionLevel); } internal abstract string ToString(RecursionLevel level); internal abstract IEnumerable SafeAllNodes(RecursionLevel level); public static implicit operator YamlNode(string value) { return new YamlScalarNode(value); } public static implicit operator YamlNode(string[] sequence) { return new YamlSequenceNode(((IEnumerable)sequence).Select((Func)((string i) => i))); } public static explicit operator string?(YamlNode node) { if (!(node is YamlScalarNode yamlScalarNode)) { throw new ArgumentException($"Attempted to convert a '{node.NodeType}' to string. This conversion is valid only for Scalars."); } return yamlScalarNode.Value; } } internal sealed class YamlNodeIdentityEqualityComparer : IEqualityComparer { public bool Equals([AllowNull] YamlNode x, [AllowNull] YamlNode y) { return x == y; } public int GetHashCode(YamlNode obj) { return obj.GetHashCode(); } } internal enum YamlNodeType { Alias, Mapping, Scalar, Sequence } [DebuggerDisplay("{Value}")] internal sealed class YamlScalarNode : YamlNode, IYamlConvertible { private bool forceImplicitPlain; private string? value; public string? Value { get { return value; } set { if (value == null) { forceImplicitPlain = true; } else { forceImplicitPlain = false; } this.value = value; } } public ScalarStyle Style { get; set; } public override YamlNodeType NodeType => YamlNodeType.Scalar; internal YamlScalarNode(IParser parser, DocumentLoadingState state) { Load(parser, state); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private void Load(IParser parser, DocumentLoadingState state) { YamlDotNet.Core.Events.Scalar scalar = parser.Consume(); Load(scalar, state); string text = scalar.Value; if (scalar.Style == ScalarStyle.Plain && base.Tag.IsEmpty) { forceImplicitPlain = text.Length switch { 0 => true, 1 => text == "~", 4 => text == "null" || text == "Null" || text == "NULL", _ => false, }; } value = text; Style = scalar.Style; } public YamlScalarNode() { } public YamlScalarNode(string? value) { Value = value; } internal override void ResolveAliases(DocumentLoadingState state) { throw new NotSupportedException("Resolving an alias on a scalar node does not make sense"); } internal override void Emit(IEmitter emitter, EmitterState state) { TagName tag = base.Tag; bool isPlainImplicit = tag.IsEmpty; if (forceImplicitPlain && Style == ScalarStyle.Plain && (Value == null || Value == "")) { tag = JsonSchema.Tags.Null; isPlainImplicit = true; } else if (tag.IsEmpty && Value == null && (Style == ScalarStyle.Plain || Style == ScalarStyle.Any)) { tag = JsonSchema.Tags.Null; isPlainImplicit = true; } emitter.Emit(new YamlDotNet.Core.Events.Scalar(base.Anchor, tag, Value ?? string.Empty, Style, isPlainImplicit, isQuotedImplicit: false)); } public override void Accept(IYamlVisitor visitor) { visitor.Visit(this); } public override bool Equals(object? obj) { if (obj is YamlScalarNode yamlScalarNode && object.Equals(base.Tag, yamlScalarNode.Tag)) { return object.Equals(Value, yamlScalarNode.Value); } return false; } public override int GetHashCode() { return YamlDotNet.Core.HashCode.CombineHashCodes(base.Tag.GetHashCode(), Value); } public static explicit operator string?(YamlScalarNode value) { return value.Value; } internal override string ToString(RecursionLevel level) { return Value ?? string.Empty; } internal override IEnumerable SafeAllNodes(RecursionLevel level) { yield return this; } void IYamlConvertible.Read(IParser parser, Type expectedType, ObjectDeserializer nestedObjectDeserializer) { Load(parser, new DocumentLoadingState()); } void IYamlConvertible.Write(IEmitter emitter, ObjectSerializer nestedObjectSerializer) { Emit(emitter, new EmitterState()); } } [DebuggerDisplay("Count = {children.Count}")] internal sealed class YamlSequenceNode : YamlNode, IEnumerable, IEnumerable, IYamlConvertible { private readonly List children = new List(); public IList Children => children; public SequenceStyle Style { get; set; } public override YamlNodeType NodeType => YamlNodeType.Sequence; internal YamlSequenceNode(IParser parser, DocumentLoadingState state) { Load(parser, state); } private void Load(IParser parser, DocumentLoadingState state) { SequenceStart sequenceStart = parser.Consume(); Load(sequenceStart, state); Style = sequenceStart.Style; bool flag = false; SequenceEnd @event; while (!parser.TryConsume(out @event)) { YamlNode yamlNode = YamlNode.ParseNode(parser, state); children.Add(yamlNode); flag = flag || yamlNode is YamlAliasNode; } if (flag) { state.AddNodeWithUnresolvedAliases(this); } } public YamlSequenceNode() { } public YamlSequenceNode(params YamlNode[] children) : this((IEnumerable)children) { } public YamlSequenceNode(IEnumerable children) { foreach (YamlNode child in children) { this.children.Add(child); } } public void Add(YamlNode child) { children.Add(child); } public void Add(string child) { children.Add(new YamlScalarNode(child)); } internal override void ResolveAliases(DocumentLoadingState state) { for (int i = 0; i < children.Count; i++) { if (children[i] is YamlAliasNode) { children[i] = state.GetNode(children[i].Anchor, children[i].Start, children[i].End); } } } internal override void Emit(IEmitter emitter, EmitterState state) { emitter.Emit(new SequenceStart(base.Anchor, base.Tag, base.Tag.IsEmpty, Style)); foreach (YamlNode child in children) { child.Save(emitter, state); } emitter.Emit(new SequenceEnd()); } public override void Accept(IYamlVisitor visitor) { visitor.Visit(this); } public override bool Equals(object? obj) { if (!(obj is YamlSequenceNode yamlSequenceNode) || !object.Equals(base.Tag, yamlSequenceNode.Tag) || children.Count != yamlSequenceNode.children.Count) { return false; } for (int i = 0; i < children.Count; i++) { if (!object.Equals(children[i], yamlSequenceNode.children[i])) { return false; } } return true; } public override int GetHashCode() { int h = 0; foreach (YamlNode child in children) { h = YamlDotNet.Core.HashCode.CombineHashCodes(h, child); } return YamlDotNet.Core.HashCode.CombineHashCodes(h, base.Tag); } internal override IEnumerable SafeAllNodes(RecursionLevel level) { level.Increment(); yield return this; foreach (YamlNode child in children) { foreach (YamlNode item in child.SafeAllNodes(level)) { yield return item; } } level.Decrement(); } internal override string ToString(RecursionLevel level) { if (!level.TryIncrement()) { return "WARNING! INFINITE RECURSION!"; } StringBuilderPool.BuilderWrapper builderWrapper = StringBuilderPool.Rent(); try { StringBuilder builder = builderWrapper.Builder; builder.Append("[ "); foreach (YamlNode child in children) { if (builder.Length > 2) { builder.Append(", "); } builder.Append(child.ToString(level)); } builder.Append(" ]"); level.Decrement(); return builder.ToString(); } finally { ((IDisposable)builderWrapper).Dispose(); } } public IEnumerator GetEnumerator() { return Children.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } void IYamlConvertible.Read(IParser parser, Type expectedType, ObjectDeserializer nestedObjectDeserializer) { Load(parser, new DocumentLoadingState()); } void IYamlConvertible.Write(IEmitter emitter, ObjectSerializer nestedObjectSerializer) { Emit(emitter, new EmitterState()); } } internal class YamlStream : IEnumerable, IEnumerable { private readonly List documents = new List(); public IList Documents => documents; public YamlStream() { } public YamlStream(params YamlDocument[] documents) : this((IEnumerable)documents) { } public YamlStream(IEnumerable documents) { foreach (YamlDocument document in documents) { this.documents.Add(document); } } public void Add(YamlDocument document) { documents.Add(document); } public void Load(TextReader input) { Load(new Parser(input)); } public void Load(IParser parser) { documents.Clear(); parser.Consume(); YamlDotNet.Core.Events.StreamEnd @event; while (!parser.TryConsume(out @event)) { YamlDocument item = new YamlDocument(parser); documents.Add(item); } } public void Save(TextWriter output) { Save(output, assignAnchors: true); } public void Save(TextWriter output, bool assignAnchors) { Save(new Emitter(output), assignAnchors); } public void Save(IEmitter emitter, bool assignAnchors) { emitter.Emit(new YamlDotNet.Core.Events.StreamStart()); foreach (YamlDocument document in documents) { document.Save(emitter, assignAnchors); } emitter.Emit(new YamlDotNet.Core.Events.StreamEnd()); } public void Accept(IYamlVisitor visitor) { visitor.Visit(this); } public IEnumerator GetEnumerator() { return documents.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } [Obsolete("Use YamlVisitorBase")] internal abstract class YamlVisitor : IYamlVisitor { protected virtual void Visit(YamlStream stream) { } protected virtual void Visited(YamlStream stream) { } protected virtual void Visit(YamlDocument document) { } protected virtual void Visited(YamlDocument document) { } protected virtual void Visit(YamlScalarNode scalar) { } protected virtual void Visited(YamlScalarNode scalar) { } protected virtual void Visit(YamlSequenceNode sequence) { } protected virtual void Visited(YamlSequenceNode sequence) { } protected virtual void Visit(YamlMappingNode mapping) { } protected virtual void Visited(YamlMappingNode mapping) { } protected virtual void VisitChildren(YamlStream stream) { foreach (YamlDocument document in stream.Documents) { document.Accept(this); } } protected virtual void VisitChildren(YamlDocument document) { if (document.RootNode != null) { document.RootNode.Accept(this); } } protected virtual void VisitChildren(YamlSequenceNode sequence) { foreach (YamlNode child in sequence.Children) { child.Accept(this); } } protected virtual void VisitChildren(YamlMappingNode mapping) { foreach (KeyValuePair child in mapping.Children) { child.Key.Accept(this); child.Value.Accept(this); } } void IYamlVisitor.Visit(YamlStream stream) { Visit(stream); VisitChildren(stream); Visited(stream); } void IYamlVisitor.Visit(YamlDocument document) { Visit(document); VisitChildren(document); Visited(document); } void IYamlVisitor.Visit(YamlScalarNode scalar) { Visit(scalar); Visited(scalar); } void IYamlVisitor.Visit(YamlSequenceNode sequence) { Visit(sequence); VisitChildren(sequence); Visited(sequence); } void IYamlVisitor.Visit(YamlMappingNode mapping) { Visit(mapping); VisitChildren(mapping); Visited(mapping); } } internal abstract class YamlVisitorBase : IYamlVisitor { public virtual void Visit(YamlStream stream) { VisitChildren(stream); } public virtual void Visit(YamlDocument document) { VisitChildren(document); } public virtual void Visit(YamlScalarNode scalar) { } public virtual void Visit(YamlSequenceNode sequence) { VisitChildren(sequence); } public virtual void Visit(YamlMappingNode mapping) { VisitChildren(mapping); } protected virtual void VisitPair(YamlNode key, YamlNode value) { key.Accept(this); value.Accept(this); } protected virtual void VisitChildren(YamlStream stream) { foreach (YamlDocument document in stream.Documents) { document.Accept(this); } } protected virtual void VisitChildren(YamlDocument document) { if (document.RootNode != null) { document.RootNode.Accept(this); } } protected virtual void VisitChildren(YamlSequenceNode sequence) { foreach (YamlNode child in sequence.Children) { child.Accept(this); } } protected virtual void VisitChildren(YamlMappingNode mapping) { foreach (KeyValuePair child in mapping.Children) { VisitPair(child.Key, child.Value); } } } } namespace YamlDotNet.Helpers { internal class DefaultFsharpHelper : IFsharpHelper { private static bool IsFsharpCore(Type t) { return t.Namespace == "Microsoft.FSharp.Core"; } public bool IsOptionType(Type t) { if (IsFsharpCore(t)) { return t.Name == "FSharpOption`1"; } return false; } public Type? GetOptionUnderlyingType(Type t) { if (!t.IsGenericType || !IsOptionType(t)) { return null; } return t.GenericTypeArguments[0]; } public object? GetValue(IObjectDescriptor objectDescriptor) { if (!IsOptionType(objectDescriptor.Type)) { throw new InvalidOperationException("Should not be called on non-Option<> type"); } if (objectDescriptor.Value == null) { return null; } return objectDescriptor.Type.GetProperty("Value").GetValue(objectDescriptor.Value); } public bool IsFsharpListType(Type t) { if (t.Namespace == "Microsoft.FSharp.Collections") { return t.Name == "FSharpList`1"; } return false; } public object? CreateFsharpListFromArray(Type t, Type itemsType, Array arr) { if (!IsFsharpListType(t)) { return null; } return t.Assembly.GetType("Microsoft.FSharp.Collections.ListModule").GetMethod("OfArray").MakeGenericMethod(itemsType) .Invoke(null, new object[1] { arr }); } } internal static class DictionaryExtensions { public static bool TryAdd(this Dictionary dictionary, T key, V value) { if (dictionary.ContainsKey(key)) { return false; } dictionary.Add(key, value); return true; } public static TValue GetOrAdd(this ConcurrentDictionary dictionary, TKey key, Func valueFactory, TArg arg) { if (dictionary == null) { throw new ArgumentNullException("dictionary"); } if (key == null) { throw new ArgumentNullException("key"); } if (valueFactory == null) { throw new ArgumentNullException("valueFactory"); } TValue value; do { if (dictionary.TryGetValue(key, out value)) { return value; } value = valueFactory(key, arg); } while (!dictionary.TryAdd(key, value)); return value; } } internal static class ExpressionExtensions { public static PropertyInfo AsProperty(this LambdaExpression propertyAccessor) { PropertyInfo propertyInfo = TryGetMemberExpression(propertyAccessor); if (propertyInfo == null) { throw new ArgumentException("Expected a lambda expression in the form: x => x.SomeProperty", "propertyAccessor"); } return propertyInfo; } [return: MaybeNull] private static TMemberInfo TryGetMemberExpression(LambdaExpression lambdaExpression) where TMemberInfo : MemberInfo { if (lambdaExpression.Parameters.Count != 1) { return null; } Expression expression = lambdaExpression.Body; if (expression is UnaryExpression unaryExpression) { if (unaryExpression.NodeType != ExpressionType.Convert) { return null; } expression = unaryExpression.Operand; } if (expression is MemberExpression memberExpression) { if (memberExpression.Expression != lambdaExpression.Parameters[0]) { return null; } return memberExpression.Member as TMemberInfo; } return null; } } internal static class FsharpHelper { public static IFsharpHelper? Instance { get; set; } public static bool IsOptionType(Type t) { return Instance?.IsOptionType(t) ?? false; } public static Type? GetOptionUnderlyingType(Type t) { return Instance?.GetOptionUnderlyingType(t); } public static object? GetValue(IObjectDescriptor objectDescriptor) { return Instance?.GetValue(objectDescriptor); } public static bool IsFsharpListType(Type t) { return Instance?.IsFsharpListType(t) ?? false; } public static object? CreateFsharpListFromArray(Type t, Type itemsType, Array arr) { return Instance?.CreateFsharpListFromArray(t, itemsType, arr); } } internal sealed class GenericCollectionToNonGenericAdapter : IList, ICollection, IEnumerable { private readonly ICollection genericCollection; public bool IsFixedSize { get { throw new NotSupportedException(); } } public bool IsReadOnly { get { throw new NotSupportedException(); } } public object? this[int index] { get { throw new NotSupportedException(); } set { ((IList)genericCollection)[index] = (T)value; } } public int Count { get { throw new NotSupportedException(); } } public bool IsSynchronized { get { throw new NotSupportedException(); } } public object SyncRoot { get { throw new NotSupportedException(); } } public GenericCollectionToNonGenericAdapter(ICollection genericCollection) { this.genericCollection = genericCollection ?? throw new ArgumentNullException("genericCollection"); } public int Add(object? value) { int count = genericCollection.Count; genericCollection.Add((T)value); return count; } public void Clear() { genericCollection.Clear(); } public bool Contains(object? value) { throw new NotSupportedException(); } public int IndexOf(object? value) { throw new NotSupportedException(); } public void Insert(int index, object? value) { throw new NotSupportedException(); } public void Remove(object? value) { throw new NotSupportedException(); } public void RemoveAt(int index) { throw new NotSupportedException(); } public void CopyTo(Array array, int index) { throw new NotSupportedException(); } public IEnumerator GetEnumerator() { return genericCollection.GetEnumerator(); } } internal sealed class GenericDictionaryToNonGenericAdapter : IDictionary, ICollection, IEnumerable where TKey : notnull { private class DictionaryEnumerator : IDictionaryEnumerator, IEnumerator { private readonly IEnumerator> enumerator; public DictionaryEntry Entry => new DictionaryEntry(Key, Value); public object Key => enumerator.Current.Key; public object? Value => enumerator.Current.Value; public object Current => Entry; public DictionaryEnumerator(IEnumerator> enumerator) { this.enumerator = enumerator; } public bool MoveNext() { return enumerator.MoveNext(); } public void Reset() { enumerator.Reset(); } } private readonly IDictionary genericDictionary; public bool IsFixedSize { get { throw new NotSupportedException(); } } public bool IsReadOnly { get { throw new NotSupportedException(); } } public ICollection Keys { get { throw new NotSupportedException(); } } public ICollection Values { get { throw new NotSupportedException(); } } public object? this[object key] { get { throw new NotSupportedException(); } set { genericDictionary[(TKey)key] = (TValue)value; } } public int Count { get { throw new NotSupportedException(); } } public bool IsSynchronized { get { throw new NotSupportedException(); } } public object SyncRoot { get { throw new NotSupportedException(); } } public GenericDictionaryToNonGenericAdapter(IDictionary genericDictionary) { this.genericDictionary = genericDictionary ?? throw new ArgumentNullException("genericDictionary"); } public void Add(object key, object? value) { throw new NotSupportedException(); } public void Clear() { throw new NotSupportedException(); } public bool Contains(object key) { throw new NotSupportedException(); } public IDictionaryEnumerator GetEnumerator() { return new DictionaryEnumerator(genericDictionary.GetEnumerator()); } public void Remove(object key) { throw new NotSupportedException(); } public void CopyTo(Array array, int index) { throw new NotSupportedException(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } internal interface IFsharpHelper { bool IsOptionType(Type t); Type? GetOptionUnderlyingType(Type t); object? GetValue(IObjectDescriptor objectDescriptor); bool IsFsharpListType(Type t); object? CreateFsharpListFromArray(Type t, Type itemsType, Array arr); } internal interface IOrderedDictionary : IDictionary, ICollection>, IEnumerable>, IEnumerable where TKey : notnull { KeyValuePair this[int index] { get; set; } void Insert(int index, TKey key, TValue value); void RemoveAt(int index); } internal class NullFsharpHelper : IFsharpHelper { public object? CreateFsharpListFromArray(Type t, Type itemsType, Array arr) { return null; } public Type? GetOptionUnderlyingType(Type t) { return null; } public object? GetValue(IObjectDescriptor objectDescriptor) { return null; } public bool IsFsharpListType(Type t) { return false; } public bool IsOptionType(Type t) { return false; } } internal static class NumberExtensions { public static bool IsPowerOfTwo(this int value) { return (value & (value - 1)) == 0; } } [Serializable] internal sealed class OrderedDictionary : IOrderedDictionary, IDictionary, ICollection>, IEnumerable>, IEnumerable where TKey : notnull { private class KeyCollection : ICollection, IEnumerable, IEnumerable { private readonly OrderedDictionary orderedDictionary; public int Count => orderedDictionary.list.Count; public bool IsReadOnly => true; public void Add(TKey item) { throw new NotSupportedException(); } public void Clear() { throw new NotSupportedException(); } public bool Contains(TKey item) { return orderedDictionary.dictionary.ContainsKey(item); } public KeyCollection(OrderedDictionary orderedDictionary) { this.orderedDictionary = orderedDictionary; } public void CopyTo(TKey[] array, int arrayIndex) { for (int i = 0; i < orderedDictionary.list.Count; i++) { array[i] = orderedDictionary.list[i + arrayIndex].Key; } } public IEnumerator GetEnumerator() { return orderedDictionary.list.Select((KeyValuePair kvp) => kvp.Key).GetEnumerator(); } public bool Remove(TKey item) { throw new NotSupportedException(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } private class ValueCollection : ICollection, IEnumerable, IEnumerable { private readonly OrderedDictionary orderedDictionary; public int Count => orderedDictionary.list.Count; public bool IsReadOnly => true; public void Add(TValue item) { throw new NotSupportedException(); } public void Clear() { throw new NotSupportedException(); } public bool Contains(TValue item) { return orderedDictionary.dictionary.ContainsValue(item); } public ValueCollection(OrderedDictionary orderedDictionary) { this.orderedDictionary = orderedDictionary; } public void CopyTo(TValue[] array, int arrayIndex) { for (int i = 0; i < orderedDictionary.list.Count; i++) { array[i] = orderedDictionary.list[i + arrayIndex].Value; } } public IEnumerator GetEnumerator() { return orderedDictionary.list.Select((KeyValuePair kvp) => kvp.Value).GetEnumerator(); } public bool Remove(TValue item) { throw new NotSupportedException(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } [NonSerialized] private Dictionary dictionary; private readonly List> list; private readonly IEqualityComparer comparer; public TValue this[TKey key] { get { return dictionary[key]; } set { TKey key2 = key; if (dictionary.ContainsKey(key2)) { int index = list.FindIndex((KeyValuePair kvp) => comparer.Equals(kvp.Key, key2)); dictionary[key2] = value; list[index] = new KeyValuePair(key2, value); } else { Add(key2, value); } } } public ICollection Keys => new KeyCollection(this); public ICollection Values => new ValueCollection(this); public int Count => dictionary.Count; public bool IsReadOnly => false; public KeyValuePair this[int index] { get { return list[index]; } set { list[index] = value; } } public OrderedDictionary() : this((IEqualityComparer)EqualityComparer.Default) { } public OrderedDictionary(IEqualityComparer comparer) { list = new List>(); dictionary = new Dictionary(comparer); this.comparer = comparer; } public void Add(KeyValuePair item) { if (!TryAdd(item)) { ThrowDuplicateKeyException(item.Key); } } public void Add(TKey key, TValue value) { if (!TryAdd(key, value)) { ThrowDuplicateKeyException(key); } } private static void ThrowDuplicateKeyException(TKey key) { throw new ArgumentException($"An item with the same key {key} has already been added."); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool TryAdd(TKey key, TValue value) { if (DictionaryExtensions.TryAdd(dictionary, key, value)) { list.Add(new KeyValuePair(key, value)); return true; } return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool TryAdd(KeyValuePair item) { if (DictionaryExtensions.TryAdd(dictionary, item.Key, item.Value)) { list.Add(item); return true; } return false; } public void Clear() { dictionary.Clear(); list.Clear(); } public bool Contains(KeyValuePair item) { return dictionary.Contains(item); } public bool ContainsKey(TKey key) { return dictionary.ContainsKey(key); } public void CopyTo(KeyValuePair[] array, int arrayIndex) { list.CopyTo(array, arrayIndex); } public IEnumerator> GetEnumerator() { return list.GetEnumerator(); } public void Insert(int index, TKey key, TValue value) { dictionary.Add(key, value); list.Insert(index, new KeyValuePair(key, value)); } public bool Remove(TKey key) { TKey key2 = key; if (dictionary.ContainsKey(key2)) { int index = list.FindIndex((KeyValuePair kvp) => comparer.Equals(kvp.Key, key2)); list.RemoveAt(index); if (!dictionary.Remove(key2)) { throw new InvalidOperationException(); } return true; } return false; } public bool Remove(KeyValuePair item) { return Remove(item.Key); } public void RemoveAt(int index) { TKey key = list[index].Key; dictionary.Remove(key); list.RemoveAt(index); } public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value) { return dictionary.TryGetValue(key, out value); } IEnumerator IEnumerable.GetEnumerator() { return list.GetEnumerator(); } [System.Runtime.Serialization.OnDeserialized] internal void OnDeserializedMethod(StreamingContext context) { dictionary = new Dictionary(); foreach (KeyValuePair item in list) { dictionary[item.Key] = item.Value; } } } internal static class ReadOnlyCollectionExtensions { public static IReadOnlyList AsReadonlyList(this List list) { return list; } public static IReadOnlyDictionary AsReadonlyDictionary(this Dictionary dictionary) where TKey : notnull { return dictionary; } } internal static class ThrowHelper { [MethodImpl(MethodImplOptions.NoInlining)] public static void ThrowArgumentOutOfRangeException(string paramName, string message) { throw new ArgumentOutOfRangeException(paramName, message); } } } namespace YamlDotNet.Core { internal readonly struct AnchorName : IEquatable { public static readonly AnchorName Empty; private static readonly Regex AnchorPattern = new Regex("^[^\\[\\]\\{\\},]+$", RegexOptions.Compiled); private readonly string? value; public string Value => value ?? throw new InvalidOperationException("Cannot read the Value of an empty anchor"); public bool IsEmpty => value == null; public AnchorName(string value) { this.value = value ?? throw new ArgumentNullException("value"); if (!AnchorPattern.IsMatch(value)) { throw new ArgumentException("Anchor cannot be empty or contain disallowed characters: []{},\nThe value was '" + value + "'.", "value"); } } public override string ToString() { return value ?? "[empty]"; } public bool Equals(AnchorName other) { return object.Equals(value, other.value); } public override bool Equals(object? obj) { if (obj is AnchorName other) { return Equals(other); } return false; } public override int GetHashCode() { return value?.GetHashCode() ?? 0; } public static bool operator ==(AnchorName left, AnchorName right) { return left.Equals(right); } public static bool operator !=(AnchorName left, AnchorName right) { return !(left == right); } public static implicit operator AnchorName(string? value) { if (value != null) { return new AnchorName(value); } return Empty; } } internal class AnchorNotFoundException : YamlException { public AnchorNotFoundException(string message) : base(message) { } public AnchorNotFoundException(in Mark start, in Mark end, string message) : base(in start, in end, message) { } public AnchorNotFoundException(string message, Exception inner) : base(message, inner) { } } [DebuggerStepThrough] internal readonly struct CharacterAnalyzer where TBuffer : ILookAheadBuffer { public TBuffer Buffer { get; } public bool EndOfInput => Buffer.EndOfInput; public CharacterAnalyzer(TBuffer buffer) { if (buffer == null) { throw new ArgumentNullException("buffer"); } Buffer = buffer; } public char Peek(int offset) { return Buffer.Peek(offset); } public void Skip(int length) { Buffer.Skip(length); } public bool IsAlphaNumericDashOrUnderscore(int offset = 0) { char c = Buffer.Peek(offset); if ((c < '0' || c > '9') && (c < 'A' || c > 'Z') && (c < 'a' || c > 'z') && c != '_') { return c == '-'; } return true; } public bool IsAscii(int offset = 0) { return Buffer.Peek(offset) <= '\u007f'; } public bool IsPrintable(int offset = 0) { char c = Buffer.Peek(offset); switch (c) { default: if (c != '\u0085' && (c < '\u00a0' || c > '\ud7ff')) { if (c >= '\ue000') { return c <= '\ufffd'; } return false; } break; case '\t': case '\n': case '\r': case ' ': case '!': case '"': case '#': case '$': case '%': case '&': case '\'': case '(': case ')': case '*': case '+': case ',': case '-': case '.': case '/': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case ':': case ';': case '<': case '=': case '>': case '?': case '@': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': case '[': case '\\': case ']': case '^': case '_': case '`': case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': case '{': case '|': case '}': case '~': break; } return true; } public bool IsDigit(int offset = 0) { char c = Buffer.Peek(offset); if (c >= '0') { return c <= '9'; } return false; } public int AsDigit(int offset = 0) { return Buffer.Peek(offset) - 48; } public bool IsHex(int offset) { char c = Buffer.Peek(offset); if ((c < '0' || c > '9') && (c < 'A' || c > 'F')) { if (c >= 'a') { return c <= 'f'; } return false; } return true; } public int AsHex(int offset) { char c = Buffer.Peek(offset); if (c <= '9') { return c - 48; } if (c <= 'F') { return c - 65 + 10; } return c - 97 + 10; } public bool IsSpace(int offset = 0) { return Check(' ', offset); } public bool IsZero(int offset = 0) { return Check('\0', offset); } public bool IsTab(int offset = 0) { return Check('\t', offset); } public bool IsWhite(int offset = 0) { if (!IsSpace(offset)) { return IsTab(offset); } return true; } public bool IsBreak(int offset = 0) { return Check("\r\n\u0085\u2028\u2029", offset); } public bool IsCrLf(int offset = 0) { if (Check('\r', offset)) { return Check('\n', offset + 1); } return false; } public bool IsBreakOrZero(int offset = 0) { if (!IsBreak(offset)) { return IsZero(offset); } return true; } public bool IsWhiteBreakOrZero(int offset = 0) { if (!IsWhite(offset)) { return IsBreakOrZero(offset); } return true; } public bool Check(char expected, int offset = 0) { return Buffer.Peek(offset) == expected; } public bool Check(string expectedCharacters, int offset = 0) { char c = Buffer.Peek(offset); return Polyfills.Contains(expectedCharacters, c); } } internal static class Constants { public static readonly TagDirective[] DefaultTagDirectives = new TagDirective[2] { new TagDirective("!", "!"), new TagDirective("!!", "tag:yaml.org,2002:") }; public const int MajorVersion = 1; public const int MinorVersion = 3; } [DebuggerStepThrough] internal sealed class Cursor { public long Index { get; private set; } public long Line { get; private set; } public long LineOffset { get; private set; } public Cursor() { Line = 1L; } public Cursor(Cursor cursor) { Index = cursor.Index; Line = cursor.Line; LineOffset = cursor.LineOffset; } public Mark Mark() { return new Mark(Index, Line, LineOffset + 1); } public void Skip() { Index++; LineOffset++; } public void SkipLineByOffset(int offset) { Index += offset; Line++; LineOffset = 0L; } public void ForceSkipLineAfterNonBreak() { if (LineOffset != 0L) { Line++; LineOffset = 0L; } } } internal class Emitter : IEmitter { private class AnchorData { public AnchorName Anchor; public bool IsAlias; } private class TagData { public string? Handle; public string? Suffix; } private class ScalarData { public string Value = string.Empty; public bool IsMultiline; public bool IsFlowPlainAllowed; public bool IsBlockPlainAllowed; public bool IsSingleQuotedAllowed; public bool IsBlockAllowed; public bool HasSingleQuotes; public ScalarStyle Style; } private static readonly Regex UriReplacer = new Regex("[^0-9A-Za-z_\\-;?@=$~\\\\\\)\\]/:&+,\\.\\*\\(\\[!]", RegexOptions.Compiled | RegexOptions.Singleline); private static readonly string[] NewLineSeparators = new string[3] { "\r\n", "\r", "\n" }; private readonly TextWriter output; private readonly bool outputUsesUnicodeEncoding; private readonly int maxSimpleKeyLength; private readonly bool isCanonical; private readonly bool skipAnchorName; private readonly int bestIndent; private readonly int bestWidth; private EmitterState state; private readonly Stack states = new Stack(); private readonly Queue events = new Queue(); private readonly Stack indents = new Stack(); private readonly TagDirectiveCollection tagDirectives = new TagDirectiveCollection(); private int indent; private int flowLevel; private bool isMappingContext; private bool isSimpleKeyContext; private int column; private bool isWhitespace; private bool isIndentation; private readonly bool forceIndentLess; private readonly bool useUtf16SurrogatePair; private bool isDocumentEndWritten; private readonly AnchorData anchorData = new AnchorData(); private readonly TagData tagData = new TagData(); private readonly ScalarData scalarData = new ScalarData(); public Emitter(TextWriter output) : this(output, EmitterSettings.Default) { } public Emitter(TextWriter output, int bestIndent) : this(output, bestIndent, int.MaxValue) { } public Emitter(TextWriter output, int bestIndent, int bestWidth) : this(output, bestIndent, bestWidth, isCanonical: false) { } public Emitter(TextWriter output, int bestIndent, int bestWidth, bool isCanonical) : this(output, new EmitterSettings(bestIndent, bestWidth, isCanonical, 1024)) { } public Emitter(TextWriter output, EmitterSettings settings) { bestIndent = settings.BestIndent; bestWidth = settings.BestWidth; isCanonical = settings.IsCanonical; maxSimpleKeyLength = settings.MaxSimpleKeyLength; skipAnchorName = settings.SkipAnchorName; forceIndentLess = !settings.IndentSequences; useUtf16SurrogatePair = settings.UseUtf16SurrogatePairs; this.output = output; this.output.NewLine = settings.NewLine; outputUsesUnicodeEncoding = IsUnicode(output.Encoding); } public void Emit(ParsingEvent @event) { events.Enqueue(@event); while (!NeedMoreEvents()) { ParsingEvent evt = events.Peek(); try { AnalyzeEvent(evt); StateMachine(evt); } finally { events.Dequeue(); } } } private bool NeedMoreEvents() { if (events.Count == 0) { return true; } int num; switch (events.Peek().Type) { case EventType.DocumentStart: num = 1; break; case EventType.SequenceStart: num = 2; break; case EventType.MappingStart: num = 3; break; default: return false; } if (events.Count > num) { return false; } int num2 = 0; foreach (ParsingEvent @event in events) { switch (@event.Type) { case EventType.DocumentStart: case EventType.SequenceStart: case EventType.MappingStart: num2++; break; case EventType.DocumentEnd: case EventType.SequenceEnd: case EventType.MappingEnd: num2--; break; } if (num2 == 0) { return false; } } return true; } private void AnalyzeEvent(ParsingEvent evt) { anchorData.Anchor = AnchorName.Empty; tagData.Handle = null; tagData.Suffix = null; if (evt is YamlDotNet.Core.Events.AnchorAlias anchorAlias) { AnalyzeAnchor(anchorAlias.Value, isAlias: true); } else if (evt is NodeEvent nodeEvent) { if (evt is YamlDotNet.Core.Events.Scalar scalar) { AnalyzeScalar(scalar); } AnalyzeAnchor(nodeEvent.Anchor, isAlias: false); if (!nodeEvent.Tag.IsEmpty && (isCanonical || nodeEvent.IsCanonical)) { AnalyzeTag(nodeEvent.Tag); } } } private void AnalyzeAnchor(AnchorName anchor, bool isAlias) { anchorData.Anchor = anchor; anchorData.IsAlias = isAlias; } private void AnalyzeScalar(YamlDotNet.Core.Events.Scalar scalar) { string value = scalar.Value; scalarData.Value = value; if (value.Length == 0) { if (scalar.Tag == "tag:yaml.org,2002:null") { scalarData.IsMultiline = false; scalarData.IsFlowPlainAllowed = false; scalarData.IsBlockPlainAllowed = true; scalarData.IsSingleQuotedAllowed = false; scalarData.IsBlockAllowed = false; } else { scalarData.IsMultiline = false; scalarData.IsFlowPlainAllowed = false; scalarData.IsBlockPlainAllowed = false; scalarData.IsSingleQuotedAllowed = true; scalarData.IsBlockAllowed = false; } return; } bool flag = false; bool flag2 = false; if (value.StartsWith("---", StringComparison.Ordinal) || value.StartsWith("...", StringComparison.Ordinal)) { flag = true; flag2 = true; } StringLookAheadBufferPool.BufferWrapper bufferWrapper = StringLookAheadBufferPool.Rent(value); try { CharacterAnalyzer characterAnalyzer = new CharacterAnalyzer(bufferWrapper.Buffer); bool flag3 = true; bool flag4 = characterAnalyzer.IsWhiteBreakOrZero(1); bool flag5 = false; bool flag6 = false; bool flag7 = false; bool flag8 = false; bool flag9 = false; bool flag10 = false; bool flag11 = false; bool flag12 = false; bool flag13 = false; bool flag14 = false; bool flag15 = false; bool flag16 = !ValueIsRepresentableInOutputEncoding(value); bool flag17 = false; bool flag18 = false; bool flag19 = true; while (!characterAnalyzer.EndOfInput) { if (flag19) { if (characterAnalyzer.Check("#,[]{}&*!|>\"%@`'")) { flag = true; flag2 = true; flag9 = characterAnalyzer.Check('\''); flag17 |= characterAnalyzer.Check('\''); } if (characterAnalyzer.Check("?:")) { flag = true; if (flag4) { flag2 = true; } } if (characterAnalyzer.Check('-') && flag4) { flag = true; flag2 = true; } } else { if (characterAnalyzer.Check(",?[]{}")) { flag = true; } if (characterAnalyzer.Check(':')) { flag = true; if (flag4) { flag2 = true; } } if (characterAnalyzer.Check('#') && flag3) { flag = true; flag2 = true; } flag17 |= characterAnalyzer.Check('\''); } if (!flag16 && !characterAnalyzer.IsPrintable()) { flag16 = true; } if (characterAnalyzer.IsBreak()) { flag15 = true; } if (characterAnalyzer.IsSpace()) { if (flag19) { flag5 = true; } if (characterAnalyzer.Buffer.Position >= characterAnalyzer.Buffer.Length - 1) { flag7 = true; } if (flag13) { flag10 = true; flag14 = true; } flag12 = true; flag13 = false; } else if (characterAnalyzer.IsBreak()) { if (flag19) { flag6 = true; } if (characterAnalyzer.Buffer.Position >= characterAnalyzer.Buffer.Length - 1) { flag8 = true; } if (flag12) { flag11 = true; } if (flag14) { flag18 = true; } flag12 = false; flag13 = true; } else { flag12 = false; flag13 = false; flag14 = false; } flag3 = characterAnalyzer.IsWhiteBreakOrZero(); characterAnalyzer.Skip(1); if (!characterAnalyzer.EndOfInput) { flag4 = characterAnalyzer.IsWhiteBreakOrZero(1); } flag19 = false; } scalarData.IsFlowPlainAllowed = true; scalarData.IsBlockPlainAllowed = true; scalarData.IsSingleQuotedAllowed = true; scalarData.IsBlockAllowed = true; if (flag5 || flag6 || flag7 || flag8 || flag9) { scalarData.IsFlowPlainAllowed = false; scalarData.IsBlockPlainAllowed = false; } if (flag7) { scalarData.IsBlockAllowed = false; } if (flag10) { scalarData.IsFlowPlainAllowed = false; scalarData.IsBlockPlainAllowed = false; scalarData.IsSingleQuotedAllowed = false; } if (flag11 || flag16) { scalarData.IsFlowPlainAllowed = false; scalarData.IsBlockPlainAllowed = false; scalarData.IsSingleQuotedAllowed = false; } if (flag18) { scalarData.IsBlockAllowed = false; } scalarData.IsMultiline = flag15; if (flag15) { scalarData.IsFlowPlainAllowed = false; scalarData.IsBlockPlainAllowed = false; } if (flag) { scalarData.IsFlowPlainAllowed = false; } if (flag2) { scalarData.IsBlockPlainAllowed = false; } scalarData.HasSingleQuotes = flag17; } finally { ((IDisposable)bufferWrapper).Dispose(); } } private bool ValueIsRepresentableInOutputEncoding(string value) { if (outputUsesUnicodeEncoding) { return true; } try { byte[] bytes = output.Encoding.GetBytes(value); string @string = output.Encoding.GetString(bytes, 0, bytes.Length); return @string.Equals(value); } catch (EncoderFallbackException) { return false; } catch (ArgumentOutOfRangeException) { return false; } } private static bool IsUnicode(Encoding encoding) { if (!(encoding is UTF8Encoding) && !(encoding is UnicodeEncoding)) { return encoding is UTF7Encoding; } return true; } private void AnalyzeTag(TagName tag) { tagData.Handle = tag.Value; foreach (TagDirective tagDirective in tagDirectives) { if (tag.Value.StartsWith(tagDirective.Prefix, StringComparison.Ordinal)) { tagData.Handle = tagDirective.Handle; tagData.Suffix = tag.Value.Substring(tagDirective.Prefix.Length); break; } } } private void StateMachine(ParsingEvent evt) { if (evt is YamlDotNet.Core.Events.Comment comment) { EmitComment(comment); return; } switch (state) { case EmitterState.StreamStart: EmitStreamStart(evt); break; case EmitterState.FirstDocumentStart: EmitDocumentStart(evt, isFirst: true); break; case EmitterState.DocumentStart: EmitDocumentStart(evt, isFirst: false); break; case EmitterState.DocumentContent: EmitDocumentContent(evt); break; case EmitterState.DocumentEnd: EmitDocumentEnd(evt); break; case EmitterState.FlowSequenceFirstItem: EmitFlowSequenceItem(evt, isFirst: true); break; case EmitterState.FlowSequenceItem: EmitFlowSequenceItem(evt, isFirst: false); break; case EmitterState.FlowMappingFirstKey: EmitFlowMappingKey(evt, isFirst: true); break; case EmitterState.FlowMappingKey: EmitFlowMappingKey(evt, isFirst: false); break; case EmitterState.FlowMappingSimpleValue: EmitFlowMappingValue(evt, isSimple: true); break; case EmitterState.FlowMappingValue: EmitFlowMappingValue(evt, isSimple: false); break; case EmitterState.BlockSequenceFirstItem: EmitBlockSequenceItem(evt, isFirst: true); break; case EmitterState.BlockSequenceItem: EmitBlockSequenceItem(evt, isFirst: false); break; case EmitterState.BlockMappingFirstKey: EmitBlockMappingKey(evt, isFirst: true); break; case EmitterState.BlockMappingKey: EmitBlockMappingKey(evt, isFirst: false); break; case EmitterState.BlockMappingSimpleValue: EmitBlockMappingValue(evt, isSimple: true); break; case EmitterState.BlockMappingValue: EmitBlockMappingValue(evt, isSimple: false); break; case EmitterState.StreamEnd: throw new YamlException("Expected nothing after STREAM-END"); default: throw new InvalidOperationException(); } } private void EmitComment(YamlDotNet.Core.Events.Comment comment) { if (flowLevel > 0 || state == EmitterState.FlowMappingFirstKey || state == EmitterState.FlowSequenceFirstItem) { return; } string[] array = comment.Value.Split(NewLineSeparators, StringSplitOptions.None); if (comment.IsInline) { Write(" # "); Write(string.Join(" ", array)); } else { bool flag = state == EmitterState.BlockMappingFirstKey; if (flag) { IncreaseIndent(isFlow: false, isIndentless: false); } string[] array2 = array; foreach (string value in array2) { WriteIndent(); Write("# "); Write(value); WriteBreak(); } if (flag) { indent = indents.Pop(); } } isIndentation = true; } private void EmitStreamStart(ParsingEvent evt) { if (!(evt is YamlDotNet.Core.Events.StreamStart)) { throw new ArgumentException("Expected STREAM-START.", "evt"); } indent = -1; column = 0; isWhitespace = true; isIndentation = true; state = EmitterState.FirstDocumentStart; } private void EmitDocumentStart(ParsingEvent evt, bool isFirst) { if (evt is YamlDotNet.Core.Events.DocumentStart documentStart) { bool flag = documentStart.IsImplicit && isFirst && !isCanonical; TagDirectiveCollection tagDirectiveCollection = NonDefaultTagsAmong(documentStart.Tags); if (!isFirst && !isDocumentEndWritten && (documentStart.Version != null || tagDirectiveCollection.Count > 0)) { isDocumentEndWritten = false; WriteIndicator("...", needWhitespace: true, whitespace: false, indentation: false); WriteIndent(); } if (documentStart.Version != null) { AnalyzeVersionDirective(documentStart.Version); Version version = documentStart.Version.Version; flag = false; WriteIndicator("%YAML", needWhitespace: true, whitespace: false, indentation: false); WriteIndicator(string.Format(CultureInfo.InvariantCulture, "{0}.{1}", version.Major, version.Minor), needWhitespace: true, whitespace: false, indentation: false); WriteIndent(); } foreach (TagDirective item in tagDirectiveCollection) { AppendTagDirectiveTo(item, allowDuplicates: false, tagDirectives); } TagDirective[] defaultTagDirectives = Constants.DefaultTagDirectives; foreach (TagDirective value in defaultTagDirectives) { AppendTagDirectiveTo(value, allowDuplicates: true, tagDirectives); } if (tagDirectiveCollection.Count > 0) { flag = false; TagDirective[] defaultTagDirectives2 = Constants.DefaultTagDirectives; foreach (TagDirective value2 in defaultTagDirectives2) { AppendTagDirectiveTo(value2, allowDuplicates: true, tagDirectiveCollection); } foreach (TagDirective item2 in tagDirectiveCollection) { WriteIndicator("%TAG", needWhitespace: true, whitespace: false, indentation: false); WriteTagHandle(item2.Handle); WriteTagContent(item2.Prefix, needsWhitespace: true); WriteIndent(); } } if (CheckEmptyDocument()) { flag = false; } if (!flag) { WriteIndent(); WriteIndicator("---", needWhitespace: true, whitespace: false, indentation: false); if (isCanonical) { WriteIndent(); } } state = EmitterState.DocumentContent; } else { if (!(evt is YamlDotNet.Core.Events.StreamEnd)) { throw new YamlException("Expected DOCUMENT-START or STREAM-END"); } state = EmitterState.StreamEnd; } } private static TagDirectiveCollection NonDefaultTagsAmong(IEnumerable? tagCollection) { TagDirectiveCollection tagDirectiveCollection = new TagDirectiveCollection(); if (tagCollection == null) { return tagDirectiveCollection; } foreach (TagDirective item2 in tagCollection) { AppendTagDirectiveTo(item2, allowDuplicates: false, tagDirectiveCollection); } TagDirective[] defaultTagDirectives = Constants.DefaultTagDirectives; foreach (TagDirective item in defaultTagDirectives) { tagDirectiveCollection.Remove(item); } return tagDirectiveCollection; } private static void AnalyzeVersionDirective(VersionDirective versionDirective) { if (versionDirective.Version.Major != 1 || versionDirective.Version.Minor > 3) { throw new YamlException("Incompatible %YAML directive"); } } private static void AppendTagDirectiveTo(TagDirective value, bool allowDuplicates, TagDirectiveCollection tagDirectives) { if (tagDirectives.Contains(value)) { if (!allowDuplicates) { throw new YamlException("Duplicate %TAG directive."); } } else { tagDirectives.Add(value); } } private void EmitDocumentContent(ParsingEvent evt) { states.Push(EmitterState.DocumentEnd); EmitNode(evt, isMapping: false, isSimpleKey: false); } private void EmitNode(ParsingEvent evt, bool isMapping, bool isSimpleKey) { isMappingContext = isMapping; isSimpleKeyContext = isSimpleKey; switch (evt.Type) { case EventType.Alias: EmitAlias(); break; case EventType.Scalar: EmitScalar(evt); break; case EventType.SequenceStart: EmitSequenceStart(evt); break; case EventType.MappingStart: EmitMappingStart(evt); break; default: throw new YamlException($"Expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS, got {evt.Type}"); } } private void EmitAlias() { ProcessAnchor(); state = states.Pop(); } private void EmitScalar(ParsingEvent evt) { SelectScalarStyle(evt); ProcessAnchor(); ProcessTag(); IncreaseIndent(isFlow: true, isIndentless: false); ProcessScalar(); indent = indents.Pop(); state = states.Pop(); } private void SelectScalarStyle(ParsingEvent evt) { YamlDotNet.Core.Events.Scalar scalar = (YamlDotNet.Core.Events.Scalar)evt; ScalarStyle scalarStyle = scalar.Style; bool flag = tagData.Handle == null && tagData.Suffix == null; if (flag && !scalar.IsPlainImplicit && !scalar.IsQuotedImplicit) { throw new YamlException("Neither tag nor isImplicit flags are specified."); } if (scalarStyle == ScalarStyle.Any) { scalarStyle = ((!scalarData.IsMultiline) ? ScalarStyle.Plain : ScalarStyle.Folded); } if (isCanonical) { scalarStyle = ScalarStyle.DoubleQuoted; } if (isSimpleKeyContext && scalarData.IsMultiline) { scalarStyle = ScalarStyle.DoubleQuoted; } if (scalarStyle == ScalarStyle.Plain) { if ((flowLevel != 0 && !scalarData.IsFlowPlainAllowed) || (flowLevel == 0 && !scalarData.IsBlockPlainAllowed)) { scalarStyle = ((scalarData.IsSingleQuotedAllowed && !scalarData.HasSingleQuotes) ? ScalarStyle.SingleQuoted : ScalarStyle.DoubleQuoted); } if (string.IsNullOrEmpty(scalarData.Value) && (flowLevel != 0 || isSimpleKeyContext)) { scalarStyle = ScalarStyle.SingleQuoted; } if (flag && !scalar.IsPlainImplicit) { scalarStyle = ScalarStyle.SingleQuoted; } } if (scalarStyle == ScalarStyle.SingleQuoted && !scalarData.IsSingleQuotedAllowed) { scalarStyle = ScalarStyle.DoubleQuoted; } if ((scalarStyle == ScalarStyle.Literal || scalarStyle == ScalarStyle.Folded) && (!scalarData.IsBlockAllowed || flowLevel != 0 || isSimpleKeyContext)) { scalarStyle = ScalarStyle.DoubleQuoted; } if (scalarStyle == ScalarStyle.ForcePlain) { scalarStyle = ScalarStyle.Plain; } scalarData.Style = scalarStyle; } private void ProcessScalar() { switch (scalarData.Style) { case ScalarStyle.Plain: WritePlainScalar(scalarData.Value, !isSimpleKeyContext); break; case ScalarStyle.SingleQuoted: WriteSingleQuotedScalar(scalarData.Value, !isSimpleKeyContext); break; case ScalarStyle.DoubleQuoted: WriteDoubleQuotedScalar(scalarData.Value, !isSimpleKeyContext); break; case ScalarStyle.Literal: WriteLiteralScalar(scalarData.Value); break; case ScalarStyle.Folded: WriteFoldedScalar(scalarData.Value); break; default: throw new InvalidOperationException(); } } private void WritePlainScalar(string value, bool allowBreaks) { if (!isWhitespace) { Write(' '); } bool flag = false; bool flag2 = false; for (int i = 0; i < value.Length; i++) { char c = value[i]; if (IsSpace(c)) { if (allowBreaks && !flag && column > bestWidth && i + 1 < value.Length && value[i + 1] != ' ') { WriteIndent(); } else { Write(c); } flag = true; continue; } if (IsBreak(c, out var breakChar)) { if (!flag2 && c == '\n') { WriteBreak(); } WriteBreak(breakChar); isIndentation = true; flag2 = true; continue; } if (flag2) { WriteIndent(); } Write(c); isIndentation = false; flag = false; flag2 = false; } isWhitespace = false; isIndentation = false; } private void WriteSingleQuotedScalar(string value, bool allowBreaks) { WriteIndicator("'", needWhitespace: true, whitespace: false, indentation: false); bool flag = false; bool flag2 = false; for (int i = 0; i < value.Length; i++) { char c = value[i]; if (c == ' ') { if (allowBreaks && !flag && column > bestWidth && i != 0 && i + 1 < value.Length && value[i + 1] != ' ') { WriteIndent(); } else { Write(c); } flag = true; continue; } if (IsBreak(c, out var breakChar)) { if (!flag2 && c == '\n') { WriteBreak(); } WriteBreak(breakChar); isIndentation = true; flag2 = true; continue; } if (flag2) { WriteIndent(); } if (c == '\'') { Write(c); } Write(c); isIndentation = false; flag = false; flag2 = false; } WriteIndicator("'", needWhitespace: false, whitespace: false, indentation: false); isWhitespace = false; isIndentation = false; } private void WriteDoubleQuotedScalar(string value, bool allowBreaks) { WriteIndicator("\"", needWhitespace: true, whitespace: false, indentation: false); bool flag = false; for (int i = 0; i < value.Length; i++) { char c = value[i]; if (IsPrintable(c) && !IsBreak(c, out var _)) { switch (c) { case '"': case '\\': break; case ' ': if (allowBreaks && !flag && column > bestWidth && i > 0 && i + 1 < value.Length) { WriteIndent(); if (value[i + 1] == ' ') { Write('\\'); } } else { Write(c); } flag = true; continue; default: Write(c); flag = false; continue; } } Write('\\'); switch (c) { case '\0': Write('0'); break; case '\a': Write('a'); break; case '\b': Write('b'); break; case '\t': Write('t'); break; case '\n': Write('n'); break; case '\v': Write('v'); break; case '\f': Write('f'); break; case '\r': Write('r'); break; case '\u001b': Write('e'); break; case '"': Write('"'); break; case '\\': Write('\\'); break; case '\u0085': Write('N'); break; case '\u00a0': Write('_'); break; case '\u2028': Write('L'); break; case '\u2029': Write('P'); break; default: { ushort num = c; if (num <= 255) { Write('x'); Write(num.ToString("X02", CultureInfo.InvariantCulture)); } else if (IsHighSurrogate(c)) { if (i + 1 >= value.Length || !IsLowSurrogate(value[i + 1])) { throw new SyntaxErrorException("While writing a quoted scalar, found an orphaned high surrogate."); } if (useUtf16SurrogatePair) { Write('u'); Write(num.ToString("X04", CultureInfo.InvariantCulture)); Write('\\'); Write('u'); Write(((ushort)value[i + 1]).ToString("X04", CultureInfo.InvariantCulture)); } else { Write('U'); Write(char.ConvertToUtf32(c, value[i + 1]).ToString("X08", CultureInfo.InvariantCulture)); } i++; } else { Write('u'); Write(num.ToString("X04", CultureInfo.InvariantCulture)); } break; } } flag = false; } WriteIndicator("\"", needWhitespace: false, whitespace: false, indentation: false); isWhitespace = false; isIndentation = false; } private void WriteLiteralScalar(string value) { bool flag = true; WriteIndicator("|", needWhitespace: true, whitespace: false, indentation: false); WriteBlockScalarHints(value); WriteBreak(); isIndentation = true; isWhitespace = true; for (int i = 0; i < value.Length; i++) { char c = value[i]; if (c == '\r' && i + 1 < value.Length && value[i + 1] == '\n') { continue; } if (IsBreak(c, out var breakChar)) { WriteBreak(breakChar); isIndentation = true; flag = true; continue; } if (flag) { WriteIndent(); } Write(c); isIndentation = false; flag = false; } } private void WriteFoldedScalar(string value) { bool flag = true; bool flag2 = true; WriteIndicator(">", needWhitespace: true, whitespace: false, indentation: false); WriteBlockScalarHints(value); WriteBreak(); isIndentation = true; isWhitespace = true; for (int i = 0; i < value.Length; i++) { char c = value[i]; if (IsBreak(c, out var breakChar)) { if (c == '\r' && i + 1 < value.Length && value[i + 1] == '\n') { continue; } if (!flag && !flag2 && breakChar == '\n') { int j; char breakChar2; for (j = 0; i + j < value.Length && IsBreak(value[i + j], out breakChar2); j++) { } if (i + j < value.Length && !IsBlank(value[i + j]) && !IsBreak(value[i + j], out breakChar2)) { WriteBreak(); } } WriteBreak(breakChar); isIndentation = true; flag = true; } else { if (flag) { WriteIndent(); flag2 = IsBlank(c); } if (!flag && c == ' ' && i + 1 < value.Length && value[i + 1] != ' ' && column > bestWidth) { WriteIndent(); } else { Write(c); } isIndentation = false; flag = false; } } } private static bool IsSpace(char character) { return character == ' '; } private static bool IsBreak(char character, out char breakChar) { switch (character) { case '\n': case '\r': case '\u0085': breakChar = '\n'; return true; case '\u2028': case '\u2029': breakChar = character; return true; default: breakChar = '\0'; return false; } } private static bool IsBlank(char character) { if (character != ' ') { return character == '\t'; } return true; } private static bool IsPrintable(char character) { switch (character) { default: if (character != '\u0085' && (character < '\u00a0' || character > '\ud7ff')) { if (character >= '\ue000') { return character <= '\ufffd'; } return false; } break; case '\t': case '\n': case '\r': case ' ': case '!': case '"': case '#': case '$': case '%': case '&': case '\'': case '(': case ')': case '*': case '+': case ',': case '-': case '.': case '/': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case ':': case ';': case '<': case '=': case '>': case '?': case '@': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': case '[': case '\\': case ']': case '^': case '_': case '`': case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': case '{': case '|': case '}': case '~': break; } return true; } private static bool IsHighSurrogate(char c) { if ('\ud800' <= c) { return c <= '\udbff'; } return false; } private static bool IsLowSurrogate(char c) { if ('\udc00' <= c) { return c <= '\udfff'; } return false; } private void EmitSequenceStart(ParsingEvent evt) { ProcessAnchor(); ProcessTag(); SequenceStart sequenceStart = (SequenceStart)evt; if (flowLevel != 0 || isCanonical || sequenceStart.Style == SequenceStyle.Flow || CheckEmptySequence()) { state = EmitterState.FlowSequenceFirstItem; } else { state = EmitterState.BlockSequenceFirstItem; } } private void EmitMappingStart(ParsingEvent evt) { ProcessAnchor(); ProcessTag(); MappingStart mappingStart = (MappingStart)evt; if (flowLevel != 0 || isCanonical || mappingStart.Style == MappingStyle.Flow || CheckEmptyMapping()) { state = EmitterState.FlowMappingFirstKey; } else { state = EmitterState.BlockMappingFirstKey; } } private void ProcessAnchor() { if (!anchorData.Anchor.IsEmpty && !skipAnchorName) { WriteIndicator(anchorData.IsAlias ? "*" : "&", needWhitespace: true, whitespace: false, indentation: false); WriteAnchor(anchorData.Anchor); } } private void ProcessTag() { if (tagData.Handle == null && tagData.Suffix == null) { return; } if (tagData.Handle != null) { WriteTagHandle(tagData.Handle); if (tagData.Suffix != null) { WriteTagContent(tagData.Suffix, needsWhitespace: false); } } else { WriteIndicator("!<", needWhitespace: true, whitespace: false, indentation: false); WriteTagContent(tagData.Suffix, needsWhitespace: false); WriteIndicator(">", needWhitespace: false, whitespace: false, indentation: false); } } private void EmitDocumentEnd(ParsingEvent evt) { if (evt is YamlDotNet.Core.Events.DocumentEnd documentEnd) { WriteIndent(); if (!documentEnd.IsImplicit) { WriteIndicator("...", needWhitespace: true, whitespace: false, indentation: false); WriteIndent(); isDocumentEndWritten = true; } state = EmitterState.DocumentStart; tagDirectives.Clear(); return; } throw new YamlException("Expected DOCUMENT-END."); } private void EmitFlowSequenceItem(ParsingEvent evt, bool isFirst) { if (isFirst) { WriteIndicator("[", needWhitespace: true, whitespace: true, indentation: false); IncreaseIndent(isFlow: true, isIndentless: false); flowLevel++; } if (evt is SequenceEnd) { flowLevel--; indent = indents.Pop(); if (isCanonical && !isFirst) { WriteIndicator(",", needWhitespace: false, whitespace: false, indentation: false); WriteIndent(); } WriteIndicator("]", needWhitespace: false, whitespace: false, indentation: false); state = states.Pop(); } else { if (!isFirst) { WriteIndicator(",", needWhitespace: false, whitespace: false, indentation: false); } if (isCanonical || column > bestWidth) { WriteIndent(); } states.Push(EmitterState.FlowSequenceItem); EmitNode(evt, isMapping: false, isSimpleKey: false); } } private void EmitFlowMappingKey(ParsingEvent evt, bool isFirst) { if (isFirst) { WriteIndicator("{", needWhitespace: true, whitespace: true, indentation: false); IncreaseIndent(isFlow: true, isIndentless: false); flowLevel++; } if (evt is MappingEnd) { flowLevel--; indent = indents.Pop(); if (isCanonical && !isFirst) { WriteIndicator(",", needWhitespace: false, whitespace: false, indentation: false); WriteIndent(); } WriteIndicator("}", needWhitespace: false, whitespace: false, indentation: false); state = states.Pop(); return; } if (!isFirst) { WriteIndicator(",", needWhitespace: false, whitespace: false, indentation: false); } if (isCanonical || column > bestWidth) { WriteIndent(); } if (!isCanonical && CheckSimpleKey()) { states.Push(EmitterState.FlowMappingSimpleValue); EmitNode(evt, isMapping: true, isSimpleKey: true); } else { WriteIndicator("?", needWhitespace: true, whitespace: false, indentation: false); states.Push(EmitterState.FlowMappingValue); EmitNode(evt, isMapping: true, isSimpleKey: false); } } private void EmitFlowMappingValue(ParsingEvent evt, bool isSimple) { if (isSimple) { WriteIndicator(":", needWhitespace: false, whitespace: false, indentation: false); } else { if (isCanonical || column > bestWidth) { WriteIndent(); } WriteIndicator(":", needWhitespace: true, whitespace: false, indentation: false); } states.Push(EmitterState.FlowMappingKey); EmitNode(evt, isMapping: true, isSimpleKey: false); } private void EmitBlockSequenceItem(ParsingEvent evt, bool isFirst) { if (isFirst) { IncreaseIndent(isFlow: false, isMappingContext && !isIndentation); } if (evt is SequenceEnd) { indent = indents.Pop(); state = states.Pop(); return; } WriteIndent(); WriteIndicator("-", needWhitespace: true, whitespace: false, indentation: true); states.Push(EmitterState.BlockSequenceItem); EmitNode(evt, isMapping: false, isSimpleKey: false); } private void EmitBlockMappingKey(ParsingEvent evt, bool isFirst) { if (isFirst) { IncreaseIndent(isFlow: false, isIndentless: false); } if (evt is MappingEnd) { indent = indents.Pop(); state = states.Pop(); return; } WriteIndent(); if (CheckSimpleKey()) { states.Push(EmitterState.BlockMappingSimpleValue); EmitNode(evt, isMapping: true, isSimpleKey: true); WriteIndicator(":", needWhitespace: false, whitespace: false, indentation: false); } else { WriteIndicator("?", needWhitespace: true, whitespace: false, indentation: true); states.Push(EmitterState.BlockMappingValue); EmitNode(evt, isMapping: true, isSimpleKey: false); } } private void EmitBlockMappingValue(ParsingEvent evt, bool isSimple) { if (!isSimple) { WriteIndent(); WriteIndicator(":", needWhitespace: true, whitespace: false, indentation: true); } states.Push(EmitterState.BlockMappingKey); EmitNode(evt, isMapping: true, isSimpleKey: false); } private void IncreaseIndent(bool isFlow, bool isIndentless) { indents.Push(indent); if (indent < 0) { indent = (isFlow ? bestIndent : 0); } else if (!isIndentless || !forceIndentLess) { indent += bestIndent; } } private bool CheckEmptyDocument() { int num = 0; foreach (ParsingEvent @event in events) { num++; if (num == 2) { if (@event is YamlDotNet.Core.Events.Scalar scalar) { return string.IsNullOrEmpty(scalar.Value); } break; } } return false; } private bool CheckSimpleKey() { if (events.Count < 1) { return false; } int num; switch (events.Peek().Type) { case EventType.Alias: num = AnchorNameLength(anchorData.Anchor); break; case EventType.Scalar: if (scalarData.IsMultiline) { return false; } num = AnchorNameLength(anchorData.Anchor) + SafeStringLength(tagData.Handle) + SafeStringLength(tagData.Suffix) + SafeStringLength(scalarData.Value); break; case EventType.SequenceStart: if (!CheckEmptySequence()) { return false; } num = AnchorNameLength(anchorData.Anchor) + SafeStringLength(tagData.Handle) + SafeStringLength(tagData.Suffix); break; case EventType.MappingStart: if (!CheckEmptySequence()) { return false; } num = AnchorNameLength(anchorData.Anchor) + SafeStringLength(tagData.Handle) + SafeStringLength(tagData.Suffix); break; default: return false; } return num <= maxSimpleKeyLength; } private static int AnchorNameLength(AnchorName value) { if (!value.IsEmpty) { return value.Value.Length; } return 0; } private static int SafeStringLength(string? value) { return value?.Length ?? 0; } private bool CheckEmptySequence() { return CheckEmptyStructure(); } private bool CheckEmptyMapping() { return CheckEmptyStructure(); } private bool CheckEmptyStructure() where TStart : NodeEvent where TEnd : ParsingEvent { if (events.Count < 2) { return false; } using Queue.Enumerator enumerator = events.GetEnumerator(); return enumerator.MoveNext() && enumerator.Current is TStart && enumerator.MoveNext() && enumerator.Current is TEnd; } private void WriteBlockScalarHints(string value) { StringLookAheadBufferPool.BufferWrapper bufferWrapper = StringLookAheadBufferPool.Rent(value); try { CharacterAnalyzer characterAnalyzer = new CharacterAnalyzer(bufferWrapper.Buffer); if (characterAnalyzer.IsSpace() || characterAnalyzer.IsBreak()) { int num = bestIndent; string indicator = num.ToString(CultureInfo.InvariantCulture); WriteIndicator(indicator, needWhitespace: false, whitespace: false, indentation: false); } string text = null; if (value.Length == 0 || !characterAnalyzer.IsBreak(value.Length - 1)) { text = "-"; } else if (value.Length >= 2 && characterAnalyzer.IsBreak(value.Length - 2)) { text = "+"; } if (text != null) { WriteIndicator(text, needWhitespace: false, whitespace: false, indentation: false); } } finally { ((IDisposable)bufferWrapper).Dispose(); } } private void WriteIndicator(string indicator, bool needWhitespace, bool whitespace, bool indentation) { if (needWhitespace && !isWhitespace) { Write(' '); } Write(indicator); isWhitespace = whitespace; isIndentation &= indentation; } private void WriteIndent() { int num = Math.Max(indent, 0); if (!isIndentation || column > num || (column == num && !isWhitespace)) { WriteBreak(); } while (column < num) { Write(' '); } isWhitespace = true; isIndentation = true; } private void WriteAnchor(AnchorName value) { Write(value.Value); isWhitespace = false; isIndentation = false; } private void WriteTagHandle(string value) { if (!isWhitespace) { Write(' '); } Write(value); isWhitespace = false; isIndentation = false; } private void WriteTagContent(string value, bool needsWhitespace) { if (needsWhitespace && !isWhitespace) { Write(' '); } Write(UrlEncode(value)); isWhitespace = false; isIndentation = false; } private static string UrlEncode(string text) { return UriReplacer.Replace(text, delegate(Match match) { StringBuilderPool.BuilderWrapper builderWrapper = StringBuilderPool.Rent(); try { StringBuilder builder = builderWrapper.Builder; byte[] bytes = Encoding.UTF8.GetBytes(match.Value); foreach (byte b in bytes) { builder.AppendFormat(CultureInfo.InvariantCulture, "%{0:X02}", b); } return builder.ToString(); } finally { ((IDisposable)builderWrapper).Dispose(); } }); } private void Write(char value) { output.Write(value); column++; } private void Write(string value) { output.Write(value); column += value.Length; } private void WriteBreak(char breakCharacter = '\n') { if (breakCharacter == '\n') { output.WriteLine(); } else { output.Write(breakCharacter); } column = 0; } } internal sealed class EmitterSettings { public static readonly EmitterSettings Default = new EmitterSettings(); public int BestIndent { get; } = 2; public int BestWidth { get; } = int.MaxValue; public string NewLine { get; } = Environment.NewLine; public bool IsCanonical { get; } public bool SkipAnchorName { get; private set; } public int MaxSimpleKeyLength { get; } = 1024; public bool IndentSequences { get; } public bool UseUtf16SurrogatePairs { get; } public EmitterSettings() { } public EmitterSettings(int bestIndent, int bestWidth, bool isCanonical, int maxSimpleKeyLength, bool skipAnchorName = false, bool indentSequences = false, string? newLine = null, bool useUtf16SurrogatePairs = false) { if (bestIndent < 2 || bestIndent > 9) { throw new ArgumentOutOfRangeException("bestIndent", "BestIndent must be between 2 and 9, inclusive"); } if (bestWidth <= bestIndent * 2) { throw new ArgumentOutOfRangeException("bestWidth", "BestWidth must be greater than BestIndent x 2."); } if (maxSimpleKeyLength < 0) { throw new ArgumentOutOfRangeException("maxSimpleKeyLength", "MaxSimpleKeyLength must be >= 0"); } BestIndent = bestIndent; BestWidth = bestWidth; IsCanonical = isCanonical; MaxSimpleKeyLength = maxSimpleKeyLength; SkipAnchorName = skipAnchorName; IndentSequences = indentSequences; NewLine = newLine ?? Environment.NewLine; UseUtf16SurrogatePairs = useUtf16SurrogatePairs; } public EmitterSettings WithBestIndent(int bestIndent) { return new EmitterSettings(bestIndent, BestWidth, IsCanonical, MaxSimpleKeyLength, SkipAnchorName, IndentSequences, NewLine, UseUtf16SurrogatePairs); } public EmitterSettings WithBestWidth(int bestWidth) { return new EmitterSettings(BestIndent, bestWidth, IsCanonical, MaxSimpleKeyLength, SkipAnchorName, IndentSequences, NewLine, UseUtf16SurrogatePairs); } public EmitterSettings WithMaxSimpleKeyLength(int maxSimpleKeyLength) { return new EmitterSettings(BestIndent, BestWidth, IsCanonical, maxSimpleKeyLength, SkipAnchorName, IndentSequences, NewLine, UseUtf16SurrogatePairs); } public EmitterSettings WithNewLine(string newLine) { return new EmitterSettings(BestIndent, BestWidth, IsCanonical, MaxSimpleKeyLength, SkipAnchorName, IndentSequences, newLine, UseUtf16SurrogatePairs); } public EmitterSettings Canonical() { return new EmitterSettings(BestIndent, BestWidth, isCanonical: true, MaxSimpleKeyLength, SkipAnchorName); } public EmitterSettings WithoutAnchorName() { return new EmitterSettings(BestIndent, BestWidth, IsCanonical, MaxSimpleKeyLength, skipAnchorName: true, IndentSequences, NewLine, UseUtf16SurrogatePairs); } public EmitterSettings WithIndentedSequences() { return new EmitterSettings(BestIndent, BestWidth, IsCanonical, MaxSimpleKeyLength, SkipAnchorName, indentSequences: true, NewLine, UseUtf16SurrogatePairs); } public EmitterSettings WithUtf16SurrogatePairs() { return new EmitterSettings(BestIndent, BestWidth, IsCanonical, MaxSimpleKeyLength, SkipAnchorName, IndentSequences, NewLine, useUtf16SurrogatePairs: true); } } internal enum EmitterState { StreamStart, StreamEnd, FirstDocumentStart, DocumentStart, DocumentContent, DocumentEnd, FlowSequenceFirstItem, FlowSequenceItem, FlowMappingFirstKey, FlowMappingKey, FlowMappingSimpleValue, FlowMappingValue, BlockSequenceFirstItem, BlockSequenceItem, BlockMappingFirstKey, BlockMappingKey, BlockMappingSimpleValue, BlockMappingValue } internal sealed class ForwardAnchorNotSupportedException : YamlException { public ForwardAnchorNotSupportedException(string message) : base(message) { } public ForwardAnchorNotSupportedException(in Mark start, in Mark end, string message) : base(in start, in end, message) { } public ForwardAnchorNotSupportedException(string message, Exception inner) : base(message, inner) { } } internal static class HashCode { public static int CombineHashCodes(int h1, int h2) { return ((h1 << 5) + h1) ^ h2; } public static int CombineHashCodes(int h1, object? o2) { return CombineHashCodes(h1, GetHashCode(o2)); } private static int GetHashCode(object? obj) { return obj?.GetHashCode() ?? 0; } } internal interface IEmitter { void Emit(ParsingEvent @event); } internal interface ILookAheadBuffer { bool EndOfInput { get; } char Peek(int offset); void Skip(int length); } internal sealed class InsertionQueue : IEnumerable, IEnumerable { private const int DefaultInitialCapacity = 128; private T[] items; private int readPtr; private int writePtr; private int mask; private int count; public int Count => count; public int Capacity => items.Length; public InsertionQueue(int initialCapacity = 128) { if (initialCapacity <= 0) { throw new ArgumentOutOfRangeException("initialCapacity", "The initial capacity must be a positive number."); } if (!initialCapacity.IsPowerOfTwo()) { throw new ArgumentException("The initial capacity must be a power of 2.", "initialCapacity"); } items = new T[initialCapacity]; readPtr = initialCapacity / 2; writePtr = initialCapacity / 2; mask = initialCapacity - 1; } public void Enqueue(T item) { ResizeIfNeeded(); items[writePtr] = item; writePtr = (writePtr - 1) & mask; count++; } public T Dequeue() { if (count == 0) { throw new InvalidOperationException("The queue is empty"); } T result = items[readPtr]; readPtr = (readPtr - 1) & mask; count--; return result; } public void Insert(int index, T item) { if (index > count) { throw new InvalidOperationException("Cannot insert outside of the bounds of the queue"); } ResizeIfNeeded(); CalculateInsertionParameters(mask, count, index, ref readPtr, ref writePtr, out var insertPtr, out var copyIndex, out var copyOffset, out var copyLength); if (copyLength != 0) { Array.Copy(items, copyIndex, items, copyIndex + copyOffset, copyLength); } items[insertPtr] = item; count++; } private void ResizeIfNeeded() { int num = items.Length; if (count == num) { T[] destinationArray = new T[num * 2]; int num2 = readPtr + 1; if (num2 > 0) { Array.Copy(items, 0, destinationArray, 0, num2); } writePtr += num; int num3 = num - num2; if (num3 > 0) { Array.Copy(items, readPtr + 1, destinationArray, writePtr + 1, num3); } items = destinationArray; mask = mask * 2 + 1; } } internal static void CalculateInsertionParameters(int mask, int count, int index, ref int readPtr, ref int writePtr, out int insertPtr, out int copyIndex, out int copyOffset, out int copyLength) { int num = (readPtr + 1) & mask; if (index == 0) { insertPtr = (readPtr = num); copyIndex = 0; copyOffset = 0; copyLength = 0; return; } insertPtr = (readPtr - index) & mask; if (index == count) { writePtr = (writePtr - 1) & mask; copyIndex = 0; copyOffset = 0; copyLength = 0; return; } int num2 = ((num >= insertPtr) ? (readPtr - insertPtr) : int.MaxValue); int num3 = ((writePtr <= insertPtr) ? (insertPtr - writePtr) : int.MaxValue); if (num2 <= num3) { insertPtr++; readPtr++; copyIndex = insertPtr; copyOffset = 1; copyLength = num2; } else { copyIndex = writePtr + 1; copyOffset = -1; copyLength = num3; writePtr = (writePtr - 1) & mask; } } public IEnumerator GetEnumerator() { int ptr = readPtr; for (int i = 0; i < Count; i++) { yield return items[ptr]; ptr = (ptr - 1) & mask; } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } internal interface IParser { ParsingEvent? Current { get; } bool MoveNext(); } internal interface IScanner { Mark CurrentPosition { get; } Token? Current { get; } bool MoveNext(); bool MoveNextWithoutConsuming(); void ConsumeCurrent(); } [DebuggerStepThrough] internal sealed class LookAheadBuffer : ILookAheadBuffer { private readonly TextReader input; private readonly char[] buffer; private readonly int blockSize; private readonly int mask; private int firstIndex; private int writeOffset; private int count; private bool endOfInput; public bool EndOfInput { get { if (endOfInput) { return count == 0; } return false; } } public LookAheadBuffer(TextReader input, int capacity) { if (capacity < 1) { throw new ArgumentOutOfRangeException("capacity", "The capacity must be positive."); } if (!capacity.IsPowerOfTwo()) { throw new ArgumentException("The capacity must be a power of 2.", "capacity"); } this.input = input ?? throw new ArgumentNullException("input"); blockSize = capacity; buffer = new char[capacity * 2]; mask = capacity * 2 - 1; } private int GetIndexForOffset(int offset) { return (firstIndex + offset) & mask; } public char Peek(int offset) { if (offset >= count) { FillBuffer(); } if (offset < count) { return buffer[(firstIndex + offset) & mask]; } return '\0'; } public void Cache(int length) { if (length >= count) { FillBuffer(); } } private void FillBuffer() { if (endOfInput) { return; } int num = blockSize; do { int num2 = input.Read(buffer, writeOffset, num); if (num2 == 0) { endOfInput = true; return; } num -= num2; writeOffset += num2; count += num2; } while (num > 0); if (writeOffset == buffer.Length) { writeOffset = 0; } } public void Skip(int length) { if (length < 1 || length > blockSize) { throw new ArgumentOutOfRangeException("length", "The length must be between 1 and the number of characters in the buffer. Use the Peek() and / or Cache() methods to fill the buffer."); } firstIndex = GetIndexForOffset(length); count -= length; } } internal readonly struct Mark : IEquatable, IComparable, IComparable { public static readonly Mark Empty = new Mark(0L, 1L, 1L); public long Index { get; } public long Line { get; } public long Column { get; } public Mark(long index, long line, long column) { if (index < 0) { ThrowHelper.ThrowArgumentOutOfRangeException("index", "Index must be greater than or equal to zero."); } if (line < 1) { ThrowHelper.ThrowArgumentOutOfRangeException("line", "Line must be greater than or equal to 1."); } if (column < 1) { ThrowHelper.ThrowArgumentOutOfRangeException("column", "Column must be greater than or equal to 1."); } Index = index; Line = line; Column = column; } public override string ToString() { return $"Line: {Line}, Col: {Column}, Idx: {Index}"; } public override bool Equals(object? obj) { return Equals((Mark)(obj ?? ((object)Empty))); } public bool Equals(Mark other) { if (Index == other.Index && Line == other.Line) { return Column == other.Column; } return false; } public override int GetHashCode() { return HashCode.CombineHashCodes(Index.GetHashCode(), HashCode.CombineHashCodes(Line.GetHashCode(), Column.GetHashCode())); } public int CompareTo(object? obj) { return CompareTo((Mark)(obj ?? ((object)Empty))); } public int CompareTo(Mark other) { int num = Line.CompareTo(other.Line); if (num == 0) { num = Column.CompareTo(other.Column); } return num; } public static bool operator ==(Mark left, Mark right) { return left.Equals(right); } public static bool operator !=(Mark left, Mark right) { return !(left == right); } public static bool operator <(Mark left, Mark right) { return left.CompareTo(right) < 0; } public static bool operator <=(Mark left, Mark right) { return left.CompareTo(right) <= 0; } public static bool operator >(Mark left, Mark right) { return left.CompareTo(right) > 0; } public static bool operator >=(Mark left, Mark right) { return left.CompareTo(right) >= 0; } } internal sealed class MaximumRecursionLevelReachedException : YamlException { public MaximumRecursionLevelReachedException(string message) : base(message) { } public MaximumRecursionLevelReachedException(in Mark start, in Mark end, string message) : base(in start, in end, message) { } public MaximumRecursionLevelReachedException(string message, Exception inner) : base(message, inner) { } } internal sealed class MergingParser : IParser { private sealed class ParsingEventCollection : IEnumerable>, IEnumerable { private readonly LinkedList events; private readonly HashSet> deleted; private readonly Dictionary> references; public ParsingEventCollection() { events = new LinkedList(); deleted = new HashSet>(); references = new Dictionary>(); } public void AddAfter(LinkedListNode node, IEnumerable items) { foreach (ParsingEvent item in items) { node = events.AddAfter(node, item); } } public void Add(ParsingEvent item) { LinkedListNode node = events.AddLast(item); AddReference(item, node); } public void MarkDeleted(LinkedListNode node) { deleted.Add(node); } public bool IsDeleted(LinkedListNode node) { return deleted.Contains(node); } public void CleanMarked() { foreach (LinkedListNode item in deleted) { events.Remove(item); } } public IEnumerable> FromAnchor(AnchorName anchor) { LinkedListNode next = references[anchor].Next; return Enumerate(next); } public IEnumerator> GetEnumerator() { return Enumerate(events.First).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } private static IEnumerable> Enumerate(LinkedListNode? node) { while (node != null) { yield return node; node = node.Next; } } private void AddReference(ParsingEvent item, LinkedListNode node) { if (item is MappingStart mappingStart) { AnchorName anchor = mappingStart.Anchor; if (!anchor.IsEmpty) { references[anchor] = node; } } } } private sealed class ParsingEventCloner : IParsingEventVisitor { private ParsingEvent? clonedEvent; public ParsingEvent Clone(ParsingEvent e) { e.Accept(this); if (clonedEvent == null) { throw new InvalidOperationException($"Could not clone event of type '{e.Type}'"); } return clonedEvent; } void IParsingEventVisitor.Visit(YamlDotNet.Core.Events.AnchorAlias e) { clonedEvent = new YamlDotNet.Core.Events.AnchorAlias(e.Value, e.Start, e.End); } void IParsingEventVisitor.Visit(YamlDotNet.Core.Events.StreamStart e) { throw new NotSupportedException(); } void IParsingEventVisitor.Visit(YamlDotNet.Core.Events.StreamEnd e) { throw new NotSupportedException(); } void IParsingEventVisitor.Visit(YamlDotNet.Core.Events.DocumentStart e) { throw new NotSupportedException(); } void IParsingEventVisitor.Visit(YamlDotNet.Core.Events.DocumentEnd e) { throw new NotSupportedException(); } void IParsingEventVisitor.Visit(YamlDotNet.Core.Events.Scalar e) { clonedEvent = new YamlDotNet.Core.Events.Scalar(AnchorName.Empty, e.Tag, e.Value, e.Style, e.IsPlainImplicit, e.IsQuotedImplicit, e.Start, e.End); } void IParsingEventVisitor.Visit(SequenceStart e) { clonedEvent = new SequenceStart(AnchorName.Empty, e.Tag, e.IsImplicit, e.Style, e.Start, e.End); } void IParsingEventVisitor.Visit(SequenceEnd e) { Mark start = e.Start; Mark end = e.End; clonedEvent = new SequenceEnd(in start, in end); } void IParsingEventVisitor.Visit(MappingStart e) { clonedEvent = new MappingStart(AnchorName.Empty, e.Tag, e.IsImplicit, e.Style, e.Start, e.End); } void IParsingEventVisitor.Visit(MappingEnd e) { Mark start = e.Start; Mark end = e.End; clonedEvent = new MappingEnd(in start, in end); } void IParsingEventVisitor.Visit(YamlDotNet.Core.Events.Comment e) { throw new NotSupportedException(); } } private readonly ParsingEventCollection events; private readonly IParser innerParser; private IEnumerator> iterator; private bool merged; public ParsingEvent? Current => iterator.Current?.Value; public MergingParser(IParser innerParser) { events = new ParsingEventCollection(); merged = false; iterator = events.GetEnumerator(); this.innerParser = innerParser; } public bool MoveNext() { if (!merged) { Merge(); events.CleanMarked(); iterator = events.GetEnumerator(); merged = true; } return iterator.MoveNext(); } private void Merge() { while (innerParser.MoveNext()) { events.Add(innerParser.Current); } foreach (LinkedListNode @event in events) { if (IsMergeToken(@event)) { events.MarkDeleted(@event); if (!HandleMerge(@event.Next)) { Mark start = @event.Value.Start; Mark end = @event.Value.End; throw new SemanticErrorException(in start, in end, "Unrecognized merge key pattern"); } } } } private bool HandleMerge(LinkedListNode? node) { if (node == null) { return false; } if (node.Value is YamlDotNet.Core.Events.AnchorAlias anchorAlias) { return HandleAnchorAlias(node, node, anchorAlias); } if (node.Value is SequenceStart) { return HandleSequence(node); } return false; } private bool HandleMergeSequence(LinkedListNode sequenceStart, LinkedListNode? node) { if (node == null) { return false; } if (node.Value is YamlDotNet.Core.Events.AnchorAlias anchorAlias) { return HandleAnchorAlias(sequenceStart, node, anchorAlias); } if (node.Value is SequenceStart) { return HandleSequence(node); } return false; } private static bool IsMergeToken(LinkedListNode node) { if (node.Value is YamlDotNet.Core.Events.Scalar scalar) { return scalar.Value == "<<"; } return false; } private bool HandleAnchorAlias(LinkedListNode node, LinkedListNode anchorNode, YamlDotNet.Core.Events.AnchorAlias anchorAlias) { IEnumerable mappingEvents = GetMappingEvents(anchorAlias.Value); events.AddAfter(node, mappingEvents); events.MarkDeleted(anchorNode); return true; } private bool HandleSequence(LinkedListNode node) { events.MarkDeleted(node); LinkedListNode linkedListNode = node; while (linkedListNode != null) { if (linkedListNode.Value is SequenceEnd) { events.MarkDeleted(linkedListNode); return true; } LinkedListNode next = linkedListNode.Next; HandleMergeSequence(node, next); linkedListNode = next; } return true; } private IEnumerable GetMappingEvents(AnchorName anchor) { ParsingEventCloner @object = new ParsingEventCloner(); int nesting = 0; return (from e in events.FromAnchor(anchor) where !events.IsDeleted(e) select e.Value).TakeWhile((ParsingEvent e) => (nesting += e.NestingIncrease) >= 0).Select(@object.Clone); } } internal class Parser : IParser { private class EventQueue { private readonly Queue highPriorityEvents = new Queue(); private readonly Queue normalPriorityEvents = new Queue(); public int Count => highPriorityEvents.Count + normalPriorityEvents.Count; public void Enqueue(ParsingEvent @event) { EventType type = @event.Type; if (type == EventType.StreamStart || type == EventType.DocumentStart) { highPriorityEvents.Enqueue(@event); } else { normalPriorityEvents.Enqueue(@event); } } public ParsingEvent Dequeue() { if (highPriorityEvents.Count <= 0) { return normalPriorityEvents.Dequeue(); } return highPriorityEvents.Dequeue(); } } private readonly Stack states = new Stack(); private readonly TagDirectiveCollection tagDirectives = new TagDirectiveCollection(); private ParserState state; private readonly IScanner scanner; private Token? currentToken; private VersionDirective? version; private readonly EventQueue pendingEvents = new EventQueue(); public ParsingEvent? Current { get; private set; } private Token? GetCurrentToken() { if (currentToken == null) { while (scanner.MoveNextWithoutConsuming()) { currentToken = scanner.Current; if (!(currentToken is YamlDotNet.Core.Tokens.Comment comment)) { break; } pendingEvents.Enqueue(new YamlDotNet.Core.Events.Comment(comment.Value, comment.IsInline, comment.Start, comment.End)); scanner.ConsumeCurrent(); } } return currentToken; } public Parser(TextReader input) : this(new Scanner(input)) { } public Parser(IScanner scanner) { this.scanner = scanner; } public bool MoveNext() { if (state == ParserState.StreamEnd) { Current = null; return false; } if (pendingEvents.Count == 0) { pendingEvents.Enqueue(StateMachine()); } Current = pendingEvents.Dequeue(); return true; } private ParsingEvent StateMachine() { return state switch { ParserState.StreamStart => ParseStreamStart(), ParserState.ImplicitDocumentStart => ParseDocumentStart(isImplicit: true), ParserState.DocumentStart => ParseDocumentStart(isImplicit: false), ParserState.DocumentContent => ParseDocumentContent(), ParserState.DocumentEnd => ParseDocumentEnd(), ParserState.BlockNode => ParseNode(isBlock: true, isIndentlessSequence: false), ParserState.BlockNodeOrIndentlessSequence => ParseNode(isBlock: true, isIndentlessSequence: true), ParserState.FlowNode => ParseNode(isBlock: false, isIndentlessSequence: false), ParserState.BlockSequenceFirstEntry => ParseBlockSequenceEntry(isFirst: true), ParserState.BlockSequenceEntry => ParseBlockSequenceEntry(isFirst: false), ParserState.IndentlessSequenceEntry => ParseIndentlessSequenceEntry(), ParserState.BlockMappingFirstKey => ParseBlockMappingKey(isFirst: true), ParserState.BlockMappingKey => ParseBlockMappingKey(isFirst: false), ParserState.BlockMappingValue => ParseBlockMappingValue(), ParserState.FlowSequenceFirstEntry => ParseFlowSequenceEntry(isFirst: true), ParserState.FlowSequenceEntry => ParseFlowSequenceEntry(isFirst: false), ParserState.FlowSequenceEntryMappingKey => ParseFlowSequenceEntryMappingKey(), ParserState.FlowSequenceEntryMappingValue => ParseFlowSequenceEntryMappingValue(), ParserState.FlowSequenceEntryMappingEnd => ParseFlowSequenceEntryMappingEnd(), ParserState.FlowMappingFirstKey => ParseFlowMappingKey(isFirst: true), ParserState.FlowMappingKey => ParseFlowMappingKey(isFirst: false), ParserState.FlowMappingValue => ParseFlowMappingValue(isEmpty: false), ParserState.FlowMappingEmptyValue => ParseFlowMappingValue(isEmpty: true), _ => throw new InvalidOperationException(), }; } private void Skip() { if (currentToken != null) { currentToken = null; scanner.ConsumeCurrent(); } } private YamlDotNet.Core.Events.StreamStart ParseStreamStart() { Token token = GetCurrentToken(); Mark start; Mark end; if (!(token is YamlDotNet.Core.Tokens.StreamStart streamStart)) { start = token?.Start ?? Mark.Empty; end = token?.End ?? Mark.Empty; throw new SemanticErrorException(in start, in end, "Did not find expected ."); } Skip(); state = ParserState.ImplicitDocumentStart; start = streamStart.Start; end = streamStart.End; return new YamlDotNet.Core.Events.StreamStart(in start, in end); } private ParsingEvent ParseDocumentStart(bool isImplicit) { if (currentToken is VersionDirective) { throw new SyntaxErrorException("While parsing a document start node, could not find document end marker before version directive."); } Token token = GetCurrentToken(); if (!isImplicit) { while (token is YamlDotNet.Core.Tokens.DocumentEnd) { Skip(); token = GetCurrentToken(); } } if (token == null) { throw new SyntaxErrorException("Reached the end of the stream while parsing a document start."); } if (token is YamlDotNet.Core.Tokens.Scalar && (state == ParserState.ImplicitDocumentStart || state == ParserState.DocumentStart)) { isImplicit = true; } if ((isImplicit && !(token is VersionDirective) && !(token is TagDirective) && !(token is YamlDotNet.Core.Tokens.DocumentStart) && !(token is YamlDotNet.Core.Tokens.StreamEnd) && !(token is YamlDotNet.Core.Tokens.DocumentEnd)) || token is BlockMappingStart) { TagDirectiveCollection tags = new TagDirectiveCollection(); ProcessDirectives(tags); states.Push(ParserState.DocumentEnd); state = ParserState.BlockNode; return new YamlDotNet.Core.Events.DocumentStart(null, tags, isImplicit: true, token.Start, token.End); } Mark start2; Mark end; if (!(token is YamlDotNet.Core.Tokens.StreamEnd) && !(token is YamlDotNet.Core.Tokens.DocumentEnd)) { Mark start = token.Start; TagDirectiveCollection tags2 = new TagDirectiveCollection(); VersionDirective versionDirective = ProcessDirectives(tags2); token = GetCurrentToken() ?? throw new SemanticErrorException("Reached the end of the stream while parsing a document start"); if (!(token is YamlDotNet.Core.Tokens.DocumentStart)) { start2 = token.Start; end = token.End; throw new SemanticErrorException(in start2, in end, "Did not find expected ."); } states.Push(ParserState.DocumentEnd); state = ParserState.DocumentContent; Mark end2 = token.End; Skip(); return new YamlDotNet.Core.Events.DocumentStart(versionDirective, tags2, isImplicit: false, start, end2); } if (token is YamlDotNet.Core.Tokens.DocumentEnd) { Skip(); } state = ParserState.StreamEnd; token = GetCurrentToken() ?? throw new SemanticErrorException("Reached the end of the stream while parsing a document start"); start2 = token.Start; end = token.End; YamlDotNet.Core.Events.StreamEnd result = new YamlDotNet.Core.Events.StreamEnd(in start2, in end); if (scanner.MoveNextWithoutConsuming()) { throw new InvalidOperationException("The scanner should contain no more tokens."); } return result; } private VersionDirective? ProcessDirectives(TagDirectiveCollection tags) { bool flag = false; VersionDirective result = null; while (true) { if (GetCurrentToken() is VersionDirective versionDirective) { if (version != null) { Mark start = versionDirective.Start; Mark end = versionDirective.End; throw new SemanticErrorException(in start, in end, "Found duplicate %YAML directive."); } if (versionDirective.Version.Major != 1 || versionDirective.Version.Minor > 3) { Mark start = versionDirective.Start; Mark end = versionDirective.End; throw new SemanticErrorException(in start, in end, "Found incompatible YAML document."); } result = (version = versionDirective); flag = true; } else { if (!(GetCurrentToken() is TagDirective tagDirective)) { break; } if (tags.Contains(tagDirective.Handle)) { Mark start = tagDirective.Start; Mark end = tagDirective.End; throw new SemanticErrorException(in start, in end, "Found duplicate %TAG directive."); } tags.Add(tagDirective); flag = true; } Skip(); } if (GetCurrentToken() is YamlDotNet.Core.Tokens.DocumentStart && (version == null || (version.Version.Major == 1 && version.Version.Minor > 1))) { if (GetCurrentToken() is YamlDotNet.Core.Tokens.DocumentStart && version == null) { version = new VersionDirective(new Version(1, 2)); } flag = true; } AddTagDirectives(tags, Constants.DefaultTagDirectives); if (flag) { tagDirectives.Clear(); } AddTagDirectives(tagDirectives, tags); return result; } private static void AddTagDirectives(TagDirectiveCollection directives, IEnumerable source) { foreach (TagDirective item in source) { if (!directives.Contains(item)) { directives.Add(item); } } } private ParsingEvent ParseDocumentContent() { if (GetCurrentToken() is VersionDirective || GetCurrentToken() is TagDirective || GetCurrentToken() is YamlDotNet.Core.Tokens.DocumentStart || GetCurrentToken() is YamlDotNet.Core.Tokens.DocumentEnd || GetCurrentToken() is YamlDotNet.Core.Tokens.StreamEnd) { state = states.Pop(); Mark position = scanner.CurrentPosition; return ProcessEmptyScalar(in position); } return ParseNode(isBlock: true, isIndentlessSequence: false); } private static YamlDotNet.Core.Events.Scalar ProcessEmptyScalar(in Mark position) { return new YamlDotNet.Core.Events.Scalar(AnchorName.Empty, TagName.Empty, string.Empty, ScalarStyle.Plain, isPlainImplicit: true, isQuotedImplicit: false, position, position); } private ParsingEvent ParseNode(bool isBlock, bool isIndentlessSequence) { Mark start; Mark end; if (GetCurrentToken() is Error error) { start = error.Start; end = error.End; throw new SemanticErrorException(in start, in end, error.Value); } Token token = GetCurrentToken() ?? throw new SemanticErrorException("Reached the end of the stream while parsing a node"); if (token is YamlDotNet.Core.Tokens.AnchorAlias anchorAlias) { state = states.Pop(); ParsingEvent result = new YamlDotNet.Core.Events.AnchorAlias(anchorAlias.Value, anchorAlias.Start, anchorAlias.End); Skip(); return result; } Mark start2 = token.Start; AnchorName anchor = AnchorName.Empty; TagName tag = TagName.Empty; Anchor anchor2 = null; Tag tag2 = null; while (true) { if (anchor.IsEmpty && token is Anchor anchor3) { anchor2 = anchor3; anchor = anchor3.Value; Skip(); } else { if (!tag.IsEmpty || !(token is Tag tag3)) { if (token is Anchor anchor4) { start = anchor4.Start; end = anchor4.End; throw new SemanticErrorException(in start, in end, "While parsing a node, found more than one anchor."); } if (token is YamlDotNet.Core.Tokens.AnchorAlias anchorAlias2) { start = anchorAlias2.Start; end = anchorAlias2.End; throw new SemanticErrorException(in start, in end, "While parsing a node, did not find expected token."); } if (!(token is Error error2)) { break; } if (tag2 != null && anchor2 != null && !anchor.IsEmpty) { return new YamlDotNet.Core.Events.Scalar(anchor, default(TagName), string.Empty, ScalarStyle.Any, isPlainImplicit: false, isQuotedImplicit: false, anchor2.Start, anchor2.End); } start = error2.Start; end = error2.End; throw new SemanticErrorException(in start, in end, error2.Value); } tag2 = tag3; if (string.IsNullOrEmpty(tag3.Handle)) { tag = new TagName(tag3.Suffix); } else { if (!tagDirectives.Contains(tag3.Handle)) { start = tag3.Start; end = tag3.End; throw new SemanticErrorException(in start, in end, "While parsing a node, found undefined tag handle."); } tag = new TagName(tagDirectives[tag3.Handle].Prefix + tag3.Suffix); } Skip(); } token = GetCurrentToken() ?? throw new SemanticErrorException("Reached the end of the stream while parsing a node"); } bool isEmpty = tag.IsEmpty; if (isIndentlessSequence && GetCurrentToken() is BlockEntry) { state = ParserState.IndentlessSequenceEntry; return new SequenceStart(anchor, tag, isEmpty, SequenceStyle.Block, start2, token.End); } if (token is YamlDotNet.Core.Tokens.Scalar scalar) { bool isPlainImplicit = false; bool isQuotedImplicit = false; if ((scalar.Style == ScalarStyle.Plain && tag.IsEmpty) || tag.IsNonSpecific) { isPlainImplicit = true; } else if (tag.IsEmpty) { isQuotedImplicit = true; } state = states.Pop(); Skip(); ParsingEvent result2 = new YamlDotNet.Core.Events.Scalar(anchor, tag, scalar.Value, scalar.Style, isPlainImplicit, isQuotedImplicit, start2, scalar.End, scalar.IsKey); if (!anchor.IsEmpty && scanner.MoveNextWithoutConsuming()) { currentToken = scanner.Current; if (currentToken is Error) { Error error3 = currentToken as Error; start = error3.Start; end = error3.End; throw new SemanticErrorException(in start, in end, error3.Value); } } if (state == ParserState.FlowMappingKey && !(scanner.Current is FlowMappingEnd) && scanner.MoveNextWithoutConsuming()) { currentToken = scanner.Current; if (currentToken != null && !(currentToken is FlowEntry) && !(currentToken is FlowMappingEnd)) { start = currentToken.Start; end = currentToken.End; throw new SemanticErrorException(in start, in end, "While parsing a flow mapping, did not find expected ',' or '}'."); } } return result2; } if (token is FlowSequenceStart flowSequenceStart) { state = ParserState.FlowSequenceFirstEntry; return new SequenceStart(anchor, tag, isEmpty, SequenceStyle.Flow, start2, flowSequenceStart.End); } if (token is FlowMappingStart flowMappingStart) { state = ParserState.FlowMappingFirstKey; return new MappingStart(anchor, tag, isEmpty, MappingStyle.Flow, start2, flowMappingStart.End); } if (isBlock) { if (token is BlockSequenceStart blockSequenceStart) { state = ParserState.BlockSequenceFirstEntry; return new SequenceStart(anchor, tag, isEmpty, SequenceStyle.Block, start2, blockSequenceStart.End); } if (token is BlockMappingStart blockMappingStart) { state = ParserState.BlockMappingFirstKey; return new MappingStart(anchor, tag, isEmpty, MappingStyle.Block, start2, blockMappingStart.End); } } if (!anchor.IsEmpty || !tag.IsEmpty) { state = states.Pop(); return new YamlDotNet.Core.Events.Scalar(anchor, tag, string.Empty, ScalarStyle.Plain, isEmpty, isQuotedImplicit: false, start2, token.End); } start = token.Start; end = token.End; throw new SemanticErrorException(in start, in end, "While parsing a node, did not find expected node content."); } private YamlDotNet.Core.Events.DocumentEnd ParseDocumentEnd() { Token token = GetCurrentToken() ?? throw new SemanticErrorException("Reached the end of the stream while parsing a document end"); bool isImplicit = true; Mark start = token.Start; Mark end = start; if (token is YamlDotNet.Core.Tokens.DocumentEnd) { end = token.End; Skip(); isImplicit = false; } else if (!(currentToken is YamlDotNet.Core.Tokens.StreamEnd) && !(currentToken is YamlDotNet.Core.Tokens.DocumentStart) && !(currentToken is FlowSequenceEnd) && !(currentToken is VersionDirective) && (!(Current is YamlDotNet.Core.Events.Scalar) || !(currentToken is Error))) { throw new SemanticErrorException(in start, in end, "Did not find expected ."); } if (version != null && version.Version.Major == 1 && version.Version.Minor > 1) { version = null; } state = ParserState.DocumentStart; return new YamlDotNet.Core.Events.DocumentEnd(isImplicit, start, end); } private ParsingEvent ParseBlockSequenceEntry(bool isFirst) { if (isFirst) { GetCurrentToken(); Skip(); } Token token = GetCurrentToken(); if (token is BlockEntry blockEntry) { Mark position = blockEntry.End; Skip(); token = GetCurrentToken(); if (!(token is BlockEntry) && !(token is BlockEnd)) { states.Push(ParserState.BlockSequenceEntry); return ParseNode(isBlock: true, isIndentlessSequence: false); } state = ParserState.BlockSequenceEntry; return ProcessEmptyScalar(in position); } Mark start; Mark end; if (token is BlockEnd blockEnd) { state = states.Pop(); start = blockEnd.Start; end = blockEnd.End; ParsingEvent result = new SequenceEnd(in start, in end); Skip(); return result; } start = token?.Start ?? Mark.Empty; end = token?.End ?? Mark.Empty; throw new SemanticErrorException(in start, in end, "While parsing a block collection, did not find expected '-' indicator."); } private ParsingEvent ParseIndentlessSequenceEntry() { Token token = GetCurrentToken(); if (token is BlockEntry blockEntry) { Mark position = blockEntry.End; Skip(); token = GetCurrentToken(); if (!(token is BlockEntry) && !(token is Key) && !(token is Value) && !(token is BlockEnd)) { states.Push(ParserState.IndentlessSequenceEntry); return ParseNode(isBlock: true, isIndentlessSequence: false); } state = ParserState.IndentlessSequenceEntry; return ProcessEmptyScalar(in position); } state = states.Pop(); Mark start = token?.Start ?? Mark.Empty; Mark end = token?.End ?? Mark.Empty; return new SequenceEnd(in start, in end); } private ParsingEvent ParseBlockMappingKey(bool isFirst) { if (isFirst) { GetCurrentToken(); Skip(); } Token token = GetCurrentToken(); if (token is Key key) { Mark position = key.End; Skip(); token = GetCurrentToken(); if (!(token is Key) && !(token is Value) && !(token is BlockEnd)) { states.Push(ParserState.BlockMappingValue); return ParseNode(isBlock: true, isIndentlessSequence: true); } state = ParserState.BlockMappingValue; return ProcessEmptyScalar(in position); } Mark position2; if (token is Value value) { Skip(); position2 = value.End; return ProcessEmptyScalar(in position2); } if (token is YamlDotNet.Core.Tokens.AnchorAlias anchorAlias) { Skip(); return new YamlDotNet.Core.Events.AnchorAlias(anchorAlias.Value, anchorAlias.Start, anchorAlias.End); } Mark end; if (token is BlockEnd blockEnd) { state = states.Pop(); position2 = blockEnd.Start; end = blockEnd.End; ParsingEvent result = new MappingEnd(in position2, in end); Skip(); return result; } if (GetCurrentToken() is Error error) { position2 = error.Start; end = error.End; throw new SyntaxErrorException(in position2, in end, error.Value); } position2 = token?.Start ?? Mark.Empty; end = token?.End ?? Mark.Empty; throw new SemanticErrorException(in position2, in end, "While parsing a block mapping, did not find expected key."); } private ParsingEvent ParseBlockMappingValue() { Token token = GetCurrentToken(); if (token is Value value) { Mark position = value.End; Skip(); token = GetCurrentToken(); if (!(token is Key) && !(token is Value) && !(token is BlockEnd)) { states.Push(ParserState.BlockMappingKey); return ParseNode(isBlock: true, isIndentlessSequence: true); } state = ParserState.BlockMappingKey; return ProcessEmptyScalar(in position); } Mark start; if (token is Error error) { start = error.Start; Mark end = error.End; throw new SemanticErrorException(in start, in end, error.Value); } state = ParserState.BlockMappingKey; start = token?.Start ?? Mark.Empty; return ProcessEmptyScalar(in start); } private ParsingEvent ParseFlowSequenceEntry(bool isFirst) { if (isFirst) { GetCurrentToken(); Skip(); } Token token = GetCurrentToken(); Mark start; Mark end; ParsingEvent result; if (!(token is FlowSequenceEnd)) { if (!isFirst) { if (!(token is FlowEntry)) { start = token?.Start ?? Mark.Empty; end = token?.End ?? Mark.Empty; throw new SemanticErrorException(in start, in end, "While parsing a flow sequence, did not find expected ',' or ']'."); } Skip(); token = GetCurrentToken(); } if (token is Key) { state = ParserState.FlowSequenceEntryMappingKey; result = new MappingStart(AnchorName.Empty, TagName.Empty, isImplicit: true, MappingStyle.Flow); Skip(); return result; } if (!(token is FlowSequenceEnd)) { states.Push(ParserState.FlowSequenceEntry); return ParseNode(isBlock: false, isIndentlessSequence: false); } } state = states.Pop(); start = token?.Start ?? Mark.Empty; end = token?.End ?? Mark.Empty; result = new SequenceEnd(in start, in end); Skip(); return result; } private ParsingEvent ParseFlowSequenceEntryMappingKey() { Token token = GetCurrentToken(); if (!(token is Value) && !(token is FlowEntry) && !(token is FlowSequenceEnd)) { states.Push(ParserState.FlowSequenceEntryMappingValue); return ParseNode(isBlock: false, isIndentlessSequence: false); } Mark position = token?.End ?? Mark.Empty; Skip(); state = ParserState.FlowSequenceEntryMappingValue; return ProcessEmptyScalar(in position); } private ParsingEvent ParseFlowSequenceEntryMappingValue() { Token token = GetCurrentToken(); if (token is Value) { Skip(); token = GetCurrentToken(); if (!(token is FlowEntry) && !(token is FlowSequenceEnd)) { states.Push(ParserState.FlowSequenceEntryMappingEnd); return ParseNode(isBlock: false, isIndentlessSequence: false); } } state = ParserState.FlowSequenceEntryMappingEnd; Mark position = token?.Start ?? Mark.Empty; return ProcessEmptyScalar(in position); } private MappingEnd ParseFlowSequenceEntryMappingEnd() { state = ParserState.FlowSequenceEntry; Token token = GetCurrentToken(); Mark start = token?.Start ?? Mark.Empty; Mark end = token?.End ?? Mark.Empty; return new MappingEnd(in start, in end); } private ParsingEvent ParseFlowMappingKey(bool isFirst) { if (isFirst) { GetCurrentToken(); Skip(); } Token token = GetCurrentToken(); Mark start; Mark end; if (!(token is FlowMappingEnd)) { if (!isFirst) { if (token is FlowEntry) { Skip(); token = GetCurrentToken(); } else if (!(token is YamlDotNet.Core.Tokens.Scalar)) { start = token?.Start ?? Mark.Empty; end = token?.End ?? Mark.Empty; throw new SemanticErrorException(in start, in end, "While parsing a flow mapping, did not find expected ',' or '}'."); } } if (token is Key) { Skip(); token = GetCurrentToken(); if (!(token is Value) && !(token is FlowEntry) && !(token is FlowMappingEnd)) { states.Push(ParserState.FlowMappingValue); return ParseNode(isBlock: false, isIndentlessSequence: false); } state = ParserState.FlowMappingValue; start = token?.Start ?? Mark.Empty; return ProcessEmptyScalar(in start); } if (token is YamlDotNet.Core.Tokens.Scalar) { states.Push(ParserState.FlowMappingValue); return ParseNode(isBlock: false, isIndentlessSequence: false); } if (!(token is FlowMappingEnd)) { states.Push(ParserState.FlowMappingEmptyValue); return ParseNode(isBlock: false, isIndentlessSequence: false); } } state = states.Pop(); Skip(); start = token?.Start ?? Mark.Empty; end = token?.End ?? Mark.Empty; return new MappingEnd(in start, in end); } private ParsingEvent ParseFlowMappingValue(bool isEmpty) { Token token = GetCurrentToken(); if (!isEmpty && token is Value) { Skip(); token = GetCurrentToken(); if (!(token is FlowEntry) && !(token is FlowMappingEnd)) { states.Push(ParserState.FlowMappingKey); return ParseNode(isBlock: false, isIndentlessSequence: false); } } state = ParserState.FlowMappingKey; if (!isEmpty && token is YamlDotNet.Core.Tokens.Scalar scalar) { Skip(); return new YamlDotNet.Core.Events.Scalar(AnchorName.Empty, TagName.Empty, scalar.Value, scalar.Style, isPlainImplicit: false, isQuotedImplicit: false, token.Start, scalar.End); } Mark position = token?.Start ?? Mark.Empty; return ProcessEmptyScalar(in position); } } internal static class ParserExtensions { public static T Consume(this IParser parser) where T : ParsingEvent { T result = parser.Require(); parser.MoveNext(); return result; } public static bool TryConsume(this IParser parser, [MaybeNullWhen(false)] out T @event) where T : ParsingEvent { if (parser.Accept(out @event)) { parser.MoveNext(); return true; } return false; } public static T Require(this IParser parser) where T : ParsingEvent { if (!parser.Accept(out var @event)) { ParsingEvent current = parser.Current; if (current == null) { throw new YamlException("Expected '" + typeof(T).Name + "', got nothing."); } Mark start = current.Start; Mark end = current.End; throw new YamlException(in start, in end, $"Expected '{typeof(T).Name}', got '{current.GetType().Name}' (at {current.Start})."); } return @event; } public static bool Accept(this IParser parser, [MaybeNullWhen(false)] out T @event) where T : ParsingEvent { if (parser.Current == null && !parser.MoveNext()) { throw new EndOfStreamException(); } if (parser.Current is T val) { @event = val; return true; } @event = null; return false; } public static void SkipThisAndNestedEvents(this IParser parser) { int num = 0; do { ParsingEvent parsingEvent = parser.Consume(); num += parsingEvent.NestingIncrease; } while (num > 0); } [Obsolete("Please use Consume() instead")] public static T Expect(this IParser parser) where T : ParsingEvent { return parser.Consume(); } [Obsolete("Please use TryConsume(out var evt) instead")] [return: MaybeNull] public static T? Allow(this IParser parser) where T : ParsingEvent { if (!parser.TryConsume(out var @event)) { return null; } return @event; } [Obsolete("Please use Accept(out var evt) instead")] [return: MaybeNull] public static T? Peek(this IParser parser) where T : ParsingEvent { if (!parser.Accept(out var @event)) { return null; } return @event; } [Obsolete("Please use TryConsume(out var evt) or Accept(out var evt) instead")] public static bool Accept(this IParser parser) where T : ParsingEvent { T @event; return parser.Accept(out @event); } public static bool TryFindMappingEntry(this IParser parser, Func selector, [MaybeNullWhen(false)] out YamlDotNet.Core.Events.Scalar? key, [MaybeNullWhen(false)] out ParsingEvent? value) { if (parser.TryConsume(out var _)) { while (parser.Current != null) { ParsingEvent current = parser.Current; if (!(current is YamlDotNet.Core.Events.Scalar scalar)) { if (current is MappingStart || current is SequenceStart) { parser.SkipThisAndNestedEvents(); } else { parser.MoveNext(); } continue; } bool flag = selector(scalar); parser.MoveNext(); if (flag) { value = parser.Current; key = scalar; return true; } parser.SkipThisAndNestedEvents(); } } key = null; value = null; return false; } } internal enum ParserState { StreamStart, StreamEnd, ImplicitDocumentStart, DocumentStart, DocumentContent, DocumentEnd, BlockNode, BlockNodeOrIndentlessSequence, FlowNode, BlockSequenceFirstEntry, BlockSequenceEntry, IndentlessSequenceEntry, BlockMappingFirstKey, BlockMappingKey, BlockMappingValue, FlowSequenceFirstEntry, FlowSequenceEntry, FlowSequenceEntryMappingKey, FlowSequenceEntryMappingValue, FlowSequenceEntryMappingEnd, FlowMappingFirstKey, FlowMappingKey, FlowMappingValue, FlowMappingEmptyValue } internal sealed class RecursionLevel { private int current; public int Maximum { get; } public RecursionLevel(int maximum) { Maximum = maximum; } public void Increment() { if (!TryIncrement()) { throw new MaximumRecursionLevelReachedException("Maximum level of recursion reached"); } } public bool TryIncrement() { if (current < Maximum) { current++; return true; } return false; } public void Decrement() { if (current == 0) { throw new InvalidOperationException("Attempted to decrement RecursionLevel to a negative value"); } current--; } } internal enum ScalarStyle { Any, Plain, SingleQuoted, DoubleQuoted, Literal, Folded, ForcePlain } internal class Scanner : IScanner { private const int MaxVersionNumberLength = 9; private static readonly SortedDictionary SimpleEscapeCodes = new SortedDictionary { { '0', '\0' }, { 'a', '\a' }, { 'b', '\b' }, { 't', '\t' }, { '\t', '\t' }, { 'n', '\n' }, { 'v', '\v' }, { 'f', '\f' }, { 'r', '\r' }, { 'e', '\u001b' }, { ' ', ' ' }, { '"', '"' }, { '\\', '\\' }, { '/', '/' }, { 'N', '\u0085' }, { '_', '\u00a0' }, { 'L', '\u2028' }, { 'P', '\u2029' } }; private readonly Stack indents = new Stack(); private readonly InsertionQueue tokens = new InsertionQueue(); private readonly Stack simpleKeys = new Stack(); private readonly CharacterAnalyzer analyzer; private readonly Cursor cursor; private bool streamStartProduced; private bool streamEndProduced; private bool plainScalarFollowedByComment; private bool flowCollectionFetched; private bool startFlowCollectionFetched; private long indent = -1L; private bool flowScalarFetched; private bool simpleKeyAllowed; private int flowLevel; private int tokensParsed; private bool tokenAvailable; private Token? previous; private Anchor? previousAnchor; private YamlDotNet.Core.Tokens.Scalar? lastScalar; private readonly int maxKeySize; private static readonly byte[] EmptyBytes = Array.Empty(); public bool SkipComments { get; private set; } public Token? Current { get; private set; } public Mark CurrentPosition => cursor.Mark(); private bool IsDocumentStart() { if (!analyzer.EndOfInput && cursor.LineOffset == 0L && analyzer.Check('-') && analyzer.Check('-', 1) && analyzer.Check('-', 2)) { return analyzer.IsWhiteBreakOrZero(3); } return false; } private bool IsDocumentEnd() { if (!analyzer.EndOfInput && cursor.LineOffset == 0L && analyzer.Check('.') && analyzer.Check('.', 1) && analyzer.Check('.', 2)) { return analyzer.IsWhiteBreakOrZero(3); } return false; } private bool IsDocumentIndicator() { if (!IsDocumentStart()) { return IsDocumentEnd(); } return true; } public Scanner(TextReader input, bool skipComments = true) : this(input, skipComments, 1024) { } public Scanner(TextReader input, bool skipComments, int maxKeySize) { analyzer = new CharacterAnalyzer(new LookAheadBuffer(input, 1024)); cursor = new Cursor(); SkipComments = skipComments; this.maxKeySize = maxKeySize; } public bool MoveNext() { if (Current != null) { ConsumeCurrent(); } return MoveNextWithoutConsuming(); } public bool MoveNextWithoutConsuming() { if (!tokenAvailable && !streamEndProduced) { FetchMoreTokens(); } if (tokens.Count > 0) { Current = tokens.Dequeue(); tokenAvailable = false; return true; } Current = null; return false; } public void ConsumeCurrent() { tokensParsed++; tokenAvailable = false; previous = Current; Current = null; } private char ReadCurrentCharacter() { char result = analyzer.Peek(0); Skip(); return result; } private char ReadLine() { if (analyzer.Check("\r\n\u0085")) { SkipLine(); return '\n'; } char result = analyzer.Peek(0); SkipLine(); return result; } private void FetchMoreTokens() { while (true) { bool flag = false; if (tokens.Count == 0) { flag = true; } else { foreach (SimpleKey simpleKey in simpleKeys) { if (simpleKey.IsPossible && simpleKey.TokenNumber == tokensParsed) { flag = true; break; } } } if (!flag) { break; } FetchNextToken(); } tokenAvailable = true; } private static bool StartsWith(StringBuilder what, char start) { if (what.Length > 0) { return what[0] == start; } return false; } private void StaleSimpleKeys() { foreach (SimpleKey simpleKey in simpleKeys) { if (simpleKey.IsPossible && (simpleKey.Line < cursor.Line || simpleKey.Index + maxKeySize < cursor.Index)) { if (simpleKey.IsRequired) { Mark mark = cursor.Mark(); tokens.Enqueue(new Error("While scanning a simple key, could not find expected ':'.", mark, mark)); } simpleKey.MarkAsImpossible(); } } } private void FetchNextToken() { if (!streamStartProduced) { FetchStreamStart(); return; } ScanToNextToken(); StaleSimpleKeys(); UnrollIndent(cursor.LineOffset); analyzer.Buffer.Cache(4); if (analyzer.Buffer.EndOfInput) { lastScalar = null; FetchStreamEnd(); } if (cursor.LineOffset == 0L && analyzer.Check('%')) { lastScalar = null; FetchDirective(); return; } if (IsDocumentStart()) { lastScalar = null; FetchDocumentIndicator(isStartToken: true); return; } if (IsDocumentEnd()) { lastScalar = null; FetchDocumentIndicator(isStartToken: false); return; } if (analyzer.Check('[')) { lastScalar = null; FetchFlowCollectionStart(isSequenceToken: true); return; } if (analyzer.Check('{')) { lastScalar = null; FetchFlowCollectionStart(isSequenceToken: false); return; } if (analyzer.Check(']')) { lastScalar = null; FetchFlowCollectionEnd(isSequenceToken: true); return; } if (analyzer.Check('}')) { lastScalar = null; FetchFlowCollectionEnd(isSequenceToken: false); return; } if (analyzer.Check(',')) { lastScalar = null; FetchFlowEntry(); return; } if (analyzer.Check('-')) { if (analyzer.IsWhiteBreakOrZero(1)) { FetchBlockEntry(); return; } if (flowLevel > 0 && analyzer.Check(",[]{}", 1)) { tokens.Enqueue(new Error("Invalid key indicator format.", cursor.Mark(), cursor.Mark())); } } if (analyzer.Check('?') && (flowLevel > 0 || analyzer.IsWhiteBreakOrZero(1)) && analyzer.IsWhiteBreakOrZero(1)) { FetchKey(); } else if (analyzer.Check(':') && (flowLevel > 0 || analyzer.IsWhiteBreakOrZero(1)) && (!simpleKeyAllowed || flowLevel <= 0) && (!flowScalarFetched || !analyzer.Check(':', 1)) && (analyzer.IsWhiteBreakOrZero(1) || analyzer.Check(',', 1) || flowScalarFetched || flowCollectionFetched || startFlowCollectionFetched)) { if (lastScalar != null) { lastScalar.IsKey = true; lastScalar = null; } FetchValue(); } else if (analyzer.Check('*')) { FetchAnchor(isAlias: true); } else if (analyzer.Check('&')) { FetchAnchor(isAlias: false); } else if (analyzer.Check('!')) { FetchTag(); } else if (analyzer.Check('|') && flowLevel == 0) { FetchBlockScalar(isLiteral: true); } else if (analyzer.Check('>') && flowLevel == 0) { FetchBlockScalar(isLiteral: false); } else if (analyzer.Check('\'')) { FetchQuotedScalar(isSingleQuoted: true); } else if (analyzer.Check('"')) { FetchQuotedScalar(isSingleQuoted: false); } else if ((!analyzer.IsWhiteBreakOrZero() && !analyzer.Check("-?:,[]{}#&*!|>'\"%@`")) || (analyzer.Check('-') && !analyzer.IsWhite(1)) || (analyzer.Check("?:") && !analyzer.IsWhiteBreakOrZero(1)) || (simpleKeyAllowed && flowLevel > 0)) { if (plainScalarFollowedByComment) { Mark mark = cursor.Mark(); tokens.Enqueue(new Error("While scanning plain scalar, found a comment between adjacent scalars.", mark, mark)); } if ((flowScalarFetched || (flowCollectionFetched && !startFlowCollectionFetched)) && analyzer.Check(':')) { Skip(); } flowScalarFetched = false; flowCollectionFetched = false; startFlowCollectionFetched = false; plainScalarFollowedByComment = false; FetchPlainScalar(); } else { if (simpleKeyAllowed && indent >= cursor.LineOffset && analyzer.IsTab()) { throw new SyntaxErrorException("While scanning a mapping, found invalid tab as indentation."); } if (!analyzer.IsWhiteBreakOrZero()) { Mark start = cursor.Mark(); Skip(); Mark end = cursor.Mark(); throw new SyntaxErrorException(in start, in end, "While scanning for the next token, found character that cannot start any token."); } Skip(); } } private bool CheckWhiteSpace() { if (!analyzer.Check(' ')) { if (flowLevel > 0 || !simpleKeyAllowed) { return analyzer.Check('\t'); } return false; } return true; } private void Skip() { cursor.Skip(); analyzer.Buffer.Skip(1); } private void SkipLine() { if (analyzer.IsCrLf()) { cursor.SkipLineByOffset(2); analyzer.Buffer.Skip(2); } else if (analyzer.IsBreak()) { cursor.SkipLineByOffset(1); analyzer.Buffer.Skip(1); } else if (!analyzer.IsZero()) { throw new InvalidOperationException("Not at a break."); } } private void ScanToNextToken() { while (true) { if (CheckWhiteSpace()) { Skip(); continue; } ProcessComment(); if (analyzer.IsBreak()) { SkipLine(); if (flowLevel == 0) { simpleKeyAllowed = true; } continue; } break; } } private void ProcessComment() { if (!analyzer.Check('#')) { return; } Mark start = cursor.Mark(); Skip(); while (analyzer.IsSpace()) { Skip(); } StringBuilderPool.BuilderWrapper builderWrapper = StringBuilderPool.Rent(); try { StringBuilder builder = builderWrapper.Builder; while (!analyzer.IsBreakOrZero()) { builder.Append(ReadCurrentCharacter()); } if (!SkipComments) { bool isInline = previous != null && previous.End.Line == start.Line && previous.End.Column != 1 && !(previous is YamlDotNet.Core.Tokens.StreamStart); tokens.Enqueue(new YamlDotNet.Core.Tokens.Comment(builder.ToString(), isInline, start, cursor.Mark())); } } finally { ((IDisposable)builderWrapper).Dispose(); } } private void FetchStreamStart() { simpleKeys.Push(new SimpleKey()); simpleKeyAllowed = true; streamStartProduced = true; Mark start = cursor.Mark(); tokens.Enqueue(new YamlDotNet.Core.Tokens.StreamStart(in start, in start)); } private void UnrollIndent(long column) { if (flowLevel == 0) { while (indent > column) { Mark start = cursor.Mark(); tokens.Enqueue(new BlockEnd(in start, in start)); indent = indents.Pop(); } } } private void FetchStreamEnd() { cursor.ForceSkipLineAfterNonBreak(); UnrollIndent(-1L); RemoveSimpleKey(); simpleKeyAllowed = false; streamEndProduced = true; Mark start = cursor.Mark(); tokens.Enqueue(new YamlDotNet.Core.Tokens.StreamEnd(in start, in start)); } private void FetchDirective() { UnrollIndent(-1L); RemoveSimpleKey(); simpleKeyAllowed = false; Token token = ScanDirective(); if (token != null) { tokens.Enqueue(token); } } private Token? ScanDirective() { Mark start = cursor.Mark(); Skip(); string text = ScanDirectiveName(in start); Token result; if (!(text == "YAML")) { if (!(text == "TAG")) { while (!analyzer.EndOfInput && !analyzer.Check('#') && !analyzer.IsBreak()) { Skip(); } return null; } result = ScanTagDirectiveValue(in start); } else { if (!(previous is YamlDotNet.Core.Tokens.DocumentStart) && !(previous is YamlDotNet.Core.Tokens.StreamStart) && !(previous is YamlDotNet.Core.Tokens.DocumentEnd)) { Mark end = cursor.Mark(); throw new SemanticErrorException(in start, in end, "While scanning a version directive, did not find preceding ."); } result = ScanVersionDirectiveValue(in start); } while (analyzer.IsWhite()) { Skip(); } ProcessComment(); if (!analyzer.IsBreakOrZero()) { Mark end = cursor.Mark(); throw new SyntaxErrorException(in start, in end, "While scanning a directive, did not find expected comment or line break."); } if (analyzer.IsBreak()) { SkipLine(); } return result; } private void FetchDocumentIndicator(bool isStartToken) { UnrollIndent(-1L); RemoveSimpleKey(); simpleKeyAllowed = false; Mark end = cursor.Mark(); Skip(); Skip(); Skip(); if (isStartToken) { InsertionQueue insertionQueue = tokens; Mark end2 = cursor.Mark(); insertionQueue.Enqueue(new YamlDotNet.Core.Tokens.DocumentStart(in end, in end2)); return; } Token token = null; while (!analyzer.EndOfInput && !analyzer.IsBreak() && !analyzer.Check('#')) { if (!analyzer.IsWhite()) { token = new Error("While scanning a document end, found invalid content after '...' marker.", end, cursor.Mark()); break; } Skip(); } tokens.Enqueue(new YamlDotNet.Core.Tokens.DocumentEnd(in end, in end)); if (token != null) { tokens.Enqueue(token); } } private void FetchFlowCollectionStart(bool isSequenceToken) { SaveSimpleKey(); IncreaseFlowLevel(); simpleKeyAllowed = true; Mark start = cursor.Mark(); Skip(); Token item = ((!isSequenceToken) ? ((Token)new FlowMappingStart(in start, in start)) : ((Token)new FlowSequenceStart(in start, in start))); tokens.Enqueue(item); startFlowCollectionFetched = true; } private void IncreaseFlowLevel() { simpleKeys.Push(new SimpleKey()); flowLevel++; } private void FetchFlowCollectionEnd(bool isSequenceToken) { RemoveSimpleKey(); DecreaseFlowLevel(); simpleKeyAllowed = false; Mark start = cursor.Mark(); Skip(); Token token = null; Token item; if (isSequenceToken) { if (analyzer.Check('#')) { token = new Error("While scanning a flow sequence end, found invalid comment after ']'.", start, start); } item = new FlowSequenceEnd(in start, in start); } else { item = new FlowMappingEnd(in start, in start); } tokens.Enqueue(item); if (token != null) { tokens.Enqueue(token); } flowCollectionFetched = true; } private void DecreaseFlowLevel() { if (flowLevel > 0) { flowLevel--; simpleKeys.Pop(); } } private void FetchFlowEntry() { RemoveSimpleKey(); simpleKeyAllowed = true; Mark start = cursor.Mark(); Skip(); Mark end = cursor.Mark(); if (analyzer.Check('#')) { tokens.Enqueue(new Error("While scanning a flow entry, found invalid comment after comma.", start, end)); } else { tokens.Enqueue(new FlowEntry(in start, in end)); } } private void FetchBlockEntry() { Mark start; if (flowLevel == 0) { if (!simpleKeyAllowed) { if (previousAnchor != null && previousAnchor.End.Line == cursor.Line) { start = previousAnchor.Start; Mark end = previousAnchor.End; throw new SemanticErrorException(in start, in end, "Anchor before sequence entry on same line is not allowed."); } Mark mark = cursor.Mark(); tokens.Enqueue(new Error("Block sequence entries are not allowed in this context.", mark, mark)); } RollIndent(cursor.LineOffset, -1, isSequence: true, cursor.Mark()); } RemoveSimpleKey(); simpleKeyAllowed = true; Mark start2 = cursor.Mark(); Skip(); InsertionQueue insertionQueue = tokens; start = cursor.Mark(); insertionQueue.Enqueue(new BlockEntry(in start2, in start)); } private void FetchKey() { if (flowLevel == 0) { if (!simpleKeyAllowed) { Mark start = cursor.Mark(); throw new SyntaxErrorException(in start, in start, "Mapping keys are not allowed in this context."); } RollIndent(cursor.LineOffset, -1, isSequence: false, cursor.Mark()); } RemoveSimpleKey(); simpleKeyAllowed = flowLevel == 0; Mark start2 = cursor.Mark(); Skip(); InsertionQueue insertionQueue = tokens; Mark end = cursor.Mark(); insertionQueue.Enqueue(new Key(in start2, in end)); } private void FetchValue() { SimpleKey simpleKey = simpleKeys.Peek(); Mark start; if (simpleKey.IsPossible) { InsertionQueue insertionQueue = tokens; int index = simpleKey.TokenNumber - tokensParsed; start = simpleKey.Mark; Mark end = simpleKey.Mark; insertionQueue.Insert(index, new Key(in start, in end)); RollIndent(simpleKey.LineOffset, simpleKey.TokenNumber, isSequence: false, simpleKey.Mark); simpleKey.MarkAsImpossible(); simpleKeyAllowed = false; } else { bool flag = flowLevel == 0; if (flag) { if (!simpleKeyAllowed) { Mark mark = cursor.Mark(); tokens.Enqueue(new Error("Mapping values are not allowed in this context.", mark, mark)); return; } RollIndent(cursor.LineOffset, -1, isSequence: false, cursor.Mark()); if (cursor.LineOffset == 0L && simpleKey.LineOffset == 0L) { InsertionQueue insertionQueue2 = tokens; int count = tokens.Count; start = simpleKey.Mark; Mark end = simpleKey.Mark; insertionQueue2.Insert(count, new Key(in start, in end)); flag = false; } } simpleKeyAllowed = flag; } Mark start2 = cursor.Mark(); Skip(); InsertionQueue insertionQueue3 = tokens; start = cursor.Mark(); insertionQueue3.Enqueue(new Value(in start2, in start)); } private void RollIndent(long column, int number, bool isSequence, Mark position) { if (flowLevel <= 0 && indent < column) { indents.Push(indent); indent = column; Token item = ((!isSequence) ? ((Token)new BlockMappingStart(in position, in position)) : ((Token)new BlockSequenceStart(in position, in position))); if (number == -1) { tokens.Enqueue(item); } else { tokens.Insert(number - tokensParsed, item); } } } private void FetchAnchor(bool isAlias) { SaveSimpleKey(); simpleKeyAllowed = false; tokens.Enqueue(ScanAnchor(isAlias)); } private Token ScanAnchor(bool isAlias) { Mark start = cursor.Mark(); Skip(); bool flag = false; if (isAlias) { SimpleKey simpleKey = simpleKeys.Peek(); flag = simpleKey.IsRequired && simpleKey.IsPossible; } StringBuilderPool.BuilderWrapper builderWrapper = StringBuilderPool.Rent(); try { StringBuilder builder = builderWrapper.Builder; while (!analyzer.IsWhiteBreakOrZero() && !analyzer.Check("[]{},") && (!flag || !analyzer.Check(':') || !analyzer.IsWhiteBreakOrZero(1))) { builder.Append(ReadCurrentCharacter()); } if (builder.Length == 0 || (!analyzer.IsWhiteBreakOrZero() && !analyzer.Check("?:,]}%@`"))) { Mark end = cursor.Mark(); throw new SyntaxErrorException(in start, in end, "While scanning an anchor or alias, found value containing disallowed: []{},"); } AnchorName value = new AnchorName(builder.ToString()); if (isAlias) { return new YamlDotNet.Core.Tokens.AnchorAlias(value, start, cursor.Mark()); } return previousAnchor = new Anchor(value, start, cursor.Mark()); } finally { ((IDisposable)builderWrapper).Dispose(); } } private void FetchTag() { SaveSimpleKey(); simpleKeyAllowed = false; tokens.Enqueue(ScanTag()); } private Tag ScanTag() { Mark start = cursor.Mark(); string text; string text2; if (analyzer.Check('<', 1)) { text = string.Empty; Skip(); Skip(); text2 = ScanTagUri(null, start); if (!analyzer.Check('>')) { Mark end = cursor.Mark(); throw new SyntaxErrorException(in start, in end, "While scanning a tag, did not find the expected '>'."); } Skip(); } else { string text3 = ScanTagHandle(isDirective: false, start); if (text3.Length > 1 && text3[0] == '!' && text3[text3.Length - 1] == '!') { text = text3; text2 = ScanTagUri(null, start); } else { text2 = ScanTagUri(text3, start); text = "!"; if (text2.Length == 0) { text2 = text; text = string.Empty; } } } if (!analyzer.IsWhiteBreakOrZero() && !analyzer.Check(',')) { Mark end = cursor.Mark(); throw new SyntaxErrorException(in start, in end, "While scanning a tag, did not find expected whitespace, comma or line break."); } return new Tag(text, text2, start, cursor.Mark()); } private void FetchBlockScalar(bool isLiteral) { SaveSimpleKey(); simpleKeyAllowed = true; tokens.Enqueue(ScanBlockScalar(isLiteral)); } private YamlDotNet.Core.Tokens.Scalar ScanBlockScalar(bool isLiteral) { StringBuilderPool.BuilderWrapper builderWrapper = StringBuilderPool.Rent(); try { StringBuilder builder = builderWrapper.Builder; StringBuilderPool.BuilderWrapper builderWrapper2 = StringBuilderPool.Rent(); try { StringBuilder builder2 = builderWrapper2.Builder; StringBuilderPool.BuilderWrapper builderWrapper3 = StringBuilderPool.Rent(); try { StringBuilder builder3 = builderWrapper3.Builder; int num = 0; int num2 = 0; long currentIndent = 0L; bool flag = false; bool? isFirstLine = null; Mark start = cursor.Mark(); Skip(); if (analyzer.Check("+-")) { num = (analyzer.Check('+') ? 1 : (-1)); Skip(); if (analyzer.IsDigit()) { if (analyzer.Check('0')) { Mark end = cursor.Mark(); throw new SyntaxErrorException(in start, in end, "While scanning a block scalar, found an indentation indicator equal to 0."); } num2 = analyzer.AsDigit(); Skip(); } } else if (analyzer.IsDigit()) { if (analyzer.Check('0')) { Mark end = cursor.Mark(); throw new SyntaxErrorException(in start, in end, "While scanning a block scalar, found an indentation indicator equal to 0."); } num2 = analyzer.AsDigit(); Skip(); if (analyzer.Check("+-")) { num = (analyzer.Check('+') ? 1 : (-1)); Skip(); } } if (analyzer.Check('#')) { Mark end = cursor.Mark(); throw new SyntaxErrorException(in start, in end, "While scanning a block scalar, found a comment without whtespace after '>' indicator."); } while (analyzer.IsWhite()) { Skip(); } ProcessComment(); if (!analyzer.IsBreakOrZero()) { Mark end = cursor.Mark(); throw new SyntaxErrorException(in start, in end, "While scanning a block scalar, did not find expected comment or line break."); } if (analyzer.IsBreak()) { SkipLine(); if (!isFirstLine.HasValue) { isFirstLine = true; } else if (isFirstLine.GetValueOrDefault()) { isFirstLine = false; } } Mark end2 = cursor.Mark(); if (num2 != 0) { currentIndent = ((indent >= 0) ? (indent + num2) : num2); } currentIndent = ScanBlockScalarBreaks(currentIndent, builder3, isLiteral, ref end2, ref isFirstLine); isFirstLine = false; while (cursor.LineOffset == currentIndent && !analyzer.IsZero() && !IsDocumentEnd()) { bool flag2 = analyzer.IsWhite(); if (!isLiteral && StartsWith(builder2, '\n') && !flag && !flag2) { if (builder3.Length == 0) { builder.Append(' '); } builder2.Length = 0; } else { builder.Append((object?)builder2); builder2.Length = 0; } builder.Append((object?)builder3); builder3.Length = 0; flag = analyzer.IsWhite(); while (!analyzer.IsBreakOrZero()) { builder.Append(ReadCurrentCharacter()); } char c = ReadLine(); if (c != 0) { builder2.Append(c); } currentIndent = ScanBlockScalarBreaks(currentIndent, builder3, isLiteral, ref end2, ref isFirstLine); } if (num != -1) { builder.Append((object?)builder2); } if (num == 1) { builder.Append((object?)builder3); } ScalarStyle style = (isLiteral ? ScalarStyle.Literal : ScalarStyle.Folded); return new YamlDotNet.Core.Tokens.Scalar(builder.ToString(), style, start, end2); } finally { ((IDisposable)builderWrapper3).Dispose(); } } finally { ((IDisposable)builderWrapper2).Dispose(); } } finally { ((IDisposable)builderWrapper).Dispose(); } } private long ScanBlockScalarBreaks(long currentIndent, StringBuilder breaks, bool isLiteral, ref Mark end, ref bool? isFirstLine) { long num = 0L; long num2 = -1L; end = cursor.Mark(); while (true) { if ((currentIndent == 0L || cursor.LineOffset < currentIndent) && analyzer.IsSpace()) { Skip(); continue; } if (cursor.LineOffset > num) { num = cursor.LineOffset; } if (!analyzer.IsBreak()) { break; } if (isFirstLine.GetValueOrDefault()) { isFirstLine = false; num2 = cursor.LineOffset; } breaks.Append(ReadLine()); end = cursor.Mark(); } if (isLiteral && isFirstLine.GetValueOrDefault()) { long num3 = cursor.LineOffset; int num4 = 0; while (!analyzer.IsBreak(num4) && analyzer.IsSpace(num4)) { num4++; num3++; } if (analyzer.IsBreak(num4) && num3 > cursor.LineOffset) { isFirstLine = false; num2 = num3; } } if (isLiteral && num2 > 1 && currentIndent < num2 - 1) { Mark end2 = cursor.Mark(); throw new SemanticErrorException(in end, in end2, "While scanning a literal block scalar, found extra spaces in first line."); } if (!isLiteral && num > cursor.LineOffset && num2 > -1) { Mark end2 = cursor.Mark(); throw new SemanticErrorException(in end, in end2, "While scanning a literal block scalar, found more spaces in lines above first content line."); } if (currentIndent == 0L && (cursor.LineOffset > 0 || indent > -1)) { currentIndent = Math.Max(num, Math.Max(indent + 1, 1L)); } return currentIndent; } private void FetchQuotedScalar(bool isSingleQuoted) { SaveSimpleKey(); simpleKeyAllowed = false; flowScalarFetched = flowLevel > 0; YamlDotNet.Core.Tokens.Scalar item = ScanFlowScalar(isSingleQuoted); tokens.Enqueue(item); lastScalar = item; if (!isSingleQuoted && analyzer.Check('#')) { Mark mark = cursor.Mark(); tokens.Enqueue(new Error("While scanning a flow sequence end, found invalid comment after double-quoted scalar.", mark, mark)); } } private YamlDotNet.Core.Tokens.Scalar ScanFlowScalar(bool isSingleQuoted) { Mark start = cursor.Mark(); Skip(); StringBuilderPool.BuilderWrapper builderWrapper = StringBuilderPool.Rent(); try { StringBuilder builder = builderWrapper.Builder; StringBuilderPool.BuilderWrapper builderWrapper2 = StringBuilderPool.Rent(); try { StringBuilder builder2 = builderWrapper2.Builder; StringBuilderPool.BuilderWrapper builderWrapper3 = StringBuilderPool.Rent(); try { StringBuilder builder3 = builderWrapper3.Builder; StringBuilderPool.BuilderWrapper builderWrapper4 = StringBuilderPool.Rent(); try { StringBuilder builder4 = builderWrapper4.Builder; bool flag = false; while (true) { if (IsDocumentIndicator()) { Mark end = cursor.Mark(); throw new SyntaxErrorException(in start, in end, "While scanning a quoted scalar, found unexpected document indicator."); } if (analyzer.IsZero()) { Mark end = cursor.Mark(); throw new SyntaxErrorException(in start, in end, "While scanning a quoted scalar, found unexpected end of stream."); } if (flag && !isSingleQuoted && indent >= cursor.LineOffset) { Mark end = cursor.Mark(); throw new SyntaxErrorException(in start, in end, "While scanning a multi-line double-quoted scalar, found wrong indentation."); } flag = false; while (!analyzer.IsWhiteBreakOrZero()) { if (isSingleQuoted && analyzer.Check('\'') && analyzer.Check('\'', 1)) { builder.Append('\''); Skip(); Skip(); continue; } if (analyzer.Check(isSingleQuoted ? '\'' : '"')) { break; } if (!isSingleQuoted && analyzer.Check('\\') && analyzer.IsBreak(1)) { Skip(); SkipLine(); flag = true; break; } if (!isSingleQuoted && analyzer.Check('\\')) { int num = 0; char c = analyzer.Peek(1); switch (c) { case 'x': num = 2; break; case 'u': num = 4; break; case 'U': num = 8; break; default: { if (SimpleEscapeCodes.TryGetValue(c, out var value)) { builder.Append(value); break; } Mark end = cursor.Mark(); throw new SyntaxErrorException(in start, in end, "While scanning a quoted scalar, found unknown escape character."); } } Skip(); Skip(); if (num <= 0) { continue; } int num2 = 0; for (int i = 0; i < num; i++) { if (!analyzer.IsHex(i)) { Mark end = cursor.Mark(); throw new SyntaxErrorException(in start, in end, "While scanning a quoted scalar, did not find expected hexadecimal number."); } num2 = (num2 << 4) + analyzer.AsHex(i); } if (num2 >= 55296 && num2 <= 57343) { for (int j = 0; j < num; j++) { Skip(); } if (analyzer.Peek(0) != '\\' || (analyzer.Peek(1) != 'u' && analyzer.Peek(1) != 'U')) { Mark end = cursor.Mark(); throw new SyntaxErrorException(in start, in end, "While scanning a quoted scalar, found invalid Unicode surrogates."); } Skip(); num = ((analyzer.Peek(0) != 'u') ? 8 : 4); Skip(); int num3 = 0; for (int k = 0; k < num; k++) { if (!analyzer.IsHex(0)) { Mark end = cursor.Mark(); throw new SyntaxErrorException(in start, in end, "While scanning a quoted scalar, did not find expected hexadecimal number."); } num3 = (num3 << 4) + analyzer.AsHex(k); } for (int l = 0; l < num; l++) { Skip(); } num2 = char.ConvertToUtf32((char)num2, (char)num3); } else { if (num2 > 1114111) { Mark end = cursor.Mark(); throw new SyntaxErrorException(in start, in end, "While scanning a quoted scalar, found invalid Unicode character escape code."); } for (int m = 0; m < num; m++) { Skip(); } } builder.Append(char.ConvertFromUtf32(num2)); } else { builder.Append(ReadCurrentCharacter()); } } if (analyzer.Check(isSingleQuoted ? '\'' : '"')) { break; } while (analyzer.IsWhite() || analyzer.IsBreak()) { if (analyzer.IsWhite()) { if (!flag) { builder2.Append(ReadCurrentCharacter()); } else { Skip(); } } else if (!flag) { builder2.Length = 0; builder3.Append(ReadLine()); flag = true; } else { builder4.Append(ReadLine()); } } if (flag) { if (StartsWith(builder3, '\n')) { if (builder4.Length == 0) { builder.Append(' '); } else { builder.Append((object?)builder4); } } else { builder.Append((object?)builder3); builder.Append((object?)builder4); } builder3.Length = 0; builder4.Length = 0; } else { builder.Append((object?)builder2); builder2.Length = 0; } } Skip(); return new YamlDotNet.Core.Tokens.Scalar(builder.ToString(), isSingleQuoted ? ScalarStyle.SingleQuoted : ScalarStyle.DoubleQuoted, start, cursor.Mark()); } finally { ((IDisposable)builderWrapper4).Dispose(); } } finally { ((IDisposable)builderWrapper3).Dispose(); } } finally { ((IDisposable)builderWrapper2).Dispose(); } } finally { ((IDisposable)builderWrapper).Dispose(); } } private void FetchPlainScalar() { SaveSimpleKey(); simpleKeyAllowed = false; bool isMultiline = false; YamlDotNet.Core.Tokens.Scalar item = (lastScalar = ScanPlainScalar(ref isMultiline)); if (isMultiline && analyzer.Check(':') && flowLevel == 0 && indent < cursor.LineOffset) { tokens.Enqueue(new Error("While scanning a multiline plain scalar, found invalid mapping.", cursor.Mark(), cursor.Mark())); } tokens.Enqueue(item); } private YamlDotNet.Core.Tokens.Scalar ScanPlainScalar(ref bool isMultiline) { StringBuilderPool.BuilderWrapper builderWrapper = StringBuilderPool.Rent(); try { StringBuilder builder = builderWrapper.Builder; StringBuilderPool.BuilderWrapper builderWrapper2 = StringBuilderPool.Rent(); try { StringBuilder builder2 = builderWrapper2.Builder; StringBuilderPool.BuilderWrapper builderWrapper3 = StringBuilderPool.Rent(); try { StringBuilder builder3 = builderWrapper3.Builder; StringBuilderPool.BuilderWrapper builderWrapper4 = StringBuilderPool.Rent(); try { StringBuilder builder4 = builderWrapper4.Builder; bool flag = false; long num = indent + 1; Mark start = cursor.Mark(); Mark end = start; SimpleKey simpleKey = simpleKeys.Peek(); while (!IsDocumentIndicator()) { if (analyzer.Check('#')) { if (indent < 0 && flowLevel == 0) { plainScalarFollowedByComment = true; } break; } bool flag2 = analyzer.Check('*') && (!simpleKey.IsPossible || !simpleKey.IsRequired); while (!analyzer.IsWhiteBreakOrZero()) { if ((analyzer.Check(':') && !flag2 && (analyzer.IsWhiteBreakOrZero(1) || (flowLevel > 0 && analyzer.Check(',', 1)))) || (flowLevel > 0 && analyzer.Check(",[]{}"))) { if (flowLevel == 0 && !simpleKey.IsPossible) { tokens.Enqueue(new Error("While scanning a plain scalar value, found invalid mapping.", cursor.Mark(), cursor.Mark())); } break; } if (flag || builder2.Length > 0) { if (flag) { if (StartsWith(builder3, '\n')) { if (builder4.Length == 0) { builder.Append(' '); } else { builder.Append((object?)builder4); } } else { builder.Append((object?)builder3); builder.Append((object?)builder4); } builder3.Length = 0; builder4.Length = 0; flag = false; } else { builder.Append((object?)builder2); builder2.Length = 0; } } if (flowLevel > 0 && cursor.LineOffset < num) { throw new InvalidOperationException(); } builder.Append(ReadCurrentCharacter()); end = cursor.Mark(); } if (!analyzer.IsWhite() && !analyzer.IsBreak()) { break; } while (analyzer.IsWhite() || analyzer.IsBreak()) { if (analyzer.IsWhite()) { if (flag && cursor.LineOffset < num && analyzer.IsTab()) { Mark end2 = cursor.Mark(); throw new SyntaxErrorException(in start, in end2, "While scanning a plain scalar, found a tab character that violate indentation."); } if (!flag) { builder2.Append(ReadCurrentCharacter()); } else { Skip(); } } else { isMultiline = true; if (!flag) { builder2.Length = 0; builder3.Append(ReadLine()); flag = true; } else { builder4.Append(ReadLine()); } } } if (flowLevel == 0 && cursor.LineOffset < num) { break; } } if (flag) { simpleKeyAllowed = true; } return new YamlDotNet.Core.Tokens.Scalar(builder.ToString(), ScalarStyle.Plain, start, end); } finally { ((IDisposable)builderWrapper4).Dispose(); } } finally { ((IDisposable)builderWrapper3).Dispose(); } } finally { ((IDisposable)builderWrapper2).Dispose(); } } finally { ((IDisposable)builderWrapper).Dispose(); } } private void RemoveSimpleKey() { SimpleKey simpleKey = simpleKeys.Peek(); if (simpleKey.IsPossible && simpleKey.IsRequired) { Mark start = simpleKey.Mark; Mark end = simpleKey.Mark; throw new SyntaxErrorException(in start, in end, "While scanning a simple key, could not find expected ':'."); } simpleKey.MarkAsImpossible(); } private string ScanDirectiveName(in Mark start) { StringBuilderPool.BuilderWrapper builderWrapper = StringBuilderPool.Rent(); try { StringBuilder builder = builderWrapper.Builder; while (analyzer.IsAlphaNumericDashOrUnderscore()) { builder.Append(ReadCurrentCharacter()); } if (builder.Length == 0) { Mark end = cursor.Mark(); throw new SyntaxErrorException(in start, in end, "While scanning a directive, could not find expected directive name."); } if (analyzer.EndOfInput) { Mark end = cursor.Mark(); throw new SyntaxErrorException(in start, in end, "While scanning a directive, found unexpected end of stream."); } if (!analyzer.IsWhiteBreakOrZero()) { Mark end = cursor.Mark(); throw new SyntaxErrorException(in start, in end, "While scanning a directive, found unexpected non-alphabetical character."); } return builder.ToString(); } finally { ((IDisposable)builderWrapper).Dispose(); } } private void SkipWhitespaces() { while (analyzer.IsWhite()) { Skip(); } } private VersionDirective ScanVersionDirectiveValue(in Mark start) { SkipWhitespaces(); int major = ScanVersionDirectiveNumber(in start); if (!analyzer.Check('.')) { Mark end = cursor.Mark(); throw new SyntaxErrorException(in start, in end, "While scanning a %YAML directive, did not find expected digit or '.' character."); } Skip(); int minor = ScanVersionDirectiveNumber(in start); return new VersionDirective(new Version(major, minor), start, start); } private TagDirective ScanTagDirectiveValue(in Mark start) { SkipWhitespaces(); string handle = ScanTagHandle(isDirective: true, start); if (!analyzer.IsWhite()) { Mark end = cursor.Mark(); throw new SyntaxErrorException(in start, in end, "While scanning a %TAG directive, did not find expected whitespace."); } SkipWhitespaces(); string prefix = ScanTagUri(null, start); if (!analyzer.IsWhiteBreakOrZero()) { Mark end = cursor.Mark(); throw new SyntaxErrorException(in start, in end, "While scanning a %TAG directive, did not find expected whitespace or line break."); } return new TagDirective(handle, prefix, start, start); } private string ScanTagUri(string? head, Mark start) { StringBuilderPool.BuilderWrapper builderWrapper = StringBuilderPool.Rent(); try { StringBuilder builder = builderWrapper.Builder; if (head != null && head.Length > 1) { builder.Append(head.Substring(1)); } while (analyzer.IsAlphaNumericDashOrUnderscore() || analyzer.Check(";/?:@&=+$.!~*'()[]%") || (analyzer.Check(',') && !analyzer.IsBreak(1))) { if (analyzer.Check('%')) { builder.Append(ScanUriEscapes(in start)); } else if (analyzer.Check('+')) { builder.Append(' '); Skip(); } else { builder.Append(ReadCurrentCharacter()); } } if (builder.Length == 0) { return string.Empty; } string text = builder.ToString(); if (Polyfills.EndsWith(text, ',')) { Mark start2 = cursor.Mark(); Mark end = cursor.Mark(); throw new SyntaxErrorException(in start2, in end, "Unexpected comma at end of tag"); } return text; } finally { ((IDisposable)builderWrapper).Dispose(); } } private string ScanUriEscapes(in Mark start) { byte[] array = EmptyBytes; int count = 0; int num = 0; do { if (!analyzer.Check('%') || !analyzer.IsHex(1) || !analyzer.IsHex(2)) { Mark end = cursor.Mark(); throw new SyntaxErrorException(in start, in end, "While scanning a tag, did not find URI escaped octet."); } int num2 = (analyzer.AsHex(1) << 4) + analyzer.AsHex(2); if (num == 0) { num = (((num2 & 0x80) == 0) ? 1 : (((num2 & 0xE0) == 192) ? 2 : (((num2 & 0xF0) == 224) ? 3 : (((num2 & 0xF8) == 240) ? 4 : 0)))); if (num == 0) { Mark end = cursor.Mark(); throw new SyntaxErrorException(in start, in end, "While scanning a tag, found an incorrect leading UTF-8 octet."); } array = new byte[num]; } else if ((num2 & 0xC0) != 128) { Mark end = cursor.Mark(); throw new SyntaxErrorException(in start, in end, "While scanning a tag, found an incorrect trailing UTF-8 octet."); } array[count++] = (byte)num2; Skip(); Skip(); Skip(); } while (--num > 0); string @string = Encoding.UTF8.GetString(array, 0, count); if (@string.Length == 0 || @string.Length > 2) { Mark end = cursor.Mark(); throw new SyntaxErrorException(in start, in end, "While scanning a tag, found an incorrect UTF-8 sequence."); } return @string; } private string ScanTagHandle(bool isDirective, Mark start) { if (!analyzer.Check('!')) { Mark end = cursor.Mark(); throw new SyntaxErrorException(in start, in end, "While scanning a tag, did not find expected '!'."); } StringBuilderPool.BuilderWrapper builderWrapper = StringBuilderPool.Rent(); try { StringBuilder builder = builderWrapper.Builder; builder.Append(ReadCurrentCharacter()); while (analyzer.IsAlphaNumericDashOrUnderscore()) { builder.Append(ReadCurrentCharacter()); } if (analyzer.Check('!')) { builder.Append(ReadCurrentCharacter()); } else if (isDirective && (builder.Length != 1 || builder[0] != '!')) { Mark end = cursor.Mark(); throw new SyntaxErrorException(in start, in end, "While scanning a tag directive, did not find expected '!'."); } return builder.ToString(); } finally { ((IDisposable)builderWrapper).Dispose(); } } private int ScanVersionDirectiveNumber(in Mark start) { int num = 0; int num2 = 0; while (analyzer.IsDigit()) { if (++num2 > 9) { Mark end = cursor.Mark(); throw new SyntaxErrorException(in start, in end, "While scanning a %YAML directive, found extremely long version number."); } num = num * 10 + analyzer.AsDigit(); Skip(); } if (num2 == 0) { Mark end = cursor.Mark(); throw new SyntaxErrorException(in start, in end, "While scanning a %YAML directive, did not find expected version number."); } return num; } private void SaveSimpleKey() { bool isRequired = flowLevel == 0 && indent == cursor.LineOffset; if (simpleKeyAllowed) { SimpleKey item = new SimpleKey(isRequired, tokensParsed + tokens.Count, cursor); RemoveSimpleKey(); simpleKeys.Pop(); simpleKeys.Push(item); } } } internal class SemanticErrorException : YamlException { public SemanticErrorException(string message) : base(message) { } public SemanticErrorException(in Mark start, in Mark end, string message) : base(in start, in end, message) { } public SemanticErrorException(string message, Exception inner) : base(message, inner) { } } internal sealed class SimpleKey { private readonly Cursor cursor; public bool IsPossible { get; private set; } public bool IsRequired { get; } public int TokenNumber { get; } public long Index => cursor.Index; public long Line => cursor.Line; public long LineOffset => cursor.LineOffset; public Mark Mark => cursor.Mark(); public void MarkAsImpossible() { IsPossible = false; } public SimpleKey() { cursor = new Cursor(); } public SimpleKey(bool isRequired, int tokenNumber, Cursor cursor) { IsPossible = true; IsRequired = isRequired; TokenNumber = tokenNumber; this.cursor = new Cursor(cursor); } } internal sealed class StringLookAheadBuffer : ILookAheadBuffer, IResettable { public string Value { get; set; } = string.Empty; public int Position { get; private set; } public int Length => Value.Length; public bool EndOfInput => IsOutside(Position); public char Peek(int offset) { int index = Position + offset; if (!IsOutside(index)) { return Value[index]; } return '\0'; } private bool IsOutside(int index) { return index >= Value.Length; } public void Skip(int length) { if (length < 0) { throw new ArgumentOutOfRangeException("length", "The length must be positive."); } Position += length; } public bool TryReset() { Position = 0; Value = string.Empty; return true; } } internal sealed class SyntaxErrorException : YamlException { public SyntaxErrorException(string message) : base(message) { } public SyntaxErrorException(in Mark start, in Mark end, string message) : base(in start, in end, message) { } public SyntaxErrorException(string message, Exception inner) : base(message, inner) { } } internal sealed class TagDirectiveCollection : KeyedCollection { public TagDirectiveCollection() { } public TagDirectiveCollection(IEnumerable tagDirectives) { foreach (TagDirective tagDirective in tagDirectives) { Add(tagDirective); } } protected override string GetKeyForItem(TagDirective item) { return item.Handle; } public new bool Contains(TagDirective directive) { return Contains(GetKeyForItem(directive)); } } internal readonly struct TagName : IEquatable { public static readonly TagName Empty; private readonly string? value; public string Value => value ?? throw new InvalidOperationException("Cannot read the Value of a non-specific tag"); public bool IsEmpty => value == null; public bool IsNonSpecific { get { if (!IsEmpty) { if (!(value == "!")) { return value == "?"; } return true; } return false; } } public bool IsLocal { get { if (!IsEmpty) { return Value[0] == '!'; } return false; } } public bool IsGlobal { get { if (!IsEmpty) { return !IsLocal; } return false; } } public TagName(string value) { this.value = value ?? throw new ArgumentNullException("value"); if (value.Length == 0) { throw new ArgumentException("Tag value must not be empty.", "value"); } if (IsGlobal && !Uri.IsWellFormedUriString(value, UriKind.RelativeOrAbsolute)) { throw new ArgumentException("Global tags must be valid URIs.", "value"); } } public override string ToString() { return value ?? "?"; } public bool Equals(TagName other) { return object.Equals(value, other.value); } public override bool Equals(object? obj) { if (obj is TagName other) { return Equals(other); } return false; } public override int GetHashCode() { return value?.GetHashCode() ?? 0; } public static bool operator ==(TagName left, TagName right) { return left.Equals(right); } public static bool operator !=(TagName left, TagName right) { return !(left == right); } public static bool operator ==(TagName left, string right) { return object.Equals(left.value, right); } public static bool operator !=(TagName left, string right) { return !(left == right); } public static implicit operator TagName(string? value) { if (value != null) { return new TagName(value); } return Empty; } } internal sealed class Version { public int Major { get; } public int Minor { get; } public Version(int major, int minor) { if (major < 0) { throw new ArgumentOutOfRangeException("major", $"{major} should be >= 0"); } Major = major; if (minor < 0) { throw new ArgumentOutOfRangeException("minor", $"{minor} should be >= 0"); } Minor = minor; } public override bool Equals(object? obj) { if (obj is Version version && Major == version.Major) { return Minor == version.Minor; } return false; } public override int GetHashCode() { return HashCode.CombineHashCodes(Major.GetHashCode(), Minor.GetHashCode()); } } internal class YamlException : Exception { public Mark Start { get; } public Mark End { get; } public YamlException(string message) : this(in Mark.Empty, in Mark.Empty, message) { } public YamlException(in Mark start, in Mark end, string message) : this(in start, in end, message, null) { } public YamlException(in Mark start, in Mark end, string message, Exception? innerException) : base(message, innerException) { Start = start; End = end; } public YamlException(string message, Exception inner) : this(in Mark.Empty, in Mark.Empty, message, inner) { } public override string ToString() { return $"({Start}) - ({End}): {Message}"; } } } namespace YamlDotNet.Core.Tokens { internal class Anchor : Token { public AnchorName Value { get; } public Anchor(AnchorName value) : this(value, Mark.Empty, Mark.Empty) { } public Anchor(AnchorName value, Mark start, Mark end) : base(in start, in end) { if (value.IsEmpty) { throw new ArgumentNullException("value"); } Value = value; } } internal sealed class AnchorAlias : Token { public AnchorName Value { get; } public AnchorAlias(AnchorName value) : this(value, Mark.Empty, Mark.Empty) { } public AnchorAlias(AnchorName value, Mark start, Mark end) : base(in start, in end) { if (value.IsEmpty) { throw new ArgumentNullException("value"); } Value = value; } } internal sealed class BlockEnd : Token { public BlockEnd() : this(in Mark.Empty, in Mark.Empty) { } public BlockEnd(in Mark start, in Mark end) : base(in start, in end) { } } internal sealed class BlockEntry : Token { public BlockEntry() : this(in Mark.Empty, in Mark.Empty) { } public BlockEntry(in Mark start, in Mark end) : base(in start, in end) { } } internal sealed class BlockMappingStart : Token { public BlockMappingStart() : this(in Mark.Empty, in Mark.Empty) { } public BlockMappingStart(in Mark start, in Mark end) : base(in start, in end) { } } internal sealed class BlockSequenceStart : Token { public BlockSequenceStart() : this(in Mark.Empty, in Mark.Empty) { } public BlockSequenceStart(in Mark start, in Mark end) : base(in start, in end) { } } internal sealed class Comment : Token { public string Value { get; } public bool IsInline { get; } public Comment(string value, bool isInline) : this(value, isInline, Mark.Empty, Mark.Empty) { } public Comment(string value, bool isInline, Mark start, Mark end) : base(in start, in end) { Value = value ?? throw new ArgumentNullException("value"); IsInline = isInline; } } internal sealed class DocumentEnd : Token { public DocumentEnd() : this(in Mark.Empty, in Mark.Empty) { } public DocumentEnd(in Mark start, in Mark end) : base(in start, in end) { } } internal sealed class DocumentStart : Token { public DocumentStart() : this(in Mark.Empty, in Mark.Empty) { } public DocumentStart(in Mark start, in Mark end) : base(in start, in end) { } } internal class Error : Token { public string Value { get; } public Error(string value, Mark start, Mark end) : base(in start, in end) { Value = value; } } internal sealed class FlowEntry : Token { public FlowEntry() : this(in Mark.Empty, in Mark.Empty) { } public FlowEntry(in Mark start, in Mark end) : base(in start, in end) { } } internal sealed class FlowMappingEnd : Token { public FlowMappingEnd() : this(in Mark.Empty, in Mark.Empty) { } public FlowMappingEnd(in Mark start, in Mark end) : base(in start, in end) { } } internal sealed class FlowMappingStart : Token { public FlowMappingStart() : this(in Mark.Empty, in Mark.Empty) { } public FlowMappingStart(in Mark start, in Mark end) : base(in start, in end) { } } internal sealed class FlowSequenceEnd : Token { public FlowSequenceEnd() : this(in Mark.Empty, in Mark.Empty) { } public FlowSequenceEnd(in Mark start, in Mark end) : base(in start, in end) { } } internal sealed class FlowSequenceStart : Token { public FlowSequenceStart() : this(in Mark.Empty, in Mark.Empty) { } public FlowSequenceStart(in Mark start, in Mark end) : base(in start, in end) { } } internal sealed class Key : Token { public Key() : this(in Mark.Empty, in Mark.Empty) { } public Key(in Mark start, in Mark end) : base(in start, in end) { } } internal sealed class Scalar : Token { public bool IsKey { get; set; } public string Value { get; } public ScalarStyle Style { get; } public Scalar(string value) : this(value, ScalarStyle.Any) { } public Scalar(string value, ScalarStyle style) : this(value, style, Mark.Empty, Mark.Empty) { } public Scalar(string value, ScalarStyle style, Mark start, Mark end) : base(in start, in end) { Value = value ?? throw new ArgumentNullException("value"); Style = style; } } internal sealed class StreamEnd : Token { public StreamEnd() : this(in Mark.Empty, in Mark.Empty) { } public StreamEnd(in Mark start, in Mark end) : base(in start, in end) { } } internal sealed class StreamStart : Token { public StreamStart() : this(in Mark.Empty, in Mark.Empty) { } public StreamStart(in Mark start, in Mark end) : base(in start, in end) { } } internal sealed class Tag : Token { public string Handle { get; } public string Suffix { get; } public Tag(string handle, string suffix) : this(handle, suffix, Mark.Empty, Mark.Empty) { } public Tag(string handle, string suffix, Mark start, Mark end) : base(in start, in end) { Handle = handle ?? throw new ArgumentNullException("handle"); Suffix = suffix ?? throw new ArgumentNullException("suffix"); } } internal class TagDirective : Token { private static readonly Regex TagHandlePattern = new Regex("^!([0-9A-Za-z_\\-]*!)?$", RegexOptions.Compiled); public string Handle { get; } public string Prefix { get; } public TagDirective(string handle, string prefix) : this(handle, prefix, Mark.Empty, Mark.Empty) { } public TagDirective(string handle, string prefix, Mark start, Mark end) : base(in start, in end) { if (string.IsNullOrEmpty(handle)) { throw new ArgumentNullException("handle", "Tag handle must not be empty."); } if (!TagHandlePattern.IsMatch(handle)) { throw new ArgumentException("Tag handle must start and end with '!' and contain alphanumerical characters only.", "handle"); } Handle = handle; if (string.IsNullOrEmpty(prefix)) { throw new ArgumentNullException("prefix", "Tag prefix must not be empty."); } Prefix = prefix; } public override bool Equals(object? obj) { if (obj is TagDirective tagDirective && Handle.Equals(tagDirective.Handle)) { return Prefix.Equals(tagDirective.Prefix); } return false; } public override int GetHashCode() { return Handle.GetHashCode() ^ Prefix.GetHashCode(); } public override string ToString() { return Handle + " => " + Prefix; } } internal abstract class Token { public Mark Start { get; } public Mark End { get; } protected Token(in Mark start, in Mark end) { Start = start; End = end; } } internal sealed class Value : Token { public Value() : this(in Mark.Empty, in Mark.Empty) { } public Value(in Mark start, in Mark end) : base(in start, in end) { } } internal sealed class VersionDirective : Token { public Version Version { get; } public VersionDirective(Version version) : this(version, Mark.Empty, Mark.Empty) { } public VersionDirective(Version version, Mark start, Mark end) : base(in start, in end) { Version = version; } public override bool Equals(object? obj) { if (obj is VersionDirective versionDirective) { return Version.Equals(versionDirective.Version); } return false; } public override int GetHashCode() { return Version.GetHashCode(); } } } namespace YamlDotNet.Core.ObjectPool { internal class DefaultObjectPool : ObjectPool where T : class { private readonly Func createFunc; private readonly Func returnFunc; private readonly int maxCapacity; private int numItems; private protected readonly ConcurrentQueue items = new ConcurrentQueue(); private protected T? fastItem; public DefaultObjectPool(IPooledObjectPolicy policy) : this(policy, Environment.ProcessorCount * 2) { } public DefaultObjectPool(IPooledObjectPolicy policy, int maximumRetained) { createFunc = policy.Create; returnFunc = policy.Return; maxCapacity = maximumRetained - 1; } public override T Get() { T result = fastItem; if (result == null || Interlocked.CompareExchange(ref fastItem, null, result) != result) { if (items.TryDequeue(out result)) { Interlocked.Decrement(ref numItems); return result; } return createFunc(); } return result; } public override void Return(T obj) { ReturnCore(obj); } private protected bool ReturnCore(T obj) { if (!returnFunc(obj)) { return false; } if (fastItem != null || Interlocked.CompareExchange(ref fastItem, obj, null) != null) { if (Interlocked.Increment(ref numItems) <= maxCapacity) { items.Enqueue(obj); return true; } Interlocked.Decrement(ref numItems); return false; } return true; } } internal class DefaultPooledObjectPolicy : IPooledObjectPolicy where T : class, new() { public T Create() { return new T(); } public bool Return(T obj) { if (obj is IResettable resettable) { return resettable.TryReset(); } return true; } } internal interface IPooledObjectPolicy where T : notnull { T Create(); bool Return(T obj); } internal interface IResettable { bool TryReset(); } internal abstract class ObjectPool where T : class { public abstract T Get(); public abstract void Return(T obj); } internal static class ObjectPool { public static ObjectPool Create(IPooledObjectPolicy? policy = null) where T : class, new() { return new DefaultObjectPool(policy ?? new DefaultPooledObjectPolicy()); } public static ObjectPool Create(int maximumRetained, IPooledObjectPolicy? policy = null) where T : class, new() { return new DefaultObjectPool(policy ?? new DefaultPooledObjectPolicy(), maximumRetained); } } [DebuggerStepThrough] internal static class StringBuilderPool { internal readonly struct BuilderWrapper : IDisposable { public readonly StringBuilder Builder; private readonly ObjectPool pool; public BuilderWrapper(StringBuilder builder, ObjectPool pool) { Builder = builder; this.pool = pool; } public override string ToString() { return Builder.ToString(); } public void Dispose() { pool.Return(Builder); } } private static readonly ObjectPool Pool = ObjectPool.Create(new StringBuilderPooledObjectPolicy { InitialCapacity = 16, MaximumRetainedCapacity = 1024 }); public static BuilderWrapper Rent() { StringBuilder builder = Pool.Get(); return new BuilderWrapper(builder, Pool); } } internal class StringBuilderPooledObjectPolicy : IPooledObjectPolicy { public int InitialCapacity { get; set; } = 100; public int MaximumRetainedCapacity { get; set; } = 4096; public StringBuilder Create() { return new StringBuilder(InitialCapacity); } public bool Return(StringBuilder obj) { if (obj.Capacity > MaximumRetainedCapacity) { return false; } obj.Clear(); return true; } } internal static class StringLookAheadBufferPool { internal readonly struct BufferWrapper : IDisposable { public readonly StringLookAheadBuffer Buffer; private readonly ObjectPool pool; public BufferWrapper(StringLookAheadBuffer buffer, ObjectPool pool) { Buffer = buffer; this.pool = pool; } public override string ToString() { return Buffer.ToString(); } public void Dispose() { pool.Return(Buffer); } } private static readonly ObjectPool Pool = ObjectPool.Create(new DefaultPooledObjectPolicy()); public static BufferWrapper Rent(string value) { StringLookAheadBuffer stringLookAheadBuffer = Pool.Get(); stringLookAheadBuffer.Value = value; return new BufferWrapper(stringLookAheadBuffer, Pool); } } } namespace YamlDotNet.Core.Events { internal sealed class AnchorAlias : ParsingEvent { internal override EventType Type => EventType.Alias; public AnchorName Value { get; } public AnchorAlias(AnchorName value, Mark start, Mark end) : base(in start, in end) { if (value.IsEmpty) { throw new YamlException(in start, in end, "Anchor value must not be empty."); } Value = value; } public AnchorAlias(AnchorName value) : this(value, Mark.Empty, Mark.Empty) { } public override string ToString() { return $"Alias [value = {Value}]"; } public override void Accept(IParsingEventVisitor visitor) { visitor.Visit(this); } } internal sealed class Comment : ParsingEvent { public string Value { get; } public bool IsInline { get; } internal override EventType Type => EventType.Comment; public Comment(string value, bool isInline) : this(value, isInline, Mark.Empty, Mark.Empty) { } public Comment(string value, bool isInline, Mark start, Mark end) : base(in start, in end) { Value = value; IsInline = isInline; } public override void Accept(IParsingEventVisitor visitor) { visitor.Visit(this); } public override string ToString() { return (IsInline ? "Inline" : "Block") + " Comment [" + Value + "]"; } } internal sealed class DocumentEnd : ParsingEvent { public override int NestingIncrease => -1; internal override EventType Type => EventType.DocumentEnd; public bool IsImplicit { get; } public DocumentEnd(bool isImplicit, Mark start, Mark end) : base(in start, in end) { IsImplicit = isImplicit; } public DocumentEnd(bool isImplicit) : this(isImplicit, Mark.Empty, Mark.Empty) { } public override string ToString() { return $"Document end [isImplicit = {IsImplicit}]"; } public override void Accept(IParsingEventVisitor visitor) { visitor.Visit(this); } } internal sealed class DocumentStart : ParsingEvent { public override int NestingIncrease => 1; internal override EventType Type => EventType.DocumentStart; public TagDirectiveCollection? Tags { get; } public VersionDirective? Version { get; } public bool IsImplicit { get; } public DocumentStart(VersionDirective? version, TagDirectiveCollection? tags, bool isImplicit, Mark start, Mark end) : base(in start, in end) { Version = version; Tags = tags; IsImplicit = isImplicit; } public DocumentStart(VersionDirective? version, TagDirectiveCollection? tags, bool isImplicit) : this(version, tags, isImplicit, Mark.Empty, Mark.Empty) { } public DocumentStart(in Mark start, in Mark end) : this(null, null, isImplicit: true, start, end) { } public DocumentStart() : this(null, null, isImplicit: true, Mark.Empty, Mark.Empty) { } public override string ToString() { return $"Document start [isImplicit = {IsImplicit}]"; } public override void Accept(IParsingEventVisitor visitor) { visitor.Visit(this); } } internal enum EventType { None, StreamStart, StreamEnd, DocumentStart, DocumentEnd, Alias, Scalar, SequenceStart, SequenceEnd, MappingStart, MappingEnd, Comment } internal interface IParsingEventVisitor { void Visit(AnchorAlias e); void Visit(StreamStart e); void Visit(StreamEnd e); void Visit(DocumentStart e); void Visit(DocumentEnd e); void Visit(Scalar e); void Visit(SequenceStart e); void Visit(SequenceEnd e); void Visit(MappingStart e); void Visit(MappingEnd e); void Visit(Comment e); } internal class MappingEnd : ParsingEvent { public override int NestingIncrease => -1; internal override EventType Type => EventType.MappingEnd; public MappingEnd(in Mark start, in Mark end) : base(in start, in end) { } public MappingEnd() : this(in Mark.Empty, in Mark.Empty) { } public override string ToString() { return "Mapping end"; } public override void Accept(IParsingEventVisitor visitor) { visitor.Visit(this); } } internal sealed class MappingStart : NodeEvent { public override int NestingIncrease => 1; internal override EventType Type => EventType.MappingStart; public bool IsImplicit { get; } public override bool IsCanonical => !IsImplicit; public MappingStyle Style { get; } public MappingStart(AnchorName anchor, TagName tag, bool isImplicit, MappingStyle style, Mark start, Mark end) : base(anchor, tag, start, end) { IsImplicit = isImplicit; Style = style; } public MappingStart(AnchorName anchor, TagName tag, bool isImplicit, MappingStyle style) : this(anchor, tag, isImplicit, style, Mark.Empty, Mark.Empty) { } public MappingStart() : this(AnchorName.Empty, TagName.Empty, isImplicit: true, MappingStyle.Any, Mark.Empty, Mark.Empty) { } public override string ToString() { return $"Mapping start [anchor = {base.Anchor}, tag = {base.Tag}, isImplicit = {IsImplicit}, style = {Style}]"; } public override void Accept(IParsingEventVisitor visitor) { visitor.Visit(this); } } internal enum MappingStyle { Any, Block, Flow } internal abstract class NodeEvent : ParsingEvent { public AnchorName Anchor { get; } public TagName Tag { get; } public abstract bool IsCanonical { get; } protected NodeEvent(AnchorName anchor, TagName tag, Mark start, Mark end) : base(in start, in end) { Anchor = anchor; Tag = tag; } protected NodeEvent(AnchorName anchor, TagName tag) : this(anchor, tag, Mark.Empty, Mark.Empty) { } } internal abstract class ParsingEvent { public virtual int NestingIncrease => 0; internal abstract EventType Type { get; } public Mark Start { get; } public Mark End { get; } public abstract void Accept(IParsingEventVisitor visitor); internal ParsingEvent(in Mark start, in Mark end) { Start = start; End = end; } } internal sealed class Scalar : NodeEvent { internal override EventType Type => EventType.Scalar; public string Value { get; } public ScalarStyle Style { get; } public bool IsPlainImplicit { get; } public bool IsQuotedImplicit { get; } public override bool IsCanonical { get { if (!IsPlainImplicit) { return !IsQuotedImplicit; } return false; } } public bool IsKey { get; } public Scalar(AnchorName anchor, TagName tag, string value, ScalarStyle style, bool isPlainImplicit, bool isQuotedImplicit, Mark start, Mark end, bool isKey = false) : base(anchor, tag, start, end) { Value = value; Style = style; IsPlainImplicit = isPlainImplicit; IsQuotedImplicit = isQuotedImplicit; IsKey = isKey; } public Scalar(AnchorName anchor, TagName tag, string value, ScalarStyle style, bool isPlainImplicit, bool isQuotedImplicit) : this(anchor, tag, value, style, isPlainImplicit, isQuotedImplicit, Mark.Empty, Mark.Empty) { } public Scalar(string value) : this(AnchorName.Empty, TagName.Empty, value, ScalarStyle.Any, isPlainImplicit: true, isQuotedImplicit: true, Mark.Empty, Mark.Empty) { } public Scalar(TagName tag, string value) : this(AnchorName.Empty, tag, value, ScalarStyle.Any, isPlainImplicit: true, isQuotedImplicit: true, Mark.Empty, Mark.Empty) { } public Scalar(AnchorName anchor, TagName tag, string value) : this(anchor, tag, value, ScalarStyle.Any, isPlainImplicit: true, isQuotedImplicit: true, Mark.Empty, Mark.Empty) { } public override string ToString() { return $"Scalar [anchor = {base.Anchor}, tag = {base.Tag}, value = {Value}, style = {Style}, isPlainImplicit = {IsPlainImplicit}, isQuotedImplicit = {IsQuotedImplicit}]"; } public override void Accept(IParsingEventVisitor visitor) { visitor.Visit(this); } } internal sealed class SequenceEnd : ParsingEvent { public override int NestingIncrease => -1; internal override EventType Type => EventType.SequenceEnd; public SequenceEnd(in Mark start, in Mark end) : base(in start, in end) { } public SequenceEnd() : this(in Mark.Empty, in Mark.Empty) { } public override string ToString() { return "Sequence end"; } public override void Accept(IParsingEventVisitor visitor) { visitor.Visit(this); } } internal sealed class SequenceStart : NodeEvent { public override int NestingIncrease => 1; internal override EventType Type => EventType.SequenceStart; public bool IsImplicit { get; } public override bool IsCanonical => !IsImplicit; public SequenceStyle Style { get; } public SequenceStart(AnchorName anchor, TagName tag, bool isImplicit, SequenceStyle style, Mark start, Mark end) : base(anchor, tag, start, end) { IsImplicit = isImplicit; Style = style; } public SequenceStart(AnchorName anchor, TagName tag, bool isImplicit, SequenceStyle style) : this(anchor, tag, isImplicit, style, Mark.Empty, Mark.Empty) { } public override string ToString() { return $"Sequence start [anchor = {base.Anchor}, tag = {base.Tag}, isImplicit = {IsImplicit}, style = {Style}]"; } public override void Accept(IParsingEventVisitor visitor) { visitor.Visit(this); } } internal enum SequenceStyle { Any, Block, Flow } internal sealed class StreamEnd : ParsingEvent { public override int NestingIncrease => -1; internal override EventType Type => EventType.StreamEnd; public StreamEnd(in Mark start, in Mark end) : base(in start, in end) { } public StreamEnd() : this(in Mark.Empty, in Mark.Empty) { } public override string ToString() { return "Stream end"; } public override void Accept(IParsingEventVisitor visitor) { visitor.Visit(this); } } internal sealed class StreamStart : ParsingEvent { public override int NestingIncrease => 1; internal override EventType Type => EventType.StreamStart; public StreamStart() : this(in Mark.Empty, in Mark.Empty) { } public StreamStart(in Mark start, in Mark end) : base(in start, in end) { } public override string ToString() { return "Stream start"; } public override void Accept(IParsingEventVisitor visitor) { visitor.Visit(this); } } } namespace System.Diagnostics.CodeAnalysis { [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)] [ExcludeFromCodeCoverage] [DebuggerNonUserCode] internal sealed class AllowNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)] [ExcludeFromCodeCoverage] [DebuggerNonUserCode] internal sealed class DisallowNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Method, Inherited = false)] [ExcludeFromCodeCoverage] [DebuggerNonUserCode] internal sealed class DoesNotReturnAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] [ExcludeFromCodeCoverage] [DebuggerNonUserCode] internal sealed class DoesNotReturnIfAttribute : Attribute { public bool ParameterValue { get; } public DoesNotReturnIfAttribute(bool parameterValue) { ParameterValue = parameterValue; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)] [ExcludeFromCodeCoverage] [DebuggerNonUserCode] internal sealed class MaybeNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] [ExcludeFromCodeCoverage] [DebuggerNonUserCode] internal sealed class MaybeNullWhenAttribute : Attribute { public bool ReturnValue { get; } public MaybeNullWhenAttribute(bool returnValue) { ReturnValue = returnValue; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] [ExcludeFromCodeCoverage] [DebuggerNonUserCode] internal sealed class MemberNotNullAttribute : Attribute { public string[] Members { get; } public MemberNotNullAttribute(string member) { Members = new string[1] { member }; } public MemberNotNullAttribute(params string[] members) { Members = members; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] [ExcludeFromCodeCoverage] [DebuggerNonUserCode] internal sealed class MemberNotNullWhenAttribute : Attribute { public bool ReturnValue { get; } public string[] Members { get; } public MemberNotNullWhenAttribute(bool returnValue, string member) { ReturnValue = returnValue; Members = new string[1] { member }; } public MemberNotNullWhenAttribute(bool returnValue, params string[] members) { ReturnValue = returnValue; Members = members; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)] [ExcludeFromCodeCoverage] [DebuggerNonUserCode] internal sealed class NotNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)] [ExcludeFromCodeCoverage] [DebuggerNonUserCode] internal sealed class NotNullIfNotNullAttribute : Attribute { public string ParameterName { get; } public NotNullIfNotNullAttribute(string parameterName) { ParameterName = parameterName; } } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] [ExcludeFromCodeCoverage] [DebuggerNonUserCode] internal sealed class NotNullWhenAttribute : Attribute { public bool ReturnValue { get; } public NotNullWhenAttribute(bool returnValue) { ReturnValue = returnValue; } } }