using System;
using System.Collections;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("Igor_Does_Nothing")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ReturnToTruckPlugin")]
[assembly: AssemblyTitle("ReturnToTruckPlugin")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
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;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.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;
}
}
}
[BepInPlugin("com.yourname.repo.returntotruck", "Return To Truck", "1.2.1")]
public class Unstucky : BaseUnityPlugin
{
public const string PluginGuid = "com.yourname.repo.returntotruck";
public const string PluginName = "Return To Truck";
public const string PluginVersion = "1.2.1";
private ConfigEntry<KeyboardShortcut> _hotkey;
private ConfigEntry<KeyboardShortcut> _pingHotkey;
private ConfigEntry<bool> _onlyInMainGame;
private ConfigEntry<bool> _enabled;
private ConfigEntry<bool> _heartbeatEnabled;
private ConfigEntry<float> _heartbeatIntervalSec;
private ConfigEntry<bool> _mirrorPingToTeleport;
private ConfigEntry<bool> _attachToGameDirector;
private ConfigEntry<int> _forceRepeats;
private ConfigEntry<float> _forceRepeatInterval;
private ConfigEntry<bool> _alignCamera;
private ConfigEntry<bool> _zeroVelocity;
private ConfigEntry<bool> _alsoMoveControllerRoot;
private ManualLogSource _log;
private static UnstuckyController _controller;
private void Awake()
{
//IL_008a: 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_0206: Unknown result type (might be due to invalid IL or missing references)
//IL_0219: Unknown result type (might be due to invalid IL or missing references)
_log = ((BaseUnityPlugin)this).Logger;
_enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Turn the mod on/off without removing it.");
_onlyInMainGame = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "OnlyInMainGame", true, "If true, the hotkey only works during gameplay (not in menus).");
_attachToGameDirector = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AttachToGameDirector", false, "If true, attach to GameDirector's GameObject when present; otherwise use a persistent hidden host.");
_hotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "TeleportHotkey", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), "Hotkey to return to the truck.");
_pingHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "PingHotkey", new KeyboardShortcut((KeyCode)288, Array.Empty<KeyCode>()), "Hotkey that only logs a Ping (for testing key detection).");
_mirrorPingToTeleport = ((BaseUnityPlugin)this).Config.Bind<bool>("Controls", "MirrorPingToTeleport", false, "If true, pressing PingHotkey will also attempt teleport.");
_heartbeatEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "HeartbeatEnabled", false, "If true, writes periodic heartbeat logs confirming the controller is alive.");
_heartbeatIntervalSec = ((BaseUnityPlugin)this).Config.Bind<float>("Debug", "HeartbeatIntervalSeconds", 10f, "Seconds between heartbeat log lines.");
_forceRepeats = ((BaseUnityPlugin)this).Config.Bind<int>("Teleport", "ForceRepeats", 6, "Re-apply teleport this many times to beat network correction (0 = once).");
_forceRepeatInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Teleport", "ForceRepeatInterval", 0.06f, "Seconds between forced teleport re-applications.");
_alignCamera = ((BaseUnityPlugin)this).Config.Bind<bool>("Teleport", "AlignCamera", true, "Align camera yaw to the spawn facing.");
_zeroVelocity = ((BaseUnityPlugin)this).Config.Bind<bool>("Teleport", "ZeroVelocity", true, "Zero rigidbody velocity/angular velocity on teleport.");
_alsoMoveControllerRoot = ((BaseUnityPlugin)this).Config.Bind<bool>("Teleport", "AlsoMoveControllerRoot", true, "Also set PlayerController.transform to the spawn pose (helps some states).");
_log.LogInfo((object)string.Format("{0} {1} loaded. Teleport: {2}, Ping: {3}, MirrorPingToTeleport: {4}, AttachToGameDirector: {5}, Heartbeat: {6}.", "Return To Truck", "1.2.1", _hotkey.Value, _pingHotkey.Value, _mirrorPingToTeleport.Value, _attachToGameDirector.Value, _heartbeatEnabled.Value ? "ON" : "OFF"));
BuildOrAttachController();
SceneManager.activeSceneChanged += OnActiveSceneChanged;
}
private void OnDestroy()
{
SceneManager.activeSceneChanged -= OnActiveSceneChanged;
_log.LogWarning((object)"Unstucky plugin OnDestroy() called (controller left running).");
}
private void OnActiveSceneChanged(Scene from, Scene to)
{
_log.LogInfo((object)("[Scene] activeSceneChanged: " + ((Scene)(ref from)).name + " -> " + ((Scene)(ref to)).name));
BuildOrAttachController();
}
private void BuildOrAttachController()
{
//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_0067: Expected O, but got Unknown
GameObject val = null;
if (_attachToGameDirector.Value && (Object)(object)GameDirector.instance != (Object)null)
{
val = ((Component)GameDirector.instance).gameObject;
_log.LogInfo((object)"Attaching controller to GameDirector GameObject.");
}
if ((Object)(object)val == (Object)null)
{
val = GameObject.Find("UnstuckyHost (BepInEx)");
if ((Object)(object)val == (Object)null)
{
val = new GameObject("UnstuckyHost (BepInEx)")
{
hideFlags = (HideFlags)61
};
Object.DontDestroyOnLoad((Object)(object)val);
_log.LogInfo((object)"Created persistent UnstuckyHost GameObject.");
}
}
UnstuckyController unstuckyController = val.GetComponent<UnstuckyController>();
if ((Object)(object)unstuckyController == (Object)null)
{
unstuckyController = val.AddComponent<UnstuckyController>();
_log.LogInfo((object)"UnstuckyController component added.");
}
unstuckyController.Configure(((BaseUnityPlugin)this).Logger, _enabled, _onlyInMainGame, _hotkey, _pingHotkey, _mirrorPingToTeleport, _heartbeatEnabled, _heartbeatIntervalSec, _forceRepeats, _forceRepeatInterval, _alignCamera, _zeroVelocity, _alsoMoveControllerRoot);
_controller = unstuckyController;
}
}
public class UnstuckyController : MonoBehaviour
{
private ManualLogSource _log;
private ConfigEntry<KeyboardShortcut> _hotkey;
private ConfigEntry<KeyboardShortcut> _pingHotkey;
private ConfigEntry<bool> _onlyInMainGame;
private ConfigEntry<bool> _enabled;
private ConfigEntry<bool> _heartbeatEnabled;
private ConfigEntry<float> _heartbeatIntervalSec;
private ConfigEntry<bool> _mirrorPingToTeleport;
private ConfigEntry<int> _forceRepeats;
private ConfigEntry<float> _forceRepeatInterval;
private ConfigEntry<bool> _alignCamera;
private ConfigEntry<bool> _zeroVelocity;
private ConfigEntry<bool> _alsoMoveControllerRoot;
private float _nextHeartbeatAt;
private int _updateCounter;
public void Configure(ManualLogSource log, ConfigEntry<bool> enabled, ConfigEntry<bool> onlyMain, ConfigEntry<KeyboardShortcut> hotkey, ConfigEntry<KeyboardShortcut> ping, ConfigEntry<bool> mirrorPing, ConfigEntry<bool> heartbeat, ConfigEntry<float> heartbeatInterval, ConfigEntry<int> forceRepeats, ConfigEntry<float> forceRepeatInterval, ConfigEntry<bool> alignCamera, ConfigEntry<bool> zeroVelocity, ConfigEntry<bool> alsoMoveRoot)
{
_log = log;
_enabled = enabled;
_onlyInMainGame = onlyMain;
_hotkey = hotkey;
_pingHotkey = ping;
_mirrorPingToTeleport = mirrorPing;
_heartbeatEnabled = heartbeat;
_heartbeatIntervalSec = heartbeatInterval;
_forceRepeats = forceRepeats;
_forceRepeatInterval = forceRepeatInterval;
_alignCamera = alignCamera;
_zeroVelocity = zeroVelocity;
_alsoMoveControllerRoot = alsoMoveRoot;
_nextHeartbeatAt = Time.unscaledTime + Mathf.Max(1f, _heartbeatIntervalSec.Value);
_log.LogInfo((object)"UnstuckyController configured.");
SafeProbeEnvironment("Configure");
((MonoBehaviour)this).CancelInvoke("RealtimeTick");
((MonoBehaviour)this).InvokeRepeating("RealtimeTick", 1f, 1f);
}
private void OnEnable()
{
ManualLogSource log = _log;
if (log != null)
{
log.LogInfo((object)"UnstuckyController OnEnable.");
}
}
private void OnDisable()
{
ManualLogSource log = _log;
if (log != null)
{
log.LogWarning((object)"UnstuckyController OnDisable.");
}
}
private void OnDestroy()
{
ManualLogSource log = _log;
if (log != null)
{
log.LogWarning((object)"UnstuckyController OnDestroy.");
}
((MonoBehaviour)this).CancelInvoke();
}
private void Update()
{
//IL_0039: 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_00e1: Unknown result type (might be due to invalid IL or missing references)
//IL_00e6: 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_0101: Unknown result type (might be due to invalid IL or missing references)
try
{
if (_enabled != null && !_enabled.Value)
{
return;
}
_updateCounter++;
KeyboardShortcut value;
if (_pingHotkey != null)
{
value = _pingHotkey.Value;
if (((KeyboardShortcut)(ref value)).IsDown())
{
_log.LogInfo((object)$"[Ping] {_pingHotkey.Value} pressed. State={DescribeState()} Truck={(Object)(object)TruckSafetySpawnPoint.instance != (Object)null} Player={(Object)(object)PlayerController.instance != (Object)null}");
if (_mirrorPingToTeleport != null && _mirrorPingToTeleport.Value)
{
_log.LogInfo((object)"[Ping] MirrorPingToTeleport=true -> attempting teleport.");
AttemptTeleportWithGates();
}
}
}
if (_hotkey != null)
{
value = _hotkey.Value;
if (((KeyboardShortcut)(ref value)).IsDown())
{
_log.LogInfo((object)$"Hotkey pressed: {_hotkey.Value}");
AttemptTeleportWithGates();
}
}
if (_heartbeatEnabled != null && _heartbeatEnabled.Value && Time.unscaledTime >= _nextHeartbeatAt)
{
_nextHeartbeatAt = Time.unscaledTime + Mathf.Max(1f, _heartbeatIntervalSec?.Value ?? 5f);
SafeProbeEnvironment("Heartbeat");
_log.LogInfo((object)$"[Heartbeat] UpdateCount={_updateCounter}");
_updateCounter = 0;
}
}
catch (Exception ex)
{
ManualLogSource log = _log;
if (log != null)
{
log.LogWarning((object)("[Update] Exception: " + ex.GetType().Name + ": " + ex.Message));
}
}
}
private void RealtimeTick()
{
try
{
if (_heartbeatEnabled != null && _heartbeatEnabled.Value)
{
_log.LogInfo((object)"[Tick] realtime tick alive");
}
}
catch
{
}
}
private void AttemptTeleportWithGates()
{
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Invalid comparison between Unknown and I4
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
if (_onlyInMainGame != null && _onlyInMainGame.Value)
{
if ((Object)(object)GameDirector.instance == (Object)null)
{
_log.LogInfo((object)"GameDirector is null; aborting teleport.");
return;
}
if ((int)GameDirector.instance.currentState != 2)
{
_log.LogInfo((object)$"Current state is {GameDirector.instance.currentState}, not Main; aborting teleport.");
return;
}
}
TryTeleportToTruckSpawn();
}
private Transform ResolveTruckSpawn()
{
if (!((Object)(object)TruckSafetySpawnPoint.instance != (Object)null))
{
return null;
}
return ((Component)TruckSafetySpawnPoint.instance).transform;
}
private void TryTeleportToTruckSpawn()
{
//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_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
//IL_00d5: 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_00c2: 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)
Transform val = ResolveTruckSpawn();
if ((Object)(object)val == (Object)null)
{
_log.LogWarning((object)"TruckSafetySpawnPoint not found in scene; cannot teleport.");
return;
}
PlayerController instance = PlayerController.instance;
PlayerAvatar val2 = (((Object)(object)instance != (Object)null) ? instance.playerAvatarScript : PlayerAvatar.instance);
if ((Object)(object)instance == (Object)null || (Object)(object)val2 == (Object)null)
{
_log.LogWarning((object)"Local player not found (PlayerController/PlayerAvatar is null); aborting.");
return;
}
PhysGrabObject val3 = null;
if ((Object)(object)val2.tumble != (Object)null)
{
val3 = ((Component)val2.tumble).GetComponent<PhysGrabObject>();
if ((Object)(object)val3 == (Object)null)
{
val3 = ((Component)val2.tumble).GetComponentInChildren<PhysGrabObject>(true);
}
}
if ((Object)(object)val3 == (Object)null)
{
val3 = ((Component)val2).GetComponentInChildren<PhysGrabObject>(true);
}
Vector3 position = val.position;
Quaternion rotation = val.rotation;
if ((Object)(object)val3 != (Object)null)
{
((MonoBehaviour)this).StartCoroutine(ForceTeleportSequence(val3, instance, val2, position, rotation));
}
else
{
ApplyFallbackMove(instance, val2, position, rotation);
}
}
private IEnumerator ForceTeleportSequence(PhysGrabObject pgo, PlayerController pc, PlayerAvatar pa, Vector3 toPos, Quaternion toRot)
{
//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_002b: 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)
int repeats = Mathf.Max(0, _forceRepeats.Value);
float interval = Mathf.Max(0.01f, _forceRepeatInterval.Value);
ApplyPgoTeleport(pgo, pc, pa, toPos, toRot);
for (int i = 0; i < repeats; i++)
{
yield return (object)new WaitForSeconds(interval);
ApplyPgoTeleport(pgo, pc, pa, toPos, toRot);
}
_log.LogInfo((object)"Teleported to truck spawn (via PhysGrabObject, with reinforcement).");
}
private void ApplyPgoTeleport(PhysGrabObject pgo, PlayerController pc, PlayerAvatar pa, Vector3 toPos, Quaternion toRot)
{
//IL_0001: 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_0028: 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_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
pgo.Teleport(toPos, toRot);
if (_zeroVelocity.Value)
{
Rigidbody component = ((Component)pgo).GetComponent<Rigidbody>();
if ((Object)(object)component != (Object)null)
{
component.velocity = Vector3.zero;
component.angularVelocity = Vector3.zero;
}
}
pa.FallDamageResetSet(2f);
if (_alignCamera.Value && (Object)(object)CameraAim.Instance != (Object)null)
{
CameraAim.Instance.CameraAimSpawn(((Quaternion)(ref toRot)).eulerAngles.y);
}
if (_alsoMoveControllerRoot.Value && (Object)(object)pc != (Object)null)
{
((Component)pc).transform.position = toPos;
((Component)pc).transform.rotation = toRot;
}
pc.InputDisable(0.2f);
pc.Kinematic(0.2f);
PlayerCollisionController collisionController = pc.CollisionController;
if (collisionController != null)
{
collisionController.ResetFalling();
}
}
private void ApplyFallbackMove(PlayerController pc, PlayerAvatar pa, Vector3 toPos, Quaternion toRot)
{
//IL_002c: 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_0053: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
_log.LogWarning((object)"PhysGrabObject missing — using direct transform fallback (may be network-corrected in MP).");
pc.InputDisable(0.2f);
pc.Kinematic(0.2f);
((Component)pc).transform.position = toPos;
((Component)pc).transform.rotation = toRot;
if ((Object)(object)pc.rb != (Object)null)
{
pc.rb.velocity = Vector3.zero;
pc.rb.angularVelocity = Vector3.zero;
}
PlayerCollisionController collisionController = pc.CollisionController;
if (collisionController != null)
{
collisionController.ResetFalling();
}
pa.FallDamageResetSet(2f);
if (_alignCamera.Value && (Object)(object)CameraAim.Instance != (Object)null)
{
CameraAim.Instance.CameraAimSpawn(((Quaternion)(ref toRot)).eulerAngles.y);
}
_log.LogInfo((object)"Teleported to truck spawn (direct transform).");
}
private void SafeProbeEnvironment(string tag)
{
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
try
{
TruckSafetySpawnPoint instance = TruckSafetySpawnPoint.instance;
PlayerController instance2 = PlayerController.instance;
PlayerAvatar val = (((Object)(object)instance2 != (Object)null) ? instance2.playerAvatarScript : PlayerAvatar.instance);
bool flag = false;
if ((Object)(object)val != (Object)null && (Object)(object)val.tumble != (Object)null)
{
PhysGrabObject component = ((Component)val.tumble).GetComponent<PhysGrabObject>();
flag = (Object)(object)component != (Object)null;
}
object obj;
if (!((Object)(object)instance != (Object)null))
{
obj = "-";
}
else
{
object arg = ((Component)instance).transform.position;
Quaternion rotation = ((Component)instance).transform.rotation;
obj = $"{arg} / {((Quaternion)(ref rotation)).eulerAngles}";
}
string text = (string)obj;
_log.LogInfo((object)$"[{tag}] Alive. State={DescribeState()} Truck={(Object)(object)instance != (Object)null} Player={(Object)(object)instance2 != (Object)null} PGO={flag} Cam={(Object)(object)CameraAim.Instance != (Object)null} TruckPose={text}");
}
catch (Exception ex)
{
_log.LogWarning((object)("[" + tag + "] Probe failed: " + ex.GetType().Name + ": " + ex.Message));
}
}
private string DescribeState()
{
if ((Object)(object)GameDirector.instance == (Object)null)
{
return "null";
}
return ((object)(gameState)(ref GameDirector.instance.currentState)).ToString();
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}