Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Enova ReadyCompany v0.1.0
ReadyCompany.dll
Decompiled 2 years agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using CSync.Extensions; using CSync.Lib; using HarmonyLib; using LethalCompanyInputUtils.Api; using LethalConfig; using LethalConfig.ConfigItems; using LethalConfig.ConfigItems.Options; using LethalNetworkAPI; using LethalNetworkAPI.Utils; using LobbyCompatibility.Enums; using LobbyCompatibility.Features; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.InputSystem; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("ClientNetworkTransform")] [assembly: IgnoresAccessChecksTo("DissonanceVoip")] [assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")] [assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")] [assembly: IgnoresAccessChecksTo("LethalCompanyInputUtils")] [assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")] [assembly: IgnoresAccessChecksTo("Unity.Burst")] [assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")] [assembly: IgnoresAccessChecksTo("Unity.Collections")] [assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")] [assembly: IgnoresAccessChecksTo("Unity.Jobs")] [assembly: IgnoresAccessChecksTo("Unity.Mathematics")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")] [assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")] [assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")] [assembly: IgnoresAccessChecksTo("Unity.Services.QoS")] [assembly: IgnoresAccessChecksTo("Unity.Services.Relay")] [assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")] [assembly: IgnoresAccessChecksTo("Unity.Timeline")] [assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")] [assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UI")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("ReadyCompany")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0+5880594799e45fc5c6bf37ebc5fd38d28c1e4bf4")] [assembly: AssemblyProduct("ReadyCompany")] [assembly: AssemblyTitle("ReadyCompany")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ReadyCompany { [BepInPlugin("ReadyCompany", "ReadyCompany", "0.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency("com.sigurd.csync", "5.0.0")] public class ReadyCompany : BaseUnityPlugin { internal static ReadyCompanyConfig Config; public static ReadyCompany Instance { get; private set; } internal static ManualLogSource Logger { get; private set; } internal static Harmony? Harmony { get; set; } internal static ReadyInputs InputActions { get; set; } private void Awake() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown //IL_0090: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown Logger = ((BaseUnityPlugin)this).Logger; Config = new ReadyCompanyConfig(((BaseUnityPlugin)this).Config); Instance = this; BoolCheckBoxConfigItem val = new BoolCheckBoxConfigItem(Config.RequireReadyToStart.Entry, false); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val); BoolCheckBoxConfigItem val2 = new BoolCheckBoxConfigItem(Config.AutoStartWhenReady.Entry, false); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val2); ConfigEntry<int> entry = Config.PercentageForReady.Entry; IntSliderOptions val3 = new IntSliderOptions { RequiresRestart = false }; ((BaseRangeOptions<int>)val3).Min = 0; ((BaseRangeOptions<int>)val3).Max = 100; IntSliderConfigItem val4 = new IntSliderConfigItem(entry, val3); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val4); if (Chainloader.PluginInfos.ContainsKey("BMX.LobbyCompatibility")) { PluginHelper.RegisterPlugin("ReadyCompany", new Version("0.1.0"), (CompatibilityLevel)1, (VersionStrictness)1); } ReadyHandler.InitializeEvents(); Patch(); Logger.LogInfo((object)"ReadyCompany v0.1.0 has loaded!"); } internal static void Patch() { //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_0018: Expected O, but got Unknown if (Harmony == null) { Harmony = new Harmony("ReadyCompany"); } Logger.LogDebug((object)"Patching..."); Harmony.PatchAll(); Logger.LogDebug((object)"Finished patching!"); } internal static void Unpatch() { Logger.LogDebug((object)"Unpatching..."); Harmony? harmony = Harmony; if (harmony != null) { harmony.UnpatchSelf(); } Logger.LogDebug((object)"Finished unpatching!"); } } public class ReadyCompanyConfig : SyncedConfig2<ReadyCompanyConfig> { [field: SyncedEntryField] public SyncedEntry<bool> RequireReadyToStart { get; private set; } [field: SyncedEntryField] public SyncedEntry<bool> AutoStartWhenReady { get; private set; } [field: SyncedEntryField] public SyncedEntry<int> PercentageForReady { get; private set; } public ReadyCompanyConfig(ConfigFile cfg) : base("ReadyCompany") { RequireReadyToStart = SyncedBindingExtensions.BindSyncedEntry<bool>(cfg, "Features", "RequireReadyToStart", false, "Require the lobby to be Ready to pull the ship lever."); AutoStartWhenReady = SyncedBindingExtensions.BindSyncedEntry<bool>(cfg, "Features", "AutoStartWhenReady", false, "Automatically pull the ship lever when the lobby is Ready."); PercentageForReady = SyncedBindingExtensions.BindSyncedEntry<int>(cfg, "Tuning", "PercentageForReady", 100, "What percentage of ready players is needed for the lobby to be considered \"Ready\"."); RequireReadyToStart.Changed += delegate { ReadyHandler.UpdateReadyMap(); }; AutoStartWhenReady.Changed += delegate { ReadyHandler.UpdateReadyMap(); }; RequireReadyToStart.Changed += delegate { ReadyHandler.UpdateReadyMap(); }; ConfigManager.Register<ReadyCompanyConfig>((SyncedConfig2<ReadyCompanyConfig>)(object)this); } } public class ReadyHandler { private const string READY_STATUS_SIG = "ReadyCompany_readyStatusVar"; private const string READY_EVENT_SIG = "ReadyCompany_playerReadyEvent"; internal const string LEVER_DISABLED_TIP = "[ Lobby must be ready to start ]"; internal const string LEVER_WARNING_TIP = "[ WARNING: Lobby Not Ready ]"; internal const string LEVER_NORMAL_TIP = "Start game : [LMB]"; private static readonly LNetworkMessage<bool> readyUpMessage; private static readonly Dictionary<ulong, bool> _playerReadyMap; public static LNetworkVariable<ReadyStatus> ReadyStatus { get; } private static int ServerLobbySize => ((Object)(object)StartOfRound.Instance == (Object)null) ? (-1) : StartOfRound.Instance.fullyLoadedPlayers.Count; internal static void InitializeEvents() { ReadyStatus.Value = new ReadyStatus(0, 0); LNetworkUtils.OnNetworkStart += delegate { UpdateReadyMap(); ReadyCompany.InputActions = new ReadyInputs(); ReadyCompany.InputActions.ReadyInput.performed += ReadyInputPerformed; ReadyCompany.InputActions.UnreadyInput.performed += UnreadyInputPerformed; }; } public static bool IsLobbyReady(ReadyStatus status) { return status.PlayersReady / status.LobbySize >= ReadyCompany.Config.PercentageForReady.Value / 100; } public static void ResetReadyUp() { _playerReadyMap.Clear(); UpdateReadyMap(); } internal static void OnClientConnected() { UpdateReadyMap(); } internal static void OnClientDisconnected() { UpdateReadyMap(); } private static void ReadyUpFromServer(bool isReady) { ReadyCompany.Logger.LogDebug((object)$"Ready up from server: {isReady}"); } private static void ReadyStatusChanged(ReadyStatus oldValue, ReadyStatus newValue) { PopupReadyStatus(newValue); ReadyCompany.Logger.LogDebug((object)$"Ready status changed: {newValue.PlayersReady}, {newValue.LobbySize}"); } private static void PopupReadyStatus(ReadyStatus status) { if (!((Object)(object)HUDManager.Instance == (Object)null) && StartOfRound.Instance.inShipPhase) { HUDManager.Instance.DisplayTip("Ready Up!", $"{status.PlayersReady} / {status.LobbySize} Players are ready.", false, false, "ReadyCompany_ReadyTip"); HUDManager.Instance.DisplaySpectatorTip($"{status.PlayersReady} / {status.LobbySize} Players are ready."); UpdateShipLever(status); } } private static void UpdateShipLever(ReadyStatus status) { StartMatchLever val = Object.FindObjectOfType<StartMatchLever>(); bool flag = IsLobbyReady(status); if (ReadyCompany.Config.RequireReadyToStart.Value) { val.triggerScript.disabledHoverTip = (flag ? "" : "[ Lobby must be ready to start ]"); val.triggerScript.hoverTip = (flag ? "Start game : [LMB]" : "[ WARNING: Lobby Not Ready ]"); val.triggerScript.interactable = flag || LNetworkUtils.IsHostOrServer; } else if (val.triggerScript.disabledHoverTip == "[ Lobby must be ready to start ]") { val.triggerScript.disabledHoverTip = ""; val.triggerScript.hoverTip = "Start game : [LMB]"; val.triggerScript.interactable = true; } if (ReadyCompany.Config.AutoStartWhenReady.Value && LNetworkUtils.IsHostOrServer && flag) { val.LeverAnimation(); val.PullLever(); } } private static void ReadyUpFromClient(bool isReady, ulong clientId) { _playerReadyMap[clientId] = isReady; UpdateReadyMap(); ReadyCompany.Logger.LogDebug((object)$"Ready up from client: {ReadyStatus.Value} and {_playerReadyMap[clientId]}"); } public static void UpdateReadyMap() { VerifyReadyUpMap(); ReadyStatus.Value = new ReadyStatus(_playerReadyMap.Count((KeyValuePair<ulong, bool> kvp) => kvp.Value), ServerLobbySize); ReadyStatus.MakeDirty(); } private static void VerifyReadyUpMap() { foreach (var (key, _) in _playerReadyMap.Where((KeyValuePair<ulong, bool> kvp) => !StartOfRound.Instance.ClientPlayerList.ContainsKey(kvp.Key))) { _playerReadyMap.Remove(key); } } public static void ReadyInputPerformed(CallbackContext context) { readyUpMessage.SendServer(true); } private static void UnreadyInputPerformed(CallbackContext context) { readyUpMessage.SendServer(false); } static ReadyHandler() { Action<ReadyStatus, ReadyStatus> action = ReadyStatusChanged; ReadyStatus = LNetworkVariable<global::ReadyCompany.ReadyStatus>.Connect("ReadyCompany_readyStatusVar", default(ReadyStatus), (LNetworkVariableWritePerms)0, action); readyUpMessage = LNetworkMessage<bool>.Connect("ReadyCompany_playerReadyEvent", (Action<bool, ulong>)ReadyUpFromClient, (Action<bool>)ReadyUpFromServer, (Action<bool, ulong>)null); _playerReadyMap = new Dictionary<ulong, bool>(); } } public class ReadyInputs : LcInputActions { [InputAction(/*Could not decode attribute arguments.*/)] public InputAction ReadyInput { get; set; } = null; [InputAction(/*Could not decode attribute arguments.*/)] public InputAction UnreadyInput { get; set; } = null; } [Serializable] public struct ReadyStatus { public int PlayersReady; public int LobbySize; public ReadyStatus(int playersReady, int lobbySize) { PlayersReady = playersReady; LobbySize = lobbySize; } } public static class MyPluginInfo { public const string PLUGIN_GUID = "ReadyCompany"; public const string PLUGIN_NAME = "ReadyCompany"; public const string PLUGIN_VERSION = "0.1.0"; } } namespace ReadyCompany.Patches { [HarmonyPatch(typeof(StartMatchLever))] [HarmonyPriority(0)] [HarmonyWrapSafe] public class StartMatchLeverPatches { [HarmonyPatch("Update")] [HarmonyPrefix] public static bool UpdatePatch(StartMatchLever __instance) { if (__instance.triggerScript.hoverTip == "[ Lobby must be ready to start ]" || __instance.triggerScript.hoverTip == "[ WARNING: Lobby Not Ready ]") { return false; } return true; } } [HarmonyPatch(typeof(StartOfRound))] [HarmonyPriority(500)] [HarmonyWrapSafe] public class StartOfRoundPatches { [HarmonyPatch("PlayerLoadedClientRpc")] [HarmonyPostfix] public static void OnClientConnectedPatch() { if (LNetworkUtils.IsHostOrServer) { ReadyHandler.OnClientConnected(); } } [HarmonyPatch("OnPlayerDC")] [HarmonyPostfix] public static void OnClientDisconnectedPatch() { if (LNetworkUtils.IsHostOrServer) { ReadyHandler.OnClientDisconnected(); } } [HarmonyPatch("SetShipReadyToLand")] [HarmonyPostfix] public static void OnShipReadyToLandPatch() { if (LNetworkUtils.IsHostOrServer) { ReadyHandler.ResetReadyUp(); } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }