using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using DropInMultiplayerPlugin.Helpers;
using Microsoft.CodeAnalysis;
using On.RoR2;
using R2API.Utils;
using RiskOfOptions;
using RiskOfOptions.Options;
using RoR2;
using UnityEngine;
using UnityEngine.Networking;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("DropInMultiplayer")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("DropInMultiplayer")]
[assembly: AssemblyTitle("DropInMultiplayer")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace DropInMultiplayerPlugin
{
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("MengHu.DropInMultiplayerPlugin", "DropInMultiplayerPlugin", "1.0.3")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
public class DropInMultiplayerPlugin : BaseUnityPlugin
{
public const string PluginGUID = "MengHu.DropInMultiplayerPlugin";
public const string PluginAuthor = "MengHu";
public const string PluginName = "DropInMultiplayerPlugin";
public const string PluginVersion = "1.0.3";
public static List<IBasePlugin> basePlugins = new List<IBasePlugin>();
public static byte[] logo;
public static Sprite logo2;
public static DropInMultiplayerPlugin Instance { get; set; }
public static ConfigFile PluginConfig { get; set; }
public void Awake()
{
Instance = this;
Console.OutputEncoding = Encoding.UTF8;
Log.Init(((BaseUnityPlugin)this).Logger);
PluginConfig = ((BaseUnityPlugin)this).Config;
ModSettingsManager.SetModDescription("Describe your mod in incredible detail over the course of the next 2 hours");
SetLogo();
DropInMultiplayer item = new DropInMultiplayer();
basePlugins.Add(item);
InitPlugins();
}
private void InitPlugins()
{
foreach (IBasePlugin basePlugin in basePlugins)
{
basePlugin.Init(PluginConfig);
Log.Info(basePlugin.GetType().Name + " initialized");
}
}
public void OnEnable()
{
foreach (IBasePlugin basePlugin in basePlugins)
{
basePlugin.OnEnable();
}
}
public void OnDisable()
{
foreach (IBasePlugin basePlugin in basePlugins)
{
basePlugin.OnDisable();
}
}
private void Start()
{
foreach (IBasePlugin basePlugin in basePlugins)
{
basePlugin.Start();
}
}
private void Update()
{
foreach (IBasePlugin basePlugin in basePlugins)
{
basePlugin.Update();
}
}
public void OnDestroy()
{
foreach (IBasePlugin basePlugin in basePlugins)
{
basePlugin.OnDestroy();
}
}
private void SetLogo()
{
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
try
{
string path = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "icon");
int num = Random.Range(0, Directory.GetFiles(path).Length);
int num2 = 0;
string[] files = Directory.GetFiles(path);
foreach (string path2 in files)
{
if (num2 == num)
{
logo = File.ReadAllBytes(path2);
}
num2++;
}
Texture2D val = LoadTexture(logo, 256, 256);
logo2 = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0f, 0f), 100f, 1u, (SpriteMeshType)1, new Vector4(0f, 0f, 0f, 0f), true);
ModSettingsManager.SetModIcon(logo2);
}
catch (Exception)
{
}
}
public static Texture2D LoadTexture(byte[] bytes, int width, int height)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Expected O, but got Unknown
Texture2D val = new Texture2D(width, height, (TextureFormat)5, false, false);
ImageConversion.LoadImage(val, bytes);
((Texture)val).filterMode = (FilterMode)0;
return val;
}
private Texture2D LoadTexture(string name)
{
//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_0028: Expected O, but got Unknown
//IL_002a: Expected O, but got Unknown
Texture2D val = new Texture2D(2, 2);
ImageConversion.LoadImage(val, File.ReadAllBytes(Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), name)));
return val;
}
private Sprite LoadTexture()
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Expected O, but got Unknown
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
string path = "icon.png";
Texture2D val = new Texture2D(2, 2);
ImageConversion.LoadImage(val, File.ReadAllBytes(Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), path)));
return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0f, 0f));
}
}
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;
}
}
public class DropInMultiplayer : IBasePlugin
{
[CompilerGenerated]
private sealed class <SendChatMessageInternal>d__43 : 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__43(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__39 : 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__39(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();
}
}
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 void Init(ConfigFile config)
{
DropInConfig = new DropInMultiplayerConfig(config);
SetupEventHandlers();
}
private 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 void Run_onRunStartGlobal(Run obj)
{
captainBlacklistInventories = new HashSet<Inventory>();
}
private void Run_SetupUserCharacterMaster(orig_SetupUserCharacterMaster orig, Run self, NetworkUser user)
{
try
{
orig.Invoke(self, user);
}
catch (Exception ex)
{
Debug.LogException(ex);
Log.Error(ex);
Log.Message("SetupUserCharacterMaster threw an exception and was caught");
}
}
private 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_009e: 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("/"))
{
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");
}
string text3 = value.Handler(sender.networkUser, arg);
if (!string.IsNullOrWhiteSpace(text3))
{
SendChatMessage(text3);
}
}
}
private void NetworkUser_onPostNetworkUserStart(NetworkUser networkUser)
{
if (NetworkServer.active && (Object)(object)Run.instance != (Object)null)
{
bool flag = (Object)(object)networkUser.master != (Object)null;
Log.Message(networkUser.userName + " has joined " + (flag ? "as a previously connected player" : "as a new player"));
GreetNewPlayer(networkUser);
if (DropInConfig.JoinAsRandomByDefault.Value && !flag)
{
Log.Message("Spawning new player as random, since JoinAsRandomByDefault is true");
((MonoBehaviour)DropInMultiplayerPlugin.Instance).StartCoroutine(SpawnPlayerAsRandomInternal(networkUser));
}
if (DropInConfig.GiveCatchUpItems.Value && DropInConfig.GiveRejoiningPlayersCatchUpItems.Value && flag)
{
GiveCatchUpItems(networkUser);
}
}
}
private static JoinAsResult SpawnPlayerWithBody(NetworkUser player, BodyIndex newBodyIndex)
{
//IL_003c: 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_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)player.master == (Object)null)
{
Log.Message($"Spawning new player {player.userName} with bodyIndex = {newBodyIndex}");
return SpawnNewPlayerWithBody(player, newBodyIndex);
}
Log.Message($"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_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: 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_004c: 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 && !DropInConfig.AllowRespawn.Value)
{
Log.Message($"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
{
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;
if (!(text == "CaptainBody"))
{
if (text == "HereticBody" && DropInConfig.GiveHereticItems.Value)
{
inventory.RemoveItem(Items.LunarPrimaryReplacement, 1);
inventory.RemoveItem(Items.LunarSecondaryReplacement, 1);
inventory.RemoveItem(Items.LunarSpecialReplacement, 1);
inventory.RemoveItem(Items.LunarUtilityReplacement, 1);
}
}
else
{
if (inventory.GetItemCount(Items.CaptainDefenseMatrix) <= 0 && DropInConfig.PreventCaptainScrapAbuse.Value)
{
captainBlacklistInventories.Add(inventory);
}
if (!captainBlacklistInventories.Contains(inventory))
{
inventory.RemoveItem(Items.CaptainDefenseMatrix, 1);
}
}
if (!(text2 == "CaptainBody"))
{
if (text2 == "HereticBody" && DropInConfig.GiveHereticItems.Value)
{
inventory.GiveItem(Items.LunarPrimaryReplacement, 1);
inventory.GiveItem(Items.LunarSecondaryReplacement, 1);
inventory.GiveItem(Items.LunarSpecialReplacement, 1);
inventory.GiveItem(Items.LunarUtilityReplacement, 1);
}
}
else if (!captainBlacklistInventories.Contains(inventory) || !DropInConfig.PreventCaptainScrapAbuse.Value)
{
inventory.GiveItem(Items.CaptainDefenseMatrix, 1);
}
}
catch (Exception ex)
{
Debug.LogException(ex);
Log.Error(ex);
Log.Message("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_0166: Unknown result type (might be due to invalid IL or missing references)
//IL_0177: Unknown result type (might be due to invalid IL or missing references)
//IL_017c: Unknown result type (might be due to invalid IL or missing references)
//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
//IL_01b9: 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_01c0: Unknown result type (might be due to invalid IL or missing references)
//IL_01c3: Invalid comparison between Unknown and I4
//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
//IL_01cf: 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";
}
Log.Error("Player " + val.userName + " is attempting to join as " + args[0]);
Log.Error($"Player {val.userName} is attempting to join as GetCurrentBody: {(Object)(object)val.GetCurrentBody() != (Object)null}");
Log.Error($"Player {val.userName} is attempting to join as lostBodyToDeath: {val.master.lostBodyToDeath}");
Log.Error($"Player {val.userName} is attempting to join as hasBody: {val.master.hasBody}");
if (!DropInConfig.RepetitionRespawn.Value)
{
if ((Object)(object)val.GetCurrentBody() != (Object)null)
{
return "Player is already spawned in, cannot use join as";
}
if ((Object)(object)val.master != (Object)null && !val.master.lostBodyToDeath)
{
return "Player is not dead, cannot use join as";
}
if ((Object)(object)val.master != (Object)null && val.master.hasBody)
{
return "Player is not dead, cannot use join as";
}
}
if (DropInConfig.RejoinOnlyAfterDeath.Value && (Object)(object)val.master != (Object)null && !val.master.lostBodyToDeath)
{
return "Player is not dead, cannot use join as";
}
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);
Log.Error(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 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 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 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 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)
{
Log.Message("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);
Log.Message($"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.GetItemCount(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.GiveItem(val2, 1);
}
catch (Exception ex)
{
Debug.LogException(ex);
Log.Error(ex);
Log.Message("Exception occured giving player an item");
}
}
}
private static Transform GetSpawnTransformForPlayer(NetworkUser player)
{
Transform val = player.GetCurrentBody()?.transform;
if ((Object)(object)val == (Object)null)
{
Log.Message(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)
{
Log.Message("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__39))]
private IEnumerator SpawnPlayerAsRandomInternal(NetworkUser player)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <SpawnPlayerAsRandomInternal>d__39(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 void GreetNewPlayer(NetworkUser player)
{
//IL_006c: 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_007d: Expected O, but got Unknown
if (DropInConfig.SendWelcomeMessage.Value)
{
string value = DropInConfig.CustomWelcomeMessage.Value;
if (value.Length > 1000)
{
Log.Message($"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 void SendChatMessage(string message)
{
((MonoBehaviour)DropInMultiplayerPlugin.Instance).StartCoroutine(SendChatMessageInternal(message));
}
[IteratorStateMachine(typeof(<SendChatMessageInternal>d__43))]
private IEnumerator SendChatMessageInternal(string message)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <SendChatMessageInternal>d__43(0)
{
message = message
};
}
}
public class DropInMultiplayerConfig
{
private const string DefaultWelcomeMessage = "你好{username}! 在聊天中输入“/join_as {幸存者姓名}”(或“/join_as random”)加入游戏。要获取可用幸存者的列表,请在聊天中输入“/list_survivors”";
public ConfigEntry<bool> AllowRespawn { get; }
public ConfigEntry<bool> RepetitionRespawn { get; }
public ConfigEntry<bool> RejoinOnlyAfterDeath { 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> 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)
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Expected O, but got Unknown
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Expected O, but got Unknown
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_008a: Expected O, but got Unknown
//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
//IL_00b6: Expected O, but got Unknown
//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
//IL_00e2: 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_0130: Unknown result type (might be due to invalid IL or missing references)
//IL_013a: Expected O, but got Unknown
//IL_015c: Unknown result type (might be due to invalid IL or missing references)
//IL_0166: Expected O, but got Unknown
//IL_0188: Unknown result type (might be due to invalid IL or missing references)
//IL_0192: Expected O, but got Unknown
//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
//IL_01be: Expected O, but got Unknown
//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
//IL_01ea: Expected O, but got Unknown
//IL_020c: Unknown result type (might be due to invalid IL or missing references)
//IL_0216: Expected O, but got Unknown
//IL_0238: Unknown result type (might be due to invalid IL or missing references)
//IL_0242: Expected O, but got Unknown
//IL_0268: Unknown result type (might be due to invalid IL or missing references)
//IL_0272: Expected O, but got Unknown
AllowRespawn = config.Bind<bool>("General", "AllowRespawn", true, "启用后,使用 /join_as 命令的死亡玩家将立即重生");
ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(AllowRespawn));
RepetitionRespawn = config.Bind<bool>("General", "RepetitionRespawn", false, "启用后,玩家可以多次使用 /join_as 命令重新生成");
ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(RepetitionRespawn));
RejoinOnlyAfterDeath = config.Bind<bool>("General", "RejoinOnlyAfterDeath", true, "启用后,玩家只能在死亡后使用 /join_as 命令重新生成");
ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(RejoinOnlyAfterDeath));
JoinAsRandomByDefault = config.Bind<bool>("General", "JoinAsRandomByDefault", false, "启用后,新加入的玩家将默认生成为随机幸存者");
ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(JoinAsRandomByDefault));
AllowJoinAsHiddenSurvivors = config.Bind<bool>("Survivors", "AllowJoinAsHiddenSurvivors", true, "启用后,允许玩家以隐藏角色的身份加入,例如异端");
ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(AllowJoinAsHiddenSurvivors));
AllowJoinAsAllBodies = config.Bind<bool>("General", "AllowJoinAsAllBodies", false, "启用后,使用 /join_as 命令将尝试与任何身体匹配,例如甲虫,警告:非常未经测试join_as!");
ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(AllowJoinAsAllBodies));
GiveHereticItems = config.Bind<bool>("Survivors", "GiveHereticItems", true, "启用后,以异端身份加入将自动获得所有 4 个异端物品。");
ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(GiveHereticItems));
PreventCaptainScrapAbuse = config.Bind<bool>("Survivors", "PreventCaptainScrapAbuse", true, "启用后,如果 船长 被报废或移除,则不会收到替换的微型机器人。");
ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PreventCaptainScrapAbuse));
GiveCatchUpItems = config.Bind<bool>("Items", "GiveCatchUpItems", true, "启用后,玩家将在加入时获得追赶物品");
ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(GiveCatchUpItems));
GiveRejoiningPlayersCatchUpItems = config.Bind<bool>("Items", "GiveRejoiningPlayersCatchUpItems", true, "启用后,离开并重新加入的玩家将获得追赶物品,警告:可以通过将所有物品交给一名玩家,然后离开并重新加入来利用");
ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(GiveRejoiningPlayersCatchUpItems));
GiveCatchUpVoidItems = config.Bind<bool>("Items", "GiveCatchUpVoidItems", false, "启用后,月球物品将在玩家开始时掉落(需要启用 GiveCatchUpItems)");
ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(GiveCatchUpVoidItems));
GiveCatchUpLunarItems = config.Bind<bool>("Items", "GiveCatchUpLunarItems", false, "启用后,月球物品将在玩家开始时掉落(需要启用 GiveCatchUpItems)");
ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(GiveCatchUpLunarItems));
SendWelcomeMessage = config.Bind<bool>("Chat Messages", "SendWelcomeMessage", true, "当新玩家加入时发送欢迎消息。");
ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(SendWelcomeMessage));
CustomWelcomeMessage = config.Bind<string>("Chat Messages", "CustomWelcomeMessage", "你好{username}! 在聊天中输入“/join_as {幸存者姓名}”(或“/join_as random”)加入游戏。要获取可用幸存者的列表,请在聊天中输入“/list_survivors”", "欢迎信息的格式。 {username} 将替换为加入用户名, {survivorlist} 将被可用幸存者名单取代。");
ModSettingsManager.AddOption((BaseOption)new StringInputFieldOption(CustomWelcomeMessage));
}
}
public interface IBasePlugin
{
void Init(ConfigFile config)
{
}
void OnEnable()
{
}
void OnDisable()
{
}
void Start()
{
}
void Update()
{
}
void OnDestroy()
{
}
}
internal static class Log
{
private static ManualLogSource _logSource;
internal static void Init(ManualLogSource logSource)
{
_logSource = logSource;
}
internal static void Debug(object data)
{
_logSource.LogDebug(data);
}
internal static void Error(object data)
{
_logSource.LogError(data);
}
internal static void Fatal(object data)
{
_logSource.LogFatal(data);
}
internal static void Info(object data)
{
_logSource.LogInfo(data);
}
internal static void Message(object data)
{
_logSource.LogMessage(data);
}
internal static void Warning(object data)
{
_logSource.LogWarning(data);
}
}
}
namespace DropInMultiplayerPlugin.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;
}
}
}