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 Redeem v1.1.1
plugins/Redeem.dll
Decompiled 2 months 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.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using JetBrains.Annotations; using LocalizationManager; using Microsoft.CodeAnalysis; using ServerSync; using TMPro; using UnityEngine; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Core.ObjectPool; using YamlDotNet.Core.Tokens; using YamlDotNet.Helpers; using YamlDotNet.Serialization; using YamlDotNet.Serialization.BufferedDeserialization; using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators; using YamlDotNet.Serialization.Callbacks; using YamlDotNet.Serialization.Converters; using YamlDotNet.Serialization.EventEmitters; using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.NodeDeserializers; using YamlDotNet.Serialization.NodeTypeResolvers; using YamlDotNet.Serialization.ObjectFactories; using YamlDotNet.Serialization.ObjectGraphTraversalStrategies; using YamlDotNet.Serialization.ObjectGraphVisitors; using YamlDotNet.Serialization.Schemas; using YamlDotNet.Serialization.TypeInspectors; using YamlDotNet.Serialization.TypeResolvers; using YamlDotNet.Serialization.Utilities; using YamlDotNet.Serialization.ValueDeserializers; [assembly: Guid("E74EB49A-461D-48EA-85BC-F462D60C98C4")] [assembly: ComVisible(false)] [assembly: AssemblyTrademark("")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyProduct("Redeem")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyDescription("")] [assembly: AssemblyTitle("Redeem")] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: AssemblyFileVersion("1.1.1")] [assembly: AssemblyCompany("Radamanto")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.1.0")] [module: <0ccb63ea-841c-4f41-ae15-7280a0205b5a>RefSafetyRules(11)] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [<da6fabe9-c3e8-4105-a9b5-7f241e936f67>Embedded] internal sealed class <da6fabe9-c3e8-4105-a9b5-7f241e936f67>EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] [<da6fabe9-c3e8-4105-a9b5-7f241e936f67>Embedded] [CompilerGenerated] internal sealed class <99544383-ab20-4483-8207-65586c01c4a5>NullableAttribute : Attribute { public readonly byte[] NullableFlags; public <99544383-ab20-4483-8207-65586c01c4a5>NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public <99544383-ab20-4483-8207-65586c01c4a5>NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] [<da6fabe9-c3e8-4105-a9b5-7f241e936f67>Embedded] [CompilerGenerated] internal sealed class <ab36df6e-28a1-4340-b83b-2a103281b663>NullableContextAttribute : Attribute { public readonly byte Flag; public <ab36df6e-28a1-4340-b83b-2a103281b663>NullableContextAttribute(byte P_0) { Flag = P_0; } } [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] [<da6fabe9-c3e8-4105-a9b5-7f241e936f67>Embedded] [CompilerGenerated] internal sealed class <0ccb63ea-841c-4f41-ae15-7280a0205b5a>RefSafetyRulesAttribute : Attribute { public readonly int Version; public <0ccb63ea-841c-4f41-ae15-7280a0205b5a>RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Redeem { [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("radamanto.Redeem", "Redeem", "1.1.1")] [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(0)] [<ab36df6e-28a1-4340-b83b-2a103281b663>NullableContext(1)] public class RedeemPlugin : BaseUnityPlugin { [<ab36df6e-28a1-4340-b83b-2a103281b663>NullableContext(0)] private sealed class PackagesData { [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(1)] public Dictionary<string, PackageDef> Packages = new Dictionary<string, PackageDef>(StringComparer.OrdinalIgnoreCase); } [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(0)] private sealed class PackageDef { public string Id = ""; public List<ItemDef> Items = new List<ItemDef>(); } [<ab36df6e-28a1-4340-b83b-2a103281b663>NullableContext(0)] private sealed class ItemDef { [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(1)] public string Prefab = ""; public int Amount = 1; public int Quality = 1; public int Variant; } [<ab36df6e-28a1-4340-b83b-2a103281b663>NullableContext(0)] private sealed class CodesData { [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(1)] public Dictionary<string, CodeInfo> Codes = new Dictionary<string, CodeInfo>(StringComparer.OrdinalIgnoreCase); } [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(0)] private sealed class CodeInfo { public string Code = ""; public string Package = ""; } [<ab36df6e-28a1-4340-b83b-2a103281b663>NullableContext(0)] private sealed class ConfigurationManagerAttributes { public bool? Browsable = false; } [CompilerGenerated] private sealed class <Core_RpcRebindWatcher>d__97 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(0)] private object <>2__current; [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(0)] public RedeemPlugin <>4__this; [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(0)] private WaitForSeconds <wait>5__1; [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(0)] private ZRoutedRpc <cur>5__2; object IEnumerator<object>.Current { [DebuggerHidden] [return: <99544383-ab20-4483-8207-65586c01c4a5>Nullable(0)] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] [return: <99544383-ab20-4483-8207-65586c01c4a5>Nullable(0)] get { return <>2__current; } } [DebuggerHidden] public <Core_RpcRebindWatcher>d__97(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <wait>5__1 = null; <cur>5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <wait>5__1 = new WaitForSeconds(1f); break; case 1: <>1__state = -1; break; } try { <cur>5__2 = ZRoutedRpc.instance; if (<cur>5__2 != _coreLastRpcRef) { _coreLastRpcRef = <cur>5__2; ResetCoreRpcFlags(); TryRegisterRpcHandlers(); TryRegisterClientHandlers(); } <cur>5__2 = null; } catch { } <>2__current = <wait>5__1; <>1__state = 1; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <FilePoller>d__76 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(0)] private object <>2__current; [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(0)] public RedeemPlugin <>4__this; [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(0)] private WaitForSeconds <wait>5__1; private DateTime <mtimePackages>5__2; private DateTime <mtimeCodes>5__3; private DateTime <mtimeInsert>5__4; [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(0)] private object <>s__5; private bool <>s__6; object IEnumerator<object>.Current { [DebuggerHidden] [return: <99544383-ab20-4483-8207-65586c01c4a5>Nullable(0)] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] [return: <99544383-ab20-4483-8207-65586c01c4a5>Nullable(0)] get { return <>2__current; } } [DebuggerHidden] public <FilePoller>d__76(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <wait>5__1 = null; <>s__5 = null; <>1__state = -2; } private bool MoveNext() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <wait>5__1 = new WaitForSeconds(2f); break; case 1: <>1__state = -1; break; } try { if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { <mtimePackages>5__2 = GetLastWriteUtcSafe(PackagesPath); if (<mtimePackages>5__2 > _pollPackagesLastWriteUtc) { _pollPackagesLastWriteUtc = <mtimePackages>5__2; <>s__5 = _packagesFileLock; <>s__6 = false; try { Monitor.Enter(<>s__5, ref <>s__6); _packages = LoadPackagesYml(PackagesPath); } finally { if (<>s__6) { Monitor.Exit(<>s__5); } } <>s__5 = null; } <mtimeCodes>5__3 = GetLastWriteUtcSafe(CodesActivePath); if (<mtimeCodes>5__3 > _pollCodesLastWriteUtc) { _pollCodesLastWriteUtc = <mtimeCodes>5__3; TryReloadCodesSafe(); } <mtimeInsert>5__4 = GetLastWriteUtcSafe(CodeInsertPath); if (<mtimeInsert>5__4 > _pollInsertLastWriteUtc) { _pollInsertLastWriteUtc = <mtimeInsert>5__4; TryProcessSingleInsert(); } } } catch { } <>2__current = <wait>5__1; <>1__state = 1; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <InFlightAndAntiFloodSweeper>d__118 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(0)] private object <>2__current; [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(0)] public RedeemPlugin <>4__this; [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(0)] private WaitForSeconds <wait>5__1; private DateTime <now>5__2; private DateTime <cutoffRecent>5__3; [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(new byte[] { 0, 0, 1 })] private KeyValuePair<string, DateTime>[] <>s__4; private int <>s__5; [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(new byte[] { 0, 1 })] private KeyValuePair<string, DateTime> <kv>5__6; [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(new byte[] { 0, 0, 1 })] private KeyValuePair<string, DateTime>[] <>s__7; private int <>s__8; [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(new byte[] { 0, 1 })] private KeyValuePair<string, DateTime> <kv>5__9; [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(new byte[] { 0, 0, 1 })] private KeyValuePair<string, DateTime>[] <>s__10; private int <>s__11; [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(new byte[] { 0, 1 })] private KeyValuePair<string, DateTime> <kv>5__12; object IEnumerator<object>.Current { [DebuggerHidden] [return: <99544383-ab20-4483-8207-65586c01c4a5>Nullable(0)] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] [return: <99544383-ab20-4483-8207-65586c01c4a5>Nullable(0)] get { return <>2__current; } } [DebuggerHidden] public <InFlightAndAntiFloodSweeper>d__118(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <wait>5__1 = null; <>s__4 = null; <kv>5__6 = default(KeyValuePair<string, DateTime>); <>s__7 = null; <kv>5__9 = default(KeyValuePair<string, DateTime>); <>s__10 = null; <kv>5__12 = default(KeyValuePair<string, DateTime>); <>1__state = -2; } private bool MoveNext() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <wait>5__1 = new WaitForSeconds(1f); break; case 1: <>1__state = -1; break; } try { <now>5__2 = DateTime.UtcNow; <>s__4 = _inFlightExpires.ToArray(); DateTime value; for (<>s__5 = 0; <>s__5 < <>s__4.Length; <>s__5++) { <kv>5__6 = <>s__4[<>s__5]; if (<kv>5__6.Value <= <now>5__2) { _inFlightExpires.TryRemove(<kv>5__6.Key, out value); _inFlightCodes.TryRemove(<kv>5__6.Key, out var _); } <kv>5__6 = default(KeyValuePair<string, DateTime>); } <>s__4 = null; <>s__7 = _codeLockTouched.ToArray(); for (<>s__8 = 0; <>s__8 < <>s__7.Length; <>s__8++) { <kv>5__9 = <>s__7[<>s__8]; if (<now>5__2 - <kv>5__9.Value > CodeLockOrphanTtl) { _codeLockTouched.TryRemove(<kv>5__9.Key, out value); _codeLocks.TryRemove(<kv>5__9.Key, out var _); } <kv>5__9 = default(KeyValuePair<string, DateTime>); } <>s__7 = null; <cutoffRecent>5__3 = <now>5__2.AddDays(-7.0); <>s__10 = _recentClaimed.ToArray(); for (<>s__11 = 0; <>s__11 < <>s__10.Length; <>s__11++) { <kv>5__12 = <>s__10[<>s__11]; if (<kv>5__12.Value < <cutoffRecent>5__3) { _recentClaimed.TryRemove(<kv>5__12.Key, out value); } <kv>5__12 = default(KeyValuePair<string, DateTime>); } <>s__10 = null; } catch { } <>2__current = <wait>5__1; <>1__state = 1; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <RegisterRpcWhenReady>d__68 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(0)] private object <>2__current; [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(0)] public RedeemPlugin <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] [return: <99544383-ab20-4483-8207-65586c01c4a5>Nullable(0)] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] [return: <99544383-ab20-4483-8207-65586c01c4a5>Nullable(0)] get { return <>2__current; } } [DebuggerHidden] public <RegisterRpcWhenReady>d__68(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; break; } if (ZRoutedRpc.instance == null) { <>2__current = null; <>1__state = 1; return true; } TryRegisterRpcHandlers(); TryRegisterClientHandlers(); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <ReloadConfigAfterQuietPeriod>d__117 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(0)] private object <>2__current; public float quietSeconds; [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(0)] public RedeemPlugin <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] [return: <99544383-ab20-4483-8207-65586c01c4a5>Nullable(0)] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] [return: <99544383-ab20-4483-8207-65586c01c4a5>Nullable(0)] get { return <>2__current; } } [DebuggerHidden] public <ReloadConfigAfterQuietPeriod>d__117(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; break; } if ((DateTime.UtcNow - <>4__this._lastCfgWriteUtc).TotalSeconds < (double)quietSeconds) { <>2__current = null; <>1__state = 1; return true; } try { if (<>4__this._configWatcher == null || !<>4__this._watcherReady) { return false; } <>4__this._configWatcher.EnableRaisingEvents = false; if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { ((BaseUnityPlugin)<>4__this).Config.Reload(); <>4__this._ignoreEventsUntilUtc = DateTime.UtcNow.AddSeconds(1.0); ((BaseUnityPlugin)<>4__this).Config.Save(); } } catch { } finally { if (<>4__this._configWatcher != null) { <>4__this._configWatcher.EnableRaisingEvents = true; } <>4__this._reloadScheduled = false; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public const string ModGUID = "radamanto.Redeem"; public const string ModName = "Redeem"; public const string ModVersion = "1.1.1"; private readonly Harmony _harmony = new Harmony("radamanto.Redeem"); private static bool _bootstrapped; internal static ManualLogSource Log = null; private const float DebounceSeconds = 2.5f; private const float SpawnYOffset = 0.5f; private const int AttemptWindowSeconds = 300; private const int MaxAttemptsPerWindow = 5; private const int BlockSeconds = 900; private const int InFlightTimeoutSeconds = 60; private const int MaxCodeLength = 128; private const int RecentClaimedTtlDays = 7; private const double InsertDebounceMs = 200.0; private const double WatcherDebounceMs = 200.0; private static readonly TimeSpan CodeLockOrphanTtl = TimeSpan.FromMinutes(10.0); private const string PackagesFile = "packages.yml"; private const string CodesActiveFile = "code.active.yml"; private const string CodesClaimedFile = "code.claimed.yml"; private const string CodeInsertFile = "code.insert.yml"; private const string RPC_RedeemRequest = "VD_RedeemRequest"; private const string RPC_RedeemResult = "VD_RedeemResult"; private const string RPC_GiveItems = "VD_GiveItems"; private const string RPC_AckDelivery = "VD_AckDelivery"; private static readonly ConcurrentDictionary<long, DateTime> _lastRequestByPeer = new ConcurrentDictionary<long, DateTime>(); private static readonly ConcurrentDictionary<string, DateTime> _lastRequestByCode = new ConcurrentDictionary<string, DateTime>(StringComparer.OrdinalIgnoreCase); private static readonly ConcurrentDictionary<string, object> _codeLocks = new ConcurrentDictionary<string, object>(StringComparer.OrdinalIgnoreCase); private static readonly ConcurrentDictionary<string, DateTime> _codeLockTouched = new ConcurrentDictionary<string, DateTime>(StringComparer.OrdinalIgnoreCase); private static readonly ConcurrentDictionary<string, DateTime> _recentClaimed = new ConcurrentDictionary<string, DateTime>(StringComparer.OrdinalIgnoreCase); private static readonly ConcurrentDictionary<long, List<DateTime>> _attemptsByPeer = new ConcurrentDictionary<long, List<DateTime>>(); private static readonly ConcurrentDictionary<long, DateTime> _peerBlockedUntil = new ConcurrentDictionary<long, DateTime>(); private static readonly ConcurrentDictionary<string, long> _inFlightCodes = new ConcurrentDictionary<string, long>(StringComparer.OrdinalIgnoreCase); private static readonly ConcurrentDictionary<string, DateTime> _inFlightExpires = new ConcurrentDictionary<string, DateTime>(StringComparer.OrdinalIgnoreCase); internal static readonly object _codesFileLock = new object(); private static readonly object _packagesFileLock = new object(); private static readonly object _claimedFileLock = new object(); private static PackagesData _packages = new PackagesData(); private static CodesData _codes = new CodesData(); [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(2)] private FileSystemWatcher _watchPackages; [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(2)] private FileSystemWatcher _watchCodesActive; [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(2)] private FileSystemWatcher _watchCodeInsert; private static DateTime _codesLastWriteUtc = DateTime.MinValue; private static DateTime _insertLastHandledUtc = DateTime.MinValue; private static DateTime _packagesLastHandledUtc = DateTime.MinValue; private static DateTime _activeLastHandledUtc = DateTime.MinValue; private static DateTime _pollPackagesLastWriteUtc = DateTime.MinValue; private static DateTime _pollCodesLastWriteUtc = DateTime.MinValue; private static DateTime _pollInsertLastWriteUtc = DateTime.MinValue; private static bool _rpcRequestRegistered; private static bool _rpcResultRegistered; private static bool _rpcGiveItemsRegistered; private static bool _rpcAckRegistered; [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(2)] private static ZRoutedRpc _coreLastRpcRef; [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(2)] internal static ConfigSync ConfigSync; [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(2)] private static ConfigEntry<bool> _serverConfigLocked; [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(2)] private FileSystemWatcher _configWatcher; private DateTime _lastCfgWriteUtc = DateTime.MinValue; private bool _reloadScheduled; private bool _watcherReady; private DateTime _ignoreEventsUntilUtc = DateTime.MinValue; private static string DataFolder => Path.Combine(Paths.ConfigPath, "Redeem_data"); private static string PackagesPath => Path.Combine(DataFolder, "packages.yml"); private static string CodesActivePath => Path.Combine(DataFolder, "code.active.yml"); private static string CodesClaimedPath => Path.Combine(DataFolder, "code.claimed.yml"); private static string CodeInsertPath => Path.Combine(DataFolder, "code.insert.yml"); public static bool IsLocalPlayerAdmin() { return ConfigSync != null && ConfigSync.IsAdmin; } internal static string RemoveRichText(string s) { return Regex.Replace(s ?? "", "<.*?>", ""); } private void Awake() { Localizer.Load(); if (!_bootstrapped) { _bootstrapped = true; Log = ((BaseUnityPlugin)this).Logger; SetupServerSyncAndWatcher(); if (IsDedicatedEnvironment()) { Directory.CreateDirectory(DataFolder); EnsureSampleFiles(); LoadAll(); TryAttachWatchers(); ((MonoBehaviour)this).StartCoroutine(FilePoller()); ((MonoBehaviour)this).StartCoroutine(InFlightAndAntiFloodSweeper()); } _harmony.PatchAll(); TryRegisterRpcHandlers(); TryRegisterClientHandlers(); ((MonoBehaviour)this).StartCoroutine(RegisterRpcWhenReady()); ((MonoBehaviour)this).StartCoroutine(Core_RpcRebindWatcher()); } } private static bool IsDedicatedEnvironment() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)SystemInfo.graphicsDeviceType == 4) { return true; } if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsDedicated()) { return true; } return false; } [IteratorStateMachine(typeof(<RegisterRpcWhenReady>d__68))] private IEnumerator RegisterRpcWhenReady() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <RegisterRpcWhenReady>d__68(0) { <>4__this = this }; } private void OnDestroy() { _configWatcher?.Dispose(); _configWatcher = null; try { _watchPackages?.Dispose(); _watchCodesActive?.Dispose(); _watchCodeInsert?.Dispose(); _watchPackages = null; _watchCodesActive = null; _watchCodeInsert = null; } catch { } } private static string SamplePackagesYml() { return "# Redeem - packages.yml (example)\r\nPackages:\r\n - Id: starter\r\n Items:\r\n - Prefab: Coins, Amount: 500\r\n - Prefab: Wood, Amount: 100\r\n - Prefab: Stone, Amount: 100\r\n - Id: vip_bundle\r\n Items:\r\n - Prefab: Coins, Amount: 5000\r\n - Prefab: Bronze, Amount: 20\r\n - Prefab: SwordIron, Amount: 1, Quality: 3\r\n"; } private static string SampleCodesYml() { return "# Redeem - code.active (example)\r\nCodes:\r\n - Code: ABCD-1234-START\r\n Package: starter\r\n - Code: VIP-ONLY-9999\r\n Package: vip_bundle\r\n"; } private static void EnsureSampleFiles() { Directory.CreateDirectory(DataFolder); if (!File.Exists(PackagesPath)) { File.WriteAllText(PackagesPath, SamplePackagesYml(), Encoding.UTF8); } if (!File.Exists(CodesActivePath)) { File.WriteAllText(CodesActivePath, SampleCodesYml(), Encoding.UTF8); } if (!File.Exists(CodesClaimedPath)) { File.WriteAllText(CodesClaimedPath, string.Empty, Encoding.UTF8); } if (!File.Exists(CodeInsertPath)) { string contents = "# Redeem - code.insert.yml\r\n# Edite a seção Codes e SALVE o arquivo para aplicar.\r\n# Se houver QUALQUER erro (duplicata em active, pacote inexistente, formato inválido),\r\n# nada é aplicado e este arquivo permanece intacto.\r\n\r\nCodes:\r\n - Code: NEW-EXAMPLE-0001\r\n Package: starter\r\n"; File.WriteAllText(CodeInsertPath, contents, Encoding.UTF8); } } private static void LoadAll() { lock (_packagesFileLock) { _packages = LoadPackagesYml(PackagesPath); } lock (_codesFileLock) { _codes = LoadCodesYml(CodesActivePath); try { _codesLastWriteUtc = GetLastWriteUtcSafe(CodesActivePath); } catch { } } ReindexClaimedFromFile(); TryProcessSingleInsert(); } private static void TryReloadCodesSafe() { try { lock (_codesFileLock) { DateTime lastWriteUtcSafe = GetLastWriteUtcSafe(CodesActivePath); if (!(lastWriteUtcSafe <= _codesLastWriteUtc)) { _codes = LoadCodesYml(CodesActivePath); _codesLastWriteUtc = lastWriteUtcSafe; } } } catch { } } private void TryAttachWatchers() { try { _watchPackages?.Dispose(); _watchPackages = new FileSystemWatcher(Path.GetDirectoryName(PackagesPath), Path.GetFileName(PackagesPath)) { IncludeSubdirectories = false, EnableRaisingEvents = true, NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite) }; _watchPackages.Changed += [<ab36df6e-28a1-4340-b83b-2a103281b663>NullableContext(0)] (object _, FileSystemEventArgs __) => { try { DateTime utcNow3 = DateTime.UtcNow; if ((utcNow3 - _packagesLastHandledUtc).TotalMilliseconds < 200.0) { return; } _packagesLastHandledUtc = utcNow3; lock (_packagesFileLock) { _packages = LoadPackagesYml(PackagesPath); } } catch { } }; } catch { } try { _watchCodesActive?.Dispose(); _watchCodesActive = new FileSystemWatcher(Path.GetDirectoryName(CodesActivePath), Path.GetFileName(CodesActivePath)) { IncludeSubdirectories = false, EnableRaisingEvents = true, NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite) }; _watchCodesActive.Changed += [<ab36df6e-28a1-4340-b83b-2a103281b663>NullableContext(0)] (object _, FileSystemEventArgs __) => { try { DateTime utcNow2 = DateTime.UtcNow; if (!((utcNow2 - _activeLastHandledUtc).TotalMilliseconds < 200.0)) { _activeLastHandledUtc = utcNow2; TryReloadCodesSafe(); } } catch { } }; } catch { } try { _watchCodeInsert?.Dispose(); _watchCodeInsert = new FileSystemWatcher(Path.GetDirectoryName(CodeInsertPath), Path.GetFileName(CodeInsertPath)) { IncludeSubdirectories = false, EnableRaisingEvents = true, NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite) }; _watchCodeInsert.Changed += [<ab36df6e-28a1-4340-b83b-2a103281b663>NullableContext(0)] (object _, FileSystemEventArgs __) => { try { DateTime utcNow = DateTime.UtcNow; if (!((utcNow - _insertLastHandledUtc).TotalMilliseconds < 200.0)) { _insertLastHandledUtc = utcNow; TryProcessSingleInsert(); } } catch { } }; } catch { } } [IteratorStateMachine(typeof(<FilePoller>d__76))] private IEnumerator FilePoller() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <FilePoller>d__76(0) { <>4__this = this }; } private static void TryProcessSingleInsert() { if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } try { if (!File.Exists(CodeInsertPath)) { return; } List<string> list = DetectInternalInsertDuplicates(CodeInsertPath); if (list.Count > 0) { return; } CodesData codesData; try { codesData = LoadCodesYml(CodeInsertPath); } catch { return; } if (codesData.Codes.Count == 0) { return; } lock (_codesFileLock) { foreach (KeyValuePair<string, CodeInfo> code in codesData.Codes) { string key = code.Key; if (string.IsNullOrWhiteSpace(key) || key.Length > 128 || _codes.Codes.ContainsKey(key)) { return; } } } if (ClaimedFileContainsAny(codesData.Codes.Keys, out var _)) { return; } lock (_packagesFileLock) { foreach (CodeInfo value in codesData.Codes.Values) { if (string.IsNullOrWhiteSpace(value.Package) || !_packages.Packages.ContainsKey(value.Package)) { return; } } } lock (_codesFileLock) { foreach (CodeInfo value2 in codesData.Codes.Values) { _codes.Codes[value2.Code] = new CodeInfo { Code = value2.Code, Package = value2.Package }; } SaveCodesAtomic(); } try { string contents = "# Redeem - code.insert.yml\r\n# Edite a seção Codes e SALVE o arquivo para aplicar.\r\nCodes:\r\n"; File.WriteAllText(CodeInsertPath, contents, Encoding.UTF8); } catch { } } catch { } } private static void SaveCodesAtomic() { lock (_codesFileLock) { string codesActivePath = CodesActivePath; string text = codesActivePath + ".tmp"; string text2 = codesActivePath + ".bak"; string contents = DumpCodesYml(_codes); int num = 0; while (true) { try { File.WriteAllText(text, contents, Encoding.UTF8); if (File.Exists(text2)) { File.Delete(text2); } if (File.Exists(codesActivePath)) { File.Move(codesActivePath, text2); } File.Move(text, codesActivePath); _codesLastWriteUtc = GetLastWriteUtcSafe(codesActivePath); try { File.Delete(text2); break; } catch { break; } } catch (IOException) { if (++num >= 3) { throw; } Thread.Sleep(num switch { 2 => 100, 1 => 50, _ => 200, }); } catch (UnauthorizedAccessException) { if (++num >= 3) { throw; } Thread.Sleep(num switch { 2 => 100, 1 => 50, _ => 200, }); } } } } private static bool ClaimedFileContainsAny(IEnumerable<string> codes, out string foundCode) { foundCode = ""; try { if (!File.Exists(CodesClaimedPath)) { return false; } HashSet<string> hashSet = new HashSet<string>(codes.Where([<ab36df6e-28a1-4340-b83b-2a103281b663>NullableContext(0)] (string c) => !string.IsNullOrWhiteSpace(c)), StringComparer.OrdinalIgnoreCase); if (hashSet.Count == 0) { return false; } using FileStream stream = new FileStream(CodesClaimedPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); using StreamReader streamReader = new StreamReader(stream, Encoding.UTF8, detectEncodingFromByteOrderMarks: true, 8192); string text; while ((text = streamReader.ReadLine()) != null) { if (string.IsNullOrWhiteSpace(text)) { continue; } string[] array = text.Split(new char[1] { '\t' }); if (array.Length >= 2) { string text2 = array[1].Trim(); if (text2.Length != 0 && hashSet.Contains(text2)) { foundCode = text2; return true; } } } } catch { } return false; } private static DateTime GetLastWriteUtcSafe(string path) { try { return File.Exists(path) ? File.GetLastWriteTimeUtc(path) : DateTime.MinValue; } catch { return DateTime.MinValue; } } private static void AppendClaimedAtomic(string code, string package, string playerName) { lock (_claimedFileLock) { code = SanitizeField(code, 128); package = SanitizeField(package, 128); playerName = SanitizeField(playerName, 64); string contents = string.Format(CultureInfo.InvariantCulture, "{0:u}\t{1}\t{2}\t{3}\n", DateTime.UtcNow, code, package, playerName); int num = 0; while (true) { try { File.AppendAllText(CodesClaimedPath, contents, Encoding.UTF8); break; } catch (IOException) { if (++num >= 3) { throw; } Thread.Sleep(num switch { 2 => 100, 1 => 50, _ => 200, }); } catch (UnauthorizedAccessException) { if (++num >= 3) { throw; } Thread.Sleep(num switch { 2 => 100, 1 => 50, _ => 200, }); } } } } private static void ReindexClaimedFromFile() { try { if (!File.Exists(CodesClaimedPath)) { return; } _recentClaimed.Clear(); using FileStream stream = new FileStream(CodesClaimedPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); using StreamReader streamReader = new StreamReader(stream, Encoding.UTF8, detectEncodingFromByteOrderMarks: true, 8192); string text; while ((text = streamReader.ReadLine()) != null) { if (string.IsNullOrWhiteSpace(text)) { continue; } string[] array = text.Split(new char[1] { '\t' }); if (array.Length >= 2) { string text2 = array[1].Trim(); if (text2.Length != 0) { DateTime result; DateTime value = ((!DateTime.TryParse(array[0].Trim(), CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal, out result)) ? DateTime.UtcNow : result); _recentClaimed[text2] = value; } } } } catch { } } private static PackagesData LoadPackagesYml(string path) { PackagesData packagesData = new PackagesData(); if (!File.Exists(path)) { return packagesData; } string[] array; try { array = File.ReadAllLines(path); } catch { return packagesData; } PackageDef packageDef = null; bool flag = false; bool flag2 = false; string[] array2 = array; foreach (string text in array2) { string text2 = text.Replace("\t", " ").Trim(); if (text2.StartsWith("#") || text2.Length == 0) { continue; } if (text2.StartsWith("Packages:", StringComparison.OrdinalIgnoreCase)) { flag = true; flag2 = false; packageDef = null; } else { if (!flag) { continue; } Match match = Regex.Match(text2, "^-+\\s*Id\\s*:\\s*(.+)$", RegexOptions.IgnoreCase); if (match.Success) { packageDef = new PackageDef { Id = match.Groups[1].Value.Trim() }; packagesData.Packages[packageDef.Id] = packageDef; flag2 = false; } else { if (packageDef == null) { continue; } if (text2.StartsWith("Items:", StringComparison.OrdinalIgnoreCase)) { flag2 = true; } else if (flag2) { Match match2 = Regex.Match(text2, "^-\\s*Prefab\\s*:\\s*([^,]+)(?:,|$)", RegexOptions.IgnoreCase); if (match2.Success) { ItemDef itemDef = new ItemDef { Prefab = match2.Groups[1].Value.Trim() }; itemDef.Amount = GetIntField(text2, "Amount", 1); itemDef.Quality = GetIntField(text2, "Quality", 1); itemDef.Variant = GetIntField(text2, "Variant", 0); packageDef.Items.Add(itemDef); } } } } } return packagesData; } private static int GetIntField(string line, string key, int def) { Match match = Regex.Match(line, key + "\\s*:\\s*([-]?\\d+)", RegexOptions.IgnoreCase); if (match.Success && int.TryParse(match.Groups[1].Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { return result; } return def; } private static CodesData LoadCodesYml(string path) { CodesData codesData = new CodesData(); if (!File.Exists(path)) { return codesData; } string[] array; try { array = File.ReadAllLines(path); } catch { return codesData; } bool flag = false; CodeInfo codeInfo = null; string[] array2 = array; foreach (string text in array2) { string text2 = text.Replace("\t", " ").Trim(); if (text2.StartsWith("#") || text2.Length == 0) { continue; } if (text2.StartsWith("Codes:", StringComparison.OrdinalIgnoreCase)) { flag = true; codeInfo = null; } else { if (!flag) { continue; } Match match = Regex.Match(text2, "^-+\\s*Code\\s*:\\s*(.+)$", RegexOptions.IgnoreCase); if (match.Success) { codeInfo = new CodeInfo { Code = match.Groups[1].Value.Trim() }; codesData.Codes[codeInfo.Code] = codeInfo; } else if (codeInfo != null) { Match match2 = Regex.Match(text2, "^Package\\s*:\\s*(.+)$", RegexOptions.IgnoreCase); if (match2.Success) { codeInfo.Package = match2.Groups[1].Value.Trim(); } } } } return codesData; } private static string DumpCodesYml(CodesData data) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("# Redeem - code.active"); stringBuilder.AppendLine("Codes:"); foreach (KeyValuePair<string, CodeInfo> item in data.Codes.OrderBy<KeyValuePair<string, CodeInfo>, string>([<ab36df6e-28a1-4340-b83b-2a103281b663>NullableContext(0)] (KeyValuePair<string, CodeInfo> k) => k.Key, StringComparer.OrdinalIgnoreCase)) { CodeInfo value = item.Value; stringBuilder.AppendLine(" - Code: " + value.Code); stringBuilder.AppendLine(" Package: " + value.Package); } return stringBuilder.ToString(); } private static string SanitizeField(string value, int maxLength) { if (string.IsNullOrEmpty(value)) { return ""; } StringBuilder stringBuilder = new StringBuilder(value.Length); foreach (char c in value) { if (c >= ' ' && c != '\t' && c != '\n' && c != '\r') { stringBuilder.Append(c); if (stringBuilder.Length >= maxLength) { break; } } } return stringBuilder.ToString(); } private static List<string> DetectInternalInsertDuplicates(string path) { List<string> list = new List<string>(); try { if (!File.Exists(path)) { return list; } string[] array = File.ReadAllLines(path); bool flag = false; HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); string[] array2 = array; foreach (string text in array2) { string text2 = text.Replace("\t", " ").Trim(); if (text2.StartsWith("#") || text2.Length == 0) { continue; } if (text2.StartsWith("Codes:", StringComparison.OrdinalIgnoreCase)) { flag = true; } else { if (!flag) { continue; } Match match = Regex.Match(text2, "^-+\\s*Code\\s*:\\s*(.+)$", RegexOptions.IgnoreCase); if (match.Success) { string text3 = match.Groups[1].Value.Trim(); if (text3.Length != 0 && !hashSet.Add(text3) && !list.Contains<string>(text3, StringComparer.OrdinalIgnoreCase)) { list.Add(text3); } } } } } catch { } return list; } private static void ResetCoreRpcFlags() { _rpcRequestRegistered = false; _rpcResultRegistered = false; _rpcGiveItemsRegistered = false; _rpcAckRegistered = false; } private static void TryRegisterRpcHandlers() { ZRoutedRpc instance = ZRoutedRpc.instance; if (instance == null) { return; } if (!_rpcRequestRegistered) { try { instance.Register<string>("VD_RedeemRequest", (Action<long, string>)OnRpcRedeemRequest_String); _rpcRequestRegistered = true; } catch (ArgumentException) { _rpcRequestRegistered = true; } catch { } } if (_rpcAckRegistered) { return; } try { instance.Register<string>("VD_AckDelivery", (Action<long, string>)OnRpcAckDelivery_Server); _rpcAckRegistered = true; } catch (ArgumentException) { _rpcAckRegistered = true; } catch { } } private static void TryRegisterClientHandlers() { ZRoutedRpc instance = ZRoutedRpc.instance; if (instance == null) { return; } if (!_rpcResultRegistered) { try { instance.Register<ZPackage>("VD_RedeemResult", (Action<long, ZPackage>)OnRpcRedeemResult_Client); _rpcResultRegistered = true; } catch (ArgumentException) { _rpcResultRegistered = true; } catch { } } if (_rpcGiveItemsRegistered) { return; } try { instance.Register<ZPackage>("VD_GiveItems", (Action<long, ZPackage>)OnRpcGiveItems_Client); _rpcGiveItemsRegistered = true; } catch (ArgumentException) { _rpcGiveItemsRegistered = true; } catch { } } [IteratorStateMachine(typeof(<Core_RpcRebindWatcher>d__97))] private IEnumerator Core_RpcRebindWatcher() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <Core_RpcRebindWatcher>d__97(0) { <>4__this = this }; } public static void ClientRequestRedeem(string code) { ZRoutedRpc instance = ZRoutedRpc.instance; ZNet instance2 = ZNet.instance; if (instance != null && !((Object)(object)instance2 == (Object)null) && !string.IsNullOrWhiteSpace(code)) { code = code.Trim(); ZNetPeer serverPeer = instance2.GetServerPeer(); if (serverPeer != null) { instance.InvokeRoutedRPC(serverPeer.m_uid, "VD_RedeemRequest", new object[1] { code }); } } } private static void OnRpcRedeemRequest_String(long senderId, string code) { if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && !string.IsNullOrWhiteSpace(code)) { HandleRedeemServer(senderId, code.Trim()); } } private static void HandleRedeemServer(long senderId, string codeRaw) { //IL_047c: Unknown result type (might be due to invalid IL or missing references) //IL_0483: Expected O, but got Unknown DateTime utcNow = DateTime.UtcNow; if (_peerBlockedUntil.TryGetValue(senderId, out var value) && utcNow < value) { SendResultTo(senderId, false, "$redeem_claim_rate_limited_wait", ((int)Math.Max(1.0, (value - utcNow).TotalSeconds)).ToString()); return; } List<DateTime> orAdd = _attemptsByPeer.GetOrAdd(senderId, (long _) => new List<DateTime>(8)); lock (orAdd) { DateTime dateTime = utcNow.AddSeconds(-300.0); for (int num = orAdd.Count - 1; num >= 0; num--) { if (orAdd[num] < dateTime) { orAdd.RemoveAt(num); } } if (orAdd.Count >= 5) { _peerBlockedUntil[senderId] = utcNow.AddSeconds(900.0); SendResultTo(senderId, false, "$redeem_claim_rate_limited_blocked"); return; } orAdd.Add(utcNow); } if (_lastRequestByPeer.TryGetValue(senderId, out var value2) && (utcNow - value2).TotalSeconds < Math.Max(0.1, 2.5)) { SendResultTo(senderId, false, "$redeem_claim_rate_limited_retry"); return; } _lastRequestByPeer[senderId] = utcNow; string text = codeRaw.Trim(); if (text.Length == 0 || text.Length > 128) { SendResultTo(senderId, false, "$redeem_claim_code_invalid"); return; } if (_lastRequestByCode.TryGetValue(text, out var value3) && (utcNow - value3).TotalSeconds < Math.Max(0.1, 2.5)) { SendResultTo(senderId, false, "$redeem_claim_code_processing"); return; } _lastRequestByCode[text] = utcNow; DateTime value8; try { object orAdd2 = _codeLocks.GetOrAdd(text, (string _) => new object()); _codeLockTouched[text] = utcNow; lock (orAdd2) { TryReloadCodesSafe(); string package; lock (_codesFileLock) { if (!_codes.Codes.TryGetValue(text, out var value4)) { SendResultTo(senderId, false, _recentClaimed.ContainsKey(text) ? "$redeem_claim_code_already_claimed" : "$redeem_claim_code_not_found"); return; } package = value4.Package; } PackageDef value5; lock (_packagesFileLock) { if (!_packages.Packages.TryGetValue(package, out value5)) { SendResultTo(senderId, false, "$redeem_claim_package_missing"); return; } } ZNet instance = ZNet.instance; ZNetPeer val = ((instance != null) ? instance.GetPeer(senderId) : null); if (val == null) { SendResultTo(senderId, false, "$redeem_claim_player_disconnected"); return; } if (_inFlightCodes.TryGetValue(text, out var value6)) { if (!_inFlightExpires.TryGetValue(text, out var value7) || !(utcNow > value7)) { SendResultTo(senderId, false, "$redeem_claim_code_processing"); return; } _inFlightCodes.TryRemove(text, out value6); _inFlightExpires.TryRemove(text, out value8); } if (!_inFlightCodes.TryAdd(text, senderId)) { SendResultTo(senderId, false, "$redeem_claim_code_processing"); return; } try { _inFlightExpires[text] = utcNow.AddSeconds(60.0); ZPackage val2 = new ZPackage(); val2.Write(text); val2.Write(value5.Items.Count); foreach (ItemDef item in value5.Items) { val2.Write(item.Prefab ?? ""); val2.Write(item.Amount); val2.Write(item.Quality); val2.Write(item.Variant); } ZRoutedRpc instance2 = ZRoutedRpc.instance; if (instance2 != null) { instance2.InvokeRoutedRPC(senderId, "VD_GiveItems", new object[1] { val2 }); } } catch { _inFlightCodes.TryRemove(text, out value6); _inFlightExpires.TryRemove(text, out value8); throw; } } } finally { _lastRequestByCode.TryRemove(text, out value8); } } private static void OnRpcAckDelivery_Server(long senderId, string code) { if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || string.IsNullOrWhiteSpace(code)) { return; } code = code.Trim(); if (!_inFlightCodes.TryGetValue(code, out var value) || value != senderId) { SendResultTo(senderId, false, "$redeem_claim_ack_invalid"); return; } object orAdd = _codeLocks.GetOrAdd(code, (string _) => new object()); _codeLockTouched[code] = DateTime.UtcNow; bool flag = false; bool flag2 = false; DateTime value4; try { lock (orAdd) { CodeInfo value2; long value3; string package; lock (_codesFileLock) { if (!_codes.Codes.TryGetValue(code, out value2)) { _inFlightCodes.TryRemove(code, out value3); _inFlightExpires.TryRemove(code, out value4); SendResultTo(senderId, false, "$redeem_claim_code_invalid"); flag2 = true; return; } package = value2.Package; } CodeInfo codeInfo = new CodeInfo { Code = value2.Code, Package = value2.Package }; try { lock (_codesFileLock) { flag = _codes.Codes.Remove(code); } SaveCodesAtomic(); try { ZNet instance = ZNet.instance; string value5 = ((instance == null) ? null : instance.GetPeer(senderId)?.m_playerName) ?? ""; string playerName = SanitizeField(value5, 64); AppendClaimedAtomic(code, package, playerName); } catch { } _recentClaimed[code] = DateTime.UtcNow; _attemptsByPeer.TryRemove(senderId, out var _); _peerBlockedUntil.TryRemove(senderId, out value4); _inFlightCodes.TryRemove(code, out value3); _inFlightExpires.TryRemove(code, out value4); SendResultTo(senderId, true, "$redeem_claim_delivered", package); flag2 = true; } catch { if (flag) { lock (_codesFileLock) { _codes.Codes[codeInfo.Code] = codeInfo; } } _inFlightCodes.TryRemove(code, out value3); _inFlightExpires.TryRemove(code, out value4); SendResultTo(senderId, false, "$redeem_claim_persist_failed"); flag2 = true; } } } finally { if (flag2) { _codeLocks.TryRemove(code, out var _); _codeLockTouched.TryRemove(code, out value4); } } } private static void SendResultTo(long peerId, bool success, string token, params string[] args) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown try { ZPackage val = new ZPackage(); val.Write(success); val.Write(token ?? ""); val.Write((args != null) ? args.Length : 0); if (args != null) { foreach (string text in args) { val.Write(text ?? ""); } } ZRoutedRpc instance = ZRoutedRpc.instance; if (instance != null) { instance.InvokeRoutedRPC(peerId, "VD_RedeemResult", new object[1] { val }); } } catch { } } private static void OnRpcRedeemResult_Client(long _sender, ZPackage pkg) { try { bool flag = pkg.ReadBool(); string text = pkg.ReadString(); int num = pkg.ReadInt(); string[] array = new string[num]; for (int i = 0; i < num; i++) { array[i] = pkg.ReadString(); } Localization instance = Localization.instance; if (instance == null) { return; } string text2 = instance.Localize(text); string text3 = text2; if (array.Length != 0) { try { object[] args = array; text3 = string.Format(text2, args); } catch { text3 = text2; } } MessageHud instance2 = MessageHud.instance; if (instance2 != null) { instance2.ShowMessage((MessageType)2, (flag ? "<color=green>" : "<color=red>") + text3 + "</color>", 0, (Sprite)null, false); } } catch { } } private static void OnRpcGiveItems_Client(long sender, ZPackage pkg) { //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) try { ZNet instance = ZNet.instance; ZNetPeer val = ((instance != null) ? instance.GetServerPeer() : null); if (val == null || sender != val.m_uid) { return; } string text = pkg.ReadString(); Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } Inventory inventory = ((Humanoid)localPlayer).GetInventory(); if (inventory == null) { return; } ObjectDB instance2 = ObjectDB.instance; if ((Object)(object)instance2 == (Object)null) { return; } int num = pkg.ReadInt(); for (int i = 0; i < num; i++) { string text2 = pkg.ReadString(); int num2 = pkg.ReadInt(); int num3 = pkg.ReadInt(); int num4 = pkg.ReadInt(); if (string.IsNullOrWhiteSpace(text2) || num2 <= 0) { continue; } GameObject itemPrefab = instance2.GetItemPrefab(text2); if ((Object)(object)itemPrefab == (Object)null) { continue; } ItemDrop component = itemPrefab.GetComponent<ItemDrop>(); if ((Object)(object)component == (Object)null || component.m_itemData == null || component.m_itemData.m_shared == null) { continue; } int num5 = num2; int num6 = Mathf.Max(1, component.m_itemData.m_shared.m_maxStackSize); while (num5 > 0) { int num7 = Mathf.Min(num5, num6); num5 -= num7; ItemData val2 = component.m_itemData.Clone(); val2.m_dropPrefab = itemPrefab; val2.m_stack = num7; val2.m_quality = Mathf.Max(1, num3); val2.m_variant = Mathf.Max(0, num4); if (!inventory.CanAddItem(val2, val2.m_stack)) { Vector3 val3 = ((Component)localPlayer).transform.position + ((Component)localPlayer).transform.forward * 1.25f + Vector3.up * 0.5f; ItemDrop.DropItem(val2, num7, val3, Quaternion.identity); } else { inventory.AddItem(val2); } } } Localization instance3 = Localization.instance; if (instance3 != null) { string text3 = instance3.Localize("$redeem_claim_items_received"); ((Character)localPlayer).Message((MessageType)1, text3, 0, (Sprite)null); } ZNetPeer val4 = ((instance != null) ? instance.GetServerPeer() : null); if (val4 != null) { ZRoutedRpc instance4 = ZRoutedRpc.instance; if (instance4 != null) { instance4.InvokeRoutedRPC(val4.m_uid, "VD_AckDelivery", new object[1] { text }); } } } catch { } } public void SetupServerSyncAndWatcher() { //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown bool flag = false; try { ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; ConfigSync = new ConfigSync(((BaseUnityPlugin)this).Info.Metadata.GUID) { DisplayName = ((BaseUnityPlugin)this).Info.Metadata.Name, CurrentVersion = ((BaseUnityPlugin)this).Info.Metadata.Version.ToString(), MinimumRequiredVersion = ((BaseUnityPlugin)this).Info.Metadata.Version.ToString() }; _serverConfigLocked = ((BaseUnityPlugin)this).Config.Bind<bool>("01 - General", "LockConfiguration", true, new ConfigDescription("If true, the server locks synchronized configs.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Browsable = false } })); ConfigSync.AddLockingConfigEntry<bool>(_serverConfigLocked); SetupConfigWatcher(); flag = true; } catch { } finally { ((BaseUnityPlugin)this).Config.SaveOnConfigSet = true; if (flag) { ((BaseUnityPlugin)this).Config.Save(); } } } protected ConfigEntry<T> Cfg<[<99544383-ab20-4483-8207-65586c01c4a5>Nullable(2)] T>(string section, string key, T defaultValue, string description, bool synced = true) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown return config(section, key, defaultValue, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synced); } private ConfigEntry<T> config<[<99544383-ab20-4483-8207-65586c01c4a5>Nullable(2)] T>(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown ConfigDescription val = new ConfigDescription(description.Description + (synchronizedSetting ? " [Synced with Server]" : " [Not Synced with Server]"), description.AcceptableValues, description.Tags); ConfigEntry<T> val2 = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, val); try { SyncedConfigEntry<T> syncedConfigEntry = ConfigSync?.AddConfigEntry<T>(val2); if (syncedConfigEntry != null) { syncedConfigEntry.SynchronizedConfig = synchronizedSetting; } } catch { } return val2; } private void SetupConfigWatcher() { try { _configWatcher?.Dispose(); _configWatcher = null; _watcherReady = false; string configPath = Paths.ConfigPath; string fileName = Path.GetFileName(((BaseUnityPlugin)this).Config.ConfigFilePath); _configWatcher = new FileSystemWatcher(configPath, fileName) { IncludeSubdirectories = false, NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite | NotifyFilters.CreationTime) }; FileSystemEventHandler onChanged = [<ab36df6e-28a1-4340-b83b-2a103281b663>NullableContext(0)] (object _, FileSystemEventArgs __) => { if (!(DateTime.UtcNow < _ignoreEventsUntilUtc)) { _lastCfgWriteUtc = DateTime.UtcNow; if (!_reloadScheduled) { _reloadScheduled = true; ((MonoBehaviour)this).StartCoroutine(ReloadConfigAfterQuietPeriod(0.75f)); } } }; _configWatcher.Changed += onChanged; _configWatcher.Created += onChanged; _configWatcher.Renamed += [<ab36df6e-28a1-4340-b83b-2a103281b663>NullableContext(0)] (object _, RenamedEventArgs __) => { onChanged(_, __); }; _configWatcher.EnableRaisingEvents = true; _watcherReady = true; } catch { } } [IteratorStateMachine(typeof(<ReloadConfigAfterQuietPeriod>d__117))] private IEnumerator ReloadConfigAfterQuietPeriod(float quietSeconds) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ReloadConfigAfterQuietPeriod>d__117(0) { <>4__this = this, quietSeconds = quietSeconds }; } [IteratorStateMachine(typeof(<InFlightAndAntiFloodSweeper>d__118))] private IEnumerator InFlightAndAntiFloodSweeper() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <InFlightAndAntiFloodSweeper>d__118(0) { <>4__this = this }; } } [HarmonyPatch(typeof(Chat), "SendText")] internal static class Redeem_ChatSendText_Patch { [<ab36df6e-28a1-4340-b83b-2a103281b663>NullableContext(1)] private static bool Prefix(Type type, string text) { if (string.IsNullOrWhiteSpace(text)) { return true; } if (text.StartsWith("/redeem", StringComparison.OrdinalIgnoreCase)) { int num = text.IndexOf(' '); if (num < 0 || num + 1 >= text.Length) { return false; } string text2 = text.Substring(num + 1).Trim(); if (string.IsNullOrEmpty(text2)) { return false; } RedeemPlugin.ClientRequestRedeem(text2); return false; } if (text.StartsWith("redeem", StringComparison.OrdinalIgnoreCase)) { return false; } return true; } } [HarmonyPatch(typeof(Terminal), "Awake")] internal static class Redeem_Terminal_Awake_Patch { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEvent <>9__1_0; internal void <Postfix>b__1_0(ConsoleEventArgs args) { if (args.Args != null && args.Args.Length >= 2) { string text = string.Join(" ", args.Args.Skip(1)).Trim(); if (!string.IsNullOrEmpty(text)) { RedeemPlugin.ClientRequestRedeem(text); } } } } private static bool _registered; private static void Postfix() { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown try { if (_registered) { return; } _registered = true; if (Terminal.commands.ContainsKey("redeem")) { return; } object obj = <>c.<>9__1_0; if (obj == null) { ConsoleEvent val = delegate(ConsoleEventArgs args) { if (args.Args != null && args.Args.Length >= 2) { string text = string.Join(" ", args.Args.Skip(1)).Trim(); if (!string.IsNullOrEmpty(text)) { RedeemPlugin.ClientRequestRedeem(text); } } }; <>c.<>9__1_0 = val; obj = (object)val; } new ConsoleCommand("redeem", "redeem <CODE> - Redeems a Redeem package", (ConsoleEvent)obj, false, true, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } catch { } } } } namespace LocalizationManager { [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(0)] [<ab36df6e-28a1-4340-b83b-2a103281b663>NullableContext(1)] [PublicAPI] public class Localizer { private static readonly Dictionary<string, Dictionary<string, Func<string>>> PlaceholderProcessors; private static readonly Dictionary<string, Dictionary<string, string>> loadedTexts; private static readonly ConditionalWeakTable<Localization, string> localizationLanguage; private static readonly List<WeakReference<Localization>> localizationObjects; [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(2)] private static BaseUnityPlugin _plugin; private static readonly List<string> fileExtensions; private static BaseUnityPlugin plugin { get { //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown if (_plugin == null) { IEnumerable<TypeInfo> source; try { source = Assembly.GetExecutingAssembly().DefinedTypes.ToList(); } catch (ReflectionTypeLoadException ex) { source = from t in ex.Types where t != null select t.GetTypeInfo(); } _plugin = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First([<ab36df6e-28a1-4340-b83b-2a103281b663>NullableContext(0)] (TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t))); } return _plugin; } } [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(2)] [method: <ab36df6e-28a1-4340-b83b-2a103281b663>NullableContext(2)] [field: <99544383-ab20-4483-8207-65586c01c4a5>Nullable(2)] public static event Action OnLocalizationComplete; private static void UpdatePlaceholderText(Localization localization, string key) { localizationLanguage.TryGetValue(localization, out var value); string text = loadedTexts[value][key]; if (PlaceholderProcessors.TryGetValue(key, out var value2)) { text = value2.Aggregate(text, [<ab36df6e-28a1-4340-b83b-2a103281b663>NullableContext(0)] (string current, KeyValuePair<string, Func<string>> kv) => current.Replace("{" + kv.Key + "}", kv.Value())); } localization.AddWord(key, text); } public static void AddPlaceholder<T>(string key, string placeholder, ConfigEntry<T> config, [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(new byte[] { 2, 1, 1 })] Func<T, string> convertConfigValue = null) { if (convertConfigValue == null) { convertConfigValue = (T val) => val.ToString(); } if (!PlaceholderProcessors.ContainsKey(key)) { PlaceholderProcessors[key] = new Dictionary<string, Func<string>>(); } config.SettingChanged += [<ab36df6e-28a1-4340-b83b-2a103281b663>NullableContext(0)] (object _, EventArgs _) => { UpdatePlaceholder(); }; if (loadedTexts.ContainsKey(Localization.instance.GetSelectedLanguage())) { UpdatePlaceholder(); } void UpdatePlaceholder() { PlaceholderProcessors[key][placeholder] = () => convertConfigValue(config.Value); UpdatePlaceholderText(Localization.instance, key); } } public static void AddText(string key, string text) { List<WeakReference<Localization>> list = new List<WeakReference<Localization>>(); foreach (WeakReference<Localization> localizationObject in localizationObjects) { if (localizationObject.TryGetTarget(out var target)) { Dictionary<string, string> dictionary = loadedTexts[localizationLanguage.GetOrCreateValue(target)]; if (!target.m_translations.ContainsKey(key)) { dictionary[key] = text; target.AddWord(key, text); } } else { list.Add(localizationObject); } } foreach (WeakReference<Localization> item in list) { localizationObjects.Remove(item); } } public static void Load() { _ = plugin; } public static void LoadLocalizationLater(Localization __instance) { LoadLocalization(Localization.instance, __instance.GetSelectedLanguage()); } public static void SafeCallLocalizeComplete() { Localizer.OnLocalizationComplete?.Invoke(); } private static void LoadLocalization(Localization __instance, string language) { if (!localizationLanguage.Remove(__instance)) { localizationObjects.Add(new WeakReference<Localization>(__instance)); } localizationLanguage.Add(__instance, language); Dictionary<string, string> dictionary = new Dictionary<string, string>(); foreach (string item in from f in Directory.GetFiles(Path.GetDirectoryName(Paths.PluginPath), plugin.Info.Metadata.Name + ".*", SearchOption.AllDirectories) where fileExtensions.IndexOf(Path.GetExtension(f)) >= 0 select f) { string[] array = Path.GetFileNameWithoutExtension(item).Split(new char[1] { '.' }); if (array.Length >= 2) { string text = array[1]; if (dictionary.ContainsKey(text)) { Debug.LogWarning((object)("Duplicate key " + text + " found for " + plugin.Info.Metadata.Name + ". The duplicate file found at " + item + " will be skipped.")); } else { dictionary[text] = item; } } } byte[] array2 = LoadTranslationFromAssembly("English"); if (array2 == null) { throw new Exception("Found no English localizations in mod " + plugin.Info.Metadata.Name + ". Expected an embedded resource translations/English.json or translations/English.yml."); } string input = Encoding.UTF8.GetString(array2).TrimStart(new char[1] { '\ufeff' }); Dictionary<string, string> dictionary2 = new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(input); if (dictionary2 == null) { throw new Exception("Localization for mod " + plugin.Info.Metadata.Name + " failed: Localization file was empty."); } string text2 = null; if (language != "English") { if (dictionary.TryGetValue(language, out var value)) { text2 = File.ReadAllText(value); } else { byte[] array3 = LoadTranslationFromAssembly(language); if (array3 != null) { text2 = Encoding.UTF8.GetString(array3); } } } if (text2 == null && dictionary.TryGetValue("English", out var value2)) { text2 = File.ReadAllText(value2); } if (text2 != null) { text2 = text2.TrimStart(new char[1] { '\ufeff' }); foreach (KeyValuePair<string, string> item2 in new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(text2) ?? new Dictionary<string, string>()) { dictionary2[item2.Key] = item2.Value; } } loadedTexts[language] = dictionary2; foreach (KeyValuePair<string, string> item3 in dictionary2) { UpdatePlaceholderText(__instance, item3.Key); } } static Localizer() { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Expected O, but got Unknown //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Expected O, but got Unknown PlaceholderProcessors = new Dictionary<string, Dictionary<string, Func<string>>>(); loadedTexts = new Dictionary<string, Dictionary<string, string>>(); localizationLanguage = new ConditionalWeakTable<Localization, string>(); localizationObjects = new List<WeakReference<Localization>>(); fileExtensions = new List<string>(2) { ".json", ".yml" }; Harmony val = new Harmony("org.bepinex.helpers.LocalizationManager"); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "SetupLanguage", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalization", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "SetupGui", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalizationLater", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "Start", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "SafeCallLocalizeComplete", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } [return: <99544383-ab20-4483-8207-65586c01c4a5>Nullable(2)] private static byte[] LoadTranslationFromAssembly(string language) { foreach (string fileExtension in fileExtensions) { byte[] array = ReadEmbeddedFileBytes("translations." + language + fileExtension); if (array != null) { return array; } } return null; } [<ab36df6e-28a1-4340-b83b-2a103281b663>NullableContext(2)] public static byte[] ReadEmbeddedFileBytes([<99544383-ab20-4483-8207-65586c01c4a5>Nullable(1)] string resourceFileName, Assembly containingAssembly = null) { using MemoryStream memoryStream = new MemoryStream(); if ((object)containingAssembly == null) { containingAssembly = Assembly.GetCallingAssembly(); } string text = containingAssembly.GetManifestResourceNames().FirstOrDefault([<ab36df6e-28a1-4340-b83b-2a103281b663>NullableContext(0)] (string str) => str.EndsWith(resourceFileName, StringComparison.Ordinal)); if (text != null) { containingAssembly.GetManifestResourceStream(text)?.CopyTo(memoryStream); } return (memoryStream.Length == 0L) ? null : memoryStream.ToArray(); } } public static class LocalizationManagerVersion { [<99544383-ab20-4483-8207-65586c01c4a5>Nullable(1)] public const string Version = "1.4.1"; } } namespace Microsoft.CodeAnalysis { [CompilerGenerated] [<b59ec622-2204-4557-bee9-a2ca267ddfb8>Embedded] internal sealed class <b59ec622-2204-4557-bee9-a2ca267ddfb8>EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] [<b59ec622-2204-4557-bee9-a2ca267ddfb8>Embedded] internal sealed class <736600b4-df17-4611-b3dd-b55b016347d3>NullableAttribute : Attribute { public readonly byte[] NullableFlags; public <736600b4-df17-4611-b3dd-b55b016347d3>NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public <736600b4-df17-4611-b3dd-b55b016347d3>NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [<b59ec622-2204-4557-bee9-a2ca267ddfb8>Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class <1f921487-6964-46fc-ab74-2eeeb9e561c9>NullableContextAttribute : Attribute { public readonly byte Flag; public <1f921487-6964-46fc-ab74-2eeeb9e561c9>NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [<b59ec622-2204-4557-bee9-a2ca267ddfb8>Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class <11348e01-4eb7-481d-956e-00370000347f>RefSafetyRulesAttribute : Attribute { public readonly int Version; public <11348e01-4eb7-481d-956e-00370000347f>RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ServerSync { [<736600b4-df17-4611-b3dd-b55b016347d3>Nullable(0)] [PublicAPI] [<1f921487-6964-46fc-ab74-2eeeb9e561c9>NullableContext(1)] internal abstract class OwnConfigEntryBase { [<736600b4-df17-4611-b3dd-b55b016347d3>Nullable(2)] public object LocalBaseValue; public bool SynchronizedConfig = true; public abstract ConfigEntryBase BaseConfig { get; } } [<1f921487-6964-46fc-ab74-2eeeb9e561c9>NullableContext(1)] [<736600b4-df17-4611-b3dd-b55b016347d3>Nullable(0)] [PublicAPI] internal class SyncedConfigEntry<[<736600b4-df17-4611-b3dd-b55b016347d3>Nullable(2)] T> : OwnConfigEntryBase { public readonly ConfigEntry<T> SourceConfig; public override ConfigEntryBase BaseConfig => (ConfigEntryBase)(object)SourceConfig; public T Value { get { return SourceConfig.Value; } set { SourceConfig.Value = value; } } public SyncedConfigEntry(ConfigEntry<T> sourceConfig) { SourceConfig = sourceConfig; base..ctor(); } public void AssignLocalValue(T value) { if (LocalBaseValue == null) { Value = value; } else { LocalBaseValue = value; } } } [<1f921487-6964-46fc-ab74-2eeeb9e561c9>NullableContext(2)] [<736600b4-df17-4611-b3dd-b55b016347d3>Nullable(0)] internal abstract class CustomSyncedValueBase { public object LocalBaseValue; [<736600b4-df17-4611-b3dd-b55b016347d3>Nullable(1)] public readonly string Identifier; [<736600b4-df17-4611-b3dd-b55b016347d3>Nullable(1)] public readonly Type Type; private object boxedValue; protected bool localIsOwner; public readonly int Priority; public object BoxedValue { get { return boxedValue; } set { boxedValue = value; this.ValueChanged?.Invoke(); } } public event Action ValueChanged; [<1f921487-6964-46fc-ab74-2eeeb9e561c9>NullableContext(1)] protected CustomSyncedValueBase(ConfigSync configSync, string identifier, Type type, int priority) { Priority = priority; Identifier = identifier; Type = type; configSync.AddCustomValue(this); localIsOwner = configSync.IsSourceOfTruth; configSync.SourceOfTruthChanged += delegate(bool truth) { localIsOwner = truth; }; } } [<1f921487-6964-46fc-ab74-2eeeb9e561c9>NullableContext(1)] [<736600b4-df17-4611-b3dd-b55b016347d3>Nullable(0)] [PublicAPI] internal sealed class CustomSyncedValue<[<736600b4-df17-4611-b3dd-b55b016347d3>Nullable(2)] T> : CustomSyncedValueBase { public T Value { get { return (T)base.BoxedValue; } set { base.BoxedValue = value; } } public CustomSyncedValue(ConfigSync configSync, string identifier, T value = default(T), int priority = 0) : base(configSync, identifier, typeof(T), priority) { Value = value; } public void AssignLocalValue(T value) { if (localIsOwner) { Value = value; } else { LocalBaseValue = value; } } } internal class ConfigurationManagerAttributes { [UsedImplicitly] public bool? ReadOnly = false; } [<1f921487-6964-46fc-ab74-2eeeb9e561c9>NullableContext(1)] [<736600b4-df17-4611-b3dd-b55b016347d3>Nullable(0)] [PublicAPI] internal class ConfigSync { [<1f921487-6964-46fc-ab74-2eeeb9e561c9>NullableContext(0)] [HarmonyPatch(typeof(ZRpc), "HandlePackage")] private static class SnatchCurrentlyHandlingRPC { [<736600b4-df17-4611-b3dd-b55b016347d3>Nullable(2)] public static ZRpc currentRpc; [HarmonyPrefix] [<1f921487-6964-46fc-ab74-2eeeb9e561c9>NullableContext(1)] private static void Prefix(ZRpc __instance) { currentRpc = __instance; } } [<1f921487-6964-46fc-ab74-2eeeb9e561c9>NullableContext(0)] [HarmonyPatch(typeof(ZNet), "Awake")] internal static class RegisterRPCPatch { [HarmonyPostfix] [<1f921487-6964-46fc-ab74-2eeeb9e561c9>NullableContext(1)] private static void Postfix(ZNet __instance) { isServer = __instance.IsServer(); foreach (ConfigSync configSync2 in configSyncs) { ZRoutedRpc.instance.Register<ZPackage>(configSync2.Name + " ConfigSync", (Action<long, ZPackage>)configSync2.RPC_FromOtherClientConfigSync); if (isServer) { configSync2.InitialSyncDone = true; Debug.Log((object)("Registered '" + configSync2.Name + " ConfigSync' RPC - waiting for incoming connections")); } } if (isServer) { ((MonoBehaviour)__instance).StartCoroutine(WatchAdminListChanges()); } [<1f921487-6964-46fc-ab74-2eeeb9e561c9>NullableContext(1)] static void SendAdmin(List<ZNetPeer> peers, bool isAdmin) { ZPackage package = ConfigsToPackage(null, null, new PackageEntry[1] { new PackageEntry { section = "Internal", key = "lockexempt", type = typeof(bool), value = isAdmin } }); ConfigSync configSync = configSyncs.First(); if (configSync != null) { ((MonoBehaviour)ZNet.instance).StartCoroutine(configSync.sendZPackage(peers, package)); } } [<1f921487-6964-46fc-ab74-2eeeb9e561c9>NullableContext(1)] static IEnumerator WatchAdminListChanges() { MethodInfo listContainsId = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null); SyncedList adminList = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance); List<string> CurrentList = new List<string>(adminList.GetList()); while (true) { yield return (object)new WaitForSeconds(30f); if (!adminList.GetList().SequenceEqual(CurrentList)) { CurrentList = new List<string>(adminList.GetList()); List<ZNetPeer> adminPeer = ZNet.instance.GetPeers().Where(delegate(ZNetPeer p) { string hostName = p.m_rpc.GetSocket().GetHostName(); return ((object)listContainsId == null) ? adminList.Contains(hostName) : ((bool)listContainsId.Invoke(ZNet.instance, new object[2] { adminList, hostName })); }).ToList(); List<ZNetPeer> nonAdminPeer = ZNet.instance.GetPeers().Except(adminPeer).ToList(); SendAdmin(nonAdminPeer, isAdmin: false); SendAdmin(adminPeer, isAdmin: true); } } } } } [<1f921487-6964-46fc-ab74-2eeeb9e561c9>NullableContext(0)] [HarmonyPatch(typeof(ZNet), "OnNewConnection")] private static class RegisterClientRPCPatch { [<1f921487-6964-46fc-ab74-2eeeb9e561c9>NullableContext(1)] [HarmonyPostfix] private static void Postfix(ZNet __instance, ZNetPeer peer) { if (__instance.IsServer()) { return; } foreach (ConfigSync configSync in configSyncs) { peer.m_rpc.Register<ZPackage>(configSync.Name + " ConfigSync", (Action<ZRpc, ZPackage>)configSync.RPC_FromServerConfigSync); } } } [<1f921487-6964-46fc-ab74-2eeeb9e561c9>NullableContext(0)] private class ParsedConfigs { [<736600b4-df17-4611-b3dd-b55b016347d3>Nullable(new byte[] { 1, 1, 2 })] public readonly Dictionary<OwnConfigEntryBase, object> configValues = new Dictionary<OwnConfigEntryBase, object>(); [<736600b4-df17-4611-b3dd-b55b016347d3>Nullable(new byte[] { 1, 1, 2 })] public readonly Dictionary<CustomSyncedValueBase, object> customValues = new Dictionary<CustomSyncedValueBase, object>(); } [<1f921487-6964-46fc-ab74-2eeeb9e561c9>NullableContext(0)] [HarmonyPatch(typeof(ZNet), "Shutdown")] private class ResetConfigsOnShutdown { [HarmonyPostfix] private static void Postfix() { ProcessingServerUpdate = true; foreach (ConfigSync configSync in configSyncs) { configSync.resetConfigsFromServer(); configSync.IsSourceOfTruth = true; configSync.InitialSyncDone = false; } ProcessingServerUpdate = false; } } [<736600b4-df17-4611-b3dd-b55b016347d3>Nullable(0)] [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] private class SendConfigsAfterLogin { [<736600b4-df17-4611-b3dd-b55b016347d3>Nullable(0)] private class BufferingSocket : ZPlayFabSocket, ISocket { public volatile bool finished = false; public volatile int versionMatchQueued = -1; public readonly List<ZPackage> Package = new List<ZPackage>(); public readonly ISocket Original; public BufferingSocket(ISocket original) { Original = original; ((ZPlayFabSocket)this)..ctor(); } public bool IsConnected() { return Original.IsConnected(); } public ZPackage Recv() { return Original.Recv(); } public int GetSendQueueSize() { return Original.GetSendQueueSize(); } public int GetCurrentSendRate() { return Original.GetCurrentSendRate(); } public bool IsHost() { return Original.IsHost(); } public void Dispose() { Original.Dispose(); } public bool GotNewData() { return Original.GotNewData(); } public void Close() { Original.Close(); } public string GetEndPointString() { return Original.GetEndPointString(); } public void GetAndResetStats(out int totalSent, out int totalRecv) { Original.GetAndResetStats(ref totalSent, ref totalRecv); } public void GetConnectionQuality(out float localQuality, out float remoteQuality, out int ping, out float outByteSec, out float inByteSec) { Original.GetConnectionQuality(ref localQuality, ref remoteQuality, ref ping, ref outByteSec, ref inByteSec); } public ISocket Accept() { return Original.Accept(); } public int GetHostPort() { return Original.GetHostPort(); } public bool Flush() { return Original.Flush(); } public string GetHostName() { return Original.GetHostName(); } public void VersionMatch() { if (finished) { Original.VersionMatch(); } else { versionMatchQueued = Package.Count; } } public void Send(ZPackage pkg) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown int pos = pkg.GetPos(); pkg.SetPos(0); int num = pkg.ReadInt(); if ((num == StringExtensionMethods.GetStableHashCode("PeerInfo") || num == StringExtensionMethods.GetStableHashCode("RoutedRPC") || num == StringExtensionMethods.GetStableHashCode("ZDOData")) && !finished) { ZPackage val = new ZPackage(pkg.GetArray()); val.SetPos(pos); Package.Add(val); } else { pkg.SetPos(pos); Original.Send(pkg); } } } [HarmonyPriority(800)] [HarmonyPrefix] private static void Prefix([<736600b4-df17-4611-b3dd-b55b016347d3>Nullable(new byte[] { 2, 1, 1 })] ref Dictionary<Assembly, BufferingSocket> __state, ZNet __instance, ZRpc rpc) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Invalid comparison between Unknown and I4 if (!__instance.IsServer()) { return; } BufferingSocket bufferingSocket = new BufferingSocket(rpc.GetSocket()); AccessTools.DeclaredField(typeof(ZRpc), "m_socket").SetValue(rpc, bufferingSocket); object? obj = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance, new object[1] { rpc }); ZNetPeer val = (ZNetPeer)((obj is ZNetPeer) ? obj : null); if (val != null && (int)ZNet.m_onlineBackend > 0) { FieldInfo fieldInfo = AccessTools.DeclaredField(typeof(ZNetPeer), "m_socket"); object? value = fieldInfo.GetValue(val); ZPlayFabSocket val2 = (ZPlayFabSocket)((value is ZPlayFabSocket) ? value : null); if (val2 != null) { typeof(ZPlayFabSocket).GetField("m_remotePlayerId").SetValue(bufferingSocket, val2.m_remotePlayerId); } fieldInfo.SetValue(val, bufferingSocket); } if (__state == null) { __state = new Dictionary<Assembly, BufferingSocket>(); } __state[Assembly.GetExecutingAssembly()] = bufferingSocket; } [HarmonyPostfix] private static void Postfix(Dictionary<Assembly, BufferingSocket> __state, ZNet __instance, ZRpc rpc) { ZNetPeer peer; if (__instance.IsServer()) { object obj = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance, new object[1] { rpc }); peer = (ZNetPeer)((obj is ZNetPeer) ? obj : null); if (peer == null) { SendBufferedData(); } else { ((MonoBehaviour)__instance).StartCoroutine(sendAsync()); } } void SendBufferedData() { if (rpc.GetSocket() is BufferingSocket bufferingSocket) { AccessTools.DeclaredField(typeof(ZRpc), "m_socket").SetValue(rpc, bufferingSocket.Original); object? obj2 = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance, new object[1] { rpc }); ZNetPeer val = (ZNetPeer)((obj2 is ZNetPeer) ? obj2 : null); if (val != null) { AccessTools.DeclaredField(typeof(ZNetPeer), "m_socket").SetValue(val, bufferingSocket.Original); } } BufferingSocket bufferingSocket2 = __state[Assembly.GetExecutingAssembly()]; bufferingSocket2.finished = true; for (int i = 0; i < bufferingSocket2.Package.Count; i++) { if (i == bufferingSocket2.versionMatchQueued) { bufferingSocket2.Original.VersionMatch(); } bufferingSocket2.Original.Send(bufferingSocket2.Package[i]); } if (bufferingSocket2.Package.Count == bufferingSocket2.versionMatchQueued) { bufferingSocket2.Original.VersionMatch(); } } IEnumerator sendAsync() { foreach (ConfigSync configSync in configSyncs) { List<PackageEntry> entries = new List<PackageEntry>(); if (configSync.CurrentVersion != null) { entries.Add(new PackageEntry { section = "Internal", key = "serverversion", type = typeof(string), value = configSync.CurrentVersion }); } MethodInfo listContainsId = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null); SyncedList adminList = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance); entries.Add(new PackageEntry { section = "Internal", key = "lockexempt", type = typeof(bool), value = (((object)listContainsId == null) ? ((object)adminList.Contains(rpc.GetSocket().GetHostName())) : listContainsId.Invoke(ZNet.instance, new object[2] { adminList, rpc.GetSocket().GetHostName() })) }); ZPackage package = ConfigsToPackage(configSync.allConfigs.Select([<1f921487-6964-46fc-ab74-2eeeb9e561c9>NullableContext(0)] (OwnConfigEntryBase c) => c.BaseConfig), configSync.allCustomValues, entries, partial: false); yield return ((MonoBehaviour)__instance).StartCoroutine(configSync.sendZPackage(new List<ZNetPeer> { peer }, package)); } SendBufferedData(); } } } [<736600b4-df17-4611-b3dd-b55b016347d3>Nullable(0)] private class PackageEntry { public string section = null; public string key = null; public Type type = null; [<736600b4-df17-4611-b3dd-b55b016347d3>Nullable(2)] public object value; } [HarmonyPatch(typeof(ConfigEntryBase), "GetSerializedValue")] [<1f921487-6964-46fc-ab74-2eeeb9e561c9>NullableContext(0)] private static class PreventSavingServerInfo { [HarmonyPrefix] [<1f921487-6964-46fc-ab74-2eeeb9e561c9>NullableContext(1)] private static bool Prefix(ConfigEntryBase __instance, ref string __result) { OwnConfigEntryBase ownConfigEntryBase = configData(__instance); if (ownConfigEntryBase == null || isWritableConfig(ownConfigEntryBase)) { return true; } __result = TomlTypeConverter.ConvertToString(ownConfigEntryBase.LocalBaseValue, __instance.SettingType); return false; } } [HarmonyPatch(typeof(ConfigEntryBase), "SetSerializedValue")] [<1f921487-6964-46fc-ab74-2eeeb9e561c9>NullableContext(0)] private static class PreventConfigRereadChangingValues { [HarmonyPrefix] [<1f921487-6964-46fc-ab74-2eeeb9e561c9>NullableContext(1)] private static bool Prefix(ConfigEntryBase __instance, string value) { OwnConfigEntryBase ownConfigEntryBase = configData(__instance); if (ownConfigEntryBase == null || ownConfigEntryBase.LocalBaseValue == null) { return true; } try { ownConfigEntryBase.LocalBaseValue = TomlTypeConverter.ConvertToValue(value, __instance.SettingType); } catch (Exception ex) { Debug.LogWarning((object)$"Config value of setting \"{__instance.Definition}\" could not be parsed and will be ignored. Reason: {ex.Message}; Value: {value}"); } return false; } } [<736600b4-df17-4611-b3dd-b55b016347d3>Nullable(0)] private class InvalidDeserializationTypeException : Exception { public string expected = null; public string received = null; public string field = ""; } public static bool ProcessingServerUpdate; public readonly string Name; [<736600b4-df17-4611-b3dd-b55b016347d3>Nullable(2)] public string DisplayName; [<736600b4-df17-4611-b3dd-b55b016347d3>Nullable(2)] public string CurrentVersion; [<736600b4-df17-4611-b3dd-b55b016347d3>Nullable(2)] public string MinimumRequiredVersion; public bool ModRequired = false; private bool? forceConfigLocking; private bool isSourceOfTruth = true; private static readonly HashSet<ConfigSync> configSyncs; private readonly HashSet<OwnConfigEntryBase> allConfigs = new HashSet<OwnConfigEntryBase>(); private HashSet<CustomSyncedValueBase> allCustomValues = new HashSet<CustomSyncedValueBase>(); private static bool isServer; private static bool lockExempt; [<736600b4-df17-4611-b3dd-b55b016347d3>Nullable(2)] private OwnConfigEntryBase lockedConfig = null; private const byte PARTIAL_CONFIGS = 1; private const byte FRAGMENTED_CONFIG = 2; private const byte COMPRESSED_CONFIG = 4; private readonly Dictionary<string, SortedDictionary<int, byte[]>> configValueCache = new Dictionary<string, SortedDictionary<int, byte[]>>(); [<736600b4-df17-4611-b3dd-b55b016347d3>Nullable(new byte[] { 1, 0, 1 })] private readonly List<KeyValuePair<long, string>> cacheExpirations = new List<KeyValuePair<long, string>>(); private static long packageCounter; public bool IsLocked { get { bool? flag = forceConfigLocking; bool num; if (!flag.HasValue) { if (lockedConfig == null) { goto IL_0052; } num = ((IConvertible)lockedConfig.BaseConfig.BoxedValue).ToInt32(CultureInfo.InvariantCulture) != 0; } else { num = flag.GetValueOrDefault(); } if (!num) { goto IL_0052; } int result = ((!lockExempt) ? 1 : 0); goto IL_0053; IL_0053: return (byte)result != 0; IL_0052: result = 0; goto IL_0053; } set { forceConfigLocking = value; } } public bool IsAdmin => lockExempt || isSourceOfTruth; public bool IsSourceOfTruth { get { return isSourceOfTruth; } private set { if (value != isSourceOfTruth) { isSourceOfTruth = value; this.SourceOfTruthChanged?.Invoke(value); } } } public bool InitialSyncDone { get; private set; } = false; [<736600b4-df17-4611-b3dd-b55b016347d3>Nullable(2)] [method: <1f921487-6964-46fc-ab74-2eeeb9e561c9>NullableContext(2)] [field: <736600b4-df17-4611-b3dd-b55b016347d3>Nullable(2)] public event Action<bool> SourceOfTruthChanged; [<736600b4-df17-4611-b3dd-b55b016347d3>Nullable(2)] [method: <1f921487-6964-46fc-ab74-2eeeb9e561c9>NullableContext(2)] [field: <736600b4-df17-4611-b3dd-b55b016347d3>Nullable(2)] private event Action lockedConfigChanged; static ConfigSync() { ProcessingServerUpdate = false; configSyncs = new HashSet<ConfigSync>(); lockExempt = false; packageCounter = 0L; RuntimeHelpers.RunClassConstructor(typeof(VersionCheck).TypeHandle); } public ConfigSync(string name) { Name = name; configSyncs.Add(this); new VersionCheck(this); } public SyncedConfigEntry<T> AddConfigEntry<[<736600b4-df17-4611-b3dd-b55b016347d3>Nullable(2)] T>(ConfigEntry<T> configEntry) { OwnConfigEntryBase ownConfigEntryBase = configData((ConfigEntryBase)(object)configEntry); SyncedConfigEntry<T> syncedEntry = ownConfigEntryBase as SyncedConfigEntry<T>; if (syncedEntry == null) { syncedEntry = new SyncedConfigEntry<T>(configEntry); AccessTools.DeclaredField(typeof(ConfigDescription), "<Tags>k__BackingField").SetValue(((ConfigEntryBase)configEntry).Description, new object[1] { new ConfigurationManagerAttributes() }.Concat(((ConfigEntryBase)configEntry).Description.Tags ?? Array.Empty<object>()).Concat(new SyncedConfigEntry<T>[1] { syncedEntry }).ToArray()); configEntry.SettingChanged += [<1f921487-6964-46fc-ab74-2eeeb9e561c9>NullableContext(0)] (object _, EventArgs _) => { if (!ProcessingServerUpdate && syncedEntry.SynchronizedConfig) { Broadcast(ZRoutedRpc.Everybody, (ConfigEntryBase)configEntry); } }; allConfigs.Add(syncedEntry); } return syncedEntry; } public SyncedConfigEntry<T> AddLockingConfigEntry<[<736600b4-df17-4611-b3dd-b55b016347d3>Nullable(0)] T>(ConfigEntry<T> lockingConfig) where T : IConvertible { if (lockedConfig != null) { throw new Exception("Cannot initialize locking ConfigEntry twice"); } lockedConfig = AddConfigEntry<T>(lockingConfig); lockingConfig.SettingChanged += [<1f921487-6964-46fc-ab74-2eeeb9e561c9>NullableContext(0)] (object _, EventArgs _) => { this.lockedConfigChanged?.Invoke(); }; return (SyncedConfigEntry<T>)lockedConfig; } internal void AddCustomValue(CustomSyncedValueBase customValue) { if (allCustomValues.Select([<1f921487-6964-46fc-ab74-2eeeb9e561c9>NullableContext(0)] (CustomSyncedValueBase v) => v.Identifier).Concat(new string[1] { "serverversion" }).Contains(customValue.Identifier)) { throw new Exception("Cannot have multiple settings with the same name or with a reserved name (serverversion)"); } allCustomValues.Add(customValue); allCustomValues = new HashSet<CustomSyncedValueBase>(allCustomValues.OrderByDescending([<1f921487-6964-46fc-ab74-2eeeb9e561c9>NullableContext(0)] (CustomSyncedValueBase v) => v.Priority)); customValue.ValueChanged += delegate { if (!ProcessingServerUpdate) { Broadcast(ZRoutedRpc.Everybody, customValue); } }; } private void RPC_FromServerConfigSync(ZRpc rpc, ZPackage package) { lockedConfigChanged += serverLockedSettingChanged; IsSourceOfTruth = false; if (HandleConfigSyncRPC(0L, package, clientUpdate: false)) { InitialSyncDone = true; } } private void RPC_FromOtherClientConfigSync(long sender, ZPackage package) { HandleConfigSyncRPC(sender, package, clientUpdate: true); } private bool HandleConfigSyncRPC(long sender, ZPackage package, bool clientUpdate) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Expected O, but got Unknown //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Expected O, but got Unknown try { if (isServer && IsLocked) { ZRpc currentRpc = SnatchCurrentlyHandlingRPC.currentRpc; object obj; if (currentRpc == null) { obj = null; } else { ISocket socket = currentRpc.GetSocket(); obj = ((socket != null) ? socket.GetHostName() : null); } string text = (string)obj; if (text != null) { MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null); SyncedList val = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance); if (!(((object)methodInfo == null) ? val.Contains(text) : ((bool)methodInfo.Invoke(ZNet.instance, new object[2] { val, text })))) { return false; } } } cacheExpirations.RemoveAll(([<736600b4-df17-4611-b3dd-b55b016347d3>Nullable(new byte[] { 0, 1 })] KeyValuePair<long, string> kv) => { if (kv.Key < DateTimeOffset.Now.Ticks) { configValueCache.Remove(kv.Value); return true; } return false; }); byte b = package.ReadByte(); if ((b & 2u) != 0) { long num = package.ReadLong(); string text2 = sender.ToString() + num; if (!configValueCache.TryGetValue(text2, out var value)) { value = new SortedDictionary<int, byte[]>(); configValueCache[text2] = value; cacheExpirations.Add(new KeyValuePair<long, string>(DateTimeOffset.Now.AddSeconds(60.0).Ticks, text2)); } int key = package.ReadInt(); int num2 = package.ReadInt(); value.Add(key, package.ReadByteArray()); if (value.Count < num2) { return false; } configValueCache.Remove(text2); package = new ZPackage(value.Values.SelectMany([<1f921487-6964-46fc-ab74-2eeeb9e561c9>NullableContext(0)] (byte[] a) => a).ToArray()); b = package.ReadByte(); } ProcessingServerUpdate = true; if ((b & 4u) != 0) { byte[] buffer = package.ReadByteArray(); MemoryStream stream = new MemoryStream(buffer); MemoryStream memoryStream = new MemoryStream(); using (DeflateStream deflateStream = new DeflateStream(stream, CompressionMode.Decompress)) { deflateStream.CopyTo(memoryStream); } package = new ZPackage(memoryStream.ToArray()); b = package.ReadByte(); } if ((b & 1) == 0) { resetConfigsFromServer(); } ParsedConfigs parsedConfigs = ReadConfigsFromPackage(package); ConfigFile val2 = null; bool saveOnConfigSet = false; foreach (KeyValuePair<OwnConfigEntryBase, object> configValue in parsedConfigs.configValues) { if (!isServer && configValue.Key.LocalBaseValue == null) { configValue.Key.LocalBaseValue = configValue.Key.BaseConfig.BoxedValue; } if (val2 == null) { val2