using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Unity.Netcode; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("ScrapVisbility")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("ScrapVisbility")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("8a6853bd-bdc9-4741-95c7-5aa2c8c6a6f9")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.0.0")] namespace YourFurnace.RandomStartSuit; [BepInPlugin("YourFurnace.RandomStartSuit", "RandomStartSuit", "1.1.0")] public class Plugin : BaseUnityPlugin { private sealed class Assignment { public ulong ClientId; public int PlayerIndex; public int SuitId; public string SuitName; public float ResendUntil; public float NextResend; } private sealed class SuitChoice { public int SuitId; public string SuitName; public object UnlockableItem; } [CompilerGenerated] private sealed class d__38 : IEnumerable, IEnumerable, IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; private int <>l__initialThreadId; private object startOfRound; public object <>3__startOfRound; private object 5__1; private IEnumerable 5__2; private IEnumerator <>s__3; private object 5__4; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__38(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } 5__1 = null; 5__2 = null; <>s__3 = null; 5__4 = null; <>1__state = -2; } private bool MoveNext() { try { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -3; goto IL_00de; } <>1__state = -1; if (startOfRound == null) { return false; } 5__1 = GetMemberValue(startOfRound, startOfRound.GetType(), "allPlayerScripts"); 5__2 = 5__1 as IEnumerable; if (5__2 == null) { return false; } <>s__3 = 5__2.GetEnumerator(); <>1__state = -3; goto IL_00e6; IL_00de: 5__4 = null; goto IL_00e6; IL_00e6: if (<>s__3.MoveNext()) { 5__4 = <>s__3.Current; if (5__4 != null) { <>2__current = 5__4; <>1__state = 1; return true; } goto IL_00de; } <>m__Finally1(); <>s__3 = null; return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>s__3 is IDisposable disposable) { disposable.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { d__38 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__38(0); } d__.startOfRound = <>3__startOfRound; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } private const string PluginGuid = "YourFurnace.RandomStartSuit"; private const string PluginName = "RandomStartSuit"; private const string PluginVersion = "1.1.0"; private static ManualLogSource Log; private static readonly BindingFlags Flags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; private readonly Dictionary assignmentsByClientId = new Dictionary(); private ConfigEntry allowedSuitsCsv; private ConfigEntry firstAssignmentDelay; private ConfigEntry rescanInterval; private ConfigEntry serverResendSeconds; private ConfigEntry serverResendInterval; private ConfigEntry onlyAssignInShipLobby; private ConfigEntry useUnlockableSuitRpcFirst; private ConfigEntry useStartOfRoundRpcFallback; private ConfigEntry setPlayerSuitFieldsAsBackup; private ConfigEntry logDebug; private Random rng; private int currentStartOfRoundId; private float nextScanTime; private void Awake() { Log = ((BaseUnityPlugin)this).Logger; rng = new Random(); allowedSuitsCsv = ((BaseUnityPlugin)this).Config.Bind("Suit Selection", "Allowed suit names", "FemaleBlue,FemaleClothed,FemaleLime,FemaleOrange,FemalePink,FemaleStar,RealMan", "Comma separated exact unlockable names. FemaleBlue will NOT match FemaleBlueOpen. FemaleStar will NOT match FemaleStarOpen."); firstAssignmentDelay = ((BaseUnityPlugin)this).Config.Bind("Assignment", "First assignment delay seconds", 3f, "How long to wait after StartOfRound exists before assigning suits."); rescanInterval = ((BaseUnityPlugin)this).Config.Bind("Assignment", "Rescan interval seconds", 2f, "How often the host checks for players without assigned suits."); serverResendSeconds = ((BaseUnityPlugin)this).Config.Bind("Assignment", "Server resend seconds", 12f, "How long the host keeps reapplying the picked suit. This fights vanilla or other mods setting default suit after spawn."); serverResendInterval = ((BaseUnityPlugin)this).Config.Bind("Assignment", "Server resend interval seconds", 1f, "How often the host reapplies during the resend window."); onlyAssignInShipLobby = ((BaseUnityPlugin)this).Config.Bind("Assignment", "Only assign while in ship lobby", true, "Recommended true. Stops suit changing after landing."); useUnlockableSuitRpcFirst = ((BaseUnityPlugin)this).Config.Bind("Apply", "Use UnlockableSuit RPC first", true, "Recommended true. This matches the original working approach. It calls SwitchSuitClientRpc on the matching UnlockableSuit object by suit ID."); useStartOfRoundRpcFallback = ((BaseUnityPlugin)this).Config.Bind("Apply", "Use StartOfRound RPC fallback", true, "Uses StartOfRound suit switching only if the UnlockableSuit object method cannot be found."); setPlayerSuitFieldsAsBackup = ((BaseUnityPlugin)this).Config.Bind("Apply", "Set player suit fields as backup", false, "Leave false unless the suit still does not show. Direct fields can fight Netcode if done too early."); logDebug = ((BaseUnityPlugin)this).Config.Bind("Debug", "Log debug info", true, "Logs parsed whitelist, allowed exact unlockable matches, chosen suit, and apply method calls."); SceneManager.sceneLoaded += OnSceneLoaded; ((BaseUnityPlugin)this).Logger.LogInfo((object)"RandomStartSuit 1.1.0 loaded. Exact comma whitelist. UnlockablesList based. No suit rack required."); } private void OnDestroy() { SceneManager.sceneLoaded -= OnSceneLoaded; } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { if (IsMenuScene(((Scene)(ref scene)).name)) { assignmentsByClientId.Clear(); currentStartOfRoundId = 0; } nextScanTime = Time.realtimeSinceStartup + Mathf.Max(0.1f, firstAssignmentDelay.Value); } private void Update() { try { if (!IsHostOrServer()) { return; } object startOfRound = GetStartOfRound(); if (startOfRound == null) { return; } int instanceId = GetInstanceId(startOfRound); if (instanceId != currentStartOfRoundId) { currentStartOfRoundId = instanceId; assignmentsByClientId.Clear(); nextScanTime = Time.realtimeSinceStartup + Mathf.Max(0.1f, firstAssignmentDelay.Value); DebugLog("New StartOfRound detected. Assignment state cleared."); } else if (IsSafeAssignTime(startOfRound)) { if (Time.realtimeSinceStartup >= nextScanTime) { nextScanTime = Time.realtimeSinceStartup + Mathf.Max(0.25f, rescanInterval.Value); AssignMissingPlayers(startOfRound); } ResendAssignments(startOfRound); } } catch (Exception ex) { Log.LogWarning((object)("RandomStartSuit update failed safely: " + ShortException(ex))); } } private void AssignMissingPlayers(object startOfRound) { List allowedSuitsFromUnlockables = GetAllowedSuitsFromUnlockables(startOfRound); if (allowedSuitsFromUnlockables.Count == 0) { Log.LogWarning((object)"No allowed exact suit names were found in StartOfRound.unlockablesList."); Log.LogWarning((object)("Raw config value: " + allowedSuitsCsv.Value)); LogAvailableSuitLikeUnlockables(startOfRound); return; } foreach (object allPlayerScript in GetAllPlayerScripts(startOfRound)) { if (IsRealPlayer(allPlayerScript)) { ulong playerClientId = GetPlayerClientId(allPlayerScript); int playerIndex = GetPlayerIndex(startOfRound, allPlayerScript); if (playerIndex >= 0 && !assignmentsByClientId.ContainsKey(playerClientId)) { SuitChoice suitChoice = allowedSuitsFromUnlockables[rng.Next(allowedSuitsFromUnlockables.Count)]; Assignment assignment = new Assignment { ClientId = playerClientId, PlayerIndex = playerIndex, SuitId = suitChoice.SuitId, SuitName = suitChoice.SuitName, ResendUntil = Time.realtimeSinceStartup + Mathf.Max(0f, serverResendSeconds.Value), NextResend = 0f }; assignmentsByClientId[playerClientId] = assignment; Log.LogInfo((object)("Assigned " + PlayerLabel(allPlayerScript) + " playerIndex=" + playerIndex + " clientId=" + playerClientId + " exactSuit=" + suitChoice.SuitName + " suitID=" + suitChoice.SuitId)); ApplyAssignment(startOfRound, assignment, "initial"); } } } } private void ResendAssignments(object startOfRound) { float realtimeSinceStartup = Time.realtimeSinceStartup; float num = Mathf.Max(0.25f, serverResendInterval.Value); foreach (Assignment item in assignmentsByClientId.Values.ToList()) { if (!(realtimeSinceStartup > item.ResendUntil) && !(realtimeSinceStartup < item.NextResend)) { item.NextResend = realtimeSinceStartup + num; ApplyAssignment(startOfRound, item, "resend"); } } } private void ApplyAssignment(object startOfRound, Assignment assignment, string reason) { if (startOfRound == null || assignment == null) { return; } object obj = FindPlayerByClientIdOrIndex(startOfRound, assignment.ClientId, assignment.PlayerIndex); bool flag = false; if (useUnlockableSuitRpcFirst.Value) { object obj2 = FindUnlockableSuitObjectById(assignment.SuitId); if (obj2 != null) { flag |= InvokeSuitMethod(obj2, "SwitchSuitClientRpc", assignment.PlayerIndex, assignment.SuitId, obj); flag |= InvokeSuitMethod(obj2, "SwitchSuitServerRpc", assignment.PlayerIndex, assignment.SuitId, obj); flag |= InvokeSuitMethod(obj2, "SwitchSuitToThis", assignment.PlayerIndex, assignment.SuitId, obj); } else { DebugLog("No UnlockableSuit component object found for suitID=" + assignment.SuitId + " " + assignment.SuitName); } } if (!flag && useStartOfRoundRpcFallback.Value) { flag |= InvokeSuitMethod(startOfRound, "SwitchSuitClientRpc", assignment.PlayerIndex, assignment.SuitId, obj); flag |= InvokeSuitMethod(startOfRound, "SwitchSuitServerRpc", assignment.PlayerIndex, assignment.SuitId, obj); flag |= InvokeSuitMethod(startOfRound, "SwitchSuitForPlayer", assignment.PlayerIndex, assignment.SuitId, obj); } if (setPlayerSuitFieldsAsBackup.Value && obj != null) { SetPlayerSuitFields(obj, assignment.SuitId); } DebugLog("Apply " + reason + " playerIndex=" + assignment.PlayerIndex + " clientId=" + assignment.ClientId + " suit=" + assignment.SuitName + " id=" + assignment.SuitId + " applied=" + flag); } private List GetAllowedSuitsFromUnlockables(object startOfRound) { HashSet hashSet = ParseWhitelist(allowedSuitsCsv.Value); bool flag = hashSet.Contains("all"); DebugLog("Raw whitelist config: " + allowedSuitsCsv.Value); DebugLog("Parsed whitelist tokens: " + string.Join(", ", hashSet.ToArray())); List list = new List(); IList unlockablesList = GetUnlockablesList(startOfRound); if (unlockablesList == null) { Log.LogWarning((object)"Could not read StartOfRound.unlockablesList.unlockables."); return list; } for (int i = 0; i < unlockablesList.Count; i++) { object obj = unlockablesList[i]; if (obj == null) { continue; } string unlockableName = GetUnlockableName(obj); if (!string.IsNullOrWhiteSpace(unlockableName)) { string item = Normalize(unlockableName); if (flag || hashSet.Contains(item)) { list.Add(new SuitChoice { SuitId = i, SuitName = unlockableName, UnlockableItem = obj }); } } } if (list.Count > 0) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("Allowed exact unlockable matches: "); foreach (SuitChoice item2 in list) { stringBuilder.Append("[").Append(item2.SuitName).Append(" id=") .Append(item2.SuitId) .Append("] "); } Log.LogInfo((object)stringBuilder.ToString()); } return list; } private static HashSet ParseWhitelist(string csv) { HashSet hashSet = new HashSet(); if (string.IsNullOrWhiteSpace(csv)) { return hashSet; } string[] array = csv.Split(new char[6] { ',', ';', '|', '\n', '\r', '\t' }, StringSplitOptions.RemoveEmptyEntries); string[] array2 = array; foreach (string text in array2) { string text2 = text.Trim().Trim(new char[1] { '"' }).Trim(new char[1] { '\'' }); string text3 = Normalize(text2); if (!string.IsNullOrWhiteSpace(text3)) { hashSet.Add(text3); } } return hashSet; } private void LogAvailableSuitLikeUnlockables(object startOfRound) { IList unlockablesList = GetUnlockablesList(startOfRound); if (unlockablesList == null) { return; } StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("Available suit-like unlockables: "); for (int i = 0; i < unlockablesList.Count; i++) { object obj = unlockablesList[i]; if (obj == null) { continue; } string unlockableName = GetUnlockableName(obj); if (!string.IsNullOrWhiteSpace(unlockableName)) { string text = unlockableName.ToLowerInvariant(); if (text.Contains("female") || text.Contains("suit") || text.Contains("realman")) { stringBuilder.Append("[").Append(unlockableName).Append(" id=") .Append(i) .Append("] "); } } } Log.LogWarning((object)stringBuilder.ToString()); } private static IList GetUnlockablesList(object startOfRound) { if (startOfRound == null) { return null; } object memberValue = GetMemberValue(startOfRound, startOfRound.GetType(), "unlockablesList"); if (memberValue == null) { return null; } object memberValue2 = GetMemberValue(memberValue, memberValue.GetType(), "unlockables"); return memberValue2 as IList; } private static string GetUnlockableName(object unlockable) { if (unlockable == null) { return null; } return GetMemberValue(unlockable, unlockable.GetType(), "unlockableName")?.ToString(); } private static object FindUnlockableSuitObjectById(int suitId) { Component[] array = Resources.FindObjectsOfTypeAll(); Component[] array2 = array; foreach (Component val in array2) { if ((Object)(object)val == (Object)null) { continue; } Type type = ((object)val).GetType(); if (IsUnlockableSuitType(type)) { int intMember = GetIntMember(val, type, "suitID", -1); if (intMember == suitId) { return val; } } } return null; } private bool InvokeSuitMethod(object target, string methodName, int playerIndex, int suitId, object player) { if (target == null) { return false; } Type type = target.GetType(); MethodInfo[] methods = type.GetMethods(Flags); bool result = false; MethodInfo[] array = methods; foreach (MethodInfo methodInfo in array) { if (!(methodInfo.Name != methodName) && TryBuildMethodArgs(methodInfo, playerIndex, suitId, player, out var args)) { try { methodInfo.Invoke(target, args); result = true; DebugLog("Called " + type.FullName + "." + methodInfo.Name + "(" + ArgsToString(args) + ") for suitID=" + suitId); } catch (Exception ex) { DebugLog("Call failed " + type.FullName + "." + methodInfo.Name + ": " + ShortException(ex)); } } } return result; } private static bool TryBuildMethodArgs(MethodInfo method, int playerIndex, int suitId, object player, out object[] args) { ParameterInfo[] parameters = method.GetParameters(); args = new object[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { ParameterInfo parameterInfo = parameters[i]; Type parameterType = parameterInfo.ParameterType; Type type = Nullable.GetUnderlyingType(parameterType) ?? parameterType; string text = (parameterInfo.Name ?? string.Empty).ToLowerInvariant(); if (player != null && parameterType.IsAssignableFrom(player.GetType())) { args[i] = player; } else if (type == typeof(int)) { if (text.Contains("suit") || text.Contains("unlockable") || i == 1) { args[i] = suitId; } else { args[i] = playerIndex; } } else if (type == typeof(uint)) { if (text.Contains("suit") || text.Contains("unlockable") || i == 1) { args[i] = (uint)Mathf.Max(0, suitId); } else { args[i] = (uint)Mathf.Max(0, playerIndex); } } else if (type == typeof(ulong)) { if (text.Contains("suit") || text.Contains("unlockable") || i == 1) { args[i] = (ulong)Mathf.Max(0, suitId); } else { args[i] = (ulong)Mathf.Max(0, playerIndex); } } else if (type == typeof(bool)) { args[i] = false; } else if (type == typeof(float)) { args[i] = 0f; } else if (parameterType.IsValueType) { args[i] = Activator.CreateInstance(parameterType); } else { args[i] = null; } } return true; } private static void SetPlayerSuitFields(object player, int suitId) { if (player != null) { Type type = player.GetType(); string[] array = new string[6] { "suitID", "suitId", "currentSuitID", "currentSuitId", "syncedSuitID", "syncedSuitId" }; foreach (string name in array) { SetMemberValue(player, type, name, suitId); } } } private static object GetStartOfRound() { Type type = Type.GetType("StartOfRound, Assembly-CSharp"); if (type == null) { return null; } object memberValue = GetMemberValue(null, type, "Instance"); if (memberValue != null) { return memberValue; } memberValue = GetMemberValue(null, type, "instance"); if (memberValue != null) { return memberValue; } Object[] array = Resources.FindObjectsOfTypeAll(type); if (array != null && array.Length != 0) { return array[0]; } return null; } [IteratorStateMachine(typeof(d__38))] private static IEnumerable GetAllPlayerScripts(object startOfRound) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__38(-2) { <>3__startOfRound = startOfRound }; } private static object FindPlayerByClientIdOrIndex(object startOfRound, ulong clientId, int fallbackIndex) { int num = 0; foreach (object allPlayerScript in GetAllPlayerScripts(startOfRound)) { if (GetPlayerClientId(allPlayerScript) == clientId) { return allPlayerScript; } if (fallbackIndex >= 0 && num == fallbackIndex) { return allPlayerScript; } num++; } return null; } private static int GetPlayerIndex(object startOfRound, object player) { if (startOfRound == null || player == null) { return -1; } int num = 0; foreach (object allPlayerScript in GetAllPlayerScripts(startOfRound)) { if (allPlayerScript == player) { return num; } num++; } return -1; } private static bool IsRealPlayer(object player) { if (player == null) { return false; } Type type = player.GetType(); bool boolMember = GetBoolMember(player, type, "isPlayerControlled", fallback: false); bool boolMember2 = GetBoolMember(player, type, "isPlayerDead", fallback: false); return boolMember && !boolMember2; } private static ulong GetPlayerClientId(object player) { if (player == null) { return 0uL; } Type type = player.GetType(); string[] array = new string[3] { "actualClientId", "playerClientId", "clientId" }; foreach (string name in array) { object memberValue = GetMemberValue(player, type, name); if (memberValue != null) { try { return Convert.ToUInt64(memberValue, CultureInfo.InvariantCulture); } catch { } } } return 0uL; } private static bool IsSafeAssignTime(object startOfRound) { if (startOfRound == null) { return false; } if (!IsNetworkActive()) { return false; } if (!NetworkManager.Singleton.IsServer && !NetworkManager.Singleton.IsHost) { return false; } if (!PluginInstanceOnlyAssignInLobby()) { return true; } Type type = startOfRound.GetType(); bool boolMember = GetBoolMember(startOfRound, type, "shipHasLanded", fallback: false); bool boolMember2 = GetBoolMember(startOfRound, type, "shipIsLeaving", fallback: false); bool boolMember3 = GetBoolMember(startOfRound, type, "inShipPhase", fallback: true); return !boolMember && !boolMember2 && boolMember3; } private static bool PluginInstanceOnlyAssignInLobby() { try { Plugin plugin = Object.FindObjectOfType(); return (Object)(object)plugin == (Object)null || plugin.onlyAssignInShipLobby == null || plugin.onlyAssignInShipLobby.Value; } catch { return true; } } private static bool IsNetworkActive() { try { NetworkManager singleton = NetworkManager.Singleton; return (Object)(object)singleton != (Object)null && singleton.IsListening && !singleton.ShutdownInProgress; } catch { return false; } } private static bool IsHostOrServer() { try { NetworkManager singleton = NetworkManager.Singleton; return (Object)(object)singleton != (Object)null && singleton.IsListening && (singleton.IsHost || singleton.IsServer); } catch { return false; } } private static bool IsMenuScene(string sceneName) { if (string.IsNullOrWhiteSpace(sceneName)) { return false; } string text = sceneName.ToLowerInvariant(); return text.Contains("menu") || text.Contains("main"); } private static bool IsUnlockableSuitType(Type type) { if (type == null) { return false; } string text = type.Name ?? string.Empty; string text2 = type.FullName ?? string.Empty; return text.Equals("UnlockableSuit", StringComparison.OrdinalIgnoreCase) || text2.EndsWith(".UnlockableSuit", StringComparison.OrdinalIgnoreCase); } private static string Normalize(string text) { if (string.IsNullOrWhiteSpace(text)) { return string.Empty; } StringBuilder stringBuilder = new StringBuilder(text.Length); foreach (char c in text) { if (char.IsLetterOrDigit(c)) { stringBuilder.Append(char.ToLowerInvariant(c)); } } return stringBuilder.ToString(); } private static object GetMemberValue(object instance, Type type, string name) { if (type == null || string.IsNullOrWhiteSpace(name)) { return null; } try { FieldInfo field = type.GetField(name, Flags); if (field != null) { return field.GetValue(instance); } PropertyInfo property = type.GetProperty(name, Flags); if (property != null && property.GetIndexParameters().Length == 0) { return property.GetValue(instance, null); } } catch { } return null; } private static void SetMemberValue(object instance, Type type, string name, object value) { if (instance == null || type == null || string.IsNullOrWhiteSpace(name)) { return; } try { FieldInfo field = type.GetField(name, Flags); if (field != null) { object value2 = Convert.ChangeType(value, Nullable.GetUnderlyingType(field.FieldType) ?? field.FieldType, CultureInfo.InvariantCulture); field.SetValue(instance, value2); return; } PropertyInfo property = type.GetProperty(name, Flags); if (property != null && property.CanWrite) { object value3 = Convert.ChangeType(value, Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType, CultureInfo.InvariantCulture); property.SetValue(instance, value3, null); } } catch { } } private static int GetIntMember(object instance, Type type, string name, int fallback) { object memberValue = GetMemberValue(instance, type, name); if (memberValue == null) { return fallback; } try { return Convert.ToInt32(memberValue, CultureInfo.InvariantCulture); } catch { return fallback; } } private static bool GetBoolMember(object instance, Type type, string name, bool fallback) { object memberValue = GetMemberValue(instance, type, name); if (memberValue == null) { return fallback; } try { return Convert.ToBoolean(memberValue, CultureInfo.InvariantCulture); } catch { return fallback; } } private static int GetInstanceId(object obj) { Object val = (Object)((obj is Object) ? obj : null); return (val != (Object)null) ? val.GetInstanceID() : 0; } private static string PlayerLabel(object player) { if (player == null) { return ""; } object memberValue = GetMemberValue(player, player.GetType(), "playerUsername"); if (memberValue != null && !string.IsNullOrWhiteSpace(memberValue.ToString())) { return memberValue.ToString(); } Object val = (Object)((player is Object) ? player : null); if (val != (Object)null) { return val.name; } return player.ToString(); } private void DebugLog(string msg) { if (logDebug != null && logDebug.Value) { Log.LogInfo((object)msg); } } private static string ArgsToString(object[] args) { if (args == null) { return string.Empty; } return string.Join(", ", args.Select((object a) => (a == null) ? "null" : a.ToString()).ToArray()); } private static string ShortException(Exception ex) { if (ex == null) { return ""; } while (ex.InnerException != null) { ex = ex.InnerException; } return ex.GetType().Name + ": " + ex.Message; } }