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 LonelyDeath v1.0.0
LonelyDeath.dll
Decompiled 2 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Microsoft.CodeAnalysis; using Photon.Pun; using UnityEngine; [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: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("REPOJP")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("zabuMod")] [assembly: AssemblyTitle("zabuMod")] [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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace REPOJP.LonelyDeath { [BepInPlugin("REPOJP.LonelyDeath", "LonelyDeath", "1.0.0")] public sealed class LonelyDeathPlugin : BaseUnityPlugin { public const string PluginGuid = "REPOJP.LonelyDeath"; public const string PluginName = "LonelyDeath"; public const string PluginVersion = "1.0.0"; internal static ManualLogSource Log; internal static LonelyDeathConfig ModConfig; private void Awake() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown try { Log = ((BaseUnityPlugin)this).Logger; ModConfig = new LonelyDeathConfig(((BaseUnityPlugin)this).Config); GameObject val = new GameObject("REPOJP_LonelyDeath_Manager"); val.transform.parent = null; ((Object)val).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)val); val.AddComponent<LonelyDeathManager>(); Log.LogInfo((object)"LonelyDeath loaded."); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Failure: LonelyDeath Awake\n" + ex)); } } } internal sealed class LonelyDeathConfig { internal readonly ConfigEntry<bool> EnableMod; internal readonly ConfigEntry<float> Radius; internal readonly ConfigEntry<float> CheckInterval; internal readonly ConfigEntry<float> KillDelay; internal readonly ConfigEntry<int> DamagePerSecond; internal readonly ConfigEntry<float> DamageStartDelay; internal readonly ConfigEntry<bool> TruckSafeZone; internal readonly ConfigEntry<string> OutsideChatMessage; internal readonly ConfigEntry<string> SafeChatMessage; internal readonly ConfigEntry<bool> EnableDebugLog; internal LonelyDeathConfig(ConfigFile config) { EnableMod = config.Bind<bool>("General", "EnableMod", true, "Enable this mod.このMODを有効化"); Radius = config.Bind<float>("General", "Radius", 25f, "Safe sphere radius from the center point.中心点からの安全球半径"); CheckInterval = config.Bind<float>("General", "CheckInterval", 1f, "Position check interval in seconds.位置判定間隔 秒"); KillDelay = config.Bind<float>("General", "KillDelay", 10f, "Seconds from leaving the safe sphere until death.安全球外に出てから死亡までの秒数"); DamagePerSecond = config.Bind<int>("General", "DamagePerSecond", 1, "Damage applied every second while outside after the delay.猶予後に球外で毎秒受けるダメージ量"); DamageStartDelay = config.Bind<float>("General", "DamageStartDelay", 0f, "Seconds before periodic damage starts after leaving the safe sphere.球外に出てから継続ダメージ開始までの猶予秒数"); TruckSafeZone = config.Bind<bool>("General", "TruckSafeZone", true, "Treat the truck as a safe zone.トラック内をセーフティーゾーン扱い"); OutsideChatMessage = config.Bind<string>("Chat", "OutsideChatMessage", "I'm too far away from everyone. I'm lonely. I'm going to die.", "Forced public chat when a player leaves the safe sphere.安全球外に出た時の強制公開チャット"); SafeChatMessage = config.Bind<string>("Chat", "SafeChatMessage", "safe", "Forced public chat when a player returns to safety.安全圏に戻った時の強制公開チャット"); EnableDebugLog = config.Bind<bool>("Debug", "EnableDebugLog", false, "Enable debug logs.デバッグログを有効化"); } } internal sealed class LonelyDeathManager : MonoBehaviour { private readonly Dictionary<string, PlayerLonelyState> playerStates = new Dictionary<string, PlayerLonelyState>(); private float nextCheckTime; private void Update() { try { LonelyDeathConfig modConfig = LonelyDeathPlugin.ModConfig; if (modConfig == null || !modConfig.EnableMod.Value) { ClearAllStates(sendSafeChat: false); return; } float num = Mathf.Max(0.1f, modConfig.CheckInterval.Value); if (!(Time.time < nextCheckTime)) { nextCheckTime = Time.time + num; RunCheck(modConfig); } } catch (Exception ex) { LonelyDeathPlugin.Log.LogError((object)("Failure: LonelyDeath Update\n" + ex)); } } private void RunCheck(LonelyDeathConfig config) { //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) if (!IsMasterClient()) { ClearAllStates(sendSafeChat: false); return; } if (!IsValidRunState()) { ClearAllStates(sendSafeChat: false); return; } List<PlayerAvatar> alivePlayers = GetAlivePlayers(); if (alivePlayers.Count < 2) { ClearAllStates(sendSafeChat: false); return; } List<PlayerAvatar> list = new List<PlayerAvatar>(); foreach (PlayerAvatar item in alivePlayers) { if (!IsPlayerInTruck(item)) { list.Add(item); } } if (list.Count < 2) { ClearAllStates(sendSafeChat: false); return; } Vector3 val = CalculateCenter(list); float num = Mathf.Max(0.1f, config.Radius.Value); foreach (PlayerAvatar item2 in alivePlayers) { string playerKey = GetPlayerKey(item2); if (string.IsNullOrEmpty(playerKey)) { continue; } bool flag = IsPlayerInTruck(item2); if (config.TruckSafeZone.Value && flag) { SetSafe(item2, playerKey, config, sendSafeChat: true); continue; } float num2 = Vector3.Distance(((Component)item2).transform.position, val); if (num2 > num) { SetOutside(item2, playerKey, config, num2, num); } else { SetSafe(item2, playerKey, config, sendSafeChat: true); } } RemoveInvalidStates(alivePlayers); } private static bool IsMasterClient() { try { if (!SemiFunc.IsMultiplayer()) { return false; } return SemiFunc.IsMasterClient(); } catch { return PhotonNetwork.IsMasterClient; } } private static bool IsValidRunState() { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Invalid comparison between Unknown and I4 try { if (!SemiFunc.IsMultiplayer()) { return false; } if (!SemiFunc.RunIsLevel()) { return false; } if (SemiFunc.RunIsShop() || SemiFunc.RunIsLobby() || SemiFunc.RunIsLobbyMenu() || SemiFunc.RunIsTutorial()) { return false; } if ((Object)(object)GameDirector.instance == (Object)null || (int)GameDirector.instance.currentState != 2) { return false; } return true; } catch { return false; } } private static List<PlayerAvatar> GetAlivePlayers() { List<PlayerAvatar> list = new List<PlayerAvatar>(); List<PlayerAvatar> list2 = null; try { list2 = SemiFunc.PlayerGetList(); } catch { if ((Object)(object)GameDirector.instance != (Object)null) { list2 = GameDirector.instance.PlayerList; } } if (list2 == null) { return list; } foreach (PlayerAvatar item in list2) { if (IsAlivePlayer(item)) { list.Add(item); } } return list; } private static bool IsAlivePlayer(PlayerAvatar player) { if ((Object)(object)player == (Object)null) { return false; } if (player.isDisabled || player.deadSet) { return false; } if ((Object)(object)player.playerHealth == (Object)null) { return false; } if (player.playerHealth.health <= 0) { return false; } return true; } private static bool IsPlayerInTruck(PlayerAvatar player) { try { return (Object)(object)player != (Object)null && (Object)(object)player.RoomVolumeCheck != (Object)null && player.RoomVolumeCheck.inTruck; } catch { return false; } } private static Vector3 CalculateCenter(List<PlayerAvatar> players) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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_0057: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Vector3.zero; foreach (PlayerAvatar player in players) { val += ((Component)player).transform.position; } return val / (float)players.Count; } private void SetOutside(PlayerAvatar player, string key, LonelyDeathConfig config, float distance, float radius) { if (!playerStates.TryGetValue(key, out PlayerLonelyState value)) { value = new PlayerLonelyState(); value.OutsideStartTime = Time.time; value.NextDamageTime = Time.time + Mathf.Max(0f, config.DamageStartDelay.Value); value.OutsideChatSent = false; playerStates[key] = value; } if (!value.OutsideChatSent) { SendForcedChat(player, config.OutsideChatMessage.Value); value.OutsideChatSent = true; } ApplyRedEyes(player); int num = Mathf.Max(0, config.DamagePerSecond.Value); if (num > 0 && Time.time >= value.NextDamageTime) { DamagePlayer(player, num); value.NextDamageTime = Time.time + 1f; } float num2 = Mathf.Max(0.1f, config.KillDelay.Value); if (Time.time - value.OutsideStartTime >= num2) { KillPlayer(player); playerStates.Remove(key); } else if (config.EnableDebugLog.Value) { LonelyDeathPlugin.Log.LogInfo((object)("Outside: " + GetPlayerName(player) + " distance=" + distance.ToString("0.00") + " radius=" + radius.ToString("0.00"))); } } private void SetSafe(PlayerAvatar player, string key, LonelyDeathConfig config, bool sendSafeChat) { if (playerStates.ContainsKey(key)) { playerStates.Remove(key); ClearRedEyes(player); if (sendSafeChat && !string.IsNullOrEmpty(config.SafeChatMessage.Value)) { SendForcedChat(player, config.SafeChatMessage.Value); } } } private void ClearAllStates(bool sendSafeChat) { if (playerStates.Count == 0) { return; } List<PlayerAvatar> alivePlayers = GetAlivePlayers(); foreach (PlayerAvatar item in alivePlayers) { string playerKey = GetPlayerKey(item); if (!string.IsNullOrEmpty(playerKey) && playerStates.ContainsKey(playerKey)) { ClearRedEyes(item); if (sendSafeChat && LonelyDeathPlugin.ModConfig != null && !string.IsNullOrEmpty(LonelyDeathPlugin.ModConfig.SafeChatMessage.Value)) { SendForcedChat(item, LonelyDeathPlugin.ModConfig.SafeChatMessage.Value); } } } playerStates.Clear(); } private void RemoveInvalidStates(List<PlayerAvatar> alivePlayers) { HashSet<string> hashSet = new HashSet<string>(); foreach (PlayerAvatar alivePlayer in alivePlayers) { string playerKey = GetPlayerKey(alivePlayer); if (!string.IsNullOrEmpty(playerKey)) { hashSet.Add(playerKey); } } List<string> list = new List<string>(); foreach (string key in playerStates.Keys) { if (!hashSet.Contains(key)) { list.Add(key); } } foreach (string item in list) { playerStates.Remove(item); } } private static void SendForcedChat(PlayerAvatar player, string message) { if ((Object)(object)player == (Object)null || string.IsNullOrEmpty(message)) { return; } try { player.ChatMessageSend(message); } catch (Exception ex) { LonelyDeathPlugin.Log.LogWarning((object)("Failure: SendForcedChat " + GetPlayerName(player) + "\n" + ex)); } } private static void DamagePlayer(PlayerAvatar player, int damage) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || (Object)(object)player.playerHealth == (Object)null || damage <= 0) { return; } try { player.playerHealth.HurtOther(damage, Vector3.zero, false, -1); } catch (Exception ex) { LonelyDeathPlugin.Log.LogWarning((object)("Failure: DamagePlayer " + GetPlayerName(player) + "\n" + ex)); } } private static void KillPlayer(PlayerAvatar player) { if ((Object)(object)player == (Object)null || player.deadSet) { return; } try { player.PlayerDeath(-1); } catch (Exception ex) { LonelyDeathPlugin.Log.LogWarning((object)("Failure: KillPlayer " + GetPlayerName(player) + "\n" + ex)); } } private static void ApplyRedEyes(PlayerAvatar player) { if ((Object)(object)player == (Object)null || (Object)(object)player.playerHealth == (Object)null) { return; } try { if (GameManager.Multiplayer() && (Object)(object)player.playerHealth.photonView != (Object)null) { player.playerHealth.photonView.RPC("EyeMaterialOverrideRPC", (RpcTarget)0, new object[2] { (object)(EyeOverrideState)1, true }); } else { player.playerHealth.EyeMaterialOverride((EyeOverrideState)1, 1.25f, 50); } } catch (Exception ex) { LonelyDeathPlugin.Log.LogWarning((object)("Failure: ApplyRedEyes " + GetPlayerName(player) + "\n" + ex)); } } private static void ClearRedEyes(PlayerAvatar player) { if ((Object)(object)player == (Object)null || (Object)(object)player.playerHealth == (Object)null) { return; } try { if (GameManager.Multiplayer() && (Object)(object)player.playerHealth.photonView != (Object)null) { player.playerHealth.photonView.RPC("EyeMaterialOverrideRPC", (RpcTarget)0, new object[2] { (object)(EyeOverrideState)1, false }); } } catch (Exception ex) { LonelyDeathPlugin.Log.LogWarning((object)("Failure: ClearRedEyes " + GetPlayerName(player) + "\n" + ex)); } } private static string GetPlayerKey(PlayerAvatar player) { if ((Object)(object)player == (Object)null) { return string.Empty; } try { if (!string.IsNullOrEmpty(player.steamID)) { return player.steamID; } } catch { } try { if ((Object)(object)player.photonView != (Object)null && player.photonView.Owner != null) { return player.photonView.Owner.ActorNumber.ToString(); } } catch { } return ((Object)player).GetInstanceID().ToString(); } private static string GetPlayerName(PlayerAvatar player) { if ((Object)(object)player == (Object)null) { return "Unknown"; } try { return SemiFunc.PlayerGetName(player); } catch { return ((Object)player).name; } } } internal sealed class PlayerLonelyState { internal float OutsideStartTime; internal float NextDamageTime; internal bool OutsideChatSent; } }