using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Extensions;
using HarmonyLib;
using Mirror;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ElevatorMod")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ElevatorMod")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("eafa11bc-f60d-47c5-b45f-3cb9e5bb4fee")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
public struct ElevatorTravelMsg : NetworkMessage
{
public bool traveled;
}
public struct PlayerFloorMsg : NetworkMessage
{
public uint[] netIds;
public int[] floors;
}
[BepInPlugin("com.yourname.elevatormod", "Elevator Mod", "1.5.0")]
public class ElevatorMod : BaseUnityPlugin
{
internal static ManualLogSource Log;
public static ConfigEntry<bool> ModEnabled;
public static ConfigEntry<bool> ShowStatusDisplay;
public static int LocalPlayerCurrentFloor = 0;
public static bool LocalPlayerTravelledLastTrip = false;
public static bool ElevatorTripOccurred = false;
public static bool ClientTraveledThisTrip = false;
public static bool ClientTravelMsgPending = false;
public static bool ClientFloorInitialized = false;
public static bool ClientFloorRpcPending = false;
public static int ClientFloorRpcIndex = 0;
public static int PendingDestinationFloor = 0;
public static Dictionary<uint, int> ServerPlayerFloors = new Dictionary<uint, int>();
public static Dictionary<uint, int> ClientPlayerFloors = new Dictionary<uint, int>();
public static bool NeedHandlerRegistration = true;
public static HashSet<int> ActivatedFloors = new HashSet<int>();
private void Awake()
{
//IL_0101: Unknown result type (might be due to invalid IL or missing references)
//IL_0107: Expected O, but got Unknown
//IL_011a: Unknown result type (might be due to invalid IL or missing references)
//IL_0120: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable or disable the elevator mod.");
ShowStatusDisplay = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowStatusDisplay", true, "Show the READY/BUSY status display on screen.");
Writer<ElevatorTravelMsg>.write = delegate(NetworkWriter w, ElevatorTravelMsg msg)
{
NetworkWriterExtensions.WriteBool(w, msg.traveled);
};
Reader<ElevatorTravelMsg>.read = delegate(NetworkReader r)
{
ElevatorTravelMsg result2 = default(ElevatorTravelMsg);
result2.traveled = NetworkReaderExtensions.ReadBool(r);
return result2;
};
Writer<PlayerFloorMsg>.write = delegate(NetworkWriter w, PlayerFloorMsg msg)
{
uint[] netIds = msg.netIds;
int num2 = ((netIds != null) ? netIds.Length : 0);
NetworkWriterExtensions.WriteInt(w, num2);
for (int j = 0; j < num2; j++)
{
NetworkWriterExtensions.WriteUInt(w, msg.netIds[j]);
NetworkWriterExtensions.WriteInt(w, msg.floors[j]);
}
};
Reader<PlayerFloorMsg>.read = delegate(NetworkReader r)
{
int num = NetworkReaderExtensions.ReadInt(r);
uint[] array = new uint[num];
int[] array2 = new int[num];
for (int i = 0; i < num; i++)
{
array[i] = NetworkReaderExtensions.ReadUInt(r);
array2[i] = NetworkReaderExtensions.ReadInt(r);
}
PlayerFloorMsg result = default(PlayerFloorMsg);
result.netIds = array;
result.floors = array2;
return result;
};
NetworkClient.OnDisconnectedEvent = (Action)Delegate.Combine(NetworkClient.OnDisconnectedEvent, new Action(ResetState));
GameObject val = new GameObject("ElevatorStatusDisplay");
val.AddComponent<ElevatorStatusDisplay>();
Object.DontDestroyOnLoad((Object)(object)val);
Harmony val2 = new Harmony("com.yourname.elevatormod");
val2.PatchAll();
Log.LogInfo((object)"ElevatorMod 1.6.2 loaded!");
}
public static void OnElevatorTravelMsg(ElevatorTravelMsg msg)
{
ClientTraveledThisTrip = msg.traveled;
ClientTravelMsgPending = true;
Log.LogDebug((object)$"ElevatorMod: [client] Travel msg received — traveled: {msg.traveled}");
ElevatorFloorChangePatch.TryResolveClientFloor();
}
public static void OnPlayerFloorMsg(PlayerFloorMsg msg)
{
for (int i = 0; i < msg.netIds.Length; i++)
{
ClientPlayerFloors[msg.netIds[i]] = msg.floors[i];
}
Log.LogDebug((object)$"ElevatorMod: [client] Player floor map updated ({msg.netIds.Length} players).");
ElevatorFloorChangePatch.RefreshPlayerVisibility();
}
private static void ResetState()
{
LocalPlayerCurrentFloor = 0;
LocalPlayerTravelledLastTrip = false;
ElevatorTripOccurred = false;
ClientTraveledThisTrip = false;
ClientTravelMsgPending = false;
ClientFloorInitialized = false;
ClientFloorRpcPending = false;
ClientFloorRpcIndex = 0;
PendingDestinationFloor = 0;
ServerPlayerFloors.Clear();
ClientPlayerFloors.Clear();
ActivatedFloors.Clear();
NeedHandlerRegistration = true;
Log.LogDebug((object)"ElevatorMod: State reset on disconnect.");
}
}
public class ElevatorStatusDisplay : MonoBehaviour
{
private const float DISPLAY_DISTANCE = 15f;
private GUIStyle _boxStyle;
private GUIStyle _textStyle;
private bool _stylesInitialized = false;
private void Update()
{
if (ElevatorMod.NeedHandlerRegistration && NetworkClient.active)
{
NetworkClient.RegisterHandler<ElevatorTravelMsg>((Action<ElevatorTravelMsg>)ElevatorMod.OnElevatorTravelMsg, true);
NetworkClient.RegisterHandler<PlayerFloorMsg>((Action<PlayerFloorMsg>)ElevatorMod.OnPlayerFloorMsg, true);
ElevatorMod.NeedHandlerRegistration = false;
ElevatorMod.Log.LogDebug((object)"ElevatorMod: Network handlers registered.");
}
}
private void InitStyles()
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Expected O, but got Unknown
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Expected O, but got Unknown
if (!_stylesInitialized)
{
_boxStyle = new GUIStyle(GUI.skin.box);
_boxStyle.fontSize = 18;
_boxStyle.fontStyle = (FontStyle)1;
_boxStyle.alignment = (TextAnchor)4;
_textStyle = new GUIStyle(GUI.skin.label);
_textStyle.fontSize = 18;
_textStyle.fontStyle = (FontStyle)1;
_textStyle.alignment = (TextAnchor)4;
_stylesInitialized = true;
}
}
private void OnGUI()
{
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: 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_0110: Unknown result type (might be due to invalid IL or missing references)
//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: 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_0140: Unknown result type (might be due to invalid IL or missing references)
//IL_014b: Unknown result type (might be due to invalid IL or missing references)
if (!ElevatorMod.ModEnabled.Value || !ElevatorMod.ShowStatusDisplay.Value || !NetworkClient.active)
{
return;
}
ElevatorManager val = Object.FindFirstObjectByType<ElevatorManager>();
if (!((Object)(object)val == (Object)null))
{
NetworkIdentity localPlayer = NetworkClient.localPlayer;
if (!((Object)(object)localPlayer == (Object)null) && !(Vector3.Distance(((Component)localPlayer).transform.position, ((Component)val).transform.position) > 15f))
{
bool isTeleporting = val.isTeleporting;
InitStyles();
Rect val2 = default(Rect);
((Rect)(ref val2))..ctor((float)Screen.width / 2f - 120f, 20f, 240f, 50f);
Color backgroundColor = GUI.backgroundColor;
GUI.backgroundColor = (isTeleporting ? new Color(0.8f, 0.1f, 0.1f, 0.85f) : new Color(0.1f, 0.7f, 0.1f, 0.85f));
GUI.Box(val2, "", _boxStyle);
GUI.backgroundColor = backgroundColor;
_textStyle.normal.textColor = Color.white;
GUI.Label(val2, isTeleporting ? "ELEVATOR — BUSY" : "ELEVATOR — READY", _textStyle);
}
}
}
}
[HarmonyPatch(typeof(ElevatorManager), "CheckPlayersInside")]
public class ElevatorCheckPatch
{
private static bool Prefix(ElevatorManager __instance, ref bool __result)
{
//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_0073: Unknown result type (might be due to invalid IL or missing references)
if (!ElevatorMod.ModEnabled.Value)
{
return true;
}
Collider value = Traverse.Create((object)__instance).Field("checkCollider").GetValue<Collider>();
if ((Object)(object)value == (Object)null)
{
return true;
}
__result = false;
foreach (PlayerReferences player in MonoSingleton<LocalManager>.Instance.players)
{
Bounds bounds = value.bounds;
if (((Bounds)(ref bounds)).Contains(player.transform.position))
{
__result = true;
break;
}
}
ElevatorMod.Log.LogDebug((object)$"ElevatorMod: CheckPlayersInside -> {__result}");
return false;
}
}
[HarmonyPatch(typeof(ElevatorManager), "ServerTryTeleportPlayers")]
public class ElevatorServerTryPatch
{
private static void Prefix(int toIndex)
{
ElevatorMod.PendingDestinationFloor = toIndex;
}
}
[HarmonyPatch(typeof(ElevatorManager), "ServerTeleportPlayersOutside")]
public class ElevatorTeleportPatch
{
private static bool Prefix(ElevatorManager __instance)
{
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
//IL_00be: Unknown result type (might be due to invalid IL or missing references)
//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
//IL_0175: Unknown result type (might be due to invalid IL or missing references)
//IL_017f: 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_0190: Unknown result type (might be due to invalid IL or missing references)
//IL_0195: Unknown result type (might be due to invalid IL or missing references)
//IL_019e: Unknown result type (might be due to invalid IL or missing references)
//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
if (!ElevatorMod.ModEnabled.Value)
{
return true;
}
Collider value = Traverse.Create((object)__instance).Field("checkCollider").GetValue<Collider>();
if ((Object)(object)value == (Object)null)
{
return true;
}
ElevatorMod.ElevatorTripOccurred = true;
NetworkIdentity localPlayer = NetworkClient.localPlayer;
Bounds bounds;
int num;
if ((Object)(object)localPlayer != (Object)null)
{
bounds = value.bounds;
num = (((Bounds)(ref bounds)).Contains(((Component)localPlayer).transform.position) ? 1 : 0);
}
else
{
num = 0;
}
bool localPlayerTravelledLastTrip = (byte)num != 0;
ElevatorMod.LocalPlayerTravelledLastTrip = localPlayerTravelledLastTrip;
int num2 = 0;
int num3 = 0;
foreach (PlayerReferences player in MonoSingleton<LocalManager>.Instance.players)
{
bool isBeingHeld = ((Item)player.carry).GetIsBeingHeld();
int num4;
if (!isBeingHeld)
{
bounds = value.bounds;
num4 = (((Bounds)(ref bounds)).Contains(player.transform.position) ? 1 : 0);
}
else
{
num4 = 0;
}
bool flag = (byte)num4 != 0;
uint netId = player.identity.netId;
if (flag)
{
ElevatorMod.ServerPlayerFloors[netId] = ElevatorMod.PendingDestinationFloor;
}
else if (!ElevatorMod.ServerPlayerFloors.ContainsKey(netId))
{
ElevatorMod.ServerPlayerFloors[netId] = 0;
}
NetworkConnection connectionToClient = (NetworkConnection)(object)((NetworkBehaviour)player.controller).netIdentity.connectionToClient;
if (connectionToClient != null)
{
connectionToClient.Send<ElevatorTravelMsg>(new ElevatorTravelMsg
{
traveled = flag
}, 0);
}
if (!isBeingHeld)
{
if (flag)
{
Vector2 val = Random.insideUnitCircle * 3f;
Vector3 position = NetworkSingleton<ElevatorManager>.Instance.playerSpawnPosition.position;
player.controller.ServerTeleport(position + new Vector3(val.x, 0f, val.y));
player.controller.ServerRotate(new Vector2(180f, 0f));
num2++;
}
else
{
num3++;
}
}
}
uint[] array = new uint[ElevatorMod.ServerPlayerFloors.Count];
int[] array2 = new int[ElevatorMod.ServerPlayerFloors.Count];
int num5 = 0;
foreach (KeyValuePair<uint, int> serverPlayerFloor in ElevatorMod.ServerPlayerFloors)
{
array[num5] = serverPlayerFloor.Key;
array2[num5] = serverPlayerFloor.Value;
num5++;
}
PlayerFloorMsg playerFloorMsg = default(PlayerFloorMsg);
playerFloorMsg.netIds = array;
playerFloorMsg.floors = array2;
NetworkServer.SendToAll<PlayerFloorMsg>(playerFloorMsg, 0, false);
ElevatorMod.Log.LogDebug((object)$"ElevatorMod: {num2} travelled, {num3} stayed.");
return false;
}
}
[HarmonyPatch(typeof(ElevatorManager), "UserCode_RpcSetActiveFloorOnly__Int32")]
public class ElevatorFloorChangePatch
{
private static bool Prefix(ElevatorManager __instance, int index)
{
if (!ElevatorMod.ModEnabled.Value)
{
return true;
}
NetworkIdentity localPlayer = NetworkClient.localPlayer;
if ((Object)(object)localPlayer == (Object)null)
{
return true;
}
if (NetworkServer.active)
{
if (!ElevatorMod.ElevatorTripOccurred)
{
ElevatorMod.Log.LogDebug((object)$"ElevatorMod: [host] Init/sync to floor {index}");
ElevatorMod.LocalPlayerCurrentFloor = index;
ApplyFloorVisuals(__instance, index, index);
return false;
}
ElevatorMod.ElevatorTripOccurred = false;
bool localPlayerTravelledLastTrip = ElevatorMod.LocalPlayerTravelledLastTrip;
ElevatorMod.Log.LogDebug((object)$"ElevatorMod: [host] traveled={localPlayerTravelledLastTrip} → floor {index}");
if (localPlayerTravelledLastTrip)
{
ElevatorMod.LocalPlayerCurrentFloor = index;
}
ApplyFloorVisuals(__instance, ElevatorMod.LocalPlayerCurrentFloor, index);
return false;
}
if (!ElevatorMod.ClientFloorInitialized)
{
ElevatorMod.Log.LogDebug((object)$"ElevatorMod: [client] Init to floor {index}");
ElevatorMod.ClientFloorInitialized = true;
ElevatorMod.LocalPlayerCurrentFloor = index;
ApplyFloorVisuals(__instance, index, index);
return false;
}
ElevatorMod.ClientFloorRpcPending = true;
ElevatorMod.ClientFloorRpcIndex = index;
ElevatorMod.Log.LogDebug((object)$"ElevatorMod: [client] Buffering RPC for floor {index}");
TryResolveClientFloor(__instance);
return false;
}
public static void TryResolveClientFloor(ElevatorManager instance = null)
{
if (ElevatorMod.ClientTravelMsgPending && ElevatorMod.ClientFloorRpcPending)
{
ElevatorMod.ClientTravelMsgPending = false;
ElevatorMod.ClientFloorRpcPending = false;
if (ElevatorMod.ClientTraveledThisTrip)
{
ElevatorMod.LocalPlayerCurrentFloor = ElevatorMod.ClientFloorRpcIndex;
}
if ((Object)(object)instance == (Object)null)
{
instance = Object.FindFirstObjectByType<ElevatorManager>();
}
if ((Object)(object)instance != (Object)null)
{
ApplyFloorVisuals(instance, ElevatorMod.LocalPlayerCurrentFloor, ElevatorMod.ClientFloorRpcIndex);
}
ElevatorMod.Log.LogDebug((object)$"ElevatorMod: [client] Floor resolved — traveled={ElevatorMod.ClientTraveledThisTrip}, floor={ElevatorMod.LocalPlayerCurrentFloor}");
}
}
private static void ApplyFloorVisuals(ElevatorManager instance, int localFloor, int newFloor)
{
ElevatorMod.ActivatedFloors.Add(localFloor);
ElevatorMod.ActivatedFloors.Add(newFloor);
List<CasinoFloor> value = Traverse.Create((object)instance).Field("allFloors").GetValue<List<CasinoFloor>>();
if (value != null)
{
foreach (CasinoFloor item in value)
{
bool flag = ElevatorMod.ActivatedFloors.Contains(item.floorIndex);
bool flag2 = item.floorIndex == localFloor;
if (flag)
{
if (!((Component)item).gameObject.activeSelf)
{
((Component)item).gameObject.SetActive(true);
}
SetFloorVisible(item, flag2);
}
else
{
((Component)item).gameObject.SetActive(false);
}
item.SetSfxTrigger(flag2);
}
}
GameBase[] array = Object.FindObjectsOfType<GameBase>();
foreach (GameBase val in array)
{
bool flag3 = val.casinoLevel == localFloor;
Renderer[] componentsInChildren = ((Component)val).GetComponentsInChildren<Renderer>(true);
foreach (Renderer val2 in componentsInChildren)
{
val2.enabled = flag3;
}
Light[] componentsInChildren2 = ((Component)val).GetComponentsInChildren<Light>(true);
foreach (Light val3 in componentsInChildren2)
{
((Behaviour)val3).enabled = flag3;
}
AudioSource[] componentsInChildren3 = ((Component)val).GetComponentsInChildren<AudioSource>(true);
foreach (AudioSource val4 in componentsInChildren3)
{
val4.mute = !flag3;
}
if (NetworkServer.active)
{
continue;
}
Collider[] componentsInChildren4 = ((Component)val).GetComponentsInChildren<Collider>(true);
foreach (Collider val5 in componentsInChildren4)
{
if (!val5.isTrigger)
{
val5.enabled = flag3;
}
}
}
Keypad[] array2 = Object.FindObjectsOfType<Keypad>();
foreach (Keypad val6 in array2)
{
GameBase value2 = Traverse.Create((object)val6).Field("casinoGame").GetValue<GameBase>();
if ((Object)(object)value2 == (Object)null)
{
continue;
}
bool flag4 = value2.casinoLevel == localFloor;
Renderer[] componentsInChildren5 = ((Component)val6).GetComponentsInChildren<Renderer>(true);
foreach (Renderer val7 in componentsInChildren5)
{
val7.enabled = flag4;
}
Light[] componentsInChildren6 = ((Component)val6).GetComponentsInChildren<Light>(true);
foreach (Light val8 in componentsInChildren6)
{
((Behaviour)val8).enabled = flag4;
}
AudioSource[] componentsInChildren7 = ((Component)val6).GetComponentsInChildren<AudioSource>(true);
foreach (AudioSource val9 in componentsInChildren7)
{
val9.mute = !flag4;
}
Camera value3 = Traverse.Create((object)val6).Field("keypadCamera").GetValue<Camera>();
if ((Object)(object)value3 != (Object)null)
{
((Behaviour)value3).enabled = flag4;
}
Canvas[] componentsInChildren8 = ((Component)val6).GetComponentsInChildren<Canvas>(true);
foreach (Canvas val10 in componentsInChildren8)
{
((Behaviour)val10).enabled = flag4;
}
if (NetworkServer.active)
{
continue;
}
Collider[] componentsInChildren9 = ((Component)val6).GetComponentsInChildren<Collider>(true);
foreach (Collider val11 in componentsInChildren9)
{
if (!val11.isTrigger)
{
val11.enabled = flag4;
}
}
}
if ((Object)(object)MonoSingleton<LightbakerManager>.Instance != (Object)null)
{
MonoSingleton<LightbakerManager>.Instance.SetLightVolume(localFloor);
}
RefreshPlayerVisibility();
ElevatorMod.Log.LogDebug((object)string.Format("ElevatorMod: Visuals set — local floor {0}, visited [{1}]", localFloor, string.Join(",", ElevatorMod.ActivatedFloors)));
}
public static void RefreshPlayerVisibility()
{
NetworkIdentity localPlayer = NetworkClient.localPlayer;
foreach (PlayerReferences player in MonoSingleton<LocalManager>.Instance.players)
{
if (!((Object)(object)player.identity == (Object)(object)localPlayer))
{
if (!ElevatorMod.ClientPlayerFloors.TryGetValue(player.identity.netId, out var value))
{
value = 0;
}
bool enabled = value == ElevatorMod.LocalPlayerCurrentFloor;
Renderer[] componentsInChildren = ((Component)player.identity).GetComponentsInChildren<Renderer>();
foreach (Renderer val in componentsInChildren)
{
val.enabled = enabled;
}
Canvas[] componentsInChildren2 = ((Component)player.identity).GetComponentsInChildren<Canvas>();
foreach (Canvas val2 in componentsInChildren2)
{
((Behaviour)val2).enabled = enabled;
}
}
}
}
private static void SetFloorVisible(CasinoFloor floor, bool visible)
{
Renderer[] componentsInChildren = ((Component)floor).GetComponentsInChildren<Renderer>();
foreach (Renderer val in componentsInChildren)
{
val.enabled = visible;
}
Light[] componentsInChildren2 = ((Component)floor).GetComponentsInChildren<Light>();
foreach (Light val2 in componentsInChildren2)
{
((Behaviour)val2).enabled = visible;
}
AudioSource[] componentsInChildren3 = ((Component)floor).GetComponentsInChildren<AudioSource>();
foreach (AudioSource val3 in componentsInChildren3)
{
val3.mute = !visible;
}
Collider[] componentsInChildren4 = ((Component)floor).GetComponentsInChildren<Collider>();
foreach (Collider val4 in componentsInChildren4)
{
if (!val4.isTrigger && !((Object)(object)((Component)val4).GetComponentInParent<GameBase>() != (Object)null))
{
val4.enabled = visible;
}
}
}
}