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 DropinMultiplayer v4.2.1
DropInMultiplayer.dll
Decompiled a month agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using DropInMultiplayer.Helpers; using HG.Reflection; using On.RoR2; using R2API.Utils; using RoR2; using UnityEngine; using UnityEngine.Networking; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: OptIn] [assembly: AssemblyTitle("DropInMultiplayer")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("DropInMultiplayer")] [assembly: AssemblyCopyright("Copyright © 2022")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("0321a436-2c1f-4f7b-8a99-becbbb8089d2")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace DropInMultiplayer { public class DropInMultiplayerConfig { private const string DefaultWelcomeMessage = "Hello {username}! Join the game by typing '/join_as {survivor name}' in chat (or '/join_as random'). To get a list of availible survivors, type '/list_survivors' in chat"; public ConfigEntry<bool> AllowRespawn { get; } public ConfigEntry<bool> JoinAsRandomByDefault { get; } public ConfigEntry<bool> AllowJoinAsHiddenSurvivors { get; } public ConfigEntry<bool> AllowJoinAsAllBodies { get; } public ConfigEntry<bool> GiveHereticItems { get; } public ConfigEntry<bool> PreventCaptainScrapAbuse { get; } public ConfigEntry<bool> PreventOperatorDroneAbuse { get; } public ConfigEntry<bool> GiveCatchUpItems { get; } public ConfigEntry<bool> GiveRejoiningPlayersCatchUpItems { get; } public ConfigEntry<bool> GiveCatchUpVoidItems { get; } public ConfigEntry<bool> GiveCatchUpLunarItems { get; } public ConfigEntry<bool> SendWelcomeMessage { get; } public ConfigEntry<string> CustomWelcomeMessage { get; } public DropInMultiplayerConfig(ConfigFile config) { AllowRespawn = config.Bind<bool>("General", "AllowRespawn", true, "When enabled dead players who use the join as command will be immediately respawned"); JoinAsRandomByDefault = config.Bind<bool>("General", "JoinAsRandomByDefault", false, "When enabled newly joined players will be spawned as random survivor by default"); AllowJoinAsHiddenSurvivors = config.Bind<bool>("Survivors", "AllowJoinAsHiddenSurvivors", true, "When enabled allows players to join as hidden characters, e.g. heretic"); AllowJoinAsAllBodies = config.Bind<bool>("General", "AllowJoinAsAllBodies", false, "When enabled using the join as command will attempt to match with any body, e.g. join_as beetle, WARNING: Very Untested!"); GiveHereticItems = config.Bind<bool>("Survivors", "GiveHereticItems", true, "When enabled joining as Heretic will give all 4 Heretic items automatically."); PreventCaptainScrapAbuse = config.Bind<bool>("Survivors", "PreventCaptainScrapAbuse", true, "When enabled Captain will not receive replacement Microbots if it was scrapped or removed."); GiveCatchUpItems = config.Bind<bool>("Items", "GiveCatchUpItems", true, "When enabled players will be given catch up items when joining"); GiveRejoiningPlayersCatchUpItems = config.Bind<bool>("Items", "GiveRejoiningPlayersCatchUpItems", true, "When enabled players who leave and rejoin will be given catchup items, WARNING: Can be exploited by giving all items to one player then leaving and rejoining"); GiveCatchUpVoidItems = config.Bind<bool>("Items", "GiveCatchUpVoidItems", false, "When enabled void items will be dropped when players start (requires GiveCatchUpItems enabled)"); GiveCatchUpLunarItems = config.Bind<bool>("Items", "GiveCatchUpLunarItems", false, "When enabled lunar items will be dropped when players start (requires GiveCatchUpItems enabled)"); SendWelcomeMessage = config.Bind<bool>("Chat Messages", "SendWelcomeMessage", true, "Sends the welcome message when a new player joins."); CustomWelcomeMessage = config.Bind<string>("Chat Messages", "CustomWelcomeMessage", "Hello {username}! Join the game by typing '/join_as {survivor name}' in chat (or '/join_as random'). To get a list of availible survivors, type '/list_survivors' in chat", "Format of welcome message. {username} will be replaced with joining users name, and {survivorlist} will be replaced by list of availible survivors."); } } internal enum JoinAsResult { Success, DeadAndNotAllowRespawn } internal class ChatCommand { public string Name { get; set; } public string HelpText { get; set; } public Func<NetworkUser, string[], string> Handler { get; set; } internal ChatCommand(string name, string helpText, Func<NetworkUser, string[], string> handler) { Name = name; HelpText = helpText; Handler = handler; } } [BepInPlugin("com.niwith.DropInMultiplayer", "Drop In Multiplayer", "4.2.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class DropInMultiplayer : BaseUnityPlugin { [CompilerGenerated] private sealed class <SendChatMessageInternal>d__54 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string message; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <SendChatMessageInternal>d__54(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 1; return true; case 1: <>1__state = -1; Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage { baseToken = message }); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <SpawnPlayerAsRandomInternal>d__50 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public NetworkUser player; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <SpawnPlayerAsRandomInternal>d__50(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_0052: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 1; return true; case 1: <>1__state = -1; SpawnPlayerWithBody(player, BodyCatalog.FindBodyIndex(GetAvailibleSurvivorForPlayerByName(player, "random").bodyPrefab)); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public const string PluginGUID = "com.niwith.DropInMultiplayer"; public const string PluginName = "Drop In Multiplayer"; public const string PluginVersion = "4.2.1"; private const string HelpHelpText = "Usage: help {command}\nDescription: Prints help text for command"; private const string JoinAsHelpText = "Usage: join_as {survivor} {player (optional)}\nDescription: Join in-progress run as the given survivor"; private const string ListSurvivorsHelpText = "Usage: list_survivors {player (optional)}\nDescription: Shows a list of all availible survivors for given player (or self)"; private const string ListBodiesHelpText = "Usage: list_bodies\nDescription: Shows a list of all bodies to be used with join_as command (if AllowJoinAsAllBodies is true)"; private const string CatchupHelpText = "Usage: catchup {player (optional)}\nDescription: Manually adds catch up items for the given player (or self)"; private const string GiveRandomItemsHelpText = "Usage: give_random_items {count} {lunarEnabled} {voidEnabled} {player (optional)}\nDescription: Adds random items for the given player (or self)"; private static readonly Random _rand = new Random(); private static readonly Dictionary<string, ChatCommand> _chatCommands = new List<ChatCommand> { new ChatCommand("HELP", "Usage: help {command}\nDescription: Prints help text for command", Help), new ChatCommand("JOIN", "Usage: join_as {survivor} {player (optional)}\nDescription: Join in-progress run as the given survivor", JoinAs), new ChatCommand("JOIN_AS", "Usage: join_as {survivor} {player (optional)}\nDescription: Join in-progress run as the given survivor", JoinAs), new ChatCommand("LIST_SURVIVORS", "Usage: list_survivors {player (optional)}\nDescription: Shows a list of all availible survivors for given player (or self)", ListSurvivors), new ChatCommand("LIST_BODIES", "Usage: list_bodies\nDescription: Shows a list of all bodies to be used with join_as command (if AllowJoinAsAllBodies is true)", ListBodies) }.ToDictionary((ChatCommand rec) => rec.Name); private static HashSet<Inventory> captainBlacklistInventories; public static DropInMultiplayerConfig DropInConfig { get; set; } public static DropInMultiplayer Instance { get; set; } internal static ManualLogSource Logger { get; set; } public void Awake() { Instance = this; Logger = ((BaseUnityPlugin)this).Logger; DropInConfig = new DropInMultiplayerConfig(((BaseUnityPlugin)this).Config); SetupEventHandlers(); } private static void SetupEventHandlers() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown Run.onRunStartGlobal += Run_onRunStartGlobal; Console.RunCmd += new hook_RunCmd(Console_RunCmd); Run.SetupUserCharacterMaster += new hook_SetupUserCharacterMaster(Run_SetupUserCharacterMaster); NetworkUser.onPostNetworkUserStart += new NetworkUserGenericDelegate(NetworkUser_onPostNetworkUserStart); } private static void Run_onRunStartGlobal(Run run) { captainBlacklistInventories = new HashSet<Inventory>(); } private static void Run_SetupUserCharacterMaster(orig_SetupUserCharacterMaster orig, Run self, NetworkUser user) { try { orig.Invoke(self, user); } catch (Exception ex) { Debug.LogException(ex); Logger.LogError((object)ex); Logger.LogMessage((object)"SetupUserCharacterMaster threw an exception and was caught"); } } private static void Console_RunCmd(orig_RunCmd orig, Console self, CmdSender sender, string concommandName, List<string> userArgs) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) orig.Invoke(self, sender, concommandName, userArgs); if (!NetworkServer.active || (Object)(object)Run.instance == (Object)null || !concommandName.Equals("say", StringComparison.InvariantCultureIgnoreCase)) { return; } string text = userArgs.FirstOrDefault(); if (string.IsNullOrWhiteSpace(text) || !text.StartsWith("/")) { return; } string[] source = text.Split(new char[1] { ' ' }); string text2 = source.FirstOrDefault().Substring(1); string[] arg = source.Skip(1).ToArray(); if (!_chatCommands.TryGetValue(text2.ToUpperInvariant(), out var value)) { SendChatMessage("Unable to find command, try /help"); return; } string text3 = value.Handler(sender.networkUser, arg); if (!string.IsNullOrWhiteSpace(text3)) { SendChatMessage(text3); } } private static void NetworkUser_onPostNetworkUserStart(NetworkUser networkUser) { if (NetworkServer.active && (Object)(object)Run.instance != (Object)null) { bool flag = (Object)(object)networkUser.master != (Object)null; Logger.LogMessage((object)(networkUser.userName + " has joined " + (flag ? "as a previously connected player" : "as a new player"))); GreetNewPlayer(networkUser); if (DropInConfig.JoinAsRandomByDefault.Value && !flag) { Logger.LogMessage((object)"Spawning new player as random, since JoinAsRandomByDefault is true"); ((MonoBehaviour)Instance).StartCoroutine(SpawnPlayerAsRandomInternal(networkUser)); } if (DropInConfig.GiveCatchUpItems.Value && DropInConfig.GiveRejoiningPlayersCatchUpItems.Value && flag) { GiveCatchUpItems(networkUser); } } } private static JoinAsResult SpawnPlayerWithBody(NetworkUser player, BodyIndex newBodyIndex) { //IL_0046: 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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player.master == (Object)null) { Logger.LogMessage((object)$"Spawning new player {player.userName} with bodyIndex = {newBodyIndex}"); return SpawnNewPlayerWithBody(player, newBodyIndex); } Logger.LogMessage((object)$"Respawning existing player {player.userName} with bodyIndex = {newBodyIndex}"); return RespawnExistingPlayerWithBody(player, newBodyIndex); } private static JoinAsResult SpawnNewPlayerWithBody(NetworkUser player, BodyIndex newBodyIndex) { //IL_0001: 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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) player.CmdSetBodyPreference(newBodyIndex); Reflection.SetFieldValue<bool>((object)Run.instance, "allowNewParticipants", true); Run.instance.OnUserAdded(player); Reflection.SetFieldValue<bool>((object)Run.instance, "allowNewParticipants", false); Transform spawnTransformForPlayer = GetSpawnTransformForPlayer(player); player.master.SpawnBody(spawnTransformForPlayer.position, spawnTransformForPlayer.rotation); HandleBodyItems(player, null, BodyCatalog.GetBodyPrefab(newBodyIndex)); if (DropInConfig.GiveCatchUpItems.Value) { GiveCatchUpItems(player); } return JoinAsResult.Success; } private static JoinAsResult RespawnExistingPlayerWithBody(NetworkUser player, BodyIndex newBodyIndex) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: 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) GameObject bodyPrefab = player.master.bodyPrefab; player.CmdSetBodyPreference(newBodyIndex); JoinAsResult result = JoinAsResult.Success; if ((((Object)(object)player.GetCurrentBody() == (Object)null && player.master.lostBodyToDeath) | ((Object)(object)player.GetCurrentBody() != (Object)null && player.GetCurrentBody().isRemoteOp)) && !DropInConfig.AllowRespawn.Value) { Logger.LogMessage((object)$"Unable immediately to spawn {player.userName} with bodyIndex = {newBodyIndex} due to being player being dead and AllowRespawn being set to false"); result = JoinAsResult.DeadAndNotAllowRespawn; } else { player.master.originalBodyPrefab = player.master.bodyPrefab; Transform spawnTransformForPlayer = GetSpawnTransformForPlayer(player); player.master.Respawn(spawnTransformForPlayer.position, spawnTransformForPlayer.rotation, false); } HandleBodyItems(player, bodyPrefab, BodyCatalog.GetBodyPrefab(newBodyIndex)); return result; } private static void HandleBodyItems(NetworkUser player, GameObject oldBodyPrefab, GameObject newBodyPrefab) { string text = null; string text2 = null; try { Inventory inventory = player.master.inventory; text = ((oldBodyPrefab != null) ? ((Object)oldBodyPrefab).name : null); text2 = ((Object)newBodyPrefab).name; switch (text) { case "CaptainBody": if (inventory.GetItemCountPermanent(Items.CaptainDefenseMatrix) <= 0 && DropInConfig.PreventCaptainScrapAbuse.Value) { captainBlacklistInventories.Add(inventory); } if (!captainBlacklistInventories.Contains(inventory)) { inventory.RemoveItemPermanent(Items.CaptainDefenseMatrix, 1); } break; case "HereticBody": if (DropInConfig.GiveHereticItems.Value) { inventory.RemoveItemPermanent(Items.LunarPrimaryReplacement, 1); inventory.RemoveItemPermanent(Items.LunarSecondaryReplacement, 1); inventory.RemoveItemPermanent(Items.LunarSpecialReplacement, 1); inventory.RemoveItemPermanent(Items.LunarUtilityReplacement, 1); } break; case "DroneTechBody": Logger.LogMessage((object)"Removing drones from players swapping off Operator is work in progress"); break; } if (!(text2 == "CaptainBody")) { if (text2 == "HereticBody" && DropInConfig.GiveHereticItems.Value) { inventory.GiveItemPermanent(Items.LunarPrimaryReplacement, 1); inventory.GiveItemPermanent(Items.LunarSecondaryReplacement, 1); inventory.GiveItemPermanent(Items.LunarSpecialReplacement, 1); inventory.GiveItemPermanent(Items.LunarUtilityReplacement, 1); } } else if (!captainBlacklistInventories.Contains(inventory) || !DropInConfig.PreventCaptainScrapAbuse.Value) { inventory.GiveItemPermanent(Items.CaptainDefenseMatrix, 1); } } catch (Exception ex) { Debug.LogException(ex); Logger.LogError((object)ex); Logger.LogMessage((object)("Handling body items for transition from " + (text ?? "none") + " to " + (text2 ?? "none") + " resulted in an exception")); } } private static string Help(NetworkUser sender, string[] args) { if (args.Length > 1) { return "Help requires either 0 or 1 argument"; } if (args.Length == 1) { if (!_chatCommands.TryGetValue(args[0].ToUpperInvariant(), out var value)) { return "Unable to find command, try /help"; } return value.HelpText; } return "Availible Commands: " + string.Join(",", _chatCommands.Values.Select((ChatCommand command) => command.Name.ToLower())); } private static string JoinAs(NetworkUser sender, string[] args) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Invalid comparison between Unknown and I4 //IL_00a5: 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_00a9: Unknown result type (might be due to invalid IL or missing references) if (args.Length != 1 && args.Length != 2) { return "join as requires either 1 or 2 arguments"; } NetworkUser val = ((args.Length == 1) ? sender : GetNetUserFromString(args[1])); if ((Object)(object)val == (Object)null) { return "Unable to find player with given name"; } string text = args[0]; SurvivorDef availibleSurvivorForPlayerByName = GetAvailibleSurvivorForPlayerByName(val, text); BodyIndex val2 = (BodyIndex)(-1); string text2; if ((Object)(object)availibleSurvivorForPlayerByName != (Object)null) { val2 = BodyCatalog.FindBodyIndex(availibleSurvivorForPlayerByName.bodyPrefab); text2 = Language.GetString(availibleSurvivorForPlayerByName.displayNameToken); } else { if (!DropInConfig.AllowJoinAsAllBodies.Value) { return "Unable to find survivor with the given name"; } BodyIndex val3 = BodyCatalog.FindBodyIndexCaseInsensitive(text.EndsWith("Body", StringComparison.InvariantCultureIgnoreCase) ? text : (text + "Body")); if ((int)val3 == -1) { return "Unable to find survivor or body with given name"; } val2 = val3; text2 = BodyCatalog.GetBodyName(val3); } JoinAsResult joinAsResult; try { joinAsResult = SpawnPlayerWithBody(val, val2); } catch (Exception ex) { Debug.LogException(ex); Logger.LogError((object)ex); return "An exception occured spawning " + val.userName + " as " + text2; } return joinAsResult switch { JoinAsResult.Success => "Spawning " + val.userName + " as " + text2, JoinAsResult.DeadAndNotAllowRespawn => val.userName + " will be spawned as " + text2 + " next stage", _ => "Unknown join as result", }; } private static string ListSurvivors(NetworkUser sender, string[] args) { if (args.Length > 1) { return "list survivors requires 0 or 1 argument"; } NetworkUser val = ((args.Length == 0) ? sender : GetNetUserFromString(args[0])); if ((Object)(object)val == (Object)null) { return "Unable to find player with given name"; } return GetSurvivorChatListForPlayer(val); } private static string ListBodies(NetworkUser sender, string[] args) { if (args.Length != 0) { return "list bodies requires no arguments"; } return string.Join(", ", BodyCatalog.allBodyPrefabs.Select((GameObject prefab) => ((Object)prefab).name)); } private static string Transform(NetworkUser sender, string[] args) { if (args.Length > 2 || args.Length == 0) { return "transform requires 1 or 2 arguments"; } NetworkUser val = ((args.Length == 1) ? sender : GetNetUserFromString(args[1])); if ((Object)(object)val == (Object)null) { return "Unable to find player with given name"; } val.master.TransformBody(args[0]); return "Transformed " + sender.userName + " into " + args[0]; } private static string Catchup(NetworkUser sender, string[] args) { if (args.Length != 0 && args.Length != 1) { return "Catchup requires 0 or 1 argument"; } NetworkUser val = ((args.Length == 0) ? sender : GetNetUserFromString(args[0])); if ((Object)(object)val == (Object)null) { return "Unable to find player with given name"; } GiveCatchUpItems(val); return "Gave " + val.userName + " catch up items"; } private static string GiveRandomItems(NetworkUser sender, string[] args) { if (args.Length != 3 && args.Length != 4) { return "Give random items requires 3 or 4 arguments"; } NetworkUser val = ((args.Length == 3) ? sender : GetNetUserFromString(args[3])); if ((Object)(object)val == (Object)null) { return "Unable to find player with given name"; } object obj; if (val == null) { obj = null; } else { CharacterMaster master = val.master; obj = ((master != null) ? master.inventory : null); } if ((Object)obj == (Object)null) { return "Player has no inventory so cannot be given items"; } int num; bool lunarEnabled; bool voidEnabled; try { num = int.Parse(args[0]); lunarEnabled = bool.Parse(args[1]); voidEnabled = bool.Parse(args[2]); } catch { return "Unable to parse arguments"; } GiveRandomItems(val.master.inventory, num, lunarEnabled, voidEnabled); return $"Gave {val.userName} {num} random items"; } [ConCommand(/*Could not decode attribute arguments.*/)] private static void CommandJoinAs(ConCommandArgs args) { //IL_0000: 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) Debug.Log((object)JoinAs(args.sender, args.userArgs.ToArray())); } [ConCommand(/*Could not decode attribute arguments.*/)] private static void CommandShowSurvivors(ConCommandArgs args) { //IL_0000: 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) Debug.Log((object)ListSurvivors(args.sender, args.userArgs.ToArray())); } [ConCommand(/*Could not decode attribute arguments.*/)] private static void CommandListBodies(ConCommandArgs args) { //IL_0000: 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) Debug.Log((object)ListBodies(args.sender, args.userArgs.ToArray())); } private static NetworkUser GetNetUserFromString(string playerString) { if (!string.IsNullOrWhiteSpace(playerString)) { if (int.TryParse(playerString, out var result)) { if (result < NetworkUser.readOnlyInstancesList.Count && result >= 0) { return NetworkUser.readOnlyInstancesList[result]; } return null; } foreach (NetworkUser readOnlyInstances in NetworkUser.readOnlyInstancesList) { if (readOnlyInstances.userName.Replace(" ", "").Equals(playerString.Replace(" ", ""), StringComparison.InvariantCultureIgnoreCase)) { return readOnlyInstances; } } return null; } return null; } public static SurvivorDef[] GetAvailibleSurvivorsForPlayer(NetworkUser player) { return SurvivorCatalog.allSurvivorDefs.Where(SurvivorIsUnlockedAndAvailable).ToArray(); static bool SurvivorIsUnlockedAndAvailable(SurvivorDef survivorDef) { if (!DropInConfig.AllowJoinAsHiddenSurvivors.Value && survivorDef.hidden) { Logger.LogMessage((object)("Survivor " + survivorDef.cachedName + " is not availible because survivor is hidden and AllowJoinAsHiddenSurvivors is false")); return false; } return true; } } public static SurvivorDef GetAvailibleSurvivorForPlayerByName(NetworkUser player, string name) { SurvivorDef[] availibleSurvivorsForPlayer = GetAvailibleSurvivorsForPlayer(player); if (string.Equals(name, "random", StringComparison.InvariantCultureIgnoreCase)) { return availibleSurvivorsForPlayer[_rand.Next(availibleSurvivorsForPlayer.Length)]; } return availibleSurvivorsForPlayer.Where(NameStringMatches).FirstOrDefault(); bool NameStringMatches(SurvivorDef survivorDef) { if (!string.Equals(survivorDef.cachedName, name, StringComparison.InvariantCultureIgnoreCase)) { return string.Equals(Language.GetString(survivorDef.displayNameToken).Replace(" ", ""), name.Replace(" ", ""), StringComparison.InvariantCultureIgnoreCase); } return true; } } private static void GiveCatchUpItems(NetworkUser player) { List<PickupIndex> list = new List<PickupIndex>(); list.AddRange(Run.instance.availableTier1DropList); list.AddRange(Run.instance.availableTier2DropList); list.AddRange(Run.instance.availableTier3DropList); list.AddRange(Run.instance.availableBossDropList); list.AddRange(Run.instance.availableVoidTier1DropList); list.AddRange(Run.instance.availableVoidTier2DropList); list.AddRange(Run.instance.availableVoidTier3DropList); list.AddRange(Run.instance.availableVoidBossDropList); list.AddRange(Run.instance.availableLunarItemDropList); Inventory[] source = (from netUser in NetworkUser.readOnlyInstancesList.Where(delegate(NetworkUser netUser) { if ((Object)(object)netUser != (Object)(object)player) { object obj; if (netUser == null) { obj = null; } else { CharacterMaster master = netUser.master; obj = ((master != null) ? master.inventory : null); } return (Object)obj != (Object)null; } return false; }) select netUser.master.inventory).ToArray(); ItemIndex[] countItemIndexes = list.Select((PickupIndex pickupIndex) => PickupCatalog.GetPickupDef(pickupIndex).itemIndex).ToArray(); int num = (int)((IEnumerable<Inventory>)source).Average((Func<Inventory, int>)CountInventoryItems); int num2 = num - CountInventoryItems(player.master.inventory); Logger.LogMessage((object)$"On average other players have {num} items, giving {player.userName} {num2} items to match"); GiveRandomItems(player.master.inventory, num2, DropInConfig.GiveCatchUpLunarItems.Value, DropInConfig.GiveCatchUpVoidItems.Value); int CountInventoryItems(Inventory inventory) { return countItemIndexes.Sum((ItemIndex itemIndex) => inventory.GetItemCountPermanent(itemIndex)); } } private static void GiveRandomItems(Inventory inventory, int count, bool lunarEnabled, bool voidEnabled) { //IL_00c5: 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_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) if (count <= 0) { return; } WeightedSelection<List<PickupIndex>> val = new WeightedSelection<List<PickupIndex>>(8); val.AddChoice(Run.instance.availableTier1DropList, 100f); val.AddChoice(Run.instance.availableTier2DropList, 60f); val.AddChoice(Run.instance.availableTier3DropList, 4f); if (lunarEnabled) { val.AddChoice(Run.instance.availableLunarItemDropList, 4f); } if (voidEnabled) { val.AddChoice(Run.instance.availableVoidTier1DropList, 4f); val.AddChoice(Run.instance.availableVoidTier2DropList, 2.3999999f); val.AddChoice(Run.instance.availableVoidTier3DropList, 0.16f); } for (int i = 0; i < count; i++) { try { List<PickupIndex> list = val.Evaluate(Random.value); PickupDef pickupDef = PickupCatalog.GetPickupDef(list.ElementAtOrDefault(Random.Range(0, list.Count))); ItemIndex val2 = (ItemIndex)((pickupDef == null) ? (-1) : ((int)pickupDef.itemIndex)); inventory.GiveItemPermanent(val2, 1); } catch (Exception ex) { Debug.LogException(ex); Logger.LogError((object)ex); Logger.LogMessage((object)"Exception occured giving player an item"); } } } private static Transform GetSpawnTransformForPlayer(NetworkUser player) { Transform val = player.GetCurrentBody()?.transform; if ((Object)(object)val == (Object)null) { Logger.LogMessage((object)(player.userName + " does not have a current body, spawning on another player")); NetworkUser? obj = NetworkUser.readOnlyInstancesList.Where((NetworkUser user) => (Object)(object)user.GetCurrentBody() != (Object)null).FirstOrDefault(); val = ((obj != null) ? obj.GetCurrentBody().transform : null); } if ((Object)(object)val == (Object)null) { Logger.LogMessage((object)("Unable to find alive player for " + player.userName + " to spawn on, defaulting to map spawn")); val = Stage.instance.GetPlayerSpawnTransform(); } return val; } [IteratorStateMachine(typeof(<SpawnPlayerAsRandomInternal>d__50))] private static IEnumerator SpawnPlayerAsRandomInternal(NetworkUser player) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <SpawnPlayerAsRandomInternal>d__50(0) { player = player }; } private static string GetSurvivorChatListForPlayer(NetworkUser player) { string[] value = (from survivor in GetAvailibleSurvivorsForPlayer(player) select survivor.cachedName + " (" + Language.GetString(survivor.displayNameToken) + ")").ToArray(); return string.Join(", ", value); } private static void GreetNewPlayer(NetworkUser player) { //IL_0071: 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_0082: Expected O, but got Unknown if (DropInConfig.SendWelcomeMessage.Value) { string value = DropInConfig.CustomWelcomeMessage.Value; if (value.Length > 1000) { Logger.LogMessage((object)$"The custom welcome message has a length of {value.Length} which is longer than the limit of 1000 characters"); return; } string baseToken = value.ReplaceOnce("{username}", player.userName).ReplaceOnce("{survivorlist}", GetSurvivorChatListForPlayer(player)); Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage { baseToken = baseToken }); } } private static void SendChatMessage(string message) { ((MonoBehaviour)Instance).StartCoroutine(SendChatMessageInternal(message)); } [IteratorStateMachine(typeof(<SendChatMessageInternal>d__54))] private static IEnumerator SendChatMessageInternal(string message) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <SendChatMessageInternal>d__54(0) { message = message }; } } } namespace DropInMultiplayer.Helpers { internal class BodyManager { private readonly Run _run; private readonly DropInMultiplayerConfig _config; private static Random _rand = new Random(); internal BodyManager(DropInMultiplayerConfig config, Run run) { _config = config; _run = run; } public SurvivorDef[] GetAvailibleSurvivorsForPlayer(NetworkUser player) { return SurvivorCatalog.allSurvivorDefs.Where(SurvivorIsUnlockedAndAvailable).ToArray(); bool SurvivorIsUnlockedAndAvailable(SurvivorDef survivorDef) { if (_config.AllowJoinAsHiddenSurvivors.Value || !survivorDef.hidden) { if (!survivorDef.CheckRequiredExpansionEnabled((NetworkUser)null)) { return false; } UnlockableDef unlockableDef = survivorDef.unlockableDef; if ((Object)(object)unlockableDef != (Object)null) { return _run.IsUnlockableUnlocked(unlockableDef); } return false; } return false; } } public SurvivorDef GetAvailibleSurvivorForPlayerByName(NetworkUser player, string name) { SurvivorDef[] availibleSurvivorsForPlayer = GetAvailibleSurvivorsForPlayer(player); if (string.Equals(name, "random", StringComparison.InvariantCultureIgnoreCase)) { return availibleSurvivorsForPlayer[_rand.Next(availibleSurvivorsForPlayer.Length)]; } return availibleSurvivorsForPlayer.Where(NameStringMatches).FirstOrDefault(); bool NameStringMatches(SurvivorDef survivorDef) { return string.Equals(survivorDef.cachedName, name); } } } public static class HelperExtensions { public static void SetPrivateFieldValue(this object instance, string fieldName, object value) { instance.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic).SetValue(instance, value); } public static string ReplaceOnce(this string source, string replacetoken, string replacewith) { int num = source.IndexOf(replacetoken); if (num > -1) { return source.Substring(0, num) + replacewith + source.Substring(num + replacetoken.Length); } return source; } } }