Decompiled source of Vanity v1.16.0
Vanity.dll
Decompiled 3 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.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using JetBrains.Annotations; using Microsoft.CodeAnalysis; using ServerSync; using Service; using TMPro; using UnityEngine; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Core.Tokens; using YamlDotNet.Helpers; using YamlDotNet.Serialization; 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: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("Vanity")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+a870dea9a7039e76f5cb933eee81d00882f12c98")] [assembly: AssemblyProduct("Vanity")] [assembly: AssemblyTitle("Vanity")] [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; } } } namespace Service { public class Watcher { private static readonly Dictionary<string, byte[]> hashes = new Dictionary<string, byte[]>(); private static byte[] GetHash(string path) { using MD5 mD = MD5.Create(); using FileStream inputStream = File.OpenRead(path); return mD.ComputeHash(inputStream); } public static void Setup(string folder, string pattern, Action action) { Action action2 = action; FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(folder, pattern); fileSystemWatcher.Changed += delegate(object s, FileSystemEventArgs e) { byte[] hash = GetHash(e.FullPath); if (!hashes.ContainsKey(e.FullPath) || !hashes[e.FullPath].SequenceEqual(hash)) { hashes[e.FullPath] = hash; action2(); } }; fileSystemWatcher.IncludeSubdirectories = true; fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher.EnableRaisingEvents = true; } public static void Setup(string file, Action action) { string fileName = Path.GetFileName(file); Setup(Paths.ConfigPath, fileName, action); } public static void Setup(ConfigFile config, ManualLogSource logger) { ConfigFile config2 = config; ManualLogSource logger2 = logger; string configFilePath = config2.ConfigFilePath; string directoryName = Path.GetDirectoryName(configFilePath); string fileName = Path.GetFileName(configFilePath); Setup(directoryName, fileName, delegate { if (!File.Exists(config2.ConfigFilePath)) { return; } try { logger2.LogDebug((object)"ReadConfigValues called"); config2.Reload(); } catch { logger2.LogError((object)("There was an issue loading your " + config2.ConfigFilePath)); logger2.LogError((object)"Please check your config entries for spelling and format!"); } }); } } } namespace Vanity { [HarmonyPatch(typeof(Player), "LateUpdate")] public class ColorCycle { private const float TickLength = 0.02f; private static int Ticks; private static int SecondsToTicks(float value) { return (int)(value / 0.02f); } private static Color GetColor(Color[] colors) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) if (colors.Length < 2) { return colors[0]; } int num = SecondsToTicks(VanityManager.ColorDuration); if (num == 0) { return colors[0]; } float num2 = (float)(Ticks % (num * colors.Length)) / (float)num; int num3 = (int)Math.Floor(num2); Color val = colors[num3]; int num4 = (int)Math.Ceiling(num2); if (num4 >= colors.Length) { num4 = 0; } Color val2 = colors[num4]; float num5 = num2 - (float)Math.Truncate(num2); return Color.Lerp(val, val2, num5); } private static void UpdateSkinColor(Player obj) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) Color color = GetColor(VanityManager.GetSkinColors(obj)); VanityManager.SkinColor = color; ((Humanoid)obj).m_visEquipment.SetSkinColor(Vector3.zero); } private static void UpdateHairColor(Player obj) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) Color color = GetColor(VanityManager.GetHairColors(obj)); VanityManager.HairColor = color; ((Humanoid)obj).m_visEquipment.SetHairColor(Vector3.zero); } private static void Postfix(Player __instance) { if (Helper.IsLocalPlayer(__instance)) { Ticks++; int num = SecondsToTicks(VanityManager.ColorUpdateInterval); if (Ticks % num == 0) { UpdateSkinColor(__instance); UpdateHairColor(__instance); } } } } public class ChangeEquipment : MonoBehaviour { [CompilerGenerated] private static class <>O { public static ConsoleEvent <0>__SetIntervalValue; public static ConsoleEvent <1>__SetDurationValue; } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static Func<string, bool> <>9__6_0; public static Func<string, bool> <>9__7_0; public static Func<string, bool> <>9__7_1; public static Func<int, List<string>> <>9__13_0; public static Func<int, List<string>> <>9__13_1; public static Func<int, List<string>> <>9__14_1; public static Func<int, List<string>> <>9__15_0; public static Func<int, List<string>> <>9__15_1; public static ConsoleOptionsFetcher <>9__16_1; public static ConsoleEvent <>9__17_0; public static ConsoleEvent <>9__17_1; public static ConsoleEvent <>9__17_2; public static ConsoleEvent <>9__17_3; public static ConsoleEvent <>9__17_4; public static ConsoleOptionsFetcher <>9__17_5; public static ConsoleEvent <>9__17_6; public static ConsoleOptionsFetcher <>9__17_7; public static ConsoleEvent <>9__17_8; public static ConsoleOptionsFetcher <>9__17_9; public static ConsoleEvent <>9__17_10; public static ConsoleOptionsFetcher <>9__17_11; public static ConsoleEvent <>9__17_12; public static ConsoleOptionsFetcher <>9__17_13; internal bool <AddPlayerId>b__6_0(string s) { return s.StartsWith("player=", StringComparison.OrdinalIgnoreCase); } internal bool <Parse>b__7_0(string s) { return s.StartsWith("player=", StringComparison.OrdinalIgnoreCase); } internal bool <Parse>b__7_1(string s) { return !s.StartsWith("player=", StringComparison.OrdinalIgnoreCase); } internal List<string> <RegisterGearAutoComplete>b__13_0(int index) { return index switch { 0 => ObjectData.Items, 1 => ObjectData.Items, 2 => CommandWrapper.Info("Item variant (number)."), _ => new List<string>(1) { "player" }, }; } internal List<string> <RegisterGearAutoComplete>b__13_1(int index) { if (index != 0) { return null; } return Helper.Players(); } internal List<string> <RegisterAutoComplete>b__14_1(int index) { if (index != 0) { return null; } return Helper.Players(); } internal List<string> <RegisterColorAutoComplete>b__15_0(int index) { return CommandWrapper.Info("Color (r,g,b)"); } internal List<string> <RegisterColorAutoComplete>b__15_1(int index) { if (index != 0) { return null; } return Helper.Players(); } internal List<string> <CreateCommand>b__16_1() { return ObjectData.Items; } internal void <AddChangeEquipment>b__17_0(ConsoleEventArgs args) { if (!((Object)(object)Player.m_localPlayer == (Object)null)) { VisEquipment component = ((Component)Player.m_localPlayer).GetComponent<VisEquipment>(); if (!((Object)(object)component == (Object)null)) { args.Context.AddString("Helmet: " + component.m_helmetItem); args.Context.AddString("Shoulder: " + component.m_shoulderItem); args.Context.AddString("Chest: " + component.m_chestItem); args.Context.AddString("Leg: " + component.m_legItem); args.Context.AddString("Utility: " + component.m_utilityItem); args.Context.AddString("Left hand: " + component.m_leftItem); args.Context.AddString("Right hand: " + component.m_rightItem); args.Context.AddString("Left back: " + component.m_leftBackItem); args.Context.AddString("Right back: " + component.m_rightBackItem); args.Context.AddString("Hair: " + component.m_hairItem); args.Context.AddString("Beard: " + component.m_beardItem); args.Context.AddString("Skin: " + ((Vector3)(ref component.m_skinColor)).ToString("F2")); args.Context.AddString("Hair color: " + ((Vector3)(ref component.m_hairColor)).ToString("F2")); } } } internal void <AddChangeEquipment>b__17_1(ConsoleEventArgs args) { string[] args2 = AddPlayerId(args); if (Vanity.ConfigSync.IsSourceOfTruth) { Parse(args2, out string id); VanityEntry entry = GetEntry(id); Set(entry, (VisSlot)2, ""); Set(entry, (VisSlot)3, ""); Set(entry, (VisSlot)9, ""); Set(entry, (VisSlot)4, ""); Set(entry, (VisSlot)10, ""); Set(entry, (VisSlot)0, ""); Set(entry, (VisSlot)1, ""); Set(entry, (VisSlot)6, ""); Set(entry, (VisSlot)6, ""); Set(entry, (VisSlot)5, ""); Set(entry, (VisSlot)7, ""); Set(entry, (VisSlot)8, ""); Set(entry, (VisSlot)8, ""); SetColor(entry, (VisSlot)10, ""); SetColor(entry, (VisSlot)5, ""); VanityData.ToFile(); } else { ServerExecution.Send((IEnumerable<string>)args2); } } internal void <AddChangeEquipment>b__17_2(ConsoleEventArgs args) { SetColorValue((VisSlot)5, args); } internal void <AddChangeEquipment>b__17_3(ConsoleEventArgs args) { SetColorValue((VisSlot)10, args); } internal void <AddChangeEquipment>b__17_4(ConsoleEventArgs args) { SetVisualValue((VisSlot)9, args); } internal List<string> <AddChangeEquipment>b__17_5() { return ObjectData.Beards; } internal void <AddChangeEquipment>b__17_6(ConsoleEventArgs args) { SetVisualValue((VisSlot)10, args); } internal List<string> <AddChangeEquipment>b__17_7() { return ObjectData.Hairs; } internal void <AddChangeEquipment>b__17_8(ConsoleEventArgs args) { string[] args2 = AddPlayerId(args); string id; string[] array = Parse(args2, out id); if (array.Length < 2) { return; } VanityEntry entry = GetEntry(id); if (entry.gear.TryGetValue(array[1], out string value)) { UndoCommands.Push(array[0] + " " + array[1] + " " + value); } else { UndoCommands.Push(array[0] + " " + array[1]); } if (Vanity.ConfigSync.IsSourceOfTruth) { if (array.Length == 2) { entry.gear.Remove(array[1]); } else { entry.gear[args[1]] = string.Join(" ", array.Skip(2)); } VanityData.ToFile(); } else { ServerExecution.Send((IEnumerable<string>)args2); } } internal List<string> <AddChangeEquipment>b__17_9() { return ObjectData.Items; } internal void <AddChangeEquipment>b__17_10(ConsoleEventArgs args) { string[] args2 = AddPlayerId(args); string id; string[] array = Parse(args2, out id); VanityEntry entry = GetEntry(id); if (entry.crafted.TryGetValue(array[1], out string value)) { UndoCommands.Push(array[0] + " " + array[1] + " " + value); } else { UndoCommands.Push(array[0] + " " + array[1]); } if (Vanity.ConfigSync.IsSourceOfTruth) { entry.crafted[array[1]] = string.Join(" ", array.Skip(2)); VanityData.ToFile(); } else { ServerExecution.Send((IEnumerable<string>)args2); } } internal List<string> <AddChangeEquipment>b__17_11() { return ObjectData.Items; } internal void <AddChangeEquipment>b__17_12(ConsoleEventArgs args) { if (UndoCommands.Count == 0) { args.Context.AddString("Nothing to undo."); return; } string text = UndoCommands.Pop(); args.Context.TryRunCommand(text, false, false); if (UndoCommands.Count > 0) { UndoCommands.Pop(); } } internal List<string> <AddChangeEquipment>b__17_13() { return ObjectData.Items; } } private static readonly Stack<string> UndoCommands = new Stack<string>(); private static string Get(VanityEntry entry, VisSlot slot) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected I4, but got Unknown return (int)slot switch { 2 => entry.leftBack, 3 => entry.rightBack, 9 => entry.beard, 4 => entry.chest, 10 => entry.hair, 0 => entry.leftHand, 1 => entry.rightHand, 6 => entry.helmet, 5 => entry.legs, 7 => entry.shoulder, 8 => entry.utility, _ => throw new NotImplementedException(), }; } private static string GetColor(VanityEntry entry, VisSlot slot) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)slot != 5) { if ((int)slot == 10) { return entry.hairColor; } throw new NotImplementedException(); } return entry.skinColor; } private static void Set(VanityEntry entry, VisSlot slot, string value) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected I4, but got Unknown switch ((int)slot) { case 2: entry.leftBack = value; break; case 3: entry.rightBack = value; break; case 9: entry.beard = value; break; case 4: entry.chest = value; break; case 10: entry.hair = value; break; case 0: entry.leftHand = value; break; case 1: entry.rightHand = value; break; case 6: entry.helmet = value; break; case 5: entry.legs = value; break; case 7: entry.shoulder = value; break; case 8: entry.utility = value; break; default: throw new NotImplementedException(); } } private static void SetColor(VanityEntry entry, VisSlot slot, string value) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)slot != 5) { if ((int)slot == 10) { entry.hairColor = value; } } else { entry.skinColor = value; } } private static VanityEntry GetEntry(string id) { VanityEntry vanityEntry = new VanityEntry(); if (VanityData.Data.TryGetValue(id, out VanityEntry value)) { vanityEntry = value; } else { VanityData.Data[id] = vanityEntry; } return vanityEntry; } private static string[] AddPlayerId(ConsoleEventArgs args) { if (string.IsNullOrEmpty(args.Args.FirstOrDefault((string s) => s.StartsWith("player=", StringComparison.OrdinalIgnoreCase)))) { return args.Args.Append("player=" + Helper.GetPlayerID()).ToArray(); } return args.Args; } private static string[] Parse(string[] args, out string id) { id = ""; string text = args.FirstOrDefault((string s) => s.StartsWith("player=", StringComparison.OrdinalIgnoreCase)); if (text == null) { return args; } string[] array = text.Split(new char[1] { '=' }); string[] result = args.Where((string s) => !s.StartsWith("player=", StringComparison.OrdinalIgnoreCase)).ToArray(); if (array.Length < 2) { throw new InvalidOperationException("Missing player id"); } if (long.TryParse(array[1], out var result2)) { id = result2.ToString(); return result; } id = Helper.GetPlayerID(array[1]); return result; } private static void SetVisualValue(VisSlot slot, ConsoleEventArgs args) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) string[] args2 = AddPlayerId(args); string id; string[] array = Parse(args2, out id); string value = string.Join(" ", array.Skip(1)); VanityEntry entry = GetEntry(id); string text = Get(entry, slot); UndoCommands.Push(array[0] + " " + text); if (Vanity.ConfigSync.IsSourceOfTruth) { Set(entry, slot, value); VanityData.ToFile(); } else { ServerExecution.Send((IEnumerable<string>)args2); } } private static void SetColorValue(VisSlot slot, ConsoleEventArgs args) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) string[] args2 = AddPlayerId(args); string id; string[] array = Parse(args2, out id); string value = string.Join(" ", array.Skip(1)).Replace(", ", ","); VanityEntry entry = GetEntry(id); string color = GetColor(entry, slot); UndoCommands.Push(array[0] + " " + color); if (Vanity.ConfigSync.IsSourceOfTruth) { SetColor(entry, slot, value); VanityData.ToFile(); } else { ServerExecution.Send((IEnumerable<string>)args2); } } private static void SetDurationValue(ConsoleEventArgs args) { string[] args2 = AddPlayerId(args); string id; string[] array = Parse(args2, out id); float value = Helper.TryFloat(string.Join(" ", array.Skip(1))); VanityEntry entry = GetEntry(id); Stack<string> undoCommands = UndoCommands; string obj = array[0]; float? colorDuration = entry.colorDuration; undoCommands.Push(obj + " " + colorDuration); if (Vanity.ConfigSync.IsSourceOfTruth) { entry.colorDuration = value; VanityData.ToFile(); } else { ServerExecution.Send((IEnumerable<string>)args2); } } private static void SetIntervalValue(ConsoleEventArgs args) { string[] args2 = AddPlayerId(args); string id; string[] array = Parse(args2, out id); float value = Helper.TryFloat(string.Join(" ", array.Skip(1))); VanityEntry entry = GetEntry(id); Stack<string> undoCommands = UndoCommands; string obj = array[0]; float? updateInterval = entry.updateInterval; undoCommands.Push(obj + " " + updateInterval); if (Vanity.ConfigSync.IsSourceOfTruth) { entry.updateInterval = value; VanityData.ToFile(); } else { ServerExecution.Send((IEnumerable<string>)args2); } } private static string SlotToString(VisSlot slot) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected I4, but got Unknown return (int)slot switch { 2 => "back_left", 3 => "back_right", 9 => "beard", 4 => "chest", 10 => "hair", 0 => "left", 1 => "right", 6 => "helmet", 5 => "legs", 7 => "shoulder", 8 => "utility", _ => throw new NotImplementedException(), }; } private static void RegisterGearAutoComplete(string name) { CommandWrapper.Register(name, (int index) => index switch { 0 => ObjectData.Items, 1 => ObjectData.Items, 2 => CommandWrapper.Info("Item variant (number)."), _ => new List<string>(1) { "player" }, }, new Dictionary<string, Func<int, List<string>>> { { "player", (int index) => (index != 0) ? null : Helper.Players() } }); } private static void RegisterAutoComplete(string name, bool variant = true) { CommandWrapper.Register(name, delegate(int index) { if (index == 0) { return ObjectData.Items; } return (index == 1 && variant) ? CommandWrapper.Info("Item variant (number).") : new List<string>(1) { "player" }; }, new Dictionary<string, Func<int, List<string>>> { { "player", (int index) => (index != 0) ? null : Helper.Players() } }); } private static void RegisterColorAutoComplete(string name) { CommandWrapper.Register(name, (int index) => CommandWrapper.Info("Color (r,g,b)"), new Dictionary<string, Func<int, List<string>>> { { "player", (int index) => (index != 0) ? null : Helper.Players() } }); } private static void CreateCommand(VisSlot slot) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected O, but got Unknown //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown RegisterAutoComplete("wear_" + SlotToString(slot)); string text = "wear_" + SlotToString(slot); ConsoleEvent val = delegate(ConsoleEventArgs args) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) SetVisualValue(slot, args); }; object obj = <>c.<>9__16_1; if (obj == null) { ConsoleOptionsFetcher val2 = () => ObjectData.Items; <>c.<>9__16_1 = val2; obj = (object)val2; } new ConsoleCommand(text, "[item name] [variant = 0] - Changes visual equipment.", val, false, false, false, false, false, (ConsoleOptionsFetcher)obj, false, false, false); } public static void AddChangeEquipment() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Expected O, but got Unknown //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Expected O, but got Unknown //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Expected O, but got Unknown //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Expected O, but got Unknown //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Expected O, but got Unknown //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_01e9: Expected O, but got Unknown //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Expected O, but got Unknown //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Expected O, but got Unknown //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Expected O, but got Unknown //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Unknown result type (might be due to invalid IL or missing references) //IL_029f: Expected O, but got Unknown //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_02bd: Unknown result type (might be due to invalid IL or missing references) //IL_02c3: Expected O, but got Unknown //IL_0330: Unknown result type (might be due to invalid IL or missing references) //IL_031c: Unknown result type (might be due to invalid IL or missing references) //IL_0321: Unknown result type (might be due to invalid IL or missing references) //IL_0327: Expected O, but got Unknown //IL_0364: Unknown result type (might be due to invalid IL or missing references) //IL_0350: Unknown result type (might be due to invalid IL or missing references) //IL_0355: Unknown result type (might be due to invalid IL or missing references) //IL_035b: Expected O, but got Unknown object obj = <>c.<>9__17_0; if (obj == null) { ConsoleEvent val = delegate(ConsoleEventArgs args) { if (!((Object)(object)Player.m_localPlayer == (Object)null)) { VisEquipment component = ((Component)Player.m_localPlayer).GetComponent<VisEquipment>(); if (!((Object)(object)component == (Object)null)) { args.Context.AddString("Helmet: " + component.m_helmetItem); args.Context.AddString("Shoulder: " + component.m_shoulderItem); args.Context.AddString("Chest: " + component.m_chestItem); args.Context.AddString("Leg: " + component.m_legItem); args.Context.AddString("Utility: " + component.m_utilityItem); args.Context.AddString("Left hand: " + component.m_leftItem); args.Context.AddString("Right hand: " + component.m_rightItem); args.Context.AddString("Left back: " + component.m_leftBackItem); args.Context.AddString("Right back: " + component.m_rightBackItem); args.Context.AddString("Hair: " + component.m_hairItem); args.Context.AddString("Beard: " + component.m_beardItem); args.Context.AddString("Skin: " + ((Vector3)(ref component.m_skinColor)).ToString("F2")); args.Context.AddString("Hair color: " + ((Vector3)(ref component.m_hairColor)).ToString("F2")); } } }; <>c.<>9__17_0 = val; obj = (object)val; } new ConsoleCommand("wear_info", "Prints information about visual equipment.", (ConsoleEvent)obj, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj2 = <>c.<>9__17_1; if (obj2 == null) { ConsoleEvent val2 = delegate(ConsoleEventArgs args) { string[] args4 = AddPlayerId(args); if (Vanity.ConfigSync.IsSourceOfTruth) { Parse(args4, out string id3); VanityEntry entry3 = GetEntry(id3); Set(entry3, (VisSlot)2, ""); Set(entry3, (VisSlot)3, ""); Set(entry3, (VisSlot)9, ""); Set(entry3, (VisSlot)4, ""); Set(entry3, (VisSlot)10, ""); Set(entry3, (VisSlot)0, ""); Set(entry3, (VisSlot)1, ""); Set(entry3, (VisSlot)6, ""); Set(entry3, (VisSlot)6, ""); Set(entry3, (VisSlot)5, ""); Set(entry3, (VisSlot)7, ""); Set(entry3, (VisSlot)8, ""); Set(entry3, (VisSlot)8, ""); SetColor(entry3, (VisSlot)10, ""); SetColor(entry3, (VisSlot)5, ""); VanityData.ToFile(); } else { ServerExecution.Send((IEnumerable<string>)args4); } }; <>c.<>9__17_1 = val2; obj2 = (object)val2; } new ConsoleCommand("wear_reset", "Resets visual equipment.", (ConsoleEvent)obj2, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); RegisterColorAutoComplete("wear_skin_color"); object obj3 = <>c.<>9__17_2; if (obj3 == null) { ConsoleEvent val3 = delegate(ConsoleEventArgs args) { SetColorValue((VisSlot)5, args); }; <>c.<>9__17_2 = val3; obj3 = (object)val3; } new ConsoleCommand("wear_skin_color", "[r1,g1,b1] [r2,g2,b2] ... - Changes skin color. Automatically cycles between multiple values.", (ConsoleEvent)obj3, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); RegisterColorAutoComplete("wear_hair_color"); object obj4 = <>c.<>9__17_3; if (obj4 == null) { ConsoleEvent val4 = delegate(ConsoleEventArgs args) { SetColorValue((VisSlot)10, args); }; <>c.<>9__17_3 = val4; obj4 = (object)val4; } new ConsoleCommand("wear_hair_color", "[r1,g1,b1] [r2,g2,b2] ... - Changes hair color. Automatically cycles between multiple values.", (ConsoleEvent)obj4, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); RegisterAutoComplete("wear_beard", variant: false); object obj5 = <>c.<>9__17_4; if (obj5 == null) { ConsoleEvent val5 = delegate(ConsoleEventArgs args) { SetVisualValue((VisSlot)9, args); }; <>c.<>9__17_4 = val5; obj5 = (object)val5; } object obj6 = <>c.<>9__17_5; if (obj6 == null) { ConsoleOptionsFetcher val6 = () => ObjectData.Beards; <>c.<>9__17_5 = val6; obj6 = (object)val6; } new ConsoleCommand("wear_beard", "[name] - Changes beard.", (ConsoleEvent)obj5, false, false, false, false, false, (ConsoleOptionsFetcher)obj6, false, false, false); RegisterAutoComplete("wear_hair", variant: false); object obj7 = <>c.<>9__17_6; if (obj7 == null) { ConsoleEvent val7 = delegate(ConsoleEventArgs args) { SetVisualValue((VisSlot)10, args); }; <>c.<>9__17_6 = val7; obj7 = (object)val7; } object obj8 = <>c.<>9__17_7; if (obj8 == null) { ConsoleOptionsFetcher val8 = () => ObjectData.Hairs; <>c.<>9__17_7 = val8; obj8 = (object)val8; } new ConsoleCommand("wear_hair", "[name] - Changes hair.", (ConsoleEvent)obj7, false, false, false, false, false, (ConsoleOptionsFetcher)obj8, false, false, false); RegisterGearAutoComplete("wear_gear"); object obj9 = <>c.<>9__17_8; if (obj9 == null) { ConsoleEvent val9 = delegate(ConsoleEventArgs args) { string[] args3 = AddPlayerId(args); string id2; string[] array2 = Parse(args3, out id2); if (array2.Length >= 2) { VanityEntry entry2 = GetEntry(id2); if (entry2.gear.TryGetValue(array2[1], out string value2)) { UndoCommands.Push(array2[0] + " " + array2[1] + " " + value2); } else { UndoCommands.Push(array2[0] + " " + array2[1]); } if (Vanity.ConfigSync.IsSourceOfTruth) { if (array2.Length == 2) { entry2.gear.Remove(array2[1]); } else { entry2.gear[args[1]] = string.Join(" ", array2.Skip(2)); } VanityData.ToFile(); } else { ServerExecution.Send((IEnumerable<string>)args3); } } }; <>c.<>9__17_8 = val9; obj9 = (object)val9; } object obj10 = <>c.<>9__17_9; if (obj10 == null) { ConsoleOptionsFetcher val10 = () => ObjectData.Items; <>c.<>9__17_9 = val10; obj10 = (object)val10; } new ConsoleCommand("wear_gear", "[item name] [visual name] [variant = 0] - Changes visual of a specific gear.", (ConsoleEvent)obj9, false, false, false, false, false, (ConsoleOptionsFetcher)obj10, false, false, false); RegisterGearAutoComplete("wear_crafted"); object obj11 = <>c.<>9__17_10; if (obj11 == null) { ConsoleEvent val11 = delegate(ConsoleEventArgs args) { string[] args2 = AddPlayerId(args); string id; string[] array = Parse(args2, out id); VanityEntry entry = GetEntry(id); if (entry.crafted.TryGetValue(array[1], out string value)) { UndoCommands.Push(array[0] + " " + array[1] + " " + value); } else { UndoCommands.Push(array[0] + " " + array[1]); } if (Vanity.ConfigSync.IsSourceOfTruth) { entry.crafted[array[1]] = string.Join(" ", array.Skip(2)); VanityData.ToFile(); } else { ServerExecution.Send((IEnumerable<string>)args2); } }; <>c.<>9__17_10 = val11; obj11 = (object)val11; } object obj12 = <>c.<>9__17_11; if (obj12 == null) { ConsoleOptionsFetcher val12 = () => ObjectData.Items; <>c.<>9__17_11 = val12; obj12 = (object)val12; } new ConsoleCommand("wear_crafted", "[item name] [visual name] [variant = 0] - Changes visual of a specific gear.", (ConsoleEvent)obj11, false, false, false, false, false, (ConsoleOptionsFetcher)obj12, false, false, false); object obj13 = <>c.<>9__17_12; if (obj13 == null) { ConsoleEvent val13 = delegate(ConsoleEventArgs args) { if (UndoCommands.Count == 0) { args.Context.AddString("Nothing to undo."); } else { string text = UndoCommands.Pop(); args.Context.TryRunCommand(text, false, false); if (UndoCommands.Count > 0) { UndoCommands.Pop(); } } }; <>c.<>9__17_12 = val13; obj13 = (object)val13; } object obj14 = <>c.<>9__17_13; if (obj14 == null) { ConsoleOptionsFetcher val14 = () => ObjectData.Items; <>c.<>9__17_13 = val14; obj14 = (object)val14; } new ConsoleCommand("wear_undo", "Reverts wear commands.", (ConsoleEvent)obj13, false, false, false, false, false, (ConsoleOptionsFetcher)obj14, false, false, false); CreateCommand((VisSlot)2); CreateCommand((VisSlot)3); CreateCommand((VisSlot)4); CreateCommand((VisSlot)0); CreateCommand((VisSlot)1); CreateCommand((VisSlot)6); CreateCommand((VisSlot)5); CreateCommand((VisSlot)7); CreateCommand((VisSlot)8); object obj15 = <>O.<0>__SetIntervalValue; if (obj15 == null) { ConsoleEvent val15 = SetIntervalValue; <>O.<0>__SetIntervalValue = val15; obj15 = (object)val15; } new ConsoleCommand("wear_color_interval", "Sets the color update interval.", (ConsoleEvent)obj15, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj16 = <>O.<1>__SetDurationValue; if (obj16 == null) { ConsoleEvent val16 = SetDurationValue; <>O.<1>__SetDurationValue = val16; obj16 = (object)val16; } new ConsoleCommand("wear_color_duration", "Sets the color duration.", (ConsoleEvent)obj16, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } } public static class CommandWrapper { public static Assembly ServerDevcommands = null; private const string GUID = "server_devcommands"; private static readonly BindingFlags PublicBinding = BindingFlags.Static | BindingFlags.Public; public static void Init() { if (Chainloader.PluginInfos.TryGetValue("server_devcommands", out var value)) { ServerDevcommands = ((object)value.Instance).GetType().Assembly; } } private static Type Type() { return ServerDevcommands.GetType("ServerDevcommands.AutoComplete"); } private static Type InfoType() { return ServerDevcommands.GetType("ServerDevcommands.ParameterInfo"); } private static MethodInfo GetMethod(Type type, string name, Type[] types) { return type.GetMethod(name, PublicBinding, null, CallingConventions.Standard, types, null); } public static void Register(string command, Func<int, int, List<string>> action) { if (!(ServerDevcommands == null)) { GetMethod(Type(), "Register", new Type[2] { typeof(string), typeof(Func<int, int, List<string>>) }).Invoke(null, new object[2] { command, action }); } } public static void Register(string command, Func<int, List<string>> action) { if (!(ServerDevcommands == null)) { GetMethod(Type(), "Register", new Type[2] { typeof(string), typeof(Func<int, List<string>>) }).Invoke(null, new object[2] { command, action }); } } public static void Register(string command, Func<int, List<string>> action, Dictionary<string, Func<int, List<string>>> named) { if (!(ServerDevcommands == null)) { GetMethod(Type(), "Register", new Type[3] { typeof(string), typeof(Func<int, List<string>>), typeof(Dictionary<string, Func<int, List<string>>>) }).Invoke(null, new object[3] { command, action, named }); } } public static List<string> Info(string value) { if (ServerDevcommands == null) { return new List<string>(); } return GetMethod(InfoType(), "Create", new Type[1] { typeof(string) }).Invoke(null, new object[1] { value }) as List<string>; } public static List<string> XZ(string name, string description, int index) { if (ServerDevcommands == null) { return new List<string>(); } return GetMethod(InfoType(), "XZ", new Type[3] { typeof(string), typeof(string), typeof(int) }).Invoke(null, new object[3] { name, description, index }) as List<string>; } public static List<string> Flag(string name, string description) { if (ServerDevcommands == null) { return new List<string>(); } return GetMethod(InfoType(), "Flag", new Type[2] { typeof(string), typeof(string) }).Invoke(null, new object[2] { name, description }) as List<string>; } public static List<string> ObjectIds() { if (ServerDevcommands == null) { return new List<string>(); } return InfoType().GetProperty("ObjectIds", PublicBinding).GetValue(null) as List<string>; } public static List<string> LocationIds() { if (ServerDevcommands == null) { return new List<string>(); } return InfoType().GetProperty("LocationIds", PublicBinding).GetValue(null) as List<string>; } public static void RegisterEmpty(string command) { if (!(ServerDevcommands == null)) { MethodInfo? method = Type().GetMethod("RegisterEmpty", PublicBinding); object[] parameters = new string[1] { command }; method.Invoke(null, parameters); } } } [HarmonyPatch(typeof(ObjectDB), "Awake")] public class ObjectDB_Awake { private static void Postfix(ObjectDB __instance) { ObjectData.Beards = (from item in __instance.GetAllItems((ItemType)10, "Beard") select ((Object)item).name).ToList(); ObjectData.Hairs = (from item in __instance.GetAllItems((ItemType)10, "Hair") select ((Object)item).name).ToList(); ObjectData.Items = __instance.m_items.Select((GameObject item) => ((Object)item).name).ToList(); } } public class ObjectData { public static List<string> Beards = new List<string>(); public static List<string> Hairs = new List<string>(); public static List<string> Items = new List<string>(); } public class VanityEntry { [DefaultValue("")] public string name = ""; [DefaultValue("")] public string player = ""; [DefaultValue("")] public string group = ""; [DefaultValue("")] public string helmet = ""; [DefaultValue("")] public string chest = ""; [DefaultValue("")] public string shoulder = ""; [DefaultValue("")] public string legs = ""; [DefaultValue("")] public string utility = ""; [DefaultValue("")] public string leftHand = ""; [DefaultValue("")] public string rightHand = ""; [DefaultValue("")] public string leftBack = ""; [DefaultValue("")] public string rightBack = ""; [DefaultValue("")] public string beard = ""; [DefaultValue("")] public string hair = ""; [DefaultValue("")] public string skinColor = ""; [DefaultValue("")] public string hairColor = ""; [DefaultValue(null)] public float? updateInterval; [DefaultValue(null)] public float? colorDuration; public Dictionary<string, string> gear = new Dictionary<string, string>(); public Dictionary<string, string> crafted = new Dictionary<string, string>(); } public class VanityInfo { public Dictionary<string, Tuple<string, int>> gear = new Dictionary<string, Tuple<string, int>>(); public Tuple<string, int>? helmet; public Tuple<string, int>? chest; public Tuple<string, int>? legs; public Tuple<string, int>? shoulder; public Tuple<string, int>? utility; public Tuple<string, int>? leftHand; public Tuple<string, int>? rightHand; public Tuple<string, int>? leftBack; public Tuple<string, int>? rightBack; public Tuple<string, int>? beard; public Tuple<string, int>? hair; public string skinColor = ""; public string hairColor = ""; public float? updateInterval; public float? colorDuration; } public class VanityData { public static Dictionary<string, VanityEntry> Data = new Dictionary<string, VanityEntry>(); public static Dictionary<string, string> PlayerIds = new Dictionary<string, string>(); public static string FileName = "vanity.yaml"; public static string FilePath = Path.Combine(Paths.ConfigPath, FileName); public static void CreateFile() { if (!File.Exists(FilePath)) { File.WriteAllText(FilePath, ""); } } public static void ToFile() { if (Vanity.ConfigSync.IsSourceOfTruth) { string contents = Serializer().Serialize(Data); File.WriteAllText(FilePath, contents); } } public static void FromFile() { if (Vanity.ConfigSync.IsSourceOfTruth) { Vanity.VanityValue.Value = File.ReadAllText(FilePath); } } public static void FromValue(string value) { Data = Deserialize<Dictionary<string, VanityEntry>>(value, "Data") ?? new Dictionary<string, VanityEntry>(); PlayerIds.Clear(); foreach (KeyValuePair<string, VanityEntry> datum in Data) { if (!string.IsNullOrEmpty(datum.Value.name)) { PlayerIds[datum.Value.name] = datum.Key; } } VanityManager.Load(); Vanity.Log.LogInfo((object)$"Reloading {Data.Count} vanity data."); } public static void SetupWatcher() { Watcher.Setup(FileName, FromFile); } public static IDeserializer Deserializer() { return new DeserializerBuilder().WithNamingConvention(CamelCaseNamingConvention.Instance).WithTypeConverter(new FloatConverter()).Build(); } public static IDeserializer DeserializerUnSafe() { return new DeserializerBuilder().WithNamingConvention(CamelCaseNamingConvention.Instance).WithTypeConverter(new FloatConverter()).IgnoreUnmatchedProperties() .Build(); } public static ISerializer Serializer() { return new SerializerBuilder().WithNamingConvention(CamelCaseNamingConvention.Instance).DisableAliases().ConfigureDefaultValuesHandling(DefaultValuesHandling.OmitDefaults) .WithTypeConverter(new FloatConverter()) .Build(); } public static T Deserialize<T>(string raw, string fileName) where T : new() { try { return Deserializer().Deserialize<T>(raw); } catch (Exception ex) { Vanity.Log.LogError((object)(fileName + ": " + ex.Message)); try { return DeserializerUnSafe().Deserialize<T>(raw); } catch (Exception) { return new T(); } } } public static Dictionary<long, T> Read<T>(string pattern) { Dictionary<long, T> dictionary = new Dictionary<long, T>(); string[] files = Directory.GetFiles(Paths.ConfigPath, pattern); foreach (string text in files) { Dictionary<long, T> dictionary2 = Deserialize<Dictionary<long, T>>(File.ReadAllText(text), text); if (dictionary2 == null) { continue; } foreach (KeyValuePair<long, T> item in dictionary2) { dictionary[item.Key] = item.Value; } } return dictionary; } private static bool UpdateName(string id, string name) { if (Data.TryGetValue(id, out VanityEntry value)) { if (value.name == name) { return false; } value.name = name; return true; } Data[id] = new VanityEntry { name = name }; return true; } private static bool UpdateNetworkId(string id, string networkId) { if (Data.TryGetValue(id, out VanityEntry value)) { if (value.player == networkId) { return false; } value.player = networkId; return true; } Data[id] = new VanityEntry { player = networkId }; return true; } public static void UpdatePlayerIds() { //IL_00b7: Unknown result type (might be due to invalid IL or missing references) ZDOMan instance = ZDOMan.instance; if (instance == null || !Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer()) { return; } bool flag = false; flag |= UpdateName("Everyone", "Everyone"); if (!ZNet.instance.IsDedicated()) { flag |= UpdateName(Game.instance.GetPlayerProfile().GetPlayerID().ToString(), Game.instance.GetPlayerProfile().GetName()); flag |= UpdateNetworkId(Game.instance.GetPlayerProfile().GetPlayerID().ToString(), Helper.GetNetworkId()); } foreach (ZDOPeer peer in instance.m_peers) { ZDO zDO = instance.GetZDO(peer.m_peer.m_characterID); if (zDO == null) { return; } long @long = zDO.GetLong(ZDOVars.s_playerID, 0L); string @string = zDO.GetString(ZDOVars.s_playerName, ""); if (@long != 0L && !(@string == "")) { flag |= UpdateName(@long.ToString(), @string); flag |= UpdateNetworkId(@long.ToString(), peer.m_peer.m_rpc.GetSocket().GetHostName()); } } if (flag) { ToFile(); } } } public class FloatConverter : IYamlTypeConverter { public bool Accepts(Type type) { return type == typeof(float); } public object ReadYaml(IParser parser, Type type) { float num = float.Parse(((YamlDotNet.Core.Events.Scalar)parser.Current).Value, NumberStyles.Float, CultureInfo.InvariantCulture); parser.MoveNext(); return num; } public void WriteYaml(IEmitter emitter, object value, Type type) { emitter.Emit(new YamlDotNet.Core.Events.Scalar(((float)value).ToString("0.###", CultureInfo.InvariantCulture))); } } public class VanityManager { public static VanityInfo Info = new VanityInfo(); public static Dictionary<string, Dictionary<string, Tuple<string, int>>> Crafted = new Dictionary<string, Dictionary<string, Tuple<string, int>>>(); public static Color? SkinColor; public static Color? HairColor; public static float ColorUpdateInterval => Info.updateInterval.GetValueOrDefault(0.1f); public static float ColorDuration => Info.colorDuration.GetValueOrDefault(1f); public static void Load() { Info = new VanityInfo(); LoadCrafted(); string playerID = Helper.GetPlayerID(); string networkId = Helper.GetNetworkId(); Load(Info, "Everyone"); Load(Info, "0"); Load(Info, networkId); Load(Info, playerID); if (Object.op_Implicit((Object)(object)Game.instance) && Game.instance.m_shuttingDown) { return; } if (Object.op_Implicit((Object)(object)FejdStartup.m_instance) && Object.op_Implicit((Object)(object)FejdStartup.m_instance.m_playerInstance)) { Player component = FejdStartup.m_instance.m_playerInstance.GetComponent<Player>(); if (component != null) { ((Humanoid)component).SetupEquipment(); } } if (Object.op_Implicit((Object)(object)Player.m_localPlayer)) { ((Humanoid)Player.m_localPlayer).SetupEquipment(); } } private static void LoadCrafted() { Crafted = new Dictionary<string, Dictionary<string, Tuple<string, int>>>(); foreach (KeyValuePair<string, VanityEntry> datum in VanityData.Data) { if (!Crafted.ContainsKey(datum.Key)) { Crafted[datum.Key] = new Dictionary<string, Tuple<string, int>>(); } foreach (KeyValuePair<string, string> item in datum.Value.crafted) { Crafted[datum.Key][item.Key] = Helper.Parse(item.Value); } } } private static void Load(VanityInfo info, string id) { if (!VanityData.Data.TryGetValue(id, out VanityEntry value)) { return; } if (!string.IsNullOrEmpty(value.group)) { string[] array = Helper.ParseGroups(value.group); foreach (string id2 in array) { Load(info, id2); } } if (!string.IsNullOrEmpty(value.beard)) { info.beard = Helper.Parse(value.beard); } if (!string.IsNullOrEmpty(value.chest)) { info.chest = Helper.Parse(value.chest); } if (value.colorDuration.HasValue) { info.colorDuration = value.colorDuration; } if (!string.IsNullOrEmpty(value.hair)) { info.hair = Helper.Parse(value.hair); } if (!string.IsNullOrEmpty(value.hairColor)) { info.hairColor = value.hairColor; } if (!string.IsNullOrEmpty(value.helmet)) { info.helmet = Helper.Parse(value.helmet); } if (!string.IsNullOrEmpty(value.leftBack)) { info.leftBack = Helper.Parse(value.leftBack); } if (!string.IsNullOrEmpty(value.leftHand)) { info.leftHand = Helper.Parse(value.leftHand); } if (!string.IsNullOrEmpty(value.legs)) { info.legs = Helper.Parse(value.legs); } if (!string.IsNullOrEmpty(value.rightBack)) { info.rightBack = Helper.Parse(value.rightBack); } if (!string.IsNullOrEmpty(value.rightHand)) { info.rightHand = Helper.Parse(value.rightHand); } if (!string.IsNullOrEmpty(value.shoulder)) { info.shoulder = Helper.Parse(value.shoulder); } if (!string.IsNullOrEmpty(value.skinColor)) { info.skinColor = value.skinColor; } if (value.updateInterval.HasValue) { info.updateInterval = value.updateInterval; } if (!string.IsNullOrEmpty(value.utility)) { info.utility = Helper.Parse(value.utility); } foreach (KeyValuePair<string, string> item in value.gear) { info.gear[item.Key] = Helper.Parse(item.Value); } } public static Tuple<string, int>? GetVisualBySlot(VisSlot slot) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected I4, but got Unknown return (int)slot switch { 2 => Info.leftBack, 3 => Info.rightBack, 9 => Info.beard, 4 => Info.chest, 10 => Info.hair, 0 => Info.leftHand, 1 => Info.rightHand, 6 => Info.helmet, 5 => Info.legs, 7 => Info.shoulder, 8 => Info.utility, _ => null, }; } public static Color[] GetSkinColors(Player obj) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) return Helper.ParseColors(Info.skinColor, obj.m_skinColor); } public static Color[] GetHairColors(Player obj) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) return Helper.ParseColors(Info.hairColor, obj.m_hairColor); } private static ItemData? GetEquipment(Player player, VisSlot slot) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected I4, but got Unknown return (ItemData?)((int)slot switch { 2 => ((Humanoid)player).m_leftItem, 3 => ((Humanoid)player).m_rightItem, 9 => null, 4 => ((Humanoid)player).m_chestItem, 10 => null, 0 => ((Humanoid)player).m_leftItem, 1 => ((Humanoid)player).m_rightItem, 6 => ((Humanoid)player).m_helmetItem, 5 => ((Humanoid)player).m_legItem, 7 => ((Humanoid)player).m_shoulderItem, 8 => ((Humanoid)player).m_utilityItem, _ => throw new NotImplementedException(), }); } public static void OverrideItem(VisEquipment vis, VisSlot slot, ref string name, ref int variant) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (Helper.IsLocalPlayer(vis)) { ItemData equipment = GetEquipment(((Component)vis).GetComponent<Player>(), slot); Tuple<string, int> visualBySlot = GetVisualBySlot(slot); Dictionary<string, Tuple<string, int>> value; Tuple<string, int> value2; Tuple<string, int> value3; if (visualBySlot != null) { name = visualBySlot.Item1; variant = visualBySlot.Item2; } else if (equipment != null && Crafted.TryGetValue(equipment.m_crafterID.ToString(), out value) && value.TryGetValue(name, out value2)) { name = value2.Item1; variant = value2.Item2; } else if (Info.gear.TryGetValue(name, out value3)) { name = value3.Item1; variant = value3.Item2; } } } private static VisSlot? GetSlot(ItemData item) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected I4, but got Unknown ItemType itemType = item.m_shared.m_itemType; return (itemType - 3) switch { 0 => (VisSlot)1, 1 => (VisSlot)0, 4 => (VisSlot)4, 3 => (VisSlot)6, 8 => (VisSlot)5, 2 => (VisSlot)0, 16 => (VisSlot)1, 14 => (VisSlot)7, 12 => (VisSlot)1, 11 => (VisSlot)1, 15 => (VisSlot)8, _ => null, }; } public static void OverrideItem(ItemData item, ref string name, ref int variant) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) VisSlot? slot = GetSlot(item); if (slot.HasValue) { Tuple<string, int> visualBySlot = GetVisualBySlot(slot.Value); Dictionary<string, Tuple<string, int>> value; Tuple<string, int> value2; Tuple<string, int> value3; if (visualBySlot != null) { name = visualBySlot.Item1; variant = visualBySlot.Item2; } else if (Crafted.TryGetValue(item.m_crafterID.ToString(), out value) && Object.op_Implicit((Object)(object)item.m_dropPrefab) && value.TryGetValue(((Object)item.m_dropPrefab).name, out value2)) { name = value2.Item1; variant = value2.Item2; } else if (Object.op_Implicit((Object)(object)item.m_dropPrefab) && Info.gear.TryGetValue(((Object)item.m_dropPrefab).name, out value3)) { name = value3.Item1; variant = value3.Item2; } } } public static void OverrideItem(VisEquipment vis, VisSlot slot, ref string name) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) int variant = 0; OverrideItem(vis, slot, ref name, ref variant); } public static void OverrideSkinColor(VisEquipment vis, ref Vector3 color) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) if (Helper.IsLocalPlayer(vis) && SkinColor.HasValue) { color.x = SkinColor.Value.r; color.y = SkinColor.Value.g; color.z = SkinColor.Value.b; } } public static void OverrideHairColor(VisEquipment vis, ref Vector3 color) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) if (Helper.IsLocalPlayer(vis) && HairColor.HasValue) { color.x = HairColor.Value.r; color.y = HairColor.Value.g; color.z = HairColor.Value.b; } } } public static class Helper { public static List<string> Players() { return (from s in VanityData.PlayerIds.Keys select s.Replace(" ", "_") into s orderby s select s).ToList(); } private static string Normalize(string name) { return name.ToLower().Replace(" ", "_"); } public static string GetPlayerID(string name) { string name2 = name; name2 = name2.ToLower().Replace(" ", "_"); Dictionary<string, string> dictionary = VanityData.PlayerIds.ToDictionary<KeyValuePair<string, string>, string, string>((KeyValuePair<string, string> kvp) => Normalize(kvp.Key), (KeyValuePair<string, string> kvp) => kvp.Value); if (dictionary.TryGetValue(name2, out var value)) { return value; } string text = dictionary.Keys.FirstOrDefault((string s) => s.StartsWith(name2, StringComparison.OrdinalIgnoreCase)); if (!string.IsNullOrEmpty(text)) { return dictionary[text]; } text = dictionary.Keys.FirstOrDefault((string s) => s.Contains(name2)); if (!string.IsNullOrEmpty(text)) { return dictionary[text]; } throw new InvalidOperationException("Unable to find the player."); } public static bool IsLocalPlayer(VisEquipment obj) { if (Object.op_Implicit((Object)(object)obj) && obj.m_isPlayer) { return IsLocalPlayer(((Component)obj).GetComponent<Player>()); } return false; } public static bool IsLocalPlayer(Player obj) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)obj)) { if (!((Object)(object)obj == (Object)(object)Player.m_localPlayer)) { return ((Character)obj).GetZDOID() == ZDOID.None; } return true; } return false; } public static bool IsTrophy(ItemData item) { if (item != null) { return Name(item).ToLower().Contains("trophy"); } return false; } public static string Name(ItemData item) { object obj; if (item == null) { obj = null; } else { GameObject dropPrefab = item.m_dropPrefab; obj = ((dropPrefab != null) ? ((Object)dropPrefab).name : null); } if (obj == null) { obj = ""; } return (string)obj; } public static float TryFloat(string arg, float defaultValue = 1f) { if (!float.TryParse(arg, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { return defaultValue; } return result; } public static float TryFloat(string[] args, int index, float defaultValue = 1f) { if (index >= args.Length) { return defaultValue; } return TryFloat(args[index], defaultValue); } public static int TryInt(string arg, int defaultValue = 1) { if (!int.TryParse(arg, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { return defaultValue; } return result; } public static int TryInt(string[] args, int index, int defaultValue = 1) { if (index >= args.Length) { return defaultValue; } return TryInt(args[index], defaultValue); } public static Tuple<string, int> Parse(string value) { char[] separator = new char[2] { ',', ' ' }; string[] array = value.Split(separator, StringSplitOptions.RemoveEmptyEntries).ToArray(); string item = array[0]; int item2 = TryInt(array, 1, 0); return new Tuple<string, int>(item, item2); } public static string[] ParseGroups(string value) { char[] separator = new char[2] { ',', ' ' }; return value.Split(separator, StringSplitOptions.RemoveEmptyEntries).ToArray(); } public static Color ParseColor(string value, Color baseColor) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) string[] args = value.Split(new char[1] { ',' }); Color val = baseColor; val.r = TryFloat(args, 0, val.r); val.g = TryFloat(args, 1, val.g); val.b = TryFloat(args, 2, val.b); return val; } public static Color[] ParseColors(string value, Vector3 baseColor) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) string[] source = value.Split(new char[1] { ' ' }); Color color = new Color(baseColor.x, baseColor.y, baseColor.z); return source.Select((string value) => ParseColor(value, color)).ToArray(); } public static string GetPlayerID() { Player localPlayer = Player.m_localPlayer; return ((localPlayer != null) ? localPlayer.GetPlayerID().ToString() : null) ?? CharacterPreview.Id; } public static string GetNetworkId() { object obj; if (PrivilegeManager.privilegeData.HasValue) { obj = PrivilegeManager.PlatformUserId; if (obj == null) { return "0"; } } else { obj = "0"; } return (string)obj; } } [HarmonyPatch(typeof(FejdStartup), "SetupCharacterPreview")] public class CharacterPreview { public static string Id = ""; private static void Prefix(PlayerProfile profile) { if (profile == null) { Id = ""; } else { Id = profile.m_playerID.ToString(); } VanityManager.Load(); } } [HarmonyPatch(typeof(Player), "Awake")] public class LoadVanity { private static void Postfix() { VanityManager.Load(); } } [HarmonyPatch] public class IconPatches { private static Sprite? OverrideItem(ItemData item) { string name = ""; int variant = 0; VanityManager.OverrideItem(item, ref name, ref variant); if (name == "") { return null; } GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(name); ItemData val = ((itemPrefab == null) ? null : itemPrefab.GetComponent<ItemDrop>()?.m_itemData); if (val == null || val.m_shared.m_icons == null || val.m_shared.m_icons.Length <= variant) { return null; } return val.m_shared.m_icons[variant]; } [HarmonyPatch(typeof(ItemData), "GetIcon")] [HarmonyPostfix] [HarmonyPriority(0)] private static Sprite GetIcon(Sprite result, ItemData __instance) { return OverrideItem(__instance) ?? result; } [HarmonyPatch(typeof(InventoryGui), "SetupUpgradeItem")] [HarmonyPostfix] [HarmonyPriority(0)] private static void SetupUpgradeItem(InventoryGui __instance, Recipe recipe, ItemData item) { if (item == null) { item = recipe.m_item.m_itemData; } __instance.m_upgradeItemIcon.sprite = OverrideItem(item) ?? __instance.m_upgradeItemIcon.sprite; } [HarmonyPatch(typeof(InventoryGui), "UpdateRecipe")] [HarmonyPostfix] [HarmonyPriority(0)] private static void UpdateRecipe(InventoryGui __instance) { ItemData itemData = ((RecipeDataPair)(ref __instance.m_selectedRecipe)).ItemData; if (itemData != null) { __instance.m_recipeIcon.sprite = OverrideItem(itemData) ?? __instance.m_recipeIcon.sprite; } } } [HarmonyPatch(typeof(Terminal), "AddString", new Type[] { typeof(string) })] public class RedirectOutput { public static ZRpc? Target; private static void Postfix(string text) { if (ZNet.m_isServer && Target != null) { ZNet.instance.RemotePrint(Target, text); } } } [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] public class ServerExecution { public static string RPC_Command = "VANITY_Command"; public static void Send(string command) { ZRpc serverRPC = ZNet.instance.GetServerRPC(); ((Terminal)Console.instance).AddString("Sending command: " + command); if (serverRPC != null) { string rPC_Command = RPC_Command; object[] array = new string[1] { command }; serverRPC.Invoke(rPC_Command, array); } } public static void Send(IEnumerable<string> args) { Send(string.Join(" ", args)); } public static void Send(ConsoleEventArgs args) { Send((IEnumerable<string>)args.Args); } private static bool IsAllowed(ZRpc rpc) { ZNet instance = ZNet.instance; if (!((Behaviour)instance).enabled) { return false; } if (rpc != null && !instance.ListContainsId(instance.m_adminList, rpc.GetSocket().GetHostName())) { ((Terminal)Console.instance).AddString("Unauthorized to set vanity."); return false; } return true; } private static void RPC_Do_Command(ZRpc rpc, string command) { RedirectOutput.Target = rpc; if (IsAllowed(rpc)) { ((Terminal)Console.instance).TryRunCommand(command, false, false); } RedirectOutput.Target = null; } private static void Postfix(ZNet __instance, ZRpc rpc) { if (__instance.IsServer()) { rpc.Register<string>(RPC_Command, (Action<ZRpc, string>)RPC_Do_Command); } } } [HarmonyPatch(typeof(Humanoid), "SetupVisEquipment")] public class SetupVisEquipment { private static void Prefix(Humanoid __instance) { SetEquipment.IsHidden = __instance.m_hiddenLeftItem != null || __instance.m_hiddenRightItem != null; } } [HarmonyPatch(typeof(VisEquipment))] [HarmonyPriority(200)] public class SetEquipment { public static bool IsHidden; [HarmonyPatch("SetRightItem")] [HarmonyPrefix] private static void SetRightItem(VisEquipment __instance, ref string name) { if (!IsHidden) { VanityManager.OverrideItem(__instance, (VisSlot)1, ref name); } } [HarmonyPatch("SetLeftItem")] [HarmonyPrefix] private static void SetLeftItem(VisEquipment __instance, ref string name, ref int variant) { if (!IsHidden) { VanityManager.OverrideItem(__instance, (VisSlot)0, ref name, ref variant); } } [HarmonyPatch("SetRightBackItem")] [HarmonyPrefix] private static void SetRightBackItem(VisEquipment __instance, ref string name) { if (IsHidden) { VanityManager.OverrideItem(__instance, (VisSlot)1, ref name); } VanityManager.OverrideItem(__instance, (VisSlot)3, ref name); } [HarmonyPatch("SetLeftBackItem")] [HarmonyPrefix] private static void SetLeftBackItem(VisEquipment __instance, ref string name, ref int variant) { if (IsHidden) { VanityManager.OverrideItem(__instance, (VisSlot)0, ref name, ref variant); } VanityManager.OverrideItem(__instance, (VisSlot)2, ref name, ref variant); } [HarmonyPatch("SetChestItem")] [HarmonyPrefix] private static void SetChestItem(VisEquipment __instance, ref string name) { VanityManager.OverrideItem(__instance, (VisSlot)4, ref name); } [HarmonyPatch("SetLegItem")] [HarmonyPrefix] private static void SetLegItem(VisEquipment __instance, ref string name) { VanityManager.OverrideItem(__instance, (VisSlot)5, ref name); } [HarmonyPatch("SetHelmetItem")] [HarmonyPrefix] private static void SetHelmetItem(VisEquipment __instance, ref string name) { VanityManager.OverrideItem(__instance, (VisSlot)6, ref name); } [HarmonyPatch("SetShoulderItem")] [HarmonyPrefix] private static void SetShoulderItem(VisEquipment __instance, ref string name, ref int variant) { VanityManager.OverrideItem(__instance, (VisSlot)7, ref name, ref variant); } [HarmonyPatch("SetUtilityItem")] [HarmonyPrefix] private static void SetUtilityItem(VisEquipment __instance, ref string name) { VanityManager.OverrideItem(__instance, (VisSlot)8, ref name); } [HarmonyPatch("SetBeardItem")] [HarmonyPrefix] private static void SetBeardItem(VisEquipment __instance, ref string name) { VanityManager.OverrideItem(__instance, (VisSlot)9, ref name); } [HarmonyPatch("SetHairItem")] [HarmonyPrefix] private static void SetHairItem(VisEquipment __instance, ref string name) { VanityManager.OverrideItem(__instance, (VisSlot)10, ref name); } [HarmonyPatch("SetSkinColor")] [HarmonyPrefix] private static void SetSkinColor(VisEquipment __instance, ref Vector3 color) { VanityManager.OverrideSkinColor(__instance, ref color); } [HarmonyPatch("SetHairColor")] [HarmonyPrefix] private static void SetHairColor(VisEquipment __instance, ref Vector3 color) { VanityManager.OverrideHairColor(__instance, ref color); } } [HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[] { typeof(ItemData), typeof(int), typeof(bool), typeof(float), typeof(int) })] public class Tooltip { private static string Postfix(string result, ItemData item, bool crafting) { if (item == null) { return result; } if (crafting) { return result; } string name = ""; int variant = 0; VanityManager.OverrideItem(item, ref name, ref variant); if (variant != 0) { name = name + " " + variant; } if (name != "") { return result + "\nStyle: <color=orange>" + name + "</color>"; } return result; } } [BepInPlugin("vanity", "Vanity", "1.16")] public class Vanity : BaseUnityPlugin { public const string GUID = "vanity"; public const string NAME = "Vanity"; public const string VERSION = "1.16"; public static ManualLogSource Log; public static CustomSyncedValue<string> VanityValue; public static ConfigSync ConfigSync = new ConfigSync("vanity") { DisplayName = "Vanity", CurrentVersion = "1.16", MinimumRequiredVersion = "1.16", IsLocked = true }; private float timer; public void Awake() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; VanityValue = new CustomSyncedValue<string>(ConfigSync, "vanity_data"); VanityValue.ValueChanged += delegate { VanityData.FromValue(VanityValue.Value); }; new Harmony("vanity").PatchAll(); VanityData.CreateFile(); VanityData.SetupWatcher(); VanityData.FromFile(); } public void Start() { CommandWrapper.Init(); } public void LateUpdate() { if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer()) { timer -= Time.deltaTime; if (timer <= 0f) { timer = 10f; VanityData.UpdatePlayerIds(); } } } } [HarmonyPatch(typeof(Terminal), "InitTerminal")] public class SetCommands { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static Func<int, List<string>> <>9__0_0; public static ConsoleEvent <>9__0_1; public static ConsoleOptionsFetcher <>9__0_2; internal List<string> <Postfix>b__0_0(int index) { if (index == 0) { return Helper.Players(); } return null; } internal void <Postfix>b__0_1(ConsoleEventArgs args) { string text = ""; text = ((args.Length <= 1) ? Helper.GetPlayerID() : Helper.GetPlayerID(string.Join(" ", args.Args.Skip(1)))); args.Context.AddString(text.ToString()); GUIUtility.systemCopyBuffer = text.ToString(); } internal List<string> <Postfix>b__0_2() { return Helper.Players(); } } private static void Postfix() { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown ChangeEquipment.AddChangeEquipment(); CommandWrapper.Register("playerid", (int index) => (index == 0) ? Helper.Players() : null); object obj = <>c.<>9__0_1; if (obj == null) { ConsoleEvent val = delegate(ConsoleEventArgs args) { string text = ""; text = ((args.Length <= 1) ? Helper.GetPlayerID() : Helper.GetPlayerID(string.Join(" ", args.Args.Skip(1)))); args.Context.AddString(text.ToString()); GUIUtility.systemCopyBuffer = text.ToString(); }; <>c.<>9__0_1 = val; obj = (object)val; } object obj2 = <>c.<>9__0_2; if (obj2 == null) { ConsoleOptionsFetcher val2 = () => Helper.Players(); <>c.<>9__0_2 = val2; obj2 = (object)val2; } new ConsoleCommand("playerid", "[name] - Copies the player id to the clipboard.", (ConsoleEvent)obj, false, false, false, false, false, (ConsoleOptionsFetcher)obj2, false, false, false); } } [HarmonyPatch(typeof(ZNet), "Awake")] public class DisableServerSync { private static void Finalizer(ZNet __instance) { if (!__instance.IsDedicated() && __instance.IsServer()) { Vanity.Log.LogInfo((object)"Self hosting detected, disabling server sync."); AccessTools.Field(typeof(ConfigSync), "isServer").SetValue(null, false); } } } } 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 object? LocalBaseValue; public readonly string Identifier; public readonly Type Type; private object? boxedValue; protected bool localIsOwner; public readonly int Priority; public object? BoxedValue { get { return boxedValue; } set { boxedValue = value; this.ValueChanged?.Invoke(); } } public event Action? ValueChanged; protected CustomSyncedValueBase(ConfigSync configSync, string identifier, Type type, int priority) { Priority = priority; Identifier = identifier; Type = type; configSync.AddCustomValue(this); localIsOwner = configSync.IsSourceOfTruth; configSync.SourceOfTruthChanged += delegate(bool truth) { localIsOwner = truth; }; } } [PublicAPI] public sealed class CustomSyncedValue<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; } [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> 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); } } } } } [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 = false; 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_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown int pos = pkg.GetPos(); pkg.SetPos(0); int num = pkg.ReadInt(); if ((num == StringExtensionMethods.GetStableHashCode("PeerInfo") || num == StringExtensionMethods.GetStableHashCode("RoutedRPC") || num == StringExtensionMethods.GetStableHashCode("ZDOData")) && !finished) { ZPackage val = new ZPackage(pkg.GetArray()); val.SetPos(pos); Package.Add(val); } else { pkg.SetPos(pos); Original.Send(pkg); } } } [HarmonyPriority(800)] [HarmonyPrefix] private static void Prefix(ref Dictionary<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()) { 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; } } [HarmonyPostfix] private static void Postfix(Dictionary<Assembly, BufferingSocket> __state, ZNet __instance, ZRpc rpc) { ZRpc rpc2 = rpc; ZNet __instance2 = __instance; Dictionary<Assembly, BufferingSocket> __state2 = __state; ZNetPeer peer; if (__instance2.IsServer()) { object obj = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance2, new object[1] { rpc2 }); peer = (ZNetPeer)((obj is ZNetPeer) ? obj : null); if (peer == null) { SendBufferedData(); } else { ((MonoBehaviour)__instance2).StartCoroutine(sendAsync()); } } void SendBufferedData() { if (rpc2.GetSocket() is BufferingSocket bufferingSocket) { AccessTools.DeclaredField(typeof(ZRpc), "m_socket").SetValue(rpc2, bufferingSocket.Original); object? obj2 = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance2, new object[1] { rpc2 }); ZNetPeer val = (ZNetPeer)((obj2 is ZNetPeer) ? obj2 : null); if (val != null) { AccessTools.DeclaredField(typeof(ZNetPeer), "m_socket").SetValue(val, bufferingSocket.Original); } } BufferingSocket bufferingSocket2 = __state2[Assembly.GetExecutingAssembly()]; bufferingSocket2.finished = true; for (int i = 0; i < bufferingSocket2.Package.Count; i++) { if (i == bufferingSocket2.versionMatchQueued) { bufferingSocket2.Original.VersionMatch(); } bufferingSocket2.Original.Send(bufferingSocket2.Package[i]); } if (bufferingSocket2.Package.Count == bufferingSocket2.versionMatchQueued) { bufferingSocket2.Original.VersionMatch(); } } IEnumerator sendAsync() { foreach (ConfigSync configSync in configSyncs) { List<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(rpc2.GetSocket().GetHostName())) : listContainsId.Invoke(ZNet.instance, new object[2] { adminList, rpc2.GetSocket().GetHostName() })) }); ZPackage package = ConfigsToPackage(configSync.allConfigs.Select((OwnConfigEntryBase c) => c.BaseConfig), configSync.allCustomValues, entries, partial: false); yield return ((MonoBehaviour)__instance2).StartCoroutine(configSync.sendZPackage(new List<ZNetPeer> { peer }, package)); } SendBufferedData(); } } } private class PackageEntry { public string section = null; public string key = null; public Type type = null; public object? value; } [HarmonyPatch(typeof(ConfigEntryBase), "GetSerializedValue")] private static class PreventSavingServerInfo { [HarmonyPrefix] private static bool Prefix(ConfigEntryBase __instance, ref string __result) { OwnConfigEntryBase ownConfigEntryBase = configData(__instance); if (ownConfigEntryBase == null || isWritableConfig(ownConfigEntryBase)) { return true; } __result = TomlTypeConverter.ConvertToString(ownConfigEntryBase.LocalBaseValue, __instance.SettingType); return false; } } [HarmonyPatch(typeof(ConfigEntryBase), "SetSerializedValue")] private static class PreventConfigRereadChangingValues { [HarmonyPrefix] private static bool Prefix(ConfigEntryBase __instance, string value) { OwnConfigEntryBase ownConfigEntryBase = configData(__instance); if (ownConfigEntryBase == null || ownConfigEntryBase.LocalBaseValue == null) { return true; } try { ownConfigEntryBase.LocalBaseValue = TomlTypeConverter.ConvertToValue(value, __instance.SettingType); } catch (Exception ex) { Debug.LogWarning((object)$"Config value of setting \"{__instance.Definition}\" could not be parsed and will be ignored. Reason: {ex.Message}; Value: {value}"); } return false; } } private class InvalidDeserializationTypeException : Exception { public string expected = null; public string received = null; public string field = ""; } public static bool ProcessingServerUpdate; public readonly string Name; public string? DisplayName; public string? CurrentVersion; public string? MinimumRequiredVersion; public bool ModRequired = false; private bool? forceConfigLocking; private bool isSourceOfTruth = true; private static readonly HashSet<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 = 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[]>>(); 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; 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) { ConfigEntry<T> configEntry2 = configEntry; OwnConfigEntryBase ownConfigEntryBase = configData((ConfigEntryBase)(object)configEntry2); SyncedConfigEntry<T> syncedEntry = ownConfigEntryBase as SyncedConfigEntry<T>; if (syncedEntry == null) { syncedEntry = new SyncedConfigEntry<T>(configEntry2); AccessTools.DeclaredField(typeof(ConfigDescription), "<Tags>k__BackingField").SetValue(((ConfigEntryBase)configEntry2).Description, new object[1] { new ConfigurationManagerAttributes() }.Concat(((ConfigEntryBase)configEntry2).Description.Tags ?? Array.Empty<object>()).Concat(new SyncedConfigEntry<T>[1] { syncedEntry }).ToArray()); configEntry2.SettingChanged += delegate { if (!ProcessingServerUpdate && syncedEntry.SynchronizedConfig) { Broadcast(ZRoutedRpc.Everybody, (ConfigEntryBase)configEntry2); } }; 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) { CustomSyncedValueBase customValue2 = customValue; if (allCustomValues.Select((CustomSyncedValueBase v) => v.Identifier).Concat(new string[1] { "serverversion" }).Contains(customValue2.Identifier)) { throw new Exception("Cannot have multiple settings with the same name or with a reserved name (serverversion)"); } allCustomValues.Add(customValue2); allCustomValues = new HashSet<CustomSyncedValueBase>(allCustomValues.OrderByDescending((CustomSyncedValueBase v) => v.Priority)); customValue2.ValueChanged += delegate { if (!ProcessingServerUpdate) { Broadcast(ZRoutedRpc.Everybody, customValue2); } }; } private void RPC_FromServerConfigSync(ZRpc rpc, ZPackage package) { lockedConfigChanged += serverLockedSettingChanged; IsSourceOfTruth = false; if (HandleConfigSyncRPC(0L, package, clientUpdate: false)) { InitialSyncDone = true; } } private void RPC_FromOtherClientConfigSync(long sender, ZPackage package) { HandleConfigSyncRPC(sender, package, clientUpdate: true); } private bool HandleConfigSyncRPC(long sender, ZPackage package, bool clientUpdate) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Expected O, but got Unknown //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Expected O, but got Unknown try { if (isServer && IsLocked) { ZRpc? currentRpc = SnatchCurrentlyHandlingRPC.currentRpc; object obj; if (currentRpc == null) { obj = null; } else { ISocket socket = currentRpc.GetSocket(); obj = ((socket != null) ? socket.GetHostName() : null); } string text = (string)obj; if (text != null) { MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null); SyncedList val = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance); if (!(((object)methodInfo == null) ? val.Contains(text) : ((bool)methodInfo.Invoke(ZNet.instance, new object[2] { val, text })))) { return false; } } } cacheExpirations.RemoveAll(delegate(KeyValuePair<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 SortedDictionary<int, byte[]> 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 (in