using System;
using System.Collections;
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 BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using PurrNet;
using PurrNet.Modules;
using PurrNet.Packing;
using PurrNet.Transports;
using PurrNet.Utils;
using UnityEngine;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("RejoinStateRecovery")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.9.0")]
[assembly: AssemblyInformationalVersion("1.0.9")]
[assembly: AssemblyProduct("RejoinStateRecovery")]
[assembly: AssemblyTitle("RejoinStateRecovery")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.9.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
}
namespace RejoinStateRecovery
{
[BepInPlugin("io.damon.ontogether.rejoinstaterecovery", "RejoinStateRecovery", "1.0.9")]
public sealed class Plugin : BaseUnityPlugin
{
private enum RejoinMessageType : byte
{
SnapshotRequest = 1,
SnapshotData,
SnapshotApplyAck
}
[Serializable]
private sealed class NetworkPayloadV1
{
public byte[] Data = Array.Empty<byte>();
}
[Serializable]
private sealed class SnapshotRequestV1
{
public string Reason = string.Empty;
public string RequestedAtUtc = string.Empty;
public ulong ClientPlayerId;
public string ClientSteamId = string.Empty;
}
[Serializable]
private sealed class SnapshotApplyAckV1
{
public long SnapshotVersion;
public string AppliedAtUtc = string.Empty;
public string Status = string.Empty;
}
[Serializable]
private sealed class RejoinSnapshotV1
{
public long SnapshotVersion;
public ulong PlayerId;
public string PlayerSteamId = string.Empty;
public string PlayerName = string.Empty;
public SerializableVector3 Position;
public SerializableQuaternion Rotation;
public int MovementState;
public int FocusIndex;
public int FocusTypeValue = -1;
public bool IsFocus;
public int PomodoroMinute;
public bool PomodoroPaused;
public int PomodoroType;
public bool IsMessagePanelOpen;
public bool IsPomodoroPanelOpen;
public bool IsTodoPanelOpen;
public bool WasFishingActive;
public int FishingStateValue = -1;
public bool HasFishingHookPosition;
public SerializableVector3 FishingHookPosition;
public string SceneName = string.Empty;
public string SnapshotSentAtUtc = string.Empty;
public string Reason = string.Empty;
public long CapturedAtUtcTicks;
}
public sealed class ConfigurationManagerAttributes
{
public string? DispName { get; set; }
public int? Order { get; set; }
}
[Serializable]
private struct SerializableVector3
{
public float X;
public float Y;
public float Z;
public static implicit operator SerializableVector3(Vector3 value)
{
//IL_000a: 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_0024: Unknown result type (might be due to invalid IL or missing references)
SerializableVector3 result = default(SerializableVector3);
result.X = value.x;
result.Y = value.y;
result.Z = value.z;
return result;
}
public static implicit operator Vector3(SerializableVector3 value)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
return new Vector3(value.X, value.Y, value.Z);
}
}
[Serializable]
private struct SerializableQuaternion
{
public float X;
public float Y;
public float Z;
public float W;
public static implicit operator SerializableQuaternion(Quaternion value)
{
//IL_000a: 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_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
SerializableQuaternion result = default(SerializableQuaternion);
result.X = value.x;
result.Y = value.y;
result.Z = value.z;
result.W = value.w;
return result;
}
public static implicit operator Quaternion(SerializableQuaternion value)
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
return new Quaternion(value.X, value.Y, value.Z, value.W);
}
}
private readonly struct DecodedEnvelope
{
public readonly byte Version;
public readonly byte MessageType;
public readonly ulong SenderPlayerId;
public readonly string PayloadJson;
public DecodedEnvelope(byte version, byte messageType, ulong senderPlayerId, string payloadJson)
{
Version = version;
MessageType = messageType;
SenderPlayerId = senderPlayerId;
PayloadJson = payloadJson;
}
}
private static class PacketEnvelopeV1
{
private static readonly byte[] Magic = new byte[4] { 79, 84, 81, 49 };
private const byte Version = 1;
public static byte[] Encode(byte messageType, ulong senderPlayerId, string payloadJson)
{
byte[] bytes = Encoding.UTF8.GetBytes(payloadJson ?? string.Empty);
using MemoryStream memoryStream = new MemoryStream();
using BinaryWriter binaryWriter = new BinaryWriter(memoryStream, Encoding.UTF8);
binaryWriter.Write(Magic);
binaryWriter.Write((byte)1);
binaryWriter.Write(messageType);
binaryWriter.Write(senderPlayerId);
binaryWriter.Write(bytes.Length);
binaryWriter.Write(bytes);
binaryWriter.Flush();
return memoryStream.ToArray();
}
public static bool TryDecode(byte[]? bytes, out DecodedEnvelope envelope)
{
envelope = default(DecodedEnvelope);
if (bytes == null || bytes.Length < 18)
{
return false;
}
try
{
using MemoryStream input = new MemoryStream(bytes);
using BinaryReader binaryReader = new BinaryReader(input, Encoding.UTF8);
byte[] array = binaryReader.ReadBytes(4);
if (array.Length != 4 || !MatchesMagic(array))
{
return false;
}
byte b = binaryReader.ReadByte();
if (b != 1)
{
return false;
}
byte messageType = binaryReader.ReadByte();
ulong senderPlayerId = binaryReader.ReadUInt64();
int num = binaryReader.ReadInt32();
if (num < 0 || num > bytes.Length)
{
return false;
}
byte[] bytes2 = binaryReader.ReadBytes(num);
string @string = Encoding.UTF8.GetString(bytes2);
envelope = new DecodedEnvelope(b, messageType, senderPlayerId, @string);
return true;
}
catch
{
return false;
}
}
private static bool MatchesMagic(byte[] value)
{
if (value[0] == Magic[0] && value[1] == Magic[1] && value[2] == Magic[2])
{
return value[3] == Magic[3];
}
return false;
}
}
[HarmonyPatch(typeof(NetworkManager), "RegisterModules")]
private static class NetworkManagerRegisterModulesPatch
{
private static void Prefix()
{
RegisterNetworkPayloadContracts();
}
}
private const string PluginGuid = "io.damon.ontogether.rejoinstaterecovery";
private const string PluginName = "RejoinStateRecovery";
private const string PluginVersion = "1.0.9";
private readonly Harmony _harmony = new Harmony("io.damon.ontogether.rejoinstaterecovery");
private readonly Dictionary<ulong, RejoinSnapshotV1> _snapshots = new Dictionary<ulong, RejoinSnapshotV1>();
private readonly Dictionary<string, RejoinSnapshotV1> _snapshotsBySteamId = new Dictionary<string, RejoinSnapshotV1>(StringComparer.Ordinal);
private readonly Dictionary<ulong, long> _lastAckByPlayer = new Dictionary<ulong, long>();
private ConfigEntry<float> _snapshotIntervalSeconds;
private ConfigEntry<bool> _sendOnReconnectOnly;
private ConfigEntry<bool> _applyUiState;
private ConfigEntry<bool> _showNotifications;
private ConfigEntry<bool> _enableLocalFallback;
private ConfigEntry<float> _localFallbackDelaySeconds;
private ConfigEntry<float> _localFallbackMaxAgeMinutes;
private ConfigEntry<float> _localCaptureIntervalSeconds;
private ConfigEntry<bool> _persistLocalSnapshot;
private ConfigEntry<bool> _safePositionRestore;
private ConfigEntry<float> _maxRestoreDistanceMeters;
private ConfigEntry<float> _groundSnapCastHeight;
private ConfigEntry<float> _groundSnapCastDistance;
private ConfigEntry<float> _groundSnapOffsetY;
private ConfigEntry<float> _groundSnapMaxUpwardAdjust;
private ConfigEntry<float> _focusRestoreDelaySeconds;
private ConfigEntry<bool> _resumeFishingOnRestore;
private NetworkManager? _network;
private Coroutine? _bootstrapCoroutine;
private Coroutine? _snapshotCoroutine;
private Coroutine? _snapshotRequestRetryCoroutine;
private Coroutine? _applySnapshotCoroutine;
private Coroutine? _localSnapshotCoroutine;
private Coroutine? _localFallbackCoroutine;
private Coroutine? _focusRestoreCoroutine;
private Coroutine? _fishingResumeCoroutine;
private bool _snapshotAppliedThisSession;
private long _lastAppliedSnapshotVersion;
private long _snapshotVersion;
private FieldInfo? _focusIndexField;
private FieldInfo? _focusSimpledTypesField;
private FieldInfo? _focusTypeField;
private FieldInfo? _characterControllerField;
private FieldInfo? _fishingCastIndicatorField;
private FieldInfo? _fishingCollisionLayersField;
private MethodInfo? _fishingCastFishingRodMethod;
private RejoinSnapshotV1? _lastLocalSnapshot;
private RejoinSnapshotV1? _lastTerminalLocalSnapshot;
private RejoinSnapshotV1? _preAttachLocalSnapshot;
private string _localSnapshotStatePath = string.Empty;
public static ManualLogSource Log;
private void Awake()
{
Log = ((BaseUnityPlugin)this).Logger;
_snapshotIntervalSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("General", "SnapshotIntervalSeconds", 5f, DescribeSetting("How frequently the host samples and stores per-player snapshot data.", "Snapshot Interval (sec)", 120, (AcceptableValueBase?)(object)new AcceptableValueRange<float>(1f, 30f)));
_sendOnReconnectOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "SendOnReconnectOnly", true, DescribeSetting("If true, targeted restore sends only when the player is marked as reconnecting.", "Send On Reconnect Only", 110));
_applyUiState = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ApplyUiState", true, DescribeSetting("If true, restores key local UI panel states on snapshot apply.", "Apply UI State", 100));
_showNotifications = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowNotifications", true, DescribeSetting("If true, shows brief in-game notifications when snapshot restore runs.", "Show Notifications", 90));
_enableLocalFallback = ((BaseUnityPlugin)this).Config.Bind<bool>("Fallback", "EnableLocalFallback", true, DescribeSetting("If true, applies last local pre-disconnect snapshot when host snapshot is unavailable.", "Enable Local Fallback", 120));
_localFallbackDelaySeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Fallback", "LocalFallbackDelaySeconds", 6f, DescribeSetting("Delay before local fallback restore is attempted after connect.", "Fallback Delay (sec)", 110, (AcceptableValueBase?)(object)new AcceptableValueRange<float>(1f, 20f)));
_localFallbackMaxAgeMinutes = ((BaseUnityPlugin)this).Config.Bind<float>("Fallback", "LocalFallbackMaxAgeMinutes", 20f, DescribeSetting("Maximum age for local fallback snapshot.", "Fallback Max Age (min)", 100, (AcceptableValueBase?)(object)new AcceptableValueRange<float>(1f, 120f)));
_localCaptureIntervalSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Fallback", "LocalCaptureIntervalSeconds", 1f, DescribeSetting("How often local fallback snapshots are captured while connected.", "Capture Interval (sec)", 90, (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0.25f, 10f)));
_persistLocalSnapshot = ((BaseUnityPlugin)this).Config.Bind<bool>("Fallback", "PersistLocalSnapshot", true, DescribeSetting("If true, stores the latest local snapshot on disk for cross-session fallback.", "Persist Local Snapshot", 80));
_safePositionRestore = ((BaseUnityPlugin)this).Config.Bind<bool>("Safety", "SafePositionRestore", true, DescribeSetting("If true, validates and ground-snaps restored positions.", "Safe Position Restore", 140));
_maxRestoreDistanceMeters = ((BaseUnityPlugin)this).Config.Bind<float>("Safety", "MaxRestoreDistanceMeters", 150f, DescribeSetting("Maximum horizontal distance allowed from current position when restoring.", "Max Restore Distance (m)", 130, (AcceptableValueBase?)(object)new AcceptableValueRange<float>(5f, 1000f)));
_groundSnapCastHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Safety", "GroundSnapCastHeight", 20f, DescribeSetting("Raycast height above desired restore position for ground snap.", "Ground Snap Cast Height", 120, (AcceptableValueBase?)(object)new AcceptableValueRange<float>(2f, 80f)));
_groundSnapCastDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Safety", "GroundSnapCastDistance", 80f, DescribeSetting("Maximum downward raycast distance used by ground snap.", "Ground Snap Cast Distance", 110, (AcceptableValueBase?)(object)new AcceptableValueRange<float>(5f, 200f)));
_groundSnapOffsetY = ((BaseUnityPlugin)this).Config.Bind<float>("Safety", "GroundSnapOffsetY", 0.15f, DescribeSetting("Vertical offset added above the chosen support hit when restoring.", "Ground Snap Offset Y", 100, (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0f, 1f)));
_groundSnapMaxUpwardAdjust = ((BaseUnityPlugin)this).Config.Bind<float>("Safety", "GroundSnapMaxUpwardAdjust", 0.35f, DescribeSetting("Maximum upward snap (meters) allowed above the saved Y before a lower nearby support is preferred.", "Ground Snap Max Upward (m)", 90, (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0f, 3f)));
_focusRestoreDelaySeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Focus", "FocusRestoreDelaySeconds", 2.5f, DescribeSetting("Delay between snapshot apply (position restore) and focus restore attempts.", "Focus Restore Delay (sec)", 120, (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0f, 15f)));
_resumeFishingOnRestore = ((BaseUnityPlugin)this).Config.Bind<bool>("Fishing", "ResumeFishingOnRestore", true, DescribeSetting("If true, attempts to reopen rod and cast to saved hook position after snapshot apply.", "Resume Fishing On Restore", 120));
_localSnapshotStatePath = Path.Combine(Paths.ConfigPath, "io.damon.ontogether.rejoinstaterecovery", "local_snapshot.json");
LoadPersistedLocalSnapshot();
_harmony.PatchAll();
SceneManager.sceneLoaded += OnSceneLoaded;
_bootstrapCoroutine = ((MonoBehaviour)this).StartCoroutine(NetworkBootstrapLoop());
((BaseUnityPlugin)this).Logger.LogInfo((object)"RejoinStateRecovery loaded (io.damon.ontogether.rejoinstaterecovery)");
}
private void OnDestroy()
{
SceneManager.sceneLoaded -= OnSceneLoaded;
if (_bootstrapCoroutine != null)
{
((MonoBehaviour)this).StopCoroutine(_bootstrapCoroutine);
_bootstrapCoroutine = null;
}
if (_snapshotCoroutine != null)
{
((MonoBehaviour)this).StopCoroutine(_snapshotCoroutine);
_snapshotCoroutine = null;
}
if (_snapshotRequestRetryCoroutine != null)
{
((MonoBehaviour)this).StopCoroutine(_snapshotRequestRetryCoroutine);
_snapshotRequestRetryCoroutine = null;
}
if (_applySnapshotCoroutine != null)
{
((MonoBehaviour)this).StopCoroutine(_applySnapshotCoroutine);
_applySnapshotCoroutine = null;
}
if (_localSnapshotCoroutine != null)
{
((MonoBehaviour)this).StopCoroutine(_localSnapshotCoroutine);
_localSnapshotCoroutine = null;
}
if (_localFallbackCoroutine != null)
{
((MonoBehaviour)this).StopCoroutine(_localFallbackCoroutine);
_localFallbackCoroutine = null;
}
if (_focusRestoreCoroutine != null)
{
((MonoBehaviour)this).StopCoroutine(_focusRestoreCoroutine);
_focusRestoreCoroutine = null;
}
if (_fishingResumeCoroutine != null)
{
((MonoBehaviour)this).StopCoroutine(_fishingResumeCoroutine);
_fishingResumeCoroutine = null;
}
if ((Object)(object)_network != (Object)null)
{
CaptureLocalSnapshot("ondestroy-capture", verbose: true);
}
UnhookNetwork();
_harmony.UnpatchSelf();
}
private void OnSceneLoaded(Scene _, LoadSceneMode __)
{
TryHookNetwork();
}
private IEnumerator NetworkBootstrapLoop()
{
while (true)
{
TryHookNetwork();
yield return (object)new WaitForSeconds(1f);
}
}
private void TryHookNetwork()
{
//IL_009e: Unknown result type (might be due to invalid IL or missing references)
//IL_00a8: Expected O, but got Unknown
//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
//IL_00d6: Expected O, but got Unknown
NetworkManager main = NetworkManager.main;
if (!((Object)(object)main == (Object)null) && main != _network)
{
if ((Object)(object)_network != (Object)null)
{
CaptureLocalSnapshot("network-switch-capture", verbose: true);
}
UnhookNetwork();
_network = main;
_preAttachLocalSnapshot = CloneSnapshot(_lastTerminalLocalSnapshot ?? _lastLocalSnapshot);
RegisterNetworkPayloadContracts();
_network.Subscribe<NetworkPayloadV1>((PlayerBroadcastDelegate<NetworkPayloadV1>)OnNetworkPayload, true);
_network.Subscribe<NetworkPayloadV1>((PlayerBroadcastDelegate<NetworkPayloadV1>)OnNetworkPayload, false);
_network.onPlayerJoined += new OnPlayerJoinedEvent(OnPlayerJoined);
_network.onClientConnectionState += OnClientConnectionState;
_network.onNetworkShutdown += new OnSubscribeDelegate(OnNetworkShutdown);
if (_snapshotCoroutine != null)
{
((MonoBehaviour)this).StopCoroutine(_snapshotCoroutine);
}
_snapshotCoroutine = ((MonoBehaviour)this).StartCoroutine(HostSnapshotLoop());
if (_localSnapshotCoroutine != null)
{
((MonoBehaviour)this).StopCoroutine(_localSnapshotCoroutine);
}
_localSnapshotCoroutine = ((MonoBehaviour)this).StartCoroutine(LocalSnapshotLoop());
_snapshotAppliedThisSession = false;
_lastAppliedSnapshotVersion = 0L;
if (_network.isClient && !_network.isServer)
{
BeginSnapshotRequestRetry("network-attached");
BeginLocalFallback("network-attached");
}
}
}
private void UnhookNetwork()
{
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Expected O, but got Unknown
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Expected O, but got Unknown
if (!((Object)(object)_network == (Object)null))
{
try
{
_network.Unsubscribe<NetworkPayloadV1>((PlayerBroadcastDelegate<NetworkPayloadV1>)OnNetworkPayload, true);
_network.Unsubscribe<NetworkPayloadV1>((PlayerBroadcastDelegate<NetworkPayloadV1>)OnNetworkPayload, false);
_network.onPlayerJoined -= new OnPlayerJoinedEvent(OnPlayerJoined);
_network.onClientConnectionState -= OnClientConnectionState;
_network.onNetworkShutdown -= new OnSubscribeDelegate(OnNetworkShutdown);
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("Network unhook warning: " + ex.Message));
}
if (_snapshotRequestRetryCoroutine != null)
{
((MonoBehaviour)this).StopCoroutine(_snapshotRequestRetryCoroutine);
_snapshotRequestRetryCoroutine = null;
}
if (_applySnapshotCoroutine != null)
{
((MonoBehaviour)this).StopCoroutine(_applySnapshotCoroutine);
_applySnapshotCoroutine = null;
}
if (_localSnapshotCoroutine != null)
{
((MonoBehaviour)this).StopCoroutine(_localSnapshotCoroutine);
_localSnapshotCoroutine = null;
}
if (_localFallbackCoroutine != null)
{
((MonoBehaviour)this).StopCoroutine(_localFallbackCoroutine);
_localFallbackCoroutine = null;
}
if (_focusRestoreCoroutine != null)
{
((MonoBehaviour)this).StopCoroutine(_focusRestoreCoroutine);
_focusRestoreCoroutine = null;
}
if (_fishingResumeCoroutine != null)
{
((MonoBehaviour)this).StopCoroutine(_fishingResumeCoroutine);
_fishingResumeCoroutine = null;
}
_snapshotAppliedThisSession = false;
_lastAppliedSnapshotVersion = 0L;
_preAttachLocalSnapshot = null;
_network = null;
}
}
private static void RegisterNetworkPayloadContracts()
{
Type typeFromHandle = typeof(NetworkPayloadV1);
if (Hasher.IsRegistered(typeFromHandle))
{
RegisterNetworkPayloadPacker();
return;
}
Hasher.PrepareType(typeFromHandle);
RegisterNetworkPayloadPacker();
}
[RegisterPackers(-10)]
private static void RegisterNetworkPayloadContractsForPurrNet()
{
NetworkRegister.Hash(typeof(NetworkPayloadV1).TypeHandle);
RegisterNetworkPayloadPacker();
}
private static void RegisterNetworkPayloadPacker()
{
Packer<NetworkPayloadV1>.RegisterWriter((WriteFunc<NetworkPayloadV1>)WriteNetworkPayload);
Packer<NetworkPayloadV1>.RegisterReader((ReadFunc<NetworkPayloadV1>)ReadNetworkPayload);
}
private static void WriteNetworkPayload(BitPacker packer, NetworkPayloadV1 payload)
{
byte[] array = payload?.Data ?? Array.Empty<byte>();
Packer<byte[]>.Write(packer, array);
}
private static void ReadNetworkPayload(BitPacker packer, ref NetworkPayloadV1 payload)
{
if (payload == null)
{
payload = new NetworkPayloadV1();
}
byte[] data = payload.Data;
Packer<byte[]>.Read(packer, ref data);
payload.Data = data ?? Array.Empty<byte>();
}
private void OnNetworkShutdown(NetworkManager manager, bool _)
{
if (manager == _network)
{
CaptureLocalSnapshot("shutdown-capture", verbose: true);
_snapshotAppliedThisSession = false;
_lastAppliedSnapshotVersion = 0L;
UnhookNetwork();
}
}
private void OnClientConnectionState(ConnectionState state)
{
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Invalid comparison between Unknown and I4
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Invalid comparison between Unknown and I4
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Invalid comparison between Unknown and I4
if (!((Object)(object)_network == (Object)null))
{
if (_network.isClient && !_network.isServer && (int)state == 1)
{
BeginSnapshotRequestRetry("client-connected");
BeginLocalFallback("client-connected");
}
else if (_network.isClient && ((int)state == 3 || (int)state == 2))
{
CaptureLocalSnapshot("disconnect-capture", verbose: true);
}
}
}
private void BeginSnapshotRequestRetry(string reason)
{
if (_snapshotRequestRetryCoroutine != null)
{
((MonoBehaviour)this).StopCoroutine(_snapshotRequestRetryCoroutine);
}
_snapshotRequestRetryCoroutine = ((MonoBehaviour)this).StartCoroutine(SnapshotRequestRetryLoop(reason));
}
private IEnumerator SnapshotRequestRetryLoop(string reason)
{
for (int attempt = 1; attempt <= 20; attempt++)
{
if ((Object)(object)_network == (Object)null || !_network.isClient || _network.isServer || _snapshotAppliedThisSession)
{
yield break;
}
SendSnapshotRequest($"{reason}-attempt-{attempt}");
yield return (object)new WaitForSeconds(2f);
}
((BaseUnityPlugin)this).Logger.LogInfo((object)("Snapshot request retries exhausted (reason='" + reason + "')"));
}
private void BeginLocalFallback(string reason)
{
if (_enableLocalFallback.Value)
{
if (_localFallbackCoroutine != null)
{
((MonoBehaviour)this).StopCoroutine(_localFallbackCoroutine);
}
_localFallbackCoroutine = ((MonoBehaviour)this).StartCoroutine(LocalFallbackAfterDelay(reason));
}
}
private IEnumerator LocalFallbackAfterDelay(string reason)
{
yield return (object)new WaitForSeconds(Mathf.Max(1f, _localFallbackDelaySeconds.Value));
if (_snapshotAppliedThisSession || (Object)(object)_network == (Object)null || !_network.isClient || _network.isServer)
{
_localFallbackCoroutine = null;
yield break;
}
RejoinSnapshotV1 preAttachLocalSnapshot = _preAttachLocalSnapshot;
if (preAttachLocalSnapshot == null)
{
((BaseUnityPlugin)this).Logger.LogInfo((object)("Local fallback skipped: no pre-attach snapshot (reason='" + reason + "')"));
_localFallbackCoroutine = null;
yield break;
}
if (preAttachLocalSnapshot.CapturedAtUtcTicks > 0)
{
DateTime dateTime = new DateTime(preAttachLocalSnapshot.CapturedAtUtcTicks, DateTimeKind.Utc);
if ((DateTime.UtcNow - dateTime).TotalMinutes > (double)Math.Max(1f, _localFallbackMaxAgeMinutes.Value))
{
((BaseUnityPlugin)this).Logger.LogInfo((object)("Local fallback skipped: snapshot too old (reason='" + reason + "')"));
_localFallbackCoroutine = null;
yield break;
}
}
Vector3 val = preAttachLocalSnapshot.Position;
if (IsLikelyInvalidLocalCapture(val, preAttachLocalSnapshot.Reason))
{
((BaseUnityPlugin)this).Logger.LogInfo((object)$"Local fallback skipped: snapshot position invalid {val.x:0.00},{val.y:0.00},{val.z:0.00} (reason='{reason}')");
_localFallbackCoroutine = null;
yield break;
}
string reason2 = preAttachLocalSnapshot.Reason;
preAttachLocalSnapshot.Reason = "local-fallback:" + reason;
((BaseUnityPlugin)this).Logger.LogInfo((object)$"Applying local fallback snapshot v{preAttachLocalSnapshot.SnapshotVersion} from {preAttachLocalSnapshot.Position.X:0.00},{preAttachLocalSnapshot.Position.Y:0.00},{preAttachLocalSnapshot.Position.Z:0.00} (capturedReason='{reason2}')");
if (_applySnapshotCoroutine != null)
{
((MonoBehaviour)this).StopCoroutine(_applySnapshotCoroutine);
}
_applySnapshotCoroutine = ((MonoBehaviour)this).StartCoroutine(ApplySnapshotWhenReady(preAttachLocalSnapshot));
_localFallbackCoroutine = null;
}
private IEnumerator LocalSnapshotLoop()
{
while (true)
{
if ((Object)(object)_network != (Object)null && _network.isClient)
{
CaptureLocalSnapshot();
}
float num = Mathf.Max(0.25f, _localCaptureIntervalSeconds.Value);
yield return (object)new WaitForSeconds(num);
}
}
private void OnPlayerJoined(PlayerID player, bool isReconnect, bool asServer)
{
//IL_0039: 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)
if (asServer && IsHostActive() && (!_sendOnReconnectOnly.Value || isReconnect))
{
if (!isReconnect)
{
CaptureSnapshots();
SendSnapshotToPlayer(player, "player-joined");
}
else
{
SendSnapshotToPlayer(player, "player-rejoined");
}
}
}
private IEnumerator HostSnapshotLoop()
{
while (true)
{
if (IsHostActive())
{
CaptureSnapshots();
}
float num = Mathf.Max(1f, _snapshotIntervalSeconds.Value);
yield return (object)new WaitForSeconds(num);
}
}
private bool IsHostActive()
{
if ((Object)(object)_network != (Object)null)
{
if (!_network.isHost)
{
return _network.isServer;
}
return true;
}
return false;
}
private ulong LocalPlayerIdOrZero()
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: 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)
try
{
NetworkManager? network = _network;
long result;
if (network == null)
{
result = 0L;
}
else
{
PlayerID localPlayer = network.localPlayer;
result = (long)((PlayerID)(ref localPlayer)).id.value;
}
return (ulong)result;
}
catch
{
return 0uL;
}
}
private void CaptureSnapshots()
{
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: 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_0126: Unknown result type (might be due to invalid IL or missing references)
//IL_0138: 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_0161: Expected I4, but got O
//IL_0169: Expected O, but got I4
//IL_0171: Expected O, but got I4
//IL_018b: Expected O, but got I4
//IL_01a3: Expected O, but got I4
//IL_01bb: Expected O, but got I4
//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
//IL_01d3: Expected O, but got I4
//IL_01eb: Expected O, but got I4
//IL_0203: Expected O, but got I4
//IL_021b: Expected O, but got I4
//IL_0223: Expected O, but got I4
//IL_022b: Expected O, but got I4
//IL_0233: Expected O, but got I4
//IL_0234: Unknown result type (might be due to invalid IL or missing references)
//IL_0240: Expected O, but got I4
//IL_0248: Expected O, but got I4
//IL_0250: Expected O, but got I4
//IL_0251: Unknown result type (might be due to invalid IL or missing references)
//IL_0256: Unknown result type (might be due to invalid IL or missing references)
//IL_0264: Expected O, but got I4
//IL_0278: Expected O, but got I4
//IL_027a: Expected O, but got I4
//IL_015c->IL015c: Incompatible stack types: O vs I4
//IL_0155->IL015c: Incompatible stack types: I4 vs O
//IL_0155->IL015c: Incompatible stack types: O vs I4
PlayerPanelController i = NetworkSingleton<PlayerPanelController>.I;
if ((Object)(object)i == (Object)null || i.PlayerIDs == null || i.PlayerTransforms == null)
{
return;
}
PomodoroController i2 = MonoSingleton<PomodoroController>.I;
UIManager i3 = MonoSingleton<UIManager>.I;
int num = Math.Min(i.PlayerIDs.Count, i.PlayerTransforms.Count);
for (int j = 0; j < num; j++)
{
NetworkTransform val = i.PlayerTransforms[j];
if (!((Object)(object)val == (Object)null))
{
PlayerID val2 = i.PlayerIDs[j];
ulong value = ((PlayerID)(ref val2)).id.value;
string playerSteamId = GetPlayerSteamId(i, j);
string playerName = GetPlayerName(i, j);
PlayerMovementController val3 = ((Component)val).GetComponent<PlayerMovementController>() ?? ((Component)val).GetComponentInChildren<PlayerMovementController>();
PlayerFocusController val4 = ((Component)val).GetComponent<PlayerFocusController>() ?? ((Component)val).GetComponentInChildren<PlayerFocusController>();
CaptureFishingSnapshotForPlayer((Component)(object)val, value, out var wasFishingActive, out var fishingStateValue, out var hasFishingHookPosition, out var fishingHookPosition);
int focusIndex = -1;
int focusTypeValue = -1;
if ((Object)(object)val4 != (Object)null)
{
focusIndex = GetFocusIndex(val4);
focusTypeValue = GetFocusTypeValue(val4);
}
object obj = new RejoinSnapshotV1
{
SnapshotVersion = ++_snapshotVersion,
PlayerId = value,
Position = val.position,
Rotation = val.rotation
};
object obj2 = obj;
int num2;
if ((Object)(object)val3 != (Object)null)
{
obj = val3.MovementState;
num2 = (int)obj;
}
else
{
num2 = -1;
obj = num2;
num2 = (int)obj;
}
((RejoinSnapshotV1)obj2).MovementState = (int)obj;
((RejoinSnapshotV1)num2).FocusIndex = focusIndex;
((RejoinSnapshotV1)num2).FocusTypeValue = focusTypeValue;
((RejoinSnapshotV1)num2).IsFocus = (Object)(object)val4 != (Object)null && val4.IsFocus;
((RejoinSnapshotV1)num2).PomodoroMinute = (((Object)(object)i2 != (Object)null) ? i2.CurrentMinute : 0);
((RejoinSnapshotV1)num2).PomodoroPaused = (Object)(object)i2 == (Object)null || i2.IsPaused;
num2 = (((RejoinSnapshotV1)num2).PomodoroType = (((Object)(object)i2 != (Object)null) ? ((int)i2.PomodoroType) : 0));
((RejoinSnapshotV1)num2).IsMessagePanelOpen = (Object)(object)i3 != (Object)null && i3.IsMessagePanelActivated;
((RejoinSnapshotV1)num2).IsPomodoroPanelOpen = (Object)(object)i3 != (Object)null && i3.IsPomodoroOpened;
((RejoinSnapshotV1)num2).IsTodoPanelOpen = (Object)(object)i3 != (Object)null && i3.IsTodoOpened;
((RejoinSnapshotV1)num2).WasFishingActive = wasFishingActive;
((RejoinSnapshotV1)num2).FishingStateValue = fishingStateValue;
((RejoinSnapshotV1)num2).HasFishingHookPosition = hasFishingHookPosition;
((RejoinSnapshotV1)num2).FishingHookPosition = fishingHookPosition;
((RejoinSnapshotV1)num2).PlayerSteamId = playerSteamId;
((RejoinSnapshotV1)num2).PlayerName = playerName;
int num3 = num2;
Scene activeScene = SceneManager.GetActiveScene();
((RejoinSnapshotV1)num3).SceneName = ((Scene)(ref activeScene)).name;
((RejoinSnapshotV1)num2).CapturedAtUtcTicks = DateTime.UtcNow.Ticks;
RejoinSnapshotV1 value2 = (RejoinSnapshotV1)num2;
_snapshots[value] = value2;
if (!string.IsNullOrWhiteSpace(playerSteamId))
{
_snapshotsBySteamId[playerSteamId] = value2;
}
}
}
}
private void CaptureLocalSnapshot(string reason = "local-capture", bool verbose = false)
{
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
//IL_0123: 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_014a: 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_00ca: Unknown result type (might be due to invalid IL or missing references)
//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
//IL_0154: Expected I4, but got O
//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
//IL_022b: Unknown result type (might be due to invalid IL or missing references)
//IL_0258: Unknown result type (might be due to invalid IL or missing references)
//IL_025d: Unknown result type (might be due to invalid IL or missing references)
//IL_0284: Expected O, but got I4
//IL_014f->IL014f: Incompatible stack types: O vs I4
//IL_0149->IL014f: Incompatible stack types: I4 vs O
//IL_0149->IL014f: Incompatible stack types: O vs I4
TextChannelManager i = NetworkSingleton<TextChannelManager>.I;
if ((Object)(object)i == (Object)null)
{
return;
}
PlayerMovementController mainMovementController = i.MainMovementController;
PlayerFocusController mainFocusController = i.MainFocusController;
UIManager i2 = MonoSingleton<UIManager>.I;
PomodoroController i3 = MonoSingleton<PomodoroController>.I;
ulong playerId = LocalPlayerIdOrZero();
string playerSteamId = ResolveLocalSteamId();
CaptureLocalFishingSnapshot(i, out var wasFishingActive, out var fishingStateValue, out var hasFishingHookPosition, out var fishingHookPosition);
int focusIndex = -1;
int focusTypeValue = -1;
if ((Object)(object)mainFocusController != (Object)null)
{
focusIndex = GetFocusIndex(mainFocusController);
focusTypeValue = GetFocusTypeValue(mainFocusController);
}
if (!TryResolveLocalPose(i, out Vector3 position, out Quaternion rotation, out string source))
{
if (verbose)
{
((BaseUnityPlugin)this).Logger.LogInfo((object)("Skipped local snapshot capture (" + reason + ") because no local pose source was available."));
}
return;
}
if (IsLikelyInvalidLocalCapture(position, reason))
{
if (verbose)
{
((BaseUnityPlugin)this).Logger.LogInfo((object)$"Skipped local snapshot capture ({reason}) due to invalid position {position.x:0.00},{position.y:0.00},{position.z:0.00}");
}
return;
}
object obj = this;
object obj2 = new RejoinSnapshotV1
{
SnapshotVersion = ++_snapshotVersion,
PlayerId = playerId,
PlayerSteamId = playerSteamId,
Position = position,
Rotation = rotation
};
obj2 = obj2;
int num;
if ((Object)(object)mainMovementController != (Object)null)
{
obj = mainMovementController.MovementState;
num = (int)obj;
}
else
{
num = -1;
obj = num;
num = (int)obj;
}
((RejoinSnapshotV1)obj2).MovementState = (int)obj;
((RejoinSnapshotV1)obj2).FocusIndex = focusIndex;
((RejoinSnapshotV1)obj2).FocusTypeValue = focusTypeValue;
((RejoinSnapshotV1)obj2).IsFocus = (Object)(object)mainFocusController != (Object)null && mainFocusController.IsFocus;
((RejoinSnapshotV1)obj2).PomodoroMinute = (((Object)(object)i3 != (Object)null) ? i3.CurrentMinute : 0);
((RejoinSnapshotV1)obj2).PomodoroPaused = (Object)(object)i3 == (Object)null || i3.IsPaused;
obj2 = obj2;
num = (((RejoinSnapshotV1)obj2).PomodoroType = (((Object)(object)i3 != (Object)null) ? ((int)i3.PomodoroType) : 0));
((RejoinSnapshotV1)obj2).IsMessagePanelOpen = (Object)(object)i2 != (Object)null && i2.IsMessagePanelActivated;
((RejoinSnapshotV1)obj2).IsPomodoroPanelOpen = (Object)(object)i2 != (Object)null && i2.IsPomodoroOpened;
((RejoinSnapshotV1)obj2).IsTodoPanelOpen = (Object)(object)i2 != (Object)null && i2.IsTodoOpened;
((RejoinSnapshotV1)obj2).WasFishingActive = wasFishingActive;
((RejoinSnapshotV1)obj2).FishingStateValue = fishingStateValue;
((RejoinSnapshotV1)obj2).HasFishingHookPosition = hasFishingHookPosition;
((RejoinSnapshotV1)obj2).FishingHookPosition = fishingHookPosition;
((RejoinSnapshotV1)obj2).Reason = reason;
((RejoinSnapshotV1)obj2).SnapshotSentAtUtc = DateTime.UtcNow.ToString("O");
object obj3 = obj2;
Scene activeScene = SceneManager.GetActiveScene();
((RejoinSnapshotV1)obj3).SceneName = ((Scene)(ref activeScene)).name;
((RejoinSnapshotV1)obj2).CapturedAtUtcTicks = DateTime.UtcNow.Ticks;
((Plugin)num)._lastLocalSnapshot = (RejoinSnapshotV1?)obj2;
if (IsTerminalCaptureReason(reason))
{
_lastTerminalLocalSnapshot = CloneSnapshot(_lastLocalSnapshot);
}
PersistLocalSnapshot(_lastLocalSnapshot);
if (verbose)
{
((BaseUnityPlugin)this).Logger.LogInfo((object)$"Captured local snapshot v{_lastLocalSnapshot.SnapshotVersion} ({reason}, source={source}) at {_lastLocalSnapshot.Position.X:0.00},{_lastLocalSnapshot.Position.Y:0.00},{_lastLocalSnapshot.Position.Z:0.00}");
}
}
private void CaptureFishingSnapshotForPlayer(Component playerTransform, ulong playerId, out bool wasFishingActive, out int fishingStateValue, out bool hasFishingHookPosition, out Vector3 fishingHookPosition)
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: Expected I4, but got Unknown
//IL_005c: 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_00b0: Invalid comparison between Unknown and I4
//IL_006f: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
//IL_00ef: 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)
wasFishingActive = false;
fishingStateValue = -1;
hasFishingHookPosition = false;
fishingHookPosition = default(Vector3);
FishingController val = playerTransform.GetComponent<FishingController>() ?? playerTransform.GetComponentInChildren<FishingController>();
if ((Object)(object)val != (Object)null)
{
wasFishingActive = (Object)(object)val.FishingRod != (Object)null && val.FishingRod.activeSelf;
Transform fishHook = val.FishHook;
if ((Object)(object)fishHook != (Object)null && IsFiniteVector3(fishHook.position))
{
hasFishingHookPosition = true;
fishingHookPosition = fishHook.position;
}
}
if (playerId != LocalPlayerIdOrZero())
{
return;
}
FishingManager i = MonoSingleton<FishingManager>.I;
if (!((Object)(object)i == (Object)null))
{
fishingStateValue = (int)i.FishingState;
wasFishingActive = wasFishingActive || i.IsActive || (int)i.FishingState > 0;
FishingController fishingCont = i.FishingCont;
if ((Object)(object)((fishingCont != null) ? fishingCont.FishHook : null) != (Object)null && IsFiniteVector3(fishingCont.FishHook.position))
{
hasFishingHookPosition = true;
fishingHookPosition = fishingCont.FishHook.position;
}
}
}
private static void CaptureLocalFishingSnapshot(TextChannelManager channel, out bool wasFishingActive, out int fishingStateValue, out bool hasFishingHookPosition, out Vector3 fishingHookPosition)
{
//IL_000b: 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_00d6: Expected I4, but got Unknown
//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
//IL_00ea: Invalid comparison between Unknown and I4
//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
//IL_0111: Unknown result type (might be due to invalid IL or missing references)
//IL_0128: Unknown result type (might be due to invalid IL or missing references)
//IL_012d: Unknown result type (might be due to invalid IL or missing references)
wasFishingActive = false;
fishingStateValue = -1;
hasFishingHookPosition = false;
fishingHookPosition = default(Vector3);
FishingManager i = MonoSingleton<FishingManager>.I;
object obj = i?.FishingCont;
if (obj == null)
{
Transform mainPlayer = channel.MainPlayer;
obj = ((mainPlayer != null) ? ((Component)mainPlayer).GetComponent<FishingController>() : null);
if (obj == null)
{
Transform mainPlayer2 = channel.MainPlayer;
obj = ((mainPlayer2 != null) ? ((Component)mainPlayer2).GetComponentInChildren<FishingController>() : null) ?? (((Object)(object)channel.MainNetTransform != (Object)null) ? ((Component)channel.MainNetTransform).GetComponentInChildren<FishingController>() : null);
}
}
FishingController val = (FishingController)obj;
if ((Object)(object)val != (Object)null)
{
wasFishingActive = (Object)(object)val.FishingRod != (Object)null && val.FishingRod.activeSelf;
Transform fishHook = val.FishHook;
if ((Object)(object)fishHook != (Object)null && IsFiniteVector3(fishHook.position))
{
hasFishingHookPosition = true;
fishingHookPosition = fishHook.position;
}
}
if (!((Object)(object)i == (Object)null))
{
fishingStateValue = (int)i.FishingState;
wasFishingActive = wasFishingActive || i.IsActive || (int)i.FishingState > 0;
FishingController fishingCont = i.FishingCont;
if ((Object)(object)((fishingCont != null) ? fishingCont.FishHook : null) != (Object)null && IsFiniteVector3(fishingCont.FishHook.position))
{
hasFishingHookPosition = true;
fishingHookPosition = fishingCont.FishHook.position;
}
}
}
private static bool IsTerminalCaptureReason(string reason)
{
if (string.IsNullOrWhiteSpace(reason))
{
return false;
}
if (reason.IndexOf("disconnect", StringComparison.OrdinalIgnoreCase) < 0 && reason.IndexOf("shutdown", StringComparison.OrdinalIgnoreCase) < 0)
{
return reason.IndexOf("network-switch", StringComparison.OrdinalIgnoreCase) >= 0;
}
return true;
}
private static bool IsLikelyInvalidLocalCapture(Vector3 position, string reason)
{
//IL_0000: 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_001c: 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)
if (!IsFiniteVector3(position))
{
return true;
}
if (Mathf.Abs(position.x) < 0.01f && Mathf.Abs(position.y) < 0.01f && Mathf.Abs(position.z) < 0.01f)
{
return true;
}
return false;
}
private static bool TryResolveLocalPose(TextChannelManager channel, out Vector3 position, out Quaternion rotation, out string source)
{
//IL_0001: 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_000d: 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_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)
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
position = default(Vector3);
rotation = Quaternion.identity;
source = string.Empty;
Transform mainPlayer = channel.MainPlayer;
Transform fallback = (((Object)(object)channel.MainNetTransform != (Object)null) ? ((Component)channel.MainNetTransform).transform : null);
Transform val = PickPreferredTransform(mainPlayer, fallback);
if ((Object)(object)val == (Object)null)
{
return false;
}
position = val.position;
rotation = val.rotation;
source = ((val == mainPlayer) ? "MainPlayer" : "MainNetTransform");
return true;
}
private static Transform? PickPreferredTransform(Transform? primary, Transform? fallback)
{
//IL_000a: 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)
if ((Object)(object)primary != (Object)null && !IsNearOrigin(primary.position))
{
return primary;
}
if ((Object)(object)fallback != (Object)null && !IsNearOrigin(fallback.position))
{
return fallback;
}
return primary ?? fallback;
}
private static bool IsNearOrigin(Vector3 value)
{
//IL_0000: 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_0024: Unknown result type (might be due to invalid IL or missing references)
if (Mathf.Abs(value.x) < 0.01f && Mathf.Abs(value.y) < 0.01f)
{
return Mathf.Abs(value.z) < 0.01f;
}
return false;
}
private static string GetPlayerSteamId(PlayerPanelController panel, int index)
{
if (panel.PlayerSteamIDs == null || index < 0 || index >= panel.PlayerSteamIDs.Count)
{
return string.Empty;
}
return panel.PlayerSteamIDs[index] ?? string.Empty;
}
private static string GetPlayerName(PlayerPanelController panel, int index)
{
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
if (panel.IDInfos == null || index < 0 || index >= panel.IDInfos.Count)
{
return string.Empty;
}
return DecodeText(panel.IDInfos[index].Name);
}
private static string DecodeText(byte[]? value)
{
if (value == null || value.Length == 0)
{
return string.Empty;
}
return Encoding.UTF8.GetString(value).Trim('\0', ' ', '\n', '\r', '\t');
}
private string ResolveSteamIdByPlayerId(ulong playerId)
{
//IL_0059: 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_0061: Unknown result type (might be due to invalid IL or missing references)
PlayerPanelController i = NetworkSingleton<PlayerPanelController>.I;
if ((Object)(object)i == (Object)null || i.PlayerIDs == null)
{
return string.Empty;
}
int num = ((i.PlayerSteamIDs == null) ? i.PlayerIDs.Count : Math.Min(i.PlayerIDs.Count, i.PlayerSteamIDs.Count));
for (int j = 0; j < num; j++)
{
PlayerID val = i.PlayerIDs[j];
if (((PlayerID)(ref val)).id.value == playerId)
{
return GetPlayerSteamId(i, j);
}
}
return string.Empty;
}
private string ResolveLocalSteamId()
{
ulong num = LocalPlayerIdOrZero();
if (num != 0L)
{
return ResolveSteamIdByPlayerId(num);
}
return string.Empty;
}
private bool TryGetLatestSnapshot(out RejoinSnapshotV1 snapshot)
{
snapshot = null;
bool flag = false;
long num = long.MinValue;
foreach (KeyValuePair<ulong, RejoinSnapshotV1> snapshot2 in _snapshots)
{
RejoinSnapshotV1 value = snapshot2.Value;
if (value != null && (!flag || value.SnapshotVersion > num))
{
snapshot = value;
num = value.SnapshotVersion;
flag = true;
}
}
return flag;
}
private static RejoinSnapshotV1? CloneSnapshot(RejoinSnapshotV1? source)
{
if (source == null)
{
return null;
}
return new RejoinSnapshotV1
{
SnapshotVersion = source.SnapshotVersion,
PlayerId = source.PlayerId,
PlayerSteamId = source.PlayerSteamId,
PlayerName = source.PlayerName,
Position = source.Position,
Rotation = source.Rotation,
MovementState = source.MovementState,
FocusIndex = source.FocusIndex,
FocusTypeValue = source.FocusTypeValue,
IsFocus = source.IsFocus,
PomodoroMinute = source.PomodoroMinute,
PomodoroPaused = source.PomodoroPaused,
PomodoroType = source.PomodoroType,
IsMessagePanelOpen = source.IsMessagePanelOpen,
IsPomodoroPanelOpen = source.IsPomodoroPanelOpen,
IsTodoPanelOpen = source.IsTodoPanelOpen,
WasFishingActive = source.WasFishingActive,
FishingStateValue = source.FishingStateValue,
HasFishingHookPosition = source.HasFishingHookPosition,
FishingHookPosition = source.FishingHookPosition,
SnapshotSentAtUtc = source.SnapshotSentAtUtc,
Reason = source.Reason,
SceneName = source.SceneName,
CapturedAtUtcTicks = source.CapturedAtUtcTicks
};
}
private void PersistLocalSnapshot(RejoinSnapshotV1? snapshot)
{
if (!_persistLocalSnapshot.Value || snapshot == null || string.IsNullOrWhiteSpace(_localSnapshotStatePath))
{
return;
}
try
{
string directoryName = Path.GetDirectoryName(_localSnapshotStatePath);
if (!string.IsNullOrWhiteSpace(directoryName))
{
Directory.CreateDirectory(directoryName);
}
File.WriteAllText(_localSnapshotStatePath, JsonUtility.ToJson((object)snapshot, true));
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("Persist local snapshot failed: " + ex.Message));
}
}
private void LoadPersistedLocalSnapshot()
{
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
if (!_persistLocalSnapshot.Value || string.IsNullOrWhiteSpace(_localSnapshotStatePath) || !File.Exists(_localSnapshotStatePath))
{
return;
}
try
{
RejoinSnapshotV1 rejoinSnapshotV = JsonUtility.FromJson<RejoinSnapshotV1>(File.ReadAllText(_localSnapshotStatePath));
if (rejoinSnapshotV != null)
{
if (IsLikelyInvalidLocalCapture(rejoinSnapshotV.Position, rejoinSnapshotV.Reason))
{
((BaseUnityPlugin)this).Logger.LogInfo((object)"Persisted local snapshot ignored because position is invalid.");
return;
}
_lastLocalSnapshot = rejoinSnapshotV;
_lastTerminalLocalSnapshot = CloneSnapshot(rejoinSnapshotV);
((BaseUnityPlugin)this).Logger.LogInfo((object)$"Loaded persisted local snapshot v{rejoinSnapshotV.SnapshotVersion} at {rejoinSnapshotV.Position.X:0.00},{rejoinSnapshotV.Position.Y:0.00},{rejoinSnapshotV.Position.Z:0.00}");
}
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("Load persisted local snapshot failed: " + ex.Message));
}
}
private int GetFocusIndex(PlayerFocusController focusController)
{
if ((object)_focusIndexField == null)
{
_focusIndexField = AccessTools.Field(typeof(PlayerFocusController), "_currentFocusMainIndex");
}
if (_focusIndexField == null)
{
return -1;
}
try
{
return (_focusIndexField.GetValue(focusController) is int num) ? num : (-1);
}
catch
{
return -1;
}
}
private int GetFocusTypeValue(PlayerFocusController focusController)
{
if ((object)_focusTypeField == null)
{
_focusTypeField = AccessTools.Field(typeof(PlayerFocusController), "_focusType");
}
if (_focusTypeField == null)
{
return -1;
}
try
{
object value = _focusTypeField.GetValue(focusController);
return (value == null) ? (-1) : Convert.ToInt32(value);
}
catch
{
return -1;
}
}
private void SendSnapshotRequest(string reason)
{
if (!((Object)(object)_network == (Object)null) && _network.isClient)
{
ulong num = LocalPlayerIdOrZero();
if (num == 0L)
{
((BaseUnityPlugin)this).Logger.LogInfo((object)("Skipping snapshot request until local player id is ready (reason='" + reason + "')"));
return;
}
SnapshotRequestV1 snapshotRequestV = new SnapshotRequestV1
{
Reason = reason,
RequestedAtUtc = DateTime.UtcNow.ToString("O"),
ClientPlayerId = num,
ClientSteamId = ResolveLocalSteamId()
};
((BaseUnityPlugin)this).Logger.LogInfo((object)$"Sending snapshot request (reason='{reason}', playerId={snapshotRequestV.ClientPlayerId}, steamId='{snapshotRequestV.ClientSteamId}')");
SendToServer(RejoinMessageType.SnapshotRequest, snapshotRequestV);
}
}
private void SendSnapshotToPlayer(PlayerID targetPlayer, string reason, string preferredSteamId = "")
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0121: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_network == (Object)null)
{
return;
}
ulong value = ((PlayerID)(ref targetPlayer)).id.value;
string text = (string.IsNullOrWhiteSpace(preferredSteamId) ? ResolveSteamIdByPlayerId(value) : preferredSteamId);
RejoinSnapshotV1 value2 = null;
bool flag = false;
string text2 = "player-id";
if (!string.IsNullOrWhiteSpace(text) && _snapshotsBySteamId.TryGetValue(text, out value2))
{
flag = true;
text2 = "steam-id";
}
else if (_snapshots.TryGetValue(value, out value2))
{
flag = true;
}
else if (TryGetLatestSnapshot(out value2))
{
flag = true;
text2 = "latest-fallback";
}
if (!flag)
{
((BaseUnityPlugin)this).Logger.LogInfo((object)$"No snapshot available for player {value} (steamId='{text}', reason='{reason}')");
return;
}
value2.PlayerId = value;
if (!string.IsNullOrWhiteSpace(text))
{
value2.PlayerSteamId = text;
}
value2.Reason = reason;
value2.SnapshotSentAtUtc = DateTime.UtcNow.ToString("O");
_snapshots[value] = value2;
if (!string.IsNullOrWhiteSpace(value2.PlayerSteamId))
{
_snapshotsBySteamId[value2.PlayerSteamId] = value2;
}
byte[] data = PacketEnvelopeV1.Encode(2, LocalPlayerIdOrZero(), JsonUtility.ToJson((object)value2));
_network.Send<NetworkPayloadV1>(targetPlayer, new NetworkPayloadV1
{
Data = data
}, (Channel)2);
((BaseUnityPlugin)this).Logger.LogInfo((object)$"Sent snapshot v{value2.SnapshotVersion} to player {value} using {text2} (reason='{reason}')");
}
private void OnNetworkPayload(PlayerID sender, NetworkPayloadV1 payload, bool asServer)
{
//IL_003e: 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)
if (!PacketEnvelopeV1.TryDecode(payload?.Data, out var envelope))
{
return;
}
switch ((RejoinMessageType)envelope.MessageType)
{
case RejoinMessageType.SnapshotRequest:
if (asServer && IsHostActive())
{
HandleSnapshotRequest(sender, envelope.PayloadJson);
}
break;
case RejoinMessageType.SnapshotData:
if (!asServer)
{
HandleSnapshotData(envelope.PayloadJson);
}
break;
case RejoinMessageType.SnapshotApplyAck:
if (asServer && IsHostActive())
{
HandleSnapshotAck(sender, envelope.PayloadJson);
}
break;
}
}
private void HandleSnapshotRequest(PlayerID sender, string json)
{
//IL_0040: 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)
try
{
SnapshotRequestV1 snapshotRequestV = JsonUtility.FromJson<SnapshotRequestV1>(json) ?? new SnapshotRequestV1();
string text = (string.IsNullOrWhiteSpace(snapshotRequestV.Reason) ? "snapshot-request" : snapshotRequestV.Reason);
((BaseUnityPlugin)this).Logger.LogInfo((object)$"Received snapshot request from {((PlayerID)(ref sender)).id.value} (reason='{text}', playerId={snapshotRequestV.ClientPlayerId}, steamId='{snapshotRequestV.ClientSteamId}')");
SendSnapshotToPlayer(sender, text, snapshotRequestV.ClientSteamId ?? string.Empty);
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("Failed handling snapshot request: " + ex.Message));
}
}
private void HandleSnapshotData(string json)
{
RejoinSnapshotV1 rejoinSnapshotV = null;
try
{
rejoinSnapshotV = JsonUtility.FromJson<RejoinSnapshotV1>(json);
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("Failed deserializing snapshot data: " + ex.Message));
}
if (rejoinSnapshotV == null)
{
return;
}
ulong num = LocalPlayerIdOrZero();
if (rejoinSnapshotV.PlayerId != 0L && num != 0L && rejoinSnapshotV.PlayerId != num)
{
((BaseUnityPlugin)this).Logger.LogInfo((object)$"Ignoring snapshot v{rejoinSnapshotV.SnapshotVersion} for player {rejoinSnapshotV.PlayerId}; local player is {num}");
return;
}
if (rejoinSnapshotV.SnapshotVersion != 0L && rejoinSnapshotV.SnapshotVersion <= _lastAppliedSnapshotVersion)
{
((BaseUnityPlugin)this).Logger.LogInfo((object)$"Skipping stale snapshot v{rejoinSnapshotV.SnapshotVersion}; last applied is v{_lastAppliedSnapshotVersion}");
return;
}
if (_applySnapshotCoroutine != null)
{
((MonoBehaviour)this).StopCoroutine(_applySnapshotCoroutine);
}
_applySnapshotCoroutine = ((MonoBehaviour)this).StartCoroutine(ApplySnapshotWhenReady(rejoinSnapshotV));
}
private IEnumerator ApplySnapshotWhenReady(RejoinSnapshotV1 snapshot)
{
bool waitedForMainPlayer = false;
for (int attempt = 0; attempt < 40; attempt++)
{
TextChannelManager i = NetworkSingleton<TextChannelManager>.I;
if ((Object)(object)i != (Object)null && (Object)(object)i.MainNetTransform != (Object)null)
{
break;
}
waitedForMainPlayer = true;
yield return (object)new WaitForSeconds(0.25f);
}
if (waitedForMainPlayer)
{
((BaseUnityPlugin)this).Logger.LogInfo((object)$"Applying snapshot v{snapshot.SnapshotVersion} after waiting for local player object.");
}
bool flag = ApplySnapshot(snapshot);
bool flag2 = ShouldRestoreFocus(snapshot);
if (flag2)
{
BeginFocusRestoreRetry(snapshot);
}
bool flag3 = ShouldResumeFishing(snapshot);
if (flag3)
{
BeginFishingResumeRetry(snapshot);
}
if (flag || flag2 || flag3)
{
_snapshotAppliedThisSession = true;
_lastAppliedSnapshotVersion = Math.Max(_lastAppliedSnapshotVersion, snapshot.SnapshotVersion);
((BaseUnityPlugin)this).Logger.LogInfo((object)$"Applied snapshot v{snapshot.SnapshotVersion} (reason='{snapshot.Reason}', focusPending={flag2}, fishingPending={flag3})");
NotifyLocal($"Rejoin state restored (v{snapshot.SnapshotVersion}).");
}
else
{
((BaseUnityPlugin)this).Logger.LogWarning((object)$"Snapshot v{snapshot.SnapshotVersion} did not apply any state (reason='{snapshot.Reason}')");
}
SnapshotApplyAckV1 payload = new SnapshotApplyAckV1
{
SnapshotVersion = snapshot.SnapshotVersion,
AppliedAtUtc = DateTime.UtcNow.ToString("O"),
Status = (flag ? "applied" : ((flag2 || flag3) ? "applied-pending-followup" : "no-op"))
};
SendToServer(RejoinMessageType.SnapshotApplyAck, payload);
_applySnapshotCoroutine = null;
}
private void HandleSnapshotAck(PlayerID sender, string json)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
try
{
SnapshotApplyAckV1 snapshotApplyAckV = JsonUtility.FromJson<SnapshotApplyAckV1>(json);
if (snapshotApplyAckV != null)
{
_lastAckByPlayer[((PlayerID)(ref sender)).id.value] = snapshotApplyAckV.SnapshotVersion;
}
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("Failed handling snapshot ack: " + ex.Message));
}
}
private bool ApplySnapshot(RejoinSnapshotV1 snapshot)
{
//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_0054: 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_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
bool result = false;
TextChannelManager i = NetworkSingleton<TextChannelManager>.I;
if ((Object)(object)i != (Object)null)
{
try
{
Transform val = PickPreferredTransform(i.MainPlayer, ((Object)(object)i.MainNetTransform != (Object)null) ? ((Component)i.MainNetTransform).transform : null);
if ((Object)(object)val != (Object)null)
{
Vector3 desiredPosition = snapshot.Position;
if (TryResolveSafeRestorePosition(snapshot, val, desiredPosition, out Vector3 safePosition, out string reason))
{
SetTransformSafely(val, safePosition, snapshot.Rotation, i.MainMovementController);
MirrorPoseToSecondaryTransform(i, val, safePosition, snapshot.Rotation);
result = true;
}
else
{
((BaseUnityPlugin)this).Logger.LogInfo((object)$"Skipped position restore for snapshot v{snapshot.SnapshotVersion}: {reason}");
}
}
}
catch (Exception arg)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)$"Position restore failed: {arg}");
}
try
{
if ((Object)(object)i.MainMovementController != (Object)null && snapshot.MovementState >= 0)
{
i.MainMovementController.MovementState = (MovementState)snapshot.MovementState;
result = true;
}
}
catch (Exception arg2)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)$"Movement restore failed: {arg2}");
}
try
{
if ((Object)(object)i.MainFocusController != (Object)null && !snapshot.IsFocus)
{
i.MainFocusController.IsFocus = false;
result = true;
}
}
catch (Exception arg3)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)$"Focus restore failed: {arg3}");
}
}
try
{
PomodoroController i2 = MonoSingleton<PomodoroController>.I;
if ((Object)(object)i2 != (Object)null)
{
SetPropertyNonPublic(i2, "CurrentMinute", snapshot.PomodoroMinute);
SetPropertyNonPublic(i2, "IsPaused", snapshot.PomodoroPaused);
if (Enum.IsDefined(typeof(PomodoroType), snapshot.PomodoroType))
{
i2.PomodoroType = (PomodoroType)snapshot.PomodoroType;
}
result = true;
}
}
catch (Exception arg4)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)$"Pomodoro restore failed: {arg4}");
}
if (_applyUiState.Value)
{
try
{
UIManager i3 = MonoSingleton<UIManager>.I;
if ((Object)(object)i3 != (Object)null)
{
i3.IsMessagePanelActivated = snapshot.IsMessagePanelOpen;
SetPropertyNonPublic(i3, "IsPomodoroOpened", snapshot.IsPomodoroPanelOpen);
SetPropertyNonPublic(i3, "IsTodoOpened", snapshot.IsTodoPanelOpen);
i3.UpdateTimerTextOnOpen();
result = true;
}
}
catch (Exception arg5)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)$"UI restore failed: {arg5}");
}
}
return result;
}
private static void MirrorPoseToSecondaryTransform(TextChannelManager channel, Transform primary, Vector3 position, Quaternion rotation)
{
//IL_001d: 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_004b: 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)
try
{
if ((Object)(object)channel.MainPlayer != (Object)null && channel.MainPlayer != primary)
{
channel.MainPlayer.SetPositionAndRotation(position, rotation);
}
if ((Object)(object)channel.MainNetTransform != (Object)null && ((Component)channel.MainNetTransform).transform != primary)
{
((Component)channel.MainNetTransform).transform.SetPositionAndRotation(position, rotation);
}
}
catch
{
}
}
private static bool ShouldRestoreFocus(RejoinSnapshotV1 snapshot)
{
return snapshot.IsFocus;
}
private void BeginFocusRestoreRetry(RejoinSnapshotV1 snapshot)
{
if (ShouldRestoreFocus(snapshot))
{
if (_focusRestoreCoroutine != null)
{
((MonoBehaviour)this).StopCoroutine(_focusRestoreCoroutine);
}
_focusRestoreCoroutine = ((MonoBehaviour)this).StartCoroutine(FocusRestoreRetryLoop(snapshot));
}
}
private IEnumerator FocusRestoreRetryLoop(RejoinSnapshotV1 snapshot)
{
float num = Mathf.Max(0f, _focusRestoreDelaySeconds.Value);
if (num > 0f)
{
((BaseUnityPlugin)this).Logger.LogInfo((object)$"Delaying focus restore for snapshot v{snapshot.SnapshotVersion} by {num:0.00}s.");
yield return (object)new WaitForSeconds(num);
}
for (int attempt = 1; attempt <= 40; attempt++)
{
PlayerFocusController val = NetworkSingleton<TextChannelManager>.I?.MainFocusController;
if ((Object)(object)val != (Object)null && TryApplyFocusSnapshotNow(val, snapshot))
{
((BaseUnityPlugin)this).Logger.LogInfo((object)$"Applied focus restore for snapshot v{snapshot.SnapshotVersion} on attempt {attempt}.");
_focusRestoreCoroutine = null;
yield break;
}
yield return (object)new WaitForSeconds(0.25f);
}
((BaseUnityPlugin)this).Logger.LogWarning((object)$"Focus restore retries exhausted for snapshot v{snapshot.SnapshotVersion}.");
_focusRestoreCoroutine = null;
}
private bool ShouldResumeFishing(RejoinSnapshotV1 snapshot)
{
if (!_resumeFishingOnRestore.Value)
{
return false;
}
if (snapshot.WasFishingActive)
{
return true;
}
if (snapshot.FishingStateValue != 1 && snapshot.FishingStateValue != 2)
{
return snapshot.FishingStateValue == 3;
}
return true;
}
private void BeginFishingResumeRetry(RejoinSnapshotV1 snapshot)
{
if (ShouldResumeFishing(snapshot))
{
if (_fishingResumeCoroutine != null)
{
((MonoBehaviour)this).StopCoroutine(_fishingResumeCoroutine);
}
_fishingResumeCoroutine = ((MonoBehaviour)this).StartCoroutine(FishingResumeRetryLoop(snapshot));
}
}
private IEnumerator FishingResumeRetryLoop(RejoinSnapshotV1 snapshot)
{
yield return (object)new WaitForSeconds(1.25f);
for (int attempt = 1; attempt <= 24; attempt++)
{
if ((Object)(object)_network == (Object)null || !_network.isClient)
{
_fishingResumeCoroutine = null;
yield break;
}
if (TryResumeFishingNow(snapshot, out string detail))
{
((BaseUnityPlugin)this).Logger.LogInfo((object)$"Fishing resume applied for snapshot v{snapshot.SnapshotVersion} on attempt {attempt} ({detail}).");
_fishingResumeCoroutine = null;
yield break;
}
if (attempt == 1 || attempt % 8 == 0)
{
((BaseUnityPlugin)this).Logger.LogInfo((object)$"Fishing resume waiting for snapshot v{snapshot.SnapshotVersion} (attempt {attempt}): {detail}");
}
yield return (object)new WaitForSeconds(0.35f);
}
((BaseUnityPlugin)this).Logger.LogWarning((object)$"Fishing resume retries exhausted for snapshot v{snapshot.SnapshotVersion}.");
_fishingResumeCoroutine = null;
}
private bool TryResumeFishingNow(RejoinSnapshotV1 snapshot, out string detail)
{
//IL_0020: 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_0056: Invalid comparison between Unknown and I4
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Invalid comparison between Unknown and I4
//IL_007b: 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_00da: 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_00ea: Unknown result type (might be due to invalid IL or missing references)
//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
//IL_00cd: 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_0105: 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_011a: 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_013b: Unknown result type (might be due to invalid IL or missing references)
//IL_0146: Unknown result type (might be due to invalid IL or missing references)
detail = string.Empty;
FishingManager i = MonoSingleton<FishingManager>.I;
if ((Object)(object)i == (Object)null)
{
detail = "FishingManager unavailable";
return false;
}
if ((int)i.CurrentBait == 0)
{
detail = "no bait selected";
return false;
}
if (!i.IsActive)
{
i.ButtonFish();
}
if (!i.IsActive)
{
detail = "rod not active yet";
return false;
}
if ((int)i.FishingState == 2 || (int)i.FishingState == 3)
{
detail = $"already in state {i.FishingState}";
return true;
}
if ((int)i.FishingState != 0)
{
detail = $"state not ready ({i.FishingState})";
return false;
}
Transform val = NetworkSingleton<TextChannelManager>.I?.MainPlayer;
if ((Object)(object)val == (Object)null)
{
detail = "main player unavailable";
return false;
}
Vector3 desiredTarget = ((snapshot.HasFishingHookPosition && IsFiniteVector3(snapshot.FishingHookPosition)) ? ((Vector3)snapshot.FishingHookPosition) : (val.position + val.forward * 3f));
if (!TryResolveFishingCastTarget(i, val, desiredTarget, out var castTarget))
{
detail = "unable to resolve water cast target";
return false;
}
if (!TryTriggerFishingCast(i, castTarget, out string reason))
{
detail = reason;
return false;
}
detail = $"cast triggered at {castTarget.x:0.00},{castTarget.y:0.00},{castTarget.z:0.00}";
return true;
}
private bool TryResolveFishingCastTarget(FishingManager fishingManager, Transform mainPlayer, Vector3 desiredTarget, out Vector3 castTarget)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0003: 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_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_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_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_0049: 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_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_0050: 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_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: 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_00a2: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
//IL_00c2: 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)
castTarget = desiredTarget;
int collisionMask = ResolveFishingCollisionMask(fishingManager);
if (TryRaycastFishingWater(desiredTarget, collisionMask, out castTarget))
{
return true;
}
Vector3 position = mainPlayer.position;
Vector3 forward = mainPlayer.forward;
Vector3 val;
if (!(((Vector3)(ref forward)).sqrMagnitude > 0.001f))
{
val = Vector3.forward;
}
else
{
forward = mainPlayer.forward;
val = ((Vector3)(ref forward)).normalized;
}
Vector3 val2 = val;
if (TryRaycastFishingWater(position + val2 * 3f, collisionMask, out castTarget))
{
return true;
}
if (TryRaycastFishingWater(position + Quaternion.Euler(0f, 30f, 0f) * val2 * 3f, collisionMask, out castTarget))
{
return true;
}
if (TryRaycastFishingWater(position + Quaternion.Euler(0f, -30f, 0f) * val2 * 3f, collisionMask, out castTarget))
{
return true;
}
return false;
}
private int ResolveFishingCollisionMask(FishingManager fishingManager)
{
//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)
if ((object)_fishingCollisionLayersField == null)
{
_fishingCollisionLayersField = AccessTools.Field(typeof(FishingManager), "_collisionLayers");
}
if (_fishingCollisionLayersField?.GetValue(fishingManager) is LayerMask val && ((LayerMask)(ref val)).value != 0)
{
return ((LayerMask)(ref val)).value;
}
return -1;
}
private static bool TryRaycastFishingWater(Vector3 target, int collisionMask, out Vector3 waterTarget)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//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_0008: 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_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)
//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)
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
waterTarget = target;
RaycastHit val = default(RaycastHit);
if (!Physics.Raycast(target + Vector3.up * 80f, Vector3.down, ref val, 160f, collisionMask, (QueryTriggerInteraction)1))
{
return false;
}
if ((Object)(object)((RaycastHit)(ref val)).transform == (Object)null || ((Component)((RaycastHit)(ref val)).transform).gameObject.layer != LayerMask.NameToLayer("Water"))
{
return false;
}
waterTarget = ((RaycastHit)(ref val)).point;
return IsFiniteVector3(waterTarget);
}
private bool TryTriggerFishingCast(FishingManager fishingManager, Vector3 castTarget, out string reason)
{
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
reason = string.Empty;
if ((object)_fishingCastIndicatorField == null)
{
_fishingCastIndicatorField = AccessTools.Field(typeof(FishingManager), "_castIndicator");
}
if ((object)_fishingCastFishingRodMethod == null)
{
_fishingCastFishingRodMethod = AccessTools.Method(typeof(FishingManager), "CastFishingRod", (Type[])null, (Type[])null);
}
object? obj = _fishingCastIndicatorField?.GetValue(fishingManager);
Transform val = (Transform)((obj is Transform) ? obj : null);
if (val == null)
{
reason = "cast indicator unavailable";
return false;
}
if (_fishingCastFishingRodMethod == null)
{
reason = "CastFishingRod method unavailable";
return false;
}
bool activeSelf = ((Component)val).gameObject.activeSelf;
try
{
val.position = castTarget;
((Component)val).gameObject.SetActive(true);
_fishingCastFishingRodMethod.Invoke(fishingManager, Array.Empty<object>());
return true;
}
catch (Exception ex)
{
reason = "cast invocation failed: " + ex.GetBaseException().Message;
return false;
}
finally
{
((Component)val).gameObject.SetActive(activeSelf);
}
}
private bool TryApplyFocusSnapshotNow(PlayerFocusController focusController, RejoinSnapshotV1 snapshot)
{
if (!ShouldRestoreFocus(snapshot))
{
return false;
}
if (!IsFocusControllerReady(focusController))
{
return false;
}
if (!TryPrimeFocusContext(focusController, snapshot, out var focusMainIndex))
{
return false;
}
try
{
focusController.SetFocus(0);
return focusController.IsFocus;
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogInfo((object)$"Focus controller not ready for SetFocus yet (mainIndex={focusMainIndex}, focusIndex={snapshot.FocusIndex}, focusType={snapshot.FocusTypeValue}): {ex}");
return false;
}
}
private bool IsFocusControllerReady(PlayerFocusController focusController)
{
if (focusController.FocusAreaControllers == null || focusController.FocusAreaControllers.Count == 0)
{
return false;
}
if ((Object)(object)NetworkSingleton<TextChannelManager>.I?.MainAnimationController == (Object)null)
{
return false;
}
if ((Object)(object)MonoSingleton<UIManager>.I == (Object)null || (Object)(object)ScriptableSingleton<GameSettings>.I == (Object)null)
{
return false;
}
if ((object)_focusSimpledTypesField == null)
{
_focusSimpledTypesField = AccessTools.Field(typeof(PlayerFocusController), "_simpledFocusTypes");
}
if ((object)_focusIndexField == null)
{
_focusIndexField = AccessTools.Field(typeof(PlayerFocusController), "_currentFocusMainIndex");
}
if (_focusSimpledTypesField == null || _focusIndexField == null)
{
return false;
}
return true;
}
private bool TryPrimeFocusContext(PlayerFocusController focusController, RejoinSnapshotV1 snapshot, out int focusMainIndex)
{
RejoinSnapshotV1 snapshot2 = snapshot;
focusMainIndex = -1;
FocusAreaController val = FindNearestFocusArea(focusController);
if ((Object)(object)val != (Object)null)
{
SetPropertyNonPublic(focusController, "CurrentFocusAreaController", val);
}
List<FocusType> list = BuildSimplifiedFocusTypes(focusController);
if (list == null || list.Count == 0 || _focusSimpledTypesField == null || _focusIndexField == null)
{
return false;
}
focusMainIndex = snapshot2.FocusIndex;
if (focusMainIndex < 0 && snapshot2.FocusTypeValue >= 0)
{
focusMainIndex = list.FindIndex((FocusType type) => Convert.ToInt32(type) == snapshot2.FocusTypeValue);
}
if (focusMainIndex < 0)
{
focusMainIndex = 0;
}
focusMainIndex = Mathf.Clamp(focusMainIndex, 0, list.Count - 1);
try
{
_focusSimpledTypesField.SetValue(focusController, list);
_focusIndexField.SetValue(focusController, focusMainIndex);
return true;
}
catch
{
return false;
}
}
private static FocusAreaController? FindNearestFocusArea(PlayerFocusController focusController)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: 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_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
if (focusController.FocusAreaControllers == null || focusController.FocusAreaControllers.Count == 0)
{
return null;
}
Vector3 position = ((Component)focusController).transform.position;
float num = float.MaxValue;
FocusAreaController result = null;
for (int i = 0; i < focusController.FocusAreaControllers.Count; i++)
{
FocusAreaController val = focusController.FocusAreaControllers[i];
if (!((Object)(object)val == (Object)null))
{
Vector3 val2 = ((Component)val).transform.position - position;
float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
if (!(sqrMagnitude >= num))
{
num = sqrMagnitude;
result = val;
}
}
}
return result;
}
private static List<FocusType>? BuildSimplifiedFocusTypes(PlayerFocusController focusController)
{
//IL_0060: 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)
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
List<FocusType> list = null;
FocusAreaController currentFocusAreaController = focusController.CurrentFocusAreaController;
if ((Object)(object)currentFocusAreaController != (Object)null && (Object)(object)currentFocusAreaController.FocusAreaSettings != (Object)null)
{
list = currentFocusAreaController.FocusAreaSettings.FocusTypes;
}
if (list == null)
{
GameSettings i = ScriptableSingleton<GameSettings>.I;
list = ((i != null) ? i.FocusTypes : null);
}
if (list == null || list.Count == 0)
{
return null;
}
List<FocusType> list2 = new List<FocusType>(list.Count);
for (int j = 0; j < list.Count; j++)
{
FocusType item = list[j];
if (!list2.Contains(item))
{
list2.Add(item);
}
}
return list2;
}
private void SendToServer<TPayload>(RejoinMessageType type, TPayload payload)
{
if (!((Object)(object)_network == (Object)null) && _network.isClient)
{
string payloadJson = JsonUtility.ToJson((object)payload);
byte[] data = PacketEnvelopeV1.Encode((byte)type, LocalPlayerIdOrZero(), payloadJson);
_network.SendToServer<NetworkPayloadV1>(new NetworkPayloadV1
{
Data = data
}, (Channel)2);
}
}
private bool TryResolveSafeRestorePosition(RejoinSnapshotV1 snapshot, Transform currentTransform, Vector3 desiredPosition, out Vector3 safePosition, out string reason)
{
//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_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//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)
//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
//IL_00b4: 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_00bf: 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_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_00fd: 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_0100: 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_010a: Unknown result type (might be due to invalid IL or missing references)
//IL_010b: 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_011c: 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_0126: Unknown result type (might be due to invalid IL or missing references)
//IL_0128: Unknown result type (might be due to invalid IL or missing references)
//IL_0152: Unknown result type (might be due to invalid IL or missing references)
//IL_0153: Unknown result type (might be due to invalid IL or missing references)
safePosition = currentTransform.position;
reason = string.Empty;
if (!_safePositionRestore.Value)
{
safePosition = desiredPosition;
return true;
}
if (!IsFiniteVector3(desiredPosition))
{
reason = "desired position is invalid";
return false;
}
if (!string.IsNullOrWhiteSpace(snapshot.SceneName))
{
Scene activeScene = SceneManager.GetActiveScene();
string name = ((Scene)(ref activeScene)).name;
if (!string.Equals(name, snapshot.SceneName, StringComparison.Ordinal))
{
reason = "scene mismatch (snapshot='" + snapshot.SceneName + "', active='" + name + "')";
return false;
}
}
Vector3 position = currentTransform.position;
float num = Vector2.Distance(new Vector2(position.x, position.z), new Vector2(desiredPosition.x, desiredPosition.z));
if (num > Math.Max(5f, _maxRestoreDistanceMeters.Value))
{
reason = $"restore distance too large ({num:0.0}m)";
return false;
}
Vector3 val = desiredPosition;
Vector3 snappedPosition2;
if (TrySnapToGround(desiredPosition, out var snappedPosition))
{
val = snappedPosition;
}
else if (desiredPosition.y < -2f && TrySnapToGround(position, out snappedPosition2))
{
val = snappedPosition2;
reason = "desired Y below threshold and ground snap failed; using current ground";
}
if (!IsFiniteVector3(val) || val.y < -10f)
{
reason = "final candidate failed safety checks";
return false;
}
safePosition = val;
return true;
}
private bool TrySnapToGround(Vector3 originPosition, out Vector3 snappedPosition)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//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_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: 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_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: 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_00a7: Unknown result type (might be due to invalid IL or missing references)
//IL_00ba: 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_011f: 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_00df: Unknown result type (might be due to invalid IL or missing references)
//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
//IL_0121: 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)
//IL_0140: Unknown result type (might be due to invalid IL or missing references)
//IL_0145: Unknown result type (might be due to invalid IL or missing references)
//IL_014a: Unknown result type (might be due to invalid IL or missing references)
//IL_00f6: 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)
snappedPosition = originPosition;
Vector3 val = originPosition + Vector3.up * Math.Max(2f, _groundSnapCastHeight.Value);
float num = Math.Max(5f, _groundSnapCastDistance.Value);
RaycastHit[] array = Physics.RaycastAll(val, Vector3.down, num, -1, (QueryTriggerInteraction)1);
if (array == null || array.Length == 0)
{
return false;
}
float num2 = Mathf.Max(0f, _groundSnapMaxUpwardAdjust.Value);
float num3 = float.MaxValue;
float num4 = float.MaxValue;
Vector3 val2 = originPosition;
Vector3 val3 = originPosition;
bool flag = false;
bool flag2 = false;
for (int i = 0; i < array.Length; i++)
{
RaycastHit val4 = array[i];
if (IsFiniteVector3(((RaycastHit)(ref val4)).point) && !(((RaycastHit)(ref val4)).normal.y < 0.2f))
{
float num5 = ((RaycastHit)(ref val4)).point.y - originPosition.y;
float num6 = Mathf.Abs(num5);
if (num6 < num4)
{
num4 = num6;
val3 = ((RaycastHit)(ref val4)).point;
flag2 = true;
}
if (!(num5 > num2) && !(num6 >= num3))
{
num3 = num6;
val2 = ((RaycastHit)(ref val4)).point;
flag = true;
}
}
}
if (!flag && !flag2)
{
return false;
}
Vector3 val5 = (flag ? val2 : val3);
snappedPosition = val5 + Vector3.up * Mathf.Max(0f, _groundSnapOffsetY.Value);
return true;
}
private static ConfigDescription DescribeSetting(string description, string displayName, int order, AcceptableValueBase? acceptableValues = null)
{
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Expected O, but got Unknown
return new ConfigDescription(description, acceptableValues, new object[1]
{
new ConfigurationManagerAttributes
{
DispName = displayName,
Order = order
}
});
}
private static bool IsFiniteVector3(Vector3 value)
{
//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_001a: 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_0034: 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)
if (!float.IsNaN(value.x) && !float.IsNaN(value.y) && !float.IsNaN(value.z) && !float.IsInfinity(value.x) && !float.IsInfinity(value.y))
{
return !float.IsInfinity(value.z);
}
return false;
}
private void SetTransformSafely(Transform targetTransform, Vector3 position, Quaternion rotation, PlayerMovementController? movementController)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: 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_0074: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)movementController == (Object)null)
{
targetTransform.SetPositionAndRotation(position, rotation);
return;
}
if ((object)_characterControllerField == null)
{
_characterControllerField = AccessTools.Field(typeof(PlayerMovementController), "_characterController");
}
object? obj = _characterControllerField?.GetValue(movementController);
CharacterController val = (CharacterController)((obj is CharacterController) ? obj : null);
if ((Object)(object)val == (Object)null)
{
targetTransform.SetPositionAndRotation(position, rotation);
return;
}
bool enabled = ((Collider)val).enabled;
try
{
if (enabled)
{
((Collider)val).enabled = false;
}
targetTransform.SetPositionAndRotation(position, rotation);
}
finally
{
if (enabled)
{
((Collider)val).enabled = true;
}
}
}
private static void SetPropertyNonPublic(object instance, string propertyName, object value)
{
try
{
AccessTools.PropertySetter(instance.GetType(), propertyName)?.Invoke(instance, new object[1] { value });
}
catch
{
}
}
private void NotifyLocal(string message)
{
if (!_showNotifications.Value)
{
return;
}
try
{
TextChannelManager i = NetworkSingleton<TextChannelManager>.I;
if (i != null)
{
i.AddNotification("[RejoinStateRecovery] " + message);
}
}
catch
{
}
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "RejoinStateRecovery";
public const string PLUGIN_NAME = "RejoinStateRecovery";
public const string PLUGIN_VERSION = "1.0.9";
}
}