using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Logging;
using GorillaLocomotion;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Steamworks;
using Steamworks.Data;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using UnityEngine.Video;
using UnityEngine.XR;
using UnityEngine.XR.Interaction.Toolkit;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("Crawlspace2MP")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+e0bbb7bd81d1b81b69a578e3d5a19b1355888e4b")]
[assembly: AssemblyProduct("Crawlspace2MP")]
[assembly: AssemblyTitle("Crawlspace2MP")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.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 Crawlspace2MP
{
public class ActorRecorder
{
public struct Frame
{
public Vector3 HeadPos;
public Quaternion HeadRot;
public Vector3 LeftHandPos;
public Quaternion LeftHandRot;
public Vector3 RightHandPos;
public Quaternion RightHandRot;
public float LeftGrip;
public float LeftTrigger;
public float RightGrip;
public float RightTrigger;
}
public class Recording
{
public List Frames = new List();
public string Name;
public float FrameInterval;
}
public class Actor
{
public string Name;
public Recording Recording;
public RemotePlayer Visual;
public int CurrentFrame;
public float FrameTimer;
public bool IsPlaying;
public bool IsLooping;
}
private Recording _currentRecording;
private float _recordTimer;
private const float RECORD_INTERVAL = 0.033f;
private int _nextActorId = 1;
public bool IsRecording { get; private set; }
public List Recordings { get; } = new List();
public List Actors { get; } = new List();
public void StartRecording()
{
_currentRecording = new Recording
{
Name = $"Recording {Recordings.Count + 1}",
FrameInterval = 0.033f,
Frames = new List()
};
_recordTimer = 0f;
IsRecording = true;
}
public void StopRecording()
{
if (IsRecording)
{
IsRecording = false;
if (_currentRecording.Frames.Count > 0)
{
Recordings.Add(_currentRecording);
}
_currentRecording = null;
}
}
public void CaptureFrame()
{
//IL_0281: Unknown result type (might be due to invalid IL or missing references)
//IL_0282: Unknown result type (might be due to invalid IL or missing references)
//IL_0289: 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)
//IL_0291: Unknown result type (might be due to invalid IL or missing references)
//IL_0292: Unknown result type (might be due to invalid IL or missing references)
//IL_0299: Unknown result type (might be due to invalid IL or missing references)
//IL_029b: Unknown result type (might be due to invalid IL or missing references)
//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
//IL_0124: Unknown result type (might be due to invalid IL or missing references)
//IL_0129: Unknown result type (might be due to invalid IL or missing references)
//IL_0131: Unknown result type (might be due to invalid IL or missing references)
//IL_0136: Unknown result type (might be due to invalid IL or missing references)
//IL_0137: Unknown result type (might be due to invalid IL or missing references)
//IL_013f: Unknown result type (might be due to invalid IL or missing references)
//IL_0149: Unknown result type (might be due to invalid IL or missing references)
//IL_014e: Unknown result type (might be due to invalid IL or missing references)
//IL_015a: Unknown result type (might be due to invalid IL or missing references)
//IL_0164: Unknown result type (might be due to invalid IL or missing references)
//IL_0169: Unknown result type (might be due to invalid IL or missing references)
//IL_016e: Unknown result type (might be due to invalid IL or missing references)
//IL_016f: Unknown result type (might be due to invalid IL or missing references)
//IL_0170: Unknown result type (might be due to invalid IL or missing references)
//IL_0172: Unknown result type (might be due to invalid IL or missing references)
//IL_017a: 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_0189: 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_019f: Unknown result type (might be due to invalid IL or missing references)
//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
//IL_00db: Unknown result type (might be due to invalid IL or missing references)
//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
//IL_00e8: 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_00f0: Unknown result type (might be due to invalid IL or missing references)
//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
//IL_00f8: 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_0101: Unknown result type (might be due to invalid IL or missing references)
//IL_0104: 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_01ef: Unknown result type (might be due to invalid IL or missing references)
//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
//IL_020b: Unknown result type (might be due to invalid IL or missing references)
//IL_0210: Unknown result type (might be due to invalid IL or missing references)
//IL_0236: Unknown result type (might be due to invalid IL or missing references)
//IL_023b: Unknown result type (might be due to invalid IL or missing references)
//IL_0252: Unknown result type (might be due to invalid IL or missing references)
//IL_0257: Unknown result type (might be due to invalid IL or missing references)
if (!IsRecording || _currentRecording == null)
{
return;
}
_recordTimer += Time.deltaTime;
if (_recordTimer < 0.033f)
{
return;
}
_recordTimer -= 0.033f;
BackpackControl val = Object.FindObjectOfType();
Camera main = Camera.main;
Transform val2 = null;
Transform val3 = null;
Transform val4 = null;
if ((Object)(object)val != (Object)null)
{
if ((Object)(object)val.cam != (Object)null)
{
val2 = val.cam.transform;
}
if ((Object)(object)val.leftHand != (Object)null)
{
val3 = val.leftHand.transform;
}
if ((Object)(object)val.rightHand != (Object)null)
{
val4 = val.rightHand.transform;
}
}
Vector3 position;
Quaternion rotation;
Vector3 leftHandPos;
Quaternion leftHandRot;
Vector3 rightHandPos;
Quaternion rightHandRot;
if ((Object)(object)val2 != (Object)null && (Object)(object)val3 != (Object)null && (Object)(object)val4 != (Object)null)
{
position = val2.position;
rotation = val2.rotation;
leftHandPos = val3.position;
leftHandRot = val3.rotation;
rightHandPos = val4.position;
rightHandRot = val4.rotation;
}
else
{
if (!((Object)(object)main != (Object)null))
{
return;
}
position = ((Component)main).transform.position;
rotation = ((Component)main).transform.rotation;
leftHandPos = position + ((Component)main).transform.right * -0.3f + ((Component)main).transform.forward * 0.2f;
leftHandRot = rotation;
rightHandPos = position + ((Component)main).transform.right * 0.3f + ((Component)main).transform.forward * 0.2f;
rightHandRot = rotation;
}
float leftGrip = 0f;
float leftTrigger = 0f;
float rightGrip = 0f;
float rightTrigger = 0f;
if ((Object)(object)val != (Object)null)
{
try
{
InputActionProperty val5;
if ((Object)(object)val.controllerLeft != (Object)null)
{
val5 = val.controllerLeft.selectActionValue;
leftGrip = ((InputActionProperty)(ref val5)).action.ReadValue();
val5 = val.controllerLeft.uiPressActionValue;
leftTrigger = ((InputActionProperty)(ref val5)).action.ReadValue();
}
if ((Object)(object)val.controllerRight != (Object)null)
{
val5 = val.controllerRight.selectActionValue;
rightGrip = ((InputActionProperty)(ref val5)).action.ReadValue();
val5 = val.controllerRight.uiPressActionValue;
rightTrigger = ((InputActionProperty)(ref val5)).action.ReadValue();
}
}
catch
{
}
}
_currentRecording.Frames.Add(new Frame
{
HeadPos = position,
HeadRot = rotation,
LeftHandPos = leftHandPos,
LeftHandRot = leftHandRot,
RightHandPos = rightHandPos,
RightHandRot = rightHandRot,
LeftGrip = leftGrip,
LeftTrigger = leftTrigger,
RightGrip = rightGrip,
RightTrigger = rightTrigger
});
}
public Actor SpawnActor(Recording recording, bool loop = true)
{
RemotePlayer visual = new RemotePlayer(-100 - _nextActorId);
Actor actor = new Actor
{
Name = $"Actor {_nextActorId} ({recording.Name})",
Recording = recording,
Visual = visual,
CurrentFrame = 0,
FrameTimer = 0f,
IsPlaying = true,
IsLooping = loop
};
_nextActorId++;
Actors.Add(actor);
if (recording.Frames.Count > 0)
{
ApplyFrame(actor, recording.Frames[0]);
}
return actor;
}
public void RemoveActor(Actor actor)
{
actor.Visual?.Destroy();
Actors.Remove(actor);
}
public void RemoveAllActors()
{
for (int num = Actors.Count - 1; num >= 0; num--)
{
Actors[num].Visual?.Destroy();
}
Actors.Clear();
}
public void DeleteRecording(Recording recording)
{
for (int num = Actors.Count - 1; num >= 0; num--)
{
if (Actors[num].Recording == recording)
{
Actors[num].Visual?.Destroy();
Actors.RemoveAt(num);
}
}
Recordings.Remove(recording);
}
public void ToggleActor(Actor actor)
{
actor.IsPlaying = !actor.IsPlaying;
if (actor.IsPlaying)
{
actor.CurrentFrame = 0;
actor.FrameTimer = 0f;
}
}
public void Update()
{
//IL_0135: Unknown result type (might be due to invalid IL or missing references)
//IL_013c: Unknown result type (might be due to invalid IL or missing references)
//IL_0142: 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_0150: Unknown result type (might be due to invalid IL or missing references)
//IL_0157: 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_016b: Unknown result type (might be due to invalid IL or missing references)
//IL_0172: Unknown result type (might be due to invalid IL or missing references)
//IL_0178: Unknown result type (might be due to invalid IL or missing references)
//IL_017d: Unknown result type (might be due to invalid IL or missing references)
//IL_0186: Unknown result type (might be due to invalid IL or missing references)
//IL_018d: Unknown result type (might be due to invalid IL or missing references)
//IL_0193: Unknown result type (might be due to invalid IL or missing references)
//IL_0198: Unknown result type (might be due to invalid IL or missing references)
//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
//IL_01ae: 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_01bc: Unknown result type (might be due to invalid IL or missing references)
//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
foreach (Actor actor in Actors)
{
if (!actor.IsPlaying || actor.Recording.Frames.Count == 0)
{
continue;
}
actor.FrameTimer += Time.deltaTime;
if (actor.FrameTimer >= actor.Recording.FrameInterval)
{
actor.FrameTimer -= actor.Recording.FrameInterval;
actor.CurrentFrame++;
if (actor.CurrentFrame >= actor.Recording.Frames.Count)
{
if (!actor.IsLooping)
{
actor.CurrentFrame = actor.Recording.Frames.Count - 1;
actor.IsPlaying = false;
continue;
}
actor.CurrentFrame = 0;
}
}
int index = (actor.CurrentFrame + 1) % actor.Recording.Frames.Count;
float num = actor.FrameTimer / actor.Recording.FrameInterval;
Frame frame = actor.Recording.Frames[actor.CurrentFrame];
Frame frame2 = actor.Recording.Frames[index];
Frame frame3 = new Frame
{
HeadPos = Vector3.Lerp(frame.HeadPos, frame2.HeadPos, num),
HeadRot = Quaternion.Slerp(frame.HeadRot, frame2.HeadRot, num),
LeftHandPos = Vector3.Lerp(frame.LeftHandPos, frame2.LeftHandPos, num),
LeftHandRot = Quaternion.Slerp(frame.LeftHandRot, frame2.LeftHandRot, num),
RightHandPos = Vector3.Lerp(frame.RightHandPos, frame2.RightHandPos, num),
RightHandRot = Quaternion.Slerp(frame.RightHandRot, frame2.RightHandRot, num),
LeftGrip = Mathf.Lerp(frame.LeftGrip, frame2.LeftGrip, num),
LeftTrigger = Mathf.Lerp(frame.LeftTrigger, frame2.LeftTrigger, num),
RightGrip = Mathf.Lerp(frame.RightGrip, frame2.RightGrip, num),
RightTrigger = Mathf.Lerp(frame.RightTrigger, frame2.RightTrigger, num)
};
ApplyFrame(actor, frame3);
}
}
private void ApplyFrame(Actor actor, Frame frame)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: 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_003f: 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_004c: 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_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: 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_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
if (actor.Visual != null)
{
Vector3 bodyPos = frame.HeadPos - Vector3.up * 0.5f;
Quaternion bodyRot = Quaternion.Euler(0f, ((Quaternion)(ref frame.HeadRot)).eulerAngles.y, 0f);
actor.Visual.SetTargets(isStanding: true, bodyPos, bodyRot, frame.HeadPos, frame.HeadRot, frame.LeftHandPos, frame.LeftHandRot, frame.RightHandPos, frame.RightHandRot, frame.LeftGrip, frame.LeftTrigger, frame.RightGrip, frame.RightTrigger);
actor.Visual.UpdateInterpolation();
}
}
public void Cleanup()
{
if (IsRecording)
{
StopRecording();
}
RemoveAllActors();
Recordings.Clear();
}
}
public class PlayerSync
{
public class RemoteBatteryState
{
public float Charge;
public int LocationID;
public bool InBackpack;
public bool LeftHolding;
public bool RightHolding;
}
private class PendingPuzzleInit
{
public bool[] ActiveStates;
public int[] PresetIDs;
public bool[] CompletedStates;
public int[][] BlockStates;
public int TotalCompleted;
public int RequiredPuzzles;
}
private const byte PACKET_PLAYER_POSITION = 1;
private const byte PACKET_FLASHLIGHT = 2;
private const byte PACKET_SCENE_CHANGE = 3;
private const byte PACKET_NIGHT_SELECTED = 4;
private const byte PACKET_TV_SYNC = 5;
private const byte PACKET_PAINTING_SYNC = 6;
private const byte PACKET_PAINTING_FLASH = 7;
private const byte PACKET_MONSTER_SYNC = 8;
private const byte PACKET_JEFF_FLASH = 9;
private const byte PACKET_BATTERY_SYNC = 10;
private const byte PACKET_PAINTING_ENTITY = 11;
private const byte PACKET_PUZZLE_INIT = 12;
private const byte PACKET_PUZZLE_COMPLETE = 13;
private const byte PACKET_PUZZLE_BLOCK = 14;
private const byte PACKET_CLOWN_HONK = 15;
private const byte PACKET_VENT_SOUND = 16;
private const byte PACKET_CLOWN_STATE = 25;
private const byte PACKET_CLOWN_ATTACK = 26;
private const byte PACKET_SMILE_TRIGGER = 27;
private const byte PACKET_VENT_DOOR = 28;
private const byte PACKET_PAINTING_DEATH = 29;
private const byte PACKET_END_PROGRESS = 40;
private const byte PACKET_INTERACTION_LOCK = 17;
private const byte PACKET_EXIT_DOOR_PROGRESS = 18;
private const byte PACKET_CRANK_SYNC = 19;
private const byte PACKET_DEATH_GHOST = 20;
private const byte PACKET_VERSION_CHECK = 21;
private const byte PACKET_PING = 22;
private const byte PACKET_PONG = 23;
private const byte PACKET_HOST_MIGRATION = 24;
private const byte PACKET_EAR_COVERING = 41;
private const byte PACKET_TARGETED_KILL = 42;
private Dictionary _remotePlayers = new Dictionary();
private bool _remotePlayerCoveringEars;
private Dictionary _peerVersions = new Dictionary();
private Dictionary _peerPings = new Dictionary();
private Dictionary _pendingPings = new Dictionary();
private float _lastPingTime;
private const float PING_INTERVAL = 2f;
private Vector3 _levelSpawnPoint = Vector3.zero;
private Quaternion _levelSpawnRotation = Quaternion.identity;
private bool _spawnPointCaptured;
private HashSet _connectedPeerIds = new HashSet();
private bool _localIsGhost;
private bool _pendingGhostTeleport;
private bool _pendingHomeLoad;
private float _pendingHomeLoadTimer;
private string _ghostSceneToReload;
public static bool IsGhostSceneReload = false;
private Player _gorillaPlayer;
private MoveTypeController _moveController;
private HandControl _handControl;
private Camera _mainCamera;
private Transform _playerTransform;
private Transform _ovrLeftHand;
private Transform _ovrRightHand;
private Transform _ovrHead;
private float _syncInterval = 0.033f;
private float _lastSyncTime;
private Flashlight _localFlashlight;
private FlashlightControl _localFlashlightControl;
private bool _lastFlashlightState;
private string _lastScene = "";
public static bool IsLoadingFromSync = false;
private int _lastNightSelected = -1;
private VideoPlayer _tvVideoPlayer;
private float _lastTvSyncTime;
private float _tvSyncInterval = 5f;
private paintingControl _paintingControl;
private float _lastPaintingSyncTime;
private float _paintingSyncInterval = 1f;
private sparkyBrain _sparky;
private jeffBrain _jeff;
private SmileBrain _smile;
private henryBrain _henry;
private mapEnBrain _harold;
private clownRandom _clown;
private float _lastMonsterSyncTime;
private float _monsterSyncInterval = 0.1f;
private bool _hostDiedInLevel;
private float _lastBatterySyncTime;
private float _batterySyncInterval = 0.1f;
private int _lastBatteryLocationID = -999;
private bool _lastBatteryInBackpack;
private float _lastBatteryCharge = -1f;
private bool _lastLeftHolding;
private bool _lastRightHolding;
private Dictionary _remoteBatteryStates = new Dictionary();
private crankControl _crankControl;
private float _lastCrankSyncTime;
private float _crankSyncInterval = 0.2f;
private float _lastCrankCharge = -1f;
private bool _lastCrankHasBattery;
private static Dictionary _interactionLocks = new Dictionary();
private static Dictionary _lockTimestamps = new Dictionary();
private const float LOCK_TIMEOUT = 5f;
private float _lastLockCleanupTime;
private HashSet _localActiveLocks = new HashSet();
private float _sceneLoadDelayTimer;
private const float SCENE_LOAD_DELAY = 0.5f;
private PuzzleMaster _puzzleMaster;
private bool _puzzleInitSent;
private PendingPuzzleInit _savedGhostPuzzleState;
private LeaveDoorControl _leaveDoor;
private int _lastDoorLeaveTimer;
private float _lastDoorSyncTime;
private bool _exitDoorFullyCharged;
private PacketWriter _writer = new PacketWriter(1024);
private INetworkTransport _steam;
private bool _recreateRemotePlayersNextFrame;
private int _updateCount;
private int _sendCount;
private string _pendingSceneLoad;
private bool _isReceivingPaintingFlash;
private bool _isReceivingJeffFlash;
private float _lastTargetedKillTime;
private Quaternion _lastCrankRotation = Quaternion.identity;
private bool _remoteCrankHasBattery;
private float _remoteCrankChargeTarget;
private float _remoteCrankChargeDisplay;
private Quaternion _remoteCrankRotTarget = Quaternion.identity;
private Quaternion _remoteCrankRotDisplay = Quaternion.identity;
private int _lastTotalCompletedPuzzles = -1;
private PendingPuzzleInit _pendingPuzzleInit;
private bool _puzzleInitStartWaited;
private bool _puzzleInitApplied;
private float _puzzleInitReapplyTimer;
private const float PUZZLE_INIT_REAPPLY_DURATION = 3f;
private bool[] _puzzleInitCompletedStates;
private bool[] _puzzleInitActiveStates;
private HashSet _completedPuzzleIDs = new HashSet();
private bool _isReceivingPuzzleBlock;
private bool _isReceivingHonk;
private clownRandom _clownRandom;
private bool _isReceivingVentSound;
public bool DebugForceGhostOnDeath;
private bool _pendingGhostPuzzleRestore;
private int _ghostPuzzleRestoreFrames;
private GameObject _ghostVisionLight;
private float _ghostTeleportDelay;
private Dictionary _ventDoorTimers = new Dictionary();
private EndControl _endControl;
private int _lastEndImageID = -1;
private float _lastEndBarFill = -1f;
private bool _lastEarCoveringState;
public bool IsAnyPlayerCoveringEars
{
get
{
if (!earMaster.isCoveringEars)
{
return _remotePlayerCoveringEars;
}
return true;
}
}
public float AveragePing
{
get
{
if (_peerPings.Count <= 0)
{
return -1f;
}
return GetAveragePing();
}
}
public bool IsLocalGhost => _localIsGhost;
public bool IsDyingThisFrame { get; set; }
public bool ShouldControlMonsters
{
get
{
if (_steam != null)
{
if (!_steam.IsHost)
{
return _hostDiedInLevel;
}
return true;
}
return false;
}
}
public bool IsReceivingPaintingFlash => _isReceivingPaintingFlash;
public bool IsReceivingJeffFlash => _isReceivingJeffFlash;
public bool RemoteHasBatteryInCrank => _remoteCrankHasBattery;
public float RemoteCrankChargeDisplay => _remoteCrankChargeDisplay;
public Quaternion RemoteCrankRotationDisplay => _remoteCrankRotDisplay;
public bool PuzzleInitApplied
{
get
{
if (!_puzzleInitApplied)
{
return _pendingPuzzleInit != null;
}
return true;
}
}
public bool IsReceivingPuzzleBlock => _isReceivingPuzzleBlock;
public bool IsReceivingHonk => _isReceivingHonk;
public bool IsReceivingVentSound => _isReceivingVentSound;
public event Action OnVersionMismatch;
public event Action OnBecameHost;
public float GetPing(int peerId)
{
if (!_peerPings.TryGetValue(peerId, out var value))
{
return -1f;
}
return value;
}
private float GetAveragePing()
{
if (_peerPings.Count == 0)
{
return -1f;
}
float num = 0f;
foreach (float value in _peerPings.Values)
{
num += value;
}
return num / (float)_peerPings.Count;
}
public static bool IsLockedByOther(string interactionId)
{
if (_interactionLocks.TryGetValue(interactionId, out var value))
{
if (_lockTimestamps.TryGetValue(interactionId, out var value2) && Time.time - value2 > 5f)
{
_interactionLocks.Remove(interactionId);
_lockTimestamps.Remove(interactionId);
return false;
}
return value != -1;
}
return false;
}
public static bool IsLockedByUs(string interactionId)
{
if (_interactionLocks.TryGetValue(interactionId, out var value))
{
return value == -1;
}
return false;
}
public void RefreshLock(string interactionId)
{
if (_interactionLocks.TryGetValue(interactionId, out var value) && value != -1)
{
if (_lockTimestamps.TryGetValue(interactionId, out var value2) && Time.time - value2 > 5f)
{
_interactionLocks[interactionId] = -1;
_lockTimestamps[interactionId] = Time.time;
_localActiveLocks.Add(interactionId);
SendInteractionLock(interactionId, locked: true);
}
return;
}
bool num = !_interactionLocks.ContainsKey(interactionId) || _interactionLocks[interactionId] != -1;
_interactionLocks[interactionId] = -1;
_lockTimestamps[interactionId] = Time.time;
if (num)
{
_localActiveLocks.Add(interactionId);
SendInteractionLock(interactionId, locked: true);
}
}
public bool TryAcquireLock(string interactionId)
{
if (IsLockedByOther(interactionId))
{
return false;
}
RefreshLock(interactionId);
return true;
}
public void ReleaseLock(string interactionId)
{
if (_interactionLocks.TryGetValue(interactionId, out var value) && value == -1)
{
_interactionLocks.Remove(interactionId);
_lockTimestamps.Remove(interactionId);
_localActiveLocks.Remove(interactionId);
SendInteractionLock(interactionId, locked: false);
}
}
private void CleanupExpiredLocks()
{
if (Time.time - _lastLockCleanupTime < 1f)
{
return;
}
_lastLockCleanupTime = Time.time;
List list = new List();
foreach (KeyValuePair lockTimestamp in _lockTimestamps)
{
if (Time.time - lockTimestamp.Value > 10f)
{
list.Add(lockTimestamp.Key);
}
}
foreach (string item in list)
{
_interactionLocks.Remove(item);
_lockTimestamps.Remove(item);
_localActiveLocks.Remove(item);
}
}
public void ClearAllLocks()
{
_interactionLocks.Clear();
_lockTimestamps.Clear();
_localActiveLocks.Clear();
}
public void Initialize(INetworkTransport steam)
{
_steam = steam;
_steam.OnPeerConnected += OnPeerConnected;
_steam.OnPeerDisconnected += OnPeerDisconnected;
_steam.OnDataReceived += OnDataReceived;
SceneManager.sceneLoaded += OnSceneLoaded;
}
private void OnPeerConnected(int peerId)
{
_connectedPeerIds.Add(peerId);
if (!_remotePlayers.ContainsKey(peerId))
{
RemotePlayer value = new RemotePlayer(peerId);
_remotePlayers[peerId] = value;
}
SendVersionCheck(peerId);
SendBatterySync();
}
private void OnPeerDisconnected(int peerId)
{
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
_connectedPeerIds.Remove(peerId);
_peerVersions.Remove(peerId);
_peerPings.Remove(peerId);
_pendingPings.Remove(peerId);
if (_remotePlayers.TryGetValue(peerId, out var value))
{
value.Destroy();
_remotePlayers.Remove(peerId);
}
MPManager.Instance?.Spectate?.StopReceiving();
MPManager.Instance?.Spectate?.StopSending();
if (_localIsGhost && _remotePlayers.Count == 0)
{
Scene activeScene = SceneManager.GetActiveScene();
if (((Scene)(ref activeScene)).name.Contains("Night") && !_pendingHomeLoad)
{
_pendingHomeLoad = true;
_pendingHomeLoadTimer = 1f;
}
}
}
private void OnDataReceived(int peerId, PacketReader reader)
{
if (reader.AvailableBytes >= 1)
{
byte b = reader.GetByte();
switch (b)
{
case 1:
HandlePositionPacket(peerId, reader);
break;
case 2:
HandleFlashlightPacket(peerId, reader);
break;
case 3:
HandleSceneChangePacket(reader);
break;
case 4:
HandleNightSelectedPacket(reader);
break;
case 5:
HandleTvSyncPacket(reader);
break;
case 6:
HandlePaintingSyncPacket(reader);
break;
case 7:
HandlePaintingFlashPacket(reader);
break;
case 8:
HandleMonsterSyncPacket(reader);
break;
case 9:
HandleJeffFlashPacket();
break;
case 10:
HandleBatterySync(peerId, reader);
break;
case 11:
HandlePaintingEntity(reader);
break;
case 12:
HandlePuzzleInit(reader);
break;
case 13:
HandlePuzzleComplete(reader);
break;
case 14:
HandlePuzzleBlock(reader);
break;
case 15:
HandleClownHonk(reader);
break;
case 16:
HandleVentSoundPacket(reader);
break;
case 17:
HandleInteractionLockPacket(peerId, reader);
break;
case 18:
HandleExitDoorProgressPacket(reader);
break;
case 19:
HandleCrankSyncPacket(reader);
break;
case 20:
HandleDeathGhostPacket(peerId, reader);
break;
case 21:
HandleVersionCheck(peerId, reader);
break;
case 22:
HandlePing(peerId, reader);
break;
case 23:
HandlePong(peerId, reader);
break;
case 24:
HandleHostMigration(peerId, reader);
break;
case 25:
HandleClownState(reader);
break;
case 26:
HandleClownAttack(reader);
break;
case 27:
HandleSmileTrigger(reader);
break;
case 28:
HandleVentDoor(reader);
break;
case 29:
HandlePaintingDeath();
break;
case 40:
HandleEndProgress(reader);
break;
case 41:
HandleEarCovering(reader);
break;
case 42:
HandleTargetedKill(reader);
break;
case 200:
MPManager.Instance?.VoiceChat?.OnVoiceDataReceived(peerId, reader);
break;
case 30:
case 31:
case 32:
MPManager.Instance?.Spectate?.OnPacketReceived(b, reader);
break;
default:
Plugin.Log.LogWarning((object)$"Unknown packet type: {b}");
break;
}
}
}
private void HandlePositionPacket(int peerId, PacketReader reader)
{
//IL_011a: 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_011c: Unknown result type (might be due to invalid IL or missing references)
//IL_011e: Unknown result type (might be due to invalid IL or missing references)
//IL_0120: Unknown result type (might be due to invalid IL or missing references)
//IL_0122: Unknown result type (might be due to invalid IL or missing references)
//IL_0124: Unknown result type (might be due to invalid IL or missing references)
//IL_0126: Unknown result type (might be due to invalid IL or missing references)
if (_remotePlayers.TryGetValue(peerId, out var value))
{
bool isStanding = reader.GetBool();
Vector3 bodyPos = default(Vector3);
((Vector3)(ref bodyPos))..ctor(reader.GetFloat(), reader.GetFloat(), reader.GetFloat());
Quaternion bodyRot = default(Quaternion);
((Quaternion)(ref bodyRot))..ctor(reader.GetFloat(), reader.GetFloat(), reader.GetFloat(), reader.GetFloat());
Vector3 headPos = default(Vector3);
((Vector3)(ref headPos))..ctor(reader.GetFloat(), reader.GetFloat(), reader.GetFloat());
Quaternion headRot = default(Quaternion);
((Quaternion)(ref headRot))..ctor(reader.GetFloat(), reader.GetFloat(), reader.GetFloat(), reader.GetFloat());
Vector3 leftHandPos = default(Vector3);
((Vector3)(ref leftHandPos))..ctor(reader.GetFloat(), reader.GetFloat(), reader.GetFloat());
Quaternion leftHandRot = default(Quaternion);
((Quaternion)(ref leftHandRot))..ctor(reader.GetFloat(), reader.GetFloat(), reader.GetFloat(), reader.GetFloat());
Vector3 rightHandPos = default(Vector3);
((Vector3)(ref rightHandPos))..ctor(reader.GetFloat(), reader.GetFloat(), reader.GetFloat());
Quaternion rightHandRot = default(Quaternion);
((Quaternion)(ref rightHandRot))..ctor(reader.GetFloat(), reader.GetFloat(), reader.GetFloat(), reader.GetFloat());
float leftGrip = reader.GetFloat();
float leftTrigger = reader.GetFloat();
float rightGrip = reader.GetFloat();
float rightTrigger = reader.GetFloat();
value.SetTargets(isStanding, bodyPos, bodyRot, headPos, headRot, leftHandPos, leftHandRot, rightHandPos, rightHandRot, leftGrip, leftTrigger, rightGrip, rightTrigger);
}
}
private void HandleFlashlightPacket(int peerId, PacketReader reader)
{
bool flashlightState = reader.GetBool();
if (_remotePlayers.TryGetValue(peerId, out var value))
{
value.SetFlashlightState(flashlightState);
}
}
private void HandleSceneChangePacket(PacketReader reader)
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
string text = reader.GetString();
int nightSelected = reader.GetInt();
Scene activeScene = SceneManager.GetActiveScene();
string name = ((Scene)(ref activeScene)).name;
if (text.Equals("Home", StringComparison.OrdinalIgnoreCase) && name.Contains("Night"))
{
sceneLeave val = Object.FindObjectOfType();
if ((Object)(object)val != (Object)null)
{
val.loadSelectedNight();
}
}
calenderControl.nightSelected = nightSelected;
if (_steam.IsHost && _localIsGhost)
{
IsLoadingFromSync = true;
ResetGhostState();
SceneManager.LoadScene(text);
}
else if (_steam.IsHost)
{
IsLoadingFromSync = true;
TriggerClientFade();
SceneManager.LoadScene(text);
}
else
{
IsLoadingFromSync = true;
_lastScene = text;
_pendingSceneLoad = text;
_sceneLoadDelayTimer = 0.1f;
TriggerClientFade();
}
}
private void HandleNightSelectedPacket(PacketReader reader)
{
calenderControl.nightSelected = reader.GetInt();
calenderControl val = Object.FindObjectOfType();
if ((Object)(object)val != (Object)null)
{
val.setNightText();
}
}
private void HandleTvSyncPacket(PacketReader reader)
{
long num = reader.GetLong();
if ((Object)(object)_tvVideoPlayer == (Object)null)
{
tvControl val = Object.FindObjectOfType();
if ((Object)(object)val != (Object)null && (Object)(object)val.TVVP != (Object)null)
{
_tvVideoPlayer = val.TVVP;
}
}
if ((Object)(object)_tvVideoPlayer != (Object)null && _tvVideoPlayer.isPrepared && Math.Abs(_tvVideoPlayer.frame - num) > 30)
{
_tvVideoPlayer.frame = num;
}
}
private void HandlePaintingSyncPacket(PacketReader reader)
{
if ((Object)(object)_paintingControl == (Object)null)
{
_paintingControl = Object.FindObjectOfType();
}
if (!((Object)(object)_paintingControl == (Object)null))
{
int num = reader.GetInt();
int num2 = reader.GetInt();
int num3 = reader.GetInt();
int num4 = reader.GetInt();
int num5 = reader.GetInt();
int num6 = reader.GetInt();
_paintingControl.intpaintingTall1 = num;
_paintingControl.intpaintingTall2 = num2;
_paintingControl.intpaintingTall3 = num3;
_paintingControl.intpaintingSquare1 = num4;
_paintingControl.intpaintingSquare2 = num5;
_paintingControl.intpaintingSquare3 = num6;
Type? typeFromHandle = typeof(paintingControl);
BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.NonPublic;
bool flag = (bool)typeFromHandle.GetField("boolpaintingTall1", bindingAttr).GetValue(_paintingControl);
bool flag2 = (bool)typeFromHandle.GetField("boolpaintingTall2", bindingAttr).GetValue(_paintingControl);
bool flag3 = (bool)typeFromHandle.GetField("boolpaintingTall3", bindingAttr).GetValue(_paintingControl);
bool flag4 = (bool)typeFromHandle.GetField("boolpaintingSquare1", bindingAttr).GetValue(_paintingControl);
bool flag5 = (bool)typeFromHandle.GetField("boolpaintingSquare2", bindingAttr).GetValue(_paintingControl);
bool flag6 = (bool)typeFromHandle.GetField("boolpaintingSquare3", bindingAttr).GetValue(_paintingControl);
_paintingControl.setPaintingMatSquare(_paintingControl.paintingTall1, num, flag, true);
_paintingControl.setPaintingMatSquare(_paintingControl.paintingTall2, num2, flag2, true);
_paintingControl.setPaintingMatSquare(_paintingControl.paintingTall3, num3, flag3, true);
_paintingControl.setPaintingMatSquare(_paintingControl.paintingSquare1, num4, flag4, false);
_paintingControl.setPaintingMatSquare(_paintingControl.paintingSquare2, num5, flag5, false);
_paintingControl.setPaintingMatSquare(_paintingControl.paintingSquare3, num6, flag6, false);
}
}
private void HandlePaintingFlashPacket(PacketReader reader)
{
int num = reader.GetInt();
_isReceivingPaintingFlash = true;
paintingControl paintingControl = _paintingControl;
if (paintingControl != null)
{
paintingControl.onPaintingFlash(num);
}
_isReceivingPaintingFlash = false;
}
private void HandleMonsterSyncPacket(PacketReader reader)
{
//IL_0132: Unknown result type (might be due to invalid IL or missing references)
//IL_0137: Unknown result type (might be due to invalid IL or missing references)
//IL_013b: 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_0223: Unknown result type (might be due to invalid IL or missing references)
//IL_0228: Unknown result type (might be due to invalid IL or missing references)
//IL_022c: Unknown result type (might be due to invalid IL or missing references)
//IL_0231: Unknown result type (might be due to invalid IL or missing references)
//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
//IL_0282: Unknown result type (might be due to invalid IL or missing references)
//IL_0294: Unknown result type (might be due to invalid IL or missing references)
if (_steam.IsHost || _hostDiedInLevel)
{
return;
}
FindMonsters();
if (reader.GetBool())
{
int num = reader.GetInt();
if ((Object)(object)_sparky != (Object)null)
{
FieldInfo field = typeof(sparkyBrain).GetField("currentState", BindingFlags.Instance | BindingFlags.NonPublic);
int num2 = ((!(field != null)) ? 1 : ((int)field.GetValue(_sparky)));
if (num == 2 && num2 == 1)
{
field?.SetValue(_sparky, num);
}
}
}
if (reader.GetBool())
{
reader.GetBool();
int num3 = reader.GetInt();
reader.GetInt();
if ((Object)(object)_jeff != (Object)null)
{
FieldInfo field2 = typeof(jeffBrain).GetField("currentState", BindingFlags.Instance | BindingFlags.NonPublic);
int num4 = ((!(field2 != null)) ? 1 : ((int)field2.GetValue(_jeff)));
if (num3 == 2 && num4 == 1)
{
field2?.SetValue(_jeff, 2);
}
}
}
if (reader.GetBool())
{
reader.GetBool();
reader.GetInt();
}
if (reader.GetBool())
{
Vector3 position = ReadVector3(reader);
Quaternion rotation = ReadQuaternion(reader);
bool flag = reader.GetBool();
bool flag2 = reader.GetBool();
if ((Object)(object)_henry != (Object)null)
{
if ((Object)(object)_henry.agent != (Object)null && ((Behaviour)_henry.agent).enabled)
{
((Behaviour)_henry.agent).enabled = false;
}
((Component)_henry).transform.position = position;
((Component)_henry).transform.rotation = rotation;
typeof(henryBrain).GetField("resetSwitch", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(_henry, flag);
typeof(henryBrain).GetField("chaseSwitch", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(_henry, flag2);
}
}
if (reader.GetBool())
{
Vector3 position2 = ReadVector3(reader);
Quaternion rotation2 = ReadQuaternion(reader);
if ((Object)(object)_harold != (Object)null)
{
if ((Object)(object)_harold.agent != (Object)null && ((Behaviour)_harold.agent).enabled)
{
((Behaviour)_harold.agent).enabled = false;
}
((Component)_harold).transform.position = position2;
((Component)_harold).transform.rotation = rotation2;
}
}
if (!reader.GetBool())
{
return;
}
int num5 = reader.GetInt();
if ((Object)(object)_clown != (Object)null)
{
if ((Object)(object)_clown.clown1 != (Object)null)
{
_clown.clown1.SetActive(num5 == 0);
}
if ((Object)(object)_clown.clown2 != (Object)null)
{
_clown.clown2.SetActive(num5 == 1);
}
if ((Object)(object)_clown.clown3 != (Object)null)
{
_clown.clown3.SetActive(num5 == 2);
}
if ((Object)(object)_clown.clown4 != (Object)null)
{
_clown.clown4.SetActive(num5 == 3);
}
if ((Object)(object)_clown.clown5 != (Object)null)
{
_clown.clown5.SetActive(num5 == 4);
}
if ((Object)(object)_clown.clown6 != (Object)null)
{
_clown.clown6.SetActive(num5 == 5);
}
if ((Object)(object)_clown.clown7 != (Object)null)
{
_clown.clown7.SetActive(num5 == 6);
}
}
}
private void HandleJeffFlashPacket()
{
_isReceivingJeffFlash = true;
jeffBrain jeff = _jeff;
if (jeff != null)
{
jeff.onFlash();
}
_isReceivingJeffFlash = false;
}
private void HandleVentSoundPacket(PacketReader reader)
{
HandleVentSound(reader);
}
private void HandleInteractionLockPacket(int peerId, PacketReader reader)
{
string key = reader.GetString();
if (reader.GetBool())
{
_interactionLocks[key] = peerId;
_lockTimestamps[key] = Time.time;
}
else
{
_interactionLocks.Remove(key);
_lockTimestamps.Remove(key);
}
}
private void HandleExitDoorProgressPacket(PacketReader reader)
{
int num = reader.GetInt();
int num2 = reader.GetInt();
if (BackpackControl.batteryLocationID == 100 && BackpackControl.batteryCharge >= 0.1f)
{
return;
}
if ((Object)(object)_leaveDoor == (Object)null)
{
_leaveDoor = Object.FindObjectOfType();
}
if (!((Object)(object)_leaveDoor != (Object)null))
{
return;
}
typeof(LeaveDoorControl).GetField("doorLeaveTimer", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(_leaveDoor, num);
typeof(LeaveDoorControl).GetField("loadingBarLock", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(_leaveDoor, num > 0);
if ((Object)(object)_leaveDoor.fillImg != (Object)null && num2 > 0)
{
_leaveDoor.fillImg.fillAmount = (float)num / (float)num2;
}
if ((Object)(object)_leaveDoor.fillIcon != (Object)null)
{
_leaveDoor.fillIcon.SetActive(num > 0);
}
FieldInfo field = typeof(LeaveDoorControl).GetField("puzzleCount", BindingFlags.Instance | BindingFlags.Public);
if (field != null && num > 0 && num2 > 0)
{
object value = field.GetValue(_leaveDoor);
if (value != null)
{
PropertyInfo property = value.GetType().GetProperty("text");
if (property != null)
{
int num3 = (int)Math.Round((float)num / (float)num2 * 100f);
if (num >= num2)
{
property.SetValue(value, "100%");
if ((Object)(object)_leaveDoor.doorLeaveHitbox != (Object)null)
{
_leaveDoor.doorLeaveHitbox.SetActive(true);
}
_exitDoorFullyCharged = true;
}
else
{
property.SetValue(value, num3 + "%");
}
}
}
}
if (num > 0)
{
if ((Object)(object)_leaveDoor.greenIcon != (Object)null)
{
_leaveDoor.greenIcon.SetActive(false);
}
if ((Object)(object)_leaveDoor.redIcon != (Object)null)
{
_leaveDoor.redIcon.SetActive(false);
}
}
}
private void HandleCrankSyncPacket(PacketReader reader)
{
//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_0025: 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)
bool flag = reader.GetBool();
float num = reader.GetFloat();
Quaternion remoteCrankRotTarget = ReadQuaternion(reader);
_remoteCrankHasBattery = flag;
_remoteCrankChargeTarget = num;
_remoteCrankRotTarget = remoteCrankRotTarget;
if (flag && _remoteCrankChargeDisplay < 0.01f)
{
_remoteCrankChargeDisplay = num;
}
if (!flag)
{
_remoteCrankChargeTarget = 0f;
_remoteCrankChargeDisplay = 0f;
}
}
private void HandleDeathGhostPacket(int peerId, PacketReader reader)
{
//IL_0274: Unknown result type (might be due to invalid IL or missing references)
//IL_0279: Unknown result type (might be due to invalid IL or missing references)
//IL_0218: Unknown result type (might be due to invalid IL or missing references)
//IL_021d: Unknown result type (might be due to invalid IL or missing references)
bool flag = reader.GetBool();
int num = reader.GetInt();
Plugin.Log.LogInfo((object)$"[Death] Received death packet from peer {peerId}: isGhost={flag}, deathType={num}");
if (_remotePlayers.TryGetValue(peerId, out var value))
{
value.SetGhostState(flag);
Plugin.Log.LogInfo((object)$"[Death] Set peer {peerId} ghost state to {flag}");
}
if (flag && _remoteBatteryStates.ContainsKey(peerId))
{
_remoteBatteryStates[peerId].LocationID = 0;
_remoteBatteryStates[peerId].Charge = 0f;
_remoteBatteryStates[peerId].LeftHolding = false;
_remoteBatteryStates[peerId].RightHolding = false;
_remoteBatteryStates[peerId].InBackpack = false;
Plugin.LogDebug($"[Death] Cleared battery state for dead peer {peerId}");
}
if (flag)
{
List list = new List();
foreach (KeyValuePair interactionLock in _interactionLocks)
{
if (interactionLock.Value == peerId)
{
list.Add(interactionLock.Key);
}
}
foreach (string item in list)
{
_interactionLocks.Remove(item);
_lockTimestamps.Remove(item);
}
if (list.Count > 0)
{
Plugin.LogDebug($"[Death] Cleared {list.Count} interaction locks from dead peer {peerId}");
}
}
_remoteCrankHasBattery = false;
Scene activeScene;
if (_localIsGhost && flag)
{
bool flag2 = false;
foreach (KeyValuePair remotePlayer in _remotePlayers)
{
if (!remotePlayer.Value.IsGhost)
{
flag2 = true;
break;
}
}
if (!flag2)
{
activeScene = SceneManager.GetActiveScene();
if (((Scene)(ref activeScene)).name.Contains("Night"))
{
Plugin.Log.LogInfo((object)"[Ghost] All players dead - scheduling Home load");
_pendingHomeLoad = true;
_pendingHomeLoadTimer = 3f;
return;
}
}
}
Plugin.LogDebug($"[Death] Partner death handled - LocalGhost={_localIsGhost}, RemoteGhost={flag}");
activeScene = SceneManager.GetActiveScene();
string name = ((Scene)(ref activeScene)).name;
if (!flag || _localIsGhost || !name.Contains("Night"))
{
return;
}
MPManager.Instance?.Spectate?.StartSending();
if (_steam.IsHost)
{
return;
}
_hostDiedInLevel = true;
Plugin.Log.LogInfo((object)"[Client] Host died - taking over monster control!");
FindMonsters();
if ((Object)(object)_sparky != (Object)null)
{
NavMeshAgent component = ((Component)_sparky).GetComponent();
if ((Object)(object)component != (Object)null)
{
((Behaviour)component).enabled = true;
}
}
if ((Object)(object)_jeff != (Object)null)
{
NavMeshAgent component2 = ((Component)_jeff).GetComponent();
if ((Object)(object)component2 != (Object)null)
{
((Behaviour)component2).enabled = true;
}
}
if ((Object)(object)_smile != (Object)null)
{
NavMeshAgent component3 = ((Component)_smile).GetComponent();
if ((Object)(object)component3 != (Object)null)
{
((Behaviour)component3).enabled = true;
}
}
if ((Object)(object)_henry != (Object)null)
{
NavMeshAgent component4 = ((Component)_henry).GetComponent();
if ((Object)(object)component4 != (Object)null)
{
((Behaviour)component4).enabled = true;
}
}
if ((Object)(object)_harold != (Object)null)
{
NavMeshAgent component5 = ((Component)_harold).GetComponent();
if ((Object)(object)component5 != (Object)null)
{
((Behaviour)component5).enabled = true;
}
}
}
private void SendToAllPeers(bool reliable = true)
{
if (_steam != null && _steam.IsRunning)
{
byte[] bytes = _writer.GetBytes();
_steam.SendToAll(bytes, reliable);
}
}
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
Plugin.Log.LogInfo((object)$"OnSceneLoaded: {((Scene)(ref scene)).name}, IsGhost={_localIsGhost}");
MinimapFriendPatch.Cleanup();
ClearAllLocks();
_spawnPointCaptured = false;
_hostDiedInLevel = false;
if (_localIsGhost && _pendingGhostTeleport && ((Scene)(ref scene)).name.Contains("Night"))
{
Plugin.Log.LogInfo((object)"[Ghost] Scene loaded as ghost, preparing teleport");
HandleGhostSceneLoaded();
}
if (((Scene)(ref scene)).name.Equals("Home", StringComparison.OrdinalIgnoreCase))
{
if (_localIsGhost)
{
Plugin.Log.LogInfo((object)"[Ghost] Entered Home, resetting ghost state");
ResetGhostState();
}
_pendingPuzzleInit = null;
}
if (((Scene)(ref scene)).name.Equals("Home", StringComparison.OrdinalIgnoreCase) || !((Scene)(ref scene)).name.Contains("Night"))
{
MPManager.Instance?.Spectate?.StopSending();
MPManager.Instance?.Spectate?.StopReceiving();
}
if (((Scene)(ref scene)).name == _lastScene && !IsLoadingFromSync)
{
if (_steam == null || !_steam.IsRunning || _connectedPeerIds.Count <= 0)
{
return;
}
foreach (RemotePlayer value in _remotePlayers.Values)
{
value.Destroy();
}
_remotePlayers.Clear();
_recreateRemotePlayersNextFrame = true;
return;
}
Plugin.Log.LogInfo((object)("Scene loaded: " + ((Scene)(ref scene)).name));
IsLoadingFromSync = false;
_lastScene = ((Scene)(ref scene)).name;
foreach (RemotePlayer value2 in _remotePlayers.Values)
{
value2.Destroy();
}
_remotePlayers.Clear();
_remoteBatteryStates.Clear();
_puzzleMaster = null;
_puzzleInitSent = false;
_puzzleInitStartWaited = false;
_puzzleInitApplied = false;
_puzzleInitReapplyTimer = 0f;
_puzzleInitCompletedStates = null;
_puzzleInitActiveStates = null;
_completedPuzzleIDs.Clear();
ClearAllLocks();
if (_steam != null && _steam != null && _steam.IsRunning)
{
_recreateRemotePlayersNextFrame = true;
}
}
public void Cleanup()
{
SceneManager.sceneLoaded -= OnSceneLoaded;
ClearRemotePlayers();
ClearAllLocks();
ResetGhostState();
_connectedPeerIds.Clear();
_remoteBatteryStates.Clear();
_pendingPuzzleInit = null;
Plugin.Log.LogInfo((object)"PlayerSync cleaned up");
}
public void Update()
{
//IL_0201: Unknown result type (might be due to invalid IL or missing references)
//IL_0227: Unknown result type (might be due to invalid IL or missing references)
//IL_0242: 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)
_updateCount++;
if (_steam == null)
{
return;
}
UpdateCrankInterpolation();
IsDyingThisFrame = false;
if (_steam.IsRunning && _steam.IsConnected && Time.realtimeSinceStartup - _lastPingTime > 2f)
{
_lastPingTime = Time.realtimeSinceStartup;
SendPingToAll();
}
if (_pendingHomeLoad)
{
_pendingHomeLoadTimer -= Time.deltaTime;
if (_pendingHomeLoadTimer <= 0f)
{
_pendingHomeLoad = false;
bool flag = true;
foreach (KeyValuePair remotePlayer in _remotePlayers)
{
if (!remotePlayer.Value.IsGhost)
{
flag = false;
break;
}
}
if (flag && _localIsGhost)
{
Scene activeScene = SceneManager.GetActiveScene();
if (((Scene)(ref activeScene)).name.Contains("Night"))
{
Plugin.Log.LogInfo((object)"[Ghost] EXECUTING DEFERRED HOME LOAD - all players dead");
ResetGhostState();
IsLoadingFromSync = true;
SceneManager.LoadScene("Home");
return;
}
}
}
}
if (_pendingSceneLoad != null)
{
if (_sceneLoadDelayTimer > 0f)
{
_sceneLoadDelayTimer -= Time.deltaTime;
return;
}
string pendingSceneLoad = _pendingSceneLoad;
_pendingSceneLoad = null;
_sceneLoadDelayTimer = 0f;
Plugin.Log.LogInfo((object)("[Client] EXECUTING DEFERRED SCENE LOAD: " + pendingSceneLoad));
try
{
TriggerClientFade();
SceneManager.LoadScene(pendingSceneLoad);
}
catch (Exception arg)
{
Plugin.Log.LogError((object)$"[Client] SceneManager.LoadScene FAILED: {arg}");
}
}
if (_recreateRemotePlayersNextFrame)
{
_recreateRemotePlayersNextFrame = false;
RecreateRemotePlayers();
}
UpdateGhostTeleport();
if (_localIsGhost && _spawnPointCaptured && _ghostTeleportDelay <= 0f)
{
Camera val = _mainCamera ?? Camera.main;
if ((Object)(object)val != (Object)null && ((Component)val).transform.position.y < -5f)
{
Plugin.Log.LogInfo((object)$"[Ghost] Fell through map (Y={((Component)_mainCamera).transform.position.y:F1}), re-teleporting to spawn");
TeleportLocalPlayer(_levelSpawnPoint);
}
}
if (_pendingGhostPuzzleRestore)
{
_ghostPuzzleRestoreFrames--;
if (_ghostPuzzleRestoreFrames <= 0)
{
_pendingGhostPuzzleRestore = false;
RestoreGhostPuzzleState();
}
}
foreach (RemotePlayer value in _remotePlayers.Values)
{
value.UpdateInterpolation();
}
if (!_steam.IsRunning || (!_steam.IsHost && !_steam.IsConnected && !_steam.IsInLobby))
{
return;
}
if (!_spawnPointCaptured && _updateCount > 10)
{
CaptureSpawnPoint();
}
if (_updateCount % 300 == 0)
{
Plugin.LogDebug($"PlayerSync.Update: remotePlayers={_remotePlayers.Count}, ping={AveragePing:F0}ms");
}
if ((Object)(object)_gorillaPlayer == (Object)null && (Object)(object)_handControl == (Object)null && (Object)(object)_mainCamera == (Object)null && (Object)(object)_ovrHead == (Object)null)
{
_gorillaPlayer = Player.Instance;
_handControl = Object.FindObjectOfType();
_moveController = Object.FindObjectOfType();
_mainCamera = Camera.main;
MonoBehaviour[] array = Object.FindObjectsOfType();
foreach (MonoBehaviour val2 in array)
{
Type type = ((object)val2).GetType();
if (type.Name == "OVRCameraRig")
{
object? obj = type.GetProperty("centerEyeAnchor")?.GetValue(val2);
Transform val3 = (Transform)((obj is Transform) ? obj : null);
object? obj2 = type.GetProperty("leftHandAnchor")?.GetValue(val2);
Transform val4 = (Transform)((obj2 is Transform) ? obj2 : null);
object? obj3 = type.GetProperty("rightHandAnchor")?.GetValue(val2);
Transform val5 = (Transform)((obj3 is Transform) ? obj3 : null);
if ((Object)(object)val3 != (Object)null && (Object)(object)val4 != (Object)null && (Object)(object)val5 != (Object)null)
{
_ovrHead = val3;
_ovrLeftHand = val4;
_ovrRightHand = val5;
}
break;
}
}
if ((Object)(object)_ovrLeftHand == (Object)null || (Object)(object)_ovrRightHand == (Object)null)
{
BackpackControl val6 = Object.FindObjectOfType();
if ((Object)(object)val6 != (Object)null)
{
if ((Object)(object)val6.leftHand != (Object)null)
{
_ovrLeftHand = val6.leftHand.transform;
}
if ((Object)(object)val6.rightHand != (Object)null)
{
_ovrRightHand = val6.rightHand.transform;
}
if ((Object)(object)val6.cam != (Object)null && (Object)(object)_ovrHead == (Object)null)
{
_ovrHead = val6.cam.transform;
}
}
}
if ((Object)(object)_ovrLeftHand == (Object)null || (Object)(object)_ovrRightHand == (Object)null)
{
ActionBasedController[] array2 = Object.FindObjectsOfType();
foreach (ActionBasedController val7 in array2)
{
string text = ((Object)((Component)val7).gameObject).name.ToLower();
if (text.Contains("left") && (Object)(object)_ovrLeftHand == (Object)null)
{
_ovrLeftHand = ((Component)val7).transform;
}
else if (text.Contains("right") && (Object)(object)_ovrRightHand == (Object)null)
{
_ovrRightHand = ((Component)val7).transform;
}
}
}
if ((Object)(object)_ovrLeftHand == (Object)null || (Object)(object)_ovrRightHand == (Object)null)
{
crankControl val8 = Object.FindObjectOfType();
if ((Object)(object)val8 != (Object)null)
{
if ((Object)(object)val8.handLeft != (Object)null && (Object)(object)_ovrLeftHand == (Object)null)
{
_ovrLeftHand = val8.handLeft.transform;
}
if ((Object)(object)val8.handRight != (Object)null && (Object)(object)_ovrRightHand == (Object)null)
{
_ovrRightHand = val8.handRight.transform;
}
}
}
Plugin.Log.LogInfo((object)("[Tracking] Head=" + (((Object)(object)_ovrHead != (Object)null) ? ((Object)_ovrHead).name : "NONE") + ", LHand=" + (((Object)(object)_ovrLeftHand != (Object)null) ? ((Object)_ovrLeftHand).name : "NONE") + ", RHand=" + (((Object)(object)_ovrRightHand != (Object)null) ? ((Object)_ovrRightHand).name : "NONE")));
if ((Object)(object)_gorillaPlayer != (Object)null)
{
_playerTransform = ((Component)_gorillaPlayer).transform;
}
}
if (!((Object)(object)_gorillaPlayer == (Object)null) || !((Object)(object)_handControl == (Object)null) || !((Object)(object)_mainCamera == (Object)null))
{
if (Time.time - _lastSyncTime >= _syncInterval)
{
SendPositionUpdate();
_lastSyncTime = Time.time;
}
CheckFlashlightState();
CheckSceneChange();
CheckCalendarChange();
CheckTvSync();
CheckPaintingSync();
CheckMonsterSync();
CheckBatterySync();
CheckCrankSync();
CheckPuzzleInitSync();
if (_pendingPuzzleInit != null && !_steam.IsHost)
{
TryApplyPuzzleInit();
}
ReapplyPuzzleIndicators();
CheckExitDoorSync();
CheckEndSceneSync();
CheckEarCoveringSync();
CleanupExpiredLocks();
}
}
private void CheckCalendarChange()
{
if (_steam.IsHost)
{
int nightSelected = calenderControl.nightSelected;
if (nightSelected != _lastNightSelected)
{
_lastNightSelected = nightSelected;
SendNightSelected(nightSelected);
}
}
}
private void CheckTvSync()
{
if (!_steam.IsHost || _localIsGhost || Time.time - _lastTvSyncTime < _tvSyncInterval)
{
return;
}
_lastTvSyncTime = Time.time;
if ((Object)(object)_tvVideoPlayer == (Object)null)
{
tvControl val = Object.FindObjectOfType();
if ((Object)(object)val != (Object)null && (Object)(object)val.TVVP != (Object)null)
{
_tvVideoPlayer = val.TVVP;
}
else
{
MoviePlayerSample val2 = Object.FindObjectOfType();
if ((Object)(object)val2 != (Object)null)
{
_tvVideoPlayer = ((Component)val2).GetComponent();
if ((Object)(object)_tvVideoPlayer != (Object)null)
{
Plugin.LogDebug("Found TV VideoPlayer");
}
}
}
}
if ((Object)(object)_tvVideoPlayer != (Object)null && _tvVideoPlayer.isPlaying)
{
SendTvSync(_tvVideoPlayer.frame);
}
}
private void SendTvSync(long frame)
{
_writer.Reset();
_writer.Put((byte)5);
_writer.Put(frame);
SendToAllPeers();
}
private void CheckPaintingSync()
{
if (_steam.IsHost && !_localIsGhost && !(Time.time - _lastPaintingSyncTime < _paintingSyncInterval))
{
_lastPaintingSyncTime = Time.time;
if ((Object)(object)_paintingControl == (Object)null)
{
_paintingControl = Object.FindObjectOfType();
}
if ((Object)(object)_paintingControl != (Object)null)
{
SendPaintingSync();
}
}
}
private void SendPaintingSync()
{
_writer.Reset();
_writer.Put((byte)6);
_writer.Put(_paintingControl.intpaintingTall1);
_writer.Put(_paintingControl.intpaintingTall2);
_writer.Put(_paintingControl.intpaintingTall3);
_writer.Put(_paintingControl.intpaintingSquare1);
_writer.Put(_paintingControl.intpaintingSquare2);
_writer.Put(_paintingControl.intpaintingSquare3);
SendToAllPeers();
}
private void SendNightSelected(int night)
{
_writer.Reset();
_writer.Put((byte)4);
_writer.Put(night);
SendToAllPeers();
Plugin.Log.LogInfo((object)$"[Host] Sent night selection: {night}");
}
private void CheckSceneChange()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
Scene activeScene = SceneManager.GetActiveScene();
string name = ((Scene)(ref activeScene)).name;
if (!(name != _lastScene))
{
return;
}
Plugin.Log.LogInfo((object)("Scene changed: " + _lastScene + " -> " + name));
_ = _lastScene;
_lastScene = name;
if (_steam.IsHost && !IsLoadingFromSync)
{
SendSceneChange(name);
}
_gorillaPlayer = null;
_handControl = null;
_mainCamera = null;
_moveController = null;
_ovrHead = null;
_ovrLeftHand = null;
_ovrRightHand = null;
_localFlashlight = null;
_localFlashlightControl = null;
_tvVideoPlayer = null;
_paintingControl = null;
_sparky = null;
_jeff = null;
_smile = null;
_henry = null;
_harold = null;
_clown = null;
_puzzleMaster = null;
_puzzleInitSent = false;
_puzzleInitStartWaited = false;
_puzzleInitApplied = false;
_puzzleInitReapplyTimer = 0f;
_puzzleInitCompletedStates = null;
_puzzleInitActiveStates = null;
_completedPuzzleIDs.Clear();
_leaveDoor = null;
_lastDoorLeaveTimer = 0;
_exitDoorFullyCharged = false;
_crankControl = null;
_lastCrankCharge = -1f;
_lastCrankHasBattery = false;
if (_steam == null || !_steam.IsRunning || _connectedPeerIds.Count <= 0)
{
return;
}
foreach (RemotePlayer value in _remotePlayers.Values)
{
value.Destroy();
}
_remotePlayers.Clear();
_remoteBatteryStates.Clear();
ClearAllLocks();
_recreateRemotePlayersNextFrame = true;
}
private bool AnyRemotePlayerValid()
{
foreach (RemotePlayer value in _remotePlayers.Values)
{
if ((Object)(object)value.Head != (Object)null)
{
return true;
}
}
return false;
}
private void ClearRemotePlayers()
{
foreach (RemotePlayer value in _remotePlayers.Values)
{
value.Destroy();
}
_remotePlayers.Clear();
}
private void RecreateRemotePlayers()
{
if (_steam == null || _steam == null)
{
return;
}
foreach (int connectedPeerId in _connectedPeerIds)
{
if (!_remotePlayers.ContainsKey(connectedPeerId))
{
RemotePlayer value = new RemotePlayer(connectedPeerId);
_remotePlayers[connectedPeerId] = value;
}
else
{
_remotePlayers[connectedPeerId].TryUpgradeVisuals();
}
}
Plugin.Log.LogInfo((object)$"Remote players recreated: {_remotePlayers.Count}");
}
public void SendSceneChange(string sceneName)
{
_writer.Reset();
_writer.Put((byte)3);
_writer.Put(sceneName);
_writer.Put(calenderControl.nightSelected);
SendToAllPeers();
Plugin.Log.LogInfo((object)$"Sent scene change: {sceneName}, night={calenderControl.nightSelected}");
}
private void CheckFlashlightState()
{
bool flag = false;
bool flag2 = false;
if ((Object)(object)_localFlashlightControl == (Object)null)
{
_localFlashlightControl = Object.FindObjectOfType();
}
if ((Object)(object)_localFlashlightControl != (Object)null && (Object)(object)_localFlashlightControl.flashlight != (Object)null)
{
flag = _localFlashlightControl.flashlight.activeSelf;
flag2 = true;
}
if (!flag2)
{
if ((Object)(object)_localFlashlight == (Object)null)
{
_localFlashlight = Object.FindObjectOfType();
}
if ((Object)(object)_localFlashlight != (Object)null && (Object)(object)_localFlashlight.spotlight != (Object)null)
{
flag = ((Behaviour)_localFlashlight.spotlight).enabled;
flag2 = true;
}
}
if (flag2 && flag != _lastFlashlightState)
{
_lastFlashlightState = flag;
SendFlashlightState(flag);
}
}
private void SendFlashlightState(bool isOn)
{
_writer.Reset();
_writer.Put((byte)2);
_writer.Put(isOn);
SendToAllPeers();
}
private void CaptureHandPoses(ref float leftGrip, ref float leftTrigger, ref float rightGrip, ref float rightTrigger)
{
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: 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_0046: 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_0089: 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)
BackpackControl val = Object.FindObjectOfType();
if (!((Object)(object)val != (Object)null))
{
return;
}
InputActionProperty val2;
if ((Object)(object)val.controllerLeft != (Object)null)
{
try
{
val2 = val.controllerLeft.selectActionValue;
leftGrip = ((InputActionProperty)(ref val2)).action.ReadValue();
val2 = val.controllerLeft.uiPressActionValue;
leftTrigger = ((InputActionProperty)(ref val2)).action.ReadValue();
}
catch (Exception)
{
}
}
if ((Object)(object)val.controllerRight != (Object)null)
{
try
{
val2 = val.controllerRight.selectActionValue;
rightGrip = ((InputActionProperty)(ref val2)).action.ReadValue();
val2 = val.controllerRight.uiPressActionValue;
rightTrigger = ((InputActionProperty)(ref val2)).action.ReadValue();
}
catch (Exception)
{
}
}
}
private void SendPositionUpdate()
{
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_009e: Unknown result type (might be due to invalid IL or missing references)
//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_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_00be: Unknown result type (might be due to invalid IL or missing references)
//IL_00c3: 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_0279: 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)
//IL_028b: Unknown result type (might be due to invalid IL or missing references)
//IL_0297: Unknown result type (might be due to invalid IL or missing references)
//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
//IL_02da: Unknown result type (might be due to invalid IL or missing references)
//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
//IL_0303: Unknown result type (might be due to invalid IL or missing references)
//IL_0308: Unknown result type (might be due to invalid IL or missing references)
//IL_030d: Unknown result type (might be due to invalid IL or missing references)
//IL_030e: Unknown result type (might be due to invalid IL or missing references)
//IL_030f: 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_0120: Unknown result type (might be due to invalid IL or missing references)
//IL_0131: Unknown result type (might be due to invalid IL or missing references)
//IL_0136: Unknown result type (might be due to invalid IL or missing references)
//IL_0142: 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_0153: Unknown result type (might be due to invalid IL or missing references)
//IL_0158: Unknown result type (might be due to invalid IL or missing references)
//IL_0165: Unknown result type (might be due to invalid IL or missing references)
//IL_016a: Unknown result type (might be due to invalid IL or missing references)
//IL_0176: Unknown result type (might be due to invalid IL or missing references)
//IL_017b: Unknown result type (might be due to invalid IL or missing references)
//IL_0314: Unknown result type (might be due to invalid IL or missing references)
//IL_0315: Unknown result type (might be due to invalid IL or missing references)
//IL_031f: Unknown result type (might be due to invalid IL or missing references)
//IL_0324: Unknown result type (might be due to invalid IL or missing references)
//IL_0329: Unknown result type (might be due to invalid IL or missing references)
//IL_0332: Unknown result type (might be due to invalid IL or missing references)
//IL_0341: Unknown result type (might be due to invalid IL or missing references)
//IL_0346: Unknown result type (might be due to invalid IL or missing references)
//IL_0386: Unknown result type (might be due to invalid IL or missing references)
//IL_0394: Unknown result type (might be due to invalid IL or missing references)
//IL_03a2: Unknown result type (might be due to invalid IL or missing references)
//IL_03af: Unknown result type (might be due to invalid IL or missing references)
//IL_03bc: Unknown result type (might be due to invalid IL or missing references)
//IL_03c9: Unknown result type (might be due to invalid IL or missing references)
//IL_03d7: Unknown result type (might be due to invalid IL or missing references)
//IL_03e4: Unknown result type (might be due to invalid IL or missing references)
//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
//IL_01db: Unknown result type (might be due to invalid IL or missing references)
//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
//IL_0202: Unknown result type (might be due to invalid IL or missing references)
//IL_0207: Unknown result type (might be due to invalid IL or missing references)
//IL_0218: Unknown result type (might be due to invalid IL or missing references)
//IL_021d: Unknown result type (might be due to invalid IL or missing references)
//IL_022f: Unknown result type (might be due to invalid IL or missing references)
//IL_0234: Unknown result type (might be due to invalid IL or missing references)
//IL_0245: Unknown result type (might be due to invalid IL or missing references)
//IL_024a: Unknown result type (might be due to invalid IL or missing references)
_writer.Reset();
_writer.Put((byte)1);
bool value = (Object)(object)_moveController != (Object)null && _moveController.debugSwitch;
_sendCount++;
string text = "none";
Vector3 position;
Quaternion rotation;
Vector3 v;
Quaternion q;
Vector3 v2;
Quaternion q2;
if ((Object)(object)_ovrHead != (Object)null && (Object)(object)_ovrLeftHand != (Object)null && (Object)(object)_ovrRightHand != (Object)null)
{
text = "OVR/BackpackControl";
position = _ovrHead.position;
rotation = _ovrHead.rotation;
v = _ovrLeftHand.position;
q = _ovrLeftHand.rotation;
v2 = _ovrRightHand.position;
q2 = _ovrRightHand.rotation;
}
else if ((Object)(object)_gorillaPlayer != (Object)null && (Object)(object)_gorillaPlayer.leftHandTransform != (Object)null && (Object)(object)_gorillaPlayer.rightHandTransform != (Object)null)
{
text = "GorillaPlayer";
position = ((Component)_gorillaPlayer.headCollider).transform.position;
rotation = ((Component)_gorillaPlayer.headCollider).transform.rotation;
v = _gorillaPlayer.leftHandTransform.position;
q = _gorillaPlayer.leftHandTransform.rotation;
v2 = _gorillaPlayer.rightHandTransform.position;
q2 = _gorillaPlayer.rightHandTransform.rotation;
}
else if ((Object)(object)_handControl != (Object)null && (Object)(object)_handControl.LTarget != (Object)null && (Object)(object)_handControl.RTarget != (Object)null)
{
text = "HandControl";
position = _handControl.Head.transform.position;
rotation = _handControl.Head.transform.rotation;
v = _handControl.LTarget.transform.position;
q = _handControl.LTarget.transform.rotation;
v2 = _handControl.RTarget.transform.position;
q2 = _handControl.RTarget.transform.rotation;
}
else
{
if (!((Object)(object)_mainCamera != (Object)null))
{
return;
}
text = "MainCamera-NoHands";
position = ((Component)_mainCamera).transform.position;
rotation = ((Component)_mainCamera).transform.rotation;
v = position + ((Component)_mainCamera).transform.right * -0.3f + ((Component)_mainCamera).transform.forward * 0.2f;
q = rotation;
v2 = position + ((Component)_mainCamera).transform.right * 0.3f + ((Component)_mainCamera).transform.forward * 0.2f;
q2 = rotation;
}
Vector3 v3 = position - Vector3.up * 0.5f;
Quaternion q3 = Quaternion.Euler(0f, ((Quaternion)(ref rotation)).eulerAngles.y, 0f);
float leftGrip = 0f;
float leftTrigger = 0f;
float rightGrip = 0f;
float rightTrigger = 0f;
CaptureHandPoses(ref leftGrip, ref leftTrigger, ref rightGrip, ref rightTrigger);
_writer.Put(value);
WriteVector3(_writer, v3);
WriteQuaternion(_writer, q3);
WriteVector3(_writer, position);
WriteQuaternion(_writer, rotation);
WriteVector3(_writer, v);
WriteQuaternion(_writer, q);
WriteVector3(_writer, v2);
WriteQuaternion(_writer, q2);
_writer.Put(leftGrip);
_writer.Put(leftTrigger);
_writer.Put(rightGrip);
_writer.Put(rightTrigger);
if (_sendCount % 100 == 1)
{
Plugin.LogDebug("[Send] src=" + text);
}
SendToAllPeers(reliable: false);
}
private void WriteVector3(PacketWriter writer, Vector3 v)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
writer.Put(v.x);
writer.Put(v.y);
writer.Put(v.z);
}
private void WriteQuaternion(PacketWriter writer, Quaternion q)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
writer.Put(q.x);
writer.Put(q.y);
writer.Put(q.z);
writer.Put(q.w);
}
private Vector3 ReadVector3(PacketReader reader)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
return new Vector3(reader.GetFloat(), reader.GetFloat(), reader.GetFloat());
}
private Quaternion ReadQuaternion(PacketReader reader)
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
return new Quaternion(reader.GetFloat(), reader.GetFloat(), reader.GetFloat(), reader.GetFloat());
}
private void SendInteractionLock(string interactionId, bool locked)
{
if (_steam != null && _steam.IsRunning)
{
_writer.Reset();
_writer.Put((byte)17);
_writer.Put(interactionId);
_writer.Put(locked);
SendToAllPeers();
}
}
private void TriggerClientFade()
{
try
{
Type type = Type.GetType("fadeControl, Assembly-CSharp");
if (type == null)
{
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
for (int i = 0; i < assemblies.Length; i++)
{
type = assemblies[i].GetType("fadeControl");
if (type != null)
{
break;
}
}
}
if (!(type != null))
{
return;
}
Object val = Object.FindObjectOfType(type);
if (val != (Object)null)
{
MethodInfo method = type.GetMethod("fadeOut", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (method != null)
{
method.Invoke(val, null);
}
}
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("[Client] Could not trigger fade: " + ex.Message));
}
}
private void HandleTvSync(PacketReader reader)
{
long num = reader.GetLong();
if (_steam.IsHost)
{
return;
}
if ((Object)(object)_tvVideoPlayer == (Object)null)
{
tvControl val = Object.FindObjectOfType();
if ((Object)(object)val != (Object)null && (Object)(object)val.TVVP != (Object)null)
{
_tvVideoPlayer = val.TVVP;
}
else
{
MoviePlayerSample val2 = Object.FindObjectOfType();
if ((Object)(object)val2 != (Object)null)
{
_tvVideoPlayer = ((Component)val2).GetComponent();
}
}
}
if ((Object)(object)_tvVideoPlayer != (Object)null && Math.Abs(_tvVideoPlayer.frame - num) > 30)
{
_tvVideoPlayer.frame = num;
}
}
private void HandlePaintingSync(PacketReader reader)
{
if (_steam.IsHost)
{
return;
}
int num = reader.GetInt();
int num2 = reader.GetInt();
int num3 = reader.GetInt();
int num4 = reader.GetInt();
int num5 = reader.GetInt();
int num6 = reader.GetInt();
if ((Object)(object)_paintingControl == (Object)null)
{
_paintingControl = Object.FindObjectOfType();
}
if ((Object)(object)_paintingControl != (Object)null)
{
bool flag = false;
if (_paintingControl.intpaintingTall1 != num)
{
_paintingControl.intpaintingTall1 = num;
_paintingControl.setPaintingMatSquare(_paintingControl.paintingTall1, num, false, true);
flag = true;
}
if (_paintingControl.intpaintingTall2 != num2)
{
_paintingControl.intpaintingTall2 = num2;
_paintingControl.setPaintingMatSquare(_paintingControl.paintingTall2, num2, false, true);
flag = true;
}
if (_paintingControl.intpaintingTall3 != num3)
{
_paintingControl.intpaintingTall3 = num3;
_paintingControl.setPaintingMatSquare(_paintingControl.paintingTall3, num3, false, true);
flag = true;
}
if (_paintingControl.intpaintingSquare1 != num4)
{
_paintingControl.intpaintingSquare1 = num4;
_paintingControl.setPaintingMatSquare(_paintingControl.paintingSquare1, num4, false, false);
flag = true;
}
if (_paintingControl.intpaintingSquare2 != num5)
{
_paintingControl.intpaintingSquare2 = num5;
_paintingControl.setPaintingMatSquare(_paintingControl.paintingSquare2, num5, false, false);
flag = true;
}
if (_paintingControl.intpaintingSquare3 != num6)
{
_paintingControl.intpaintingSquare3 = num6;
_paintingControl.setPaintingMatSquare(_paintingControl.paintingSquare3, num6, false, false);
flag = true;
}
if (flag)
{
Plugin.LogDebug("[Client] Paintings synced from host");
}
}
}
public void SendPaintingFlash(int paintingId)
{
if (_steam != null && _steam.IsRunning)
{
_writer.Reset();
_writer.Put((byte)7);
_writer.Put(paintingId);
SendToAllPeers();
}
}
public void SendPaintingEntityState(paintingControl pc)
{
if (_steam != null && _steam.IsRunning && ShouldControlMonsters)
{
Type? typeFromHandle = typeof(paintingControl);
bool value = (bool)typeFromHandle.GetField("boolpaintingTall1", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(pc);
bool value2 = (bool)typeFromHandle.GetField("boolpaintingTall2", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(pc);
bool value3 = (bool)typeFromHandle.GetField("boolpaintingTall3", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(pc);
bool value4 = (bool)typeFromHandle.GetField("boolpaintingSquare1", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(pc);
bool value5 = (bool)typeFromHandle.GetField("boolpaintingSquare2", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(pc);
bool value6 = (bool)typeFromHandle.GetField("boolpaintingSquare3", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(pc);
_writer.Reset();
_writer.Put((byte)11);
_writer.Put(value);
_writer.Put(value2);
_writer.Put(value3);
_writer.Put(value4);
_writer.Put(value5);
_writer.Put(value6);
_writer.Put(pc.intpaintingTall1);
_writer.Put(pc.intpaintingTall2);
_writer.Put(pc.intpaintingTall3);
_writer.Put(pc.intpaintingSquare1);
_writer.Put(pc.intpaintingSquare2);
_writer.Put(pc.intpaintingSquare3);
SendToAllPeers();
}
}
private void HandlePaintingEntity(PacketReader reader)
{
bool flag = reader.GetBool();
bool flag2 = reader.GetBool();
bool flag3 = reader.GetBool();
bool flag4 = reader.GetBool();
bool flag5 = reader.GetBool();
bool flag6 = reader.GetBool();
int num = reader.GetInt();
int num2 = reader.GetInt();
int num3 = reader.GetInt();
int num4 = reader.GetInt();
int num5 = reader.GetInt();
int num6 = reader.GetInt();
if ((Object)(object)_paintingControl == (Object)null)
{
_paintingControl = Object.FindObjectOfType();
}
if ((Object)(object)_paintingControl != (Object)null)
{
Type? typeFromHandle = typeof(paintingControl);
typeFromHandle.GetField("boolpaintingTall1", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(_paintingControl, flag);
typeFromHandle.GetField("boolpaintingTall2", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(_paintingControl, flag2);
typeFromHandle.GetField("boolpaintingTall3", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(_paintingControl, flag3);
typeFromHandle.GetField("boolpaintingSquare1", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(_paintingControl, flag4);
typeFromHandle.GetField("boolpaintingSquare2", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(_paintingControl, flag5);
typeFromHandle.GetField("boolpaintingSquare3", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(_paintingControl, flag6);
_paintingControl.setPaintingMatSquare(_paintingControl.paintingTall1, num, flag, true);
_paintingControl.setPaintingMatSquare(_paintingControl.paintingTall2, num2, flag2, true);
_paintingControl.setPaintingMatSquare(_paintingControl.paintingTall3, num3, flag3, true);
_paintingControl.setPaintingMatSquare(_paintingControl.paintingSquare1, num4, flag4, false);
_paintingControl.setPaintingMatSquare(_paintingControl.paintingSquare2, num5, flag5, false);
_paintingControl.setPaintingMatSquare(_paintingControl.paintingSquare3, num6, flag6, false);
}
}
public List GetRemotePlayerPositions()
{
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
List list = new List();
foreach (RemotePlayer value in _remotePlayers.Values)
{
if ((Object)(object)value.Head != (Object)null)
{
list.Add(value.Head.transform.position);
}
}
return list;
}
public Vector3? GetRemotePlayerPosition(int peerId)
{
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
if (_remotePlayers.TryGetValue(peerId, out var value) && (Object)(object)value.Head != (Object)null)
{
return value.Head.transform.position;
}
return null;
}
public List GetRemotePlayerPositionsNonGhost()
{
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
List list = new List();
foreach (RemotePlayer value in _remotePlayers.Values)
{
if ((Object)(object)value.Head != (Object)null && !value.IsGhost)
{
list.Add(value.Head.transform.position);
}
}
return list;
}
private void CheckMonsterSync()
{
if (ShouldControlMonsters && !_localIsGhost && !(Time.time - _lastMonsterSyncTime < _monsterSyncInterval))
{
_lastMonsterSyncTime = Time.time;
FindMonsters();
CheckSyncedMonsterKills();
SendMonsterSync();
}
}
private void FindMonsters()
{
if ((Object)(object)_sparky == (Object)null)
{
_sparky = Object.FindObjectOfType();
}
if ((Object)(object)_jeff == (Object)null)
{
_jeff = Object.FindObjectOfType();
}
if ((Object)(object)_smile == (Object)null)
{
_smile = Object.FindObjectOfType();
}
if ((Object)(object)_henry == (Object)null)
{
_henry = Object.FindObjectOfType();
}
if ((Object)(object)_harold == (Object)null)
{
_harold = Object.FindObjectOfType();
}
if ((Object)(object)_clown == (Object)null)
{
_clown = Object.FindObjectOfType();
}
}
private void SendMonsterSync()
{
//IL_0192: Unknown result type (might be due to invalid IL or missing references)
//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
//IL_0272: Unknown result type (might be due to invalid IL or missing references)
//IL_028e: Unknown result type (might be due to invalid IL or missing references)
_writer.Reset();
_writer.Put((byte)8);
bool flag = (Object)(object)_sparky != (Object)null;
_writer.Put(flag);
if (flag)
{
FieldInfo field = typeof(sparkyBrain).GetField("currentState", BindingFlags.Instance | BindingFlags.NonPublic);
int value = ((!(field != null)) ? 1 : ((int)field.GetValue(_sparky)));
_writer.Put(value);
}
bool flag2 = (Object)(object)_jeff != (Object)null;
_writer.Put(flag2);
if (flag2)
{
_writer.Put((Object)(object)_jeff.jeffBody != (Object)null && _jeff.jeffBody.activeSelf);
FieldInfo field2 = typeof(jeffBrain).GetField("currentState", BindingFlags.Instance | BindingFlags.NonPublic);
int value2 = ((!(field2 != null)) ? 1 : ((int)field2.GetValue(_jeff)));
_writer.Put(value2);
FieldInfo field3 = typeof(jeffBrain).GetField("totalFlashes", BindingFlags.Instance | BindingFlags.NonPublic);
int value3 = ((field3 != null) ? ((int)field3.GetValue(_jeff)) : 0);
_writer.Put(value3);
}
_writer.Put(value: false);
bool flag3 = (Object)(object)_henry != (Object)null;
_writer.Put(flag3);
if (flag3)
{
WriteVector3(_writer, ((Component)_henry).transform.position);
WriteQuaternion(_writer, ((Component)_henry).transform.rotation);
FieldInfo field4 = typeof(henryBrain).GetField("resetSwitch", BindingFlags.Instance | BindingFlags.NonPublic);
bool value4 = field4 != null && (bool)field4.GetValue(_henry);
_writer.Put(value4);
FieldInfo field5 = typeof(henryBrain).GetField("chaseSwitch", BindingFlags.Instance | BindingFlags.NonPublic);
bool value5 = field5 != null && (bool)field5.GetValue(_henry);
_writer.Put(value5);
}
bool flag4 = (Object)(object)_harold != (Object)null;
_writer.Put(flag4);
if (flag4)
{
WriteVector3(_writer, ((Component)_harold).transform.position);
WriteQuaternion(_writer, ((Component)_harold).transform.rotation);
}
bool flag5 = (Object)(object)_clown != (Object)null;
_writer.Put(flag5);
if (flag5)
{
int value6 = -1;
if ((Object)(object)_clown.clown1 != (Object)null && _clown.clown1.activeSelf)
{
value6 = 0;
}
else if ((Object)(object)_clown.clown2 != (Object)null && _clown.clown2.activeSelf)
{
value6 = 1;
}
else if ((Object)(object)_clown.clown3 != (Object)null && _clown.clown3.activeSelf)
{
value6 = 2;
}
else if ((Object)(object)_clown.clown4 != (Object)null && _clown.clown4.activeSelf)
{
value6 = 3;
}
else if ((Object)(object)_clown.clown5 != (Object)null && _clown.clown5.activeSelf)
{
value6 = 4;
}
else if ((Object)(object)_clown.clown6 != (Object)null && _clown.clown6.activeSelf)
{
value6 = 5;
}
else if ((Object)(object)_clown.clown7 != (Object)null && _clown.clown7.activeSelf)
{
value6 = 6;
}
_writer.Put(value6);
}
SendToAllPeers(reliable: false);
}
private void CheckSyncedMonsterKills()
{
//IL_019f: Unknown result type (might be due to invalid IL or missing references)
//IL_01af: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
if (Time.time - _lastTargetedKillTime < 1f || _remotePlayers.Count == 0)
{
return;
}
if ((Object)(object)_henry != (Object)null)
{
FieldInfo field = typeof(henryBrain).GetField("resetSwitch", BindingFlags.Instance | BindingFlags.NonPublic);
if (!(field != null) || !(bool)field.GetValue(_henry))
{
foreach (KeyValuePair remotePlayer in _remotePlayers)
{
if (!remotePlayer.Value.IsGhost && !((Object)(object)remotePlayer.Value.Head == (Object)null))
{
float num = Vector3.Distance(remotePlayer.Value.Head.transform.position, ((Component)_henry).transform.position);
if (num < 0.6f)
{
Plugin.Log.LogInfo((object)$"[Host] Henry near peer {remotePlayer.Key} (dist={num:F2}) - sending targeted kill");
SendTargetedKillTo(remotePlayer.Key, 4);
_lastTargetedKillTime = Time.time;
return;
}
}
}
}
}
if (!((Object)(object)_harold != (Object)null))
{
return;
}
foreach (KeyValuePair remotePlayer2 in _remotePlayers)
{
if (!remotePlayer2.Value.IsGhost && !((Object)(object)remotePlayer2.Value.Head == (Object)null))
{
float num2 = Vector3.Distance(remotePlayer2.Value.Head.transform.position, ((Component)_harold).transform.position);
if (num2 < 0.6f)
{
Plugin.Log.LogInfo((object)$"[Host] Harold near peer {remotePlayer2.Key} (dist={num2:F2}) - sending targeted kill");
SendTargetedKillTo(remotePlayer2.Key, 2);
_lastTargetedKillTime = Time.time;
break;
}
}
}
}
private void SendTargetedKillTo(int peerId, int deathType)
{
if (_steam != null && _steam.IsRunning)
{
_writer.Reset();
_writer.Put((byte)42);
_writer.Put(deathType);
byte[] bytes = _writer.GetBytes();
_steam.SendTo(peerId, bytes);
}
}
private void HandleTargetedKill(PacketReader reader)
{
int num = reader.GetInt();
if (_localIsGhost)
{
return;
}
Plugin.Log.LogInfo((object)$"[Client] Received targeted kill from host: deathType={num}");
jumpscareController val = Object.FindObjectOfType();
if (!((Object)(object)val == (Object)null))
{
switch (num)
{
case 2:
val.onDeathHarold();
break;
case 4:
val.onDeathHenry();
break;
}
}
}
public void SendJeffFlash()
{
if (_steam != null && _steam.IsRunning)
{
_writer.Reset();
_writer.Put((byte)9);
SendToAllPeers();
}
}
private void CheckBatterySync()
{
if (Time.time - _lastBatterySyncTime < _batterySyncInterval)
{
return;
}
_lastBatterySyncTime = Time.time;
if (_localIsGhost)
{
return;
}
BackpackControl val = Object.FindObjectOfType();
bool flag = false;
bool flag2 = false;
if ((Object)(object)val != (Object)null)
{
FieldInfo field = typeof(BackpackControl).GetField("leftHoldingBattery", BindingFlags.Instance | BindingFlags.NonPublic);
FieldInfo field2 = typeof(BackpackControl).GetField("rightHoldingBattery", BindingFlags.Instance | BindingFlags.NonPublic);
if (field != null)
{
flag = (bool)field.GetValue(val);
}
if (field2 != null)
{
flag2 = (bool)field2.GetValue(val);
}
}
bool num = BackpackControl.batteryLocationID != _lastBatteryLocationID;
bool flag3 = BackpackControl.batteryIsInBackpack != _lastBatteryInBackpack;
bool flag4 = Mathf.Abs(BackpackControl.batteryCharge - _lastBatteryCharge) > 2f;
bool flag5 = flag != _lastLeftHolding || flag2 != _lastRightHolding;
if (num || flag3 || flag4 || flag5)
{
_lastBatteryLocationID = BackpackControl.batteryLocationID;
_lastBatteryInBackpack = BackpackControl.batteryIsInBackpack;
_lastBatteryCharge = BackpackControl.batteryCharge;
_lastLeftHolding = flag;
_lastRightHolding = flag2;
SendBatterySync();
}
}
private void SendBatterySync()
{
_writer.Reset();
_writer.Put((byte)10);
_writer.Put(BackpackControl.batteryCharge);
_writer.Put(BackpackControl.batteryLocationID);
_writer.Put(BackpackControl.batteryIsInBackpack);
BackpackControl val = Object.FindObjectOfType();
bool value = false;
bool value2 = false;
if ((Object)(object)val != (Object)null)
{
FieldInfo field = typeof(BackpackControl).GetField("leftHoldingBattery", BindingFlags.Instance | BindingFlags.NonPublic);
FieldInfo field2 = typeof(BackpackControl).GetField("rightHoldingBattery", BindingFlags.Instance | BindingFlags.NonPublic);
if (field != null)
{
value = (bool)field.GetValue(val);
}
if (field2 != null)
{
value2 = (bool)field2.GetValue(val);
}
}
_writer.Put(value);
_writer.Put(value2);
SendToAllPeers();
}
private void HandleBatterySync(int peerId, PacketReader reader)
{
float num = reader.GetFloat();
int num2 = reader.GetInt();
bool flag = reader.GetBool();
bool flag2 = reader.GetBool();
bool flag3 = reader.GetBool();
Plugin.LogDebug($"[Battery] Peer {peerId}: charge={num:F1}, loc={num2}, backpack={flag}, L={flag2}, R={flag3}");
if (!_remotePlayers.TryGetValue(peerId, out var value) || !value.IsGhost)
{
if (!_remoteBatteryStates.ContainsKey(peerId))
{
_remoteBatteryStates[peerId] = new RemoteBatteryState();
}
_remoteBatteryStates[peerId].Charge = num;
_remoteBatteryStates[peerId].LocationID = num2;
_remoteBatteryStates[peerId].InBackpack = flag;
_remoteBatteryStates[peerId].LeftHolding = flag2;
_remoteBatteryStates[peerId].RightHolding = flag3;
value?.SetBatteryState(flag2, flag3);
}
}
public RemoteBatteryState GetRemoteBatteryState(int peerId)
{
if (_remoteBatteryStates.TryGetValue(peerId, out var value))
{
return value;
}
return null;
}
public float GetRemoteBatteryCharge()
{
using (Dictionary.ValueCollection.Enumerator enumerator = _remoteBatteryStates.Values.GetEnumerator())
{
if (enumerator.MoveNext())
{
return enumerator.Current.Charge;
}
}
return -1f;
}
public int GetRemoteBatteryLocationID()
{
using (Dictionary.ValueCollection.Enumerator enumerator = _remoteBatteryStates.Values.GetEnumerator())
{
if (enumerator.MoveNext())
{
return enumerator.Current.LocationID;
}
}
return 0;
}
public bool IsRemoteBatteryAtExit()
{
foreach (RemoteBatteryState value in _remoteBatteryStates.Values)
{
if (value.LocationID == 100 && value.Charge >= 0.1f)
{
return true;
}
}
return false;
}
public RemoteBatteryState GetFirstRemoteBatteryState()
{
using (Dictionary.ValueCollection.Enumerator enumerator = _remoteBatteryStates.Values.GetEnumerator())
{
if (enumerator.MoveNext())
{
return enumerator.Current;
}
}
return null;
}
public RemoteBatteryState GetRemoteBatteryAtLocation(int locationID)
{
foreach (KeyValuePair remoteBatteryState in _remoteBatteryStates)
{
if ((!_remotePlayers.TryGetValue(remoteBatteryState.Key, out var value) || !value.IsGhost) && remoteBatteryState.Value.LocationID == locationID)
{
return remoteBatteryState.Value;
}
}
return null;
}
private void CheckCrankSync()
{
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_00a8: 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_00e2: Unknown result type (might be due to invalid IL or missing references)
//IL_00e3: 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)
if (_localIsGhost)
{
return;
}
if ((Object)(object)_crankControl == (Object)null)
{
_crankControl = Object.FindObjectOfType();
}
if ((Object)(object)_crankControl == (Object)null)
{
return;
}
bool flag = BackpackControl.batteryLocationID == 1;
float batteryCharge = BackpackControl.batteryCharge;
Quaternion rotation = ((Component)_crankControl).transform.rotation;
bool flag2 = crankControl.holdTimer > 0;
float num = (flag2 ? 0.05f : _crankSyncInterval);
if (!(Time.time - _lastCrankSyncTime < num))
{
_lastCrankSyncTime = Time.time;
bool flag3 = flag && Mathf.Abs(batteryCharge - _lastCrankCharge) > 0.1f;
bool flag4 = flag2 && Quaternion.Angle(_lastCrankRotation, rotation) > 2f;
if (flag != _lastCrankHasBattery || flag3 || flag4)
{
_lastCrankHasBattery = flag;
_lastCrankCharge = batteryCharge;
_lastCrankRotation = rotation;
SendCrankSync(flag, batteryCharge, rotation);
}
}
}
private void SendCrankSync(bool hasBattery, float charge, Quaternion rotation)
{
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
_writer.Reset();
_writer.Put((byte)19);
_writer.Put(hasBattery);
_writer.Put(charge);
WriteQuaternion(_writer, rotation);
SendToAllPeers();
}
public void UpdateCrankInterpolation()
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
_remoteCrankChargeDisplay = Mathf.Lerp(_remoteCrankChargeDisplay, _remoteCrankChargeTarget, Time.deltaTime * 15f);
_remoteCrankRotDisplay = Quaternion.Slerp(_remoteCrankRotDisplay, _remoteCrankRotTarget, Time.deltaTime * 15f);
}
private void CheckPuzzleInitSync()
{
if (_steam.IsHost && !_localIsGhost && !_pendingGhostPuzzleRestore)
{
if ((Object)(object)_puzzleMaster == (Object)null)
{
_puzzleMaster = Object.FindObjectOfType();
}
if (!((Object)(object)_puzzleMaster == (Object)null) && !_puzzleInitSent)
{
SendPuzzleInit();
_puzzleInitSent = true;
_lastTotalCompletedPuzzles = PuzzleMaster.totalCompletedPuzzles;
}
}
}
private void SendPuzzleInit()
{
if ((Object)(object)_puzzleMaster == (Object)null)
{
return;
}
_writer.Reset();
_writer.Put((byte)12);
Type typeFromHandle = typeof(PuzzleMaster);
Type typeFromHandle2 = typeof(PuzzleController);
bool[] array = new bool[9];
int[] array2 = new int[9];
bool[] array3 = new bool[9];
PuzzleController[] array4 = (PuzzleController[])(object)new PuzzleController[9] { _puzzleMaster.pCon1, _puzzleMaster.pCon2, _puzzleMaster.pCon3, _puzzleMaster.pCon4, _puzzleMaster.pCon5, _puzzleMaster.pCon6, _puzzleMaster.pCon7, _puzzleMaster.pCon8, _puzzleMaster.pCon9 };
string[] array5 = new string[9] { "ps1", "ps2", "ps3", "ps4", "ps5", "ps6", "ps7", "ps8", "ps9" };
for (int i = 0; i < 9; i++)
{
FieldInfo field = typeFromHandle.GetField(array5[i], BindingFlags.Instance | BindingFlags.NonPublic);
array[i] = (bool)field.GetValue(_puzzleMaster);
if ((Object)(object)array4[i] != (Object)null)
{
FieldInfo field2 = typeFromHandle2.GetField("puzzlePresetID", BindingFlags.Instance | BindingFlags.NonPublic);
array2[i] = (int)field2.GetValue(array4[i]);
FieldInfo field3 = typeFromHandle2.GetField("puzzleHasCompleted", BindingFlags.Instance | BindingFlags.NonPublic);
array3[i] = (bool)field3.GetValue(array4[i]);
}
}
for (int j = 0; j < 9; j++)
{
_writer.Put(array[j]);
_writer.Put(array2[j]);
_writer.Put(array3[j]);
if ((Object)(object)array4[j] != (Object)null && array4[j].cubeList != null)
{
_writer.Put(array4[j].cubeList.Length);
PuzzleBlock[] cubeList = array4[j].cubeList;
foreach (PuzzleBlock val in cubeList)
{
_writer.Put(val.blockIDValue);
}
}
else
{
_writer.Put(0);
}
}
_writer.Put(PuzzleMaster.totalCompletedPuzzles);
_writer.Put(PuzzleMaster.requiredPuzzles);
SendToAllPeers();
Plugin.Log.LogInfo((object)$"[Host] Sent puzzle init: required={PuzzleMaster.requiredPuzzles}, completed={PuzzleMaster.totalCompletedPuzzles}");
}
private void SavePuzzleStateForGhost()
{
if ((Object)(object)_puzzleMaster == (Object)null)
{
_puzzleMaster = Object.FindObjectOfType();
}
if ((Object)(object)_puzzleMaster == (Object)null)
{
Plugin.Log.LogWarning((object)"[Ghost] Can't save puzzle state - PuzzleMaster not found");
return;
}
Type typeFromHandle = typeof(PuzzleMaster);
Type typeFromHandle2 = typeof(PuzzleController);
bool[] array = new bool[9];
int[] array2 = new int[9];
bool[] array3 = new bool[9];
int[][] array4 = new int[9][];
PuzzleController[] array5 = (PuzzleController[])(object)new PuzzleController[9] { _puzzleMaster.pCon1, _puzzleMaster.pCon2, _puzzleMaster.pCon3, _puzzleMaster.pCon4, _puzzleMaster.pCon5, _puzzleMaster.pCon6, _puzzleMaster.pCon7, _puzzleMaster.pCon8, _puzzleMaster.pCon9 };
string[] array6 = new string[9] { "ps1", "ps2", "ps3", "ps4", "ps5", "ps6", "ps7", "ps8", "ps9" };
for (int i = 0; i < 9; i++)
{
FieldInfo field = typeFromHandle.GetField(array6[i], BindingFlags.Instance | BindingFlags.NonPublic);
array[i] = (bool)field.GetValue(_puzzleMaster);
if ((Object)(object)array5[i] != (Object)null)
{
FieldInfo field2 = typeFromHandle2.GetField("puzzlePresetID", BindingFlags.Instance | BindingFlags.NonPublic);
array2[i] = (int)field2.GetValue(array5[i]);
FieldInfo field3 = typeFromHandle2.GetField("puzzleHasCompleted", BindingFlags.Instance | BindingFlags.NonPublic);
array3[i] = (bool)field3.GetValue(array5[i]);
if (array5[i].cubeList != null)
{
array4[i] = new int[array5[i].cubeList.Length];
for (int j = 0; j < array5[i].cubeList.Length; j++)
{
array4[i][j] = array5[i].cubeList[j].blockIDValue;
}
}
else
{
array4[i] = new int[0];
}
}
else
{
array4[i] = new int[0];
}
}
_savedGhostPuzzleState = new PendingPuzzleInit
{
ActiveStates = array,
PresetIDs = array2,
CompletedStates = array3,
BlockStates = array4,
TotalCompleted = PuzzleMaster.totalCompletedPuzzles,
RequiredPuzzles = PuzzleMaster.requiredPuzzles
};
Plugin.Log.LogInfo((object)$"[Ghost] Saved puzzle state: completed={PuzzleMaster.totalCompletedPuzzles}, required={PuzzleMaster.requiredPuzzles}");
}
public void RestoreGhostPuzzleState()
{
if (_savedGhostPuzzleState == null)
{
return;
}
if ((Object)(object)_puzzleMaster == (Object)null)
{
_puzzleMaster = Object.FindObjectOfType();
}
if ((Object)(object)_puzzleMaster == (Object)null)
{
Plugin.Log.LogWarning((object)"[Ghost] Can't restore puzzle state - PuzzleMaster not found yet");
return;
}
Type typeFromHandle = typeof(PuzzleMaster);
Type typeFromHandle2 = typeof(PuzzleController);
PendingPuzzleInit savedGhostPuzzleState = _savedGhostPuzzleState;
PuzzleController[] array = (PuzzleController[])(object)new PuzzleController[9] { _puzzleMaster.pCon1, _puzzleMaster.pCon2, _puzzleMaster.pCon3, _puzzleMaster.pCon4, _puzzleMaster.pCon5, _puzzleMaster.pCon6, _puzzleMaster.pCon7, _puzzleMaster.pCon8, _puzzleMaster.pCon9 };
string[] array2 = new string[9] { "ps1", "ps2", "ps3", "ps4", "ps5", "ps6", "ps7", "ps8", "ps9" };
for (int i = 0; i < 9; i++)
{
typeFromHandle.GetField(array2[i], BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(_puzzleMaster, savedGhostPuzzleState.ActiveStates[i]);
if (!((Object)(object)array[i] != (Object)null))
{
continue;
}
typeFromHandle2.GetField("puzzlePresetID", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(array[i], savedGhostPuzzleState.PresetIDs[i]);
typeFromHandle2.GetField("puzzleHasCompleted", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(array[i], savedGhostPuzzleState.CompletedStates[i]);
if (savedGhostPuzzleState.CompletedStates[i] || !savedGhostPuzzleState.ActiveStates[i])
{
if ((Object)(object)array[i].fanspin != (Object)null)
{
array[i].fanspin.isOn = true;
}
GameObject thisMapIndicator = array[i].thisMapIndicator;
if (thisMapIndicator != null)
{
thisMapIndicator.SetActive(true);
}
}
else
{
GameObject thisMapIndicator2 = array[i].thisMapIndicator;
if (thisMapIndicator2 != null)
{
thisMapIndicator2.SetActive(false);
}
}
if (savedGhostPuzzleState.BlockStates[i] != null && array[i].cubeList != null)
{
int num = Mathf.Min(savedGhostPuzzleState.BlockStates[i].Length, array[i].cubeList.Length);
for (int j = 0; j < num; j++)
{
array[i].cubeList[j].setThisID(savedGhostPuzzleState.BlockStates[i][j]);
}
}
}
PuzzleMaster.totalCompletedPuzzles = savedGhostPuzzleState.TotalCompleted;
PuzzleMaster.requiredPuzzles = savedGhostPuzzleState.RequiredPuzzles;
_lastTotalCompletedPuzzles = savedGhostPuzzleState.TotalCompleted;
_completedPuzzleIDs.Clear();
for (int k = 0; k < 9; k++)
{
if (savedGhostPuzzleState.CompletedStates[k] && savedGhostPuzzleState.ActiveStates[k] && (Object)(object)array[k] != (Object)null)
{
_completedPuzzleIDs.Add(array[k].thisPuzzleID);
}
}
Plugin.Log.LogInfo((object)$"[Ghost] Restored puzzle state: completed={savedGhostPuzzleState.TotalCompleted}, required={savedGhostPuzzleState.RequiredPuzzles}");
_puzzleInitCompletedStates = savedGhostPuzzleState.CompletedStates;
_puzzleInitActiveStates = savedGhostPuzzleState.ActiveStates;
_puzzleInitReapplyTimer = 3f;
_puzzleInitApplied = true;
_savedGhostPuzzleState = null;
}
private void HandlePuzzleInit(PacketReader reader)
{
if (_steam.IsHost)
{
return;
}
Plugin.LogDebug("[Client] Received puzzle init");
if (_puzzleInitApplied)
{
for (int i = 0; i < 9; i++)
{
reader.GetBool();
reader.GetInt();
reader.GetBool();
int num = reader.GetInt();
for (int j = 0; j < num; j++)
{
reader.GetInt();
}
}
reader.GetInt();
reader.GetInt();
Plugin.LogDebug("[Client] Ignoring duplicate puzzle init (already applied)");
return;
}
bool[] array = new bool[9];
int[] array2 = new int[9];
bool[] array3 = new bool[9];
int[][] array4 = new int[9][];
for (int k = 0; k < 9; k++)
{
array[k] = reader.GetBool();
array2[k] = reader.GetInt();
array3[k] = reader.GetBool();
int num2 = reader.GetInt();
array4[k] = new int[num2];
for (int l = 0; l < num2; l++)
{
array4[k][l] = reader.GetInt();
}
}
int totalCompleted = reader.GetInt();
int requiredPuzzles = reader.GetInt();
_pendingPuzzleInit = new PendingPuzzleInit
{
ActiveStates = array,
PresetIDs = array2,
CompletedStates = array3,
BlockStates = array4,
TotalCompleted = totalCompleted,
RequiredPuzzles = requiredPuzzles
};
_puzzleInitStartWaited = false;
TryApplyPuzzleInit();
}
private void TryApplyPuzzleInit()
{
if (_pendingPuzzleInit == null)
{
return;
}
if ((Object)(object)_puzzleMaster == (Object)null)
{
_puzzleMaster = Object.FindObjectOfType();
}
if ((Object)(object)_puzzleMaster == (Object)null)
{
Plugin.Log.LogWarning((object)"[Client] PuzzleMaster not found, will retry later");
return;
}
if (!_puzzleInitStartWaited)
{
_puzzleInitStartWaited = true;
return;
}
Type typeFromHandle = typeof(PuzzleMaster);
Type typeFromHandle2 = typeof(PuzzleController);
PuzzleController[] array = (PuzzleController[])(object)new PuzzleController[9] { _puzzleMaster.pCon1, _puzzleMaster.pCon2, _puzzleMaster.pCon3, _puzzleMaster.pCon4, _puzzleMaster.pCon5, _puzzleMaster.pCon6, _puzzleMaster.pCon7, _puzzleMaster.pCon8, _puzzleMaster.pCon9 };
string[] array2 = new string[9] { "ps1", "ps2", "ps3", "ps4", "ps5", "ps6", "ps7", "ps8", "ps9" };
_isReceivingPuzzleBlock = true;
for (int i = 0; i < 9; i++)
{
bool flag = _pendingPuzzleInit.ActiveStates[i];
int num = _pendingPuzzleInit.PresetIDs[i];
bool flag2 = _pendingPuzzleInit.CompletedStates[i];
typeFromHandle.GetField(array2[i], BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(_puzzleMaster, flag);
if (!((Object)(object)array[i] != (Object)null))
{
continue;
}
typeFromHandle2.GetField("puzzlePresetID", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(array[i], num);
FieldInfo field = typeFromHandle2.GetField("puzzleHasCompleted", BindingFlags.Instance | BindingFlags.NonPublic);
bool flag3 = (Object)(object)array[i] != (Object)null && _completedPuzzleIDs.Contains(array[i].thisPuzzleID);
if (!flag3)
{
field?.SetValue(array[i], flag2);
}
if (flag2 || flag3)
{
if ((Object)(object)array[i].fanspin != (Object)null)
{
array[i].fanspin.isOn = true;
}
GameObject thisMapIndicator = array[i].thisMapIndicator;
if (thisMapIndicator != null)
{
thisMapIndicator.SetActive(true);
}
}
else if (!flag)
{
field?.SetValue(array[i], true);
if ((Object)(object)array[i].fanspin != (Object)null)
{
array[i].fanspin.isOn = true;
}
GameObject thisMapIndicator2 = array[i].thisMapIndicator;
if (thisMapIndicator2 != null)
{
thisMapIndicator2.SetActive(true);
}
}
else
{
field?.SetValue(array[i], false);
if ((Object)(object)array[i].fanspin != (Object)null)
{
array[i].fanspin.isOn = false;
}
GameObject thisMapIndicator3 = array[i].thisMapIndicator;
if (thisMapIndicator3 != null)
{
thisMapIndicator3.SetActive(false);
}
}
int[] array3 = _pendingPuzzleInit.BlockStates[i];
if (array3 != null && array[i].cubeList != null)
{
int num2 = Mathf.Min(array3.Length, array[i].cubeList.Length);
for (int j = 0; j < num2; j++)
{
array[i].cubeList[j].setThisID(array3[j]);
}
}
}
_isReceivingPuzzleBlock = false;
if (_pendingPuzzleInit.TotalCompleted > PuzzleMaster.totalCompletedPuzzles)
{
PuzzleMaster.totalCompletedPuzzles = _pendingPuzzleInit.TotalCompleted;
}
PuzzleMaster.requiredPuzzles = _pendingPuzzleInit.RequiredPuzzles;
for (int k = 0; k < 9; k++)
{
if (_pendingPuzzleInit.CompletedStates[k] && (Object)(object)array[k] != (Object)null)
{
_completedPuzzleIDs.Add(array[k].thisPuzzleID);
}
}
Plugin.LogDebug($"[Client] Applied puzzle init: completed={PuzzleMaster.totalCompletedPuzzles}, required={PuzzleMaster.requiredPuzzles}");
foreach (int completedPuzzleID in _completedPuzzleIDs)
{
for (int l = 0; l < 9; l++)
{
if ((Object)(object)array[l] != (Object)null && array[l].thisPuzzleID == completedPuzzleID)
{
FieldInfo field2 = typeFromHandle2.GetField("puzzleHasCompleted", BindingFlags.Instance | BindingFlags.NonPublic);
if (field2 != null)
{
field2.SetValue(array[l], true);
}
if ((Object)(object)array[l].fanspin != (Object)null)
{
array[l].fanspin.isOn = true;
}
GameObject thisMapIndicator4 = array[l].thisMapIndicator;
if (thisMapIndicator4 != null)
{
thisMapIndicator4.SetActive(true);
}
break;
}
}
}
_puzzleInitCompletedStates = _pendingPuzzleInit.CompletedStates;
_puzzleInitActiveStates = _pendingPuzzleInit.ActiveStates;
_pendingPuzzleInit = null;
_puzzleInitApplied = true;
_puzzleInitReapplyTimer = 3f;
}
private void ReapplyPuzzleIndicators()
{
if (_puzzleInitReapplyTimer <= 0f)
{
return;
}
_puzzleInitReapplyTimer -= Time.deltaTime;
if ((Object)(object)_puzzleMaster == (Object)null || _puzzleInitCompletedStates == null || _puzzleInitActiveStates == null)
{
return;
}
FieldInfo field = typeof(PuzzleController).GetField("puzzleHasCompleted", BindingFlags.Instance | BindingFlags.NonPublic);
PuzzleController[] array = (PuzzleController[])(object)new PuzzleController[9] { _puzzleMaster.pCon1, _puzzleMaster.pCon2, _puzzleMaster.pCon3, _puzzleMaster.pCon4, _puzzleMaster.pCon5, _puzzleMaster.pCon6, _puzzleMaster.pCon7, _puzzleMaster.pCon8, _puzzleMaster.pCon9 };
for (int i = 0; i < 9; i++)
{
if ((Object)(object)array[i] == (Object)null || (!_puzzleInitCompletedStates[i] && _puzzleInitActiveStates[i]))
{
continue;
}
bool num = field != null && (bool)field.GetValue(array[i]);
bool flag = (Object)(object)array[i].thisMapIndicator != (Object)null && array[i].thisMapIndicator.activeSelf;
if (!num || !flag)
{
if (field != null)
{
field.SetValue(array[i], true);
}
if ((Object)(object)array[i].fanspin != (Object)null)
{
array[i].fanspin.isOn = true;
}
GameObject thisMapIndicator = array[i].thisMapIndicator;
if (thisMapIndicator != null)
{
thisMapIndicator.SetActive(true);
}
Plugin.LogDebug($"[PuzzleInit] Re-applied completed state for puzzle index {i} (something reset it)");
}
}
}
private void CheckExitDoorSync()
{
if (_localIsGhost || Time.time - _lastDoorSyncTime < 0.1f)
{
return;
}
_lastDoorSyncTime = Time.time;
if (BackpackControl.batteryLocationID != 100 || BackpackControl.batteryCharge < 0.1f)
{
if (_lastDoorLeaveTimer > 0 && !_exitDoorFullyCharged)
{
_lastDoorLeaveTimer = 0;
SendExitDoorProgress(0, 100);
}
return;
}
if ((Object)(object)_leaveDoor == (Object)null)
{
_leaveDoor = Object.FindObjectOfType();
}
if (!((Object)(object)_leaveDoor != (Object)null))
{
return;
}
FieldInfo field = typeof(LeaveDoorControl).GetField("doorLeaveTimer", BindingFlags.Instance | BindingFlags.NonPublic);
if (field != null)
{
int num = (int)field.GetValue(_leaveDoor);
if (num >= _leaveDoor.doorLeaveRequiredTime && _leaveDoor.doorLeaveRequiredTime > 0)
{
_exitDoorFullyCharged = true;
}
if (num != _lastDoorLeaveTimer)
{
_lastDoorLeaveTimer = num;
SendExitDoorProgress(num, _leaveDoor.doorLeaveRequiredTime);
}
}
}
private void SendExitDoorProgress(int timer, int requiredTime)
{
_writer.Reset();
_writer.Put((byte)18);
_writer.Put(timer);
_writer.Put(requiredTime);
SendToAllPeers();
}
public void MarkPuzzleCompleted(int puzzleID)
{
_completedPuzzleIDs.Add(puzzleID);
Plugin.LogDebug($"[Puzzle] Marked puzzle {puzzleID} as completed locally");
}
public bool IsPuzzleCompleted(int puzzleID)
{
return _completedPuzzleIDs.Contains(puzzleID);
}
public void SendPuzzleComplete(int puzzleID)
{
if (_steam != null && _steam.IsRunning)
{
_writer.Reset();
_writer.Put((byte)13);
_writer.Put(puzzleID);
_writer.Put(PuzzleMaster.totalCompletedPuzzles);
SendToAllPeers();
Plugin.LogDebug($"[Puzzle] Sent puzzle complete: puzzleID={puzzleID}, total={PuzzleMaster.totalCompletedPuzzles}");
}
}
private void HandlePuzzleComplete(PacketReader reader)
{
int num = reader.GetInt();
int num2 = reader.GetInt();
Plugin.LogDebug($"[Puzzle] Received puzzle complete: puzzleID={num}, remoteTotal={num2}, localTotal={PuzzleMaster.totalCompletedPuzzles}");
if (_completedPuzzleIDs.Contains(num))
{
Plugin.LogDebug($"[Puzzle] Puzzle {num} already marked complete, skipping");
return;
}
if (num == BackpackControl.batteryLocationID && BackpackControl.batteryCharge > 0f)
{
Plugin.LogDebug($"[Puzzle] Local battery is in puzzle {num} — skipping remote completion (local player is solving it)");
PuzzleMaster.totalCompletedPuzzles++;
_completedPuzzleIDs.Add(num);
return;
}
_completedPuzzleIDs.Add(num);
PuzzleMaster.totalCompletedPuzzles++;
Plugin.LogDebug($"[Puzzle] Incremented local total to {PuzzleMaster.totalCompletedPuzzles}");
if ((Object)(object)_puzzleMaster == (Object)null)
{
_puzzleMaster = Object.FindObjectOfType();
}
if (!((Object)(object)_puzzleMaster != (Object)null))
{
return;
}
PuzzleController[] array = (PuzzleController[])(object)new PuzzleController[9] { _puzzleMaster.pCon1, _puzzleMaster.pCon2, _puzzleMaster.pCon3, _puzzleMaster.pCon4, _puzzleMaster.pCon5, _puzzleMaster.pCon6, _puzzleMaster.pCon7, _puzzleMaster.pCon8, _puzzleMaster.pCon9 };
foreach (PuzzleController val in array)
{
if ((Object)(object)val != (Object)null && val.thisPuzzleID == num)
{
Type? typeFromHandle = typeof(PuzzleController);
BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.NonPublic;
typeFromHandle.GetField("puzzleHasCompleted", bindingAttr).SetValue(val, true);
FieldInfo field = typeFromHandle.GetField("totalCompletions", bindingAttr);
if (field != null)
{
field.SetValue(val, 0);
}
for (int j = 0; j < val.cubeList.Length; j++)
{
val.cubeList[j].setThisID(0);
}
if ((Object)(object)val.fanspin != (Object)null)
{
val.fanspin.isOn = true;
}
GameObject thisMapIndicator = val.thisMapIndicator;
if (thisMapIndicator != null)
{
thisMapIndicator.SetActive(true);
}
AudioSource winAudio = val.winAudio;
if (winAudio != null)
{
winAudio.Play();
}
Plugin.LogDebug($"Marked puzzle {num} as complete (board cleared)");
break;
}
}
}
public void SendPuzzleBlock(int puzzleID, int blockNumber, int blockIDValue)
{
if (_steam != null && _steam.IsRunning)
{
_writer.Reset();
_writer.Put((byte)14);
_writer.Put(puzzleID);
_writer.Put(blockNumber);
_writer.Put(blockIDValue);
SendToAllPeers();
}
}
private void HandlePuzzleBlock(PacketReader reader)
{
int num = reader.GetInt();
int num2 = reader.GetInt();
int thisID = reader.GetInt();
if ((Object)(object)_puzzleMaster == (Object)null)
{
_puzzleMaster = Object.FindObjectOfType();
}
if ((Object)(object)_puzzleMaster == (Object)null)
{
return;
}
PuzzleController[] array = (PuzzleController[])(object)new PuzzleController[9] { _puzzleMaster.pCon1, _puzzleMaster.pCon2, _puzzleMaster.pCon3, _puzzleMaster.pCon4, _puzzleMaster.pCon5, _puzzleMaster.pCon6, _puzzleMaster.pCon7, _puzzleMaster.pCon8, _puzzleMaster.pCon9 };
foreach (PuzzleController val in array)
{
if ((Object)(object)val != (Object)null && val.thisPuzzleID == num)
{
if (num2 >= 0 && num2 < val.cubeList.Length)
{
_isReceivingPuzzleBlock = true;
val.cubeList[num2].setThisID(thisID);
_isReceivingPuzzleBlock = false;
}
break;
}
}
}
public void SendClownHonk()
{
if (_steam != null && _steam.IsRunning)
{
_writer.Reset();
_writer.Put((byte)15);
SendToAllPeers();
}
}
private void HandleClownHonk(PacketReader reader)
{
clownNose val = Object.FindObjectOfType();
if ((Object)(object)val != (Object)null && (Object)(object)val.honkSound != (Object)null)
{
_isReceivingHonk = true;
val.honkSound.Play();
_isReceivingHonk = false;
}
}
public void SendClownState(clownRandom clown)
{
if (_steam != null && _steam.IsRunning && ShouldControlMonsters)
{
_writer.Reset();
_writer.Put((byte)25);
_writer.Put(clown.clown1.activeSelf);
_writer.Put(clown.clown2.activeSelf);
_writer.Put(clown.clown3.activeSelf);
_writer.Put(clown.clown4.activeSelf);
_writer.Put(clown.clown5.activeSelf);
_writer.Put(clown.clown6.activeSelf);
_writer.Put(clown.clown7.activeSelf);
SendToAllPeers();
Plugin.Log.LogInfo((object)"[Controller] Sent clown state");
}
}
public void SendClownAttack()
{
if (_steam != null && _steam.IsRunning && ShouldControlMonsters)
{
_writer.Reset();
_writer.Put((byte)26);
SendToAllPeers();
}
}
private void HandleClownState(PacketReader reader)
{
bool active = reader.GetBool();
bool active2 = reader.GetBool();
bool active3 = reader.GetBool();
bool active4 = reader.GetBool();
bool active5 = reader.GetBool();
bool active6 = reader.GetBool();
bool active7 = reader.GetBool();
if ((Object)(object)_clownRandom == (Object)null)
{
_clownRandom = Object.FindObjectOfType();
}
if ((Object)(object)_clownRandom != (Object)null)
{
_clownRandom.clown1.SetActive(active);
_clownRandom.clown2.SetActive(active2);
_clownRandom.clown3.SetActive(active3);
_clownRandom.clown4.SetActive(active4);
_clownRandom.clown5.SetActive(active5);
_clownRandom.clown6.SetActive(active6);
_clownRandom.clown7.SetActive(active7);
}
}
private void HandleClownAttack(PacketReader reader)
{
if ((Object)(object)_clownRandom == (Object)null)
{
_clownRandom = Object.FindObjectOfType();
}
if ((Object)(object)_clownRandom != (Object)null)
{
bool flag = false;
if ((Object)(object)_clownRandom.c1R != (Object)null && _clownRandom.c1R.isVisible)
{
flag = true;
}
if ((Object)(object)_clownRandom.c2R != (Object)null && _clownRandom.c2R.isVisible)
{
flag = true;
}
if ((Object)(object)_clownRandom.c3R != (Object)null && _clownRandom.c3R.isVisible)
{
flag = true;
}
if ((Object)(object)_clownRandom.c4R != (Object)null && _clownRandom.c4R.isVisible)
{
flag = true;
}
if ((Object)(object)_clownRandom.c5R != (Object)null && _clownRandom.c5R.isVisible)
{
flag = true;
}
if ((Object)(object)_clownRandom.c6R != (Object)null && _clownRandom.c6R.isVisible)
{
flag = true;
}
if ((Object)(object)_clownRandom.c7R != (Object)null && _clownRandom.c7R.isVisible)
{
flag = true;
}
if (flag)
{
Plugin.LogDebug("[Client] Ignoring clown attack - client can see the clown");
return;
}
_clownRandom.clown1.SetActive(false);
_clownRandom.clown2.SetActive(false);
_clownRandom.clown3.SetActive(false);
_clownRandom.clown4.SetActive(false);
_clownRandom.clown5.SetActive(false);
_clownRandom.clown6.SetActive(false);
_clownRandom.clown7.SetActive(false);
typeof(clownRandom).GetField("clownAttackingSwitch", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(_clownRandom, true);
}
}
public void SendSmileTrigger(Vector3 position)
{
}
private void HandleSmileTrigger(PacketReader reader)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
ReadVector3(reader);
}
public void SendVentSound(Vector3 position, int soundIndex)
{
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
if (_steam != null && _steam.IsRunning)
{
_writer.Reset();
_writer.Put((byte)16);
WriteVector3(_writer, position);
_writer.Put(soundIndex);
SendToAllPeers();
}
}
public void SendCrawlSound(Vector3 position, bool inMainRoom)
{
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
if (_steam != null && _steam.IsRunning)
{
_writer.Reset();
_writer.Put((byte)16);
WriteVector3(_writer, position);
_writer.Put(2);
_writer.Put(inMainRoom);
SendToAllPeers();
}
}
private void HandleVentSound(PacketReader reader)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: 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_0046: Unknown result type (might be due to invalid IL or missing references)
Vector3 position = ReadVector3(reader);
int num = reader.GetInt();
_isReceivingVentSound = true;
switch (num)
{
case 0:
{
ventSoundPlayer val = Object.FindObjectOfType();
if ((Object)(object)val != (Object)null && (Object)(object)val.soundPrefab != (Object)null)
{
Object.Instantiate(val.soundPrefab).transform.position = position;
}
break;
}
case 1:
PlayRemoteCrawlSound(position, inMainRoom: false);
break;
case 2:
{
bool inMainRoom = reader.GetBool();
PlayRemoteCrawlSound(position, inMainRoom);
break;
}
}
_isReceivingVentSound = false;
}
private void PlayRemoteCrawlSound(Vector3 position, bool inMainRoom)
{
//IL_0080: 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_008b: 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_00ee: Expected O, but got Unknown
crawlSoundContrl val = Object.FindObjectOfType();
if (!((Object)(object)val == (Object)null))
{
AudioSource val2;
if (inMainRoom)
{
val2 = val.w1;
}
else
{
AudioSource[] array = (AudioSource[])(object)new AudioSource[4] { val.m1, val.m2, val.m3, val.m4 };
val2 = array[Random.Range(0, array.Length)];
}
if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2.clip == (Object)null))
{
float pitch = Random.Range(0.8f, 1.2f);
GameObject val3 = new GameObject("RemoteCrawlSound");
val3.transform.position = position;
AudioSource obj = val3.AddComponent();
obj.clip = val2.clip;
obj.pitch = pitch;
obj.spatialBlend = 1f;
obj.volume = val2.volume;
obj.maxDistance = 10f;
obj.rolloffMode = (AudioRolloffMode)1;
obj.Play();
Object.Destroy((Object)val3, val2.clip.length + 0.1f);
}
}
}
private void HandleFlashlightUpdate(int peerId, PacketReader reader)
{
bool flashlightState = reader.GetBool();
if (_remotePlayers.TryGetValue(peerId, out var value))
{
value.SetFlashlightState(flashlightState);
}
}
private void HandlePositionUpdate(int peerId, PacketReader reader)
{
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: 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_0049: 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_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: 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_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: 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_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ca: 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)
//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
if (!_remotePlayers.TryGetValue(peerId, out var value))
{
Plugin.Log.LogWarning((object)$"No remote player for peer {peerId}");
return;
}
bool isStanding = reader.GetBool();
Vector3 bodyPos = ReadVector3(reader);
Quaternion bodyRot = ReadQuaternion(reader);
Vector3 val = ReadVector3(reader);
Quaternion headRot = ReadQuaternion(reader);
Vector3 leftHandPos = ReadVector3(reader);
Quaternion leftHandRot = ReadQuaternion(reader);
Vector3 rightHandPos = ReadVector3(reader);
Quaternion rightHandRot = ReadQuaternion(reader);
float leftGrip = reader.GetFloat();
float leftTrigger = reader.GetFloat();
float rightGrip = reader.GetFloat();
float rightTrigger = reader.GetFloat();
if (_updateCount % 150 == 0)
{
Plugin.LogDebug($"[Recv] peer {peerId}: head={val}");
}
value.SetTargets(isStanding, bodyPos, bodyRot, val, headRot, leftHandPos, leftHandRot, rightHandPos, rightHandRot, leftGrip, leftTrigger, rightGrip, rightTrigger);
}
public void CaptureSpawnPoint()
{
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: 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)
if (!_spawnPointCaptured)
{
MoveTypeController val = Object.FindObjectOfType();
if ((Object)(object)val != (Object)null && val.debugSwitch && (Object)(object)val.playerObj != (Object)null)
{
_levelSpawnPoint = val.playerObj.transform.position;
_spawnPointCaptured = true;
Plugin.Log.LogInfo((object)$"[Ghost] Captured spawn point from playerObj (standing): {_levelSpawnPoint}");
}
}
}
public void SendDeathGhost(bool isGhost, int deathType)
{
Plugin.Log.LogInfo((object)$"[Death] SendDeathGhost called: isGhost={isGhost}, deathType={deathType}, steamRunning={_steam?.IsRunning}, localIsGhost={_localIsGhost}, debugForce={DebugForceGhostOnDeath}");
if (_steam == null || !_steam.IsRunning)
{
Plugin.Log.LogInfo((object)"[Death] Steam not running, skipping send");
return;
}
if (isGhost && _localIsGhost)
{
Plugin.Log.LogInfo((object)"[Death] Already a ghost, skipping duplicate death notification");
return;
}
_writer.Reset();
_writer.Put((byte)20);
_writer.Put(isGhost);
_writer.Put(deathType);
SendToAllPeers();
Plugin.Log.LogInfo((object)$"[Death] Sent death notification: deathType={deathType}");
if (isGhost)
{
IsDyingThisFrame = true;
BecomeGhost();
}
}
public void BecomeGhost()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
Scene activeScene = SceneManager.GetActiveScene();
string name = ((Scene)(ref activeScene)).name;
Plugin.Log.LogInfo((object)$"[Ghost] BecomeGhost: scene={name}, alreadyGhost={_localIsGhost}, debugForce={DebugForceGhostOnDeath}, remotePlayers={_remotePlayers.Count}");
if (!name.Contains("Night"))
{
Plugin.Log.LogInfo((object)"[Ghost] Not in Night scene, aborting");
return;
}
bool flag = DebugForceGhostOnDeath;
if (!flag)
{
foreach (KeyValuePair remotePlayer in _remotePlayers)
{
if (!remotePlayer.Value.IsGhost)
{
flag = true;
break;
}
}
}
Plugin.Log.LogInfo((object)$"[Ghost] partnerAlive={flag}");
if (!flag)
{
Plugin.Log.LogInfo((object)"[Ghost] No alive partners - all players dead, going to Home");
ResetGhostState();
return;
}
Plugin.Log.LogInfo((object)("[Ghost] Partner alive - becoming ghost in " + name));
_localIsGhost = true;
DebugForceGhostOnDeath = false;
BackpackControl.batteryLocationID = 0;
BackpackControl.batteryCharge = 0f;
BackpackControl.batteryIsInBackpack = false;
IsGhostSceneReload = true;
}
public void ReloadSceneAsGhost()
{
if (string.IsNullOrEmpty(_ghostSceneToReload))
{
Plugin.Log.LogWarning((object)"[Ghost] ReloadSceneAsGhost called but no scene to reload!");
return;
}
SavePuzzleStateForGhost();
Plugin.Log.LogInfo((object)("[Ghost] ReloadSceneAsGhost - Loading: " + _ghostSceneToReload));
IsLoadingFromSync = true;
SceneManager.LoadScene(_ghostSceneToReload);
}
public void HandleGhostSceneLoaded()
{
if (_localIsGhost && _pendingGhostTeleport)
{
_pendingGhostTeleport = false;
IsGhostSceneReload = false;
Plugin.Log.LogInfo((object)"[Ghost] Scene loaded as ghost, teleporting to partner");
_writer.Reset();
_writer.Put((byte)20);
_writer.Put(value: true);
_writer.Put(0);
SendToAllPeers();
CreateGhostVision();
_pendingGhostPuzzleRestore = true;
_ghostPuzzleRestoreFrames = 2;
_ghostTeleportDelay = 1f;
}
}
private void CreateGhostVision()
{
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Expected O, but got Unknown
//IL_007f: 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)
if ((Object)(object)_ghostVisionLight != (Object)null)
{
Object.Destroy((Object)(object)_ghostVisionLight);
_ghostVisionLight = null;
}
Camera val = Camera.main;
if ((Object)(object)val == (Object)null)
{
val = Object.FindObjectOfType();
}
if ((Object)(object)val == (Object)null)
{
Plugin.Log.LogWarning((object)"[Ghost] No camera found for ghost vision");
return;
}
_ghostVisionLight = new GameObject("GhostVision");
_ghostVisionLight.transform.SetParent(((Component)val).transform);
_ghostVisionLight.transform.localPosition = Vector3.zero;
Light obj = _ghostVisionLight.AddComponent();
obj.type = (LightType)2;
obj.color = new Color(0.6f, 0.6f, 0.8f);
obj.intensity = 0.8f;
obj.range = 6f;
obj.shadows = (LightShadows)0;
Plugin.Log.LogInfo((object)"[Ghost] Created ghost vision light");
}
private void DestroyGhostVision()
{
if ((Object)(object)_ghostVisionLight != (Object)null)
{
Object.Destroy((Object)(object)_ghostVisionLight);
_ghostVisionLight = null;
}
}
public void TeleportToPartner()
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
Plugin.Log.LogInfo((object)$"[Ghost] TeleportToPartner called, setting delay=2.5s, spawnCaptured={_spawnPointCaptured}, spawnPoint={_levelSpawnPoint}");
_ghostTeleportDelay = 2.5f;
_pendingGhostTeleport = false;
CreateGhostVision();
_writer.Reset();
_writer.Put((byte)20);
_writer.Put(value: true);
_writer.Put(0);
SendToAllPeers();
}
private void UpdateGhostTeleport()
{
//IL_00d1: 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_0166: Unknown result type (might be due to invalid IL or missing references)
//IL_0177: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: Unknown result type (might be due to invalid IL or missing references)
//IL_0120: Unknown result type (might be due to invalid IL or missing references)
if (_ghostTeleportDelay <= 0f)
{
return;
}
_ghostTeleportDelay -= Time.deltaTime;
if (_ghostTeleportDelay > 0f)
{
return;
}
MoveTypeController val = Object.FindObjectOfType();
if ((Object)(object)val != (Object)null && val.debugSwitch)
{
Plugin.Log.LogInfo((object)"[Ghost] Player was standing when died — no teleport needed");
return;
}
if ((Object)(object)val != (Object)null)
{
val.debugSwitch = true;
if ((Object)(object)val.ccol != (Object)null)
{
val.ccol.height = val.standingHeight;
}
if ((Object)(object)val.cmpb != (Object)null)
{
val.cmpb.moveSpeed = val.standingSpeed;
}
}
Player val2 = _gorillaPlayer ?? Player.Instance ?? Object.FindObjectOfType();
if ((Object)(object)val2 != (Object)null)
{
val2.maxArmLength = 0f;
}
Vector3 val3 = _levelSpawnPoint;
if (!_spawnPointCaptured)
{
foreach (KeyValuePair remotePlayer in _remotePlayers)
{
if ((Object)(object)remotePlayer.Value.Head != (Object)null)
{
val3 = remotePlayer.Value.Head.transform.position;
break;
}
}
}
val3.y = 0f;
Plugin.Log.LogInfo((object)string.Format("[Ghost] Teleporting to {0} at floor level: {1}", _spawnPointCaptured ? "spawn" : "partner", val3));
TeleportLocalPlayer(val3);
}
private void TeleportLocalPlayer(Vector3 position)
{
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: 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_0074: 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_00f7: Unknown result type (might be due to invalid IL or missing references)
//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
//IL_0125: Unknown result type (might be due to invalid IL or missing references)
//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
//IL_0183: Unknown result type (might be due to invalid IL or missing references)
Player val = _gorillaPlayer ?? Player.Instance;
if ((Object)(object)val == (Object)null)
{
val = Object.FindObjectOfType();
}
if ((Object)(object)val != (Object)null)
{
object? obj = typeof(Player).GetField("playerRigidBody", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(val);
Rigidbody val2 = (Rigidbody)((obj is Rigidbody) ? obj : null);
if ((Object)(object)val2 != (Object)null)
{
val2.velocity = Vector3.zero;
val2.angularVelocity = Vector3.zero;
val2.position = position;
((Component)val2).transform.position = position;
}
((Component)val).transform.position = position;
FieldInfo field = typeof(Player).GetField("lastLeftHandPosition", BindingFlags.Instance | BindingFlags.NonPublic);
FieldInfo field2 = typeof(Player).GetField("lastRightHandPosition", BindingFlags.Instance | BindingFlags.NonPublic);
FieldInfo field3 = typeof(Player).GetField("lastHeadPosition", BindingFlags.Instance | BindingFlags.NonPublic);
if (field != null && (Object)(object)val.leftHandTransform != (Object)null)
{
field.SetValue(val, val.leftHandTransform.position);
}
if (field2 != null && (Object)(object)val.rightHandTransform != (Object)null)
{
field2.SetValue(val, val.rightHandTransform.position);
}
FieldInfo field4 = typeof(Player).GetField("headCollider", BindingFlags.Instance | BindingFlags.Public);
if (field3 != null && field4 != null)
{
object? value = field4.GetValue(val);
SphereCollider val3 = (SphereCollider)((value is SphereCollider) ? value : null);
if ((Object)(object)val3 != (Object)null)
{
field3.SetValue(val, ((Component)val3).transform.position);
}
}
_gorillaPlayer = val;
Plugin.Log.LogInfo((object)$"[Ghost] Teleported GorillaPlayer to {position}, rb.position={((val2 != null) ? new Vector3?(val2.position) : ((Vector3?)null))}");
}
else
{
Plugin.Log.LogWarning((object)"[Ghost] GorillaPlayer not found even via FindObjectOfType!");
}
}
public void ResetGhostState()
{
bool localIsGhost = _localIsGhost;
_localIsGhost = false;
_pendingGhostTeleport = false;
_pendingHomeLoad = false;
_pendingHomeLoadTimer = 0f;
_ghostSceneToReload = null;
_ghostTeleportDelay = 0f;
_pendingGhostPuzzleRestore = false;
_ghostPuzzleRestoreFrames = 0;
_savedGhostPuzzleState = null;
IsGhostSceneReload = false;
DestroyGhostVision();
if (localIsGhost && _steam != null && _steam.IsRunning)
{
_writer.Reset();
_writer.Put((byte)20);
_writer.Put(value: false);
_writer.Put(0);
SendToAllPeers();
}
Plugin.Log.LogInfo((object)"[Ghost] Ghost state reset");
}
private void SendVersionCheck(int peerId)
{
_writer.Reset();
_writer.Put((byte)21);
_writer.Put("1.2.6");
_steam.SendTo(peerId, _writer.GetBytes());
Plugin.Log.LogInfo((object)string.Format("Sent version {0} to peer {1}", "1.2.6", peerId));
}
private void HandleVersionCheck(int peerId, PacketReader reader)
{
string text = reader.GetString();
_peerVersions[peerId] = text;
Plugin.Log.LogInfo((object)string.Format("Peer {0} version: {1} (ours: {2})", peerId, text, "1.2.6"));
if (text != "1.2.6")
{
Plugin.Log.LogWarning((object)string.Format("VERSION MISMATCH! Peer {0} has {1}, we have {2}", peerId, text, "1.2.6"));
this.OnVersionMismatch?.Invoke(peerId, text);
}
}
private void SendPingToAll()
{
float realtimeSinceStartup = Time.realtimeSinceStartup;
foreach (int connectedPeerId in _connectedPeerIds)
{
_pendingPings[connectedPeerId] = realtimeSinceStartup;
_writer.Reset();
_writer.Put((byte)22);
_writer.Put(realtimeSinceStartup);
_steam.SendTo(connectedPeerId, _writer.GetBytes(), reliable: false);
}
}
private void HandlePing(int peerId, PacketReader reader)
{
float value = reader.GetFloat();
_writer.Reset();
_writer.Put((byte)23);
_writer.Put(value);
_steam.SendTo(peerId, _writer.GetBytes(), reliable: false);
}
private void HandlePong(int peerId, PacketReader reader)
{
float num = reader.GetFloat();
float value = (Time.realtimeSinceStartup - num) * 1000f;
_peerPings[peerId] = value;
_pendingPings.Remove(peerId);
}
private void HandleHostMigration(int peerId, PacketReader reader)
{
if (reader.GetBool())
{
Plugin.Log.LogInfo((object)"HOST MIGRATION: We are now the host!");
_steam.BecomeHost();
this.OnBecameHost?.Invoke();
}
}
public void TransferHost(int newHostPeerId)
{
if (_steam.IsHost)
{
_writer.Reset();
_writer.Put((byte)24);
_writer.Put(value: true);
_steam.SendTo(newHostPeerId, _writer.GetBytes());
Plugin.Log.LogInfo((object)$"Transferred host to peer {newHostPeerId}");
}
}
public int GetFirstConnectedPeer()
{
using (HashSet.Enumerator enumerator = _connectedPeerIds.GetEnumerator())
{
if (enumerator.MoveNext())
{
return enumerator.Current;
}
}
return -1;
}
public void SendVentDoorTrigger(int ventId, Vector3 position)
{
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
if (_steam != null && _steam.IsRunning)
{
_writer.Reset();
_writer.Put((byte)28);
_writer.Put(ventId);
WriteVector3(_writer, position);
SendToAllPeers();
}
}
private void HandleVentDoor(PacketReader reader)
{
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
reader.GetInt();
Vector3 val = ReadVector3(reader);
VentAnimControl[] array = Object.FindObjectsOfType();
VentAnimControl val2 = null;
float num = float.MaxValue;
VentAnimControl[] array2 = array;
foreach (VentAnimControl val3 in array2)
{
float num2 = Vector3.Distance(((Component)val3).transform.position, val);
if (num2 < num)
{
num = num2;
val2 = val3;
}
}
if ((Object)(object)val2 != (Object)null && num < 2f)
{
FieldInfo field = typeof(VentAnimControl).GetField("timer1", BindingFlags.Instance | BindingFlags.NonPublic);
if (field != null)
{
field.SetValue(val2, 10);
}
}
}
public void SendPaintingDeath()
{
if (_steam != null && _steam.IsRunning)
{
_writer.Reset();
_writer.Put((byte)29);
SendToAllPeers();
Plugin.Log.LogInfo((object)"[Host] Sent painting death to all players");
}
}
private void HandlePaintingDeath()
{
Plugin.Log.LogInfo((object)"[Client] Received painting death event");
MoveTypeController val = Object.FindObjectOfType();
if ((Object)(object)val == (Object)null || !val.isInMainRoom)
{
return;
}
paintingControl val2 = Object.FindObjectOfType();
if (!((Object)(object)val2 != (Object)null))
{
return;
}
FieldInfo field = typeof(paintingControl).GetField("jsc", BindingFlags.Instance | BindingFlags.Public);
if (!(field != null))
{
return;
}
object? value = field.GetValue(val2);
jumpscareController val3 = (jumpscareController)((value is jumpscareController) ? value : null);
if ((Object)(object)val3 != (Object)null)
{
switch (Random.Range(0, 5))
{
case 0:
val3.onDeathHarold();
break;
case 1:
val3.onDeathHenry();
break;
case 2:
val3.onDeathSmiley();
break;
case 3:
val3.onDeathSparky();
break;
case 4:
val3.onDeathJeff();
break;
}
}
}
public void CheckEndSceneSync()
{
if (_steam == null || !_steam.IsRunning || !_steam.IsHost)
{
return;
}
if ((Object)(object)_endControl == (Object)null)
{
_endControl = Object.FindObjectOfType();
}
if (!((Object)(object)_endControl == (Object)null))
{
bool num = _endControl.imageID != _lastEndImageID;
bool flag = Mathf.Abs(_endControl.barFill1 - _lastEndBarFill) > 50f;
if (num || flag)
{
_lastEndImageID = _endControl.imageID;
_lastEndBarFill = _endControl.barFill1;
SendEndProgress(_endControl.imageID, _endControl.barFill1);
}
}
}
private void SendEndProgress(int imageID, float barFill)
{
_writer.Reset();
_writer.Put((byte)40);
_writer.Put(imageID);
_writer.Put(barFill);
SendToAllPeers();
}
private void HandleEndProgress(PacketReader reader)
{
int imageID = reader.GetInt();
float barFill = reader.GetFloat();
if ((Object)(object)_endControl == (Object)null)
{
_endControl = Object.FindObjectOfType();
}
if ((Object)(object)_endControl != (Object)null)
{
_endControl.imageID = imageID;
_endControl.barFill1 = barFill;
}
}
private void CheckEarCoveringSync()
{
if (_steam != null && _steam.IsRunning && !_localIsGhost)
{
bool isCoveringEars = earMaster.isCoveringEars;
if (isCoveringEars != _lastEarCoveringState)
{
_lastEarCoveringState = isCoveringEars;
SendEarCovering(isCoveringEars);
}
}
}
private void SendEarCovering(bool isCovering)
{
_writer.Reset();
_writer.Put((byte)41);
_writer.Put(isCovering);
SendToAllPeers();
}
private void HandleEarCovering(PacketReader reader)
{
_remotePlayerCoveringEars = reader.GetBool();
}
}
public class RemotePlayer
{
private bool _usingRealHands;
private float _handUpgradeRetryTime;
private int _handUpgradeRetryCount;
private const int MAX_HAND_UPGRADE_RETRIES = 100;
private const float HAND_UPGRADE_RETRY_INTERVAL = 0.1f;
private bool _isGhost;
private float _targetLeftGrip;
private float _targetLeftTrigger;
private float _targetRightGrip;
private float _targetRightTrigger;
private Animator _leftHandAnimator;
private Animator _rightHandAnimator;
private int _animParamFlex = -1;
private int _animParamPinch = -1;
private bool _isStanding;
private Vector3 _targetHeadPos;
private Quaternion _targetHeadRot;
private Vector3 _targetLeftHandPos;
private Quaternion _targetLeftHandRot;
private Vector3 _targetRightHandPos;
private Quaternion _targetRightHandRot;
private float _lerpSpeed = 25f;
private bool _hasReceivedData;
private int _logCounter;
public int PeerId { get; }
public GameObject Head { get; private set; }
public GameObject FaceIndicator { get; private set; }
public GameObject LeftHand { get; private set; }
public GameObject RightHand { get; private set; }
public Light Flashlight { get; private set; }
public GameObject FlashlightCone { get; private set; }
public GameObject LeftBattery { get; private set; }
public GameObject RightBattery { get; private set; }
public bool IsGhost => _isGhost;
public RemotePlayer(int peerId)
{
PeerId = peerId;
CreateVisual();
}
private void CreateVisual()
{
//IL_0113: Unknown result type (might be due to invalid IL or missing references)
//IL_0134: 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_0227: Unknown result type (might be due to invalid IL or missing references)
//IL_023c: Unknown result type (might be due to invalid IL or missing references)
//IL_0251: Unknown result type (might be due to invalid IL or missing references)
//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
//IL_01df: Unknown result type (might be due to invalid IL or missing references)
//IL_0200: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)Plugin.HelmetPrefab != (Object)null)
{
Head = Object.Instantiate(Plugin.HelmetPrefab);
((Object)Head).name = $"RemotePlayer_{PeerId}_Head";
Head.transform.localScale = new Vector3(0.15f, 0.15f, 0.15f);
Collider[] componentsInChildren = Head.GetComponentsInChildren();
for (int i = 0; i < componentsInChildren.Length; i++)
{
Object.Destroy((Object)(object)componentsInChildren[i]);
}
MonoBehaviour[] componentsInChildren2 = Head.GetComponentsInChildren();
for (int i = 0; i < componentsInChildren2.Length; i++)
{
Object.Destroy((Object)(object)componentsInChildren2[i]);
}
Renderer[] componentsInChildren3 = Head.GetComponentsInChildren();
for (int i = 0; i < componentsInChildren3.Length; i++)
{
componentsInChildren3[i].enabled = true;
}
}
else
{
Head = GameObject.CreatePrimitive((PrimitiveType)0);
((Object)Head).name = $"RemotePlayer_{PeerId}_Head";
Head.transform.localScale = new Vector3(0.25f, 0.25f, 0.25f);
Object.Destroy((Object)(object)Head.GetComponent());
SetColor(Head, Color.yellow);
}
SphereCollider obj = Head.AddComponent();
obj.radius = 0.5f;
((Collider)obj).isTrigger = true;
if ((Object)(object)Plugin.HelmetPrefab == (Object)null)
{
FaceIndicator = GameObject.CreatePrimitive((PrimitiveType)0);
((Object)FaceIndicator).name = "FaceIndicator";
FaceIndicator.transform.SetParent(Head.transform);
FaceIndicator.transform.localPosition = new Vector3(0f, 0f, 0.5f);
FaceIndicator.transform.localScale = new Vector3(0.3f, 0.3f, 0.5f);
Object.Destroy((Object)(object)FaceIndicator.GetComponent());
SetColor(FaceIndicator, Color.white);
}
SetupHandVisuals();
SetupFlashlight();
SetupBatteryVisuals();
Head.transform.position = Vector3.zero;
LeftHand.transform.position = Vector3.zero;
RightHand.transform.position = Vector3.zero;
}
private void SetupHandVisuals()
{
GameObject val = null;
GameObject val2 = null;
Transform[] array = Object.FindObjectsOfType(true);
foreach (Transform val3 in array)
{
if (((Object)val3).name == "CustomHandLeft" && (Object)(object)val == (Object)null)
{
Transform parent = val3.parent;
val = ((!((Object)(object)parent != (Object)null) || !((Object)parent).name.ToLower().Contains("offsettu")) ? ((Component)val3).gameObject : ((Component)parent).gameObject);
}
else if (((Object)val3).name == "CustomHandRight" && (Object)(object)val2 == (Object)null)
{
Transform parent2 = val3.parent;
val2 = ((!((Object)(object)parent2 != (Object)null) || !((Object)parent2).name.ToLower().Contains("offsettu")) ? ((Component)val3).gameObject : ((Component)parent2).gameObject);
}
}
if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null)
{
bool num = (Object)(object)val.GetComponentInChildren(true) != (Object)null;
bool flag = (Object)(object)val2.GetComponentInChildren(true) != (Object)null;
if (num && flag)
{
LeftHand = CloneHandMesh(val, $"RemotePlayer_{PeerId}_LeftHand");
RightHand = CloneHandMesh(val2, $"RemotePlayer_{PeerId}_RightHand");
_usingRealHands = true;
TryFindHandAnimators();
return;
}
}
CreateFallbackHands();
}
private void LogHandHierarchyDetailed(Transform parent, int depth)
{
}
private GameObject FindChildByNameContains(Transform parent, string nameContains)
{
Transform[] componentsInChildren = ((Component)parent).GetComponentsInChildren(true);
foreach (Transform val in componentsInChildren)
{
if (((Object)val).name.ToLower().Contains(nameContains.ToLower()))
{
return ((Component)val).gameObject;
}
}
return null;
}
private GameObject FindHandMeshInChildren(Transform parent, string handSide)
{
Renderer[] componentsInChildren = ((Component)parent).GetComponentsInChildren(true);
foreach (Renderer val in componentsInChildren)
{
string text = ((Object)((Component)val).gameObject).name.ToLower();
if (!text.Contains("ui") && !text.Contains("canvas") && !text.Contains("text") && (text.Contains("hand") || text.Contains("palm") || text.Contains("glove") || val is SkinnedMeshRenderer))
{
return ((Component)val).gameObject;
}
}
componentsInChildren = ((Component)parent).GetComponentsInChildren(true);
foreach (Renderer val2 in componentsInChildren)
{
if (val2 is SkinnedMeshRenderer || (Object)(object)((Component)val2).GetComponent() != (Object)null)
{
return ((Component)val2).gameObject;
}
}
return null;
}
private GameObject CloneHandMesh(GameObject source, string newName)
{
//IL_0175: Unknown result type (might be due to invalid IL or missing references)
//IL_017a: Unknown result type (might be due to invalid IL or missing references)
//IL_017e: 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)
GameObject val = Object.Instantiate(source);
((Object)val).name = newName;
Hand component = val.GetComponent();
if ((Object)(object)component != (Object)null)
{
Object.Destroy((Object)(object)component);
}
MonoBehaviour[] componentsInChildren = val.GetComponentsInChildren();
for (int i = 0; i < componentsInChildren.Length; i++)
{
Object.Destroy((Object)(object)componentsInChildren[i]);
}
Collider[] componentsInChildren2 = val.GetComponentsInChildren();
for (int i = 0; i < componentsInChildren2.Length; i++)
{
Object.Destroy((Object)(object)componentsInChildren2[i]);
}
Transform[] componentsInChildren3 = val.GetComponentsInChildren(true);
foreach (Transform val2 in componentsInChildren3)
{
string text = ((Object)val2).name.ToLower();
if (text.Contains("indicator") || text.Contains("tipindicator") || text.Contains("fingertip") || text.Contains("tip_") || text.Contains("collidervisual") || text.Contains("grabvolume") || text.Contains("leftcollider") || text.Contains("rightcollider") || text.Contains("coll_hands"))
{
((Component)val2).gameObject.SetActive(false);
}
if (text.Contains("battery") || text.Contains("energycell"))
{
Object.Destroy((Object)(object)((Component)val2).gameObject);
}
if (text == "canvas")
{
Object.Destroy((Object)(object)((Component)val2).gameObject);
}
}
Renderer[] componentsInChildren4 = val.GetComponentsInChildren(true);
foreach (Renderer val3 in componentsInChildren4)
{
Bounds bounds = val3.bounds;
Vector3 size = ((Bounds)(ref bounds)).size;
if (((Vector3)(ref size)).magnitude < 0.05f)
{
string text2 = ((Object)((Component)val3).gameObject).name.ToLower();
if (!text2.Contains("hand") && !text2.Contains("geom"))
{
val3.enabled = false;
}
}
}
componentsInChildren4 = val.GetComponentsInChildren();
foreach (Renderer val4 in componentsInChildren4)
{
if (((Component)val4).gameObject.activeInHierarchy)
{
val4.enabled = true;
}
}
return val;
}
private void CreateFallbackHands()
{
//IL_0046: 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_00cb: Unknown result type (might be due to invalid IL or missing references)
//IL_0100: Unknown result type (might be due to invalid IL or missing references)
LeftHand = GameObject.CreatePrimitive((PrimitiveType)0);
((Object)LeftHand).name = $"RemotePlayer_{PeerId}_LeftHand";
LeftHand.transform.localScale = new Vector3(0.08f, 0.08f, 0.08f);
Object.Destroy((Object)(object)LeftHand.GetComponent());
SetColor(LeftHand, new Color(0f, 0.8f, 1f, 0.8f));
RightHand = GameObject.CreatePrimitive((PrimitiveType)0);
((Object)RightHand).name = $"RemotePlayer_{PeerId}_RightHand";
RightHand.transform.localScale = new Vector3(0.08f, 0.08f, 0.08f);
Object.Destroy((Object)(object)RightHand.GetComponent());
SetColor(RightHand, new Color(0f, 0.8f, 1f, 0.8f));
_usingRealHands = false;
}
private void SetupFlashlight()
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Expected O, but got Unknown
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0130: Unknown result type (might be due to invalid IL or missing references)
//IL_0154: Unknown result type (might be due to invalid IL or missing references)
//IL_0178: Unknown result type (might be due to invalid IL or missing references)
//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
GameObject val = new GameObject("Flashlight");
val.transform.SetParent(Head.transform);
val.transform.localPosition = new Vector3(0f, 0f, 0.15f);
val.transform.localRotation = Quaternion.identity;
Flashlight = val.AddComponent();
Flashlight.type = (LightType)0;
Flashlight.color = new Color(1f, 0.95f, 0.8f);
Flashlight.intensity = 0.8f;
Flashlight.range = 8f;
Flashlight.spotAngle = 35f;
Flashlight.innerSpotAngle = 20f;
Flashlight.shadows = (LightShadows)0;
((Behaviour)Flashlight).enabled = false;
FlashlightCone = GameObject.CreatePrimitive((PrimitiveType)2);
((Object)FlashlightCone).name = "FlashlightCone";
FlashlightCone.transform.SetParent(Head.transform);
FlashlightCone.transform.localPosition = new Vector3(0f, 0f, 0.4f);
FlashlightCone.transform.localRotation = Quaternion.Euler(90f, 0f, 0f);
FlashlightCone.transform.localScale = new Vector3(0.15f, 0.25f, 0.15f);
Object.Destroy((Object)(object)FlashlightCone.GetComponent());
SetColor(FlashlightCone, new Color(1f, 1f, 0.7f, 0.15f));
FlashlightCone.SetActive(false);
}
private void SetupBatteryVisuals()
{
//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
//IL_021b: Unknown result type (might be due to invalid IL or missing references)
//IL_024b: Unknown result type (might be due to invalid IL or missing references)
//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
//IL_0316: Unknown result type (might be due to invalid IL or missing references)
BackpackControl val = Object.FindObjectOfType();
if ((Object)(object)val != (Object)null && (Object)(object)val.batteryLeft != (Object)null && (Object)(object)val.batteryRight != (Object)null)
{
LeftBattery = Object.Instantiate(val.batteryLeft);
((Object)LeftBattery).name = $"RemotePlayer_{PeerId}_LeftBattery";
LeftBattery.transform.SetParent(LeftHand.transform, false);
Collider[] componentsInChildren = LeftBattery.GetComponentsInChildren();
for (int i = 0; i < componentsInChildren.Length; i++)
{
Object.Destroy((Object)(object)componentsInChildren[i]);
}
MonoBehaviour[] componentsInChildren2 = LeftBattery.GetComponentsInChildren();
for (int i = 0; i < componentsInChildren2.Length; i++)
{
Object.Destroy((Object)(object)componentsInChildren2[i]);
}
RightBattery = Object.Instantiate(val.batteryRight);
((Object)RightBattery).name = $"RemotePlayer_{PeerId}_RightBattery";
RightBattery.transform.SetParent(RightHand.transform, false);
componentsInChildren = RightBattery.GetComponentsInChildren();
for (int i = 0; i < componentsInChildren.Length; i++)
{
Object.Destroy((Object)(object)componentsInChildren[i]);
}
componentsInChildren2 = RightBattery.GetComponentsInChildren();
for (int i = 0; i < componentsInChildren2.Length; i++)
{
Object.Destroy((Object)(object)componentsInChildren2[i]);
}
LeftBattery.SetActive(false);
RightBattery.SetActive(false);
Renderer[] componentsInChildren3 = LeftBattery.GetComponentsInChildren(true);
for (int i = 0; i < componentsInChildren3.Length; i++)
{
componentsInChildren3[i].enabled = false;
}
}
else
{
LeftBattery = GameObject.CreatePrimitive((PrimitiveType)3);
((Object)LeftBattery).name = $"RemotePlayer_{PeerId}_LeftBattery";
LeftBattery.transform.SetParent(LeftHand.transform);
LeftBattery.transform.localPosition = new Vector3(0f, 0f, 0.05f);
LeftBattery.transform.localScale = new Vector3(0.04f, 0.06f, 0.08f);
Object.Destroy((Object)(object)LeftBattery.GetComponent());
SetColor(LeftBattery, new Color(1f, 0.5f, 0f));
LeftBattery.SetActive(false);
RightBattery = GameObject.CreatePrimitive((PrimitiveType)3);
((Object)RightBattery).name = $"RemotePlayer_{PeerId}_RightBattery";
RightBattery.transform.SetParent(RightHand.transform);
RightBattery.transform.localPosition = new Vector3(0f, 0f, 0.05f);
RightBattery.transform.localScale = new Vector3(0.04f, 0.06f, 0.08f);
Object.Destroy((Object)(object)RightBattery.GetComponent());
SetColor(RightBattery, new Color(1f, 0.5f, 0f));
RightBattery.SetActive(false);
}
}
public void TryUpgradeVisuals()
{
_handUpgradeRetryCount = 0;
_handUpgradeRetryTime = Time.time;
TryUpgradeHandVisuals();
}
private void TryHandUpgradeWithRetry()
{
if (!_usingRealHands && _handUpgradeRetryCount < 100 && !(Time.time - _handUpgradeRetryTime < 0.1f))
{
_handUpgradeRetryTime = Time.time;
_handUpgradeRetryCount++;
TryUpgradeHandVisuals();
}
}
private void TryFindHandAnimators()
{
if ((Object)(object)LeftHand != (Object)null && (Object)(object)_leftHandAnimator == (Object)null)
{
_leftHandAnimator = LeftHand.GetComponentInChildren();
}
if ((Object)(object)RightHand != (Object)null && (Object)(object)_rightHandAnimator == (Object)null)
{
_rightHandAnimator = RightHand.GetComponentInChildren();
}
if (((Object)(object)_leftHandAnimator != (Object)null || (Object)(object)_rightHandAnimator != (Object)null) && _animParamFlex == -1)
{
_animParamFlex = Animator.StringToHash("Flex");
_animParamPinch = Animator.StringToHash("Pinch");
}
}
private void TryUpgradeHandVisuals()
{
//IL_0343: Unknown result type (might be due to invalid IL or missing references)
//IL_0348: Unknown result type (might be due to invalid IL or missing references)
//IL_0355: Unknown result type (might be due to invalid IL or missing references)
//IL_035a: Unknown result type (might be due to invalid IL or missing references)
//IL_0367: Unknown result type (might be due to invalid IL or missing references)
//IL_036c: Unknown result type (might be due to invalid IL or missing references)
//IL_0379: Unknown result type (might be due to invalid IL or missing references)
//IL_037e: Unknown result type (might be due to invalid IL or missing references)
//IL_0423: Unknown result type (might be due to invalid IL or missing references)
//IL_0435: Unknown result type (might be due to invalid IL or missing references)
//IL_0447: Unknown result type (might be due to invalid IL or missing references)
//IL_0459: Unknown result type (might be due to invalid IL or missing references)
if (_usingRealHands)
{
return;
}
GameObject val = null;
GameObject val2 = null;
Transform[] array = Object.FindObjectsOfType(true);
Transform[] array2 = array;
foreach (Transform val3 in array2)
{
if (((Object)val3).name == "CustomHandLeft" && (Object)(object)val == (Object)null)
{
Transform parent = val3.parent;
val = ((!((Object)(object)parent != (Object)null) || !((Object)parent).name.ToLower().Contains("offsettu")) ? ((Component)val3).gameObject : ((Component)parent).gameObject);
}
else if (((Object)val3).name == "CustomHandRight" && (Object)(object)val2 == (Object)null)
{
Transform parent2 = val3.parent;
val2 = ((!((Object)(object)parent2 != (Object)null) || !((Object)parent2).name.ToLower().Contains("offsettu")) ? ((Component)val3).gameObject : ((Component)parent2).gameObject);
}
}
if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
{
array2 = array;
foreach (Transform val4 in array2)
{
string text = ((Object)val4).name.ToLower();
if (text.Contains("l_hand_skeletal") && (Object)(object)val == (Object)null)
{
val = ((Component)val4).gameObject;
}
else if (text.Contains("r_hand_skeletal") && (Object)(object)val2 == (Object)null)
{
val2 = ((Component)val4).gameObject;
}
}
}
if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
{
BackpackControl val5 = Object.FindObjectOfType();
if ((Object)(object)val5 != (Object)null)
{
if ((Object)(object)val == (Object)null && (Object)(object)val5.leftHand != (Object)null)
{
Transform val6 = val5.leftHand.transform.Find("offsettu");
if ((Object)(object)val6 != (Object)null)
{
val = ((Component)val6).gameObject;
}
else
{
SkinnedMeshRenderer componentInChildren = val5.leftHand.GetComponentInChildren(true);
if ((Object)(object)componentInChildren != (Object)null)
{
val = ((Component)componentInChildren).gameObject;
}
}
}
if ((Object)(object)val2 == (Object)null && (Object)(object)val5.rightHand != (Object)null)
{
Transform val7 = val5.rightHand.transform.Find("offsettu");
if ((Object)(object)val7 != (Object)null)
{
val2 = ((Component)val7).gameObject;
}
else
{
SkinnedMeshRenderer componentInChildren2 = val5.rightHand.GetComponentInChildren(true);
if ((Object)(object)componentInChildren2 != (Object)null)
{
val2 = ((Component)componentInChildren2).gameObject;
}
}
}
}
}
if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
{
HandAnim[] array3 = Object.FindObjectsOfType(true);
foreach (HandAnim val8 in array3)
{
string text2 = ((Object)((Component)val8).gameObject).name.ToLower();
if ((text2.Contains("left") || text2.Contains("l_")) && (Object)(object)val == (Object)null)
{
val = ((Component)val8).gameObject;
}
else if ((text2.Contains("right") || text2.Contains("r_")) && (Object)(object)val2 == (Object)null)
{
val2 = ((Component)val8).gameObject;
}
}
}
if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
{
return;
}
bool num = (Object)(object)val.GetComponentInChildren(true) != (Object)null;
bool flag = (Object)(object)val2.GetComponentInChildren(true) != (Object)null;
if (num && flag)
{
Vector3 position = LeftHand.transform.position;
Quaternion rotation = LeftHand.transform.rotation;
Vector3 position2 = RightHand.transform.position;
Quaternion rotation2 = RightHand.transform.rotation;
if ((Object)(object)LeftBattery != (Object)null)
{
LeftBattery.transform.SetParent((Transform)null);
}
if ((Object)(object)RightBattery != (Object)null)
{
RightBattery.transform.SetParent((Transform)null);
}
Object.Destroy((Object)(object)LeftHand);
Object.Destroy((Object)(object)RightHand);
LeftHand = CloneHandMesh(val, $"RemotePlayer_{PeerId}_LeftHand");
RightHand = CloneHandMesh(val2, $"RemotePlayer_{PeerId}_RightHand");
LeftHand.transform.position = position;
LeftHand.transform.rotation = rotation;
RightHand.transform.position = position2;
RightHand.transform.rotation = rotation2;
if ((Object)(object)LeftBattery != (Object)null)
{
LeftBattery.transform.SetParent(LeftHand.transform);
}
if ((Object)(object)RightBattery != (Object)null)
{
RightBattery.transform.SetParent(RightHand.transform);
}
_usingRealHands = true;
TryFindHandAnimators();
}
}
private void SetColor(GameObject obj, Color color)
{
//IL_0080: 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: Expected O, but got Unknown
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
Renderer component = obj.GetComponent();
if ((Object)(object)component != (Object)null)
{
Shader val = Shader.Find("Standard");
if ((Object)(object)val == (Object)null)
{
val = Shader.Find("Unlit/Color");
}
if ((Object)(object)val == (Object)null)
{
val = Shader.Find("Diffuse");
}
if ((Object)(object)val == (Object)null)
{
val = Shader.Find("Mobile/Diffuse");
}
if ((Object)(object)val != (Object)null)
{
component.material = new Material(val);
component.material.color = color;
}
else
{
component.material.color = color;
}
component.enabled = true;
}
}
public void SetTargets(bool isStanding, Vector3 bodyPos, Quaternion bodyRot, Vector3 headPos, Quaternion headRot, Vector3 leftHandPos, Quaternion leftHandRot, Vector3 rightHandPos, Quaternion rightHandRot, float leftGrip, float leftTrigger, float rightGrip, float rightTrigger)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: 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_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: 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_0083: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
_isStanding = isStanding;
_targetHeadPos = headPos;
_targetHeadRot = headRot;
_targetLeftHandPos = leftHandPos;
_targetLeftHandRot = leftHandRot;
_targetRightHandPos = rightHandPos;
_targetRightHandRot = rightHandRot;
_targetLeftGrip = leftGrip;
_targetLeftTrigger = leftTrigger;
_targetRightGrip = rightGrip;
_targetRightTrigger = rightTrigger;
if (!_hasReceivedData)
{
_hasReceivedData = true;
Head.transform.position = headPos;
Head.transform.rotation = headRot;
LeftHand.transform.position = leftHandPos;
LeftHand.transform.rotation = leftHandRot;
RightHand.transform.position = rightHandPos;
RightHand.transform.rotation = rightHandRot;
}
}
public void UpdateInterpolation()
{
//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
//IL_019f: Unknown result type (might be due to invalid IL or missing references)
//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
//IL_020f: Unknown result type (might be due to invalid IL or missing references)
//IL_0215: Unknown result type (might be due to invalid IL or missing references)
//IL_021b: Unknown result type (might be due to invalid IL or missing references)
//IL_023b: Unknown result type (might be due to invalid IL or missing references)
//IL_0241: Unknown result type (might be due to invalid IL or missing references)
//IL_0247: Unknown result type (might be due to invalid IL or missing references)
//IL_0267: Unknown result type (might be due to invalid IL or missing references)
//IL_026d: Unknown result type (might be due to invalid IL or missing references)
//IL_0273: Unknown result type (might be due to invalid IL or missing references)
//IL_0293: Unknown result type (might be due to invalid IL or missing references)
//IL_0299: Unknown result type (might be due to invalid IL or missing references)
//IL_029f: 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_0126: Unknown result type (might be due to invalid IL or missing references)
//IL_013c: 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_0168: Unknown result type (might be due to invalid IL or missing references)
//IL_017e: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)Head == (Object)null) && _hasReceivedData)
{
_logCounter++;
TryHandUpgradeWithRetry();
if (_animParamFlex == -1 && _usingRealHands)
{
TryFindHandAnimators();
}
if ((Object)(object)_leftHandAnimator != (Object)null && _animParamFlex != -1)
{
_leftHandAnimator.SetFloat(_animParamFlex, _targetLeftGrip);
_leftHandAnimator.SetFloat(_animParamPinch, _targetLeftTrigger);
}
if ((Object)(object)_rightHandAnimator != (Object)null && _animParamFlex != -1)
{
_rightHandAnimator.SetFloat(_animParamFlex, _targetRightGrip);
_rightHandAnimator.SetFloat(_animParamPinch, _targetRightTrigger);
}
float num = Mathf.Clamp01(Time.deltaTime * _lerpSpeed);
if (Vector3.Distance(Head.transform.position, _targetHeadPos) > 0.5f)
{
Head.transform.position = _targetHeadPos;
Head.transform.rotation = _targetHeadRot;
LeftHand.transform.position = _targetLeftHandPos;
LeftHand.transform.rotation = _targetLeftHandRot;
RightHand.transform.position = _targetRightHandPos;
RightHand.transform.rotation = _targetRightHandRot;
}
else
{
Head.transform.position = Vector3.Lerp(Head.transform.position, _targetHeadPos, num);
Head.transform.rotation = Quaternion.Slerp(Head.transform.rotation, _targetHeadRot, num);
float num2 = Mathf.Clamp01(Time.deltaTime * _lerpSpeed * 1.5f);
LeftHand.transform.position = Vector3.Lerp(LeftHand.transform.position, _targetLeftHandPos, num2);
LeftHand.transform.rotation = Quaternion.Slerp(LeftHand.transform.rotation, _targetLeftHandRot, num2);
RightHand.transform.position = Vector3.Lerp(RightHand.transform.position, _targetRightHandPos, num2);
RightHand.transform.rotation = Quaternion.Slerp(RightHand.transform.rotation, _targetRightHandRot, num2);
}
}
}
public void SetFlashlightState(bool isOn)
{
if ((Object)(object)Flashlight != (Object)null)
{
((Behaviour)Flashlight).enabled = isOn;
}
if ((Object)(object)FlashlightCone != (Object)null)
{
FlashlightCone.SetActive(isOn);
}
}
public void SetBatteryState(bool leftHolding, bool rightHolding)
{
if ((Object)(object)LeftBattery != (Object)null)
{
LeftBattery.SetActive(leftHolding);
Renderer[] componentsInChildren = LeftBattery.GetComponentsInChildren(true);
for (int i = 0; i < componentsInChildren.Length; i++)
{
componentsInChildren[i].enabled = leftHolding;
}
}
if ((Object)(object)RightBattery != (Object)null)
{
RightBattery.SetActive(rightHolding);
Renderer[] componentsInChildren = RightBattery.GetComponentsInChildren(true);
for (int i = 0; i < componentsInChildren.Length; i++)
{
componentsInChildren[i].enabled = rightHolding;
}
}
}
public void SetGhostState(bool isGhost)
{
_isGhost = isGhost;
float alpha = (isGhost ? 0.4f : 1f);
SetObjectTransparency(Head, alpha);
SetObjectTransparency(FaceIndicator, alpha);
SetObjectTransparency(LeftHand, alpha);
SetObjectTransparency(RightHand, alpha);
}
private void SetObjectTransparency(GameObject obj, float alpha)
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: 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)
if ((Object)(object)obj == (Object)null)
{
return;
}
Renderer[] componentsInChildren = obj.GetComponentsInChildren();
foreach (Renderer val in componentsInChildren)
{
if ((Object)(object)val.material != (Object)null)
{
Color color = val.material.color;
color.a = alpha;
val.material.color = color;
if (alpha < 1f)
{
val.material.SetFloat("_Mode", 3f);
val.material.SetInt("_SrcBlend", 5);
val.material.SetInt("_DstBlend", 10);
val.material.SetInt("_ZWrite", 0);
val.material.DisableKeyword("_ALPHATEST_ON");
val.material.EnableKeyword("_ALPHABLEND_ON");
val.material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
val.material.renderQueue = 3000;
}
else
{
val.material.SetFloat("_Mode", 0f);
val.material.SetInt("_SrcBlend", 1);
val.material.SetInt("_DstBlend", 0);
val.material.SetInt("_ZWrite", 1);
val.material.DisableKeyword("_ALPHATEST_ON");
val.material.DisableKeyword("_ALPHABLEND_ON");
val.material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
val.material.renderQueue = -1;
}
}
}
}
public void Destroy()
{
if ((Object)(object)Head != (Object)null)
{
Object.Destroy((Object)(object)Head);
}
if ((Object)(object)FaceIndicator != (Object)null)
{
Object.Destroy((Object)(object)FaceIndicator);
}
if ((Object)(object)LeftHand != (Object)null)
{
Object.Destroy((Object)(object)LeftHand);
}
if ((Object)(object)RightHand != (Object)null)
{
Object.Destroy((Object)(object)RightHand);
}
if ((Object)(object)LeftBattery != (Object)null)
{
Object.Destroy((Object)(object)LeftBattery);
}
if ((Object)(object)RightBattery != (Object)null)
{
Object.Destroy((Object)(object)RightBattery);
}
}
}
public class SpectateSystem
{
public const byte PACKET_SPECTATE_FRAME = 30;
public const byte PACKET_SPECTATE_START = 31;
public const byte PACKET_SPECTATE_STOP = 32;
private const int CAPTURE_WIDTH = 320;
private const int CAPTURE_HEIGHT = 180;
private const float CAPTURE_INTERVAL = 0.25f;
private const int JPEG_QUALITY = 60;
private RenderTexture _captureRT;
private Texture2D _captureTex;
private Camera _captureCamera;
private float _lastCaptureTime;
private bool _isSending;
private Texture2D _receiveTex;
private MoviePlayerSample _tvPlayer;
private Renderer _tvRenderer;
private bool _isReceiving;
private bool _tvWasPlaying;
private INetworkTransport _steam;
private PacketWriter _writer = new PacketWriter(65536);
public bool IsSending => _isSending;
public bool IsReceiving => _isReceiving;
public void Initialize(INetworkTransport steam)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Expected O, but got Unknown
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Expected O, but got Unknown
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Expected O, but got Unknown
_steam = steam;
_captureRT = new RenderTexture(320, 180, 16);
_captureRT.Create();
_captureTex = new Texture2D(320, 180, (TextureFormat)3, false);
_receiveTex = new Texture2D(2, 2, (TextureFormat)3, false);
}
public void Update()
{
if (_steam != null && _steam.IsRunning && _isSending)
{
UpdateSender();
}
}
public void StartSending()
{
if (!_isSending)
{
_captureCamera = Camera.main;
if ((Object)(object)_captureCamera == (Object)null)
{
_captureCamera = Object.FindObjectOfType();
}
if ((Object)(object)_captureCamera == (Object)null)
{
Plugin.Log.LogWarning((object)"[Spectate] No camera found, can't send frames");
return;
}
_isSending = true;
_lastCaptureTime = 0f;
SendSpectateStart();
}
}
public void StopSending()
{
if (_isSending)
{
_isSending = false;
_captureCamera = null;
SendSpectateStop();
}
}
public void StartReceiving()
{
if (_isReceiving)
{
return;
}
_tvPlayer = Object.FindObjectOfType();
if ((Object)(object)_tvPlayer == (Object)null)
{
Plugin.Log.LogWarning((object)"[Spectate] No MoviePlayerSample found in scene");
return;
}
_tvRenderer = ((Component)_tvPlayer).GetComponent();
if ((Object)(object)_tvRenderer == (Object)null)
{
Plugin.Log.LogWarning((object)"[Spectate] No Renderer on TV");
return;
}
_tvWasPlaying = _tvPlayer.IsPlaying;
_tvPlayer.Stop();
if ((Object)(object)_tvRenderer.material != (Object)null)
{
_tvRenderer.material.mainTexture = (Texture)(object)_receiveTex;
}
_isReceiving = true;
}
public void StopReceiving()
{
if (_isReceiving)
{
_isReceiving = false;
if ((Object)(object)_tvPlayer != (Object)null && _tvWasPlaying)
{
_tvPlayer.Play();
}
_tvPlayer = null;
_tvRenderer = null;
}
}
private void UpdateSender()
{
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)_captureCamera == (Object)null) && _isSending && !(Time.realtimeSinceStartup - _lastCaptureTime < 0.25f))
{
_lastCaptureTime = Time.realtimeSinceStartup;
RenderTexture targetTexture = _captureCamera.targetTexture;
_captureCamera.targetTexture = _captureRT;
_captureCamera.Render();
_captureCamera.targetTexture = targetTexture;
RenderTexture active = RenderTexture.active;
RenderTexture.active = _captureRT;
_captureTex.ReadPixels(new Rect(0f, 0f, 320f, 180f), 0, 0);
_captureTex.Apply();
RenderTexture.active = active;
byte[] array = ImageConversion.EncodeToJPG(_captureTex, 60);
if (array != null && array.Length != 0)
{
SendFrame(array);
}
}
}
private void SendFrame(byte[] jpegData)
{
if (_steam != null && _steam.IsRunning)
{
_writer.Reset();
_writer.Put((byte)30);
_writer.Put(jpegData.Length);
for (int i = 0; i < jpegData.Length; i++)
{
_writer.Put(jpegData[i]);
}
_steam.SendToAll(_writer.GetBytes(), reliable: false);
}
}
private void SendSpectateStart()
{
if (_steam != null && _steam.IsRunning)
{
_writer.Reset();
_writer.Put((byte)31);
_steam.SendToAll(_writer.GetBytes());
}
}
private void SendSpectateStop()
{
if (_steam != null && _steam.IsRunning)
{
_writer.Reset();
_writer.Put((byte)32);
_steam.SendToAll(_writer.GetBytes());
}
}
public void OnPacketReceived(byte packetType, PacketReader reader)
{
switch (packetType)
{
case 30:
HandleFrame(reader);
break;
case 31:
HandleSpectateStart();
break;
case 32:
HandleSpectateStop();
break;
}
}
private void HandleFrame(PacketReader reader)
{
if (!_isReceiving)
{
return;
}
int num = reader.GetInt();
if (num > 0 && num <= 102400)
{
byte[] array = new byte[num];
for (int i = 0; i < num; i++)
{
array[i] = reader.GetByte();
}
ImageConversion.LoadImage(_receiveTex, array);
if ((Object)(object)_tvRenderer != (Object)null && (Object)(object)_tvRenderer.material != (Object)null)
{
_tvRenderer.material.mainTexture = (Texture)(object)_receiveTex;
}
}
}
private void HandleSpectateStart()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
Scene activeScene = SceneManager.GetActiveScene();
if (((Scene)(ref activeScene)).name.Equals("Home", StringComparison.OrdinalIgnoreCase))
{
StartReceiving();
}
}
private void HandleSpectateStop()
{
StopReceiving();
}
public void Cleanup()
{
StopSending();
StopReceiving();
if ((Object)(object)_captureRT != (Object)null)
{
_captureRT.Release();
Object.Destroy((Object)(object)_captureRT);
_captureRT = null;
}
if ((Object)(object)_captureTex != (Object)null)
{
Object.Destroy((Object)(object)_captureTex);
_captureTex = null;
}
if ((Object)(object)_receiveTex != (Object)null)
{
Object.Destroy((Object)(object)_receiveTex);
_receiveTex = null;
}
}
}
public class VoiceChat
{
public const byte PACKET_VOICE = 200;
private bool _isRecording;
private INetworkTransport _steam;
private Dictionary _voicePlayers = new Dictionary();
private int _steamSampleRate;
private PacketWriter _writer = new PacketWriter(24576);
public bool Enabled { get; set; } = true;
public bool PushToTalk { get; set; }
public float MaxDistance { get; set; } = 30f;
public float MinDistance { get; set; } = 2f;
public void Initialize(INetworkTransport steam)
{
_steam = steam;
}
private void EnsureSteamReady()
{
if (_steamSampleRate != 0 || !SteamClient.IsValid)
{
return;
}
try
{
_steamSampleRate = (int)SteamUser.OptimalSampleRate;
if (_steamSampleRate == 0)
{
_steamSampleRate = 24000;
}
Plugin.Log.LogInfo((object)$"[Voice] Steam rate={_steamSampleRate}, Unity rate={AudioSettings.outputSampleRate}");
}
catch (Exception ex)
{
Plugin.Log.LogError((object)("[Voice] Sample rate error: " + ex.Message));
_steamSampleRate = 24000;
}
}
public void Update()
{
if (Enabled && _steam != null && _steam.IsConnected)
{
EnsureSteamReady();
if (_steamSampleRate != 0)
{
UpdateRecording();
UpdateVoicePlayerPositions();
}
}
}
private void UpdateRecording()
{
bool flag = !PushToTalk;
if (flag && !_isRecording)
{
SteamUser.VoiceRecord = true;
_isRecording = true;
}
else if (!flag && _isRecording)
{
SteamUser.VoiceRecord = false;
_isRecording = false;
}
if (!_isRecording || !SteamUser.HasVoiceData)
{
return;
}
byte[] array = SteamUser.ReadVoiceDataBytes();
if (array != null && array.Length != 0)
{
_writer.Reset();
_writer.Put((byte)200);
_writer.Put(array.Length);
for (int i = 0; i < array.Length; i++)
{
_writer.Put(array[i]);
}
_steam.SendToAll(_writer.GetBytes(), reliable: false);
}
}
public void OnVoiceDataReceived(int peerId, PacketReader reader)
{
if (!Enabled)
{
return;
}
EnsureSteamReady();
int num = reader.GetInt();
if (num <= 0 || num > 20000)
{
return;
}
byte[] array = new byte[num];
for (int i = 0; i < num; i++)
{
array[i] = reader.GetByte();
}
using MemoryStream memoryStream = new MemoryStream();
if (SteamUser.DecompressVoice(array, (Stream)memoryStream) > 0)
{
byte[] pcm = memoryStream.ToArray();
if (!_voicePlayers.TryGetValue(peerId, out var value))
{
value = CreateVoicePlayer(peerId);
_voicePlayers[peerId] = value;
}
value?.QueueAudio(pcm, _steamSampleRate);
}
}
private VoicePlayer CreateVoicePlayer(int peerId)
{
//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_001b: Expected O, but got Unknown
GameObject val = new GameObject($"VoicePlayer_{peerId}");
Object.DontDestroyOnLoad((Object)val);
VoicePlayer voicePlayer = val.AddComponent();
voicePlayer.PeerId = peerId;
voicePlayer.MinDistance = MinDistance;
voicePlayer.MaxDistance = MaxDistance;
return voicePlayer;
}
private void UpdateVoicePlayerPositions()
{
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
PlayerSync playerSync = MPManager.Instance?.PlayerSync;
if (playerSync == null)
{
return;
}
List list = null;
foreach (KeyValuePair voicePlayer in _voicePlayers)
{
if ((Object)(object)voicePlayer.Value == (Object)null || (Object)(object)((Component)voicePlayer.Value).gameObject == (Object)null)
{
if (list == null)
{
list = new List();
}
list.Add(voicePlayer.Key);
}
else
{
Vector3? remotePlayerPosition = playerSync.GetRemotePlayerPosition(voicePlayer.Key);
if (remotePlayerPosition.HasValue)
{
((Component)voicePlayer.Value).transform.position = remotePlayerPosition.Value;
}
}
}
if (list == null)
{
return;
}
foreach (int item in list)
{
_voicePlayers.Remove(item);
}
}
public void OnPeerDisconnected(int peerId)
{
if (_voicePlayers.TryGetValue(peerId, out var value))
{
if ((Object)(object)value != (Object)null && (Object)(object)((Component)value).gameObject != (Object)null)
{
Object.Destroy((Object)(object)((Component)value).gameObject);
}
_voicePlayers.Remove(peerId);
}
}
public void Cleanup()
{
if (_isRecording)
{
SteamUser.VoiceRecord = false;
_isRecording = false;
}
foreach (VoicePlayer value in _voicePlayers.Values)
{
if ((Object)(object)value != (Object)null && (Object)(object)((Component)value).gameObject != (Object)null)
{
Object.Destroy((Object)(object)((Component)value).gameObject);
}
}
_voicePlayers.Clear();
}
}
public class VoicePlayer : MonoBehaviour
{
private AudioSource _audioSource;
private float[] _ringBuffer;
private volatile int _writePos;
private volatile int _readPos;
private volatile int _samplesAvailable;
private readonly object _lock = new object();
private int _bufferSize;
private int _outputRate;
private float _resampleStep;
private float _resampleFrac;
private const int JITTER_MS = 20;
private int _jitterSamples;
private bool _playing;
private float _silenceTimer;
public int PeerId { get; set; }
public float MinDistance { get; set; } = 2f;
public float MaxDistance { get; set; } = 30f;
private void Awake()
{
//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
//IL_0105: Expected O, but got Unknown
_outputRate = AudioSettings.outputSampleRate;
_bufferSize = _outputRate * 2;
_ringBuffer = new float[_bufferSize];
_jitterSamples = _outputRate * 20 / 1000;
_audioSource = ((Component)this).gameObject.AddComponent();
_audioSource.spatialBlend = 1f;
_audioSource.rolloffMode = (AudioRolloffMode)1;
_audioSource.minDistance = MinDistance;
_audioSource.maxDistance = MaxDistance;
_audioSource.loop = true;
_audioSource.playOnAwake = false;
_audioSource.volume = 1f;
_audioSource.dopplerLevel = 0f;
_audioSource.priority = 0;
AudioClip clip = AudioClip.Create($"Voice_{PeerId}", 1024, 1, _outputRate, true, new PCMReaderCallback(OnAudioRead));
_audioSource.clip = clip;
_audioSource.Play();
}
public void QueueAudio(byte[] pcm, int inputRate)
{
if (pcm == null || pcm.Length < 2)
{
return;
}
_resampleStep = (float)inputRate / (float)_outputRate;
int num = pcm.Length / 2;
float[] array = new float[num];
for (int i = 0; i < num; i++)
{
short num2 = (short)(pcm[i * 2] | (pcm[i * 2 + 1] << 8));
array[i] = (float)num2 / 32768f;
}
lock (_lock)
{
while (_resampleFrac < (float)(num - 1))
{
int num3 = (int)_resampleFrac;
float num4 = _resampleFrac - (float)num3;
float num5 = ((num3 + 1 >= num) ? array[num3] : (array[num3] * (1f - num4) + array[num3 + 1] * num4));
_ringBuffer[_writePos] = num5;
_writePos = (_writePos + 1) % _bufferSize;
if (_samplesAvailable < _bufferSize)
{
_samplesAvailable++;
}
_resampleFrac += _resampleStep;
}
_resampleFrac -= (int)_resampleFrac;
if (_resampleFrac < 0f)
{
_resampleFrac = 0f;
}
}
_silenceTimer = 0f;
}
private void OnAudioRead(float[] data)
{
lock (_lock)
{
if (!_playing)
{
if (_samplesAvailable < _jitterSamples)
{
Array.Clear(data, 0, data.Length);
return;
}
_playing = true;
}
for (int i = 0; i < data.Length; i++)
{
if (_samplesAvailable > 0)
{
data[i] = _ringBuffer[_readPos];
_readPos = (_readPos + 1) % _bufferSize;
_samplesAvailable--;
}
else
{
data[i] = 0f;
_playing = false;
}
}
}
}
private void Update()
{
if ((Object)(object)_audioSource != (Object)null)
{
_audioSource.minDistance = MinDistance;
_audioSource.maxDistance = MaxDistance;
}
_silenceTimer += Time.deltaTime;
if (_silenceTimer > 1f)
{
lock (_lock)
{
_samplesAvailable = 0;
_readPos = _writePos;
_playing = false;
}
}
}
private void OnDestroy()
{
if ((Object)(object)_audioSource != (Object)null)
{
_audioSource.Stop();
if ((Object)(object)_audioSource.clip != (Object)null)
{
Object.Destroy((Object)(object)_audioSource.clip);
}
}
}
}
public interface INetworkTransport
{
bool IsRunning { get; }
bool IsHost { get; }
bool IsConnected { get; }
bool IsInLobby { get; }
bool IsJoining { get; }
bool IsLobbyLocked { get; }
int ConnectedPeerCount { get; }
int Ping { get; }
event Action OnPeerConnected;
event Action OnPeerDisconnected;
event Action OnDataReceived;
event Action OnLobbyCreated;
event Action OnLobbyJoined;
event Action OnJoinFailed;
event Action OnLobbyLeft;
event Action OnPlayerJoined;
event Action OnPlayerLeft;
event Action OnVersionMismatch;
event Action OnBecameHost;
bool Initialize();
void Shutdown();
void Update();
void StartHost(int port = 0);
void Connect(string address, int port);
void Disconnect();
void LockLobby();
void UnlockLobby();
void JoinLobby(string lobbyId);
void ProcessPendingJoin();
void BecomeHost();
void SendToAll(byte[] data, bool reliable = true);
void SendTo(int peerId, byte[] data, bool reliable = true);
string GetLobbyId();
string GetPlayerName();
List GetConnectedPlayerNames();
void InviteFriends();
}
public class PacketWriter
{
private byte[] _buffer;
private int _position;
public int Length => _position;
public PacketWriter(int initialCapacity = 256)
{
_buffer = new byte[initialCapacity];
_position = 0;
}
public void Reset()
{
_position = 0;
}
public byte[] GetBytes()
{
byte[] array = new byte[_position];
Array.Copy(_buffer, array, _position);
return array;
}
private void EnsureCapacity(int additionalBytes)
{
if (_position + additionalBytes > _buffer.Length)
{
byte[] array = new byte[Math.Max(_buffer.Length * 2, _position + additionalBytes)];
Array.Copy(_buffer, array, _position);
_buffer = array;
}
}
public void Put(byte value)
{
EnsureCapacity(1);
_buffer[_position++] = value;
}
public void Put(bool value)
{
Put(value ? ((byte)1) : ((byte)0));
}
public void Put(int value)
{
EnsureCapacity(4);
_buffer[_position++] = (byte)value;
_buffer[_position++] = (byte)(value >> 8);
_buffer[_position++] = (byte)(value >> 16);
_buffer[_position++] = (byte)(value >> 24);
}
public void Put(long value)
{
byte[] bytes = BitConverter.GetBytes(value);
EnsureCapacity(8);
Array.Copy(bytes, 0, _buffer, _position, 8);
_position += 8;
}
public void Put(float value)
{
byte[] bytes = BitConverter.GetBytes(value);
EnsureCapacity(4);
Array.Copy(bytes, 0, _buffer, _position, 4);
_position += 4;
}
public void Put(double value)
{
byte[] bytes = BitConverter.GetBytes(value);
EnsureCapacity(8);
Array.Copy(bytes, 0, _buffer, _position, 8);
_position += 8;
}
public void Put(string value)
{
if (string.IsNullOrEmpty(value))
{
Put(0);
return;
}
byte[] bytes = Encoding.UTF8.GetBytes(value);
Put(bytes.Length);
EnsureCapacity(bytes.Length);
Array.Copy(bytes, 0, _buffer, _position, bytes.Length);
_position += bytes.Length;
}
}
public class PacketReader
{
private byte[] _buffer;
private int _position;
private int _length;
public int AvailableBytes => _length - _position;
public PacketReader(byte[] data)
{
_buffer = data;
_position = 0;
_length = data.Length;
}
public byte GetByte()
{
return _buffer[_position++];
}
public bool GetBool()
{
return GetByte() != 0;
}
public int GetInt()
{
int result = _buffer[_position] | (_buffer[_position + 1] << 8) | (_buffer[_position + 2] << 16) | (_buffer[_position + 3] << 24);
_position += 4;
return result;
}
public long GetLong()
{
long result = BitConverter.ToInt64(_buffer, _position);
_position += 8;
return result;
}
public float GetFloat()
{
float result = BitConverter.ToSingle(_buffer, _position);
_position += 4;
return result;
}
public double GetDouble()
{
double result = BitConverter.ToDouble(_buffer, _position);
_position += 8;
return result;
}
public string GetString()
{
int num = GetInt();
if (num == 0)
{
return string.Empty;
}
string result = Encoding.UTF8.GetString(_buffer, _position, num);
_position += num;
return result;
}
}
public class SteamTransport : INetworkTransport
{
public class FriendGameInfo
{
public Friend Friend;
public string Name;
public SteamId SteamId;
public bool IsInGame;
public bool IsJoinable;
public ulong LobbyId;
public string Status;
}
private float _lastPingTime;
private float _pingInterval = 2f;
private Dictionary _pingSentTimes = new Dictionary();
private Dictionary _peerPings = new Dictionary();
private const byte TRANSPORT_PING = 250;
private const byte TRANSPORT_PONG = 251;
private const byte TRANSPORT_VERSION_CHECK = 252;
private const byte TRANSPORT_VERSION_MISMATCH = 253;
private const byte TRANSPORT_HOST_MIGRATION = 254;
private Dictionary _steamIdToPeerId = new Dictionary();
private Dictionary _peerIdToSteamId = new Dictionary();
private HashSet _connectedPeers = new HashSet();
private int _nextPeerId = 1;
private bool _initialized;
private const uint CRAWLSPACE2_APP_ID = 2258670u;
private HashSet _versionVerifiedPeers = new HashSet();
private int _sendFailCount;
private ulong _pendingJoinLobbyId;
public bool IsRunning { get; private set; }
public bool IsHost { get; private set; }
public bool IsJoining { get; private set; }
public bool IsConnected => _connectedPeers.Count > 0;
public int ConnectedPeerCount => _connectedPeers.Count;
public bool IsLobbyLocked { get; private set; }
public Lobby CurrentLobby { get; private set; }
public bool IsInLobby
{
get
{
//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_0009: Unknown result type (might be due to invalid IL or missing references)
Lobby currentLobby = CurrentLobby;
return ((Lobby)(ref currentLobby)).Id.Value != 0;
}
}
public int Ping { get; private set; }
public event Action OnPeerConnected;
public event Action OnPeerDisconnected;
public event Action OnDataReceived;
public event Action OnVersionMismatch;
public event Action OnBecameHost;
event Action INetworkTransport.OnLobbyCreated
{
add
{
_onLobbyCreatedString += value;
}
remove
{
_onLobbyCreatedString -= value;
}
}
event Action INetworkTransport.OnLobbyJoined
{
add
{
_onLobbyJoinedString += value;
}
remove
{
_onLobbyJoinedString -= value;
}
}
event Action INetworkTransport.OnPlayerJoined
{
add
{
_onPlayerJoinedString += value;
}
remove
{
_onPlayerJoinedString -= value;
}
}
event Action INetworkTransport.OnPlayerLeft
{
add
{
_onPlayerLeftString += value;
}
remove
{
_onPlayerLeftString -= value;
}
}
private event Action _onLobbyCreatedString;
private event Action _onLobbyJoinedString;
private event Action _onPlayerJoinedString;
private event Action _onPlayerLeftString;
public event Action OnLobbyCreated;
public event Action OnLobbyJoined;
public event Action OnJoinFailed;
public event Action OnLobbyLeft;
public event Action OnPlayerJoined;
public event Action OnPlayerLeft;
public bool Initialize()
{
if (_initialized)
{
return true;
}
try
{
if (!SteamClient.IsValid)
{
uint steamAppId = GetSteamAppId();
Plugin.Log.LogInfo((object)$"Initializing Steam with App ID: {steamAppId}");
try
{
SteamClient.Init(steamAppId, false);
}
catch (Exception ex)
{
Plugin.Log.LogError((object)("SteamClient.Init failed: " + ex.Message));
Plugin.Log.LogInfo((object)"Make sure Steam is running and you own the game!");
return false;
}
}
if (!SteamClient.IsValid)
{
Plugin.Log.LogError((object)"Steam client is not valid after init attempt");
return false;
}
SteamMatchmaking.OnLobbyCreated += HandleLobbyCreated;
SteamMatchmaking.OnLobbyEntered += HandleLobbyEntered;
SteamMatchmaking.OnLobbyMemberJoined += HandleLobbyMemberJoined;
SteamMatchmaking.OnLobbyMemberLeave += HandleLobbyMemberLeave;
SteamFriends.OnGameLobbyJoinRequested += HandleGameLobbyJoinRequested;
SteamFriends.OnGameRichPresenceJoinRequested += HandleRichPresenceJoinRequested;
SteamNetworking.OnP2PSessionRequest = (Action)Delegate.Combine(SteamNetworking.OnP2PSessionRequest, new Action(HandleP2PSessionRequest));
_initialized = true;
CheckCommandLineJoin();
return true;
}
catch (Exception ex2)
{
Plugin.Log.LogError((object)("Failed to initialize Steam: " + ex2.Message));
Plugin.Log.LogError((object)"Ensure steam_api64.dll is in the game folder and Steam is running");
return false;
}
}
private uint GetSteamAppId()
{
string path = Path.Combine(Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location))), "steam_appid.txt");
try
{
if (File.Exists(path) && uint.TryParse(File.ReadAllText(path).Trim(), out var result))
{
Plugin.Log.LogInfo((object)$"Found steam_appid.txt with ID: {result}");
return result;
}
}
catch
{
}
try
{
File.WriteAllText(path, 2258670u.ToString());
Plugin.Log.LogInfo((object)$"Created steam_appid.txt with App ID: {2258670u}");
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("Could not create steam_appid.txt: " + ex.Message));
}
return 2258670u;
}
public void StartHost(int port = 0)
{
if (Initialize())
{
IsHost = true;
IsRunning = true;
CreateLobbyAsync();
}
}
public void Connect(string address, int port)
{
if (Initialize())
{
IsHost = false;
IsRunning = true;
if (ulong.TryParse(address, out var result))
{
JoinLobbyAsync(result);
}
else
{
Plugin.Log.LogWarning((object)"Steam transport: Use lobby ID or join via Steam friends");
}
}
}
public void Disconnect()
{
LeaveLobby();
}
public void Shutdown()
{
LeaveLobby();
ClearRichPresence();
_connectedPeers.Clear();
_steamIdToPeerId.Clear();
_peerIdToSteamId.Clear();
IsRunning = false;
IsHost = false;
IsJoining = false;
}
public void Update()
{
if (!_initialized)
{
return;
}
SteamClient.RunCallbacks();
ProcessPendingJoin();
if (IsRunning)
{
ReceiveP2PMessages();
if (IsConnected && Time.realtimeSinceStartup - _lastPingTime > _pingInterval)
{
_lastPingTime = Time.realtimeSinceStartup;
SendPing();
Plugin.LogDebug($"P2P status: {_connectedPeers.Count} peers, Ping={Ping}ms");
}
}
}
private void SendPing()
{
//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)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
PacketWriter packetWriter = new PacketWriter(16);
packetWriter.Put((byte)250);
packetWriter.Put(Time.realtimeSinceStartup);
foreach (SteamId connectedPeer in _connectedPeers)
{
_pingSentTimes[connectedPeer] = Time.realtimeSinceStartup;
SendToSteamId(connectedPeer, packetWriter.GetBytes(), reliable: false);
}
}
private void HandlePing(SteamId from, float sentTime)
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
PacketWriter packetWriter = new PacketWriter(16);
packetWriter.Put((byte)251);
packetWriter.Put(sentTime);
SendToSteamId(from, packetWriter.GetBytes(), reliable: false);
}
private void HandlePong(SteamId from, float originalSentTime)
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
int value = (int)((Time.realtimeSinceStartup - originalSentTime) * 1000f / 2f);
_peerPings[from] = value;
int num = 0;
foreach (int value2 in _peerPings.Values)
{
if (value2 > num)
{
num = value2;
}
}
Ping = num;
}
private void SendVersionCheck(SteamId target)
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
PacketWriter packetWriter = new PacketWriter(64);
packetWriter.Put((byte)252);
packetWriter.Put("1.2.6");
SendToSteamId(target, packetWriter.GetBytes(), reliable: true);
}
private void HandleVersionCheck(SteamId from, string remoteVersion)
{
//IL_0006: 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_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
if (_versionVerifiedPeers.Contains(from))
{
return;
}
_versionVerifiedPeers.Add(from);
if (remoteVersion != "1.2.6")
{
Plugin.Log.LogWarning((object)("Version mismatch! Local: 1.2.6, Remote: " + remoteVersion));
PacketWriter packetWriter = new PacketWriter(64);
packetWriter.Put((byte)253);
packetWriter.Put("1.2.6");
SendToSteamId(from, packetWriter.GetBytes(), reliable: true);
if (_steamIdToPeerId.TryGetValue(from, out var _))
{
this.OnVersionMismatch?.Invoke("Player has v" + remoteVersion + " (you have v1.2.6)");
}
}
}
private void HandleVersionMismatch(SteamId from, string hostVersion)
{
this.OnVersionMismatch?.Invoke("Version mismatch! Host has v" + hostVersion + ", you have v1.2.6");
}
public void LockLobby()
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
if (IsInLobby && IsHost)
{
IsLobbyLocked = true;
Lobby currentLobby = CurrentLobby;
((Lobby)(ref currentLobby)).SetJoinable(false);
}
}
public void UnlockLobby()
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
if (IsInLobby && IsHost)
{
IsLobbyLocked = false;
Lobby currentLobby = CurrentLobby;
((Lobby)(ref currentLobby)).SetJoinable(true);
}
}
private async void CreateLobbyAsync(int maxPlayers = 10)
{
try
{
Lobby? val = await SteamMatchmaking.CreateLobbyAsync(maxPlayers);
if (val.HasValue)
{
CurrentLobby = val.Value;
Lobby currentLobby = CurrentLobby;
((Lobby)(ref currentLobby)).SetData("game", "Crawlspace2MP");
currentLobby = CurrentLobby;
((Lobby)(ref currentLobby)).SetData("version", "1.2.6");
currentLobby = CurrentLobby;
((Lobby)(ref currentLobby)).SetPublic();
currentLobby = CurrentLobby;
((Lobby)(ref currentLobby)).SetJoinable(true);
currentLobby = CurrentLobby;
((Lobby)(ref currentLobby)).SetGameServer(SteamClient.SteamId);
UpdateRichPresence();
this.OnLobbyCreated?.Invoke(CurrentLobby);
Action action = this._onLobbyCreatedString;
if (action != null)
{
currentLobby = CurrentLobby;
action(((Lobby)(ref currentLobby)).Id.Value.ToString());
}
}
else
{
IsRunning = false;
IsHost = false;
Plugin.Log.LogWarning((object)"Lobby creation returned null");
}
}
catch (Exception arg)
{
IsRunning = false;
IsHost = false;
Plugin.Log.LogError((object)$"Failed to create lobby: {arg}");
}
}
private async void JoinLobbyAsync(ulong lobbyId)
{
IsJoining = true;
try
{
Plugin.Log.LogInfo((object)$"Joining lobby {lobbyId}...");
Lobby lobby = new Lobby(SteamId.op_Implicit(lobbyId));
Plugin.Log.LogInfo((object)$"Refreshing lobby data for {lobbyId}...");
bool flag = ((Lobby)(ref lobby)).Refresh();
Plugin.Log.LogInfo((object)$"Lobby refresh result: {flag}");
await Task.Delay(500);
Task joinTask = ((Lobby)(ref lobby)).Join();
Task timeoutTask = Task.Delay(15000);
if (await Task.WhenAny(new Task[2] { joinTask, timeoutTask }) == timeoutTask)
{
IsRunning = false;
IsHost = false;
IsJoining = false;
Plugin.Log.LogWarning((object)$"Join lobby timed out for {lobbyId}");
this.OnJoinFailed?.Invoke("Connection timed out - check if host is still in lobby");
return;
}
RoomEnter val = await joinTask;
Plugin.Log.LogInfo((object)$"Lobby.Join() result: {val}");
if ((int)val == 1)
{
CurrentLobby = lobby;
IsJoining = false;
Plugin.Log.LogInfo((object)$"Joined lobby successfully! ID: {((Lobby)(ref lobby)).Id}");
await Task.Delay(100);
if (_connectedPeers.Count == 0)
{
Plugin.Log.LogInfo((object)"No peers yet after join, HandleLobbyEntered should add them...");
foreach (Friend member in ((Lobby)(ref lobby)).Members)
{
Friend current = member;
if (SteamId.op_Implicit(current.Id) != SteamId.op_Implicit(SteamClient.SteamId) && !_connectedPeers.Contains(current.Id))
{
Plugin.Log.LogInfo((object)$"Manually adding peer: {((Friend)(ref current)).Name} ({current.Id})");
SteamNetworking.AcceptP2PSessionWithUser(current.Id);
AcceptPeer(current.Id);
}
}
}
UpdateRichPresence();
this.OnLobbyJoined?.Invoke(lobby);
this._onLobbyJoinedString?.Invoke(((Lobby)(ref lobby)).Id.Value.ToString());
}
else
{
IsRunning = false;
IsHost = false;
IsJoining = false;
string text = (val - 2) switch
{
0 => "Lobby doesn't exist - host may have left",
1 => "Not allowed to join - lobby may be full or locked",
2 => "Lobby is full",
3 => "Steam error - try again",
4 => "You are banned from this lobby",
5 => "Limited user account",
6 => "Clan disabled",
7 => "Community ban",
8 => "Host has blocked you",
9 => "You have blocked the host",
_ => $"Join failed: {val}",
};
Plugin.Log.LogWarning((object)$"Join failed: {val} - {text}");
this.OnJoinFailed?.Invoke(text);
}
}
catch (Exception ex)
{
IsRunning = false;
IsHost = false;
IsJoining = false;
Plugin.Log.LogError((object)$"Failed to join lobby: {ex}");
this.OnJoinFailed?.Invoke("Error: " + ex.Message);
}
}
public void JoinLobby(SteamId lobbyId)
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
if (Initialize())
{
IsHost = false;
IsRunning = true;
JoinLobbyAsync(SteamId.op_Implicit(lobbyId));
}
}
public void JoinLobby(string lobbyId)
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
if (ulong.TryParse(lobbyId, out var result))
{
JoinLobby(new SteamId
{
Value = result
});
}
}
private void LeaveLobby()
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: 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_0054: Unknown result type (might be due to invalid IL or missing references)
if (!IsInLobby)
{
return;
}
foreach (SteamId connectedPeer in _connectedPeers)
{
SteamNetworking.CloseP2PSessionWithUser(connectedPeer);
}
Lobby val = CurrentLobby;
((Lobby)(ref val)).Leave();
val = (CurrentLobby = default(Lobby));
_connectedPeers.Clear();
this.OnLobbyLeft?.Invoke();
}
public void SendToAll(byte[] data, bool reliable = true)
{
//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_0017: Unknown result type (might be due to invalid IL or missing references)
foreach (SteamId connectedPeer in _connectedPeers)
{
SendToSteamId(connectedPeer, data, reliable);
}
}
public void SendTo(int peerId, byte[] data, bool reliable = true)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
if (_peerIdToSteamId.TryGetValue(peerId, out var value))
{
SendToSteamId(value, data, reliable);
}
}
private void SendToSteamId(SteamId target, byte[] data, bool reliable)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
P2PSend val = (P2PSend)(reliable ? 2 : 0);
if (!SteamNetworking.SendP2PPacket(target, data, data.Length, 0, val) && data.Length != 0 && data[0] != 1)
{
_sendFailCount++;
if (_sendFailCount <= 3 || _sendFailCount % 100 == 0)
{
Plugin.Log.LogWarning((object)($"Failed to send P2P packet to {target}, type={data[0]}, reliable={reliable}" + ((_sendFailCount > 3) ? $" (x{_sendFailCount})" : "")));
}
}
}
private void ReceiveP2PMessages()
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_0125: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: 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_00e7: Unknown result type (might be due to invalid IL or missing references)
//IL_00f7: 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_0117: Unknown result type (might be due to invalid IL or missing references)
int num = 0;
while (SteamNetworking.IsP2PPacketAvailable(0))
{
P2Packet? val = SteamNetworking.ReadP2PPacket(0);
if (!val.HasValue)
{
continue;
}
num++;
SteamId steamId = val.Value.SteamId;
byte[] data = val.Value.Data;
if (num <= 3)
{
Plugin.LogDebug(string.Format("Received P2P packet from {0}, size={1}, type={2}", steamId, data.Length, (data.Length != 0) ? data[0].ToString() : "empty"));
}
if (!_connectedPeers.Contains(steamId) && IsLobbyMember(steamId))
{
AcceptPeer(steamId);
}
if (data.Length != 0)
{
byte b = data[0];
if (b >= 250)
{
PacketReader packetReader = new PacketReader(data);
packetReader.GetByte();
switch (b)
{
case 250:
HandlePing(steamId, packetReader.GetFloat());
break;
case 251:
HandlePong(steamId, packetReader.GetFloat());
break;
case 252:
HandleVersionCheck(steamId, packetReader.GetString());
break;
case 253:
HandleVersionMismatch(steamId, packetReader.GetString());
break;
case 254:
HandleHostMigration(steamId);
break;
}
continue;
}
}
if (_steamIdToPeerId.TryGetValue(steamId, out var value))
{
PacketReader arg = new PacketReader(data);
this.OnDataReceived?.Invoke(value, arg);
}
}
}
private void HandleHostMigration(SteamId newHostId)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
if (SteamId.op_Implicit(newHostId) == SteamId.op_Implicit(SteamClient.SteamId))
{
IsHost = true;
this.OnBecameHost?.Invoke();
}
}
private bool IsLobbyMember(SteamId id)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: 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_0026: 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)
if (!IsInLobby)
{
return false;
}
Lobby currentLobby = CurrentLobby;
foreach (Friend member in ((Lobby)(ref currentLobby)).Members)
{
if (SteamId.op_Implicit(member.Id) == SteamId.op_Implicit(id))
{
return true;
}
}
return false;
}
private void AcceptPeer(SteamId steamId)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: 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)
SteamNetworking.AcceptP2PSessionWithUser(steamId);
_connectedPeers.Add(steamId);
int num = _nextPeerId++;
_steamIdToPeerId[steamId] = num;
_peerIdToSteamId[num] = steamId;
_sendFailCount = 0;
SendVersionCheck(steamId);
this.OnPeerConnected?.Invoke(num);
}
private void RemovePeer(SteamId steamId)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: 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_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
if (_steamIdToPeerId.TryGetValue(steamId, out var value))
{
_steamIdToPeerId.Remove(steamId);
_peerIdToSteamId.Remove(value);
_connectedPeers.Remove(steamId);
_peerPings.Remove(steamId);
_pingSentTimes.Remove(steamId);
_versionVerifiedPeers.Remove(steamId);
SteamNetworking.CloseP2PSessionWithUser(steamId);
this.OnPeerDisconnected?.Invoke(value);
}
}
private void HandleP2PSessionRequest(SteamId steamId)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
if (IsLobbyMember(steamId))
{
SteamNetworking.AcceptP2PSessionWithUser(steamId);
if (!_connectedPeers.Contains(steamId))
{
AcceptPeer(steamId);
}
}
}
private void HandleLobbyCreated(Result result, Lobby lobby)
{
}
private void HandleLobbyEntered(Lobby lobby)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: 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_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: 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_006f: Unknown result type (might be due to invalid IL or missing references)
//IL_0087: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
//IL_0100: Unknown result type (might be due to invalid IL or missing references)
//IL_0102: Unknown result type (might be due to invalid IL or missing references)
//IL_0104: Unknown result type (might be due to invalid IL or missing references)
//IL_010e: Unknown result type (might be due to invalid IL or missing references)
//IL_0120: Unknown result type (might be due to invalid IL or missing references)
//IL_0122: Unknown result type (might be due to invalid IL or missing references)
//IL_013f: Unknown result type (might be due to invalid IL or missing references)
//IL_0141: Unknown result type (might be due to invalid IL or missing references)
//IL_0155: Unknown result type (might be due to invalid IL or missing references)
//IL_0157: Unknown result type (might be due to invalid IL or missing references)
//IL_0163: Unknown result type (might be due to invalid IL or missing references)
//IL_0165: Unknown result type (might be due to invalid IL or missing references)
//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
ManualLogSource log = Plugin.Log;
object arg = ((Lobby)(ref lobby)).Id;
Friend owner = ((Lobby)(ref lobby)).Owner;
log.LogInfo((object)$"Entered lobby: {arg}, Owner: {((Friend)(ref owner)).Name} ({((Lobby)(ref lobby)).Owner.Id})");
Plugin.Log.LogInfo((object)$"We are: {SteamClient.Name} ({SteamClient.SteamId}), IsHost={IsHost}");
CurrentLobby = lobby;
int num = 0;
foreach (Friend member in ((Lobby)(ref lobby)).Members)
{
Friend current = member;
num++;
Plugin.Log.LogInfo((object)$" Lobby member {num}: {((Friend)(ref current)).Name} ({current.Id})");
}
Plugin.Log.LogInfo((object)$"Total lobby members: {num}");
foreach (Friend member2 in ((Lobby)(ref lobby)).Members)
{
Friend current2 = member2;
if (SteamId.op_Implicit(current2.Id) != SteamId.op_Implicit(SteamClient.SteamId) && !_connectedPeers.Contains(current2.Id))
{
Plugin.Log.LogInfo((object)$"Adding peer for existing lobby member: {((Friend)(ref current2)).Name} ({current2.Id})");
SteamNetworking.AcceptP2PSessionWithUser(current2.Id);
AcceptPeer(current2.Id);
}
}
Plugin.Log.LogInfo((object)$"After HandleLobbyEntered: connectedPeers={_connectedPeers.Count}, IsConnected={IsConnected}");
UpdateRichPresence();
this.OnLobbyJoined?.Invoke(lobby);
this._onLobbyJoinedString?.Invoke(((Lobby)(ref lobby)).Id.Value.ToString());
}
private void HandleLobbyMemberJoined(Lobby lobby, Friend friend)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: 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_007b: Unknown result type (might be due to invalid IL or missing references)
if (SteamId.op_Implicit(friend.Id) != SteamId.op_Implicit(SteamClient.SteamId))
{
Plugin.Log.LogInfo((object)$"Player joined lobby: {((Friend)(ref friend)).Name} ({friend.Id})");
SteamNetworking.AcceptP2PSessionWithUser(friend.Id);
if (!_connectedPeers.Contains(friend.Id))
{
AcceptPeer(friend.Id);
}
UpdateRichPresence();
this.OnPlayerJoined?.Invoke(friend);
this._onPlayerJoinedString?.Invoke(((Friend)(ref friend)).Name);
}
}
private void HandleLobbyMemberLeave(Lobby lobby, Friend friend)
{
//IL_001b: 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)
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: 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_0065: Unknown result type (might be due to invalid IL or missing references)
Plugin.Log.LogInfo((object)("Player left lobby: " + ((Friend)(ref friend)).Name));
bool num = SteamId.op_Implicit(friend.Id) == SteamId.op_Implicit(((Lobby)(ref lobby)).Owner.Id);
this.OnPlayerLeft?.Invoke(friend);
this._onPlayerLeftString?.Invoke(((Friend)(ref friend)).Name);
RemovePeer(friend.Id);
UpdateRichPresence();
if (num && IsInLobby && !IsHost)
{
CheckHostMigration();
}
}
private async void CheckHostMigration()
{
await Task.Delay(500);
if (IsInLobby)
{
Lobby currentLobby = CurrentLobby;
if (SteamId.op_Implicit(((Lobby)(ref currentLobby)).Owner.Id) == SteamId.op_Implicit(SteamClient.SteamId) && !IsHost)
{
Plugin.Log.LogInfo((object)"Host migration: We are now the lobby owner!");
IsHost = true;
PacketWriter packetWriter = new PacketWriter(16);
packetWriter.Put((byte)254);
SendToAll(packetWriter.GetBytes());
this.OnBecameHost?.Invoke();
}
}
}
private void HandleGameLobbyJoinRequested(Lobby lobby, SteamId friendId)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: 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_00dd: Unknown result type (might be due to invalid IL or missing references)
//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
Plugin.Log.LogInfo((object)$"=== STEAM JOIN REQUESTED === lobby={((Lobby)(ref lobby)).Id}, friend={friendId}");
if (((Lobby)(ref lobby)).Id.Value == 0L)
{
Plugin.Log.LogWarning((object)"Invalid lobby ID in join request");
this.OnJoinFailed?.Invoke("Invalid lobby - try using lobby code instead");
return;
}
if (IsRunning || IsInLobby || IsJoining)
{
Plugin.Log.LogWarning((object)$"Already in session (Running={IsRunning}, InLobby={IsInLobby}, Joining={IsJoining})");
this.OnJoinFailed?.Invoke("Already in a session - disconnect first");
return;
}
IsRunning = true;
IsHost = false;
IsJoining = true;
Plugin.Log.LogInfo((object)$"Joining lobby {((Lobby)(ref lobby)).Id} via Steam overlay...");
JoinLobbyAsync(SteamId.op_Implicit(((Lobby)(ref lobby)).Id));
}
private void HandleRichPresenceJoinRequested(Friend friend, string connectString)
{
Plugin.Log.LogInfo((object)("Rich presence join requested from " + ((Friend)(ref friend)).Name + ": " + connectString));
if (string.IsNullOrEmpty(connectString))
{
Plugin.Log.LogWarning((object)"Empty connect string in rich presence join");
return;
}
string[] array = connectString.Split(new char[1] { ' ' });
if (array.Length >= 2 && array[0] == "+connect_lobby")
{
if (ulong.TryParse(array[1], out var result))
{
if (IsRunning || IsInLobby || IsJoining)
{
Plugin.Log.LogWarning((object)"Already in a session, ignoring rich presence join");
this.OnJoinFailed?.Invoke("Already in a session - disconnect first");
return;
}
IsRunning = true;
IsHost = false;
IsJoining = true;
Plugin.Log.LogInfo((object)$"Joining lobby {result} via rich presence...");
JoinLobbyAsync(result);
}
else
{
Plugin.Log.LogWarning((object)("Invalid lobby ID in connect string: " + array[1]));
}
}
else
{
Plugin.Log.LogWarning((object)("Unknown connect string format: " + connectString));
}
}
private void CheckCommandLineJoin()
{
string[] commandLineArgs = Environment.GetCommandLineArgs();
Plugin.Log.LogInfo((object)("Command line args: " + string.Join(" ", commandLineArgs)));
for (int i = 0; i < commandLineArgs.Length; i++)
{
if (commandLineArgs[i] == "+connect_lobby" && i + 1 < commandLineArgs.Length && ulong.TryParse(commandLineArgs[i + 1], out var result))
{
Plugin.Log.LogInfo((object)$"Found lobby ID in command line: {result}");
_pendingJoinLobbyId = result;
}
}
}
public void ProcessPendingJoin()
{
if (_pendingJoinLobbyId != 0L && !IsRunning && !IsInLobby && !IsJoining)
{
ulong pendingJoinLobbyId = _pendingJoinLobbyId;
_pendingJoinLobbyId = 0uL;
Plugin.Log.LogInfo((object)$"Processing pending join for lobby {pendingJoinLobbyId}");
IsRunning = true;
IsHost = false;
IsJoining = true;
JoinLobbyAsync(pendingJoinLobbyId);
}
}
public string GetLobbyId()
{
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: 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)
if (!IsInLobby)
{
return "";
}
Lobby currentLobby = CurrentLobby;
return ((Lobby)(ref currentLobby)).Id.Value.ToString();
}
public void BecomeHost()
{
IsHost = true;
Plugin.Log.LogInfo((object)"BecomeHost called - we are now the host");
}
public void InviteFriends()
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
if (!IsInLobby)
{
Plugin.Log.LogWarning((object)"Cannot invite friends - not in a lobby");
return;
}
Lobby currentLobby = CurrentLobby;
SteamFriends.OpenGameInviteOverlay(((Lobby)(ref currentLobby)).Id);
Plugin.Log.LogInfo((object)"Opened Steam invite overlay");
}
public string GetPlayerName()
{
if (!SteamClient.IsValid)
{
return "Unknown";
}
return SteamClient.Name;
}
public List GetConnectedPlayerNames()
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: 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_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: 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_0038: Unknown result type (might be due to invalid IL or missing references)
List list = new List();
if (!IsInLobby)
{
return list;
}
Lobby currentLobby = CurrentLobby;
foreach (Friend member in ((Lobby)(ref currentLobby)).Members)
{
Friend current = member;
if (SteamId.op_Implicit(current.Id) != SteamId.op_Implicit(SteamClient.SteamId))
{
list.Add(((Friend)(ref current)).Name);
}
}
return list;
}
public void UpdateRichPresence()
{
//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_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
//IL_009d: 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_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)
//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
if (!_initialized)
{
return;
}
try
{
if (IsInLobby)
{
int num = _connectedPeers.Count + 1;
string arg = (IsHost ? "Hosting" : "In");
SteamFriends.SetRichPresence("status", $"{arg} Co-op ({num}P)");
Lobby currentLobby = CurrentLobby;
SteamFriends.SetRichPresence("steam_player_group", ((object)((Lobby)(ref currentLobby)).Id/*cast due to .constrained prefix*/).ToString());
SteamFriends.SetRichPresence("steam_player_group_size", num.ToString());
currentLobby = CurrentLobby;
SteamFriends.SetRichPresence("connect", $"+connect_lobby {((Lobby)(ref currentLobby)).Id}");
ManualLogSource log = Plugin.Log;
object arg2 = num;
currentLobby = CurrentLobby;
log.LogInfo((object)$"Rich presence: {arg} Co-op ({arg2}P), connect=+connect_lobby {((Lobby)(ref currentLobby)).Id}");
}
else
{
ClearRichPresence();
}
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("Failed to update rich presence: " + ex.Message));
}
}
public void ClearRichPresence()
{
if (!_initialized)
{
return;
}
try
{
SteamFriends.ClearRichPresence();
}
catch
{
}
}
public bool InviteFriend(SteamId friendId)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: 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_0033: Unknown result type (might be due to invalid IL or missing references)
if (!IsInLobby)
{
Plugin.Log.LogWarning((object)"Cannot invite friend - not in a lobby");
return false;
}
Lobby currentLobby = CurrentLobby;
bool flag = ((Lobby)(ref currentLobby)).InviteFriend(friendId);
Plugin.Log.LogInfo((object)string.Format("Invited {0} to lobby: {1}", friendId, flag ? "success" : "failed"));
return flag;
}
public List GetAllOnlineFriends()
{
//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)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: 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_0054: Unknown result type (might be due to invalid IL or missing references)
List list = new List();
if (!_initialized)
{
return list;
}
try
{
foreach (Friend friend in SteamFriends.GetFriends())
{
Friend current = friend;
if (!((Friend)(ref current)).IsOnline)
{
continue;
}
FriendGameInfo friendGameInfo = new FriendGameInfo
{
Friend = current,
Name = ((Friend)(ref current)).Name,
SteamId = current.Id,
IsInGame = ((Friend)(ref current)).IsPlayingThisGame,
IsJoinable = false,
LobbyId = 0uL,
Status = (((Friend)(ref current)).IsPlayingThisGame ? "Playing Crawlspace 2" : "Online")
};
if (((Friend)(ref current)).IsPlayingThisGame)
{
string richPresence = ((Friend)(ref current)).GetRichPresence("connect");
if (!string.IsNullOrEmpty(richPresence) && richPresence.StartsWith("+connect_lobby"))
{
string[] array = richPresence.Split(new char[1] { ' ' });
if (array.Length >= 2 && ulong.TryParse(array[1], out var result))
{
friendGameInfo.IsJoinable = true;
friendGameInfo.LobbyId = result;
friendGameInfo.Status = "In Lobby - Joinable";
}
}
string richPresence2 = ((Friend)(ref current)).GetRichPresence("status");
if (!string.IsNullOrEmpty(richPresence2))
{
friendGameInfo.Status = richPresence2;
}
}
list.Add(friendGameInfo);
}
list.Sort(delegate(FriendGameInfo a, FriendGameInfo b)
{
if (a.IsInGame != b.IsInGame)
{
return b.IsInGame.CompareTo(a.IsInGame);
}
return (a.IsJoinable != b.IsJoinable) ? b.IsJoinable.CompareTo(a.IsJoinable) : string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase);
});
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("Error getting friends list: " + ex.Message));
}
return list;
}
public List GetFriendsPlayingGame()
{
//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)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: 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_0069: Unknown result type (might be due to invalid IL or missing references)
List list = new List();
if (!_initialized)
{
return list;
}
try
{
foreach (Friend friend in SteamFriends.GetFriends())
{
Friend current = friend;
if ((!((Friend)(ref current)).IsOnline && !((Friend)(ref current)).IsPlayingThisGame) || !((Friend)(ref current)).IsPlayingThisGame)
{
continue;
}
FriendGameInfo friendGameInfo = new FriendGameInfo
{
Friend = current,
Name = ((Friend)(ref current)).Name,
SteamId = current.Id,
IsInGame = true,
IsJoinable = false,
LobbyId = 0uL,
Status = "Playing"
};
string richPresence = ((Friend)(ref current)).GetRichPresence("connect");
if (!string.IsNullOrEmpty(richPresence) && richPresence.StartsWith("+connect_lobby"))
{
string[] array = richPresence.Split(new char[1] { ' ' });
if (array.Length >= 2 && ulong.TryParse(array[1], out var result))
{
friendGameInfo.IsJoinable = true;
friendGameInfo.LobbyId = result;
friendGameInfo.Status = "In Lobby - Joinable";
}
}
string richPresence2 = ((Friend)(ref current)).GetRichPresence("status");
if (!string.IsNullOrEmpty(richPresence2))
{
friendGameInfo.Status = richPresence2;
}
list.Add(friendGameInfo);
}
}
catch (Exception ex)
{
Plugin.Log.LogWarning((object)("Error getting friends list: " + ex.Message));
}
return list;
}
public void JoinFriendGame(ulong lobbyId)
{
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
if (lobbyId == 0L)
{
Plugin.Log.LogWarning((object)"Cannot join friend - no lobby ID");
return;
}
Plugin.Log.LogInfo((object)$"Joining friend's lobby: {lobbyId}");
JoinLobby(SteamId.op_Implicit(lobbyId));
}
}
[BepInPlugin("com.crawlspace2.multiplayer", "Crawlspace2MP", "1.2.6")]
public class Plugin : BaseUnityPlugin
{
public static ManualLogSource Log { get; private set; }
public static GameObject HelmetPrefab { get; private set; }
public static bool VerboseLogging { get; private set; }
public static void LogDebug(string message)
{
if (VerboseLogging)
{
ManualLogSource log = Log;
if (log != null)
{
log.LogInfo((object)message);
}
}
}
private void Awake()
{
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: 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_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0087: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
VerboseLogging = ((BaseUnityPlugin)this).Config.Bind("Logging", "VerboseLogging", false, "Enable detailed diagnostic logging. Turn this on when reporting bugs, then send BepInEx/LogOutput.log").Value;
Log.LogInfo((object)"Crawlspace 2 Multiplayer v1.2.6 loading...");
if (VerboseLogging)
{
Log.LogInfo((object)"[Config] Verbose logging ENABLED");
}
ValidateReflection();
LoadCustomAssets();
new Harmony("com.crawlspace2.multiplayer").PatchAll();
GameObject val = new GameObject("Crawlspace2MP_Manager");
val.AddComponent();
Object.DontDestroyOnLoad((Object)val);
((Object)val).hideFlags = (HideFlags)61;
Log.LogInfo((object)"Multiplayer mod loaded!");
}
private void ValidateReflection()
{
List list = new List();
BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
if (typeof(henryBrain).GetField("resetSwitch", bindingAttr) == null)
{
list.Add("henryBrain.resetSwitch");
}
if (typeof(henryBrain).GetField("chaseSwitch", bindingAttr) == null)
{
list.Add("henryBrain.chaseSwitch");
}
if (typeof(sparkyBrain).GetField("currentState", bindingAttr) == null)
{
list.Add("sparkyBrain.currentState");
}
if (typeof(jeffBrain).GetField("currentState", bindingAttr) == null)
{
list.Add("jeffBrain.currentState");
}
if (typeof(jeffBrain).GetField("totalFlashes", bindingAttr) == null)
{
list.Add("jeffBrain.totalFlashes");
}
if (typeof(SmileBrain).GetField("isChasing", bindingAttr) == null)
{
list.Add("SmileBrain.isChasing");
}
if (typeof(SmileBrain).GetField("chaseTime", bindingAttr) == null)
{
list.Add("SmileBrain.chaseTime");
}
if (typeof(clownRandom).GetField("clownAttackingSwitch", bindingAttr) == null)
{
list.Add("clownRandom.clownAttackingSwitch");
}
if (typeof(clownRandom).GetField("clownKillTimer", bindingAttr) == null)
{
list.Add("clownRandom.clownKillTimer");
}
if (typeof(PuzzleController).GetField("puzzleHasCompleted", bindingAttr) == null)
{
list.Add("PuzzleController.puzzleHasCompleted");
}
if (typeof(PuzzleController).GetField("puzzlePresetID", bindingAttr) == null)
{
list.Add("PuzzleController.puzzlePresetID");
}
if (typeof(PuzzleController).GetField("timer2", bindingAttr) == null)
{
list.Add("PuzzleController.timer2");
}
if (typeof(PuzzleController).GetField("timer", bindingAttr) == null)
{
list.Add("PuzzleController.timer");
}
if (typeof(PuzzleController).GetField("handColorID", bindingAttr) == null)
{
list.Add("PuzzleController.handColorID");
}
if (typeof(PuzzleController).GetField("originCubeID", bindingAttr) == null)
{
list.Add("PuzzleController.originCubeID");
}
if (typeof(paintingControl).GetField("boolpaintingTall1", bindingAttr) == null)
{
list.Add("paintingControl.boolpaintingTall1");
}
if (typeof(paintingControl).GetField("boolpaintingTall2", bindingAttr) == null)
{
list.Add("paintingControl.boolpaintingTall2");
}
if (typeof(paintingControl).GetField("boolpaintingTall3", bindingAttr) == null)
{
list.Add("paintingControl.boolpaintingTall3");
}
if (typeof(paintingControl).GetField("boolpaintingSquare1", bindingAttr) == null)
{
list.Add("paintingControl.boolpaintingSquare1");
}
if (typeof(paintingControl).GetField("boolpaintingSquare2", bindingAttr) == null)
{
list.Add("paintingControl.boolpaintingSquare2");
}
if (typeof(paintingControl).GetField("boolpaintingSquare3", bindingAttr) == null)
{
list.Add("paintingControl.boolpaintingSquare3");
}
if (typeof(PuzzleBlock).GetField("blockIDValue") == null)
{
list.Add("PuzzleBlock.blockIDValue");
}
if (typeof(BackpackControl).GetField("batteryLocationID") == null)
{
list.Add("BackpackControl.batteryLocationID (static)");
}
if (typeof(BackpackControl).GetField("batteryCharge") == null)
{
list.Add("BackpackControl.batteryCharge (static)");
}
if (typeof(PuzzleMaster).GetField("totalCompletedPuzzles") == null)
{
list.Add("PuzzleMaster.totalCompletedPuzzles (static)");
}
if (typeof(earMaster).GetField("isCoveringEars") == null)
{
list.Add("earMaster.isCoveringEars (static)");
}
if (typeof(MinimapControl).GetField("timer", bindingAttr) == null)
{
list.Add("MinimapControl.timer");
}
if (typeof(MinimapControl).GetField("haroldTimer", bindingAttr) == null)
{
list.Add("MinimapControl.haroldTimer");
}
if (list.Count > 0)
{
Log.LogError((object)"╔═══════════════════════════════════════════════════════════════╗");
Log.LogError((object)$"║ CRITICAL: Reflection validation failed for {list.Count,2} field(s) ║");
Log.LogError((object)"╠═══════════════════════════════════════════════════════════════╣");
foreach (string item in list)
{
Log.LogError((object)$"║ ✗ {item,-57} ║");
}
Log.LogError((object)"╠═══════════════════════════════════════════════════════════════╣");
Log.LogError((object)"║ The game may have updated. Multiplayer features WILL break. ║");
Log.LogError((object)"║ Please report this to the mod developer. ║");
Log.LogError((object)"╚═══════════════════════════════════════════════════════════════╝");
}
else
{
Log.LogInfo((object)"✓ Reflection validation passed - all fields found");
}
}
private void LoadCustomAssets()
{
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
string text = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "mpassets");
if (!File.Exists(text))
{
return;
}
try
{
AssetBundle val = AssetBundle.LoadFromFile(text);
if (!((Object)(object)val == (Object)null))
{
GameObject val2 = val.LoadAsset("assets/sm_kaska_lp.fbx");
GameObject val3 = val.LoadAsset("assets/vr.dae");
if ((Object)(object)val2 != (Object)null && (Object)(object)val3 != (Object)null)
{
HelmetPrefab = val2;
GameObject obj = Object.Instantiate(val3);
obj.transform.SetParent(val2.transform, false);
obj.transform.localPosition = new Vector3(0f, -0.11f, 0.211f);
obj.transform.localRotation = Quaternion.identity;
((Object)obj).name = "VR_Visor";
Log.LogInfo((object)"✓ Loaded helmet with visor (SM_Kaska_LP + VR)");
}
else if ((Object)(object)val2 != (Object)null)
{
HelmetPrefab = val2;
Log.LogWarning((object)"Loaded helmet only (visor missing from asset bundle)");
}
else if ((Object)(object)val3 != (Object)null)
{
HelmetPrefab = val3;
Log.LogWarning((object)"Loaded visor only (helmet missing from asset bundle)");
}
else
{
Log.LogError((object)"Failed to load helmet or visor from asset bundle - remote players will use fallback visuals");
}
}
}
catch (Exception ex)
{
Log.LogError((object)("Error loading custom assets: " + ex.Message));
}
}
}
public class MPManager : MonoBehaviour
{
private string _statusMessage = "Initializing Steam...";
private string _connectedPlayerName = "";
private bool _steamInitialized;
private float _copiedTime = -10f;
private bool _uiHidden;
private GameObject _tutorialSign;
private string _lastLobbyId = "";
public static MPManager Instance { get; private set; }
public PlayerSync PlayerSync { get; private set; }
public SteamTransport Steam { get; private set; }
public VoiceChat VoiceChat { get; private set; }
public SpectateSystem Spectate { get; private set; }
public MultiplayerUI WorldUI { get; private set; }
public bool IsHost => Steam?.IsHost ?? false;
public bool IsConnected => Steam?.IsConnected ?? false;
public bool IsRunning => Steam?.IsRunning ?? false;
public bool IsJoining => Steam?.IsJoining ?? false;
public string LastLobbyId => _lastLobbyId;
public string StatusMessage
{
get
{
return _statusMessage;
}
set
{
_statusMessage = value;
}
}
private void Awake()
{
Instance = this;
Steam = new SteamTransport();
PlayerSync = new PlayerSync();
PlayerSync.Initialize(Steam);
VoiceChat = new VoiceChat();
VoiceChat.Initialize(Steam);
Spectate = new SpectateSystem();
Spectate.Initialize(Steam);
Steam.OnLobbyCreated += OnSteamLobbyCreated;
Steam.OnLobbyJoined += OnSteamLobbyJoined;
Steam.OnJoinFailed += OnJoinFailed;
Steam.OnPeerConnected += OnPeerConnected;
Steam.OnPeerDisconnected += OnPeerDisconnected;
Steam.OnPlayerJoined += OnPlayerJoined;
Steam.OnPlayerLeft += OnPlayerLeft;
Steam.OnVersionMismatch += OnVersionMismatch;
Steam.OnBecameHost += OnBecameHost;
SceneManager.sceneLoaded += OnSceneLoadedForLobby;
SceneManager.sceneLoaded += OnSceneLoadedForUI;
if (Steam.Initialize())
{
_steamInitialized = true;
_statusMessage = "Welcome, " + SteamClient.Name + "!";
}
else
{
_statusMessage = "Steam init failed! Is Steam running?";
Plugin.Log.LogError((object)"Failed to initialize Steam");
}
}
private void OnSteamLobbyCreated(Lobby lobby)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
string systemCopyBuffer = ((Lobby)(ref lobby)).Id.Value.ToString();
_statusMessage = "Lobby created! Code auto-copied";
GUIUtility.systemCopyBuffer = systemCopyBuffer;
_copiedTime = Time.realtimeSinceStartup;
}
private void OnSteamLobbyJoined(Lobby lobby)
{
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: 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)
Friend owner = ((Lobby)(ref lobby)).Owner;
_connectedPlayerName = ((Friend)(ref owner)).Name;
owner = ((Lobby)(ref lobby)).Owner;
_statusMessage = "Joined " + ((Friend)(ref owner)).Name + "'s game!";
}
private void OnJoinFailed(string reason)
{
_statusMessage = reason;
}
private void OnPlayerJoined(Friend friend)
{
_connectedPlayerName = ((Friend)(ref friend)).Name;
_statusMessage = ((Friend)(ref friend)).Name + " joined!";
}
private void OnPlayerLeft(Friend friend)
{
_statusMessage = ((Friend)(ref friend)).Name + " left";
if (Steam.ConnectedPeerCount == 0)
{
_connectedPlayerName = "";
_statusMessage = (IsHost ? "Waiting for players..." : "Disconnected");
}
}
private void OnPeerConnected(int peerId)
{
}
private void OnPeerDisconnected(int peerId)
{
if (Steam.ConnectedPeerCount == 0)
{
_connectedPlayerName = "";
_statusMessage = (IsHost ? "Waiting for players..." : "Partner disconnected");
}
}
private void OnVersionMismatch(string message)
{
_statusMessage = "⚠\ufe0f " + message;
Plugin.Log.LogWarning((object)("Version mismatch: " + message));
}
private void OnBecameHost()
{
_statusMessage = "You are now the host!";
}
private void OnSceneLoadedForLobby(Scene scene, LoadSceneMode mode)
{
if (Steam != null && Steam.IsInLobby)
{
if (((Scene)(ref scene)).name.Equals("Home", StringComparison.OrdinalIgnoreCase))
{
Steam.UnlockLobby();
}
else if (((Scene)(ref scene)).name.Contains("Night"))
{
Steam.LockLobby();
}
}
}
private void OnSceneLoadedForUI(Scene scene, LoadSceneMode mode)
{
bool num = ((Scene)(ref scene)).name.Equals("Home", StringComparison.OrdinalIgnoreCase);
bool num2 = ((Scene)(ref scene)).name.Equals("PreHome", StringComparison.OrdinalIgnoreCase);
if ((Object)(object)_tutorialSign != (Object)null)
{
Object.Destroy((Object)(object)_tutorialSign);
_tutorialSign = null;
}
if (num2)
{
_tutorialSign = CreateTutorialSign();
}
if (num)
{
if ((Object)(object)WorldUI == (Object)null)
{
WorldUI = ((Component)this).gameObject.AddComponent();
}
WorldUI.Initialize(this);
}
else
{
WorldUI?.Hide();
}
}
private GameObject CreateTutorialSign()
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Expected O, but got Unknown
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: 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_0084: Unknown result type (might be due to invalid IL or missing references)
//IL_00a6: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
//IL_00d2: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
//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)
//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
//IL_0105: Unknown result type (might be due to invalid IL or missing references)
//IL_0125: Unknown result type (might be due to invalid IL or missing references)
//IL_0139: Unknown result type (might be due to invalid IL or missing references)
//IL_015b: Unknown result type (might be due to invalid IL or missing references)
//IL_0160: Unknown result type (might be due to invalid IL or missing references)
//IL_016d: Unknown result type (might be due to invalid IL or missing references)
//IL_0174: 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_0194: Unknown result type (might be due to invalid IL or missing references)
//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
//IL_0203: Unknown result type (might be due to invalid IL or missing references)
GameObject val = new GameObject("MP_TutorialSign");
val.transform.position = new Vector3(-0.2434f, 1.782f, -3.8182f);
val.transform.rotation = Quaternion.Euler(0f, 180f, 0f);
Canvas obj = val.AddComponent