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.Reflection.Emit; 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.EventSystems; 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.7")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.7.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; } private const string ScanCommand = "zs_scan"; private const string StatusCommand = "zs_status"; private const string DebugZoneCommand = "zs_debugzone"; 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 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_scan", "[steamID] [dry|save|reset] - Runs an auto archive scan, optionally filtered to one Steam owner.", (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_status", "- Writes a YAML report with recent auto archive runs.", (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_debugzone", "(x,z) - Writes a YAML report explaining auto archive eligibility for one zone.", (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_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) { onComplete(ExecuteRequest(request)); } 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_scan": ExecuteScan(array, messages); break; case "zs_status": ExecuteStatus(messages); break; case "zs_debugzone": 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) { IEnumerable args2 = args.Skip(1); List list = null; string targetLabel = ""; if (args.Length > 1 && !IsArchiveModeToken(args[1])) { list = ResolveTargetPlayerIds(args[1], out targetLabel); args2 = args.Skip(2); } ParseMode(args2, out var dryRun, out var reset); if (!((list == null) ? AutoArchiveService.QueueManualScan(dryRun, reset) : AutoArchiveService.QueueManualScan(dryRun, reset, list))) { messages.Add("Auto archive scan could not be started. World may not be ready or another scan is running."); } else { messages.Add((list == null) ? "Auto archive scan started." : ("Auto archive scan started for " + targetLabel + ".")); } } private static void ExecuteStatus(List messages) { AutoArchiveStatusReport autoArchiveStatusReport = BuildStatusReport(); string text = WriteStatusReport(autoArchiveStatusReport); messages.Add($"Archive status report: {autoArchiveStatusReport.Runs.Count}/{autoArchiveStatusReport.TotalRuns} run(s)."); if (autoArchiveStatusReport.Runs.Count > 0) { ArchiveRunRecord archiveRunRecord = autoArchiveStatusReport.Runs[0]; messages.Add($"Latest: {archiveRunRecord.RunId}, dry={archiveRunRecord.DryRun}, reset={archiveRunRecord.ResetAfterSave}, candidates={archiveRunRecord.CandidateZones}, processed={archiveRunRecord.ProcessedZones}, clusters={archiveRunRecord.Clusters.Count}."); } messages.Add("Wrote YAML: " + text); } private static AutoArchiveStatusReport BuildStatusReport() { List runs = AutoArchiveStore.State.Runs.OrderByDescending((ArchiveRunRecord run) => run.CreatedUtc).ToList(); AutoArchiveStatusReport autoArchiveStatusReport = new AutoArchiveStatusReport(); ZNet instance = ZNet.instance; autoArchiveStatusReport.World = ((instance != null) ? instance.GetWorldName() : null) ?? "unknown"; autoArchiveStatusReport.CreatedAt = ZoneSaviorTimestamp.Format(DateTime.UtcNow); autoArchiveStatusReport.TotalRuns = AutoArchiveStore.State.Runs.Count; autoArchiveStatusReport.Runs = runs; return autoArchiveStatusReport; } private static string WriteStatusReport(AutoArchiveStatusReport report) { string text = Path.Combine(ZoneSaviorPlugin.DataStorageFullPath, "Diagnostics"); Directory.CreateDirectory(text); string path = "archive_status_" + DateTime.UtcNow.ToString("yyyyMMdd_HHmmss", CultureInfo.InvariantCulture) + ".yml"; string text2 = Path.Combine(text, path); File.WriteAllText(text2, ZoneBundleSerialization.Serialize(report)); return text2; } 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 AutoArchiveZoneDebugReport BuildZoneDebugReport(Vector2i zone) { //IL_003d: 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_00fd: 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) 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 = ZoneSaviorZones.ToModel(zone); autoArchiveZoneDebugReport.Settings = new AutoArchiveZoneDebugSettings { DryRun = AutoArchiveConfig.DryRun, ResetAfterSave = AutoArchiveConfig.ResetAfterSave, InactiveDays = AutoArchiveConfig.InactiveDays, MinimumPiecesPerCluster = AutoArchiveConfig.MinimumPiecesPerCluster, 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_0041: 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_0067: 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) ZoneStructureInfo zoneStructureInfo = ZoneStructureClassifier.Inspect(zdo, requestedZone); AutoArchiveZoneDebugObject autoArchiveZoneDebugObject = new AutoArchiveZoneDebugObject(); autoArchiveZoneDebugObject.ZdoId = zoneStructureInfo.ZdoId; autoArchiveZoneDebugObject.PrefabHash = zoneStructureInfo.PrefabHash; autoArchiveZoneDebugObject.Prefab = zoneStructureInfo.Prefab; autoArchiveZoneDebugObject.Position = new float[3] { Round(zoneStructureInfo.Position.x), Round(zoneStructureInfo.Position.y), Round(zoneStructureInfo.Position.z) }; autoArchiveZoneDebugObject.ObjectZone = ZoneSaviorZones.ToModel(zoneStructureInfo.ObjectZone); autoArchiveZoneDebugObject.CreatorPlayerId = zoneStructureInfo.CreatorPlayerId; autoArchiveZoneDebugObject.CreatorName = zoneStructureInfo.CreatorName; autoArchiveZoneDebugObject.HasPrefab = zoneStructureInfo.HasPrefab; autoArchiveZoneDebugObject.HasZNetView = zoneStructureInfo.HasZNetView; autoArchiveZoneDebugObject.HasWearNTear = zoneStructureInfo.HasWearNTear; autoArchiveZoneDebugObject.HasPiece = zoneStructureInfo.HasPiece; autoArchiveZoneDebugObject.HasBuildRecipe = zoneStructureInfo.HasBuildRecipe; autoArchiveZoneDebugObject.InRequestedZone = zoneStructureInfo.InRequestedZone; autoArchiveZoneDebugObject.AutoArchiveCandidatePiece = zoneStructureInfo.AutoArchiveCandidatePiece; autoArchiveZoneDebugObject.ExclusionReasons = zoneStructureInfo.ExclusionReasons; return autoArchiveZoneDebugObject; } private static AutoArchiveZoneDebugCreator BuildCreatorDebug(long playerId, DateTime utcNow) { AutoArchiveCreatorEligibility autoArchiveCreatorEligibility = AutoArchiveStore.EvaluateCreatorArchiveEligibility(playerId, utcNow, AutoArchiveConfig.InactiveDays, recordUnknownPlayer: false); return new AutoArchiveZoneDebugCreator { PlayerId = autoArchiveCreatorEligibility.PlayerId, PlatformId = autoArchiveCreatorEligibility.PlatformId, Names = autoArchiveCreatorEligibility.Names, RecordedInActivity = autoArchiveCreatorEligibility.RecordedInActivity, UnknownActivityRecord = autoArchiveCreatorEligibility.UnknownActivityRecord, 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_debugzone (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 (IsArchiveModeToken(arg, "dry") || IsArchiveModeToken(arg, "dry-run")) { dryRun = true; reset = false; continue; } if (IsArchiveModeToken(arg, "save")) { dryRun = false; reset = false; continue; } if (IsArchiveModeToken(arg, "reset")) { dryRun = false; reset = true; continue; } throw new InvalidOperationException("Unknown archive mode '" + arg + "'. Use dry, save, or reset."); } } private static bool IsArchiveModeToken(string arg) { if (!IsArchiveModeToken(arg, "dry") && !IsArchiveModeToken(arg, "dry-run") && !IsArchiveModeToken(arg, "save")) { return IsArchiveModeToken(arg, "reset"); } return true; } private static bool IsArchiveModeToken(string arg, string expected) { return string.Equals(arg, expected, StringComparison.OrdinalIgnoreCase); } 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 (ZoneSaviorSteamIds.LooksLikeSteamId(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_scan [steamID] [dry|save|reset]"); } 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); } } } } 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 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(); } 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 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 AutoArchiveStatusReport { public int Version { get; set; } = 1; public string World { get; set; } = ""; public string CreatedAt { get; set; } = ""; public int TotalRuns { get; set; } public List Runs { 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 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 MinimumPiecesPerCluster { 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 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 sealed class AutoArchiveScanPolicy { public bool DryRun { get; } public bool ResetAfterSave { get; } public HashSet TargetPlayerIds { get; } public bool IsTargetOverride => TargetPlayerIds.Count > 0; public bool UsesMinimumClusterSize => !IsTargetOverride; public bool RequiresCreatorEligibility => !IsTargetOverride; public bool BlocksMixedOwnerReset { get { if (IsTargetOverride) { return ResetAfterSave; } return false; } } private AutoArchiveScanPolicy(AutoArchiveScanOptions options) { DryRun = options.DryRun; ResetAfterSave = options.ResetAfterSave; TargetPlayerIds = options.TargetPlayerIds.ToHashSet(); } public static AutoArchiveScanPolicy FromOptions(AutoArchiveScanOptions options) { return new AutoArchiveScanPolicy(options); } public bool IncludesTargetCreator(IEnumerable creators) { return creators.Any(TargetPlayerIds.Contains); } public bool IsSmallCluster(ArchiveClusterRecord record) { if (UsesMinimumClusterSize) { return record.PieceCount < AutoArchiveConfig.MinimumPiecesPerCluster; } return false; } public string DryRunCandidateReason() { if (!IsTargetOverride) { return "candidate only; dry run is enabled"; } return "target override candidate; dry run is enabled"; } } 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 AutoArchiveScanPolicy 5__5; private Dictionary 5__6; private int 5__7; private int 5__8; private IEnumerator> <>7__wrap8; private List 5__10; private ArchiveClusterRecord 5__11; 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; 5__6 = null; <>7__wrap8 = null; 5__10 = null; 5__11 = 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 = AutoArchiveScanPolicy.FromOptions(options); 5__6 = BuildCandidateZones(5__4, 5__2, 5__5, 5__3); 5__3.CandidateZones = 5__6.Count; List> source = BuildClusters(5__6); 5__7 = 0; 5__8 = 0; <>7__wrap8 = (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__11.Status = "failed"; 5__11.Reason = "save failed: archive coroutine did not return a result"; 5__3.Clusters.Add(5__11); _logger.LogError((object)("Auto archive save failed for tag '" + 5__11.Tag + "': archive coroutine did not return a result.")); <>2__current = null; <>1__state = 4; return true; } 5__11.TerrainLoaded = <>8__1.saveResult.TerrainLoaded; 5__11.TerrainCaptured = <>8__1.saveResult.TerrainCaptured; if (!<>8__1.saveResult.Success) { 5__11.Status = "failed"; 5__11.Reason = <>8__1.saveResult.Message; 5__3.Clusters.Add(5__11); break; } 5__11.Status = "saved"; 5__11.Reason = <>8__1.saveResult.Message; if (options.ResetAfterSave) { <>8__2 = new <>c__DisplayClass3_1(); <>8__2.resetResult = null; <>2__current = ZoneBundleCommands.ResetGeneratedZonesAsync(5__10, delegate(ZoneBundleResetResult result) { <>8__2.resetResult = result; }); <>1__state = 5; return true; } goto IL_0800; case 4: <>1__state = -3; break; case 5: <>1__state = -3; if (<>8__2.resetResult == null) { 5__11.Status = "saved-reset-failed"; 5__11.Reason = "reset failed: reset coroutine did not return a result"; 5__3.Clusters.Add(5__11); _logger.LogError((object)("Auto archive reset failed for tag '" + 5__11.Tag + "': reset coroutine did not return a result.")); <>2__current = null; <>1__state = 6; return true; } 5__11.Status = (<>8__2.resetResult.Success ? "reset" : "saved-reset-failed"); 5__11.Reason = <>8__2.resetResult.Message; <>8__2 = null; goto IL_0800; case 6: <>1__state = -3; break; case 7: { <>1__state = -3; <>8__1 = null; 5__11 = null; 5__10 = null; break; } IL_0800: 5__3.Clusters.Add(5__11); 5__7 += 5__10.Count; <>2__current = null; <>1__state = 7; return true; } while (<>7__wrap8.MoveNext()) { 5__10 = <>7__wrap8.Current; <>8__1 = new <>c__DisplayClass3_0(); 5__8++; 5__11 = BuildClusterRecord(5__10, 5__6); bool flag = 5__5.IsSmallCluster(5__11); if (5__7 + 5__10.Count > AutoArchiveConfig.MaxZonesPerRun) { 5__11.Status = "skipped"; 5__11.Reason = $"max zones per run would be exceeded ({5__7 + 5__10.Count}/{AutoArchiveConfig.MaxZonesPerRun})"; 5__3.Clusters.Add(5__11); continue; } if (5__5.RequiresCreatorEligibility && !AllCreatorsEligible(5__11.Creators, 5__2, out string reason)) { 5__11.Status = "skipped"; 5__11.Reason = reason; 5__3.Clusters.Add(5__11); continue; } if (flag) { if (!options.ResetAfterSave) { 5__11.Status = "skipped"; 5__11.Reason = $"piece count {5__11.PieceCount} is below minimum {AutoArchiveConfig.MinimumPiecesPerCluster}; reset mode is not enabled"; 5__3.Clusters.Add(5__11); continue; } if (options.DryRun) { 5__11.Status = "dry-run-reset-without-save"; 5__11.Reason = $"small inactive cluster would be reset without saving ({5__11.PieceCount}/{AutoArchiveConfig.MinimumPiecesPerCluster} pieces)"; 5__3.Clusters.Add(5__11); 5__7 += 5__10.Count; continue; } ZoneBundleResetResult zoneBundleResetResult = ZoneBundleCommands.ResetGeneratedZones(5__10); 5__11.Status = (zoneBundleResetResult.Success ? "reset-without-save" : "reset-without-save-failed"); 5__11.Reason = zoneBundleResetResult.Message; 5__3.Clusters.Add(5__11); 5__7 += 5__10.Count; <>2__current = null; <>1__state = 2; return true; } 5__11.Tag = ZoneBundleCommands.MakeUniqueAutoArchiveTag(BuildTag(5__8, 5__10, 5__6)); if (options.DryRun) { 5__11.Status = "dry-run"; 5__11.Reason = 5__5.DryRunCandidateReason(); 5__3.Clusters.Add(5__11); 5__7 += 5__10.Count; continue; } <>8__1.saveResult = null; <>2__current = ZoneBundleCommands.SaveZonesAsync(5__10, 5__11.Tag, delegate(ZoneBundleArchiveResult result) { <>8__1.saveResult = result; }, 0L); <>1__state = 3; return true; } <>m__Finally1(); <>7__wrap8 = null; 5__3.ProcessedZones = 5__7; 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__wrap8 != null) { <>7__wrap8.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_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) zone = default(Vector2i); creator = 0L; if (!ZoneStructureClassifier.TryInspectAutoArchiveCandidate(zdo, out ZoneStructureInfo info)) { return false; } creator = info.CreatorPlayerId; AutoArchiveStore.RecordUnknownPlayer(creator, utcNow, info.CreatorName); zone = info.ObjectZone; 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, AutoArchiveScanPolicy policy, ArchiveRunRecord run) { //IL_00ec: 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_00ce: 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_0061: 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) Dictionary dictionary = new Dictionary(); foreach (AutoArchiveZoneInfo value in zoneInfos.Values) { string reason; if (policy.IsTargetOverride) { if (policy.IncludesTargetCreator(value.Creators)) { if (policy.BlocksMixedOwnerReset && HasNonTargetCreators(value.Creators, policy.TargetPlayerIds, out List nonTargetCreators)) { run.Messages.Add($"Skipped zone ({value.Zone.x},{value.Zone.y}): target reset blocked for mixed-owner zone; non-target creator(s): {FormatCreatorList(nonTargetCreators)}"); } else { dictionary[value.Zone] = value; } } } else if (!AllCreatorsEligible(value.Creators, utcNow, out reason)) { run.Messages.Add($"Skipped zone ({value.Zone.x},{value.Zone.y}): {reason}"); } else { dictionary[value.Zone] = value; } } return dictionary; } private static bool HasNonTargetCreators(IEnumerable creators, HashSet targetPlayerIds, out List nonTargetCreators) { HashSet targetPlayerIds2 = targetPlayerIds; nonTargetCreators = (from creator in creators.Where((long creator) => creator != 0L && !targetPlayerIds2.Contains(creator)).Distinct() orderby creator select creator).ToList(); return nonTargetCreators.Count > 0; } private static string FormatCreatorList(IEnumerable creators) { return string.Join(", ", creators.Select((long creator) => creator.ToString(CultureInfo.InvariantCulture))); } 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_008b: 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_0092: 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 zone).Select(ZoneSaviorZones.ToModel).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, 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 ZoneSaviorPaths.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 text = ZoneSaviorSteamIds.Normalize(record.PlatformId); if (!string.IsNullOrWhiteSpace(text)) { return text; } string text2 = new string((from character in record.PlatformId.Substring("steam:".Length) where char.IsLetterOrDigit(character) || character == '-' || character == '_' select 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 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__DisplayClass15_0 { public ArchiveRunRecord completed; internal void b__0(ArchiveRunRecord run) { completed = run; } } [CompilerGenerated] private sealed class d__15 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public AutoArchiveScanOptions options; private <>c__DisplayClass15_0 <>8__1; 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() { <>8__1 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass15_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 bool IsScanRunning => _scanRunning; 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__15))] private static IEnumerator RunScan(AutoArchiveScanOptions options) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__15(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 int MaxRunHistory = 50; private static readonly TimeSpan InternalWriteReloadGrace = TimeSpan.FromSeconds(2.0); 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 DateTime _lastInternalWriteUtc = 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 { if (!TryReadStateFromDisk(out AutoArchiveState state, out string error)) { throw new InvalidDataException(error); } State = state; 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; _lastInternalWriteUtc = utcNow; _dirty = false; } } } } public static bool TryReloadFromDiskIfSafe(bool scanRunning, out string message) { lock (Sync) { if (_dirty) { message = "Activity reload skipped: runtime activity state has unsaved changes."; return false; } if (scanRunning) { message = "Activity reload skipped: auto archive scan is running."; return false; } if (DateTime.UtcNow - _lastInternalWriteUtc < InternalWriteReloadGrace) { message = "Activity reload skipped: change was caused by a recent ZoneSavior activity flush."; return false; } if (!File.Exists(FilePath)) { message = "Activity reload skipped: activity.yml does not exist."; return false; } if (!TryReadStateFromDisk(out AutoArchiveState state, out string error)) { message = "Activity reload skipped: " + error; return false; } State = state; RebuildIndexes(); _dirty = false; message = "Activity reload complete."; return true; } } 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 }; State.Players.Add(playerActivityRecord); IndexPlayer(playerActivityRecord); } 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 RecordUnknownPlayer(long playerId, DateTime utcNow, string observedName = "") { if (playerId == 0L) { return; } lock (Sync) { if (PlayersById.TryGetValue(playerId, out PlayerActivityRecord value)) { if (value.LastSeenUtc == DateTime.MinValue) { value.LastSeenUtc = utcNow; _dirty = true; } 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 = ZoneSaviorSteamIds.Normalize(steamId); playerIds = new List(); if (string.IsNullOrWhiteSpace(normalizedSteamId)) { return false; } lock (Sync) { foreach (PlayerActivityRecord player in State.Players) { if (!ZoneSaviorSteamIds.TryNormalizePlatformId(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 AutoArchiveCreatorEligibility EvaluateCreatorArchiveEligibility(long playerId, DateTime utcNow, int inactiveDays, bool recordUnknownPlayer, string observedName = "") { AutoArchiveCreatorEligibility autoArchiveCreatorEligibility = new AutoArchiveCreatorEligibility { PlayerId = 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 (!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 lastSeenUtc = record.LastSeenUtc; if (lastSeenUtc == DateTime.MinValue) { autoArchiveCreatorEligibility.Reason = $"player {playerId} has no usable activity timestamp"; return autoArchiveCreatorEligibility; } TimeSpan timeSpan = utcNow - DateTime.SpecifyKind(lastSeenUtc, DateTimeKind.Utc); if (timeSpan.TotalDays < (double)inactiveDays) { autoArchiveCreatorEligibility.Reason = (flag2 ? $"unknown player {playerId} discovered {timeSpan.TotalDays:F1}/{inactiveDays} days ago" : $"player {playerId} last seen {timeSpan.TotalDays:F1}/{inactiveDays} days ago"); return autoArchiveCreatorEligibility; } autoArchiveCreatorEligibility.Eligible = true; autoArchiveCreatorEligibility.Reason = (flag2 ? $"unknown player {playerId} inactive since discovery for {timeSpan.TotalDays:F1} days" : $"player {playerId} inactive for {timeSpan.TotalDays:F1} days"); return autoArchiveCreatorEligibility; } public static bool IsCreatorArchiveEligible(long playerId, DateTime utcNow, int inactiveDays, out string reason) { AutoArchiveCreatorEligibility autoArchiveCreatorEligibility = EvaluateCreatorArchiveEligibility(playerId, utcNow, inactiveDays, 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; } } 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, LastSeenUtc = utcNow, 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 (item.LastSeenUtc > target2.LastSeenUtc) { target2.LastSeenUtc = item.LastSeenUtc; } 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 bool IsUnknown(PlayerActivityRecord record) { return record.PlatformId.StartsWith("unknown:", StringComparison.Ordinal); } private static bool TryReadStateFromDisk(out AutoArchiveState state, out string error) { state = new AutoArchiveState(); error = ""; try { string input = File.ReadAllText(FilePath); state = Deserializer.Deserialize(input) ?? new AutoArchiveState(); NormalizeState(state); return true; } catch (Exception ex) { error = ex.Message; return false; } } private static void NormalizeState(AutoArchiveState state) { AutoArchiveState autoArchiveState = state; if (autoArchiveState.Players == null) { List list2 = (autoArchiveState.Players = new List()); } autoArchiveState = state; if (autoArchiveState.Runs == null) { List list4 = (autoArchiveState.Runs = new List()); } } 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 VeiledRecipesCompat { private const string PluginGuid = "sighsorry.VeiledRecipes"; private const string ApiTypeName = "VeiledRecipes.VeiledRecipesCompat"; private static readonly BindingFlags PublicStaticFlags = BindingFlags.Static | BindingFlags.Public; private static ManualLogSource? _logger; private static bool _initialized; private static bool _registered; private static MethodInfo? _registerKnownPieceOverrideMethod; private static readonly Func KnownPieceOverride = AdminTerrainTool.IsProxyPiece; public static void Initialize(ManualLogSource logger) { _logger = logger; EnsureInitialized(); RegisterKnownPieceOverride(); } private static void EnsureInitialized() { if (!_initialized) { _initialized = true; if (Chainloader.PluginInfos.TryGetValue("sighsorry.VeiledRecipes", out var value)) { _registerKnownPieceOverrideMethod = ((((object)value.Instance)?.GetType().Assembly)?.GetType("VeiledRecipes.VeiledRecipesCompat", throwOnError: false))?.GetMethod("RegisterKnownPieceOverride", PublicStaticFlags, null, new Type[1] { typeof(Func) }, null); } } } private static void RegisterKnownPieceOverride() { if (_registered || _registerKnownPieceOverrideMethod == null) { return; } try { _registerKnownPieceOverrideMethod.Invoke(null, new object[1] { KnownPieceOverride }); _registered = true; ManualLogSource? logger = _logger; if (logger != null) { logger.LogDebug((object)"Registered ZoneSavior admin terrain tools with VeiledRecipes."); } } catch (Exception ex) { ManualLogSource? logger2 = _logger; if (logger2 != null) { logger2.LogDebug((object)("Could not register ZoneSavior admin terrain tools with VeiledRecipes: " + ex.Message)); } } } } internal static class AdminTerrainInfinityHammerCompat { private static ManualLogSource? _logger; private static bool _available; private static bool _patched; private static bool _saveDataConfigured; private static Type? _configurationType; public static void Initialize(ManualLogSource logger, Harmony harmony) { _logger = logger; if (!_patched) { _configurationType = FindLoadedType("InfinityHammer.Configuration"); _available = _configurationType != null; if (!_available) { _logger.LogDebug((object)"Infinity Hammer compat skipped: Infinity Hammer is not loaded."); return; } int num = 0; num += PatchMethod(harmony, "InfinityHammer.BaseSelection:PostProcessPlaced", new Type[1] { typeof(GameObject) }, "InfinityHammerPostProcessPrefix", prefix: true); num += PatchMethod(harmony, "InfinityHammer.BaseSelection:PostProcessPlaced", new Type[1] { typeof(GameObject) }, "InfinityHammerPostProcessPostfix", prefix: false); num += PatchMethod(harmony, "InfinityHammer.NoCreator:Set", new Type[2] { typeof(ZNetView), typeof(Piece) }, "InfinityHammerNoCreatorPrefix", prefix: true); _patched = num > 0; EnsureSavesTerrainData(); _logger.LogInfo((object)$"Infinity Hammer compat initialized. Patched {num} method(s)."); } } public static void Update() { if (_available) { EnsureSavesTerrainData(); } } public static void Shutdown() { _patched = false; _saveDataConfigured = false; _configurationType = null; } private static Type? FindLoadedType(string fullName) { foreach (PluginInfo value in Chainloader.PluginInfos.Values) { Type type = ((object)value.Instance)?.GetType().Assembly.GetType(fullName, throwOnError: false); if (type != null) { return type; } } return null; } private static int PatchMethod(Harmony harmony, string fullMethodName, Type[] parameters, string patchMethodName, bool prefix) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(fullMethodName, parameters, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(AdminTerrainInfinityHammerCompat), patchMethodName, (Type[])null, (Type[])null); if (methodInfo == null || methodInfo2 == null) { ManualLogSource? logger = _logger; if (logger != null) { logger.LogDebug((object)("Infinity Hammer compat skipped method: " + fullMethodName)); } return 0; } HarmonyMethod val = new HarmonyMethod(methodInfo2); if (prefix) { harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } else { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } return 1; } private static void InfinityHammerPostProcessPrefix(GameObject obj) { AdminTerrainTool.PrepareInfinityHammerPlaced(obj); } private static void InfinityHammerPostProcessPostfix(GameObject obj) { AdminTerrainTool.ApplyInfinityHammerPlaced(obj); } private static bool InfinityHammerNoCreatorPrefix(ZNetView view, Piece piece) { return AdminTerrainTool.ShouldRunInfinityHammerNoCreator(view, piece); } private static void EnsureSavesTerrainData() { if (!_saveDataConfigured && (_configurationType?.GetField("SavedObjectData", BindingFlags.Static | BindingFlags.Public))?.GetValue(null) is HashSet hashSet) { hashSet.Add("ZoneSaviorTerrainProxy".ToLowerInvariant()); hashSet.Add("ZoneSaviorTerrainProxySlope".ToLowerInvariant()); hashSet.Add("ZoneSaviorPaintProxy".ToLowerInvariant()); _saveDataConfigured = true; } } } internal static class AdminTerrainTool { private enum PreviewKind { None, Circle, Width, Slope } private enum TerrainProxyMode { Circle, Slope, Paint } private readonly struct SlopePlacement { public Vector3 Center { get; } public Quaternion Rotation { get; } public float Width { get; } public float Length { get; } public float HeightDelta { get; } public SlopePlacement(Vector3 center, Quaternion rotation, float width, float length, float heightDelta) { //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_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) Center = center; Rotation = rotation; Width = width; Length = length; HeightDelta = heightDelta; } public Vector3 GetWorldPoint(float localX, float localZ) { //IL_0001: 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_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_0022: 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_005e: Unknown result type (might be due to invalid IL or missing references) Vector3 result = Center + Rotation * new Vector3(localX, 0f, localZ); result.y = Center.y + Mathf.Clamp(localZ / Mathf.Max(Length, 0.001f), -0.5f, 0.5f) * HeightDelta; return result; } } private readonly struct TerrainProxySettings { public TerrainProxyMode Mode { get; } public float Radius { get; } public float Width { get; } public float Length { get; } public float SlopeHeightDelta { get; } public float TerrainEdgeSoftness { get; } public AdminTerrainPaintType PaintType { get; } public bool ModifiesHeight { get { TerrainProxyMode mode = Mode; if ((uint)mode <= 1u) { return true; } return false; } } public bool ModifiesPaint => Mode == TerrainProxyMode.Paint; public bool HasCircleFootprint => Mode != TerrainProxyMode.Slope; public float TerrainRadius { get { if (Mode != TerrainProxyMode.Slope) { return Radius; } return Mathf.Sqrt(Width * Width + Length * Length) * 0.5f; } } public float SearchRadius => TerrainRadius; public TerrainProxySettings(TerrainProxyMode mode, float radius, float width, float length, float slopeHeightDelta, float terrainEdgeSoftness, AdminTerrainPaintType paintType) { Mode = mode; Radius = Mathf.Clamp(radius, 0.5f, 128f); Width = Mathf.Clamp(width, 0.5f, 256f); Length = Mathf.Clamp(length, 0.5f, 256f); SlopeHeightDelta = Mathf.Clamp(slopeHeightDelta, -1024f, 1024f); TerrainEdgeSoftness = Mathf.Clamp01(terrainEdgeSoftness); PaintType = paintType; } public float GetNormalizedDistance(float x, float z) { if (Mode == TerrainProxyMode.Slope) { return Mathf.Max(Mathf.Abs(x) / (Width * 0.5f), Mathf.Abs(z) / (Length * 0.5f)); } return Mathf.Sqrt(x * x + z * z) / Radius; } public float GetTargetHeight(Vector3 center, float heightmapWorldY, float localZ) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) float num = center.y; if (Mode == TerrainProxyMode.Slope) { num += Mathf.Clamp(localZ / Length, -0.5f, 0.5f) * SlopeHeightDelta; } return num - heightmapWorldY; } public float GetLevelFalloff(float x, float z) { if (Mode != 0 || TerrainEdgeSoftness <= 0f) { return 1f; } float num = Mathf.Sqrt(x * x + z * z); float num2 = Mathf.Pow(1f - TerrainEdgeSoftness, 1.5f); float num3 = Radius * num2; if (num <= num3) { return 1f; } float num4 = Mathf.Max(Radius - num3, 0.001f); float num5 = Mathf.Clamp01((Radius - num) / num4); float num6 = Mathf.Lerp(1f, 4f, TerrainEdgeSoftness); return Mathf.Pow(num5, 1f / num6); } } private static readonly List PieceTableScratch = new List(); private const float TooltipFontSizeMultiplier = 1.15f; private static float _defaultTooltipFontSize = -1f; public const string PrefabName = "ZoneSaviorTerrainProxy"; public const string SlopePrefabName = "ZoneSaviorTerrainProxySlope"; public const string PaintPrefabName = "ZoneSaviorPaintProxy"; public const string ResetPrefabName = "ZoneSaviorTerrainReset"; public const string PaintResetPrefabName = "ZoneSaviorPaintReset"; private const int DataVersion = 11; private const float AdminTerrainMaxDelta = 1024f; private const float MinCircleRadius = 0.5f; private const float MaxCircleRadius = 128f; private const float MinSlopeSize = 0.5f; private const float MaxSlopeSize = 256f; private const float TerrainEdgeSoftnessStep = 0.05f; private const float SearchPadding = 4f; private const float AreaLineWidth = 0.05f; private const float PreviewPositionEpsilon = 0.01f; private const float PreviewFloatEpsilon = 0.01f; private const string AreaLineName = "ZoneSaviorTerrainProxyArea"; private static readonly int PrefabHash = StringExtensionMethods.GetStableHashCode("ZoneSaviorTerrainProxy"); private static readonly int SlopePrefabHash = StringExtensionMethods.GetStableHashCode("ZoneSaviorTerrainProxySlope"); private static readonly int PaintPrefabHash = StringExtensionMethods.GetStableHashCode("ZoneSaviorPaintProxy"); private static readonly int ResetPrefabHash = StringExtensionMethods.GetStableHashCode("ZoneSaviorTerrainReset"); private static readonly int PaintResetPrefabHash = StringExtensionMethods.GetStableHashCode("ZoneSaviorPaintReset"); private static readonly int VersionHash = Hash("version"); private static readonly int ModeHash = Hash("mode"); private static readonly int AppliedHash = Hash("applied"); private static readonly int AppliedPositionHash = Hash("applied_position"); private static readonly int RadiusHash = Hash("radius"); private static readonly int WidthHash = Hash("width"); private static readonly int LengthHash = Hash("length"); private static readonly int SlopeHeightDeltaHash = Hash("slope_height_delta"); private static readonly int TerrainEdgeSoftnessHash = Hash("terrain_edge_softness"); private static readonly int PaintTypeHash = Hash("paint_type"); private static ManualLogSource _logger = null; private static GameObject? _prefab; private static GameObject? _slopePrefab; private static GameObject? _paintPrefab; private static GameObject? _resetPrefab; private static GameObject? _paintResetPrefab; private static Sprite? _icon; private static Sprite? _slopeIcon; private static Sprite? _paintIcon; private static Sprite? _resetIcon; private static Sprite? _paintResetIcon; private static GameObject? _previewRoot; private static LineRenderer? _areaLine; private static Material? _lineMaterial; private static ZNetScene? _registeredScene; private static float _runtimeRadius = float.NaN; private static float _lastConfigRadius = float.NaN; private static float _runtimeSlopeWidth = float.NaN; private static float _lastConfigSlopeWidth = float.NaN; private static float _runtimeTerrainEdgeSoftness = float.NaN; private static float _lastConfigTerrainEdgeSoftness = float.NaN; private static AdminTerrainPaintType _runtimePaintType; private static AdminTerrainPaintType _lastConfigPaintType; private static bool _runtimePaintTypeInitialized; private static bool _hasPendingSlopeStart; private static Vector3 _pendingSlopeStart; private static int _pendingSlopeStartFrame; private static PreviewKind _lastPreviewKind = PreviewKind.None; private static Vector3 _lastPreviewPosition; private static float _lastPreviewYaw; private static float _lastPreviewRadius; private static float _lastPreviewWidth; private static float _lastPreviewLength; private static float _lastPreviewHeightDelta; private static Sprite GetIcon(bool slope, bool reset, bool paint, bool paintReset) { //IL_0086: 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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0609: Unknown result type (might be due to invalid IL or missing references) //IL_0618: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_024f: 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_0264: Unknown result type (might be due to invalid IL or missing references) //IL_0265: 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_027d: Unknown result type (might be due to invalid IL or missing references) //IL_0284: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_0312: Unknown result type (might be due to invalid IL or missing references) //IL_0321: Unknown result type (might be due to invalid IL or missing references) //IL_0300: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: Unknown result type (might be due to invalid IL or missing references) //IL_040c: Unknown result type (might be due to invalid IL or missing references) //IL_041b: Unknown result type (might be due to invalid IL or missing references) //IL_0302: Unknown result type (might be due to invalid IL or missing references) //IL_05c9: Unknown result type (might be due to invalid IL or missing references) //IL_03fd: Unknown result type (might be due to invalid IL or missing references) //IL_03fe: Unknown result type (might be due to invalid IL or missing references) //IL_0476: Unknown result type (might be due to invalid IL or missing references) //IL_0478: Unknown result type (might be due to invalid IL or missing references) //IL_03b7: Unknown result type (might be due to invalid IL or missing references) //IL_03b9: Unknown result type (might be due to invalid IL or missing references) //IL_04f7: Unknown result type (might be due to invalid IL or missing references) //IL_04f9: Unknown result type (might be due to invalid IL or missing references) //IL_0480: Unknown result type (might be due to invalid IL or missing references) //IL_0482: Unknown result type (might be due to invalid IL or missing references) //IL_03c1: Unknown result type (might be due to invalid IL or missing references) //IL_03c3: Unknown result type (might be due to invalid IL or missing references) //IL_0567: Unknown result type (might be due to invalid IL or missing references) //IL_0568: Unknown result type (might be due to invalid IL or missing references) //IL_0516: Unknown result type (might be due to invalid IL or missing references) //IL_0518: Unknown result type (might be due to invalid IL or missing references) //IL_052e: Unknown result type (might be due to invalid IL or missing references) //IL_0533: Unknown result type (might be due to invalid IL or missing references) //IL_04b9: Unknown result type (might be due to invalid IL or missing references) //IL_04ba: Unknown result type (might be due to invalid IL or missing references) //IL_05c1: Unknown result type (might be due to invalid IL or missing references) //IL_05c2: Unknown result type (might be due to invalid IL or missing references) if (paintReset && Object.op_Implicit((Object)(object)_paintResetIcon)) { return _paintResetIcon; } if (paint && Object.op_Implicit((Object)(object)_paintIcon)) { return _paintIcon; } if (reset && Object.op_Implicit((Object)(object)_resetIcon)) { return _resetIcon; } if (!paint && !paintReset && !reset && !slope && Object.op_Implicit((Object)(object)_icon)) { return _icon; } if (!paint && !paintReset && !reset && slope && Object.op_Implicit((Object)(object)_slopeIcon)) { return _slopeIcon; } Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false) { filterMode = (FilterMode)1, wrapMode = (TextureWrapMode)1 }; Color val2 = default(Color); ((Color)(ref val2))..ctor(0f, 0f, 0f, 0f); Color val3 = default(Color); ((Color)(ref val3))..ctor(0.08f, 0.09f, 0.12f, 0.95f); Color val4 = default(Color); ((Color)(ref val4))..ctor(1f, 0.05f, 0.85f, 1f); Color val5 = default(Color); ((Color)(ref val5))..ctor(1f, 0.05f, 0.85f, 0.32f); Color val6 = default(Color); ((Color)(ref val6))..ctor(0.95f, 0.72f, 0.18f, 1f); Color val7 = default(Color); ((Color)(ref val7))..ctor(0.38f, 0.2f, 0.04f, 1f); Color val8 = default(Color); ((Color)(ref val8))..ctor(1f, 0.22f, 0.18f, 1f); Color val9 = default(Color); ((Color)(ref val9))..ctor(0.36f, 0.06f, 0.04f, 1f); Color val10 = (Color)(paint ? val6 : (paintReset ? val6 : (reset ? val8 : (slope ? new Color(0.35f, 0.78f, 0.86f, 1f) : new Color(0.18f, 0.72f, 0.48f, 1f))))); Color val11 = (Color)(paint ? val7 : (paintReset ? val7 : (reset ? val9 : (slope ? new Color(0.07f, 0.24f, 0.32f, 1f) : new Color(0.05f, 0.24f, 0.16f, 1f))))); Vector2 val12 = default(Vector2); ((Vector2)(ref val12))..ctor(31.5f, 31.5f); for (int i = 0; i < 64; i++) { for (int j = 0; j < 64; j++) { float num = Vector2.Distance(new Vector2((float)j, (float)i), val12); Color val13 = val2; if (num <= 28f) { val13 = val3; } if (num >= 21f && num <= 25f) { val13 = val4; } else if (num >= 17.5f && num < 21f) { val13 = Color.Lerp(val13, val5, 0.65f); } bool flag = i >= 31 && i <= 47 && j >= 16 && j <= 48; if (!slope && !reset && !paint && !paintReset && flag) { float num2 = Mathf.Abs((float)j - 32f) / 16f; float num3 = ((float)i - 31f) / 16f; if (num3 >= num2 * 0.55f) { val13 = ((num3 > 0.75f) ? val11 : val10); } } if (paint || paintReset) { bool num4 = Vector2.Distance(new Vector2((float)j, (float)i), new Vector2(30f, 28f)) <= 9f; bool flag2 = j >= 37 && j <= 49 && i >= 39 && i <= 45 && Mathf.Abs((float)i - 42f - ((float)j - 43f) * 0.16f) <= 3f; bool flag3 = i >= 44 && i <= 48 && j >= 17 && j <= 43 && Mathf.Sin(((float)j - 17f) * 0.5f) > -0.35f; if (num4 || flag3) { val13 = val10; } else if (flag2) { val13 = val11; } } if (paintReset && ((Mathf.Abs(j - i) <= 2 && j >= 18 && j <= 46) || (Mathf.Abs(j + i - 64) <= 2 && j >= 18 && j <= 46))) { val13 = val4; } if (reset) { bool num5 = Vector2.Distance(new Vector2((float)j, (float)i), new Vector2(30f, 30f)) <= 11f; bool flag4 = j >= 38 && j <= 49 && i >= 40 && i <= 45 && Mathf.Abs((float)i - 42.5f - ((float)j - 43.5f) * 0.18f) <= 3f; if (num5) { val13 = val10; } else if (flag4) { val13 = val11; } if ((Mathf.Abs(j - i) <= 2 && j >= 18 && j <= 46) || (Mathf.Abs(j + i - 64) <= 2 && j >= 18 && j <= 46)) { val13 = val4; } } if (slope) { float num6 = 47f - ((float)j - 14f) * 0.62f; if (j >= 14 && j <= 50 && Mathf.Abs((float)i - num6) <= 2f) { val13 = val10; } else if (j >= 14 && j <= 50 && (float)i > num6 && i < 49) { val13 = Color.Lerp(val11, val10, Mathf.Clamp01((49f - (float)i) / 18f)); } if ((Mathf.Abs(j - 16) <= 1 && i >= 41 && i <= 50) || (Mathf.Abs(j - 50) <= 1 && i >= 18 && i <= 29)) { val13 = val4; } } if (!slope && !reset && !paint && !paintReset && ((Mathf.Abs(j - 32) <= 1 && i >= 12 && i <= 21) || (Mathf.Abs(i - 32) <= 1 && j >= 12 && j <= 21) || (Mathf.Abs(i - 32) <= 1 && j >= 43 && j <= 52))) { val13 = val4; } val.SetPixel(j, i, val13); } } val.Apply(); Sprite val14 = Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 64f); if (paintReset) { _paintResetIcon = val14; } else if (paint) { _paintIcon = val14; } else if (reset) { _resetIcon = val14; } else if (slope) { _slopeIcon = val14; } else { _icon = val14; } return val14; } private static bool TryGetProxyGhost(GameObject ghost, out GameObject proxyGhost) { proxyGhost = null; if (!Object.op_Implicit((Object)(object)ghost)) { return false; } if (IsProxyObject(ghost)) { proxyGhost = ghost; return true; } ZoneSaviorTerrainProxy componentInChildren = ghost.GetComponentInChildren(true); if (Object.op_Implicit((Object)(object)componentInChildren)) { proxyGhost = ((Component)componentInChildren).gameObject; return true; } return false; } public static void PreparePlacementGhost(Player player) { //IL_008a: 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_0064: 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_003e: 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) if (!ShouldShowTo(player) || !Object.op_Implicit((Object)(object)player.m_placementGhost) || !TryGetProxyGhost(player.m_placementGhost, out GameObject proxyGhost)) { ClearPendingSlopeStart(); HideAreaLine(); } else if (IsSlopeProxyObject(proxyGhost)) { if (_hasPendingSlopeStart && TryCreateSlopePlacement(_pendingSlopeStart, proxyGhost.transform.position, out var placement)) { DrawSlopeAreaLineIfChanged(placement); } else { DrawWidthLineIfChanged(proxyGhost.transform.position, proxyGhost.transform.rotation, CurrentSlopeWidth()); } } else { ClearPendingSlopeStart(); DrawCircleLineIfChanged(proxyGhost.transform.position, Quaternion.identity, CurrentCircleRadius()); } } private static void UpdatePlacementPreview() { Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer)) { HideAreaLine(); } else { PreparePlacementGhost(localPlayer); } } private static void UpdatePlacementSizingInput() { Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer) || !Object.op_Implicit((Object)(object)localPlayer.m_placementGhost) || !TryGetProxyGhost(localPlayer.m_placementGhost, out GameObject proxyGhost)) { return; } float axis = Input.GetAxis("Mouse ScrollWheel"); if (Mathf.Abs(axis) < 0.001f) { return; } float num = Mathf.Sign(axis); if (IsSlopeProxyObject(proxyGhost)) { if (IsTerrainToolModifierHeld()) { _runtimeSlopeWidth = Mathf.Clamp(CurrentSlopeWidth() + num, 0.5f, 256f); UpdatePieceDescriptions(); } } else if (IsTerrainProxyObject(proxyGhost) && IsTerrainToolModifierHeld()) { _runtimeTerrainEdgeSoftness = Mathf.Clamp01(CurrentTerrainEdgeSoftness() + num * 0.05f); UpdatePieceDescriptions(); } else if (IsPaintProxyObject(proxyGhost) && IsTerrainToolModifierHeld()) { _runtimePaintType = RotatePaintType(CurrentPaintType(), num); UpdatePieceDescriptions(); } else { _runtimeRadius = Mathf.Clamp(CurrentCircleRadius() + num, 0.5f, 128f); UpdatePieceDescriptions(); } } internal static float GetPlacementMouseScrollWheel() { if (!ShouldSuppressVanillaPlacementWheelRotation()) { return ZInput.GetMouseScrollWheel(); } return 0f; } private static bool ShouldSuppressVanillaPlacementWheelRotation() { Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer) || !Object.op_Implicit((Object)(object)localPlayer.m_placementGhost) || !TryGetProxyGhost(localPlayer.m_placementGhost, out GameObject proxyGhost)) { return false; } if (IsSlopeProxyObject(proxyGhost) || IsTerrainProxyObject(proxyGhost) || IsPaintProxyObject(proxyGhost)) { return IsTerrainToolModifierHeld(); } return false; } private static float CurrentCircleRadius() { return CurrentRuntimeValue(ref _runtimeRadius, ref _lastConfigRadius, AdminTerrainToolConfig.Radius, 0.5f, 128f); } private static float CurrentSlopeWidth() { return CurrentRuntimeValue(ref _runtimeSlopeWidth, ref _lastConfigSlopeWidth, AdminTerrainToolConfig.SlopeWidth, 0.5f, 256f); } private static float CurrentTerrainEdgeSoftness() { return CurrentRuntimeValue(ref _runtimeTerrainEdgeSoftness, ref _lastConfigTerrainEdgeSoftness, AdminTerrainToolConfig.TerrainEdgeSoftness, 0f, 1f); } private static AdminTerrainPaintType CurrentPaintType() { AdminTerrainPaintType paintType = AdminTerrainToolConfig.PaintType; if (!_runtimePaintTypeInitialized || _lastConfigPaintType != paintType) { _runtimePaintType = paintType; _lastConfigPaintType = paintType; _runtimePaintTypeInitialized = true; } if (!GetPaintTypeValues().Contains(_runtimePaintType)) { _runtimePaintType = paintType; } return _runtimePaintType; } private static AdminTerrainPaintType RotatePaintType(AdminTerrainPaintType current, float direction) { AdminTerrainPaintType[] paintTypeValues = GetPaintTypeValues(); int num = Array.IndexOf(paintTypeValues, current); if (num < 0) { num = Array.IndexOf(paintTypeValues, AdminTerrainToolConfig.PaintType); } if (num < 0) { num = 0; } int num2 = ((direction > 0f) ? 1 : (-1)); int num3 = (num + num2 + paintTypeValues.Length) % paintTypeValues.Length; return paintTypeValues[num3]; } private static AdminTerrainPaintType[] GetPaintTypeValues() { return (from value in Enum.GetValues(typeof(AdminTerrainPaintType)).Cast().Distinct() orderby (int)value select value).ToArray(); } private static bool IsTerrainProxyObject(GameObject obj) { if (IsProxyObject(obj) && !IsSlopeProxyObject(obj) && !IsPaintProxyObject(obj) && !IsResetProxyObject(obj)) { return !IsPaintResetProxyObject(obj); } return false; } private static bool IsTerrainToolModifierHeld() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return IsShortcutHeld(AdminTerrainToolConfig.TerrainToolModifierKey); } private static bool IsShortcutHeld(KeyboardShortcut shortcut) { //IL_0002: 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) if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0) { return ((KeyboardShortcut)(ref shortcut)).Modifiers.All(IsModifierHeld); } if (IsKeyHeld(((KeyboardShortcut)(ref shortcut)).MainKey)) { return ((KeyboardShortcut)(ref shortcut)).Modifiers.All(IsModifierHeld); } return false; } private static bool IsModifierHeld(KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return IsKeyHeld(key); } private static bool IsKeyHeld(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 float CurrentRuntimeValue(ref float runtimeValue, ref float lastConfigValue, float configValue, float min, float max) { configValue = Mathf.Clamp(configValue, min, max); if (float.IsNaN(runtimeValue) || float.IsNaN(lastConfigValue) || !Mathf.Approximately(lastConfigValue, configValue)) { runtimeValue = configValue; lastConfigValue = configValue; } runtimeValue = Mathf.Clamp(runtimeValue, min, max); return runtimeValue; } private static bool ConfigureNewSlopeProxy(ZoneSaviorTerrainProxy proxy, ZDO zdo) { //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_003b: 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_0013: 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_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0087: 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_00a1: 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_0051: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)proxy).transform.position; if (!_hasPendingSlopeStart) { _pendingSlopeStart = position; _hasPendingSlopeStart = true; _pendingSlopeStartFrame = Time.frameCount; ShowMessage("ZoneSavior slope start marker set."); proxy.QueueDestroy(); return false; } Vector3 pendingSlopeStart = _pendingSlopeStart; _hasPendingSlopeStart = false; if (!TryCreateSlopePlacement(pendingSlopeStart, position, out var placement)) { _pendingSlopeStart = position; _hasPendingSlopeStart = true; _pendingSlopeStartFrame = Time.frameCount; ShowMessage("ZoneSavior slope start marker reset."); proxy.QueueDestroy(); return false; } ((Component)proxy).transform.SetPositionAndRotation(placement.Center, placement.Rotation); zdo.SetPosition(placement.Center); zdo.SetRotation(placement.Rotation); WriteSettings(zdo, SlopeSettings(placement)); return true; } private static bool TryCreateSlopePlacement(Vector3 start, Vector3 end, out SlopePlacement placement) { //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_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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_0064: 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) //IL_0077: 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_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: 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) Vector3 val = end - start; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { placement = default(SlopePlacement); return false; } Vector3 normalized = ((Vector3)(ref val)).normalized; float length = Mathf.Clamp(((Vector3)(ref val)).magnitude, 0.5f, 256f); float width = CurrentSlopeWidth(); Vector3 center = default(Vector3); ((Vector3)(ref center))..ctor((start.x + end.x) * 0.5f, (start.y + end.y) * 0.5f, (start.z + end.z) * 0.5f); Quaternion rotation = Quaternion.LookRotation(normalized, Vector3.up); placement = new SlopePlacement(center, rotation, width, length, end.y - start.y); return true; } private static void ClearPendingSlopeStart() { if (_hasPendingSlopeStart && Time.frameCount > _pendingSlopeStartFrame) { _hasPendingSlopeStart = false; _pendingSlopeStartFrame = 0; } } public static void AddToAvailablePieces(PieceTable table, Player player) { if (ShouldShowTo(player)) { EnsureRegistered(); if (Object.op_Implicit((Object)(object)_prefab) && Object.op_Implicit((Object)(object)_slopePrefab) && Object.op_Implicit((Object)(object)_paintPrefab) && Object.op_Implicit((Object)(object)_resetPrefab) && Object.op_Implicit((Object)(object)_paintResetPrefab)) { SanitizePieceTable(table); AddPieceToTable(table, _prefab); AddPieceToTable(table, _slopePrefab); AddPieceToTable(table, _paintPrefab); AddPieceToTable(table, _paintResetPrefab); AddPieceToTable(table, _resetPrefab); } } } private static GameObject? EnsureRegistered() { ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance == (Object)null) { return _prefab; } if (!Object.op_Implicit((Object)(object)_prefab)) { _prefab = CreatePrefab("ZoneSaviorTerrainProxy", slope: false); } if (!Object.op_Implicit((Object)(object)_slopePrefab)) { _slopePrefab = CreatePrefab("ZoneSaviorTerrainProxySlope", slope: true); } if (!Object.op_Implicit((Object)(object)_paintPrefab)) { _paintPrefab = CreatePrefab("ZoneSaviorPaintProxy", slope: false, reset: false, paint: true); } if (!Object.op_Implicit((Object)(object)_resetPrefab)) { _resetPrefab = CreatePrefab("ZoneSaviorTerrainReset", slope: false, reset: true); } if (!Object.op_Implicit((Object)(object)_paintResetPrefab)) { _paintResetPrefab = CreatePrefab("ZoneSaviorPaintReset", slope: false, reset: false, paint: false, paintReset: true); } if ((Object)(object)_registeredScene == (Object)(object)instance && IsRegistered(instance, PrefabHash) && IsRegistered(instance, SlopePrefabHash) && IsRegistered(instance, PaintPrefabHash) && IsRegistered(instance, ResetPrefabHash) && IsRegistered(instance, PaintResetPrefabHash)) { return _prefab; } RegisterPrefab(instance, PrefabHash, "ZoneSaviorTerrainProxy", _prefab); RegisterPrefab(instance, SlopePrefabHash, "ZoneSaviorTerrainProxySlope", _slopePrefab); RegisterPrefab(instance, PaintPrefabHash, "ZoneSaviorPaintProxy", _paintPrefab); RegisterPrefab(instance, PaintResetPrefabHash, "ZoneSaviorPaintReset", _paintResetPrefab); RegisterPrefab(instance, ResetPrefabHash, "ZoneSaviorTerrainReset", _resetPrefab); _registeredScene = instance; return _prefab; } private static bool IsRegistered(ZNetScene scene, int prefabHash) { if (scene.m_namedPrefabs.TryGetValue(prefabHash, out var value)) { return Object.op_Implicit((Object)(object)value); } return false; } private static GameObject? GetRegisteredPrefab(int prefabHash) { EnsureRegistered(); if (prefabHash != PrefabHash) { if (prefabHash != SlopePrefabHash) { if (prefabHash != PaintPrefabHash) { if (prefabHash != ResetPrefabHash) { if (prefabHash != PaintResetPrefabHash) { return null; } return _paintResetPrefab; } return _resetPrefab; } return _paintPrefab; } return _slopePrefab; } return _prefab; } private static void RegisterPrefab(ZNetScene scene, int prefabHash, string prefabName, GameObject prefab) { string prefabName2 = prefabName; if (!scene.m_namedPrefabs.ContainsKey(prefabHash)) { scene.m_namedPrefabs[prefabHash] = prefab; } if (!scene.m_prefabs.Any((GameObject registered) => Object.op_Implicit((Object)(object)registered) && string.Equals(Utils.GetPrefabName(registered), prefabName2, StringComparison.Ordinal))) { scene.m_prefabs.Add(prefab); } } private static void AddPieceToTable(PieceTable table, GameObject prefab) { //IL_0040: 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_0094: Expected I4, but got Unknown string prefabName = Utils.GetPrefabName(prefab); if (!table.m_pieces.Any((GameObject piece) => Object.op_Implicit((Object)(object)piece) && string.Equals(Utils.GetPrefabName(piece), prefabName, StringComparison.Ordinal))) { table.m_pieces.Add(prefab); } Piece component = prefab.GetComponent(); component.m_category = (PieceCategory)0; component.m_clipEverything = true; component.m_icon = GetIcon(IsSlopeProxyObject(prefab), IsResetProxyObject(prefab), IsPaintProxyObject(prefab), IsPaintResetProxyObject(prefab)); component.m_description = GetPieceDescription(prefab); int num = Mathf.Clamp((int)component.m_category, 0, table.m_availablePieces.Count - 1); if (num >= 0) { List list = table.m_availablePieces[num]; if (!list.Any((Piece piece) => Object.op_Implicit((Object)(object)piece) && string.Equals(Utils.GetPrefabName(((Component)piece).gameObject), prefabName, StringComparison.Ordinal))) { list.Add(component); } } } internal static void SanitizeKnownRecipePieceTables(Player player) { if (!Object.op_Implicit((Object)(object)player)) { return; } SanitizePieceTable(player.m_buildPieces); PieceTableScratch.Clear(); Inventory inventory = ((Humanoid)player).m_inventory; if (inventory != null) { inventory.GetAllPieceTables(PieceTableScratch); } foreach (PieceTable item in PieceTableScratch) { SanitizePieceTable(item); } PieceTableScratch.Clear(); } private static void SanitizePieceTable(PieceTable? table) { if (!Object.op_Implicit((Object)(object)table) || table.m_pieces == null) { return; } table.m_pieces.RemoveAll((GameObject piece) => !Object.op_Implicit((Object)(object)piece)); foreach (List availablePiece in table.m_availablePieces) { availablePiece?.RemoveAll((Piece piece) => !Object.op_Implicit((Object)(object)piece)); } } private static void UpdatePieceDescriptions() { UpdatePieceDescription(_prefab); UpdatePieceDescription(_slopePrefab); UpdatePieceDescription(_paintPrefab); UpdatePieceDescription(_paintResetPrefab); UpdatePieceDescription(_resetPrefab); } private static void UpdatePieceDescription(GameObject? prefab) { if (Object.op_Implicit((Object)(object)prefab)) { Piece component = prefab.GetComponent(); if (Object.op_Implicit((Object)(object)component)) { component.m_description = GetPieceDescription(prefab); } } } private static string GetPieceDescription(GameObject prefab) { if (IsSlopeProxyObject(prefab)) { return string.Join("\n", "Places start and end markers to store and replay a terrain slope.", "", "Width: " + FormatMeters(CurrentSlopeWidth()), "Start marker: " + (_hasPendingSlopeStart ? "set" : "not set"), FormatTerrainToolWheelAction("width")); } if (IsPaintProxyObject(prefab)) { return string.Join("\n", "Stores and replays terrain paint in this circle.", "", "Current radius: " + FormatMeters(CurrentCircleRadius()), $"Paint: {CurrentPaintType()}", FormatTerrainToolWheelAction("paint type")); } if (IsPaintResetProxyObject(prefab)) { return string.Join("\n", "Resets terrain paint in this radius and removes intersecting ZoneSavior paint proxies.", "", "Current radius: " + FormatMeters(CurrentCircleRadius())); } if (IsResetProxyObject(prefab)) { return string.Join("\n", "Resets terrain in this radius and removes intersecting ZoneSavior terrain proxies.", "", "Current radius: " + FormatMeters(CurrentCircleRadius())); } return string.Join("\n", "Stores and replays terrain filled to this marker height.", "", "Current radius: " + FormatMeters(CurrentCircleRadius()), $"Edge Softness: {CurrentTerrainEdgeSoftness():0.##}", FormatTerrainToolWheelAction("edge softness")); } private static string FormatMeters(float value) { return $"{value:0.#}m"; } private static string FormatTerrainToolWheelAction(string action) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) string text = FormatShortcut(AdminTerrainToolConfig.TerrainToolModifierKey); if (!string.IsNullOrWhiteSpace(text)) { return text + " + wheel: " + action; } return "Wheel: " + action; } private static string FormatShortcut(KeyboardShortcut shortcut) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) List list = (from key in ((KeyboardShortcut)(ref shortcut)).Modifiers.Select(FormatKey) where !string.IsNullOrWhiteSpace(key) select key).ToList(); string text = FormatKey(((KeyboardShortcut)(ref shortcut)).MainKey); if (!string.IsNullOrWhiteSpace(text)) { list.Add(text); } if (list.Count <= 0) { return ""; } return string.Join(" + ", list); } private static string FormatKey(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 if ((int)key != 0) { switch (key - 303) { case 4: case 5: return "Alt"; case 2: case 3: return "Ctrl"; case 0: case 1: return "Shift"; default: return ((object)(KeyCode)(ref key)).ToString(); } } return ""; } private static GameObject CreatePrefab(string prefabName, bool slope, bool reset = false, bool paint = false, bool paintReset = false) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_004d: 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) GameObject val = new GameObject(prefabName); ((Object)val).name = prefabName; val.SetActive(false); Object.DontDestroyOnLoad((Object)(object)val); int num = LayerMask.NameToLayer("piece"); if (num >= 0) { val.layer = num; } ZNetView obj = val.AddComponent(); obj.m_persistent = !(reset || paintReset); obj.m_distant = false; obj.m_type = (ObjectType)2; obj.m_syncInitialScale = true; Piece obj2 = val.AddComponent(); obj2.m_name = (paintReset ? "ZoneSavior Paint Reset" : (paint ? "ZoneSavior Paint Proxy" : (reset ? "ZoneSavior Terrain Reset" : (slope ? "ZoneSavior TerrainProxy Slope" : "ZoneSavior Terrain Proxy")))); obj2.m_enabled = true; obj2.m_category = (PieceCategory)0; obj2.m_groundOnly = false; obj2.m_groundPiece = false; obj2.m_clipGround = false; obj2.m_clipEverything = true; obj2.m_allowAltGroundPlacement = true; obj2.m_canBeRemoved = true; obj2.m_noClipping = true; obj2.m_resources = Array.Empty(); val.AddComponent(); obj2.m_icon = GetIcon(slope, reset, paint, paintReset); obj2.m_description = GetPieceDescription(val); return val; } private static void HideAreaLine() { if (Object.op_Implicit((Object)(object)_areaLine)) { ((Renderer)_areaLine).enabled = false; } _lastPreviewKind = PreviewKind.None; } private static void EnsureAreaLine() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_00af: 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) if (!Object.op_Implicit((Object)(object)_areaLine)) { _previewRoot = new GameObject("ZoneSaviorTerrainProxyArea"); Object.DontDestroyOnLoad((Object)(object)_previewRoot); if (_lineMaterial == null) { _lineMaterial = CreateLineMaterial(); } _areaLine = _previewRoot.AddComponent(); _areaLine.useWorldSpace = true; _areaLine.startWidth = 0.05f; _areaLine.endWidth = 0.05f; _areaLine.numCornerVertices = 2; _areaLine.numCapVertices = 2; ((Renderer)_areaLine).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)_areaLine).receiveShadows = false; ((Renderer)_areaLine).material = _lineMaterial; _areaLine.startColor = AreaColor(); _areaLine.endColor = AreaColor(); ((Renderer)_areaLine).enabled = false; } } private static Material? CreateLineMaterial() { //IL_0024: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown Shader val = Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Color"); if (!Object.op_Implicit((Object)(object)val)) { return null; } return new Material(val) { color = Color.white }; } private static void DrawCircleLineIfChanged(Vector3 center, Quaternion rotation, float radius) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0004: 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_0027: Unknown result type (might be due to invalid IL or missing references) if (!PreviewUnchanged(PreviewKind.Circle, center, ((Quaternion)(ref rotation)).eulerAngles.y, radius, 0f, 0f, 0f)) { DrawCircleLine(center, rotation, radius); } } private static void DrawSlopeAreaLineIfChanged(SlopePlacement placement) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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_0012: Unknown result type (might be due to invalid IL or missing references) Vector3 center = placement.Center; Quaternion rotation = placement.Rotation; if (!PreviewUnchanged(PreviewKind.Slope, center, ((Quaternion)(ref rotation)).eulerAngles.y, 0f, placement.Width, placement.Length, placement.HeightDelta)) { DrawSlopeAreaLine(placement); } } private static void DrawWidthLineIfChanged(Vector3 center, Quaternion rotation, float width) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0004: 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_0027: Unknown result type (might be due to invalid IL or missing references) if (!PreviewUnchanged(PreviewKind.Width, center, ((Quaternion)(ref rotation)).eulerAngles.y, 0f, width, 0f, 0f)) { DrawWidthLine(center, rotation, width); } } private static bool PreviewUnchanged(PreviewKind kind, Vector3 position, float yaw, float radius, float width, float length, float heightDelta) { //IL_00b1: 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_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_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) if (Object.op_Implicit((Object)(object)_areaLine) && ((Renderer)_areaLine).enabled && _lastPreviewKind == kind) { Vector3 val = _lastPreviewPosition - position; if (((Vector3)(ref val)).sqrMagnitude <= 0.0001f && Mathf.Abs(Mathf.DeltaAngle(_lastPreviewYaw, yaw)) <= 0.01f && Mathf.Abs(_lastPreviewRadius - radius) <= 0.01f && Mathf.Abs(_lastPreviewWidth - width) <= 0.01f && Mathf.Abs(_lastPreviewLength - length) <= 0.01f && Mathf.Abs(_lastPreviewHeightDelta - heightDelta) <= 0.01f) { return true; } } _lastPreviewKind = kind; _lastPreviewPosition = position; _lastPreviewYaw = yaw; _lastPreviewRadius = radius; _lastPreviewWidth = width; _lastPreviewLength = length; _lastPreviewHeightDelta = heightDelta; return false; } private static void DrawAreaLine(Vector3 center, Quaternion rotation, float width, float length) { //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) //IL_0028: 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: 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) EnsureAreaLine(); if (Object.op_Implicit((Object)(object)_areaLine)) { ((Renderer)_areaLine).enabled = true; Color val = AreaColor(); _areaLine.startColor = val; _areaLine.endColor = val; DrawRectangleLine(center, rotation, width * 0.5f, length * 0.5f); } } private static void DrawCircleLine(Vector3 center, Quaternion rotation, float radius) { //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) //IL_0028: 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_005e: 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_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_0084: 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) EnsureAreaLine(); if (Object.op_Implicit((Object)(object)_areaLine)) { ((Renderer)_areaLine).enabled = true; Color val = AreaColor(); _areaLine.startColor = val; _areaLine.endColor = val; _areaLine.positionCount = 97; for (int i = 0; i <= 96; i++) { float num = (float)i * (float)Math.PI * 2f / 96f; Vector3 val2 = center + rotation * new Vector3(Mathf.Cos(num) * radius, 0f, Mathf.Sin(num) * radius); _areaLine.SetPosition(i, val2); } } } private static void DrawRectangleLine(Vector3 center, Quaternion rotation, float halfX, float halfZ) { //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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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_0036: 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_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_004a: 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_005b: 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_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_007d: 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_0087: 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_00a1: 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_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) _areaLine.positionCount = 5; _areaLine.SetPosition(0, center + rotation * new Vector3(0f - halfX, 0f, 0f - halfZ)); _areaLine.SetPosition(1, center + rotation * new Vector3(0f - halfX, 0f, halfZ)); _areaLine.SetPosition(2, center + rotation * new Vector3(halfX, 0f, halfZ)); _areaLine.SetPosition(3, center + rotation * new Vector3(halfX, 0f, 0f - halfZ)); _areaLine.SetPosition(4, center + rotation * new Vector3(0f - halfX, 0f, 0f - halfZ)); } private static void DrawWidthLine(Vector3 center, Quaternion rotation, float width) { //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) //IL_0028: 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_0052: 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_0060: 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_006a: 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_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0087: 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) EnsureAreaLine(); if (Object.op_Implicit((Object)(object)_areaLine)) { ((Renderer)_areaLine).enabled = true; Color val = AreaColor(); _areaLine.startColor = val; _areaLine.endColor = val; float num = width * 0.5f; _areaLine.positionCount = 2; _areaLine.SetPosition(0, center + rotation * new Vector3(0f - num, 0f, 0f)); _areaLine.SetPosition(1, center + rotation * new Vector3(num, 0f, 0f)); } } private static void DrawSlopeAreaLine(SlopePlacement placement) { //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) //IL_0028: 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_006c: 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) //IL_0095: 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_00c0: Unknown result type (might be due to invalid IL or missing references) EnsureAreaLine(); if (Object.op_Implicit((Object)(object)_areaLine)) { ((Renderer)_areaLine).enabled = true; Color val = AreaColor(); _areaLine.startColor = val; _areaLine.endColor = val; float num = placement.Width * 0.5f; float num2 = placement.Length * 0.5f; _areaLine.positionCount = 5; _areaLine.SetPosition(0, placement.GetWorldPoint(0f - num, 0f - num2)); _areaLine.SetPosition(1, placement.GetWorldPoint(0f - num, num2)); _areaLine.SetPosition(2, placement.GetWorldPoint(num, num2)); _areaLine.SetPosition(3, placement.GetWorldPoint(num, 0f - num2)); _areaLine.SetPosition(4, placement.GetWorldPoint(0f - num, 0f - num2)); } } private static Color AreaColor() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) return new Color(1f, 0.05f, 0.85f, 1f); } private static void ApplyStoredSettings(ZoneSaviorTerrainProxy proxy, bool force, bool notify = false) { //IL_003b: 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_006a: 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) ZNetView component = ((Component)proxy).GetComponent(); ZDO val = (Object.op_Implicit((Object)(object)component) ? component.GetZDO() : null); if (val != null && (force || !val.GetBool(AppliedHash, false))) { TerrainProxySettings settings = ReadSettings(val); int num = ApplyTerrain(((Component)proxy).transform.position, ((Component)proxy).transform.rotation, settings); val.Set(AppliedHash, true); val.Set(AppliedPositionHash, ((Component)proxy).transform.position); string text = ((settings.Mode == TerrainProxyMode.Paint) ? "paint proxy" : "terrain proxy"); string text2 = ((settings.Mode == TerrainProxyMode.Paint) ? $"Paint={settings.PaintType}, Radius={settings.SearchRadius:0.##}" : $"TargetY={((Component)proxy).transform.position.y:0.##}, Radius={settings.SearchRadius:0.##}"); if (num > 0) { ReportTerrainResult($"ZoneSavior {text} applied {num} terrain compiler(s). Mode={settings.Mode}, {text2}.", notify); } else { ReportTerrainResult($"ZoneSavior {text} made no terrain changes. Mode={settings.Mode}, {text2}.", notify); } } } private static int ApplyTerrain(Vector3 position, Quaternion rotation, TerrainProxySettings settings) { //IL_0006: 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_005c: 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) List list = new List(); Heightmap.FindHeightmap(position, settings.SearchRadius + 4f, list); int num = 0; HashSet hashSet = new HashSet(); foreach (Heightmap item in list) { if (Object.op_Implicit((Object)(object)item)) { TerrainComp andCreateTerrainCompiler = item.GetAndCreateTerrainCompiler(); if (Object.op_Implicit((Object)(object)andCreateTerrainCompiler) && hashSet.Add(andCreateTerrainCompiler) && ApplyTerrainCompiler(andCreateTerrainCompiler, position, rotation, settings)) { num++; } } } if (num > 0) { ClutterSystem instance = ClutterSystem.instance; if (instance != null) { instance.ResetGrass(position, settings.SearchRadius + 4f); } } return num; } private static int ResetTerrain(Vector3 position, Quaternion rotation, TerrainProxySettings settings) { //IL_0006: 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_0065: 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_009b: Unknown result type (might be due to invalid IL or missing references) List list = new List(); Heightmap.FindHeightmap(position, settings.SearchRadius + 4f, list); int num = 0; HashSet hashSet = new HashSet(); foreach (Heightmap item in list) { if (Object.op_Implicit((Object)(object)item)) { TerrainComp val = TerrainComp.FindTerrainCompiler(((Component)item).transform.position); if (Object.op_Implicit((Object)(object)val) && hashSet.Add(val) && ResetTerrainCompiler(val, position, rotation, settings)) { num++; } } } if (num > 0) { ClutterSystem instance = ClutterSystem.instance; if (instance != null) { instance.ResetGrass(position, settings.SearchRadius + 4f); } } return num; } private static bool ApplyTerrainCompiler(TerrainComp compiler, Vector3 position, Quaternion rotation, TerrainProxySettings settings) { //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: 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_00e5: 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_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: 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_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)compiler.m_nview) || !compiler.m_nview.IsValid()) { return false; } if (!compiler.m_nview.IsOwner()) { compiler.m_nview.ClaimOwnership(); } Heightmap hmap = compiler.m_hmap; int num = hmap.m_width + 1; int num2 = num * num; if (compiler.m_modifiedHeight.Length != num2 || compiler.m_levelDelta.Length != num2 || compiler.m_smoothDelta.Length != num2 || compiler.m_modifiedPaint.Length != num2 || compiler.m_paintMask.Length != num2) { return false; } bool flag = false; Quaternion val = Quaternion.Inverse(Quaternion.Euler(0f, ((Quaternion)(ref rotation)).eulerAngles.y, 0f)); if (!TryGetHeightmapIndexRange(hmap, position, settings.SearchRadius + 4f, out var minX, out var maxX, out var minZ, out var maxZ)) { return false; } for (int i = minZ; i <= maxZ; i++) { for (int j = minX; j <= maxX; j++) { int index = i * num + j; Vector3 val2 = VertexToWorld(hmap, j, i); Vector3 val3 = val * (val2 - position); float normalizedDistance = settings.GetNormalizedDistance(val3.x, val3.z); if (settings.ModifiesHeight && normalizedDistance <= 1f) { float targetHeight = settings.GetTargetHeight(position, ((Component)hmap).transform.position.y, val3.z); float height = hmap.GetHeight(j, i); flag |= ApplyHeightNode(compiler, index, height, targetHeight, val3.x, val3.z, settings); } if (settings.ModifiesPaint) { flag |= ApplyPaintNode(compiler, hmap, j, i, index, normalizedDistance, settings); } } } if (!flag) { return false; } compiler.m_operations++; compiler.m_lastOpPoint = position; compiler.m_lastOpRadius = settings.SearchRadius; compiler.Save(); hmap.Poke(false); return true; } private static bool ResetTerrainCompiler(TerrainComp compiler, Vector3 position, Quaternion rotation, TerrainProxySettings settings) { //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: 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_00e5: 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_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: 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_0106: 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_01a4: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)compiler.m_nview) || !compiler.m_nview.IsValid()) { return false; } if (!compiler.m_nview.IsOwner()) { compiler.m_nview.ClaimOwnership(); } Heightmap hmap = compiler.m_hmap; int num = hmap.m_width + 1; int num2 = num * num; if (compiler.m_modifiedHeight.Length != num2 || compiler.m_levelDelta.Length != num2 || compiler.m_smoothDelta.Length != num2 || compiler.m_modifiedPaint.Length != num2 || compiler.m_paintMask.Length != num2) { return false; } bool flag = false; Quaternion val = Quaternion.Inverse(Quaternion.Euler(0f, ((Quaternion)(ref rotation)).eulerAngles.y, 0f)); if (!TryGetHeightmapIndexRange(hmap, position, settings.SearchRadius + 4f, out var minX, out var maxX, out var minZ, out var maxZ)) { return false; } for (int i = minZ; i <= maxZ; i++) { for (int j = minX; j <= maxX; j++) { int num3 = i * num + j; Vector3 val2 = VertexToWorld(hmap, j, i); Vector3 val3 = val * (val2 - position); if (!(settings.GetNormalizedDistance(val3.x, val3.z) > 1f)) { if (settings.ModifiesHeight && (compiler.m_modifiedHeight[num3] || Mathf.Abs(compiler.m_levelDelta[num3]) > 0.001f || Mathf.Abs(compiler.m_smoothDelta[num3]) > 0.001f)) { compiler.m_modifiedHeight[num3] = false; compiler.m_levelDelta[num3] = 0f; compiler.m_smoothDelta[num3] = 0f; flag = true; } if (compiler.m_modifiedPaint[num3]) { compiler.m_modifiedPaint[num3] = false; compiler.m_paintMask[num3] = Color.clear; flag = true; } } } } if (!flag) { return false; } compiler.m_operations++; compiler.m_lastOpPoint = position; compiler.m_lastOpRadius = settings.SearchRadius; compiler.Save(); hmap.Poke(false); return true; } private static bool TryGetHeightmapIndexRange(Heightmap heightmap, Vector3 position, float radius, out int minX, out int maxX, out int minZ, out int maxZ) { //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_0033: 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_0057: 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_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_009f: 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) int width = heightmap.m_width; float num = Mathf.Max(heightmap.m_scale, 0.001f); float num2 = (float)heightmap.m_width * 0.5f; Vector3 position2 = ((Component)heightmap).transform.position; minX = Mathf.Clamp(Mathf.FloorToInt((position.x - radius - position2.x) / num + num2) - 1, 0, width); maxX = Mathf.Clamp(Mathf.CeilToInt((position.x + radius - position2.x) / num + num2) + 1, 0, width); minZ = Mathf.Clamp(Mathf.FloorToInt((position.z - radius - position2.z) / num + num2) - 1, 0, width); maxZ = Mathf.Clamp(Mathf.CeilToInt((position.z + radius - position2.z) / num + num2) + 1, 0, width); if (minX <= maxX) { return minZ <= maxZ; } return false; } private static bool ApplyHeightNode(TerrainComp compiler, int index, float currentHeight, float targetHeight, float localX, float localZ, TerrainProxySettings settings) { float num = (targetHeight - currentHeight + compiler.m_smoothDelta[index]) * settings.GetLevelFalloff(localX, localZ); compiler.m_smoothDelta[index] = 0f; float num2 = compiler.m_levelDelta[index]; compiler.m_levelDelta[index] = Mathf.Clamp(num2 + num, -1024f, 1024f); compiler.m_modifiedHeight[index] = Mathf.Abs(compiler.m_levelDelta[index]) > 0.001f; return Mathf.Abs(num2 - compiler.m_levelDelta[index]) > 0.001f; } private static bool ApplyPaintNode(TerrainComp compiler, Heightmap heightmap, int x, int z, int index, float normalized, TerrainProxySettings settings) { //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_001b: 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_0021: 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_0023: 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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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) //IL_0086: 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_0093: 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) if (normalized > 1f) { return false; } Color paintMask = heightmap.GetPaintMask(x, z); Color paintTarget = GetPaintTarget(settings.PaintType, paintMask); Color val = Color.Lerp(paintMask, paintTarget, Mathf.Pow(1f - Mathf.Clamp01(normalized), 0.1f)); if (settings.PaintType != AdminTerrainPaintType.ClearVegetation) { val.a = paintMask.a; } if (compiler.m_modifiedPaint[index]) { if (!Approximately(compiler.m_paintMask[index], val)) { return SetPaintNode(compiler, index, val); } return false; } if (Approximately(paintMask, val)) { return false; } return SetPaintNode(compiler, index, val); } private static bool SetPaintNode(TerrainComp compiler, int index, Color desired) { //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) compiler.m_modifiedPaint[index] = true; compiler.m_paintMask[index] = desired; return true; } private static Color GetPaintTarget(AdminTerrainPaintType paintType, Color current) { //IL_0037: 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_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) //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) //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_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) //IL_0086: 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_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_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_00cb: 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) //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) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) return (Color)(paintType switch { AdminTerrainPaintType.Grass => Heightmap.m_paintMaskNothing, AdminTerrainPaintType.Dirt => Heightmap.m_paintMaskDirt, AdminTerrainPaintType.Cultivated => Heightmap.m_paintMaskCultivated, AdminTerrainPaintType.Paved => Heightmap.m_paintMaskPaved, AdminTerrainPaintType.DarkGrass => new Color(0.6f, 0.5f, 0f), AdminTerrainPaintType.PatchyGrass => new Color(0f, 0.75f, 0f), AdminTerrainPaintType.MossyPaving => new Color(0f, 0f, 0.5f), AdminTerrainPaintType.DirtPaving => new Color(1f, 0f, 0.5f), AdminTerrainPaintType.DarkPaving => new Color(0f, 1f, 0.5f), AdminTerrainPaintType.ClearVegetation => Heightmap.m_paintMaskClearVegetation, _ => current, }); } 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_0050: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)heightmap).transform.position; position.x += ((float)x - (float)heightmap.m_width / 2f) * heightmap.m_scale; position.z += ((float)z - (float)heightmap.m_width / 2f) * heightmap.m_scale; return position; } 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; } internal static void PreparePieceTooltip(Hud hud, Piece piece) { if (Object.op_Implicit((Object)(object)hud) && Object.op_Implicit((Object)(object)hud.m_pieceDescription)) { if (_defaultTooltipFontSize < 0f) { _defaultTooltipFontSize = hud.m_pieceDescription.fontSize; } if (!IsProxyPiece(piece)) { hud.m_pieceDescription.fontSize = _defaultTooltipFontSize; } else { piece.m_description = GetPieceDescription(((Component)piece).gameObject); } } } internal static void ApplyPieceTooltipStyle(Hud hud, Piece piece) { if (Object.op_Implicit((Object)(object)hud) && Object.op_Implicit((Object)(object)hud.m_pieceDescription) && IsProxyPiece(piece)) { if (_defaultTooltipFontSize < 0f) { _defaultTooltipFontSize = hud.m_pieceDescription.fontSize; } hud.m_pieceDescription.fontSize = Mathf.Max(_defaultTooltipFontSize * 1.15f, _defaultTooltipFontSize + 1f); } } public static void Initialize(ManualLogSource logger) { _logger = logger; } public static void Update() { EnsureRegistered(); AdminTerrainInfinityHammerCompat.Update(); UpdatePlacementSizingInput(); } public static void LateUpdate() { UpdatePlacementPreview(); } public static void InitializeCompat(Harmony harmony) { AdminTerrainInfinityHammerCompat.Initialize(_logger, harmony); } public static void Shutdown() { if (Object.op_Implicit((Object)(object)_prefab)) { Object.Destroy((Object)(object)_prefab); } if (Object.op_Implicit((Object)(object)_slopePrefab)) { Object.Destroy((Object)(object)_slopePrefab); } if (Object.op_Implicit((Object)(object)_paintPrefab)) { Object.Destroy((Object)(object)_paintPrefab); } if (Object.op_Implicit((Object)(object)_resetPrefab)) { Object.Destroy((Object)(object)_resetPrefab); } if (Object.op_Implicit((Object)(object)_paintResetPrefab)) { Object.Destroy((Object)(object)_paintResetPrefab); } if (Object.op_Implicit((Object)(object)_previewRoot)) { Object.Destroy((Object)(object)_previewRoot); } _prefab = null; _slopePrefab = null; _paintPrefab = null; _resetPrefab = null; _paintResetPrefab = null; _previewRoot = null; _areaLine = null; _lineMaterial = null; _registeredScene = null; AdminTerrainInfinityHammerCompat.Shutdown(); _hasPendingSlopeStart = false; _pendingSlopeStartFrame = 0; _lastPreviewKind = PreviewKind.None; } public static bool IsProxyPiece(Piece piece) { if (Object.op_Implicit((Object)(object)piece)) { return IsProxyPrefabName(Utils.GetPrefabName(((Component)piece).gameObject)); } return false; } public static bool IsProxyObject(GameObject obj) { if (Object.op_Implicit((Object)(object)obj)) { return IsProxyPrefabName(Utils.GetPrefabName(obj)); } return false; } private static bool IsSlopeProxyObject(GameObject obj) { if (Object.op_Implicit((Object)(object)obj)) { return string.Equals(Utils.GetPrefabName(obj), "ZoneSaviorTerrainProxySlope", StringComparison.Ordinal); } return false; } private static bool IsPaintProxyObject(GameObject obj) { if (Object.op_Implicit((Object)(object)obj)) { return string.Equals(Utils.GetPrefabName(obj), "ZoneSaviorPaintProxy", StringComparison.Ordinal); } return false; } private static bool IsResetProxyObject(GameObject obj) { if (Object.op_Implicit((Object)(object)obj)) { return string.Equals(Utils.GetPrefabName(obj), "ZoneSaviorTerrainReset", StringComparison.Ordinal); } return false; } private static bool IsPaintResetProxyObject(GameObject obj) { if (Object.op_Implicit((Object)(object)obj)) { return string.Equals(Utils.GetPrefabName(obj), "ZoneSaviorPaintReset", StringComparison.Ordinal); } return false; } private static bool IsProxyPrefabName(string prefabName) { if (!string.Equals(prefabName, "ZoneSaviorTerrainProxy", StringComparison.Ordinal) && !string.Equals(prefabName, "ZoneSaviorTerrainProxySlope", StringComparison.Ordinal) && !string.Equals(prefabName, "ZoneSaviorPaintProxy", StringComparison.Ordinal) && !string.Equals(prefabName, "ZoneSaviorTerrainReset", StringComparison.Ordinal)) { return string.Equals(prefabName, "ZoneSaviorPaintReset", StringComparison.Ordinal); } return true; } public static void ConfigurePlacedProxy(ZoneSaviorTerrainProxy proxy) { //IL_00dc: 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_00ad: 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) EnsurePlacedProxyInitialized(proxy); ZNetView component = ((Component)proxy).GetComponent(); ZDO val = (Object.op_Implicit((Object)(object)component) ? component.GetZDO() : null); if (val == null) { ShowMessage("ZoneSavior terrain proxy could not initialize ZDO data."); return; } if (!IsAdmin()) { ShowMessage("ZoneSavior terrain proxy is admin only."); proxy.QueueDestroy(); return; } bool flag = !HasStoredSettings(val); if (flag && IsResetProxyObject(((Component)proxy).gameObject)) { HandleResetPlacement(proxy, component); return; } if (flag && IsPaintResetProxyObject(((Component)proxy).gameObject)) { HandlePaintResetPlacement(proxy, component); return; } if (flag) { if (IsSlopeProxyObject(((Component)proxy).gameObject)) { if (!ConfigureNewSlopeProxy(proxy, val)) { return; } } else if (IsPaintProxyObject(((Component)proxy).gameObject)) { val.SetPosition(((Component)proxy).transform.position); val.SetRotation(((Component)proxy).transform.rotation); WriteSettings(val, CurrentPaintSettings()); } else { val.SetPosition(((Component)proxy).transform.position); val.SetRotation(((Component)proxy).transform.rotation); WriteCurrentSettings(val); } } val.Set(AppliedHash, false); ApplyStoredSettings(proxy, force: true, notify: true); } private static void HandleResetPlacement(ZoneSaviorTerrainProxy proxy, ZNetView? placedView) { //IL_0006: 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_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_0026: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)proxy).transform.position; Quaternion rotation = ((Component)proxy).transform.rotation; TerrainProxySettings settings = CurrentSettings(); int num = ResetTerrain(position, rotation, settings); int terrainCompilers; int num2 = ResetIntersectingProxyObjects(position, rotation, settings, placedView, out terrainCompilers); num += terrainCompilers; ShowMessage($"ZoneSavior terrain reset {num} terrain compiler(s), removed {num2} terrain proxy object(s)."); proxy.QueueDestroy(); } private static void HandlePaintResetPlacement(ZoneSaviorTerrainProxy proxy, ZNetView? placedView) { //IL_0006: 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_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_0026: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)proxy).transform.position; Quaternion rotation = ((Component)proxy).transform.rotation; TerrainProxySettings settings = CurrentPaintSettings(); int num = ResetTerrain(position, rotation, settings); int terrainCompilers; int num2 = ResetIntersectingPaintProxyObjects(position, rotation, settings, placedView, out terrainCompilers); num += terrainCompilers; ShowMessage($"ZoneSavior paint reset {num} terrain compiler(s), removed {num2} paint proxy object(s)."); proxy.QueueDestroy(); } public static void ApplyLoadedProxy(ZoneSaviorTerrainProxy proxy) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) ZNetView component = ((Component)proxy).GetComponent(); ZDO val = (Object.op_Implicit((Object)(object)component) ? component.GetZDO() : null); if (val != null && HasStoredSettings(val)) { bool @bool = val.GetBool(AppliedHash, false); if (!@bool || !HasAppliedAtPosition(val, ((Component)proxy).transform.position)) { ApplyStoredSettings(proxy, @bool); } } } public static bool TryCreateLoadedProxy(ZDO zdo, ref GameObject result) { //IL_002a: 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_006d: Unknown result type (might be due to invalid IL or missing references) if (zdo == null) { return false; } GameObject registeredPrefab = GetRegisteredPrefab(zdo.GetPrefab()); if (!Object.op_Implicit((Object)(object)registeredPrefab)) { return false; } ZNetView.m_useInitZDO = true; ZNetView.m_initZDO = zdo; try { result = Object.Instantiate(registeredPrefab, zdo.GetPosition(), zdo.GetRotation()); if (Object.op_Implicit((Object)(object)result) && !result.activeSelf) { result.SetActive(true); } if (ZNetView.m_initZDO != null) { ManualLogSource logger = _logger; if (logger != null) { logger.LogWarning((object)$"ZoneSavior terrain object failed to consume ZDO {zdo.m_uid}."); } } return (Object)(object)result != (Object)null; } finally { ZNetView.m_initZDO = null; ZNetView.m_useInitZDO = false; } } public static void PrepareInfinityHammerPlaced(GameObject obj) { if (IsProxyObject(obj)) { ZoneSaviorTerrainProxy component = obj.GetComponent(); if (Object.op_Implicit((Object)(object)component)) { EnsurePlacedProxyInitialized(component); } } } public static bool ShouldRunInfinityHammerNoCreator(ZNetView view, Piece piece) { if (!Object.op_Implicit((Object)(object)view) || !Object.op_Implicit((Object)(object)piece)) { return false; } if (view.GetZDO() != null) { return true; } PrepareInfinityHammerPlaced(((Component)piece).gameObject); return view.GetZDO() != null; } internal static void ApplyInfinityHammerPlaced(GameObject obj) { if (IsProxyObject(obj)) { ZoneSaviorTerrainProxy component = obj.GetComponent(); if (Object.op_Implicit((Object)(object)component)) { EnsurePlacedProxyInitialized(component); ApplyLoadedProxy(component); } } } private static TerrainProxySettings CurrentSettings() { return new TerrainProxySettings(TerrainProxyMode.Circle, CurrentCircleRadius(), AdminTerrainToolConfig.SlopeWidth, AdminTerrainToolConfig.SlopeWidth, 0f, CurrentTerrainEdgeSoftness(), AdminTerrainPaintType.Grass); } private static TerrainProxySettings CurrentPaintSettings() { return new TerrainProxySettings(TerrainProxyMode.Paint, CurrentCircleRadius(), AdminTerrainToolConfig.SlopeWidth, AdminTerrainToolConfig.SlopeWidth, 0f, 0f, CurrentPaintType()); } private static void EnsurePlacedProxyInitialized(ZoneSaviorTerrainProxy proxy) { EnsurePlacedObjectInitialized(((Component)proxy).gameObject); } private static void EnsurePlacedObjectInitialized(GameObject obj) { if (!obj.activeSelf) { obj.SetActive(true); } Piece component = obj.GetComponent(); ZNetView component2 = obj.GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component2 != (Object)null && (Object)(object)component.m_nview == (Object)null) { component.m_nview = component2; } } private static int ResetIntersectingProxyObjects(Vector3 position, Quaternion rotation, TerrainProxySettings settings, ZNetView? placedView, out int terrainCompilers) { //IL_007c: 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) //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_0090: 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_0093: 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_00a5: 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) terrainCompilers = 0; ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance == (Object)null) { return 0; } List list = instance.m_instances.Values.ToList(); int num = 0; foreach (ZNetView item in list) { if (!Object.op_Implicit((Object)(object)item) || (Object)(object)item == (Object)(object)placedView || !IsProxyObject(((Component)item).gameObject)) { continue; } ZDO zDO = item.GetZDO(); if (zDO != null && HasStoredSettings(zDO)) { TerrainProxySettings terrainProxySettings = ReadSettings(zDO); Vector3 position2 = ((Component)item).transform.position; Quaternion rotation2 = ((Component)item).transform.rotation; if (FootprintsIntersect(position, rotation, settings, position2, rotation2, terrainProxySettings)) { terrainCompilers += ResetTerrain(position2, rotation2, terrainProxySettings); DestroyProxy(item); num++; } } } return num; } private static int ResetIntersectingPaintProxyObjects(Vector3 position, Quaternion rotation, TerrainProxySettings settings, ZNetView? placedView, out int terrainCompilers) { //IL_007c: 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) //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_0090: 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_0093: 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_00a5: 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) terrainCompilers = 0; ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance == (Object)null) { return 0; } List list = instance.m_instances.Values.ToList(); int num = 0; foreach (ZNetView item in list) { if (!Object.op_Implicit((Object)(object)item) || (Object)(object)item == (Object)(object)placedView || !IsPaintProxyObject(((Component)item).gameObject)) { continue; } ZDO zDO = item.GetZDO(); if (zDO != null && HasStoredSettings(zDO)) { TerrainProxySettings terrainProxySettings = ReadSettings(zDO); Vector3 position2 = ((Component)item).transform.position; Quaternion rotation2 = ((Component)item).transform.rotation; if (FootprintsIntersect(position, rotation, settings, position2, rotation2, terrainProxySettings)) { terrainCompilers += ResetTerrain(position2, rotation2, terrainProxySettings); DestroyProxy(item); num++; } } } return num; } private static bool FootprintsIntersect(Vector3 aPosition, Quaternion aRotation, TerrainProxySettings aSettings, Vector3 bPosition, Quaternion bRotation, TerrainProxySettings bSettings) { //IL_0015: 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_001b: 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_003e: 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_0047: 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_007f: 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_008f: 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_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) bool hasCircleFootprint = aSettings.HasCircleFootprint; bool hasCircleFootprint2 = bSettings.HasCircleFootprint; if (hasCircleFootprint && hasCircleFootprint2) { return Vector2.Distance(ToXZ(aPosition), ToXZ(bPosition)) <= aSettings.Radius + bSettings.Radius; } if (hasCircleFootprint) { return CircleIntersectsRect(aPosition, aSettings.Radius, bPosition, bRotation, bSettings.Width, bSettings.Length); } if (hasCircleFootprint2) { return CircleIntersectsRect(bPosition, bSettings.Radius, aPosition, aRotation, aSettings.Width, aSettings.Length); } return RectIntersectsRect(aPosition, aRotation, aSettings.Width, aSettings.Length, bPosition, bRotation, bSettings.Width, bSettings.Length); } private static bool CircleIntersectsRect(Vector3 circlePosition, float radius, Vector3 rectPosition, Quaternion rectRotation, float rectWidth, float rectLength) { //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_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_0012: 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_004a: Unknown result type (might be due to invalid IL or missing references) Vector3 val = InverseYaw(rectRotation) * (circlePosition - rectPosition); float num = Mathf.Clamp(val.x, rectWidth * -0.5f, rectWidth * 0.5f); float num2 = Mathf.Clamp(val.z, rectLength * -0.5f, rectLength * 0.5f); float num3 = val.x - num; float num4 = val.z - num2; return num3 * num3 + num4 * num4 <= radius * radius; } private static bool RectIntersectsRect(Vector3 aPosition, Quaternion aRotation, float aWidth, float aLength, Vector3 bPosition, Quaternion bRotation, float bWidth, float bLength) { //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_0007: 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_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) //IL_0024: 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_002b: 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_002f: 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) //IL_003f: 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_005c: 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_005f: 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_006f: 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_0089: 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_008c: 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_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: 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_00c9: 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) Vector2 val = ToXZ(aPosition); Vector2 val2 = ToXZ(bPosition); GetRectAxes(aRotation, out var xAxis, out var zAxis); GetRectAxes(bRotation, out var xAxis2, out var zAxis2); Vector2 centerDelta = val2 - val; if (OverlapsOnAxis(xAxis, centerDelta, xAxis, zAxis, aWidth * 0.5f, aLength * 0.5f, xAxis2, zAxis2, bWidth * 0.5f, bLength * 0.5f) && OverlapsOnAxis(zAxis, centerDelta, xAxis, zAxis, aWidth * 0.5f, aLength * 0.5f, xAxis2, zAxis2, bWidth * 0.5f, bLength * 0.5f) && OverlapsOnAxis(xAxis2, centerDelta, xAxis, zAxis, aWidth * 0.5f, aLength * 0.5f, xAxis2, zAxis2, bWidth * 0.5f, bLength * 0.5f)) { return OverlapsOnAxis(zAxis2, centerDelta, xAxis, zAxis, aWidth * 0.5f, aLength * 0.5f, xAxis2, zAxis2, bWidth * 0.5f, bLength * 0.5f); } return false; } private static bool OverlapsOnAxis(Vector2 axis, Vector2 centerDelta, Vector2 aX, Vector2 aZ, float aHalfWidth, float aHalfLength, Vector2 bX, Vector2 bZ, float bHalfWidth, float bHalfLength) { //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_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_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_002e: 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_003e: 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) float num = Mathf.Abs(Vector2.Dot(centerDelta, axis)); float num2 = aHalfWidth * Mathf.Abs(Vector2.Dot(aX, axis)) + aHalfLength * Mathf.Abs(Vector2.Dot(aZ, axis)); float num3 = bHalfWidth * Mathf.Abs(Vector2.Dot(bX, axis)) + bHalfLength * Mathf.Abs(Vector2.Dot(bZ, axis)); return num <= num2 + num3; } private static void GetRectAxes(Quaternion rotation, out Vector2 xAxis, out Vector2 zAxis) { //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_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_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_0017: 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_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_0024: 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_002c: 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_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_0040: Unknown result type (might be due to invalid IL or missing references) Quaternion val = Yaw(rotation); Vector3 value = val * Vector3.right; Vector3 value2 = val * Vector3.forward; Vector2 val2 = ToXZ(value); xAxis = ((Vector2)(ref val2)).normalized; val2 = ToXZ(value2); zAxis = ((Vector2)(ref val2)).normalized; } private static Quaternion InverseYaw(Quaternion rotation) { //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) return Quaternion.Inverse(Yaw(rotation)); } private static Quaternion Yaw(Quaternion rotation) { //IL_0007: 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) return Quaternion.Euler(0f, ((Quaternion)(ref rotation)).eulerAngles.y, 0f); } private static Vector2 ToXZ(Vector3 value) { //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) return new Vector2(value.x, value.z); } private static bool ShouldShowTo(Player player) { if ((Object)(object)player != (Object)null && (Object)(object)player == (Object)(object)Player.m_localPlayer && IsDebugModeEnabled()) { return IsAdmin(); } return false; } private static bool IsDebugModeEnabled() { return Player.m_debugMode; } private static bool IsAdmin() { if ((Object)(object)ZNet.instance == (Object)null) { return false; } if (!ZNet.instance.LocalPlayerIsAdminOrHost()) { return IsCheatsEnabled(); } return true; } private static bool IsCheatsEnabled() { if ((Object)(object)Console.instance != (Object)null) { return ((Terminal)Console.instance).IsCheatsEnabled(); } return false; } private static bool HasStoredSettings(ZDO zdo) { return zdo.GetInt(VersionHash, 0) == 11; } private static void WriteCurrentSettings(ZDO zdo) { WriteSettings(zdo, CurrentSettings()); } private static TerrainProxySettings SlopeSettings(SlopePlacement placement) { return new TerrainProxySettings(TerrainProxyMode.Slope, CurrentCircleRadius(), placement.Width, placement.Length, placement.HeightDelta, 0f, AdminTerrainPaintType.Grass); } private static void WriteSettings(ZDO zdo, TerrainProxySettings settings) { zdo.Set(VersionHash, 11, false); zdo.Set(ModeHash, (int)settings.Mode, false); zdo.Set(RadiusHash, settings.Radius); zdo.Set(WidthHash, settings.Width); zdo.Set(LengthHash, settings.Length); zdo.Set(SlopeHeightDeltaHash, settings.SlopeHeightDelta); zdo.Set(TerrainEdgeSoftnessHash, settings.TerrainEdgeSoftness); zdo.Set(PaintTypeHash, (int)settings.PaintType, false); } private static TerrainProxySettings ReadSettings(ZDO zdo) { int num = ((zdo.GetPrefab() == SlopePrefabHash) ? 1 : ((zdo.GetPrefab() == PaintPrefabHash) ? 2 : 0)); return new TerrainProxySettings((TerrainProxyMode)zdo.GetInt(ModeHash, num), Mathf.Clamp(zdo.GetFloat(RadiusHash, 8f), 0.5f, 128f), Mathf.Clamp(zdo.GetFloat(WidthHash, 8f), 0.5f, 256f), Mathf.Clamp(zdo.GetFloat(LengthHash, 8f), 0.5f, 256f), Mathf.Clamp(zdo.GetFloat(SlopeHeightDeltaHash, 0f), -1024f, 1024f), Mathf.Clamp01(zdo.GetFloat(TerrainEdgeSoftnessHash, 0f)), (AdminTerrainPaintType)zdo.GetInt(PaintTypeHash, 1)); } internal static void DestroyProxy(ZNetView nview) { if (Object.op_Implicit((Object)(object)nview) && nview.IsValid()) { if (!nview.IsOwner()) { nview.ClaimOwnership(); } ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance != (Object)null) { instance.Destroy(((Component)nview).gameObject); } else { nview.Destroy(); } } } public static float GetTerrainCompHeightClampLimit() { return 1024f; } private static bool HasAppliedAtPosition(ZDO zdo, Vector3 position) { //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_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) Vector3 val = default(Vector3); if (!zdo.GetVec3(AppliedPositionHash, ref val)) { return false; } if (Utils.DistanceXZ(val, position) < 0.1f) { return Mathf.Abs(val.y - position.y) < 0.1f; } return false; } private static void ReportTerrainResult(string message, bool notify) { if (notify) { ShowMessage(message); return; } ManualLogSource logger = _logger; if (logger != null) { logger.LogDebug((object)message); } } private static void ShowMessage(string message) { ManualLogSource logger = _logger; if (logger != null) { logger.LogInfo((object)message); } Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)1, message, 0, (Sprite)null); } } private static int Hash(string key) { return StringExtensionMethods.GetStableHashCode("sighsorry.ZoneSavior.terrain_proxy." + key); } } [HarmonyPatch(typeof(Hud), "SetupPieceInfo")] internal static class AdminTerrainToolTooltipPatch { private static void Prefix(Hud __instance, Piece piece) { AdminTerrainTool.PreparePieceTooltip(__instance, piece); } private static void Postfix(Hud __instance, Piece piece) { AdminTerrainTool.ApplyPieceTooltipStyle(__instance, piece); } } internal sealed class ZoneSaviorTerrainProxy : MonoBehaviour, IPlaced { [CompilerGenerated] private sealed class d__4 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public ZoneSaviorTerrainProxy <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__4(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; ZoneSaviorTerrainProxy zoneSaviorTerrainProxy = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: { <>1__state = -1; ZNetView component = ((Component)zoneSaviorTerrainProxy).GetComponent(); if (Object.op_Implicit((Object)(object)component)) { AdminTerrainTool.DestroyProxy(component); } 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 Coroutine? _destroyRoutine; private void Awake() { AdminTerrainTool.ApplyLoadedProxy(this); } public void OnPlaced() { AdminTerrainTool.ConfigurePlacedProxy(this); } public void QueueDestroy() { if (_destroyRoutine == null) { _destroyRoutine = ((MonoBehaviour)this).StartCoroutine(DestroyNextFrame()); } } [IteratorStateMachine(typeof(d__4))] private IEnumerator DestroyNextFrame() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__4(0) { <>4__this = this }; } } [HarmonyPatch(typeof(ZNetScene), "Awake")] internal static class AdminTerrainToolScenePatch { private static void Postfix() { AdminTerrainTool.Update(); } } [HarmonyPatch(typeof(ZNetScene), "CreateObject")] internal static class AdminTerrainToolCreateObjectPatch { private static bool Prefix(ZDO zdo, ref GameObject __result) { return !AdminTerrainTool.TryCreateLoadedProxy(zdo, ref __result); } } [HarmonyPatch(typeof(PieceTable), "UpdateAvailable")] internal static class AdminTerrainToolPieceTablePatch { private static void Postfix(PieceTable __instance, Player player) { AdminTerrainTool.AddToAvailablePieces(__instance, player); } } [HarmonyPatch(typeof(Player), "UpdateKnownRecipesList")] internal static class AdminTerrainToolKnownRecipesPatch { [HarmonyPriority(800)] private static void Prefix(Player __instance) { AdminTerrainTool.SanitizeKnownRecipePieceTables(__instance); } } [HarmonyPatch(typeof(Player), "UpdatePlacementGhost")] internal static class AdminTerrainToolPlacementGhostPatch { [HarmonyPriority(0)] private static void Postfix(Player __instance) { AdminTerrainTool.PreparePlacementGhost(__instance); } } [HarmonyPatch(typeof(Player), "UpdatePlacement")] internal static class AdminTerrainToolPlacementWheelPatch { [CompilerGenerated] private sealed class d__1 : IEnumerable, IEnumerable, IEnumerator, IDisposable, IEnumerator { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; private IEnumerable instructions; public IEnumerable <>3__instructions; private MethodInfo original; public MethodInfo <>3__original; private MethodInfo replacement; public MethodInfo <>3__replacement; private IEnumerator <>7__wrap1; CodeInstruction IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__1(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <>7__wrap1 = null; <>1__state = -2; } private bool MoveNext() { try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>7__wrap1 = instructions.GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; break; } if (<>7__wrap1.MoveNext()) { CodeInstruction current = <>7__wrap1.Current; if (CodeInstructionExtensions.Calls(current, original)) { current.operand = replacement; } <>2__current = current; <>1__state = 1; return true; } <>m__Finally1(); <>7__wrap1 = null; 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__wrap1 != null) { <>7__wrap1.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { d__1 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__1(0); } d__.instructions = <>3__instructions; d__.original = <>3__original; d__.replacement = <>3__replacement; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } private static IEnumerable Transpiler(IEnumerable instructions) { MethodInfo methodInfo = AccessTools.Method(typeof(ZInput), "GetMouseScrollWheel", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(AdminTerrainTool), "GetPlacementMouseScrollWheel", (Type[])null, (Type[])null); if (methodInfo == null || methodInfo2 == null) { return instructions; } return ReplaceMouseScrollWheel(instructions, methodInfo, methodInfo2); } [IteratorStateMachine(typeof(d__1))] private static IEnumerable ReplaceMouseScrollWheel(IEnumerable instructions, MethodInfo original, MethodInfo replacement) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__1(-2) { <>3__instructions = instructions, <>3__original = original, <>3__replacement = replacement }; } } [HarmonyPatch(typeof(TerrainComp), "ApplyToHeightmap")] internal static class AdminTerrainToolTerrainCompPatch { [CompilerGenerated] private sealed class d__1 : IEnumerable, IEnumerable, IEnumerator, IDisposable, IEnumerator { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; private IEnumerable instructions; public IEnumerable <>3__instructions; private MethodInfo limit; public MethodInfo <>3__limit; private IEnumerator <>7__wrap1; CodeInstruction IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__1(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <>7__wrap1 = null; <>1__state = -2; } private bool MoveNext() { try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>7__wrap1 = instructions.GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; break; } if (<>7__wrap1.MoveNext()) { CodeInstruction current = <>7__wrap1.Current; if (current.opcode == OpCodes.Ldc_R4 && current.operand is float num && Math.Abs(num - 8f) < 0.001f) { current.opcode = OpCodes.Call; current.operand = limit; } <>2__current = current; <>1__state = 1; return true; } <>m__Finally1(); <>7__wrap1 = null; 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__wrap1 != null) { <>7__wrap1.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { d__1 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__1(0); } d__.instructions = <>3__instructions; d__.limit = <>3__limit; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } private static IEnumerable Transpiler(IEnumerable instructions) { MethodInfo methodInfo = AccessTools.Method(typeof(AdminTerrainTool), "GetTerrainCompHeightClampLimit", (Type[])null, (Type[])null); if (methodInfo == null) { return instructions; } return ReplaceVanillaTerrainCompClamp(instructions, methodInfo); } [IteratorStateMachine(typeof(d__1))] private static IEnumerable ReplaceVanillaTerrainCompClamp(IEnumerable instructions, MethodInfo limit) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__1(-2) { <>3__instructions = instructions, <>3__limit = limit }; } } internal static class ZoneSaviorSteamIds { private const string SteamPrefix = "steam:"; public static string Normalize(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; } public static bool IsBareSteamId64(string value) { string text = value?.Trim() ?? ""; if (text.Length == 17) { return text.All(char.IsDigit); } return false; } public static bool LooksLikeSteamId(string value) { return !string.IsNullOrWhiteSpace(Normalize(value)); } public static bool TryNormalizePlatformId(string platformId, out string steamId) { steamId = ""; if (string.IsNullOrWhiteSpace(platformId) || !platformId.StartsWith("steam:", StringComparison.OrdinalIgnoreCase)) { return false; } steamId = Normalize(platformId); return !string.IsNullOrWhiteSpace(steamId); } } internal static class ZoneSaviorPaths { public 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; } public static string SanitizeTagToken(string value, int maxLength = 32) { if (string.IsNullOrWhiteSpace(value)) { return "unknown"; } char[] invalidChars = Path.GetInvalidFileNameChars(); string text = new string(value.Select(delegate(char character) { if (invalidChars.Contains(character) || 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 > maxLength) { text = text.Substring(0, maxLength).Trim(new char[1] { '_' }); } if (!string.IsNullOrWhiteSpace(text)) { return text; } return "unknown"; } } internal static class ZoneSaviorZones { public 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 }; } public 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); } } 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()) { TrackPeer(peer, utcNow, requireReady: true); } } internal static bool TryGetPeerActivity(ZNetPeer peer, out string platformId, out long playerId, out string name) { return TryGetPeerActivity(peer, requireReady: true, out platformId, out playerId, out name); } internal static void TrackPeer(ZRpc rpc) { if (IsServerReady()) { TrackPeer(ZNet.instance.GetPeer(rpc), DateTime.UtcNow, requireReady: false); } } private static void TrackPeer(ZNetPeer peer, DateTime utcNow, bool requireReady) { try { if (TryGetPeerActivity(peer, requireReady, out string platformId, out long playerId, out string name)) { AutoArchiveStore.RecordPlayerSeen(platformId, playerId, name, utcNow); } } catch (Exception ex) { _logger.LogWarning((object)("Failed to update peer activity: " + ex.Message)); } } private static bool TryGetPeerActivity(ZNetPeer peer, bool requireReady, out string platformId, out long playerId, out string name) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) platformId = ""; playerId = 0L; name = ""; if (peer == null || (requireReady && !peer.IsReady())) { return false; } playerId = TryReadPlayerId(peer.m_characterID); platformId = BuildPlatformId(peer, playerId); name = peer.m_playerName; if (!string.IsNullOrWhiteSpace(platformId)) { if (!requireReady && playerId == 0L) { return !string.IsNullOrWhiteSpace(name); } return true; } return false; } 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, long playerId) { return ZonePlayerIdentity.ResolvePeerPlatformId(peer, playerId); } 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; } } [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] internal static class PlayerActivityPeerInfoPatch { private static void Postfix(ZRpc rpc) { PlayerActivityTracker.TrackPeer(rpc); } } [HarmonyPatch(typeof(ZNet), "RPC_CharacterID")] internal static class PlayerActivityCharacterIdPatch { private static void Postfix(ZRpc rpc) { PlayerActivityTracker.TrackPeer(rpc); } } 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() && !ZoneSaviorInputBlockers.IsTextInputVisible()) { 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 ZoneBundleCommandEndpoint { [CompilerGenerated] private static class <>O { public static ConsoleEvent <0>__HandleSaveZoneCommand; public static ConsoleEvent <1>__HandleLoadZoneCommand; public static Action <2>__RPC_HandleRequest; public static Action <3>__RPC_HandleResult; } private const string RequestRpcName = "sighsorry.ZoneSavior_ZoneBundleRequest"; private const string ResultRpcName = "sighsorry.ZoneSavior_ZoneBundleResult"; private static readonly ZoneRpcRegistrar RpcRegistrar = new ZoneRpcRegistrar(); private static ManualLogSource _logger = null; public static void Initialize(ManualLogSource logger) { //IL_0034: 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_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_0068: 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_005f: Expected O, but got Unknown _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,z) or (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", "tag [restore|source (x,z)] [to (x,z)] [offset=Y] - Loads saved zone bundles.", (ConsoleEvent)obj2, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } public 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) { ZoneBundleCommands.EnsureCommandAllowed(); DispatchRequest(ZoneBundleCommands.ParseRequest(args.ArgsAll, "zs_savezone", requireSingleZone: false, requireTarget: false), args.Context); } private static void HandleLoadZoneCommand(ConsoleEventArgs args) { ZoneBundleCommands.EnsureCommandAllowed(); DispatchRequest(ZoneBundleCommands.ParseLoadRequest(args.ArgsAll), args.Context); } private static void DispatchRequest(ZoneBundleCommandRequest request, Terminal context) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown Terminal context2 = context; if (ZNet.instance.IsServer()) { ZoneBundleCommands.StartRequest(request, delegate(ZoneBundleCommandResult result) { ZoneBundleCommands.ShowResult(result, context2); }, 0L); 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 (!ZoneBundleCommands.IsAuthorizedSender(sender)) { SendResult(sender, ZoneBundleCommandResult.Fail("Admin only.")); return; } ZoneBundleCommands.StartRequest(ZoneBundleSerialization.Deserialize(package.ReadString()), delegate(ZoneBundleCommandResult result) { SendResult(sender, result); }, sender); } 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()) { ZoneBundleCommands.ShowResult(ZoneBundleSerialization.Deserialize(package.ReadString()), (Terminal?)(object)Console.instance); } } } internal static class ZoneBundleCommands { 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 struct ZoneLoadTotals { public int Removed { get; private set; } public int Created { get; private set; } public int TerrainApplied { get; private set; } public void Add(ZoneLoadStats stats, bool terrainApplied) { Removed += stats.Removed; Created += stats.Created; if (terrainApplied) { TerrainApplied++; } } } private readonly struct TerrainPreparationResult { public bool Success { get; } public string Message { get; } private HashSet ClientPreparedZones { get; } public int PreparedZones { get; } public int ChangedZones { get; } private TerrainPreparationResult(bool success, string message, HashSet clientPreparedZones, int preparedZones, int changedZones) { Success = success; Message = message; ClientPreparedZones = clientPreparedZones; PreparedZones = preparedZones; ChangedZones = changedZones; } public bool WasClientPrepared(Vector2i zone) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return ClientPreparedZones.Contains(zone); } public string Describe() { if (ClientPreparedZones.Count <= 0) { return ""; } return $", terrainBy: witness-client {ChangedZones}/{PreparedZones} prepared"; } public static TerrainPreparationResult Completed(bool clientAssisted, int preparedZones, int changedZones) { return new TerrainPreparationResult(success: true, "", clientAssisted ? new HashSet() : new HashSet(), preparedZones, changedZones); } public static TerrainPreparationResult Completed(HashSet clientPreparedZones, int preparedZones, int changedZones) { return new TerrainPreparationResult(success: true, "", clientPreparedZones, preparedZones, changedZones); } public static TerrainPreparationResult Failed(string message) { return new TerrainPreparationResult(success: false, message, new HashSet(), 0, 0); } } private readonly struct TerrainWitnessCandidate { public long PeerId { get; } public float DistanceSqr { get; } public bool Preferred { get; } public TerrainWitnessCandidate(long peerId, float distanceSqr, bool preferred) { PeerId = peerId; DistanceSqr = distanceSqr; Preferred = preferred; } } 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; } } private readonly struct ResetVerificationResult { public int Removed { get; } public int RemainingWearNTear { get; } public ResetVerificationResult(int removed, int remainingWearNTear) { Removed = removed; RemainingWearNTear = remainingWearNTear; } } private sealed class ArchiveSaveProgress { public int BundleIndex; public int TotalEntries; public int TotalMonsters; public int TerrainLoaded; public int TerrainCaptured; } private enum SaveEntryKind { Static, Monster } [CompilerGenerated] private sealed class <>c__DisplayClass101_0 { public bool requiresTerrainApply; internal void b__0(bool value) { requiresTerrainApply = value; } } [CompilerGenerated] private sealed class <>c__DisplayClass104_0 { public TerrainPlacementContext context; internal void b__1(TerrainPlacementContext? value) { context = value; } } [CompilerGenerated] private sealed class <>c__DisplayClass108_0 { public TerrainPlacementContext terrainContext; public TerrainPreparationResult terrainPreparation; public string prepareError; public ZoneLoadTotals totals; internal void b__0(TerrainPlacementContext? context, TerrainPreparationResult preparation, string error) { terrainContext = context; terrainPreparation = preparation; prepareError = error; } internal void b__1(ZoneLoadTotals value) { totals = value; } } [CompilerGenerated] private sealed class <>c__DisplayClass109_0 { public string readyError; public TerrainPlacementContext terrainContext; public string contextError; public ZoneLoadTotals totals; internal void b__0(string value) { readyError = value; } internal void b__1(TerrainPlacementContext? context, string error) { terrainContext = context; contextError = error; } internal void b__2(ZoneLoadTotals value) { totals = value; } } [CompilerGenerated] private sealed class <>c__DisplayClass110_0 { public string readyError; public TerrainPlacementContext terrainContext; public string contextError; public TerrainPreparationResult terrainPreparation; internal void b__0(string value) { readyError = value; } internal void b__1(TerrainPlacementContext? context, string error) { terrainContext = context; contextError = error; } internal void b__2(TerrainPreparationResult value) { terrainPreparation = value; } } [CompilerGenerated] private sealed class <>c__DisplayClass111_0 { public ZoneLoadStats stats; internal void b__0(ZoneLoadStats value) { stats = value; } } [CompilerGenerated] private sealed class <>c__DisplayClass112_0 { public ZoneBundleClientTerrainApplyResponse response; public Action <>9__1; internal void b__1(ZoneBundleClientTerrainApplyResponse? value) { response = value; } } [CompilerGenerated] private sealed class <>c__DisplayClass127_0 { public bool hasWearNTearEntries; internal void b__0(bool value) { hasWearNTearEntries = value; } } [CompilerGenerated] private sealed class <>c__DisplayClass138_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__DisplayClass141_0 { public ZoneLoadTotals totals; public string restoreError; internal void b__0(ZoneLoadTotals loadTotals, string error) { totals = loadTotals; restoreError = error; } } [CompilerGenerated] private sealed class <>c__DisplayClass144_0 { public int removed; public ResetVerificationResult verification; internal void b__0(int value) { removed = value; } internal void b__1(ResetVerificationResult value) { verification = value; } } [CompilerGenerated] private sealed class <>c__DisplayClass146_0 { public int remainingWearNTear; public int verificationRemoved; internal void b__0(int value) { remainingWearNTear = value; } internal void b__1(int value) { verificationRemoved = value; } internal void b__2(int value) { remainingWearNTear = value; } } [CompilerGenerated] private sealed class <>c__DisplayClass67_0 { public ZoneBundleArchiveResult archiveResult; internal void b__0(ZoneBundleArchiveResult result) { archiveResult = result; } } [CompilerGenerated] private sealed class <>c__DisplayClass68_0 { public ZoneBundleCommandResult result; internal void b__0(ZoneBundleCommandResult value) { result = value; } internal void b__1(ZoneBundleCommandResult value) { result = value; } internal void b__2(ZoneBundleCommandResult value) { result = value; } } [CompilerGenerated] private sealed class <>c__DisplayClass76_0 { public ZoneBundleTerrain.TerrainSourceAnchor sourceAnchor; internal void b__0(ZoneBundleTerrain.TerrainSourceAnchor anchor) { sourceAnchor = anchor; } } [CompilerGenerated] private sealed class <>c__DisplayClass76_1 { public CaptureBundleResult capture; internal void b__1(CaptureBundleResult result) { capture = result; } } [CompilerGenerated] private sealed class <>c__DisplayClass76_2 { public ZoneBundleClientTerrainCaptureResponse terrainResponse; public Action <>9__2; internal void b__2(ZoneBundleClientTerrainCaptureResponse? value) { terrainResponse = value; } } [CompilerGenerated] private sealed class <>c__DisplayClass95_0 { public ZoneLoadTotals totals; public TerrainPreparationResult terrainPreparation; public string loadError; internal void b__0(ZoneLoadTotals loadTotals, TerrainPreparationResult preparation, string error) { totals = loadTotals; terrainPreparation = preparation; loadError = error; } } [CompilerGenerated] private sealed class <>c__DisplayClass97_0 { public ZoneLoadTotals totals; public TerrainPreparationResult terrainPreparation; public string loadError; internal void b__0(ZoneLoadTotals loadTotals, TerrainPreparationResult preparation, string error) { totals = loadTotals; terrainPreparation = preparation; loadError = error; } } [CompilerGenerated] private sealed class d__138 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Vector2i targetZone; private <>c__DisplayClass138_0 <>8__1; public bool applyTerrain; 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 List.Enumerator <>7__wrap4; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__138(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__wrap4 = default(List.Enumerator); <>1__state = -2; } private bool MoveNext() { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0128: 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_00b7: 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) try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass138_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 (applyTerrain && terrainContext != null) { <>2__current = ZoneBundleTerrain.ApplySupportFillAsync(targetZone, bundle.Entries, bundle.TerrainContacts, bundle.TerrainContactsCaptured, terrainContext, delegate(bool result) { <>8__1.terrainApplied = result; }); <>1__state = 3; return true; } goto IL_0113; case 3: <>1__state = -1; goto IL_0113; case 4: { <>1__state = -3; break; } IL_0113: 5__2 = 0; 5__3 = 0; 5__4 = ZoneSystem.GetZonePos(targetZone); <>7__wrap4 = bundle.Entries.GetEnumerator(); <>1__state = -3; break; } while (<>7__wrap4.MoveNext()) { if (TryCreateLoadedZdo(<>7__wrap4.Current, 5__4, bundle, terrainContext, yOffset, out ZDO zdo) && zdo != null) { ZNetScene.instance.CreateObject(zdo); 5__2++; } 5__3++; if (5__3 >= 1000) { 5__3 = 0; <>2__current = null; <>1__state = 4; return true; } } <>m__Finally1(); <>7__wrap4 = 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__wrap4).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__116 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public ZoneBundleClientTerrainApplyRequest request; public long sender; private ZoneBundleClientTerrainApplyResponse 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__116(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__wrap2 = default(List.Enumerator); <>1__state = -2; } private bool MoveNext() { //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_0285: 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_0123: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0142: 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_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_0242: 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; 5__2 = new ZoneBundleClientTerrainApplyResponse { RequestId = request.RequestId, TargetZones = request.TargetZones.Count }; if (request.Context == null) { 5__2.Success = false; 5__2.Message = "Client terrain apply failed: missing terrain context."; SendClientTerrainApplyResponse(sender, 5__2); result = false; } else { if (request.Context.SupportRelativeHeights != null && request.Context.SupportRelativeHeights.Count != 0) { <>7__wrap2 = request.TargetZones.GetEnumerator(); <>1__state = -3; break; } 5__2.Success = false; 5__2.Message = "Client terrain apply failed: terrain context has no support points."; SendClientTerrainApplyResponse(sender, 5__2); result = false; } goto end_IL_0000; case 1: <>1__state = -3; break; } Vector2i val; if (<>7__wrap2.MoveNext()) { val = ToVector2i(<>7__wrap2.Current); try { if (!ZoneBundleTerrain.CanApply(val)) { 5__2.Success = false; 5__2.Message = $"Client target zone ({val.x},{val.y}) is not loaded for terrain overwrite. Move the admin client into the target area and try again."; SendClientTerrainApplyResponse(sender, 5__2); result = false; } else { if (ZoneBundleTerrain.HasApplicableSupportFill(val, Enumerable.Empty(), Enumerable.Empty(), contactsCaptured: false, request.Context)) { goto IL_0242; } 5__2.Success = false; 5__2.Message = $"Client target zone ({val.x},{val.y}) has no applicable terrain support points."; SendClientTerrainApplyResponse(sender, 5__2); result = false; } } catch (Exception ex) { 5__2.Success = false; 5__2.Message = $"Client terrain validation failed for zone ({val.x},{val.y}): {ex.Message}"; SendClientTerrainApplyResponse(sender, 5__2); result = false; } goto IL_0305; } <>m__Finally1(); <>7__wrap2 = default(List.Enumerator); 5__2.Success = true; 5__2.Message = $"Client applied terrain support for {request.TargetZones.Count} target zone(s)."; SendClientTerrainApplyResponse(sender, 5__2); result = false; goto end_IL_0000; IL_0242: bool flag; try { flag = ZoneBundleTerrain.ApplySupportFill(val, Enumerable.Empty(), Enumerable.Empty(), contactsCaptured: false, request.Context); } catch (Exception ex2) { 5__2.Success = false; 5__2.Message = $"Client terrain apply failed for zone ({val.x},{val.y}): {ex2.Message}"; SendClientTerrainApplyResponse(sender, 5__2); result = false; goto IL_0305; } if (flag) { 5__2.ChangedZones++; } <>2__current = null; <>1__state = 1; result = true; goto end_IL_0000; IL_0305: <>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__wrap2).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__111 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public IEnumerable work; public TerrainPreparationResult terrainPreparation; public TerrainPlacementContext terrainContext; public float yOffset; private <>c__DisplayClass111_0 <>8__1; public Action onComplete; private ZoneLoadTotals 5__2; private IEnumerator <>7__wrap2; private LoadWorkItem 5__4; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__111(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(); } } <>8__1 = null; <>7__wrap2 = null; 5__4 = default(LoadWorkItem); <>1__state = -2; } private bool MoveNext() { //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0097: 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) try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__2 = default(ZoneLoadTotals); <>7__wrap2 = work.GetEnumerator(); <>1__state = -3; break; case 1: { <>1__state = -3; bool terrainApplied = <>8__1.stats.TerrainApplied || (terrainPreparation.WasClientPrepared(5__4.TargetZone) && RequiresTerrainApply(5__4.Bundle)); 5__2.Add(<>8__1.stats, terrainApplied); <>8__1 = null; 5__4 = default(LoadWorkItem); break; } } if (<>7__wrap2.MoveNext()) { 5__4 = <>7__wrap2.Current; <>8__1 = new <>c__DisplayClass111_0(); <>8__1.stats = default(ZoneLoadStats); bool applyTerrain = !terrainPreparation.WasClientPrepared(5__4.TargetZone); <>2__current = ApplyBundleToZoneAsync(5__4.TargetZone, 5__4.Bundle, terrainContext, yOffset, delegate(ZoneLoadStats value) { <>8__1.stats = value; }, applyTerrain); <>1__state = 1; return true; } <>m__Finally1(); <>7__wrap2 = 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__wrap2 != null) { <>7__wrap2.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__131 : 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__131(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_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: 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) //IL_00e2: 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 list2 = new List(); try { ZDOMan.instance.FindObjects(zone, list2); } catch (Exception ex3) { onComplete(CaptureBundleResult.Failed(ex3.Message)); result = false; break; } 5__6 = 0; 5__7 = 0; 5__8 = 0; <>7__wrap8 = list2.GetEnumerator(); <>1__state = -3; goto IL_017d; } case 1: <>1__state = -3; goto IL_017d; case 2: { <>1__state = -1; try { bool contactsCaptured; List list = ZoneBundleTerrain.CaptureSupportContacts(zone, sourceAnchor.BaseWorldY, 5__4, out contactsCaptured); ZoneBundleTerrainCaptureState terrainCaptureState = GetTerrainCaptureState(contactsCaptured, list.Count); ZoneBundleFile bundle = CreateCapturedBundle(zone, tag, sourceAnchor, 5__3, 5__4, 5__5, list, contactsCaptured, terrainCaptureState); onComplete(CaptureBundleResult.Completed(bundle, 5__4.Count, 5__7, terrainCaptureState)); } catch (Exception ex) { onComplete(CaptureBundleResult.Failed(ex.Message)); } result = false; break; } IL_017d: while (true) { if (<>7__wrap8.MoveNext()) { ZDO current = <>7__wrap8.Current; try { if (TryCreateBundleEntry(current, zone, 5__2, sourceAnchor, 5__3, 5__5, ref 5__6, ref 5__7, out ZoneBundleEntry entry)) { 5__4.Add(entry); } } catch (Exception ex2) { onComplete(CaptureBundleResult.Failed(ex2.Message)); result = false; goto IL_0195; } 5__8++; if (5__8 >= 1000) { 5__8 = 0; <>2__current = null; <>1__state = 1; result = true; break; } continue; } <>m__Finally1(); <>7__wrap8 = default(List.Enumerator); <>2__current = null; <>1__state = 2; result = true; break; IL_0195: <>m__Finally1(); 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__149 : 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__149(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; 5__2 += (TryDestroyOverwritableZdo(current) ? 1 : 0); 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__155 : 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__155(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) 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_016d; IL_016d: 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_014b; } <>m__Finally1(); <>7__wrap5 = default(HashSet.Enumerator); onComplete(5__4); return false; IL_014b: 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_016d; IL_00fb: if (TryCollectResetZoneObject(5__8, zones, 5__2, out ZDO resetObject) && IsResettableZoneObject(resetObject, zones, protectedCharacterIds) && IsCreatorWearNTear(resetObject)) { 5__4++; 5__8 = null; } goto IL_014b; } 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__104 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public IEnumerable work; public Action onComplete; public bool exactSource; private <>c__DisplayClass104_0 <>8__1; public float yOffset; public bool validateTargetTerrain; private List 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__104(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__DisplayClass104_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 = ZoneBundleTerrain.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, validateTargetTerrain); 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__15 : 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__15(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__15 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__15(0); } d__.range = <>3__range; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } [CompilerGenerated] private sealed class d__68 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public ZoneBundleCommandRequest request; public long terrainAssistPeer; public Action onComplete; private <>c__DisplayClass68_0 <>8__1; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__68(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__DisplayClass68_0(); <>8__1.result = ZoneBundleCommandResult.Fail("Load failed before it started."); if (request.Operation == "zs_loadzone") { if (request.RestoreOriginal) { <>2__current = RestoreTagToOriginalZonesAsync(request.Tag, delegate(ZoneBundleCommandResult value) { <>8__1.result = value; }); <>1__state = 1; return true; } if (request.LoadSourceZone) { <>2__current = LoadZoneRequestAsync(request, delegate(ZoneBundleCommandResult value) { <>8__1.result = value; }, terrainAssistPeer); <>1__state = 2; return true; } <>2__current = LoadArchiveManifestAsync(request, delegate(ZoneBundleCommandResult value) { <>8__1.result = value; }, terrainAssistPeer); <>1__state = 3; return true; } <>8__1.result = ExecuteRequest(request); break; case 1: <>1__state = -1; break; case 2: <>1__state = -1; break; case 3: <>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__67 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public ZoneBundleCommandRequest request; public long terrainAssistPeer; private <>c__DisplayClass67_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__67(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__DisplayClass67_0(); <>8__1.archiveResult = null; <>2__current = SaveZonesAsync(EnumerateZones(request.SourceRange), request.Tag, delegate(ZoneBundleArchiveResult result) { <>8__1.archiveResult = result; }, terrainAssistPeer); <>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__128 : 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__128(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__97 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public ZoneBundleCommandRequest request; public Action onComplete; private <>c__DisplayClass97_0 <>8__1; public long terrainAssistPeer; private Vector2i 5__2; private List 5__3; private int 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__97(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(); } } <>8__1 = null; 5__3 = null; <>7__wrap5 = default(List.Enumerator); <>1__state = -2; } private bool MoveNext() { //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: 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_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) bool result; try { ZoneBundleManifest zoneBundleManifest; switch (<>1__state) { default: result = false; break; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass97_0(); try { zoneBundleManifest = ZoneBundleStore.LoadManifest(request.Tag); if (zoneBundleManifest.Bundles.Count == 0) { onComplete(ZoneBundleCommandResult.Fail("Manifest for tag '" + request.Tag + "' contains no zone bundles.")); result = false; break; } 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_0171; } catch (Exception ex) { _logger.LogError((object)$"Zone bundle async archive load failed: {ex}"); onComplete(ZoneBundleCommandResult.Fail(ex.Message)); result = false; } break; case 1: <>1__state = -3; goto IL_0236; case 2: { <>1__state = -1; if (!string.IsNullOrWhiteSpace(<>8__1.loadError)) { onComplete(ZoneBundleCommandResult.Fail(<>8__1.loadError)); result = false; break; } onComplete(ZoneBundleCommandResult.Ok($"Loaded archive '{request.Tag}' as {5__3.Count} manifest zone(s) to target start ({5__2.x},{5__2.y}) " + $"(removed: {<>8__1.totals.Removed}, created: {<>8__1.totals.Created}, terrain: {<>8__1.totals.TerrainApplied}/{5__3.Count}, mode: SupportFill{<>8__1.terrainPreparation.Describe()}, yOffset: {Round(request.YOffset)}).")); result = false; break; } IL_0236: if (<>7__wrap5.MoveNext()) { ZoneBundleManifestEntry current = <>7__wrap5.Current; Vector2i sourceZone = ToVector2i(current.Zone); if (!ZoneBundleStore.TryLoadBundleFromManifestEntry(request.Tag, current, 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(CreateLoadWorkItem(sourceZone, 5__4, 5__5, bundle)); <>2__current = null; <>1__state = 1; result = true; } } else { <>m__Finally1(); <>7__wrap5 = default(List.Enumerator); <>8__1.totals = default(ZoneLoadTotals); <>8__1.terrainPreparation = default(TerrainPreparationResult); <>8__1.loadError = ""; <>2__current = PrepareAndApplyLoadWorkAsync("Zone bundle async archive load failed", request, 5__3, exactSource: false, request.YOffset, terrainAssistPeer, delegate(ZoneLoadTotals loadTotals, TerrainPreparationResult preparation, string error) { <>8__1.totals = loadTotals; <>8__1.terrainPreparation = preparation; <>8__1.loadError = error; }); <>1__state = 2; result = true; } break; IL_0171: 5__3 = new List(); <>7__wrap5 = zoneBundleManifest.Bundles.GetEnumerator(); <>1__state = -3; goto IL_0236; } } 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(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__95 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public ZoneBundleCommandRequest request; public Action onComplete; private <>c__DisplayClass95_0 <>8__1; public long terrainAssistPeer; private Vector2i 5__2; private Vector2i 5__3; private ZoneBundleFile 5__4; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__95(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__1 = null; 5__4 = null; <>1__state = -2; } private bool MoveNext() { //IL_00f8: 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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_009d: 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__DisplayClass95_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; } if (!ZoneBundleStore.TryLoadBundleFromManifestZone(request.Tag, 5__2, 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; List work = new List(1) { new LoadWorkItem(5__3, 5__4) }; <>8__1.totals = default(ZoneLoadTotals); <>8__1.terrainPreparation = default(TerrainPreparationResult); <>8__1.loadError = ""; <>2__current = PrepareAndApplyLoadWorkAsync("Zone bundle async load failed", request, work, exactSource: false, request.YOffset, terrainAssistPeer, delegate(ZoneLoadTotals loadTotals, TerrainPreparationResult preparation, string error) { <>8__1.totals = loadTotals; <>8__1.terrainPreparation = preparation; <>8__1.loadError = error; }); <>1__state = 2; return true; } case 2: <>1__state = -1; if (!string.IsNullOrWhiteSpace(<>8__1.loadError)) { onComplete(ZoneBundleCommandResult.Fail(<>8__1.loadError)); return false; } 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{3}, yOffset: {4}).", <>8__1.totals.Removed, <>8__1.totals.Created, (<>8__1.totals.TerrainApplied > 0) ? "yes" : "no", <>8__1.terrainPreparation.Describe(), 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__73 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public ZoneBundleCommandRequest request; public Action onComplete; public long terrainAssistPeer; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__73(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; <>2__current = LoadSingleZoneAsync(request, onComplete, terrainAssistPeer); <>1__state = 1; return true; case 1: <>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(); } } [CompilerGenerated] private sealed class d__108 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string failurePrefix; public ZoneBundleCommandRequest request; public IReadOnlyCollection work; public bool exactSource; public float yOffset; public long terrainAssistPeer; private <>c__DisplayClass108_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__108(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__DisplayClass108_0(); <>8__1.terrainContext = null; <>8__1.terrainPreparation = default(TerrainPreparationResult); <>8__1.prepareError = ""; <>2__current = PrepareLoadWorkAsync(failurePrefix, request, work, exactSource, yOffset, terrainAssistPeer, delegate(TerrainPlacementContext? context, TerrainPreparationResult preparation, string error) { <>8__1.terrainContext = context; <>8__1.terrainPreparation = preparation; <>8__1.prepareError = error; }); <>1__state = 1; return true; case 1: <>1__state = -1; if (!string.IsNullOrWhiteSpace(<>8__1.prepareError)) { onComplete(default(ZoneLoadTotals), <>8__1.terrainPreparation, <>8__1.prepareError); return false; } <>8__1.totals = default(ZoneLoadTotals); <>2__current = ApplyLoadWorkAsync(work, <>8__1.terrainContext, yOffset, <>8__1.terrainPreparation, delegate(ZoneLoadTotals value) { <>8__1.totals = value; }); <>1__state = 2; return true; case 2: <>1__state = -1; onComplete(<>8__1.totals, <>8__1.terrainPreparation, ""); 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__109 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public IReadOnlyCollection work; private <>c__DisplayClass109_0 <>8__1; public string failurePrefix; public Action onComplete; public bool exactSource; public float yOffset; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__109(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__DisplayClass109_0(); <>8__1.readyError = ""; <>2__current = ValidateLoadReadyAsync(work, delegate(string value) { <>8__1.readyError = value; }); <>1__state = 1; return true; case 1: <>1__state = -1; if (!string.IsNullOrWhiteSpace(<>8__1.readyError)) { _logger.LogError((object)(failurePrefix + ": " + <>8__1.readyError)); onComplete(default(ZoneLoadTotals), <>8__1.readyError); return false; } <>8__1.terrainContext = null; <>8__1.contextError = ""; <>2__current = CreateAndValidateTerrainPlacementContextAsync(work, exactSource, yOffset, delegate(TerrainPlacementContext? context, string error) { <>8__1.terrainContext = context; <>8__1.contextError = error; }); <>1__state = 2; return true; case 2: { <>1__state = -1; if (!string.IsNullOrWhiteSpace(<>8__1.contextError)) { _logger.LogError((object)(failurePrefix + ": " + <>8__1.contextError)); onComplete(default(ZoneLoadTotals), <>8__1.contextError); return false; } <>8__1.totals = default(ZoneLoadTotals); TerrainPreparationResult terrainPreparation = TerrainPreparationResult.Completed(clientAssisted: false, CountRequiredTerrainTargets(work), 0); <>2__current = ApplyLoadWorkAsync(work, <>8__1.terrainContext, yOffset, terrainPreparation, delegate(ZoneLoadTotals value) { <>8__1.totals = value; }); <>1__state = 3; return true; } case 3: <>1__state = -1; onComplete(<>8__1.totals, ""); 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__110 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public long terrainAssistPeer; public IReadOnlyCollection work; private <>c__DisplayClass110_0 <>8__1; public string failurePrefix; public Action onComplete; public bool exactSource; public float yOffset; public ZoneBundleCommandRequest request; private bool 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__110(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__DisplayClass110_0(); <>8__1.readyError = ""; 5__2 = terrainAssistPeer != 0; <>2__current = ValidateLoadReadyAsync(work, delegate(string value) { <>8__1.readyError = value; }, 5__2); <>1__state = 1; return true; case 1: <>1__state = -1; if (!string.IsNullOrWhiteSpace(<>8__1.readyError)) { _logger.LogError((object)(failurePrefix + ": " + <>8__1.readyError)); onComplete(null, default(TerrainPreparationResult), <>8__1.readyError); return false; } <>8__1.terrainContext = null; <>8__1.contextError = ""; <>2__current = CreateAndValidateTerrainPlacementContextAsync(work, exactSource, yOffset, delegate(TerrainPlacementContext? context, string error) { <>8__1.terrainContext = context; <>8__1.contextError = error; }, !5__2); <>1__state = 2; return true; case 2: <>1__state = -1; if (!string.IsNullOrWhiteSpace(<>8__1.contextError)) { _logger.LogError((object)(failurePrefix + ": " + <>8__1.contextError)); onComplete(null, default(TerrainPreparationResult), <>8__1.contextError); return false; } <>8__1.terrainPreparation = default(TerrainPreparationResult); <>2__current = PrepareTerrainForLoadAsync(request, work, <>8__1.terrainContext, terrainAssistPeer, delegate(TerrainPreparationResult value) { <>8__1.terrainPreparation = value; }); <>1__state = 3; return true; case 3: <>1__state = -1; if (!<>8__1.terrainPreparation.Success) { _logger.LogError((object)(failurePrefix + ": " + <>8__1.terrainPreparation.Message)); onComplete(null, <>8__1.terrainPreparation, <>8__1.terrainPreparation.Message); return false; } onComplete(<>8__1.terrainContext, <>8__1.terrainPreparation, ""); 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 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public IReadOnlyCollection work; public Action onComplete; public TerrainPlacementContext terrainContext; public long terrainAssistPeer; public ZoneBundleCommandRequest request; private <>c__DisplayClass112_0 <>8__1; private HashSet 5__2; private List.Enumerator <>7__wrap2; private Vector2i 5__4; private string 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__112(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(); } } <>8__1 = null; 5__2 = null; <>7__wrap2 = default(List.Enumerator); 5__5 = null; <>7__wrap5 = default(List.Enumerator); <>1__state = -2; } private bool MoveNext() { //IL_02d6: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) bool result; try { int num = <>1__state; if (num != 0) { if (num == 1) { <>1__state = -4; if (<>8__1.response == null || !<>8__1.response.Success) { 5__5 = <>8__1.response?.Message ?? "client terrain apply did not return a response"; goto IL_023b; } goto IL_024b; } result = false; } else { <>1__state = -1; if (!work.Any((LoadWorkItem item) => RequiresTerrainApply(item.Bundle))) { onComplete(TerrainPreparationResult.Completed(clientAssisted: false, 0, 0)); result = false; } else if (terrainContext == null) { onComplete(TerrainPreparationResult.Failed("Zone bundle terrain support placement could not be resolved. Load aborted before overwriting target zones.")); result = false; } else { if (!AllRequiredTerrainTargetsCanApply(work)) { 5__2 = new HashSet(); <>7__wrap2 = RequiredTerrainTargetZones(work).GetEnumerator(); <>1__state = -3; goto IL_02ef; } try { ValidateTerrainPlacementContext(work, terrainContext); onComplete(TerrainPreparationResult.Completed(clientAssisted: false, CountRequiredTerrainTargets(work), 0)); } catch (Exception ex) { onComplete(TerrainPreparationResult.Failed(ex.Message)); } result = false; } } goto end_IL_0000; IL_023b: if (!<>7__wrap5.MoveNext()) { goto IL_024b; } long current = <>7__wrap5.Current; <>2__current = RequestClientTerrainApplyAsync(current, request, new <>z__ReadOnlySingleElementList(5__4), terrainContext, delegate(ZoneBundleClientTerrainApplyResponse? value) { <>8__1.response = value; }); <>1__state = 1; result = true; goto end_IL_0000; IL_02ef: while (true) { if (<>7__wrap2.MoveNext()) { 5__4 = <>7__wrap2.Current; <>8__1 = new <>c__DisplayClass112_0(); if (ZoneBundleTerrain.CanApply(5__4)) { continue; } <>8__1.response = null; 5__5 = ""; <>7__wrap5 = GetTerrainWitnessCandidates(5__4, terrainAssistPeer).GetEnumerator(); <>1__state = -4; goto IL_023b; } <>m__Finally1(); <>7__wrap2 = default(List.Enumerator); onComplete(TerrainPreparationResult.Completed(5__2, CountRequiredTerrainTargets(work), 5__2.Count)); result = false; break; } goto end_IL_0000; IL_024b: <>m__Finally2(); <>7__wrap5 = default(List.Enumerator); if (<>8__1.response != null && <>8__1.response.Success) { 5__2.Add(5__4); <>8__1 = null; 5__5 = null; goto IL_02ef; } onComplete(TerrainPreparationResult.Failed(string.IsNullOrWhiteSpace(5__5) ? $"Target zone ({5__4.x},{5__4.y}) is not loaded for terrain overwrite and no ZoneSavior terrain witness is nearby." : 5__5)); result = false; <>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__wrap2).Dispose(); } private void <>m__Finally2() { <>1__state = -3; ((IDisposable)<>7__wrap5).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__162 : 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__162(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__113 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public IReadOnlyCollection targetZones; public ZoneBundleCommandRequest commandRequest; public TerrainPlacementContext terrainContext; public long terrainAssistPeer; public Action onComplete; private string 5__2; private float 5__3; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__113(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: { <>1__state = -1; 5__2 = Guid.NewGuid().ToString("N"); List list = targetZones.Distinct().Select(ToModel).ToList(); ZoneBundleClientTerrainApplyRequest value = new ZoneBundleClientTerrainApplyRequest { RequestId = 5__2, Operation = commandRequest.Operation, Tag = commandRequest.Tag, Context = terrainContext, TargetZones = list }; ClientTerrainApplyResponses.Remove(5__2); ZPackage val = new ZPackage(); val.Write(ZoneBundleSerialization.Serialize(value)); ZRoutedRpc.instance.InvokeRoutedRPC(terrainAssistPeer, "sighsorry.ZoneSavior_ZoneBundleClientTerrainApplyRequest", new object[1] { val }); 5__3 = Time.realtimeSinceStartup + 180f; break; } case 1: <>1__state = -1; break; } if (Time.realtimeSinceStartup < 5__3) { if (ClientTerrainApplyResponses.TryGetValue(5__2, out ZoneBundleClientTerrainApplyResponse value2)) { ClientTerrainApplyResponses.Remove(5__2); onComplete(value2); return false; } <>2__current = null; <>1__state = 1; return true; } ClientTerrainApplyResponses.Remove(5__2); onComplete(new ZoneBundleClientTerrainApplyResponse { RequestId = 5__2, Success = false, Message = $"Client terrain apply timed out after {180f:0} seconds." }); 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__114 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string tag; public Vector2i zone; public ZoneBundleFile bundle; public Action onComplete; public long terrainAssistPeer; private string 5__2; private float 5__3; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__114(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: { <>1__state = -1; 5__2 = Guid.NewGuid().ToString("N"); ZoneBundleClientTerrainCaptureRequest zoneBundleClientTerrainCaptureRequest = new ZoneBundleClientTerrainCaptureRequest { RequestId = 5__2, Tag = tag, Zone = ToModel(zone), SourceBaseY = bundle.SourceBaseY, Entries = CreateTerrainContactCaptureEntries(bundle) }; if (zoneBundleClientTerrainCaptureRequest.Entries.Count == 0) { onComplete(new ZoneBundleClientTerrainCaptureResponse { RequestId = 5__2, Success = true, ContactsCaptured = true, Message = "No WearNTear entries require terrain contacts." }); return false; } ClientTerrainCaptureResponses.Remove(5__2); ZPackage val = new ZPackage(); val.Write(ZoneBundleSerialization.Serialize(zoneBundleClientTerrainCaptureRequest)); ZRoutedRpc.instance.InvokeRoutedRPC(terrainAssistPeer, "sighsorry.ZoneSavior_ZoneBundleClientTerrainCaptureRequest", new object[1] { val }); 5__3 = Time.realtimeSinceStartup + 180f; break; } case 1: <>1__state = -1; break; } if (Time.realtimeSinceStartup < 5__3) { if (ClientTerrainCaptureResponses.TryGetValue(5__2, out ZoneBundleClientTerrainCaptureResponse value)) { ClientTerrainCaptureResponses.Remove(5__2); onComplete(value); return false; } <>2__current = null; <>1__state = 1; return true; } ClientTerrainCaptureResponses.Remove(5__2); onComplete(new ZoneBundleClientTerrainCaptureResponse { RequestId = 5__2, Success = false, Message = $"Client terrain capture timed out after {180f:0} seconds." }); 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__127 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public ZoneBundleFile bundle; public Action onComplete; private <>c__DisplayClass127_0 <>8__1; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__127(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__DisplayClass127_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__144 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public IEnumerable sourceZones; public Action onComplete; private <>c__DisplayClass144_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__144(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_010e: 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__DisplayClass144_0(); 5__2 = NormalizeZones(sourceZones); 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_0155; case 2: <>1__state = -3; goto IL_0155; case 3: { <>1__state = -1; <>8__1.removed += <>8__1.verification.Removed; ClutterSystem instance2 = ClutterSystem.instance; if (instance2 != null) { instance2.ClearAll(); } <>2__current = RecalculateLoadedTerrainAsync(); <>1__state = 4; return true; } case 4: { <>1__state = -1; Minimap instance = Minimap.instance; if (instance != null) { instance.UpdateLocationPins(1000f); } onComplete(BuildResetResult(5__2.Count, <>8__1.removed, <>8__1.verification.Removed, <>8__1.verification.RemainingWearNTear)); return false; } IL_0155: 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.verification = default(ResetVerificationResult); <>2__current = VerifyResetObjectsAsync(5__4, 5__3, delegate(ResetVerificationResult value) { <>8__1.verification = 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__153 : 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__153(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) try { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -4; goto IL_0100; } <>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_0170; IL_0170: 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_014e; } <>m__Finally1(); <>7__wrap5 = default(HashSet.Enumerator); ZoneBundleZdoHelper.FlushDestroyed(); onComplete(5__4); return false; IL_014e: 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_0100; } <>m__Finally2(); <>7__wrap6 = default(List.Enumerator); goto IL_0170; IL_0100: if (TryCollectResetZoneObject(5__8, zones, 5__2, out ZDO resetObject)) { if (IsResettableZoneObject(resetObject, zones, protectedCharacterIds)) { ZoneBundleZdoHelper.Destroy(resetObject); 5__4++; } 5__8 = null; } goto IL_014e; } 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__141 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string tag; public Action onComplete; private <>c__DisplayClass141_0 <>8__1; private List 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__141(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(); } } <>8__1 = null; 5__2 = null; <>7__wrap2 = default(List.Enumerator); <>1__state = -2; } private bool MoveNext() { //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: 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; <>8__1 = new <>c__DisplayClass141_0(); ZoneBundleManifest zoneBundleManifest; try { zoneBundleManifest = ZoneBundleStore.LoadManifest(tag); } catch (Exception ex) { _logger.LogError((object)$"Zone bundle async archive restore failed: {ex}"); onComplete(ZoneBundleCommandResult.Fail(ex.Message)); result = false; break; } 5__2 = new List(); <>7__wrap2 = zoneBundleManifest.Bundles.GetEnumerator(); <>1__state = -3; goto IL_0127; } case 1: <>1__state = -3; goto IL_0127; case 2: { <>1__state = -1; if (!string.IsNullOrWhiteSpace(<>8__1.restoreError)) { onComplete(ZoneBundleCommandResult.Fail(<>8__1.restoreError)); result = false; break; } onComplete(ZoneBundleCommandResult.Ok($"Restored {5__2.Count} archived zone bundle(s) for tag '{tag}' " + $"(removed: {<>8__1.totals.Removed}, created: {<>8__1.totals.Created}, terrain: {<>8__1.totals.TerrainApplied}/{5__2.Count}).")); result = false; break; } IL_0127: if (<>7__wrap2.MoveNext()) { ZoneBundleManifestEntry current = <>7__wrap2.Current; Vector2i targetZone = ToVector2i(current.Zone); if (!ZoneBundleStore.TryLoadBundleFromManifestEntry(tag, current, 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__wrap2 = default(List.Enumerator); <>8__1.totals = default(ZoneLoadTotals); <>8__1.restoreError = ""; <>2__current = PrepareAndApplyLocalLoadWorkAsync("Zone bundle async archive restore failed", 5__2, exactSource: true, 0f, delegate(ZoneLoadTotals loadTotals, string error) { <>8__1.totals = loadTotals; <>8__1.restoreError = error; }); <>1__state = 2; result = true; } 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__wrap2).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 IEnumerable sourceZones; public Action onComplete; public string tag; private <>c__DisplayClass76_0 <>8__1; private <>c__DisplayClass76_1 <>8__2; public long terrainAssistPeer; private <>c__DisplayClass76_2 <>8__3; private List 5__2; private ZoneBundleManifest 5__3; private string 5__4; private ArchiveSaveProgress 5__5; private List.Enumerator <>7__wrap5; private Vector2i 5__7; private ZoneBundleFile 5__8; private int 5__9; private int 5__10; private ZoneBundleTerrainCaptureState 5__11; private string 5__12; private List.Enumerator <>7__wrap12; 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 ((uint)(num - -4) <= 1u || (uint)(num - 2) <= 2u) { try { if (num == -4 || num == 3) { try { } finally { <>m__Finally2(); } } } finally { <>m__Finally1(); } } <>8__1 = null; <>8__2 = null; <>8__3 = null; 5__2 = null; 5__3 = null; 5__4 = null; 5__5 = null; <>7__wrap5 = default(List.Enumerator); 5__8 = null; 5__12 = null; <>7__wrap12 = default(List.Enumerator); <>1__state = -2; } private bool MoveNext() { //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_02a2: Unknown result type (might be due to invalid IL or missing references) //IL_048d: Unknown result type (might be due to invalid IL or missing references) //IL_02de: Unknown result type (might be due to invalid IL or missing references) bool result2; try { long current; switch (<>1__state) { default: result2 = false; goto end_IL_0000; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass76_0(); 5__2 = NormalizeZones(sourceZones); if (5__2.Count == 0) { onComplete(new ZoneBundleArchiveResult { Success = false, Tag = tag, Message = "No zones to save." }); result2 = false; } else { 5__3 = CreateManifest(tag, 5__2, out 5__4); <>8__1.sourceAnchor = new ZoneBundleTerrain.TerrainSourceAnchor(float.NaN); <>2__current = ZoneBundleTerrain.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 = new ArchiveSaveProgress(); <>7__wrap5 = 5__2.GetEnumerator(); <>1__state = -3; goto IL_0522; case 2: <>1__state = -3; if (<>8__2.capture == null || !<>8__2.capture.Success || <>8__2.capture.Bundle == null) { onComplete(CreateArchiveResult(success: false, tag, 5__4, 5__3, 5__5, "save failed: " + (<>8__2.capture?.ErrorMessage ?? "capture coroutine did not return a result"))); result2 = false; break; } 5__8 = <>8__2.capture.Bundle; 5__9 = <>8__2.capture.EntryCount; 5__10 = <>8__2.capture.MonsterCount; 5__11 = <>8__2.capture.TerrainState; if (5__11 == ZoneBundleTerrainCaptureState.NotLoaded) { <>8__3 = new <>c__DisplayClass76_2(); <>8__3.terrainResponse = null; 5__12 = ""; <>7__wrap12 = GetTerrainWitnessCandidates(5__7, terrainAssistPeer).GetEnumerator(); <>1__state = -4; goto IL_037c; } goto IL_0480; case 3: <>1__state = -4; if (<>8__3.terrainResponse == null || !<>8__3.terrainResponse.Success) { 5__12 = <>8__3.terrainResponse?.Message ?? "capture coroutine did not return a response"; goto IL_037c; } goto IL_038c; case 4: { <>1__state = -3; <>8__2 = null; 5__8 = null; goto IL_0522; } IL_0522: if (<>7__wrap5.MoveNext()) { 5__7 = <>7__wrap5.Current; <>8__2 = new <>c__DisplayClass76_1(); <>8__2.capture = null; <>2__current = CaptureBundleAsync(5__7, tag, <>8__1.sourceAnchor, delegate(CaptureBundleResult result) { <>8__2.capture = result; }); <>1__state = 2; result2 = true; } else { <>m__Finally1(); <>7__wrap5 = default(List.Enumerator); try { UpdateManifestSourceZoneCreators(5__3); ZoneBundleStore.SaveManifest(5__4, 5__3); } catch (Exception ex) { onComplete(CreateArchiveResult(success: false, tag, 5__4, 5__3, 5__5, "manifest save failed: " + ex.Message)); result2 = false; goto end_IL_0000; } onComplete(CreateArchiveResult(success: true, tag, 5__4, 5__3, 5__5)); result2 = false; } goto end_IL_0000; IL_037c: if (!<>7__wrap12.MoveNext()) { goto IL_038c; } current = <>7__wrap12.Current; <>2__current = RequestClientTerrainCaptureAsync(current, tag, 5__7, 5__8, delegate(ZoneBundleClientTerrainCaptureResponse? value) { <>8__3.terrainResponse = value; }); <>1__state = 3; result2 = true; goto end_IL_0000; IL_0480: try { StoreCapturedBundle(tag, 5__3, 5__7, 5__8, 5__9, 5__10, 5__11, 5__5); } catch (Exception ex2) { onComplete(CreateArchiveResult(success: false, tag, 5__4, 5__3, 5__5, "save failed: " + ex2.Message)); result2 = false; break; } <>2__current = null; <>1__state = 4; result2 = true; goto end_IL_0000; IL_038c: <>m__Finally2(); <>7__wrap12 = default(List.Enumerator); if (<>8__3.terrainResponse != null && <>8__3.terrainResponse.Success && <>8__3.terrainResponse.ContactsCaptured) { 5__8.TerrainContactsCaptured = true; 5__8.TerrainContacts = <>8__3.terrainResponse.Contacts; 5__11 = GetTerrainCaptureState(contactsCaptured: true, <>8__3.terrainResponse.Contacts.Count); 5__8.TerrainCaptureState = 5__11; } else if (!string.IsNullOrWhiteSpace(5__12)) { _logger.LogWarning((object)$"Client terrain capture skipped for zone ({5__7.x},{5__7.y}): {5__12}"); } <>8__3 = null; 5__12 = null; goto IL_0480; } <>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__wrap5).Dispose(); } private void <>m__Finally2() { <>1__state = -3; ((IDisposable)<>7__wrap12).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__101 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public IEnumerable work; public Action onComplete; public bool allowClientTerrainApply; private <>c__DisplayClass101_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__101(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_00f7: 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_0129: 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_0173; case 1: <>1__state = -3; if ((!allowClientTerrainApply & <>8__1.requiresTerrainApply) && !ZoneBundleTerrain.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_0173; } IL_0173: if (<>7__wrap1.MoveNext()) { 5__3 = <>7__wrap1.Current; <>8__1 = new <>c__DisplayClass101_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(); } } [CompilerGenerated] private sealed class d__146 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public HashSet zoneSet; public HashSet characterIds; private <>c__DisplayClass146_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__146(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__DisplayClass146_0(); <>8__1.remainingWearNTear = 0; <>2__current = CountRemainingCreatorWearNTearAsync(zoneSet, characterIds, delegate(int value) { <>8__1.remainingWearNTear = value; }); <>1__state = 1; return true; case 1: <>1__state = -1; if (<>8__1.remainingWearNTear <= 0) { onComplete(new ResetVerificationResult(0, <>8__1.remainingWearNTear)); return false; } <>8__1.verificationRemoved = 0; <>2__current = ResetZoneObjectsAsync(zoneSet, characterIds, delegate(int value) { <>8__1.verificationRemoved = value; }); <>1__state = 2; return true; case 2: <>1__state = -1; <>2__current = CountRemainingCreatorWearNTearAsync(zoneSet, characterIds, delegate(int value) { <>8__1.remainingWearNTear = value; }); <>1__state = 3; return true; case 3: <>1__state = -1; onComplete(new ResetVerificationResult(<>8__1.verificationRemoved, <>8__1.remainingWearNTear)); 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 Regex CommandPattern = new Regex("^\\s*(\\([^)]+\\))\\s+([^\\s]+)(?:\\s+to\\s+(\\([^)]+\\)))?\\s*$", RegexOptions.IgnoreCase | RegexOptions.Compiled); private static readonly Regex LoadZonePattern = new Regex("^\\s*([^\\s]+)(?:\\s+(?:(restore)|source\\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); internal const string SaveOperation = "zs_savezone"; internal const string LoadOperation = "zs_loadzone"; private const string ClientTerrainApplyRequestRpcName = "sighsorry.ZoneSavior_ZoneBundleClientTerrainApplyRequest"; private const string ClientTerrainApplyResponseRpcName = "sighsorry.ZoneSavior_ZoneBundleClientTerrainApplyResponse"; private const string ClientTerrainCaptureRequestRpcName = "sighsorry.ZoneSavior_ZoneBundleClientTerrainCaptureRequest"; private const string ClientTerrainCaptureResponseRpcName = "sighsorry.ZoneSavior_ZoneBundleClientTerrainCaptureResponse"; private const string TerrainWitnessAnnounceRpcName = "sighsorry.ZoneSavior_ZoneBundleTerrainWitnessAnnounce"; 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 const float ClientTerrainApplyTimeoutSeconds = 180f; private const float TerrainWitnessSearchRadius = 160f; private static readonly Dictionary EmptyParameters = new Dictionary(); private static ManualLogSource _logger = null; private static bool _initialized; private static readonly ZoneRpcRegistrar RpcRegistrar = new ZoneRpcRegistrar(); private static readonly Dictionary ClientTerrainApplyResponses = new Dictionary(); private static readonly Dictionary ClientTerrainCaptureResponses = new Dictionary(); private static readonly HashSet TerrainWitnessPeers = new HashSet(); private static long _announcedTerrainWitnessServer; internal static ZoneBundleCommandRequest ParseLoadRequest(string argsAll) { //IL_0091: 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_00db: 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_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) float yOffset = ExtractYOffsetOption(ref argsAll); Match match = LoadZonePattern.Match(argsAll); if (!match.Success) { throw new InvalidOperationException("Syntax: zs_loadzone tag [restore|source (x,z)] [to (x,z)] [offset=Y]"); } bool success = match.Groups[2].Success; bool success2 = match.Groups[3].Success; if ((success && success2) || (success && match.Groups[4].Success)) { throw new InvalidOperationException("Syntax: zs_loadzone tag [restore|source (x,z)] [to (x,z)] [offset=Y]"); } Vector2i? val = (success2 ? new Vector2i?(ParseSingleZone(match.Groups[3].Value)) : null); ZoneBundleCommandRequest zoneBundleCommandRequest = new ZoneBundleCommandRequest { Operation = "zs_loadzone", Tag = match.Groups[1].Value, TargetZone = (success ? null : (match.Groups[4].Success ? ToModel(ParseSingleZone(match.Groups[4].Value)) : ToModel(GetCurrentPlayerZone()))), YOffset = yOffset, RestoreOriginal = success, LoadSourceZone = success2 }; if (val.HasValue) { zoneBundleCommandRequest.SourceRange = CreateRange(val.Value.x, val.Value.y, val.Value.x, val.Value.y); } return zoneBundleCommandRequest; } internal static ZoneBundleCommandRequest ParseRequest(string argsAll, string operation, bool requireSingleZone, bool requireTarget) { //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) float yOffset = ExtractYOffsetOption(ref argsAll); Match match = CommandPattern.Match(argsAll); if (!match.Success) { string message = ((!(operation == "zs_savezone")) ? "Syntax: zs_loadzone tag [restore|source (x,z)] [to (x,z)] [offset=Y]" : "Syntax: zs_savezone (x,z) tag or zs_savezone (x~x,z~z) tag"); 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__15))] private static IEnumerable EnumerateZones(ZoneBundleRange range) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__15(-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); } internal 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."); } } internal 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; } internal 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 GetWorldName() { return ZNet.instance.GetWorldName(); } internal static string GetCurrentWorldName() { return GetWorldName(); } private static ZoneBundleZone ToModel(Vector2i zone) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return ZoneSaviorZones.ToModel(zone); } private static Vector2i ToVector2i(ZoneBundleZone zone) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return ZoneSaviorZones.ToVector2i(zone); } 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; } public static void Initialize(ManualLogSource logger) { if (!_initialized) { _initialized = true; _logger = logger; ZoneBundleCommandEndpoint.Initialize(logger); RegisterRpcs(); } } internal static void RegisterRpcs() { ZoneBundleCommandEndpoint.RegisterRpcs(); RpcRegistrar.EnsureRegistered(delegate(ZRoutedRpc routedRpc) { routedRpc.Register("sighsorry.ZoneSavior_ZoneBundleClientTerrainApplyRequest", (Action)RPC_HandleClientTerrainApplyRequest); routedRpc.Register("sighsorry.ZoneSavior_ZoneBundleClientTerrainApplyResponse", (Action)RPC_HandleClientTerrainApplyResponse); routedRpc.Register("sighsorry.ZoneSavior_ZoneBundleClientTerrainCaptureRequest", (Action)RPC_HandleClientTerrainCaptureRequest); routedRpc.Register("sighsorry.ZoneSavior_ZoneBundleClientTerrainCaptureResponse", (Action)RPC_HandleClientTerrainCaptureResponse); routedRpc.Register("sighsorry.ZoneSavior_ZoneBundleTerrainWitnessAnnounce", (Action)RPC_HandleTerrainWitnessAnnounce); }); AnnounceTerrainWitnessIfReady(); } private static void RPC_HandleClientTerrainApplyRequest(long sender, ZPackage package) { if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer()) { return; } try { ZoneBundleClientTerrainApplyRequest zoneBundleClientTerrainApplyRequest = ZoneBundleSerialization.Deserialize(package.ReadString()); if ((Object)(object)ZoneSaviorPlugin.Instance == (Object)null) { SendClientTerrainApplyResponse(sender, new ZoneBundleClientTerrainApplyResponse { RequestId = zoneBundleClientTerrainApplyRequest.RequestId, Success = false, Message = "ZoneSavior client plugin instance is not available." }); } else { ((MonoBehaviour)ZoneSaviorPlugin.Instance).StartCoroutine(ApplyClientTerrainRequestAsync(sender, zoneBundleClientTerrainApplyRequest)); } } catch (Exception arg) { _logger.LogError((object)$"Zone bundle client terrain RPC failed: {arg}"); } } private static void RPC_HandleClientTerrainApplyResponse(long sender, ZPackage package) { if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer()) { return; } try { ZoneBundleClientTerrainApplyResponse zoneBundleClientTerrainApplyResponse = ZoneBundleSerialization.Deserialize(package.ReadString()); if (!string.IsNullOrWhiteSpace(zoneBundleClientTerrainApplyResponse.RequestId)) { ClientTerrainApplyResponses[zoneBundleClientTerrainApplyResponse.RequestId] = zoneBundleClientTerrainApplyResponse; } } catch (Exception arg) { _logger.LogError((object)$"Zone bundle client terrain response failed: {arg}"); } } private static void RPC_HandleClientTerrainCaptureRequest(long sender, ZPackage package) { if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer()) { return; } try { ZoneBundleClientTerrainCaptureResponse result = CaptureClientTerrainContacts(ZoneBundleSerialization.Deserialize(package.ReadString())); SendClientTerrainCaptureResponse(sender, result); } catch (Exception arg) { _logger.LogError((object)$"Zone bundle client terrain capture RPC failed: {arg}"); } } private static void RPC_HandleClientTerrainCaptureResponse(long sender, ZPackage package) { if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer()) { return; } try { ZoneBundleClientTerrainCaptureResponse zoneBundleClientTerrainCaptureResponse = ZoneBundleSerialization.Deserialize(package.ReadString()); if (!string.IsNullOrWhiteSpace(zoneBundleClientTerrainCaptureResponse.RequestId)) { ClientTerrainCaptureResponses[zoneBundleClientTerrainCaptureResponse.RequestId] = zoneBundleClientTerrainCaptureResponse; } } catch (Exception arg) { _logger.LogError((object)$"Zone bundle client terrain capture response failed: {arg}"); } } private static void RPC_HandleTerrainWitnessAnnounce(long sender, ZPackage package) { if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer()) { TerrainWitnessPeers.Add(sender); } } private static void SendClientTerrainApplyResponse(long target, ZoneBundleClientTerrainApplyResponse 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_ZoneBundleClientTerrainApplyResponse", new object[1] { val }); } private static void SendClientTerrainCaptureResponse(long target, ZoneBundleClientTerrainCaptureResponse 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_ZoneBundleClientTerrainCaptureResponse", new object[1] { val }); } private static void AnnounceTerrainWitnessIfReady() { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown if (!((Object)(object)ZNet.instance == (Object)null) && !ZNet.instance.IsServer() && ZRoutedRpc.instance != null) { long serverPeerID = ZRoutedRpc.instance.GetServerPeerID(); if (serverPeerID != 0L && _announcedTerrainWitnessServer != serverPeerID) { ZRoutedRpc.instance.InvokeRoutedRPC(serverPeerID, "sighsorry.ZoneSavior_ZoneBundleTerrainWitnessAnnounce", new object[1] { (object)new ZPackage() }); _announcedTerrainWitnessServer = serverPeerID; } } } internal static void StartRequest(ZoneBundleCommandRequest request, Action onComplete, long terrainAssistPeer = 0L) { if (request.Operation == "zs_savezone" && (Object)(object)ZoneSaviorPlugin.Instance != (Object)null) { ((MonoBehaviour)ZoneSaviorPlugin.Instance).StartCoroutine(ExecuteSaveRequestAsync(request, onComplete, terrainAssistPeer)); } else if (request.Operation == "zs_loadzone" && (Object)(object)ZoneSaviorPlugin.Instance != (Object)null) { ((MonoBehaviour)ZoneSaviorPlugin.Instance).StartCoroutine(ExecuteLoadRequestAsync(request, onComplete, terrainAssistPeer)); } else { onComplete(ExecuteRequest(request)); } } [IteratorStateMachine(typeof(d__67))] private static IEnumerator ExecuteSaveRequestAsync(ZoneBundleCommandRequest request, Action onComplete, long terrainAssistPeer) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__67(0) { request = request, onComplete = onComplete, terrainAssistPeer = terrainAssistPeer }; } [IteratorStateMachine(typeof(d__68))] private static IEnumerator ExecuteLoadRequestAsync(ZoneBundleCommandRequest request, Action onComplete, long terrainAssistPeer) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__68(0) { request = request, onComplete = onComplete, terrainAssistPeer = terrainAssistPeer }; } private static ZoneBundleCommandResult ExecuteRequest(ZoneBundleCommandRequest request) { try { string operation = request.Operation; return (operation == "zs_savezone") ? SaveRange(request) : ((!(operation == "zs_loadzone")) ? ZoneBundleCommandResult.Fail("Unsupported operation '" + request.Operation + "'.") : ExecuteLoadRequest(request)); } 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 ExecuteLoadRequest(ZoneBundleCommandRequest request) { if (request.RestoreOriginal) { return RestoreTagToOriginalZones(request.Tag); } if (!request.LoadSourceZone) { return LoadArchiveManifest(request); } return LoadZoneRequest(request); } private static ZoneBundleCommandResult LoadZoneRequest(ZoneBundleCommandRequest request) { return LoadSingleZone(request); } [IteratorStateMachine(typeof(d__73))] private static IEnumerator LoadZoneRequestAsync(ZoneBundleCommandRequest request, Action onComplete, long terrainAssistPeer) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__73(0) { request = request, onComplete = onComplete, terrainAssistPeer = terrainAssistPeer }; } 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_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_0059: 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) List list = NormalizeZones(sourceZones); if (list.Count == 0) { return new ZoneBundleArchiveResult { Success = false, Tag = tag, Message = "No zones to save." }; } string manifestPath; ZoneBundleManifest manifest = CreateManifest(tag, list, out manifestPath); ZoneBundleTerrain.TerrainSourceAnchor sourceAnchor = ZoneBundleTerrain.ComputeSupportAnchor(list); ArchiveSaveProgress progress = new ArchiveSaveProgress(); foreach (Vector2i item in list) { int entries; int monsters; ZoneBundleTerrainCaptureState terrainState; ZoneBundleFile bundle = CaptureBundle(item, tag, sourceAnchor, out entries, out monsters, out terrainState); StoreCapturedBundle(tag, manifest, item, bundle, entries, monsters, terrainState, progress); } UpdateManifestSourceZoneCreators(manifest); ZoneBundleStore.SaveManifest(manifestPath, manifest); return CreateArchiveResult(success: true, tag, manifestPath, manifest, progress); } [IteratorStateMachine(typeof(d__76))] internal static IEnumerator SaveZonesAsync(IEnumerable sourceZones, string tag, Action onComplete, long terrainAssistPeer = 0L) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__76(0) { sourceZones = sourceZones, tag = tag, onComplete = onComplete, terrainAssistPeer = terrainAssistPeer }; } private static void StoreCapturedBundle(string tag, ZoneBundleManifest manifest, Vector2i zone, ZoneBundleFile bundle, int entryCount, int monsterCount, ZoneBundleTerrainCaptureState terrainState, ArchiveSaveProgress progress) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) progress.TotalEntries += entryCount; progress.TotalMonsters += monsterCount; if (terrainState != 0) { progress.TerrainLoaded++; } if (terrainState == ZoneBundleTerrainCaptureState.Contacts) { progress.TerrainCaptured++; } string bundlePath = ZoneBundleStore.GetBundlePath(tag, ++progress.BundleIndex); ZoneBundleStore.SaveBundle(bundlePath, bundle); AddBundleToManifest(manifest, zone, bundlePath, bundle); } private static List NormalizeZones(IEnumerable zones) { return (from zone in zones.Distinct() orderby zone.y, zone.x select zone).ToList(); } private static ZoneBundleManifest CreateManifest(string tag, List zones, out string manifestPath) { ZoneBundleRange sourceRange = CreateRange(zones.Min((Vector2i zone) => zone.x), zones.Min((Vector2i zone) => zone.y), zones.Max((Vector2i zone) => zone.x), zones.Max((Vector2i zone) => zone.y)); manifestPath = ZoneBundleStore.GetManifestPath(tag); return new ZoneBundleManifest { Tag = tag, World = GetWorldName(), SavedAt = ZoneSaviorTimestamp.Now(), SourceRange = sourceRange }; } private static void AddBundleToManifest(ZoneBundleManifest manifest, Vector2i zone, string bundlePath, ZoneBundleFile bundle) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) manifest.Bundles.Add(new ZoneBundleManifestEntry { Zone = ToModel(zone), File = Path.GetFileName(bundlePath), SourceZoneCreators = CloneSourceZoneCreators(bundle.SourceZoneCreators) }); } private static ZoneBundleArchiveResult CreateArchiveResult(bool success, string tag, string manifestPath, ZoneBundleManifest manifest, ArchiveSaveProgress progress, string? message = null) { return CreateArchiveResult(success, tag, manifestPath, manifest, progress.TotalEntries, progress.TotalMonsters, progress.TerrainLoaded, progress.TerrainCaptured, message); } private static ZoneBundleArchiveResult CreateArchiveResult(bool success, string tag, string manifestPath, ZoneBundleManifest manifest, int totalEntries, int totalMonsters, int terrainLoaded, int terrainCaptured, string? message = null) { return new ZoneBundleArchiveResult { Success = success, Tag = tag, ManifestPath = manifestPath, ZoneCount = manifest.Bundles.Count, EntryCount = totalEntries, MonsterCount = totalMonsters, TerrainLoaded = terrainLoaded, TerrainCaptured = terrainCaptured, Message = (message ?? BuildArchiveSuccessMessage(tag, manifestPath, manifest, totalEntries, totalMonsters, terrainLoaded, terrainCaptured)) }; } private static string BuildArchiveSuccessMessage(string tag, string manifestPath, ZoneBundleManifest manifest, int totalEntries, int totalMonsters, int terrainLoaded, int terrainCaptured) { return $"Saved {manifest.Bundles.Count} zone bundle(s) for tag '{tag}' to '{Path.GetDirectoryName(manifestPath)}' " + $"(entries: {totalEntries}, monsters: {totalMonsters}, terrain contacts: {terrainCaptured}/{manifest.Bundles.Count}, terrain loaded: {terrainLoaded}/{manifest.Bundles.Count}, mode: SupportFill)."; } 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_002c: 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_0069: 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_0085: Unknown result type (might be due to invalid IL or missing references) Vector2i val = ToSingleSourceZone(request.SourceRange); Vector2i val2 = ToVector2i(request.TargetZone); ZoneBundleFile bundle = ZoneBundleStore.LoadBundleFromManifestZone(request.Tag, val); ZoneLoadTotals zoneLoadTotals = ApplyLoadWork(new List(1) { new LoadWorkItem(val2, bundle) }, exactSource: false, 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}).", zoneLoadTotals.Removed, zoneLoadTotals.Created, (zoneLoadTotals.TerrainApplied > 0) ? "yes" : "no", Round(request.YOffset))); } [IteratorStateMachine(typeof(d__95))] private static IEnumerator LoadSingleZoneAsync(ZoneBundleCommandRequest request, Action onComplete, long terrainAssistPeer) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__95(0) { request = request, onComplete = onComplete, terrainAssistPeer = terrainAssistPeer }; } private static ZoneBundleCommandResult LoadArchiveManifest(ZoneBundleCommandRequest request) { //IL_003a: 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_0047: 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_008e: Unknown result type (might be due to invalid IL or missing references) ZoneBundleManifest zoneBundleManifest = ZoneBundleStore.LoadManifest(request.Tag); if (zoneBundleManifest.Bundles.Count == 0) { return ZoneBundleCommandResult.Fail("Manifest for tag '" + request.Tag + "' contains no zone bundles."); } Vector2i val = ToVector2i(request.TargetZone); List list = BuildArchiveLoadWork(request.Tag, zoneBundleManifest, val); ZoneLoadTotals zoneLoadTotals = ApplyLoadWork(list, exactSource: false, request.YOffset); return ZoneBundleCommandResult.Ok($"Loaded archive '{request.Tag}' as {list.Count} manifest zone(s) to target start ({val.x},{val.y}) " + $"(removed: {zoneLoadTotals.Removed}, created: {zoneLoadTotals.Created}, terrain: {zoneLoadTotals.TerrainApplied}/{list.Count}, mode: SupportFill, yOffset: {Round(request.YOffset)})."); } [IteratorStateMachine(typeof(d__97))] private static IEnumerator LoadArchiveManifestAsync(ZoneBundleCommandRequest request, Action onComplete, long terrainAssistPeer) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__97(0) { request = request, onComplete = onComplete, terrainAssistPeer = terrainAssistPeer }; } private static List BuildArchiveLoadWork(string tag, ZoneBundleManifest manifest, Vector2i targetStart) { //IL_0030: 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_00af: 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_00c1: Unknown result type (might be due to invalid IL or missing references) List source = manifest.Bundles.Select((ZoneBundleManifestEntry entry) => ToVector2i(entry.Zone)).ToList(); int offsetX = targetStart.x - source.Min((Vector2i zone) => zone.x); int offsetZ = targetStart.y - source.Min((Vector2i zone) => zone.y); List list = new List(); foreach (ZoneBundleManifestEntry bundle2 in manifest.Bundles) { Vector2i sourceZone = ToVector2i(bundle2.Zone); ZoneBundleFile bundle = ZoneBundleStore.LoadBundleFromManifestEntry(tag, bundle2); list.Add(CreateLoadWorkItem(sourceZone, offsetX, offsetZ, bundle)); } return list; } private static LoadWorkItem CreateLoadWorkItem(Vector2i sourceZone, int offsetX, int offsetZ, ZoneBundleFile bundle) { //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) //IL_0010: Unknown result type (might be due to invalid IL or missing references) return new LoadWorkItem(new Vector2i(sourceZone.x + offsetX, sourceZone.y + offsetZ), bundle); } 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) && !ZoneBundleTerrain.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__101))] private static IEnumerator ValidateLoadReadyAsync(IEnumerable work, Action onComplete, bool allowClientTerrainApply = false) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__101(0) { work = work, onComplete = onComplete, allowClientTerrainApply = allowClientTerrainApply }; } private static TerrainPlacementContext? CreateTerrainPlacementContext(IEnumerable work, bool exactSource) { List list = work.ToList(); if (list.Count == 0) { return null; } if (exactSource) { return ZoneBundleTerrain.CreateExactContext(list.Min((LoadWorkItem item) => item.Bundle.SourceBaseY)); } return ZoneBundleTerrain.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__104))] private static IEnumerator CreateAndValidateTerrainPlacementContextAsync(IEnumerable work, bool exactSource, float yOffset, Action onComplete, bool validateTargetTerrain = true) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__104(0) { work = work, exactSource = exactSource, yOffset = yOffset, onComplete = onComplete, validateTargetTerrain = validateTargetTerrain }; } private static void ValidateTerrainPlacementContext(IReadOnlyCollection work, TerrainPlacementContext? terrainContext, bool validateTargetTerrain = true) { //IL_0074: 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."); } if (!validateTargetTerrain) { if (terrainContext.SupportRelativeHeights.Count != 0) { return; } throw new InvalidOperationException("Zone bundle terrain support placement produced no support points. Load aborted before overwriting target zones."); } bool flag = false; foreach (LoadWorkItem item in work) { if (RequiresTerrainApply(item.Bundle) && ZoneBundleTerrain.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 ZoneLoadTotals ApplyLoadWork(List work, bool exactSource, float yOffset) { ValidateLoadReady(work); TerrainPlacementContext terrainContext = CreateAndValidateTerrainPlacementContext(work, exactSource, yOffset); return ApplyLoadWork(work, terrainContext, yOffset); } private static ZoneLoadTotals ApplyLoadWork(IEnumerable work, TerrainPlacementContext? terrainContext, float yOffset) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) ZoneLoadTotals result = default(ZoneLoadTotals); foreach (LoadWorkItem item in work) { ZoneLoadStats stats = ApplyBundleToZone(item.TargetZone, item.Bundle, terrainContext, yOffset); result.Add(stats, stats.TerrainApplied); } return result; } [IteratorStateMachine(typeof(d__108))] private static IEnumerator PrepareAndApplyLoadWorkAsync(string failurePrefix, ZoneBundleCommandRequest request, IReadOnlyCollection work, bool exactSource, float yOffset, long terrainAssistPeer, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__108(0) { failurePrefix = failurePrefix, request = request, work = work, exactSource = exactSource, yOffset = yOffset, terrainAssistPeer = terrainAssistPeer, onComplete = onComplete }; } [IteratorStateMachine(typeof(d__109))] private static IEnumerator PrepareAndApplyLocalLoadWorkAsync(string failurePrefix, IReadOnlyCollection work, bool exactSource, float yOffset, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__109(0) { failurePrefix = failurePrefix, work = work, exactSource = exactSource, yOffset = yOffset, onComplete = onComplete }; } [IteratorStateMachine(typeof(d__110))] private static IEnumerator PrepareLoadWorkAsync(string failurePrefix, ZoneBundleCommandRequest request, IReadOnlyCollection work, bool exactSource, float yOffset, long terrainAssistPeer, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__110(0) { failurePrefix = failurePrefix, request = request, work = work, exactSource = exactSource, yOffset = yOffset, terrainAssistPeer = terrainAssistPeer, onComplete = onComplete }; } [IteratorStateMachine(typeof(d__111))] private static IEnumerator ApplyLoadWorkAsync(IEnumerable work, TerrainPlacementContext? terrainContext, float yOffset, TerrainPreparationResult terrainPreparation, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__111(0) { work = work, terrainContext = terrainContext, yOffset = yOffset, terrainPreparation = terrainPreparation, onComplete = onComplete }; } [IteratorStateMachine(typeof(d__112))] private static IEnumerator PrepareTerrainForLoadAsync(ZoneBundleCommandRequest request, IReadOnlyCollection work, TerrainPlacementContext? terrainContext, long terrainAssistPeer, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__112(0) { request = request, work = work, terrainContext = terrainContext, terrainAssistPeer = terrainAssistPeer, onComplete = onComplete }; } [IteratorStateMachine(typeof(d__113))] private static IEnumerator RequestClientTerrainApplyAsync(long terrainAssistPeer, ZoneBundleCommandRequest commandRequest, IReadOnlyCollection targetZones, TerrainPlacementContext terrainContext, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__113(0) { terrainAssistPeer = terrainAssistPeer, commandRequest = commandRequest, targetZones = targetZones, terrainContext = terrainContext, onComplete = onComplete }; } [IteratorStateMachine(typeof(d__114))] private static IEnumerator RequestClientTerrainCaptureAsync(long terrainAssistPeer, string tag, Vector2i zone, ZoneBundleFile bundle, Action onComplete) { //IL_0015: 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) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__114(0) { terrainAssistPeer = terrainAssistPeer, tag = tag, zone = zone, bundle = bundle, onComplete = onComplete }; } private static ZoneBundleClientTerrainCaptureResponse CaptureClientTerrainContacts(ZoneBundleClientTerrainCaptureRequest request) { //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_001e: 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_0089: 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_005c: Unknown result type (might be due to invalid IL or missing references) ZoneBundleClientTerrainCaptureResponse zoneBundleClientTerrainCaptureResponse = new ZoneBundleClientTerrainCaptureResponse { RequestId = request.RequestId }; try { Vector2i val = ToVector2i(request.Zone); bool contactsCaptured; List list = ZoneBundleTerrain.CaptureSupportContacts(val, request.SourceBaseY, request.Entries, out contactsCaptured); zoneBundleClientTerrainCaptureResponse.Success = contactsCaptured; zoneBundleClientTerrainCaptureResponse.ContactsCaptured = contactsCaptured; zoneBundleClientTerrainCaptureResponse.Contacts = list; zoneBundleClientTerrainCaptureResponse.Message = (contactsCaptured ? $"Client captured {list.Count} terrain contact(s) for zone ({val.x},{val.y})." : $"Client source zone ({val.x},{val.y}) is not loaded for terrain contact capture."); } catch (Exception ex) { zoneBundleClientTerrainCaptureResponse.Success = false; zoneBundleClientTerrainCaptureResponse.Message = "Client terrain contact capture failed: " + ex.Message; } return zoneBundleClientTerrainCaptureResponse; } [IteratorStateMachine(typeof(d__116))] private static IEnumerator ApplyClientTerrainRequestAsync(long sender, ZoneBundleClientTerrainApplyRequest request) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__116(0) { sender = sender, request = request }; } private static bool AllRequiredTerrainTargetsCanApply(IEnumerable work) { return work.Where((LoadWorkItem item) => RequiresTerrainApply(item.Bundle)).All((LoadWorkItem item) => ZoneBundleTerrain.CanApply(item.TargetZone)); } private static int CountRequiredTerrainTargets(IEnumerable work) { return RequiredTerrainTargetZones(work).Count; } private static List RequiredTerrainTargetZones(IEnumerable work) { return (from item in work where RequiresTerrainApply(item.Bundle) select item.TargetZone).Distinct().ToList(); } private static List GetTerrainWitnessCandidates(Vector2i zone, long preferredPeer) { //IL_0021: 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) if ((Object)(object)ZNet.instance == (Object)null) { return new List(); } List list = new List(); HashSet seen = new HashSet(); AddTerrainWitnessCandidate(list, seen, zone, preferredPeer, preferred: true); foreach (long item in TerrainWitnessPeers.ToList()) { AddTerrainWitnessCandidate(list, seen, zone, item, preferred: false); } return (from candidate in list orderby (!candidate.Preferred) ? 1 : 0, candidate.DistanceSqr select candidate.PeerId).ToList(); } private static void AddTerrainWitnessCandidate(List candidates, HashSet seen, Vector2i zone, long peerId, bool preferred) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) if (peerId == 0L || !seen.Add(peerId) || (Object)(object)ZNet.instance == (Object)null) { return; } ZNetPeer peer = ZNet.instance.GetPeer(peerId); float distanceSqr; if (peer == null || !peer.IsReady()) { TerrainWitnessPeers.Remove(peerId); } else if (TryGetPeerZoneDistanceSqr(peer, zone, out distanceSqr)) { float num = 25600f; if (!(distanceSqr > num)) { candidates.Add(new TerrainWitnessCandidate(peerId, distanceSqr, preferred)); } } } private static bool TryGetPeerZoneDistanceSqr(ZNetPeer peer, Vector2i zone, out float distanceSqr) { //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_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_0014: 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) //IL_0027: Unknown result type (might be due to invalid IL or missing references) distanceSqr = float.PositiveInfinity; Vector3 refPos = peer.m_refPos; Vector3 zonePos = ZoneSystem.GetZonePos(zone); float num = refPos.x - zonePos.x; float num2 = refPos.z - zonePos.z; distanceSqr = num * num + num2 * num2; return true; } private static List CreateTerrainContactCaptureEntries(ZoneBundleFile bundle) { List list = new List(); 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)) { list.Add(new ZoneBundleEntry { SaveId = entry.SaveId, Kind = entry.Kind, Prefab = entry.Prefab, LocalPos = entry.LocalPos, Rot = entry.Rot, Scale = entry.Scale }); } } } return list; } private static bool IsSupportFillBundle(ZoneBundleFile bundle) { return string.Equals(bundle.TerrainMode, "support-fill-v1", 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__127))] private static IEnumerator RequiresTerrainApplyAsync(ZoneBundleFile bundle, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__127(0) { bundle = bundle, onComplete = onComplete }; } [IteratorStateMachine(typeof(d__128))] private static IEnumerator HasWearNTearEntriesAsync(ZoneBundleFile bundle, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__128(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_004f: 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_0082: 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) Vector3 zonePos = ZoneSystem.GetZonePos(zone); bool useRelativePlacement = !float.IsNaN(sourceAnchor.BaseWorldY); List list = new List(); Dictionary creatorNames = new Dictionary(); List list2 = new List(); ZDOMan.instance.FindObjects(zone, list2); int staticCount = 0; int monsterCount = 0; foreach (ZDO item in list2) { if (TryCreateBundleEntry(item, zone, zonePos, sourceAnchor, useRelativePlacement, creatorNames, ref staticCount, ref monsterCount, out ZoneBundleEntry entry)) { list.Add(entry); } } bool contactsCaptured; List list3 = ZoneBundleTerrain.CaptureSupportContacts(zone, sourceAnchor.BaseWorldY, list, out contactsCaptured); terrainState = GetTerrainCaptureState(contactsCaptured, list3.Count); entries = list.Count; monsters = monsterCount; return CreateCapturedBundle(zone, tag, sourceAnchor, useRelativePlacement, list, creatorNames, list3, contactsCaptured, terrainState); } [IteratorStateMachine(typeof(d__131))] 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__131(0) { zone = zone, tag = tag, sourceAnchor = sourceAnchor, onComplete = onComplete }; } private static bool TryCreateBundleEntry(ZDO zdo, Vector2i zone, Vector3 zoneCenter, ZoneBundleTerrain.TerrainSourceAnchor sourceAnchor, bool useRelativePlacement, Dictionary creatorNames, ref int staticCount, ref int monsterCount, out ZoneBundleEntry entry) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //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_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_0162: 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_0185: 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_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: 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_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) entry = null; if (zdo == null || !zdo.IsValid()) { return false; } if (!TryClassify(zdo, out SaveEntryKind kind, out GameObject prefab)) { return false; } bool flag = (Object)(object)prefab.GetComponent() != (Object)null; bool flag2 = kind == SaveEntryKind.Monster; long num = (flag ? zdo.GetLong(ZDOVars.s_creator, 0L) : 0); string text = (flag ? zdo.GetString(ZDOVars.s_creatorName, "") : ""); AddCreatorPlayer(creatorNames, num, text); if (flag && !ZoneSaviorBuildRecipeRules.HasBuildRecipe(prefab)) { return false; } if (!ZoneBundleTerrain.IsSupportWearNTear(zdo, zone, out GameObject _) && !flag2) { return false; } ZoneBundleZdoData zoneBundleZdoData = new ZoneBundleZdoData(zdo); string text2 = ((kind == SaveEntryKind.Monster) ? "monster-v1" : ((!flag) ? "" : "wearntear-v1")); string sanitize = text2; SanitizeForSave(kind, zoneBundleZdoData, sanitize); Vector3 position = zdo.m_position; Quaternion rotation = zdo.GetRotation(); Vector3 val = ReadScale(zdo, prefab); ZoneBundleEntry zoneBundleEntry = new ZoneBundleEntry(); text2 = ((kind != SaveEntryKind.Monster) ? $"s_{++staticCount:D4}" : $"m_{++monsterCount: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 - zoneCenter.x), Round(useRelativePlacement ? (position.y - sourceAnchor.BaseWorldY) : position.y), Round(position.z - zoneCenter.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; entry = zoneBundleEntry; return true; } private static ZoneBundleFile CreateCapturedBundle(Vector2i zone, string tag, ZoneBundleTerrain.TerrainSourceAnchor sourceAnchor, bool useRelativePlacement, List zoneEntries, Dictionary creatorNames, List terrainContacts, bool contactsCaptured, ZoneBundleTerrainCaptureState terrainState) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) return new ZoneBundleFile { Tag = tag, SourceZone = ToModel(zone), TerrainMode = "support-fill-v1", SourceBaseY = (useRelativePlacement ? sourceAnchor.BaseWorldY : 0f), TerrainCaptureState = terrainState, TerrainContactsCaptured = contactsCaptured, TerrainContacts = terrainContacts, SourceZoneCreators = BuildSourceZoneCreators(creatorNames), Entries = zoneEntries.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() }; } 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_0045: Unknown result type (might be due to invalid IL or missing references) int removed = ClearTargetZone(targetZone); bool terrainApplied = false; if (terrainContext != null) { terrainApplied = ZoneBundleTerrain.ApplySupportFill(targetZone, bundle.Entries, bundle.TerrainContacts, bundle.TerrainContactsCaptured, terrainContext); } int num = 0; Vector3 zonePos = ZoneSystem.GetZonePos(targetZone); foreach (ZoneBundleEntry entry in bundle.Entries) { if (TryCreateLoadedZdo(entry, zonePos, bundle, terrainContext, yOffset, out ZDO zdo) && zdo != null) { ZNetScene.instance.CreateObject(zdo); num++; } } return new ZoneLoadStats(removed, num, terrainApplied); } [IteratorStateMachine(typeof(d__138))] private static IEnumerator ApplyBundleToZoneAsync(Vector2i targetZone, ZoneBundleFile bundle, TerrainPlacementContext? terrainContext, float yOffset, Action onComplete, bool applyTerrain = true) { //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__138(0) { targetZone = targetZone, bundle = bundle, terrainContext = terrainContext, yOffset = yOffset, onComplete = onComplete, applyTerrain = applyTerrain }; } private static bool TryCreateLoadedZdo(ZoneBundleEntry entry, Vector3 zoneCenter, ZoneBundleFile bundle, TerrainPlacementContext? terrainContext, float yOffset, out ZDO? zdo) { //IL_0099: 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_0130: 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_0133: Unknown result type (might be due to invalid IL or missing references) zdo = null; if (string.Equals(entry.Kind, "item", StringComparison.OrdinalIgnoreCase)) { return false; } 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.")); return false; } if (Object.op_Implicit((Object)(object)prefab.GetComponent())) { return false; } float num = terrainContext?.BaseWorldY ?? (bundle.SourceBaseY + yOffset); float num2 = (UsesRelativeY(bundle) ? (num + entry.LocalPos[1]) : (entry.LocalPos[1] + yOffset)); Vector3 position = default(Vector3); ((Vector3)(ref position))..ctor(zoneCenter.x + entry.LocalPos[0], num2, zoneCenter.z + entry.LocalPos[2]); Quaternion rotation = default(Quaternion); ((Quaternion)(ref rotation))..ctor(entry.Rot[0], entry.Rot[1], entry.Rot[2], entry.Rot[3]); Vector3 value = default(Vector3); ((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 = ZoneBundleZdoHelper.Init(prefab, position, rotation, value, data, EmptyParameters); return zdo != null; } internal static ZoneBundleCommandResult RestoreTagToOriginalZones(string tag) { //IL_0027: 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_0038: Unknown result type (might be due to invalid IL or missing references) ZoneBundleManifest zoneBundleManifest = ZoneBundleStore.LoadManifest(tag); List list = new List(); foreach (ZoneBundleManifestEntry bundle2 in zoneBundleManifest.Bundles) { Vector2i targetZone = ToVector2i(bundle2.Zone); ZoneBundleFile bundle = ZoneBundleStore.LoadBundleFromManifestEntry(tag, bundle2); list.Add(new LoadWorkItem(targetZone, bundle)); } ZoneLoadTotals zoneLoadTotals = ApplyLoadWork(list, exactSource: true, 0f); return ZoneBundleCommandResult.Ok($"Restored {list.Count} archived zone bundle(s) for tag '{tag}' " + $"(removed: {zoneLoadTotals.Removed}, created: {zoneLoadTotals.Created}, terrain: {zoneLoadTotals.TerrainApplied}/{list.Count})."); } [IteratorStateMachine(typeof(d__141))] internal static IEnumerator RestoreTagToOriginalZonesAsync(string tag, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__141(0) { tag = tag, onComplete = onComplete }; } internal static string MakeUniqueAutoArchiveTag(string preferredTag) { if (!ZoneBundleStore.ArchiveTagExists(preferredTag)) { return preferredTag; } for (int i = 2; i <= 999; i++) { string text = $"{preferredTag}_n{i:D3}"; if (!ZoneBundleStore.ArchiveTagExists(text)) { return text; } } throw new InvalidOperationException("Could not find a free archive tag for '" + preferredTag + "'."); } internal static ZoneBundleResetResult ResetGeneratedZones(IEnumerable sourceZones) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) List list = NormalizeZones(sourceZones); if (list.Count == 0) { return new ZoneBundleResetResult { Success = false, Message = "No zones to reset." }; } HashSet onlineCharacterIds = GetOnlineCharacterIds(); HashSet hashSet = list.ToHashSet(); int num = ResetZoneObjects(hashSet, onlineCharacterIds); foreach (Vector2i item in list) { ResetZoneSystemState(item); } ResetVerificationResult resetVerificationResult = VerifyResetObjects(hashSet, onlineCharacterIds); num += resetVerificationResult.Removed; ClutterSystem instance = ClutterSystem.instance; if (instance != null) { instance.ClearAll(); } RecalculateLoadedTerrain(); Minimap instance2 = Minimap.instance; if (instance2 != null) { instance2.UpdateLocationPins(1000f); } return BuildResetResult(list.Count, num, resetVerificationResult.Removed, resetVerificationResult.RemainingWearNTear); } [IteratorStateMachine(typeof(d__144))] internal static IEnumerator ResetGeneratedZonesAsync(IEnumerable sourceZones, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__144(0) { sourceZones = sourceZones, onComplete = onComplete }; } private static ResetVerificationResult VerifyResetObjects(HashSet zoneSet, HashSet characterIds) { int num = CountRemainingCreatorWearNTear(zoneSet, characterIds); if (num <= 0) { return new ResetVerificationResult(0, num); } int removed = ResetZoneObjects(zoneSet, characterIds); num = CountRemainingCreatorWearNTear(zoneSet, characterIds); return new ResetVerificationResult(removed, num); } [IteratorStateMachine(typeof(d__146))] private static IEnumerator VerifyResetObjectsAsync(HashSet zoneSet, HashSet characterIds, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__146(0) { zoneSet = zoneSet, characterIds = characterIds, onComplete = onComplete }; } private static ZoneBundleResetResult BuildResetResult(int zoneCount, int removed, int verificationRemoved, int remainingWearNTear) { string text = $"Reset {zoneCount} generated zone(s), removed {removed} ZDO(s)."; if (verificationRemoved > 0) { text += $" Verification pass removed {verificationRemoved} ZDO(s)."; _logger.LogWarning((object)text); } if (remainingWearNTear > 0) { text += $" {remainingWearNTear} creator WearNTear ZDO(s) still remain after reset."; _logger.LogWarning((object)text); } return new ZoneBundleResetResult { Success = (remainingWearNTear == 0), ZoneCount = zoneCount, RemovedCount = removed, RemainingWearNTearCount = remainingWearNTear, Message = text }; } 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()) { num += (TryDestroyOverwritableZdo(item) ? 1 : 0); } ZoneBundleZdoHelper.FlushDestroyed(); return num; } [IteratorStateMachine(typeof(d__149))] 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__149(0) { targetZone = targetZone, onComplete = onComplete }; } private static bool TryDestroyOverwritableZdo(ZDO zdo) { if (zdo == null || !zdo.IsValid()) { return false; } GameObject prefab = ZNetScene.instance.GetPrefab(zdo.GetPrefab()); if (!Object.op_Implicit((Object)(object)prefab) || !ShouldDeleteForOverwrite(prefab, zdo)) { return false; } ZoneBundleZdoHelper.Destroy(zdo); return true; } 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__153))] private static IEnumerator ResetZoneObjectsAsync(HashSet zones, HashSet protectedCharacterIds, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__153(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) && IsCreatorWearNTear(item)) { num++; } } return num; } [IteratorStateMachine(typeof(d__155))] private static IEnumerator CountRemainingCreatorWearNTearAsync(HashSet zones, HashSet protectedCharacterIds, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__155(0) { zones = zones, protectedCharacterIds = protectedCharacterIds, onComplete = onComplete }; } private static List GetResetZoneObjects(HashSet zones) { //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) //IL_002f: Unknown result type (might be due to invalid IL or missing references) List list = new List(); HashSet seen = new HashSet(); List list2 = new List(); foreach (Vector2i zone in zones) { list2.Clear(); ZDOMan.instance.FindObjects(zone, list2); foreach (ZDO item in list2) { if (TryCollectResetZoneObject(item, zones, seen, out ZDO resetObject)) { list.Add(resetObject); } } } return list; } private static bool TryCollectResetZoneObject(ZDO zdo, HashSet zones, HashSet seen, out ZDO resetObject) { //IL_0010: 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) resetObject = null; if (zdo == null || !zdo.IsValid() || !seen.Add(zdo.m_uid) || !zones.Contains(ZoneSystem.GetZone(zdo.GetPosition()))) { return false; } resetObject = zdo; return true; } 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 bool IsCreatorWearNTear(ZDO zdo) { if (zdo.GetLong(ZDOVars.s_creator, 0L) == 0L) { return false; } GameObject prefab = ZNetScene.instance.GetPrefab(zdo.GetPrefab()); if (Object.op_Implicit((Object)(object)prefab)) { return (Object)(object)prefab.GetComponent() != (Object)null; } 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__162))] private static IEnumerator RecalculateLoadedTerrainAsync() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__162(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); } } 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(); } 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 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; } public bool RestoreOriginal { get; set; } public bool LoadSourceZone { 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 Dictionary SupportRelativeHeights { get; set; } = new Dictionary(); } internal sealed class ZoneBundleClientTerrainApplyRequest { public string RequestId { get; set; } = ""; public string Operation { get; set; } = ""; public string Tag { get; set; } = ""; public TerrainPlacementContext? Context { get; set; } public List TargetZones { get; set; } = new List(); } internal sealed class ZoneBundleClientTerrainApplyResponse { public string RequestId { get; set; } = ""; public bool Success { get; set; } public string Message { get; set; } = ""; public int TargetZones { get; set; } public int ChangedZones { get; set; } } internal sealed class ZoneBundleClientTerrainCaptureRequest { public string RequestId { get; set; } = ""; public string Tag { get; set; } = ""; public ZoneBundleZone Zone { get; set; } = new ZoneBundleZone(); public float SourceBaseY { get; set; } public List Entries { get; set; } = new List(); } internal sealed class ZoneBundleClientTerrainCaptureResponse { public string RequestId { get; set; } = ""; public bool Success { get; set; } public string Message { get; set; } = ""; public bool ContactsCaptured { get; set; } public List Contacts { get; set; } = new List(); } 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 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 WorldSupportContactPlan { public Dictionary SupportHeights { get; } public List SupportCells { get; } public List Zones { get; } public bool HasSupport => SupportCells.Count > 0; public WorldSupportContactPlan(Dictionary supportHeights, List supportCells, List zones) { SupportHeights = supportHeights; SupportCells = supportCells; Zones = zones; } } 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 = ZoneBundleTerrainGrid.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(ZoneBundleTerrainGrid.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; } } private abstract class TerrainSupportStrategy { 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 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 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 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; } } [CompilerGenerated] private sealed class <>c__DisplayClass76_0 { public List samples; internal void b__0(List value) { samples = value; } } [CompilerGenerated] private sealed class <>c__DisplayClass82_0 { public bool changed; internal void b__0(bool result) { changed = result; } } [CompilerGenerated] private sealed class <>c__DisplayClass94_0 { public bool zoneChanged; internal void b__0(bool result) { zoneChanged = result; } } [CompilerGenerated] private sealed class d__98 : 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__98(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() { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; goto IL_0122; } <>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_0153; IL_0153: if (5__8 < 5__2) { 5__9 = 0; goto IL_0132; } if (!5__6) { onComplete(obj: false); return false; } PersistAppliedSupportCells(heightmap, 5__2, 5__3, 5__4, applyOptions); onComplete(obj: true); return false; IL_0122: 5__9++; goto IL_0132; IL_0132: if (5__9 < 5__2) { 5__6 |= ComputeSupportNode(heightmap, 5__2, 5__9, 5__8, supportHeights, 5__5, applyOptions, 5__3, 5__4); 5__7++; if (5__7 >= 1024) { 5__7 = 0; <>2__current = null; <>1__state = 1; return true; } goto IL_0122; } 5__8++; goto IL_0153; } 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__82 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Vector2i zone; public IEnumerable entries; public IEnumerable contacts; public bool contactsCaptured; public TerrainPlacementContext context; public Action onComplete; private <>c__DisplayClass82_0 <>8__1; 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() { <>8__1 = null; <>1__state = -2; } private bool MoveNext() { //IL_0026: 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__DisplayClass82_0(); Heightmap heightmap; TerrainSupportApplyOptions applyOptions; TerrainSupportApplicationPlan terrainSupportApplicationPlan = CreateSupportPlan(zone, entries, contacts, contactsCaptured, context, out heightmap, out 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__94 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public IEnumerable supportContacts; public Action onComplete; private <>c__DisplayClass94_0 <>8__1; private WorldSupportContactPlan 5__2; private bool 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__94(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 = default(WorldSupportContactPlan); <>7__wrap3 = default(List.Enumerator); <>1__state = -2; } private bool MoveNext() { //IL_0088: 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 = BuildWorldSupportContactPlan(supportContacts); if (5__2.HasSupport) { 5__3 = false; <>7__wrap3 = 5__2.Zones.GetEnumerator(); <>1__state = -3; break; } onComplete(obj: false); result2 = false; goto end_IL_0000; case 1: <>1__state = -3; 5__3 |= <>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__wrap3.MoveNext()) { Vector2i current = <>7__wrap3.Current; <>8__1 = new <>c__DisplayClass94_0(); if (!TryGetHeightmap(current, out Heightmap heightmap)) { onComplete(obj: false); result2 = false; <>m__Finally1(); } else { <>8__1.zoneChanged = false; <>2__current = ApplySupportCellsToHeightmapAsync(heightmap, 5__2.SupportHeights, 5__2.SupportCells, TerrainSupportApplyOptions.SupportContacts(), delegate(bool result) { <>8__1.zoneChanged = result; }); <>1__state = 1; result2 = true; } } else { <>m__Finally1(); <>7__wrap3 = default(List.Enumerator); onComplete(5__3); 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__wrap3).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 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__38(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_007d: 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; } while (<>7__wrap5.MoveNext()) { AddEntrySupportSamples(<>7__wrap5.Current, 5__3, baseWorldY, 5__4, 5__2); 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__72 : 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__72(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 = null; <>1__state = -2; } private bool MoveNext() { //IL_0053: 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; } if (<>7__wrap3.MoveNext()) { AccumulateSupportAnchor(<>7__wrap3.Current, ref 5__2, ref 5__3); <>2__current = null; <>1__state = 1; return true; } <>m__Finally1(); <>7__wrap3 = null; onComplete(CreateTerrainSourceAnchor(5__2, 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__wrap3 != null) { <>7__wrap3.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 IEnumerable targets; private <>c__DisplayClass76_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__76(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__DisplayClass76_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__51 : 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__51(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__51 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__51(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 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 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_0155: 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 = paints.Length == width * width; Color[] basePaints = (flag ? TryGetBasePaints(item.m_hmap, width) : null); if (ResetSupportFillHeights(item.m_hmap, width, worldHeights, dictionary.TryGetValue(item, out var value) ? value : null) | ResetSupportFillPaints(width, paints, basePaints, (flag && dictionary2.TryGetValue(item, out var value2)) ? value2 : null)) { if (IsSupportFillBaseLayerNative(item.m_hmap, width, worldHeights, paints, basePaints)) { 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 ResetSupportFillHeights(Heightmap heightmap, int width, float[] worldHeights, IEnumerable? heightSet) { //IL_0032: 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_0039: 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) if (heightSet == null) { return false; } bool result = false; foreach (int item in heightSet) { if (ZoneBundleTerrainGrid.IsValidPayloadIndex(item, width, worldHeights.Length)) { ZoneBundleTerrainGrid.IndexToXZ(item, width, out var x, out var z); Vector3 val = ZoneBundleTerrainGrid.VertexToWorld(heightmap, x, z); if (TryGetTerrainBaseHeight(val.x, val.z, out var height) && !(Mathf.Abs(worldHeights[item] - height) <= 0.01f)) { worldHeights[item] = height; result = true; } } } return result; } private static bool ResetSupportFillPaints(int width, Color[] paints, Color[]? basePaints, IEnumerable? paintSet) { //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_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_0046: Unknown result type (might be due to invalid IL or missing references) if (paintSet == null || basePaints == null) { return false; } bool result = false; foreach (int item in paintSet) { if (ZoneBundleTerrainGrid.IsValidPayloadIndex(item, width, paints.Length) && item < basePaints.Length) { Color val = basePaints[item]; if (!Approximately(paints[item], val)) { paints[item] = val; result = true; } } } return result; } 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 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++) { ZoneBundleTerrainGrid.IndexToXZ(i, width, out var x, out var z); Vector3 val = ZoneBundleTerrainGrid.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 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_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Expected O, but got Unknown //IL_0093: 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_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_009e: 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) List list = new List(); List list2 = new List(); for (int i = 0; i < worldHeights.Length; i++) { ZoneBundleTerrainGrid.IndexToXZ(i, width, out var x, out var z); float terrainBaseOrCurrentHeight = GetTerrainBaseOrCurrentHeight(heightmap, x, z); if (!(Mathf.Abs(worldHeights[i] - terrainBaseOrCurrentHeight) <= 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 val = new ZPackage(); val.Write(3); val.Write(width); val.Write(worldHeights.Length); val.Write(list.Count); for (int k = 0; k < list.Count; k++) { val.Write(list[k]); val.Write(list2[k]); } val.Write(list3.Count); for (int l = 0; l < list3.Count; l++) { val.Write(list3[l]); WriteColor(val, list4[l]); } return Utils.Compress(val.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_00d7: 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) //IL_00f3: 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) 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++) { ZoneBundleTerrainGrid.IndexToXZ(i, width, out var x, out var z); worldHeights[i] = GetTerrainBaseOrCurrentHeight(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 val = ReadColor(package); if (num5 < 0 || num5 >= paints.Length) { return false; } paints[num5] = val; } 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) { 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++) { ZoneBundleTerrainGrid.IndexToXZ(i, width, out var x, out var z); float terrainBaseOrCurrentHeight = GetTerrainBaseOrCurrentHeight(compiler.m_hmap, x, z); float num3 = Mathf.Clamp(worldHeights[i] - terrainBaseOrCurrentHeight, 0f - num2, num2); compiler.m_smoothDelta[i] = 0f; compiler.m_levelDelta[i] = num3; compiler.m_modifiedHeight[i] = Mathf.Abs(num3) > 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 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()); } 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 = ZoneBundleTerrainGrid.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 GetMedianOffset(list); } return result; } 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 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_0026: Unknown result type (might be due to invalid IL or missing references) List list = new List(); Vector3 zonePos = ZoneSystem.GetZonePos(zone); bool useWorldY = !float.IsNaN(baseWorldY); foreach (ZoneBundleEntry entry in entries) { AddEntrySupportSamples(entry, zonePos, baseWorldY, useWorldY, list); } return list; } [IteratorStateMachine(typeof(d__38))] 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__38(0) { zone = zone, entries = entries, baseWorldY = baseWorldY, onComplete = onComplete }; } private static void AddEntrySupportSamples(ZoneBundleEntry entry, Vector3 zoneCenter, float baseWorldY, bool useWorldY, List samples) { //IL_0042: 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_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: 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_00d7: Unknown result type (might be due to invalid IL or missing references) GameObject prefab = ZNetScene.instance.GetPrefab(entry.Prefab); if (!Object.op_Implicit((Object)(object)prefab) || (Object)(object)prefab.GetComponent() == (Object)null) { return; } float num = (useWorldY ? (baseWorldY + entry.LocalPos[1]) : entry.LocalPos[1]); Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(zoneCenter.x + entry.LocalPos[0], num, zoneCenter.z + entry.LocalPos[2]); Quaternion rotation = default(Quaternion); ((Quaternion)(ref rotation))..ctor(entry.Rot[0], entry.Rot[1], entry.Rot[2], entry.Rot[3]); Vector3 scale = default(Vector3); ((Vector3)(ref scale))..ctor(entry.Scale[0], entry.Scale[1], entry.Scale[2]); List list = new List(); AddWearNTearSupportSamples(prefab, val, rotation, scale, useWorldY ? baseWorldY : 0f, list); float num2 = (useWorldY ? (val.y - baseWorldY) : entry.LocalPos[1]) - 8f; foreach (TerrainSupportSample item in list) { if (item.RelativeY >= num2) { samples.Add(item); } } } 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__51))] 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__51(-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); } public static TerrainSourceAnchor ComputeSupportAnchor(IEnumerable zones) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) float min = float.PositiveInfinity; float tamedFallbackMin = float.PositiveInfinity; foreach (Vector2i zone in zones) { AccumulateSupportAnchor(zone, ref min, ref tamedFallbackMin); } return CreateTerrainSourceAnchor(min, tamedFallbackMin); } [IteratorStateMachine(typeof(d__72))] public static IEnumerator ComputeSupportAnchorAsync(IEnumerable zones, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__72(0) { zones = zones, onComplete = onComplete }; } private static void AccumulateSupportAnchor(Vector2i zone, ref float min, ref float tamedFallbackMin) { //IL_0020: 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_009c: 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_0053: 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_00aa: 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_0075: 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) if (ZDOMan.instance == null || (Object)(object)ZNetScene.instance == (Object)null) { return; } 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)) { min = Mathf.Min(min, ((Bounds)(ref bounds)).min.y); } if (TryReadTamedMonster(item, zone, out GameObject _)) { tamedFallbackMin = Mathf.Min(tamedFallbackMin, item.GetPosition().y); } } } private static TerrainSourceAnchor CreateTerrainSourceAnchor(float min, float tamedFallbackMin) { if (!float.IsPositiveInfinity(min)) { return new TerrainSourceAnchor(min); } if (!float.IsPositiveInfinity(tamedFallbackMin)) { return new TerrainSourceAnchor(tamedFallbackMin); } return new TerrainSourceAnchor(float.NaN); } 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__76))] public static IEnumerator CreateSupportFillPlacementContextAsync(IEnumerable targets, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__76(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 }; 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[ZoneBundleTerrainGrid.PackCell(x, z)] = item.RelativeY; } } return terrainPlacementContext; } public static TerrainPlacementContext CreateExactContext(float sourceBaseY) { return new TerrainPlacementContext { BaseWorldY = sourceBaseY }; } 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_0000: Unknown result type (might be due to invalid IL or missing references) Heightmap heightmap; TerrainSupportApplyOptions applyOptions; TerrainSupportApplicationPlan terrainSupportApplicationPlan = CreateSupportPlan(zone, entries, contacts, contactsCaptured, context, out heightmap, out 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_0000: Unknown result type (might be due to invalid IL or missing references) Heightmap heightmap; TerrainSupportApplyOptions applyOptions; return CreateSupportPlan(zone, entries, contacts, contactsCaptured, context, out heightmap, out applyOptions).HasSupport; } [IteratorStateMachine(typeof(d__82))] 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__82(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 CreateSupportPlan(Vector2i zone, IEnumerable entries, IEnumerable contacts, bool contactsCaptured, TerrainPlacementContext context, out Heightmap heightmap, out TerrainSupportApplyOptions applyOptions) { //IL_0023: 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_0032: 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) List list = contacts.ToList(); bool hasContacts = contactsCaptured && list.Count > 0; applyOptions = TerrainSupportApplyOptions.ZoneBundle(); if (!TryGetHeightmap(zone, out 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); } 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) { ZoneBundleTerrainGrid.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) { ZoneBundleTerrainGrid.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 = ZoneBundleTerrainGrid.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_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_002b: 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_0045: Unknown result type (might be due to invalid IL or missing references) WorldSupportContactPlan worldSupportContactPlan = BuildWorldSupportContactPlan(supportContacts); if (!worldSupportContactPlan.HasSupport) { return false; } bool flag = false; foreach (Vector2i zone in worldSupportContactPlan.Zones) { if (!TryGetHeightmap(zone, out Heightmap heightmap)) { throw new InvalidOperationException($"Target terrain zone ({zone.x},{zone.y}) is not loaded for support contact placement."); } flag |= ApplySupportCellsToHeightmap(heightmap, worldSupportContactPlan.SupportHeights, worldSupportContactPlan.SupportCells, TerrainSupportApplyOptions.SupportContacts()); } return flag; } [IteratorStateMachine(typeof(d__94))] public static IEnumerator ApplyWorldSupportContactsAsync(IEnumerable supportContacts, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__94(0) { supportContacts = supportContacts, onComplete = onComplete }; } private static WorldSupportContactPlan BuildWorldSupportContactPlan(IEnumerable supportContacts) { 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 ZoneBundleTerrainGrid.PackCell(cell.X, cell.Z) into @group select @group.OrderBy((TerrainSupportCell cell) => cell.Height).First()).ToList(); Dictionary supportHeights = list.ToDictionary((TerrainSupportCell cell) => ZoneBundleTerrainGrid.PackCell(cell.X, cell.Z), (TerrainSupportCell cell) => cell.Height); List zones = list.Select((TerrainSupportCell cell) => ZoneSystem.GetZone(new Vector3((float)cell.X, 0f, (float)cell.Z))).Distinct().ToList(); return new WorldSupportContactPlan(supportHeights, list, zones); } 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) { int num = heightmap.m_width + 1; float[] worldHeights = new float[num * num]; Color[] paints = (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++) { flag |= ComputeSupportNode(heightmap, num, j, i, supportHeights, supportIndex, applyOptions, worldHeights, paints); } } if (flag) { return PersistAppliedSupportCells(heightmap, num, worldHeights, paints, applyOptions); } return false; } [IteratorStateMachine(typeof(d__98))] 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__98(0) { heightmap = heightmap, supportHeights = supportHeights, supportCells = supportCells, applyOptions = applyOptions, onComplete = onComplete }; } private static bool ComputeSupportNode(Heightmap heightmap, int width, int x, int z, Dictionary supportHeights, TerrainSupportCellIndex supportIndex, TerrainSupportApplyOptions applyOptions, float[] worldHeights, Color[] paints) { //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_0018: 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_003c: 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_0048: 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_007a: Unknown result type (might be due to invalid IL or missing references) int num = z * width + x; Vector3 val = ZoneBundleTerrainGrid.VertexToWorld(heightmap, x, z); float worldHeight = GetWorldHeight(heightmap, x, z); float height; float num2 = (TryGetTerrainBaseHeight(val.x, val.z, out height) ? height : worldHeight); float num3 = num2; paints[num] = GetPaint(heightmap, x, z); float height2; if (supportHeights.TryGetValue(ZoneBundleTerrainGrid.PackCell(Mathf.RoundToInt(val.x), Mathf.RoundToInt(val.z)), out var value)) { num3 = applyOptions.ClampTerrainDelta(value, num2); } else if (TryGetFeatheredSupportHeight(val, num2, supportIndex, applyOptions.FeatherWidth, out height2)) { num3 = applyOptions.ClampTerrainDelta(height2, num2); } worldHeights[num] = num3; return Mathf.Abs(worldHeight - num3) > 0.01f; } private static bool PersistAppliedSupportCells(Heightmap heightmap, int width, float[] worldHeights, Color[] paints, TerrainSupportApplyOptions applyOptions) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) PersistSupportFillTerrain(heightmap.GetAndCreateTerrainCompiler(), width, worldHeights, paints, applyOptions); heightmap.Poke(false); ClutterSystem instance = ClutterSystem.instance; if (instance != null) { instance.ResetGrass(((Component)heightmap).transform.position, 48f); } return true; } 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 float GetTerrainBaseOrCurrentHeight(Heightmap heightmap, int x, int z) { //IL_0003: 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_000f: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ZoneBundleTerrainGrid.VertexToWorld(heightmap, x, z); if (!TryGetTerrainBaseHeight(val.x, val.z, out var height)) { return GetWorldHeight(heightmap, x, z); } return height; } 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; } } internal static class ZoneBundleTerrainGrid { public static long PackCell(int x, int z) { return ((long)x << 32) ^ (uint)z; } public static void UnpackCell(long key, out int x, out int z) { x = (int)(key >> 32); z = (int)key; } public static bool IsValidPayloadIndex(int index, int width, int length) { if (width > 0 && index >= 0 && index < length) { return index < width * width; } return false; } public static void IndexToXZ(int index, int width, out int x, out int z) { z = index / width; x = index - z * width; } public 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; } } 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 SupportContacts() { return new TerrainSupportApplyOptions(ZoneBundleConfig.SupportFillFeatherWidth, 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 ZoneBundleStore { public static string GetManifestPath(string tag) { return Path.Combine(GetTagDirectory(tag), "manifest.yml"); } public static string GetBundlePath(string tag, int index) { return Path.Combine(GetTagDirectory(tag), $"bundle{index:D3}.zonebundle.yml"); } public static string GetBundlePath(string tag, ZoneBundleManifestEntry entry) { return Path.Combine(GetTagDirectory(tag), entry.File); } public static bool ArchiveTagExists(string tag) { if (!Directory.Exists(GetTagDirectory(tag))) { return File.Exists(GetManifestPath(tag)); } return true; } public static ZoneBundleManifest LoadManifest(string tag) { return ZoneBundleSerialization.LoadManifest(GetManifestPath(tag)); } public static void SaveManifest(string manifestPath, ZoneBundleManifest manifest) { ZoneBundleSerialization.SaveManifest(manifestPath, manifest); } public static void SaveBundle(string path, ZoneBundleFile bundle) { ZoneBundleSerialization.SaveBundle(path, bundle); } public static ZoneBundleFile LoadBundleFromManifestZone(string tag, Vector2i zone) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return ZoneBundleSerialization.LoadBundle(GetBundlePathFromManifest(tag, zone)); } public static bool TryLoadBundleFromManifestZone(string tag, Vector2i zone, out ZoneBundleFile bundle, out string reason) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) bundle = null; try { bundle = LoadBundleFromManifestZone(tag, zone); reason = ""; return true; } catch (Exception ex) { reason = ex.Message; return false; } } public static ZoneBundleFile LoadBundleFromManifestEntry(string tag, ZoneBundleManifestEntry entry) { return ZoneBundleSerialization.LoadBundle(GetBundlePath(tag, entry)); } public static bool TryLoadBundleFromManifestEntry(string tag, ZoneBundleManifestEntry entry, out ZoneBundleFile bundle, out string reason) { return TryLoadBundleFile(GetBundlePath(tag, entry), out bundle, out reason); } public static string GetTagDirectory(string tag) { return Path.Combine(ZoneSaviorPlugin.ZoneBundleStorageFullPath, ZoneSaviorPaths.SanitizePathSegment(tag)); } 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 = LoadManifest(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 = ZoneSaviorZones.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 GetBundlePath(tag, zoneBundleManifestEntry); } 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; } } } 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 (ZoneSaviorSteamIds.TryNormalizePlatformId(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 = (ZoneSaviorSteamIds.IsBareSteamId64(steamId) ? steamId.Trim() : ""); 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 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++) { if (!ZoneSaviorSteamIds.IsBareSteamId64(file.SteamIds[i])) { 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 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 = ZoneExternalPieceMarkers.ShouldForceCount(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 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 static class ZoneStructureClassifier { public static bool TryInspectAutoArchiveCandidate(ZDO zdo, out ZoneStructureInfo info) { info = Inspect(zdo); return info.AutoArchiveCandidatePiece; } public static ZoneStructureInfo Inspect(ZDO zdo, Vector2i? requestedZone = null) { //IL_0024: 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_002a: 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_0030: 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_006e: 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_0082: 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_00d8: Unknown result type (might be due to invalid IL or missing references) ZoneStructureInfo zoneStructureInfo = new ZoneStructureInfo(); if (zdo == null || !zdo.IsValid()) { zoneStructureInfo.ExclusionReasons.Add("invalid_zdo"); return zoneStructureInfo; } Vector3 position = zdo.GetPosition(); Vector2i zone = ZoneSystem.GetZone(position); ZNetScene instance = ZNetScene.instance; GameObject val = ((instance != null) ? instance.GetPrefab(zdo.GetPrefab()) : null); bool flag = (Object)(object)val != (Object)null && Object.op_Implicit((Object)(object)val); bool flag2 = !requestedZone.HasValue || (zone.x == requestedZone.Value.x && zone.y == requestedZone.Value.y); zoneStructureInfo.ZdoId = ((object)(ZDOID)(ref zdo.m_uid)).ToString(); zoneStructureInfo.PrefabHash = zdo.GetPrefab(); zoneStructureInfo.Prefab = (flag ? Utils.GetPrefabName(val) : ""); zoneStructureInfo.Position = position; zoneStructureInfo.ObjectZone = zone; zoneStructureInfo.CreatorPlayerId = zdo.GetLong(ZDOVars.s_creator, 0L); zoneStructureInfo.CreatorName = zdo.GetString(ZDOVars.s_creatorName, ""); zoneStructureInfo.HasPrefab = flag; zoneStructureInfo.HasZNetView = flag && (Object)(object)val.GetComponent() != (Object)null; zoneStructureInfo.HasWearNTear = flag && (Object)(object)val.GetComponent() != (Object)null; zoneStructureInfo.HasPiece = flag && (Object)(object)val.GetComponent() != (Object)null; zoneStructureInfo.HasBuildRecipe = flag && ZoneSaviorBuildRecipeRules.HasBuildRecipe(val); zoneStructureInfo.InRequestedZone = flag2; if (!flag2) { zoneStructureInfo.ExclusionReasons.Add("outside_requested_zone"); } if (!flag) { zoneStructureInfo.ExclusionReasons.Add("prefab_missing"); } if (flag && !zoneStructureInfo.HasZNetView) { zoneStructureInfo.ExclusionReasons.Add("no_znetview"); } if (!zoneStructureInfo.HasWearNTear) { zoneStructureInfo.ExclusionReasons.Add("not_wearntear"); } if (zoneStructureInfo.CreatorPlayerId == 0L) { zoneStructureInfo.ExclusionReasons.Add("creatorless_or_missing_creator"); } if (zoneStructureInfo.HasWearNTear && !zoneStructureInfo.HasBuildRecipe) { zoneStructureInfo.ExclusionReasons.Add("no_player_build_recipe_or_resource_cost"); } zoneStructureInfo.AutoArchiveCandidatePiece = flag2 && zoneStructureInfo.CreatorPlayerId != 0L && zoneStructureInfo.HasWearNTear && zoneStructureInfo.HasBuildRecipe; if (zoneStructureInfo.AutoArchiveCandidatePiece) { zoneStructureInfo.ExclusionReasons.Clear(); } return zoneStructureInfo; } } internal sealed class ZoneStructureInfo { public string ZdoId { get; set; } = ""; public int PrefabHash { get; set; } public string Prefab { get; set; } = ""; public Vector3 Position { get; set; } public Vector2i ObjectZone { get; set; } 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; } = new List(); } 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 ZoneExternalPieceMarkers { private static readonly int HomesteadBlueprintPieceHash = StringExtensionMethods.GetStableHashCode("sighsorry.Homestead.blueprint_piece"); public static bool ShouldForceCount(ZDO zdo) { return zdo.GetBool(HomesteadBlueprintPieceHash, false); } } internal static class ZoneSaviorBuildRecipeRules { 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 sealed class ConfigurationManagerAttributes { public int Order { get; set; } } internal static class ConfigSections { public const string General = "01 - General"; public const string ZoneSavior = "02 - ZoneSavior"; public const string AutoArchive = "03 - Auto Archive"; public const string TerrainTool = "04 - Terrain Tool"; } internal static class ConfigDescriptions { public static ConfigDescription Ordered(string description, int order) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown return new ConfigDescription(description, (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = order } }); } public static ConfigDescription Ordered(string description, AcceptableValueBase acceptableValues, int order) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown return new ConfigDescription(description, acceptableValues, new object[1] { new ConfigurationManagerAttributes { Order = order } }); } } 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("02 - ZoneSavior", "Zone WearNTear Limit", ZoneSaviorPlugin.Toggle.Off, ConfigDescriptions.Ordered("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.", 590)); _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_004e: Unknown result type (might be due to invalid IL or missing references) _counterVisibleSeconds = plugin.config("02 - ZoneSavior", "Build Counter Visible Seconds", 2.5f, ConfigDescriptions.Ordered("How long the top build counter stays visible after you place a build piece.", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 10f), 570), synchronizedSetting: false); _zoneUiToggleHotkey = plugin.config("02 - ZoneSavior", "Zone UI Toggle Hotkey", new KeyboardShortcut((KeyCode)289, Array.Empty()), ConfigDescriptions.Ordered("Client-only hotkey that toggles the current zone number HUD and floor boundary line. The Zone UI starts hidden after login.", 580), 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) { _wearNTearSaveMode = plugin.config("02 - ZoneSavior", "WearNTear Save Mode", ZoneBundleWearNTearSaveMode.CreatorOnly, ConfigDescriptions.Ordered("Controls which WearNTear objects SupportFill saves. CreatorOnly saves only player-created WearNTear. IncludeCreatorless also saves WearNTear with no creator id.", 600)); _supportFillFeatherWidth = plugin.config("02 - ZoneSavior", "Zone Bundle Support Fill Feather Width", 6f, ConfigDescriptions.Ordered("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), 550)); _supportFillContactTolerance = plugin.config("02 - ZoneSavior", "Support Fill Contact Tolerance", 0.5f, ConfigDescriptions.Ordered("How close loaded source-zone terrain must be to a WearNTear bottom at a 1m x/z cell to be saved as a terrain contact. If the source zone terrain is not loaded, terrain contacts cannot be captured and SupportFill falls back to prefab footprint bounds.", (AcceptableValueBase)(object)new AcceptableValueRange(0.01f, 2f), 560)); } } internal static class AutoArchiveConfig { private static ConfigEntry _inactiveDays; private static ConfigEntry _dryRun; private static ConfigEntry _resetAfterSave; private static ConfigEntry _minimumPiecesPerCluster; private static ConfigEntry _maxZonesPerRun; private static ConfigEntry _scanIntervalMinutes; 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 int MinimumPiecesPerCluster => Mathf.Clamp(_minimumPiecesPerCluster.Value, 1, 10000); public static int MaxZonesPerRun => Mathf.Clamp(_maxZonesPerRun.Value, 1, 10000); public static int ScanIntervalMinutes => Mathf.Clamp(_scanIntervalMinutes.Value, 0, 525600); public static int ScannerBatchSize => Mathf.Clamp(_scannerBatchSize.Value, 100, 10000); public static void Bind(ZoneSaviorPlugin plugin) { _dryRun = plugin.config("03 - Auto Archive", "Dry Run", ZoneSaviorPlugin.Toggle.On, ConfigDescriptions.Ordered("If on, auto archive only reports candidate zones and never saves or resets them.", 700)); _resetAfterSave = plugin.config("03 - Auto Archive", "Reset After Save", ZoneSaviorPlugin.Toggle.Off, ConfigDescriptions.Ordered("If on, saved candidate zones are reset after their bundle is written.", 690)); _minimumPiecesPerCluster = plugin.config("03 - Auto Archive", "Minimum Pieces Per Cluster", 5, ConfigDescriptions.Ordered("Candidate clusters with fewer player structures are not saved. During reset runs, they are reset without saving; otherwise they are skipped.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 10000), 680)); _inactiveDays = plugin.config("03 - Auto Archive", "Inactive Days", 30, ConfigDescriptions.Ordered("A creator must be unseen for this many days before their zones can be archived. Existing-world owners first discovered by the scanner use that discovery time as their last seen time.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 3650), 670)); _scanIntervalMinutes = plugin.config("03 - Auto Archive", "Scan Interval Minutes", 0, ConfigDescriptions.Ordered("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), 660)); _scannerBatchSize = plugin.config("03 - Auto Archive", "Scanner Batch Size", 1000, ConfigDescriptions.Ordered("How many ZDOs the auto archive scanner inspects before yielding a frame.", (AcceptableValueBase)(object)new AcceptableValueRange(100, 10000), 650)); _maxZonesPerRun = plugin.config("03 - Auto Archive", "Max Zones Per Run", 50, ConfigDescriptions.Ordered("Maximum number of zones to save or reset in one automatic run.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 10000), 640)); } } internal static class AdminTerrainToolConfig { private static ConfigEntry _radius; private static ConfigEntry _slopeWidth; private static ConfigEntry _terrainEdgeSoftness; private static ConfigEntry _paintType; private static ConfigEntry _terrainToolModifierKey; public static float Radius => Mathf.Clamp(_radius.Value, 0.5f, 128f); public static float SlopeWidth => Mathf.Clamp(_slopeWidth.Value, 0.5f, 256f); public static float TerrainEdgeSoftness => Mathf.Clamp01(_terrainEdgeSoftness.Value); public static AdminTerrainPaintType PaintType => _paintType.Value; public static KeyboardShortcut TerrainToolModifierKey => _terrainToolModifierKey.Value; public static void Bind(ZoneSaviorPlugin plugin) { //IL_00e6: Unknown result type (might be due to invalid IL or missing references) _radius = plugin.config("04 - Terrain Tool", "Radius", 8f, ConfigDescriptions.Ordered("Default circle radius for newly placed terrain proxy objects.", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 128f), 500)); _slopeWidth = plugin.config("04 - Terrain Tool", "Slope Width", 8f, ConfigDescriptions.Ordered("Width in meters for the ZoneSavior TerrainProxy Slope created between two placed slope markers.", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 256f), 490)); _terrainEdgeSoftness = plugin.config("04 - Terrain Tool", "Terrain Edge Softness", 0f, ConfigDescriptions.Ordered("Softness for ZoneSavior Terrain Proxy edges. 0 keeps a hard cylinder edge, 1 rounds the whole circle toward the edge.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1f), 480)); _paintType = plugin.config("04 - Terrain Tool", "Paint Type", AdminTerrainPaintType.Dirt, ConfigDescriptions.Ordered("Paint type for newly placed ZoneSavior Paint Proxy objects.", 470)); _terrainToolModifierKey = plugin.config("04 - Terrain Tool", "Terrain Tool Modifier Key", new KeyboardShortcut((KeyCode)308, Array.Empty()), ConfigDescriptions.Ordered("Client-only modifier key used with mouse wheel by ZoneSavior terrain tools.", 460), synchronizedSetting: false); } } internal enum AdminTerrainPaintType { Grass = 0, Dirt = 1, Cultivated = 2, Cultivate = 2, Paved = 3, DarkGrass = 4, PatchyGrass = 5, MossyPaving = 6, DirtPaving = 7, DarkPaving = 8, ClearVegetation = 10 } internal static class ZoneSaviorFeatureBootstrap { public static void Initialize(ManualLogSource logger) { ZoneSaviorInputBlockers.Initialize(logger); ZoneLimitConfiguration.Initialize(ZoneSaviorPlugin.ConfigSync, logger); ZonePieceCounter.Initialize(logger); ZoneBundleCommands.Initialize(logger); AutoArchiveStore.Initialize(logger); AutoArchiveService.Initialize(logger); AutoArchiveCommands.Initialize(logger); AdminTerrainTool.Initialize(logger); } public static void InitializeCompat(ManualLogSource logger, Harmony harmony) { ZoneWorldEditTerrainCompat.Initialize(logger, harmony); AdminTerrainTool.InitializeCompat(harmony); VeiledRecipesCompat.Initialize(logger); } public static void Update() { ZoneBundleCommands.RegisterRpcs(); AutoArchiveCommands.RegisterRpcs(); ZoneWorldEditTerrainCompat.Update(); AutoArchiveService.Update(); ZoneBoundaryOverlay.Update(); AdminTerrainTool.Update(); } public static void LateUpdate() { AdminTerrainTool.LateUpdate(); } public static void Shutdown() { ZonePieceCounter.Clear(); ZoneBoundaryOverlay.Shutdown(); AutoArchiveService.Shutdown(); AutoArchiveStore.Flush(force: true); AdminTerrainTool.Shutdown(); } public static void ReloadZoneRulesFromDisk() { ZoneLimitConfiguration.ReloadFromDisk(); } public static bool TryReloadActivityFromDisk(out string message) { return AutoArchiveStore.TryReloadFromDiskIfSafe(AutoArchiveService.IsScanRunning, out message); } } internal static class ZoneSaviorInputBlockers { private static ManualLogSource? _logger; private static bool _useTextInputFallback; private static bool _loggedTextInputFallback; internal static void Initialize(ManualLogSource logger) { _logger = logger; } internal static bool IsTextInputVisible() { if (!_useTextInputFallback) { try { return TextInput.IsVisible() || IsFocusedInputField(); } catch (Exception ex) { _useTextInputFallback = true; LogTextInputFallback(ex); } } if (!IsValheimTextInputVisible()) { return IsFocusedInputField(); } return true; } private static bool IsValheimTextInputVisible() { TextInput instance = TextInput.instance; if (Object.op_Implicit((Object)(object)instance)) { return instance.m_visibleFrame; } return false; } private static bool IsFocusedInputField() { EventSystem current = EventSystem.current; if ((Object)(object)current == (Object)null) { return false; } GameObject currentSelectedGameObject = current.currentSelectedGameObject; if (!Object.op_Implicit((Object)(object)currentSelectedGameObject)) { return false; } InputField val = currentSelectedGameObject.GetComponent() ?? currentSelectedGameObject.GetComponentInParent(); if ((Object)(object)val != (Object)null && val.isFocused) { return true; } TMP_InputField val2 = currentSelectedGameObject.GetComponent() ?? currentSelectedGameObject.GetComponentInParent(); if ((Object)(object)val2 != (Object)null) { return val2.isFocused; } return false; } private static void LogTextInputFallback(Exception ex) { if (!_loggedTextInputFallback) { _loggedTextInputFallback = true; ManualLogSource? logger = _logger; if (logger != null) { logger.LogWarning((object)("TextInput.IsVisible failed (" + ex.GetType().Name + ": " + ex.Message + "); using ZoneSavior's safe input visibility fallback.")); } } } } [BepInPlugin("sighsorry.ZoneSavior", "ZoneSavior", "1.0.7")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class ZoneSaviorPlugin : BaseUnityPlugin { public enum Toggle { On = 1, Off = 0 } internal const string ModName = "ZoneSavior"; internal const string ModVersion = "1.0.7"; 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.7", MinimumRequiredVersion = "1.0.7" }; 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 FileSystemWatcher? _activityWatcher; private DateTime _lastConfigReloadTime; private DateTime _lastZoneRuleReloadTime; private DateTime _lastActivityReloadTime; 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(); _activityWatcher?.Dispose(); } private void Update() { ZoneSaviorFeatureBootstrap.Update(); } private void LateUpdate() { ZoneSaviorFeatureBootstrap.LateUpdate(); } private void BindConfiguration() { GeneralConfig.Bind(this); ClientConfig.Bind(this); ZoneBundleConfig.Bind(this); AutoArchiveConfig.Bind(this); AdminTerrainToolConfig.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; _activityWatcher = new FileSystemWatcher(DataStorageFullPath, "activity.yml"); _activityWatcher.Changed += ReadActivityValues; _activityWatcher.Created += ReadActivityValues; _activityWatcher.Renamed += ReadActivityValues; _activityWatcher.IncludeSubdirectories = false; _activityWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; _activityWatcher.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 void ReadActivityValues(object sender, FileSystemEventArgs e) { if (!CanReload(ref _lastActivityReloadTime)) { return; } lock (_reloadLock) { try { if (ZoneSaviorFeatureBootstrap.TryReloadActivityFromDisk(out string message)) { ZoneSaviorLogger.LogInfo((object)message); } else { ZoneSaviorLogger.LogDebug((object)message); } } catch (Exception arg) { ZoneSaviorLogger.LogError((object)$"Error reloading activity 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(); } } public static bool IsOn(this ZoneSaviorPlugin.Toggle value) { return value == ZoneSaviorPlugin.Toggle.On; } } 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(); } 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_003d: 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) point = default(Vector3); if ((Object)(object)player == (Object)null) { return false; } if (TryGetCameraRay(out var origin, out var direction)) { int mask = ((player.m_placeRayMask != 0) ? player.m_placeRayMask : (-5)); float rayDistance = Mathf.Max(50f, maxToolDistance); if (TryRaycastAim(player, origin, direction, rayDistance, mask, null, out point)) { point.y = SampleGroundY(point.x, point.z, point.y); return true; } } return false; } public static bool TryGetRawAimPoint(Player player, float maxToolDistance, GameObject? ignoreRoot, out Vector3 point) { //IL_0001: 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_003e: 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_0053: Unknown result type (might be due to invalid IL or missing references) point = default(Vector3); if ((Object)(object)player == (Object)null || !TryGetCameraRay(out var origin, out var direction)) { return false; } float rayDistance = Mathf.Max(50f, maxToolDistance); int num = ((player.m_placeRayMask != 0) ? player.m_placeRayMask : (-5)); if (TryRaycastAim(player, origin, direction, rayDistance, num, ignoreRoot, out point)) { return true; } if (num != -5) { return TryRaycastAim(player, origin, direction, rayDistance, -5, ignoreRoot, out point); } 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; } private static bool TryRaycastAim(Player player, Vector3 origin, Vector3 direction, float rayDistance, int mask, GameObject? ignoreRoot, out Vector3 point) { //IL_0002: 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_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_0091: 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) point = default(Vector3); RaycastHit[] array = Physics.RaycastAll(origin, direction, rayDistance, mask, (QueryTriggerInteraction)1); Array.Sort(array, (RaycastHit left, RaycastHit right) => ((RaycastHit)(ref left)).distance.CompareTo(((RaycastHit)(ref right)).distance)); RaycastHit[] array2 = array; for (int i = 0; i < array2.Length; i++) { RaycastHit val = array2[i]; Collider collider = ((RaycastHit)(ref val)).collider; if (Object.op_Implicit((Object)(object)collider)) { Transform transform = ((Component)collider).transform; if ((!Object.op_Implicit((Object)(object)ignoreRoot) || !transform.IsChildOf(ignoreRoot.transform)) && (!Object.op_Implicit((Object)(object)player) || !transform.IsChildOf(((Component)player).transform))) { point = ((RaycastHit)(ref val)).point; return true; } } } 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_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown if (_patched || !Chainloader.PluginInfos.ContainsKey("world_edit_commands")) { 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.LogDebug((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; } } }