using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using DefaultNamespace;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ContentWarningHostOnlyLobby")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.2.0.0")]
[assembly: AssemblyInformationalVersion("1.2.0+34b643bbda542a68bca944b7e0033ffeb995a662")]
[assembly: AssemblyProduct("ContentWarningHostOnlyLobby")]
[assembly: AssemblyTitle("ContentWarningHostOnlyLobby")]
[assembly: AssemblyVersion("1.2.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[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 ContentWarningHostOnlyLobby
{
[ContentWarningPlugin("local.contentwarning.hostonlylobby", "1.2.0", true)]
[BepInPlugin("local.contentwarning.hostonlylobby", "HostOnlyLobby", "1.2.0")]
public sealed class HostOnlyLobbyPlugin : BaseUnityPlugin
{
public const string PluginGuid = "local.contentwarning.hostonlylobby";
public const string PluginName = "HostOnlyLobby";
public const string PluginVersion = "1.2.0";
private Harmony? _harmony;
private bool _wasInHostRoom;
private int _lastSceneHandle = -1;
private float _indicatorVisibleFrom;
private float _indicatorVisibleUntil;
private GUIStyle? _indicatorTitleStyle;
private GUIStyle? _indicatorDetailStyle;
internal static int MaxPlayers { get; private set; } = 8;
internal static int RequiredSleepers { get; private set; } = 4;
internal static bool ShowStatusIndicator { get; private set; } = true;
internal static float IndicatorSeconds { get; private set; } = 12f;
internal static ManualLogSource? Log { get; private set; }
private void Awake()
{
//IL_00af: Unknown result type (might be due to invalid IL or missing references)
//IL_00b9: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
ConfigEntry<int> obj = ((BaseUnityPlugin)this).Config.Bind<int>("Lobby", "MaxPlayers", 8, "Maximum lobby size. Keep between 5 and 16 for cross-platform testing.");
ConfigEntry<bool> val = ((BaseUnityPlugin)this).Config.Bind<bool>("Interface", "ShowStatusIndicator", true, "Show a status card when the host enters a room or loads a world.");
ConfigEntry<float> val2 = ((BaseUnityPlugin)this).Config.Bind<float>("Interface", "IndicatorSeconds", 12f, "How many seconds the status card remains visible. Keep between 3 and 30.");
MaxPlayers = Clamp(obj.Value, 5, 16);
RequiredSleepers = Math.Min(4, MaxPlayers);
ShowStatusIndicator = val.Value;
IndicatorSeconds = Mathf.Clamp(val2.Value, 3f, 30f);
_harmony = new Harmony("local.contentwarning.hostonlylobby");
_harmony.PatchAll();
((BaseUnityPlugin)this).Logger.LogInfo((object)$"Lobby patches active. MaxPlayers={MaxPlayers}. Extra PC clients in slots 5+ also need this plugin for safe local spawning.");
((BaseUnityPlugin)this).Logger.LogInfo((object)"Late joining is intentionally disabled; have everyone join before opening the house door.");
((BaseUnityPlugin)this).Logger.LogInfo((object)"Spawn compatibility is active on this device for house, dive-bell return, and hospital spawns.");
((BaseUnityPlugin)this).Logger.LogInfo((object)$"Status indicator enabled: {ShowStatusIndicator} ({IndicatorSeconds:0.#} seconds).");
RunStartupDiagnostics();
}
private void Update()
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: 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)
bool flag = PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient;
Scene activeScene = SceneManager.GetActiveScene();
int handle = ((Scene)(ref activeScene)).handle;
if (ShowStatusIndicator && flag && (!_wasInHostRoom || handle != _lastSceneHandle))
{
_indicatorVisibleFrom = Time.realtimeSinceStartup + 1f;
_indicatorVisibleUntil = _indicatorVisibleFrom + IndicatorSeconds;
ManualLogSource logger = ((BaseUnityPlugin)this).Logger;
activeScene = SceneManager.GetActiveScene();
logger.LogInfo((object)("Status indicator scheduled in scene '" + ((Scene)(ref activeScene)).name + "'."));
}
_wasInHostRoom = flag;
_lastSceneHandle = handle;
}
private void OnGUI()
{
//IL_00df: Unknown result type (might be due to invalid IL or missing references)
//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
//IL_0109: Unknown result type (might be due to invalid IL or missing references)
//IL_0128: 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_013d: Unknown result type (might be due to invalid IL or missing references)
//IL_0147: 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)
if (ShowStatusIndicator && !(Time.realtimeSinceStartup < _indicatorVisibleFrom) && !(Time.realtimeSinceStartup > _indicatorVisibleUntil))
{
EnsureIndicatorStyles();
float num = Mathf.Min(340f, (float)Screen.width - 32f);
Rect val = default(Rect);
((Rect)(ref val))..ctor((float)Screen.width - num - 16f, 18f, num, 72f);
Rect val2 = default(Rect);
((Rect)(ref val2))..ctor(((Rect)(ref val)).x, ((Rect)(ref val)).y, 5f, ((Rect)(ref val)).height);
Rect val3 = default(Rect);
((Rect)(ref val3))..ctor(((Rect)(ref val)).x + 18f, ((Rect)(ref val)).y + 10f, ((Rect)(ref val)).width - 28f, 24f);
Rect val4 = new Rect(((Rect)(ref val)).x + 18f, ((Rect)(ref val)).y + 36f, ((Rect)(ref val)).width - 28f, 24f);
Color color = GUI.color;
GUI.color = new Color(0.055f, 0.071f, 0.102f, 0.94f);
GUI.DrawTexture(val, (Texture)(object)Texture2D.whiteTexture);
GUI.color = new Color(0.25f, 0.88f, 0.55f, 1f);
GUI.DrawTexture(val2, (Texture)(object)Texture2D.whiteTexture);
GUI.color = Color.white;
GUI.Label(val3, "HOSTONLYLOBBY ATIVO", _indicatorTitleStyle);
GUI.Label(val4, $"Sala do host • até {MaxPlayers} jogadores", _indicatorDetailStyle);
GUI.color = color;
}
}
private void OnDestroy()
{
Harmony? harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
Log = null;
}
private void EnsureIndicatorStyles()
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Expected O, but got Unknown
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: 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_0075: Expected O, but got Unknown
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
if (_indicatorTitleStyle == null || _indicatorDetailStyle == null)
{
_indicatorTitleStyle = new GUIStyle(GUI.skin.label)
{
alignment = (TextAnchor)3,
fontSize = 15,
fontStyle = (FontStyle)1
};
_indicatorTitleStyle.normal.textColor = Color.white;
_indicatorDetailStyle = new GUIStyle(GUI.skin.label)
{
alignment = (TextAnchor)3,
fontSize = 12
};
_indicatorDetailStyle.normal.textColor = new Color(0.78f, 0.82f, 0.88f, 1f);
}
}
private static int Clamp(int value, int minimum, int maximum)
{
if (value < minimum)
{
return minimum;
}
if (value > maximum)
{
return maximum;
}
return value;
}
internal static void LogSpawnRemap(int originalIndex, int safeIndex)
{
ManualLogSource? log = Log;
if (log != null)
{
log.LogInfo((object)$"Spawn compatibility remapped local slot {originalIndex} to vanilla spawn {safeIndex}.");
}
}
private void RunStartupDiagnostics()
{
MethodBase[] array = new MethodBase[8]
{
AccessTools.Method(typeof(SteamLobbyHandler), "HostMatch", (Type[])null, (Type[])null),
AccessTools.Method(typeof(PhotonNetwork), "CreateRoom", new Type[4]
{
typeof(string),
typeof(RoomOptions),
typeof(TypedLobby),
typeof(string[])
}, (Type[])null),
AccessTools.PropertyGetter(typeof(InviteFriendsTerminal), "IsGameFull"),
AccessTools.Method(typeof(RichPresenceHandler), "SetGroupSize", (Type[])null, (Type[])null),
AccessTools.Method(typeof(BedBoss), "OnPlayerJoined", (Type[])null, (Type[])null),
AccessTools.Method(typeof(PlayerHandler), "AllPlayersInBed", (Type[])null, (Type[])null),
AccessTools.Method(typeof(PlayerHandler), "AllPlayersAsleep", (Type[])null, (Type[])null),
AccessTools.Method(typeof(SpawnHandler), "FindLocalSpawnIndex", (Type[])null, (Type[])null)
};
int num = 0;
MethodBase[] array2 = array;
foreach (MethodBase methodBase in array2)
{
Patches patchInfo = Harmony.GetPatchInfo(methodBase);
bool flag = false;
if (patchInfo != null)
{
foreach (string owner in patchInfo.Owners)
{
if (owner == "local.contentwarning.hostonlylobby")
{
flag = true;
break;
}
}
}
if (flag)
{
num++;
continue;
}
((BaseUnityPlugin)this).Logger.LogError((object)("Startup diagnostic failed: patch missing on " + methodBase.DeclaringType?.Name + "." + methodBase.Name + "."));
}
if (num == array.Length)
{
((BaseUnityPlugin)this).Logger.LogInfo((object)$"Startup diagnostics passed: {num}/{array.Length} host-side patches registered.");
}
}
}
internal static class HostOnlyLobbyRules
{
internal static byte PhotonRoomLimit => 0;
internal static bool IsAtCapacity(int playerCount)
{
return playerCount >= HostOnlyLobbyPlugin.MaxPlayers;
}
internal static int RichPresenceMaximum(int requestedMaximum)
{
if (requestedMaximum > 4)
{
return requestedMaximum;
}
return HostOnlyLobbyPlugin.MaxPlayers;
}
internal static int BedAssignmentCount(int bedCount, int playerCount)
{
return Math.Min(4, Math.Min(bedCount, playerCount));
}
internal static bool EnoughPlayersReady(int alivePlayers, int readyPlayers)
{
int num = Math.Min(HostOnlyLobbyPlugin.RequiredSleepers, alivePlayers);
if (num > 0)
{
return readyPlayers >= num;
}
return false;
}
internal static int SafeSpawnIndex(int originalIndex, int houseSpawnCount, int diveBellSpawnCount)
{
if (originalIndex <= 0)
{
return 0;
}
int num = Math.Min(houseSpawnCount, diveBellSpawnCount);
if (num <= 1)
{
return 0;
}
return 1 + (originalIndex - 1) % (num - 1);
}
}
[HarmonyPatch(typeof(SpawnHandler))]
[HarmonyPriority(800)]
internal static class SpawnHandlerPatches
{
private static readonly FieldInfo LocalSpawnIndexField = typeof(SpawnHandler).GetField("m_LocalSpawnIndex", BindingFlags.Instance | BindingFlags.NonPublic) ?? throw new MissingFieldException(typeof(SpawnHandler).FullName, "m_LocalSpawnIndex");
private static readonly FieldInfo HouseSpawnsField = typeof(SpawnHandler).GetField("m_HouseSpawns", BindingFlags.Instance | BindingFlags.NonPublic) ?? throw new MissingFieldException(typeof(SpawnHandler).FullName, "m_HouseSpawns");
private static readonly FieldInfo DiveBellSpawnsField = typeof(SpawnHandler).GetField("m_DiveBellSpawns", BindingFlags.Instance | BindingFlags.NonPublic) ?? throw new MissingFieldException(typeof(SpawnHandler).FullName, "m_DiveBellSpawns");
[HarmonyPostfix]
[HarmonyPatch("FindLocalSpawnIndex")]
private static void FindLocalSpawnIndexPostfix(SpawnHandler __instance)
{
int num = (int)LocalSpawnIndexField.GetValue(__instance);
Transform[] array = (Transform[])HouseSpawnsField.GetValue(__instance);
Transform[] array2 = (Transform[])DiveBellSpawnsField.GetValue(__instance);
int num2 = HostOnlyLobbyRules.SafeSpawnIndex(num, (array != null) ? array.Length : 0, (array2 != null) ? array2.Length : 0);
if (num2 != num)
{
LocalSpawnIndexField.SetValue(__instance, num2);
HostOnlyLobbyPlugin.LogSpawnRemap(num, num2);
}
}
}
[HarmonyPatch(typeof(SteamLobbyHandler))]
internal static class SteamLobbyPatches
{
private static readonly FieldInfo MaxPlayersField = typeof(SteamLobbyHandler).GetField("m_MaxPlayers", BindingFlags.Instance | BindingFlags.NonPublic) ?? throw new MissingFieldException(typeof(SteamLobbyHandler).FullName, "m_MaxPlayers");
[HarmonyPrefix]
[HarmonyPatch("HostMatch")]
private static void HostMatchPrefix(SteamLobbyHandler __instance)
{
MaxPlayersField.SetValue(__instance, HostOnlyLobbyPlugin.MaxPlayers);
}
}
[HarmonyPatch(typeof(PhotonNetwork))]
internal static class PhotonRoomPatches
{
[HarmonyPrefix]
[HarmonyPatch("CreateRoom", new Type[]
{
typeof(string),
typeof(RoomOptions),
typeof(TypedLobby),
typeof(string[])
})]
private static void CreateRoomPrefix(ref RoomOptions roomOptions)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Expected O, but got Unknown
if (roomOptions == null)
{
roomOptions = new RoomOptions();
}
roomOptions.MaxPlayers = HostOnlyLobbyRules.PhotonRoomLimit;
}
}
[HarmonyPatch(typeof(InviteFriendsTerminal))]
internal static class InviteTerminalPatches
{
[HarmonyPrefix]
[HarmonyPatch(/*Could not decode attribute arguments.*/)]
private static bool IsGameFullPrefix(ref bool __result)
{
__result = (Object)(object)PlayerHandler.instance != (Object)null && HostOnlyLobbyRules.IsAtCapacity(PlayerHandler.instance.players.Count);
return false;
}
}
[HarmonyPatch(typeof(RichPresenceHandler))]
internal static class RichPresencePatches
{
[HarmonyPrefix]
[HarmonyPatch("SetGroupSize")]
private static void SetGroupSizePrefix(ref int maxSize)
{
maxSize = HostOnlyLobbyRules.RichPresenceMaximum(maxSize);
}
}
[HarmonyPatch(typeof(BedBoss))]
[HarmonyPriority(800)]
internal static class BedPatches
{
[HarmonyPrefix]
[HarmonyPatch("OnPlayerJoined")]
private static bool OnPlayerJoinedPrefix(BedBoss __instance)
{
if (!PhotonNetwork.IsMasterClient || (Object)(object)PlayerHandler.instance == (Object)null)
{
return false;
}
int num = HostOnlyLobbyRules.BedAssignmentCount(__instance.beds.Count, PlayerHandler.instance.players.Count);
PhotonView component = ((Component)__instance).GetComponent<PhotonView>();
for (int i = 0; i < num; i++)
{
Player val = PlayerHandler.instance.players[i];
component.RPC("AssignBed", (RpcTarget)0, new object[2]
{
val.refs.view.ViewID,
i
});
}
return false;
}
}
[HarmonyPatch(typeof(PlayerHandler))]
internal static class SleepPatches
{
[HarmonyPostfix]
[HarmonyPatch("AllPlayersInBed")]
private static void AllPlayersInBedPostfix(PlayerHandler __instance, ref bool __result)
{
if (!PhotonNetwork.IsMasterClient)
{
return;
}
int num = 0;
for (int i = 0; i < __instance.playersAlive.Count; i++)
{
if ((Object)(object)__instance.playersAlive[i].data.currentBed != (Object)null)
{
num++;
}
}
__result = HostOnlyLobbyRules.EnoughPlayersReady(__instance.playersAlive.Count, num);
}
[HarmonyPostfix]
[HarmonyPatch("AllPlayersAsleep")]
private static void AllPlayersAsleepPostfix(PlayerHandler __instance, ref bool __result)
{
if (!PhotonNetwork.IsMasterClient)
{
return;
}
int num = 0;
for (int i = 0; i < __instance.playersAlive.Count; i++)
{
if (__instance.playersAlive[i].data.sleepAmount >= 0.9f)
{
num++;
}
}
__result = HostOnlyLobbyRules.EnoughPlayersReady(__instance.playersAlive.Count, num);
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}