using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Lockout;
using Microsoft.CodeAnalysis;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Events;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Lockout")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Lockout")]
[assembly: AssemblyTitle("Lockout")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/AntoninJuquel/lethal-company-lockout")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
[Serializable]
public class SyncedInstance<T>
{
[NonSerialized]
protected static int IntSize = 4;
internal static CustomMessagingManager MessageManager => NetworkManager.Singleton.CustomMessagingManager;
internal static bool IsClient => NetworkManager.Singleton.IsClient;
internal static bool IsHost => NetworkManager.Singleton.IsHost;
public static T Default { get; private set; }
public static T Instance { get; private set; }
public static bool Synced { get; internal set; }
protected void InitInstance(T instance)
{
Default = instance;
Instance = instance;
IntSize = 4;
}
internal static void SyncInstance(byte[] data)
{
Instance = DeserializeFromBytes(data);
Synced = true;
}
internal static void RevertSync()
{
Instance = Default;
Synced = false;
}
public static byte[] SerializeToBytes(T val)
{
BinaryFormatter binaryFormatter = new BinaryFormatter();
using MemoryStream memoryStream = new MemoryStream();
try
{
binaryFormatter.Serialize(memoryStream, val);
return memoryStream.ToArray();
}
catch (Exception arg)
{
LockoutBase.Logger.LogError((object)$"Error serializing instance: {arg}");
return null;
}
}
public static T DeserializeFromBytes(byte[] data)
{
BinaryFormatter binaryFormatter = new BinaryFormatter();
using MemoryStream serializationStream = new MemoryStream(data);
try
{
return (T)binaryFormatter.Deserialize(serializationStream);
}
catch (Exception arg)
{
LockoutBase.Logger.LogError((object)$"Error deserializing instance: {arg}");
return default(T);
}
}
}
namespace Lockout
{
[BepInPlugin("com.github.somindras.lethal-company-lockout", "Lockout", "1.3.1")]
public class LockoutBase : BaseUnityPlugin
{
public enum KeyUsage
{
No,
Inventory,
Hand
}
[HarmonyPatch(typeof(TimeOfDay))]
internal class TimeOfDayPatch : HarmonyPatch
{
[HarmonyPatch("TimeOfDayEvents")]
[HarmonyPostfix]
public static void TimeOfDayEventsPostfix(float ___currentDayTime, float ___totalTime)
{
timeRatio = ___currentDayTime / ___totalTime;
if (timeRatio < TimeBeforeLockout || (CanPowerOffLockout && !powerOn))
{
if (isLocked)
{
Logger.LogInfo((object)"TimeOfDayEventsPostfix: Unlock Alert");
HUDManager.Instance.ReadDialogue(unlockDialog);
isLocked = false;
}
}
else if (timeRatio < TimeBeforeUnlock)
{
if (!isLocked)
{
Logger.LogInfo((object)"TimeOfDayEventsPostfix: Lockout Alert");
HUDManager.Instance.ReadDialogue(lockoutDialog);
isLocked = true;
}
}
else if (isLocked)
{
Logger.LogInfo((object)"TimeOfDayEventsPostfix: Unlock Alert");
HUDManager.Instance.ReadDialogue(unlockDialog);
isLocked = false;
}
}
}
[HarmonyPatch(typeof(EntranceTeleport))]
internal class EntranceTeleportPatch : HarmonyPatch
{
private static bool UseKey()
{
PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
switch (CanUseKey)
{
case KeyUsage.No:
Logger.LogInfo((object)$"UseKey: config DISABLED key usage: {CanUseKey}");
return false;
default:
{
int num = Array.FindIndex(localPlayerController.ItemSlots, (GrabbableObject item) => Object.op_Implicit((Object)(object)item) && item is KeyItem);
bool flag2 = num != -1;
if (flag2)
{
localPlayerController.isHoldingObject = true;
localPlayerController.DestroyItemInSlotAndSync(num);
}
Logger.LogInfo((object)string.Format("UseKey: was ({0}) to use key in inventory got slot {1}", flag2 ? "ABLE" : "UNABLE", num));
return flag2;
}
case KeyUsage.Hand:
{
bool flag = Object.op_Implicit((Object)(object)localPlayerController.currentlyHeldObjectServer) && localPlayerController.currentlyHeldObjectServer is KeyItem;
if (flag)
{
localPlayerController.DespawnHeldObject();
}
Logger.LogInfo((object)("UseKey: was (" + (flag ? "ABLE" : "UNABLE") + ") to use currently held key"));
return flag;
}
}
}
private static bool CanEnter(bool isMainEntrance)
{
if (isLocked)
{
if (isMainEntrance)
{
return CanEnterMainEntranceDuringLockout;
}
return CanEnterFireExitDuringLockout;
}
if (isMainEntrance)
{
return CanEnterMainEntranceDuringUnlock;
}
return CanEnterFireExitDuringUnlock;
}
private static bool CanExit(bool isMainEntrance)
{
if (isLocked)
{
if (isMainEntrance)
{
return CanExitMainEntranceDuringLockout;
}
return CanExitFireExitDuringLockout;
}
if (isMainEntrance)
{
return CanExitMainEntranceDuringUnlock;
}
return CanExitFireExitDuringUnlock;
}
[HarmonyPatch("TeleportPlayer")]
[HarmonyPrefix]
public static bool TeleportPlayerPrefix(bool ___isEntranceToBuilding, int ___entranceId)
{
bool flag = ___entranceId == 0;
bool flag2 = ___isEntranceToBuilding;
bool flag3 = (flag2 ? CanEnter(flag) : CanExit(flag)) || UseKey();
Logger.LogInfo((object)("Player is " + (flag3 ? "ALLOWED" : "UNALLOWED") + " to " + (flag2 ? "ENTER" : "EXIT") + " through the " + (flag ? "MAIN ENTRANCE" : "FIRE EXIT")));
if (!flag3)
{
HUDManager.Instance.DisplayTip("???", (flag2 ? "ENTERING" : "EXITING") + " through the " + (flag ? "MAIN ENTRANCE" : "FIRE EXIT") + " seems blocked", false, false, "LC_Tip1");
}
return flag3;
}
}
[HarmonyPatch(typeof(PlayerControllerB))]
internal class PlayerControllerBPatch : HarmonyPatch
{
[CompilerGenerated]
private static class <>O
{
public static HandleNamedMessageDelegate <0>__OnRequestSync;
public static HandleNamedMessageDelegate <1>__OnReceiveSync;
}
[HarmonyPatch("ConnectClientToPlayerObject")]
[HarmonyPostfix]
public static void ConnectClientToPlayerObjectPostfix()
{
//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_0035: 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_0040: Expected O, but got Unknown
if (SyncedInstance<LockoutConfig>.IsHost)
{
Logger.LogInfo((object)"ConnectClientToPlayerObjectPostfix: Host is syncing config");
CustomMessagingManager messageManager = SyncedInstance<LockoutConfig>.MessageManager;
object obj = <>O.<0>__OnRequestSync;
if (obj == null)
{
HandleNamedMessageDelegate val = LockoutConfig.OnRequestSync;
<>O.<0>__OnRequestSync = val;
obj = (object)val;
}
messageManager.RegisterNamedMessageHandler("Lockout_OnRequestConfigSync", (HandleNamedMessageDelegate)obj);
SyncedInstance<LockoutConfig>.Synced = true;
return;
}
Logger.LogInfo((object)"ConnectClientToPlayerObjectPostfix: Client is requesting config sync");
SyncedInstance<LockoutConfig>.Synced = false;
CustomMessagingManager messageManager2 = SyncedInstance<LockoutConfig>.MessageManager;
object obj2 = <>O.<1>__OnReceiveSync;
if (obj2 == null)
{
HandleNamedMessageDelegate val2 = LockoutConfig.OnReceiveSync;
<>O.<1>__OnReceiveSync = val2;
obj2 = (object)val2;
}
messageManager2.RegisterNamedMessageHandler("Lockout_OnReceiveConfigSync", (HandleNamedMessageDelegate)obj2);
LockoutConfig.RequestSync();
}
}
[HarmonyPatch(typeof(GameNetworkManager))]
internal class GameNetworkManagerPatch : HarmonyPatch
{
[HarmonyPatch("StartDisconnect")]
[HarmonyPostfix]
public static void StartDisconnectPostfix()
{
Logger.LogInfo((object)"StartDisconnectPostfix: Disconnecting");
SyncedInstance<LockoutConfig>.RevertSync();
}
}
[HarmonyPatch(typeof(RoundManager))]
internal class RoundManagerPatch : HarmonyPatch
{
[HarmonyPatch("Start")]
[HarmonyPostfix]
private static void StartPostfix()
{
Logger.LogInfo((object)"Start: Registering event handlers");
((UnityEvent<bool>)(object)RoundManager.Instance.onPowerSwitch).AddListener((UnityAction<bool>)OnPowerSwitch);
}
[HarmonyPatch("OnDestroy")]
[HarmonyPostfix]
private static void OnDestroy()
{
Logger.LogInfo((object)"OnDestroy: Unregistering event handlers");
((UnityEvent<bool>)(object)RoundManager.Instance.onPowerSwitch).RemoveListener((UnityAction<bool>)OnPowerSwitch);
}
[HarmonyPatch("SetLevelObjectVariables")]
[HarmonyPrefix]
private static void SetLevelObjectVariablesPrefix()
{
OnPowerSwitch(on: true);
isLocked = false;
}
private static void OnPowerSwitch(bool on)
{
Logger.LogInfo((object)$"OnPowerSwitch: {on}");
powerOn = on;
}
}
private readonly Harmony harmony = new Harmony("com.github.somindras.lethal-company-lockout");
private static LockoutBase Instance;
private static float timeRatio = 0f;
private static bool isLocked = false;
private static bool powerOn = true;
private static readonly DialogueSegment[] lockoutDialog = (DialogueSegment[])(object)new DialogueSegment[1]
{
new DialogueSegment
{
speakerText = "Facility AI",
bodyText = "The building is now locked down.",
waitTime = 3f
}
};
private static readonly DialogueSegment[] unlockDialog = (DialogueSegment[])(object)new DialogueSegment[1]
{
new DialogueSegment
{
speakerText = "Facility AI",
bodyText = "The building is now unlocked.",
waitTime = 3f
}
};
internal static ManualLogSource Logger { get; private set; }
public static LockoutConfig Config { get; internal set; }
private static float TimeBeforeLockout => SyncedInstance<LockoutConfig>.Instance.timeBeforeLockout;
private static float TimeBeforeUnlock => SyncedInstance<LockoutConfig>.Instance.timeBeforeUnlock;
private static bool CanEnterFireExitDuringLockout => SyncedInstance<LockoutConfig>.Instance.canEnterFireExitDuringLockout;
private static bool CanEnterFireExitDuringUnlock => SyncedInstance<LockoutConfig>.Instance.canEnterFireExitDuringUnlock;
private static bool CanExitFireExitDuringLockout => SyncedInstance<LockoutConfig>.Instance.canExitFireExitDuringLockout;
private static bool CanExitFireExitDuringUnlock => SyncedInstance<LockoutConfig>.Instance.canExitFireExitDuringUnlock;
private static bool CanEnterMainEntranceDuringLockout => SyncedInstance<LockoutConfig>.Instance.canEnterMainEntranceDuringLockout;
private static bool CanEnterMainEntranceDuringUnlock => SyncedInstance<LockoutConfig>.Instance.canEnterMainEntranceDuringUnlock;
private static bool CanExitMainEntranceDuringLockout => SyncedInstance<LockoutConfig>.Instance.canExitMainEntranceDuringLockout;
private static bool CanExitMainEntranceDuringUnlock => SyncedInstance<LockoutConfig>.Instance.canExitMainEntranceDuringUnlock;
private static bool CanPowerOffLockout => SyncedInstance<LockoutConfig>.Instance.canPowerOffLockout;
private static KeyUsage CanUseKey => SyncedInstance<LockoutConfig>.Instance.canUseKey;
private void Awake()
{
if ((Object)(object)Instance == (Object)null)
{
Instance = this;
}
Logger = Logger.CreateLogSource("com.github.somindras.lethal-company-lockout");
Logger.LogInfo((object)"Plugin Lockout is loaded!");
Config = new LockoutConfig(((BaseUnityPlugin)this).Config);
harmony.PatchAll(typeof(TimeOfDayPatch));
harmony.PatchAll(typeof(EntranceTeleportPatch));
harmony.PatchAll(typeof(LockoutConfig));
harmony.PatchAll(typeof(PlayerControllerBPatch));
harmony.PatchAll(typeof(GameNetworkManagerPatch));
harmony.PatchAll(typeof(RoundManagerPatch));
}
}
[Serializable]
public class LockoutConfig : SyncedInstance<LockoutConfig>
{
public float timeBeforeLockout = 0.2f;
public float timeBeforeUnlock = 0.9f;
public bool canEnterFireExitDuringLockout = false;
public bool canEnterFireExitDuringUnlock = false;
public bool canExitFireExitDuringLockout = true;
public bool canExitFireExitDuringUnlock = true;
public bool canEnterMainEntranceDuringLockout = false;
public bool canEnterMainEntranceDuringUnlock = true;
public bool canExitMainEntranceDuringLockout = false;
public bool canExitMainEntranceDuringUnlock = true;
public bool canPowerOffLockout = true;
public LockoutBase.KeyUsage canUseKey = LockoutBase.KeyUsage.Inventory;
public LockoutConfig(ConfigFile cfg)
{
InitInstance(this);
timeBeforeLockout = cfg.Bind<float>("Time", "Time Before Lockout", 0.2f, "The time of day when the building lockout (0-1)").Value;
timeBeforeUnlock = cfg.Bind<float>("Time", "Time Before Unlock", 0.9f, "The time of day when the building unlocks (0-1)").Value;
canEnterFireExitDuringLockout = cfg.Bind<bool>("Fire Exit", "Can Enter Fire Exit During Lockout", false, "Can enter the fire exit during lockout").Value;
canEnterFireExitDuringUnlock = cfg.Bind<bool>("Fire Exit", "Can Enter Fire Exit During Unlock", false, "Can enter the fire exit during unlock").Value;
canExitFireExitDuringLockout = cfg.Bind<bool>("Fire Exit", "Can Exit Fire Exit During Lockout", true, "Can exit the fire exit during lockout").Value;
canExitFireExitDuringUnlock = cfg.Bind<bool>("Fire Exit", "Can Exit Fire Exit During Unlock", true, "Can exit the fire exit during unlock").Value;
canEnterMainEntranceDuringLockout = cfg.Bind<bool>("Main Entrance", "Can Enter Main Entrance During Lockout", false, "Can enter the main entrance during lockout").Value;
canEnterMainEntranceDuringUnlock = cfg.Bind<bool>("Main Entrance", "Can Enter Main Entrance During Unlock", true, "Can enter the main entrance during unlock").Value;
canExitMainEntranceDuringLockout = cfg.Bind<bool>("Main Entrance", "Can Exit Main Entrance During Lockout", false, "Can exit the main entrance during lockout").Value;
canExitMainEntranceDuringUnlock = cfg.Bind<bool>("Main Entrance", "Can Exit Main Entrance During Unlock", true, "Can exit the main entrance during unlock").Value;
canPowerOffLockout = cfg.Bind<bool>("Power", "Can Power Off Lockout", true, "Can power off the lockout").Value;
canUseKey = (LockoutBase.KeyUsage)cfg.Bind<int>("Key", "Can use key", 1, "Can use the key to enter/exit during lockout |0: No|1: Key in inventory slot|2: Key must be held|").Value;
if (timeBeforeLockout < 0f || timeBeforeLockout > 1f)
{
LockoutBase.Logger.LogWarning((object)$"Time Before Lockout was set to {timeBeforeLockout}. Setting to default.");
timeBeforeLockout = 0.2f;
}
if (timeBeforeUnlock < 0f || timeBeforeUnlock > 1f)
{
LockoutBase.Logger.LogWarning((object)$"Time Before Unlock was set to {timeBeforeUnlock}. Setting to default.");
timeBeforeUnlock = 0.9f;
}
if (timeBeforeLockout > timeBeforeUnlock)
{
LockoutBase.Logger.LogWarning((object)$"Time Before Lockout was set to {timeBeforeLockout} and is Greater than Time Before Unlock was set to {timeBeforeUnlock}. Setting to default.");
timeBeforeLockout = 0.2f;
timeBeforeUnlock = 0.9f;
}
if (!Enum.IsDefined(typeof(LockoutBase.KeyUsage), canUseKey))
{
LockoutBase.Logger.LogWarning((object)$"Can Use Key was set to {canUseKey}. Setting to default.");
canUseKey = LockoutBase.KeyUsage.Inventory;
}
LockoutBase.Logger.LogInfo((object)"Config loaded.");
LockoutBase.Logger.LogInfo((object)$"Time Before Lockout: {timeBeforeLockout}");
LockoutBase.Logger.LogInfo((object)$"Time Before Unlock: {timeBeforeUnlock}");
LockoutBase.Logger.LogInfo((object)$"Can Enter Fire Exit During Lockout: {canEnterFireExitDuringLockout}");
LockoutBase.Logger.LogInfo((object)$"Can Enter Fire Exit During Unlock: {canEnterFireExitDuringUnlock}");
LockoutBase.Logger.LogInfo((object)$"Can Exit Fire Exit During Lockout: {canExitFireExitDuringLockout}");
LockoutBase.Logger.LogInfo((object)$"Can Exit Fire Exit During Unlock: {canExitFireExitDuringUnlock}");
LockoutBase.Logger.LogInfo((object)$"Can Enter Main Entrance During Lockout: {canEnterMainEntranceDuringLockout}");
LockoutBase.Logger.LogInfo((object)$"Can Enter Main Entrance During Unlock: {canEnterMainEntranceDuringUnlock}");
LockoutBase.Logger.LogInfo((object)$"Can Exit Main Entrance During Lockout: {canExitMainEntranceDuringLockout}");
LockoutBase.Logger.LogInfo((object)$"Can Exit Main Entrance During Unlock: {canExitMainEntranceDuringUnlock}");
LockoutBase.Logger.LogInfo((object)$"Can Power Off Lockout: {canPowerOffLockout}");
LockoutBase.Logger.LogInfo((object)$"Can Use Key: {canUseKey}");
}
public static void RequestSync()
{
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
if (!SyncedInstance<LockoutConfig>.IsClient)
{
return;
}
FastBufferWriter val = default(FastBufferWriter);
((FastBufferWriter)(ref val))..ctor(SyncedInstance<LockoutConfig>.IntSize, (Allocator)2, -1);
try
{
SyncedInstance<LockoutConfig>.MessageManager.SendNamedMessage("Lockout_OnRequestConfigSync", 0uL, val, (NetworkDelivery)3);
}
finally
{
((IDisposable)(FastBufferWriter)(ref val)).Dispose();
}
}
public static void OnRequestSync(ulong clientId, FastBufferReader _)
{
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
if (!SyncedInstance<LockoutConfig>.IsHost)
{
return;
}
LockoutBase.Logger.LogInfo((object)$"Config sync request received from client: {clientId}");
byte[] array = SyncedInstance<LockoutConfig>.SerializeToBytes(SyncedInstance<LockoutConfig>.Instance);
int num = array.Length;
FastBufferWriter val = default(FastBufferWriter);
((FastBufferWriter)(ref val))..ctor(num + SyncedInstance<LockoutConfig>.IntSize, (Allocator)2, -1);
try
{
((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num, default(ForPrimitives));
((FastBufferWriter)(ref val)).WriteBytesSafe(array, -1, 0);
SyncedInstance<LockoutConfig>.MessageManager.SendNamedMessage("Lockout_OnReceiveConfigSync", clientId, val, (NetworkDelivery)3);
}
catch (Exception arg)
{
LockoutBase.Logger.LogInfo((object)$"Error occurred syncing config with client: {clientId}\n{arg}");
}
finally
{
((IDisposable)(FastBufferWriter)(ref val)).Dispose();
}
}
public static void OnReceiveSync(ulong _, FastBufferReader reader)
{
//IL_002d: 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)
if (!((FastBufferReader)(ref reader)).TryBeginRead(SyncedInstance<LockoutConfig>.IntSize))
{
LockoutBase.Logger.LogError((object)"Config sync error: Could not begin reading buffer.");
return;
}
int num = default(int);
((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives));
if (!((FastBufferReader)(ref reader)).TryBeginRead(num))
{
LockoutBase.Logger.LogError((object)"Config sync error: Host could not sync.");
return;
}
byte[] data = new byte[num];
((FastBufferReader)(ref reader)).ReadBytesSafe(ref data, num, 0);
SyncedInstance<LockoutConfig>.SyncInstance(data);
LockoutBase.Logger.LogInfo((object)"Successfully synced config with host.");
}
}
public static class LockoutInfo
{
public const string GUID = "com.github.somindras.lethal-company-lockout";
public const string NAME = "Lockout";
public const string VERSION = "1.3.1";
}
public static class PluginInfo
{
public const string PLUGIN_GUID = "Lockout";
public const string PLUGIN_NAME = "Lockout";
public const string PLUGIN_VERSION = "1.0.0";
}
}