Decompiled source of AvatarInfection v2.0.0
Mods/AvatarInfection.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Net; using System.Net.Http; using System.Net.Security; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.Cryptography.X509Certificates; using System.Text.Json; using System.Text.Json.Serialization; using System.Threading; using System.Threading.Tasks; using AvatarInfection; using AvatarInfection.Helper; using AvatarInfection.Managers; using AvatarInfection.Patches; using AvatarInfection.Settings; using AvatarInfection.Utilities; using BoneLib; using BoneLib.BoneMenu; using BoneLib.Notifications; using HarmonyLib; using Il2CppCysharp.Threading.Tasks; using Il2CppInterop.Runtime; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSLZ.Bonelab; using Il2CppSLZ.Interaction; using Il2CppSLZ.Marrow; using Il2CppSLZ.Marrow.Interaction; using Il2CppSLZ.Marrow.Warehouse; using Il2CppSLZ.VRMK; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using LabFusion.Data; using LabFusion.Downloading; using LabFusion.Entities; using LabFusion.Extensions; using LabFusion.Marrow; using LabFusion.Marrow.Integration; using LabFusion.Marrow.Proxies; using LabFusion.Menu.Data; using LabFusion.Menu.Gamemodes; using LabFusion.Network; using LabFusion.Player; using LabFusion.Preferences; using LabFusion.Preferences.Client; using LabFusion.Preferences.Server; using LabFusion.RPC; using LabFusion.SDK.Gamemodes; using LabFusion.SDK.Metadata; using LabFusion.SDK.Modules; using LabFusion.SDK.Points; using LabFusion.SDK.Triggers; using LabFusion.Scene; using LabFusion.Senders; using LabFusion.UI.Popups; using LabFusion.Utilities; using LabPresence.Managers; using MelonLoader; using MelonLoader.Preferences; using MelonLoader.Utils; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Semver; using Tomlet.Attributes; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(Core), "AvatarInfection", "2.0.0", "HAHOOS", "https://thunderstore.io/c/bonelab/p/HAHOOS/AvatarInfection")] [assembly: MelonGame("Stress Level Zero", "BONELAB")] [assembly: MelonColor(0, 0, 255, 0)] [assembly: MelonAuthorColor(0, 255, 165, 0)] [assembly: MelonOptionalDependencies(new string[] { "LabPresence" })] [assembly: AssemblyTitle("A fusion gamemode where you infect others and they turn into a selected avatar until the gamemode ends!")] [assembly: AssemblyDescription("A fusion gamemode where you infect others and they turn into a selected avatar until the gamemode ends!")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("HAHOOS")] [assembly: AssemblyProduct("AvatarInfection")] [assembly: AssemblyFileVersion("2.0.0")] [assembly: AssemblyInformationalVersion("2.0.0")] [assembly: ComVisible(false)] [assembly: Guid("4bf6c046-91bd-4503-93ca-5ef3b7d6c95e")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyVersion("2.0.0.0")] [module: RefSafetyRules(11)] [CompilerGenerated] internal sealed class <>z__ReadOnlyArray<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T> { int ICollection.Count => _items.Length; bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; object IList.this[int index] { get { return _items[index]; } set { throw new NotSupportedException(); } } bool IList.IsFixedSize => true; bool IList.IsReadOnly => true; int IReadOnlyCollection<T>.Count => _items.Length; T IReadOnlyList<T>.this[int index] => _items[index]; int ICollection<T>.Count => _items.Length; bool ICollection<T>.IsReadOnly => true; T IList<T>.this[int index] { get { return _items[index]; } set { throw new NotSupportedException(); } } public <>z__ReadOnlyArray(T[] items) { _items = items; } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)_items).GetEnumerator(); } void ICollection.CopyTo(Array array, int index) { ((ICollection)_items).CopyTo(array, index); } int IList.Add(object? value) { throw new NotSupportedException(); } void IList.Clear() { throw new NotSupportedException(); } bool IList.Contains(object? value) { return ((IList)_items).Contains(value); } int IList.IndexOf(object? value) { return ((IList)_items).IndexOf(value); } void IList.Insert(int index, object? value) { throw new NotSupportedException(); } void IList.Remove(object? value) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } IEnumerator<T> IEnumerable<T>.GetEnumerator() { return ((IEnumerable<T>)_items).GetEnumerator(); } void ICollection<T>.Add(T item) { throw new NotSupportedException(); } void ICollection<T>.Clear() { throw new NotSupportedException(); } bool ICollection<T>.Contains(T item) { return ((ICollection<T>)_items).Contains(item); } void ICollection<T>.CopyTo(T[] array, int arrayIndex) { ((ICollection<T>)_items).CopyTo(array, arrayIndex); } bool ICollection<T>.Remove(T item) { throw new NotSupportedException(); } int IList<T>.IndexOf(T item) { return ((IList<T>)_items).IndexOf(item); } void IList<T>.Insert(int index, T item) { throw new NotSupportedException(); } void IList<T>.RemoveAt(int index) { throw new NotSupportedException(); } } namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace AvatarInfection { internal static class Constants { internal static class Defaults { public const int TimeLimit = 10; public const bool NoTimeLimit = false; public static readonly TeamSettings InfectedStats = new TeamSettings { Height = new ToggleSetting<float>(1f, enabled: false), Vitality = new ToggleSetting<float>(0.75f), JumpPower = new ToggleSetting<float>(1.5f), Speed = new ToggleSetting<float>(2.8f), Agility = new ToggleSetting<float>(2f), StrengthUpper = new ToggleSetting<float>(0.5f), Mortality = true, CanUseGuns = false }; public static readonly TeamSettings InfectedChildrenStats = new TeamSettings { Height = new ToggleSetting<float>(1f, enabled: false), Vitality = new ToggleSetting<float>(0.5f), JumpPower = new ToggleSetting<float>(1.25f), Speed = new ToggleSetting<float>(1.8f), Agility = new ToggleSetting<float>(1.5f), StrengthUpper = new ToggleSetting<float>(0.35f), Mortality = true, CanUseGuns = false }; public static readonly TeamSettings SurvivorsStats = new TeamSettings { Height = new ToggleSetting<float>(1f, enabled: false), Vitality = new ToggleSetting<float>(1f), JumpPower = new ToggleSetting<float>(1f), Speed = new ToggleSetting<float>(1.2f), Agility = new ToggleSetting<float>(1f), StrengthUpper = new ToggleSetting<float>(1.5f), Mortality = true, CanUseGuns = true }; public const bool DisableSpawnGun = true; public const bool DisableDeveloperTools = true; public const bool AllowKeepInventory = false; public const int InfectedCount = 1; public const bool TeleportOnStart = true; public const int CountdownLength = 30; public const Infection.InfectType _InfectType = Infection.InfectType.TOUCH; public const bool SuicideInfects = true; public const int HoldTime = 0; public const bool TeleportOnEnd = false; public const bool UseDeathMatchSpawns = true; public const bool SyncWithInfected = false; public const bool ShowCountdownToAll = false; public const bool FriendlyFire = true; public const bool DontRepeatInfected = true; public const AvatarSelectMode SelectMode = AvatarSelectMode.CONFIG; } public const string Name = "<color=#73FF00>A</color><color=#6BFA02>v</color><color=#64F604>a</color><color=#5DF106>t</color><color=#56ED09>a</color><color=#4FE80B>r</color> <color=#40DF10>I</color><color=#39DB12>n</color><color=#32D714>f</color><color=#2BD217>e</color><color=#23CE19>c</color><color=#1CC91B>t</color><color=#15C51E>i</color><color=#0EC020>o</color><color=#07BC22>n</color>"; public const string PlainName = "Avatar Infection"; public const string Description = "An infection is spreading, turning people into a selected avatar by the host."; public const string Author = "HAHOOS"; public const string Version = "2.0.0"; public const string Barcode = "HAHOOS.Avatar Infection"; public const int InfectedBitReward = 50; public const int SurvivorsBitReward = 75; public static readonly MonoDiscReference[] Tracks = (MonoDiscReference[])(object)new MonoDiscReference[6] { Disk("TheRecurringDream"), Disk("HeavySteps"), Disk("StankFace"), Disk("AlexinWonderland"), Disk("ItDoBeGroovin"), Disk("ConcreteCrypt") }; internal static MonoDiscReference Disk(string name) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown return new MonoDiscReference("SLZ.BONELAB.Content.MonoDisc." + name); } } public class Core : MelonMod { public static Instance Logger { get; private set; } public static Texture2D Icon { get; private set; } public static MelonPreferences_Category Category { get; private set; } public static Thunderstore Thunderstore { get; private set; } private static bool FirstLoad { get; set; } = true; public override void OnInitializeMelon() { Logger = ((MelonBase)this).LoggerInstance; Category = MelonPreferences.CreateCategory("AvatarInfection_Save"); Category.SetFilePath(Path.Combine(MelonEnvironment.UserDataDirectory, "AvatarInfection.cfg")); try { ((MelonBase)this).LoggerInstance.Msg("Loading icon"); Icon = ImageConversion.LoadTexture("AvatarInfectionIcon", "AvatarInfection.png"); } catch (Exception ex) { ((MelonBase)this).LoggerInstance.Error("Failed to load icon", ex); } try { ((MelonBase)this).LoggerInstance.Msg("Patching grab related methods"); ((MelonBase)this).HarmonyInstance.PatchAll(typeof(GrabPatches)); } catch (Exception ex2) { ((MelonBase)this).LoggerInstance.Error("Failed to patch methods related to grab", ex2); ((MelonBase)this).LoggerInstance.Error("To ensure fair play, the mod will be unloaded. Grab patches failing will cause some of the restrictions to not work properly. If you repeatedly get this issue, please create an issue at https://github.com/HAHOOS/AvatarInfection"); ((MelonBase)this).Unregister("Exception occurred preventing GrabPatches from working", false); return; } Thunderstore = new Thunderstore("Avatar Infection / 2.0.0 A BONELAB Mod"); Thunderstore.BL_FetchPackage("Avatar Infection".Replace(" ", ""), "HAHOOS", "2.0.0", ((MelonBase)this).LoggerInstance); Hooking.OnLevelLoaded += OnLevelLoaded; ((MelonBase)this).LoggerInstance.Msg("Registering module"); ModuleManager.RegisterModule<FusionModule>(); ((MelonBase)this).LoggerInstance.Msg("Initialized."); } private static void OnLevelLoaded(LevelInfo info) { if (FirstLoad) { FirstLoad = false; Thunderstore.BL_SendNotification(); } } public override void OnFixedUpdate() { TimeManager.OnEarlyFixedUpdate(); } public override void OnUpdate() { TimeManager.OnEarlyUpdate(); TimeManager.OnUpdate(); } } public class FusionModule : Module { public override string Name => "Avatar Infection"; public override string Author => "HAHOOS"; public override ConsoleColor Color => ConsoleColor.Green; public override Version Version => Version.Parse("2.0.0"); internal static ModuleLogger Logger { get; private set; } protected override void OnModuleRegistered() { ((Module)this).OnModuleRegistered(); Logger = ((Module)this).LoggerInstance; GamemodeRegistration.RegisterGamemode<Infection>(); LabPresenceExtension.Init(); } } public class Infection : Gamemode { public enum InfectType { TOUCH, DEATH } public enum EventType { PlayerInfected, SwapAvatar, RefreshStats, TeleportToHost, OneMinuteLeft, InfectedVictory, SurvivorsVictory } [CompilerGenerated] private static class <>O { public static ServerEvent <0>__IHaveAvatarInfection; public static UpdateEvent <1>__IHaveAvatarInfection; public static Action <2>__Update; public static Action <3>__OnUpdate; public static Action <4>__EnsureOverrides; public static Action<string> <5>__RefreshStats; public static Action<SwapAvatarData> <6>__SwapAvatarEvent; public static Action <7>__TeleportToHost; public static Func<ulong, PlayerID> <8>__GetPlayerID; } [CompilerGenerated] private sealed class <InfectedLookingWait>d__103 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Infection <>4__this; private int <remaining>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <InfectedLookingWait>d__103(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown int num = <>1__state; Infection infection = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <remaining>5__2 = infection.Config.CountdownLength.Value; break; case 1: <>1__state = -1; <remaining>5__2--; if (((MetadataVariableT<int>)(object)infection.CountdownValue).GetValue() != <remaining>5__2) { ((MetadataVariableT<int>)(object)infection.CountdownValue).SetValue(<remaining>5__2); } break; } if (<remaining>5__2 > 0) { <>2__current = (object)new WaitForSeconds(1f); <>1__state = 1; return true; } ((MetadataVariableT<bool>)(object)infection.InfectedLooking).SetValue(true); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private float _elapsedTime; private readonly Dictionary<PlayerID, PlayerActionType> LastPlayerActions = new Dictionary<PlayerID, PlayerActionType>(); private int _surivorsLastCheckedMinutes; private static bool appliedDeathmatchSpawns; private bool WasStarted; public override string Title => "<color=#73FF00>A</color><color=#6BFA02>v</color><color=#64F604>a</color><color=#5DF106>t</color><color=#56ED09>a</color><color=#4FE80B>r</color> <color=#40DF10>I</color><color=#39DB12>n</color><color=#32D714>f</color><color=#2BD217>e</color><color=#23CE19>c</color><color=#1CC91B>t</color><color=#15C51E>i</color><color=#0EC020>o</color><color=#07BC22>n</color>"; public override string Author => "HAHOOS"; public override string Barcode => "HAHOOS.Avatar Infection"; public override string Description => "An infection is spreading, turning people into a selected avatar by the host."; public override Texture Logo => (Texture)(object)Core.Icon; public override bool DisableSpawnGun => (Config?.DisableSpawnGun?.Value).GetValueOrDefault(true); public override bool DisableDevTools => (Config?.DisableDevTools?.Value).GetValueOrDefault(true); public override bool AutoHolsterOnDeath => true; public override bool DisableManualUnragdoll => true; public override bool AutoStopOnSceneLoad => true; public override bool ManualReady => false; public static Infection Instance { get; private set; } internal InfectionTeam Infected { get; private set; } internal InfectionTeam Survivors { get; private set; } internal InfectionTeam InfectedChildren { get; private set; } internal InfectionTeamManager TeamManager { get; } = new InfectionTeamManager(); public MusicPlaylist PlayList { get; } = new MusicPlaylist(); internal MetadataBool InfectedLooking { get; private set; } internal bool InitialTeam { get; private set; } = true; public bool HasBeenInfected { get; private set; } public float ElapsedSeconds => _elapsedTime; public int ElapsedMinutes => Mathf.FloorToInt(ElapsedSeconds / 60f); internal MetadataInt CountdownValue { get; private set; } internal InfectionSettings Config { get; set; } public bool OneMinuteLeft { get; private set; } private List<ulong> LastInfected { get; } = new List<ulong>(); private bool KnockoutRevert { get; set; } private bool KnockoutFirstCheck { get; set; } = true; public bool IsInfected(InfectionTeam team) { if (team != null) { if (team != Infected) { return team == InfectedChildren; } return true; } return false; } public bool IsPlayerInfected(PlayerID id) { return IsInfected(TeamManager?.GetPlayerTeam(id)); } public bool IsLocalPlayerInfected() { return IsInfected(TeamManager?.GetLocalTeam()); } public override GroupElementData CreateSettingsGroup() { return GamemodeMenuManager.CreateSettingsGroup(); } public override void OnGamemodeRegistered() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Expected O, but got Unknown //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_028f: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Expected O, but got Unknown //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_02af: Expected O, but got Unknown WasStarted = false; Instance = this; Config = new InfectionSettings(); FusionOverrides.OnValidateNametag += new UserOverride(OnValidateNameTag); MultiplayerHooking.OnPlayerAction += new PlayerAction(OnPlayerAction); MultiplayerHooking.OnPlayerJoined += new PlayerUpdate(OnPlayerJoin); MultiplayerHooking.OnPlayerLeft += new PlayerUpdate(OnPlayerLeave); object obj = <>O.<0>__IHaveAvatarInfection; if (obj == null) { ServerEvent val = MetadataManager.IHaveAvatarInfection; <>O.<0>__IHaveAvatarInfection = val; obj = (object)val; } MultiplayerHooking.OnStartedServer += (ServerEvent)obj; object obj2 = <>O.<0>__IHaveAvatarInfection; if (obj2 == null) { ServerEvent val2 = MetadataManager.IHaveAvatarInfection; <>O.<0>__IHaveAvatarInfection = val2; obj2 = (object)val2; } MultiplayerHooking.OnJoinedServer += (ServerEvent)obj2; object obj3 = <>O.<1>__IHaveAvatarInfection; if (obj3 == null) { UpdateEvent val3 = MetadataManager.IHaveAvatarInfection; <>O.<1>__IHaveAvatarInfection = val3; obj3 = (object)val3; } MultiplayerHooking.OnTargetLevelLoaded += (UpdateEvent)obj3; MultiplayerHooking.OnDisconnected += new ServerEvent(Cleanup); TimeManager.Repeat(Timer); TimeManager.Repeat(GrabPatches.Update); TimeManager.Repeat(VisionManager.OnUpdate); TimeManager.Repeat(SurvivorsUpdate); TimeManager.Repeat(EnsureKnockout); TimeManager.Repeat(AvatarPatches.EnsureOverrides); Infected = new InfectionTeam("Infected", Color.green, (Gamemode)(object)this, new TeamSettings(Constants.Defaults.InfectedStats)); Survivors = new InfectionTeam("Survivors", Color.cyan, (Gamemode)(object)this, new TeamSettings(Constants.Defaults.SurvivorsStats)); InfectionTeam infectionTeam = new InfectionTeam("InfectedChildren", new Color(0f, 1f, 0f), (Gamemode)(object)this, new TeamSettings(Constants.Defaults.InfectedChildrenStats), GetInfectedChildrenMetadata); ((Team)infectionTeam).DisplayName = "Infected Children"; InfectedChildren = infectionTeam; TeamManager.Register((Gamemode)(object)this); TeamManager.AddTeam(Infected); TeamManager.AddTeam(Survivors); TeamManager.AddTeam(InfectedChildren); TeamManager.OnAssignedToInfectedTeam += OnAssignedToTeam; InfectedLooking = new MetadataBool("InfectedLooking", ((Gamemode)this).Metadata); CountdownValue = new MetadataInt("CountdownValue", ((Gamemode)this).Metadata); ((Gamemode)this).Metadata.OnMetadataChanged += OnMetadataChanged; EventManager.RegisterEvent<string>(EventType.RefreshStats, StatsManager.RefreshStats, serverOnly: true); EventManager.RegisterEvent<PlayerInfectedData>(EventType.PlayerInfected, PlayerInfected, serverOnly: true); EventManager.RegisterEvent<SwapAvatarData>(EventType.SwapAvatar, SwapAvatarEvent, serverOnly: true); EventManager.RegisterEvent(EventType.TeleportToHost, TeleportToHost, serverOnly: true); EventManager.RegisterEvent(EventType.OneMinuteLeft, OneMinuteLeftEvent, serverOnly: true); EventManager.RegisterNotification(EventType.InfectedVictory, "Infected Won", "Everyone has been infected!", 4f, serverOnly: true, showPopup: true, (NotificationType)0); EventManager.RegisterNotification(EventType.SurvivorsVictory, "Survivors Won", "There were people not infected in time!", 4f, serverOnly: true, showPopup: true, (NotificationType)0); BoneMenuManager.Setup(); } private TeamMetadata GetInfectedChildrenMetadata() { if (!Config.SyncWithInfected.Value) { return InfectedChildren.StaticMetadata; } return Infected.Metadata; } private void OneMinuteLeftEvent() { MenuHelper.ShowNotification("Avatar Infection", "One minute left!", 3.5f, showPopup: true, (NotificationType)0); OneMinuteLeft = true; } private static void SwapAvatarEvent(SwapAvatarData data) { if (data.Target == PlayerIDManager.LocalPlatformID) { Overrides.SetAvatarOverride(data.Barcode, data.Origin); } } private void OnMetadataChanged(string key, string value) { ((Gamemode)this).OnMetadataChanged(key, value); if (!string.IsNullOrWhiteSpace(key) && !string.IsNullOrWhiteSpace(value) && ((Gamemode)this).IsStarted && key == "InfectedLooking" && ((MetadataVariableT<bool>)(object)InfectedLooking).GetValue()) { InfectedLookingEvent(); } } public override void OnGamemodeUnregistered() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown FusionOverrides.OnValidateNametag -= new UserOverride(OnValidateNameTag); MultiplayerHooking.OnPlayerAction -= new PlayerAction(OnPlayerAction); MultiplayerHooking.OnPlayerJoined -= new PlayerUpdate(OnPlayerJoin); MultiplayerHooking.OnPlayerLeft -= new PlayerUpdate(OnPlayerLeave); MultiplayerHooking.OnDisconnected -= new ServerEvent(Cleanup); TeamManager.Unregister(); ((Gamemode)this).Metadata.OnMetadataChanged -= OnMetadataChanged; EventManager.OnUnregistered(); BoneMenuManager.Destroy(); } private void OnPlayerLeave(PlayerID id) { if (NetworkInfo.IsHost && ((Gamemode)this).IsStarted) { ((TeamManager)TeamManager).TryUnassignTeam(id); if (((Team)Infected).PlayerCount == 0 && ((Team)InfectedChildren).PlayerCount == 0) { EventManager.TryInvokeEvent(EventType.SurvivorsVictory); GamemodeManager.StopGamemode(); } else if (((Team)Survivors).PlayerCount == 0) { EventManager.TryInvokeEvent(EventType.InfectedVictory); GamemodeManager.StopGamemode(); } } } private void OnPlayerJoin(PlayerID playerId) { if (NetworkInfo.IsHost && ((Gamemode)this).IsStarted && TeamManager.GetPlayerTeam(playerId) == null) { ((TeamManager)TeamManager).TryAssignTeam(playerId, (Team)(object)Survivors); } } private void InfectedLookingEvent() { if (((Gamemode)this).IsStarted && !IsInfected(TeamManager.GetLocalTeam())) { MenuHelper.ShowNotification("Run...", "The infected have awaken... you have to run... save yourselves.. please", 5f, showPopup: true, (NotificationType)1); } } private void PlayerInfected(PlayerInfectedData data) { ulong userId = data.UserId; long by = data.By; if (!((Gamemode)this).IsStarted) { return; } PlayerID playerID = PlayerIDManager.GetPlayerID(userId); if (playerID == null) { return; } if (by != -1 && by == (long)PlayerIDManager.LocalPlatformID) { PointItemManager.RewardBits(50, true); } if (NetworkInfo.IsHost && ((Team)Survivors).HasPlayer(playerID)) { if (((Team)Survivors).PlayerCount <= 1) { EventManager.TryInvokeEvent(EventType.InfectedVictory); GamemodeManager.StopGamemode(); } else { ((TeamManager)TeamManager).TryAssignTeam(playerID, (Team)(object)InfectedChildren); SetAvatar(playerID, isChildren: true); } } BoneMenuManager.PopulatePage(); } private void SurvivorNotification(PlayerID playerId) { string text = default(string); MetadataHelper.TryGetDisplayName(playerId, ref text); string value = (string.IsNullOrWhiteSpace(text) ? "N/A" : text); string value2 = "look out for them..."; if (((Team)Survivors).PlayerCount == 0) { value2 = "the last survivor has fallen..."; } MenuHelper.ShowNotification("Infected", $"{value} is now infected, {value2} ({((Team)Survivors).PlayerCount} survivors left)", 4f, showPopup: true, (NotificationType)0); } [IteratorStateMachine(typeof(<InfectedLookingWait>d__103))] private IEnumerator InfectedLookingWait() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <InfectedLookingWait>d__103(0) { <>4__this = this }; } private void OnAssignedToTeam(PlayerID player, InfectionTeam team) { FusionOverrides.ForceUpdateOverrides(); BoneMenuManager.PopulatePage(); if (team == null || player == null || !player.IsValid) { return; } if (player.IsMe) { StatsManager.ApplyStats(); team?.Metadata.CanUseGunsChanged(); } if (InitialTeam) { if (player.IsMe) { HandleInitialTeam(team); } } else if (team == InfectedChildren) { if (player.IsMe) { MenuHelper.ShowNotification("Infected", "Oh no, you got infected! Now you have to infect others...", 4f, showPopup: true, (NotificationType)0); } else if (!player.IsMe) { SurvivorNotification(player); } } } private void HandleInitialTeam(InfectionTeam team) { InitialTeam = false; if (team != Infected) { MenuHelper.ShowNotification("Survivor", "You got lucky! Make sure you don't get infected!", 3f, showPopup: true, (NotificationType)0); } if (!((MetadataVariableT<bool>)(object)InfectedLooking).GetValue()) { VisionManager.HideVisionAndReveal((team != Infected) ? 3 : 0); } } private void Timer() { if (!((Gamemode)this).IsStarted) { return; } _elapsedTime += TimeManager.DeltaTime; if (NetworkInfo.IsHost && !Config.NoTimeLimit.Value) { if (!OneMinuteLeft && Config.TimeLimit.Value - ElapsedMinutes == 1) { EventManager.TryInvokeEvent(EventType.OneMinuteLeft); } if (ElapsedMinutes >= Config.TimeLimit.Value) { EventManager.TryInvokeEvent(EventType.SurvivorsVictory); GamemodeManager.StopGamemode(); } } } private void SurvivorsUpdate() { if (((Gamemode)Instance).IsStarted && TeamManager.GetLocalTeam() == Survivors && _surivorsLastCheckedMinutes != ElapsedMinutes) { _surivorsLastCheckedMinutes = ElapsedMinutes; PointItemManager.RewardBits(75, true); } } public override bool CheckReadyConditions() { if (NetworkPlayer.Players.Count < 2) { Core.Logger.Error("There must be at least 2 players to start"); return false; } SelectedAvatarData value = Config.SelectedAvatar.Value; if (value != null && value.SelectMode == AvatarSelectMode.CONFIG && !AvatarConditions(Config.SelectedAvatar?.Value?.Barcode, "children")) { return false; } if (Config.ChildrenSelectedAvatar.Enabled) { SelectedAvatarData value2 = Config.ChildrenSelectedAvatar.Value; if (value2 != null && value2.SelectMode == AvatarSelectMode.CONFIG && !AvatarConditions(Config.ChildrenSelectedAvatar?.Value?.Barcode, "children")) { return false; } } if (NetworkPlayer.Players.Count <= Config.InfectedCount.Value) { Core.Logger.Error($"There must be at least {Config.InfectedCount.Value + 1} player(s) to start"); return false; } if (MetadataManager.CountPlayersWithAvatarInfection() <= Config.InfectedCount.Value) { Core.Logger.Error($"There must be at least {Config.InfectedCount.Value + 1} player(s) with AvatarInfection installed"); return false; } return true; } private static bool AvatarConditions(string barcode, string prefix = "") { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown Barcode val = new Barcode(barcode); if (string.IsNullOrWhiteSpace(barcode)) { Core.Logger.Error("No" + ((!string.IsNullOrWhiteSpace(prefix)) ? (" " + prefix + " ") : string.Empty) + "avatar selected while in CONFIG mode"); return false; } if (val == null || !BarcodeExtensions.IsValid(val) || val == null || !BarcodeExtensions.IsValidSize(val)) { Core.Logger.Error(((!string.IsNullOrWhiteSpace(prefix)) ? (FirstCharToUpper(prefix) + " ") : string.Empty) + "Avatar selected while in CONFIG mode is not valid"); return false; } Crate crate = default(Crate); if (!AssetWarehouse.Instance.TryGetCrate(val, ref crate)) { Core.Logger.Error(((!string.IsNullOrWhiteSpace(prefix)) ? (FirstCharToUpper(prefix) + " ") : string.Empty) + "Avatar selected while in CONFIG mode is not installed"); return false; } if (!crate.IsPublic()) { Core.Logger.Error(((!string.IsNullOrWhiteSpace(prefix)) ? (FirstCharToUpper(prefix) + " ") : string.Empty) + "Modded avatar selected while in CONFIG mode is not public"); return false; } return true; } private static string FirstCharToUpper(string input) { if (string.IsNullOrEmpty(input)) { return string.Empty; } DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(0, 2); defaultInterpolatedStringHandler.AppendFormatted(char.ToUpper(input[0])); defaultInterpolatedStringHandler.AppendFormatted(input.Substring(1, input.Length - 1)); return defaultInterpolatedStringHandler.ToStringAndClear(); } public override void OnGamemodeReady() { MetadataManager.IHaveAvatarInfection(); } public override void OnGamemodeSelected() { MetadataManager.IHaveAvatarInfection(); } public override bool CanAttack(PlayerID player) { if (!((Gamemode)this).IsStarted) { return true; } if (Config.FriendlyFire.Value) { return true; } InfectionTeam playerTeam = TeamManager.GetPlayerTeam(player); InfectionTeam localTeam = TeamManager.GetLocalTeam(); if (playerTeam != localTeam) { if (IsInfected(playerTeam)) { return !IsInfected(TeamManager.GetLocalTeam()); } return true; } return false; } private void ApplyGamemodeSettings() { AvatarSetting(AvatarSelectMode.RANDOM, delegate(AvatarSetting setting) { setting.SetRandomAvatar(); }); ((MetadataVariableT<int>)(object)CountdownValue).SetValue(Config.CountdownLength.Value); TeamManager.InfectedTeams.ForEach(delegate(InfectionTeam x) { x.Metadata.ApplyConfig(); }); DateTimeOffset now = DateTimeOffset.Now; Config.StartUnix.Value = now.ToUnixTimeMilliseconds(); if (!Config.NoTimeLimit.Value) { Config.EndUnix.Value = now.AddMinutes(Config.TimeLimit.Value).ToUnixTimeMilliseconds(); } else { Config.EndUnix.Value = -1L; } ((MetadataVariableT<bool>)(object)InfectedLooking).SetValue(false); } public override void OnGamemodeStarted() { ((Gamemode)this).OnGamemodeStarted(); PlayList.SetPlaylist(AudioReference.CreateReferences(Constants.Tracks)); PlayList.Shuffle(); RevertToDefault(); if (NetworkInfo.IsHost) { EnsureKnockout(); ApplyGamemodeSettings(); AssignTeams(); MelonCoroutines.Start(InfectedLookingWait()); if (Config.TeleportOnStart.Value) { EventManager.TryInvokeEvent(EventType.TeleportToHost); } } PlayList.StartPlaylist(); FusionSceneManager.HookOnTargetLevelLoad((Action)delegate { BoneMenuManager.PopulatePage(); StatsManager.ApplyStats(); Config.SelectedPlayerOverride(); if (Config.UseDeathmatchSpawns.Value) { UseDeathmatchSpawns_Init(!Config.TeleportOnStart.Value); } else { ClearDeathmatchSpawns(); } }); if (NetworkInfo.IsHost) { GamemodeMenuManager.RefreshSettingsPage(); } } private void EnsureKnockout() { if (!NetworkInfo.IsHost) { return; } if (!((Gamemode)this).IsStarted) { KnockoutFirstCheck = true; if (KnockoutRevert) { SavedServerSettings.Knockout.Value = true; KnockoutRevert = false; } return; } LocalSetting<InfectType> infectType = Config.InfectType; if (infectType == null || infectType.Value != InfectType.DEATH) { return; } if (CommonPreferences.Knockout) { if (KnockoutFirstCheck) { KnockoutRevert = true; } SavedServerSettings.Knockout.Value = false; } KnockoutFirstCheck = false; } private void RevertToDefault(bool wasStarted = true) { KnockoutRevert = false; KnockoutFirstCheck = true; HasBeenInfected = false; _elapsedTime = 0f; _surivorsLastCheckedMinutes = 0; OneMinuteLeft = false; VisionManager.HideVision = false; InitialTeam = true; WasStarted = wasStarted; ((MetadataVariableT<bool>)(object)InfectedLooking).SetValue(false); } internal static void UseDeathmatchSpawns_Init(bool teleport = true) { if (!appliedDeathmatchSpawns) { appliedDeathmatchSpawns = true; GamemodeHelper.SetSpawnPoints((IEnumerable<GamemodeMarker>)GamemodeMarker.FilterMarkers((BoneTagReference)null)); if (teleport) { GamemodeHelper.TeleportToSpawnPoint(); } } } internal static void ClearDeathmatchSpawns() { appliedDeathmatchSpawns = false; GamemodeHelper.ResetSpawnPoints(); } public override void OnGamemodeStopped() { ((Gamemode)this).OnGamemodeStopped(); Cleanup(); if (NetworkInfo.HasServer) { if (NetworkInfo.IsHost) { ((TeamManager)TeamManager).UnassignAllPlayers(); } else if (Config.TeleportOnEnd.Value) { TeleportToHost(); } if (NetworkInfo.IsHost) { GamemodeMenuManager.RefreshSettingsPage(); } } } private void Cleanup() { if (WasStarted) { BoneMenuManager.PopulatePage(); RevertToDefault(wasStarted: false); PlayList.StopPlaylist(); ClearDeathmatchSpawns(); StatsManager.ClearOverrides(); LocalAvatar.HeightOverride = null; FusionOverrides.ForceUpdateOverrides(); } } private static void TeleportToHost() { //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) NetworkPlayer val = default(NetworkPlayer); if (!NetworkInfo.IsHost && NetworkPlayerManager.TryGetPlayer(PlayerID.op_Implicit(PlayerIDManager.GetHostID()), ref val) && val.HasRig) { LocalPlayer.TeleportToPosition(val.RigRefs.RigManager.physicsRig.feet.transform.position, Vector3.forward); } } protected bool OnValidateNameTag(PlayerID id) { if (!((Gamemode)this).IsStarted) { return true; } InfectionTeam playerTeam = TeamManager.GetPlayerTeam(id); InfectionTeam localTeam = TeamManager.GetLocalTeam(); if (playerTeam != localTeam) { if (IsInfected(playerTeam)) { return IsInfected(localTeam); } return false; } return true; } private void AssignTeams() { List<ulong> last = new List<ulong>(LastInfected); LastInfected.Clear(); List<PlayerID> list = new List<PlayerID>(PlayerIDManager.PlayerIDs); IEnumerableExtensions.Shuffle<PlayerID>((IList<PlayerID>)list); bool flag = false; int num = 0; int num2 = 0; List<PlayerID> list2 = new List<PlayerID>(list); list2.RemoveAll((PlayerID x) => last.Contains(x.PlatformID)); bool flag2 = false; if (list2.Count < Config.InfectedCount.Value) { last.Clear(); } else { list.RemoveAll((PlayerID x) => last.Contains(x.PlatformID)); flag2 = true; } while (num2 < 1000) { num2++; if (num >= Config.InfectedCount.Value) { break; } PlayerID val = list.Random(); if (MetadataManager.DoYouHaveAvatarInfection(val)) { num++; InfectionTeam infected = Infected; ((TeamManager)TeamManager).TryAssignTeam(val, (Team)(object)infected); if (!flag) { flag = TrySetFirstInfected(val); } SetAvatar(val, infected == InfectedChildren); list.Remove(val); LastInfected.Add(val.PlatformID); } } if (!flag) { AvatarSetting(AvatarSelectMode.FIRST_INFECTED, delegate(AvatarSetting setting) { setting.SetRandomAvatar(); }); } if (flag2) { list.AddRange(((IEnumerable<ulong>)last).Select((Func<ulong, PlayerID>)PlayerIDManager.GetPlayerID)); } list.ForEach(delegate(PlayerID x) { ((TeamManager)TeamManager).TryAssignTeam(x, (Team)(object)Survivors); }); } private bool TrySetFirstInfected(PlayerID player) { NetworkPlayer val = default(NetworkPlayer); if (NetworkPlayerManager.TryGetPlayer(player.SmallID, ref val) && val.HasRig) { RigRefs rigRefs = val.RigRefs; object obj; if (rigRefs == null) { obj = null; } else { RigManager rigManager = rigRefs.RigManager; if (rigManager == null) { obj = null; } else { AvatarCrateReference avatarCrate = rigManager.AvatarCrate; if (avatarCrate == null) { obj = null; } else { Barcode barcode = ((ScannableReference)avatarCrate).Barcode; obj = ((barcode != null) ? barcode.ID : null); } } } string avatar = (string)obj; if (!string.IsNullOrWhiteSpace(avatar) && player.IsAvatarDownloadable()) { AvatarSetting(AvatarSelectMode.FIRST_INFECTED, delegate(AvatarSetting setting) { setting.SetAvatar(avatar, player); }); return true; } } return false; } private void AvatarSetting(AvatarSelectMode target, Action<AvatarSetting> callback) { foreach (ISetting settings in Config._settingsList) { if (settings is AvatarSetting avatarSetting) { SelectedAvatarData value = avatarSetting.Value; if (value != null && value.SelectMode == target) { callback?.Invoke(avatarSetting); } } } } private void SetAvatar(PlayerID player, bool isChildren) { if (!isChildren || (isChildren && !Config.ChildrenSelectedAvatar.Enabled)) { EventManager.TryInvokeEvent(EventType.SwapAvatar, SwapAvatarData.Create(player, Config.SelectedAvatar)); } else { EventManager.TryInvokeEvent(EventType.SwapAvatar, SwapAvatarData.Create(player, Config.ChildrenSelectedAvatar)); } } protected void OnPlayerAction(PlayerID player, PlayerActionType type, PlayerID otherPlayer = null) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Invalid comparison between Unknown and I4 //IL_0031: Unknown result type (might be due to invalid IL or missing references) if (((Gamemode)this).IsStarted && NetworkInfo.IsHost) { if ((int)type == 5) { KilledEvent(player, otherPlayer); } else if ((int)type == 3) { DyingEvent(player, otherPlayer); } LastPlayerActions[player] = type; } } private void DyingEvent(PlayerID player, PlayerID otherPlayer) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Invalid comparison between Unknown and I4 if (Config.SuicideInfects.Value && otherPlayer == null && (!LastPlayerActions.ContainsKey(player) || (int)LastPlayerActions[player] != 5) && TeamManager.GetPlayerTeam(player) == Survivors) { EventManager.TryInvokeEvent(EventType.PlayerInfected, new PlayerInfectedData(player.PlatformID, -1L)); } } private void KilledEvent(PlayerID player, PlayerID killer) { if (killer != null && killer.IsValid && Config.InfectType.Value == InfectType.DEATH && TeamManager.GetPlayerTeam(player) == Survivors && IsPlayerInfected(killer)) { EventManager.TryInvokeEvent(EventType.PlayerInfected, new PlayerInfectedData(player.PlatformID, (long)killer.PlatformID)); } } } internal class SwapAvatarData { public ulong Target { get; set; } public string Barcode { get; set; } public long Origin { get; set; } public SwapAvatarData(ulong target, string barcode, long origin = -1L) { Target = target; Barcode = barcode; Origin = origin; base..ctor(); } public static SwapAvatarData Create(PlayerID player, AvatarSetting setting) { return new SwapAvatarData(player.PlatformID, setting.Value?.Barcode, setting.Value?.Origin ?? (-1)); } } internal class PlayerInfectedData { public ulong UserId { get; set; } public long By { get; set; } public PlayerInfectedData(ulong userId, long by) { UserId = userId; By = by; base..ctor(); } } } namespace AvatarInfection.Utilities { internal static class LabPresenceExtension { public const string SmallImage = "hahoos_avatarinfection"; public static MelonBase LabPresenceMelon => MelonBase.FindMelon("LabPresence", "HAHOOS"); public static void Init() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown if (LabPresenceMelon != null) { MelonInfoAttribute info = LabPresenceMelon.Info; if (((info != null) ? info.SemanticVersion : null) >= new SemVersion(1, 3, 0, "", "")) { Internal_Init(); return; } } FusionModule.Logger.Warn("Could not find LabPresence (minimum version required: v1.3.0)"); } internal static void Internal_Init() { GamemodeManager.RegisterGamemode("HAHOOS.Avatar Infection", (Func<string>)CustomToolTip, (Func<Timestamp>)CustomTimestamp, "hahoos_avatarinfection"); } private static string CustomToolTip() { return $"{((Team)Infection.Instance.Survivors).PlayerCount} survivors left!"; } private static Timestamp CustomTimestamp() { //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Expected O, but got Unknown if (Infection.Instance.Config.StartUnix.Value == -1 && Infection.Instance.Config.EndUnix.Value == -1) { return null; } long value = Infection.Instance.Config.StartUnix.Value; long? num = Infection.Instance.Config.EndUnix.Value; if (num == -1) { num = null; } return new Timestamp((ulong?)(ulong)value, (ulong?)num); } } public static class Overrides { public static float? Speed { get; private set; } public static float? Agility { get; private set; } public static float? StrengthUpper { get; private set; } public static float? Vitality { get; private set; } public static bool? Mortality { get; private set; } public static string Avatar { get; private set; } public static string LastAvatar { get; private set; } internal static void SetOverrides(float? speed, float? agility, float? strengthUpper, float? vitality, bool? mortality) { Speed = speed; Agility = agility; StrengthUpper = strengthUpper; Vitality = vitality; Mortality = mortality; RigManager rigManager = Player.RigManager; Avatar val = ((rigManager != null) ? rigManager._avatar : null); if ((Object)(object)val != (Object)null) { if (SetOverrideValue(Agility, val._agility, out var changed, out var res)) { val._agility = res; } if (SetOverrideValue(Speed, val._speed, out var changed2, out var res2)) { val._speed = res2; } if (SetOverrideValue(StrengthUpper, val._strengthUpper, out var changed3, out var res3)) { val._strengthUpper = res3; val._strengthGrip = res3; } if (SetOverrideValue(Vitality, val._speed, out var changed4, out var res4)) { val._vitality = res4; } SetMortality(mortality, out var changed5); if (changed || changed2 || changed3 || changed4 || changed5) { rigManager.SwapAvatarCrate(((ScannableReference)rigManager.AvatarCrate).Barcode, false, (Action<bool>)null); } } } private static bool SetOverrideValue(float? _override, float? actual, out bool changed, out float res) { changed = false; if (_override.HasValue && !actual.Equals(Agility.Value)) { changed = true; res = _override.Value; return true; } res = -1f; return false; } public static void RefreshAvatar() { RigManager rigManager = Player.RigManager; if (((rigManager != null) ? rigManager.AvatarCrate : null) != null) { rigManager.SwapAvatarCrate(((ScannableReference)rigManager.AvatarCrate).Barcode, false, (Action<bool>)null); } } private static void SetMortality(bool? mortality, out bool changed) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected I4, but got Unknown changed = false; RigManager rigManager = Player.RigManager; if ((Object)(object)((rigManager != null) ? rigManager.health : null) != (Object)null && mortality.HasValue) { HealthMode val = (HealthMode)(mortality.Value ? 1 : 0); changed = rigManager.health.healthMode != val; rigManager.health.SetHealthMode((int)val); } } internal static void ClearAllOverrides() { if (!Agility.HasValue && !Speed.HasValue && !StrengthUpper.HasValue && !Vitality.HasValue && !Mortality.HasValue) { return; } Agility = null; Speed = null; StrengthUpper = null; Vitality = null; Mortality = null; if ((Object)(object)Player.RigManager != (Object)null) { RigManager rigManager = Player.RigManager; if (rigManager.AvatarCrate != null) { rigManager.SwapAvatarCrate(((ScannableReference)rigManager.AvatarCrate).Barcode, false, (Action<bool>)null); } } } public static void SetAvatarOverride(string barcode, long origin = -1L) { bool flag = string.IsNullOrEmpty(Avatar); if ((Object)(object)Player.RigManager != (Object)null && AssetWarehouse.ready && flag) { LastAvatar = ((ScannableReference)Player.RigManager.AvatarCrate).Barcode.ID ?? "c3534c5a-94b2-40a4-912a-24a8506f6c79"; } Avatar = barcode; SwapAvatar(barcode, origin, (ModResult)0); } public static void ClearAvatarOverride() { Avatar = null; if ((Object)(object)Player.RigManager != (Object)null && !string.IsNullOrWhiteSpace(LastAvatar) && AssetWarehouse.ready) { SwapAvatar(LastAvatar, -1L, (ModResult)0); LastAvatar = null; } } private static void ForceChange(string barcode) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown GameObject val = new GameObject("AI_PCFC"); PullCordForceChange obj = val.GetComponent<PullCordForceChange>() ?? val.AddComponent<PullCordForceChange>(); obj.avatarCrate = new AvatarCrateReference(barcode); obj.rigManager = Player.RigManager; obj.ForceChange(((Component)Player.RigManager).gameObject); Object.Destroy((Object)(object)val); } private static void SwapAvatar(string barcode, long origin = -1L, ModResult downloadResult = 0) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Invalid comparison between Unknown and I4 //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Invalid comparison between Unknown and I4 //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Expected O, but got Unknown //IL_014c: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrWhiteSpace(barcode) || barcode == Barcode.EMPTY || (Object)(object)Player.RigManager == (Object)null) { return; } if (CrateFilterer.HasCrate<AvatarCrate>(new Barcode(barcode))) { ForceChange(barcode); } else { if (!ClientSettings.Downloading.DownloadAvatars.Value) { return; } if ((int)downloadResult == 1 || (int)downloadResult == 3) { FusionModule.Logger.Error("Download of avatar '" + barcode + "' has failed, not setting avatar"); return; } if (origin > 0) { origin = (long)PlayerIDManager.GetHostID().PlatformID; } PlayerID val = ((IEnumerable<PlayerID>)PlayerIDManager.PlayerIDs).FirstOrDefault((Func<PlayerID, bool>)((PlayerID x) => x.PlatformID == (ulong)origin)); if (val == null) { FusionModule.Logger.Error("Cannot download avatar '" + barcode + "', the player that has the avatar was not found"); return; } ModInstallInfo val2 = default(ModInstallInfo); val2.Barcode = barcode; val2.Target = val.SmallID; val2.FinishDownloadCallback = (DownloadCallback)delegate(DownloadCallbackInfo ev) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) SwapAvatar(barcode, origin, ev.Result); }; val2.MaxBytes = DataConversions.ConvertMegabytesToBytes((long)ClientSettings.Downloading.MaxFileSize.Value); val2.HighPriority = true; NetworkModRequester.RequestAndInstallMod(val2); } } } public class Thunderstore { public readonly string UserAgent; private Package _fetchedPackage; private bool _isLatestVersion; private string _currentVersion; public bool IsV1Deprecated { get; set; } public Thunderstore(string userAgent) { UserAgent = userAgent; } public Thunderstore(string userAgent, bool isV1Deprecated) : this(userAgent) { IsV1Deprecated = isV1Deprecated; } public Thunderstore() { Assembly executingAssembly = Assembly.GetExecutingAssembly(); if (executingAssembly != null) { AssemblyName name = executingAssembly.GetName(); if (name != null) { UserAgent = $"{name.Name} / {name.Version} C# Application"; } } } public Thunderstore(bool isV1Deprecated) { IsV1Deprecated = isV1Deprecated; Assembly executingAssembly = Assembly.GetExecutingAssembly(); if (executingAssembly != null) { AssemblyName name = executingAssembly.GetName(); if (name != null) { UserAgent = $"{name.Name} / {name.Version}"; } } } public void BL_FetchPackage(string name, string author, string currentVersion, Instance logger = null) { if (_fetchedPackage != null) { return; } _currentVersion = currentVersion; try { _fetchedPackage = GetPackage(author, name); if (_fetchedPackage == null && logger != null) { logger.Warning("Could not find Thunderstore package for " + name); } if (string.IsNullOrWhiteSpace(_fetchedPackage.Latest?.Version) && logger != null) { logger.Warning("Latest version could not be found or the version is empty"); } _isLatestVersion = _fetchedPackage.IsLatestVersion(currentVersion); if (!_isLatestVersion) { if (logger != null) { logger.Warning($"A new version of {name} is available: v{_fetchedPackage.Latest.Version} while the current is v{currentVersion}. It is recommended that you update"); } } else if (SemVersion.Parse(currentVersion, false) == _fetchedPackage.Latest.SemanticVersion) { if (logger != null) { logger.Msg($"Latest version of {name} is installed! (v{currentVersion})"); } } else if (logger != null) { logger.Msg($"Beta release of {name} is installed (v{_fetchedPackage.Latest.Version} is newest, v{currentVersion} is installed)"); } } catch (ThunderstorePackageNotFoundException) { if (logger != null) { logger.Warning("Could not find Thunderstore package for " + name); } } catch (Exception ex2) { if (logger != null) { logger.Error("An unexpected error has occurred while trying to check if " + name + " is the latest version", ex2); } } } public void BL_CreateMenuLabel(Page page, bool createBlankSpace = true) { //IL_0012: 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) if (_fetchedPackage != null) { if (createBlankSpace) { ((Element)page.CreateFunction("", Color.white, (Action)null)).SetProperty((ElementProperties)1); } ((Element)page.CreateFunction("Current Version: v" + _currentVersion + ((_isLatestVersion || _fetchedPackage == null) ? string.Empty : "<br><color=#00FF00>(Update available!)</color>"), Color.white, (Action)null)).SetProperty((ElementProperties)1); } } public void BL_SendNotification() { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_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_009e: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown if (_fetchedPackage != null && !_isLatestVersion) { NotificationText message = default(NotificationText); ((NotificationText)(ref message))..ctor($"There is a new version of {_fetchedPackage.Name}. Go to Thunderstore and download the latest version which is <color=#00FF00>v{_fetchedPackage.Latest.Version}</color>", Color.white, true); Notifier.Send(new Notification { Title = NotificationText.op_Implicit("Update!"), Message = message, PopupLength = 5f, ShowTitleOnPopup = true, Type = (NotificationType)1 }); } } public Package GetPackage(string @namespace, string name, string version = null) { Package package = SendRequest<Package>($"https://thunderstore.io/api/experimental/package/{@namespace}/{name}/{version ?? string.Empty}"); if (!IsV1Deprecated && package != null) { V1PackageMetrics packageMetrics = GetPackageMetrics(@namespace, name); if (packageMetrics != null) { package.TotalDownloads = packageMetrics.Downloads; package.RatingScore = packageMetrics.RatingScore; } } return package; } private static bool IsTaskGood<T>(Task<T> task) where T : class { if (task != null && task.IsCompletedSuccessfully) { return task.Result != null; } return false; } public T SendRequest<T>(string url) { Task<HttpResponseMessage> async = new HttpClient(new HttpClientHandler { ClientCertificateOptions = ClientCertificateOption.Manual, ServerCertificateCustomValidationCallback = (HttpRequestMessage _, X509Certificate2? _, X509Chain? _, SslPolicyErrors _) => true }) { DefaultRequestHeaders = { { "User-Agent", UserAgent }, { "Accept", "application/json" } } }.GetAsync(url); async.Wait(); HttpResponseMessage httpResponseMessage = async?.Result; if (IsTaskGood(async)) { if (!httpResponseMessage.IsSuccessStatusCode) { HandleHttpError(httpResponseMessage); return default(T); } Task<string> task = httpResponseMessage.Content.ReadAsStringAsync(); task.Wait(); string text = task?.Result; if (IsTaskGood(task)) { return JsonConvert.DeserializeObject<T>(text); } } return default(T); } private static void HandleHttpError(HttpResponseMessage result) { if (IsThunderstoreError(result, out var details)) { if (IsPackageNotFound(result, details)) { throw new ThunderstorePackageNotFoundException("Thunderstore could not find the package"); } throw new ThunderstoreErrorException("Thunderstore API has thrown an unexpected error!", result); } result.EnsureSuccessStatusCode(); } public V1PackageMetrics GetPackageMetrics(string @namespace, string name) { if (IsV1Deprecated) { return null; } return SendRequest<V1PackageMetrics>($"https://thunderstore.io/api/v1/package-metrics/{@namespace}/{name}/"); } public bool IsLatestVersion(string @namespace, string name, string currentVersion) { SemVersion currentVersion2 = default(SemVersion); if (SemVersion.TryParse(currentVersion, ref currentVersion2, false)) { return IsLatestVersion(@namespace, name, currentVersion2); } return false; } public bool IsLatestVersion(string @namespace, string name, Version currentVersion) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown return IsLatestVersion(@namespace, name, new SemVersion(currentVersion)); } public bool IsLatestVersion(string @namespace, string name, SemVersion currentVersion) { if (!IsV1Deprecated) { return GetPackageMetrics(@namespace, name)?.IsLatestVersion(currentVersion) ?? false; } return GetPackage(@namespace, name)?.IsLatestVersion(currentVersion) ?? false; } private static bool IsPackageNotFound(HttpResponseMessage response, string details = "") { if (response.StatusCode != HttpStatusCode.NotFound) { return false; } if (details != null && details.Length == 0) { details = GetDetails(response); } return string.Equals(details, "Not found.", StringComparison.OrdinalIgnoreCase); } private static bool IsThunderstoreError(HttpResponseMessage response, out string details) { details = GetDetails(response); return !string.IsNullOrWhiteSpace(details); } private static string GetDetails(HttpResponseMessage response) { if (response.IsSuccessStatusCode) { return null; } Task<string> task = response.Content.ReadAsStringAsync(); task.Wait(); string result = task.Result; if (string.IsNullOrWhiteSpace(result)) { return null; } ThunderstoreErrorResponse thunderstoreErrorResponse; try { thunderstoreErrorResponse = JsonConvert.DeserializeObject<ThunderstoreErrorResponse>(result); } catch (JsonException) { return null; } if (!string.IsNullOrWhiteSpace(thunderstoreErrorResponse?.Details)) { return thunderstoreErrorResponse.Details; } return null; } } public class Package { [JsonProperty("namespace")] public string Namespace { get; internal set; } [JsonProperty("name")] public string Name { get; internal set; } [JsonProperty("full_name")] public string FullName { get; internal set; } [JsonProperty("owner")] public string Owner { get; internal set; } [JsonProperty("package_url")] public string PackageURL { get; internal set; } [JsonProperty("date_created")] public DateTime CreatedAt { get; internal set; } [JsonProperty("date_updated")] public DateTime UpdatedAt { get; internal set; } [JsonProperty("rating_score")] public int RatingScore { get; internal set; } [JsonProperty("is_pinned")] public bool IsPinned { get; internal set; } [JsonProperty("is_deprecated")] public bool IsDeprecated { get; internal set; } [JsonProperty("total_downloads")] public int TotalDownloads { get; internal set; } [JsonProperty("latest")] public PackageVersion Latest { get; internal set; } [JsonProperty("community_listings")] public PackageListing[] CommunityListings { get; internal set; } public bool IsLatestVersion(string current) { if (string.IsNullOrWhiteSpace(current)) { return false; } if (Latest == null || Latest.SemanticVersion == (SemVersion)null) { return false; } SemVersion val = default(SemVersion); if (SemVersion.TryParse(current, ref val, false)) { return val >= Latest.SemanticVersion; } return false; } public bool IsLatestVersion(SemVersion current) { if (current == (SemVersion)null) { return false; } if (Latest == null || Latest.SemanticVersion == (SemVersion)null) { return false; } return current >= Latest.SemanticVersion; } public bool IsLatestVersion(Version current) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown if (current == null) { return false; } if (Latest == null || Latest.SemanticVersion == (SemVersion)null) { return false; } return new SemVersion(current) >= Latest.SemanticVersion; } } public class PackageVersion { [JsonProperty("namespace")] public string Namespace { get; internal set; } [JsonProperty("name")] public string Name { get; internal set; } [JsonProperty("version_number")] public string Version { get { return ((object)SemanticVersion).ToString(); } internal set { SemanticVersion = SemVersion.Parse(value, false); } } [JsonIgnore] public SemVersion SemanticVersion { get; internal set; } [JsonProperty("full_name")] public string FullName { get; internal set; } [JsonProperty("description")] public string Description { get; internal set; } [JsonProperty("icon")] public string Icon { get; internal set; } [JsonProperty("dependencies")] public List<string> Dependencies { get; internal set; } [JsonProperty("download_url")] public string DownloadURL { get; internal set; } [JsonProperty("date_created")] public DateTime CreatedAt { get; internal set; } [JsonProperty("downloads")] public int Downloads { get; internal set; } [JsonProperty("website_url")] public string WebsiteURL { get; internal set; } [JsonProperty("is_active")] public bool IsActive { get; internal set; } } public class PackageListing { public enum ReviewStatus { UNREVIEWED, APPROVED, REJECTED } [JsonProperty("has_nsfw_content")] public bool HasNSFWContent { get; internal set; } [JsonProperty("categories")] public List<string> Categories { get; internal set; } [JsonProperty("community")] public string Community { get; internal set; } [JsonProperty("review_status")] public string ReviewStatusString { get { return ReviewStatusValue.ToString(); } internal set { if (value == null) { throw new ArgumentNullException("value"); } if (string.Equals(value, "unreviewed", StringComparison.OrdinalIgnoreCase)) { ReviewStatusValue = ReviewStatus.UNREVIEWED; } else if (string.Equals(value, "approved", StringComparison.OrdinalIgnoreCase)) { ReviewStatusValue = ReviewStatus.APPROVED; } else if (string.Equals(value, "rejected", StringComparison.OrdinalIgnoreCase)) { ReviewStatusValue = ReviewStatus.REJECTED; } } } [JsonIgnore] public ReviewStatus ReviewStatusValue { get; internal set; } } public class V1PackageMetrics { [JsonProperty("downloads")] public int Downloads { get; internal set; } [JsonProperty("rating_score")] public int RatingScore { get; internal set; } [JsonProperty("latest_version")] public string LatestVersion { get { return ((object)LatestSemanticVersion).ToString(); } internal set { LatestSemanticVersion = SemVersion.Parse(value, false); } } [JsonIgnore] public SemVersion LatestSemanticVersion { get; internal set; } public bool IsLatestVersion(string current) { if (string.IsNullOrWhiteSpace(current)) { return false; } if (LatestSemanticVersion == (SemVersion)null) { return false; } SemVersion val = default(SemVersion); if (SemVersion.TryParse(current, ref val, false)) { return val >= LatestSemanticVersion; } return false; } public bool IsLatestVersion(SemVersion current) { if (current == (SemVersion)null) { return false; } if (LatestSemanticVersion == (SemVersion)null) { return false; } return current >= LatestSemanticVersion; } public bool IsLatestVersion(Version current) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown if (current == null) { return false; } if (LatestSemanticVersion == (SemVersion)null) { return false; } return new SemVersion(current) >= LatestSemanticVersion; } } public class ThunderstoreErrorResponse { [JsonProperty("detail")] public string Details { get; internal set; } } public class ThunderstoreErrorException : Exception { public string Details { get; } public HttpStatusCode HttpStatusCode { get; } public ThunderstoreErrorException() { } public ThunderstoreErrorException(string message) : base(message) { } public ThunderstoreErrorException(string message, Exception innerException) : base(message, innerException) { } public ThunderstoreErrorException(string message, string details, HttpStatusCode httpStatusCode, Exception innerException) : base(message, innerException) { Details = details; HttpStatusCode = httpStatusCode; } public ThunderstoreErrorException(string message, HttpResponseMessage response) : base(message) { if (response.IsSuccessStatusCode) { return; } HttpStatusCode = response.StatusCode; Task<string> task = response.Content.ReadAsStringAsync(); task.Wait(); string result = task.Result; if (string.IsNullOrWhiteSpace(result)) { Details = string.Empty; return; } ThunderstoreErrorResponse thunderstoreErrorResponse; try { thunderstoreErrorResponse = JsonConvert.DeserializeObject<ThunderstoreErrorResponse>(result); } catch (JsonException) { Details = string.Empty; return; } if (thunderstoreErrorResponse != null) { Details = thunderstoreErrorResponse.Details; } } } public class ThunderstorePackageNotFoundException : ThunderstoreErrorException { public string Namespace { get; } public string Name { get; } public string Version { get; } public ThunderstorePackageNotFoundException(string message, string @namespace, string name, string details, HttpStatusCode httpStatusCode, Exception innerException) : base(message, details, httpStatusCode, innerException) { Namespace = @namespace; Name = name; } public ThunderstorePackageNotFoundException(string message, string @namespace, string name, string version, string details, HttpStatusCode httpStatusCode, Exception innerException) : base(message, details, httpStatusCode, innerException) { Namespace = @namespace; Name = name; Version = version; } public ThunderstorePackageNotFoundException(string message, string @namespace, string name, HttpResponseMessage response) : base(message, response) { Namespace = @namespace; Name = name; } public ThunderstorePackageNotFoundException(string message, string @namespace, string name, string version, HttpResponseMessage response) : base(message, response) { Namespace = @namespace; Name = name; Version = version; } public ThunderstorePackageNotFoundException() { } public ThunderstorePackageNotFoundException(string message) : base(message) { } public ThunderstorePackageNotFoundException(string message, Exception innerException) : base(message, innerException) { } public ThunderstorePackageNotFoundException(string message, string details, HttpStatusCode httpStatusCode, Exception innerException) : base(message, details, httpStatusCode, innerException) { } public ThunderstorePackageNotFoundException(string message, HttpResponseMessage response) : base(message, response) { } } public class ToggleMetadataVariable { private static readonly JsonSerializerOptions SerializerOptions = new JsonSerializerOptions { IncludeFields = true }; public NetworkMetadata Metadata { get; } public string Key { get; } [JsonIgnore] public bool IsEnabled { get { if (!bool.TryParse(Metadata.GetMetadata(ToggledKey), out var result)) { return false; } return result; } } public string ToggledKey => Key + "-Toggled"; public ToggleMetadataVariable(string key, NetworkMetadata metadata) { Metadata = metadata; Key = key; base..ctor(); } public void Remove() { Metadata.TryRemoveMetadata(Key); Metadata.TryRemoveMetadata(ToggledKey); } public void SetValue(string value) { Metadata.TrySetMetadata(Key, value); } public void SetValue<TValue>(TValue value) { SetValue(JsonSerializer.Serialize(value, SerializerOptions)); } public void Toggle() { if (bool.TryParse(Metadata.GetMetadata(ToggledKey), out var result)) { Metadata.TrySetMetadata(ToggledKey, (!result).ToString()); } else { Metadata.TrySetMetadata(ToggledKey, true.ToString()); } } public void SetEnabled(bool enabled) { Metadata.TrySetMetadata(ToggledKey, enabled.ToString()); } public string GetValue() { return Metadata.GetMetadata(Key); } public TValue GetValue<TValue>() { string value = GetValue(); if (string.IsNullOrEmpty(value)) { return default(TValue); } return JsonSerializer.Deserialize<TValue>(value, SerializerOptions); } } public class ToggleMetadataVariableT<TValue> : ToggleMetadataVariable { public ToggleMetadataVariableT(string key, NetworkMetadata metadata) : base(key, metadata) { } public void SetValue(TValue value) { base.SetValue(value); } public new TValue GetValue() { return GetValue<TValue>(); } } } namespace AvatarInfection.Settings { public class AvatarSetting : ToggleServerSetting<SelectedAvatarData> { public string GroupName { get; set; } public bool Optional { get; set; } public AvatarSelectMode[] DisallowedSelectModes { get; set; } = Array.Empty<AvatarSelectMode>(); public string OptionalToggle { get; set; } = "Seperate From Main"; public GroupElementData CreateGroup() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown GroupElementData val2 = new GroupElementData(GroupName); if (Optional) { val2.AddElement(OptionalToggle, base.Enabled, delegate(bool val) { base.Enabled = val; GamemodeMenuManager.RefreshSettingsPage(); }); } if (Optional && !base.Enabled) { return val2; } val2.AddElement($"Select Mode: {base.Value?.SelectMode ?? AvatarSelectMode.CONFIG}", SelectModeElement); SelectedAvatarData value = base.Value; if (value != null && value.SelectMode == AvatarSelectMode.CONFIG) { string barcodeTitle = GetBarcodeTitle(Infection.Instance.Config.SelectedAvatar.Value?.Barcode); val2.AddElement(barcodeTitle, null); val2.AddElement("Select From Current Avatar", SelectNewAvatar); } else { SelectedAvatarData value2 = base.Value; if (value2 != null && value2.SelectMode == AvatarSelectMode.RANDOM) { val2.AddElement($"Chosen from {GetAvatars().Length} Avatars", null); if (((Gamemode)Infection.Instance).IsStarted) { val2.AddElement("Select New Random Avatar", delegate { if (((Gamemode)Infection.Instance).IsStarted) { SetRandomAvatar(); } }); } } } return val2; } private void SelectModeElement() { Array values = Enum.GetValues(typeof(AvatarSelectMode)); int num = 0; for (int i = 0; i < values.Length; i++) { if ((AvatarSelectMode)values.GetValue(i) == base.Value?.SelectMode) { num = i; break; } } if (!values.Cast<AvatarSelectMode>().All((AvatarSelectMode x) => DisallowedSelectModes.Contains(x))) { do { num++; num %= values.Length; } while (DisallowedSelectModes.Contains((AvatarSelectMode)values.GetValue(num))); SetSelectMode((AvatarSelectMode)values.GetValue(num)); GamemodeMenuManager.RefreshSettingsPage(); } } public Barcode AsBarcode() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown if (base.Value == null) { return null; } return new Barcode(base.Value.Barcode); } public void SetRandomAvatar() { string barcode = GetAvatars().Random(); SetAvatar(barcode, PlayerIDManager.LocalID); } public static string GetRandomAvatar() { return GetAvatars().Random(); } public static string[] GetAvatars() { List<AvatarCrate> crates = AssetWarehouse.Instance.GetCrates<AvatarCrate>((ICrateFilter<AvatarCrate>)null); crates.ExcludeRedacted(); crates.ExcludeNonPublic(); return ((IEnumerable<AvatarCrate>)crates.ToArray()).Select((AvatarCrate x) => ((Scannable)x).Barcode.ID).ToArray(); } public void SetSelectMode(AvatarSelectMode mode) { if (base.Value != null) { base.Value.SelectMode = mode; if (base.AutoSync) { Sync(); } } else { base.Value = new SelectedAvatarData(null, mode, -1L); } } public void SetAvatar(string barcode, PlayerID player) { if (base.Value != null) { base.Value.Barcode = barcode; base.Value.Origin = (long)player.PlatformID; if (base.AutoSync) { Sync(); } } else { base.Value = new SelectedAvatarData(barcode, AvatarSelectMode.CONFIG, PlayerID.op_Implicit(player)); } } private void SelectNewAvatar() { if (((Gamemode)Infection.Instance).IsStarted) { return; } RigManager rigManager = Player.RigManager; object obj; if (rigManager == null) { obj = null; } else { AvatarCrateReference avatarCrate = rigManager.AvatarCrate; obj = ((avatarCrate != null) ? ((ScannableReference)avatarCrate).Barcode : null); } if (!((Barcode)obj != (Barcode)null)) { return; } string iD = ((ScannableReference)rigManager.AvatarCrate).Barcode.ID; if (!string.IsNullOrWhiteSpace(iD)) { if (!((Crate)(object)((CrateReferenceT<AvatarCrate>)(object)rigManager.AvatarCrate).Crate).IsPublic()) { MenuHelper.ShowNotification("Error", "The modded avatar does not have an associated Mod ID, which is required! That means it must be installed through mod.io in-game", 5f, showPopup: true, (NotificationType)2); return; } SetAvatar(iD, PlayerIDManager.LocalID); GamemodeMenuManager.RefreshSettingsPage(); } } public override void Load() { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown base.Load(); if (base.Value != null && base.Saveable && !string.IsNullOrWhiteSpace(base.Value.Barcode)) { Crate crate = default(Crate); if (base.Value.SelectMode == AvatarSelectMode.RANDOM || base.Value.SelectMode == AvatarSelectMode.FIRST_INFECTED) { base.Value.Barcode = null; base.Value.Origin = -1L; } else if (!AssetWarehouse.Instance.TryGetCrate(new Barcode(base.Value.Barcode), ref crate) || !crate.IsPublic()) { MenuHelper.ShowNotification("Error", "The loaded avatar with barcode '" + base.Value.Barcode + "' could not be found, or is not public! It will be reset to default.", 5f, showPopup: true, (NotificationType)2); FusionModule.Logger.Error("The loaded avatar with barcode '" + base.Value.Barcode + "' could not be found, or is not public! It will be reset to default."); base.Value = new SelectedAvatarData(null, AvatarSelectMode.CONFIG, -1L); Save(); } else { base.Value.Origin = (long)PlayerIDManager.LocalPlatformID; } } } public override void Save() { if (base.Saveable) { if (base.Value.SelectMode != 0) { base.Entry.Value = new SelectedAvatarData(null, base.Value.SelectMode, -1L); base.EnabledEntry.Value = base.Enabled; } else { base.Save(); } } } private static string GetBarcodeTitle(string barcode) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown if (string.IsNullOrWhiteSpace(barcode)) { return "N/A"; } AvatarCrateReference val = new AvatarCrateReference(barcode); object obj; if ((int)val == 0) { obj = null; } else { AvatarCrate crate = ((CrateReferenceT<AvatarCrate>)val).Crate; obj = ((crate != null) ? ((Scannable)crate).Title : null); } if (obj == null) { obj = "N/A"; } return (string)obj; } public AvatarSetting(Gamemode gamemode, string name, string displayName = null, bool autoSync = true) : base(gamemode, name, displayName, autoSync, saveable: true) { base.Value = new SelectedAvatarData(null, AvatarSelectMode.CONFIG, -1L); } public AvatarSetting(Gamemode gamemode, string name, SelectedAvatarData value, string displayName = null, bool autoSync = true) : base(gamemode, name, value, displayName, autoSync, saveable: true) { } public AvatarSetting(Gamemode gamemode, string name, SelectedAvatarData value, bool enabled, string displayName = null, bool autoSync = true) : base(gamemode, name, value, enabled, displayName, autoSync, saveable: true) { } } public sealed class SelectedAvatarData : IEquatable<SelectedAvatarData> { public string Barcode { get; set; } [TomlNonSerialized] public long Origin { get; set; } public AvatarSelectMode SelectMode { get; set; } public SelectedAvatarData(string barcode, AvatarSelectMode selectMode = AvatarSelectMode.CONFIG, long origin = -1L) { Barcode = barcode; Origin = origin; SelectMode = selectMode; base..ctor(); } public override bool Equals(object obj) { if (obj is SelectedAvatarData selectedAvatarData && selectedAvatarData.Barcode == Barcode && selectedAvatarData.Origin == Origin) { return selectedAvatarData.SelectMode == SelectMode; } return false; } public bool Equals(SelectedAvatarData other) { if (other != null && other.Barcode == Barcode && other.Origin == Origin) { return other.SelectMode == SelectMode; } return false; } public override int GetHashCode() { return Barcode.GetHashCode() + Origin.GetHashCode() + SelectMode.GetHashCode(); } } public enum AvatarSelectMode { CONFIG, FIRST_INFECTED, RANDOM } internal class InfectionSettings : SettingsCollection { internal AvatarSetting SelectedAvatar { get; set; } internal AvatarSetting ChildrenSelectedAvatar { get; set; } internal ServerSetting<bool> SyncWithInfected { get; set; } internal ServerSetting<bool> DisableSpawnGun { get; set; } internal ServerSetting<bool> DisableDevTools { get; set; } internal ServerSetting<bool> AllowKeepInventory { get; set; } internal ServerSetting<bool> TeleportOnEnd { get; set; } internal ServerSetting<bool> UseDeathmatchSpawns { get; set; } internal ServerSetting<bool> ShowCountdownToAll { get; set; } internal ServerSetting<bool> FriendlyFire { get; set; } internal ServerSetting<int> CountdownLength { get; set; } internal ServerSetting<long> StartUnix { get; set; } internal ServerSetting<long> EndUnix { get; set; } internal LocalSetting<Infection.InfectType> InfectType { get; set; } internal LocalSetting<int> TimeLimit { get; set; } internal LocalSetting<int> InfectedCount { get; set; } internal LocalSetting<int> HoldTime { get; set; } internal LocalSetting<bool> NoTimeLimit { get; set; } internal LocalSetting<bool> DontRepeatInfected { get; set; } internal LocalSetting<bool> TeleportOnStart { get; set; } internal LocalSetting<bool> SuicideInfects { get; set; } internal InfectionSettings() { DisableDevTools = CreateServerSetting("DisableDevTools", value: true); DisableSpawnGun = CreateServerSetting("DisableSpawnGun", value: true); SelectedAvatar = CreateAvatarSetting("SelectedAvatar", AvatarSelectMode.CONFIG, enabled: true, autoSync: true, optional: false, "Infected Avatar", SelectedPlayerOverride); ChildrenSelectedAvatar = CreateAvatarSetting("ChildrenSelectedAvatar", AvatarSelectMode.CONFIG, enabled: false, autoSync: true, optional: true, "Infected Children Avatar", ChildrenSelectedPlayerOverride); ChildrenSelectedAvatar.DisallowedSelectModes = new AvatarSelectMode[1] { AvatarSelectMode.FIRST_INFECTED }; SyncWithInfected = CreateServerSetting("SyncWithInfected", value: false, null, autoSync: true, saveable: true, SyncWithInfectedUpdated); CountdownLength = CreateServerSetting("CountdownLength", 30); AllowKeepInventory = CreateServerSetting("AllowKeepInventory", value: false); TeleportOnEnd = CreateServerSetting("TeleportOnEnd", value: false); UseDeathmatchSpawns = CreateServerSetting("UseDeathmatchSpawns", value: true, null, autoSync: true, saveable: true, DeathmathUpdated); ShowCountdownToAll = CreateServerSetting("ShowCountdownToAll", value: false); FriendlyFire = CreateServerSetting("FriendlyFire", value: true); StartUnix = CreateServerSetting("StartUnix", -1L, null, autoSync: true, saveable: false); EndUnix = CreateServerSetting("EndUnix", -1L, null, autoSync: true, saveable: false); DontRepeatInfected = CreateLocalSetting("DontRepeatInfected", value: true); HoldTime = CreateLocalSetting("HoldTime", 0); InfectedCount = CreateLocalSetting("InfectedCount", 1); InfectType = CreateLocalSetting("InfectType", Infection.InfectType.TOUCH); NoTimeLimit = CreateLocalSetting("NoTimeLimit", value: false); SuicideInfects = CreateLocalSetting("SuicideInfects", value: true); TeleportOnStart = CreateLocalSetting("TeleportOnStart", value: true); TimeLimit = CreateLocalSetting("TimeLimit", 10); } private static void SyncWithInfectedUpdated() { if (((Gamemode)Infection.Instance).IsStarted && Infection.Instance.TeamManager.GetLocalTeam() == Infection.Instance.InfectedChildren) { StatsManager.ApplyStats(); } } private void DeathmathUpdated() { if (((Gamemode)Infection.Instance).IsStarted) { if (UseDeathmatchSpawns.Value) { Infection.UseDeathmatchSpawns_Init(teleport: false); } else { Infection.ClearDeathmatchSpawns(); } } } internal void SelectedPlayerOverride() { if (((Gamemode)Infection.Instance).IsStarted && (Infection.Instance.TeamManager.GetLocalTeam() == Infection.Instance.Infected || (Infection.Instance.TeamManager.GetLocalTeam() == Infection.Instance.InfectedChildren && !ChildrenSelectedAvatar.Enabled))) { Overrides.SetAvatarOverride(SelectedAvatar.Value.Barcode, SelectedAvatar.Value?.Origin ?? (-1)); } } internal void ChildrenSelectedPlayerOverride() { if (((Gamemode)Infection.Instance).IsStarted && Infection.Instance.TeamManager.GetLocalTeam() == Infection.Instance.InfectedChildren && ChildrenSelectedAvatar.Enabled) { Overrides.SetAvatarOverride(ChildrenSelectedAvatar.Value.Barcode, ChildrenSelectedAvatar.Value?.Origin ?? (-1)); } } public void SetAvatar(string barcode, PlayerID player) { SelectedAvatar.SetAvatar(barcode, player); } public void SetChildrenAvatar(string barcode, PlayerID player) { ChildrenSelectedAvatar.SetAvatar(barcode, player); } } public class InfectionTeam : Team { public TeamMetadata StaticMetadata { get; set; } public TeamMetadata Metadata { get { if (Func == null) { return StaticMetadata; } return Func(); } set { StaticMetadata = value; Func = null; } } public Color Color { get; set; } public Func<TeamMetadata> Func { get; set; } public InfectionTeam(string name) : base(name) { } public InfectionTeam(string name, Color color, TeamMetadata metadata) : base(name) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) Color = color; Metadata = metadata; } public InfectionTeam(string name, Color color, Func<TeamMetadata> function) : base(name) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) Color = color; Func = function; } public InfectionTeam(string name, Color color, TeamMetadata metadata, Func<TeamMetadata> function) : base(name) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) Color = color; StaticMetadata = metadata; Func = function; } public InfectionTeam(string name, Color color, Gamemode gamemode, TeamSettings? config = null, Func<TeamMetadata> function = null) : base(name) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) Color = color; StaticMetadata = new TeamMetadata((Team)(object)this, gamemode, config); Func = function; } public override bool Equals(object obj) { if (obj != null) { if (this != obj && (!(obj is InfectionTeam infectionTeam) || this != infectionTeam)) { Team val = (Team)((obj is Team) ? obj : null); if (val == null || this != val) { if (obj is TeamMetadata teamMetadata) { return teamMetadata.Team == this; } return false; } } return true; } return false; } public override int GetHashCode() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) int num = ((Team)this).TeamName.GetHashCode() + ((Team)this).PlayerCount.GetHashCode(); Color color = Color; return num + ((object)(Color)(ref color)).GetHashCode(); } } public interface IServerSetting : ISetting { bool IsSynced { get; } event Action OnSynced; void Sync(); } public interface ISetting { string Name { get; } bool Saveable { get; } event Action OnValueChanged; void Save(); void Load(); } internal class LocalSetting<T> : ISetting { private T _value; public T Value { get { return _value; } set { _value = value; this.OnValueChanged?.Invoke(); } } public MelonPreferences_Entry<T> Entry { get; } public string Name { get; } public bool Saveable { get; } public event Action OnValueChanged; public virtual void Load() { Value = Entry.Value; } public virtual void Save() { Entry.Value = Value; } public LocalSetting(string name, bool saveable = true) { Value = default(T); Name = name; Saveable = saveable; Entry = Core.Category.CreateEntry<T>(name, default(T), (string)null, (string)null, false, false, (ValueValidator)null, (string)null); } public LocalSetting(string name, T value, bool saveable = true) { Value = value; Name = name; Saveable = saveable; Entry = Core.Category.CreateEntry<T>(name, value, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); } } public class ServerSetting<T> : IServerSetting, ISetting where T : IEquatable<T> { private readonly Gamemode gamemode; private T _value; public string Name { get; private set; } public bool Saveable { get; } public string DisplayName { get; set; } public bool AutoSync { get; set; } public T Value { get { return _value; } set { _value = value; if (AutoSync) { Sync(); } else { this.OnValueChanged?.Invoke(); } } } public MetadataVariableT<T> ServerValue { get; } public MelonPreferences_Entry<T> Entry { get; set; } public bool IsSynced => Value.Equals(ServerValue.GetValue()); public event Action OnValueChanged; public event Action OnSynced; public void Sync() { ServerValue.SetValue(_value); } public virtual void Load() { if (Saveable) { Value = Entry.Value; } } public virtual void Save() { if (Saveable) { Entry.Value = Value; } } private void InitEvent(string name) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown Name = name; if (Saveable) { Entry = Core.Category.CreateEntry<T>(name, Value, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); } GamemodeManager.OnGamemodeStarted += OnGamemodeStarted; MultiplayerHooking.OnStartedServer += new ServerEvent(Sync); MultiplayerHooking.OnJoinedServer += new ServerEvent(RetrieveValues); MultiplayerHooking.OnTargetLevelLoaded += new UpdateEvent(RetrieveValues); gamemode.Metadata.OnMetadataChanged += MetadataChanged; } private void OnGamemodeStarted() { if (NetworkInfo.IsHost) { Sync(); } } private void RetrieveValues() { if (NetworkInfo.HasServer && !NetworkInfo.IsHost) { _value = ServerValue.GetValue(); } } private void MetadataChanged(string key, string value) { if (!(key == ((MetadataVariable)ServerValue).Key)) { return; } ref T reference = ref _value; T val = default(T); if (val == null) { val = reference; reference = ref val; } if (reference.Equals(ServerValue.GetValue())) { this.OnSynced?.Invoke(); return; } if (!NetworkInfo.IsHost) { _value = ServerValue.GetValue(); } this.OnValueChanged?.Invoke(); } public ServerSetting(Gamemode gamemode, string name, string displayName = null, bool autoSync = true, bool saveable = true) { if (displayName == null) { displayName = name; } DisplayName = displayName; AutoSync = autoSync; Saveable = saveable; this.gamemode = gamemode; ServerValue = new MetadataVariableT<T>("ServerSetting_" + name, gamemode.Metadata); Value = default(T); InitEvent(name); } public ServerSetting(Gamemode gamemode, string name, T value, string displayName = null, bool autoSync = true, bool saveable = true) { if (displayName == null) { displayName = name; } DisplayName = displayName; AutoSync = autoSync; Saveable = saveable; this.gamemode = gamemode; ServerValue = new MetadataVariableT<T>("ServerSetting_" + name, gamemode.Metadata); Value = value; InitEvent(name); } } public class ToggleServerSetting<T> : IServerSetting, ISetting { private readonly Gamemode gamemode; private T _value; private bool _enabled; public bool AutoSync { get; set; } public string Name { get; private set; } public bool Saveable { get; } public string DisplayName { get; set; } public T Value { get { return _value; } set { _value = value; if (AutoSync) { Sync(); } else { this.OnValueChanged?.Invoke(); } } } public bool Enabled { get { return _enabled; } set { _enabled = value; if (AutoSync) { Sync(); } else { this.OnValueChanged?.Invoke(); } } } public bool IsSynced { get { if (Value.Equals(ServerValue.GetValue())) { return Enabled == ServerValue.IsEnabled; } return false; } } public MelonPreferences_Entry<T> Entry { get; set; } public MelonPreferences_Entry<bool> EnabledEntry { get; set; } public ToggleMetadataVariableT<T> ServerValue { get; } public event Action OnValueChanged; public event Action OnSynced; public void Sync() { ServerValue.SetValue(_value); ServerValue.SetEnabled(_enabled); } public virtual void Load() { if (Saveable) { Value = Entry.Value; Enabled = EnabledEntry.Value; } } public virtual void Save() { if (Saveable) { Entry.Value = Value; EnabledEntry.Value = Enabled; } } private void InitEvent(string name) { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Expected O, but got Unknown Name = name; if (Saveable) { Entry = Core.Category.CreateEntry<T>(name, Value, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); EnabledEntry = Core.Category.CreateEntry<bool>(name + "_Enabled", Enabled, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); } GamemodeManager.OnGamemodeStarted += OnGamemodeStarted; MultiplayerHooking.OnStartedServer += new ServerEvent(Sync); MultiplayerHooking.OnJoinedServer += new ServerEvent(RetrieveValues); MultiplayerHooking.OnTargetLevelLoaded += new UpdateEvent(RetrieveValues); gamemode.Metadata.OnMetadataChanged += MetadataChanged; } private void OnGamemodeStarted() { if (NetworkInfo.IsHost) { Sync(); } } private void RetrieveValues() { if (NetworkInfo.HasServer && !NetworkInfo.IsHost) { _value = ServerValue.GetValue(); _enabled = ServerValue.IsEnabled; } } private void MetadataChanged(string key, string value) { if (key == ServerValue.Key) { ref T reference = ref _value; T val = default(T); if (val == null) { val = reference; reference = ref val; } if (reference.Equals(ServerValue.GetValue())) { this.OnSynced?.Invoke(); return; } if (!NetworkInfo.IsHost) { _value = ServerValue.GetValue(); } this.OnValueChanged?.Invoke(); } else { if (!(key == ServerValue.ToggledKey)) { return; } if (Enabled == ServerValue.IsEnabled) { this.OnSynced?.Invoke(); return; } if (!NetworkInfo.IsHost) { _enabled = ServerValue.IsEnabled; } this.OnValueChanged?.Invoke(); } } public ToggleServerSetting(Gamemode gamemode, string name, string displayName = null, bool autoSync = true, bool saveable = true) { if (displayName == null) { displayName = name; } DisplayName = displayName; AutoSync = autoSync; Saveable = saveable; this.gamemode = gamemode; ServerValue = new ToggleMetadataVariableT<T>("ServerSetting_" + name, gamemode.Metadata); Value = default(T); Enabled = false; InitEvent(name); } public ToggleServerSetting(Gamemode gamemode, string name, T value, string displayName = null, bool autoSync = true, bool saveable = true) { if (displayName == null) { displayName = name; } DisplayName = displayName; AutoSync = autoSync; Saveable = saveable; this.gamemode = gamemode; ServerValue = new ToggleMetadataVariableT<T>("ServerSetting_" + name, gamemode.Metadata); Value = value; Enabled = false; InitEvent(name); } public ToggleServerSetting(Gamemode gamemode, string name, T value, bool enabled, string displayName = null, bool autoSync = true, bool saveable = true) { if (displayName == null) { displayName = name; } DisplayName = displayName; AutoSync = autoSync; Saveable = saveable; this.gamemode = gamemode; ServerValue = new ToggleMetadataVariableT<T>("ServerSetting_" + name, gamemode.Metadata); Value = value; Enabled = enabled; InitEvent(name); } } public class SettingsCollection { internal readonly List<ISetting> _settingsList = new List<ISetting>(); public IReadOnlyCollection<ISetting> Settings => _settingsList.AsReadOnly(); public ISetting this[string name] => _settingsList.Find((ISetting x) => x.Name == name); public ISetting this[int index] => _settingsList[index]; public event Action OnSettingChanged; public event Action OnSettingSynced; public void Save(bool toFile = true) { _settingsList.ForEach(delegate(ISetting x) { x.Save(); }); if (toFile) { Core.Category.SaveToFile(false); } } public void Load() { _settingsList.ForEach(delegate(ISetting x) { x.Load(); }); } public void Sync() { _settingsList.ForEach(delegate(ISetting x) { if (x.IsServerSetting()) { ((IServerSetting)x).Sync(); } }); } internal ServerSetting<T> CreateServerSetting<T>(string name, T value, string displayName = null, bool autoSync = true, bool saveable = true, Action onValueChanged = null) where T : IEquatable<T> { ServerSetting<T> serverSetting = new ServerSetting<T>((Gamemode)(object)Infection.Instance, name, value, displayName, autoSync, saveable); serverSetting.OnValueChanged += delegate { this.OnSettingChanged?.Invoke(); }; serverSetting.OnSynced += delegate { this.OnSettingSynced?.Invoke(); }; if (onValueChanged != nul