Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of OdinEyeClient v1.2.31
plugins/OdinEye.Client.dll
Decompiled a day agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Net.Http; using System.Net.Http.Headers; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using OdinEye.Client.Counters; using OdinEye.Client.Events; using OdinEye.Client.Hud; using OdinEye.Client.Patches; using OdinEye.Client.Stats; using OdinEye.Client.Submission; using OdinEye.Models; using OdinEye.Models.Api; using Steamworks; using UnityEngine; using Utf8Json; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("OdinEye.Client")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("OdinEye.Client")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("2f6e4b8e-6a3f-4b1a-9b0e-8f6c5b4a3d2e")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace OdinEye.Client { [BepInPlugin("org.bepinex.plugins.odineye.client", "odineye.client", "1.0.0.0")] public class OdinEyeClientPlugin : BaseUnityPlugin { private static readonly TimeSpan CheckInterval = TimeSpan.FromSeconds(30.0); private static readonly TimeSpan HeartbeatInterval = TimeSpan.FromMinutes(5.0); private static readonly TimeSpan EventFlushInterval = TimeSpan.FromSeconds(5.0); private static readonly TimeSpan OutpostScanInterval = TimeSpan.FromSeconds(60.0); private static readonly TimeSpan SeedTimeout = TimeSpan.FromSeconds(10.0); private static readonly TimeSpan ClockUpdateInterval = TimeSpan.FromSeconds(1.0); private IPlayerStatsSource statsSource; private IStatsSubmitter statsSubmitter; private ICheatStatusSubmitter cheatStatusSubmitter; private ChangeDrivenPolicy policy; private Guid? currentPlayerId; private Uri serverBaseUri; private HttpClient seedClient; private HttpEventSubmitter eventSubmitter; private CustomCounterStore counters; private OutpostAnchorStore outpostAnchors; private DateTime nextOutpostScanUtc; private IPlayerStatsSource fullStatsSource; private volatile bool seeded; private DateTime seedDeadlineUtc; private bool loginSubmitted; private DateTime nextEventFlushUtc; private volatile IReadOnlyDictionary<string, float> lastSubmittedStats; private ConfigEntry<bool> showClock; private ClockHudElement clockHud; private DateTime nextClockUpdateUtc; private void Awake() { //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Expected O, but got Unknown showClock = ((BaseUnityPlugin)this).Config.Bind<bool>("Hud", "ShowClock", true, "Show a small in-game clock just below the minimap (VALSER-40/41's own \"temporal hours\" reading -- dawn is always 6:00 AM, dusk always 6:00 PM). Purely local/visual -- reads nothing from your character and sends nothing anywhere, unaffected by ServerUrl below."); clockHud = new ClockHudElement(); ConfigEntry<string> val = ((BaseUnityPlugin)this).Config.Bind<string>("Server", "ServerUrl", string.Empty, "The OdinEye server's base URL to submit this character's lifetime stats to (e.g. http://yourserver.com:2469/). Leave empty to disable stats/cheat-status submission -- nothing is read from your character or sent anywhere unless this is set. Does not affect the HUD clock above."); if (string.IsNullOrWhiteSpace(val.Value)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"OdinEye client: ServerUrl not configured, character-stats submission is disabled."); return; } if (!Uri.TryCreate(EnsureTrailingSlash(val.Value), UriKind.Absolute, out Uri result)) { ((BaseUnityPlugin)this).Logger.LogError((object)("OdinEye client: ServerUrl '" + val.Value + "' is not a valid URL. Character-stats submission is disabled.")); return; } serverBaseUri = result; statsSource = new PlayerProfileStatsSource(); statsSubmitter = new HttpStatsSubmitter(result, delegate(string message) { ((BaseUnityPlugin)this).Logger.LogWarning((object)message); }); cheatStatusSubmitter = new HttpCheatStatusSubmitter(result, delegate(string message) { ((BaseUnityPlugin)this).Logger.LogWarning((object)message); }); policy = new ChangeDrivenPolicy(CheckInterval, HeartbeatInterval); seedClient = new HttpClient(); eventSubmitter = new HttpEventSubmitter(result, delegate(string message) { ((BaseUnityPlugin)this).Logger.LogWarning((object)message); }); ClientRuntime.LogWarning = delegate(string message) { ((BaseUnityPlugin)this).Logger.LogWarning((object)message); }; ApplyPatches(); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"OdinEye client: character-stats submission enabled, reporting to {result}"); } private void ApplyPatches() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown Harmony val = new Harmony("org.bepinex.plugins.odineye.client"); Type[] types = typeof(OdinEyeClientPlugin).Assembly.GetTypes(); foreach (Type type in types) { if (type.IsDefined(typeof(HarmonyPatch), inherit: false)) { try { val.CreateClassProcessor(type).Patch(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("OdinEye client: could not apply " + type.Name + " (" + ex.Message + "); the achievement it feeds will not progress until this is updated for the current game version.")); } } } } private void OnDestroy() { EndSession(); (statsSubmitter as IDisposable)?.Dispose(); (cheatStatusSubmitter as IDisposable)?.Dispose(); eventSubmitter?.Dispose(); HttpClient obj = seedClient; if (obj != null) { ((HttpMessageInvoker)obj).Dispose(); } } private void EndSession() { ClientRuntime.Counters = null; counters?.Flush(); counters = null; outpostAnchors?.Flush(); outpostAnchors = null; fullStatsSource = null; currentPlayerId = null; loginSubmitted = false; lastSubmittedStats = null; } private void Update() { UpdateClock(); if (statsSubmitter == null) { return; } if ((Object)(object)Player.m_localPlayer == (Object)null) { EndSession(); return; } DateTime utcNow = DateTime.UtcNow; if (!currentPlayerId.HasValue) { currentPlayerId = ComputeLocalPlayerId(); if (!currentPlayerId.HasValue) { return; } BeginSession(currentPlayerId.Value, utcNow); } Guid value = currentPlayerId.Value; if (utcNow >= nextEventFlushUtc) { nextEventFlushUtc = utcNow + EventFlushInterval; eventSubmitter.Flush(value, ClientRuntime.Events); } if (utcNow >= nextOutpostScanUtc) { nextOutpostScanUtc = utcNow + OutpostScanInterval; OutpostTracking.Scan(outpostAnchors); outpostAnchors.Flush(); } if (!loginSubmitted) { if (seeded || !(utcNow < seedDeadlineUtc)) { loginSubmitted = true; policy.OnLogin(utcNow); SubmitAll(value, utcNow); } } else if (policy.IsCheckDue(utcNow)) { counters?.Flush(); IReadOnlyDictionary<string, float> stats = fullStatsSource.GetStats(); if (policy.ShouldSubmit(utcNow, StatsChange.HasChanged(lastSubmittedStats, stats))) { SubmitAll(value, utcNow); } } } private void BeginSession(Guid playerId, DateTime nowUtc) { counters = new CustomCounterStore(Path.Combine(Paths.ConfigPath, $"odineye.client.counters.{playerId:N}.json"), delegate(string message) { ((BaseUnityPlugin)this).Logger.LogWarning((object)message); }); outpostAnchors = new OutpostAnchorStore(Path.Combine(Paths.ConfigPath, $"odineye.client.outposts.{playerId:N}.json"), delegate(string message) { ((BaseUnityPlugin)this).Logger.LogWarning((object)message); }); fullStatsSource = new CounterAugmentedStatsSource(statsSource, counters, StationNames.Get, NorthTracking.CurrentNorthZ, NorthTracking.IsInDeepNorth, BoatTracking.IsOnBoat, SwampTracking.IsInSwamp, OvenTracking.IsNearOven); seeded = false; seedDeadlineUtc = nowUtc + SeedTimeout; loginSubmitted = false; lastSubmittedStats = null; nextEventFlushUtc = nowUtc + EventFlushInterval; nextOutpostScanUtc = nowUtc + OutpostScanInterval; CustomCounterStore store = counters; Task.Run(async delegate { Dictionary<string, float> serverValues = await StatsSeeder.FetchAsync(seedClient, serverBaseUri, playerId, SeedTimeout, delegate(string message) { ((BaseUnityPlugin)this).Logger.LogWarning((object)message); }).ConfigureAwait(continueOnCapturedContext: false); store.SeedFrom(serverValues); if (counters == store) { seeded = true; } }); ClientRuntime.Counters = counters; } private void SubmitAll(Guid playerId, DateTime nowUtc) { SubmitCurrentStats(playerId); SubmitCheatStatus(playerId); policy.MarkSubmitted(nowUtc); } private void UpdateClock() { if (!showClock.Value) { return; } DateTime utcNow = DateTime.UtcNow; if (!(utcNow < nextClockUpdateUtc)) { nextClockUpdateUtc = utcNow + ClockUpdateInterval; double? totalSeconds = EnvManTimeReader.GetTotalSeconds(); if (totalSeconds.HasValue) { clockHud.SetText(TemporalClock.Format(totalSeconds.Value)); } } } private void SubmitCurrentStats(Guid playerId) { //IL_0015: 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_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown IReadOnlyDictionary<string, float> stats = fullStatsSource.GetStats(); if (stats.Count == 0) { return; } SubmissionMeta meta = new SubmissionMeta { PlayerId = ClientRuntime.LocalPlayerId().ToString(), ClientVersion = typeof(OdinEyeClientPlugin).Assembly.GetName().Version.ToString() }; CharacterStatsSubmission val = CharacterStatsPayloadBuilder.Build(stats, meta); if (val.Stats.Count == 0) { return; } lastSubmittedStats = stats; statsSubmitter.Submit(playerId, val, delegate(bool accepted) { if (!accepted) { lastSubmittedStats = null; } }); } private void SubmitCheatStatus(Guid playerId) { bool? flag = CheatStatusReader.IsCheated(); if (flag.HasValue) { cheatStatusSubmitter.Submit(playerId, flag.Value, CheatBypassReader.IsEnabled()); } } private static Guid? ComputeLocalPlayerId() { //IL_0038: 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) Game instance = Game.instance; PlayerProfile val = ((instance != null) ? instance.GetPlayerProfile() : null); if (val == null) { return null; } string name = val.GetName(); if (string.IsNullOrEmpty(name)) { return null; } return NameBasedGuid.NewPlayerGuid(SteamUser.GetSteamID().m_SteamID.ToString(), name); } private static string EnsureTrailingSlash(string url) { if (!url.EndsWith("/", StringComparison.Ordinal)) { return url + "/"; } return url; } } public static class MyPluginInfo { public const string PLUGIN_GUID = "OdinEye.Client"; public const string PLUGIN_NAME = ""; public const string PLUGIN_VERSION = "1.0.0.0"; } } namespace OdinEye.Client.Patches { [HarmonyPatch] public static class ArrowHitPatch { private static readonly FieldInfo OwnerField = AccessTools.Field(typeof(Projectile), "m_owner"); private static readonly FieldInfo SkillField = AccessTools.Field(typeof(Projectile), "m_skill"); [HarmonyPrepare] private static bool Prepare() { if (TargetMethod() != null && OwnerField != null) { return SkillField != null; } return false; } private static MethodBase TargetMethod() { return AccessTools.Method(typeof(Projectile), "OnHit", (Type[])null, (Type[])null); } [HarmonyPrefix] private static void Prefix(Projectile __instance, object[] __args) { ClientRuntime.Guard("arrow hit count", delegate { CustomCounterStore counters = ClientRuntime.Counters; if (counters != null && !((Object)(object)Player.m_localPlayer == (Object)null)) { object obj = __args[0]; object obj2 = ((obj is Component) ? obj : null); Character val = ((obj2 != null) ? ((Component)obj2).GetComponentInParent<Character>() : null); if (CounterRules.CountsAsArrowHitOnEnemy(OwnerField.GetValue(__instance) == Player.m_localPlayer, SkillField.GetValue(__instance)?.ToString(), (Object)(object)val != (Object)null, (Object)(object)val != (Object)null && val.IsPlayer(), (Object)(object)val != (Object)null && val.IsTamed(), (Object)(object)val != (Object)null && val.IsDead())) { counters.Increment("Custom:ArrowHitsEnemy"); } } }); } } public static class BedPatches { [HarmonyPatch(typeof(WearNTear), "Remove")] public static class BedRemovedPatch { private static readonly MethodInfo GetOwner = AccessTools.Method(typeof(Bed), "GetOwner", (Type[])null, (Type[])null); [HarmonyPrepare] private static bool Prepare() { return GetOwner != null; } [HarmonyPrefix] private static void Prefix(WearNTear __instance) { ClientRuntime.Guard("bed removal report", delegate { //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_0053: 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: Unknown result type (might be due to invalid IL or missing references) if (ClientRuntime.Counters != null) { Bed component = ((Component)__instance).GetComponent<Bed>(); if (!((Object)(object)component == (Object)null)) { ClientRuntime.Counters.Increment("Custom:BedsDestroyed"); Vector3 spawnPoint = component.GetSpawnPoint(); ClientEvent val = BedEvents.Removed((long)GetOwner.Invoke(component, null), ClientRuntime.LocalPlayerId(), spawnPoint.x, spawnPoint.y, spawnPoint.z); if (val != null) { ClientRuntime.Events.Enqueue(val); } } } }); } } [HarmonyPatch(typeof(Game), "FindSpawnPoint")] public static class BedMissingPatch { [HarmonyPrefix] private static void Prefix(Game __instance, out object __state) { __state = null; object captured = null; ClientRuntime.Guard("respawn check", delegate { //IL_0022: Unknown result type (might be due to invalid IL or missing references) PlayerProfile playerProfile = __instance.GetPlayerProfile(); if (ClientRuntime.Counters != null && playerProfile != null && playerProfile.HaveCustomSpawnPoint()) { captured = playerProfile.GetCustomSpawnPoint(); } }); __state = captured; } [HarmonyPostfix] private static void Postfix(Game __instance, object __state) { if (__state == null) { return; } ClientRuntime.Guard("respawn report", delegate { //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_0029: 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_0035: Unknown result type (might be due to invalid IL or missing references) PlayerProfile playerProfile = __instance.GetPlayerProfile(); if (playerProfile != null && !playerProfile.HaveCustomSpawnPoint()) { Vector3 val = (Vector3)__state; ClientRuntime.Events.Enqueue(BedEvents.MissingAtRespawn(val.x, val.y, val.z)); } }); } } } internal static class ClientRuntime { public static volatile CustomCounterStore Counters; public static readonly ClientEventQueue Events = new ClientEventQueue(); public static Action<string> LogWarning = delegate { }; public static long LocalPlayerId() { Game instance = Game.instance; long? obj; if (instance == null) { obj = null; } else { PlayerProfile playerProfile = instance.GetPlayerProfile(); obj = ((playerProfile != null) ? new long?(playerProfile.GetPlayerID()) : ((long?)null)); } long? num = obj; return num.GetValueOrDefault(); } public static void Guard(string what, Action action) { try { action(); } catch (Exception ex) { LogWarning("OdinEye client: " + what + " failed: " + ex.Message); } } } public static class CookingStationPatches { [HarmonyPatch(typeof(CookingStation), "OnInteract")] public static class OnInteractPatch { [HarmonyPrepare] private static bool Prepare() { return Available; } [HarmonyPrefix] private static void Prefix(CookingStation __instance, Humanoid user) { ClientRuntime.Guard("cooking station check", delegate { nextRemovalProductName = null; nextRemovalIsBurnt = false; if (ClientRuntime.Counters != null && (object)user == Player.m_localPlayer) { (string, string)? tuple = NextFinishedSlot(__instance); if (tuple.HasValue) { if (tuple.Value.Item1 == "Burnt") { nextRemovalIsBurnt = true; } else { nextRemovalProductName = tuple.Value.Item2; } } } }); } [HarmonyPostfix] private static void Postfix() { nextRemovalProductName = null; nextRemovalIsBurnt = false; } } [HarmonyPatch(typeof(ZNetView), "InvokeRPC", new Type[] { typeof(string), typeof(object[]) })] public static class RemoveDoneItemPatch { [HarmonyPrefix] private static void Prefix(object[] __args) { if (!(__args[0] is string text) || text != "RPC_RemoveDoneItem" || (nextRemovalProductName == null && !nextRemovalIsBurnt)) { return; } string productName = nextRemovalProductName; bool isBurnt = nextRemovalIsBurnt; nextRemovalProductName = null; nextRemovalIsBurnt = false; ClientRuntime.Guard("cooking station count", delegate { int amountTaken = ((!(__args[1] is object[] array) || array.Length <= 1) ? 1 : Convert.ToInt32(array[1])); if (productName != null) { int num = CounterRules.BreadToCount(itemIsDone: true, productName, amountTaken); if (num > 0) { ClientRuntime.Counters?.Increment("Custom:BreadCollected", num); } int num2 = CounterRules.CookedChickenMeatToCount(itemIsDone: true, productName, amountTaken); if (num2 > 0) { ClientRuntime.Counters?.Increment("Custom:ChickenMeatCooked", num2); } int num3 = CounterRules.LoxPieToCount(itemIsDone: true, productName, amountTaken); if (num3 > 0) { ClientRuntime.Counters?.Increment("Custom:LoxPiesCooked", num3); } } if (isBurnt) { int num4 = CounterRules.FoodBurntToCoal(isBurntStatus: true, amountTaken); if (num4 > 0) { ClientRuntime.Counters?.Increment("Custom:FoodBurntToCoal", num4); } } }); } } private static string nextRemovalProductName; private static bool nextRemovalIsBurnt; private static readonly MethodInfo GetSlot = AccessTools.Method(typeof(CookingStation), "GetSlot", (Type[])null, (Type[])null); private static readonly MethodInfo GetItemConversion = AccessTools.Method(typeof(CookingStation), "GetItemConversion", (Type[])null, (Type[])null); private static bool Available { get { if (GetSlot != null) { return GetItemConversion != null; } return false; } } private static (string Status, string ProductName)? NextFinishedSlot(CookingStation station) { for (int i = 0; i < station.m_slots.Length; i++) { object[] array = new object[5] { i, null, 0f, null, false }; GetSlot.Invoke(station, array); string text = array[1] as string; string text2 = array[3]?.ToString(); if (!string.IsNullOrEmpty(text) && (!(text2 != "Done") || !(text2 != "Burnt"))) { if (text2 != "Done") { return ("Burnt", null); } object obj = GetItemConversion.Invoke(station, new object[1] { text }); object? obj2 = obj?.GetType().GetField("m_to")?.GetValue(obj); Object val = (Object)((obj2 is Object) ? obj2 : null); return ("Done", (val != null) ? val.name : null); } } return null; } } [HarmonyPatch(typeof(Fermenter), "Interact")] public static class FermenterTapPatch { private static readonly MethodInfo GetStatus = AccessTools.Method(typeof(Fermenter), "GetStatus", (Type[])null, (Type[])null); private static readonly MethodInfo GetContent = AccessTools.Method(typeof(Fermenter), "GetContent", (Type[])null, (Type[])null); private static bool Available { get { if (GetStatus != null) { return GetContent != null; } return false; } } [HarmonyPrepare] private static bool Prepare() { return Available; } [HarmonyPrefix] private static void Prefix(Fermenter __instance, Humanoid user) { ClientRuntime.Guard("fermenter tap check", delegate { if (ClientRuntime.Counters != null && (object)user == Player.m_localPlayer) { bool flag = GetStatus.Invoke(__instance, null)?.ToString() == "Ready"; int contentHash = (flag ? ((int)GetContent.Invoke(__instance, null)) : 0); int num = CounterRules.MeadsToCount(flag, ((contentHash == 0) ? null : __instance.m_conversion?.FirstOrDefault((Func<ItemConversion, bool>)((ItemConversion c) => (Object)(object)c?.m_from != (Object)null && StringExtensionMethods.GetStableHashCode(((Object)((Component)c.m_from).gameObject).name) == contentHash)))?.m_producedItems ?? 0); if (num > 0) { ClientRuntime.Counters.Increment("Custom:MeadsMade", num); } } }); } } [HarmonyPatch(typeof(Character), "ApplyDamage")] public static class IncomingHitPatch { [HarmonyPostfix] private static void Postfix(Character __instance, HitData hit) { ClientRuntime.Guard("incoming hit count", delegate { if (ClientRuntime.Counters != null && hit != null && !((Object)(object)__instance == (Object)null) && (object)__instance == Player.m_localPlayer) { if (CounterRules.CountsAsPoisonDeath(targetIsLocalPlayer: true, __instance.IsDead(), hit.m_damage.m_poison)) { ClientRuntime.Counters.Increment("Custom:PoisonDeaths"); } Character attacker = hit.GetAttacker(); string attackerPrefabName = (((Object)(object)attacker == (Object)null) ? null : Utils.GetPrefabName(((Component)attacker).gameObject)); if (CounterRules.CountsAsLeechHit(targetIsLocalPlayer: true, attackerPrefabName)) { ClientRuntime.Counters.Increment("Custom:LeechHits"); } } }); } } [HarmonyPatch(typeof(Humanoid), "Pickup")] public static class ItemPickupPatch { [HarmonyPrefix] private static void Prefix(Humanoid __instance, GameObject go, out object __state) { __state = null; object captured = null; ClientRuntime.Guard("item pickup check", delegate { if (ClientRuntime.Counters != null && (object)__instance == Player.m_localPlayer && !((Object)(object)go == (Object)null)) { ItemData val = go.GetComponent<ItemDrop>()?.m_itemData; if ((Object)(object)val?.m_dropPrefab != (Object)null) { captured = (Utils.GetPrefabName(val.m_dropPrefab), val.m_stack); } } }); __state = captured; } [HarmonyPostfix] private static void Postfix(bool __result, object __state) { ClientRuntime.Guard("item pickup count", delegate { if (__result && __state is ValueTuple<string, int>) { (string, int) tuple = ((string, int))__state; string item = tuple.Item1; int item2 = tuple.Item2; CustomCounterStore counters = ClientRuntime.Counters; int num = CounterRules.DwarfEyesToCount(byLocalPlayer: true, pickupSucceeded: true, item, item2); if (num > 0) { counters?.Increment("Custom:DwarfEyesTouched", num); } int num2 = CounterRules.GuckToCount(byLocalPlayer: true, pickupSucceeded: true, item, item2); if (num2 > 0) { counters?.Increment("Custom:GuckCollected", num2); } int num3 = CounterRules.BloodBagToCount(byLocalPlayer: true, pickupSucceeded: true, item, item2); if (num3 > 0) { counters?.Increment("Custom:BloodBagsCollected", num3); } int num4 = CounterRules.ElderBarkToCount(byLocalPlayer: true, pickupSucceeded: true, item, item2); if (num4 > 0) { counters?.Increment("Custom:ElderBarkCollected", num4); } int num5 = CounterRules.WoodToCount(byLocalPlayer: true, pickupSucceeded: true, item, item2); if (num5 > 0) { counters?.Increment("Custom:WoodCollected", num5); } int num6 = CounterRules.StoneToCount(byLocalPlayer: true, pickupSucceeded: true, item, item2); if (num6 > 0) { counters?.Increment("Custom:StoneCollected", num6); } int num7 = CounterRules.ResinToCount(byLocalPlayer: true, pickupSucceeded: true, item, item2); if (num7 > 0) { counters?.Increment("Custom:ResinHandled", num7); } } }); } } [HarmonyPatch(typeof(MineRock5), "DamageArea")] public static class MudPilePatch { [HarmonyPostfix] private static void Postfix(MineRock5 __instance, HitData hit, bool ___m_allDestroyed) { ClientRuntime.Guard("mud pile count", delegate { if (ClientRuntime.Counters != null && hit != null && !((Object)(object)__instance == (Object)null) && ___m_allDestroyed) { bool byLocalPlayer = (object)hit.GetAttacker() == Player.m_localPlayer; string prefabName = Utils.GetPrefabName(((Component)__instance).gameObject); if (CounterRules.CountsAsMuddyScrapPileOpened(byLocalPlayer, nowFullyDestroyed: true, prefabName)) { ClientRuntime.Counters.Increment("Custom:MuddyScrapPilesOpened"); } } }); } } [HarmonyPatch(typeof(Smelter), "OnEmpty")] public static class SmelterEmptyPatch { [HarmonyPrefix] private static void Prefix(Humanoid user, ZNetView ___m_nview) { ClientRuntime.Guard("smelter empty count", delegate { if (ClientRuntime.Counters != null && !((Object)(object)___m_nview == (Object)null) && (object)user == Player.m_localPlayer) { ZDO zDO = ___m_nview.GetZDO(); if (zDO != null) { string queuedOreName = zDO.GetString(ZDOVars.s_spawnOre, ""); int queuedAmount = zDO.GetInt(ZDOVars.s_spawnAmount, 0); int num = CounterRules.IronToProcess(queuedOreName, queuedAmount); if (num > 0) { ClientRuntime.Counters.Increment("Custom:IronProcessed", num); } } } }); } } [HarmonyPatch(typeof(Tameable), "Tame")] public static class TameablePatch { [HarmonyPostfix] private static void Postfix(Character ___m_character) { ClientRuntime.Guard("tame count", delegate { if (ClientRuntime.Counters != null && !((Object)(object)___m_character == (Object)null)) { string text = CounterRules.TamedSpeciesCounterKey(Utils.GetPrefabName(((Component)___m_character).gameObject)); if (text != null) { ClientRuntime.Counters.Increment(text); } } }); } } [HarmonyPatch(typeof(Player), "ConsumeItem")] public static class VomitBombPatch { [HarmonyPrefix] private static void Prefix(Player __instance, out object __state) { __state = null; object captured = null; ClientRuntime.Guard("vomit bomb pre-check", delegate { if (__instance == Player.m_localPlayer) { captured = __instance.GetFoods()?.Count ?? 0; } }); __state = captured; } [HarmonyPostfix] private static void Postfix(ItemData item, bool __result, object __state) { ClientRuntime.Guard("vomit bomb count", delegate { if (ClientRuntime.Counters != null && __state is int) { int activeFoodCountBeforeEating = (int)__state; bool eatenSuccessfully = __result; ItemData obj = item; object itemSharedName; if (obj == null) { itemSharedName = null; } else { GameObject dropPrefab = obj.m_dropPrefab; itemSharedName = ((dropPrefab != null) ? ((Object)dropPrefab).name : null); } if (CounterRules.CountsAsVomitBomb(eatenSuccessfully, (string)itemSharedName, activeFoodCountBeforeEating)) { ClientRuntime.Counters.Increment("Custom:VomitBombs"); } } }); } } [HarmonyPatch(typeof(Character), "ApplyDamage")] public static class WeaponKillPatch { [HarmonyPostfix] private static void Postfix(Character __instance, HitData hit) { ClientRuntime.Guard("weapon kill count", delegate { if (ClientRuntime.Counters != null && hit != null) { bool byLocalPlayer = (object)hit.GetAttacker() == Player.m_localPlayer; string skillName = ((object)Unsafe.As<SkillType, SkillType>(ref hit.m_skill)/*cast due to .constrained prefix*/).ToString(); bool flag = (Object)(object)__instance != (Object)null; bool targetIsPlayer = flag && __instance.IsPlayer(); bool targetIsTamed = flag && __instance.IsTamed(); bool targetIsDeadNow = flag && __instance.IsDead(); if (CounterRules.CountsAsWeaponKill(byLocalPlayer, skillName, "Unarmed", flag, targetIsPlayer, targetIsTamed, targetIsDeadNow)) { ClientRuntime.Counters.Increment("Custom:FistKills"); } if (CounterRules.CountsAsWeaponKill(byLocalPlayer, skillName, "Swords", flag, targetIsPlayer, targetIsTamed, targetIsDeadNow)) { ClientRuntime.Counters.Increment("Custom:SwordKills"); } } }); } } } namespace OdinEye.Client.Events { public static class BedEvents { public static ClientEvent Removed(long ownerPlayerId, long removerPlayerId, float x, float y, float z) { //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_0019: 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_0033: 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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown if (ownerPlayerId == 0L || ownerPlayerId == removerPlayerId) { return null; } return new ClientEvent { Type = "BedRemoved", OwnerPlayerId = ownerPlayerId.ToString(), RemoverPlayerId = removerPlayerId.ToString(), X = x, Y = y, Z = z }; } public static ClientEvent MissingAtRespawn(float x, float y, float z) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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_0026: Expected O, but got Unknown return new ClientEvent { Type = "BedMissingAtRespawn", X = x, Y = y, Z = z }; } } public sealed class ClientEventQueue { public const int DefaultCapacity = 100; private readonly object gate = new object(); private readonly LinkedList<ClientEvent> items = new LinkedList<ClientEvent>(); private readonly int capacity; public int Count { get { lock (gate) { return items.Count; } } } public ClientEventQueue(int capacity = 100) { this.capacity = ((capacity > 0) ? capacity : 100); } public void Enqueue(ClientEvent clientEvent) { if (clientEvent == null) { return; } lock (gate) { items.AddLast(clientEvent); Trim(); } } public List<ClientEvent> TakeBatch(int max) { List<ClientEvent> list = new List<ClientEvent>(); lock (gate) { while (items.Count > 0 && list.Count < max) { list.Add(items.First.Value); items.RemoveFirst(); } } return list; } public void Requeue(List<ClientEvent> batch) { if (batch == null) { return; } lock (gate) { for (int num = batch.Count - 1; num >= 0; num--) { items.AddFirst(batch[num]); } Trim(); } } private void Trim() { while (items.Count > capacity) { items.RemoveFirst(); } } } } namespace OdinEye.Client.Submission { public sealed class ChangeDrivenPolicy { private readonly TimeSpan checkInterval; private readonly TimeSpan heartbeatInterval; private DateTime? nextCheckAtUtc; private DateTime? lastSubmittedAtUtc; public ChangeDrivenPolicy(TimeSpan checkInterval, TimeSpan heartbeatInterval) { if (checkInterval <= TimeSpan.Zero) { throw new ArgumentOutOfRangeException("checkInterval", "Check interval must be positive."); } if (heartbeatInterval < checkInterval) { throw new ArgumentOutOfRangeException("heartbeatInterval", "The heartbeat cannot be more frequent than the change check."); } this.checkInterval = checkInterval; this.heartbeatInterval = heartbeatInterval; } public void OnLogin(DateTime nowUtc) { lastSubmittedAtUtc = nowUtc; nextCheckAtUtc = nowUtc + checkInterval; } public bool IsCheckDue(DateTime nowUtc) { if (nextCheckAtUtc.HasValue) { DateTime? dateTime = nextCheckAtUtc; if (!(nowUtc < dateTime)) { nextCheckAtUtc = nowUtc + checkInterval; return true; } } return false; } public bool ShouldSubmit(DateTime nowUtc, bool changed) { if (lastSubmittedAtUtc.HasValue) { if (!changed) { return nowUtc - lastSubmittedAtUtc.Value >= heartbeatInterval; } return true; } return false; } public void MarkSubmitted(DateTime nowUtc) { lastSubmittedAtUtc = nowUtc; } } public sealed class HttpEventSubmitter : IDisposable { private const int BatchSize = 20; private readonly HttpClient httpClient = new HttpClient(); private readonly Uri serverBaseUri; private readonly Action<string> logWarning; private int sending; public HttpEventSubmitter(Uri serverBaseUri, Action<string> logWarning) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown this.serverBaseUri = serverBaseUri ?? throw new ArgumentNullException("serverBaseUri"); this.logWarning = logWarning ?? throw new ArgumentNullException("logWarning"); } public async void Flush(Guid playerId, ClientEventQueue queue) { if (queue.Count == 0 || Interlocked.Exchange(ref sending, 1) == 1) { return; } try { while (queue.Count > 0) { List<ClientEvent> batch = queue.TakeBatch(20); if (!(await SendAsync(playerId, batch).ConfigureAwait(continueOnCapturedContext: false))) { queue.Requeue(batch); break; } } } finally { Interlocked.Exchange(ref sending, 0); } } private async Task<bool> SendAsync(Guid playerId, List<ClientEvent> batch) { try { byte[] array = JsonSerializer.Serialize<ClientEventsSubmission>(new ClientEventsSubmission { Events = batch }); ByteArrayContent content = new ByteArrayContent(array); try { ((HttpContent)content).Headers.ContentType = new MediaTypeHeaderValue("application/json") { CharSet = Encoding.UTF8.WebName }; HttpResponseMessage val = await httpClient.PostAsync(new Uri(serverBaseUri, $"players/{playerId}/events"), (HttpContent)(object)content).ConfigureAwait(continueOnCapturedContext: false); if (val.IsSuccessStatusCode) { return true; } int statusCode = (int)val.StatusCode; logWarning($"OdinEye server did not accept {batch.Count} event(s): {statusCode} {val.ReasonPhrase}"); return statusCode == 400; } finally { ((IDisposable)content)?.Dispose(); } } catch (Exception ex) { logWarning("Failed to send events to OdinEye server: " + ex.Message); return false; } } public void Dispose() { ((HttpMessageInvoker)httpClient).Dispose(); } } public static class StatsSeeder { public static Dictionary<string, float> ParseOwnStats(string json, Guid playerId) { Dictionary<string, float> dictionary = new Dictionary<string, float>(); if (string.IsNullOrWhiteSpace(json)) { return dictionary; } try { Dictionary<string, Dictionary<string, float>> dictionary2 = JsonSerializer.Deserialize<Dictionary<string, Dictionary<string, float>>>(json); if (dictionary2 != null && dictionary2.TryGetValue(playerId.ToString(), out var value) && value != null) { foreach (KeyValuePair<string, float> item in value) { dictionary[item.Key] = item.Value; } } } catch { } return dictionary; } public static async Task<Dictionary<string, float>> FetchAsync(HttpClient client, Uri serverBaseUri, Guid playerId, TimeSpan timeout, Action<string> logWarning) { _ = 1; try { using CancellationTokenSource cts = new CancellationTokenSource(timeout); HttpResponseMessage val = await client.GetAsync(new Uri(serverBaseUri, "players/stats"), cts.Token).ConfigureAwait(continueOnCapturedContext: false); if (!val.IsSuccessStatusCode) { logWarning($"OdinEye server would not share existing counters: {(int)val.StatusCode}"); return new Dictionary<string, float>(); } return ParseOwnStats(await val.Content.ReadAsStringAsync().ConfigureAwait(continueOnCapturedContext: false), playerId); } catch (Exception ex) { logWarning("Could not read existing counters from OdinEye server: " + ex.Message); return new Dictionary<string, float>(); } } } public sealed class HttpCheatStatusSubmitter : ICheatStatusSubmitter, IDisposable { private readonly HttpClient httpClient; private readonly Uri serverBaseUri; private readonly Action<string> logWarning; public HttpCheatStatusSubmitter(Uri serverBaseUri, Action<string> logWarning) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown this.serverBaseUri = serverBaseUri ?? throw new ArgumentNullException("serverBaseUri"); this.logWarning = logWarning ?? throw new ArgumentNullException("logWarning"); httpClient = new HttpClient(); } public async void Submit(Guid playerId, bool cheated, bool bypassEnabled) { try { byte[] array = JsonSerializer.Serialize<CheatStatusSubmission>(new CheatStatusSubmission { Cheated = cheated, BypassEnabled = bypassEnabled }); Uri uri = new Uri(serverBaseUri, $"players/{playerId}/cheatStatus"); ByteArrayContent content = new ByteArrayContent(array); try { ((HttpContent)content).Headers.ContentType = new MediaTypeHeaderValue("application/json") { CharSet = Encoding.UTF8.WebName }; HttpResponseMessage val = await httpClient.PostAsync(uri, (HttpContent)(object)content).ConfigureAwait(continueOnCapturedContext: false); if (!val.IsSuccessStatusCode) { logWarning($"OdinEye server rejected cheat-status submission: {(int)val.StatusCode} {val.ReasonPhrase}"); } } finally { ((IDisposable)content)?.Dispose(); } } catch (Exception ex) { logWarning("Failed to submit cheat status to OdinEye server: " + ex.Message); } } public void Dispose() { ((HttpMessageInvoker)httpClient).Dispose(); } } public sealed class HttpStatsSubmitter : IStatsSubmitter, IDisposable { private readonly HttpClient httpClient; private readonly Uri serverBaseUri; private readonly Action<string> logWarning; public HttpStatsSubmitter(Uri serverBaseUri, Action<string> logWarning) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown this.serverBaseUri = serverBaseUri ?? throw new ArgumentNullException("serverBaseUri"); this.logWarning = logWarning ?? throw new ArgumentNullException("logWarning"); httpClient = new HttpClient(); } public async void Submit(Guid playerId, CharacterStatsSubmission submission, Action<bool> onComplete = null) { bool accepted = false; try { byte[] array = JsonSerializer.Serialize<CharacterStatsSubmission>(submission); Uri uri = new Uri(serverBaseUri, $"players/{playerId}/stats"); ByteArrayContent content = new ByteArrayContent(array); try { ((HttpContent)content).Headers.ContentType = new MediaTypeHeaderValue("application/json") { CharSet = Encoding.UTF8.WebName }; HttpResponseMessage val = await httpClient.PostAsync(uri, (HttpContent)(object)content).ConfigureAwait(continueOnCapturedContext: false); accepted = val.IsSuccessStatusCode; if (!accepted) { logWarning($"OdinEye server rejected character-stats submission: {(int)val.StatusCode} {val.ReasonPhrase}"); } } finally { ((IDisposable)content)?.Dispose(); } } catch (Exception ex) { logWarning("Failed to submit character stats to OdinEye server: " + ex.Message); } try { onComplete?.Invoke(accepted); } catch { } } public void Dispose() { ((HttpMessageInvoker)httpClient).Dispose(); } } public interface ICheatStatusSubmitter { void Submit(Guid playerId, bool cheated, bool bypassEnabled); } public interface IStatsSubmitter { void Submit(Guid playerId, CharacterStatsSubmission submission, Action<bool> onComplete = null); } public sealed class SubmissionScheduler { private readonly TimeSpan interval; private DateTime? nextSubmissionAtUtc; public SubmissionScheduler(TimeSpan interval) { if (interval <= TimeSpan.Zero) { throw new ArgumentOutOfRangeException("interval", "Submission interval must be positive."); } this.interval = interval; } public void OnLogin(DateTime nowUtc) { nextSubmissionAtUtc = nowUtc + interval; } public bool IsDue(DateTime nowUtc) { if (nextSubmissionAtUtc.HasValue) { DateTime? dateTime = nextSubmissionAtUtc; if (!(nowUtc < dateTime)) { nextSubmissionAtUtc = nowUtc + interval; return true; } } return false; } } } namespace OdinEye.Client.Stats { public static class PieceStats { public const string PiecePlacedPrefix = "PiecePlaced:"; public const string StationTotalKey = "Derived:StationOrUpgradePlaced"; public static Dictionary<string, float> Prefix(IEnumerable<KeyValuePair<string, float>> placed) { Dictionary<string, float> dictionary = new Dictionary<string, float>(); foreach (KeyValuePair<string, float> item in placed ?? Enumerable.Empty<KeyValuePair<string, float>>()) { if (!string.IsNullOrEmpty(item.Key) && !float.IsNaN(item.Value) && !float.IsInfinity(item.Value) && item.Value >= 0f) { dictionary["PiecePlaced:" + item.Key] = item.Value; } } return dictionary; } public static float StationTotal(IEnumerable<KeyValuePair<string, float>> placed, ISet<string> stationNames) { if (placed == null || stationNames == null || stationNames.Count == 0) { return 0f; } return placed.Where((KeyValuePair<string, float> kv) => stationNames.Contains(kv.Key) && !float.IsNaN(kv.Value) && !float.IsInfinity(kv.Value) && kv.Value > 0f).Sum((KeyValuePair<string, float> kv) => kv.Value); } } public static class StatsChange { public static bool HasChanged(IReadOnlyDictionary<string, float> previous, IReadOnlyDictionary<string, float> current) { if (current == null) { return false; } if (previous == null || previous.Count != current.Count) { return true; } foreach (KeyValuePair<string, float> item in current) { if (!previous.TryGetValue(item.Key, out var value) || value != item.Value) { return true; } } return false; } } public static class BoatTracking { public static bool IsOnBoat() { return (Object)(object)Ship.GetLocalShip() != (Object)null; } } public sealed class CounterAugmentedStatsSource : IPlayerStatsSource { private static readonly TimeSpan MaxPlausibleBoatGap = TimeSpan.FromMinutes(5.0); private static readonly TimeSpan MaxPlausibleSwampGap = TimeSpan.FromMinutes(5.0); private static readonly TimeSpan MaxPlausibleBakeryGap = TimeSpan.FromMinutes(5.0); private readonly IPlayerStatsSource inner; private readonly CustomCounterStore store; private readonly Func<ISet<string>> stationNames; private readonly Func<float?> currentNorthZ; private readonly Func<bool> isInDeepNorth; private readonly Func<bool> isOnBoat; private readonly Func<bool> isInSwamp; private readonly Func<bool> isNearOven; private readonly Func<DateTime> nowUtc; private DateTime? lastBoatSampleUtc; private DateTime? lastSwampSampleUtc; private DateTime? lastBakerySampleUtc; public CounterAugmentedStatsSource(IPlayerStatsSource inner, CustomCounterStore store, Func<ISet<string>> stationNames, Func<float?> currentNorthZ = null, Func<bool> isInDeepNorth = null, Func<bool> isOnBoat = null, Func<bool> isInSwamp = null, Func<bool> isNearOven = null, Func<DateTime> nowUtc = null) { this.inner = inner ?? throw new ArgumentNullException("inner"); this.store = store ?? throw new ArgumentNullException("store"); this.stationNames = stationNames ?? ((Func<ISet<string>>)(() => (ISet<string>)null)); this.currentNorthZ = currentNorthZ ?? ((Func<float?>)(() => (float?)null)); this.isInDeepNorth = isInDeepNorth ?? ((Func<bool>)(() => false)); this.isOnBoat = isOnBoat ?? ((Func<bool>)(() => false)); this.isInSwamp = isInSwamp ?? ((Func<bool>)(() => false)); this.isNearOven = isNearOven ?? ((Func<bool>)(() => false)); this.nowUtc = nowUtc ?? ((Func<DateTime>)(() => DateTime.UtcNow)); } public IReadOnlyDictionary<string, float> GetStats() { Dictionary<string, float> dictionary = new Dictionary<string, float>(); foreach (KeyValuePair<string, float> stat in inner.GetStats()) { dictionary[stat.Key] = stat.Value; } if (dictionary.Count == 0) { return dictionary; } float num = PieceStats.StationTotal(from kv in dictionary where kv.Key.StartsWith("PiecePlaced:", StringComparison.Ordinal) select new KeyValuePair<string, float>(kv.Key.Substring("PiecePlaced:".Length), kv.Value), stationNames()); if (num > 0f) { store.RaiseTo("Derived:StationOrUpgradePlaced", num); } float? num2 = currentNorthZ(); if (num2.HasValue) { store.RaiseTo("Derived:FurthestNorthZ", CounterRules.NorthDistanceToRaise(num2.Value)); } if (isInDeepNorth()) { store.RaiseTo("Custom:ReachedDeepNorth", 1f); } DateTime dateTime = nowUtc(); if (lastBoatSampleUtc.HasValue) { float elapsedSeconds = (float)(dateTime - lastBoatSampleUtc.Value).TotalSeconds; bool num3 = isOnBoat(); TimeSpan maxPlausibleBoatGap = MaxPlausibleBoatGap; float num4 = CounterRules.BoatSecondsToAdd(num3, elapsedSeconds, (float)maxPlausibleBoatGap.TotalSeconds); if (num4 > 0f) { store.Increment("Custom:TimeOnBoatSeconds", num4); } } lastBoatSampleUtc = dateTime; if (lastSwampSampleUtc.HasValue) { float elapsedSeconds2 = (float)(dateTime - lastSwampSampleUtc.Value).TotalSeconds; bool num5 = isInSwamp(); TimeSpan maxPlausibleBoatGap = MaxPlausibleSwampGap; float num6 = CounterRules.SwampSecondsToAdd(num5, elapsedSeconds2, (float)maxPlausibleBoatGap.TotalSeconds); if (num6 > 0f) { store.Increment("Custom:TimeInSwampSeconds", num6); } } lastSwampSampleUtc = dateTime; if (lastBakerySampleUtc.HasValue) { float elapsedSeconds3 = (float)(dateTime - lastBakerySampleUtc.Value).TotalSeconds; bool num7 = isNearOven(); TimeSpan maxPlausibleBoatGap = MaxPlausibleBakeryGap; float num8 = CounterRules.BakerySecondsToAdd(num7, elapsedSeconds3, (float)maxPlausibleBoatGap.TotalSeconds); if (num8 > 0f) { store.Increment("Custom:TimeInBakerySeconds", num8); } } lastBakerySampleUtc = dateTime; foreach (KeyValuePair<string, float> item in store.Snapshot()) { dictionary[item.Key] = item.Value; } return dictionary; } } public static class NorthTracking { public static float? CurrentNorthZ() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Player.m_localPlayer != (Object)null)) { return null; } return ((Component)Player.m_localPlayer).transform.position.z; } public static bool IsInDeepNorth() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Invalid comparison between Unknown and I4 if ((Object)(object)Player.m_localPlayer != (Object)null) { return (int)Player.m_localPlayer.GetCurrentBiome() == 64; } return false; } } public sealed class OutpostAnchorStore { private readonly object gate = new object(); private readonly string path; private readonly Action<string> logWarning; private readonly List<float[]> anchors = new List<float[]>(); private bool dirty; public IReadOnlyList<(float X, float Z)> Anchors { get { lock (gate) { (float, float)[] array = new(float, float)[anchors.Count]; for (int i = 0; i < anchors.Count; i++) { array[i] = (anchors[i][0], anchors[i][1]); } return array; } } } public OutpostAnchorStore(string path, Action<string> logWarning = null) { this.path = path ?? throw new ArgumentNullException("path"); this.logWarning = logWarning ?? ((Action<string>)delegate { }); Load(); } public void Add(float x, float z) { if (float.IsNaN(x) || float.IsInfinity(x) || float.IsNaN(z) || float.IsInfinity(z)) { return; } lock (gate) { anchors.Add(new float[2] { x, z }); dirty = true; } } public bool Flush() { byte[] bytes; lock (gate) { if (!dirty) { return true; } bytes = JsonSerializer.Serialize<List<float[]>>(anchors); } try { string directoryName = Path.GetDirectoryName(path); if (!string.IsNullOrEmpty(directoryName)) { Directory.CreateDirectory(directoryName); } string sourceFileName = path + ".tmp"; File.WriteAllBytes(sourceFileName, bytes); if (File.Exists(path)) { File.Delete(path); } File.Move(sourceFileName, path); lock (gate) { dirty = false; } return true; } catch (Exception ex) { logWarning("OdinEye client: could not save outpost anchors to '" + path + "': " + ex.Message); return false; } } private void Load() { string sourceFileName = path + ".tmp"; try { if (!File.Exists(path) && File.Exists(sourceFileName)) { File.Move(sourceFileName, path); } if (!File.Exists(path)) { return; } foreach (float[] item in JsonSerializer.Deserialize<List<float[]>>(File.ReadAllBytes(path)) ?? throw new InvalidDataException("outpost anchor file was empty")) { if (item != null && item.Length == 2 && !float.IsNaN(item[0]) && !float.IsNaN(item[1])) { anchors.Add(item); } } } catch (Exception ex) { logWarning("OdinEye client: outpost anchor file '" + path + "' was unreadable (" + ex.Message + "); starting fresh"); try { string destFileName = path + ".bad"; if (File.Exists(destFileName)) { File.Delete(destFileName); } File.Move(path, destFileName); } catch { } anchors.Clear(); } } } public static class OutpostTracking { public const float OutpostRadius = 15f; private const int OceanSampleSteps = 20; private static readonly MethodInfo GetOwner = AccessTools.Method(typeof(Bed), "GetOwner", (Type[])null, (Type[])null); private static bool Available => GetOwner != null; public static void Scan(OutpostAnchorStore anchors) { //IL_0074: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) if (!Available || anchors == null || (Object)(object)Player.m_localPlayer == (Object)null || ClientRuntime.Counters == null) { return; } long num = ClientRuntime.LocalPlayerId(); if (num == 0L) { return; } List<Piece> list = new List<Piece>(); Bed[] array = Object.FindObjectsByType<Bed>((FindObjectsSortMode)0); foreach (Bed val in array) { if (!((Object)(object)val == (Object)null) && (long)GetOwner.Invoke(val, null) == num) { Vector3 pos = val.GetSpawnPoint(); list.Clear(); Piece.GetAllPiecesInRadius(pos, 15f, list); bool hasCraftingStationNearby = list.Any((Piece p) => (Object)(object)p != (Object)null && (Object)(object)((Component)p).GetComponent<CraftingStation>() != (Object)null); bool hasPortalNearby = list.Any((Piece p) => (Object)(object)p != (Object)null && (Object)(object)((Component)p).GetComponent<TeleportWorld>() != (Object)null); if (CounterRules.IsQualifyingOutpost(Cover.IsUnderRoof(pos), hasCraftingStationNearby, hasPortalNearby) && CounterRules.IsNewLandmass(anchors.Anchors.Select(((float X, float Z) a) => CrossesOcean(pos, a.X, a.Z)))) { anchors.Add(pos.x, pos.z); ClientRuntime.Counters.Increment("Custom:OutpostLandmasses"); } } } } private static bool CrossesOcean(Vector3 from, float toX, float toZ) { //IL_000c: 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_001d: 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_0031: 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_003c: Invalid comparison between Unknown and I4 if (WorldGenerator.instance == null) { return false; } Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(toX, from.y, toZ); for (int i = 0; i <= 20; i++) { Vector3 val2 = Vector3.Lerp(from, val, (float)i / 20f); if ((int)WorldGenerator.instance.GetBiome(val2) == 256) { return true; } } return false; } } public static class OvenTracking { public const float OvenRadius = 10f; public const string OvenPieceName = "piece_oven"; private static readonly List<Piece> nearby = new List<Piece>(); public static bool IsNearOven() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.m_localPlayer == (Object)null) { return false; } nearby.Clear(); Piece.GetAllPiecesInRadius(((Component)Player.m_localPlayer).transform.position, 10f, nearby); return nearby.Any((Piece p) => (Object)(object)p != (Object)null && Utils.GetPrefabName(((Component)p).gameObject) == "piece_oven"); } } public static class StationNames { private static HashSet<string> cached; public static ISet<string> Get() { if (cached != null) { return cached; } ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance == (Object)null || instance.m_prefabs == null || instance.m_prefabs.Count == 0) { return null; } HashSet<string> hashSet = new HashSet<string>(); foreach (GameObject prefab in instance.m_prefabs) { if (!((Object)(object)prefab == (Object)null)) { Piece component = prefab.GetComponent<Piece>(); if ((Object)(object)component != (Object)null && !string.IsNullOrEmpty(component.m_name) && ((Object)(object)prefab.GetComponent<CraftingStation>() != (Object)null || (Object)(object)prefab.GetComponent<StationExtension>() != (Object)null)) { hashSet.Add(component.m_name); } } } if (hashSet.Count > 0) { cached = hashSet; } if (hashSet.Count <= 0) { return null; } return hashSet; } } public static class SwampTracking { public static bool IsInSwamp() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Invalid comparison between Unknown and I4 if ((Object)(object)Player.m_localPlayer != (Object)null) { return (int)Player.m_localPlayer.GetCurrentBiome() == 2; } return false; } } public static class CharacterStatsPayloadBuilder { public static CharacterStatsSubmission Build(IReadOnlyDictionary<string, float> rawStats, SubmissionMeta meta = null) { //IL_0077: 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_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown if (rawStats == null) { throw new ArgumentNullException("rawStats"); } Dictionary<string, float> stats = rawStats.Where((KeyValuePair<string, float> stat) => IsValidStatValue(stat.Value)).ToDictionary((KeyValuePair<string, float> stat) => stat.Key, (KeyValuePair<string, float> stat) => stat.Value); return new CharacterStatsSubmission { Stats = stats, Meta = meta }; } private static bool IsValidStatValue(float value) { if (!float.IsNaN(value) && !float.IsInfinity(value)) { return value >= 0f; } return false; } } public interface IPlayerStatsSource { IReadOnlyDictionary<string, float> GetStats(); } public static class CheatBypassReader { private const string BypassKey = "bypasscheatchecks"; public static bool IsEnabled() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return false; } string text = default(string); if (localPlayer.TryGetUniqueKeyValue("bypasscheatchecks", ref text)) { return text == "1"; } return false; } } public static class CheatStatusReader { private static readonly Lazy<MethodInfo> IsCheatedAtAllMethod = new Lazy<MethodInfo>(() => typeof(PlayerProfile).Assembly.GetType("Achievements")?.GetMethod("IsCheatedAtAll", BindingFlags.Static | BindingFlags.Public)); public static bool? IsCheated() { MethodInfo value = IsCheatedAtAllMethod.Value; if (value == null) { return null; } try { return (bool)value.Invoke(null, null); } catch { return null; } } } public sealed class PlayerProfileStatsSource : IPlayerStatsSource { public const string PlayTimeSecondsKey = "PlayTimeSeconds"; public const string KnownWorldsCountKey = "KnownWorldsCount"; public const string EnemyKillKeyPrefix = "EnemyKill:"; private const int RawStatsIndex = 0; private static object GetFieldValue(object target, string fieldName) { return target?.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public)?.GetValue(target); } private static object GetRawPlayerStats(object profile) { if (!(GetFieldValue(profile, "m_playerStats") is Array { Length: >0 } array)) { return null; } return array.GetValue(0); } public IReadOnlyDictionary<string, float> GetStats() { Game instance = Game.instance; PlayerProfile val = ((instance != null) ? instance.GetPlayerProfile() : null); if (val == null) { return new Dictionary<string, float>(); } Dictionary<string, float> dictionary = new Dictionary<string, float>(); object rawPlayerStats = GetRawPlayerStats(val); if (GetFieldValue(rawPlayerStats, "m_stats") is IDictionary dictionary2) { foreach (DictionaryEntry item in dictionary2) { dictionary[item.Key.ToString()] = Convert.ToSingle(item.Value); } } float num = 0f; int num2 = 0; if (GetFieldValue(rawPlayerStats, "m_knownWorlds") is IDictionary dictionary3) { num2 = dictionary3.Count; foreach (object value in dictionary3.Values) { num += Convert.ToSingle(value); } } dictionary["PlayTimeSeconds"] = num; dictionary["KnownWorldsCount"] = num2; if (GetFieldValue(rawPlayerStats, "m_enemyStats") is Array { Length: >0 } array && array.GetValue(0) is IDictionary dictionary4) { foreach (DictionaryEntry item2 in dictionary4) { dictionary["EnemyKill:" + item2.Key] = Convert.ToSingle(item2.Value); } } if (GetFieldValue(rawPlayerStats, "m_piecesPlacedStats") is IDictionary dictionary5) { Dictionary<string, float> dictionary6 = new Dictionary<string, float>(); foreach (DictionaryEntry item3 in dictionary5) { dictionary6[item3.Key.ToString()] = Convert.ToSingle(item3.Value); } foreach (KeyValuePair<string, float> item4 in PieceStats.Prefix(dictionary6)) { dictionary[item4.Key] = item4.Value; } } return dictionary; } } } namespace OdinEye.Client.Counters { public sealed class CustomCounterStore { public static readonly string[] SeedablePrefixes = new string[2] { "Custom:", "Derived:" }; private readonly object gate = new object(); private readonly string path; private readonly Action<string> logWarning; private readonly Dictionary<string, float> values = new Dictionary<string, float>(); private bool dirty; public bool IsDirty { get { lock (gate) { return dirty; } } } public CustomCounterStore(string path, Action<string> logWarning = null) { this.path = path ?? throw new ArgumentNullException("path"); this.logWarning = logWarning ?? ((Action<string>)delegate { }); Load(); } public void Increment(string key, float amount = 1f) { if (string.IsNullOrEmpty(key) || float.IsNaN(amount) || float.IsInfinity(amount) || amount <= 0f) { return; } lock (gate) { values.TryGetValue(key, out var value); values[key] = value + amount; dirty = true; } } public float Get(string key) { lock (gate) { float value; return values.TryGetValue(key, out value) ? value : 0f; } } public IReadOnlyDictionary<string, float> Snapshot() { lock (gate) { return new Dictionary<string, float>(values); } } public float RaiseTo(string key, float value) { if (string.IsNullOrEmpty(key) || float.IsNaN(value) || float.IsInfinity(value) || value < 0f) { return Get(key); } lock (gate) { values.TryGetValue(key, out var value2); if (value > value2 || !values.ContainsKey(key)) { values[key] = Math.Max(value, value2); dirty = true; } return values[key]; } } public void SeedFrom(IEnumerable<KeyValuePair<string, float>> serverValues) { if (serverValues == null) { return; } lock (gate) { foreach (KeyValuePair<string, float> kv in serverValues) { if (SeedablePrefixes.Any((string p) => kv.Key != null && kv.Key.StartsWith(p, StringComparison.Ordinal)) && !float.IsNaN(kv.Value) && !float.IsInfinity(kv.Value) && !(kv.Value < 0f)) { values.TryGetValue(kv.Key, out var value); if (kv.Value > value) { values[kv.Key] = kv.Value; dirty = true; } } } } } public bool Flush() { byte[] bytes; lock (gate) { if (!dirty) { return true; } bytes = JsonSerializer.Serialize<Dictionary<string, float>>(values); } try { string directoryName = Path.GetDirectoryName(path); if (!string.IsNullOrEmpty(directoryName)) { Directory.CreateDirectory(directoryName); } string sourceFileName = path + ".tmp"; File.WriteAllBytes(sourceFileName, bytes); if (File.Exists(path)) { File.Delete(path); } File.Move(sourceFileName, path); lock (gate) { dirty = false; } return true; } catch (Exception ex) { logWarning("OdinEye client: could not save counters to '" + path + "': " + ex.Message); return false; } } private void Load() { string sourceFileName = path + ".tmp"; try { if (!File.Exists(path) && File.Exists(sourceFileName)) { File.Move(sourceFileName, path); } if (!File.Exists(path)) { return; } foreach (KeyValuePair<string, float> item in JsonSerializer.Deserialize<Dictionary<string, float>>(File.ReadAllBytes(path)) ?? throw new InvalidDataException("counter file was empty")) { if (!float.IsNaN(item.Value) && !float.IsInfinity(item.Value) && item.Value >= 0f) { values[item.Key] = item.Value; } } } catch (Exception ex) { logWarning("OdinEye client: counter file '" + path + "' was unreadable (" + ex.Message + "); starting fresh and keeping the old one as .bad"); try { string destFileName = path + ".bad"; if (File.Exists(destFileName)) { File.Delete(destFileName); } File.Move(path, destFileName); } catch { } values.Clear(); } } } public static class CounterRules { public const string ArrowHitsEnemyKey = "Custom:ArrowHitsEnemy"; public const string BreadCollectedKey = "Custom:BreadCollected"; public const string DwarfEyesTouchedKey = "Custom:DwarfEyesTouched"; public const string FoodBurntToCoalKey = "Custom:FoodBurntToCoal"; public const string TimeOnBoatSecondsKey = "Custom:TimeOnBoatSeconds"; public const string VomitBombsKey = "Custom:VomitBombs"; public const string FistKillsKey = "Custom:FistKills"; public const string SwordKillsKey = "Custom:SwordKills"; public const string ChickenMeatCookedKey = "Custom:ChickenMeatCooked"; public const string LoxPiesCookedKey = "Custom:LoxPiesCooked"; public const string MeadsMadeKey = "Custom:MeadsMade"; public const string OutpostLandmassesKey = "Custom:OutpostLandmasses"; public const string PoisonDeathsKey = "Custom:PoisonDeaths"; public const string LeechHitsKey = "Custom:LeechHits"; public const string GuckCollectedKey = "Custom:GuckCollected"; public const string BloodBagsCollectedKey = "Custom:BloodBagsCollected"; public const string MuddyScrapPilesOpenedKey = "Custom:MuddyScrapPilesOpened"; public const string ElderBarkCollectedKey = "Custom:ElderBarkCollected"; public const string IronProcessedKey = "Custom:IronProcessed"; public const string TimeInSwampSecondsKey = "Custom:TimeInSwampSeconds"; public const string WoodCollectedKey = "Custom:WoodCollected"; public const string BedsDestroyedKey = "Custom:BedsDestroyed"; public const string StoneCollectedKey = "Custom:StoneCollected"; public const string TimeInBakerySecondsKey = "Custom:TimeInBakerySeconds"; public const string ResinHandledKey = "Custom:ResinHandled"; public const string TamedBoarKey = "Custom:TamedBoar"; public const string TamedWolfKey = "Custom:TamedWolf"; public const string TamedLoxKey = "Custom:TamedLox"; public const string FurthestNorthZKey = "Derived:FurthestNorthZ"; public const string ReachedDeepNorthKey = "Custom:ReachedDeepNorth"; public const string BreadItemName = "Bread"; public const string DwarfEyeItemName = "GreydwarfEye"; public const string VomitBombItemName = "Pukeberries"; public const string CookedChickenItemName = "CookedChickenMeat"; public const string LoxMeatPieItemName = "LoxMeatPie"; public const string GuckItemName = "Guck"; public const string BloodBagItemName = "Bloodbag"; public const string ElderBarkItemName = "ElderBark"; public static readonly HashSet<string> LeechPrefabNames = new HashSet<string> { "Leech", "Leech_cave" }; public static readonly HashSet<string> MudPilePrefabNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "MudPile", "MudPile2" }; public const string IronScrapItemName = "IronScrap"; public static readonly HashSet<string> WoodItemNames = new HashSet<string> { "Wood", "RoundLog", "FineWood", "Blackwood", "Frostwood", "YggdrasilWood" }; public static readonly HashSet<string> StoneItemNames = new HashSet<string> { "Stone", "Flint" }; public const string ResinItemName = "Resin"; public static bool CountsAsArrowHitOnEnemy(bool firedByLocalPlayer, string skillName, bool targetIsCharacter, bool targetIsPlayer, bool targetIsTamed, bool targetIsDead) { if (firedByLocalPlayer && skillName == "Bows" && targetIsCharacter && !targetIsPlayer && !targetIsTamed) { return !targetIsDead; } return false; } public static int BreadToCount(bool itemIsDone, string producedItemName, int amountTaken) { if (!itemIsDone || !(producedItemName == "Bread") || amountTaken <= 0) { return 0; } return amountTaken; } public static int FoodBurntToCoal(bool isBurntStatus, int amountTaken) { if (!isBurntStatus || amountTaken <= 0) { return 0; } return amountTaken; } public static int CookedChickenMeatToCount(bool itemIsDone, string producedItemName, int amountTaken) { if (!itemIsDone || !(producedItemName == "CookedChickenMeat") || amountTaken <= 0) { return 0; } return amountTaken; } public static int LoxPieToCount(bool itemIsDone, string producedItemName, int amountTaken) { if (!itemIsDone || !(producedItemName == "LoxMeatPie") || amountTaken <= 0) { return 0; } return amountTaken; } public static string TamedSpeciesCounterKey(string prefabName) { return prefabName switch { "Boar" => "Custom:TamedBoar", "Wolf" => "Custom:TamedWolf", "Lox" => "Custom:TamedLox", _ => null, }; } public static int MeadsToCount(bool statusIsReady, int producedItems) { if (!statusIsReady || producedItems <= 0) { return 0; } return producedItems; } public static int DwarfEyesToCount(bool byLocalPlayer, bool pickupSucceeded, string itemSharedName, int stack) { if (!(byLocalPlayer && pickupSucceeded) || !(itemSharedName == "GreydwarfEye") || stack <= 0) { return 0; } return stack; } public static float NorthDistanceToRaise(float positionZ) { if (!(positionZ > 0f)) { return 0f; } return positionZ; } public static float BoatSecondsToAdd(bool isOnBoat, float elapsedSeconds, float maxPlausibleGapSeconds) { if (!isOnBoat || !(elapsedSeconds > 0f) || !(elapsedSeconds <= maxPlausibleGapSeconds)) { return 0f; } return elapsedSeconds; } public static bool CountsAsVomitBomb(bool eatenSuccessfully, string itemSharedName, int activeFoodCountBeforeEating) { if (eatenSuccessfully && itemSharedName == "Pukeberries") { return activeFoodCountBeforeEating == 0; } return false; } public static bool IsQualifyingOutpost(bool bedIsCovered, bool hasCraftingStationNearby, bool hasPortalNearby) { return bedIsCovered && hasCraftingStationNearby && hasPortalNearby; } public static bool IsNewLandmass(IEnumerable<bool> oceanSeparatedFromEachKnownLandmass) { return oceanSeparatedFromEachKnownLandmass.All((bool separated) => separated); } public static bool CountsAsWeaponKill(bool byLocalPlayer, string skillName, string wantSkillName, bool targetIsCharacter, bool targetIsPlayer, bool targetIsTamed, bool targetIsDeadNow) { return byLocalPlayer && skillName == wantSkillName && targetIsCharacter && !targetIsPlayer && !targetIsTamed && targetIsDeadNow; } public static bool CountsAsPoisonDeath(bool targetIsLocalPlayer, bool targetIsDeadNow, float poisonDamageInHit) { if (targetIsLocalPlayer && targetIsDeadNow) { return poisonDamageInHit > 0f; } return false; } public static bool CountsAsLeechHit(bool targetIsLocalPlayer, string attackerPrefabName) { if (targetIsLocalPlayer && attackerPrefabName != null) { return LeechPrefabNames.Contains(attackerPrefabName); } return false; } public static int GuckToCount(bool byLocalPlayer, bool pickupSucceeded, string itemPrefabName, int stack) { if (!(byLocalPlayer && pickupSucceeded) || !(itemPrefabName == "Guck") || stack <= 0) { return 0; } return stack; } public static int BloodBagToCount(bool byLocalPlayer, bool pickupSucceeded, string itemPrefabName, int stack) { if (!(byLocalPlayer && pickupSucceeded) || !(itemPrefabName == "Bloodbag") || stack <= 0) { return 0; } return stack; } public static int ElderBarkToCount(bool byLocalPlayer, bool pickupSucceeded, string itemPrefabName, int stack) { if (!(byLocalPlayer && pickupSucceeded) || !(itemPrefabName == "ElderBark") || stack <= 0) { return 0; } return stack; } public static bool CountsAsMuddyScrapPileOpened(bool byLocalPlayer, bool nowFullyDestroyed, string prefabName) { if (byLocalPlayer && nowFullyDestroyed && prefabName != null) { return MudPilePrefabNames.Contains(prefabName); } return false; } public static int IronToProcess(string queuedOreName, int queuedAmount) { if (!(queuedOreName == "IronScrap") || queuedAmount <= 0) { return 0; } return queuedAmount; } public static float SwampSecondsToAdd(bool isInSwamp, float elapsedSeconds, float maxPlausibleGapSeconds) { if (!isInSwamp || !(elapsedSeconds > 0f) || !(elapsedSeconds <= maxPlausibleGapSeconds)) { return 0f; } return elapsedSeconds; } public static int WoodToCount(bool byLocalPlayer, bool pickupSucceeded, string itemPrefabName, int stack) { if (!(byLocalPlayer && pickupSucceeded) || stack <= 0 || itemPrefabName == null || !WoodItemNames.Contains(itemPrefabName)) { return 0; } return stack; } public static int StoneToCount(bool byLocalPlayer, bool pickupSucceeded, string itemPrefabName, int stack) { if (!(byLocalPlayer && pickupSucceeded) || stack <= 0 || itemPrefabName == null || !StoneItemNames.Contains(itemPrefabName)) { return 0; } return stack; } public static float BakerySecondsToAdd(bool isNearOven, float elapsedSeconds, float maxPlausibleGapSeconds) { if (!isNearOven || !(elapsedSeconds > 0f) || !(elapsedSeconds <= maxPlausibleGapSeconds)) { return 0f; } return elapsedSeconds; } public static int ResinToCount(bool byLocalPlayer, bool pickupSucceeded, string itemPrefabName, int stack) { if (!(byLocalPlayer && pickupSucceeded) || !(itemPrefabName == "Resin") || stack <= 0) { return 0; } return stack; } } } namespace OdinEye.Client.Hud { public sealed class ClockHudElement { private static readonly Lazy<PropertyInfo> TmpTextProperty = new Lazy<PropertyInfo>(() => AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "Unity.TextMeshPro")?.GetType("TMPro.TMP_Text")?.GetProperty("text")); private static readonly FieldInfo BiomeNameSmallField = typeof(Minimap).GetField("m_biomeNameSmall", BindingFlags.Instance | BindingFlags.Public); private Component clockLabel; private bool triedToCreate; private Minimap ownerMinimap; public void SetText(string text) { Component val = EnsureCreated(); PropertyInfo value = TmpTextProperty.Value; if ((Object)(object)val == (Object)null || value == null) { return; } try { value.SetValue(val, text); } catch { } } private Component EnsureCreated() { //IL_00b9: 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_00cd: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Minimap.instance != (Object)(object)ownerMinimap) { ownerMinimap = Minimap.instance; clockLabel = null; triedToCreate = false; } if ((Object)(object)clockLabel != (Object)null || triedToCreate || (Object)(object)Minimap.instance == (Object)null || BiomeNameSmallField == null) { return clockLabel; } triedToCreate = true; try { object? value = BiomeNameSmallField.GetValue(Minimap.instance); Component val = (Component)((value is Component) ? value : null); if (val == null) { return null; } GameObject val2 = Object.Instantiate<GameObject>(val.gameObject, val.transform.parent); ((Object)val2).name = "OdinEyeClockText"; RectTransform component = val2.GetComponent<RectTransform>(); if ((Object)(object)component != (Object)null) { component.anchoredPosition += new Vector2(0f, -30f); } clockLabel = val2.GetComponent(((object)val).GetType()); } catch { clockLabel = null; } return clockLabel; } } public static class EnvManTimeReader { private static readonly Lazy<FieldInfo> TotalSecondsField = new Lazy<FieldInfo>(() => typeof(EnvMan).GetField("m_totalSeconds", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)); public static double? GetTotalSeconds() { EnvMan instance = EnvMan.instance; FieldInfo value = TotalSecondsField.Value; if ((Object)(object)instance == (Object)null || value == null) { return null; } try { return (double)value.GetValue(instance); } catch { return null; } } } public static class TemporalClock { private const double DayLengthSeconds = 1800.0; private const double DawnPhaseOffset = 270.0; private const double DaylightSeconds = 1260.0; private const double NightSeconds = 540.0; public static string Format(double totalSeconds) { double num = Mod(Mod(totalSeconds, 1800.0) - 270.0, 1800.0); double num2 = Mod((num < 1260.0) ? (6.0 + num / 1260.0 * 12.0) : (18.0 + (num - 1260.0) / 540.0 * 12.0), 24.0); int num3 = (int)num2; int num4 = (int)Math.Round((num2 - (double)num3) * 60.0); if (num4 == 60) { num4 = 0; num3 = (num3 + 1) % 24; } string arg = ((num3 < 12) ? "AM" : "PM"); int num5 = num3 % 12; if (num5 == 0) { num5 = 12; } return $"{num5}:{num4:D2} {arg}"; } private static double Mod(double value, double modulus) { double num = value % modulus; if (!(num < 0.0)) { return num; } return num + modulus; } } }
plugins/OdinEye.Models.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using NGuid; using ProtoBuf; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyCompany("sparcopt")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+54bc12311450691a0ebdbd8b7a54cc3a57b8e72c")] [assembly: AssemblyProduct("OdinEye.Models")] [assembly: AssemblyTitle("OdinEye.Models")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/sparcopt/odin-eye")] [assembly: AssemblyVersion("1.0.0.0")] namespace OdinEye.Models { public static class NameBasedGuid { private static readonly Guid NamespaceId = new Guid("4b01a09a-9b18-493c-9877-4786611eeea2"); public static Guid NewPlayerGuid(string steamId, string playerName) { return GuidHelpers.CreateFromName(NamespaceId, steamId + playerName, 5); } } } namespace OdinEye.Models.Proto { public enum EventType { Unknown = 0, PlayerJoin = 1, PlayerSpawn = 2, PlayerDeath = 3, PlayerDisconnect = 4, PlayerChat = 5, PlayersSleepStart = 6, PlayerSleepStop = 7, GameAwake = 50, GameQuit = 51, WorldLoad = 53, WorldSave = 54, ServerShutdown = 55, GlobalKeyAdd = 56, GlobalKeyRemove = 57, RandomEventActivate = 100, RandomEventDeactivate = 101, RandomEventSet = 102, EnvironmentMorningStart = 200, EnvironmentEveningStart = 201, EnemyKilled = 300, BedRemoved = 400, BedMissingAtRespawn = 401 } [ProtoContract] public class GameEvent : Message { [ProtoMember(1)] public string Message { get; set; } [ProtoMember(2)] public EventType Type { get; set; } [ProtoMember(4)] public Player Player { get; set; } [ProtoMember(5)] public IDictionary<string, object> Data { get; set; } [ProtoIgnore] public IDictionary<string, object> Details { get; set; } public static GameEvent New(EventType type, string message, Player player = null) { return new GameEvent { CreatedDate = DateTime.UtcNow, Type = type, Message = message, Player = player }; } public static GameEvent New(EventType type, string message, Player player, IDictionary<string, object> details) { return new GameEvent { CreatedDate = DateTime.UtcNow, Type = type, Message = message, Player = player, Details = details }; } } [ProtoContract] public class GameStatsSnapshot : Message { [ProtoMember(1)] public IEnumerable<PlayerStats> PlayerStats { get; set; } = new List<PlayerStats>(); [ProtoMember(2)] public WorldStats WorldStats { get; set; } } [ProtoContract] [ProtoInclude(2, typeof(GameEvent))] [ProtoInclude(3, typeof(GameStatsSnapshot))] public class Message { [ProtoMember(1)] public DateTime CreatedDate { get; set; } } [ProtoContract] public class Player { [ProtoMember(1)] public Guid Id { get; set; } [ProtoMember(2)] public string CharacterId { get; set; } [ProtoMember(3)] public string SteamId { get; set; } [ProtoMember(4)] public string Name { get; set; } [ProtoMember(5)] public float Health { get; set; } [ProtoMember(6)] public float MaxHealth { get; set; } [ProtoMember(7)] public float Stamina { get; set; } } [ProtoContract] public class PlayerStats { [ProtoMember(1)] public Guid Id { get; set; } [ProtoMember(2)] public string CharacterId { get; set; } [ProtoMember(3)] public float Health { get; set; } [ProtoMember(4)] public float MaxHealth { get; set; } [ProtoMember(5)] public float Stamina { get; set; } } [ProtoContract] public class WorldStats { [ProtoMember(1)] public int DayNumber { get; set; } [ProtoMember(2)] public string DayCycle { get; set; } } } namespace OdinEye.Models.Api { public class AcceptedResponse { public bool Accepted { get; set; } = true; } public class Boss { public string Key { get; set; } public string Name { get; set; } public bool IsDefeated { get; set; } } public class BossDetails { public int ActiveBosses { get; set; } public IEnumerable<Boss> Bosses { get; set; } = Enumerable.Empty<Boss>(); } public class CharacterStatsSubmission { public Dictionary<string, float> Stats { get; set; } public SubmissionMeta Meta { get; set; } } public class SubmissionMeta { public string PlayerId { get; set; } public string ClientVersion { get; set; } } public class CheatStatusSubmission { public bool Cheated { get; set; } public bool BypassEnabled { get; set; } } public class ClientEventsSubmission { public List<ClientEvent> Events { get; set; } } public class ClientEvent { public string Type { get; set; } public string OwnerPlayerId { get; set; } public string RemoverPlayerId { get; set; } public float X { get; set; } public float Y { get; set; } public float Z { get; set; } } public class GlobalKey { public string Name { get; set; } public string Value { get; set; } } public class NotifyRequest { public string Message { get; set; } } public class Player { public Guid Id { get; set; } public string CharacterId { get; set; } public string SteamId { get; set; } public string Name { get; set; } public float Health { get; set; } public float MaxHealth { get; set; } public float Stamina { get; set; } } public class ServerDetails { public int MaxNumberOfPlayers { get; set; } public string GameVersion { get; set; } public string SteamAppId { get; set; } } public class WorldDetails { public int DayNumber { get; set; } public string DayCycle { get; set; } public double NetTime { get; set; } public string WorldName { get; set; } public string SeedName { get; set; } public IEnumerable<string> WorldKeys { get; set; } = Enumerable.Empty<string>(); public IEnumerable<GlobalKey> GlobalKeys { get; set; } = Enumerable.Empty<GlobalKey>(); } public class WorldModifiersDetails { public IEnumerable<WorldModifierValue> Modifiers { get; set; } = Enumerable.Empty<WorldModifierValue>(); public string Summary { get; set; } } public class WorldModifierValue { public string Category { get; set; } public string Value { get; set; } } }
plugins/NGuid.dll
Decompiled a day agousing System; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyCompany("Bradley Grainger")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright 2023 Bradley Grainger")] [assembly: AssemblyDescription("Creates GUIDs according to RFC 4122 and the UUID Revision Working Draft.")] [assembly: AssemblyFileVersion("0.2.0.0")] [assembly: AssemblyInformationalVersion("0.2.0+0752fad0bd0c6f95ace49389bc01bdc07f7d6c59")] [assembly: AssemblyProduct("NGuid")] [assembly: AssemblyTitle("NGuid")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/bgrainger/NGuid.git")] [assembly: InternalsVisibleTo("NGuid.Tests")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace NGuid { public static class GuidHelpers { public static readonly Guid DnsNamespace = new Guid("6ba7b810-9dad-11d1-80b4-00c04fd430c8"); public static readonly Guid UrlNamespace = new Guid("6ba7b811-9dad-11d1-80b4-00c04fd430c8"); public static readonly Guid IsoOidNamespace = new Guid("6ba7b812-9dad-11d1-80b4-00c04fd430c8"); public static readonly Guid Sha256HashSpaceId = new Guid("3fb32780-953c-4464-9cfd-e85dbbe9843d"); public static readonly Guid Sha384HashSpaceId = new Guid("e6800581-f333-484b-8778-601ff2b58da8"); public static readonly Guid Sha512HashSpaceId = new Guid("0fde22f2-e7ba-4fd1-9753-9c2ea88fa3f9"); private static readonly DateTime s_gregorianEpoch = new DateTime(1582, 10, 15, 0, 0, 0, DateTimeKind.Utc); public static Guid CreateFromName(Guid namespaceId, string name, int version = 5) { if (name == null) { throw new ArgumentNullException("name"); } byte[] bytes = Encoding.UTF8.GetBytes(name); return CreateFromName(namespaceId, bytes, version); } public static Guid CreateFromName(Guid namespaceId, byte[] name, int version = 5) { if ((version != 3 && version != 5) || 1 == 0) { throw new ArgumentOutOfRangeException("version", version, "version must be either 3 or 5."); } byte[] array = namespaceId.ToByteArray(); SwapByteOrder(array); byte[] buffer = array.Concat(name).ToArray(); byte[] sourceArray; using (HashAlgorithm hashAlgorithm = ((version == 3) ? ((HashAlgorithm)MD5.Create()) : ((HashAlgorithm)SHA1.Create()))) { sourceArray = hashAlgorithm.ComputeHash(buffer); } byte[] array2 = new byte[16]; Array.Copy(sourceArray, 0, array2, 0, 16); array2[6] = (byte)((array2[6] & 0xF) | (version << 4)); array2[8] = (byte)((array2[8] & 0x3F) | 0x80); SwapByteOrder(array2); return new Guid(array2); } public static Guid CreateVersion6() { return CreateVersion6(DateTimeOffset.UtcNow); } private static Guid CreateVersion6(DateTimeOffset timestamp) { long ticks = (timestamp.UtcDateTime - s_gregorianEpoch).Ticks; if (ticks < 0) { throw new ArgumentOutOfRangeException("timestamp", timestamp, "The timestamp must be after 15 October 1582."); } uint a = (uint)(ticks >> 28); ushort b = (ushort)(ticks >> 12); ushort c = (ushort)((ticks & 0xFFF) | 0x6000); byte[] array = new byte[8]; using RandomNumberGenerator randomNumberGenerator = RandomNumberGenerator.Create(); randomNumberGenerator.GetBytes(array); return new Guid(a, b, c, (byte)((array[0] & 0x3F) | 0x80), array[1], array[2], array[3], array[4], array[5], array[6], array[7]); } public static Guid CreateVersion6FromVersion1(Guid guid) { byte[] array = guid.ToByteArray(); if ((array[7] & 0xF0) != 16) { throw new ArgumentException("The GUID must be a version 1 GUID.", "guid"); } ulong num = (ulong)((long)(array[7] & 0xF) << 56) | ((ulong)array[6] << 48) | ((ulong)array[5] << 40) | ((ulong)array[4] << 32) | ((ulong)array[3] << 24) | ((ulong)array[2] << 16) | ((ulong)array[1] << 8) | array[0]; array[3] = (byte)(num >> 52); array[2] = (byte)(num >> 44); array[1] = (byte)(num >> 36); array[0] = (byte)(num >> 28); array[5] = (byte)(num >> 20); array[4] = (byte)(num >> 12); array[7] = (byte)(0x60 | ((num >> 8) & 0xF)); array[6] = (byte)num; return new Guid(array); } public static Guid CreateVersion7() { return CreateVersion7(DateTimeOffset.UtcNow); } private static Guid CreateVersion7(DateTimeOffset timestamp) { long num = timestamp.ToUnixTimeMilliseconds(); if (num < 0) { throw new ArgumentOutOfRangeException("timestamp", timestamp, "The timestamp must be after 1 January 1970."); } uint a = (uint)(num >> 16); ushort b = (ushort)num; byte[] array = new byte[10]; using RandomNumberGenerator randomNumberGenerator = RandomNumberGenerator.Create(); randomNumberGenerator.GetBytes(array); ushort c = (ushort)(0x7000uL | (ulong)((array[0] & 0xF) << 8) | array[1]); return new Guid(a, b, c, (byte)((array[2] & 0x3F) | 0x80), array[3], array[4], array[5], array[6], array[7], array[8], array[9]); } public static Guid CreateVersion8(byte[] bytes) { if (bytes == null) { throw new ArgumentNullException("bytes"); } if (bytes.Length < 16) { throw new ArgumentException("At least sixteen bytes must be provided", "bytes"); } byte[] array = new byte[16]; bytes.AsSpan(0, 16).CopyTo(array); SwapByteOrder(array); array[7] = (byte)(0x80 | (array[7] & 0xF)); array[8] = (byte)(0x80 | (array[8] & 0x3F)); return new Guid(array); } public static Guid CreateVersion8FromName(HashAlgorithmName hashAlgorithmName, Guid namespaceId, byte[] name) { var (guid, hashAlgorithm) = GetHashSpaceAndAlgorithm(hashAlgorithmName); using (hashAlgorithm) { byte[] array = guid.ToByteArray(); SwapByteOrder(array); hashAlgorithm.TransformBlock(array, 0, array.Length, null, 0); byte[] array2 = namespaceId.ToByteArray(); SwapByteOrder(array2); hashAlgorithm.TransformBlock(array2, 0, array2.Length, null, 0); hashAlgorithm.TransformFinalBlock(name, 0, name.Length); byte[] array3 = new byte[16]; Array.Copy(hashAlgorithm.Hash, array3, 16); array3[6] = (byte)((array3[6] & 0xF) | 0x80); array3[8] = (byte)((array3[8] & 0x3F) | 0x80); SwapByteOrder(array3); return new Guid(array3); } } private static (Guid NamespaceId, HashAlgorithm Algorithm) GetHashSpaceAndAlgorithm(HashAlgorithmName hashAlgorithmName) { return hashAlgorithmName.Name switch { "SHA256" => (NamespaceId: Sha256HashSpaceId, Algorithm: SHA256.Create()), "SHA384" => (NamespaceId: Sha384HashSpaceId, Algorithm: SHA384.Create()), "SHA512" => (NamespaceId: Sha512HashSpaceId, Algorithm: SHA512.Create()), _ => throw new ArgumentException("Unsupported hash algorithm name: " + hashAlgorithmName.Name, "hashAlgorithmName"), }; } internal static void SwapByteOrder(Span<byte> guid) { SwapBytes(guid, 0, 3); SwapBytes(guid, 1, 2); SwapBytes(guid, 4, 5); SwapBytes(guid, 6, 7); } private static void SwapBytes(Span<byte> guid, int left, int right) { ref byte source = ref Unsafe.AsRef(in guid[0]); ref byte reference = ref Unsafe.Add(ref source, right); ref byte reference2 = ref Unsafe.Add(ref source, left); byte b = Unsafe.Add(ref source, left); byte b2 = Unsafe.Add(ref source, right); reference = b; reference2 = b2; } } }
plugins/Utf8Json.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Dynamic; using System.Globalization; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Numerics; 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 System.Threading.Tasks; using Utf8Json.Formatters; using Utf8Json.Formatters.Internal; using Utf8Json.Internal; using Utf8Json.Internal.DoubleConversion; using Utf8Json.Internal.Emit; using Utf8Json.Resolvers; using Utf8Json.Resolvers.Internal; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Utf8Json")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("929e3779-4c3a-42a3-bc72-3d77511e988f")] [assembly: AssemblyFileVersion("1.3.7")] [assembly: TargetFramework(".NETFramework,Version=v4.7", FrameworkDisplayName = ".NET Framework 4.7")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.3.7.0")] [module: UnverifiableCode] namespace Utf8Json { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Interface, AllowMultiple = false, Inherited = true)] public class JsonFormatterAttribute : Attribute { public Type FormatterType { get; private set; } public object[] Arguments { get; private set; } public JsonFormatterAttribute(Type formatterType) { FormatterType = formatterType; } public JsonFormatterAttribute(Type formatterType, params object[] arguments) { FormatterType = formatterType; Arguments = arguments; } } [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = true)] public class SerializationConstructorAttribute : Attribute { } public delegate void JsonSerializeAction<T>(ref JsonWriter writer, T value, IJsonFormatterResolver resolver); public delegate T JsonDeserializeFunc<T>(ref JsonReader reader, IJsonFormatterResolver resolver); public interface IJsonFormatter { } public interface IJsonFormatter<T> : IJsonFormatter { void Serialize(ref JsonWriter writer, T value, IJsonFormatterResolver formatterResolver); T Deserialize(ref JsonReader reader, IJsonFormatterResolver formatterResolver); } public interface IObjectPropertyNameFormatter<T> { void SerializeToPropertyName(ref JsonWriter writer, T value, IJsonFormatterResolver formatterResolver); T DeserializeFromPropertyName(ref JsonReader reader, IJsonFormatterResolver formatterResolver); } public static class JsonFormatterExtensions { public static string ToJsonString<T>(this IJsonFormatter<T> formatter, T value, IJsonFormatterResolver formatterResolver) { JsonWriter writer = default(JsonWriter); formatter.Serialize(ref writer, value, formatterResolver); return writer.ToString(); } } public interface IJsonFormatterResolver { IJsonFormatter<T> GetFormatter<T>(); } public static class JsonFormatterResolverExtensions { public static IJsonFormatter<T> GetFormatterWithVerify<T>(this IJsonFormatterResolver resolver) { IJsonFormatter<T> formatter; try { formatter = resolver.GetFormatter<T>(); } catch (TypeInitializationException innerException) { while (innerException.InnerException != null) { innerException = (TypeInitializationException)innerException.InnerException; } throw innerException; } if (formatter == null) { throw new FormatterNotRegisteredException(typeof(T).FullName + " is not registered in this resolver. resolver:" + resolver.GetType().Name); } return formatter; } public static object GetFormatterDynamic(this IJsonFormatterResolver resolver, Type type) { return typeof(IJsonFormatterResolver).GetRuntimeMethod("GetFormatter", Type.EmptyTypes).MakeGenericMethod(type).Invoke(resolver, null); } } public class FormatterNotRegisteredException : Exception { public FormatterNotRegisteredException(string message) : base(message) { } } public struct JsonReader { internal static class StringBuilderCache { [ThreadStatic] private static byte[] buffer; [ThreadStatic] private static char[] codePointStringBuffer; public static byte[] GetBuffer() { if (buffer == null) { buffer = new byte[65535]; } return buffer; } public static char[] GetCodePointStringBuffer() { if (codePointStringBuffer == null) { codePointStringBuffer = new char[65535]; } return codePointStringBuffer; } } private static readonly ArraySegment<byte> nullTokenSegment = new ArraySegment<byte>(new byte[4] { 110, 117, 108, 108 }, 0, 4); private static readonly byte[] bom = Encoding.UTF8.GetPreamble(); private readonly byte[] bytes; private int offset; private bool IsInRange => offset < bytes.Length; public JsonReader(byte[] bytes) : this(bytes, 0) { } public JsonReader(byte[] bytes, int offset) { this.bytes = bytes; this.offset = offset; checked { if (bytes.Length >= 3 && bytes[offset] == bom[0] && bytes[offset + 1] == bom[1] && bytes[offset + 2] == bom[2]) { this.offset = (offset += 3); } } } private JsonParsingException CreateParsingException(string expected) { char c = (char)bytes[offset]; string text = c.ToString(); int num = offset; try { switch (GetCurrentJsonToken()) { case JsonToken.Number: { ArraySegment<byte> arraySegment = ReadNumberSegment(); text = StringEncoding.UTF8.GetString(arraySegment.Array, arraySegment.Offset, arraySegment.Count); break; } case JsonToken.String: text = "\"" + ReadString() + "\""; break; case JsonToken.True: text = "true"; break; case JsonToken.False: text = "false"; break; case JsonToken.Null: text = "null"; break; } } catch { } return new JsonParsingException("expected:'" + expected + "', actual:'" + text + "', at offset:" + num, bytes, num, offset, text); } private JsonParsingException CreateParsingExceptionMessage(string message) { char c = (char)bytes[offset]; string actualChar = c.ToString(); int limit = offset; return new JsonParsingException(message, bytes, limit, limit, actualChar); } public void AdvanceOffset(int offset) { checked { this.offset += offset; } } public byte[] GetBufferUnsafe() { return bytes; } public int GetCurrentOffsetUnsafe() { return offset; } public JsonToken GetCurrentJsonToken() { SkipWhiteSpace(); if (offset < bytes.Length) { return bytes[offset] switch { 123 => JsonToken.BeginObject, 125 => JsonToken.EndObject, 91 => JsonToken.BeginArray, 93 => JsonToken.EndArray, 116 => JsonToken.True, 102 => JsonToken.False, 110 => JsonToken.Null, 44 => JsonToken.ValueSeparator, 58 => JsonToken.NameSeparator, 45 => JsonToken.Number, 48 => JsonToken.Number, 49 => JsonToken.Number, 50 => JsonToken.Number, 51 => JsonToken.Number, 52 => JsonToken.Number, 53 => JsonToken.Number, 54 => JsonToken.Number, 55 => JsonToken.Number, 56 => JsonToken.Number, 57 => JsonToken.Number, 34 => JsonToken.String, _ => JsonToken.None, }; } return JsonToken.None; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SkipWhiteSpace() { for (int i = offset; i < bytes.Length; i = checked(i + 1)) { switch (bytes[i]) { case 47: i = ReadComment(bytes, i); break; default: offset = i; return; case 9: case 10: case 13: case 32: break; } } offset = bytes.Length; } public bool ReadIsNull() { SkipWhiteSpace(); checked { if (IsInRange && bytes[offset] == 110) { if (bytes[offset + 1] == 117 && bytes[offset + 2] == 108 && bytes[offset + 3] == 108) { offset += 4; return true; } throw CreateParsingException("null"); } return false; } } public bool ReadIsBeginArray() { SkipWhiteSpace(); checked { if (IsInRange && bytes[offset] == 91) { offset++; return true; } return false; } } public void ReadIsBeginArrayWithVerify() { if (!ReadIsBeginArray()) { throw CreateParsingException("["); } } public bool ReadIsEndArray() { SkipWhiteSpace(); checked { if (IsInRange && bytes[offset] == 93) { offset++; return true; } return false; } } public void ReadIsEndArrayWithVerify() { if (!ReadIsEndArray()) { throw CreateParsingException("]"); } } public bool ReadIsEndArrayWithSkipValueSeparator(ref int count) { SkipWhiteSpace(); checked { if (IsInRange && bytes[offset] == 93) { offset++; return true; } if (count++ != 0) { ReadIsValueSeparatorWithVerify(); } return false; } } public bool ReadIsInArray(ref int count) { if (count == 0) { ReadIsBeginArrayWithVerify(); if (ReadIsEndArray()) { return false; } } else { if (ReadIsEndArray()) { return false; } ReadIsValueSeparatorWithVerify(); } checked { count++; return true; } } public bool ReadIsBeginObject() { SkipWhiteSpace(); checked { if (IsInRange && bytes[offset] == 123) { offset++; return true; } return false; } } public void ReadIsBeginObjectWithVerify() { if (!ReadIsBeginObject()) { throw CreateParsingException("{"); } } public bool ReadIsEndObject() { SkipWhiteSpace(); checked { if (IsInRange && bytes[offset] == 125) { offset++; return true; } return false; } } public void ReadIsEndObjectWithVerify() { if (!ReadIsEndObject()) { throw CreateParsingException("}"); } } public bool ReadIsEndObjectWithSkipValueSeparator(ref int count) { SkipWhiteSpace(); checked { if (IsInRange && bytes[offset] == 125) { offset++; return true; } if (count++ != 0) { ReadIsValueSeparatorWithVerify(); } return false; } } public bool ReadIsInObject(ref int count) { if (count == 0) { ReadIsBeginObjectWithVerify(); if (ReadIsEndObject()) { return false; } } else { if (ReadIsEndObject()) { return false; } ReadIsValueSeparatorWithVerify(); } checked { count++; return true; } } public bool ReadIsValueSeparator() { SkipWhiteSpace(); checked { if (IsInRange && bytes[offset] == 44) { offset++; return true; } return false; } } public void ReadIsValueSeparatorWithVerify() { if (!ReadIsValueSeparator()) { throw CreateParsingException(","); } } public bool ReadIsNameSeparator() { SkipWhiteSpace(); checked { if (IsInRange && bytes[offset] == 58) { offset++; return true; } return false; } } public void ReadIsNameSeparatorWithVerify() { if (!ReadIsNameSeparator()) { throw CreateParsingException(":"); } } private void ReadStringSegmentCore(out byte[] resultBytes, out int resultOffset, out int resultLength) { byte[] array = null; int num = 0; char[] array2 = null; int num2 = 0; if (bytes[offset] != 34) { throw CreateParsingException("String Begin Token"); } checked { offset++; int num3 = offset; for (int i = offset; i < bytes.Length; i++) { byte b = 0; switch (bytes[i]) { case 92: { switch (unchecked((char)bytes[checked(i + 1)])) { case '"': case '/': case '\\': b = bytes[i + 1]; break; case 'b': b = 8; break; case 'f': b = 12; break; case 'n': b = 10; break; case 'r': b = 13; break; case 't': b = 9; break; case 'u': { if (array2 == null) { array2 = StringBuilderCache.GetCodePointStringBuffer(); } if (num2 == 0) { if (array == null) { array = StringBuilderCache.GetBuffer(); } int num5 = i - num3; BinaryUtil.EnsureCapacity(ref array, num, num5 + 1); Buffer.BlockCopy(bytes, num3, array, num, num5); num += num5; } if (array2.Length == num2) { Array.Resize(ref array2, array2.Length * 2); } byte a = bytes[i + 2]; unchecked { char b2 = (char)bytes[checked(i + 3)]; char c = (char)bytes[checked(i + 4)]; char d = (char)bytes[checked(i + 5)]; int codePoint = GetCodePoint((char)a, b2, c, d); array2[checked(num2++)] = (char)checked((ushort)codePoint); } i += 5; offset += 6; num3 = offset; continue; } default: throw CreateParsingExceptionMessage("Bad JSON escape."); } if (array == null) { array = StringBuilderCache.GetBuffer(); } if (num2 != 0) { BinaryUtil.EnsureCapacity(ref array, num, StringEncoding.UTF8.GetMaxByteCount(num2)); num += StringEncoding.UTF8.GetBytes(array2, 0, num2, array, num); num2 = 0; } int num6 = i - num3; BinaryUtil.EnsureCapacity(ref array, num, num6 + 1); Buffer.BlockCopy(bytes, num3, array, num, num6); num += num6; array[num++] = b; i++; offset += 2; num3 = offset; continue; } case 34: { offset++; if (num == 0 && num2 == 0) { resultBytes = bytes; resultOffset = num3; resultLength = offset - 1 - num3; return; } if (array == null) { array = StringBuilderCache.GetBuffer(); } if (num2 != 0) { BinaryUtil.EnsureCapacity(ref array, num, StringEncoding.UTF8.GetMaxByteCount(num2)); num += StringEncoding.UTF8.GetBytes(array2, 0, num2, array, num); num2 = 0; } int num4 = offset - num3 - 1; BinaryUtil.EnsureCapacity(ref array, num, num4); Buffer.BlockCopy(bytes, num3, array, num, num4); num += num4; resultBytes = array; resultOffset = 0; resultLength = num; return; } } if (num2 != 0) { if (array == null) { array = StringBuilderCache.GetBuffer(); } BinaryUtil.EnsureCapacity(ref array, num, StringEncoding.UTF8.GetMaxByteCount(num2)); num += StringEncoding.UTF8.GetBytes(array2, 0, num2, array, num); num2 = 0; } offset++; } resultLength = 0; resultBytes = null; resultOffset = 0; throw CreateParsingException("String End Token"); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int GetCodePoint(char a, char b, char c, char d) { return checked(((ToNumber(a) * 16 + ToNumber(b)) * 16 + ToNumber(c)) * 16 + ToNumber(d)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int ToNumber(char x) { checked { if ('0' <= x && x <= '9') { return x - 48; } if ('a' <= x && x <= 'f') { return x - 97 + 10; } if ('A' <= x && x <= 'F') { return x - 65 + 10; } throw new JsonParsingException("Invalid Character" + x); } } public ArraySegment<byte> ReadStringSegmentUnsafe() { if (ReadIsNull()) { return nullTokenSegment; } ReadStringSegmentCore(out var resultBytes, out var resultOffset, out var resultLength); return new ArraySegment<byte>(resultBytes, resultOffset, resultLength); } public string ReadString() { if (ReadIsNull()) { return null; } ReadStringSegmentCore(out var resultBytes, out var resultOffset, out var resultLength); return Encoding.UTF8.GetString(resultBytes, resultOffset, resultLength); } public string ReadPropertyName() { string result = ReadString(); ReadIsNameSeparatorWithVerify(); return result; } public ArraySegment<byte> ReadStringSegmentRaw() { ArraySegment<byte> arraySegment = default(ArraySegment<byte>); if (ReadIsNull()) { return nullTokenSegment; } checked { if (bytes[offset++] != 34) { throw CreateParsingException("\""); } int num = offset; for (int i = offset; i < bytes.Length; i++) { if (bytes[i] == 34 && bytes[i - 1] != 92) { offset = i + 1; return new ArraySegment<byte>(bytes, num, offset - num - 1); } } throw CreateParsingExceptionMessage("not found end string."); } } public ArraySegment<byte> ReadPropertyNameSegmentRaw() { ArraySegment<byte> result = ReadStringSegmentRaw(); ReadIsNameSeparatorWithVerify(); return result; } public bool ReadBoolean() { SkipWhiteSpace(); checked { if (bytes[offset] == 116) { if (bytes[offset + 1] == 114 && bytes[offset + 2] == 117 && bytes[offset + 3] == 101) { offset += 4; return true; } throw CreateParsingException("true"); } if (bytes[offset] == 102) { if (bytes[offset + 1] == 97 && bytes[offset + 2] == 108 && bytes[offset + 3] == 115 && bytes[offset + 4] == 101) { offset += 5; return false; } throw CreateParsingException("false"); } throw CreateParsingException("true | false"); } } private static bool IsWordBreak(byte c) { switch (c) { case 32: case 34: case 44: case 58: case 91: case 93: case 123: case 125: return true; default: return false; } } public void ReadNext() { JsonToken currentJsonToken = GetCurrentJsonToken(); ReadNextCore(currentJsonToken); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private void ReadNextCore(JsonToken token) { checked { switch (token) { case JsonToken.BeginObject: case JsonToken.EndObject: case JsonToken.BeginArray: case JsonToken.EndArray: case JsonToken.ValueSeparator: case JsonToken.NameSeparator: offset++; break; case JsonToken.True: case JsonToken.Null: offset += 4; break; case JsonToken.False: offset += 5; break; case JsonToken.String: { offset++; for (int j = offset; j < bytes.Length; j++) { if (bytes[j] == 34 && bytes[j - 1] != 92) { offset = j + 1; return; } } throw CreateParsingExceptionMessage("not found end string."); } case JsonToken.Number: { for (int i = offset; i < bytes.Length; i++) { if (IsWordBreak(bytes[i])) { offset = i; return; } } offset = bytes.Length; break; } case JsonToken.None: break; } } } public void ReadNextBlock() { ReadNextBlockCore(0); } private void ReadNextBlockCore(int stack) { JsonToken currentJsonToken = GetCurrentJsonToken(); checked { switch (currentJsonToken) { default: return; case JsonToken.BeginObject: case JsonToken.BeginArray: offset++; ReadNextBlockCore(stack + 1); return; case JsonToken.EndObject: case JsonToken.EndArray: offset++; if (stack - 1 != 0) { ReadNextBlockCore(stack - 1); } return; case JsonToken.Number: case JsonToken.String: case JsonToken.True: case JsonToken.False: case JsonToken.Null: case JsonToken.ValueSeparator: case JsonToken.NameSeparator: break; case JsonToken.None: return; } } do { ReadNextCore(currentJsonToken); currentJsonToken = GetCurrentJsonToken(); } while (stack != 0 && (int)currentJsonToken >= 5); if (stack != 0) { ReadNextBlockCore(stack); } } public ArraySegment<byte> ReadNextBlockSegment() { int num = offset; ReadNextBlock(); return new ArraySegment<byte>(bytes, num, checked(offset - num)); } public sbyte ReadSByte() { return checked((sbyte)ReadInt64()); } public short ReadInt16() { return checked((short)ReadInt64()); } public int ReadInt32() { return checked((int)ReadInt64()); } public long ReadInt64() { SkipWhiteSpace(); int readCount; long result = NumberConverter.ReadInt64(bytes, offset, out readCount); if (readCount == 0) { throw CreateParsingException("Number Token"); } checked { offset += readCount; return result; } } public byte ReadByte() { return checked((byte)ReadUInt64()); } public ushort ReadUInt16() { return checked((ushort)ReadUInt64()); } public uint ReadUInt32() { return checked((uint)ReadUInt64()); } public ulong ReadUInt64() { SkipWhiteSpace(); int readCount; ulong result = NumberConverter.ReadUInt64(bytes, offset, out readCount); if (readCount == 0) { throw CreateParsingException("Number Token"); } checked { offset += readCount; return result; } } public float ReadSingle() { SkipWhiteSpace(); int readCount; float result = StringToDoubleConverter.ToSingle(bytes, offset, out readCount); if (readCount == 0) { throw CreateParsingException("Number Token"); } checked { offset += readCount; return result; } } public double ReadDouble() { SkipWhiteSpace(); int readCount; double result = StringToDoubleConverter.ToDouble(bytes, offset, out readCount); if (readCount == 0) { throw CreateParsingException("Number Token"); } checked { offset += readCount; return result; } } public ArraySegment<byte> ReadNumberSegment() { SkipWhiteSpace(); int num = offset; int num2 = offset; checked { while (true) { if (num2 < bytes.Length) { if (!NumberConverter.IsNumberRepresentation(bytes[num2])) { offset = num2; break; } num2++; continue; } offset = bytes.Length; break; } return new ArraySegment<byte>(bytes, num, offset - num); } } private static int ReadComment(byte[] bytes, int offset) { checked { if (bytes[offset + 1] == 47) { offset += 2; for (int i = offset; i < bytes.Length; i++) { if (bytes[i] == 13 || bytes[i] == 10) { return i; } } throw new JsonParsingException("Can not find end token of single line comment(\r or \n)."); } if (bytes[offset + 1] == 42) { offset += 2; for (int j = offset; j < bytes.Length; j++) { if (bytes[j] == 42 && bytes[j + 1] == 47) { return j + 1; } } throw new JsonParsingException("Can not find end token of multi line comment(*/)."); } return offset; } } } public class JsonParsingException : Exception { private WeakReference underyingBytes; private int limit; public int Offset { get; private set; } public string ActualChar { get; set; } public JsonParsingException(string message) : base(message) { } public JsonParsingException(string message, byte[] underlyingBytes, int offset, int limit, string actualChar) : base(message) { underyingBytes = new WeakReference(underlyingBytes); Offset = offset; ActualChar = actualChar; this.limit = limit; } public byte[] GetUnderlyingByteArrayUnsafe() { return underyingBytes.Target as byte[]; } public string GetUnderlyingStringUnsafe() { if (underyingBytes.Target is byte[] bytes) { return StringEncoding.UTF8.GetString(bytes, 0, limit) + "..."; } return null; } } public static class JsonSerializer { private static class MemoryPool { [ThreadStatic] private static byte[] buffer; public static byte[] GetBuffer() { if (buffer == null) { buffer = new byte[65536]; } return buffer; } } public static class NonGeneric { private delegate void SerializeJsonWriter(ref JsonWriter writer, object value, IJsonFormatterResolver resolver); private delegate object DeserializeJsonReader(ref JsonReader reader, IJsonFormatterResolver resolver); private class CompiledMethods { public readonly Func<object, IJsonFormatterResolver, byte[]> serialize1; public readonly Action<Stream, object, IJsonFormatterResolver> serialize2; public readonly SerializeJsonWriter serialize3; public readonly Func<object, IJsonFormatterResolver, ArraySegment<byte>> serializeUnsafe; public readonly Func<object, IJsonFormatterResolver, string> toJsonString; public readonly Func<string, IJsonFormatterResolver, object> deserialize1; public readonly Func<byte[], int, IJsonFormatterResolver, object> deserialize2; public readonly Func<Stream, IJsonFormatterResolver, object> deserialize3; public readonly DeserializeJsonReader deserialize4; public readonly Func<Stream, object, IJsonFormatterResolver, Task> serializeAsync; public readonly Func<Stream, IJsonFormatterResolver, Task<object>> deserializeAsync; public CompiledMethods(Type type) { DynamicMethod dynamicMethod = new DynamicMethod("serialize1", typeof(byte[]), new Type[2] { typeof(object), typeof(IJsonFormatterResolver) }, type.Module, skipVisibility: true); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); iLGenerator.EmitLdarg(0); iLGenerator.EmitUnboxOrCast(type); iLGenerator.EmitLdarg(1); iLGenerator.EmitCall(GetMethod(type, "Serialize", new Type[2] { null, typeof(IJsonFormatterResolver) })); iLGenerator.Emit(OpCodes.Ret); serialize1 = CreateDelegate<Func<object, IJsonFormatterResolver, byte[]>>(dynamicMethod); DynamicMethod dynamicMethod2 = new DynamicMethod("serialize2", null, new Type[3] { typeof(Stream), typeof(object), typeof(IJsonFormatterResolver) }, type.Module, skipVisibility: true); ILGenerator iLGenerator2 = dynamicMethod2.GetILGenerator(); iLGenerator2.EmitLdarg(0); iLGenerator2.EmitLdarg(1); iLGenerator2.EmitUnboxOrCast(type); iLGenerator2.EmitLdarg(2); iLGenerator2.EmitCall(GetMethod(type, "Serialize", new Type[3] { typeof(Stream), null, typeof(IJsonFormatterResolver) })); iLGenerator2.Emit(OpCodes.Ret); serialize2 = CreateDelegate<Action<Stream, object, IJsonFormatterResolver>>(dynamicMethod2); DynamicMethod dynamicMethod3 = new DynamicMethod("serialize3", null, new Type[3] { typeof(JsonWriter).MakeByRefType(), typeof(object), typeof(IJsonFormatterResolver) }, type.Module, skipVisibility: true); ILGenerator iLGenerator3 = dynamicMethod3.GetILGenerator(); iLGenerator3.EmitLdarg(0); iLGenerator3.EmitLdarg(1); iLGenerator3.EmitUnboxOrCast(type); iLGenerator3.EmitLdarg(2); iLGenerator3.EmitCall(GetMethod(type, "Serialize", new Type[3] { typeof(JsonWriter).MakeByRefType(), null, typeof(IJsonFormatterResolver) })); iLGenerator3.Emit(OpCodes.Ret); serialize3 = CreateDelegate<SerializeJsonWriter>(dynamicMethod3); DynamicMethod dynamicMethod4 = new DynamicMethod("serializeUnsafe", typeof(ArraySegment<byte>), new Type[2] { typeof(object), typeof(IJsonFormatterResolver) }, type.Module, skipVisibility: true); ILGenerator iLGenerator4 = dynamicMethod4.GetILGenerator(); iLGenerator4.EmitLdarg(0); iLGenerator4.EmitUnboxOrCast(type); iLGenerator4.EmitLdarg(1); iLGenerator4.EmitCall(GetMethod(type, "SerializeUnsafe", new Type[2] { null, typeof(IJsonFormatterResolver) })); iLGenerator4.Emit(OpCodes.Ret); serializeUnsafe = CreateDelegate<Func<object, IJsonFormatterResolver, ArraySegment<byte>>>(dynamicMethod4); DynamicMethod dynamicMethod5 = new DynamicMethod("toJsonString", typeof(string), new Type[2] { typeof(object), typeof(IJsonFormatterResolver) }, type.Module, skipVisibility: true); ILGenerator iLGenerator5 = dynamicMethod5.GetILGenerator(); iLGenerator5.EmitLdarg(0); iLGenerator5.EmitUnboxOrCast(type); iLGenerator5.EmitLdarg(1); iLGenerator5.EmitCall(GetMethod(type, "ToJsonString", new Type[2] { null, typeof(IJsonFormatterResolver) })); iLGenerator5.Emit(OpCodes.Ret); toJsonString = CreateDelegate<Func<object, IJsonFormatterResolver, string>>(dynamicMethod5); DynamicMethod dynamicMethod6 = new DynamicMethod("Deserialize", typeof(object), new Type[2] { typeof(string), typeof(IJsonFormatterResolver) }, type.Module, skipVisibility: true); ILGenerator iLGenerator6 = dynamicMethod6.GetILGenerator(); iLGenerator6.EmitLdarg(0); iLGenerator6.EmitLdarg(1); iLGenerator6.EmitCall(GetMethod(type, "Deserialize", new Type[2] { typeof(string), typeof(IJsonFormatterResolver) })); iLGenerator6.EmitBoxOrDoNothing(type); iLGenerator6.Emit(OpCodes.Ret); deserialize1 = CreateDelegate<Func<string, IJsonFormatterResolver, object>>(dynamicMethod6); DynamicMethod dynamicMethod7 = new DynamicMethod("Deserialize", typeof(object), new Type[3] { typeof(byte[]), typeof(int), typeof(IJsonFormatterResolver) }, type.Module, skipVisibility: true); ILGenerator iLGenerator7 = dynamicMethod7.GetILGenerator(); iLGenerator7.EmitLdarg(0); iLGenerator7.EmitLdarg(1); iLGenerator7.EmitLdarg(2); iLGenerator7.EmitCall(GetMethod(type, "Deserialize", new Type[3] { typeof(byte[]), typeof(int), typeof(IJsonFormatterResolver) })); iLGenerator7.EmitBoxOrDoNothing(type); iLGenerator7.Emit(OpCodes.Ret); deserialize2 = CreateDelegate<Func<byte[], int, IJsonFormatterResolver, object>>(dynamicMethod7); DynamicMethod dynamicMethod8 = new DynamicMethod("Deserialize", typeof(object), new Type[2] { typeof(Stream), typeof(IJsonFormatterResolver) }, type.Module, skipVisibility: true); ILGenerator iLGenerator8 = dynamicMethod8.GetILGenerator(); iLGenerator8.EmitLdarg(0); iLGenerator8.EmitLdarg(1); iLGenerator8.EmitCall(GetMethod(type, "Deserialize", new Type[2] { typeof(Stream), typeof(IJsonFormatterResolver) })); iLGenerator8.EmitBoxOrDoNothing(type); iLGenerator8.Emit(OpCodes.Ret); deserialize3 = CreateDelegate<Func<Stream, IJsonFormatterResolver, object>>(dynamicMethod8); DynamicMethod dynamicMethod9 = new DynamicMethod("Deserialize", typeof(object), new Type[2] { typeof(JsonReader).MakeByRefType(), typeof(IJsonFormatterResolver) }, type.Module, skipVisibility: true); ILGenerator iLGenerator9 = dynamicMethod9.GetILGenerator(); iLGenerator9.EmitLdarg(0); iLGenerator9.EmitLdarg(1); iLGenerator9.EmitCall(GetMethod(type, "Deserialize", new Type[2] { typeof(JsonReader).MakeByRefType(), typeof(IJsonFormatterResolver) })); iLGenerator9.EmitBoxOrDoNothing(type); iLGenerator9.Emit(OpCodes.Ret); deserialize4 = CreateDelegate<DeserializeJsonReader>(dynamicMethod9); DynamicMethod dynamicMethod10 = new DynamicMethod("SerializeAsync", typeof(Task), new Type[3] { typeof(Stream), typeof(object), typeof(IJsonFormatterResolver) }, type.Module, skipVisibility: true); ILGenerator iLGenerator10 = dynamicMethod10.GetILGenerator(); iLGenerator10.EmitLdarg(0); iLGenerator10.EmitLdarg(1); iLGenerator10.EmitUnboxOrCast(type); iLGenerator10.EmitLdarg(2); iLGenerator10.EmitCall(GetMethod(type, "SerializeAsync", new Type[3] { typeof(Stream), null, typeof(IJsonFormatterResolver) })); iLGenerator10.Emit(OpCodes.Ret); serializeAsync = CreateDelegate<Func<Stream, object, IJsonFormatterResolver, Task>>(dynamicMethod10); DynamicMethod dynamicMethod11 = new DynamicMethod("DeserializeAsync", typeof(Task<object>), new Type[2] { typeof(Stream), typeof(IJsonFormatterResolver) }, type.Module, skipVisibility: true); ILGenerator iLGenerator11 = dynamicMethod11.GetILGenerator(); iLGenerator11.EmitLdarg(0); iLGenerator11.EmitLdarg(1); iLGenerator11.EmitCall(GetMethod(type, "DeserializeAsync", new Type[2] { typeof(Stream), typeof(IJsonFormatterResolver) })); iLGenerator11.EmitCall(typeof(CompiledMethods).GetMethod("TaskCast", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).MakeGenericMethod(type)); iLGenerator11.Emit(OpCodes.Ret); deserializeAsync = CreateDelegate<Func<Stream, IJsonFormatterResolver, Task<object>>>(dynamicMethod11); } private static async Task<object> TaskCast<T>(Task<T> task) { return await task.ConfigureAwait(continueOnCapturedContext: false); } private static T CreateDelegate<T>(DynamicMethod dm) { return (T)(object)dm.CreateDelegate(typeof(T)); } private static MethodInfo GetMethod(Type type, string name, Type[] arguments) { return (from x in typeof(JsonSerializer).GetMethods(BindingFlags.Static | BindingFlags.Public) where x.Name == name select x).Single(delegate(MethodInfo x) { ParameterInfo[] parameters = x.GetParameters(); if (parameters.Length != arguments.Length) { return false; } for (int i = 0; i < parameters.Length; i = checked(i + 1)) { if ((!(arguments[i] == null) || !parameters[i].ParameterType.IsGenericParameter) && parameters[i].ParameterType != arguments[i]) { return false; } } return true; }).MakeGenericMethod(type); } } private static readonly Func<Type, CompiledMethods> CreateCompiledMethods; private static readonly ThreadsafeTypeKeyHashTable<CompiledMethods> serializes; static NonGeneric() { serializes = new ThreadsafeTypeKeyHashTable<CompiledMethods>(64); CreateCompiledMethods = (Type t) => new CompiledMethods(t); } private static CompiledMethods GetOrAdd(Type type) { return serializes.GetOrAdd(type, CreateCompiledMethods); } public static byte[] Serialize(object value) { if (value == null) { return JsonSerializer.Serialize(value); } return Serialize(value.GetType(), value, defaultResolver); } public static byte[] Serialize(Type type, object value) { return Serialize(type, value, defaultResolver); } public static byte[] Serialize(object value, IJsonFormatterResolver resolver) { if (value == null) { return JsonSerializer.Serialize(value, resolver); } return Serialize(value.GetType(), value, resolver); } public static byte[] Serialize(Type type, object value, IJsonFormatterResolver resolver) { return GetOrAdd(type).serialize1(value, resolver); } public static void Serialize(Stream stream, object value) { if (value == null) { JsonSerializer.Serialize(stream, value); } else { Serialize(value.GetType(), stream, value, defaultResolver); } } public static void Serialize(Type type, Stream stream, object value) { Serialize(type, stream, value, defaultResolver); } public static void Serialize(Stream stream, object value, IJsonFormatterResolver resolver) { if (value == null) { JsonSerializer.Serialize(stream, value, resolver); } else { Serialize(value.GetType(), stream, value, resolver); } } public static void Serialize(Type type, Stream stream, object value, IJsonFormatterResolver resolver) { GetOrAdd(type).serialize2(stream, value, resolver); } public static Task SerializeAsync(Stream stream, object value) { if (value == null) { return JsonSerializer.SerializeAsync(stream, value); } return SerializeAsync(value.GetType(), stream, value, defaultResolver); } public static Task SerializeAsync(Type type, Stream stream, object value) { return SerializeAsync(type, stream, value, defaultResolver); } public static Task SerializeAsync(Stream stream, object value, IJsonFormatterResolver resolver) { if (value == null) { return JsonSerializer.SerializeAsync(stream, value, resolver); } return SerializeAsync(value.GetType(), stream, value, resolver); } public static Task SerializeAsync(Type type, Stream stream, object value, IJsonFormatterResolver resolver) { return GetOrAdd(type).serializeAsync(stream, value, resolver); } public static void Serialize(ref JsonWriter writer, object value, IJsonFormatterResolver resolver) { if (value == null) { writer.WriteNull(); } else { Serialize(value.GetType(), ref writer, value, resolver); } } public static void Serialize(Type type, ref JsonWriter writer, object value) { Serialize(type, ref writer, value, defaultResolver); } public static void Serialize(Type type, ref JsonWriter writer, object value, IJsonFormatterResolver resolver) { GetOrAdd(type).serialize3(ref writer, value, resolver); } public static ArraySegment<byte> SerializeUnsafe(object value) { if (value == null) { return JsonSerializer.SerializeUnsafe(value); } return SerializeUnsafe(value.GetType(), value); } public static ArraySegment<byte> SerializeUnsafe(Type type, object value) { return SerializeUnsafe(type, value, defaultResolver); } public static ArraySegment<byte> SerializeUnsafe(object value, IJsonFormatterResolver resolver) { if (value == null) { return JsonSerializer.SerializeUnsafe(value); } return SerializeUnsafe(value.GetType(), value, resolver); } public static ArraySegment<byte> SerializeUnsafe(Type type, object value, IJsonFormatterResolver resolver) { return GetOrAdd(type).serializeUnsafe(value, resolver); } public static string ToJsonString(object value) { if (value == null) { return "null"; } return ToJsonString(value.GetType(), value); } public static string ToJsonString(Type type, object value) { return ToJsonString(type, value, defaultResolver); } public static string ToJsonString(object value, IJsonFormatterResolver resolver) { if (value == null) { return "null"; } return ToJsonString(value.GetType(), value, resolver); } public static string ToJsonString(Type type, object value, IJsonFormatterResolver resolver) { return GetOrAdd(type).toJsonString(value, resolver); } public static object Deserialize(Type type, string json) { return Deserialize(type, json, defaultResolver); } public static object Deserialize(Type type, string json, IJsonFormatterResolver resolver) { return GetOrAdd(type).deserialize1(json, resolver); } public static object Deserialize(Type type, byte[] bytes) { return Deserialize(type, bytes, defaultResolver); } public static object Deserialize(Type type, byte[] bytes, IJsonFormatterResolver resolver) { return Deserialize(type, bytes, 0, defaultResolver); } public static object Deserialize(Type type, byte[] bytes, int offset) { return Deserialize(type, bytes, offset, defaultResolver); } public static object Deserialize(Type type, byte[] bytes, int offset, IJsonFormatterResolver resolver) { return GetOrAdd(type).deserialize2(bytes, offset, resolver); } public static object Deserialize(Type type, Stream stream) { return Deserialize(type, stream, defaultResolver); } public static object Deserialize(Type type, Stream stream, IJsonFormatterResolver resolver) { return GetOrAdd(type).deserialize3(stream, resolver); } public static object Deserialize(Type type, ref JsonReader reader) { return Deserialize(type, ref reader, defaultResolver); } public static object Deserialize(Type type, ref JsonReader reader, IJsonFormatterResolver resolver) { return GetOrAdd(type).deserialize4(ref reader, resolver); } public static Task<object> DeserializeAsync(Type type, Stream stream) { return DeserializeAsync(type, stream, defaultResolver); } public static Task<object> DeserializeAsync(Type type, Stream stream, IJsonFormatterResolver resolver) { return GetOrAdd(type).deserializeAsync(stream, resolver); } } private static IJsonFormatterResolver defaultResolver; private static readonly byte[][] indent = (from x in Enumerable.Range(0, 100) select Encoding.UTF8.GetBytes(new string(' ', checked(x * 2)))).ToArray(); private static readonly byte[] newLine = Encoding.UTF8.GetBytes(Environment.NewLine); public static IJsonFormatterResolver DefaultResolver { get { if (defaultResolver == null) { defaultResolver = StandardResolver.Default; } return defaultResolver; } } public static bool IsInitialized => defaultResolver != null; public static void SetDefaultResolver(IJsonFormatterResolver resolver) { defaultResolver = resolver; } public static byte[] Serialize<T>(T obj) { return Serialize(obj, defaultResolver); } public static byte[] Serialize<T>(T value, IJsonFormatterResolver resolver) { if (resolver == null) { resolver = DefaultResolver; } JsonWriter writer = new JsonWriter(MemoryPool.GetBuffer()); resolver.GetFormatterWithVerify<T>().Serialize(ref writer, value, resolver); return writer.ToUtf8ByteArray(); } public static void Serialize<T>(ref JsonWriter writer, T value) { Serialize(ref writer, value, defaultResolver); } public static void Serialize<T>(ref JsonWriter writer, T value, IJsonFormatterResolver resolver) { if (resolver == null) { resolver = DefaultResolver; } resolver.GetFormatterWithVerify<T>().Serialize(ref writer, value, resolver); } public static void Serialize<T>(Stream stream, T value) { Serialize(stream, value, defaultResolver); } public static void Serialize<T>(Stream stream, T value, IJsonFormatterResolver resolver) { if (resolver == null) { resolver = DefaultResolver; } ArraySegment<byte> arraySegment = SerializeUnsafe(value, resolver); stream.Write(arraySegment.Array, arraySegment.Offset, arraySegment.Count); } public static Task SerializeAsync<T>(Stream stream, T value) { return SerializeAsync(stream, value, defaultResolver); } public static async Task SerializeAsync<T>(Stream stream, T value, IJsonFormatterResolver resolver) { if (resolver == null) { resolver = DefaultResolver; } byte[] buf = BufferPool.Default.Rent(); try { JsonWriter writer = new JsonWriter(buf); resolver.GetFormatterWithVerify<T>().Serialize(ref writer, value, resolver); ArraySegment<byte> buffer = writer.GetBuffer(); await stream.WriteAsync(buffer.Array, buffer.Offset, buffer.Count).ConfigureAwait(continueOnCapturedContext: false); } finally { BufferPool.Default.Return(buf); } } public static ArraySegment<byte> SerializeUnsafe<T>(T obj) { return SerializeUnsafe(obj, defaultResolver); } public static ArraySegment<byte> SerializeUnsafe<T>(T value, IJsonFormatterResolver resolver) { if (resolver == null) { resolver = DefaultResolver; } JsonWriter writer = new JsonWriter(MemoryPool.GetBuffer()); resolver.GetFormatterWithVerify<T>().Serialize(ref writer, value, resolver); return writer.GetBuffer(); } public static string ToJsonString<T>(T value) { return ToJsonString(value, defaultResolver); } public static string ToJsonString<T>(T value, IJsonFormatterResolver resolver) { if (resolver == null) { resolver = DefaultResolver; } JsonWriter writer = new JsonWriter(MemoryPool.GetBuffer()); resolver.GetFormatterWithVerify<T>().Serialize(ref writer, value, resolver); return writer.ToString(); } public static T Deserialize<T>(string json) { return Deserialize<T>(json, defaultResolver); } public static T Deserialize<T>(string json, IJsonFormatterResolver resolver) { return Deserialize<T>(StringEncoding.UTF8.GetBytes(json), resolver); } public static T Deserialize<T>(byte[] bytes) { return Deserialize<T>(bytes, defaultResolver); } public static T Deserialize<T>(byte[] bytes, IJsonFormatterResolver resolver) { return Deserialize<T>(bytes, 0, resolver); } public static T Deserialize<T>(byte[] bytes, int offset) { return Deserialize<T>(bytes, offset, defaultResolver); } public static T Deserialize<T>(byte[] bytes, int offset, IJsonFormatterResolver resolver) { if (resolver == null) { resolver = DefaultResolver; } JsonReader reader = new JsonReader(bytes, offset); return resolver.GetFormatterWithVerify<T>().Deserialize(ref reader, resolver); } public static T Deserialize<T>(ref JsonReader reader) { return Deserialize<T>(ref reader, defaultResolver); } public static T Deserialize<T>(ref JsonReader reader, IJsonFormatterResolver resolver) { if (resolver == null) { resolver = DefaultResolver; } return resolver.GetFormatterWithVerify<T>().Deserialize(ref reader, resolver); } public static T Deserialize<T>(Stream stream) { return Deserialize<T>(stream, defaultResolver); } public static T Deserialize<T>(Stream stream, IJsonFormatterResolver resolver) { if (resolver == null) { resolver = DefaultResolver; } if (stream is MemoryStream memoryStream && memoryStream.TryGetBuffer(out var buffer)) { if (new JsonReader(buffer.Array, buffer.Offset).GetCurrentJsonToken() == JsonToken.Number) { byte[] array = new byte[buffer.Count]; Buffer.BlockCopy(buffer.Array, buffer.Offset, array, 0, array.Length); return Deserialize<T>(array, 0, resolver); } return Deserialize<T>(buffer.Array, buffer.Offset, resolver); } byte[] buffer2 = MemoryPool.GetBuffer(); int newSize = FillFromStream(stream, ref buffer2); if (new JsonReader(buffer2).GetCurrentJsonToken() == JsonToken.Number) { buffer2 = BinaryUtil.FastCloneWithResize(buffer2, newSize); } return Deserialize<T>(buffer2, resolver); } public static Task<T> DeserializeAsync<T>(Stream stream) { return DeserializeAsync<T>(stream, defaultResolver); } public static async Task<T> DeserializeAsync<T>(Stream stream, IJsonFormatterResolver resolver) { if (resolver == null) { resolver = DefaultResolver; } byte[] buffer = BufferPool.Default.Rent(); byte[] buf = buffer; checked { try { int length = 0; while (true) { int num; int read = (num = await stream.ReadAsync(buf, length, buf.Length - length).ConfigureAwait(continueOnCapturedContext: false)); if (num <= 0) { break; } length += read; if (length == buf.Length) { BinaryUtil.FastResize(ref buf, length * 2); } } if (new JsonReader(buf).GetCurrentJsonToken() == JsonToken.Number) { buf = BinaryUtil.FastCloneWithResize(buf, length); } return Deserialize<T>(buf, resolver); } finally { BufferPool.Default.Return(buffer); } } } public static string PrettyPrint(byte[] json) { return PrettyPrint(json, 0); } public static string PrettyPrint(byte[] json, int offset) { JsonReader reader = new JsonReader(json, offset); JsonWriter writer = new JsonWriter(MemoryPool.GetBuffer()); WritePrittyPrint(ref reader, ref writer, 0); return writer.ToString(); } public static string PrettyPrint(string json) { JsonReader reader = new JsonReader(Encoding.UTF8.GetBytes(json)); JsonWriter writer = new JsonWriter(MemoryPool.GetBuffer()); WritePrittyPrint(ref reader, ref writer, 0); return writer.ToString(); } public static byte[] PrettyPrintByteArray(byte[] json) { return PrettyPrintByteArray(json, 0); } public static byte[] PrettyPrintByteArray(byte[] json, int offset) { JsonReader reader = new JsonReader(json, offset); JsonWriter writer = new JsonWriter(MemoryPool.GetBuffer()); WritePrittyPrint(ref reader, ref writer, 0); return writer.ToUtf8ByteArray(); } public static byte[] PrettyPrintByteArray(string json) { JsonReader reader = new JsonReader(Encoding.UTF8.GetBytes(json)); JsonWriter writer = new JsonWriter(MemoryPool.GetBuffer()); WritePrittyPrint(ref reader, ref writer, 0); return writer.ToUtf8ByteArray(); } private static void WritePrittyPrint(ref JsonReader reader, ref JsonWriter writer, int depth) { checked { switch (reader.GetCurrentJsonToken()) { case JsonToken.BeginObject: { writer.WriteBeginObject(); writer.WriteRaw(newLine); int count2 = 0; while (reader.ReadIsInObject(ref count2)) { if (count2 != 1) { writer.WriteRaw(44); writer.WriteRaw(newLine); } writer.WriteRaw(indent[depth + 1]); writer.WritePropertyName(reader.ReadPropertyName()); writer.WriteRaw(32); WritePrittyPrint(ref reader, ref writer, depth + 1); } writer.WriteRaw(newLine); writer.WriteRaw(indent[depth]); writer.WriteEndObject(); break; } case JsonToken.BeginArray: { writer.WriteBeginArray(); writer.WriteRaw(newLine); int count = 0; while (reader.ReadIsInArray(ref count)) { if (count != 1) { writer.WriteRaw(44); writer.WriteRaw(newLine); } writer.WriteRaw(indent[depth + 1]); WritePrittyPrint(ref reader, ref writer, depth + 1); } writer.WriteRaw(newLine); writer.WriteRaw(indent[depth]); writer.WriteEndArray(); break; } case JsonToken.Number: { double value3 = reader.ReadDouble(); writer.WriteDouble(value3); break; } case JsonToken.String: { string value2 = reader.ReadString(); writer.WriteString(value2); break; } case JsonToken.True: case JsonToken.False: { bool value = reader.ReadBoolean(); writer.WriteBoolean(value); break; } case JsonToken.Null: reader.ReadIsNull(); writer.WriteNull(); break; case JsonToken.EndObject: case JsonToken.EndArray: break; } } } private static int FillFromStream(Stream input, ref byte[] buffer) { int num = 0; checked { int num2; while ((num2 = input.Read(buffer, num, buffer.Length - num)) > 0) { num += num2; if (num == buffer.Length) { BinaryUtil.FastResize(ref buffer, num * 2); } } return num; } } } public enum JsonToken : byte { None, BeginObject, EndObject, BeginArray, EndArray, Number, String, True, False, Null, ValueSeparator, NameSeparator } public struct JsonWriter { private static readonly byte[] emptyBytes = new byte[0]; internal byte[] buffer; internal int offset; public int CurrentOffset => offset; public void AdvanceOffset(int offset) { checked { this.offset += offset; } } public static byte[] GetEncodedPropertyName(string propertyName) { JsonWriter jsonWriter = default(JsonWriter); jsonWriter.WritePropertyName(propertyName); return jsonWriter.ToUtf8ByteArray(); } public static byte[] GetEncodedPropertyNameWithPrefixValueSeparator(string propertyName) { JsonWriter jsonWriter = default(JsonWriter); jsonWriter.WriteValueSeparator(); jsonWriter.WritePropertyName(propertyName); return jsonWriter.ToUtf8ByteArray(); } public static byte[] GetEncodedPropertyNameWithBeginObject(string propertyName) { JsonWriter jsonWriter = default(JsonWriter); jsonWriter.WriteBeginObject(); jsonWriter.WritePropertyName(propertyName); return jsonWriter.ToUtf8ByteArray(); } public static byte[] GetEncodedPropertyNameWithoutQuotation(string propertyName) { JsonWriter jsonWriter = default(JsonWriter); jsonWriter.WriteString(propertyName); ArraySegment<byte> arraySegment = jsonWriter.GetBuffer(); checked { byte[] array = new byte[arraySegment.Count - 2]; Buffer.BlockCopy(arraySegment.Array, arraySegment.Offset + 1, array, 0, array.Length); return array; } } public JsonWriter(byte[] initialBuffer) { buffer = initialBuffer; offset = 0; } public ArraySegment<byte> GetBuffer() { if (buffer == null) { return new ArraySegment<byte>(emptyBytes, 0, 0); } return new ArraySegment<byte>(buffer, 0, offset); } public byte[] ToUtf8ByteArray() { if (buffer == null) { return emptyBytes; } return BinaryUtil.FastCloneWithResize(buffer, offset); } public override string ToString() { if (buffer == null) { return null; } return Encoding.UTF8.GetString(buffer, 0, offset); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void EnsureCapacity(int appendLength) { BinaryUtil.EnsureCapacity(ref buffer, offset, appendLength); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteRaw(byte rawValue) { BinaryUtil.EnsureCapacity(ref buffer, offset, 1); buffer[checked(offset++)] = rawValue; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteRaw(byte[] rawValue) { UnsafeMemory.WriteRaw(ref this, rawValue); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteRawUnsafe(byte rawValue) { buffer[checked(offset++)] = rawValue; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteBeginArray() { BinaryUtil.EnsureCapacity(ref buffer, offset, 1); buffer[checked(offset++)] = 91; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteEndArray() { BinaryUtil.EnsureCapacity(ref buffer, offset, 1); buffer[checked(offset++)] = 93; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteBeginObject() { BinaryUtil.EnsureCapacity(ref buffer, offset, 1); buffer[checked(offset++)] = 123; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteEndObject() { BinaryUtil.EnsureCapacity(ref buffer, offset, 1); buffer[checked(offset++)] = 125; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteValueSeparator() { BinaryUtil.EnsureCapacity(ref buffer, offset, 1); buffer[checked(offset++)] = 44; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteNameSeparator() { BinaryUtil.EnsureCapacity(ref buffer, offset, 1); buffer[checked(offset++)] = 58; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WritePropertyName(string propertyName) { WriteString(propertyName); WriteNameSeparator(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteQuotation() { BinaryUtil.EnsureCapacity(ref buffer, offset, 1); buffer[checked(offset++)] = 34; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteNull() { BinaryUtil.EnsureCapacity(ref buffer, offset, 4); buffer[offset] = 110; checked { buffer[offset + 1] = 117; buffer[offset + 2] = 108; buffer[offset + 3] = 108; offset += 4; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteBoolean(bool value) { checked { if (value) { BinaryUtil.EnsureCapacity(ref buffer, offset, 4); buffer[offset] = 116; buffer[offset + 1] = 114; buffer[offset + 2] = 117; buffer[offset + 3] = 101; offset += 4; } else { BinaryUtil.EnsureCapacity(ref buffer, offset, 5); buffer[offset] = 102; buffer[offset + 1] = 97; buffer[offset + 2] = 108; buffer[offset + 3] = 115; buffer[offset + 4] = 101; offset += 5; } } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteTrue() { BinaryUtil.EnsureCapacity(ref buffer, offset, 4); buffer[offset] = 116; checked { buffer[offset + 1] = 114; buffer[offset + 2] = 117; buffer[offset + 3] = 101; offset += 4; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteFalse() { BinaryUtil.EnsureCapacity(ref buffer, offset, 5); buffer[offset] = 102; checked { buffer[offset + 1] = 97; buffer[offset + 2] = 108; buffer[offset + 3] = 115; buffer[offset + 4] = 101; offset += 5; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteSingle(float value) { checked { offset += DoubleToStringConverter.GetBytes(ref buffer, offset, value); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteDouble(double value) { checked { offset += DoubleToStringConverter.GetBytes(ref buffer, offset, value); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteByte(byte value) { WriteUInt64(value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteUInt16(ushort value) { WriteUInt64(value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteUInt32(uint value) { WriteUInt64(value); } public void WriteUInt64(ulong value) { checked { offset += NumberConverter.WriteUInt64(ref buffer, offset, value); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteSByte(sbyte value) { WriteInt64(value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteInt16(short value) { WriteInt64(value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteInt32(int value) { WriteInt64(value); } public void WriteInt64(long value) { checked { offset += NumberConverter.WriteInt64(ref buffer, offset, value); } } public void WriteString(string value) { if (value == null) { WriteNull(); return; } int num = offset; checked { int num2 = StringEncoding.UTF8.GetMaxByteCount(value.Length) + 2; BinaryUtil.EnsureCapacity(ref buffer, num, num2); int num3 = 0; _ = value.Length; buffer[offset++] = 34; for (int i = 0; i < value.Length; i++) { byte b = 0; switch (value[i]) { case '"': b = 34; break; case '\\': b = 92; break; case '\b': b = 98; break; case '\f': b = 102; break; case '\n': b = 110; break; case '\r': b = 114; break; case '\t': b = 116; break; default: continue; } num2 += 2; BinaryUtil.EnsureCapacity(ref buffer, num, num2); offset += StringEncoding.UTF8.GetBytes(value, num3, i - num3, buffer, offset); num3 = i + 1; buffer[offset++] = 92; buffer[offset++] = b; } if (num3 != value.Length) { offset += StringEncoding.UTF8.GetBytes(value, num3, value.Length - num3, buffer, offset); } buffer[offset++] = 34; } } } } namespace Utf8Json.Resolvers { public sealed class AttributeFormatterResolver : IJsonFormatterResolver { private static class FormatterCache<T> { public static readonly IJsonFormatter<T> formatter; static FormatterCache() { JsonFormatterAttribute customAttribute = typeof(T).GetTypeInfo().GetCustomAttribute<JsonFormatterAttribute>(); if (customAttribute == null) { return; } try { if (customAttribute.FormatterType.IsGenericType && !customAttribute.FormatterType.GetTypeInfo().IsConstructedGenericType()) { formatter = (IJsonFormatter<T>)Activator.CreateInstance(customAttribute.FormatterType.MakeGenericType(typeof(T)), customAttribute.Arguments); } else { formatter = (IJsonFormatter<T>)Activator.CreateInstance(customAttribute.FormatterType, customAttribute.Arguments); } } catch (Exception innerException) { throw new InvalidOperationException("Can not create formatter from JsonFormatterAttribute, check the target formatter is public and has constructor with right argument. FormatterType:" + customAttribute.FormatterType.Name, innerException); } } } public static IJsonFormatterResolver Instance = new AttributeFormatterResolver(); private AttributeFormatterResolver() { } public IJsonFormatter<T> GetFormatter<T>() { return FormatterCache<T>.formatter; } } public sealed class BuiltinResolver : IJsonFormatterResolver { private static class FormatterCache<T> { public static readonly IJsonFormatter<T> formatter; static FormatterCache() { formatter = (IJsonFormatter<T>)BuiltinResolverGetFormatterHelper.GetFormatter(typeof(T)); } } internal static class BuiltinResolverGetFormatterHelper { private static readonly Dictionary<Type, object> formatterMap = new Dictionary<Type, object> { { typeof(short), Int16Formatter.Default }, { typeof(int), Int32Formatter.Default }, { typeof(long), Int64Formatter.Default }, { typeof(ushort), UInt16Formatter.Default }, { typeof(uint), UInt32Formatter.Default }, { typeof(ulong), UInt64Formatter.Default }, { typeof(float), SingleFormatter.Default }, { typeof(double), DoubleFormatter.Default }, { typeof(bool), BooleanFormatter.Default }, { typeof(byte), ByteFormatter.Default }, { typeof(sbyte), SByteFormatter.Default }, { typeof(short?), NullableInt16Formatter.Default }, { typeof(int?), NullableInt32Formatter.Default }, { typeof(long?), NullableInt64Formatter.Default }, { typeof(ushort?), NullableUInt16Formatter.Default }, { typeof(uint?), NullableUInt32Formatter.Default }, { typeof(ulong?), NullableUInt64Formatter.Default }, { typeof(float?), NullableSingleFormatter.Default }, { typeof(double?), NullableDoubleFormatter.Default }, { typeof(bool?), NullableBooleanFormatter.Default }, { typeof(byte?), NullableByteFormatter.Default }, { typeof(sbyte?), NullableSByteFormatter.Default }, { typeof(DateTime), ISO8601DateTimeFormatter.Default }, { typeof(TimeSpan), ISO8601TimeSpanFormatter.Default }, { typeof(DateTimeOffset), ISO8601DateTimeOffsetFormatter.Default }, { typeof(DateTime?), new StaticNullableFormatter<DateTime>(ISO8601DateTimeFormatter.Default) }, { typeof(TimeSpan?), new StaticNullableFormatter<TimeSpan>(ISO8601TimeSpanFormatter.Default) }, { typeof(DateTimeOffset?), new StaticNullableFormatter<DateTimeOffset>(ISO8601DateTimeOffsetFormatter.Default) }, { typeof(string), NullableStringFormatter.Default }, { typeof(char), CharFormatter.Default }, { typeof(char?), NullableCharFormatter.Default }, { typeof(decimal), DecimalFormatter.Default }, { typeof(decimal?), new StaticNullableFormatter<decimal>(DecimalFormatter.Default) }, { typeof(Guid), GuidFormatter.Default }, { typeof(Guid?), new StaticNullableFormatter<Guid>(GuidFormatter.Default) }, { typeof(Uri), UriFormatter.Default }, { typeof(Version), VersionFormatter.Default }, { typeof(System.Text.StringBuilder), StringBuilderFormatter.Default }, { typeof(BitArray), BitArrayFormatter.Default }, { typeof(Type), TypeFormatter.Default }, { typeof(byte[]), ByteArrayFormatter.Default }, { typeof(short[]), Int16ArrayFormatter.Default }, { typeof(int[]), Int32ArrayFormatter.Default }, { typeof(long[]), Int64ArrayFormatter.Default }, { typeof(ushort[]), UInt16ArrayFormatter.Default }, { typeof(uint[]), UInt32ArrayFormatter.Default }, { typeof(ulong[]), UInt64ArrayFormatter.Default }, { typeof(float[]), SingleArrayFormatter.Default }, { typeof(double[]), DoubleArrayFormatter.Default }, { typeof(bool[]), BooleanArrayFormatter.Default }, { typeof(sbyte[]), SByteArrayFormatter.Default }, { typeof(char[]), CharArrayFormatter.Default }, { typeof(string[]), NullableStringArrayFormatter.Default }, { typeof(List<short>), new ListFormatter<short>() }, { typeof(List<int>), new ListFormatter<int>() }, { typeof(List<long>), new ListFormatter<long>() }, { typeof(List<ushort>), new ListFormatter<ushort>() }, { typeof(List<uint>), new ListFormatter<uint>() }, { typeof(List<ulong>), new ListFormatter<ulong>() }, { typeof(List<float>), new ListFormatter<float>() }, { typeof(List<double>), new ListFormatter<double>() }, { typeof(List<bool>), new ListFormatter<bool>() }, { typeof(List<byte>), new ListFormatter<byte>() }, { typeof(List<sbyte>), new ListFormatter<sbyte>() }, { typeof(List<DateTime>), new ListFormatter<DateTime>() }, { typeof(List<char>), new ListFormatter<char>() }, { typeof(List<string>), new ListFormatter<string>() }, { typeof(ArraySegment<byte>), ByteArraySegmentFormatter.Default }, { typeof(ArraySegment<byte>?), new StaticNullableFormatter<ArraySegment<byte>>(ByteArraySegmentFormatter.Default) }, { typeof(BigInteger), BigIntegerFormatter.Default }, { typeof(BigInteger?), new StaticNullableFormatter<BigInteger>(BigIntegerFormatter.Default) }, { typeof(Complex), ComplexFormatter.Default }, { typeof(Complex?), new StaticNullableFormatter<Complex>(ComplexFormatter.Default) }, { typeof(ExpandoObject), ExpandoObjectFormatter.Default }, { typeof(Task), TaskUnitFormatter.Default } }; internal static object GetFormatter(Type t) { if (formatterMap.TryGetValue(t, out var value)) { return value; } return null; } } public static readonly IJsonFormatterResolver Instance = new BuiltinResolver(); private BuiltinResolver() { } public IJsonFormatter<T> GetFormatter<T>() { return FormatterCache<T>.formatter; } } public sealed class CompositeResolver : IJsonFormatterResolver { private static class FormatterCache<T> { public static readonly IJsonFormatter<T> formatter; static FormatterCache() { isFreezed = true; IJsonFormatter[] formatters = CompositeResolver.formatters; foreach (IJsonFormatter jsonFormatter in formatters) { foreach (Type implementedInterface in jsonFormatter.GetType().GetTypeInfo().ImplementedInterfaces) { TypeInfo typeInfo = implementedInterface.GetTypeInfo(); if (typeInfo.IsGenericType && typeInfo.GenericTypeArguments[0] == typeof(T)) { formatter = (IJsonFormatter<T>)jsonFormatter; return; } } } IJsonFormatterResolver[] resolvers = CompositeResolver.resolvers; for (int i = 0; i < resolvers.Length; i++) { IJsonFormatter<T> jsonFormatter2 = resolvers[i].GetFormatter<T>(); if (jsonFormatter2 != null) { formatter = jsonFormatter2; break; } } } } public static readonly CompositeResolver Instance = new CompositeResolver(); private static bool isFreezed = false; private static IJsonFormatter[] formatters = new IJsonFormatter[0]; private static IJsonFormatterResolver[] resolvers = new IJsonFormatterResolver[0]; private CompositeResolver() { } public static void Register(params IJsonFormatterResolver[] resolvers) { if (isFreezed) { throw new InvalidOperationException("Register must call on startup(before use GetFormatter<T>)."); } CompositeResolver.resolvers = resolvers; } public static void Register(params IJsonFormatter[] formatters) { if (isFreezed) { throw new InvalidOperationException("Register must call on startup(before use GetFormatter<T>)."); } CompositeResolver.formatters = formatters; } public static void Register(IJsonFormatter[] formatters, IJsonFormatterResolver[] resolvers) { if (isFreezed) { throw new InvalidOperationException("Register must call on startup(before use GetFormatter<T>)."); } CompositeResolver.resolvers = resolvers; CompositeResolver.formatters = formatters; } public static void RegisterAndSetAsDefault(params IJsonFormatterResolver[] resolvers) { Register(resolvers); JsonSerializer.SetDefaultResolver(Instance); } public static void RegisterAndSetAsDefault(params IJsonFormatter[] formatters) { Register(formatters); JsonSerializer.SetDefaultResolver(Instance); } public static void RegisterAndSetAsDefault(IJsonFormatter[] formatters, IJsonFormatterResolver[] resolvers) { Register(formatters); Register(resolvers); JsonSerializer.SetDefaultResolver(Instance); } public static IJsonFormatterResolver Create(params IJsonFormatter[] formatters) { return Create(formatters, new IJsonFormatterResolver[0]); } public static IJsonFormatterResolver Create(params IJsonFormatterResolver[] resolvers) { return Create(new IJsonFormatter[0], resolvers); } public static IJsonFormatterResolver Create(IJsonFormatter[] formatters, IJsonFormatterResolver[] resolvers) { return DynamicCompositeResolver.Create(formatters, resolvers); } public IJsonFormatter<T> GetFormatter<T>() { return FormatterCache<T>.formatter; } } public abstract class DynamicCompositeResolver : IJsonFormatterResolver { private const string ModuleName = "Utf8Json.Resolvers.DynamicCompositeResolver"; private static readonly DynamicAssembly assembly; public readonly IJsonFormatter[] formatters; public readonly IJsonFormatterResolver[] resolvers; static DynamicCompositeResolver() { assembly = new DynamicAssembly("Utf8Json.Resolvers.DynamicCompositeResolver"); } public static IJsonFormatterResolver Create(IJsonFormatter[] formatters, IJsonFormatterResolver[] resolvers) { string text = Guid.NewGuid().ToString().Replace("-", ""); TypeBuilder typeBuilder = assembly.DefineType("DynamicCompositeResolver_" + text, TypeAttributes.Public | TypeAttributes.Sealed, typeof(DynamicCompositeResolver)); TypeBuilder typeBuilder2 = assembly.DefineType("DynamicCompositeResolverCache_" + text, TypeAttributes.Public | TypeAttributes.Sealed, null); GenericTypeParameterBuilder genericTypeParameterBuilder = typeBuilder2.DefineGenericParameters("T")[0]; FieldBuilder fieldInfo = typeBuilder.DefineField("instance", typeBuilder, FieldAttributes.Public | FieldAttributes.Static); FieldBuilder field = typeBuilder2.DefineField("formatter", typeof(IJsonFormatter<>).MakeGenericType(genericTypeParameterBuilder), FieldAttributes.Public | FieldAttributes.Static); ILGenerator iLGenerator = typeBuilder2.DefineConstructor(MethodAttributes.Static, CallingConventions.Standard, Type.EmptyTypes).GetILGenerator(); iLGenerator.EmitLdsfld(fieldInfo); iLGenerator.EmitCall(typeof(DynamicCompositeResolver).GetMethod("GetFormatterLoop").MakeGenericMethod(genericTypeParameterBuilder)); iLGenerator.Emit(OpCodes.Stsfld, field); iLGenerator.Emit(OpCodes.Ret); Type type = typeBuilder2.CreateTypeInfo().AsType(); ILGenerator iLGenerator2 = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[2] { typeof(IJsonFormatter[]), typeof(IJsonFormatterResolver[]) }).GetILGenerator(); iLGenerator2.EmitLdarg(0); iLGenerator2.EmitLdarg(1); iLGenerator2.EmitLdarg(2); iLGenerator2.Emit(OpCodes.Call, typeof(DynamicCompositeResolver).GetConstructors()[0]); iLGenerator2.Emit(OpCodes.Ret); MethodBuilder methodBuilder = typeBuilder.DefineMethod("GetFormatter", MethodAttributes.Public | MethodAttributes.Virtual); GenericTypeParameterBuilder genericTypeParameterBuilder2 = methodBuilder.DefineGenericParameters("T")[0]; methodBuilder.SetReturnType(typeof(IJsonFormatter<>).MakeGenericType(genericTypeParameterBuilder2)); ILGenerator iLGenerator3 = methodBuilder.GetILGenerator(); FieldInfo field2 = TypeBuilder.GetField(type.MakeGenericType(genericTypeParameterBuilder2), type.GetField("formatter", BindingFlags.Static | BindingFlags.Public | BindingFlags.GetField)); iLGenerator3.EmitLdsfld(field2); iLGenerator3.Emit(OpCodes.Ret); object obj = Activator.CreateInstance(typeBuilder.CreateTypeInfo().AsType(), new object[2] { formatters, resolvers }); obj.GetType().GetField("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).SetValue(null, obj); return (IJsonFormatterResolver)obj; } public DynamicCompositeResolver(IJsonFormatter[] formatters, IJsonFormatterResolver[] resolvers) { this.formatters = formatters; this.resolvers = resolvers; } public IJsonFormatter<T> GetFormatterLoop<T>() { IJsonFormatter[] array = formatters; foreach (IJsonFormatter jsonFormatter in array) { foreach (Type implementedInterface in jsonFormatter.GetType().GetTypeInfo().ImplementedInterfaces) { TypeInfo typeInfo = implementedInterface.GetTypeInfo(); if (typeInfo.IsGenericType && typeInfo.GenericTypeArguments[0] == typeof(T)) { return (IJsonFormatter<T>)jsonFormatter; } } } IJsonFormatterResolver[] array2 = resolvers; for (int i = 0; i < array2.Length; i++) { IJsonFormatter<T> formatter = array2[i].GetFormatter<T>(); if (formatter != null) { return formatter; } } return null; } public abstract IJsonFormatter<T> GetFormatter<T>(); } public sealed class DynamicGenericResolver : IJsonFormatterResolver { private static class FormatterCache<T> { public static readonly IJsonFormatter<T> formatter; static FormatterCache() { formatter = (IJsonFormatter<T>)DynamicGenericResolverGetFormatterHelper.GetFormatter(typeof(T)); } } public static readonly IJsonFormatterResolver Instance = new DynamicGenericResolver(); private DynamicGenericResolver() { } public IJsonFormatter<T> GetFormatter<T>() { return FormatterCache<T>.formatter; } } public static class DynamicObjectResolver { public static readonly IJsonFormatterResolver Default = DynamicObjectResolverAllowPrivateFalseExcludeNullFalseNameMutateOriginal.Instance; public static readonly IJsonFormatterResolver CamelCase = DynamicObjectResolverAllowPrivateFalseExcludeNullFalseNameMutateCamelCase.Instance; public static readonly IJsonFormatterResolver SnakeCase = DynamicObjectResolverAllowPrivateFalseExcludeNullFalseNameMutateSnakeCase.Instance; public static readonly IJsonFormatterResolver ExcludeNull = DynamicObjectResolverAllowPrivateFalseExcludeNullTrueNameMutateOriginal.Instance; public static readonly IJsonFormatterResolver ExcludeNullCamelCase = DynamicObjectResolverAllowPrivateFalseExcludeNullTrueNameMutateCamelCase.Instance; public static readonly IJsonFormatterResolver ExcludeNullSnakeCase = DynamicObjectResolverAllowPrivateFalseExcludeNullTrueNameMutateSnakeCase.Instance; public static readonly IJsonFormatterResolver AllowPrivate = DynamicObjectResolverAllowPrivateTrueExcludeNullFalseNameMutateOriginal.Instance; public static readonly IJsonFormatterResolver AllowPrivateCamelCase = DynamicObjectResolverAllowPrivateTrueExcludeNullFalseNameMutateCamelCase.Instance; public static readonly IJsonFormatterResolver AllowPrivateSnakeCase = DynamicObjectResolverAllowPrivateTrueExcludeNullFalseNameMutateSnakeCase.Instance; public static readonly IJsonFormatterResolver AllowPrivateExcludeNull = DynamicObjectResolverAllowPrivateTrueExcludeNullTrueNameMutateOriginal.Instance; public static readonly IJsonFormatterResolver AllowPrivateExcludeNullCamelCase = DynamicObjectResolverAllowPrivateTrueExcludeNullTrueNameMutateCamelCase.Instance; public static readonly IJsonFormatterResolver AllowPrivateExcludeNullSnakeCase = DynamicObjectResolverAllowPrivateTrueExcludeNullTrueNameMutateSnakeCase.Instance; } public static class EnumResolver { public static readonly IJsonFormatterResolver Default = EnumDefaultResolver.Instance; public static readonly IJsonFormatterResolver UnderlyingValue = EnumUnderlyingValueResolver.Instance; } public static class StandardResolver { public static readonly IJsonFormatterResolver Default = DefaultStandardResolver.Instance; public static readonly IJsonFormatterResolver CamelCase = CamelCaseStandardResolver.Instance; public static readonly IJsonFormatterResolver SnakeCase = SnakeCaseStandardResolver.Instance; public static readonly IJsonFormatterResolver ExcludeNull = ExcludeNullStandardResolver.Instance; public static readonly IJsonFormatterResolver ExcludeNullCamelCase = ExcludeNullCamelCaseStandardResolver.Instance; public static readonly IJsonFormatterResolver ExcludeNullSnakeCase = ExcludeNullSnakeCaseStandardResolver.Instance; public static readonly IJsonFormatterResolver AllowPrivate = AllowPrivateStandardResolver.Instance; public static readonly IJsonFormatterResolver AllowPrivateCamelCase = AllowPrivateCamelCaseStandardResolver.Instance; public static readonly IJsonFormatterResolver AllowPrivateSnakeCase = AllowPrivateSnakeCaseStandardResolver.Instance; public static readonly IJsonFormatterResolver AllowPrivateExcludeNull = AllowPrivateExcludeNullStandardResolver.Instance; public static readonly IJsonFormatterResolver AllowPrivateExcludeNullCamelCase = AllowPrivateExcludeNullCamelCaseStandardResolver.Instance; public static readonly IJsonFormatterResolver AllowPrivateExcludeNullSnakeCase = AllowPrivateExcludeNullSnakeCaseStandardResolver.Instance; } } namespace Utf8Json.Resolvers.Internal { internal static class DynamicGenericResolverGetFormatterHelper { private static readonly Dictionary<Type, Type> formatterMap = new Dictionary<Type, Type> { { typeof(List<>), typeof(ListFormatter<>) }, { typeof(LinkedList<>), typeof(LinkedListFormatter<>) }, { typeof(Queue<>), typeof(QeueueFormatter<>) }, { typeof(Stack<>), typeof(StackFormatter<>) }, { typeof(HashSet<>), typeof(HashSetFormatter<>) }, { typeof(ReadOnlyCollection<>), typeof(ReadOnlyCollectionFormatter<>) }, { typeof(IList<>), typeof(InterfaceListFormatter<>) }, { typeof(ICollection<>), typeof(InterfaceCollectionFormatter<>) }, { typeof(IEnumerable<>), typeof(InterfaceEnumerableFormatter<>) }, { typeof(Dictionary<, >), typeof(DictionaryFormatter<, >) }, { typeof(IDictionary<, >), typeof(InterfaceDictionaryFormatter<, >) }, { typeof(SortedDictionary<, >), typeof(SortedDictionaryFormatter<, >) }, { typeof(SortedList<, >), typeof(SortedListFormatter<, >) }, { typeof(ILookup<, >), typeof(InterfaceLookupFormatter<, >) }, { typeof(IGrouping<, >), typeof(InterfaceGroupingFormatter<, >) }, { typeof(ObservableCollection<>), typeof(ObservableCollectionFormatter<>) }, { typeof(ReadOnlyObservableCollection<>), typeof(ReadOnlyObservableCollectionFormatter<>) }, { typeof(IReadOnlyList<>), typeof(InterfaceReadOnlyListFormatter<>) }, { typeof(IReadOnlyCollection<>), typeof(InterfaceReadOnlyCollectionFormatter<>) }, { typeof(ISet<>), typeof(InterfaceSetFormatter<>) }, { typeof(ConcurrentBag<>), typeof(ConcurrentBagFormatter<>) }, { typeof(ConcurrentQueue<>), typeof(ConcurrentQueueFormatter<>) }, { typeof(ConcurrentStack<>), typeof(ConcurrentStackFormatter<>) }, { typeof(ReadOnlyDictionary<, >), typeof(ReadOnlyDictionaryFormatter<, >) }, { typeof(IReadOnlyDictionary<, >), typeof(InterfaceReadOnlyDictionaryFormatter<, >) }, { typeof(ConcurrentDictionary<, >), typeof(ConcurrentDictionaryFormatter<, >) }, { typeof(Lazy<>), typeof(LazyFormatter<>) }, { typeof(Task<>), typeof(TaskValueFormatter<>) } }; internal static object GetFormatter(Type t) { TypeInfo typeInfo = t.GetTypeInfo(); if (t.IsArray) { switch (t.GetArrayRank()) { case 1: if (t.GetElementType() == typeof(byte)) { return ByteArrayFormatter.Default; } return Activator.CreateInstance(typeof(ArrayFormatter<>).MakeGenericType(t.GetElementType())); case 2: return Activator.CreateInstance(typeof(TwoDimentionalArrayFormatter<>).MakeGenericType(t.GetElementType())); case 3: return Activator.CreateInstance(typeof(ThreeDimentionalArrayFormatter<>).MakeGenericType(t.GetElementType())); case 4: return Activator.CreateInstance(typeof(FourDimentionalArrayFormatter<>).MakeGenericType(t.GetElementType())); default: return null; } } if (typeInfo.IsGenericType) { Type genericTypeDefinition = typeInfo.GetGenericTypeDefinition(); bool flag = genericTypeDefinition.GetTypeInfo().IsNullable(); Type type = (flag ? typeInfo.GenericTypeArguments[0] : null); if (genericTypeDefinition == typeof(KeyValuePair<, >)) { return CreateInstance(typeof(KeyValuePairFormatter<, >), typeInfo.GenericTypeArguments); } if (flag && type.GetTypeInfo().IsConstructedGenericType() && type.GetGenericTypeDefinition() == typeof(KeyValuePair<, >)) { return CreateInstance(typeof(NullableFormatter<>), new Type[1] { type }); } if (genericTypeDefinition == typeof(ValueTask<>)) { return CreateInstance(typeof(ValueTaskFormatter<>), typeInfo.GenericTypeArguments); } if (flag && type.IsConstructedGenericType && type.GetGenericTypeDefinition() == typeof(ValueTask<>)) { return CreateInstance(typeof(NullableFormatter<>), new Type[1] { type }); } if (typeInfo.FullName.StartsWith("System.Tuple")) { Type genericType = null; switch (typeInfo.GenericTypeArguments.Length) { case 1: genericType = typeof(TupleFormatter<>); break; case 2: genericType = typeof(TupleFormatter<, >); break; case 3: genericType = typeof(TupleFormatter<, , >); break; case 4: genericType = typeof(TupleFormatter<, , , >); break; case 5: genericType = typeof(TupleFormatter<, , , , >); break; case 6: genericType = typeof(TupleFormatter<, , , , , >); break; case 7: genericType = typeof(TupleFormatter<, , , , , , >); break; case 8: genericType = typeof(TupleFormatter<, , , , , , , >); break; } return CreateInstance(genericType, typeInfo.GenericTypeArguments); } if (typeInfo.FullName.StartsWith("System.ValueTuple")) { Type genericType2 = null; switch (typeInfo.GenericTypeArguments.Length) { case 1: genericType2 = typeof(ValueTupleFormatter<>); break; case 2: genericType2 = typeof(ValueTupleFormatter<, >); break; case 3: genericType2 = typeof(ValueTupleFormatter<, , >); break; case 4: genericType2 = typeof(ValueTupleFormatter<, , , >); break; case 5: genericType2 = typeof(ValueTupleFormatter<, , , , >); break; case 6: genericType2 = typeof(ValueTupleFormatter<, , , , , >); break; case 7: genericType2 = typeof(ValueTupleFormatter<, , , , , , >); break; case 8: genericType2 = typeof(ValueTupleFormatter<, , , , , , , >); break; } return CreateInstance(genericType2, typeInfo.GenericTypeArguments); } if (genericTypeDefinition == typeof(ArraySegment<>)) { if (typeInfo.GenericTypeArguments[0] == typeof(byte)) { return ByteArraySegmentFormatter.Default; } return CreateInstance(typeof(ArraySegmentFormatter<>), typeInfo.GenericTypeArguments); } if (flag && type.GetTypeInfo().IsConstructedGenericType() && type.GetGenericTypeDefinition() == typeof(ArraySegment<>)) { if (type == typeof(ArraySegment<byte>)) { return new StaticNullableFormatter<ArraySegment<byte>>(ByteArraySegmentFormatter.Default); } return CreateInstance(typeof(NullableFormatter<>), new Type[1] { type }); } if (formatterMap.TryGetValue(genericTypeDefinition, out var value)) { return CreateInstance(value, typeInfo.GenericTypeArguments); } if (typeInfo.GenericTypeArguments.Length == 1 && typeInfo.ImplementedInterfaces.Any((Type x) => x.GetTypeInfo().IsConstructedGenericType() && x.GetGenericTypeDefinition() == typeof(ICollection<>)) && typeInfo.DeclaredConstructors.Any((ConstructorInfo x) => x.GetParameters().Length == 0)) { Type type2 = typeInfo.GenericTypeArguments[0]; return CreateInstance(typeof(GenericCollectionFormatter<, >), new Type[2] { type2, t }); } if (typeInfo.GenericTypeArguments.Length == 2 && typeInfo.ImplementedInterfaces.Any((Type x) => x.GetTypeInfo().IsConstructedGenericType() && x.GetGenericTypeDefinition() == typeof(IDictionary<, >)) && typeInfo.DeclaredConstructors.Any((ConstructorInfo x) => x.GetParameters().Length == 0)) { Type type3 = typeInfo.GenericTypeArguments[0]; Type type4 = typeInfo.GenericTypeArguments[1]; return CreateInstance(typeof(GenericDictionaryFormatter<, , >), new Type[3] { type3, type4, t }); } } else { if (t == typeof(IEnumerable)) { return NonGenericInterfaceEnumerableFormatter.Default; } if (t == typeof(ICollection)) { return NonGenericInterfaceCollectionFormatter.Default; } if (t == typeof(IList)) { return NonGenericInterfaceListFormatter.Default; } if (t == typeof(IDictionary)) { return NonGenericInterfaceDictionaryFormatter.Default; } if (typeof(IList).GetTypeInfo().IsAssignableFrom(typeInfo) && typeInfo.DeclaredConstructors.Any((ConstructorInfo x) => x.GetParameters().Length == 0)) { return Activator.CreateInstance(typeof(NonGenericListFormatter<>).MakeGenericType(t)); } if (typeof(IDictionary).GetTypeInfo().IsAssignableFrom(typeInfo) && typeInfo.DeclaredConstructors.Any((ConstructorInfo x) => x.GetParameters().Length == 0)) { return Activator.CreateInstance(typeof(NonGenericDictionaryFormatter<>).MakeGenericType(t)); } } return null; } private static object CreateInstance(Type genericType, Type[] genericTypeArguments, params object[] arguments) { return Activator.CreateInstance(genericType.MakeGenericType(genericTypeArguments), arguments); } } internal sealed class DynamicObjectResolverAllowPrivateFalseExcludeNullFalseNameMutateOriginal : IJsonFormatterResolver { private static class FormatterCache<T> { public static readonly IJsonFormatter<T> formatter; static FormatterCache() { formatter = (IJsonFormatter<T>)DynamicObjectTypeBuilder.BuildFormatterToAssembly<T>(assembly, Instance, nameMutator, excludeNull); } } public static readonly IJsonFormatterResolver Instance; private static readonly Func<string, string> nameMutator; private static readonly bool excludeNull; private const string ModuleName = "Utf8Json.Resolvers.DynamicObjectResolverAllowPrivateFalseExcludeNullFalseNameMutateOriginal"; private static readonly DynamicAssembly assembly; static DynamicObjectResolverAllowPrivateFalseExcludeNullFalseNameMutateOriginal() { Instance = new DynamicObjectResolverAllowPrivateFalseExcludeNullFalseNameMutateOriginal(); nameMutator = StringMutator.Original; excludeNull = false; assembly = new DynamicAssembly("Utf8Json.Resolvers.DynamicObjectResolverAllowPrivateFalseExcludeNullFalseNameMutateOriginal"); } private DynamicObjectResolverAllowPrivateFalseExcludeNullFalseNameMutateOriginal() { } public IJsonFormatter<T> GetFormatter<T>() { return FormatterCache<T>.formatter; } } internal sealed class DynamicObjectResolverAllowPrivateFalseExcludeNullFalseNameMutateCamelCase : IJsonFormatterResolver { private static class FormatterCache<T> { public static readonly IJsonFormatter<T> formatter; static FormatterCache() { formatter = (IJsonFormatter<T>)DynamicObjectTypeBuilder.BuildFormatterToAssembly<T>(assembly, Instance, nameMutator, excludeNull); } } public static readonly IJsonFormatterResolver Instance; private static readonly Func<string, string> nameMutator; private static readonly bool excludeNull; private const string ModuleName = "Utf8Json.Resolvers.DynamicObjectResolverAllowPrivateFalseExcludeNullFalseNameMutateCamelCase"; private static readonly DynamicAssembly assembly; static DynamicObjectResolverAllowPrivateFalseExcludeNullFalseNameMutateCamelCase() { Instance = new DynamicObjectResolverAllowPrivateFalseExcludeNullFalseNameMutateCamelCase(); nameMutator = StringMutator.ToCamelCase; excludeNull = false; assembly = new DynamicAssembly("Utf8Json.Resolvers.DynamicObjectResolverAllowPrivateFalseExcludeNullFalseNameMutateCamelCase"); } private DynamicObjectResolverAllowPrivateFalseExcludeNullFalseNameMutateCamelCase() { } public IJsonFormatter<T> GetFormatter<T>() { return FormatterCache<T>.formatter; } } internal sealed class DynamicObjectResolverAllowPrivateFalseExcludeNullFalseNameMutateSnakeCase : IJsonFormatterResolver { private static class FormatterCache<T> { public static readonly IJsonFormatter<T> formatter; static FormatterCache() { formatter = (IJsonFormatter<T>)DynamicObjectTypeBuilder.BuildFormatterToAssembly<T>(assembly, Instance, nameMutator, excludeNull); } } public static readonly IJsonFormatterResolver Instance; private static readonly Func<string, string> nameMutator; private static readonly bool excludeNull; private const string ModuleName = "Utf8Json.Resolvers.DynamicObjectResolverAllowPrivateFalseExcludeNullFalseNameMutateSnakeCase"; private static readonly DynamicAssembly assembly; static DynamicObjectResolverAllowPrivateFalseExcludeNullFalseNameMutateSnakeCase() { Instance = new DynamicObjectResolverAllowPrivateFalseExcludeNullFalseNameMutateSnakeCase(); nameMutator = StringMutator.ToSnakeCase; excludeNull = false; assembly = new DynamicAssembly("Utf8Json.Resolvers.DynamicObjectResolverAllowPrivateFalseExcludeNullFalseNameMutateSnakeCase"); } private DynamicObjectResolverAllowPrivateFalseExcludeNullFalseNameMutateSnakeCase() { } public IJsonFormatter<T> GetFormatter<T>() { return FormatterCache<T>.formatter; } } internal sealed class DynamicObjectResolverAllowPrivateFalseExcludeNullTrueNameMutateOriginal : IJsonFormatterResolver { private static class FormatterCache<T> { public static readonly IJsonFormatter<T> formatter; static FormatterCache() { formatter = (IJsonFormatter<T>)DynamicObjectTypeBuilder.BuildFormatterToAssembly<T>(assembly, Instance, nameMutator, excludeNull); } } public static readonly IJsonFormatterResolver Instance; private static readonly Func<string, string> nameMutator; private static readonly bool excludeNull; private const string ModuleName = "Utf8Json.Resolvers.DynamicObjectResolverAllowPrivateFalseExcludeNullTrueNameMutateOriginal"; private static readonly DynamicAssembly assembly; static DynamicObjectResolverAllowPrivateFalseExcludeNullTrueNameMutateOriginal() { Instance = new DynamicObjectResolverAllowPrivateFalseExcludeNullTrueNameMutateOriginal(); nameMutator = StringMutator.Original; excludeNull = true; assembly = new DynamicAssembly("Utf8Json.Resolvers.DynamicObjectResolverAllowPrivateFalseExcludeNullTrueNameMutateOriginal"); } private DynamicObjectResolverAllowPrivateFalseExcludeNullTrueNameMutateOriginal() { } public IJsonFormatter<T> GetFormatter<T>() { return FormatterCache<T>.formatter; } } internal sealed class DynamicObjectResolverAllowPrivateFalseExcludeNullTrueNameMutateCamelCase : IJsonFormatterResolver { private static class FormatterCache<T> { public static readonly IJsonFormatter<T> formatter; static FormatterCache() { formatter = (IJsonFormatter<T>)DynamicObjectTypeBuilder.BuildFormatterToAssembly<T>(assembly, Instance, nameMutator, excludeNull); } } public static readonly IJsonFormatterResolver Instance; private static readonly Func<string, string> nameMutator; private static readonly bool excludeNull; private const string ModuleName = "Utf8Json.Resolvers.DynamicObjectResolverAllowPrivateFalseExcludeNullTrueNameMutateCamelCase"; private static readonly DynamicAssembly assembly; static DynamicObjectResolverAllowPrivateFalseExcludeNullTrueNameMutateCamelCase() { Instance = new DynamicObjectResolverAllowPrivateFalseExcludeNullTrueNameMutateCamelCase(); nameMutator = StringMutator.ToCamelCase; excludeNull = true; assembly = new DynamicAssembly("Utf8Json.Resolvers.DynamicObjectResolverAllowPrivateFalseExcludeNullTrueNameMutateCamelCase"); } private DynamicObjectResolverAllowPrivateFalseExcludeNullTrueNameMutateCamelCase() { } public IJsonFormatter<T> GetFormatter<T>() { return FormatterCache<T>.formatter; } } internal sealed class DynamicObjectResolverAllowPrivateFalseExcludeNullTrueNameMutateSnakeCase : IJsonFormatterResolver { private static class FormatterCache<T> { public static readonly IJsonFormatter<T> formatter; static FormatterCache() { formatter = (IJsonFormatter<T>)DynamicObjectTypeBuilder.BuildFormatterToAssembly<T>(assembly, Instance, nameMutator, excludeNull); } } public static readonly IJsonFormatterResolver Instance; private static readonly Func<string, string> nameMutator; private static readonly bool excludeNull; private const string ModuleName = "Utf8Json.Resolvers.DynamicObjectResolverAllowPrivateFalseExcludeNullTrueNameMutateSnakeCase"; private static readonly DynamicAssembly assembly; static DynamicObjectResolverAllowPrivateFalseExcludeNullTrueNameMutateSnakeCase() { Instance = new DynamicObjectResolverAllowPrivateFalseExcludeNullTrueNameMutateSnakeCase(); nameMutator = StringMutator.ToSnakeCase; excludeNull = true; assembly = new DynamicAssembly("Utf8Json.Resolvers.DynamicObjectResolverAllowPrivateFalseExcludeNullTrueNameMutateSnakeCase"); } private DynamicObjectResolverAllowPrivateFalseExcludeNullTrueNameMutateSnakeCase() { } public IJsonFormatter<T> GetFormatter<T>() { return FormatterCache<T>.formatter; } } internal sealed class DynamicObjectResolverAllowPrivateTrueExcludeNullFalseNameMutateOriginal : IJsonFormatterResolver { private static class FormatterCache<T> { public static readonly IJsonFormatter<T> formatter; static FormatterCache() { formatter = (IJsonFormatter<T>)DynamicObjectTypeBuilder.BuildFormatterToDynamicMethod<T>(Instance, nameMutator, excludeNull, allowPrivate: true); } } public static readonly IJsonFormatterResolver Instance = new DynamicObjectResolverAllowPrivateTrueExcludeNullFalseNameMutateOriginal(); private static readonly Func<string, string> nameMutator = StringMutator.Original; private static readonly bool excludeNull = false; public IJsonFormatter<T> GetFormatter<T>() { return FormatterCache<T>.formatter; } } internal sealed class DynamicObjectResolverAllowPrivateTrueExcludeNullFalseNameMutateCamelCase : IJsonFormatterResolver { private static class FormatterCache<T> { public static readonly IJsonFormatter<T> formatter; static FormatterCache() { formatter = (IJsonFormatter<T>)DynamicObjectTypeBuilder.BuildFormatterToDynamicMethod<T>(Instance, nameMutator, excludeNull, allowPrivate: true); } } public static readonly IJsonFormatterResolver Instance = new DynamicObjectResolverAllowPrivateTrueExcludeNullFalseNameMutateCamelCase(); private static readonly Func<string, string> nameMutator = StringMutator.ToCamelCase; private static readonly bool excludeNull = false; public IJsonFormatter<T> GetFormatter<T>() { return FormatterCache<T>.formatter; } } internal sealed class DynamicObjectResolverAllowPrivateTrueExcludeNullFalseNameMutateSnakeCase : IJsonFormatterResolver { private static class FormatterCache<T> { public static readonly IJsonFormatter<T> formatter; static FormatterCache() { formatter = (IJsonFormatter<T>)DynamicObjectTypeBuilder.BuildFormatterToDynamicMethod<T>(Instance, nameMutator, excludeNull, allowPrivate: true); } } public static readonly IJsonFormatterResolver Instance = new DynamicObjectResolverAllowPrivateTrueExcludeNullFalseNameMutateSnakeCase(); private static readonly Func<string, string> nameMutator = StringMutator.ToSnakeCase; private static readonly bool excludeNull = false; public IJsonFormatter<T> GetFormatter<T>() { return FormatterCache<T>.formatter; } } internal sealed class DynamicObjectResolverAllowPrivateTrueExcludeNullTrueNameMutateOriginal : IJsonFormatterResolver { private static class FormatterCache<T> { public static readonly IJsonFormatter<T> formatter; static FormatterCache() { formatter = (IJsonFormatter<T>)DynamicObjectTypeBuilder.BuildFormatterToDynamicMethod<T>(Instance, nameMutator, excludeNull, allowPrivate: true); } } public static readonly IJsonFormatterResolver Instance = new DynamicObjectResolverAllowPrivateTrueExcludeNullTrueNameMutateOriginal(); private static readonly Func<string, string> nameMutator = StringMutator.Original; private static readonly bool excludeNull = true; public IJsonFormatter<T> GetFormatter<T>() { return FormatterCache<T>.formatter; } } internal sealed class DynamicObjectResolverAllowPrivateTrueExcludeNullTrueNameMutateCamelCase : IJsonFormatterResolver { private static class FormatterCache<T> { public static readonly IJsonFormatter<T> formatter; static FormatterCache() { formatter = (IJsonFormatter<T>)DynamicObjectTypeBuilder.BuildFormatterToDynamicMethod<T>(Instance, nameMutator, excludeNull, allowPrivate: true); } } public static readonly IJsonFormatterResolver Instance = new DynamicObjectResolverAllowPrivateTrueExcludeNullTrueNameMutateCamelCase(); private static readonly Func<string, string> nameMutator = StringMutator.ToCamelCase; private static readonly bool excludeNull = true; public IJsonFormatter<T> GetFormatter<T>() { return FormatterCache<T>.formatter; } } internal sealed class DynamicObjectResolverAllowPrivateTrueExcludeNullTrueNameMutateSnakeCase : IJsonFormatterResolver { private static class FormatterCache<T> { public static readonly IJsonFormatter<T> formatter; static FormatterCache() { formatter = (IJsonFormatter<T>)DynamicObjectTypeBuilder.BuildFormatterToDynamicMethod<T>(Instance, nameMutator, excludeNull, allowPrivate: true); } } public static readonly IJsonFormatterResolver Instance = new DynamicObjectResolverAllowPrivateTrueExcludeNullTrueNameMutateSnakeCase(); private static readonly Func<string, string> nameMutator = StringMutator.ToSnakeCase; private static readonly bool excludeNull = true; public IJsonFormatter<T> GetFormatter<T>() { return FormatterCache<T>.formatter; } } internal static class DynamicObjectTypeBuilder { private struct DeserializeInfo { public MetaMember MemberInfo; public LocalBuilder LocalField; public LocalBuilder IsDeserializedField; } internal static class EmitInfo { internal static class JsonWriter { public static readonly MethodInfo GetEncodedPropertyNameWithBeginObject; public static readonly MethodInfo GetEncodedPropertyNameWithPrefixValueSeparator; public static readonly MethodInfo GetEncodedPropertyNameWithoutQuotation; public static readonly MethodInfo GetEncodedPropertyName; public static readonly MethodInfo WriteNull; public static readonly MethodInfo WriteRaw; public static readonly MethodInfo WriteBeginObject; public static readonly MethodInfo WriteEndObject; public static readonly MethodInfo WriteValueSeparator; static JsonWriter() { GetEncodedPropertyNameWithBeginObject = ExpressionUtility.GetMethodInfo(() => Utf8Json.JsonWriter.GetEncodedPropertyNameWithBeginObject(null)); GetEncodedPropertyNameWithPrefixValueSeparator = ExpressionUtility.GetMethodInfo(() => Utf8Json.JsonWriter.GetEncodedPropertyNameWithPrefixValueSeparator(null)); GetEncodedPropertyNameWithoutQuotation = ExpressionUtility.GetMethodInfo(() => Utf8Json.JsonWriter
plugins/System.Threading.Tasks.Extensions.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security; using System.Threading.Tasks; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("System.Threading.Tasks.Extensions")] [assembly: AssemblyDescription("System.Threading.Tasks.Extensions")] [assembly: AssemblyDefaultAlias("System.Threading.Tasks.Extensions")] [assembly: AssemblyCompany("Microsoft Corporation")] [assembly: AssemblyProduct("Microsoft® .NET Framework")] [assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")] [assembly: AssemblyFileVersion("4.6.25519.03")] [assembly: AssemblyInformationalVersion("4.6.25519.03 built by: dlab-DDVSOWINAGE013. Commit Hash: 8321c729934c0f8be754953439b88e6e1c120c24")] [assembly: CLSCompliant(true)] [assembly: AssemblyMetadata(".NETFrameworkAssembly", "")] [assembly: AssemblyMetadata("Serviceable", "True")] [assembly: AssemblyMetadata("PreferInbox", "True")] [assembly: AssemblyVersion("4.1.1.0")] namespace System.Threading.Tasks { [StructLayout(LayoutKind.Auto)] [AsyncMethodBuilder(typeof(AsyncValueTaskMethodBuilder<>))] public struct ValueTask<TResult> : IEquatable<ValueTask<TResult>> { internal readonly Task<TResult> _task; internal readonly TResult _result; public bool IsCompleted { get { if (_task != null) { return _task.IsCompleted; } return true; } } public bool IsCompletedSuccessfully { get { if (_task != null) { return _task.Status == TaskStatus.RanToCompletion; } return true; } } public bool IsFaulted { get { if (_task != null) { return _task.IsFaulted; } return false; } } public bool IsCanceled { get { if (_task != null) { return _task.IsCanceled; } return false; } } public TResult Result { get { if (_task != null) { return _task.GetAwaiter().GetResult(); } return _result; } } public ValueTask(TResult result) { _task = null; _result = result; } public ValueTask(Task<TResult> task) { if (task == null) { throw new ArgumentNullException("task"); } _task = task; _result = default(TResult); } public override int GetHashCode() { if (_task == null) { if (_result == null) { return 0; } return _result.GetHashCode(); } return _task.GetHashCode(); } public override bool Equals(object obj) { if (obj is ValueTask<TResult>) { return Equals((ValueTask<TResult>)obj); } return false; } public bool Equals(ValueTask<TResult> other) { if (_task == null && other._task == null) { return EqualityComparer<TResult>.Default.Equals(_result, other._result); } return _task == other._task; } public static bool operator ==(ValueTask<TResult> left, ValueTask<TResult> right) { return left.Equals(right); } public static bool operator !=(ValueTask<TResult> left, ValueTask<TResult> right) { return !left.Equals(right); } public Task<TResult> AsTask() { return _task ?? Task.FromResult(_result); } public ValueTaskAwaiter<TResult> GetAwaiter() { return new ValueTaskAwaiter<TResult>(this); } public ConfiguredValueTaskAwaitable<TResult> ConfigureAwait(bool continueOnCapturedContext) { return new ConfiguredValueTaskAwaitable<TResult>(this, continueOnCapturedContext); } public override string ToString() { if (_task != null) { if (_task.Status != TaskStatus.RanToCompletion || _task.Result == null) { return string.Empty; } return _task.Result.ToString(); } if (_result == null) { return string.Empty; } return _result.ToString(); } [EditorBrowsable(EditorBrowsableState.Never)] public static AsyncValueTaskMethodBuilder<TResult> CreateAsyncMethodBuilder() { return AsyncValueTaskMethodBuilder<TResult>.Create(); } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false, AllowMultiple = false)] public sealed class AsyncMethodBuilderAttribute : Attribute { public Type BuilderType { get; } public AsyncMethodBuilderAttribute(Type builderType) { BuilderType = builderType; } } [StructLayout(LayoutKind.Auto)] public struct AsyncValueTaskMethodBuilder<TResult> { private AsyncTaskMethodBuilder<TResult> _methodBuilder; private TResult _result; private bool _haveResult; private bool _useBuilder; public ValueTask<TResult> Task { get { if (_haveResult) { return new ValueTask<TResult>(_result); } _useBuilder = true; return new ValueTask<TResult>(_methodBuilder.Task); } } public static AsyncValueTaskMethodBuilder<TResult> Create() { return new AsyncValueTaskMethodBuilder<TResult> { _methodBuilder = AsyncTaskMethodBuilder<TResult>.Create() }; } public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { _methodBuilder.Start(ref stateMachine); } public void SetStateMachine(IAsyncStateMachine stateMachine) { _methodBuilder.SetStateMachine(stateMachine); } public void SetResult(TResult result) { if (_useBuilder) { _methodBuilder.SetResult(result); return; } _result = result; _haveResult = true; } public void SetException(Exception exception) { _methodBuilder.SetException(exception); } public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine { _useBuilder = true; _methodBuilder.AwaitOnCompleted(ref awaiter, ref stateMachine); } [SecuritySafeCritical] public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine { _useBuilder = true; _methodBuilder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine); } } [StructLayout(LayoutKind.Auto)] public struct ConfiguredValueTaskAwaitable<TResult> { [StructLayout(LayoutKind.Auto)] public struct ConfiguredValueTaskAwaiter : ICriticalNotifyCompletion, INotifyCompletion { private readonly ValueTask<TResult> _value; private readonly bool _continueOnCapturedContext; public bool IsCompleted => _value.IsCompleted; internal ConfiguredValueTaskAwaiter(ValueTask<TResult> value, bool continueOnCapturedContext) { _value = value; _continueOnCapturedContext = continueOnCapturedContext; } public TResult GetResult() { if (_value._task != null) { return _value._task.GetAwaiter().GetResult(); } return _value._result; } public void OnCompleted(Action continuation) { _value.AsTask().ConfigureAwait(_continueOnCapturedContext).GetAwaiter() .OnCompleted(continuation); } public void UnsafeOnCompleted(Action continuation) { _value.AsTask().ConfigureAwait(_continueOnCapturedContext).GetAwaiter() .UnsafeOnCompleted(continuation); } } private readonly ValueTask<TResult> _value; private readonly bool _continueOnCapturedContext; internal ConfiguredValueTaskAwaitable(ValueTask<TResult> value, bool continueOnCapturedContext) { _value = value; _continueOnCapturedContext = continueOnCapturedContext; } public ConfiguredValueTaskAwaiter GetAwaiter() { return new ConfiguredValueTaskAwaiter(_value, _continueOnCapturedContext); } } public struct ValueTaskAwaiter<TResult> : ICriticalNotifyCompletion, INotifyCompletion { private readonly ValueTask<TResult> _value; public bool IsCompleted => _value.IsCompleted; internal ValueTaskAwaiter(ValueTask<TResult> value) { _value = value; } public TResult GetResult() { if (_value._task != null) { return _value._task.GetAwaiter().GetResult(); } return _value._result; } public void OnCompleted(Action continuation) { _value.AsTask().ConfigureAwait(continueOnCapturedContext: true).GetAwaiter() .OnCompleted(continuation); } public void UnsafeOnCompleted(Action continuation) { _value.AsTask().ConfigureAwait(continueOnCapturedContext: true).GetAwaiter() .UnsafeOnCompleted(continuation); } } [AttributeUsage(AttributeTargets.All)] internal class __BlockReflectionAttribute : Attribute { } }