using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using HawkNetworking;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using Rewired;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("LargerLobbyMod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1")]
[assembly: AssemblyProduct("LargerLobbyMod")]
[assembly: AssemblyTitle("LargerLobbyMod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace LargerLobbyMod
{
internal static class Jail
{
private static readonly PlayerListFile jailed = new PlayerListFile("LargerLobbyMod.jailed.txt", "# Larger Lobby Mod jail list: platform-user-id|name (one per line)");
internal static string KeyFor(PlayerManagerUI.PersonRow person)
{
if (string.IsNullOrEmpty(person.UserId))
{
return "name:" + person.Name;
}
return person.UserId;
}
internal static bool IsJailed(PlayerManagerUI.PersonRow person)
{
return jailed.Contains(KeyFor(person));
}
internal static List<PlayerListFile.Entry> All()
{
return jailed.All();
}
internal static bool TryGetPosition(out Vector3 position)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
position = Vector3.zero;
string[] array = (Plugin.JailPosition.Value ?? "").Split(',');
if (array.Length != 3)
{
return false;
}
if (!float.TryParse(array[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
{
return false;
}
if (!float.TryParse(array[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2))
{
return false;
}
if (!float.TryParse(array[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result3))
{
return false;
}
position = new Vector3(result, result2, result3);
return true;
}
internal static void SetPosition(Vector3 position)
{
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
Plugin.JailPosition.Value = position.x.ToString("0.0", CultureInfo.InvariantCulture) + "," + position.y.ToString("0.0", CultureInfo.InvariantCulture) + "," + position.z.ToString("0.0", CultureInfo.InvariantCulture);
Plugin.Logger.LogInfo((object)("[Jail] Jail set to " + Format(position)));
}
internal static string Format(Vector3 p)
{
return "X " + p.x.ToString("0.0", CultureInfo.InvariantCulture) + " Y " + p.y.ToString("0.0", CultureInfo.InvariantCulture) + " Z " + p.z.ToString("0.0", CultureInfo.InvariantCulture);
}
internal static string Lock(PlayerManagerUI.PersonRow person)
{
if (!TryGetPosition(out var _))
{
return "Set the jail location first.";
}
jailed.Add(KeyFor(person), person.Name);
Plugin.Logger.LogInfo((object)("[Jail] Jailed '" + person.Name + "'"));
return "Jailed " + person.Name + ".";
}
internal static string Release(PlayerManagerUI.PersonRow person)
{
jailed.Remove(KeyFor(person));
Plugin.Logger.LogInfo((object)("[Jail] Released '" + person.Name + "'"));
if ((Object)(object)person.Controller != (Object)null)
{
Teleporter.Bring(person.Controller, person.Name, 0, 1);
}
return "Released " + person.Name + ".";
}
internal static void Release(PlayerListFile.Entry entry)
{
jailed.Remove(entry.Key);
Plugin.Logger.LogInfo((object)("[Jail] Released '" + entry.Name + "' (not in the world)"));
}
internal static void Enforce(List<PlayerManagerUI.PersonRow> people)
{
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
if (jailed.All().Count == 0 || !TryGetPosition(out var position))
{
return;
}
float num = Mathf.Max(1f, Plugin.JailRadius.Value);
int num2 = 0;
foreach (PlayerManagerUI.PersonRow person in people)
{
if (!((Object)(object)person.Controller == (Object)null) && IsJailed(person))
{
Vector3 val = position + Quaternion.Euler(0f, (float)num2 * 60f, 0f) * Vector3.forward * ((num2 == 0) ? 0f : 1.2f);
num2++;
PlayerCharacter playerCharacter = person.Controller.GetPlayerCharacter();
if (!((Object)(object)playerCharacter == (Object)null) && !Teleporter.IsPending(person.Controller) && !(Vector3.Distance(playerCharacter.GetPlayerPosition(), val) <= num))
{
Teleporter.MoveTo(person.Controller, person.Name, val, Quaternion.identity, quiet: true);
}
}
}
}
}
internal class PlayerListFile
{
internal class Entry
{
public string Key;
public string Name;
}
private readonly string path;
private readonly string header;
private List<Entry> entries;
internal PlayerListFile(string fileName, string header)
{
path = Path.Combine(Paths.ConfigPath, fileName);
this.header = header;
}
internal List<Entry> All()
{
if (entries != null)
{
return entries;
}
entries = new List<Entry>();
try
{
if (File.Exists(path))
{
string[] array = File.ReadAllLines(path);
foreach (string text in array)
{
if (text.Trim().Length != 0 && !text.StartsWith("#"))
{
int num = text.IndexOf('|');
entries.Add((num < 0) ? new Entry
{
Key = text.Trim(),
Name = text.Trim()
} : new Entry
{
Key = text.Substring(0, num).Trim(),
Name = text.Substring(num + 1).Trim()
});
}
}
}
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("Couldn't read " + Path.GetFileName(path) + ": " + ex.Message));
}
return entries;
}
internal bool Contains(string key)
{
return All().Exists((Entry e) => e.Key == key);
}
internal void Add(string key, string name)
{
if (!Contains(key))
{
All().Add(new Entry
{
Key = key,
Name = name
});
Save();
}
}
internal void Remove(string key)
{
All().RemoveAll((Entry e) => e.Key == key);
Save();
}
private void Save()
{
try
{
List<string> list = new List<string> { header };
foreach (Entry entry in entries)
{
list.Add(entry.Key + "|" + entry.Name);
}
File.WriteAllLines(path, list);
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("Couldn't save " + Path.GetFileName(path) + ": " + ex.Message));
}
}
}
public class PlayerManagerUI : MonoBehaviour
{
internal class DeviceRow
{
public HawkConnection Connection;
public int Id;
public string Name;
public string Platform;
public bool IsHost;
public readonly List<PersonRow> People = new List<PersonRow>();
}
internal class PersonRow
{
public string Name;
public string UserId;
public CrossPlayPlatform Platform;
public PlayerController Controller;
}
internal static class Bans
{
private static readonly PlayerListFile file = new PlayerListFile("LargerLobbyMod.bans.txt", "# Larger Lobby Mod ban list: platform-user-id|name (one per line)");
internal static List<PlayerListFile.Entry> All()
{
return file.All();
}
internal static void Add(DeviceRow row)
{
bool flag = false;
foreach (PersonRow person in row.People)
{
if (!string.IsNullOrEmpty(person.UserId))
{
file.Add(person.UserId, person.Name);
flag = true;
}
}
if (!flag)
{
file.Add("name:" + row.Name, row.Name);
}
Plugin.Logger.LogInfo((object)("[Ban] Banned '" + row.Name + "'"));
}
internal static void Remove(string key)
{
file.Remove(key);
}
internal static string FindMatch(DeviceRow row)
{
if (file.All().Count == 0)
{
return null;
}
foreach (PersonRow person in row.People)
{
if (!string.IsNullOrEmpty(person.UserId) && file.Contains(person.UserId))
{
return "id " + person.UserId;
}
}
if (file.Contains("name:" + row.Name))
{
return "name " + row.Name;
}
return null;
}
}
private const int MaxLocalPlayersPerDevice = 4;
private const float ScanInterval = 1f;
private bool open;
private bool savedCursorVisible;
private CursorLockMode savedCursorLock;
private Vector2 scroll;
private Vector2 bannedScroll;
private string search = "";
private string announceText = "";
private string pendingAnnouncement;
private bool confirming;
private float nextAnnounceAllowed;
private bool inputBlocked;
private bool savedKeyboardEnabled;
private bool savedMouseEnabled;
private const int MaxAnnouncementLength = 150;
private const int MaxAnnouncementCopies = 15;
private string announceCurrent;
private int announceCopiesLeft;
private float announceInterval;
private float nextCopyTime;
private float nextScan;
private readonly List<DeviceRow> rows = new List<DeviceRow>();
private readonly Dictionary<int, float> recentlyKicked = new Dictionary<int, float>();
private readonly HashSet<string> loggedErrors = new HashSet<string>();
private string status = "";
private int tab;
private Vector2 teleportScroll;
private Vector2 jailScroll;
private bool confirmingBringAll;
private static readonly Il2CppReferenceArray<GUILayoutOption> NoOptions = new Il2CppReferenceArray<GUILayoutOption>(0L);
public PlayerManagerUI(IntPtr ptr)
: base(ptr)
{
}
private void Update()
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
try
{
if (Input.GetKeyDown(Plugin.PlayerManagerKey.Value))
{
Toggle();
}
}
catch (Exception e)
{
LogOnce("input", e);
}
try
{
UpdateAnnouncement();
}
catch (Exception e2)
{
announceCopiesLeft = 0;
LogOnce("announce", e2);
}
try
{
Teleporter.Tick();
}
catch (Exception e3)
{
LogOnce("teleport", e3);
}
if (Time.unscaledTime < nextScan)
{
return;
}
nextScan = Time.unscaledTime + 1f;
try
{
Refresh();
}
catch (Exception e4)
{
LogOnce("refresh", e4);
}
}
private void Toggle()
{
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
open = !open;
status = "";
if (open)
{
savedCursorVisible = Cursor.visible;
savedCursorLock = Cursor.lockState;
}
else
{
Cursor.visible = savedCursorVisible;
Cursor.lockState = savedCursorLock;
confirming = false;
pendingAnnouncement = null;
confirmingBringAll = false;
}
SetGameInputBlocked(open);
Plugin.Logger.LogInfo((object)("[PlayerManager] " + (open ? "opened" : "closed")));
}
private void SetGameInputBlocked(bool block)
{
try
{
if (block != inputBlocked && (!block || Plugin.PlayerManagerBlockInput.Value) && ReInput.isReady)
{
ControllerHelper controllers = ReInput.controllers;
if (block)
{
savedKeyboardEnabled = ((Controller)controllers.Keyboard).enabled;
savedMouseEnabled = ((Controller)controllers.Mouse).enabled;
((Controller)controllers.Keyboard).enabled = false;
((Controller)controllers.Mouse).enabled = false;
}
else
{
((Controller)controllers.Keyboard).enabled = savedKeyboardEnabled;
((Controller)controllers.Mouse).enabled = savedMouseEnabled;
}
inputBlocked = block;
}
}
catch (Exception e)
{
LogOnce("input-block", e);
}
}
private void TrySendAnnouncement()
{
string text = (announceText ?? "").Trim();
if (text.Length == 0)
{
status = "Type a message first.";
return;
}
if (text.Length > 150)
{
text = text.Substring(0, 150);
}
if (Time.unscaledTime < nextAnnounceAllowed)
{
status = "The last announcement is still showing. Wait " + Mathf.CeilToInt(nextAnnounceAllowed - Time.unscaledTime) + " more seconds.";
return;
}
pendingAnnouncement = text;
confirming = true;
}
private void SendAnnouncement(string text)
{
if ((Object)(object)Object.FindObjectOfType<NotificationManager>() == (Object)null)
{
status = "Can't send: the game's notification system wasn't found.";
return;
}
float num = NotificationManager.PromptShowTime;
if (num <= 0.5f)
{
num = 3f;
}
float num2 = num + 0.5f;
float num3 = Mathf.Max(num2, Plugin.AnnouncementInterval.Value);
int num4 = Mathf.Clamp(Mathf.FloorToInt((Plugin.AnnouncementSeconds.Value - num2) / num3) + 1, 1, 15);
announceCurrent = text;
announceCopiesLeft = num4;
announceInterval = num3;
nextCopyTime = Time.unscaledTime;
nextAnnounceAllowed = Time.unscaledTime + (float)(num4 - 1) * num3 + num2;
announceText = "";
status = "";
Plugin.Logger.LogInfo((object)("[Announce] Sending x" + num4 + ", one every " + num3 + "s (banner time " + num + "s): " + text));
}
private void UpdateAnnouncement()
{
if (announceCopiesLeft > 0 && !(Time.unscaledTime < nextCopyTime))
{
HawkNetworkManager defaultInstance = HawkNetworkManager.DefaultInstance;
NotificationManager val = Object.FindObjectOfType<NotificationManager>();
if ((Object)(object)defaultInstance == (Object)null || !defaultInstance.IsServer() || (Object)(object)val == (Object)null)
{
announceCopiesLeft = 0;
return;
}
val.ServerQueuePrompt(announceCurrent);
announceCopiesLeft--;
nextCopyTime = Time.unscaledTime + announceInterval;
}
}
private void DrawConfirm()
{
GUILayout.Space(10f);
GUILayout.Label("Send this to everyone in your world?", NoOptions);
GUILayout.Space(6f);
GUILayout.Label("\"" + pendingAnnouncement + "\"", NoOptions);
GUILayout.Space(10f);
GUILayout.BeginHorizontal(NoOptions);
if (GUILayout.Button("Back", Width(100f)))
{
confirming = false;
pendingAnnouncement = null;
status = "Announcement not sent.";
}
GUILayout.FlexibleSpace();
if (GUILayout.Button("Confirm", Width(100f)))
{
confirming = false;
string text = pendingAnnouncement;
pendingAnnouncement = null;
if (text != null)
{
SendAnnouncement(text);
}
}
GUILayout.EndHorizontal();
}
private void Refresh()
{
//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
rows.Clear();
HawkNetworkManager defaultInstance = HawkNetworkManager.DefaultInstance;
if ((Object)(object)defaultInstance == (Object)null || !defaultInstance.IsServer())
{
return;
}
GameInstance val = (UnitySingleton<GameInstance>.InstanceExists ? UnitySingleton<GameInstance>.Instance : null);
List<HawkConnection> players = defaultInstance.GetPlayers();
if (players == null)
{
return;
}
for (int i = 0; i < players.Count; i++)
{
HawkConnection val2 = players[i];
if (val2 == null)
{
continue;
}
DeviceRow deviceRow = new DeviceRow
{
Connection = val2,
Id = val2.Id,
Name = val2.Name,
Platform = val2.Platform,
IsHost = (val2.IsHost || val2.Me)
};
if ((Object)(object)val != (Object)null)
{
for (int j = 0; j < 4; j++)
{
PlayerController val3 = null;
try
{
val3 = val.GetPlayerController(val2, j);
}
catch
{
}
if (!((Object)(object)val3 == (Object)null))
{
deviceRow.People.Add(new PersonRow
{
Name = val3.GetPlayerName(),
UserId = val3.PlatformUserId,
Platform = val3.GetCrossPlayPlatform(),
Controller = val3
});
}
}
}
rows.Add(deviceRow);
EnforceBan(deviceRow);
}
if (Plugin.JailEnabled.Value)
{
Jail.Enforce(OtherPeople());
}
}
private void EnforceBan(DeviceRow row)
{
if (!row.IsHost)
{
string text = Bans.FindMatch(row);
if (text != null && (!recentlyKicked.TryGetValue(row.Id, out var value) || !(Time.unscaledTime < value)))
{
recentlyKicked[row.Id] = Time.unscaledTime + 5f;
Plugin.Logger.LogWarning((object)("[Ban] Kicking banned player '" + row.Name + "' (" + text + ")"));
Kick(row);
}
}
}
private void Kick(DeviceRow row)
{
if (!row.IsHost)
{
WobblyNetworkManager val = (WobblyNetworkManager.InstanceExists ? WobblyNetworkManager.Instance : null);
if ((Object)(object)val == (Object)null)
{
status = "Can't kick: network manager not found.";
return;
}
val.KickPlayer(row.Connection);
Plugin.Logger.LogInfo((object)("[PlayerManager] Kicked '" + row.Name + "' (connection " + row.Id + ")"));
status = "Kicked " + row.Name;
}
}
private void ShowProfile(PersonRow person)
{
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: Invalid comparison between Unknown and I4
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Invalid comparison between Unknown and I4
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Invalid comparison between Unknown and I4
string text = null;
if (((int)person.Platform == 5 || (int)person.Platform == 8) && !string.IsNullOrEmpty(person.Name))
{
text = "https://www.xbox.com/en-US/play/user/" + Uri.EscapeDataString(person.Name);
}
else if ((int)person.Platform == 3 && IsSteamId(person.UserId))
{
text = "https://steamcommunity.com/profiles/" + person.UserId;
}
if (text == null)
{
status = "No profile page for " + person.Name + " (" + ((object)Unsafe.As<CrossPlayPlatform, CrossPlayPlatform>(ref person.Platform)/*cast due to .constrained prefix*/).ToString() + ").";
Plugin.Logger.LogInfo((object)("[PlayerManager] No profile page for '" + person.Name + "', platform " + ((object)Unsafe.As<CrossPlayPlatform, CrossPlayPlatform>(ref person.Platform)/*cast due to .constrained prefix*/).ToString() + ", id '" + person.UserId + "'"));
}
else
{
Application.OpenURL(text);
status = "Opened " + person.Name + "'s profile in your web browser.";
Plugin.Logger.LogInfo((object)("[PlayerManager] Opened profile page for '" + person.Name + "' (" + ((object)Unsafe.As<CrossPlayPlatform, CrossPlayPlatform>(ref person.Platform)/*cast due to .constrained prefix*/).ToString() + ")"));
}
}
private static bool IsSteamId(string id)
{
if (string.IsNullOrEmpty(id) || id.Length != 17 || !id.StartsWith("7656119"))
{
return false;
}
foreach (char c in id)
{
if (c < '0' || c > '9')
{
return false;
}
}
return true;
}
private bool MatchesSearch(string text)
{
if (search.Length != 0)
{
if (text != null)
{
return text.IndexOf(search.Trim(), StringComparison.OrdinalIgnoreCase) >= 0;
}
return false;
}
return true;
}
private bool MatchesSearch(DeviceRow row)
{
if (MatchesSearch(row.Name))
{
return true;
}
foreach (PersonRow person in row.People)
{
if (MatchesSearch(person.Name))
{
return true;
}
}
return false;
}
private void OnGUI()
{
try
{
if (!open)
{
DrawHint();
return;
}
Cursor.visible = true;
Cursor.lockState = (CursorLockMode)0;
DrawPanel();
}
catch (Exception e)
{
LogOnce("gui", e);
}
}
private void DrawHint()
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: 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)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
if (Plugin.PlayerManagerShowHint.Value)
{
Color color = GUI.color;
GUI.color = new Color(1f, 1f, 1f, 0.7f);
if (GUI.Button(new Rect(8f, 8f, 230f, 24f), "Press " + ((object)Plugin.PlayerManagerKey.Value/*cast due to .constrained prefix*/).ToString() + " for Player Manager"))
{
Toggle();
}
GUI.color = color;
}
}
private void DrawPanel()
{
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
//IL_0148: Unknown result type (might be due to invalid IL or missing references)
//IL_014d: Unknown result type (might be due to invalid IL or missing references)
//IL_04fa: Unknown result type (might be due to invalid IL or missing references)
//IL_0506: Unknown result type (might be due to invalid IL or missing references)
//IL_050b: Unknown result type (might be due to invalid IL or missing references)
//IL_07d8: Unknown result type (might be due to invalid IL or missing references)
//IL_07e4: Unknown result type (might be due to invalid IL or missing references)
//IL_07e9: Unknown result type (might be due to invalid IL or missing references)
float num = Mathf.Min(620f, (float)Screen.width - 40f);
float num2 = Mathf.Min(700f, (float)Screen.height - 40f);
Rect val = default(Rect);
((Rect)(ref val))..ctor(20f, 20f, num, num2);
GUI.Box(val, "");
GUILayout.BeginArea(new Rect(((Rect)(ref val)).x + 10f, ((Rect)(ref val)).y + 10f, ((Rect)(ref val)).width - 20f, ((Rect)(ref val)).height - 20f));
HawkNetworkManager defaultInstance = HawkNetworkManager.DefaultInstance;
if ((Object)(object)defaultInstance == (Object)null || !defaultInstance.IsServer())
{
GUILayout.Label("Player Manager (" + ((object)Plugin.PlayerManagerKey.Value/*cast due to .constrained prefix*/).ToString() + " to close)", NoOptions);
GUILayout.Label("Only works while you are hosting.", NoOptions);
GUILayout.EndArea();
return;
}
int num3 = 0;
foreach (DeviceRow row in rows)
{
num3 += Math.Max(1, row.People.Count);
}
GUILayout.Label("Player Manager (" + ((object)Plugin.PlayerManagerKey.Value/*cast due to .constrained prefix*/).ToString() + " to close) Devices: " + rows.Count + " People: " + num3 + " Max: " + defaultInstance.GetMaxPlayerCount(), NoOptions);
GUILayout.BeginHorizontal(NoOptions);
GUILayout.Label("Search:", Width(55f));
float num4 = ((Rect)(ref val)).width - 20f;
search = GUILayout.TextField(search ?? "", Width(num4 - 55f - 60f - 20f));
if (GUILayout.Button("Clear", Width(60f)))
{
search = "";
}
GUILayout.EndHorizontal();
if (Plugin.AnnouncementsEnabled.Value)
{
GUILayout.BeginHorizontal(NoOptions);
GUILayout.Label("Announce:", Width(70f));
announceText = GUILayout.TextField(announceText ?? "", 150, Width(num4 - 70f - 60f - 20f));
if (GUILayout.Button("Send", Width(60f)))
{
TrySendAnnouncement();
}
GUILayout.EndHorizontal();
}
GUILayout.Label((status.Length > 0) ? status : " ", NoOptions);
if (confirming)
{
DrawConfirm();
GUILayout.EndArea();
return;
}
if (confirmingBringAll)
{
DrawBringAllConfirm();
GUILayout.EndArea();
return;
}
float num5 = ((Rect)(ref val)).height - 20f - (Plugin.AnnouncementsEnabled.Value ? 150f : 120f);
if (Plugin.TeleportEnabled.Value || Plugin.JailEnabled.Value)
{
GUILayout.BeginHorizontal(NoOptions);
if (GUILayout.Button((tab == 0) ? "[ Players ]" : "Players", Width(110f)))
{
tab = 0;
}
if (Plugin.TeleportEnabled.Value && GUILayout.Button((tab == 1) ? "[ Teleport ]" : "Teleport", Width(110f)))
{
tab = 1;
}
if (Plugin.JailEnabled.Value && GUILayout.Button((tab == 2) ? "[ Jail ]" : "Jail", Width(110f)))
{
tab = 2;
}
GUILayout.EndHorizontal();
num5 -= 30f;
if (tab == 1 && Plugin.TeleportEnabled.Value)
{
DrawTeleportTab(num5);
GUILayout.EndArea();
return;
}
if (tab == 2 && Plugin.JailEnabled.Value)
{
DrawJailTab(num5);
GUILayout.EndArea();
return;
}
}
DeviceRow[] array = rows.ToArray();
PlayerListFile.Entry[] array2 = Bans.All().ToArray();
DeviceRow[] array3 = Array.FindAll(array, (DeviceRow r) => MatchesSearch(r));
PlayerListFile.Entry[] array4 = Array.FindAll(array2, (PlayerListFile.Entry b) => MatchesSearch(b.Name) || MatchesSearch(b.Key));
float num6 = ((array2.Length != 0) ? (num5 * 0.6f) : num5);
float h = num5 - num6;
GUILayout.Label("In your world (" + array3.Length + ((array3.Length != array.Length) ? (" of " + array.Length) : "") + ")", NoOptions);
scroll = GUILayout.BeginScrollView(scroll, Height(num6));
DeviceRow[] array5 = array3;
foreach (DeviceRow deviceRow in array5)
{
bool flag = deviceRow.People.Count <= 1;
PersonRow personRow = ((deviceRow.People.Count == 1) ? deviceRow.People[0] : null);
GUILayout.BeginHorizontal(NoOptions);
string text = ((personRow != null) ? personRow.Name : deviceRow.Name);
string text2 = (flag ? "" : (" " + deviceRow.People.Count + " players"));
GUILayout.Label((deviceRow.IsHost ? "[You] " : "") + text + " (" + deviceRow.Platform + ")" + text2, NoOptions);
GUILayout.FlexibleSpace();
if (!deviceRow.IsHost)
{
if (personRow != null && Plugin.PlayerManagerProfileButton.Value && GUILayout.Button("Profile", Width(70f)))
{
ShowProfile(personRow);
}
if (GUILayout.Button("Kick", Width(60f)))
{
Kick(deviceRow);
}
if (GUILayout.Button("Ban", Width(60f)))
{
Bans.Add(deviceRow);
status = "Banned " + deviceRow.Name;
Kick(deviceRow);
}
}
GUILayout.EndHorizontal();
if (flag)
{
continue;
}
foreach (PersonRow person in deviceRow.People)
{
GUILayout.BeginHorizontal(NoOptions);
GUILayout.Label(" " + person.Name + " (" + ((object)Unsafe.As<CrossPlayPlatform, CrossPlayPlatform>(ref person.Platform)/*cast due to .constrained prefix*/).ToString() + ")", NoOptions);
GUILayout.FlexibleSpace();
if (!deviceRow.IsHost && Plugin.PlayerManagerProfileButton.Value && GUILayout.Button("Profile", Width(70f)))
{
ShowProfile(person);
}
GUILayout.EndHorizontal();
}
}
GUILayout.EndScrollView();
if (array2.Length != 0)
{
GUILayout.Label("Banned (" + array4.Length + ((array4.Length != array2.Length) ? (" of " + array2.Length) : "") + ")", NoOptions);
bannedScroll = GUILayout.BeginScrollView(bannedScroll, Height(h));
PlayerListFile.Entry[] array6 = array4;
foreach (PlayerListFile.Entry entry in array6)
{
GUILayout.BeginHorizontal(NoOptions);
GUILayout.Label(" " + entry.Name, NoOptions);
GUILayout.FlexibleSpace();
if (GUILayout.Button("Unban", Width(70f)))
{
Bans.Remove(entry.Key);
status = "Unbanned " + entry.Name;
}
GUILayout.EndHorizontal();
}
GUILayout.EndScrollView();
}
GUILayout.EndArea();
}
private List<PersonRow> OtherPeople()
{
List<PersonRow> list = new List<PersonRow>();
DeviceRow[] array = rows.ToArray();
foreach (DeviceRow deviceRow in array)
{
if (deviceRow.IsHost)
{
continue;
}
foreach (PersonRow person in deviceRow.People)
{
if ((Object)(object)person.Controller != (Object)null)
{
list.Add(person);
}
}
}
return list;
}
private void DrawTeleportTab(float listHeight)
{
//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
List<PersonRow> list = OtherPeople();
List<PersonRow> list2 = list.FindAll((PersonRow p) => MatchesSearch(p.Name));
GUILayout.BeginHorizontal(NoOptions);
GUILayout.Label("Players (" + list2.Count + ((list2.Count != list.Count) ? (" of " + list.Count) : "") + ")", NoOptions);
GUILayout.FlexibleSpace();
if (GUILayout.Button("Bring everyone to me", Width(170f)))
{
if (list.Count == 0)
{
status = "There's nobody else in your world.";
}
else
{
confirmingBringAll = true;
}
}
GUILayout.EndHorizontal();
teleportScroll = GUILayout.BeginScrollView(teleportScroll, Height(listHeight - 30f));
foreach (PersonRow item in list2)
{
GUILayout.BeginHorizontal(NoOptions);
GUILayout.Label(item.Name + " (" + ((object)Unsafe.As<CrossPlayPlatform, CrossPlayPlatform>(ref item.Platform)/*cast due to .constrained prefix*/).ToString() + ")", NoOptions);
GUILayout.FlexibleSpace();
if (GUILayout.Button("Go to", Width(70f)))
{
status = Teleporter.GoTo(item.Controller, item.Name);
}
if (GUILayout.Button("Bring here", Width(90f)))
{
status = Teleporter.Bring(item.Controller, item.Name, 0, 1);
}
GUILayout.EndHorizontal();
}
GUILayout.EndScrollView();
}
private void DrawJailTab(float listHeight)
{
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
//IL_0107: Unknown result type (might be due to invalid IL or missing references)
//IL_010c: Unknown result type (might be due to invalid IL or missing references)
//IL_012c: Unknown result type (might be due to invalid IL or missing references)
//IL_012d: Unknown result type (might be due to invalid IL or missing references)
//IL_0132: Unknown result type (might be due to invalid IL or missing references)
//IL_0152: Unknown result type (might be due to invalid IL or missing references)
//IL_0153: Unknown result type (might be due to invalid IL or missing references)
//IL_015d: Unknown result type (might be due to invalid IL or missing references)
//IL_0162: Unknown result type (might be due to invalid IL or missing references)
//IL_0183: Unknown result type (might be due to invalid IL or missing references)
//IL_0274: Unknown result type (might be due to invalid IL or missing references)
//IL_0285: Unknown result type (might be due to invalid IL or missing references)
//IL_028a: Unknown result type (might be due to invalid IL or missing references)
PlayerCharacter val = Teleporter.HostCharacter();
Vector3 position;
bool flag = Jail.TryGetPosition(out position);
GUILayout.Label("Your position: " + (((Object)(object)val != (Object)null) ? Jail.Format(val.GetPlayerPosition()) : "(no character)"), NoOptions);
GUILayout.Label("Jail: " + (flag ? Jail.Format(position) : "not set yet"), NoOptions);
GUILayout.BeginHorizontal(NoOptions);
if (GUILayout.Button("Set jail at my position", Width(170f)))
{
if ((Object)(object)val == (Object)null)
{
status = "Your character isn't spawned right now.";
}
else
{
Jail.SetPosition(val.GetPlayerPosition());
status = "Jail set to your position.";
}
}
if (flag)
{
if (GUILayout.Button("Up 1m", Width(60f)))
{
Jail.SetPosition(position + Vector3.up);
}
if (GUILayout.Button("Up 5m", Width(60f)))
{
Jail.SetPosition(position + Vector3.up * 5f);
}
if (GUILayout.Button("Down 1m", Width(70f)))
{
Jail.SetPosition(position - Vector3.up);
}
if (GUILayout.Button("Down 5m", Width(70f)))
{
Jail.SetPosition(position - Vector3.up * 5f);
}
if (GUILayout.Button("Go to jail", Width(90f)))
{
status = Teleporter.GoToPoint(position, "the jail");
}
}
GUILayout.EndHorizontal();
List<PersonRow> list = OtherPeople();
List<PersonRow> list2 = list.FindAll((PersonRow p) => MatchesSearch(p.Name));
HashSet<string> presentKeys = new HashSet<string>();
foreach (PersonRow item in list)
{
presentKeys.Add(Jail.KeyFor(item));
}
List<PlayerListFile.Entry> list3 = Jail.All().FindAll((PlayerListFile.Entry e) => !presentKeys.Contains(e.Key) && (MatchesSearch(e.Name) || MatchesSearch(e.Key)));
GUILayout.Label("Players (" + list2.Count + ((list2.Count != list.Count) ? (" of " + list.Count) : "") + ")", NoOptions);
jailScroll = GUILayout.BeginScrollView(jailScroll, Height(listHeight - 110f));
foreach (PersonRow item2 in list2)
{
bool flag2 = Jail.IsJailed(item2);
GUILayout.BeginHorizontal(NoOptions);
GUILayout.Label(item2.Name + " (" + ((object)Unsafe.As<CrossPlayPlatform, CrossPlayPlatform>(ref item2.Platform)/*cast due to .constrained prefix*/).ToString() + ")" + (flag2 ? " [In jail]" : ""), NoOptions);
GUILayout.FlexibleSpace();
if (flag2)
{
if (GUILayout.Button("Release", Width(80f)))
{
status = Jail.Release(item2);
}
}
else if (GUILayout.Button("Jail", Width(80f)))
{
status = Jail.Lock(item2);
}
GUILayout.EndHorizontal();
}
PlayerListFile.Entry[] array = list3.ToArray();
foreach (PlayerListFile.Entry entry in array)
{
GUILayout.BeginHorizontal(NoOptions);
GUILayout.Label(entry.Name + " (not here, still jailed)", NoOptions);
GUILayout.FlexibleSpace();
if (GUILayout.Button("Release", Width(80f)))
{
Jail.Release(entry);
status = "Released " + entry.Name + ".";
}
GUILayout.EndHorizontal();
}
GUILayout.EndScrollView();
GUILayout.Label("Jailed players are pulled back if they get more than " + Plugin.JailRadius.Value.ToString("0") + "m from the jail. Release brings them to you.", NoOptions);
}
private void DrawBringAllConfirm()
{
int count = OtherPeople().Count;
GUILayout.Space(10f);
GUILayout.Label("Teleport all " + count + " players to you?", NoOptions);
GUILayout.Space(6f);
GUILayout.Label("Everyone will be pulled away from whatever they're doing, including vehicles, jobs and missions.", NoOptions);
GUILayout.Space(10f);
GUILayout.BeginHorizontal(NoOptions);
if (GUILayout.Button("Back", Width(100f)))
{
confirmingBringAll = false;
status = "Nobody was teleported.";
}
GUILayout.FlexibleSpace();
if (GUILayout.Button("Confirm", Width(100f)))
{
confirmingBringAll = false;
List<PersonRow> list = OtherPeople();
for (int i = 0; i < list.Count; i++)
{
Teleporter.Bring(list[i].Controller, list[i].Name, i, list.Count);
}
status = "Teleporting " + list.Count + " players to you.";
Plugin.Logger.LogInfo((object)("[Teleport] Bringing everyone (" + list.Count + ") to the host"));
}
GUILayout.EndHorizontal();
}
private static Il2CppReferenceArray<GUILayoutOption> Width(float w)
{
return new Il2CppReferenceArray<GUILayoutOption>(1L) { [0] = GUILayout.Width(w) };
}
private static Il2CppReferenceArray<GUILayoutOption> Height(float h)
{
return new Il2CppReferenceArray<GUILayoutOption>(1L) { [0] = GUILayout.Height(Mathf.Max(60f, h)) };
}
private void LogOnce(string where, Exception e)
{
if (loggedErrors.Add(where + e.GetType().Name))
{
Plugin.Logger.LogError((object)("[PlayerManager] " + where + ": " + e));
}
}
}
[BepInPlugin("local.wobblylife.largerlobbymod", "Larger Lobby Mod", "1.0.1")]
public class Plugin : BasePlugin
{
internal static ManualLogSource Logger;
internal static ConfigEntry<int> MaxPlayers;
internal static ConfigEntry<bool> JoinDiagnostics;
internal static ConfigEntry<bool> DropDiagnostics;
internal static ConfigEntry<string> DropHooks;
internal static ConfigEntry<bool> PlayerManagerEnabled;
internal static ConfigEntry<KeyCode> PlayerManagerKey;
internal static ConfigEntry<bool> PlayerManagerProfileButton;
internal static ConfigEntry<bool> PlayerManagerShowHint;
internal static ConfigEntry<bool> PlayerManagerBlockInput;
internal static ConfigEntry<bool> AnnouncementsEnabled;
internal static ConfigEntry<float> AnnouncementSeconds;
internal static ConfigEntry<float> AnnouncementInterval;
internal static ConfigEntry<bool> TeleportEnabled;
internal static ConfigEntry<bool> TeleportRespawnFallback;
internal static ConfigEntry<bool> JailEnabled;
internal static ConfigEntry<string> JailPosition;
internal static ConfigEntry<float> JailRadius;
public override void Load()
{
//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
//IL_02e6: Expected O, but got Unknown
//IL_049b: Unknown result type (might be due to invalid IL or missing references)
//IL_04a0: Unknown result type (might be due to invalid IL or missing references)
Logger = ((BasePlugin)this).Log;
MaxPlayers = ((BasePlugin)this).Config.Bind<int>("General", "MaxPlayers", 100, "Online lobby size used when you host. The mod only ever raises the game's own value.");
JoinDiagnostics = ((BasePlugin)this).Config.Bind<bool>("Debug", "JoinDiagnostics", false, "Log extra detail about joins, the joinable flag, kicks and failed connections.");
DropDiagnostics = ((BasePlugin)this).Config.Bind<bool>("Debug", "DropDiagnostics", false, "Log when the host drops a player after accepting them, and the player counts it publishes (added in 0.4.2).");
DropHooks = ((BasePlugin)this).Config.Bind<string>("Debug", "DropHooks", "HostDisconnectPlayerLog,HostKickPlayerLog,HostNotJoinableOverrideLog,EosPlayerCountLog,XboxActivityCountLog", "Which DropDiagnostics hooks to turn on (comma-separated). Others: HostAuthFailedLog,HostAuthSucceededLog,HostNotAcceptedLog (untested). Do NOT add HostForceDisconnectLog: it crashes the game at the splash screen.");
PlayerManagerEnabled = ((BasePlugin)this).Config.Bind<bool>("PlayerManager", "Enabled", true, "In-game panel listing every player, with Profile / Kick / Ban (host only).");
PlayerManagerKey = ((BasePlugin)this).Config.Bind<KeyCode>("PlayerManager", "ToggleKey", (KeyCode)289, "Key that opens and closes the player manager.");
PlayerManagerShowHint = ((BasePlugin)this).Config.Bind<bool>("PlayerManager", "ShowHint", true, "Show a small 'Press F8 for Player Manager' button in the top-left corner.");
PlayerManagerBlockInput = ((BasePlugin)this).Config.Bind<bool>("PlayerManager", "BlockGameInput", false, "While the player manager is open, the game ignores your keyboard and mouse (so typing doesn't move your character).");
AnnouncementsEnabled = ((BasePlugin)this).Config.Bind<bool>("Announcements", "Enabled", true, "Lets the host send a message that every player sees in the game's notification banner.");
AnnouncementSeconds = ((BasePlugin)this).Config.Bind<float>("Announcements", "DisplaySeconds", 15f, "Roughly how long an announcement stays on players' screens. The message is re-sent every RepeatEverySeconds to cover this time, so the banner slides out and back in between copies.");
AnnouncementInterval = ((BasePlugin)this).Config.Bind<float>("Announcements", "RepeatEverySeconds", 4f, "Seconds between copies of an announcement. Each banner shows for about 3.5s, so lower values cut copies short.");
TeleportEnabled = ((BasePlugin)this).Config.Bind<bool>("Teleport", "Enabled", true, "Adds a Teleport tab to the player manager (go to a player, bring a player or everyone to you).");
TeleportRespawnFallback = ((BasePlugin)this).Config.Bind<bool>("Teleport", "RespawnFallback", true, "If a pulled player's game snaps them back, respawn their character next to you instead. A respawn may make them drop what they're holding.");
JailEnabled = ((BasePlugin)this).Config.Bind<bool>("Jail", "Enabled", true, "Adds a Jail tab: jailed players are kept at the jail spot until you release them.");
JailPosition = ((BasePlugin)this).Config.Bind<string>("Jail", "Position", "", "Jail location as X,Y,Z. Set it in game with 'Set jail at my position' on the Jail tab.");
JailRadius = ((BasePlugin)this).Config.Bind<float>("Jail", "Radius", 4f, "How far (metres) a jailed player can move from the jail before being pulled back.");
PlayerManagerProfileButton = ((BasePlugin)this).Config.Bind<bool>("PlayerManager", "ProfileButton", true, "Show the Profile button. It opens the player's Xbox or Steam profile page in your web browser.");
((BasePlugin)this).Log.LogInfo((object)("Larger Lobby Mod 1.0.1 loaded. MaxPlayers=" + MaxPlayers.Value + ", JoinDiagnostics=" + JoinDiagnostics.Value + ", DropDiagnostics=" + DropDiagnostics.Value + (DropDiagnostics.Value ? (", DropHooks=" + DropHooks.Value) : "")));
Harmony harmony = new Harmony("local.wobblylife.largerlobbymod");
TryPatch(harmony, typeof(EosHostPatch));
TryPatch(harmony, typeof(GameCoreHostPatch));
TryPatch(harmony, typeof(PlayerAcceptedLog));
TryPatch(harmony, typeof(PlayerDisconnectedLog));
if (JoinDiagnostics.Value)
{
TryPatch(harmony, typeof(SetJoinableLog));
TryPatch(harmony, typeof(LocalJoinCheckLog));
TryPatch(harmony, typeof(RemoteLocalJoinRequestLog));
TryPatch(harmony, typeof(RemoteLocalSpawnLog));
TryPatch(harmony, typeof(KickedLog));
TryPatch(harmony, typeof(FailedToConnectLog));
}
if (DropDiagnostics.Value)
{
HashSet<string> hashSet = new HashSet<string>(DropHooks.Value.Split(','), StringComparer.OrdinalIgnoreCase);
Type[] array = new Type[9]
{
typeof(HostDisconnectPlayerLog),
typeof(HostAuthFailedLog),
typeof(HostAuthSucceededLog),
typeof(HostNotAcceptedLog),
typeof(HostKickPlayerLog),
typeof(HostNotJoinableOverrideLog),
typeof(HostForceDisconnectLog),
typeof(EosPlayerCountLog),
typeof(XboxActivityCountLog)
};
foreach (Type type in array)
{
if (hashSet.Contains(type.Name.Trim()))
{
TryPatch(harmony, type);
}
}
}
if (PlayerManagerEnabled.Value)
{
try
{
((BasePlugin)this).AddComponent<PlayerManagerUI>();
((BasePlugin)this).Log.LogInfo((object)("Player manager ready (press " + ((object)PlayerManagerKey.Value/*cast due to .constrained prefix*/).ToString() + " while hosting)."));
}
catch (Exception ex)
{
((BasePlugin)this).Log.LogError((object)("FAILED to start player manager: " + ex));
}
}
}
private void TryPatch(Harmony harmony, Type patchType)
{
try
{
harmony.PatchAll(patchType);
((BasePlugin)this).Log.LogInfo((object)("Patched: " + patchType.Name));
}
catch (Exception ex)
{
((BasePlugin)this).Log.LogError((object)("FAILED to patch " + patchType.Name + ": " + ex));
}
}
}
internal static class Limits
{
private static readonly Dictionary<string, int> seen = new Dictionary<string, int>();
internal static void ApplyArg(string name, ref int value, int wanted)
{
int num = value;
if (wanted > 0 && value < wanted)
{
value = wanted;
}
seen.TryGetValue(name, out var value2);
if (value2 < 10)
{
seen[name] = value2 + 1;
Plugin.Logger.LogInfo((object)(name + " called: original=" + num + ", now=" + value));
}
}
}
internal static class Net
{
internal static string State()
{
try
{
HawkNetworkManager defaultInstance = HawkNetworkManager.DefaultInstance;
if ((Object)(object)defaultInstance == (Object)null)
{
return "no network manager";
}
return "players " + defaultInstance.GetCurrentPlayerCount() + "/" + defaultInstance.GetMaxPlayerCount() + ", joinable=" + defaultInstance.IsJoinable() + ", server=" + defaultInstance.IsServer();
}
catch (Exception ex)
{
return "state unavailable (" + ex.GetType().Name + ")";
}
}
internal static string Describe(Object obj)
{
if (obj == null)
{
return "null";
}
try
{
return obj.GetIl2CppType().FullName;
}
catch
{
return "unknown";
}
}
}
[HarmonyPatch(typeof(EOSNetworkManager), "HostServer")]
internal static class EosHostPatch
{
[HarmonyPrefix]
private static void Prefix(ref int __0)
{
try
{
Limits.ApplyArg("EOSNetworkManager.HostServer", ref __0, Plugin.MaxPlayers.Value);
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)ex);
}
}
}
[HarmonyPatch(typeof(GameCoreNetworkManager), "HostServer")]
internal static class GameCoreHostPatch
{
[HarmonyPrefix]
private static void Prefix(ref int __0)
{
try
{
Limits.ApplyArg("GameCoreNetworkManager.HostServer", ref __0, Plugin.MaxPlayers.Value);
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)ex);
}
}
}
[HarmonyPatch(typeof(HawkNetworkManager), "OnPlayerAccepted")]
internal static class PlayerAcceptedLog
{
[HarmonyPostfix]
private static void Postfix(HawkNetworkManager __instance)
{
try
{
Plugin.Logger.LogInfo((object)("[" + DateTime.Now.ToString("HH:mm:ss.f") + "] Player accepted. Players now: " + __instance.GetCurrentPlayerCount() + " (max " + __instance.GetMaxPlayerCount() + ")"));
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)ex);
}
}
}
[HarmonyPatch(typeof(HawkNetworkManager), "OnPlayerDisconnected")]
internal static class PlayerDisconnectedLog
{
[HarmonyPostfix]
private static void Postfix(HawkNetworkManager __instance)
{
try
{
Plugin.Logger.LogInfo((object)("[" + DateTime.Now.ToString("HH:mm:ss.f") + "] Player disconnected. Players now: " + __instance.GetCurrentPlayerCount() + " (max " + __instance.GetMaxPlayerCount() + ")"));
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)ex);
}
}
}
[HarmonyPatch(typeof(HawkNetworkManager), "SetJoinable")]
internal static class SetJoinableLog
{
[HarmonyPostfix]
private static void Postfix(HawkNetworkManager __instance, Object __0, bool __1)
{
try
{
Plugin.Logger.LogInfo((object)("[Joinable] " + Net.Describe(__0) + " set joinable=" + __1 + " -> session joinable now " + __instance.IsJoinable()));
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)ex);
}
}
}
[HarmonyPatch(typeof(LocalPlayerManager), "IsLocalPlayerAbleToJoin")]
internal static class LocalJoinCheckLog
{
private static string last;
[HarmonyPostfix]
private static void Postfix(bool __result)
{
try
{
string text = "able=" + __result + " (" + Net.State() + ")";
if (text != last)
{
last = text;
Plugin.Logger.LogInfo((object)("[LocalJoin] Split-screen join check: " + text));
}
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)ex);
}
}
}
[HarmonyPatch(typeof(LocalPlayerManager), "ServerRequestLocalPlayerJoin")]
internal static class RemoteLocalJoinRequestLog
{
[HarmonyPrefix]
private static void Prefix()
{
try
{
Plugin.Logger.LogInfo((object)("[LocalJoin] Remote split-screen join request received. " + Net.State()));
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)ex);
}
}
}
[HarmonyPatch(typeof(LocalPlayerManager), "ServerSpawnLocalPlayer")]
internal static class RemoteLocalSpawnLog
{
[HarmonyPostfix]
private static void Postfix()
{
try
{
Plugin.Logger.LogInfo((object)("[LocalJoin] Split-screen player spawned. " + Net.State()));
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)ex);
}
}
}
[HarmonyPatch(typeof(WobblyNetworkManager), "OnKicked")]
internal static class KickedLog
{
[HarmonyPrefix]
private static void Prefix(int __0)
{
try
{
Plugin.Logger.LogWarning((object)("[Join] Kicked from session, reason code " + __0));
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)ex);
}
}
}
[HarmonyPatch(typeof(WobblyNetworkManager), "OnFailedToConnect")]
internal static class FailedToConnectLog
{
[HarmonyPrefix]
private static void Prefix(string __0, Object __1, int __2)
{
try
{
Plugin.Logger.LogWarning((object)("[Join] Failed to connect: message='" + __0 + "', detail=" + Net.Describe(__1) + ", code=" + __2));
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)ex);
}
}
}
[HarmonyPatch(typeof(HawkNetworkManager), "DisconnectPlayer")]
internal static class HostDisconnectPlayerLog
{
[HarmonyPrefix]
private static void Prefix(int __1)
{
try
{
Plugin.Logger.LogWarning((object)("[" + DateTime.Now.ToString("HH:mm:ss.f") + "] [Drop] Host is disconnecting a player, reason code " + __1 + ". " + Net.State()));
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)ex);
}
}
}
[HarmonyPatch(typeof(HawkNetworkManager), "OnAuthenticationFailed")]
internal static class HostAuthFailedLog
{
[HarmonyPrefix]
private static void Prefix()
{
try
{
Plugin.Logger.LogWarning((object)("[Drop] A joining player FAILED authentication. " + Net.State()));
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)ex);
}
}
}
[HarmonyPatch(typeof(HawkNetworkManager), "OnAuthenticationSucceeded")]
internal static class HostAuthSucceededLog
{
[HarmonyPrefix]
private static void Prefix()
{
try
{
Plugin.Logger.LogInfo((object)("[Join] A joining player passed authentication. " + Net.State()));
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)ex);
}
}
}
[HarmonyPatch(typeof(HawkNetworkManager), "OnPlayerNotAccepted")]
internal static class HostNotAcceptedLog
{
[HarmonyPrefix]
private static void Prefix()
{
try
{
Plugin.Logger.LogWarning((object)("[Drop] A joining player was NOT accepted. " + Net.State()));
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)ex);
}
}
}
[HarmonyPatch(typeof(WobblyNetworkManager), "KickPlayer")]
internal static class HostKickPlayerLog
{
[HarmonyPrefix]
private static void Prefix()
{
try
{
Plugin.Logger.LogWarning((object)("[Drop] Game called KickPlayer. " + Net.State()));
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)ex);
}
}
}
[HarmonyPatch(typeof(WobblyNetworkManager), "OnDisconnectNotJoinableOverride")]
internal static class HostNotJoinableOverrideLog
{
[HarmonyPrefix]
private static void Prefix()
{
try
{
Plugin.Logger.LogWarning((object)("[Drop] Player dropped because the session was not joinable. " + Net.State()));
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)ex);
}
}
}
[HarmonyPatch(typeof(EOSNetworkManager), "ForceDisconnectPlayer")]
internal static class HostForceDisconnectLog
{
[HarmonyPrefix]
private static void Prefix()
{
try
{
Plugin.Logger.LogWarning((object)("[Drop] EOS force-disconnected a player. " + Net.State()));
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)ex);
}
}
}
[HarmonyPatch(typeof(EOSNetworkManager), "ServerUpdatePlayerCount")]
internal static class EosPlayerCountLog
{
private static string last;
[HarmonyPrefix]
private static void Prefix(int __0, int __1, int __2)
{
try
{
string text = "players=" + __0 + ", steam=" + __1 + ", ps=" + __2;
if (!(text == last))
{
last = text;
Plugin.Logger.LogInfo((object)("[Count] Host publishes to online lobby: " + text + ". " + Net.State()));
}
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)ex);
}
}
}
[HarmonyPatch(typeof(GameCoreNetworkManager), "SyncGameCoreMPActivityWithEOSSession")]
internal static class XboxActivityCountLog
{
private static string last;
[HarmonyPrefix]
private static void Prefix(int __0, int __1, int __2)
{
try
{
string text = "players=" + __0 + ", steam=" + __1 + ", ps=" + __2;
if (!(text == last))
{
last = text;
Plugin.Logger.LogInfo((object)("[Count] Host publishes to Xbox Multiplayer Activity: " + text));
}
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)ex);
}
}
}
internal static class Teleporter
{
private class PendingCheck
{
public PlayerController Controller;
public string Name;
public Vector3 Origin;
public Vector3 Target;
public Quaternion Rotation;
public float CheckAt;
public bool Quiet;
}
private const float CheckDelay = 1.5f;
private const float StuckDistance = 6f;
private const float SnapBackDistance = 4f;
private static readonly List<PendingCheck> pending = new List<PendingCheck>();
internal static PlayerCharacter HostCharacter()
{
if (!UnitySingleton<GameInstance>.InstanceExists)
{
return null;
}
PlayerController firstLocalPlayerController = UnitySingleton<GameInstance>.Instance.GetFirstLocalPlayerController();
if (!((Object)(object)firstLocalPlayerController == (Object)null))
{
return firstLocalPlayerController.GetPlayerCharacter();
}
return null;
}
internal static string GoTo(PlayerController target, string name)
{
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: 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_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: 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_0073: Unknown result type (might be due to invalid IL or missing references)
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
PlayerCharacter val = HostCharacter();
if ((Object)(object)val == (Object)null)
{
return "Your character isn't spawned right now.";
}
PlayerCharacter val2 = (((Object)(object)target == (Object)null) ? null : target.GetPlayerCharacter());
if ((Object)(object)val2 == (Object)null)
{
return name + " doesn't have a character right now.";
}
Vector3 val3 = Flat(val2.GetPlayerTransform().forward);
Vector3 val4 = val2.GetPlayerPosition() - val3 * 2f + Vector3.up * 0.5f;
val.SetPlayerPositionAndRotation(val4, Quaternion.LookRotation(val3), true);
Plugin.Logger.LogInfo((object)("[Teleport] Host went to '" + name + "'"));
return "Teleported to " + name + ".";
}
internal static string GoToPoint(Vector3 position, string what)
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
PlayerCharacter val = HostCharacter();
if ((Object)(object)val == (Object)null)
{
return "Your character isn't spawned right now.";
}
val.SetPlayerPositionAndRotation(position, Quaternion.LookRotation(Flat(val.GetPlayerTransform().forward)), true);
Plugin.Logger.LogInfo((object)("[Teleport] Host went to " + what));
return "Teleported to " + what + ".";
}
internal static string Bring(PlayerController target, string name, int index, int count)
{
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: 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_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
//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_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_008e: Unknown result type (might be due to invalid IL or missing references)
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
//IL_00da: Unknown result type (might be due to invalid IL or missing references)
//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
PlayerCharacter val = HostCharacter();
if ((Object)(object)val == (Object)null)
{
return "Your character isn't spawned right now.";
}
if ((Object)(object)(((Object)(object)target == (Object)null) ? null : target.GetPlayerCharacter()) == (Object)null)
{
return name + " doesn't have a character right now.";
}
Vector3 playerPosition = val.GetPlayerPosition();
Vector3 val2 = Flat(val.GetPlayerTransform().forward);
Vector3 val3 = ((count <= 1) ? (val2 * 2f) : (Quaternion.Euler(0f, (float)index * 360f / (float)count, 0f) * val2 * 2.5f));
Vector3 dest = playerPosition + val3 + Vector3.up * 0.5f;
Quaternion rotation = Quaternion.LookRotation(Flat(-val3));
Plugin.Logger.LogInfo((object)("[Teleport] Moving '" + name + "' to the host"));
if (!MoveTo(target, name, dest, rotation, quiet: false))
{
return name + " doesn't have a character right now.";
}
return "Teleporting " + name + " to you.";
}
internal static bool IsPending(PlayerController target)
{
return pending.Exists((PendingCheck p) => (Object)(object)p.Controller == (Object)(object)target);
}
internal static bool MoveTo(PlayerController target, string name, Vector3 dest, Quaternion rotation, bool quiet)
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: 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)
PlayerCharacter val = (((Object)(object)target == (Object)null) ? null : target.GetPlayerCharacter());
if ((Object)(object)val == (Object)null)
{
return false;
}
Vector3 playerPosition = val.GetPlayerPosition();
val.SetPlayerPositionAndRotation(dest, rotation, true);
pending.Add(new PendingCheck
{
Controller = target,
Name = name,
Origin = playerPosition,
Target = dest,
Rotation = rotation,
CheckAt = Time.unscaledTime + 1.5f,
Quiet = quiet
});
return true;
}
internal static void Tick()
{
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: 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_0094: 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_0184: Unknown result type (might be due to invalid IL or missing references)
//IL_018a: Unknown result type (might be due to invalid IL or missing references)
for (int num = pending.Count - 1; num >= 0; num--)
{
PendingCheck pendingCheck = pending[num];
if (!(Time.unscaledTime < pendingCheck.CheckAt))
{
pending.RemoveAt(num);
if (!((Object)(object)pendingCheck.Controller == (Object)null))
{
PlayerCharacter playerCharacter = pendingCheck.Controller.GetPlayerCharacter();
if (!((Object)(object)playerCharacter == (Object)null))
{
Vector3 playerPosition = playerCharacter.GetPlayerPosition();
float num2 = Vector3.Distance(playerPosition, pendingCheck.Target);
if (!(num2 > 6f) || !(Vector3.Distance(playerPosition, pendingCheck.Origin) < 4f) || !(Vector3.Distance(pendingCheck.Origin, pendingCheck.Target) > 6f))
{
if (!pendingCheck.Quiet)
{
Plugin.Logger.LogInfo((object)("[Teleport] Move worked for '" + pendingCheck.Name + "'"));
}
}
else if (!Plugin.TeleportRespawnFallback.Value)
{
Plugin.Logger.LogWarning((object)("[Teleport] Move didn't stick for '" + pendingCheck.Name + "' (snapped back, " + num2.ToString("0") + "m away); RespawnFallback is off"));
}
else
{
Plugin.Logger.LogWarning((object)("[Teleport] Move didn't stick for '" + pendingCheck.Name + "' (snapped back, " + num2.ToString("0") + "m away); respawning them at the target"));
Respawn(pendingCheck.Controller, pendingCheck.Name, pendingCheck.Target, pendingCheck.Rotation);
}
}
}
}
}
}
private static void Respawn(PlayerController pc, string name, Vector3 position, Quaternion rotation)
{
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
try
{
PlayerCharacter playerCharacterPrefab = pc.playerCharacterPrefab;
if ((Object)(object)playerCharacterPrefab == (Object)null)
{
Plugin.Logger.LogWarning((object)("[Teleport] Can't respawn '" + name + "': no character prefab"));
return;
}
pc.ServerDestoryPlayerCharacter(false, true);
pc.ServerSpawnPlayerCharacter(playerCharacterPrefab, (Action<PlayerCharacter>)null, new Nullable<Vector3>(position), new Nullable<Quaternion>(rotation), true, new Nullable<uint>());
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("[Teleport] Respawn failed for '" + name + "': " + ex));
}
}
private static Vector3 Flat(Vector3 v)
{
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
v.y = 0f;
if (!(((Vector3)(ref v)).sqrMagnitude < 0.001f))
{
return ((Vector3)(ref v)).normalized;
}
return Vector3.forward;
}
}
}