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 : IEnumerable, ICollection, IList, IEnumerable, IReadOnlyCollection, IReadOnlyList, ICollection, IList { 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.Count => _items.Length; T IReadOnlyList.this[int index] => _items[index]; int ICollection.Count => _items.Length; bool ICollection.IsReadOnly => true; T IList.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 IEnumerable.GetEnumerator() { return ((IEnumerable)_items).GetEnumerator(); } void ICollection.Add(T item) { throw new NotSupportedException(); } void ICollection.Clear() { throw new NotSupportedException(); } bool ICollection.Contains(T item) { return ((ICollection)_items).Contains(item); } void ICollection.CopyTo(T[] array, int arrayIndex) { ((ICollection)_items).CopyTo(array, arrayIndex); } bool ICollection.Remove(T item) { throw new NotSupportedException(); } int IList.IndexOf(T item) { return ((IList)_items).IndexOf(item); } void IList.Insert(int index, T item) { throw new NotSupportedException(); } void IList.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(1f, enabled: false), Vitality = new ToggleSetting(0.75f), JumpPower = new ToggleSetting(1.5f), Speed = new ToggleSetting(2.8f), Agility = new ToggleSetting(2f), StrengthUpper = new ToggleSetting(0.5f), Mortality = true, CanUseGuns = false }; public static readonly TeamSettings InfectedChildrenStats = new TeamSettings { Height = new ToggleSetting(1f, enabled: false), Vitality = new ToggleSetting(0.5f), JumpPower = new ToggleSetting(1.25f), Speed = new ToggleSetting(1.8f), Agility = new ToggleSetting(1.5f), StrengthUpper = new ToggleSetting(0.35f), Mortality = true, CanUseGuns = false }; public static readonly TeamSettings SurvivorsStats = new TeamSettings { Height = new ToggleSetting(1f, enabled: false), Vitality = new ToggleSetting(1f), JumpPower = new ToggleSetting(1f), Speed = new ToggleSetting(1.2f), Agility = new ToggleSetting(1f), StrengthUpper = new ToggleSetting(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 = "Avatar Infection"; 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(); ((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(); 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 <5>__RefreshStats; public static Action <6>__SwapAvatarEvent; public static Action <7>__TeleportToHost; public static Func <8>__GetPlayerID; } [CompilerGenerated] private sealed class d__103 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Infection <>4__this; private int 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public 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; 5__2 = infection.Config.CountdownLength.Value; break; case 1: <>1__state = -1; 5__2--; if (((MetadataVariableT)(object)infection.CountdownValue).GetValue() != 5__2) { ((MetadataVariableT)(object)infection.CountdownValue).SetValue(5__2); } break; } if (5__2 > 0) { <>2__current = (object)new WaitForSeconds(1f); <>1__state = 1; return true; } ((MetadataVariableT)(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 LastPlayerActions = new Dictionary(); private int _surivorsLastCheckedMinutes; private static bool appliedDeathmatchSpawns; private bool WasStarted; public override string Title => "Avatar Infection"; 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 LastInfected { get; } = new List(); 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(EventType.RefreshStats, StatsManager.RefreshStats, serverOnly: true); EventManager.RegisterEvent(EventType.PlayerInfected, PlayerInfected, serverOnly: true); EventManager.RegisterEvent(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)(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(d__103))] private IEnumerator InfectedLookingWait() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new 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)(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)(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)(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 = 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)(object)InfectedLooking).SetValue(false); } internal static void UseDeathmatchSpawns_Init(bool teleport = true) { if (!appliedDeathmatchSpawns) { appliedDeathmatchSpawns = true; GamemodeHelper.SetSpawnPoints((IEnumerable)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 last = new List(LastInfected); LastInfected.Clear(); List list = new List(PlayerIDManager.PlayerIDs); IEnumerableExtensions.Shuffle((IList)list); bool flag = false; int num = 0; int num2 = 0; List list2 = new List(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)last).Select((Func)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 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)CustomToolTip, (Func)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)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)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)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() ?? val.AddComponent(); 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(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)PlayerIDManager.PlayerIDs).FirstOrDefault((Func)((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 : "
(Update available!)"), 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 v{_fetchedPackage.Latest.Version}", 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($"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(Task task) where T : class { if (task != null && task.IsCompletedSuccessfully) { return task.Result != null; } return false; } public T SendRequest(string url) { Task 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 task = httpResponseMessage.Content.ReadAsStringAsync(); task.Wait(); string text = task?.Result; if (IsTaskGood(task)) { return JsonConvert.DeserializeObject(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($"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 task = response.Content.ReadAsStringAsync(); task.Wait(); string result = task.Result; if (string.IsNullOrWhiteSpace(result)) { return null; } ThunderstoreErrorResponse thunderstoreErrorResponse; try { thunderstoreErrorResponse = JsonConvert.DeserializeObject(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 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 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 task = response.Content.ReadAsStringAsync(); task.Wait(); string result = task.Result; if (string.IsNullOrWhiteSpace(result)) { Details = string.Empty; return; } ThunderstoreErrorResponse thunderstoreErrorResponse; try { thunderstoreErrorResponse = JsonConvert.DeserializeObject(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 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() { string value = GetValue(); if (string.IsNullOrEmpty(value)) { return default(TValue); } return JsonSerializer.Deserialize(value, SerializerOptions); } } public class ToggleMetadataVariableT : ToggleMetadataVariable { public ToggleMetadataVariableT(string key, NetworkMetadata metadata) : base(key, metadata) { } public void SetValue(TValue value) { base.SetValue(value); } public new TValue GetValue() { return GetValue(); } } } namespace AvatarInfection.Settings { public class AvatarSetting : ToggleServerSetting { public string GroupName { get; set; } public bool Optional { get; set; } public AvatarSelectMode[] DisallowedSelectModes { get; set; } = Array.Empty(); 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().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 crates = AssetWarehouse.Instance.GetCrates((ICrateFilter)null); crates.ExcludeRedacted(); crates.ExcludeNonPublic(); return ((IEnumerable)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)(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)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 { 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 SyncWithInfected { get; set; } internal ServerSetting DisableSpawnGun { get; set; } internal ServerSetting DisableDevTools { get; set; } internal ServerSetting AllowKeepInventory { get; set; } internal ServerSetting TeleportOnEnd { get; set; } internal ServerSetting UseDeathmatchSpawns { get; set; } internal ServerSetting ShowCountdownToAll { get; set; } internal ServerSetting FriendlyFire { get; set; } internal ServerSetting CountdownLength { get; set; } internal ServerSetting StartUnix { get; set; } internal ServerSetting EndUnix { get; set; } internal LocalSetting InfectType { get; set; } internal LocalSetting TimeLimit { get; set; } internal LocalSetting InfectedCount { get; set; } internal LocalSetting HoldTime { get; set; } internal LocalSetting NoTimeLimit { get; set; } internal LocalSetting DontRepeatInfected { get; set; } internal LocalSetting TeleportOnStart { get; set; } internal LocalSetting 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 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 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 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 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 : ISetting { private T _value; public T Value { get { return _value; } set { _value = value; this.OnValueChanged?.Invoke(); } } public MelonPreferences_Entry 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(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(name, value, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); } } public class ServerSetting : IServerSetting, ISetting where T : IEquatable { 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 ServerValue { get; } public MelonPreferences_Entry 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(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("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("ServerSetting_" + name, gamemode.Metadata); Value = value; InitEvent(name); } } public class ToggleServerSetting : 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 Entry { get; set; } public MelonPreferences_Entry EnabledEntry { get; set; } public ToggleMetadataVariableT 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(name, Value, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); EnabledEntry = Core.Category.CreateEntry(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("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("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("ServerSetting_" + name, gamemode.Metadata); Value = value; Enabled = enabled; InitEvent(name); } } public class SettingsCollection { internal readonly List _settingsList = new List(); public IReadOnlyCollection 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 CreateServerSetting(string name, T value, string displayName = null, bool autoSync = true, bool saveable = true, Action onValueChanged = null) where T : IEquatable { ServerSetting serverSetting = new ServerSetting((Gamemode)(object)Infection.Instance, name, value, displayName, autoSync, saveable); serverSetting.OnValueChanged += delegate { this.OnSettingChanged?.Invoke(); }; serverSetting.OnSynced += delegate { this.OnSettingSynced?.Invoke(); }; if (onValueChanged != null) { serverSetting.OnValueChanged += onValueChanged; } _settingsList.Add(serverSetting); return serverSetting; } internal LocalSetting CreateLocalSetting(string name, T value, bool saveable = true, Action onValueChanged = null) { LocalSetting localSetting = new LocalSetting(name, value, saveable); localSetting.OnValueChanged += delegate { this.OnSettingChanged?.Invoke(); }; if (onValueChanged != null) { localSetting.OnValueChanged += onValueChanged; } _settingsList.Add(localSetting); return localSetting; } internal ToggleServerSetting CreateToggleServerSetting(string name, T value, bool enabled, string displayName = null, bool autoSync = true, bool saveable = true, Action onValueChanged = null) where T : IEquatable { ToggleServerSetting toggleServerSetting = new ToggleServerSetting((Gamemode)(object)Infection.Instance, name, value, enabled, displayName, autoSync, saveable); toggleServerSetting.OnValueChanged += delegate { this.OnSettingChanged?.Invoke(); }; toggleServerSetting.OnSynced += delegate { this.OnSettingSynced?.Invoke(); }; if (onValueChanged != null) { toggleServerSetting.OnValueChanged += onValueChanged; } _settingsList.Add(toggleServerSetting); return toggleServerSetting; } internal AvatarSetting CreateAvatarSetting(string name, AvatarSelectMode value, bool enabled, bool autoSync = true, bool optional = false, string groupName = "", Action onValueChanged = null) { return CreateAvatarSetting(name, new SelectedAvatarData(null, value, -1L), enabled, autoSync, optional, groupName, onValueChanged); } internal AvatarSetting CreateAvatarSetting(string name, SelectedAvatarData value, bool enabled, bool autoSync = true, bool optional = false, string groupName = "", Action onValueChanged = null) { AvatarSetting avatarSetting = new AvatarSetting((Gamemode)(object)Infection.Instance, name, value, enabled, null, autoSync); avatarSetting.OnValueChanged += delegate { this.OnSettingChanged?.Invoke(); }; avatarSetting.OnSynced += delegate { this.OnSettingSynced?.Invoke(); }; avatarSetting.Optional = optional; avatarSetting.GroupName = groupName; if (onValueChanged != null) { avatarSetting.OnValueChanged += onValueChanged; } _settingsList.Add(avatarSetting); return avatarSetting; } } public static class SettingsHelper { public static bool IsServerSetting(this ISetting setting) { return setting is IServerSetting; } } public class TeamMetadata : SettingsCollection { public readonly Team Team; private readonly Gamemode Gamemode; public ServerSetting Mortality { get; set; } public ServerSetting CanUseGuns { get; set; } public ToggleServerSetting Height { get; set; } public ToggleServerSetting Vitality { get; set; } public ToggleServerSetting Speed { get; set; } public ToggleServerSetting Agility { get; set; } public ToggleServerSetting StrengthUpper { get; set; } public bool IsApplied { get { if (!Gamemode.IsStarted) { return true; } return _settingsList.TrueForAll((ISetting x) => !x.IsServerSetting() || ((IServerSetting)x).IsSynced); } } public TeamMetadata(Team team, Gamemode gamemode, TeamSettings? config = null) { Gamemode = gamemode; Team = team; Mortality = CreateSetting("Mortality", config?.Mortality ?? false, "Mortality"); CanUseGuns = CreateSetting("CanUseGuns", config?.CanUseGuns ?? false, "Can Use Guns"); Height = CreateSetting("Height", config?.Height, "Height"); Vitality = CreateSetting("Vitality", config?.Vitality, "Vitality"); Speed = CreateSetting("Speed", config?.Speed, "Speed"); Agility = CreateSetting("Agility", config?.Agility, "Agility"); StrengthUpper = CreateSetting("StrengthUpper", config?.StrengthUpper, "Strength Upper"); base.OnSettingChanged += UpdateMenu; base.OnSettingSynced += UpdateMenu; } public new void Sync() { base.Sync(); UpdateMenu(); } public void UpdateMenu() { if (Gamemode.IsStarted) { InfectionTeam infectionTeamFromTeam = Infection.Instance.TeamManager.GetInfectionTeamFromTeam(Team); if (infectionTeamFromTeam != null) { GamemodeMenuManager.FormatApplyName(infectionTeamFromTeam); } } } private ToggleServerSetting CreateSetting(string name, ToggleSetting config, string displayName = null) where T : IEquatable { T value; if (config == null) { value = default(T); } else { T value2 = config.Value; value = ((value2 != null) ? value2 : default(T)); } return CreateToggleServerSetting(Team.TeamName + "_" + name, value, config?.Enabled ?? false, displayName, autoSync: false); } private ServerSetting CreateSetting(string name, T value, string displayName = null) where T : IEquatable { return CreateServerSetting(Team.TeamName + "_" + name, value, displayName, autoSync: false); } public void ApplyConfig() { if (NetworkInfo.IsHost) { Sync(); } } private static void CheckForGun(Hand hand) { GameObject currentAttachedGO = hand.m_CurrentAttachedGO; object obj = ((currentAttachedGO != null) ? currentAttachedGO.GetComponent() : null); if (obj == null) { GameObject currentAttachedGO2 = hand.m_CurrentAttachedGO; obj = ((currentAttachedGO2 != null) ? currentAttachedGO2.GetComponentInParent() : null); } if ((Object)obj != (Object)null) { HandExtensions.TryDetach(hand); } } internal void CanUseGunsChanged() { if (Infection.Instance.TeamManager.GetLocalTeam() == Infection.Instance.TeamManager.GetInfectionTeamFromTeam(Team) && !CanUseGuns.Value) { CheckForGun(Player.LeftHand); CheckForGun(Player.RightHand); } } } public struct TeamSettings { public bool Mortality { get; set; } public bool CanUseGuns { get; set; } public ToggleSetting Height { get; set; } public ToggleSetting Vitality { get; set; } public ToggleSetting Speed { get; set; } public ToggleSetting JumpPower { get; set; } public ToggleSetting StrengthUpper { get; set; } public ToggleSetting Agility { get; set; } public TeamSettings() { Mortality = false; CanUseGuns = false; Height = null; Vitality = null; Speed = null; JumpPower = null; StrengthUpper = null; Agility = null; } public TeamSettings(TeamSettings old) { Height = old.Height; Vitality = old.Vitality; Speed = old.Speed; JumpPower = old.JumpPower; Agility = old.Agility; Mortality = old.Mortality; StrengthUpper = old.StrengthUpper; CanUseGuns = old.CanUseGuns; } } public class ToggleSetting { public T Value { get; set; } public bool Enabled { get; set; } public ToggleSetting(T value, bool enabled = true) { Value = value; Enabled = enabled; base..ctor(); } } } namespace AvatarInfection.Patches { [HarmonyPatch(typeof(Avatar))] public static class AvatarPatches { internal static bool DontOverrideMass { get; set; } [HarmonyPriority(int.MinValue)] [HarmonyPostfix] [HarmonyPatch("ComputeBaseStats")] public static void OverrideStats(Avatar __instance) { if ((Object)(object)__instance == (Object)null || ((Object)__instance).name == "[RealHeptaRig (Marrow1)]") { return; } RigManager componentInParent = ((Component)__instance).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)(object)Player.RigManager) { return; } if (Overrides.Speed.HasValue) { __instance._speed = Overrides.Speed.Value; } if (Overrides.Agility.HasValue) { __instance._agility = Overrides.Agility.Value; } if (Overrides.Vitality.HasValue) { __instance._vitality = Overrides.Vitality.Value; } if (Overrides.Mortality.HasValue) { componentInParent.health.healthMode = (HealthMode)(Overrides.Mortality.Value ? 1 : 0); } if (Overrides.StrengthUpper.HasValue) { __instance._strengthUpper = Overrides.StrengthUpper.Value; __instance._strengthGrip = Overrides.StrengthUpper.Value; if (!DontOverrideMass) { __instance._strengthLower = 0.6628f * Overrides.StrengthUpper.Value + 0.4095f; } } } [HarmonyPriority(int.MinValue)] [HarmonyPostfix] [HarmonyPatch("ComputeMass")] public static void OverrideMass(Avatar __instance) { if (!((Object)(object)__instance == (Object)null) && !(((Object)__instance).name == "[RealHeptaRig (Marrow1)]") && !((Object)(object)((Component)__instance).GetComponentInParent() != (Object)(object)Player.RigManager) && Overrides.StrengthUpper.HasValue && !DontOverrideMass) { __instance._massTotal = 15.375f * Overrides.StrengthUpper.Value + 62.438f; } } public static void EnsureOverrides() { Infection instance = Infection.Instance; if (instance != null && ((Gamemode)instance).IsStarted && !((Object)(object)Player.RigManager == (Object)null)) { Avatar avatar = Player.RigManager.avatar; if (!((Object)(object)avatar == (Object)null) && !(((Object)avatar).name == "[RealHeptaRig (Marrow1)]")) { OverrideStats(avatar); OverrideMass(avatar); } } } } public static class GrabPatches { internal static readonly Dictionary HoldTime = new Dictionary(); [HarmonyPostfix] [HarmonyPatch(typeof(Grip), "OnAttachedToHand")] public static void Postfix(Grip __instance, Hand hand) { Grabbed(__instance, hand); } [HarmonyPostfix] [HarmonyPatch(typeof(Grip), "OnDetachedFromHand")] public static void Postfix2(Grip __instance) { if (Has(__instance)) { HoldTime.Remove(__instance); } } [HarmonyPrefix] [HarmonyPatch(typeof(Hand), "AttachObject")] [HarmonyPriority(10000)] public static bool GrabAttempt(Hand __instance, GameObject objectToAttach) { return CanGrab(__instance, objectToAttach); } [HarmonyPrefix] [HarmonyPatch(typeof(InventorySlotReceiver), "OnHandHoverBegin")] [HarmonyPatch(typeof(InventorySlotReceiver), "OnHandHoverEnd")] [HarmonyPriority(10000)] public static bool InventoryGrabAttempt(InventorySlotReceiver __instance, Hand hand) { object gameObject; if (__instance == null) { gameObject = null; } else { IGrippable weaponHost = __instance._weaponHost; gameObject = ((weaponHost != null) ? weaponHost.GetHostGameObject() : null); } return CanGrab(hand, (GameObject)gameObject); } [HarmonyPrefix] [HarmonyPatch(typeof(InventorySlotReceiver), "OnHandGrab")] [HarmonyPriority(10000)] public static bool InventoryGrabAttempt2(InventorySlotReceiver __instance, Hand hand) { object gameObject; if (__instance == null) { gameObject = null; } else { IGrippable weaponHost = __instance._weaponHost; gameObject = ((weaponHost != null) ? weaponHost.GetHostGameObject() : null); } bool num = CanGrab(hand, (GameObject)gameObject); if (!num && __instance != null) { __instance.DropWeapon(); } return num; } [HarmonyPrefix] [HarmonyPatch(typeof(InteractableIcon), "MyFarHandHoverBegin")] [HarmonyPatch(typeof(InteractableIcon), "MyHandHoverBegin")] [HarmonyPriority(10000)] public static bool IconAttempt(InteractableIcon __instance, Hand hand) { return CanGrab(hand, (__instance != null) ? ((Component)__instance).gameObject : null); } [HarmonyPrefix] [HarmonyPatch(typeof(ForcePullGrip), "CoPull")] [HarmonyPatch(typeof(ForcePullGrip), "OnStartAttach")] [HarmonyPatch(typeof(ForcePullGrip), "OnFarHandHoverBegin")] [HarmonyPatch(typeof(ForcePullGrip), "OnFarHandHoverUpdate")] [HarmonyPatch(typeof(ForcePullGrip), "OnFarHandHoverEnd")] [HarmonyPatch(typeof(ForcePullGrip), "OnForcePullComplete")] [HarmonyPriority(10000)] public static bool ForceGrabAttempt(Hand hand, ForcePullGrip __instance) { return CanGrab(hand, (__instance != null) ? ((Component)__instance).gameObject : null); } private static bool Has(Grip grip) { return HoldTime.Any((KeyValuePair x) => (Object)(object)x.Key == (Object)(object)grip); } private static void Grabbed(Grip grip, Hand hand) { if (NetworkInfo.IsHost && Infection.Instance != null && ((Gamemode)Infection.Instance).IsStarted && Infection.Instance.Config.InfectType.Value == Infection.InfectType.TOUCH && ((MetadataVariableT)(object)Infection.Instance.InfectedLooking).GetValue()) { RigManager manager = hand.manager; object obj; if (manager == null) { obj = null; } else { PhysicsRig physicsRig = manager.physicsRig; obj = ((physicsRig != null) ? physicsRig.marrowEntity : null); } MarrowEntity val = (MarrowEntity)obj; NetworkPlayer val2 = default(NetworkPlayer); NetworkPlayer val3 = default(NetworkPlayer); if (!((Object)(object)val == (Object)null) && NetworkPlayerManager.TryGetPlayer(val, ref val2) && Infection.Instance.TeamManager.GetPlayerTeam(val2.PlayerID) != Infection.Instance.Survivors && Object.op_Implicit((Object)(object)grip._marrowEntity) && NetworkPlayerManager.TryGetPlayer(grip._marrowEntity, ref val3) && Infection.Instance.TeamManager.GetPlayerTeam(val3.PlayerID) == Infection.Instance.Survivors) { RegisterTouch(grip, val3.PlayerID.PlatformID, val2.PlayerID.PlatformID); } } } private static void RegisterTouch(Grip grip, ulong platformId, ulong by) { if (Infection.Instance.Config.HoldTime.Value == 0) { EventManager.TryInvokeEvent(Infection.EventType.PlayerInfected, new PlayerInfectedData(platformId, (long)by)); } else { HoldTime.Add(grip, new GripData(by)); } } private static bool CanGrab(Hand hand, GameObject gameObject) { if (!NetworkInfo.HasServer) { return true; } Infection instance = Infection.Instance; if (instance == null || !((Gamemode)instance).IsStarted) { return true; } if ((Object)(object)hand == (Object)null || (Object)(object)gameObject == (Object)null || (Object)(object)Player.RigManager != (Object)(object)((hand != null) ? ((Component)hand).GetComponentInParent() : null)) { return true; } TeamMetadata metadata = Infection.Instance.TeamManager.GetLocalTeam().Metadata; if (metadata == null) { return true; } Gun val = gameObject.GetComponent() ?? gameObject.GetComponentInParent(); if (IsSpawnGun(gameObject)) { return true; } if (!((Object)(object)val == (Object)null)) { return metadata.CanUseGuns.Value; } return true; } private static bool IsSpawnGun(GameObject gameObject) { return (Object)(object)(gameObject.GetComponent() ?? gameObject.GetComponentInParent()) != (Object)null; } internal static void Update() { ClearHoldIfNecessary(); NetworkPlayer val = default(NetworkPlayer); foreach (KeyValuePair item in new Dictionary(HoldTime)) { item.Value.Time += TimeManager.DeltaTime; HoldTime[item.Key] = item.Value; if (item.Value.Time >= (float)Infection.Instance.Config.HoldTime.Value && Object.op_Implicit((Object)(object)item.Key._marrowEntity) && NetworkPlayerManager.TryGetPlayer(item.Key._marrowEntity, ref val) && !Infection.Instance.IsPlayerInfected(val.PlayerID)) { HoldTime.Remove(item.Key); EventManager.TryInvokeEvent(Infection.EventType.PlayerInfected, new PlayerInfectedData(val.PlayerID.PlatformID, (long)item.Value.By)); } } } private static void ClearHoldIfNecessary() { if (!NetworkInfo.HasServer && NetworkInfo.IsHost) { Infection instance = Infection.Instance; if ((instance == null || !((Gamemode)instance).IsStarted) && !((Object)(object)Player.RigManager != (Object)null)) { HoldTime.Clear(); } } } } public class GripData { public ulong By { get; set; } public float Time { get; set; } public GripData(ulong by, float time = 0f) { By = by; Time = time; base..ctor(); } } [HarmonyPatch(typeof(LocalHealth))] public static class LocalHealthPatches { public static MethodBase TargetMethod() { return AccessTools.Method(typeof(LocalHealth), "OnOverrideHealth", (Type[])null, (Type[])null); } public static bool Prefix() { if (!NetworkInfo.HasServer) { return true; } Infection instance = Infection.Instance; if (instance == null || !((Gamemode)instance).IsStarted) { return true; } return false; } } [HarmonyPatch(typeof(PullCordDevice))] public static class PullCordDevicePatches { [HarmonyPrefix] [HarmonyPatch("OnBallGripAttached")] [HarmonyPatch("OnBallGripDetached")] [HarmonyPatch("OnBallGripUpdate")] public static bool OnBall(PullCordDevice __instance) { if ((Object)(object)__instance == (Object)null) { return true; } if ((Object)(object)((Component)__instance).GetComponentInParent() != (Object)(object)Player.RigManager) { return true; } if (!NetworkInfo.HasServer) { return true; } Infection instance = Infection.Instance; if (instance == null || !((Gamemode)instance).IsStarted) { return true; } return !Infection.Instance.IsLocalPlayerInfected(); } } [HarmonyPatch(typeof(RigManager))] public static class RigManagerPatches { [HarmonyPrefix] [HarmonyPriority(int.MaxValue)] [HarmonyPatch("SwapAvatarCrate")] public static bool AvatarChangeOverride(RigManager __instance, Barcode barcode, ref UniTask __result) { try { __result = new UniTask(true); if (IsBarcodeEmpty(barcode)) { return true; } if (!NetworkInfo.HasServer) { return true; } if (__instance == null || !FusionPlayer.IsLocalPlayer(__instance)) { return true; } if (!((Gamemode)Infection.Instance).IsStarted) { return true; } if (Infection.Instance.TeamManager?.GetLocalTeam() == null) { return true; } if (string.IsNullOrWhiteSpace(Infection.Instance.Config.SelectedAvatar.Value?.Barcode)) { return true; } if (Infection.Instance.TeamManager.GetLocalTeam() == Infection.Instance.Survivors) { return barcode != Infection.Instance.Config.SelectedAvatar.AsBarcode() && barcode != Infection.Instance.Config.ChildrenSelectedAvatar.AsBarcode(); } return (((barcode != null) ? barcode.ID : null) == GetOverrideBarcode()) ? Infection.Instance.IsLocalPlayerInfected() : (!Infection.Instance.IsLocalPlayerInfected()); } catch (Exception value) { FusionModule.Logger.Error($"An unexpected error has occurred while handing SwapAvatarCrate in RigManager, exception:\n{value}"); return true; } } private static string GetOverrideBarcode() { if (IsPrimary()) { return Infection.Instance.Config.SelectedAvatar.Value?.Barcode; } return Infection.Instance.Config.ChildrenSelectedAvatar.Value?.Barcode; } private static bool IsPrimary() { if (Infection.Instance.TeamManager.GetLocalTeam() == Infection.Instance.InfectedChildren) { return !Infection.Instance.Config.ChildrenSelectedAvatar.Enabled; } return true; } private static bool IsBarcodeEmpty(Barcode barcode) { if (!(barcode == (Barcode)null) && !string.IsNullOrWhiteSpace(barcode.ID)) { return barcode.ID == Barcode.EMPTY; } return true; } } } namespace AvatarInfection.Managers { internal static class BoneMenuManager { [CompilerGenerated] private static class <>O { public static ServerEvent <0>__PopulatePage; public static PlayerUpdate <1>__Hook; public static Action <2>__PopulatePage; } private static readonly Dictionary Teams = new Dictionary(); public static Page ModPage { get; private set; } public static Page DebugPage { get; private set; } public static void Setup() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Expected O, but got Unknown ModPage = Page.Root.CreatePage("Avatar Infection", Color.white, 0, true); PopulatePage(); object obj = <>O.<0>__PopulatePage; if (obj == null) { ServerEvent val = PopulatePage; <>O.<0>__PopulatePage = val; obj = (object)val; } MultiplayerHooking.OnDisconnected += (ServerEvent)obj; object obj2 = <>O.<0>__PopulatePage; if (obj2 == null) { ServerEvent val2 = PopulatePage; <>O.<0>__PopulatePage = val2; obj2 = (object)val2; } MultiplayerHooking.OnJoinedServer += (ServerEvent)obj2; object obj3 = <>O.<0>__PopulatePage; if (obj3 == null) { ServerEvent val3 = PopulatePage; <>O.<0>__PopulatePage = val3; obj3 = (object)val3; } MultiplayerHooking.OnStartedServer += (ServerEvent)obj3; object obj4 = <>O.<1>__Hook; if (obj4 == null) { PlayerUpdate val4 = Hook; <>O.<1>__Hook = val4; obj4 = (object)val4; } MultiplayerHooking.OnPlayerJoined += (PlayerUpdate)obj4; object obj5 = <>O.<1>__Hook; if (obj5 == null) { PlayerUpdate val5 = Hook; <>O.<1>__Hook = val5; obj5 = (object)val5; } MultiplayerHooking.OnPlayerLeft += (PlayerUpdate)obj5; } public static void Destroy() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown Menu.DestroyPage(ModPage); ModPage = null; object obj = <>O.<0>__PopulatePage; if (obj == null) { ServerEvent val = PopulatePage; <>O.<0>__PopulatePage = val; obj = (object)val; } MultiplayerHooking.OnDisconnected -= (ServerEvent)obj; object obj2 = <>O.<0>__PopulatePage; if (obj2 == null) { ServerEvent val2 = PopulatePage; <>O.<0>__PopulatePage = val2; obj2 = (object)val2; } MultiplayerHooking.OnJoinedServer -= (ServerEvent)obj2; object obj3 = <>O.<0>__PopulatePage; if (obj3 == null) { ServerEvent val3 = PopulatePage; <>O.<0>__PopulatePage = val3; obj3 = (object)val3; } MultiplayerHooking.OnStartedServer -= (ServerEvent)obj3; object obj4 = <>O.<1>__Hook; if (obj4 == null) { PlayerUpdate val4 = Hook; <>O.<1>__Hook = val4; obj4 = (object)val4; } MultiplayerHooking.OnPlayerJoined -= (PlayerUpdate)obj4; object obj5 = <>O.<1>__Hook; if (obj5 == null) { PlayerUpdate val5 = Hook; <>O.<1>__Hook = val5; obj5 = (object)val5; } MultiplayerHooking.OnPlayerLeft -= (PlayerUpdate)obj5; } private static void Hook(PlayerID _) { PopulatePage(); } public static void PopulatePage() { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) if (ModPage == null || Infection.Instance == null) { return; } ModPage.RemoveAll(); if (DebugPage == null) { DebugPage = ModPage.CreatePage("Debug", Color.yellow, 0, false); } ModPage.CreateFunction("Refresh", Color.cyan, (Action)PopulatePage); Core.Thunderstore.BL_CreateMenuLabel(ModPage, createBlankSpace: false); ((Element)ModPage.CreateFunction("[===============]", Color.magenta, (Action)null)).SetProperty((ElementProperties)1); if (!NetworkInfo.HasServer) { CreateErrorMessage("You aren't in any server :("); return; } if (!((Gamemode)Infection.Instance).IsStarted) { CreateErrorMessage("Gamemode is not started :("); return; } Teams.Clear(); foreach (PlayerID playerID in PlayerIDManager.PlayerIDs) { Teams.Add(playerID, (Team)(object)Infection.Instance?.TeamManager?.GetPlayerTeam(playerID)); } List list = new List(); list.Add(CreateTeamPage((Team)(object)Infection.Instance.Infected)); list.Add(CreateTeamPage((Team)(object)Infection.Instance.InfectedChildren)); list.Add(CreateTeamPage((Team)(object)Infection.Instance.Survivors)); list.Add(CreateTeamPage(null)); string text = default(string); foreach (KeyValuePair player in Teams) { if (MetadataHelper.TryGetDisplayName(player.Key, ref text)) { TeamPage teamPage = list?.FirstOrDefault((TeamPage x) => x?.Team == player.Value); if (teamPage != null) { teamPage.Page.CreateFunction(text, Color.white, (Action)null); } } } } private static TeamPage CreateTeamPage(Team team) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) if (!Teams.Any((KeyValuePair x) => x.Value == team)) { return null; } string value = ((team != null) ? team.DisplayName : "Unidentified"); Color val = ((team != null) ? Infection.Instance.TeamManager.GetInfectionTeamFromTeam(team).Color : Color.gray); return new TeamPage(ModPage.CreatePage($"{value} ({Teams.Count((KeyValuePair x) => x.Value == team)})", val, 0, true), team); } private static void CreateErrorMessage(string error) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) ((Element)ModPage.CreateFunction(error, Color.white, (Action)null)).SetProperty((ElementProperties)1); } } internal class TeamPage { public Page Page { get; } public Team Team { get; } public TeamPage(Page page, Team team) { Page = page; Team = team; base..ctor(); } } public static class EventManager { private static readonly Dictionary _events = new Dictionary(); public static IReadOnlyCollection Events => new <>z__ReadOnlyArray(_events.Keys.ToArray()); internal static void OnUnregistered() { IEnumerableExtensions.ForEach>((IEnumerable>)_events, (Action>)delegate(KeyValuePair e) { e.Key.UnregisterEvent(); }); _events.Clear(); } public static void RegisterEvent(string name, Action callback, bool serverOnly = false) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown if (_events.Any((KeyValuePair x) => x.Key.Name == name)) { throw new ArgumentException("An event with the same name is registered!"); } new TriggerEvent(name, ((Gamemode)Infection.Instance).Relay, serverOnly).OnTriggered += callback; _events.Add(new TriggerEvent(name, ((Gamemode)Infection.Instance).Relay, serverOnly), null); } public static void RegisterEvent(string name, Action callback, bool serverOnly = false) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown if (_events.Any((KeyValuePair x) => x.Key.Name == name)) { throw new ArgumentException("An event with the same name is registered!"); } new TriggerEvent(name, ((Gamemode)Infection.Instance).Relay, serverOnly).OnTriggeredWithValue += delegate(string val) { T obj; try { obj = JsonSerializer.Deserialize(val); } catch (Exception value) { FusionModule.Logger.Error($"Failed to convert value to type '{typeof(T).Name}' in trigger event callback, exception:\n{value}"); return; } callback?.Invoke(obj); }; _events.Add(new TriggerEvent(name, ((Gamemode)Infection.Instance).Relay, serverOnly), typeof(T)); } public static void RegisterEvent(Enum @enum, Action callback, bool serverOnly = false) { RegisterEvent(@enum.ToString(), callback, serverOnly); } public static void RegisterEvent(Enum @enum, Action callback, bool serverOnly = false) { RegisterEvent(@enum.ToString(), callback, serverOnly); } public static void RegisterNotification(string name, Notification notification, bool serverOnly = true) { RegisterEvent(name, delegate { if (((Gamemode)Infection.Instance).IsStarted) { Notifier.Send(notification); } }, serverOnly); } public static void RegisterNotification(Enum @enum, Notification notification, bool serverOnly = true) { RegisterNotification(@enum.ToString(), notification, serverOnly); } public static void RegisterNotification(Enum @enum, string title, string message, float popupDuration = 4f, bool serverOnly = true, bool showPopup = true, NotificationType type = 0) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) RegisterNotification(@enum.ToString(), title, message, popupDuration, serverOnly, showPopup, type); } public static void RegisterNotification(string name, string title, string message, float popupDuration = 4f, bool serverOnly = true, bool showPopup = true, NotificationType type = 0) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) RegisterEvent(name, delegate { //IL_0026: Unknown result type (might be due to invalid IL or missing references) if (((Gamemode)Infection.Instance).IsStarted) { MenuHelper.ShowNotification(title, message, popupDuration, showPopup, type); } }, serverOnly); } public static void UnregisterEvent(string name) { TriggerEvent key = _events.FirstOrDefault((KeyValuePair x) => x.Key.Name == name).Key; if (key != null) { key.UnregisterEvent(); _events.Remove(key); } } public static void UnregisterEvent(Enum @enum) { UnregisterEvent(@enum.ToString()); } public static bool TryInvokeEvent(Enum @enum) { return TryInvokeEvent(@enum.ToString()); } public static bool TryInvokeEvent(Enum @enum, T value) { return TryInvokeEvent(@enum.ToString(), value); } public static bool TryInvokeEvent(string name) { KeyValuePair keyValuePair = _events.FirstOrDefault((KeyValuePair x) => x.Key.Name == name); if (keyValuePair.Key != null) { if (keyValuePair.Value == null) { return keyValuePair.Key.TryInvoke(); } return false; } return false; } public static bool TryInvokeEvent(string name, T value) { KeyValuePair keyValuePair = _events.FirstOrDefault((KeyValuePair x) => x.Key.Name == name); if (keyValuePair.Key != null) { if (keyValuePair.Value != null) { return keyValuePair.Key.TryInvoke(JsonSerializer.Serialize(value)); } return false; } return false; } } internal static class GamemodeMenuManager { private const string TeamConfigName = "{0} Stats"; private static readonly Dictionary IncrementTeams = new Dictionary(); private static readonly IReadOnlyList IncrementValues = new <>z__ReadOnlyArray(new float[4] { 0.2f, 0.5f, 1f, 5f }); internal static GroupElementData CreateSettingsGroup() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown GroupElementData group = new GroupElementData { Title = ((Gamemode)Infection.Instance).Title }; if (group == null) { FusionModule.Logger.Error("Group is null"); return null; } Infection.Instance.Config._settingsList.ForEach(delegate(ISetting x) { if (x is AvatarSetting avatarSetting) { group.AddElement(avatarSetting.CreateGroup()); } }); group.AddElement(CreateElementsForTeam(Infection.Instance.Infected)); group.AddElement(CreateElementsForTeam(Infection.Instance.InfectedChildren)); group.AddElement(CreateElementsForTeam(Infection.Instance.Survivors)); GroupElementData group2 = group.AddGroup("General"); group2.AddElement("Infected Start Number", Infection.Instance.Config.InfectedCount.Value, delegate(int val) { Infection.Instance.Config.InfectedCount.Value = val; }, 1, 1, 5); group2.AddElement("No Time Limit", Infection.Instance.Config.NoTimeLimit.Value, delegate(bool val) { Infection.Instance.Config.NoTimeLimit.Value = val; if (((Gamemode)Infection.Instance).IsStarted) { Infection.Instance.Config.EndUnix.Value = -1L; } RefreshSettingsPage(); }); if (!Infection.Instance.Config.NoTimeLimit.Value) { group2.AddElement("Time Limit", Infection.Instance.Config.TimeLimit.Value, SetTimeLimit, 1, 1); } group2.AddElement("Friendly Fire", Infection.Instance.Config.FriendlyFire.Value, delegate(bool val) { Infection.Instance.Config.FriendlyFire.Value = val; }); group2.AddElement("Dont Repeat Infected", Infection.Instance.Config.DontRepeatInfected.Value, delegate(bool val) { Infection.Instance.Config.DontRepeatInfected.Value = val; }); group2.AddElement("Disable Spawn Gun", ((Gamemode)Infection.Instance).DisableSpawnGun, delegate(bool val) { Infection.Instance.Config.DisableSpawnGun.Value = val; }); group2.AddElement("Disable Developer Tools", ((Gamemode)Infection.Instance).DisableDevTools, delegate(bool val) { Infection.Instance.Config.DisableDevTools.Value = val; }); group2.AddElement("Allow Keep Inventory", Infection.Instance.Config.AllowKeepInventory.Value, delegate(bool val) { Infection.Instance.Config.AllowKeepInventory.Value = val; }); group2.AddElement("Use DeathMatch Spawns", Infection.Instance.Config.UseDeathmatchSpawns.Value, delegate(bool val) { Infection.Instance.Config.UseDeathmatchSpawns.Value = val; }); group2.AddElement("Teleport To Host On Start", Infection.Instance.Config.TeleportOnStart.Value, delegate(bool val) { Infection.Instance.Config.TeleportOnStart.Value = val; }); group2.AddElement("Teleport To Host On End", Infection.Instance.Config.TeleportOnEnd.Value, delegate(bool val) { Infection.Instance.Config.TeleportOnEnd.Value = val; }); group2.AddElement("Countdown Length", Infection.Instance.Config.CountdownLength.Value, SetCountdownLength, 5, 0, 3600); if (Infection.Instance.Config.CountdownLength.Value > 0) { group2.AddElement("Show Countdown to All Players", Infection.Instance.Config.ShowCountdownToAll.Value, delegate(bool val) { Infection.Instance.Config.ShowCountdownToAll.Value = val; }); } group2.AddElement("Infect Type", Infection.Instance.Config.InfectType.Value, delegate(Enum val) { Infection.Instance.Config.InfectType.Value = (Infection.InfectType)(object)val; RefreshSettingsPage(); }); if (Infection.Instance.Config.InfectType.Value == Infection.InfectType.TOUCH) { group2.AddElement("Hold Time", Infection.Instance.Config.HoldTime.Value, delegate(int val) { Infection.Instance.Config.HoldTime.Value = val; }, 1, 0, 60); } else if (Infection.Instance.Config.InfectType.Value == Infection.InfectType.DEATH) { group2.AddElement("Death infect type will disable Knockout", null); } group2.AddElement("Suicide Infects", Infection.Instance.Config.SuicideInfects.Value, delegate(bool val) { Infection.Instance.Config.SuicideInfects.Value = val; }); group2.AddElement("Save Settings", SaveSettings); group2.AddElement("Load Settings", LoadSettings); return group; } private static void SaveSettings() { try { Infection.Instance.TeamManager.InfectedTeams.ForEach(delegate(InfectionTeam x) { x.Metadata.Save(toFile: false); }); Infection.Instance.Config.Save(); MenuHelper.ShowNotification("Success", "Successfully saved settings!", 3.5f, showPopup: true, (NotificationType)0); } catch (Exception ex) { Core.Logger.Error((object)ex); MenuHelper.ShowNotification("Fail", "Failed to save settings, check console for more details", 5f, showPopup: true, (NotificationType)2); } } private static void LoadSettings() { try { Infection.Instance.Config.Load(); Infection.Instance.TeamManager.InfectedTeams.ForEach(delegate(InfectionTeam x) { x.Metadata.Load(); }); RefreshSettingsPage(); MenuHelper.ShowNotification("Success", "Successfully loaded settings!", 3.5f, showPopup: true, (NotificationType)0); } catch (Exception ex) { Core.Logger.Error((object)ex); MenuHelper.ShowNotification("Fail", "Failed to load settings, check console for more details", 5f, showPopup: true, (NotificationType)2); } } private static void SetTimeLimit(int val) { Infection.Instance.Config.TimeLimit.Value = val; if (((Gamemode)Infection.Instance).IsStarted) { Infection.Instance.Config.EndUnix.Value = DateTimeOffset.FromUnixTimeMilliseconds(Infection.Instance.Config.StartUnix.Value).AddMinutes(val).ToUnixTimeMilliseconds(); } } private static void SetCountdownLength(int val) { int value = Infection.Instance.Config.CountdownLength.Value; Infection.Instance.Config.CountdownLength.Value = val; if ((value == 0 && val > 0) || (value > 0 && val == 0)) { RefreshSettingsPage(); } } internal static GroupElementData CreateElementsForTeam(InfectionTeam team) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown GroupElementData group = new GroupElementData { Title = team.GetGroupName() }; bool flag = team == Infection.Instance.InfectedChildren; if (flag) { group.AddElement("Sync With Infected", Infection.Instance.Config.SyncWithInfected.Value, delegate(bool val) { Infection.Instance.Config.SyncWithInfected.Value = val; RefreshSettingsPage(); }); } if (!flag || (flag && !Infection.Instance.Config.SyncWithInfected.Value)) { if (((Gamemode)Infection.Instance).IsStarted) { group.AddElement(FormatApplyName(team, apply: false), delegate { ApplyMetadata(team); }); } FunctionElementData val2 = IncrementElem(((Team)team).TeamName); group.AddElement(val2); team.StaticMetadata._settingsList.Types(delegate(ISetting x) { if (x is ToggleServerSetting stat) { group.CreateStatElement(team, stat); } else if (x is ServerSetting stat2) { group.CreateStatElement(stat2); } }, typeof(ToggleServerSetting), typeof(ServerSetting)); group.AddElement(val2); } return group; } private static FunctionElementData IncrementElem(string teamName) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown return new FunctionElementData { Title = $"Increment: {GetIncrement(teamName)}", OnPressed = delegate { if (!IncrementTeams.TryGetValue(teamName, out var value)) { value = 0; } value++; value %= IncrementValues.Count; IncrementTeams[teamName] = value; RefreshSettingsPage(); } }; } private static float GetIncrement(string teamName) { if (IncrementTeams.TryGetValue(teamName, out var value)) { return IncrementValues[value]; } IncrementTeams[teamName] = 0; return IncrementValues[0]; } private static void CreateStatElement(this GroupElementData group, InfectionTeam team, ToggleServerSetting stat) { group.AddElement("Override " + stat.DisplayName, stat.Enabled, delegate(bool val) { stat.Enabled = val; RefreshSettingsPage(); }); if (stat.Enabled) { group.AddElement(stat.DisplayName, stat.Value, delegate(float val) { stat.Value = val; }, GetIncrement(((Team)team).TeamName)); } } private static void CreateStatElement(this GroupElementData group, ServerSetting stat) { group.AddElement(stat.DisplayName, stat.Value, delegate(bool val) { stat.Value = val; }); } internal static string FormatApplyName(InfectionTeam team, bool apply = true) { string _name; if (team.Metadata.IsApplied) { _name = "Apply new settings (Applied)"; } else { _name = "Apply new settings (Not Applied)"; } if (apply) { ((Gamemode)(object)Infection.Instance).ChangeElement(team.GetGroupName(), "Apply new settings", (Action)delegate(FunctionElement el) { ((MenuElement)el).Title = _name; }, startsWith: false); } return _name; } private static void ApplyMetadata(InfectionTeam team) { if (((Gamemode)Infection.Instance).IsStarted) { if (!team.Metadata.IsApplied) { team.Metadata.ApplyConfig(); EventManager.TryInvokeEvent(Infection.EventType.RefreshStats, ((Team)team).TeamName); } FormatApplyName(team); } } private static string GetGroupName(this InfectionTeam team) { return $"{((Team)team).DisplayName} Stats"; } internal static void RefreshSettingsPage() { if (MenuGamemode.SelectedGamemode != Infection.Instance) { return; } List openGroups = new List(); ((GroupElement)MenuGamemode.SettingsPageElement).Elements.ForEach(delegate(MenuElement x) { DropdownElement val2 = (DropdownElement)(object)((x is DropdownElement) ? x : null); if (val2 != null && val2.Expanded) { openGroups.Add(((MenuElement)val2).Title); } }); Internal_Refresh(); ((GroupElement)MenuGamemode.SettingsPageElement).Elements.ForEach(delegate(MenuElement x) { DropdownElement val = (DropdownElement)(object)((x is DropdownElement) ? x : null); if (val != null && !val.Expanded && openGroups.Contains(((MenuElement)val).Title)) { val.Expand(); } }); } internal static void Internal_Refresh() { ((MenuElement)MenuGamemode.SettingsPageElement).Clear(); MenuGamemode.SettingsGrid.SetActive(true); if (NetworkInfo.IsHost) { typeof(MenuGamemode).GetMethod("ApplySettingsData", BindingFlags.Static | BindingFlags.NonPublic).Invoke(null, new object[1] { Infection.Instance }); } } } internal class InfectionTeamManager : TeamManager { private readonly Dictionary _playersToInfectedTeam = new Dictionary(); public List InfectedTeams { get; } = new List(); public event Action OnAssignedToInfectedTeam; public event Action OnRemovedFromInfectedTeam; public void Register(Gamemode gamemode) { ((TeamManager)this).Register(gamemode); gamemode.Metadata.OnMetadataChanged += OnMetadataChanged; gamemode.Metadata.OnMetadataRemoved += OnMetadataRemoved; } public void Unregister() { ((TeamManager)this).Unregister(); ((TeamManager)this).Gamemode.Metadata.OnMetadataChanged -= OnMetadataChanged; ((TeamManager)this).Gamemode.Metadata.OnMetadataRemoved -= OnMetadataRemoved; } private void OnMetadataChanged(string key, string value) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown if (!KeyHelper.KeyMatchesVariable(key, "Team")) { return; } byte playerFromKey = KeyHelper.GetPlayerFromKey(key); PlayerID playerID = PlayerIDManager.GetPlayerID(playerFromKey); _playersToInfectedTeam[playerFromKey] = new MetadataVariable(key, ((TeamManager)this).Gamemode.Metadata); foreach (InfectionTeam infectedTeam in InfectedTeams) { if (((Team)infectedTeam).HasPlayer(playerFromKey)) { if (((Team)infectedTeam).HasPlayer(playerFromKey)) { ((Team)infectedTeam).ForceRemovePlayer(playerFromKey); } if (playerID != null) { this.OnRemovedFromInfectedTeam?.Invoke(playerID, infectedTeam); } } } InfectionTeam teamByName = GetTeamByName(value); if (teamByName != null) { if (!((Team)teamByName).HasPlayer(playerFromKey)) { ((Team)teamByName).ForceAddPlayer(playerFromKey); } if (playerID != null) { this.OnAssignedToInfectedTeam?.Invoke(playerID, teamByName); } } } private void OnMetadataRemoved(string key, string value) { if (!KeyHelper.KeyMatchesVariable(key, "Team")) { return; } byte playerFromKey = KeyHelper.GetPlayerFromKey(key); PlayerID playerID = PlayerIDManager.GetPlayerID(playerFromKey); _playersToInfectedTeam.Remove(playerFromKey); InfectionTeam teamByName = GetTeamByName(value); if (teamByName != null) { if (((Team)teamByName).HasPlayer(playerFromKey)) { ((Team)teamByName).ForceRemovePlayer(playerFromKey); } if (playerID != null) { this.OnRemovedFromInfectedTeam?.Invoke(playerID, teamByName); } } } public void AddTeam(InfectionTeam team) { InfectedTeams.Add(team); ((TeamManager)this).AddTeam((Team)(object)team); } public void RemoveTeam(InfectionTeam team) { InfectedTeams.Remove(team); ((TeamManager)this).RemoveTeam((Team)(object)team); } public void ClearTeams() { ((TeamManager)this).UnassignAllPlayers(); InfectionTeam[] array = InfectedTeams.ToArray(); foreach (InfectionTeam team in array) { RemoveTeam(team); } } public InfectionTeam GetTeamByName(string name) { foreach (InfectionTeam infectedTeam in InfectedTeams) { if (((Team)infectedTeam).TeamName == name) { return infectedTeam; } } return null; } public InfectionTeam GetPlayerTeam(PlayerID player) { return InfectedTeams.FirstOrDefault((InfectionTeam x) => ((Team)x).HasPlayer(player)); } public InfectionTeam GetLocalTeam() { return GetPlayerTeam(PlayerIDManager.LocalID); } public InfectionTeam GetRandomTeam() { return InfectedTeams.Random(); } public InfectionTeam GetTeamWithFewestPlayers() { int num = int.MaxValue; InfectionTeam result = null; foreach (InfectionTeam infectedTeam in InfectedTeams) { if (((Team)infectedTeam).PlayerCount < num) { num = ((Team)infectedTeam).PlayerCount; result = infectedTeam; } } return result; } public InfectionTeam GetInfectionTeamFromTeam(Team team) { return InfectedTeams.FirstOrDefault((InfectionTeam x) => x == team); } } public static class MetadataManager { public const string HAS_AVATAR_INFECTION_KEY = "DoYouHaveAvatarInfection"; public const string AVATAR_MOD_ID = "AvatarInfection-AvatarModId"; public static void IHaveAvatarInfection() { LocalPlayer.Metadata.Metadata.TrySetMetadata("DoYouHaveAvatarInfection", bool.TrueString); } public static bool DoYouHaveAvatarInfection(PlayerID player) { string value = default(string); bool result = default(bool); return player.Metadata.Metadata.TryGetMetadata("DoYouHaveAvatarInfection", ref value) && !string.IsNullOrWhiteSpace(value) && bool.TryParse(value, out result) && result; } public static int CountPlayersWithAvatarInfection() { int plrs = 0; IEnumerableExtensions.ForEach((IEnumerable)PlayerIDManager.PlayerIDs, (Action)delegate(PlayerID x) { string text = default(string); if (x.Metadata.Metadata.TryGetMetadata("DoYouHaveAvatarInfection", ref text) && !string.IsNullOrWhiteSpace(text) && text == bool.TrueString) { plrs++; } }); return plrs; } public static bool IsAvatarDownloadable(this PlayerID player) { object value; if (player == null) { value = null; } else { PlayerMetadata metadata = player.Metadata; if (metadata == null) { value = null; } else { MetadataInt avatarModID = metadata.AvatarModID; value = ((avatarModID != null) ? ((MetadataVariable)avatarModID).GetValueOrEmpty() : null); } } if (!string.IsNullOrWhiteSpace((string?)value)) { return ((MetadataVariableT)(object)player.Metadata.AvatarModID).GetValue() != -1; } return false; } } public static class StatsManager { public static void ClearOverrides() { Overrides.ClearAllOverrides(); Overrides.ClearAvatarOverride(); } internal static void ApplyStats() { if (((Gamemode)Infection.Instance).IsStarted) { InfectionTeam localTeam = Infection.Instance.TeamManager.GetLocalTeam(); if (localTeam == null) { ClearOverrides(); } else { Internal_SetStats(localTeam); } } } private static T? GetToggleValue(ToggleServerSetting serverSetting) where T : struct, IEquatable { if (serverSetting == null) { return null; } if (serverSetting.Enabled) { return serverSetting.Value; } return null; } private static void Internal_SetStats(InfectionTeam team) { TeamMetadata metadata = team.Metadata; if (metadata != null) { FusionOverrides.ForceUpdateOverrides(); float? toggleValue = GetToggleValue(metadata.Speed); float? toggleValue2 = GetToggleValue(metadata.Agility); float? toggleValue3 = GetToggleValue(metadata.StrengthUpper); float? toggleValue4 = GetToggleValue(metadata.Vitality); LocalAvatar.HeightOverride = GetToggleValue(metadata.Height); Overrides.SetOverrides(toggleValue, toggleValue2, toggleValue3, toggleValue4, metadata.Mortality.Value); } } internal static void RefreshStats(string teamName) { InfectionTeam teamByName = Infection.Instance.TeamManager.GetTeamByName(teamName); if (teamByName != null && Infection.Instance.TeamManager.GetLocalTeam() == teamByName) { ApplyStats(); } } } public static class TimeManager { private static float _deltaTime = 1f; private static float _fixedDeltaTime = 0.02f; private static float _timeSinceStartup = 0f; private static float _timeScale = 1f; private static int _frameCount = 0; public static List RepeatedActions { get; } = new List(); public static float DeltaTime => _deltaTime; public static float FixedDeltaTime => _fixedDeltaTime; public static float TimeSinceStartup => _timeSinceStartup; public static float TimeScale => _timeScale; public static int FrameCount => _frameCount; internal static void OnEarlyUpdate() { _timeScale = Time.timeScale; _deltaTime = Time.deltaTime; _timeSinceStartup += _deltaTime; _frameCount++; } internal static void OnEarlyFixedUpdate() { _fixedDeltaTime = Time.fixedDeltaTime; } public static bool IsMatchingFrame(int interval) { return FrameCount % interval == 0; } public static bool IsMatchingFrame(int interval, int offset) { return (FrameCount + offset) % interval == 0; } public static void Repeat(Action action, int? milliseconds = null) { RepeatedActions.Add(new RepeatedAction { Milliseconds = milliseconds, Action = action }); } public static void OnUpdate() { RepeatedActions.ForEach(delegate(RepeatedAction x) { if (!x.Milliseconds.HasValue) { try { x.Action?.Invoke(); return; } catch (Exception ex) { MelonLogger.Error("An unexpected error has occured while running a repeated action", ex); return; } } x.Elapsed += DeltaTime; if (x.Elapsed >= (float)x.Milliseconds.Value / 1000f) { try { x.Action?.Invoke(); } catch (Exception ex2) { MelonLogger.Error("An unexpected error has occured while running a repeated action", ex2); } x.Elapsed = 0f; } }); } } public class RepeatedAction { public int? Milliseconds { get; set; } public float Elapsed { get; set; } public Action Action { get; set; } } internal static class VisionManager { [CompilerGenerated] private sealed class d__16 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public CancellationTokenSource token; public float delaySeconds; private CancellationToken 5__2; private bool 5__3; private int 5__4; private float 5__5; private float 5__6; private int 5__7; private bool 5__8; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__16(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 1) <= 1u) { try { } finally { <>m__Finally1(); } } 5__2 = default(CancellationToken); <>1__state = -2; } private bool MoveNext() { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>1__state = -3; 5__2 = HandleToken(token); 5__3 = false; if (!IsCountdownActive() || !IsAllowed()) { break; } if (delaySeconds > 0f) { <>2__current = (object)new WaitForSeconds(delaySeconds); <>1__state = 1; return true; } goto IL_008f; case 1: <>1__state = -3; goto IL_008f; case 2: { <>1__state = -3; goto IL_0186; } IL_008f: InfectedVisionEffect(active: true); 5__4 = ((MetadataVariableT)(object)Infection.Instance.CountdownValue).GetValue(); 5__5 = 0f; 5__6 = 0f; 5__7 = 0; 5__8 = true; goto IL_0186; IL_0186: if (5__7 < 5__4) { if (!IsCancelled(5__4, 5__2)) { if (TeamManager.GetLocalTeam() == Infected) { float num = Mathf.Max((float)5__4 - 1f, 0f); float num2 = Mathf.Max(5__6 - num, 0f) / 1f; LocalVision.BlindColor = Color.Lerp(Color.black, Color.clear, num2); } HandleTime(5__4, ref 5__5, ref 5__6, ref 5__7, ref 5__8); <>2__current = null; <>1__state = 2; return true; } 5__3 = true; } VisionEffect(active: false); TutorialRig.Instance.headTitles.CLOSEDISPLAY(); break; } if (TeamManager.GetLocalTeam() == Infected && !5__3) { MenuHelper.ShowNotification("Countdown Over", "GO AND INFECT THEM ALL!", 3.5f, showPopup: true, (NotificationType)0); } 5__2 = default(CancellationToken); <>m__Finally1(); return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; HideVision = false; } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } internal static bool HideVision { get; set; } private static TeamManager TeamManager => (TeamManager)(object)Infection.Instance.TeamManager; private static InfectionSettings Config => Infection.Instance.Config; private static Team Infected => (Team)(object)Infection.Instance.Infected; private static CancellationTokenSource CancellationToken { get; set; } internal static void OnUpdate() { if (HideVision && !LocalVision.Blind) { LocalVision.Blind = true; } } internal static void HideVisionAndReveal(float delaySeconds = 0f) { MelonCoroutines.Start(Internal_HideVisionAndReveal(delaySeconds)); } [IteratorStateMachine(typeof(d__16))] private static IEnumerator Internal_HideVisionAndReveal(float delaySeconds = 0f, CancellationTokenSource token = null) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__16(0) { delaySeconds = delaySeconds, token = token }; } private static CancellationToken HandleToken(CancellationTokenSource source) { if (CancellationToken != null) { CancellationToken.Cancel(); CancellationToken.Dispose(); CancellationToken = null; } CancellationToken = source ?? new CancellationTokenSource(); return CancellationToken.Token; } private static bool IsCancelled(int target, CancellationToken token) { if (((Gamemode)Infection.Instance).IsStarted && (!((MetadataVariableT)(object)Infection.Instance.InfectedLooking).GetValue() || target <= 5)) { return token.IsCancellationRequested; } return true; } private static void DisplayCountdown(int num) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) int value = ((MetadataVariableT)(object)Infection.Instance.CountdownValue).GetValue(); Sprite val = Sprite.Create(Texture2D.whiteTexture, new Rect(0f, 0f, 0f, 0f), new Vector2(0.5f, 0.5f), 100f); TutorialRig instance = TutorialRig.Instance; HeadTitles headTitles = instance.headTitles; ((Component)instance).gameObject.SetActive(true); ((Component)headTitles).gameObject.SetActive(true); instance.headTitles.timeToScale = Mathf.Lerp(0.05f, 0.4f, Mathf.Clamp01((float)value - 1f)); instance.headTitles.CUSTOMDISPLAY("Countdown, get ready...", num.ToString(), val, (float)value, (AudioClip)null, false, (Sprite)null, (Sprite)null, (Sprite)null, (Sprite)null); instance.headTitles.sr_element.sprite = val; } private static bool IsCountdownActive() { if (Config.CountdownLength.Value != 0 && ((MetadataVariableT)(object)Infection.Instance.CountdownValue).GetValue() != 0) { return !((MetadataVariableT)(object)Infection.Instance.InfectedLooking).GetValue(); } return false; } private static bool IsAllowed() { if (((Gamemode)Infection.Instance).IsStarted) { if (!Infection.Instance.Config.ShowCountdownToAll.Value || TeamManager.GetLocalTeam() == Infected) { return TeamManager.GetLocalTeam() == Infected; } return true; } return false; } private static void InfectedVisionEffect(bool active) { if (TeamManager.GetLocalTeam() == Infected) { VisionEffect(active); } } private static void HandleTime(int target, ref float elapsed, ref float totalElapsed, ref int seconds, ref bool secondPassed) { if (secondPassed) { DisplayCountdown(target - seconds); secondPassed = false; } elapsed += TimeManager.DeltaTime; totalElapsed += TimeManager.DeltaTime; if (elapsed >= 1f) { elapsed -= 1f; seconds++; secondPassed = true; } } private static void VisionEffect(bool active) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) LocalControls.LockedMovement = active; if (active) { HideVision = true; } LocalVision.BlindColor = Color.black; LocalVision.Blind = active; Overrides.SetOverrides(Overrides.Speed, Overrides.Agility, Overrides.StrengthUpper, Overrides.Vitality, !active && Infection.Instance.Infected.Metadata.Mortality.Value); } } } namespace AvatarInfection.Helper { public static class CollectionHelper { private static readonly Random random = new Random(); public static T Random(this List list) { return list[random.Next(0, list.Count)]; } public static T Random(this T[] list) { return list[random.Next(0, list.Length)]; } public static KeyValuePair Random(this Dictionary dictionary) { return dictionary.ElementAt(random.Next(0, dictionary.Count)); } public static T Random(this List list) { return list[random.Next(0, list.Count)]; } public static KeyValuePair Random(this Dictionary dictionary) { Entry val = ((Il2CppArrayBase>)(object)dictionary._entries)[random.Next(0, dictionary.Count)]; return new KeyValuePair(val.key, val.value); } internal static void Types(this List settings, Action forEach, params Type[] types) { List list = new List(settings); list.RemoveAll((ISetting x) => !types.Contains(x.GetType())); list.ForEach(delegate(ISetting x) { if (x != null && types.Contains(x.GetType())) { forEach(x); } }); } } public static class ImageConversion { private delegate IntPtr TextureOnlyDelegate(IntPtr tex); private delegate IntPtr TextureAndQualityDelegate(IntPtr tex, int quality); private delegate IntPtr TextureAndFlagDelegate(IntPtr tex, EXRFlags flags); private delegate bool LoadImageDelegate(IntPtr tex, IntPtr data, bool markNonReadable); private const string NullTextureError = "The texture cannot be null."; private static readonly TextureAndFlagDelegate EncodeToEXRDelegateField = IL2CPP.ResolveICall("UnityEngine.ImageConversion::EncodeToEXR"); private static readonly TextureOnlyDelegate EncodeToTGADelegateField = IL2CPP.ResolveICall("UnityEngine.ImageConversion::EncodeToTGA"); private static readonly TextureOnlyDelegate EncodeToPNGDelegateField = IL2CPP.ResolveICall("UnityEngine.ImageConversion::EncodeToPNG"); private static readonly TextureAndQualityDelegate EncodeToJPGDelegateField = IL2CPP.ResolveICall("UnityEngine.ImageConversion::EncodeToJPG"); private static readonly LoadImageDelegate LoadImageDelegateField = IL2CPP.ResolveICall("UnityEngine.ImageConversion::LoadImage"); public static Il2CppStructArray EncodeToTGA(this Texture2D tex) { if ((Object)(object)tex == (Object)null) { throw new ArgumentNullException("tex", "The texture cannot be null."); } if (EncodeToTGADelegateField == null) { throw new InvalidOperationException("The EncodeToTGADelegateField cannot be null."); } IntPtr intPtr = EncodeToTGADelegateField(IL2CPP.Il2CppObjectBaseToPtr((Il2CppObjectBase)(object)tex)); if (intPtr != IntPtr.Zero) { return new Il2CppStructArray(intPtr); } return null; } public static Il2CppStructArray EncodeToPNG(this Texture2D tex) { if ((Object)(object)tex == (Object)null) { throw new ArgumentNullException("tex", "The texture cannot be null."); } if (EncodeToPNGDelegateField == null) { throw new InvalidOperationException("The EncodeToPNGDelegateField cannot be null."); } IntPtr intPtr = EncodeToPNGDelegateField(IL2CPP.Il2CppObjectBaseToPtr((Il2CppObjectBase)(object)tex)); if (intPtr != IntPtr.Zero) { return new Il2CppStructArray(intPtr); } return null; } public static Il2CppStructArray EncodeToJPG(this Texture2D tex, int quality) { if ((Object)(object)tex == (Object)null) { throw new ArgumentNullException("tex", "The texture cannot be null."); } if (EncodeToJPGDelegateField == null) { throw new InvalidOperationException("The EncodeToJPGDelegateField cannot be null."); } IntPtr intPtr = EncodeToJPGDelegateField(IL2CPP.Il2CppObjectBaseToPtr((Il2CppObjectBase)(object)tex), quality); if (intPtr != IntPtr.Zero) { return new Il2CppStructArray(intPtr); } return null; } public static Il2CppStructArray EncodeToJPG(this Texture2D tex) { return tex.EncodeToJPG(75); } public static Il2CppStructArray EncodeToEXR(this Texture2D tex, EXRFlags flags) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)tex == (Object)null) { throw new ArgumentNullException("tex", "The texture cannot be null."); } if (EncodeToEXRDelegateField == null) { throw new InvalidOperationException("The EncodeToEXRDelegateField cannot be null."); } IntPtr intPtr = EncodeToEXRDelegateField(IL2CPP.Il2CppObjectBaseToPtr((Il2CppObjectBase)(object)tex), flags); if (intPtr != IntPtr.Zero) { return new Il2CppStructArray(intPtr); } return null; } public static Il2CppStructArray EncodeToEXR(this Texture2D tex) { return tex.EncodeToEXR((EXRFlags)0); } public static bool LoadImage(this Texture2D tex, Il2CppStructArray data, bool markNonReadable) { if ((Object)(object)tex == (Object)null) { throw new ArgumentNullException("tex", "The texture cannot be null."); } if (data == null) { throw new ArgumentNullException("data", "The data cannot be null."); } if (LoadImageDelegateField == null) { throw new InvalidOperationException("The LoadImageDelegateField cannot be null."); } return LoadImageDelegateField(IL2CPP.Il2CppObjectBaseToPtr((Il2CppObjectBase)(object)tex), IL2CPP.Il2CppObjectBaseToPtr((Il2CppObjectBase)(object)data), markNonReadable); } public static bool LoadImage(this Texture2D tex, Il2CppStructArray data) { return tex.LoadImage(data, markNonReadable: false); } public static Texture2D LoadTexture(string name, byte[] bytes) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown Texture2D val = new Texture2D(2, 2); LoadImage(val, Il2CppStructArray.op_Implicit(bytes), markNonReadable: false); ((Object)val).name = name; ((Object)val).hideFlags = (HideFlags)32; return val; } public static Texture2D LoadTexture(string name, string file, string folder = "Icons") { byte[] bytes = ReadEmbeddedFile(file, folder); return LoadTexture(name, bytes); } public static byte[] ReadEmbeddedFile(string file, string folder = "Icons") { if (string.IsNullOrWhiteSpace(file)) { return Array.Empty(); } Assembly executingAssembly = Assembly.GetExecutingAssembly(); string name = executingAssembly.GetName().Name + ".Embedded." + ((!string.IsNullOrWhiteSpace(folder)) ? (folder + ".") : string.Empty) + file; Stream manifestResourceStream = executingAssembly.GetManifestResourceStream(name); if (manifestResourceStream == null) { return Array.Empty(); } manifestResourceStream.Position = 0L; using MemoryStream memoryStream = new MemoryStream(); manifestResourceStream.CopyTo(memoryStream); return memoryStream.ToArray(); } } public static class MenuHelper { public static MenuElement GetElement(this Gamemode gamemode, string groupName, string elementName, bool startsWith = true) { if (MenuGamemode.SelectedGamemode != gamemode) { return null; } MenuElement? obj = ((IEnumerable)((GroupElement)MenuGamemode.SettingsPageElement).Elements).FirstOrDefault((Func)((MenuElement x) => x.Title == groupName)); GroupElement val = (GroupElement)(object)((obj is GroupElement) ? obj : null); if (val == null) { return null; } return val.Elements?.FirstOrDefault((Func)((MenuElement x) => (!startsWith) ? x.Title.Contains(elementName) : x.Title.StartsWith(elementName))); } public static ElementT ChangeElement(this Gamemode gamemode, string groupName, string elementName, Action changes, bool startsWith = true) where ElementT : MenuElement { MenuElement element = gamemode.GetElement(groupName, elementName, startsWith); ElementT val = (((Object)(object)element == (Object)null) ? default(ElementT) : ((ElementT)(object)element)); if ((Object)(object)val != (Object)null) { changes(val); } return val; } public static StringElementData AddElement(this GroupElementData group, string title, string value, Action callback) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown StringElementData val2 = new StringElementData { Title = title, Value = value, OnValueChanged = delegate(string val) { callback?.Invoke(val); } }; group.AddElement(val2); return val2; } public static FunctionElementData AddElement(this GroupElementData group, string title, Action callback) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown FunctionElementData val = new FunctionElementData { Title = title, OnPressed = delegate { callback?.Invoke(); } }; group.AddElement(val); return val; } public static IntElementData AddElement(this GroupElementData group, string title, int value, Action callback, int increment = 1, int min = 0, int max = 100) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown IntElementData val2 = new IntElementData { Title = title, Increment = increment, MaxValue = max, MinValue = min, Value = value, OnValueChanged = delegate(int val) { callback?.Invoke(val); } }; group.AddElement(val2); return val2; } public static FloatElementData AddElement(this GroupElementData group, string title, float value, Action callback, float increment = 0.2f, float min = 0.2f, float max = 100f) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown FloatElementData val2 = new FloatElementData { Title = title, Increment = increment, MaxValue = max, MinValue = min, Value = value, OnValueChanged = delegate(float val) { callback?.Invoke(val); } }; group.AddElement(val2); return val2; } public static BoolElementData AddElement(this GroupElementData group, string title, bool value, Action callback) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown BoolElementData val2 = new BoolElementData { Title = title, Value = value, OnValueChanged = delegate(bool val) { callback?.Invoke(val); } }; group.AddElement(val2); return val2; } public static EnumElementData AddElement(this GroupElementData group, string title, Enum @enum, Action callback) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown EnumElementData val = new EnumElementData { Title = title, EnumType = @enum.GetType(), Value = @enum, OnValueChanged = callback }; group.AddElement(val); return val; } public static GroupElementData AddGroup(this GroupElementData group, string title) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown GroupElementData val = new GroupElementData(title); group.AddElement(val); return val; } public static void ShowNotification(string title, string message, float popupLength, bool showPopup = true, NotificationType type = 0, bool saveToMenu = false) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown Notifier.Send(new Notification { Message = NotificationText.op_Implicit(message), Title = NotificationText.op_Implicit(title), PopupLength = popupLength, ShowPopup = showPopup, Type = type, OnAccepted = null, OnDeclined = null, SaveToMenu = saveToMenu }); } } public static class WarehouseHelper { public static void ExcludeRedacted(this List list) { list.RemoveAll(Predicate.op_Implicit((Func)((AvatarCrate x) => ((Scannable)x).Redacted))); } public static void ExcludeNonPublic(this List list) { list.RemoveAll(Predicate.op_Implicit((Func)((AvatarCrate x) => !((Crate)(object)x).IsPublic()))); } public static bool IsPublic(this Crate crate) { if (CrateFilterer.GetModID(crate.Pallet) == -1) { return AssetWarehouse.Instance.gamePallets.Contains(((Scannable)crate.Pallet).Barcode); } return true; } } }