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 LethalAlcoolico v1.4.0
Sociors.LethalAlcoolico.dll
Decompiled 3 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; 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 GameNetcodeStuff; using HarmonyLib; using LethalAlcoolico.Board; using LethalAlcoolico.Network; using LethalAlcoolico.Networking; using LethalAlcoolico.Patches; using LethalAlcoolico.Save; using LethalConfig; using LethalConfig.ConfigItems; using LethalConfig.ConfigItems.Options; using Microsoft.CodeAnalysis; using Sociors.LethalAlcoolico.NetcodePatcher; using TMPro; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.UI; [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("Sociors.LethalAlcoolico")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("LethalAlcoolico")] [assembly: AssemblyTitle("Sociors.LethalAlcoolico")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [module: NetcodePatchedAssembly] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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] [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; } } } public static class LAConfig { public static ConfigEntry<float> PlayerWeight; public static ConfigEntry<float> AlcoholABVPercent; public static ConfigEntry<float> ShotSize; public static ConfigEntry<int> ShotsPerDeath; public static ConfigEntry<bool> BoomboxShakeEnabled; public static ConfigEntry<float> BoomboxShakeIntensityDisplay; public static ConfigEntry<string> LanIdentitySeed; public static void Init(ConfigFile config) { PlayerWeight = config.Bind<float>("Geral", "Seu Peso (kg)", 75f, "Seu peso para a estimativa de sobriedade."); AlcoholABVPercent = config.Bind<float>("Geral", "Teor Alcoólico (%)", 35f, "Teor da bebida em porcentagem. Ex: 35 = 35%."); ShotSize = config.Bind<float>("Geral", "Tamanho do Shot (ml)", 50f, "Volume de cada dose em ml."); ShotsPerDeath = config.Bind<int>("Geral", "Shots por Morte", 1, "Quantidade de shots pendentes por morte."); BoomboxShakeEnabled = config.Bind<bool>("Boombox Shake", "Ativado", true, "Ativa o tremor da câmera com base no grave da boombox."); BoomboxShakeIntensityDisplay = config.Bind<float>("Boombox Shake", "Intensidade", 3.5f, "Quanto a câmera treme quando o grave bate."); LanIdentitySeed = config.Bind<string>("Rede", "LAN Identity Seed", "", "Identidade persistida por profile para fallback de LAN."); if (string.IsNullOrWhiteSpace(LanIdentitySeed.Value)) { LanIdentitySeed.Value = Guid.NewGuid().ToString("N"); } } public static void RegisterLethalConfig() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown //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_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Expected O, but got Unknown //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Expected O, but got Unknown //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Expected O, but got Unknown //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Expected O, but got Unknown //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Expected O, but got Unknown //IL_00ec: Expected O, but got Unknown //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Expected O, but got Unknown //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Expected O, but got Unknown //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Expected O, but got Unknown //IL_0114: 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_0121: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Expected O, but got Unknown //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Expected O, but got Unknown //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Expected O, but got Unknown //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Expected O, but got Unknown ConfigEntry<float> playerWeight = PlayerWeight; FloatStepSliderOptions val = new FloatStepSliderOptions { RequiresRestart = false }; ((BaseRangeOptions<float>)val).Min = 40f; ((BaseRangeOptions<float>)val).Max = 200f; val.Step = 1f; LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatStepSliderConfigItem(playerWeight, val)); ConfigEntry<float> alcoholABVPercent = AlcoholABVPercent; FloatStepSliderOptions val2 = new FloatStepSliderOptions { RequiresRestart = false }; ((BaseRangeOptions<float>)val2).Min = 1f; ((BaseRangeOptions<float>)val2).Max = 100f; val2.Step = 1f; LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatStepSliderConfigItem(alcoholABVPercent, val2)); ConfigEntry<float> shotSize = ShotSize; FloatStepSliderOptions val3 = new FloatStepSliderOptions { RequiresRestart = false }; ((BaseRangeOptions<float>)val3).Min = 10f; ((BaseRangeOptions<float>)val3).Max = 500f; val3.Step = 5f; LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatStepSliderConfigItem(shotSize, val3)); ConfigEntry<int> shotsPerDeath = ShotsPerDeath; IntSliderOptions val4 = new IntSliderOptions { RequiresRestart = false }; ((BaseRangeOptions<int>)val4).Min = 0; ((BaseRangeOptions<int>)val4).Max = 10; LethalConfigManager.AddConfigItem((BaseConfigItem)new IntSliderConfigItem(shotsPerDeath, val4)); LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(BoomboxShakeEnabled, new BoolCheckBoxOptions { RequiresRestart = false })); ConfigEntry<float> boomboxShakeIntensityDisplay = BoomboxShakeIntensityDisplay; FloatStepSliderOptions val5 = new FloatStepSliderOptions { RequiresRestart = false }; ((BaseRangeOptions<float>)val5).Min = 0f; ((BaseRangeOptions<float>)val5).Max = 10f; val5.Step = 0.1f; LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatStepSliderConfigItem(boomboxShakeIntensityDisplay, val5)); } } public class AlcoholButtonInteract : MonoBehaviour { public void OnInteract(PlayerControllerB playerWhoPressed) { if (!((Object)(object)playerWhoPressed != (Object)(object)GameNetworkManager.Instance.localPlayerController)) { AlcoholSyncManager.RequestDrinkShot(playerWhoPressed); } } } namespace LethalAlcoolico { internal static class AlcoholAssets { public static AssetBundle Bundle; public static GameObject ScreenPrefab; public static GameObject PlayerPagePrefab; public static GameObject PlayerPrefab; public static void Load() { if ((Object)(object)Bundle != (Object)null) { return; } string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string text = Path.Combine(directoryName, "alcoholmod"); Bundle = AssetBundle.LoadFromFile(text); if ((Object)(object)Bundle == (Object)null) { LethalAlcoolico.Logger.LogError((object)"Failed to load alcoholmod AssetBundle"); return; } ScreenPrefab = Bundle.LoadAsset<GameObject>("ScreenPrefab"); PlayerPagePrefab = Bundle.LoadAsset<GameObject>("PlayerPage"); PlayerPrefab = Bundle.LoadAsset<GameObject>("Player"); if ((Object)(object)ScreenPrefab == (Object)null) { LethalAlcoolico.Logger.LogError((object)"ScreenPrefab não encontrado!"); } if ((Object)(object)PlayerPagePrefab == (Object)null) { LethalAlcoolico.Logger.LogError((object)"PlayerPage não encontrado!"); } if ((Object)(object)PlayerPrefab == (Object)null) { LethalAlcoolico.Logger.LogError((object)"PlayerPrefab não encontrado!"); } } } [BepInPlugin("Sociors.LethalAlcoolico", "LethalAlcoolico", "1.0.0")] public class LethalAlcoolico : BaseUnityPlugin { public static LethalAlcoolico Instance { get; private set; } internal static ManualLogSource Logger { get; private set; } internal static Harmony? Harmony { get; set; } private void Awake() { Logger = ((BaseUnityPlugin)this).Logger; Instance = this; AlcoholAssets.Load(); LAConfig.Init(((BaseUnityPlugin)this).Config); if (Chainloader.PluginInfos.ContainsKey("ainavt.lc.lethalconfig") || Chainloader.PluginInfos.ContainsKey("com.sayless.lethalconfig")) { RegisterLethalConfigWrapper(); } Patch(); } private void RegisterLethalConfigWrapper() { LAConfig.RegisterLethalConfig(); } 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("Sociors.LethalAlcoolico"); } Harmony.PatchAll(); } internal static void Unpatch() { Harmony? harmony = Harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } public class BoomboxBassShakeController : MonoBehaviour { [Header("Scan")] [SerializeField] private float scanInterval = 1f; [Header("Audio")] [SerializeField] private FFTWindow fftWindow = (FFTWindow)5; [SerializeField] private int spectrumSize = 512; [SerializeField] private int bassStartIndex = 0; [SerializeField] private int bassEndIndex = 10; [Header("Response")] [SerializeField] private float smoothSpeed = 12f; [SerializeField] private float noiseSpeed = 25f; [SerializeField] private float returnSpeed = 12f; [Header("Debug")] [SerializeField] private float bassValue; [SerializeField] private float smoothedBass; [SerializeField] private float bassDebugScaled; [SerializeField] private float shakeStrength; [SerializeField] private string currentBoomboxName; [SerializeField] private float currentDistance; [Header("Derived Config Values")] [SerializeField] private float currentShakeAmount; private readonly List<BoomboxItem> cachedBoomboxes = new List<BoomboxItem>(); private float scanTimer; private float[] spectrum; private Transform cameraTarget; private Vector3 originalLocalPos; private Camera cachedCamera; private const float BassThreshold = 0.38f; private const float BassFullShake = 1f; private const float BassCurve = 0.7f; private const float ShakeBoost = 1.25f; private static bool searchedTooManyEmotesReflection; private static Type tooManyEmotesCameraType; private static FieldInfo tooManyEmotesEmoteCameraField; private void Awake() { spectrum = new float[spectrumSize]; } private void Start() { RefreshConfigValues(); HookConfigEvents(); } private void OnDisable() { UnhookConfigEvents(); } private void OnDestroy() { UnhookConfigEvents(); } private void Update() { //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) RefreshCameraTargetIfNeeded(); scanTimer -= Time.deltaTime; if (scanTimer <= 0f) { scanTimer = scanInterval; RefreshBoomboxCache(); } BoomboxItem bestBoombox = GetBestBoombox(); if (!LAConfig.BoomboxShakeEnabled.Value) { currentBoomboxName = string.Empty; currentDistance = 0f; bassValue = 0f; bassDebugScaled = 0f; shakeStrength = 0f; smoothedBass = Mathf.Lerp(smoothedBass, 0f, Time.deltaTime * returnSpeed); ApplyShake(0f); } else if (!((Object)(object)cameraTarget == (Object)null)) { if ((Object)(object)bestBoombox == (Object)null || (Object)(object)bestBoombox.boomboxAudio == (Object)null || !bestBoombox.boomboxAudio.isPlaying) { currentBoomboxName = string.Empty; currentDistance = 0f; bassValue = 0f; bassDebugScaled = 0f; shakeStrength = 0f; smoothedBass = Mathf.Lerp(smoothedBass, 0f, Time.deltaTime * returnSpeed); ApplyShake(0f); } else { currentBoomboxName = ((Object)bestBoombox).name; currentDistance = Vector3.Distance(GetListenerPosition(), ((Component)bestBoombox).transform.position); bestBoombox.boomboxAudio.GetSpectrumData(spectrum, 0, fftWindow); bassValue = GetBassValue(); smoothedBass = Mathf.Lerp(smoothedBass, bassValue, Time.deltaTime * smoothSpeed); bassDebugScaled = bassValue * 10000f; shakeStrength = GetShakeStrength(smoothedBass); ApplyShake(shakeStrength); } } } private void HookConfigEvents() { LAConfig.BoomboxShakeEnabled.SettingChanged += OnConfigChanged; LAConfig.BoomboxShakeIntensityDisplay.SettingChanged += OnConfigChanged; } private void UnhookConfigEvents() { LAConfig.BoomboxShakeEnabled.SettingChanged -= OnConfigChanged; LAConfig.BoomboxShakeIntensityDisplay.SettingChanged -= OnConfigChanged; } private void OnConfigChanged(object sender, EventArgs e) { RefreshConfigValues(); } private void RefreshConfigValues() { currentShakeAmount = LAConfig.BoomboxShakeIntensityDisplay.Value / 10f; } private void RefreshBoomboxCache() { cachedBoomboxes.Clear(); BoomboxItem[] array = Object.FindObjectsOfType<BoomboxItem>(); for (int i = 0; i < array.Length; i++) { if ((Object)(object)array[i] != (Object)null) { cachedBoomboxes.Add(array[i]); } } } private BoomboxItem GetBestBoombox() { //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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) Vector3 listenerPosition = GetListenerPosition(); BoomboxItem result = null; float num = float.MaxValue; for (int i = 0; i < cachedBoomboxes.Count; i++) { BoomboxItem val = cachedBoomboxes[i]; if (!((Object)(object)val == (Object)null) && val.isPlayingMusic && !((Object)(object)val.boomboxAudio == (Object)null) && val.boomboxAudio.isPlaying) { float num2 = Vector3.Distance(listenerPosition, ((Component)val).transform.position); if (num2 < num) { num = num2; result = val; } } } return result; } private Vector3 GetListenerPosition() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)GameNetworkManager.Instance != (Object)null && (Object)(object)GameNetworkManager.Instance.localPlayerController != (Object)null) { return ((Component)GameNetworkManager.Instance.localPlayerController).transform.position; } if ((Object)(object)cameraTarget != (Object)null) { return cameraTarget.position; } return Vector3.zero; } private void RefreshCameraTargetIfNeeded() { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) Camera currentShakeCamera = GetCurrentShakeCamera(); if (!((Object)(object)currentShakeCamera == (Object)null) && (!((Object)(object)cachedCamera == (Object)(object)currentShakeCamera) || !((Object)(object)cameraTarget != (Object)null))) { cachedCamera = currentShakeCamera; cameraTarget = ((Component)currentShakeCamera).transform; originalLocalPos = cameraTarget.localPosition; } } private Camera GetCurrentShakeCamera() { Camera val = TryGetTooManyEmotesCamera(); if ((Object)(object)val != (Object)null && ((Behaviour)val).enabled && ((Component)val).gameObject.activeInHierarchy) { return val; } PlayerControllerB val2 = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val2 != (Object)null && (Object)(object)val2.gameplayCamera != (Object)null) { return val2.gameplayCamera; } return null; } private Camera TryGetTooManyEmotesCamera() { if (!Chainloader.PluginInfos.ContainsKey("FlipMods.TooManyEmotes")) { return null; } if (!searchedTooManyEmotesReflection) { searchedTooManyEmotesReflection = true; tooManyEmotesCameraType = AccessTools.TypeByName("TooManyEmotes.Patches.ThirdPersonEmoteController"); if (tooManyEmotesCameraType != null) { tooManyEmotesEmoteCameraField = AccessTools.Field(tooManyEmotesCameraType, "emoteCamera"); } } if (tooManyEmotesEmoteCameraField == null) { return null; } object? value = tooManyEmotesEmoteCameraField.GetValue(null); return (Camera)((value is Camera) ? value : null); } private void ApplyShake(float normalizedStrength) { //IL_005f: 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_006a: 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) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)cameraTarget == (Object)null)) { float num = normalizedStrength * currentShakeAmount; float num2 = Time.time * noiseSpeed; Vector3 val = new Vector3((Mathf.PerlinNoise(num2, 0f) - 0.5f) * 2f, (Mathf.PerlinNoise(0f, num2) - 0.5f) * 2f, 0f) * num; cameraTarget.localPosition = Vector3.Lerp(cameraTarget.localPosition, originalLocalPos + val, Time.deltaTime * returnSpeed); } } private float GetBassValue() { float num = 0f; int num2 = Mathf.Max(0, bassStartIndex); int num3 = Mathf.Max(num2, bassEndIndex); for (int i = num2; i <= num3 && i < spectrum.Length; i++) { num += spectrum[i]; } return num; } private float GetShakeStrength(float bass) { float num = Mathf.InverseLerp(0.38f, 1f, bass); num = Mathf.Clamp01(num); float num2 = Mathf.Pow(num, 0.7f); return Mathf.Clamp01(num2 * 1.25f); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "Sociors.LethalAlcoolico"; public const string PLUGIN_NAME = "LethalAlcoolico"; public const string PLUGIN_VERSION = "1.0.0"; } } namespace LethalAlcoolico.Networking { [HarmonyPatch] public static class AlcoholSyncManager { private struct PlayerAlcoholStateData { public ulong ClientId; public ulong IdentityKey; public int TotalDeaths; public int PendingCups; public float DrunkPercentage; } private struct LanIdentityRegistrationData { public ulong BaseId; public ulong SessionNonce; public ulong ResolvedId; } private struct RecentPlayerHitData { public ulong AttackerClientId; public float Time; } [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnRequestFullSyncServer; public static HandleNamedMessageDelegate <1>__OnPlayerDiedServer; public static HandleNamedMessageDelegate <2>__OnPlayerDrankShotServer; public static HandleNamedMessageDelegate <3>__OnRegisterLanIdentityServer; public static HandleNamedMessageDelegate <4>__OnFullSyncClient; } private const string MsgRequestFullSync = "LethalAlcoolico.RequestFullSync"; private const string MsgFullSync = "LethalAlcoolico.FullSync"; private const string MsgPlayerDied = "LethalAlcoolico.PlayerDied"; private const string MsgPlayerDrankShot = "LethalAlcoolico.PlayerDrankShot"; private const string MsgRegisterLanIdentity = "LethalAlcoolico.RegisterLanIdentity"; private static readonly Dictionary<ulong, PlayerAlcoholStateData> serverStates = new Dictionary<ulong, PlayerAlcoholStateData>(); private static readonly Dictionary<ulong, PlayerAlcoholStateData> syncedStates = new Dictionary<ulong, PlayerAlcoholStateData>(); private static readonly Dictionary<ulong, LanIdentityRegistrationData> lanIdentityByClientId = new Dictionary<ulong, LanIdentityRegistrationData>(); private static readonly Dictionary<ulong, RecentPlayerHitData> recentHitsByVictim = new Dictionary<ulong, RecentPlayerHitData>(); private static bool serverHandlersRegistered; private static bool clientHandlersRegistered; private static bool requestedSync; private static bool loadedSaveData; private static bool sentLanIdentity; private static bool localLanIdentityInitialized; private static ulong localLanBaseId; private static ulong localLanSessionNonce; private static bool firstDeathEnabled; private static bool firstDeathAnnounced; private static bool punishKillsEnabled = true; private static float decayTimer; private const int MurdererBonusShots = 2; private const float RecentPlayerHitWindowSeconds = 2f; public static bool IsTrackablePlayerPublic(PlayerControllerB player) { return IsTrackablePlayer(player); } [HarmonyPatch(typeof(StartOfRound), "Awake")] [HarmonyPostfix] public static void ResetSession() { serverStates.Clear(); syncedStates.Clear(); lanIdentityByClientId.Clear(); recentHitsByVictim.Clear(); serverHandlersRegistered = false; clientHandlersRegistered = false; requestedSync = false; loadedSaveData = false; sentLanIdentity = false; localLanIdentityInitialized = false; localLanBaseId = 0uL; localLanSessionNonce = 0uL; firstDeathEnabled = false; firstDeathAnnounced = false; punishKillsEnabled = true; decayTimer = 0f; LethalAlcoolicoPatches.ResetVisualState(); LethalAlcoolicoPatches.SetFirstDeathEnabledMirror(value: false); LethalAlcoolicoPatches.SetFirstDeathAnnouncedMirror(value: false); } [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyPostfix] public static void Init() { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Expected O, but got Unknown //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Expected O, but got Unknown //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Expected O, but got Unknown if ((Object)(object)NetworkManager.Singleton == (Object)null) { return; } if (NetworkManager.Singleton.IsServer && !serverHandlersRegistered) { serverHandlersRegistered = true; EnsureSaveLoaded(); CustomMessagingManager customMessagingManager = NetworkManager.Singleton.CustomMessagingManager; object obj = <>O.<0>__OnRequestFullSyncServer; if (obj == null) { HandleNamedMessageDelegate val = OnRequestFullSyncServer; <>O.<0>__OnRequestFullSyncServer = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("LethalAlcoolico.RequestFullSync", (HandleNamedMessageDelegate)obj); CustomMessagingManager customMessagingManager2 = NetworkManager.Singleton.CustomMessagingManager; object obj2 = <>O.<1>__OnPlayerDiedServer; if (obj2 == null) { HandleNamedMessageDelegate val2 = OnPlayerDiedServer; <>O.<1>__OnPlayerDiedServer = val2; obj2 = (object)val2; } customMessagingManager2.RegisterNamedMessageHandler("LethalAlcoolico.PlayerDied", (HandleNamedMessageDelegate)obj2); CustomMessagingManager customMessagingManager3 = NetworkManager.Singleton.CustomMessagingManager; object obj3 = <>O.<2>__OnPlayerDrankShotServer; if (obj3 == null) { HandleNamedMessageDelegate val3 = OnPlayerDrankShotServer; <>O.<2>__OnPlayerDrankShotServer = val3; obj3 = (object)val3; } customMessagingManager3.RegisterNamedMessageHandler("LethalAlcoolico.PlayerDrankShot", (HandleNamedMessageDelegate)obj3); CustomMessagingManager customMessagingManager4 = NetworkManager.Singleton.CustomMessagingManager; object obj4 = <>O.<3>__OnRegisterLanIdentityServer; if (obj4 == null) { HandleNamedMessageDelegate val4 = OnRegisterLanIdentityServer; <>O.<3>__OnRegisterLanIdentityServer = val4; obj4 = (object)val4; } customMessagingManager4.RegisterNamedMessageHandler("LethalAlcoolico.RegisterLanIdentity", (HandleNamedMessageDelegate)obj4); if (IsLanFallbackActive()) { EnsureLocalLanIdentity(); RegisterLanIdentityForClient(NetworkManager.Singleton.LocalClientId, localLanBaseId, localLanSessionNonce); } EnsureServerStatesForScene(); ApplyLocalStateCacheToScene(refreshBoard: true, resyncVisuals: true); } if (NetworkManager.Singleton.IsClient && !NetworkManager.Singleton.IsServer) { requestedSync = false; syncedStates.Clear(); sentLanIdentity = false; if (!clientHandlersRegistered) { clientHandlersRegistered = true; CustomMessagingManager customMessagingManager5 = NetworkManager.Singleton.CustomMessagingManager; object obj5 = <>O.<4>__OnFullSyncClient; if (obj5 == null) { HandleNamedMessageDelegate val5 = OnFullSyncClient; <>O.<4>__OnFullSyncClient = val5; obj5 = (object)val5; } customMessagingManager5.RegisterNamedMessageHandler("LethalAlcoolico.FullSync", (HandleNamedMessageDelegate)obj5); } } ApplyLocalStateCacheToScene(refreshBoard: true, resyncVisuals: true); } [HarmonyPatch(typeof(PlayerControllerB), "SendNewPlayerValuesClientRpc")] [HarmonyPostfix] private static void OnPlayerValuesSynchronized() { if (!((Object)(object)NetworkManager.Singleton == (Object)null)) { if (NetworkManager.Singleton.IsServer) { EnsureSaveLoaded(); EnsureServerStatesForScene(); ApplyLocalStateCacheToScene(refreshBoard: true, resyncVisuals: true); } else if (syncedStates.Count > 0) { ApplyLocalStateCacheToScene(refreshBoard: true, resyncVisuals: true); } } } [HarmonyPatch(typeof(StartOfRound), "OnPlayerDC")] [HarmonyPostfix] private static void OnPlayerDisconnected() { if (!((Object)(object)NetworkManager.Singleton == (Object)null)) { if (NetworkManager.Singleton.IsServer) { PruneDisconnectedLanIdentities(); SaveServerStates(); BroadcastStateToClients(refreshBoard: true, resyncVisuals: true); } if (NetworkManager.Singleton.IsServer || syncedStates.Count > 0) { ApplyLocalStateCacheToScene(refreshBoard: true, resyncVisuals: true); } } } [HarmonyPatch(typeof(GameNetworkManager), "SaveGame")] [HarmonyPostfix] private static void OnGameSaved() { if (!((Object)(object)NetworkManager.Singleton != (Object)null) || NetworkManager.Singleton.IsServer || NetworkManager.Singleton.IsHost) { SaveServerStates(); } } [HarmonyPatch(typeof(GameNetworkManager), "ResetSavedGameValues")] [HarmonyPostfix] private static void OnSaveReset() { SaveManager.Clear(); serverStates.Clear(); syncedStates.Clear(); lanIdentityByClientId.Clear(); loadedSaveData = false; } [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPostfix] public static void Tick(PlayerControllerB __instance) { if ((Object)(object)GameNetworkManager.Instance?.localPlayerController != (Object)(object)__instance || (Object)(object)NetworkManager.Singleton == (Object)null) { return; } if (NetworkManager.Singleton.IsClient && IsLanFallbackActive() && !localLanIdentityInitialized) { EnsureLocalLanIdentity(); } if (NetworkManager.Singleton.IsClient && !NetworkManager.Singleton.IsServer && IsLanFallbackActive() && !sentLanIdentity) { sentLanIdentity = true; SendLanIdentityRegistration(); return; } if (NetworkManager.Singleton.IsClient && !NetworkManager.Singleton.IsServer && !requestedSync) { requestedSync = true; SendFullSyncRequest(); } if (NetworkManager.Singleton.IsServer) { HostDecayTick(); } } [HarmonyPatch(typeof(StartOfRound), "PlayerLoadedClientRpc")] [HarmonyPostfix] private static void OnPlayerLoadedClientRpc(ulong clientId) { if (!((Object)(object)NetworkManager.Singleton == (Object)null)) { if (NetworkManager.Singleton.IsServer) { EnsureSaveLoaded(); EnsureServerStatesForScene(); ApplyLocalStateCacheToScene(refreshBoard: true, resyncVisuals: true); } else if (syncedStates.Count > 0) { ApplyLocalStateCacheToScene(refreshBoard: true, resyncVisuals: true); } } } public unsafe static void RequestDrinkShot(PlayerControllerB player) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player != (Object)(object)GameNetworkManager.Instance?.localPlayerController || (Object)(object)NetworkManager.Singleton == (Object)null) { return; } if (NetworkManager.Singleton.IsServer) { HostApplyDrinkShot(player); return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(0, (Allocator)2, -1); try { NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("LethalAlcoolico.PlayerDrankShot", 0uL, val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } public unsafe static void RequestDeath(PlayerControllerB player) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player != (Object)(object)GameNetworkManager.Instance?.localPlayerController || (Object)(object)NetworkManager.Singleton == (Object)null) { return; } if (NetworkManager.Singleton.IsServer) { HostApplyDeath(player); return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(0, (Allocator)2, -1); try { NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("LethalAlcoolico.PlayerDied", 0uL, val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } public static void HostSetShots(PlayerControllerB player, int shots) { if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer || (Object)(object)player == (Object)null) { return; } EnsureSaveLoaded(); EnsureServerStatesForScene(); if (TryGetPlayerIdentityKey(player, out var identityKey)) { if (!serverStates.TryGetValue(identityKey, out var value)) { value = CreateDefaultState(identityKey); } value.TotalDeaths = Mathf.Max(0, shots); value.DrunkPercentage = CalculateBAC(value.TotalDeaths); value.IdentityKey = identityKey; serverStates[identityKey] = value; SaveServerStates(); BroadcastStateToClients(refreshBoard: true, resyncVisuals: false); ApplyLocalStateCacheToScene(refreshBoard: true, resyncVisuals: false); } } public static void HostSetPending(PlayerControllerB player, int pending) { if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer || (Object)(object)player == (Object)null) { return; } EnsureSaveLoaded(); EnsureServerStatesForScene(); if (TryGetPlayerIdentityKey(player, out var identityKey)) { if (!serverStates.TryGetValue(identityKey, out var value)) { value = CreateDefaultState(identityKey); } value.PendingCups = Mathf.Max(0, pending); value.IdentityKey = identityKey; serverStates[identityKey] = value; SaveServerStates(); BroadcastStateToClients(refreshBoard: true, resyncVisuals: true); ApplyLocalStateCacheToScene(refreshBoard: true, resyncVisuals: true); } } public static void HostSetFirstDeathEnabled(bool enabled) { if (!((Object)(object)NetworkManager.Singleton == (Object)null) && NetworkManager.Singleton.IsServer) { EnsureSaveLoaded(); firstDeathEnabled = enabled; LethalAlcoolicoPatches.SetFirstDeathEnabledMirror(firstDeathEnabled); SaveServerStates(); BroadcastStateToClients(refreshBoard: false, resyncVisuals: false); ApplyLocalStateCacheToScene(refreshBoard: false, resyncVisuals: false); } } public static void HostRefreshBoard(bool resyncVisuals) { if (!((Object)(object)NetworkManager.Singleton == (Object)null) && NetworkManager.Singleton.IsServer) { EnsureSaveLoaded(); EnsureServerStatesForScene(); BroadcastStateToClients(refreshBoard: true, resyncVisuals); ApplyLocalStateCacheToScene(refreshBoard: true, resyncVisuals); } } public static void HandleRoundStartServer() { if (!((Object)(object)NetworkManager.Singleton == (Object)null) && NetworkManager.Singleton.IsServer) { firstDeathAnnounced = false; LethalAlcoolicoPatches.SetFirstDeathAnnouncedMirror(value: false); EnsureSaveLoaded(); EnsureServerStatesForScene(); BroadcastStateToClients(refreshBoard: true, resyncVisuals: true); ApplyLocalStateCacheToScene(refreshBoard: true, resyncVisuals: true); } } public static void HostRegisterPlayerHit(ulong victimClientId, ulong attackerClientId) { if (!((Object)(object)NetworkManager.Singleton == (Object)null) && NetworkManager.Singleton.IsServer && victimClientId != attackerClientId) { recentHitsByVictim[victimClientId] = new RecentPlayerHitData { AttackerClientId = attackerClientId, Time = Time.time }; } } public static void HostSetPunishKillsEnabled(bool enabled) { if (!((Object)(object)NetworkManager.Singleton == (Object)null) && NetworkManager.Singleton.IsServer) { EnsureSaveLoaded(); punishKillsEnabled = enabled; SaveServerStates(); BroadcastStateToClients(refreshBoard: false, resyncVisuals: false); ApplyLocalStateCacheToScene(refreshBoard: false, resyncVisuals: false); } } private unsafe static void SendFullSyncRequest() { //IL_0048: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsClient || NetworkManager.Singleton.IsServer) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(0, (Allocator)2, -1); try { NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("LethalAlcoolico.RequestFullSync", 0uL, val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private static void OnRequestFullSyncServer(ulong clientId, FastBufferReader reader) { if (!((Object)(object)NetworkManager.Singleton == (Object)null) && NetworkManager.Singleton.IsServer) { EnsureSaveLoaded(); EnsureServerStatesForScene(); SendStateToClient(clientId, refreshBoard: true, resyncVisuals: true); BroadcastStateToClients(refreshBoard: true, resyncVisuals: true); ApplyLocalStateCacheToScene(refreshBoard: true, resyncVisuals: true); } } private static void OnPlayerDiedServer(ulong clientId, FastBufferReader reader) { if (!((Object)(object)NetworkManager.Singleton == (Object)null) && NetworkManager.Singleton.IsServer && TryGetPlayerByClientId(clientId, out PlayerControllerB player)) { HostApplyDeath(player); } } private static void OnPlayerDrankShotServer(ulong clientId, FastBufferReader reader) { if (!((Object)(object)NetworkManager.Singleton == (Object)null) && NetworkManager.Singleton.IsServer && TryGetPlayerByClientId(clientId, out PlayerControllerB player)) { HostApplyDrinkShot(player); } } private static void OnRegisterLanIdentityServer(ulong clientId, FastBufferReader reader) { //IL_002a: 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_003d: 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) if (!((Object)(object)NetworkManager.Singleton == (Object)null) && NetworkManager.Singleton.IsServer) { ulong baseId = default(ulong); ((FastBufferReader)(ref reader)).ReadValue<ulong>(ref baseId, default(ForPrimitives)); ulong sessionNonce = default(ulong); ((FastBufferReader)(ref reader)).ReadValue<ulong>(ref sessionNonce, default(ForPrimitives)); RegisterLanIdentityForClient(clientId, baseId, sessionNonce); EnsureSaveLoaded(); EnsureServerStatesForScene(); SendStateToClient(clientId, refreshBoard: true, resyncVisuals: true); BroadcastStateToClients(refreshBoard: true, resyncVisuals: true); ApplyLocalStateCacheToScene(refreshBoard: true, resyncVisuals: true); } } private static void OnFullSyncClient(ulong clientId, FastBufferReader reader) { //IL_0012: 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_0026: 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_003a: 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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) syncedStates.Clear(); bool flag = default(bool); ((FastBufferReader)(ref reader)).ReadValue<bool>(ref flag, default(ForPrimitives)); bool flag2 = default(bool); ((FastBufferReader)(ref reader)).ReadValue<bool>(ref flag2, default(ForPrimitives)); bool flag3 = default(bool); ((FastBufferReader)(ref reader)).ReadValue<bool>(ref flag3, default(ForPrimitives)); bool refreshBoard = default(bool); ((FastBufferReader)(ref reader)).ReadValue<bool>(ref refreshBoard, default(ForPrimitives)); bool resyncVisuals = default(bool); ((FastBufferReader)(ref reader)).ReadValue<bool>(ref resyncVisuals, default(ForPrimitives)); int num = default(int); ((FastBufferReader)(ref reader)).ReadValue<int>(ref num, default(ForPrimitives)); ulong num2 = default(ulong); ulong identityKey = default(ulong); int totalDeaths = default(int); int pendingCups = default(int); float drunkPercentage = default(float); for (int i = 0; i < num; i++) { ((FastBufferReader)(ref reader)).ReadValue<ulong>(ref num2, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValue<ulong>(ref identityKey, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValue<int>(ref totalDeaths, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValue<int>(ref pendingCups, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValue<float>(ref drunkPercentage, default(ForPrimitives)); syncedStates[num2] = new PlayerAlcoholStateData { ClientId = num2, IdentityKey = identityKey, TotalDeaths = totalDeaths, PendingCups = pendingCups, DrunkPercentage = drunkPercentage }; } firstDeathEnabled = flag; firstDeathAnnounced = flag2; punishKillsEnabled = flag3; LethalAlcoolicoPatches.SetFirstDeathEnabledMirror(firstDeathEnabled); LethalAlcoolicoPatches.SetFirstDeathAnnouncedMirror(firstDeathAnnounced); ApplyLocalStateCacheToScene(refreshBoard, resyncVisuals); } private static void HostApplyDrinkShot(PlayerControllerB player) { if (TryGetPlayerIdentityKey(player, out var identityKey)) { EnsureSaveLoaded(); EnsureServerStatesForScene(); if (!serverStates.TryGetValue(identityKey, out var value)) { value = CreateDefaultState(identityKey); } if (value.PendingCups > 0) { value.PendingCups--; } value.TotalDeaths++; value.DrunkPercentage = CalculateBAC(value.TotalDeaths); value.IdentityKey = identityKey; serverStates[identityKey] = value; SaveServerStates(); BroadcastStateToClients(refreshBoard: true, resyncVisuals: true); ApplyLocalStateCacheToScene(refreshBoard: true, resyncVisuals: true); } } private static void HostApplyDeath(PlayerControllerB player) { if (!TryGetPlayerIdentityKey(player, out var identityKey)) { return; } ulong actualClientId = player.actualClientId; EnsureSaveLoaded(); EnsureServerStatesForScene(); if (!serverStates.TryGetValue(identityKey, out var value)) { value = CreateDefaultState(identityKey); } ulong attackerClientId; bool flag = TryGetRecentAttacker(actualClientId, out attackerClientId) && attackerClientId != actualClientId; int num = LAConfig.ShotsPerDeath.Value; bool flag2 = false; if (!flag && firstDeathEnabled && !firstDeathAnnounced) { firstDeathAnnounced = true; flag2 = true; num++; LethalAlcoolicoPatches.SetFirstDeathAnnouncedMirror(value: true); } value.PendingCups += num; value.IdentityKey = identityKey; serverStates[identityKey] = value; if (flag && punishKillsEnabled && TryGetPlayerByClientId(attackerClientId, out PlayerControllerB player2) && TryGetPlayerIdentityKey(player2, out var identityKey2)) { if (!serverStates.TryGetValue(identityKey2, out var value2)) { value2 = CreateDefaultState(identityKey2); } value2.PendingCups += 2; value2.IdentityKey = identityKey2; serverStates[identityKey2] = value2; HUDManager.Instance.AddTextToChatOnServer($"{player2.playerUsername} matou {player.playerUsername}. Assassinos bebem {2} shots!", -1); } if (flag2) { HUDManager.Instance.AddTextToChatOnServer($"{player.playerUsername} foi o primeiro a morrer! Bebe {num} shots!", -1); } recentHitsByVictim.Remove(actualClientId); SaveServerStates(); BroadcastStateToClients(refreshBoard: false, resyncVisuals: true); ApplyLocalStateCacheToScene(refreshBoard: false, resyncVisuals: true); } private static void HostDecayTick() { decayTimer += Time.deltaTime; if (decayTimer < 12f) { return; } decayTimer = 0f; EnsureSaveLoaded(); EnsureServerStatesForScene(); bool flag = false; float num = 0.00125f; List<ulong> list = new List<ulong>(serverStates.Keys); for (int i = 0; i < list.Count; i++) { ulong key = list[i]; PlayerAlcoholStateData value = serverStates[key]; if (!(value.DrunkPercentage <= 0f)) { float num2 = Mathf.Max(0f, value.DrunkPercentage - num); if (Mathf.Abs(num2 - value.DrunkPercentage) > 0.001f) { value.DrunkPercentage = num2; serverStates[key] = value; flag = true; } } } if (flag) { SaveServerStates(); BroadcastStateToClients(refreshBoard: false, resyncVisuals: false); ApplyLocalStateCacheToScene(refreshBoard: false, resyncVisuals: false); } } private static void EnsureServerStatesForScene() { if ((Object)(object)StartOfRound.Instance == (Object)null || StartOfRound.Instance.allPlayerScripts == null) { return; } PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if (IsTrackablePlayer(val) && TryGetPlayerIdentityKey(val, out var identityKey) && !serverStates.ContainsKey(identityKey)) { LethalAlcoolicoPlayerState component = ((Component)val).GetComponent<LethalAlcoolicoPlayerState>(); serverStates[identityKey] = new PlayerAlcoholStateData { ClientId = val.actualClientId, IdentityKey = identityKey, TotalDeaths = (((Object)(object)component != (Object)null) ? component.TotalDeaths : 0), PendingCups = (((Object)(object)component != (Object)null) ? component.PendingCups : 0), DrunkPercentage = (((Object)(object)component != (Object)null) ? component.DrunkPercentage : 0f) }; } } } private unsafe static void SendStateToClient(ulong clientId, bool refreshBoard, bool resyncVisuals) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) FastBufferWriter val = BuildStateWriter(refreshBoard, resyncVisuals); try { NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("LethalAlcoolico.FullSync", clientId, val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private unsafe static void BroadcastStateToClients(bool refreshBoard, bool resyncVisuals) { //IL_0026: 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_003b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer) { return; } FastBufferWriter val = BuildStateWriter(refreshBoard, resyncVisuals); try { NetworkManager.Singleton.CustomMessagingManager.SendNamedMessageToAll("LethalAlcoolico.FullSync", val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private static FastBufferWriter BuildStateWriter(bool refreshBoard, bool resyncVisuals) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0034: 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_004a: 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) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) FastBufferWriter result = default(FastBufferWriter); ((FastBufferWriter)(ref result))..ctor(4096, (Allocator)2, -1); List<PlayerAlcoholStateData> list = new List<PlayerAlcoholStateData>(); ((FastBufferWriter)(ref result)).WriteValue<bool>(ref firstDeathEnabled, default(ForPrimitives)); ((FastBufferWriter)(ref result)).WriteValue<bool>(ref firstDeathAnnounced, default(ForPrimitives)); ((FastBufferWriter)(ref result)).WriteValue<bool>(ref punishKillsEnabled, default(ForPrimitives)); ((FastBufferWriter)(ref result)).WriteValue<bool>(ref refreshBoard, default(ForPrimitives)); ((FastBufferWriter)(ref result)).WriteValue<bool>(ref resyncVisuals, default(ForPrimitives)); if ((Object)(object)StartOfRound.Instance != (Object)null && StartOfRound.Instance.allPlayerScripts != null) { PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if (IsTrackablePlayer(val) && TryGetPlayerIdentityKey(val, out var identityKey)) { if (!serverStates.TryGetValue(identityKey, out var value)) { value = CreateDefaultState(identityKey); } value.ClientId = val.actualClientId; value.IdentityKey = identityKey; list.Add(value); } } } int count = list.Count; ((FastBufferWriter)(ref result)).WriteValue<int>(ref count, default(ForPrimitives)); foreach (PlayerAlcoholStateData item in list) { PlayerAlcoholStateData current = item; ((FastBufferWriter)(ref result)).WriteValue<ulong>(ref current.ClientId, default(ForPrimitives)); ((FastBufferWriter)(ref result)).WriteValue<ulong>(ref current.IdentityKey, default(ForPrimitives)); ((FastBufferWriter)(ref result)).WriteValue<int>(ref current.TotalDeaths, default(ForPrimitives)); ((FastBufferWriter)(ref result)).WriteValue<int>(ref current.PendingCups, default(ForPrimitives)); ((FastBufferWriter)(ref result)).WriteValue<float>(ref current.DrunkPercentage, default(ForPrimitives)); } return result; } private static void ApplyLocalStateCacheToScene(bool refreshBoard, bool resyncVisuals) { if ((Object)(object)StartOfRound.Instance == (Object)null || StartOfRound.Instance.allPlayerScripts == null) { return; } PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if ((Object)(object)val == (Object)null) { continue; } LethalAlcoolicoPlayerState lethalAlcoolicoPlayerState = ((Component)val).GetComponent<LethalAlcoolicoPlayerState>(); if ((Object)(object)lethalAlcoolicoPlayerState == (Object)null) { lethalAlcoolicoPlayerState = ((Component)val).gameObject.AddComponent<LethalAlcoolicoPlayerState>(); } if (!IsTrackablePlayer(val)) { lethalAlcoolicoPlayerState.ApplyState(0, 0, 0f); if (resyncVisuals) { LethalAlcoolicoPatches.SyncVisuals(val, 0); } continue; } PlayerAlcoholStateData value2; if ((Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsServer) { if (TryGetPlayerIdentityKey(val, out var identityKey) && serverStates.TryGetValue(identityKey, out var value)) { lethalAlcoolicoPlayerState.ApplyState(value.TotalDeaths, value.PendingCups, value.DrunkPercentage); } else { lethalAlcoolicoPlayerState.ApplyState(0, 0, 0f); } } else if (syncedStates.TryGetValue(val.actualClientId, out value2)) { lethalAlcoolicoPlayerState.ApplyState(value2.TotalDeaths, value2.PendingCups, value2.DrunkPercentage); } else { lethalAlcoolicoPlayerState.ApplyState(0, 0, 0f); } if (resyncVisuals) { LethalAlcoolicoPatches.SyncVisuals(val, lethalAlcoolicoPlayerState.PendingCups); } } if (refreshBoard) { LethalAlcoolicoPatches.RefreshBoard(); } } private static bool TryGetPlayerByClientId(ulong clientId, out PlayerControllerB player) { player = null; if ((Object)(object)StartOfRound.Instance == (Object)null || StartOfRound.Instance.allPlayerScripts == null) { return false; } PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if (IsTrackablePlayer(val) && val.actualClientId == clientId) { player = val; return true; } } return false; } private static bool TryGetRecentAttacker(ulong victimClientId, out ulong attackerClientId) { attackerClientId = 0uL; if (!recentHitsByVictim.TryGetValue(victimClientId, out var value)) { return false; } if (Time.time - value.Time > 2f) { recentHitsByVictim.Remove(victimClientId); return false; } attackerClientId = value.AttackerClientId; return true; } private static PlayerAlcoholStateData CreateDefaultState(ulong identityKey) { return new PlayerAlcoholStateData { IdentityKey = identityKey, TotalDeaths = 0, PendingCups = 0, DrunkPercentage = 0f }; } private static float CalculateBAC(int totalShots) { if (totalShots <= 0) { return 0f; } float value = LAConfig.PlayerWeight.Value; float num = LAConfig.AlcoholABVPercent.Value / 100f; float value2 = LAConfig.ShotSize.Value; float num2 = 0.65f; float num3 = 4f; float num4 = (float)totalShots * value2 * num * 0.8f; float num5 = num4 / (value * num2); return num5 / num3 * 100f; } private static bool IsTrackablePlayer(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return false; } if (player.isPlayerControlled) { return true; } if (player.isPlayerDead) { return true; } return false; } private static bool TryGetPlayerIdentityKey(PlayerControllerB player, out ulong identityKey) { identityKey = 0uL; if ((Object)(object)player == (Object)null) { return false; } if (player.playerSteamId != 0) { identityKey = player.playerSteamId; return true; } if (!IsLanFallbackActive()) { return false; } if (!lanIdentityByClientId.TryGetValue(player.actualClientId, out var value)) { return false; } identityKey = value.ResolvedId; return identityKey != 0; } private static void EnsureSaveLoaded() { if (AlcoholSyncManager.loadedSaveData || (Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer) { return; } AlcoholSyncManager.loadedSaveData = true; serverStates.Clear(); LoadedSaveData loadedSaveData = SaveManager.Load(); firstDeathEnabled = loadedSaveData.firstDeathEnabled; punishKillsEnabled = loadedSaveData.punishKillsEnabled; LethalAlcoolicoPatches.SetFirstDeathEnabledMirror(firstDeathEnabled); foreach (KeyValuePair<ulong, PlayerStats> player in loadedSaveData.players) { serverStates[player.Key] = new PlayerAlcoholStateData { IdentityKey = player.Key, TotalDeaths = player.Value.totalDeaths, PendingCups = player.Value.pendingCups, DrunkPercentage = player.Value.drunkPercent }; } } private static void SaveServerStates() { if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer) { return; } EnsureSaveLoaded(); Dictionary<ulong, PlayerStats> dictionary = new Dictionary<ulong, PlayerStats>(serverStates.Count); foreach (KeyValuePair<ulong, PlayerAlcoholStateData> serverState in serverStates) { dictionary[serverState.Key] = new PlayerStats { totalDeaths = serverState.Value.TotalDeaths, pendingCups = serverState.Value.PendingCups, drunkPercent = serverState.Value.DrunkPercentage }; } SaveManager.Save(dictionary, firstDeathEnabled, punishKillsEnabled); } private static bool IsLanFallbackActive() { return (Object)(object)GameNetworkManager.Instance != (Object)null && GameNetworkManager.Instance.disableSteam; } private static void EnsureLocalLanIdentity() { if (!localLanIdentityInitialized) { localLanIdentityInitialized = true; string text = LAConfig.LanIdentitySeed.Value; if (string.IsNullOrWhiteSpace(text)) { text = Guid.NewGuid().ToString("N"); LAConfig.LanIdentitySeed.Value = text; } localLanBaseId = HashIdentityString("lan-base:" + text); localLanSessionNonce = HashIdentityString("lan-session:" + text + ":" + Guid.NewGuid().ToString("N")); } } private unsafe static void SendLanIdentityRegistration() { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006d: 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) if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsClient || NetworkManager.Singleton.IsServer || !IsLanFallbackActive()) { return; } EnsureLocalLanIdentity(); FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(16, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValue<ulong>(ref localLanBaseId, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValue<ulong>(ref localLanSessionNonce, default(ForPrimitives)); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("LethalAlcoolico.RegisterLanIdentity", 0uL, val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private static void RegisterLanIdentityForClient(ulong clientId, ulong baseId, ulong sessionNonce) { if (baseId != 0) { ulong resolvedId = ResolveLanIdentityForClient(clientId, baseId, sessionNonce); lanIdentityByClientId[clientId] = new LanIdentityRegistrationData { BaseId = baseId, SessionNonce = sessionNonce, ResolvedId = resolvedId }; } } private static ulong ResolveLanIdentityForClient(ulong clientId, ulong baseId, ulong sessionNonce) { if (lanIdentityByClientId.TryGetValue(clientId, out var value) && value.BaseId == baseId && value.SessionNonce == sessionNonce && value.ResolvedId != 0) { return value.ResolvedId; } ulong num = baseId; int num2 = 0; while (num == 0L || IsLanIdentityInUseByAnotherClient(clientId, num)) { num2++; num = HashIdentityString(baseId + ":" + sessionNonce + ":" + num2); } return num; } private static bool IsLanIdentityInUseByAnotherClient(ulong clientId, ulong identityKey) { foreach (KeyValuePair<ulong, LanIdentityRegistrationData> item in lanIdentityByClientId) { if (item.Key == clientId || item.Value.ResolvedId != identityKey) { continue; } return true; } return false; } private static void PruneDisconnectedLanIdentities() { if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer) { return; } HashSet<ulong> hashSet = new HashSet<ulong>(NetworkManager.Singleton.ConnectedClientsIds); List<ulong> list = new List<ulong>(lanIdentityByClientId.Keys); for (int i = 0; i < list.Count; i++) { ulong num = list[i]; if (!hashSet.Contains(num)) { lanIdentityByClientId.Remove(num); } } } private static ulong HashIdentityString(string value) { ulong num = 14695981039346656037uL; for (int i = 0; i < value.Length; i++) { num ^= value[i]; num *= 1099511628211L; } return (num == 0L) ? 1 : num; } } } namespace LethalAlcoolico.Board { public class PlayerInfoManager : MonoBehaviour { public TMP_Text playerName; public TMP_Text playerShots; public TMP_Text playerPendingShots; public TMP_Text playerBloodAlcohol; private void Awake() { if ((Object)(object)playerName == (Object)null) { playerName = ((Component)((Component)this).transform.Find("Name")).GetComponent<TMP_Text>(); } if ((Object)(object)playerShots == (Object)null) { playerShots = ((Component)((Component)this).transform.Find("ShotCount")).GetComponent<TMP_Text>(); } if ((Object)(object)playerPendingShots == (Object)null) { playerPendingShots = ((Component)((Component)this).transform.Find("ShotPending")).GetComponent<TMP_Text>(); } if ((Object)(object)playerBloodAlcohol == (Object)null) { playerBloodAlcohol = ((Component)((Component)this).transform.Find("AlcBlood")).GetComponent<TMP_Text>(); } } public void ChangePlayerStats(string playerName, string playerShots, string playerPendingShots, string playerBloodAlcohol) { this.playerName.text = playerName; this.playerShots.text = playerShots; this.playerPendingShots.text = playerPendingShots; this.playerBloodAlcohol.text = playerBloodAlcohol; } } public class PlayerPageManager : MonoBehaviour { public Transform[] slots = (Transform[])(object)new Transform[10]; private void Awake() { int childCount = ((Component)this).transform.childCount; slots = (Transform[])(object)new Transform[childCount]; for (int i = 0; i < childCount; i++) { slots[i] = ((Component)this).transform.GetChild(i); } } } } namespace LethalAlcoolico.Save { [Serializable] public class PlayerStats { public int totalDeaths; public int pendingCups; public float drunkPercent; } [Serializable] public class SaveData { public Dictionary<string, PlayerStats> players = new Dictionary<string, PlayerStats>(); public bool firstDeathEnabled; public bool punishKillsEnabled = true; } public class LoadedSaveData { public Dictionary<ulong, PlayerStats> players = new Dictionary<ulong, PlayerStats>(); public bool firstDeathEnabled; public bool punishKillsEnabled = true; } public static class SaveManager { private const string ES3Key = "LethalAlcoolico_PlayerData"; private static string CurrentFile => GameNetworkManager.Instance.currentSaveFileName; public static void Save(IReadOnlyDictionary<ulong, PlayerStats> statsBySteamId, bool firstDeathEnabled, bool punishKillsEnabled) { if ((Object)(object)GameNetworkManager.Instance == (Object)null || string.IsNullOrEmpty(CurrentFile)) { return; } SaveData saveData = new SaveData { players = new Dictionary<string, PlayerStats>(statsBySteamId.Count), firstDeathEnabled = firstDeathEnabled, punishKillsEnabled = punishKillsEnabled }; foreach (KeyValuePair<ulong, PlayerStats> item in statsBySteamId) { saveData.players[item.Key.ToString()] = item.Value; } ES3.Save<SaveData>("LethalAlcoolico_PlayerData", saveData, CurrentFile); } public static LoadedSaveData Load() { if ((Object)(object)GameNetworkManager.Instance == (Object)null || string.IsNullOrEmpty(CurrentFile)) { return new LoadedSaveData(); } if (!ES3.KeyExists("LethalAlcoolico_PlayerData", CurrentFile)) { return new LoadedSaveData(); } try { SaveData saveData = ES3.Load<SaveData>("LethalAlcoolico_PlayerData", CurrentFile); LoadedSaveData loadedSaveData = new LoadedSaveData { firstDeathEnabled = saveData.firstDeathEnabled, punishKillsEnabled = saveData.punishKillsEnabled }; foreach (KeyValuePair<string, PlayerStats> player in saveData.players) { if (ulong.TryParse(player.Key, out var result) && result != 0) { loadedSaveData.players[result] = player.Value; } } return loadedSaveData; } catch { Dictionary<string, PlayerStats> dictionary = ES3.Load<Dictionary<string, PlayerStats>>("LethalAlcoolico_PlayerData", CurrentFile); LoadedSaveData loadedSaveData2 = new LoadedSaveData(); foreach (KeyValuePair<string, PlayerStats> item in dictionary) { if (ulong.TryParse(item.Key, out var result2) && result2 != 0) { loadedSaveData2.players[result2] = item.Value; } } return loadedSaveData2; } } public static void Clear() { if (!((Object)(object)GameNetworkManager.Instance == (Object)null) && !string.IsNullOrEmpty(CurrentFile) && ES3.KeyExists("LethalAlcoolico_PlayerData", CurrentFile)) { ES3.DeleteKey("LethalAlcoolico_PlayerData", CurrentFile); } } } } namespace LethalAlcoolico.Patches { [HarmonyPatch(typeof(StartOfRound))] internal static class BoomboxShakeHostPatches { [HarmonyPatch("Start")] [HarmonyPostfix] private static void StartPostfix(StartOfRound __instance) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)((Component)__instance).GetComponent<BoomboxBassShakeController>() != (Object)null)) { ((Component)__instance).gameObject.AddComponent<BoomboxBassShakeController>(); } } } [HarmonyPatch] internal static class ChatInputLockPatches { private static bool terminalMenuOwnedByChat; private static TMP_InputField hookedChatField; [HarmonyPatch(typeof(HUDManager), "EnableChat_performed")] [HarmonyPostfix] private static void EnableChatPostfix() { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)val == (Object)null) && IsChatLockActive(HUDManager.Instance, val)) { ApplyChatLock(val); } } [HarmonyPatch(typeof(HUDManager), "SubmitChat_performed")] [HarmonyPostfix] private static void SubmitChatPostfix() { ReleaseChatLock(GameNetworkManager.Instance?.localPlayerController); } [HarmonyPatch(typeof(HUDManager), "OpenMenu_performed")] [HarmonyPostfix] private static void OpenMenuPostfix() { ReleaseChatLock(GameNetworkManager.Instance?.localPlayerController); } [HarmonyPatch(typeof(HUDManager), "Update")] [HarmonyPostfix] private static void UpdatePostfix(HUDManager __instance) { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val == (Object)null) { UnhookChatField(); terminalMenuOwnedByChat = false; return; } HookChatField(__instance); if (IsChatLockActive(__instance, val)) { TryManualSubmit(__instance, val); ApplyChatLock(val); } else if (terminalMenuOwnedByChat) { ReleaseChatLock(val); } } [HarmonyPatch(typeof(PlayerControllerB), "Jump_performed")] [HarmonyPrefix] private static bool JumpPrefix(PlayerControllerB __instance) { return !IsChatLockActive(HUDManager.Instance, __instance); } [HarmonyPatch(typeof(PlayerControllerB), "Crouch_performed")] [HarmonyPrefix] private static bool CrouchPrefix(PlayerControllerB __instance) { return !IsChatLockActive(HUDManager.Instance, __instance); } private static bool IsChatLockActive(HUDManager hud, PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return false; } if (player.isTypingChat) { return true; } if ((Object)(object)hud == (Object)null) { return false; } bool flag = (Object)(object)hud.chatTextField != (Object)null && (hud.chatTextField.isFocused || ((Object)(object)EventSystem.current != (Object)null && (Object)(object)EventSystem.current.currentSelectedGameObject == (Object)(object)((Component)hud.chatTextField).gameObject)); bool flag2 = (Object)(object)hud.typingIndicator != (Object)null && ((Behaviour)hud.typingIndicator).enabled; return flag || flag2; } private static bool IsChatFieldFocused(HUDManager hud) { return (Object)(object)hud != (Object)null && (Object)(object)hud.chatTextField != (Object)null && (hud.chatTextField.isFocused || ((Object)(object)EventSystem.current != (Object)null && (Object)(object)EventSystem.current.currentSelectedGameObject == (Object)(object)((Component)hud.chatTextField).gameObject)); } private static void HookChatField(HUDManager hud) { if (!((Object)(object)hud == (Object)null) && !((Object)(object)hud.chatTextField == (Object)(object)hookedChatField)) { UnhookChatField(); hookedChatField = hud.chatTextField; if ((Object)(object)hookedChatField != (Object)null) { ((UnityEvent<string>)(object)hookedChatField.onEndEdit).AddListener((UnityAction<string>)OnChatEndEdit); } } } private static void UnhookChatField() { if (!((Object)(object)hookedChatField == (Object)null)) { ((UnityEvent<string>)(object)hookedChatField.onEndEdit).RemoveListener((UnityAction<string>)OnChatEndEdit); hookedChatField = null; } } private static void OnChatEndEdit(string text) { HUDManager instance = HUDManager.Instance; PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)instance == (Object)null) && !((Object)(object)val == (Object)null) && terminalMenuOwnedByChat && val.isTypingChat) { SubmitChat(instance, val); } } private static void TryManualSubmit(HUDManager hud, PlayerControllerB player) { if (!((Object)(object)hud == (Object)null) && !((Object)(object)player == (Object)null) && player.isTypingChat && !player.isPlayerDead) { Keyboard current = Keyboard.current; bool flag = current != null && ((ButtonControl)current.enterKey).wasPressedThisFrame; Keyboard current2 = Keyboard.current; bool flag2 = current2 != null && ((ButtonControl)current2.numpadEnterKey).wasPressedThisFrame; if (flag || flag2) { SubmitChat(hud, player); } } } private static void SubmitChat(HUDManager hud, PlayerControllerB player) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrEmpty(hud.chatTextField.text) && hud.chatTextField.text.Length < 50) { hud.AddTextToChatOnServer(hud.chatTextField.text, (int)player.playerClientId); } for (int i = 0; i < StartOfRound.Instance.allPlayerScripts.Length; i++) { if (StartOfRound.Instance.allPlayerScripts[i].isPlayerControlled && Vector3.Distance(((Component)player).transform.position, ((Component)StartOfRound.Instance.allPlayerScripts[i]).transform.position) > 24.4f && (!player.holdingWalkieTalkie || !StartOfRound.Instance.allPlayerScripts[i].holdingWalkieTalkie)) { hud.playerCouldRecieveTextChatAnimator.SetTrigger("ping"); break; } } player.isTypingChat = false; hud.chatTextField.text = ""; EventSystem.current.SetSelectedGameObject((GameObject)null); hud.PingHUDElement(hud.Chat, 2f, 1f, 0.2f); ((Behaviour)hud.typingIndicator).enabled = false; ReleaseChatLock(player); } private static void ApplyChatLock(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return; } HUDManager instance = HUDManager.Instance; if ((Object)(object)instance != (Object)null) { if (!IsChatFieldFocused(instance)) { ((Selectable)instance.chatTextField).Select(); instance.chatTextField.ActivateInputField(); } ((Behaviour)instance.typingIndicator).enabled = true; instance.Chat.targetAlpha = 1f; if ((Object)(object)instance.Chat.canvasGroup != (Object)null) { instance.Chat.canvasGroup.alpha = 1f; } } player.isTypingChat = true; terminalMenuOwnedByChat = true; player.disableMoveInput = true; player.disableLookInput = true; } private static void ReleaseChatLock(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { terminalMenuOwnedByChat = false; return; } player.disableMoveInput = false; player.disableLookInput = false; terminalMenuOwnedByChat = false; } } [HarmonyPatch(typeof(PlayerControllerB))] public static class LethalAlcoolicoPatches { private static Dictionary<PlayerControllerB, List<GameObject>> playerCups = new Dictionary<PlayerControllerB, List<GameObject>>(); private static Dictionary<PlayerControllerB, float> playerCupExtraWeight = new Dictionary<PlayerControllerB, float>(); private static GameObject plasticCupPrefab; public static Animator boardAnimator; private static bool firstDeathAnnounced; public static bool firstDeathEnabled; public static Transform[] slots; public static void SetFirstDeathEnabledMirror(bool value) { firstDeathEnabled = value; } public static void SetFirstDeathAnnouncedMirror(bool value) { firstDeathAnnounced = value; } [HarmonyPatch(typeof(HUDManager), "Update")] [HarmonyPostfix] public static void CheckKeys() { StartOfRound instance = StartOfRound.Instance; if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance.localPlayerController == (Object)null)) { PlayerControllerB localPlayerController = instance.localPlayerController; if (localPlayerController.isPlayerControlled && ((ButtonControl)Keyboard.current.numpadEqualsKey).wasPressedThisFrame) { RefreshBoard(); } } } [HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")] [HarmonyPostfix] private static void OnPlayerDied(PlayerControllerB __instance) { if (!((Object)(object)__instance != (Object)(object)GameNetworkManager.Instance?.localPlayerController)) { AlcoholSyncManager.RequestDeath(__instance); } } [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPostfix] private static void MaintainCupWeight(PlayerControllerB __instance) { if (!((Object)(object)__instance != (Object)(object)GameNetworkManager.Instance?.localPlayerController) && playerCupExtraWeight.TryGetValue(__instance, out var value) && !(value <= 0f)) { float num = 1f + value; if (!(__instance.carryWeight >= num)) { __instance.carryWeight = num; StartOfRound.Instance.SendChangedWeightEvent(); } } } public static void SyncVisuals(PlayerControllerB player, int pendingCount) { float num = (float)pendingCount * 0.05f; playerCupExtraWeight.TryGetValue(player, out var value); player.carryWeight = Mathf.Max(1f, player.carryWeight - value + num); playerCupExtraWeight[player] = num; if ((Object)(object)player == (Object)(object)GameNetworkManager.Instance?.localPlayerController) { StartOfRound.Instance.SendChangedWeightEvent(); } RebuildCups(player, pendingCount); } public static void ResetVisualState() { playerCups.Clear(); playerCupExtraWeight.Clear(); } private static void RebuildCups(PlayerControllerB p, int pending) { //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) if (!playerCups.TryGetValue(p, out List<GameObject> value)) { value = new List<GameObject>(); playerCups[p] = value; } if (value.Count == pending) { return; } foreach (GameObject item in value) { if ((Object)(object)item != (Object)null) { Object.Destroy((Object)(object)item); } } value.Clear(); GameObject val = GetPlasticCupPrefab(); if ((Object)(object)val == (Object)null) { LethalAlcoolico.Logger.LogError((object)"[Alcoolico] ERRO FATAL: Prefab do copo nao foi encontrado no GetPlasticCupPrefab!"); return; } for (int i = 0; i < pending; i++) { GameObject val2 = Object.Instantiate<GameObject>(val, p.playerGlobalHead); if (((NetworkBehaviour)p).IsOwner) { val2.layer = 23; } if ((Object)(object)val2 == (Object)null) { LethalAlcoolico.Logger.LogError((object)"[Alcoolico] Instantiate falhou e retornou NULL!"); continue; } CleanCup(val2); val2.transform.localPosition = new Vector3(0f, 0.53f + (float)i * 0.05f, -0.02f); val2.transform.localRotation = Quaternion.Euler(-90f, 0f, 0f); val2.transform.localScale = Vector3.one * 0.3f; value.Add(val2); } } public static void RefreshBoard() { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)boardAnimator != (Object)null) { boardAnimator.Play("ScreenRefreshing", 0, 0f); } if (slots == null) { return; } Transform[] array = slots; foreach (Transform val in array) { foreach (Transform item in val) { Transform val2 = item; Object.Destroy((Object)(object)((Component)val2).gameObject); } } StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null || instance.allPlayerScripts == null) { return; } List<(string, int, int, float)> list = new List<(string, int, int, float)>(); PlayerControllerB[] allPlayerScripts = instance.allPlayerScripts; foreach (PlayerControllerB val3 in allPlayerScripts) { if (!((Object)(object)val3 == (Object)null) && AlcoholSyncManager.IsTrackablePlayerPublic(val3)) { LethalAlcoolicoPlayerState component = ((Component)val3).GetComponent<LethalAlcoolicoPlayerState>(); if (!((Object)(object)component == (Object)null)) { list.Add((val3.playerUsername, component.TotalDeaths, component.PendingCups, component.DrunkPercentage)); } } } list.Sort(delegate((string name, int deaths, int pending, float drunk) a, (string name, int deaths, int pending, float drunk) b) { int num2 = b.deaths.CompareTo(a.deaths); return (num2 != 0) ? num2 : b.pending.CompareTo(a.pending); }); for (int num = 0; num < list.Count && num < slots.Length; num++) { GameObject val4 = Object.Instantiate<GameObject>(AlcoholAssets.PlayerPrefab, slots[num]); val4.transform.localPosition = Vector3.zero; val4.transform.localRotation = Quaternion.identity; val4.transform.localScale = Vector3.one; PlayerInfoManager playerInfoManager = val4.GetComponent<PlayerInfoManager>(); if ((Object)(object)playerInfoManager == (Object)null) { playerInfoManager = val4.AddComponent<PlayerInfoManager>(); } playerInfoManager.ChangePlayerStats(list[num].Item1, list[num].Item2.ToString(), list[num].Item3.ToString(), list[num].Item4.ToString("F1") + "%"); } } [HarmonyPatch(typeof(StartOfRound), "AllPlayersHaveRevivedClientRpc")] [HarmonyPostfix] private static void OnAllPlayersHaveRevived() { if (!((Object)(object)NetworkManager.Singleton == (Object)null) && NetworkManager.Singleton.IsServer) { AlcoholSyncManager.HandleRoundStartServer(); } } [HarmonyPatch(typeof(StartOfRound), "Start")] [HarmonyPostfix] private static void OnStart() { SpawnBoard(); } private static GameObject GetPlasticCupPrefab() { if ((Object)(object)plasticCupPrefab != (Object)null) { return plasticCupPrefab; } List<Item> itemsList = StartOfRound.Instance.allItemsList.itemsList; foreach (Item item in itemsList) { if (item.itemName == "Plastic cup") { return plasticCupPrefab = item.spawnPrefab; } } return null; } private static void CleanCup(GameObject cup) { Object.Destroy((Object)(object)cup.GetComponent<GrabbableObject>()); Object.Destroy((Object)(object)cup.GetComponent<Rigidbody>()); Object.Destroy((Object)(object)cup.GetComponent<Collider>()); MonoBehaviour[] components = cup.GetComponents<MonoBehaviour>(); foreach (MonoBehaviour val in components) { Object.Destroy((Object)(object)val); } } [HarmonyPatch(typeof(PlayerControllerB), "DamagePlayerFromOtherClientServerRpc")] [HarmonyPostfix] private static void OnPlayerDamagedByOtherClient(PlayerControllerB __instance, int damageAmount, Vector3 hitDirection, int playerWhoHit) { if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer) { return; } StartOfRound instance = StartOfRound.Instance; if (!((Object)(object)instance == (Object)null) && instance.allPlayerScripts != null && playerWhoHit >= 0 && playerWhoHit < instance.allPlayerScripts.Length) { PlayerControllerB val = instance.allPlayerScripts[playerWhoHit]; if (AlcoholSyncManager.IsTrackablePlayerPublic(val)) { ulong actualClientId = __instance.actualClientId; ulong actualClientId2 = val.actualClientId; AlcoholSyncManager.HostRegisterPlayerHit(actualClientId, actualClientId2); } } } private static void SpawnBoard() { //IL_002d: 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_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Expected O, but got Unknown //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Expected O, but got Unknown //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Expected O, but got Unknown Transform elevatorTransform = StartOfRound.Instance.elevatorTransform; GameObject val = Object.Instantiate<GameObject>(AlcoholAssets.ScreenPrefab, elevatorTransform); val.transform.localPosition = new Vector3(0f, 0f, -4.8f); val.transform.localRotation = Quaternion.Euler(0f, 270f, 0f); val.transform.localScale = new Vector3(0.8f, 0.8f, 0.8f); boardAnimator = val.GetComponent<Animator>(); Transform val2 = val.transform.Find("Screen/PlayerPage"); int childCount = val2.childCount; slots = (Transform[])(object)new Transform[childCount]; for (int i = 0; i < childCount; i++) { slots[i] = val2.GetChild(i); } Transform val3 = val.transform.Find("Button"); if ((Object)(object)val3 == (Object)null) { LethalAlcoolico.Logger.LogError((object)"[Alcoolico] Botao nao encontrado no prefab!"); return; } MeshCollider component = ((Component)val3).GetComponent<MeshCollider>(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } BoxCollider val4 = ((Component)val3).gameObject.AddComponent<BoxCollider>(); ((Collider)val4).isTrigger = true; ((Component)val3).gameObject.layer = 9; ((Component)val3).gameObject.tag = "InteractTrigger"; InteractTrigger val5 = ((Component)val3).gameObject.AddComponent<InteractTrigger>(); typeof(InteractTrigger).GetField("playersManager", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(val5, StartOfRound.Instance); val5.hoverTip = "Beber Shot"; val5.interactable = true; val5.holdInteraction = false; val5.cooldownTime = 5f; val5.interactCooldown = true; val5.disableTriggerMesh = false; val5.hidePlayerItem = false; GameObject val6 = GameObject.Find("LightSwitch"); InteractTrigger componentInChildren = val6.GetComponentInChildren<InteractTrigger>(); val5.hoverIcon = componentInChildren.hoverIcon; val5.disabledHoverIcon = componentInChildren.disabledHoverIcon; val5.onInteract = new InteractEvent(); val5.onStopInteract = new InteractEvent(); val5.onCancelAnimation = new InteractEvent(); AlcoholButtonInteract alcoholButtonInteract = ((Component)val3).gameObject.AddComponent<AlcoholButtonInteract>(); ((UnityEvent<PlayerControllerB>)(object)val5.onInteract).AddListener((UnityAction<PlayerControllerB>)alcoholButtonInteract.OnInteract); } } [HarmonyPatch(typeof(PlayerControllerB), "Awake")] public static class PlayerInjectionPatch { [HarmonyPostfix] public static void Postfix(PlayerControllerB __instance) { if ((Object)(object)((Component)__instance).GetComponent<LethalAlcoolicoPlayerState>() == (Object)null) { ((Component)__instance).gameObject.AddComponent<LethalAlcoolicoPlayerState>(); } } } } namespace LethalAlcoolico.Network { public class LethalAlcoolicoPlayerState : MonoBehaviour { public int PendingCups { get; private set; } public int TotalDeaths { get; private set; } public float DrunkPercentage { get; private set; } public void ApplyState(int totalDeaths, int pendingCups, float drunkPercentage) { TotalDeaths = totalDeaths; PendingCups = pendingCups; DrunkPercentage = drunkPercentage; } } } namespace LethalAlcoolico.Commands { [HarmonyPatch(typeof(HUDManager))] public static class ChatCommandHandler { [HarmonyPatch("SubmitChat_performed")] [HarmonyPrefix] public static bool OnChatSubmit(HUDManager __instance) { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val == (Object)null) { return true; } string text = __instance.chatTextField.text.Trim(); if (!text.StartsWith("!")) { return true; } if (!NetworkManager.Singleton.IsHost) { __instance.chatTextField.text = ""; HUDManager.Instance.AddTextToChatOnServer("[Alcoolico] Apenas o host pode usar comandos!", -1); return false; } string[] array = text.Split(' '); switch (array[0].ToLower()) { case "!setshots": { if (array.Length < 3 || !int.TryParse(array[^1], out var result)) { SendFeedback("Uso: !setshots <nome> <quantidade>"); break; } string text2 = string.Join(" ", array, 1, array.Length - 2); PlayerControllerB val2 = FindPlayer(text2); if ((Object)(object)val2 == (Object)null) { SendFeedback("Player '" + text2 + "' não encontrado!"); break; } AlcoholSyncManager.HostSetShots(val2, result); SendFeedback($"Shots de {val2.playerUsername} setado para {result}!"); break; } case "!setpending": { if (array.Length < 3 || !int.TryParse(array[^1], out var result2)) { SendFeedback("Uso: !setpending <nome> <quantidade>"); break; } string text3 = string.Join(" ", array, 1, array.Length - 2); PlayerControllerB val3 = FindPlayer(text3); if ((Object)(object)val3 == (Object)null) { SendFeedback("Player '" + text3 + "' não encontrado!"); break; } AlcoholSyncManager.HostSetPending(val3, result2); SendFeedback($"Pending de {val3.playerUsername} setado para {result2}!"); break; } case "!firstdeath": { if (array.Length < 2) { SendFeedback("Uso: !firstdeath <true/false>"); break; } bool flag2 = array[1].ToLower() == "true"; AlcoholSyncManager.HostSetFirstDeathEnabled(flag2); SendFeedback("First death " + (flag2 ? "ativado" : "desativado") + "!"); break; } case "!punishkills": { if (array.Length < 2) { SendFeedback("Uso: !punishKills <true/false>"); break; } bool flag = array[1].ToLower() == "true"; AlcoholSyncManager.HostSetPunishKillsEnabled(flag); SendFeedback("PunishKills " + (flag ? "ativado" : "desativado") + "!"); break; } case "!refreshboard": AlcoholSyncManager.HostRefreshBoard(resyncVisuals: true); SendFeedback("Board refreshado para todos!"); break; default: return true; } __instance.chatTextField.text = ""; return false; } private static PlayerControllerB FindPlayer(string nameArg) { string text = nameArg.Trim().ToLower(); PlayerControllerB val = null; PlayerControllerB val2 = null; PlayerControllerB val3 = null; PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val4 in allPlayerScripts) { if (AlcoholSyncManager.IsTrackablePlayerPublic(val4)) { string text2 = val4.playerUsername.ToLower(); if (text2 == text) { val = val4; } else if ((Object)(object)val2 == (Object)null && text2.StartsWith(text)) { val2 = val4; } else if ((Object)(object)val3 == (Object)null && text2.Contains(text)) { val3 = val4; } } } return val ?? val2 ?? val3; } private static void SendFeedback(string msg) { HUDManager.Instance.AddTextToChatOnServer("[Alcoolico] " + msg, -1); } } } namespace __GEN { internal class NetworkVariableSerializationHelper { [RuntimeInitializeOnLoadMethod] internal static void InitializeSerialization() { } } } namespace Sociors.LethalAlcoolico.NetcodePatcher { [AttributeUsage(AttributeTargets.Module)] internal class NetcodePatchedAssemblyAttribute : Attribute { } }