Decompiled source of Krumpac Reforge ModPack v7.3.4
plugins/Krumpac_UI.dll
Decompiled 2 weeks 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.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using JetBrains.Annotations; using LocalizationManager; using Microsoft.CodeAnalysis; using ServerSync; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Core.ObjectPool; using YamlDotNet.Core.Tokens; using YamlDotNet.Helpers; using YamlDotNet.Serialization; using YamlDotNet.Serialization.BufferedDeserialization; using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators; using YamlDotNet.Serialization.Callbacks; using YamlDotNet.Serialization.Converters; using YamlDotNet.Serialization.EventEmitters; using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.NodeDeserializers; using YamlDotNet.Serialization.NodeTypeResolvers; using YamlDotNet.Serialization.ObjectFactories; using YamlDotNet.Serialization.ObjectGraphTraversalStrategies; using YamlDotNet.Serialization.ObjectGraphVisitors; using YamlDotNet.Serialization.Schemas; using YamlDotNet.Serialization.TypeInspectors; using YamlDotNet.Serialization.TypeResolvers; using YamlDotNet.Serialization.Utilities; using YamlDotNet.Serialization.ValueDeserializers; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("VandemUI")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("KG")] [assembly: AssemblyProduct("VandemUI")] [assembly: AssemblyCopyright("Copyright © KG 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("BF0A7CF2-B797-4B8A-942D-864FBB09673A")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } public class WildcardPattern { private readonly string _expression; private readonly Regex _regex; public WildcardPattern(string pattern) { if (string.IsNullOrEmpty(pattern)) { throw new ArgumentNullException("pattern"); } _expression = "^" + Regex.Escape(pattern).Replace("\\\\\\?", "??").Replace("\\?", ".") .Replace("??", "\\?") .Replace("\\\\\\*", "**") .Replace("\\*", ".*") .Replace("**", "\\*") + "$"; _regex = new Regex(_expression, RegexOptions.Compiled); } public bool IsMatch(string value) { return _regex.IsMatch(value); } } namespace ServerSync { [PublicAPI] public abstract class OwnConfigEntryBase { public object? LocalBaseValue; public bool SynchronizedConfig = true; public abstract ConfigEntryBase BaseConfig { get; } } [PublicAPI] public class SyncedConfigEntry<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; } public void AssignLocalValue(T value) { if (LocalBaseValue == null) { Value = value; } else { LocalBaseValue = value; } } } public abstract class CustomSyncedValueBase { public Action? ValueChanged; public object? LocalBaseValue; public readonly string Identifier; public readonly Type Type; private object? boxedValue; protected bool localIsOwner; public readonly int Priority; public object? BoxedValue { get { return boxedValue; } set { boxedValue = value; ValueChanged?.Invoke(); } } protected CustomSyncedValueBase(ConfigSync configSync, string identifier, Type type, int priority) { Priority = priority; Identifier = identifier; Type = type; configSync.AddCustomValue(this); localIsOwner = configSync.IsSourceOfTruth; configSync.SourceOfTruthChanged += delegate(bool truth) { localIsOwner = truth; }; } } [PublicAPI] public sealed class CustomSyncedValue<T> : CustomSyncedValueBase { public T Value { get { return (T)base.BoxedValue; } set { base.BoxedValue = value; } } public void Update() { ValueChanged?.Invoke(); } public CustomSyncedValue(ConfigSync configSync, string identifier, T value = default(T), int priority = 0) : base(configSync, identifier, typeof(T), priority) { Value = value; } public void AssignLocalValue(T value) { if (localIsOwner) { Value = value; } else { LocalBaseValue = value; } } } internal class ConfigurationManagerAttributes { [UsedImplicitly] public bool? ReadOnly = false; } [PublicAPI] public class ConfigSync { [HarmonyPatch(typeof(ZRpc), "HandlePackage")] private static class SnatchCurrentlyHandlingRPC { public static ZRpc? currentRpc; [HarmonyPrefix] private static void Prefix(ZRpc __instance) { currentRpc = __instance; } } [HarmonyPatch(typeof(ZNet), "Awake")] internal static class RegisterRPCPatch { [HarmonyPostfix] private static void Postfix(ZNet __instance) { isServer = __instance.IsServer(); foreach (ConfigSync configSync2 in configSyncs) { ZRoutedRpc.instance.Register<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()); } 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)); } } 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> list = ZNet.instance.GetPeers().Where(delegate(ZNetPeer p) { string hostName = p.m_rpc.GetSocket().GetHostName(); return ((object)listContainsId != null) ? ((bool)listContainsId.Invoke(ZNet.instance, new object[2] { adminList, hostName })) : adminList.Contains(hostName); }).ToList(); List<ZNetPeer> peers2 = ZNet.instance.GetPeers().Except(list).ToList(); SendAdmin(peers2, isAdmin: false); SendAdmin(list, isAdmin: true); } } } } } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] private static class RegisterClientRPCPatch { [HarmonyPostfix] private static void Postfix(ZNet __instance, ZNetPeer peer) { if (__instance.IsServer()) { return; } foreach (ConfigSync configSync in configSyncs) { peer.m_rpc.Register<ZPackage>(configSync.Name + " ConfigSync", (Action<ZRpc, ZPackage>)configSync.RPC_FromServerConfigSync); } } } private class ParsedConfigs { public readonly Dictionary<OwnConfigEntryBase, object?> configValues = new Dictionary<OwnConfigEntryBase, object>(); public readonly Dictionary<CustomSyncedValueBase, object?> customValues = new Dictionary<CustomSyncedValueBase, object>(); } [HarmonyPatch(typeof(ZNet), "Shutdown")] private class ResetConfigsOnShutdown { [HarmonyPostfix] private static void Postfix() { ProcessingServerUpdate = true; foreach (ConfigSync configSync in configSyncs) { configSync.resetConfigsFromServer(); configSync.IsSourceOfTruth = true; configSync.InitialSyncDone = false; } ProcessingServerUpdate = false; } } [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] private class SendConfigsAfterLogin { private class BufferingSocket : ISocket { public volatile bool finished; public volatile int versionMatchQueued = -1; public readonly List<ZPackage> Package = new List<ZPackage>(); public readonly ISocket Original; public BufferingSocket(ISocket original) { Original = original; } 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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown int pos = pkg.GetPos(); pkg.SetPos(0); int num = pkg.ReadInt(); if ((num == StringExtensionMethods.GetStableHashCode("PeerInfo") || num == StringExtensionMethods.GetStableHashCode("RoutedRPC") || num == StringExtensionMethods.GetStableHashCode("ZDOData")) && !finished) { ZPackage val = new ZPackage(pkg.GetArray()); val.SetPos(pos); Package.Add(val); } else { pkg.SetPos(pos); Original.Send(pkg); } } } [HarmonyPriority(800)] [HarmonyPrefix] private static void Prefix(ref Dictionary<Assembly, BufferingSocket>? __state, ZNet __instance, ZRpc rpc) { //IL_0073: Unknown result type (might be due to invalid IL or missing references) if (__instance.IsServer()) { BufferingSocket value = new BufferingSocket(rpc.GetSocket()); AccessTools.DeclaredField(typeof(ZRpc), "m_socket").SetValue(rpc, value); 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) { AccessTools.DeclaredField(typeof(ZNetPeer), "m_socket").SetValue(val, value); } if (__state == null) { __state = new Dictionary<Assembly, BufferingSocket>(); } __state[Assembly.GetExecutingAssembly()] = value; } } [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); FieldInfo fieldInfo = AccessTools.Field(typeof(ZNetPeer), "m_socket"); FieldInfo fieldInfo2 = AccessTools.Field(typeof(ZPlayFabSocket), "m_remotePlayerId"); val.MatchForward(false, (CodeMatch[])(object)new CodeMatch[4] { new CodeMatch((OpCode?)OpCodes.Ldloc_1, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldfld, (object)fieldInfo, (string)null), new CodeMatch((OpCode?)OpCodes.Isinst, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldfld, (object)fieldInfo2, (string)null) }); if (val.IsInvalid) { return instructions; } val.SetAndAdvance(OpCodes.Ldstr, (object)"none"); val.SetOpcodeAndAdvance(OpCodes.Nop); val.SetOpcodeAndAdvance(OpCodes.Nop); val.SetOpcodeAndAdvance(OpCodes.Nop); return val.InstructionEnumeration(); } [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 val2 = (ZNetPeer)((obj2 is ZNetPeer) ? obj2 : null); if (val2 != null) { AccessTools.DeclaredField(typeof(ZNetPeer), "m_socket").SetValue(val2, 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> list = new List<PackageEntry>(); if (configSync.CurrentVersion != null) { list.Add(new PackageEntry { section = "Internal", key = "serverversion", type = typeof(string), value = configSync.CurrentVersion }); } MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null); SyncedList val = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance); list.Add(new PackageEntry { section = "Internal", key = "lockexempt", type = typeof(bool), value = (((object)methodInfo == null) ? ((object)val.Contains(rpc.GetSocket().GetHostName())) : methodInfo.Invoke(ZNet.instance, new object[2] { val, rpc.GetSocket().GetHostName() })) }); ZPackage package = ConfigsToPackage(configSync.allConfigs.Select((OwnConfigEntryBase c) => c.BaseConfig), configSync.allCustomValues, list, partial: false); yield return ((MonoBehaviour)__instance).StartCoroutine(configSync.sendZPackage(new List<ZNetPeer> { peer }, package)); } SendBufferedData(); } } } private class PackageEntry { public string section; public string key; public Type type; public object? value; } [HarmonyPatch(typeof(ConfigEntryBase), "GetSerializedValue")] private static class PreventSavingServerInfo { [HarmonyPrefix] private static bool Prefix(ConfigEntryBase __instance, ref string __result) { OwnConfigEntryBase ownConfigEntryBase = configData(__instance); if (ownConfigEntryBase == null || isWritableConfig(ownConfigEntryBase)) { return true; } __result = TomlTypeConverter.ConvertToString(ownConfigEntryBase.LocalBaseValue, __instance.SettingType); return false; } } [HarmonyPatch(typeof(ConfigEntryBase), "SetSerializedValue")] private static class PreventConfigRereadChangingValues { [HarmonyPrefix] private static bool Prefix(ConfigEntryBase __instance, string value) { OwnConfigEntryBase ownConfigEntryBase = configData(__instance); if (ownConfigEntryBase == null || ownConfigEntryBase.LocalBaseValue == null) { return true; } try { ownConfigEntryBase.LocalBaseValue = TomlTypeConverter.ConvertToValue(value, __instance.SettingType); } catch (Exception ex) { Debug.LogWarning((object)$"Config value of setting \"{__instance.Definition}\" could not be parsed and will be ignored. Reason: {ex.Message}; Value: {value}"); } return false; } } private class InvalidDeserializationTypeException : Exception { public string expected; public string received; public string field = ""; } public static bool ProcessingServerUpdate; public readonly string Name; public string? DisplayName; public string? CurrentVersion; public string? MinimumRequiredVersion; public bool ModRequired; 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; private OwnConfigEntryBase? lockedConfig; 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[]>>(); 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_0051; } num = ((IConvertible)lockedConfig.BaseConfig.BoxedValue).ToInt32(CultureInfo.InvariantCulture) != 0; } else { num = flag.GetValueOrDefault(); } if (num) { return !lockExempt; } goto IL_0051; IL_0051: return false; } set { forceConfigLocking = value; } } public bool IsAdmin { get { if (!lockExempt) { return isSourceOfTruth; } return true; } } public bool IsSourceOfTruth { get { return isSourceOfTruth; } private set { if (value != isSourceOfTruth) { isSourceOfTruth = value; this.SourceOfTruthChanged?.Invoke(value); } } } public bool InitialSyncDone { get; private set; } public event Action<bool>? SourceOfTruthChanged; 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<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 += delegate { if (!ProcessingServerUpdate && syncedEntry.SynchronizedConfig) { Broadcast(ZRoutedRpc.Everybody, (ConfigEntryBase)configEntry); } }; allConfigs.Add(syncedEntry); } return syncedEntry; } public SyncedConfigEntry<T> AddLockingConfigEntry<T>(ConfigEntry<T> lockingConfig) where T : IConvertible { if (lockedConfig != null) { throw new Exception("Cannot initialize locking ConfigEntry twice"); } lockedConfig = AddConfigEntry<T>(lockingConfig); lockingConfig.SettingChanged += delegate { this.lockedConfigChanged?.Invoke(); }; return (SyncedConfigEntry<T>)lockedConfig; } internal void AddCustomValue(CustomSyncedValueBase customValue) { if (allCustomValues.Select((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((CustomSyncedValueBase v) => v.Priority)); CustomSyncedValueBase customSyncedValueBase = customValue; customSyncedValueBase.ValueChanged = (Action)Delegate.Combine(customSyncedValueBase.ValueChanged, (Action)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_0215: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Expected O, but got Unknown //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown try { if (isServer && IsLocked) { ZRpc? currentRpc = SnatchCurrentlyHandlingRPC.currentRpc; object obj; if (currentRpc == null) { obj = null; } else { ISocket socket = currentRpc.GetSocket(); obj = ((socket != null) ? socket.GetHostName() : null); } string text = (string)obj; if (text != null) { MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null); SyncedList val = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance); if (!(((object)methodInfo == null) ? val.Contains(text) : ((bool)methodInfo.Invoke(ZNet.instance, new object[2] { val, text })))) { return false; } } } cacheExpirations.RemoveAll(delegate(KeyValuePair<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((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 = configValue.Key.BaseConfig.ConfigFile; saveOnConfigSet = val2.SaveOnConfigSet; val2.SaveOnConfigSet = false; } configValue.Key.BaseConfig.BoxedValue = configValue.Value; } if (val2 != null) { val2.SaveOnConfigSet = saveOnConfigSet; } foreach (KeyValuePair<CustomSyncedValueBase, object> customValue in parsedConfigs.customValues) { if (!isServer) { CustomSyncedValueBase key2 = customValue.Key; if (key2.LocalBaseValue == null) { key2.LocalBaseValue = customValue.Key.BoxedValue; } } customValue.Key.BoxedValue = customValue.Value; } Debug.Log((object)string.Format("Received {0} configs and {1} custom values from {2} for mod {3}", parsedConfigs.configValues.Count, parsedConfigs.customValues.Count, (isServer || clientUpdate) ? $"client {sender}" : "the server", DisplayName ?? Name)); if (!isServer) { serverLockedSettingChanged(); } return true; } finally { ProcessingServerUpdate = false; } } private ParsedConfigs ReadConfigsFromPackage(ZPackage package) { ParsedConfigs parsedConfigs = new ParsedConfigs(); Dictionary<string, OwnConfigEntryBase> dictionary = allConfigs.Where((OwnConfigEntryBase c) => c.SynchronizedConfig).ToDictionary((OwnConfigEntryBase c) => c.BaseConfig.Definition.Section + "_" + c.BaseConfig.Definition.Key, (OwnConfigEntryBase c) => c); Dictionary<string, CustomSyncedValueBase> dictionary2 = allCustomValues.ToDictionary((CustomSyncedValueBase c) => c.Identifier, (CustomSyncedValueBase c) => c); int num = package.ReadInt(); for (int i = 0; i < num; i++) { string text = package.ReadString(); string text2 = package.ReadString(); string text3 = package.ReadString(); Type type = Type.GetType(text3); if (text3 == "" || type != null) { object obj; try { obj = ((text3 == "") ? null : ReadValueWithTypeFromZPackage(package, type)); } catch (InvalidDeserializationTypeException ex) { Debug.LogWarning((object)("Got unexpected struct internal type " + ex.received + " for field " + ex.field + " struct " + text3 + " for " + text2 + " in section " + text + " for mod " + (DisplayName ?? Name) + ", expecting " + ex.expected)); continue; } OwnConfigEntryBase value2; if (text == "Internal") { CustomSyncedValueBase value; if (text2 == "serverversion") { if (obj?.ToString() != CurrentVersion) { Debug.LogWarning((object)("Received server version is not equal: server version = " + (obj?.ToString() ?? "null") + "; local version = " + (CurrentVersion ?? "unknown"))); } } else if (text2 == "lockexempt") { if (obj is bool flag) { lockExempt = flag; } } else if (dictionary2.TryGetValue(text2, out value)) { if ((text3 == "" && (!value.Type.IsValueType || Nullable.GetUnderlyingType(value.Type) != null)) || GetZPackageTypeString(value.Type) == text3) { parsedConfigs.customValues[value] = obj; continue; } Debug.LogWarning((object)("Got unexpected type " + text3 + " for internal value " + text2 + " for mod " + (DisplayName ?? Name) + ", expecting " + value.Type.AssemblyQualifiedName)); } } else if (dictionary.TryGetValue(text + "_" + text2, out value2)) { Type type2 = configType(value2.BaseConfig); if ((text3 == "" && (!type2.IsValueType || Nullable.GetUnderlyingType(type2) != null)) || GetZPackageTypeString(type2) == text3) { parsedConfigs.configValues[value2] = obj; continue; } Debug.LogWarning((object)("Got unexpected type " + text3 + " for " + text2 + " in section " + text + " for mod " + (DisplayName ?? Name) + ", expecting " + type2.AssemblyQualifiedName)); } else { Debug.LogWarning((object)("Received unknown config entry " + text2 + " in section " + text + " for mod " + (DisplayName ?? Name) + ". This may happen if client and server versions of the mod do not match.")); } continue; } Debug.LogWarning((object)("Got invalid type " + text3 + ", abort reading of received configs")); return new ParsedConfigs(); } return parsedConfigs; } private static bool isWritableConfig(OwnConfigEntryBase config) { ConfigSync configSync = configSyncs.FirstOrDefault((ConfigSync cs) => cs.allConfigs.Contains(config)); if (configSync == null) { return true; } if (!configSync.IsSourceOfTruth && config.SynchronizedConfig && config.LocalBaseValue != null) { if (!configSync.IsLocked) { if (config == configSync.lockedConfig) { return lockExempt; } return true; } return false; } return true; } private void serverLockedSettingChanged() { foreach (OwnConfigEntryBase allConfig in allConfigs) { configAttribute<ConfigurationManagerAttributes>(allConfig.BaseConfig).ReadOnly = !isWritableConfig(allConfig); } } private void resetConfigsFromServer() { ConfigFile val = null; bool saveOnConfigSet = false; foreach (OwnConfigEntryBase item in allConfigs.Where((OwnConfigEntryBase config) => config.LocalBaseValue != null)) { if (val == null) { val = item.BaseConfig.ConfigFile; saveOnConfigSet = val.SaveOnConfigSet; val.SaveOnConfigSet = false; } item.BaseConfig.BoxedValue = item.LocalBaseValue; item.LocalBaseValue = null; } if (val != null) { val.SaveOnConfigSet = saveOnConfigSet; } foreach (CustomSyncedValueBase item2 in allCustomValues.Where((CustomSyncedValueBase config) => config.LocalBaseValue != null)) { item2.BoxedValue = item2.LocalBaseValue; item2.LocalBaseValue = null; } lockedConfigChanged -= serverLockedSettingChanged; serverLockedSettingChanged(); } private IEnumerator<bool> distributeConfigToPeers(ZNetPeer peer, ZPackage package) { ZRoutedRpc rpc = ZRoutedRpc.instance; if (rpc == null) { yield break; } byte[] data = package.GetArray(); if (data != null && data.LongLength > 250000) { int fragments = (int)(1 + (data.LongLength - 1) / 250000); long packageIdentifier = ++packageCounter; int fragment = 0; while (fragment < fragments) { foreach (bool item in waitForQueue()) { yield return item; } if (peer.m_socket.IsConnected()) { ZPackage val = new ZPackage(); val.Write((byte)2); val.Write(packageIdentifier); val.Write(fragment); val.Write(fragments); val.Write(data.Skip(250000 * fragment).Take(250000).ToArray()); SendPackage(val); if (fragment != fragments - 1) { yield return true; } int num = fragment + 1; fragment = num; continue; } break; } yield break; } foreach (bool item2 in waitForQueue()) { yield return item2; } SendPackage(package); void SendPackage(ZPackage pkg) { string text = Name + " ConfigSync"; if (isServer) { peer.m_rpc.Invoke(text, new object[1] { pkg }); } else { rpc.InvokeRoutedRPC(peer.m_server ? 0 : peer.m_uid, text, new object[1] { pkg }); } } IEnumerable<bool> waitForQueue() { float timeout = Time.time + 30f; while (peer.m_socket.GetSendQueueSize() > 20000) { if (Time.time > timeout) { Debug.Log((object)$"Disconnecting {peer.m_uid} after 30 seconds config sending timeout"); peer.m_rpc.Invoke("Error", new object[1] { (object)(ConnectionStatus)5 }); ZNet.instance.Disconnect(peer); break; } yield return false; } } } private IEnumerator sendZPackage(long target, ZPackage package) { if (!Object.op_Implicit((Object)(object)ZNet.instance)) { return Enumerable.Empty<object>().GetEnumerator(); } List<ZNetPeer> list = (List<ZNetPeer>)AccessTools.DeclaredField(typeof(ZRoutedRpc), "m_peers").GetValue(ZRoutedRpc.instance); if (target != ZRoutedRpc.Everybody) { list = list.Where((ZNetPeer p) => p.m_uid == target).ToList(); } return sendZPackage(list, package); } private IEnumerator sendZPackage(List<ZNetPeer> peers, ZPackage package) { if (!Object.op_Implicit((Object)(object)ZNet.instance)) { yield break; } byte[] array = package.GetArray(); if (array != null && array.LongLength > 10000) { ZPackage val = new ZPackage(); val.Write((byte)4); MemoryStream memoryStream = new MemoryStream(); using (DeflateStream deflateStream = new DeflateStream(memoryStream, CompressionLevel.Optimal)) { deflateStream.Write(array, 0, array.Length); } val.Write(memoryStream.ToArray()); package = val; } List<IEnumerator<bool>> writers = (from peer in peers where peer.IsReady() select peer into p select distributeConfigToPeers(p, package)).ToList(); writers.RemoveAll((IEnumerator<bool> writer) => !writer.MoveNext()); while (writers.Count > 0) { yield return null; writers.RemoveAll((IEnumerator<bool> writer) => !writer.MoveNext()); } } private void Broadcast(long target, params ConfigEntryBase[] configs) { if (!IsLocked || isServer) { ZPackage package = ConfigsToPackage(configs); ZNet instance = ZNet.instance; if (instance != null) { ((MonoBehaviour)instance).StartCoroutine(sendZPackage(target, package)); } } } private void Broadcast(long target, params CustomSyncedValueBase[] customValues) { if (!IsLocked || isServer) { ZPackage package = ConfigsToPackage(null, customValues); ZNet instance = ZNet.instance; if (instance != null) { ((MonoBehaviour)instance).StartCoroutine(sendZPackage(target, package)); } } } private static OwnConfigEntryBase? configData(ConfigEntryBase config) { return config.Description.Tags?.OfType<OwnConfigEntryBase>().SingleOrDefault(); } public static SyncedConfigEntry<T>? ConfigData<T>(ConfigEntry<T> config) { return ((ConfigEntryBase)config).Description.Tags?.OfType<SyncedConfigEntry<T>>().SingleOrDefault(); } private static T configAttribute<T>(ConfigEntryBase config) { return config.Description.Tags.OfType<T>().First(); } private static Type configType(ConfigEntryBase config) { return configType(config.SettingType); } private static Type configType(Type type) { if (!type.IsEnum) { return type; } return Enum.GetUnderlyingType(type); } private static ZPackage ConfigsToPackage(IEnumerable<ConfigEntryBase>? configs = null, IEnumerable<CustomSyncedValueBase>? customValues = null, IEnumerable<PackageEntry>? packageEntries = null, bool partial = true) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown List<ConfigEntryBase> list = configs?.Where((ConfigEntryBase config) => configData(config).SynchronizedConfig).ToList() ?? new List<ConfigEntryBase>(); List<CustomSyncedValueBase> list2 = customValues?.ToList() ?? new List<CustomSyncedValueBase>(); ZPackage val = new ZPackage(); val.Write(partial ? ((byte)1) : ((byte)0)); val.Write(list.Count + list2.Count + (packageEntries?.Count() ?? 0)); foreach (PackageEntry item in packageEntries ?? Array.Empty<PackageEntry>()) { AddEntryToPackage(val, item); } foreach (CustomSyncedValueBase item2 in list2) { AddEntryToPackage(val, new PackageEntry { section = "Internal", key = item2.Identifier, type = item2.Type, value = item2.BoxedValue }); } foreach (ConfigEntryBase item3 in list) { AddEntryToPackage(val, new PackageEntry { section = item3.Definition.Section, key = item3.Definition.Key, type = configType(item3), value = item3.BoxedValue }); } return val; } private static void AddEntryToPackage(ZPackage package, PackageEntry entry) { package.Write(entry.section); package.Write(entry.key); package.Write((entry.value == null) ? "" : GetZPackageTypeString(entry.type)); AddValueToZPackage(package, entry.value); } private static string GetZPackageTypeString(Type type) { return type.AssemblyQualifiedName; } private static void AddValueToZPackage(ZPackage package, object? value) { Type type = value?.GetType(); if (value is Enum) { value = ((IConvertible)value).ToType(Enum.GetUnderlyingType(value.GetType()), CultureInfo.InvariantCulture); } else { if (value is ICollection collection) { package.Write(collection.Count); { foreach (object item in collection) { AddValueToZPackage(package, item); } return; } } if ((object)type != null && type.IsValueType && !type.IsPrimitive) { FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); package.Write(fields.Length); FieldInfo[] array = fields; foreach (FieldInfo fieldInfo in array) { package.Write(GetZPackageTypeString(fieldInfo.FieldType)); AddValueToZPackage(package, fieldInfo.GetValue(value)); } return; } } ZRpc.Serialize(new object[1] { value }, ref package); } private static object ReadValueWithTypeFromZPackage(ZPackage package, Type type) { if ((object)type != null && type.IsValueType && !type.IsPrimitive && !type.IsEnum) { FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); int num = package.ReadInt(); if (num != fields.Length) { throw new InvalidDeserializationTypeException { received = $"(field count: {num})", expected = $"(field count: {fields.Length})" }; } object uninitializedObject = FormatterServices.GetUninitializedObject(type); FieldInfo[] array = fields; foreach (FieldInfo fieldInfo in array) { string text = package.ReadString(); if (text != GetZPackageTypeString(fieldInfo.FieldType)) { throw new InvalidDeserializationTypeException { received = text, expected = GetZPackageTypeString(fieldInfo.FieldType), field = fieldInfo.Name }; } fieldInfo.SetValue(uninitializedObject, ReadValueWithTypeFromZPackage(package, fieldInfo.FieldType)); } return uninitializedObject; } if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<, >)) { int num2 = package.ReadInt(); IDictionary dictionary = (IDictionary)Activator.CreateInstance(type); Type type2 = typeof(KeyValuePair<, >).MakeGenericType(type.GenericTypeArguments); FieldInfo field = type2.GetField("key", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo field2 = type2.GetField("value", BindingFlags.Instance | BindingFlags.NonPublic); for (int j = 0; j < num2; j++) { object obj = ReadValueWithTypeFromZPackage(package, type2); dictionary.Add(field.GetValue(obj), field2.GetValue(obj)); } return dictionary; } if (type != typeof(List<string>) && type.IsGenericType) { Type type3 = typeof(ICollection<>).MakeGenericType(type.GenericTypeArguments[0]); if ((object)type3 != null && type3.IsAssignableFrom(type)) { int num3 = package.ReadInt(); object obj2 = Activator.CreateInstance(type); MethodInfo method = type3.GetMethod("Add"); for (int k = 0; k < num3; k++) { method.Invoke(obj2, new object[1] { ReadValueWithTypeFromZPackage(package, type.GenericTypeArguments[0]) }); } return obj2; } } ParameterInfo parameterInfo = (ParameterInfo)FormatterServices.GetUninitializedObject(typeof(ParameterInfo)); AccessTools.DeclaredField(typeof(ParameterInfo), "ClassImpl").SetValue(parameterInfo, type); List<object> source = new List<object>(); ZRpc.Deserialize(new ParameterInfo[2] { null, parameterInfo }, package, ref source); return source.First(); } } [PublicAPI] [HarmonyPatch] public class VersionCheck { private static readonly HashSet<VersionCheck> versionChecks; private static readonly Dictionary<string, string> notProcessedNames; public string Name; private string? displayName; private string? currentVersion; private string? minimumRequiredVersion; public bool ModRequired = true; private string? ReceivedCurrentVersion; private string? ReceivedMinimumRequiredVersion; private readonly List<ZRpc> ValidatedClients = new List<ZRpc>(); private ConfigSync? ConfigSync; public string DisplayName { get { return displayName ?? Name; } set { displayName = value; } } public string CurrentVersion { get { return currentVersion ?? "0.0.0"; } set { currentVersion = value; } } public string MinimumRequiredVersion { get { string text = minimumRequiredVersion; if (text == null) { if (!ModRequired) { return "0.0.0"; } text = CurrentVersion; } return text; } set { minimumRequiredVersion = value; } } private static void PatchServerSync() { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown Patches patchInfo = PatchProcessor.GetPatchInfo((MethodBase)AccessTools.DeclaredMethod(typeof(ZNet), "Awake", (Type[])null, (Type[])null)); if (patchInfo != null && patchInfo.Postfixes.Count((Patch p) => p.PatchMethod.DeclaringType == typeof(ConfigSync.RegisterRPCPatch)) > 0) { return; } Harmony val = new Harmony("org.bepinex.helpers.ServerSync"); foreach (Type item in from t in typeof(ConfigSync).GetNestedTypes(BindingFlags.NonPublic).Concat(new Type[1] { typeof(VersionCheck) }) where t.IsClass select t) { val.PatchAll(item); } } static VersionCheck() { versionChecks = new HashSet<VersionCheck>(); notProcessedNames = new Dictionary<string, string>(); typeof(ThreadingHelper).GetMethod("StartSyncInvoke").Invoke(ThreadingHelper.Instance, new object[1] { new Action(PatchServerSync) }); } public VersionCheck(string name) { Name = name; ModRequired = true; versionChecks.Add(this); } public VersionCheck(ConfigSync configSync) { ConfigSync = configSync; Name = ConfigSync.Name; versionChecks.Add(this); } public void Initialize() { ReceivedCurrentVersion = null; ReceivedMinimumRequiredVersion = null; if (ConfigSync != null) { Name = ConfigSync.Name; DisplayName = ConfigSync.DisplayName; CurrentVersion = ConfigSync.CurrentVersion; MinimumRequiredVersion = ConfigSync.MinimumRequiredVersion; ModRequired = ConfigSync.ModRequired; } } private bool IsVersionOk() { if (ReceivedMinimumRequiredVersion == null || ReceivedCurrentVersion == null) { return !ModRequired; } bool flag = new System.Version(CurrentVersion) >= new System.Version(ReceivedMinimumRequiredVersion); bool flag2 = new System.Version(ReceivedCurrentVersion) >= new System.Version(MinimumRequiredVersion); return flag && flag2; } private string ErrorClient() { if (ReceivedMinimumRequiredVersion == null) { return DisplayName + " is not installed on the server."; } if (!(new System.Version(CurrentVersion) >= new System.Version(ReceivedMinimumRequiredVersion))) { return DisplayName + " needs to be at least version " + ReceivedMinimumRequiredVersion + ". You have version " + CurrentVersion + "."; } return DisplayName + " may not be higher than version " + ReceivedCurrentVersion + ". You have version " + CurrentVersion + "."; } private string ErrorServer(ZRpc rpc) { return "Disconnect: The client (" + rpc.GetSocket().GetHostName() + ") doesn't have the correct " + DisplayName + " version " + MinimumRequiredVersion; } private string Error(ZRpc? rpc = null) { if (rpc != null) { return ErrorServer(rpc); } return ErrorClient(); } private static VersionCheck[] GetFailedClient() { return versionChecks.Where((VersionCheck check) => !check.IsVersionOk()).ToArray(); } private static VersionCheck[] GetFailedServer(ZRpc rpc) { return versionChecks.Where((VersionCheck check) => check.ModRequired && !check.ValidatedClients.Contains(rpc)).ToArray(); } private static void Logout() { Game.instance.Logout(true, true); AccessTools.DeclaredField(typeof(ZNet), "m_connectionStatus").SetValue(null, (object)(ConnectionStatus)3); } private static void DisconnectClient(ZRpc rpc) { rpc.Invoke("Error", new object[1] { 3 }); } private static void CheckVersion(ZRpc rpc, ZPackage pkg) { CheckVersion(rpc, pkg, null); } private static void CheckVersion(ZRpc rpc, ZPackage pkg, Action<ZRpc, ZPackage>? original) { string text = pkg.ReadString(); string text2 = pkg.ReadString(); string text3 = pkg.ReadString(); bool flag = false; foreach (VersionCheck versionCheck in versionChecks) { if (!(text != versionCheck.Name)) { Debug.Log((object)("Received " + versionCheck.DisplayName + " version " + text3 + " and minimum version " + text2 + " from the " + (ZNet.instance.IsServer() ? "client" : "server") + ".")); versionCheck.ReceivedMinimumRequiredVersion = text2; versionCheck.ReceivedCurrentVersion = text3; if (ZNet.instance.IsServer() && versionCheck.IsVersionOk()) { versionCheck.ValidatedClients.Add(rpc); } flag = true; } } if (flag) { return; } pkg.SetPos(0); if (original != null) { original(rpc, pkg); if (pkg.GetPos() == 0) { notProcessedNames.Add(text, text3); } } } [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] [HarmonyPrefix] private static bool RPC_PeerInfo(ZRpc rpc, ZNet __instance) { VersionCheck[] array = (__instance.IsServer() ? GetFailedServer(rpc) : GetFailedClient()); if (array.Length == 0) { return true; } VersionCheck[] array2 = array; foreach (VersionCheck versionCheck in array2) { Debug.LogWarning((object)versionCheck.Error(rpc)); } if (__instance.IsServer()) { DisconnectClient(rpc); } else { Logout(); } return false; } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] [HarmonyPrefix] private static void RegisterAndCheckVersion(ZNetPeer peer, ZNet __instance) { //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Expected O, but got Unknown notProcessedNames.Clear(); IDictionary dictionary = (IDictionary)typeof(ZRpc).GetField("m_functions", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(peer.m_rpc); if (dictionary.Contains(StringExtensionMethods.GetStableHashCode("ServerSync VersionCheck"))) { object obj = dictionary[StringExtensionMethods.GetStableHashCode("ServerSync VersionCheck")]; Action<ZRpc, ZPackage> action = (Action<ZRpc, ZPackage>)obj.GetType().GetField("m_action", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(obj); peer.m_rpc.Register<ZPackage>("ServerSync VersionCheck", (Action<ZRpc, ZPackage>)delegate(ZRpc rpc, ZPackage pkg) { CheckVersion(rpc, pkg, action); }); } else { peer.m_rpc.Register<ZPackage>("ServerSync VersionCheck", (Action<ZRpc, ZPackage>)CheckVersion); } foreach (VersionCheck versionCheck in versionChecks) { versionCheck.Initialize(); if (versionCheck.ModRequired || __instance.IsServer()) { Debug.Log((object)("Sending " + versionCheck.DisplayName + " version " + versionCheck.CurrentVersion + " and minimum version " + versionCheck.MinimumRequiredVersion + " to the " + (__instance.IsServer() ? "client" : "server") + ".")); ZPackage val = new ZPackage(); val.Write(versionCheck.Name); val.Write(versionCheck.MinimumRequiredVersion); val.Write(versionCheck.CurrentVersion); peer.m_rpc.Invoke("ServerSync VersionCheck", new object[1] { val }); } } } [HarmonyPatch(typeof(ZNet), "Disconnect")] [HarmonyPrefix] private static void RemoveDisconnected(ZNetPeer peer, ZNet __instance) { if (!__instance.IsServer()) { return; } foreach (VersionCheck versionCheck in versionChecks) { versionCheck.ValidatedClients.Remove(peer.m_rpc); } } [HarmonyPatch(typeof(FejdStartup), "ShowConnectError")] [HarmonyPostfix] private static void ShowConnectionError(FejdStartup __instance) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) if (!__instance.m_connectionFailedPanel.activeSelf || (int)ZNet.GetConnectionStatus() != 3) { return; } bool flag = false; VersionCheck[] failedClient = GetFailedClient(); if (failedClient.Length != 0) { string text = string.Join("\n", failedClient.Select((VersionCheck check) => check.Error())); TMP_Text connectionFailedError = __instance.m_connectionFailedError; connectionFailedError.text = connectionFailedError.text + "\n" + text; flag = true; } foreach (KeyValuePair<string, string> item in notProcessedNames.OrderBy((KeyValuePair<string, string> kv) => kv.Key)) { if (!__instance.m_connectionFailedError.text.Contains(item.Key)) { TMP_Text connectionFailedError2 = __instance.m_connectionFailedError; connectionFailedError2.text = connectionFailedError2.text + "\nServer expects you to have " + item.Key + " (Version: " + item.Value + ") installed."; flag = true; } } if (flag) { RectTransform component = ((Component)__instance.m_connectionFailedPanel.transform.Find("Image")).GetComponent<RectTransform>(); Vector2 sizeDelta = component.sizeDelta; sizeDelta.x = 675f; component.sizeDelta = sizeDelta; __instance.m_connectionFailedError.ForceMeshUpdate(false, false); float num = __instance.m_connectionFailedError.renderedHeight + 105f; RectTransform component2 = ((Component)((Component)component).transform.Find("ButtonOk")).GetComponent<RectTransform>(); component2.anchoredPosition = new Vector2(component2.anchoredPosition.x, component2.anchoredPosition.y - (num - component.sizeDelta.y) / 2f); sizeDelta = component.sizeDelta; sizeDelta.y = num; component.sizeDelta = sizeDelta; } } } } namespace LocalizationManager { [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; private static BaseUnityPlugin? _plugin; private static readonly List<string> fileExtensions; private static BaseUnityPlugin plugin { get { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: 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((TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t))); } return _plugin; } } 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, (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, Func<T, string>? convertConfigValue = null) where T : notnull { Func<T, string> convertConfigValue2 = convertConfigValue; if (convertConfigValue2 == null) { convertConfigValue2 = (T val) => val.ToString(); } if (!PlaceholderProcessors.ContainsKey(key)) { PlaceholderProcessors[key] = new Dictionary<string, Func<string>>(); } config.SettingChanged += delegate { UpdatePlaceholder(); }; if (loadedTexts.ContainsKey(Localization.instance.GetSelectedLanguage())) { UpdatePlaceholder(); } void UpdatePlaceholder() { PlaceholderProcessors[key][placeholder] = () => convertConfigValue2(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() { LoadLocalization(Localization.instance, Localization.instance.GetSelectedLanguage()); } 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 text = Path.GetFileNameWithoutExtension(item).Split(new char[1] { '.' })[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[] array = LoadTranslationFromAssembly("English"); if (array == 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."); } Dictionary<string, string> dictionary2 = new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(Encoding.UTF8.GetString(array)); 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.ContainsKey(language)) { text2 = File.ReadAllText(dictionary[language]); } else { byte[] array2 = LoadTranslationFromAssembly(language); if (array2 != null) { text2 = Encoding.UTF8.GetString(array2); } } } if (text2 == null && dictionary.ContainsKey("English")) { text2 = File.ReadAllText(dictionary["English"]); } if (text2 != null) { 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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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> { ".json", ".yml" }; Harmony val = new Harmony("org.bepinex.helpers.LocalizationManager"); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "LoadCSV", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalization", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } private static byte[]? LoadTranslationFromAssembly(string language) { foreach (string fileExtension in fileExtensions) { byte[] array = ReadEmbeddedFileBytes("translations." + language + fileExtension); if (array != null) { return array; } } return null; } public static byte[]? ReadEmbeddedFileBytes(string resourceFileName, Assembly? containingAssembly = null) { using MemoryStream memoryStream = new MemoryStream(); if ((object)containingAssembly == null) { containingAssembly = Assembly.GetCallingAssembly(); } string text = containingAssembly.GetManifestResourceNames().FirstOrDefault((string str) => str.EndsWith(resourceFileName, StringComparison.Ordinal)); if (text != null) { containingAssembly.GetManifestResourceStream(text)?.CopyTo(memoryStream); } return (memoryStream.Length == 0L) ? null : memoryStream.ToArray(); } } } namespace VandemUI { public static class RectTransformExtensions { public enum ElementAnchor { TopLeft, Top, TopRight, Right, BottomRight, Bottom, BottomLeft, Left, Middle } public static void SetAnchor(this RectTransform rectTransform, ElementAnchor anchor) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) switch (anchor) { case ElementAnchor.TopLeft: rectTransform.anchorMin = new Vector2(0f, 1f); rectTransform.anchorMax = new Vector2(0f, 1f); break; case ElementAnchor.Top: rectTransform.anchorMin = new Vector2(0.5f, 1f); rectTransform.anchorMax = new Vector2(0.5f, 1f); break; case ElementAnchor.TopRight: rectTransform.anchorMin = new Vector2(1f, 1f); rectTransform.anchorMax = new Vector2(1f, 1f); break; case ElementAnchor.Right: rectTransform.anchorMin = new Vector2(1f, 0.5f); rectTransform.anchorMax = new Vector2(1f, 0.5f); break; case ElementAnchor.BottomRight: rectTransform.anchorMin = new Vector2(1f, 0f); rectTransform.anchorMax = new Vector2(1f, 0f); break; case ElementAnchor.Bottom: rectTransform.anchorMin = new Vector2(0.5f, 0f); rectTransform.anchorMax = new Vector2(0.5f, 0f); break; case ElementAnchor.BottomLeft: rectTransform.anchorMin = new Vector2(0f, 0f); rectTransform.anchorMax = new Vector2(0f, 0f); break; case ElementAnchor.Left: rectTransform.anchorMin = new Vector2(0f, 0.5f); rectTransform.anchorMax = new Vector2(0f, 0.5f); break; case ElementAnchor.Middle: rectTransform.anchorMin = new Vector2(0.5f, 0.5f); rectTransform.anchorMax = new Vector2(0.5f, 0.5f); break; default: throw new ArgumentOutOfRangeException("anchor", anchor, null); } } } public class Marker { private const string base64 = "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